@effect-agent/platform-cloudflare 0.0.1-beta.3 → 0.0.1-beta.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -373,12 +373,25 @@ interface CloudflareDurableRuntimeOptions {
373
373
  readonly toolReconciler?: Layer.Layer<ToolReconciler> | undefined;
374
374
  /**
375
375
  * Registered worker Bindings resolved at durable claim time (S2, spec/subagents.md §11):
376
- * build each with `DurableWorkerBinding.make(binding, digests)`. An Effect form is accepted
377
- * because the capture is effectful; it runs once per incarnation during Layer construction.
378
- * Defaults to the empty registration (every resolved claim fails closed).
376
+ * build each with `DurableWorkerBinding.make(binding, digests)`. An Effect or callback form is
377
+ * accepted because capture can be effectful. The callback receives the live Object context and
378
+ * derived identities and is evaluated once per incarnation during Layer construction. Defaults
379
+ * to the empty registration (every resolved claim fails closed).
379
380
  */
380
- readonly bindings?: ReadonlyArray<ResolvedBinding> | Effect.Effect<ReadonlyArray<ResolvedBinding>> | undefined;
381
+ readonly bindings?: CloudflareBindingSource | undefined;
381
382
  }
383
+ /** Per-incarnation host values available while registered worker Bindings are captured. */
384
+ interface CloudflareBindingSourceContext {
385
+ readonly ctx: DurableObjectState;
386
+ readonly env: unknown;
387
+ readonly conversationId: ConversationId;
388
+ readonly producerId: ProducerId;
389
+ }
390
+ /**
391
+ * Registered worker Bindings, or a closed Effect/callback that captures them once for each
392
+ * Durable Object incarnation. Callback Effects cannot require services or fail typed.
393
+ */
394
+ type CloudflareBindingSource = ReadonlyArray<ResolvedBinding> | Effect.Effect<ReadonlyArray<ResolvedBinding>, never, never> | ((context: CloudflareBindingSourceContext) => ReadonlyArray<ResolvedBinding> | Effect.Effect<ReadonlyArray<ResolvedBinding>, never, never>);
382
395
  /** Every construction failure of the assembled Cloudflare durable runtime stack. */
383
396
  type CloudflareDurableRuntimeInitializationError = CloudflarePlatformConfigError | DoStorageInitializationError;
384
397
  /** The services `CloudflareDurableRuntime.layer` provides. */
@@ -579,14 +592,6 @@ declare const encodeHostResponse: (input: AbortRecorded | ApprovalRecorded | Hos
579
592
  readonly createdAt: string;
580
593
  readonly deploymentId: string;
581
594
  readonly payload: {
582
- readonly _tag: "SubagentStarted";
583
- readonly runId: string;
584
- readonly toolCallId: string;
585
- readonly childConversationId: string;
586
- readonly childSubmissionId: string;
587
- readonly childReceiptId: string;
588
- readonly childRunId: string;
589
- } | {
590
595
  readonly _tag: "ConversationCreated";
591
596
  readonly agentId: string;
592
597
  readonly definitions: {
@@ -717,6 +722,14 @@ declare const encodeHostResponse: (input: AbortRecorded | ApprovalRecorded | Hos
717
722
  readonly childConversationId: string;
718
723
  readonly childPrincipal: string;
719
724
  readonly childIdempotencyKey: string;
725
+ } | {
726
+ readonly _tag: "SubagentStarted";
727
+ readonly runId: string;
728
+ readonly toolCallId: string;
729
+ readonly childConversationId: string;
730
+ readonly childSubmissionId: string;
731
+ readonly childReceiptId: string;
732
+ readonly childRunId: string;
720
733
  } | {
721
734
  readonly _tag: "SubagentJoined";
722
735
  readonly runId: string;
@@ -1478,5 +1491,5 @@ interface ConversationObjectClass {
1478
1491
  */
1479
1492
  declare const makeConversationObjectClass: (options: ConversationObjectOptions) => ConversationObjectClass;
1480
1493
  //#endregion
1481
- export { AbortRecorded, AdminExplainRequest, AdminFailed, AdminFailure, AdminResponse, AdminVerifyRequest, AdmissionLimitExceeded, ApprovalRecorded, CLOUDFLARE_DATABASE_CAP_BYTES, CLOUDFLARE_RUNTIME_DEFAULTS, ClientAbortFailure, ClientApprovalFailure, ClientAwaitFailure, ClientObserveFailure, ClientSubmitFailure, ClientUnknownFailure, CloudflareAdmissionLimitsValue, CloudflareBindingError, CloudflareConversationClient, CloudflareDurableRuntime, CloudflareDurableRuntimeConfig, CloudflareDurableRuntimeConfigValue, CloudflareDurableRuntimeInitializationError, CloudflareDurableRuntimeOptions, CloudflareDurableRuntimeServices, CloudflarePlatformConfigError, ConversationClientError, ConversationMaintenance, ConversationObjectClass, ConversationObjectIdentity, ConversationObjectInstance, ConversationObjectNamespace, ConversationObjectOptions, ConversationObjectPorts, ConversationObjectRpc, DEFAULT_MAX_DATABASE_BYTES, DurableAlarmError, DurableAlarmService, DurableObjectContext, ExplainedRecovery, HostFailed, HostFailure, HostProtocolError, HostResponse, MaintenancePassFailure, MaintenancePassReport, ObligationsScanned, ObservePageRequest, ObservedPage, RetryExecuted, SettlementReached, SubmitRequest, SubmitSucceeded, UnknownResolutionRecorded, VerifiedIntegrity, boundHostDiagnostic, cloudflareWakeSchedulerLayer, conversationNamespaceFromEnv, conversationNamespaceLayer, conversationPortTransportLayer, decodeAbortCommand, decodeAdminExplainRequest, decodeAdminResponse, decodeAdminVerifyRequest, decodeApprovalDecisionCommand, decodeHostResponse, decodeObligationThresholds, decodeObservePageRequest, decodeReceipt, decodeRetryCommand, decodeSubmitRequest, decodeUnknownResolutionCommand, encodeAbortCommand, encodeAdminResponse, encodeApprovalDecisionCommand, encodeHostResponse, encodeObservePageRequest, encodeReceipt, encodeSubmitRequest, encodeUnknownResolutionCommand, makeConversationObjectClass };
1494
+ export { AbortRecorded, AdminExplainRequest, AdminFailed, AdminFailure, AdminResponse, AdminVerifyRequest, AdmissionLimitExceeded, ApprovalRecorded, CLOUDFLARE_DATABASE_CAP_BYTES, CLOUDFLARE_RUNTIME_DEFAULTS, ClientAbortFailure, ClientApprovalFailure, ClientAwaitFailure, ClientObserveFailure, ClientSubmitFailure, ClientUnknownFailure, CloudflareAdmissionLimitsValue, CloudflareBindingError, CloudflareBindingSource, CloudflareBindingSourceContext, CloudflareConversationClient, CloudflareDurableRuntime, CloudflareDurableRuntimeConfig, CloudflareDurableRuntimeConfigValue, CloudflareDurableRuntimeInitializationError, CloudflareDurableRuntimeOptions, CloudflareDurableRuntimeServices, CloudflarePlatformConfigError, ConversationClientError, ConversationMaintenance, ConversationObjectClass, ConversationObjectIdentity, ConversationObjectInstance, ConversationObjectNamespace, ConversationObjectOptions, ConversationObjectPorts, ConversationObjectRpc, DEFAULT_MAX_DATABASE_BYTES, DurableAlarmError, DurableAlarmService, DurableObjectContext, ExplainedRecovery, HostFailed, HostFailure, HostProtocolError, HostResponse, MaintenancePassFailure, MaintenancePassReport, ObligationsScanned, ObservePageRequest, ObservedPage, RetryExecuted, SettlementReached, SubmitRequest, SubmitSucceeded, UnknownResolutionRecorded, VerifiedIntegrity, boundHostDiagnostic, cloudflareWakeSchedulerLayer, conversationNamespaceFromEnv, conversationNamespaceLayer, conversationPortTransportLayer, decodeAbortCommand, decodeAdminExplainRequest, decodeAdminResponse, decodeAdminVerifyRequest, decodeApprovalDecisionCommand, decodeHostResponse, decodeObligationThresholds, decodeObservePageRequest, decodeReceipt, decodeRetryCommand, decodeSubmitRequest, decodeUnknownResolutionCommand, encodeAbortCommand, encodeAdminResponse, encodeApprovalDecisionCommand, encodeHostResponse, encodeObservePageRequest, encodeReceipt, encodeSubmitRequest, encodeUnknownResolutionCommand, makeConversationObjectClass };
1482
1495
  //# sourceMappingURL=index.d.mts.map
package/dist/index.mjs CHANGED
@@ -13,7 +13,7 @@ import { DurableObject } from "cloudflare:workers";
13
13
  * per incarnation and everything downstream consumes the services.
14
14
  */
15
15
  /** A Cloudflare platform binding was missing or carried the wrong shape (DEPLOY-003/010). */
16
- var CloudflareBindingError = class extends Schema.TaggedErrorClass()("CloudflareBindingError", {
16
+ var CloudflareBindingError = class extends Schema.TaggedError()("CloudflareBindingError", {
17
17
  binding: Schema.String,
18
18
  message: Schema.String
19
19
  }) {};
@@ -76,7 +76,7 @@ var ConversationObjectIdentity = class extends Context.Service()("@effect-agent/
76
76
  const PositiveMillis = Schema.Int.check(Schema.isGreaterThan(0));
77
77
  const NonNegativeMillis = Schema.Int.check(Schema.isGreaterThanOrEqualTo(0));
78
78
  /** The supplied Cloudflare durable runtime configuration failed validation (DEPLOY-003). */
79
- var CloudflarePlatformConfigError = class extends Schema.TaggedErrorClass()("CloudflarePlatformConfigError", {
79
+ var CloudflarePlatformConfigError = class extends Schema.TaggedError()("CloudflarePlatformConfigError", {
80
80
  message: Schema.String,
81
81
  cause: Schema.optionalKey(Schema.Defect())
82
82
  }) {};
@@ -88,7 +88,7 @@ var CloudflarePlatformConfigError = class extends Schema.TaggedErrorClass()("Clo
88
88
  * Conversation Object's submit entry point before `DurableAgentRuntime.submit` runs, and
89
89
  * nothing was admitted or written.
90
90
  */
91
- var AdmissionLimitExceeded = class extends Schema.TaggedErrorClass()("AdmissionLimitExceeded", {
91
+ var AdmissionLimitExceeded = class extends Schema.TaggedError()("AdmissionLimitExceeded", {
92
92
  limit: Schema.Literals([
93
93
  "queue-depth",
94
94
  "input-bytes",
@@ -185,7 +185,7 @@ const CLOUDFLARE_RUNTIME_DEFAULTS = {
185
185
  * alarms are harmless by design: a pass over an all-settled lane simply deletes the slot.
186
186
  */
187
187
  /** The Durable Object alarm API failed; surfaces on host entry points as a typed refusal. */
188
- var DurableAlarmError = class extends Schema.TaggedErrorClass()("DurableAlarmError", {
188
+ var DurableAlarmError = class extends Schema.TaggedError()("DurableAlarmError", {
189
189
  operation: Schema.String,
190
190
  message: Schema.String,
191
191
  cause: Schema.optionalKey(Schema.Defect())
@@ -351,7 +351,7 @@ var ConversationMaintenance = class ConversationMaintenance extends Context.Serv
351
351
  */
352
352
  const WAKE_BUFFER_CAPACITY = 1024;
353
353
  /** A remote wake stub call failed; always swallowed and logged (hints are droppable). */
354
- var RemoteWakeDropped = class extends Schema.TaggedErrorClass()("RemoteWakeDropped", {
354
+ var RemoteWakeDropped = class extends Schema.TaggedError()("RemoteWakeDropped", {
355
355
  conversationId: Schema.String,
356
356
  message: Schema.String,
357
357
  cause: Schema.optionalKey(Schema.Defect())
@@ -453,7 +453,10 @@ const conversationIdFromState = (ctx) => ctx.id.name === void 0 ? Effect.fail(Cl
453
453
  message: `The Durable Object name is not a valid ConversationId: ${error.message}`,
454
454
  cause: error
455
455
  })));
456
- const resolveBindings = (bindings) => bindings === void 0 ? Effect.succeed([]) : Effect.isEffect(bindings) ? bindings : Effect.succeed(bindings);
456
+ const resolveBindings = (source, context) => source === void 0 ? Effect.succeed([]) : Effect.isEffect(source) ? source : typeof source === "function" ? Effect.suspend(() => {
457
+ const bindings = source(context);
458
+ return Effect.isEffect(bindings) ? bindings : Effect.succeed(bindings);
459
+ }) : Effect.succeed(source);
457
460
  /**
458
461
  * The DC Layer assembly (deployment §12: a Layer-assembly library, not an app entrypoint;
459
462
  * plan §1.4). `layer(options)` decodes the configuration, derives this Object's Conversation
@@ -474,7 +477,7 @@ const resolveBindings = (bindings) => bindings === void 0 ? Effect.succeed([]) :
474
477
  var CloudflareDurableRuntime = class {
475
478
  static layer(options) {
476
479
  return Layer.unwrap(Effect.gen(function* () {
477
- const { ctx } = yield* DurableObjectContext;
480
+ const { ctx, env } = yield* DurableObjectContext;
478
481
  const config = yield* configFromOptions(options);
479
482
  const conversationId = yield* conversationIdFromState(ctx);
480
483
  const producerId = yield* decodeProducerId(`${config.producerPrefix}:${conversationId}`).pipe(Effect.mapError((error) => CloudflarePlatformConfigError.make({
@@ -515,7 +518,12 @@ var CloudflareDurableRuntime = class {
515
518
  }));
516
519
  const runtimeFailpointLayer = options.runtimeFailpoint === void 0 ? DurableRuntimeFailpoint.layer : Layer.succeed(DurableRuntimeFailpoint)({ hit: options.runtimeFailpoint(ctx) });
517
520
  const reconcilerLayer = options.toolReconciler ?? ToolReconciler.uncertain;
518
- const bindingResolverLayer = Layer.effect(AgentBindingResolver)(Effect.map(resolveBindings(options.bindings), AgentBindingResolver.fromBindings));
521
+ const bindingResolverLayer = Layer.effect(AgentBindingResolver)(Effect.map(resolveBindings(options.bindings, {
522
+ ctx,
523
+ env,
524
+ conversationId,
525
+ producerId
526
+ }), (bindings) => AgentBindingResolver.fromBindings(bindings)));
519
527
  const base = Layer.mergeAll(identityLayer, cloudflareConfigLayer, DurableAlarmService.layer);
520
528
  const runtimeStack = DurableAgentRuntime.layer.pipe(Layer.provideMerge(routedPorts), Layer.provideMerge(cloudflareWakeSchedulerLayer), Layer.provideMerge(runtimeConfigLayer), Layer.provideMerge(bindingResolverLayer), Layer.provide(Layer.mergeAll(runtimeFailpointLayer, reconcilerLayer, BrowserCrypto.layer)), Layer.provideMerge(base));
521
529
  return Layer.mergeAll(runtimeStack, ConversationMaintenance.layer.pipe(Layer.provide(runtimeStack)), portsEndpointLayer);
@@ -541,9 +549,9 @@ const boundHostDiagnostic = (value) => value.length > MAX_HOST_DIAGNOSTIC_LENGTH
541
549
  * The envelope itself could not be honored: the Object could not decode the request, or a
542
550
  * response could not be encoded/decoded. Never carries operation semantics.
543
551
  */
544
- var HostProtocolError = class extends Schema.TaggedErrorClass()("HostProtocolError", { message: BoundedDiagnostic }) {};
552
+ var HostProtocolError = class extends Schema.TaggedError()("HostProtocolError", { message: BoundedDiagnostic }) {};
545
553
  /** The Worker-side stub call itself failed (RPC rejection, overload, eviction mid-call). */
546
- var ConversationClientError = class extends Schema.TaggedErrorClass()("ConversationClientError", {
554
+ var ConversationClientError = class extends Schema.TaggedError()("ConversationClientError", {
547
555
  conversationId: Schema.String,
548
556
  message: Schema.String,
549
557
  cause: Schema.optionalKey(Schema.Defect())
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["#runtime"],"sources":["../src/bindings.ts","../src/config.ts","../src/alarm.ts","../src/wake-scheduler.ts","../src/transport.ts","../src/layers.ts","../src/client.ts","../src/conversation-object.ts"],"sourcesContent":["import type { ConversationId } from \"@effect-agent/core\";\nimport type { ProducerId } from \"@effect-agent/session\";\nimport { Context, Effect, Layer, Schema } from \"effect\";\n\n/**\n * Cloudflare platform bindings as Effect services (DEPLOY-010: \"Cloudflare platform bindings\n * are supplied as Effect services/Layers\"). Application code never reads `env` or touches a\n * `DurableObjectState` directly — the Conversation Object class constructs these Layers once\n * per incarnation and everything downstream consumes the services.\n */\n\n/** A Cloudflare platform binding was missing or carried the wrong shape (DEPLOY-003/010). */\nexport class CloudflareBindingError extends Schema.TaggedErrorClass<CloudflareBindingError>()(\n \"CloudflareBindingError\",\n {\n binding: Schema.String,\n message: Schema.String,\n },\n) {}\n\n/**\n * The RPC surface one Conversation Durable Object exposes to Workers and to sibling\n * Conversation Objects. `makeConversationObjectClass` implements it; the Worker-side client\n * and the cross-Object transport call it through `DurableObjectNamespace` stubs. Every\n * `encoded` value is a Schema-encoded envelope (`client.ts` wire schemas for host entry\n * points, `@effect-agent/storage-cloudflare` port envelopes for `portCall`), so the RPC\n * boundary carries only structured-cloneable JSON.\n */\nexport interface ConversationObjectRpc extends Rpc.DurableObjectBranded {\n /** Admission-limits gate + `DurableAgentRuntime.submit`; answers a `SubmitResponse`. */\n submitEncoded(encoded: unknown): Promise<unknown>;\n /** Wake-hinted, poll-guaranteed settlement wait; answers an `AwaitSettlementResponse`. */\n awaitSettlementEncoded(encoded: unknown): Promise<unknown>;\n /** One bounded page of canonical records; answers an `ObservePageResponse`. */\n observePage(encoded: unknown): Promise<unknown>;\n /** Durable abort intent; answers an `AbortResponse`. */\n abortEncoded(encoded: unknown): Promise<unknown>;\n /** Durable approval decision (plan §2.6); answers a `ResolveApprovalResponse`. */\n resolveApprovalEncoded(encoded: unknown): Promise<unknown>;\n /** Authorized DUR-017 Unknown-Outcome resolution; answers a `ResolveUnknownResponse`. */\n resolveUnknownEncoded(encoded: unknown): Promise<unknown>;\n /** Owner-side cross-Object port endpoint (WP2 envelopes, executed on LOCAL facets). */\n portCall(encoded: unknown): Promise<unknown>;\n /** Droppable liveness hint from another Object: arms an immediate alarm. */\n wake(): Promise<void>;\n}\n\n/**\n * The `DurableObjectNamespace` binding that addresses Conversation Objects. The Object\n * identity rule is `namespace.idFromName(conversationId)` (plan §1.2): Conversation IDs are\n * globally unique, so the mapping is total and deterministic and no directory service exists.\n */\nexport class ConversationObjectNamespace extends Context.Service<\n ConversationObjectNamespace,\n {\n readonly namespace: DurableObjectNamespace<ConversationObjectRpc>;\n }\n>()(\"@effect-agent/platform-cloudflare/ConversationObjectNamespace\") {\n static layer(\n namespace: DurableObjectNamespace<ConversationObjectRpc>,\n ): Layer.Layer<ConversationObjectNamespace> {\n return Layer.succeed(ConversationObjectNamespace)({ namespace });\n }\n}\n\n/**\n * Narrow one `env` member to a `DurableObjectNamespace`. `env` is an untyped platform value,\n * and a namespace binding is a host object no Schema can decode, so this is the documented\n * narrowest-boundary check (structural probe for the namespace surface the transport uses);\n * a missing or misshaped binding fails typed before any Layer is built.\n */\nexport const conversationNamespaceFromEnv = (\n env: unknown,\n binding: string,\n): Effect.Effect<DurableObjectNamespace<ConversationObjectRpc>, CloudflareBindingError> =>\n Effect.suspend(() => {\n if (typeof env !== \"object\" || env === null) {\n return Effect.fail(\n CloudflareBindingError.make({\n binding,\n message: \"The Worker environment is not an object; no bindings are available.\",\n }),\n );\n }\n const candidate: unknown = (env as Record<string, unknown>)[binding];\n if (\n typeof candidate === \"object\" &&\n candidate !== null &&\n \"idFromName\" in candidate &&\n typeof candidate.idFromName === \"function\" &&\n \"get\" in candidate &&\n typeof candidate.get === \"function\"\n ) {\n // The structural probe above is the entire runtime contract this package relies on;\n // the assertion records that `idFromName`/`get` name a DurableObjectNamespace.\n return Effect.succeed(candidate as DurableObjectNamespace<ConversationObjectRpc>);\n }\n return Effect.fail(\n CloudflareBindingError.make({\n binding,\n message:\n `env.${binding} is not a DurableObjectNamespace binding; declare the Conversation ` +\n \"Object class under this binding in the Worker configuration.\",\n }),\n );\n });\n\n/** `ConversationObjectNamespace` built from the untyped Worker `env` (fails typed). */\nexport const conversationNamespaceLayer = (\n env: unknown,\n binding: string,\n): Layer.Layer<ConversationObjectNamespace, CloudflareBindingError> =>\n Layer.effect(ConversationObjectNamespace)(\n Effect.map(conversationNamespaceFromEnv(env, binding), (namespace) => ({ namespace })),\n );\n\n/**\n * The live Durable Object execution context of THIS incarnation. Only Layer construction and\n * the alarm service consume it; important state never lives on it (`ctx.storage` is truth,\n * everything in memory is a cache — deployment spec §11).\n */\nexport class DurableObjectContext extends Context.Service<\n DurableObjectContext,\n {\n readonly ctx: DurableObjectState;\n readonly env: unknown;\n }\n>()(\"@effect-agent/platform-cloudflare/DurableObjectContext\") {\n static layer(ctx: DurableObjectState, env: unknown): Layer.Layer<DurableObjectContext> {\n return Layer.succeed(DurableObjectContext)({ ctx, env });\n }\n}\n\n/**\n * The Conversation identity this Object serializes and the producer identity its Attempts\n * write with (`{producerPrefix}:{conversationId}`, plan §1.4). Derived once per incarnation\n * from `ctx.id.name` — the Object identity rule guarantees the name IS the Conversation ID.\n */\nexport class ConversationObjectIdentity extends Context.Service<\n ConversationObjectIdentity,\n {\n readonly conversationId: ConversationId;\n readonly producerId: ProducerId;\n }\n>()(\"@effect-agent/platform-cloudflare/ConversationObjectIdentity\") {}\n","import { DEFAULT_OWNERSHIP_LEASE_DURATION, DeploymentId } from \"@effect-agent/session\";\nimport { DEFAULT_MAX_STORED_VALUE_BYTES } from \"@effect-agent/storage-cloudflare\";\nimport { Context, Duration, Schema } from \"effect\";\n\n/**\n * Schema-validated configuration for the Cloudflare durable runtime (deployment spec §4:\n * decoded once during Layer construction, exposed as a typed service; DEPLOY-003). Every\n * cadence is in milliseconds; every bound is finite and checked before any resource opens.\n */\n\nconst PositiveMillis = Schema.Int.check(Schema.isGreaterThan(0));\nconst NonNegativeMillis = Schema.Int.check(Schema.isGreaterThanOrEqualTo(0));\n\n/** The supplied Cloudflare durable runtime configuration failed validation (DEPLOY-003). */\nexport class CloudflarePlatformConfigError extends Schema.TaggedErrorClass<CloudflarePlatformConfigError>()(\n \"CloudflarePlatformConfigError\",\n {\n message: Schema.String,\n cause: Schema.optionalKey(Schema.Defect()),\n },\n) {}\n\n/**\n * An admission was refused by a host resource limit BEFORE any ledger row existed\n * (deployment spec §8, DEPLOY-007: \"Admission has explicit bounded quota and overload\n * behavior... a typed rejection\"). This is the DC analogue of `NodeDurableHost`'s\n * `AdmissionClosed` host gate: the port surface stays untouched, the refusal happens in the\n * Conversation Object's submit entry point before `DurableAgentRuntime.submit` runs, and\n * nothing was admitted or written.\n */\nexport class AdmissionLimitExceeded extends Schema.TaggedErrorClass<AdmissionLimitExceeded>()(\n \"AdmissionLimitExceeded\",\n {\n limit: Schema.Literals([\"queue-depth\", \"input-bytes\", \"database-bytes\"]),\n actual: Schema.Int,\n maximum: Schema.Int,\n },\n) {\n override get message() {\n return (\n `Admission refused before any ledger row existed: ${this.limit} ${this.actual} exceeds ` +\n `the configured maximum ${this.maximum}. Accepted work is unaffected; retry after the ` +\n \"lane drains or raise the limit (DEPLOY-007).\"\n );\n }\n}\n\n/** The platform's hard per-Object database cap (10 GB, developers.cloudflare.com limits). */\nexport const CLOUDFLARE_DATABASE_CAP_BYTES = 10_000_000_000;\n\n/** Default database-size admission ceiling: a 1 GB safety margin under the platform cap. */\nexport const DEFAULT_MAX_DATABASE_BYTES = 9_000_000_000;\n\n/**\n * Explicit bounded admission quotas checked by the Conversation Object BEFORE admission\n * (exit gate \"resource limits are checked before admission\").\n */\nexport class CloudflareAdmissionLimitsValue extends Schema.Class<CloudflareAdmissionLimitsValue>(\n \"@effect-agent/platform-cloudflare/CloudflareAdmissionLimitsValue\",\n)({\n /** Maximum nonterminal Submissions per Conversation lane before new admissions refuse. */\n maxQueueDepthPerLane: Schema.Int.check(\n Schema.isGreaterThan(0),\n Schema.isLessThanOrEqualTo(100_000),\n ),\n /** Maximum encoded input bytes; never above the storage per-value bound. */\n maxInputBytes: Schema.Int.check(Schema.isGreaterThan(0), Schema.isLessThanOrEqualTo(2_000_000)),\n /** Maximum `ctx.storage.sql.databaseSize` at admission; stays under the 10 GB platform cap. */\n maxDatabaseBytes: Schema.Int.check(\n Schema.isGreaterThan(0),\n Schema.isLessThanOrEqualTo(CLOUDFLARE_DATABASE_CAP_BYTES),\n ),\n}) {}\n\n/**\n * Validated Cloudflare durable runtime configuration. The producer identity of one\n * Conversation Object is `{producerPrefix}:{conversationId}` — stable across incarnations of\n * the same deployment, distinct across deployments — and producer-epoch fencing (not the\n * producer name) remains the correctness authority (DUR-006).\n */\nexport class CloudflareDurableRuntimeConfigValue extends Schema.Class<CloudflareDurableRuntimeConfigValue>(\n \"@effect-agent/platform-cloudflare/CloudflareDurableRuntimeConfigValue\",\n)({\n deploymentId: DeploymentId,\n /** Head of the minted producer identity `{producerPrefix}:{conversationId}`. */\n producerPrefix: Schema.NonEmptyString.check(Schema.isMaxLength(256)),\n /** Submission ownership lease duration (D5); fences work across Object incarnations. */\n ownershipLeaseDuration: PositiveMillis,\n /** Base delay of the alarm re-arm backoff when a pass makes no progress. */\n alarmBackoffBase: PositiveMillis,\n /** Ceiling of the alarm re-arm backoff. */\n alarmBackoffCap: PositiveMillis,\n /**\n * The maintenance-pass scan cadence and the ceiling of every re-arm delay: nonterminal\n * work is revisited at least this often (wake/scan pairing, persistence §14).\n */\n wakeScanInterval: PositiveMillis,\n /** `awaitSettlement` ledger re-check cadence when no wake arrives. */\n settlementPollInterval: PositiveMillis,\n /** Worker ownership-lease renewal cadence during an active Attempt. */\n leaseRenewalInterval: PositiveMillis,\n /** Active-Run abort-intent poll cadence. */\n abortPollInterval: PositiveMillis,\n /** Canonical observation poll cadence of the Durable Object store. */\n observationPollInterval: NonNegativeMillis,\n /** Per-value byte bound; must stay under the platform's 2 MB SQLite value limit. */\n maxStoredValueBytes: Schema.Int.check(\n Schema.isGreaterThan(0),\n Schema.isLessThanOrEqualTo(2_000_000),\n ),\n /** Opt-in full payload/digest-chain audit while opening the store. */\n verifyOnOpen: Schema.Boolean,\n limits: CloudflareAdmissionLimitsValue,\n}) {}\n\n/** Explicit configuration authority for the assembled Cloudflare durable runtime. */\nexport class CloudflareDurableRuntimeConfig extends Context.Service<\n CloudflareDurableRuntimeConfig,\n CloudflareDurableRuntimeConfigValue\n>()(\"@effect-agent/platform-cloudflare/CloudflareDurableRuntimeConfig\") {}\n\n/** Documented production defaults applied by `CloudflareDurableRuntime.layer`. */\nexport const CLOUDFLARE_RUNTIME_DEFAULTS = {\n ownershipLeaseDuration: Duration.toMillis(DEFAULT_OWNERSHIP_LEASE_DURATION),\n alarmBackoffBase: 100,\n alarmBackoffCap: 5_000,\n wakeScanInterval: 1_000,\n settlementPollInterval: 500,\n leaseRenewalInterval: 10_000,\n abortPollInterval: 500,\n observationPollInterval: 25,\n maxStoredValueBytes: DEFAULT_MAX_STORED_VALUE_BYTES,\n verifyOnOpen: false,\n maxQueueDepthPerLane: 256,\n maxInputBytes: DEFAULT_MAX_STORED_VALUE_BYTES,\n maxDatabaseBytes: DEFAULT_MAX_DATABASE_BYTES,\n} as const;\n","import {\n AgentBindingResolver,\n DurableAgentRuntime,\n SubmissionLedger,\n type DurableBindingFailure,\n type DurableWorkerFailure,\n type RecoveryReport,\n} from \"@effect-agent/session\";\nimport { Clock, Context, Effect, Layer, Option, Random, Ref, Schema, Stream } from \"effect\";\n\nimport { ConversationObjectIdentity, DurableObjectContext } from \"./bindings.ts\";\nimport { CloudflareDurableRuntimeConfig } from \"./config.ts\";\n\n/**\n * The single multiplexed Durable Object alarm (decision D-P6-2). A Durable Object has ONE\n * alarm slot; every cadence the Node host ran on fibers (wake scan, lease expiry, settlement\n * and abort re-checks, retry backoff) multiplexes into one idempotent maintenance pass, and\n * the slot always holds the EARLIEST deadline any caller asked for.\n *\n * The alarm invariant (plan §1.4): committed nonterminal work implies a committed alarm.\n * It is established by pre-arming — every mutating entry point and every pass arms the alarm\n * BEFORE its durable mutations — so an eviction at any failpoint leaves a persisted alarm\n * that workerd re-delivers to a fresh incarnation WITHOUT any incoming request. Spurious\n * alarms are harmless by design: a pass over an all-settled lane simply deletes the slot.\n */\n\n/** The Durable Object alarm API failed; surfaces on host entry points as a typed refusal. */\nexport class DurableAlarmError extends Schema.TaggedErrorClass<DurableAlarmError>()(\n \"DurableAlarmError\",\n {\n operation: Schema.String,\n message: Schema.String,\n cause: Schema.optionalKey(Schema.Defect()),\n },\n) {}\n\nconst alarmFailure =\n (operation: string) =>\n (cause: unknown): DurableAlarmError =>\n DurableAlarmError.make({\n operation,\n message: cause instanceof Error ? cause.message : String(cause),\n cause,\n });\n\n/** `ctx.storage` alarm slot as an Effect service; storage is truth, never a memory field. */\nexport class DurableAlarmService extends Context.Service<\n DurableAlarmService,\n {\n /** The scheduled deadline in epoch milliseconds, if any. */\n readonly scheduled: Effect.Effect<Option.Option<number>, DurableAlarmError>;\n /** Replace the slot with this deadline. */\n readonly scheduleAt: (epochMillis: number) => Effect.Effect<void, DurableAlarmError>;\n /** Keep the EARLIER of the existing deadline and this one (the multiplexing rule). */\n readonly ensureScheduledBy: (epochMillis: number) => Effect.Effect<void, DurableAlarmError>;\n /**\n * Arm an immediate alarm (the durable, coalescing local wake) — DEFERRED while a\n * maintenance pass is executing. Workerd cancels an in-flight alarm handler when a new\n * EARLIER deadline is written during its execution (`requestScheduledAlarm`), and the\n * maintenance pass runs INSIDE the alarm handler: an immediate wake landing mid-pass\n * (a routed port mutation, a sibling's `wake()`, the coordinator's own local notify)\n * would kill the running Attempt — manufacturing an ownership loss no real eviction\n * caused, and routing open uncertain-class Tool Calls into spurious Unknown Outcomes.\n * Deferral is contract-safe: wakes are droppable hints, every mutating entry point\n * pre-arms BEFORE its first durable mutation (the alarm invariant never rests on this\n * call), and the deferred wake is flushed when the pass completes.\n */\n readonly scheduleNow: Effect.Effect<void, DurableAlarmError>;\n /**\n * Run one maintenance pass with wake deferral (see `scheduleNow`): `scheduleNow` calls\n * while `body` executes coalesce into one flag, flushed as an immediate re-arm after the\n * pass — failures of the flush are logged and swallowed (hints are droppable; the pass's\n * own re-arm policy already bounded the next delivery).\n */\n readonly withWakesDeferred: <A, E, R>(body: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R>;\n /** Clear the slot; only the maintenance pass does this, and only when all work settled. */\n readonly cancel: Effect.Effect<void, DurableAlarmError>;\n }\n>()(\"@effect-agent/platform-cloudflare/DurableAlarmService\") {\n static readonly layer: Layer.Layer<DurableAlarmService, never, DurableObjectContext> =\n Layer.effect(DurableAlarmService)(\n Effect.gen(function* () {\n const { ctx } = yield* DurableObjectContext;\n /**\n * In-memory pass bookkeeping — a pure CACHE, never state: a fresh incarnation has no\n * running pass, and a deferred wake lost to eviction was only ever a promptness hint\n * on top of the already-committed pre-armed alarm.\n */\n const runningPasses = yield* Ref.make(0);\n const wakeDeferred = yield* Ref.make(false);\n const scheduled = Effect.tryPromise({\n try: () => ctx.storage.getAlarm(),\n catch: alarmFailure(\"get alarm\"),\n }).pipe(\n Effect.map((deadline) =>\n deadline === null ? Option.none<number>() : Option.some(deadline),\n ),\n );\n const scheduleAt = (epochMillis: number) =>\n Effect.tryPromise({\n try: () => ctx.storage.setAlarm(epochMillis),\n catch: alarmFailure(\"set alarm\"),\n });\n const ensureScheduledBy = (epochMillis: number) =>\n scheduled.pipe(\n Effect.flatMap((existing) =>\n Option.isSome(existing) && existing.value <= epochMillis\n ? Effect.void\n : scheduleAt(epochMillis),\n ),\n );\n const armNow = Clock.currentTimeMillis.pipe(\n Effect.flatMap((now) => ensureScheduledBy(now)),\n );\n const scheduleNow = Ref.get(runningPasses).pipe(\n Effect.flatMap((passes) => (passes > 0 ? Ref.set(wakeDeferred, true) : armNow)),\n );\n /**\n * Flush after the LAST concurrent pass: the re-arm lands at the very end of the alarm\n * handler, where a superseding cancellation only re-delivers to the already-idempotent\n * pass. Runs inside `Effect.ensuring`, so flush failures are logged, never raised.\n */\n const flushDeferredWake = Ref.get(runningPasses).pipe(\n Effect.flatMap((passes) =>\n passes > 0\n ? Effect.void\n : Ref.getAndSet(wakeDeferred, false).pipe(\n Effect.flatMap((wanted) => (wanted ? armNow : Effect.void)),\n ),\n ),\n Effect.catch((error) =>\n Effect.logWarning(\"DurableAlarmService: deferred wake flush failed\", error),\n ),\n );\n const withWakesDeferred = <A, E, R>(body: Effect.Effect<A, E, R>): Effect.Effect<A, E, R> =>\n Ref.update(runningPasses, (passes) => passes + 1).pipe(\n Effect.andThen(body),\n Effect.ensuring(\n Ref.update(runningPasses, (passes) => passes - 1).pipe(\n Effect.andThen(flushDeferredWake),\n ),\n ),\n );\n const cancel = Effect.tryPromise({\n try: () => ctx.storage.deleteAlarm(),\n catch: alarmFailure(\"delete alarm\"),\n });\n return DurableAlarmService.of({\n scheduled,\n scheduleAt,\n ensureScheduledBy,\n scheduleNow,\n withWakesDeferred,\n cancel,\n });\n }),\n );\n}\n\n/** What one maintenance pass did — auditable evidence mirroring `NodeDurableHost`'s report. */\nexport class MaintenancePassReport extends Schema.Class<MaintenancePassReport>(\n \"@effect-agent/platform-cloudflare/MaintenancePassReport\",\n)({\n /** Recovery decisions executed (or deferred) BEFORE any new claim in this pass. */\n recovered: Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)),\n /** Settlements the drain pass finalized. */\n settled: Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)),\n /** Submissions still nonterminal after the pass (suspended/unknown lanes stay honest). */\n nonterminal: Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)),\n /** `rearmed` while nonterminal work remains, `cleared` once everything settled. */\n alarm: Schema.Literals([\"rearmed\", \"cleared\"]),\n}) {}\n\nexport type MaintenancePassFailure =\n | DurableWorkerFailure\n | DurableBindingFailure\n | DurableAlarmError;\n\n/**\n * The idempotent maintenance pass and the alarm-invariant helpers (plan §1.4, D-P6-1/2).\n *\n * `pass` = pre-arm → `runRecovery` → `processConversationResolved` → re-arm-or-clear:\n *\n * 1. **Pre-arm**: the alarm is re-armed at `now + wakeScanInterval` BEFORE any work, so an\n * eviction (or thrown failure → workerd alarm retry) at any point of the pass leaves a\n * committed alarm and the fresh incarnation converges without an incoming request.\n * 2. **Reconcile before new work** (exit gate): every pass classifies and repairs every\n * nonterminal Submission before the drain claims anything; the pure classifier and the\n * repair executors are idempotent, so at-least-once alarm delivery re-runs them safely.\n * 3. **Drain**: one bounded `processConversationResolved` pass over this Object's lane — the\n * D-P6-1 shape; no infinite `runResolvedWorker` loop ever pins the Object.\n * 4. **Re-arm policy**: nonterminal work re-arms at `now + min(backoff-with-jitter,\n * wakeScanInterval)` — the scan interval bounds every wait (lease expiry of a dead\n * incarnation included, since claims retry each pass) and the backoff (reset on progress,\n * grown otherwise) keeps stuck lanes from busy-spinning; all settled clears the slot.\n *\n * Every step is a durability-protocol step that already tolerates re-execution, which is\n * what makes double-fired alarms harmless (the alarm.test.ts gate).\n */\nexport class ConversationMaintenance extends Context.Service<\n ConversationMaintenance,\n {\n /** One idempotent maintenance pass; failures propagate so workerd retries the alarm. */\n readonly pass: Effect.Effect<MaintenancePassReport, MaintenancePassFailure>;\n /**\n * Defensive half of the alarm invariant, run by the constructor gate: if any local\n * Submission is nonterminal and no alarm is scheduled, arm one within the scan interval.\n * Local-only (one ledger scan + the alarm slot) — never a recovery pass, never transport.\n */\n readonly ensureAlarm: Effect.Effect<void, MaintenancePassFailure>;\n /**\n * The pre-arm every mutating entry point runs BEFORE its first durable mutation: with\n * the alarm committed first, a committed admission (or any other committed nonterminal\n * transition) can never be observed without the alarm that will finish it.\n */\n readonly preArm: Effect.Effect<void, DurableAlarmError>;\n }\n>()(\"@effect-agent/platform-cloudflare/ConversationMaintenance\") {\n static readonly layer: Layer.Layer<\n ConversationMaintenance,\n never,\n | DurableAgentRuntime\n | AgentBindingResolver\n | SubmissionLedger\n | DurableAlarmService\n | CloudflareDurableRuntimeConfig\n | ConversationObjectIdentity\n > = Layer.effect(ConversationMaintenance)(\n Effect.gen(function* () {\n const runtime = yield* DurableAgentRuntime;\n const resolver = yield* AgentBindingResolver;\n const ledger = yield* SubmissionLedger;\n const alarm = yield* DurableAlarmService;\n const config = yield* CloudflareDurableRuntimeConfig;\n const identity = yield* ConversationObjectIdentity;\n\n /**\n * Consecutive no-progress passes — an in-memory CACHE, not state: a fresh incarnation\n * restarts at zero and merely re-arms sooner than a long-lived one would have.\n */\n const stalls = yield* Ref.make(0);\n\n const preArm = Clock.currentTimeMillis.pipe(\n Effect.flatMap((now) => alarm.ensureScheduledBy(now + config.wakeScanInterval)),\n );\n\n const countNonterminal = Stream.runCollect(ledger.scanNonterminal).pipe(\n Effect.map((snapshots) => snapshots.length),\n );\n\n const rearmDelay = Effect.fn(\"ConversationMaintenance.rearmDelay\")(function* (\n progressed: boolean,\n ) {\n const priorStalls = yield* Ref.getAndUpdate(stalls, (count) =>\n progressed ? 0 : count + 1,\n );\n if (progressed) return config.alarmBackoffBase;\n const exponent = Math.min(priorStalls, 30);\n const backoff = Math.min(config.alarmBackoffCap, config.alarmBackoffBase * 2 ** exponent);\n const jitter = yield* Random.next;\n // Full jitter over [backoff/2, backoff]: desynchronizes retry storms without ever\n // waiting longer than the deterministic bound.\n const jittered = Math.ceil(backoff / 2 + (backoff / 2) * jitter);\n return Math.min(jittered, config.wakeScanInterval);\n });\n\n const pass = Effect.fn(\"ConversationMaintenance.pass\")(function* (): Effect.fn.Return<\n MaintenancePassReport,\n MaintenancePassFailure\n > {\n // Step 1 — pre-arm: an abort or throw anywhere below leaves a committed alarm.\n yield* preArm;\n // Step 2 — reconciliation strictly precedes new work in this pass (exit gate).\n const recovered: ReadonlyArray<RecoveryReport> = yield* runtime.runRecovery;\n // Step 3 — one bounded drain pass over this Object's own lane.\n const settlements = yield* runtime\n .processConversationResolved(identity.conversationId)\n .pipe(Effect.provideService(AgentBindingResolver, resolver));\n // Step 4 — re-arm or clear.\n const nonterminal = yield* countNonterminal;\n if (nonterminal === 0) {\n yield* alarm.cancel;\n yield* Ref.set(stalls, 0);\n // Close the cancel/admission interleaving window: a submission committing between\n // the count and the cancel (Durable Object events interleave at storage-operation\n // boundaries) must not be left without its alarm. The recount re-arms if anything\n // appeared; the submit entry's own `scheduleNow` covers commits after the recount.\n const appeared = yield* countNonterminal;\n if (appeared > 0) {\n yield* preArm;\n return MaintenancePassReport.make({\n recovered: recovered.length,\n settled: settlements.length,\n nonterminal: appeared,\n alarm: \"rearmed\",\n });\n }\n return MaintenancePassReport.make({\n recovered: recovered.length,\n settled: settlements.length,\n nonterminal,\n alarm: \"cleared\",\n });\n }\n const progressed =\n settlements.length > 0 || recovered.some((report) => report.disposition === \"repaired\");\n const delay = yield* rearmDelay(progressed);\n const now = yield* Clock.currentTimeMillis;\n yield* alarm.ensureScheduledBy(now + delay);\n return MaintenancePassReport.make({\n recovered: recovered.length,\n settled: settlements.length,\n nonterminal,\n alarm: \"rearmed\",\n });\n });\n\n const ensureAlarm = Effect.fn(\"ConversationMaintenance.ensureAlarm\")(function* () {\n const nonterminal = yield* countNonterminal;\n if (nonterminal === 0) return;\n yield* preArm;\n });\n\n return ConversationMaintenance.of({\n // Wake deferral (see `DurableAlarmService.scheduleNow`): an immediate wake written\n // while THIS handler runs would make workerd cancel it mid-Attempt; deferring keeps\n // the running pass alive and flushes the hint as the pass's final re-arm.\n pass: alarm.withWakesDeferred(pass()),\n ensureAlarm: ensureAlarm(),\n preArm,\n });\n }),\n );\n}\n","import type { ConversationId } from \"@effect-agent/core\";\nimport { WakeScheduler } from \"@effect-agent/session\";\nimport { Effect, Layer, PubSub, Schema, Stream } from \"effect\";\n\nimport { DurableAlarmService } from \"./alarm.ts\";\nimport { ConversationObjectIdentity, ConversationObjectNamespace } from \"./bindings.ts\";\n\n/**\n * Bounded in-memory wake buffer for same-incarnation `awaitSettlement` subscribers. Wake\n * hints are droppable by contract (consumers pair every subscription with ledger polls), so\n * a full buffer slides out the oldest hint and an eviction simply loses the buffer — the\n * poll interval and the persisted alarm keep liveness (persistence §14).\n */\nconst WAKE_BUFFER_CAPACITY = 1_024;\n\n/** A remote wake stub call failed; always swallowed and logged (hints are droppable). */\nclass RemoteWakeDropped extends Schema.TaggedErrorClass<RemoteWakeDropped>()(\"RemoteWakeDropped\", {\n conversationId: Schema.String,\n message: Schema.String,\n cause: Schema.optionalKey(Schema.Defect()),\n}) {}\n\n/**\n * The DC `WakeScheduler` (plan §1.4):\n *\n * - `notify(local)` → `setAlarm(now)` — durable, cheap, coalescing (the alarm slot keeps the\n * earliest deadline) — plus a same-incarnation PubSub hint for `awaitSettlement` waiters.\n * - `notify(remote)` → fire-and-forget `wake()` on the owning Object's stub with every error\n * swallowed and logged: hints are droppable, and the target's own alarm/scan pairing (the\n * maintenance pass re-polls unsettled children) guarantees liveness without this call.\n * - `wakes` → the bounded sliding PubSub only. No important state lives in memory: the\n * subscription accelerates waiters within one incarnation and the settlement poll interval\n * is the correctness path.\n */\nexport const cloudflareWakeSchedulerLayer: Layer.Layer<\n WakeScheduler,\n never,\n DurableAlarmService | ConversationObjectIdentity | ConversationObjectNamespace\n> = Layer.effect(WakeScheduler)(\n Effect.gen(function* () {\n const alarm = yield* DurableAlarmService;\n const identity = yield* ConversationObjectIdentity;\n const { namespace } = yield* ConversationObjectNamespace;\n const hints = yield* PubSub.sliding<ConversationId>(WAKE_BUFFER_CAPACITY);\n yield* Effect.addFinalizer(() => PubSub.shutdown(hints));\n\n const notifyLocal = (conversationId: ConversationId) =>\n PubSub.publish(hints, conversationId).pipe(\n Effect.andThen(alarm.scheduleNow),\n Effect.catch((error) =>\n // `notify` never fails by contract; a failed alarm write degrades to \"hint lost\"\n // and the pass re-arm (or the next entry point's pre-arm) restores the invariant.\n Effect.logWarning(\"CloudflareWakeScheduler: local alarm wake failed\", error),\n ),\n Effect.asVoid,\n );\n\n const notifyRemote = (conversationId: ConversationId) =>\n Effect.tryPromise({\n try: () => namespace.get(namespace.idFromName(conversationId)).wake(),\n catch: (cause) =>\n RemoteWakeDropped.make({\n conversationId,\n message: cause instanceof Error ? cause.message : String(cause),\n cause,\n }),\n }).pipe(\n Effect.catch((error) =>\n Effect.logWarning(\n `CloudflareWakeScheduler: remote wake of ${conversationId} dropped`,\n error,\n ),\n ),\n Effect.asVoid,\n );\n\n return WakeScheduler.of({\n notify: (conversationId) =>\n conversationId === identity.conversationId\n ? notifyLocal(conversationId)\n : notifyRemote(conversationId),\n wakes: Stream.fromPubSub(hints),\n });\n }),\n);\n","import { ConversationPortTransport, portTransportFailure } from \"@effect-agent/storage-cloudflare\";\nimport { Effect, Layer } from \"effect\";\n\nimport { ConversationObjectNamespace } from \"./bindings.ts\";\n\n/**\n * `ConversationPortTransport` over native Durable Object JS RPC (decision D-P6-3): one\n * `portCall(envelope)` on the stub of the Object that owns the addressed Conversation\n * (`namespace.idFromName(conversationId)` — 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 conversationPortTransportLayer: Layer.Layer<\n ConversationPortTransport,\n never,\n ConversationObjectNamespace\n> = Layer.effect(ConversationPortTransport)(\n Effect.gen(function* () {\n const { namespace } = yield* ConversationObjectNamespace;\n return ConversationPortTransport.of({\n call: (conversationId, request) =>\n Effect.tryPromise({\n try: () => namespace.get(namespace.idFromName(conversationId)).portCall(request),\n catch: (cause) => portTransportFailure(conversationId, cause),\n }).pipe(\n Effect.withSpan(\"CloudflarePortTransport.call\", {\n attributes: { conversationId },\n }),\n ),\n });\n }),\n);\n","import { ConversationId } from \"@effect-agent/core\";\nimport {\n AgentBindingResolver,\n ConversationStore,\n DurableAgentRuntime,\n DurableRuntimeConfig,\n DurableRuntimeFailpoint,\n ProducerId,\n SubmissionLedger,\n ToolReconciler,\n WakeScheduler,\n type DurableRuntimeFailpointHandler,\n type ResolvedBinding,\n} from \"@effect-agent/session\";\nimport {\n conversationStoreLayer,\n handleEncodedPortRequest,\n routedConversationStoreLayer,\n routedSubmissionLedgerLayer,\n storageConfigLayer,\n storageFailpointLayer,\n submissionLedgerLayer,\n type DoStorageFailpointHandler,\n type DoStorageInitializationError,\n type DoStorageOptions,\n} from \"@effect-agent/storage-cloudflare\";\nimport { BrowserCrypto } from \"@effect/platform-browser\";\nimport { SqliteClient } from \"@effect/sql-sqlite-do\";\nimport { Context, Duration, Effect, Layer, Schema } from \"effect\";\n\nimport { ConversationMaintenance, DurableAlarmService } from \"./alarm.ts\";\nimport {\n ConversationObjectIdentity,\n ConversationObjectNamespace,\n DurableObjectContext,\n} from \"./bindings.ts\";\nimport {\n CLOUDFLARE_RUNTIME_DEFAULTS,\n CloudflareDurableRuntimeConfig,\n CloudflareDurableRuntimeConfigValue,\n CloudflarePlatformConfigError,\n} from \"./config.ts\";\nimport { conversationPortTransportLayer } from \"./transport.ts\";\nimport { cloudflareWakeSchedulerLayer } from \"./wake-scheduler.ts\";\n\n/**\n * Raw (unvalidated) construction options for `CloudflareDurableRuntime.layer`, mirroring\n * `NodeDurableRuntimeOptions`. 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}:{conversationId}`. */\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 /** 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 /**\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 * Registered worker Bindings resolved at durable claim time (S2, spec/subagents.md §11):\n * build each with `DurableWorkerBinding.make(binding, digests)`. An Effect form is accepted\n * because the capture is effectful; it runs once per incarnation during Layer construction.\n * Defaults to the empty registration (every resolved claim fails closed).\n */\n readonly bindings?:\n | ReadonlyArray<ResolvedBinding>\n | Effect.Effect<ReadonlyArray<ResolvedBinding>>\n | undefined;\n}\n\n/** Every construction failure of the assembled Cloudflare durable runtime stack. */\nexport type CloudflareDurableRuntimeInitializationError =\n | CloudflarePlatformConfigError\n | DoStorageInitializationError;\n\n/** The services `CloudflareDurableRuntime.layer` provides. */\nexport type CloudflareDurableRuntimeServices =\n | DurableAgentRuntime\n | SubmissionLedger\n | ConversationStore\n | WakeScheduler\n | DurableRuntimeConfig\n | AgentBindingResolver\n | CloudflareDurableRuntimeConfig\n | ConversationObjectIdentity\n | DurableAlarmService\n | ConversationMaintenance\n | ConversationObjectPorts;\n\n/**\n * Owner-side endpoint body for the Conversation Object's `portCall` (plan §1.3): decode,\n * execute against THIS Object's LOCAL port facets — never the routed decorators, so a\n * request cannot bounce between Objects — and answer the encoded response envelope. Total by\n * construction (protocol anomalies answer `PortFailed(PortProtocolError)`).\n */\nexport class ConversationObjectPorts extends Context.Service<\n ConversationObjectPorts,\n {\n readonly handle: (encoded: unknown) => Effect.Effect<unknown>;\n }\n>()(\"@effect-agent/platform-cloudflare/ConversationObjectPorts\") {}\n\nconst decodeConfigValue = Schema.decodeUnknownEffect(CloudflareDurableRuntimeConfigValue);\nconst decodeConversationId = Schema.decodeUnknownEffect(ConversationId);\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 Conversation this Object owns, from the Object identity rule (plan §1.2): Conversation\n * Objects are addressed exclusively by `idFromName(conversationId)`, so `ctx.id.name` IS the\n * Conversation ID. An unnamed Object (from `newUniqueId`) is a deployment error, not a lane.\n */\nconst conversationIdFromState = (\n ctx: DurableObjectState,\n): Effect.Effect<ConversationId, CloudflarePlatformConfigError> =>\n ctx.id.name === undefined\n ? Effect.fail(\n CloudflarePlatformConfigError.make({\n message:\n \"This Durable Object was not created via idFromName(conversationId); Conversation \" +\n \"Objects must be addressed by their Conversation identity (plan §1.2).\",\n }),\n )\n : decodeConversationId(ctx.id.name).pipe(\n Effect.mapError((error) =>\n CloudflarePlatformConfigError.make({\n message: `The Durable Object name is not a valid ConversationId: ${error.message}`,\n cause: error,\n }),\n ),\n );\n\nconst resolveBindings = (\n bindings: CloudflareDurableRuntimeOptions[\"bindings\"],\n): Effect.Effect<ReadonlyArray<ResolvedBinding>> =>\n bindings === undefined\n ? Effect.succeed([])\n : Effect.isEffect(bindings)\n ? bindings\n : Effect.succeed(bindings);\n\n/**\n * The DC Layer assembly (deployment §12: a Layer-assembly library, not an app entrypoint;\n * plan §1.4). `layer(options)` decodes the configuration, derives this Object's Conversation\n * and producer identities, opens the Object's private SQLite database through\n * `@effect/sql-sqlite-do` for BOTH the Conversation Log and the Submission Ledger (so claims\n * fence the same producer epochs — ADR-0011 D7 transposed), wraps the local port facets with\n * the WP2 cross-Object routing decorators over the Durable Object RPC transport, wires the\n * alarm-backed wake scheduler and the maintenance pass, defaults reconciliation to the\n * fail-closed `ToolReconciler.uncertain`, and provides a ready `DurableAgentRuntime` on top.\n *\n * Storage compatibility is verified during construction: an incompatible database fails the\n * Layer typed (`DoStorageCompatibilityError`) before anything is mutated (DEPLOY-008).\n *\n * Requires only the two binding services (`DurableObjectContext`,\n * `ConversationObjectNamespace`) — platform values enter exclusively through Layers\n * (DEPLOY-010).\n */\nexport class CloudflareDurableRuntime {\n static layer(\n options: CloudflareDurableRuntimeOptions,\n ): Layer.Layer<\n CloudflareDurableRuntimeServices,\n CloudflareDurableRuntimeInitializationError,\n DurableObjectContext | ConversationObjectNamespace\n > {\n return Layer.unwrap(\n Effect.gen(function* () {\n const { ctx } = yield* DurableObjectContext;\n const config = yield* configFromOptions(options);\n const conversationId = yield* conversationIdFromState(ctx);\n const producerId = yield* decodeProducerId(\n `${config.producerPrefix}:${conversationId}`,\n ).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 const identityLayer = Layer.succeed(ConversationObjectIdentity)({\n conversationId,\n producerId,\n });\n const cloudflareConfigLayer = Layer.succeed(CloudflareDurableRuntimeConfig)(config);\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 failpoint: options.storageFailpoint?.(ctx),\n };\n const infrastructure = Layer.mergeAll(\n storageConfigLayer(storageOptions),\n storageFailpointLayer(storageOptions),\n SqliteClient.layer({ storage: ctx.storage }),\n BrowserCrypto.layer,\n );\n\n /**\n * ONE local-facet instance (a shared Layer value) serves both the routed decorators\n * and the owner-side `portCall` executor — the executor must never see the routed\n * ports (plan §1.3: re-routing could bounce a request between Objects).\n */\n const localPorts = Layer.mergeAll(conversationStoreLayer, submissionLedgerLayer).pipe(\n Layer.provide(infrastructure),\n );\n\n const portsEndpointLayer = Layer.effect(ConversationObjectPorts)(\n Effect.gen(function* () {\n const local = yield* Effect.context<SubmissionLedger | ConversationStore>();\n return ConversationObjectPorts.of({\n handle: (encoded) => handleEncodedPortRequest(encoded).pipe(Effect.provide(local)),\n });\n }),\n ).pipe(Layer.provide(localPorts));\n\n const routedPorts = Layer.mergeAll(\n routedSubmissionLedgerLayer({ localConversationId: conversationId }),\n routedConversationStoreLayer({ localConversationId: conversationId }),\n ).pipe(Layer.provide(localPorts), Layer.provide(conversationPortTransportLayer));\n\n const runtimeConfigLayer = Layer.succeed(DurableRuntimeConfig)(\n DurableRuntimeConfig.make({\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 }),\n );\n\n const runtimeFailpointLayer =\n options.runtimeFailpoint === undefined\n ? DurableRuntimeFailpoint.layer\n : Layer.succeed(DurableRuntimeFailpoint)({ hit: options.runtimeFailpoint(ctx) });\n const reconcilerLayer = options.toolReconciler ?? ToolReconciler.uncertain;\n const bindingResolverLayer = Layer.effect(AgentBindingResolver)(\n Effect.map(resolveBindings(options.bindings), AgentBindingResolver.fromBindings),\n );\n\n const base = Layer.mergeAll(\n identityLayer,\n cloudflareConfigLayer,\n DurableAlarmService.layer,\n );\n\n const runtimeStack = DurableAgentRuntime.layer.pipe(\n Layer.provideMerge(routedPorts),\n Layer.provideMerge(cloudflareWakeSchedulerLayer),\n Layer.provideMerge(runtimeConfigLayer),\n Layer.provideMerge(bindingResolverLayer),\n Layer.provide(\n Layer.mergeAll(runtimeFailpointLayer, reconcilerLayer, BrowserCrypto.layer),\n ),\n Layer.provideMerge(base),\n );\n\n return Layer.mergeAll(\n runtimeStack,\n ConversationMaintenance.layer.pipe(Layer.provide(runtimeStack)),\n portsEndpointLayer,\n );\n }),\n );\n }\n}\n","import { AgentId, AgentInputError, type ConversationId } from \"@effect-agent/core\";\nimport {\n AbortCommand,\n AbortIntent,\n AdmissionConflict,\n AppendConflict,\n ApprovalConflict,\n ApprovalDecisionCommand,\n ApprovalDecisionIntent,\n CanonicalRecordEnvelope,\n CanonicalSequence,\n ConversationNotMaterialized,\n ConversationStoreError,\n DefinitionDigests,\n DigestError,\n DurableRuntimeFailpointError,\n FenceRejected,\n IdempotencyKey,\n JoinedToHost,\n LedgerError,\n PersistedJson,\n Principal,\n Receipt,\n Settlement,\n SettlementConflict,\n UnknownResolutionCommand,\n UnknownResolutionConflict,\n UnknownResolutionIntent,\n type DurableSubmitAgent,\n type DurableSubmitOptions,\n} from \"@effect-agent/session\";\nimport { Context, Effect, Layer, Schema } from \"effect\";\n\nimport { DurableAlarmError } from \"./alarm.ts\";\nimport { ConversationObjectNamespace, type ConversationObjectRpc } from \"./bindings.ts\";\nimport { AdmissionLimitExceeded } from \"./config.ts\";\n\n/**\n * The Worker↔Conversation-Object host protocol (plan §1.4): Schema envelopes for the host\n * entry points (`submitEncoded`, `awaitSettlementEncoded`, `observePage`, `abortEncoded`,\n * `resolveApprovalEncoded`, `resolveUnknownEncoded`) plus the Worker-side client that speaks\n * it. Mirrors the WP2 port protocol: requests and responses are closed Schema unions, typed\n * failures travel as their own tagged classes and RE-DECODE to identical tags on the caller\n * (error-tag fidelity), and protocol anomalies are answered typed instead of thrown.\n */\n\n/** Ceiling for host protocol diagnostic strings. */\nconst MAX_HOST_DIAGNOSTIC_LENGTH = 4_096;\n\nconst BoundedDiagnostic = Schema.String.check(Schema.isMaxLength(MAX_HOST_DIAGNOSTIC_LENGTH));\n\n/** Truncate a diagnostic string to the host protocol's bounded length. */\nexport const boundHostDiagnostic = (value: string): string =>\n value.length > MAX_HOST_DIAGNOSTIC_LENGTH\n ? `${value.slice(0, MAX_HOST_DIAGNOSTIC_LENGTH - 3)}...`\n : value;\n\n/**\n * The envelope itself could not be honored: the Object could not decode the request, or a\n * response could not be encoded/decoded. Never carries operation semantics.\n */\nexport class HostProtocolError extends Schema.TaggedErrorClass<HostProtocolError>()(\n \"HostProtocolError\",\n {\n message: BoundedDiagnostic,\n },\n) {}\n\n/** The Worker-side stub call itself failed (RPC rejection, overload, eviction mid-call). */\nexport class ConversationClientError extends Schema.TaggedErrorClass<ConversationClientError>()(\n \"ConversationClientError\",\n {\n conversationId: Schema.String,\n message: Schema.String,\n cause: Schema.optionalKey(Schema.Defect()),\n },\n) {}\n\n// ---------------------------------------------------------------------------\n// Requests\n// ---------------------------------------------------------------------------\n\n/**\n * One durable submission, input ALREADY encoded by the caller through the Agent Binding's\n * input schema (the Worker bundles the same Agent definitions as the Object, so schema\n * validation happens client-side; the resolved Binding re-validates at claim time). The\n * Conversation identity is deliberately absent — the addressed Object IS the lane.\n */\nexport class SubmitRequest extends Schema.Class<SubmitRequest>(\n \"@effect-agent/platform-cloudflare/SubmitRequest\",\n)({\n agentId: AgentId,\n principal: Principal,\n idempotencyKey: IdempotencyKey,\n definitions: DefinitionDigests,\n inputPayload: PersistedJson,\n}) {}\n\n/** One bounded page of canonical records after an optional sequence. */\nexport class ObservePageRequest extends Schema.Class<ObservePageRequest>(\n \"@effect-agent/platform-cloudflare/ObservePageRequest\",\n)({\n afterSequence: Schema.optionalKey(CanonicalSequence),\n limit: Schema.Int.check(Schema.isGreaterThan(0), Schema.isLessThanOrEqualTo(1_024)),\n}) {}\n\n// ---------------------------------------------------------------------------\n// Responses\n// ---------------------------------------------------------------------------\n\n/**\n * Every typed failure a host entry point can produce, plus the protocol's own errors. Same\n * closed-union discipline as the WP2 `PortFailure`: members re-decode to the SAME tagged\n * classes on the Worker side; `cause` chains travel as Schema defects without instance\n * fidelity (plan §2.8).\n */\nexport const HostFailure = Schema.Union([\n AgentInputError,\n DigestError,\n AdmissionConflict,\n SettlementConflict,\n ApprovalConflict,\n UnknownResolutionConflict,\n JoinedToHost,\n LedgerError,\n ConversationStoreError,\n ConversationNotMaterialized,\n AppendConflict,\n FenceRejected,\n DurableRuntimeFailpointError,\n AdmissionLimitExceeded,\n DurableAlarmError,\n HostProtocolError,\n]);\nexport type HostFailure = typeof HostFailure.Type;\n\nexport class SubmitSucceeded extends Schema.TaggedClass<SubmitSucceeded>(\n \"@effect-agent/platform-cloudflare/SubmitSucceeded\",\n)(\"SubmitSucceeded\", {\n receipt: Receipt,\n}) {}\n\nexport class SettlementReached extends Schema.TaggedClass<SettlementReached>(\n \"@effect-agent/platform-cloudflare/SettlementReached\",\n)(\"SettlementReached\", {\n settlement: Settlement,\n}) {}\n\nexport class ObservedPage extends Schema.TaggedClass<ObservedPage>(\n \"@effect-agent/platform-cloudflare/ObservedPage\",\n)(\"ObservedPage\", {\n records: Schema.Array(CanonicalRecordEnvelope).check(Schema.isMaxLength(1_024)),\n}) {}\n\nexport class AbortRecorded extends Schema.TaggedClass<AbortRecorded>(\n \"@effect-agent/platform-cloudflare/AbortRecorded\",\n)(\"AbortRecorded\", {\n intent: AbortIntent,\n}) {}\n\nexport class ApprovalRecorded extends Schema.TaggedClass<ApprovalRecorded>(\n \"@effect-agent/platform-cloudflare/ApprovalRecorded\",\n)(\"ApprovalRecorded\", {\n intent: ApprovalDecisionIntent,\n}) {}\n\nexport class UnknownResolutionRecorded extends Schema.TaggedClass<UnknownResolutionRecorded>(\n \"@effect-agent/platform-cloudflare/UnknownResolutionRecorded\",\n)(\"UnknownResolutionRecorded\", {\n intent: UnknownResolutionIntent,\n}) {}\n\n/** The entry point failed TYPED on the Object; the failure re-decodes verbatim. */\nexport class HostFailed extends Schema.TaggedClass<HostFailed>(\n \"@effect-agent/platform-cloudflare/HostFailed\",\n)(\"HostFailed\", {\n failure: HostFailure,\n}) {}\n\n/** The uniform answer of one host entry point. Callers narrow by the tag their call implies. */\nexport const HostResponse = Schema.Union([\n SubmitSucceeded,\n SettlementReached,\n ObservedPage,\n AbortRecorded,\n ApprovalRecorded,\n UnknownResolutionRecorded,\n HostFailed,\n]);\nexport type HostResponse = typeof HostResponse.Type;\n\n// ---------------------------------------------------------------------------\n// Codecs (shared by the Object endpoints and the Worker client)\n// ---------------------------------------------------------------------------\n\nexport const decodeSubmitRequest = Schema.decodeUnknownEffect(SubmitRequest);\nexport const encodeSubmitRequest = Schema.encodeEffect(SubmitRequest);\nexport const decodeReceipt = Schema.decodeUnknownEffect(Receipt);\nexport const encodeReceipt = Schema.encodeEffect(Receipt);\nexport const decodeObservePageRequest = Schema.decodeUnknownEffect(ObservePageRequest);\nexport const encodeObservePageRequest = Schema.encodeEffect(ObservePageRequest);\nexport const decodeAbortCommand = Schema.decodeUnknownEffect(AbortCommand);\nexport const encodeAbortCommand = Schema.encodeEffect(AbortCommand);\nexport const decodeApprovalDecisionCommand = Schema.decodeUnknownEffect(ApprovalDecisionCommand);\nexport const encodeApprovalDecisionCommand = Schema.encodeEffect(ApprovalDecisionCommand);\nexport const decodeUnknownResolutionCommand = Schema.decodeUnknownEffect(UnknownResolutionCommand);\nexport const encodeUnknownResolutionCommand = Schema.encodeEffect(UnknownResolutionCommand);\nexport const encodeHostResponse = Schema.encodeEffect(HostResponse);\nexport const decodeHostResponse = Schema.decodeUnknownEffect(HostResponse);\n\n// ---------------------------------------------------------------------------\n// Worker-side client\n// ---------------------------------------------------------------------------\n\n/** Failure surface of `CloudflareConversationClient.submit`. */\nexport type ClientSubmitFailure =\n | AgentInputError\n | DigestError\n | AdmissionConflict\n | LedgerError\n | ConversationStoreError\n | ConversationNotMaterialized\n | AppendConflict\n | FenceRejected\n | DurableRuntimeFailpointError\n | AdmissionLimitExceeded\n | DurableAlarmError\n | HostProtocolError\n | ConversationClientError;\n\nexport type ClientAwaitFailure =\n | LedgerError\n | SettlementConflict\n | HostProtocolError\n | ConversationClientError;\n\nexport type ClientObserveFailure =\n | ConversationStoreError\n | ConversationNotMaterialized\n | HostProtocolError\n | ConversationClientError;\n\nexport type ClientAbortFailure =\n | LedgerError\n | SettlementConflict\n | JoinedToHost\n | DurableRuntimeFailpointError\n | DurableAlarmError\n | HostProtocolError\n | ConversationClientError;\n\nexport type ClientApprovalFailure =\n | LedgerError\n | SettlementConflict\n | ApprovalConflict\n | DurableAlarmError\n | HostProtocolError\n | ConversationClientError;\n\nexport type ClientUnknownFailure =\n | LedgerError\n | SettlementConflict\n | UnknownResolutionConflict\n | JoinedToHost\n | DurableRuntimeFailpointError\n | DurableAlarmError\n | HostProtocolError\n | ConversationClientError;\n\nconst SUBMIT_FAILURE_TAGS: ReadonlySet<string> = new Set([\n \"AgentInputError\",\n \"DigestError\",\n \"AdmissionConflict\",\n \"LedgerError\",\n \"ConversationStoreError\",\n \"ConversationNotMaterialized\",\n \"AppendConflict\",\n \"FenceRejected\",\n \"DurableRuntimeFailpointError\",\n \"AdmissionLimitExceeded\",\n \"DurableAlarmError\",\n \"HostProtocolError\",\n]);\nconst AWAIT_FAILURE_TAGS: ReadonlySet<string> = new Set([\n \"LedgerError\",\n \"SettlementConflict\",\n \"HostProtocolError\",\n]);\nconst OBSERVE_FAILURE_TAGS: ReadonlySet<string> = new Set([\n \"ConversationStoreError\",\n \"ConversationNotMaterialized\",\n \"HostProtocolError\",\n]);\nconst ABORT_FAILURE_TAGS: ReadonlySet<string> = new Set([\n \"LedgerError\",\n \"SettlementConflict\",\n \"JoinedToHost\",\n \"DurableRuntimeFailpointError\",\n \"DurableAlarmError\",\n \"HostProtocolError\",\n]);\nconst APPROVAL_FAILURE_TAGS: ReadonlySet<string> = new Set([\n \"LedgerError\",\n \"SettlementConflict\",\n \"ApprovalConflict\",\n \"DurableAlarmError\",\n \"HostProtocolError\",\n]);\nconst UNKNOWN_FAILURE_TAGS: ReadonlySet<string> = new Set([\n \"LedgerError\",\n \"SettlementConflict\",\n \"UnknownResolutionConflict\",\n \"JoinedToHost\",\n \"DurableRuntimeFailpointError\",\n \"DurableAlarmError\",\n \"HostProtocolError\",\n]);\n\nconst outOfContract = (\n conversationId: string,\n operation: string,\n observed: string,\n): ConversationClientError =>\n ConversationClientError.make({\n conversationId,\n message: boundHostDiagnostic(\n `The Conversation Object answered ${operation} with the out-of-contract ${observed}.`,\n ),\n });\n\n/**\n * Narrow one decoded `HostFailed.failure` to the operation's declared failure family; an\n * out-of-contract tag folds into `ConversationClientError` instead of being erased or\n * re-thrown raw (the WP2 discipline). The predicate is the single documented narrowing over\n * the closed `HostFailure` union.\n */\nconst narrowFailure =\n <Failure extends HostFailure>(tags: ReadonlySet<string>) =>\n (failure: HostFailure): failure is Failure =>\n tags.has(failure._tag);\n\n/** Worker-side client over the Conversation Object namespace (DEPLOY-010). */\nexport class CloudflareConversationClient extends Context.Service<\n CloudflareConversationClient,\n {\n /** Encode the input client-side, then durably submit to the owning Object. */\n readonly submit: <InputSchema extends Schema.Top>(\n agent: DurableSubmitAgent<InputSchema>,\n input: InputSchema[\"Type\"],\n options: DurableSubmitOptions,\n ) => Effect.Effect<Receipt, ClientSubmitFailure, InputSchema[\"EncodingServices\"]>;\n /** Wake-hinted, poll-guaranteed settlement wait executed inside the owning Object. */\n readonly awaitSettlement: (receipt: Receipt) => Effect.Effect<Settlement, ClientAwaitFailure>;\n /** One bounded page of canonical records. */\n readonly readPage: (\n conversationId: ConversationId,\n options?: {\n readonly afterSequence?: CanonicalSequence | undefined;\n readonly limit?: number | undefined;\n },\n ) => Effect.Effect<ReadonlyArray<CanonicalRecordEnvelope>, ClientObserveFailure>;\n /**\n * Every canonical record up to the CURRENT committed tail, via repeated pages. A\n * snapshot read, not a live observation — callers wanting liveness re-read after\n * `awaitSettlement`.\n */\n readonly readAll: (\n conversationId: ConversationId,\n ) => Effect.Effect<ReadonlyArray<CanonicalRecordEnvelope>, ClientObserveFailure>;\n /**\n * Submission-addressed operations take the owning Conversation explicitly (from the\n * Receipt): minted Submission identities stay OPAQUE outside the storage adapter that\n * minted them (D-P6-5), so the client never parses one to find the lane.\n */\n readonly abort: (\n conversationId: ConversationId,\n command: AbortCommand,\n ) => Effect.Effect<AbortIntent, ClientAbortFailure>;\n readonly resolveApproval: (\n conversationId: ConversationId,\n command: ApprovalDecisionCommand,\n ) => Effect.Effect<ApprovalDecisionIntent, ClientApprovalFailure>;\n readonly resolveUnknown: (\n conversationId: ConversationId,\n command: UnknownResolutionCommand,\n ) => Effect.Effect<UnknownResolutionIntent, ClientUnknownFailure>;\n }\n>()(\"@effect-agent/platform-cloudflare/CloudflareConversationClient\") {\n static readonly layer: Layer.Layer<\n CloudflareConversationClient,\n never,\n ConversationObjectNamespace\n > = Layer.effect(CloudflareConversationClient)(\n Effect.gen(function* () {\n const { namespace } = yield* ConversationObjectNamespace;\n\n const call = (\n conversationId: string,\n operation: string,\n invoke: (stub: DurableObjectStub<ConversationObjectRpc>) => Promise<unknown>,\n ): Effect.Effect<HostResponse, ConversationClientError | HostProtocolError> =>\n Effect.tryPromise({\n try: () => invoke(namespace.get(namespace.idFromName(conversationId))),\n catch: (cause) =>\n ConversationClientError.make({\n conversationId,\n message: boundHostDiagnostic(\n `${operation} did not reach the Conversation Object: ${\n cause instanceof Error ? cause.message : String(cause)\n }`,\n ),\n cause,\n }),\n }).pipe(\n Effect.flatMap((raw) =>\n decodeHostResponse(raw).pipe(\n Effect.mapError(\n (error): HostProtocolError =>\n HostProtocolError.make({\n message: boundHostDiagnostic(\n `The ${operation} answer could not be decoded: ${error.message}`,\n ),\n }),\n ),\n ),\n ),\n Effect.withSpan(\"CloudflareConversationClient.call\", {\n attributes: { conversationId, operation },\n }),\n );\n\n const expect = <\n Result extends Exclude<HostResponse, HostFailed>,\n Failure extends HostFailure,\n >(\n conversationId: string,\n operation: string,\n resultTag: Result[\"_tag\"],\n tags: ReadonlySet<string>,\n ) => {\n const isExpected = narrowFailure<Failure>(tags);\n return (\n response: HostResponse,\n ): Effect.Effect<Result, Failure | ConversationClientError> => {\n if (response._tag === \"HostFailed\") {\n const failure = response.failure;\n return isExpected(failure)\n ? Effect.fail(failure)\n : Effect.fail(outOfContract(conversationId, operation, `failure ${failure._tag}`));\n }\n if (response._tag !== resultTag) {\n return Effect.fail(outOfContract(conversationId, operation, `result ${response._tag}`));\n }\n return Effect.succeed(response as Result);\n };\n };\n\n const readPage = (\n conversationId: ConversationId,\n options?: {\n readonly afterSequence?: CanonicalSequence | undefined;\n readonly limit?: number | undefined;\n },\n ) =>\n Effect.gen(function* () {\n const request = ObservePageRequest.make({\n ...(options?.afterSequence === undefined\n ? {}\n : { afterSequence: options.afterSequence }),\n limit: options?.limit ?? 256,\n });\n const encoded = yield* encodeObservePageRequest(request).pipe(\n Effect.mapError((error) =>\n HostProtocolError.make({\n message: boundHostDiagnostic(`observePage request encode failed: ${error.message}`),\n }),\n ),\n );\n const response = yield* call(conversationId, \"observePage\", (stub) =>\n stub.observePage(encoded),\n );\n const page = yield* expect<ObservedPage, ClientObserveFailure & HostFailure>(\n conversationId,\n \"observePage\",\n \"ObservedPage\",\n OBSERVE_FAILURE_TAGS,\n )(response);\n return page.records;\n });\n\n return CloudflareConversationClient.of({\n submit: <InputSchema extends Schema.Top>(\n agent: DurableSubmitAgent<InputSchema>,\n input: InputSchema[\"Type\"],\n options: DurableSubmitOptions,\n ) =>\n Effect.gen(function* () {\n // Client-side half of `DurableAgentRuntime.submit`'s input boundary: encode\n // through the Agent's input schema and prove the canonical persistence bounds.\n const encodedInput = yield* Schema.encodeEffect(agent.definition.input)(input).pipe(\n Effect.mapError((cause) =>\n AgentInputError.make({ message: `Unable to encode Agent input: ${cause.message}` }),\n ),\n );\n const inputPayload = yield* Schema.decodeUnknownEffect(PersistedJson)(\n encodedInput,\n ).pipe(\n Effect.mapError(() =>\n AgentInputError.make({\n message: \"Agent input does not satisfy the canonical persistence bounds\",\n }),\n ),\n );\n const request = SubmitRequest.make({\n agentId: agent.definition.id,\n principal: options.principal,\n idempotencyKey: options.idempotencyKey,\n definitions: options.definitions,\n inputPayload,\n });\n const encoded = yield* encodeSubmitRequest(request).pipe(\n Effect.mapError((error) =>\n HostProtocolError.make({\n message: boundHostDiagnostic(`submit request encode failed: ${error.message}`),\n }),\n ),\n );\n const response = yield* call(options.conversationId, \"submit\", (stub) =>\n stub.submitEncoded(encoded),\n );\n const succeeded = yield* expect<SubmitSucceeded, ClientSubmitFailure & HostFailure>(\n options.conversationId,\n \"submit\",\n \"SubmitSucceeded\",\n SUBMIT_FAILURE_TAGS,\n )(response);\n return succeeded.receipt;\n }),\n\n awaitSettlement: (receipt) =>\n Effect.gen(function* () {\n const encoded = yield* encodeReceipt(receipt).pipe(\n Effect.mapError((error) =>\n HostProtocolError.make({\n message: boundHostDiagnostic(`receipt encode failed: ${error.message}`),\n }),\n ),\n );\n const response = yield* call(receipt.conversationId, \"awaitSettlement\", (stub) =>\n stub.awaitSettlementEncoded(encoded),\n );\n const settled = yield* expect<SettlementReached, ClientAwaitFailure & HostFailure>(\n receipt.conversationId,\n \"awaitSettlement\",\n \"SettlementReached\",\n AWAIT_FAILURE_TAGS,\n )(response);\n return settled.settlement;\n }),\n\n readPage,\n\n readAll: (conversationId) =>\n Effect.gen(function* () {\n const all: Array<CanonicalRecordEnvelope> = [];\n let after: CanonicalSequence | undefined;\n for (;;) {\n const page = yield* readPage(conversationId, { afterSequence: after, limit: 1_024 });\n all.push(...page);\n const last = page.at(-1);\n if (page.length < 1_024 || last === undefined) return all;\n after = last.sequence;\n }\n }),\n\n abort: (conversationId, command) =>\n Effect.gen(function* () {\n const encoded = yield* encodeAbortCommand(command).pipe(\n Effect.mapError((error) =>\n HostProtocolError.make({\n message: boundHostDiagnostic(`abort command encode failed: ${error.message}`),\n }),\n ),\n );\n const response = yield* call(conversationId, \"abort\", (stub) =>\n stub.abortEncoded(encoded),\n );\n const recorded = yield* expect<AbortRecorded, ClientAbortFailure & HostFailure>(\n conversationId,\n \"abort\",\n \"AbortRecorded\",\n ABORT_FAILURE_TAGS,\n )(response);\n return recorded.intent;\n }),\n\n resolveApproval: (conversationId, command) =>\n Effect.gen(function* () {\n const encoded = yield* encodeApprovalDecisionCommand(command).pipe(\n Effect.mapError((error) =>\n HostProtocolError.make({\n message: boundHostDiagnostic(`approval command encode failed: ${error.message}`),\n }),\n ),\n );\n const response = yield* call(conversationId, \"resolveApproval\", (stub) =>\n stub.resolveApprovalEncoded(encoded),\n );\n const recorded = yield* expect<ApprovalRecorded, ClientApprovalFailure & HostFailure>(\n conversationId,\n \"resolveApproval\",\n \"ApprovalRecorded\",\n APPROVAL_FAILURE_TAGS,\n )(response);\n return recorded.intent;\n }),\n\n resolveUnknown: (conversationId, command) =>\n Effect.gen(function* () {\n const encoded = yield* encodeUnknownResolutionCommand(command).pipe(\n Effect.mapError((error) =>\n HostProtocolError.make({\n message: boundHostDiagnostic(\n `resolution command encode failed: ${error.message}`,\n ),\n }),\n ),\n );\n const response = yield* call(conversationId, \"resolveUnknown\", (stub) =>\n stub.resolveUnknownEncoded(encoded),\n );\n const recorded = yield* expect<\n UnknownResolutionRecorded,\n ClientUnknownFailure & HostFailure\n >(\n conversationId,\n \"resolveUnknown\",\n \"UnknownResolutionRecorded\",\n UNKNOWN_FAILURE_TAGS,\n )(response);\n return recorded.intent;\n }),\n });\n }),\n );\n}\n","import type { AgentId } from \"@effect-agent/core\";\nimport { SubmissionId } from \"@effect-agent/core\";\nimport {\n AppendConflict,\n ConversationNotMaterialized,\n ConversationRead,\n ConversationStore,\n ConversationStoreError,\n DigestError,\n DurableAgentRuntime,\n DurableRuntimeFailpointError,\n FenceRejected,\n IntegrityReport,\n LedgerError,\n ObligationReport,\n ObligationThresholds,\n OperationAuthorizationRequest,\n OperationAuthorizer,\n OperationDenied,\n OwnershipLost,\n PersistedJson,\n RecoveryExplanation,\n RecoveryReport,\n RetryCommand,\n RetryRefused,\n RunJournalError,\n SettlementConflict,\n SubmissionLedger,\n SubmissionLookupByKey,\n type DurableSubmitAgent,\n} from \"@effect-agent/session\";\nimport { DurableObject } from \"cloudflare:workers\";\nimport { Effect, Layer, ManagedRuntime, Option, Schema, Stream } from \"effect\";\n\nimport { ConversationMaintenance, DurableAlarmError, DurableAlarmService } from \"./alarm.ts\";\nimport {\n ConversationObjectIdentity,\n DurableObjectContext,\n conversationNamespaceLayer,\n type CloudflareBindingError,\n} from \"./bindings.ts\";\nimport {\n AbortRecorded,\n ApprovalRecorded,\n HostFailed,\n HostProtocolError,\n ObservedPage,\n SettlementReached,\n SubmitSucceeded,\n UnknownResolutionRecorded,\n boundHostDiagnostic,\n decodeAbortCommand,\n decodeApprovalDecisionCommand,\n decodeObservePageRequest,\n decodeReceipt,\n decodeSubmitRequest,\n decodeUnknownResolutionCommand,\n encodeHostResponse,\n type HostFailure,\n type HostResponse,\n} from \"./client.ts\";\nimport { AdmissionLimitExceeded, CloudflareDurableRuntimeConfig } from \"./config.ts\";\nimport {\n CloudflareDurableRuntime,\n ConversationObjectPorts,\n type CloudflareDurableRuntimeInitializationError,\n type CloudflareDurableRuntimeOptions,\n type CloudflareDurableRuntimeServices,\n} from \"./layers.ts\";\n\n/**\n * `makeConversationObjectClass(options)` — the Conversation Durable Object (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 Conversation 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` + `processConversationResolved` pass, and the persisted alarm\n * (the single multiplexed slot, D-P6-2) finishes accepted work across evictions WITHOUT any\n * incoming request.\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 Conversation Object class. */\nexport interface ConversationObjectOptions extends CloudflareDurableRuntimeOptions {\n /**\n * Name of the Worker `env` binding carrying THIS class's `DurableObjectNamespace` — the\n * Object's route back to sibling Conversation 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}\n\ntype ConversationObjectError = CloudflareDurableRuntimeInitializationError | CloudflareBindingError;\n\ntype EndpointServices = CloudflareDurableRuntimeServices | DurableObjectContext;\n\n/** Port envelope tags whose owner-side execution durably mutates this Object's lane. */\nconst MUTATING_PORT_TAGS: ReadonlySet<string> = new Set([\n \"LedgerAdmit\",\n \"LedgerMarkReady\",\n \"LedgerRequestAbort\",\n \"LedgerRecordChildSettled\",\n \"StoreMaterialize\",\n \"StoreAppend\",\n]);\n\nconst isMutatingPortRequest = (encoded: unknown): boolean =>\n typeof encoded === \"object\" &&\n encoded !== null &&\n \"_tag\" in encoded &&\n typeof encoded._tag === \"string\" &&\n MUTATING_PORT_TAGS.has(encoded._tag);\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: unknown): 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(\"ConversationObject.gateAdmissionLimits\")(\n function* (request: {\n readonly principal: SubmissionLookupByKey[\"principal\"];\n readonly idempotencyKey: SubmissionLookupByKey[\"idempotencyKey\"];\n readonly inputPayload: PersistedJson;\n }) {\n const identity = yield* ConversationObjectIdentity;\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 conversationId: identity.conversationId,\n principal: request.principal,\n idempotencyKey: request.idempotencyKey,\n }),\n );\n if (Option.isSome(existing)) return;\n\n const inputBytes = utf8Bytes(request.inputPayload);\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 Conversation per Object (durability §5): the local scan IS this lane's queue.\n const nonterminal = yield* Stream.runCollect(ledger.scanNonterminal);\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 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/**\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* ConversationObjectIdentity;\n const maintenance = yield* ConversationMaintenance;\n const runtime = yield* DurableAgentRuntime;\n yield* gateAdmissionLimits(request);\n // Alarm invariant: the alarm commits BEFORE the admission it will finish (D-P6-2).\n yield* maintenance.preArm;\n const receipt = yield* runtime.submit(\n passthroughSubmitAgent(request.agentId),\n request.inputPayload,\n {\n conversationId: identity.conversationId,\n principal: request.principal,\n idempotencyKey: request.idempotencyKey,\n definitions: request.definitions,\n },\n );\n return SubmitSucceeded.make({ 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 return SettlementReached.make({ settlement });\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* ConversationObjectIdentity;\n const store = yield* ConversationStore;\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 yield* authorizer\n .authorize(\n OperationAuthorizationRequest.make({\n operation: \"observe\",\n conversationId: identity.conversationId,\n }),\n )\n .pipe(Effect.catchTag(\"OperationDenied\", deniedToProtocolFailure));\n const records = yield* Stream.runCollect(\n store.read(\n ConversationRead.make({\n conversationId: identity.conversationId,\n ...(request.afterSequence === undefined\n ? {}\n : { afterSequence: request.afterSequence }),\n limit: request.limit,\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* ConversationMaintenance;\n const runtime = yield* DurableAgentRuntime;\n yield* maintenance.preArm;\n const intent = yield* runtime.abort(command);\n return AbortRecorded.make({ intent });\n }),\n ),\n respond,\n Effect.flatMap(encodeResponse),\n );\n\n/**\n * The pre-P7 host protocol's failure union does not carry `OperationDenied` (the Worker client\n * predates the authorizer). This assembly always runs the default possession authorizer — no\n * `CloudflareDurableRuntimeOptions` authorizer lever exists yet — so a denial here is\n * unreachable today; if one ever surfaces it degrades to the protocol failure instead of an\n * out-of-contract throw. The four P7 admin entry points below carry `OperationDenied` typed.\n */\nconst deniedToProtocolFailure = (\n denied: OperationDenied,\n): Effect.Effect<never, HostProtocolError> =>\n Effect.fail(\n HostProtocolError.make({\n message: boundHostDiagnostic(\n `The ${denied.operation} operation was denied: ${denied.reason}`,\n ),\n }),\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* ConversationMaintenance;\n const runtime = yield* DurableAgentRuntime;\n yield* maintenance.preArm;\n const intent = yield* runtime\n .resolveApproval(command)\n .pipe(Effect.catchTag(\"OperationDenied\", deniedToProtocolFailure));\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* ConversationMaintenance;\n const runtime = yield* DurableAgentRuntime;\n yield* maintenance.preArm;\n const intent = yield* runtime\n .resolveUnknown(command)\n .pipe(Effect.catchTag(\"OperationDenied\", deniedToProtocolFailure));\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 OperationDenied,\n RetryRefused,\n LedgerError,\n RunJournalError,\n DigestError,\n OwnershipLost,\n SettlementConflict,\n ConversationStoreError,\n ConversationNotMaterialized,\n AppendConflict,\n FenceRejected,\n DurableRuntimeFailpointError,\n DurableAlarmError,\n HostProtocolError,\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]);\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* ConversationObjectIdentity;\n const runtime = yield* DurableAgentRuntime;\n const explanations =\n request.submissionId === undefined\n ? yield* runtime.explainConversation(identity.conversationId)\n : [yield* runtime.explain(request.submissionId)];\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* ConversationObjectIdentity;\n const runtime = yield* DurableAgentRuntime;\n const report = yield* runtime.verify(identity.conversationId);\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* ConversationMaintenance;\n const runtime = yield* DurableAgentRuntime;\n // Alarm invariant: retry may repair durable state, so the alarm that will finish the\n // lane commits BEFORE the mutation (D-P6-2), exactly like abort.\n yield* maintenance.preArm;\n const report = yield* runtime.retry(command);\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 return ObligationsScanned.make({ report });\n }),\n ),\n respondAdmin,\n Effect.flatMap(encodeAdminResponseTotal),\n );\n\n/**\n * Owner-side `portCall`: pre-arm before a mutating envelope (a routed admission committed by\n * THIS Object must already carry the alarm that will finish it), execute on the LOCAL facets\n * (never the routed decorators), then arm an immediate alarm so the mutated lane is\n * processed promptly. Protocol anomalies answer `PortFailed(PortProtocolError)`.\n */\nconst portCallEndpoint = (encoded: unknown): Effect.Effect<unknown, never, EndpointServices> =>\n Effect.gen(function* () {\n const ports = yield* ConversationObjectPorts;\n const maintenance = yield* ConversationMaintenance;\n const alarm = yield* DurableAlarmService;\n const mutating = isMutatingPortRequest(encoded);\n if (mutating) {\n const preArmed = yield* maintenance.preArm.pipe(Effect.exit);\n if (preArmed._tag === \"Failure\") {\n // Without the committed alarm the invariant cannot be promised; refuse the mutation.\n return encodedPortProtocolFailure(\n \"The owner Object could not arm its maintenance alarm before the mutation.\",\n );\n }\n }\n const response = yield* ports.handle(encoded);\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(\"ConversationObject.portCall: immediate re-arm failed\", error),\n ),\n );\n }\n return response;\n });\n\nconst wakeEndpoint: Effect.Effect<void, never, EndpointServices> = Effect.gen(function* () {\n const alarm = yield* DurableAlarmService;\n // Wake hints are droppable by contract: a failed alarm write is logged and swallowed; the\n // sender's own alarm/scan pairing (or this Object's next entry point) restores liveness.\n yield* alarm.scheduleNow.pipe(\n Effect.catch((error) => Effect.logWarning(\"ConversationObject.wake dropped\", error)),\n );\n});\n\nconst alarmEndpoint: Effect.Effect<void, unknown, EndpointServices> = Effect.gen(function* () {\n const maintenance = yield* ConversationMaintenance;\n // Typed pass failures propagate: the rejected promise makes workerd retry the alarm\n // (at-least-once delivery), and the pass's own pre-arm keeps the slot committed meanwhile.\n yield* maintenance.pass;\n});\n\nconst gateEndpoint: Effect.Effect<void, unknown, EndpointServices> = Effect.gen(function* () {\n // Forcing ConversationMaintenance 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* ConversationMaintenance;\n yield* maintenance.ensureAlarm;\n});\n\n/** The public endpoint surface of one Conversation Object instance. */\nexport interface ConversationObjectInstance extends DurableObject {\n submitEncoded(encoded: unknown): Promise<unknown>;\n awaitSettlementEncoded(encoded: unknown): Promise<unknown>;\n observePage(encoded: unknown): Promise<unknown>;\n abortEncoded(encoded: unknown): Promise<unknown>;\n resolveApprovalEncoded(encoded: unknown): Promise<unknown>;\n resolveUnknownEncoded(encoded: 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(): Promise<void>;\n}\n\n/** The constructor shape workerd instantiates for each Conversation Object. */\nexport interface ConversationObjectClass {\n new (ctx: DurableObjectState, env: Cloudflare.Env): ConversationObjectInstance;\n}\n\n/**\n * Build the application's Conversation Object class (export it from the\n * Worker entry). The explicit return type is what makes declaration emit\n * possible: the class body carries a private runtime field, and TS4094\n * rejects inferring an exported anonymous class type around it.\n */\nexport const makeConversationObjectClass = (\n options: ConversationObjectOptions,\n): ConversationObjectClass => {\n class ConversationObject extends DurableObject {\n readonly #runtime: ManagedRuntime.ManagedRuntime<EndpointServices, ConversationObjectError>;\n\n constructor(ctx: DurableObjectState, env: Cloudflare.Env) {\n super(ctx, env);\n this.#runtime = ManagedRuntime.make(\n CloudflareDurableRuntime.layer(options).pipe(\n Layer.provideMerge(\n Layer.mergeAll(\n DurableObjectContext.layer(ctx, env),\n conversationNamespaceLayer(env, options.namespaceBinding),\n ),\n ),\n ),\n );\n // The constructor gate: local-only checks; never the recovery pass (deadlock argument,\n // plan §1.4). A failure here fails every delivery with the typed construction error.\n ctx.blockConcurrencyWhile(() => this.#runtime.runPromise(gateEndpoint));\n }\n\n async submitEncoded(encoded: unknown): Promise<unknown> {\n return this.#runtime.runPromise(submitEndpoint(encoded));\n }\n\n async awaitSettlementEncoded(encoded: unknown): Promise<unknown> {\n return this.#runtime.runPromise(awaitSettlementEndpoint(encoded));\n }\n\n async observePage(encoded: unknown): Promise<unknown> {\n return this.#runtime.runPromise(observePageEndpoint(encoded));\n }\n\n async abortEncoded(encoded: unknown): Promise<unknown> {\n return this.#runtime.runPromise(abortEndpoint(encoded));\n }\n\n async resolveApprovalEncoded(encoded: unknown): Promise<unknown> {\n return this.#runtime.runPromise(resolveApprovalEndpoint(encoded));\n }\n\n async resolveUnknownEncoded(encoded: unknown): Promise<unknown> {\n return this.#runtime.runPromise(resolveUnknownEndpoint(encoded));\n }\n\n async explainEncoded(encoded: unknown): Promise<unknown> {\n return this.#runtime.runPromise(explainEndpoint(encoded));\n }\n\n async verifyEncoded(encoded: unknown): Promise<unknown> {\n return this.#runtime.runPromise(verifyEndpoint(encoded));\n }\n\n async retryEncoded(encoded: unknown): Promise<unknown> {\n return this.#runtime.runPromise(retryEndpoint(encoded));\n }\n\n async obligationsEncoded(encoded: unknown): Promise<unknown> {\n return this.#runtime.runPromise(obligationsEndpoint(encoded));\n }\n\n async portCall(encoded: unknown): Promise<unknown> {\n return this.#runtime.runPromise(portCallEndpoint(encoded));\n }\n\n async wake(): Promise<void> {\n await this.#runtime.runPromise(wakeEndpoint);\n }\n\n override async alarm(): Promise<void> {\n await this.#runtime.runPromise(alarmEndpoint);\n }\n }\n\n return ConversationObject;\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":["#runtime"],"sources":["../src/bindings.ts","../src/config.ts","../src/alarm.ts","../src/wake-scheduler.ts","../src/transport.ts","../src/layers.ts","../src/client.ts","../src/conversation-object.ts"],"sourcesContent":["import type { ConversationId } from \"@effect-agent/core\";\nimport type { ProducerId } from \"@effect-agent/session\";\nimport { Context, Effect, Layer, Schema } from \"effect\";\n\n/**\n * Cloudflare platform bindings as Effect services (DEPLOY-010: \"Cloudflare platform bindings\n * are supplied as Effect services/Layers\"). Application code never reads `env` or touches a\n * `DurableObjectState` directly — the Conversation Object class constructs these Layers once\n * per incarnation and everything downstream consumes the services.\n */\n\n/** A Cloudflare platform binding was missing or carried the wrong shape (DEPLOY-003/010). */\nexport class CloudflareBindingError extends Schema.TaggedError<CloudflareBindingError>()(\n \"CloudflareBindingError\",\n {\n binding: Schema.String,\n message: Schema.String,\n },\n) {}\n\n/**\n * The RPC surface one Conversation Durable Object exposes to Workers and to sibling\n * Conversation Objects. `makeConversationObjectClass` implements it; the Worker-side client\n * and the cross-Object transport call it through `DurableObjectNamespace` stubs. Every\n * `encoded` value is a Schema-encoded envelope (`client.ts` wire schemas for host entry\n * points, `@effect-agent/storage-cloudflare` port envelopes for `portCall`), so the RPC\n * boundary carries only structured-cloneable JSON.\n */\nexport interface ConversationObjectRpc extends Rpc.DurableObjectBranded {\n /** Admission-limits gate + `DurableAgentRuntime.submit`; answers a `SubmitResponse`. */\n submitEncoded(encoded: unknown): Promise<unknown>;\n /** Wake-hinted, poll-guaranteed settlement wait; answers an `AwaitSettlementResponse`. */\n awaitSettlementEncoded(encoded: unknown): Promise<unknown>;\n /** One bounded page of canonical records; answers an `ObservePageResponse`. */\n observePage(encoded: unknown): Promise<unknown>;\n /** Durable abort intent; answers an `AbortResponse`. */\n abortEncoded(encoded: unknown): Promise<unknown>;\n /** Durable approval decision (plan §2.6); answers a `ResolveApprovalResponse`. */\n resolveApprovalEncoded(encoded: unknown): Promise<unknown>;\n /** Authorized DUR-017 Unknown-Outcome resolution; answers a `ResolveUnknownResponse`. */\n resolveUnknownEncoded(encoded: unknown): Promise<unknown>;\n /** Owner-side cross-Object port endpoint (WP2 envelopes, executed on LOCAL facets). */\n portCall(encoded: unknown): Promise<unknown>;\n /** Droppable liveness hint from another Object: arms an immediate alarm. */\n wake(): Promise<void>;\n}\n\n/**\n * The `DurableObjectNamespace` binding that addresses Conversation Objects. The Object\n * identity rule is `namespace.idFromName(conversationId)` (plan §1.2): Conversation IDs are\n * globally unique, so the mapping is total and deterministic and no directory service exists.\n */\nexport class ConversationObjectNamespace extends Context.Service<\n ConversationObjectNamespace,\n {\n readonly namespace: DurableObjectNamespace<ConversationObjectRpc>;\n }\n>()(\"@effect-agent/platform-cloudflare/ConversationObjectNamespace\") {\n static layer(\n namespace: DurableObjectNamespace<ConversationObjectRpc>,\n ): Layer.Layer<ConversationObjectNamespace> {\n return Layer.succeed(ConversationObjectNamespace)({ namespace });\n }\n}\n\n/**\n * Narrow one `env` member to a `DurableObjectNamespace`. `env` is an untyped platform value,\n * and a namespace binding is a host object no Schema can decode, so this is the documented\n * narrowest-boundary check (structural probe for the namespace surface the transport uses);\n * a missing or misshaped binding fails typed before any Layer is built.\n */\nexport const conversationNamespaceFromEnv = (\n env: unknown,\n binding: string,\n): Effect.Effect<DurableObjectNamespace<ConversationObjectRpc>, CloudflareBindingError> =>\n Effect.suspend(() => {\n if (typeof env !== \"object\" || env === null) {\n return Effect.fail(\n CloudflareBindingError.make({\n binding,\n message: \"The Worker environment is not an object; no bindings are available.\",\n }),\n );\n }\n const candidate: unknown = (env as Record<string, unknown>)[binding];\n if (\n typeof candidate === \"object\" &&\n candidate !== null &&\n \"idFromName\" in candidate &&\n typeof candidate.idFromName === \"function\" &&\n \"get\" in candidate &&\n typeof candidate.get === \"function\"\n ) {\n // The structural probe above is the entire runtime contract this package relies on;\n // the assertion records that `idFromName`/`get` name a DurableObjectNamespace.\n return Effect.succeed(candidate as DurableObjectNamespace<ConversationObjectRpc>);\n }\n return Effect.fail(\n CloudflareBindingError.make({\n binding,\n message:\n `env.${binding} is not a DurableObjectNamespace binding; declare the Conversation ` +\n \"Object class under this binding in the Worker configuration.\",\n }),\n );\n });\n\n/** `ConversationObjectNamespace` built from the untyped Worker `env` (fails typed). */\nexport const conversationNamespaceLayer = (\n env: unknown,\n binding: string,\n): Layer.Layer<ConversationObjectNamespace, CloudflareBindingError> =>\n Layer.effect(ConversationObjectNamespace)(\n Effect.map(conversationNamespaceFromEnv(env, binding), (namespace) => ({ namespace })),\n );\n\n/**\n * The live Durable Object execution context of THIS incarnation. Only Layer construction and\n * the alarm service consume it; important state never lives on it (`ctx.storage` is truth,\n * everything in memory is a cache — deployment spec §11).\n */\nexport class DurableObjectContext extends Context.Service<\n DurableObjectContext,\n {\n readonly ctx: DurableObjectState;\n readonly env: unknown;\n }\n>()(\"@effect-agent/platform-cloudflare/DurableObjectContext\") {\n static layer(ctx: DurableObjectState, env: unknown): Layer.Layer<DurableObjectContext> {\n return Layer.succeed(DurableObjectContext)({ ctx, env });\n }\n}\n\n/**\n * The Conversation identity this Object serializes and the producer identity its Attempts\n * write with (`{producerPrefix}:{conversationId}`, plan §1.4). Derived once per incarnation\n * from `ctx.id.name` — the Object identity rule guarantees the name IS the Conversation ID.\n */\nexport class ConversationObjectIdentity extends Context.Service<\n ConversationObjectIdentity,\n {\n readonly conversationId: ConversationId;\n readonly producerId: ProducerId;\n }\n>()(\"@effect-agent/platform-cloudflare/ConversationObjectIdentity\") {}\n","import { DEFAULT_OWNERSHIP_LEASE_DURATION, DeploymentId } from \"@effect-agent/session\";\nimport { DEFAULT_MAX_STORED_VALUE_BYTES } from \"@effect-agent/storage-cloudflare\";\nimport { Context, Duration, Schema } from \"effect\";\n\n/**\n * Schema-validated configuration for the Cloudflare durable runtime (deployment spec §4:\n * decoded once during Layer construction, exposed as a typed service; DEPLOY-003). Every\n * cadence is in milliseconds; every bound is finite and checked before any resource opens.\n */\n\nconst PositiveMillis = Schema.Int.check(Schema.isGreaterThan(0));\nconst NonNegativeMillis = Schema.Int.check(Schema.isGreaterThanOrEqualTo(0));\n\n/** The supplied Cloudflare durable runtime configuration failed validation (DEPLOY-003). */\nexport class CloudflarePlatformConfigError extends Schema.TaggedError<CloudflarePlatformConfigError>()(\n \"CloudflarePlatformConfigError\",\n {\n message: Schema.String,\n cause: Schema.optionalKey(Schema.Defect()),\n },\n) {}\n\n/**\n * An admission was refused by a host resource limit BEFORE any ledger row existed\n * (deployment spec §8, DEPLOY-007: \"Admission has explicit bounded quota and overload\n * behavior... a typed rejection\"). This is the DC analogue of `NodeDurableHost`'s\n * `AdmissionClosed` host gate: the port surface stays untouched, the refusal happens in the\n * Conversation Object's submit entry point before `DurableAgentRuntime.submit` runs, and\n * nothing was admitted or written.\n */\nexport class AdmissionLimitExceeded extends Schema.TaggedError<AdmissionLimitExceeded>()(\n \"AdmissionLimitExceeded\",\n {\n limit: Schema.Literals([\"queue-depth\", \"input-bytes\", \"database-bytes\"]),\n actual: Schema.Int,\n maximum: Schema.Int,\n },\n) {\n override get message() {\n return (\n `Admission refused before any ledger row existed: ${this.limit} ${this.actual} exceeds ` +\n `the configured maximum ${this.maximum}. Accepted work is unaffected; retry after the ` +\n \"lane drains or raise the limit (DEPLOY-007).\"\n );\n }\n}\n\n/** The platform's hard per-Object database cap (10 GB, developers.cloudflare.com limits). */\nexport const CLOUDFLARE_DATABASE_CAP_BYTES = 10_000_000_000;\n\n/** Default database-size admission ceiling: a 1 GB safety margin under the platform cap. */\nexport const DEFAULT_MAX_DATABASE_BYTES = 9_000_000_000;\n\n/**\n * Explicit bounded admission quotas checked by the Conversation Object BEFORE admission\n * (exit gate \"resource limits are checked before admission\").\n */\nexport class CloudflareAdmissionLimitsValue extends Schema.Class<CloudflareAdmissionLimitsValue>(\n \"@effect-agent/platform-cloudflare/CloudflareAdmissionLimitsValue\",\n)({\n /** Maximum nonterminal Submissions per Conversation lane before new admissions refuse. */\n maxQueueDepthPerLane: Schema.Int.check(\n Schema.isGreaterThan(0),\n Schema.isLessThanOrEqualTo(100_000),\n ),\n /** Maximum encoded input bytes; never above the storage per-value bound. */\n maxInputBytes: Schema.Int.check(Schema.isGreaterThan(0), Schema.isLessThanOrEqualTo(2_000_000)),\n /** Maximum `ctx.storage.sql.databaseSize` at admission; stays under the 10 GB platform cap. */\n maxDatabaseBytes: Schema.Int.check(\n Schema.isGreaterThan(0),\n Schema.isLessThanOrEqualTo(CLOUDFLARE_DATABASE_CAP_BYTES),\n ),\n}) {}\n\n/**\n * Validated Cloudflare durable runtime configuration. The producer identity of one\n * Conversation Object is `{producerPrefix}:{conversationId}` — stable across incarnations of\n * the same deployment, distinct across deployments — and producer-epoch fencing (not the\n * producer name) remains the correctness authority (DUR-006).\n */\nexport class CloudflareDurableRuntimeConfigValue extends Schema.Class<CloudflareDurableRuntimeConfigValue>(\n \"@effect-agent/platform-cloudflare/CloudflareDurableRuntimeConfigValue\",\n)({\n deploymentId: DeploymentId,\n /** Head of the minted producer identity `{producerPrefix}:{conversationId}`. */\n producerPrefix: Schema.NonEmptyString.check(Schema.isMaxLength(256)),\n /** Submission ownership lease duration (D5); fences work across Object incarnations. */\n ownershipLeaseDuration: PositiveMillis,\n /** Base delay of the alarm re-arm backoff when a pass makes no progress. */\n alarmBackoffBase: PositiveMillis,\n /** Ceiling of the alarm re-arm backoff. */\n alarmBackoffCap: PositiveMillis,\n /**\n * The maintenance-pass scan cadence and the ceiling of every re-arm delay: nonterminal\n * work is revisited at least this often (wake/scan pairing, persistence §14).\n */\n wakeScanInterval: PositiveMillis,\n /** `awaitSettlement` ledger re-check cadence when no wake arrives. */\n settlementPollInterval: PositiveMillis,\n /** Worker ownership-lease renewal cadence during an active Attempt. */\n leaseRenewalInterval: PositiveMillis,\n /** Active-Run abort-intent poll cadence. */\n abortPollInterval: PositiveMillis,\n /** Canonical observation poll cadence of the Durable Object store. */\n observationPollInterval: NonNegativeMillis,\n /** Per-value byte bound; must stay under the platform's 2 MB SQLite value limit. */\n maxStoredValueBytes: Schema.Int.check(\n Schema.isGreaterThan(0),\n Schema.isLessThanOrEqualTo(2_000_000),\n ),\n /** Opt-in full payload/digest-chain audit while opening the store. */\n verifyOnOpen: Schema.Boolean,\n limits: CloudflareAdmissionLimitsValue,\n}) {}\n\n/** Explicit configuration authority for the assembled Cloudflare durable runtime. */\nexport class CloudflareDurableRuntimeConfig extends Context.Service<\n CloudflareDurableRuntimeConfig,\n CloudflareDurableRuntimeConfigValue\n>()(\"@effect-agent/platform-cloudflare/CloudflareDurableRuntimeConfig\") {}\n\n/** Documented production defaults applied by `CloudflareDurableRuntime.layer`. */\nexport const CLOUDFLARE_RUNTIME_DEFAULTS = {\n ownershipLeaseDuration: Duration.toMillis(DEFAULT_OWNERSHIP_LEASE_DURATION),\n alarmBackoffBase: 100,\n alarmBackoffCap: 5_000,\n wakeScanInterval: 1_000,\n settlementPollInterval: 500,\n leaseRenewalInterval: 10_000,\n abortPollInterval: 500,\n observationPollInterval: 25,\n maxStoredValueBytes: DEFAULT_MAX_STORED_VALUE_BYTES,\n verifyOnOpen: false,\n maxQueueDepthPerLane: 256,\n maxInputBytes: DEFAULT_MAX_STORED_VALUE_BYTES,\n maxDatabaseBytes: DEFAULT_MAX_DATABASE_BYTES,\n} as const;\n","import {\n AgentBindingResolver,\n DurableAgentRuntime,\n SubmissionLedger,\n type DurableBindingFailure,\n type DurableWorkerFailure,\n type RecoveryReport,\n} from \"@effect-agent/session\";\nimport { Clock, Context, Effect, Layer, Option, Random, Ref, Schema, Stream } from \"effect\";\n\nimport { ConversationObjectIdentity, DurableObjectContext } from \"./bindings.ts\";\nimport { CloudflareDurableRuntimeConfig } from \"./config.ts\";\n\n/**\n * The single multiplexed Durable Object alarm (decision D-P6-2). A Durable Object has ONE\n * alarm slot; every cadence the Node host ran on fibers (wake scan, lease expiry, settlement\n * and abort re-checks, retry backoff) multiplexes into one idempotent maintenance pass, and\n * the slot always holds the EARLIEST deadline any caller asked for.\n *\n * The alarm invariant (plan §1.4): committed nonterminal work implies a committed alarm.\n * It is established by pre-arming — every mutating entry point and every pass arms the alarm\n * BEFORE its durable mutations — so an eviction at any failpoint leaves a persisted alarm\n * that workerd re-delivers to a fresh incarnation WITHOUT any incoming request. Spurious\n * alarms are harmless by design: a pass over an all-settled lane simply deletes the slot.\n */\n\n/** The Durable Object alarm API failed; surfaces on host entry points as a typed refusal. */\nexport class DurableAlarmError extends Schema.TaggedError<DurableAlarmError>()(\n \"DurableAlarmError\",\n {\n operation: Schema.String,\n message: Schema.String,\n cause: Schema.optionalKey(Schema.Defect()),\n },\n) {}\n\nconst alarmFailure =\n (operation: string) =>\n (cause: unknown): DurableAlarmError =>\n DurableAlarmError.make({\n operation,\n message: cause instanceof Error ? cause.message : String(cause),\n cause,\n });\n\n/** `ctx.storage` alarm slot as an Effect service; storage is truth, never a memory field. */\nexport class DurableAlarmService extends Context.Service<\n DurableAlarmService,\n {\n /** The scheduled deadline in epoch milliseconds, if any. */\n readonly scheduled: Effect.Effect<Option.Option<number>, DurableAlarmError>;\n /** Replace the slot with this deadline. */\n readonly scheduleAt: (epochMillis: number) => Effect.Effect<void, DurableAlarmError>;\n /** Keep the EARLIER of the existing deadline and this one (the multiplexing rule). */\n readonly ensureScheduledBy: (epochMillis: number) => Effect.Effect<void, DurableAlarmError>;\n /**\n * Arm an immediate alarm (the durable, coalescing local wake) — DEFERRED while a\n * maintenance pass is executing. Workerd cancels an in-flight alarm handler when a new\n * EARLIER deadline is written during its execution (`requestScheduledAlarm`), and the\n * maintenance pass runs INSIDE the alarm handler: an immediate wake landing mid-pass\n * (a routed port mutation, a sibling's `wake()`, the coordinator's own local notify)\n * would kill the running Attempt — manufacturing an ownership loss no real eviction\n * caused, and routing open uncertain-class Tool Calls into spurious Unknown Outcomes.\n * Deferral is contract-safe: wakes are droppable hints, every mutating entry point\n * pre-arms BEFORE its first durable mutation (the alarm invariant never rests on this\n * call), and the deferred wake is flushed when the pass completes.\n */\n readonly scheduleNow: Effect.Effect<void, DurableAlarmError>;\n /**\n * Run one maintenance pass with wake deferral (see `scheduleNow`): `scheduleNow` calls\n * while `body` executes coalesce into one flag, flushed as an immediate re-arm after the\n * pass — failures of the flush are logged and swallowed (hints are droppable; the pass's\n * own re-arm policy already bounded the next delivery).\n */\n readonly withWakesDeferred: <A, E, R>(body: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R>;\n /** Clear the slot; only the maintenance pass does this, and only when all work settled. */\n readonly cancel: Effect.Effect<void, DurableAlarmError>;\n }\n>()(\"@effect-agent/platform-cloudflare/DurableAlarmService\") {\n static readonly layer: Layer.Layer<DurableAlarmService, never, DurableObjectContext> =\n Layer.effect(DurableAlarmService)(\n Effect.gen(function* () {\n const { ctx } = yield* DurableObjectContext;\n /**\n * In-memory pass bookkeeping — a pure CACHE, never state: a fresh incarnation has no\n * running pass, and a deferred wake lost to eviction was only ever a promptness hint\n * on top of the already-committed pre-armed alarm.\n */\n const runningPasses = yield* Ref.make(0);\n const wakeDeferred = yield* Ref.make(false);\n const scheduled = Effect.tryPromise({\n try: () => ctx.storage.getAlarm(),\n catch: alarmFailure(\"get alarm\"),\n }).pipe(\n Effect.map((deadline) =>\n deadline === null ? Option.none<number>() : Option.some(deadline),\n ),\n );\n const scheduleAt = (epochMillis: number) =>\n Effect.tryPromise({\n try: () => ctx.storage.setAlarm(epochMillis),\n catch: alarmFailure(\"set alarm\"),\n });\n const ensureScheduledBy = (epochMillis: number) =>\n scheduled.pipe(\n Effect.flatMap((existing) =>\n Option.isSome(existing) && existing.value <= epochMillis\n ? Effect.void\n : scheduleAt(epochMillis),\n ),\n );\n const armNow = Clock.currentTimeMillis.pipe(\n Effect.flatMap((now) => ensureScheduledBy(now)),\n );\n const scheduleNow = Ref.get(runningPasses).pipe(\n Effect.flatMap((passes) => (passes > 0 ? Ref.set(wakeDeferred, true) : armNow)),\n );\n /**\n * Flush after the LAST concurrent pass: the re-arm lands at the very end of the alarm\n * handler, where a superseding cancellation only re-delivers to the already-idempotent\n * pass. Runs inside `Effect.ensuring`, so flush failures are logged, never raised.\n */\n const flushDeferredWake = Ref.get(runningPasses).pipe(\n Effect.flatMap((passes) =>\n passes > 0\n ? Effect.void\n : Ref.getAndSet(wakeDeferred, false).pipe(\n Effect.flatMap((wanted) => (wanted ? armNow : Effect.void)),\n ),\n ),\n Effect.catch((error) =>\n Effect.logWarning(\"DurableAlarmService: deferred wake flush failed\", error),\n ),\n );\n const withWakesDeferred = <A, E, R>(body: Effect.Effect<A, E, R>): Effect.Effect<A, E, R> =>\n Ref.update(runningPasses, (passes) => passes + 1).pipe(\n Effect.andThen(body),\n Effect.ensuring(\n Ref.update(runningPasses, (passes) => passes - 1).pipe(\n Effect.andThen(flushDeferredWake),\n ),\n ),\n );\n const cancel = Effect.tryPromise({\n try: () => ctx.storage.deleteAlarm(),\n catch: alarmFailure(\"delete alarm\"),\n });\n return DurableAlarmService.of({\n scheduled,\n scheduleAt,\n ensureScheduledBy,\n scheduleNow,\n withWakesDeferred,\n cancel,\n });\n }),\n );\n}\n\n/** What one maintenance pass did — auditable evidence mirroring `NodeDurableHost`'s report. */\nexport class MaintenancePassReport extends Schema.Class<MaintenancePassReport>(\n \"@effect-agent/platform-cloudflare/MaintenancePassReport\",\n)({\n /** Recovery decisions executed (or deferred) BEFORE any new claim in this pass. */\n recovered: Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)),\n /** Settlements the drain pass finalized. */\n settled: Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)),\n /** Submissions still nonterminal after the pass (suspended/unknown lanes stay honest). */\n nonterminal: Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)),\n /** `rearmed` while nonterminal work remains, `cleared` once everything settled. */\n alarm: Schema.Literals([\"rearmed\", \"cleared\"]),\n}) {}\n\nexport type MaintenancePassFailure =\n | DurableWorkerFailure\n | DurableBindingFailure\n | DurableAlarmError;\n\n/**\n * The idempotent maintenance pass and the alarm-invariant helpers (plan §1.4, D-P6-1/2).\n *\n * `pass` = pre-arm → `runRecovery` → `processConversationResolved` → re-arm-or-clear:\n *\n * 1. **Pre-arm**: the alarm is re-armed at `now + wakeScanInterval` BEFORE any work, so an\n * eviction (or thrown failure → workerd alarm retry) at any point of the pass leaves a\n * committed alarm and the fresh incarnation converges without an incoming request.\n * 2. **Reconcile before new work** (exit gate): every pass classifies and repairs every\n * nonterminal Submission before the drain claims anything; the pure classifier and the\n * repair executors are idempotent, so at-least-once alarm delivery re-runs them safely.\n * 3. **Drain**: one bounded `processConversationResolved` pass over this Object's lane — the\n * D-P6-1 shape; no infinite `runResolvedWorker` loop ever pins the Object.\n * 4. **Re-arm policy**: nonterminal work re-arms at `now + min(backoff-with-jitter,\n * wakeScanInterval)` — the scan interval bounds every wait (lease expiry of a dead\n * incarnation included, since claims retry each pass) and the backoff (reset on progress,\n * grown otherwise) keeps stuck lanes from busy-spinning; all settled clears the slot.\n *\n * Every step is a durability-protocol step that already tolerates re-execution, which is\n * what makes double-fired alarms harmless (the alarm.test.ts gate).\n */\nexport class ConversationMaintenance extends Context.Service<\n ConversationMaintenance,\n {\n /** One idempotent maintenance pass; failures propagate so workerd retries the alarm. */\n readonly pass: Effect.Effect<MaintenancePassReport, MaintenancePassFailure>;\n /**\n * Defensive half of the alarm invariant, run by the constructor gate: if any local\n * Submission is nonterminal and no alarm is scheduled, arm one within the scan interval.\n * Local-only (one ledger scan + the alarm slot) — never a recovery pass, never transport.\n */\n readonly ensureAlarm: Effect.Effect<void, MaintenancePassFailure>;\n /**\n * The pre-arm every mutating entry point runs BEFORE its first durable mutation: with\n * the alarm committed first, a committed admission (or any other committed nonterminal\n * transition) can never be observed without the alarm that will finish it.\n */\n readonly preArm: Effect.Effect<void, DurableAlarmError>;\n }\n>()(\"@effect-agent/platform-cloudflare/ConversationMaintenance\") {\n static readonly layer: Layer.Layer<\n ConversationMaintenance,\n never,\n | DurableAgentRuntime\n | AgentBindingResolver\n | SubmissionLedger\n | DurableAlarmService\n | CloudflareDurableRuntimeConfig\n | ConversationObjectIdentity\n > = Layer.effect(ConversationMaintenance)(\n Effect.gen(function* () {\n const runtime = yield* DurableAgentRuntime;\n const resolver = yield* AgentBindingResolver;\n const ledger = yield* SubmissionLedger;\n const alarm = yield* DurableAlarmService;\n const config = yield* CloudflareDurableRuntimeConfig;\n const identity = yield* ConversationObjectIdentity;\n\n /**\n * Consecutive no-progress passes — an in-memory CACHE, not state: a fresh incarnation\n * restarts at zero and merely re-arms sooner than a long-lived one would have.\n */\n const stalls = yield* Ref.make(0);\n\n const preArm = Clock.currentTimeMillis.pipe(\n Effect.flatMap((now) => alarm.ensureScheduledBy(now + config.wakeScanInterval)),\n );\n\n const countNonterminal = Stream.runCollect(ledger.scanNonterminal).pipe(\n Effect.map((snapshots) => snapshots.length),\n );\n\n const rearmDelay = Effect.fn(\"ConversationMaintenance.rearmDelay\")(function* (\n progressed: boolean,\n ) {\n const priorStalls = yield* Ref.getAndUpdate(stalls, (count) =>\n progressed ? 0 : count + 1,\n );\n if (progressed) return config.alarmBackoffBase;\n const exponent = Math.min(priorStalls, 30);\n const backoff = Math.min(config.alarmBackoffCap, config.alarmBackoffBase * 2 ** exponent);\n const jitter = yield* Random.next;\n // Full jitter over [backoff/2, backoff]: desynchronizes retry storms without ever\n // waiting longer than the deterministic bound.\n const jittered = Math.ceil(backoff / 2 + (backoff / 2) * jitter);\n return Math.min(jittered, config.wakeScanInterval);\n });\n\n const pass = Effect.fn(\"ConversationMaintenance.pass\")(function* (): Effect.fn.Return<\n MaintenancePassReport,\n MaintenancePassFailure\n > {\n // Step 1 — pre-arm: an abort or throw anywhere below leaves a committed alarm.\n yield* preArm;\n // Step 2 — reconciliation strictly precedes new work in this pass (exit gate).\n const recovered: ReadonlyArray<RecoveryReport> = yield* runtime.runRecovery;\n // Step 3 — one bounded drain pass over this Object's own lane.\n const settlements = yield* runtime\n .processConversationResolved(identity.conversationId)\n .pipe(Effect.provideService(AgentBindingResolver, resolver));\n // Step 4 — re-arm or clear.\n const nonterminal = yield* countNonterminal;\n if (nonterminal === 0) {\n yield* alarm.cancel;\n yield* Ref.set(stalls, 0);\n // Close the cancel/admission interleaving window: a submission committing between\n // the count and the cancel (Durable Object events interleave at storage-operation\n // boundaries) must not be left without its alarm. The recount re-arms if anything\n // appeared; the submit entry's own `scheduleNow` covers commits after the recount.\n const appeared = yield* countNonterminal;\n if (appeared > 0) {\n yield* preArm;\n return MaintenancePassReport.make({\n recovered: recovered.length,\n settled: settlements.length,\n nonterminal: appeared,\n alarm: \"rearmed\",\n });\n }\n return MaintenancePassReport.make({\n recovered: recovered.length,\n settled: settlements.length,\n nonterminal,\n alarm: \"cleared\",\n });\n }\n const progressed =\n settlements.length > 0 || recovered.some((report) => report.disposition === \"repaired\");\n const delay = yield* rearmDelay(progressed);\n const now = yield* Clock.currentTimeMillis;\n yield* alarm.ensureScheduledBy(now + delay);\n return MaintenancePassReport.make({\n recovered: recovered.length,\n settled: settlements.length,\n nonterminal,\n alarm: \"rearmed\",\n });\n });\n\n const ensureAlarm = Effect.fn(\"ConversationMaintenance.ensureAlarm\")(function* () {\n const nonterminal = yield* countNonterminal;\n if (nonterminal === 0) return;\n yield* preArm;\n });\n\n return ConversationMaintenance.of({\n // Wake deferral (see `DurableAlarmService.scheduleNow`): an immediate wake written\n // while THIS handler runs would make workerd cancel it mid-Attempt; deferring keeps\n // the running pass alive and flushes the hint as the pass's final re-arm.\n pass: alarm.withWakesDeferred(pass()),\n ensureAlarm: ensureAlarm(),\n preArm,\n });\n }),\n );\n}\n","import type { ConversationId } from \"@effect-agent/core\";\nimport { WakeScheduler } from \"@effect-agent/session\";\nimport { Effect, Layer, PubSub, Schema, Stream } from \"effect\";\n\nimport { DurableAlarmService } from \"./alarm.ts\";\nimport { ConversationObjectIdentity, ConversationObjectNamespace } from \"./bindings.ts\";\n\n/**\n * Bounded in-memory wake buffer for same-incarnation `awaitSettlement` subscribers. Wake\n * hints are droppable by contract (consumers pair every subscription with ledger polls), so\n * a full buffer slides out the oldest hint and an eviction simply loses the buffer — the\n * poll interval and the persisted alarm keep liveness (persistence §14).\n */\nconst WAKE_BUFFER_CAPACITY = 1_024;\n\n/** A remote wake stub call failed; always swallowed and logged (hints are droppable). */\nclass RemoteWakeDropped extends Schema.TaggedError<RemoteWakeDropped>()(\"RemoteWakeDropped\", {\n conversationId: Schema.String,\n message: Schema.String,\n cause: Schema.optionalKey(Schema.Defect()),\n}) {}\n\n/**\n * The DC `WakeScheduler` (plan §1.4):\n *\n * - `notify(local)` → `setAlarm(now)` — durable, cheap, coalescing (the alarm slot keeps the\n * earliest deadline) — plus a same-incarnation PubSub hint for `awaitSettlement` waiters.\n * - `notify(remote)` → fire-and-forget `wake()` on the owning Object's stub with every error\n * swallowed and logged: hints are droppable, and the target's own alarm/scan pairing (the\n * maintenance pass re-polls unsettled children) guarantees liveness without this call.\n * - `wakes` → the bounded sliding PubSub only. No important state lives in memory: the\n * subscription accelerates waiters within one incarnation and the settlement poll interval\n * is the correctness path.\n */\nexport const cloudflareWakeSchedulerLayer: Layer.Layer<\n WakeScheduler,\n never,\n DurableAlarmService | ConversationObjectIdentity | ConversationObjectNamespace\n> = Layer.effect(WakeScheduler)(\n Effect.gen(function* () {\n const alarm = yield* DurableAlarmService;\n const identity = yield* ConversationObjectIdentity;\n const { namespace } = yield* ConversationObjectNamespace;\n const hints = yield* PubSub.sliding<ConversationId>(WAKE_BUFFER_CAPACITY);\n yield* Effect.addFinalizer(() => PubSub.shutdown(hints));\n\n const notifyLocal = (conversationId: ConversationId) =>\n PubSub.publish(hints, conversationId).pipe(\n Effect.andThen(alarm.scheduleNow),\n Effect.catch((error) =>\n // `notify` never fails by contract; a failed alarm write degrades to \"hint lost\"\n // and the pass re-arm (or the next entry point's pre-arm) restores the invariant.\n Effect.logWarning(\"CloudflareWakeScheduler: local alarm wake failed\", error),\n ),\n Effect.asVoid,\n );\n\n const notifyRemote = (conversationId: ConversationId) =>\n Effect.tryPromise({\n try: () => namespace.get(namespace.idFromName(conversationId)).wake(),\n catch: (cause) =>\n RemoteWakeDropped.make({\n conversationId,\n message: cause instanceof Error ? cause.message : String(cause),\n cause,\n }),\n }).pipe(\n Effect.catch((error) =>\n Effect.logWarning(\n `CloudflareWakeScheduler: remote wake of ${conversationId} dropped`,\n error,\n ),\n ),\n Effect.asVoid,\n );\n\n return WakeScheduler.of({\n notify: (conversationId) =>\n conversationId === identity.conversationId\n ? notifyLocal(conversationId)\n : notifyRemote(conversationId),\n wakes: Stream.fromPubSub(hints),\n });\n }),\n);\n","import { ConversationPortTransport, portTransportFailure } from \"@effect-agent/storage-cloudflare\";\nimport { Effect, Layer } from \"effect\";\n\nimport { ConversationObjectNamespace } from \"./bindings.ts\";\n\n/**\n * `ConversationPortTransport` over native Durable Object JS RPC (decision D-P6-3): one\n * `portCall(envelope)` on the stub of the Object that owns the addressed Conversation\n * (`namespace.idFromName(conversationId)` — 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 conversationPortTransportLayer: Layer.Layer<\n ConversationPortTransport,\n never,\n ConversationObjectNamespace\n> = Layer.effect(ConversationPortTransport)(\n Effect.gen(function* () {\n const { namespace } = yield* ConversationObjectNamespace;\n return ConversationPortTransport.of({\n call: (conversationId, request) =>\n Effect.tryPromise({\n try: () => namespace.get(namespace.idFromName(conversationId)).portCall(request),\n catch: (cause) => portTransportFailure(conversationId, cause),\n }).pipe(\n Effect.withSpan(\"CloudflarePortTransport.call\", {\n attributes: { conversationId },\n }),\n ),\n });\n }),\n);\n","import { ConversationId } from \"@effect-agent/core\";\nimport {\n AgentBindingResolver,\n ConversationStore,\n DurableAgentRuntime,\n DurableRuntimeConfig,\n DurableRuntimeFailpoint,\n ProducerId,\n SubmissionLedger,\n ToolReconciler,\n WakeScheduler,\n type DurableRuntimeFailpointHandler,\n type ResolvedBinding,\n} from \"@effect-agent/session\";\nimport {\n conversationStoreLayer,\n handleEncodedPortRequest,\n routedConversationStoreLayer,\n routedSubmissionLedgerLayer,\n storageConfigLayer,\n storageFailpointLayer,\n submissionLedgerLayer,\n type DoStorageFailpointHandler,\n type DoStorageInitializationError,\n type DoStorageOptions,\n} from \"@effect-agent/storage-cloudflare\";\nimport { BrowserCrypto } from \"@effect/platform-browser\";\nimport { SqliteClient } from \"@effect/sql-sqlite-do\";\nimport { Context, Duration, Effect, Layer, Schema } from \"effect\";\n\nimport { ConversationMaintenance, DurableAlarmService } from \"./alarm.ts\";\nimport {\n ConversationObjectIdentity,\n ConversationObjectNamespace,\n DurableObjectContext,\n} from \"./bindings.ts\";\nimport {\n CLOUDFLARE_RUNTIME_DEFAULTS,\n CloudflareDurableRuntimeConfig,\n CloudflareDurableRuntimeConfigValue,\n CloudflarePlatformConfigError,\n} from \"./config.ts\";\nimport { conversationPortTransportLayer } from \"./transport.ts\";\nimport { cloudflareWakeSchedulerLayer } from \"./wake-scheduler.ts\";\n\n/**\n * Raw (unvalidated) construction options for `CloudflareDurableRuntime.layer`, mirroring\n * `NodeDurableRuntimeOptions`. 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}:{conversationId}`. */\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 /** 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 /**\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 * Registered worker Bindings resolved at durable claim time (S2, spec/subagents.md §11):\n * build each with `DurableWorkerBinding.make(binding, digests)`. An Effect or callback form is\n * accepted because capture can be effectful. The callback receives the live Object context and\n * derived identities and is evaluated once per incarnation during Layer construction. Defaults\n * to the empty registration (every resolved claim fails closed).\n */\n readonly bindings?: CloudflareBindingSource | undefined;\n}\n\n/** Per-incarnation host values available while registered worker Bindings are captured. */\nexport interface CloudflareBindingSourceContext {\n readonly ctx: DurableObjectState;\n readonly env: unknown;\n readonly conversationId: ConversationId;\n readonly producerId: ProducerId;\n}\n\n/**\n * Registered worker Bindings, or a closed Effect/callback that captures them once for each\n * Durable Object incarnation. Callback Effects cannot require services or fail typed.\n */\nexport type CloudflareBindingSource =\n | ReadonlyArray<ResolvedBinding>\n | Effect.Effect<ReadonlyArray<ResolvedBinding>, never, never>\n | ((\n context: CloudflareBindingSourceContext,\n ) =>\n | ReadonlyArray<ResolvedBinding>\n | Effect.Effect<ReadonlyArray<ResolvedBinding>, never, never>);\n\n/** Every construction failure of the assembled Cloudflare durable runtime stack. */\nexport type CloudflareDurableRuntimeInitializationError =\n | CloudflarePlatformConfigError\n | DoStorageInitializationError;\n\n/** The services `CloudflareDurableRuntime.layer` provides. */\nexport type CloudflareDurableRuntimeServices =\n | DurableAgentRuntime\n | SubmissionLedger\n | ConversationStore\n | WakeScheduler\n | DurableRuntimeConfig\n | AgentBindingResolver\n | CloudflareDurableRuntimeConfig\n | ConversationObjectIdentity\n | DurableAlarmService\n | ConversationMaintenance\n | ConversationObjectPorts;\n\n/**\n * Owner-side endpoint body for the Conversation Object's `portCall` (plan §1.3): decode,\n * execute against THIS Object's LOCAL port facets — never the routed decorators, so a\n * request cannot bounce between Objects — and answer the encoded response envelope. Total by\n * construction (protocol anomalies answer `PortFailed(PortProtocolError)`).\n */\nexport class ConversationObjectPorts extends Context.Service<\n ConversationObjectPorts,\n {\n readonly handle: (encoded: unknown) => Effect.Effect<unknown>;\n }\n>()(\"@effect-agent/platform-cloudflare/ConversationObjectPorts\") {}\n\nconst decodeConfigValue = Schema.decodeUnknownEffect(CloudflareDurableRuntimeConfigValue);\nconst decodeConversationId = Schema.decodeUnknownEffect(ConversationId);\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 Conversation this Object owns, from the Object identity rule (plan §1.2): Conversation\n * Objects are addressed exclusively by `idFromName(conversationId)`, so `ctx.id.name` IS the\n * Conversation ID. An unnamed Object (from `newUniqueId`) is a deployment error, not a lane.\n */\nconst conversationIdFromState = (\n ctx: DurableObjectState,\n): Effect.Effect<ConversationId, CloudflarePlatformConfigError> =>\n ctx.id.name === undefined\n ? Effect.fail(\n CloudflarePlatformConfigError.make({\n message:\n \"This Durable Object was not created via idFromName(conversationId); Conversation \" +\n \"Objects must be addressed by their Conversation identity (plan §1.2).\",\n }),\n )\n : decodeConversationId(ctx.id.name).pipe(\n Effect.mapError((error) =>\n CloudflarePlatformConfigError.make({\n message: `The Durable Object name is not a valid ConversationId: ${error.message}`,\n cause: error,\n }),\n ),\n );\n\nconst resolveBindings = (\n source: CloudflareDurableRuntimeOptions[\"bindings\"],\n context: CloudflareBindingSourceContext,\n): Effect.Effect<ReadonlyArray<ResolvedBinding>> =>\n source === undefined\n ? Effect.succeed([])\n : Effect.isEffect(source)\n ? source\n : typeof source === \"function\"\n ? Effect.suspend(() => {\n const bindings = source(context);\n return Effect.isEffect(bindings) ? bindings : Effect.succeed(bindings);\n })\n : Effect.succeed(source);\n\n/**\n * The DC Layer assembly (deployment §12: a Layer-assembly library, not an app entrypoint;\n * plan §1.4). `layer(options)` decodes the configuration, derives this Object's Conversation\n * and producer identities, opens the Object's private SQLite database through\n * `@effect/sql-sqlite-do` for BOTH the Conversation Log and the Submission Ledger (so claims\n * fence the same producer epochs — ADR-0011 D7 transposed), wraps the local port facets with\n * the WP2 cross-Object routing decorators over the Durable Object RPC transport, wires the\n * alarm-backed wake scheduler and the maintenance pass, defaults reconciliation to the\n * fail-closed `ToolReconciler.uncertain`, and provides a ready `DurableAgentRuntime` on top.\n *\n * Storage compatibility is verified during construction: an incompatible database fails the\n * Layer typed (`DoStorageCompatibilityError`) before anything is mutated (DEPLOY-008).\n *\n * Requires only the two binding services (`DurableObjectContext`,\n * `ConversationObjectNamespace`) — platform values enter exclusively through Layers\n * (DEPLOY-010).\n */\nexport class CloudflareDurableRuntime {\n static layer(\n options: CloudflareDurableRuntimeOptions,\n ): Layer.Layer<\n CloudflareDurableRuntimeServices,\n CloudflareDurableRuntimeInitializationError,\n DurableObjectContext | ConversationObjectNamespace\n > {\n return Layer.unwrap(\n Effect.gen(function* () {\n const { ctx, env } = yield* DurableObjectContext;\n const config = yield* configFromOptions(options);\n const conversationId = yield* conversationIdFromState(ctx);\n const producerId = yield* decodeProducerId(\n `${config.producerPrefix}:${conversationId}`,\n ).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 const identityLayer = Layer.succeed(ConversationObjectIdentity)({\n conversationId,\n producerId,\n });\n const cloudflareConfigLayer = Layer.succeed(CloudflareDurableRuntimeConfig)(config);\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 failpoint: options.storageFailpoint?.(ctx),\n };\n const infrastructure = Layer.mergeAll(\n storageConfigLayer(storageOptions),\n storageFailpointLayer(storageOptions),\n SqliteClient.layer({ storage: ctx.storage }),\n BrowserCrypto.layer,\n );\n\n /**\n * ONE local-facet instance (a shared Layer value) serves both the routed decorators\n * and the owner-side `portCall` executor — the executor must never see the routed\n * ports (plan §1.3: re-routing could bounce a request between Objects).\n */\n const localPorts = Layer.mergeAll(conversationStoreLayer, submissionLedgerLayer).pipe(\n Layer.provide(infrastructure),\n );\n\n const portsEndpointLayer = Layer.effect(ConversationObjectPorts)(\n Effect.gen(function* () {\n const local = yield* Effect.context<SubmissionLedger | ConversationStore>();\n return ConversationObjectPorts.of({\n handle: (encoded) => handleEncodedPortRequest(encoded).pipe(Effect.provide(local)),\n });\n }),\n ).pipe(Layer.provide(localPorts));\n\n const routedPorts = Layer.mergeAll(\n routedSubmissionLedgerLayer({ localConversationId: conversationId }),\n routedConversationStoreLayer({ localConversationId: conversationId }),\n ).pipe(Layer.provide(localPorts), Layer.provide(conversationPortTransportLayer));\n\n const runtimeConfigLayer = Layer.succeed(DurableRuntimeConfig)(\n DurableRuntimeConfig.make({\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 }),\n );\n\n const runtimeFailpointLayer =\n options.runtimeFailpoint === undefined\n ? DurableRuntimeFailpoint.layer\n : Layer.succeed(DurableRuntimeFailpoint)({ hit: options.runtimeFailpoint(ctx) });\n const reconcilerLayer = options.toolReconciler ?? ToolReconciler.uncertain;\n const bindingResolverLayer = Layer.effect(AgentBindingResolver)(\n Effect.map(\n resolveBindings(options.bindings, { ctx, env, conversationId, producerId }),\n (bindings) => AgentBindingResolver.fromBindings(bindings),\n ),\n );\n\n const base = Layer.mergeAll(\n identityLayer,\n cloudflareConfigLayer,\n DurableAlarmService.layer,\n );\n\n const runtimeStack = DurableAgentRuntime.layer.pipe(\n Layer.provideMerge(routedPorts),\n Layer.provideMerge(cloudflareWakeSchedulerLayer),\n Layer.provideMerge(runtimeConfigLayer),\n Layer.provideMerge(bindingResolverLayer),\n Layer.provide(\n Layer.mergeAll(runtimeFailpointLayer, reconcilerLayer, BrowserCrypto.layer),\n ),\n Layer.provideMerge(base),\n );\n\n return Layer.mergeAll(\n runtimeStack,\n ConversationMaintenance.layer.pipe(Layer.provide(runtimeStack)),\n portsEndpointLayer,\n );\n }),\n );\n }\n}\n","import { AgentId, AgentInputError, type ConversationId } from \"@effect-agent/core\";\nimport {\n AbortCommand,\n AbortIntent,\n AdmissionConflict,\n AppendConflict,\n ApprovalConflict,\n ApprovalDecisionCommand,\n ApprovalDecisionIntent,\n CanonicalRecordEnvelope,\n CanonicalSequence,\n ConversationNotMaterialized,\n ConversationStoreError,\n DefinitionDigests,\n DigestError,\n DurableRuntimeFailpointError,\n FenceRejected,\n IdempotencyKey,\n JoinedToHost,\n LedgerError,\n PersistedJson,\n Principal,\n Receipt,\n Settlement,\n SettlementConflict,\n UnknownResolutionCommand,\n UnknownResolutionConflict,\n UnknownResolutionIntent,\n type DurableSubmitAgent,\n type DurableSubmitOptions,\n} from \"@effect-agent/session\";\nimport { Context, Effect, Layer, Schema } from \"effect\";\n\nimport { DurableAlarmError } from \"./alarm.ts\";\nimport { ConversationObjectNamespace, type ConversationObjectRpc } from \"./bindings.ts\";\nimport { AdmissionLimitExceeded } from \"./config.ts\";\n\n/**\n * The Worker↔Conversation-Object host protocol (plan §1.4): Schema envelopes for the host\n * entry points (`submitEncoded`, `awaitSettlementEncoded`, `observePage`, `abortEncoded`,\n * `resolveApprovalEncoded`, `resolveUnknownEncoded`) plus the Worker-side client that speaks\n * it. Mirrors the WP2 port protocol: requests and responses are closed Schema unions, typed\n * failures travel as their own tagged classes and RE-DECODE to identical tags on the caller\n * (error-tag fidelity), and protocol anomalies are answered typed instead of thrown.\n */\n\n/** Ceiling for host protocol diagnostic strings. */\nconst MAX_HOST_DIAGNOSTIC_LENGTH = 4_096;\n\nconst BoundedDiagnostic = Schema.String.check(Schema.isMaxLength(MAX_HOST_DIAGNOSTIC_LENGTH));\n\n/** Truncate a diagnostic string to the host protocol's bounded length. */\nexport const boundHostDiagnostic = (value: string): string =>\n value.length > MAX_HOST_DIAGNOSTIC_LENGTH\n ? `${value.slice(0, MAX_HOST_DIAGNOSTIC_LENGTH - 3)}...`\n : value;\n\n/**\n * The envelope itself could not be honored: the Object could not decode the request, or a\n * response could not be encoded/decoded. Never carries operation semantics.\n */\nexport class HostProtocolError extends Schema.TaggedError<HostProtocolError>()(\n \"HostProtocolError\",\n {\n message: BoundedDiagnostic,\n },\n) {}\n\n/** The Worker-side stub call itself failed (RPC rejection, overload, eviction mid-call). */\nexport class ConversationClientError extends Schema.TaggedError<ConversationClientError>()(\n \"ConversationClientError\",\n {\n conversationId: Schema.String,\n message: Schema.String,\n cause: Schema.optionalKey(Schema.Defect()),\n },\n) {}\n\n// ---------------------------------------------------------------------------\n// Requests\n// ---------------------------------------------------------------------------\n\n/**\n * One durable submission, input ALREADY encoded by the caller through the Agent Binding's\n * input schema (the Worker bundles the same Agent definitions as the Object, so schema\n * validation happens client-side; the resolved Binding re-validates at claim time). The\n * Conversation identity is deliberately absent — the addressed Object IS the lane.\n */\nexport class SubmitRequest extends Schema.Class<SubmitRequest>(\n \"@effect-agent/platform-cloudflare/SubmitRequest\",\n)({\n agentId: AgentId,\n principal: Principal,\n idempotencyKey: IdempotencyKey,\n definitions: DefinitionDigests,\n inputPayload: PersistedJson,\n}) {}\n\n/** One bounded page of canonical records after an optional sequence. */\nexport class ObservePageRequest extends Schema.Class<ObservePageRequest>(\n \"@effect-agent/platform-cloudflare/ObservePageRequest\",\n)({\n afterSequence: Schema.optionalKey(CanonicalSequence),\n limit: Schema.Int.check(Schema.isGreaterThan(0), Schema.isLessThanOrEqualTo(1_024)),\n}) {}\n\n// ---------------------------------------------------------------------------\n// Responses\n// ---------------------------------------------------------------------------\n\n/**\n * Every typed failure a host entry point can produce, plus the protocol's own errors. Same\n * closed-union discipline as the WP2 `PortFailure`: members re-decode to the SAME tagged\n * classes on the Worker side; `cause` chains travel as Schema defects without instance\n * fidelity (plan §2.8).\n */\nexport const HostFailure = Schema.Union([\n AgentInputError,\n DigestError,\n AdmissionConflict,\n SettlementConflict,\n ApprovalConflict,\n UnknownResolutionConflict,\n JoinedToHost,\n LedgerError,\n ConversationStoreError,\n ConversationNotMaterialized,\n AppendConflict,\n FenceRejected,\n DurableRuntimeFailpointError,\n AdmissionLimitExceeded,\n DurableAlarmError,\n HostProtocolError,\n]);\nexport type HostFailure = typeof HostFailure.Type;\n\nexport class SubmitSucceeded extends Schema.TaggedClass<SubmitSucceeded>(\n \"@effect-agent/platform-cloudflare/SubmitSucceeded\",\n)(\"SubmitSucceeded\", {\n receipt: Receipt,\n}) {}\n\nexport class SettlementReached extends Schema.TaggedClass<SettlementReached>(\n \"@effect-agent/platform-cloudflare/SettlementReached\",\n)(\"SettlementReached\", {\n settlement: Settlement,\n}) {}\n\nexport class ObservedPage extends Schema.TaggedClass<ObservedPage>(\n \"@effect-agent/platform-cloudflare/ObservedPage\",\n)(\"ObservedPage\", {\n records: Schema.Array(CanonicalRecordEnvelope).check(Schema.isMaxLength(1_024)),\n}) {}\n\nexport class AbortRecorded extends Schema.TaggedClass<AbortRecorded>(\n \"@effect-agent/platform-cloudflare/AbortRecorded\",\n)(\"AbortRecorded\", {\n intent: AbortIntent,\n}) {}\n\nexport class ApprovalRecorded extends Schema.TaggedClass<ApprovalRecorded>(\n \"@effect-agent/platform-cloudflare/ApprovalRecorded\",\n)(\"ApprovalRecorded\", {\n intent: ApprovalDecisionIntent,\n}) {}\n\nexport class UnknownResolutionRecorded extends Schema.TaggedClass<UnknownResolutionRecorded>(\n \"@effect-agent/platform-cloudflare/UnknownResolutionRecorded\",\n)(\"UnknownResolutionRecorded\", {\n intent: UnknownResolutionIntent,\n}) {}\n\n/** The entry point failed TYPED on the Object; the failure re-decodes verbatim. */\nexport class HostFailed extends Schema.TaggedClass<HostFailed>(\n \"@effect-agent/platform-cloudflare/HostFailed\",\n)(\"HostFailed\", {\n failure: HostFailure,\n}) {}\n\n/** The uniform answer of one host entry point. Callers narrow by the tag their call implies. */\nexport const HostResponse = Schema.Union([\n SubmitSucceeded,\n SettlementReached,\n ObservedPage,\n AbortRecorded,\n ApprovalRecorded,\n UnknownResolutionRecorded,\n HostFailed,\n]);\nexport type HostResponse = typeof HostResponse.Type;\n\n// ---------------------------------------------------------------------------\n// Codecs (shared by the Object endpoints and the Worker client)\n// ---------------------------------------------------------------------------\n\nexport const decodeSubmitRequest = Schema.decodeUnknownEffect(SubmitRequest);\nexport const encodeSubmitRequest = Schema.encodeEffect(SubmitRequest);\nexport const decodeReceipt = Schema.decodeUnknownEffect(Receipt);\nexport const encodeReceipt = Schema.encodeEffect(Receipt);\nexport const decodeObservePageRequest = Schema.decodeUnknownEffect(ObservePageRequest);\nexport const encodeObservePageRequest = Schema.encodeEffect(ObservePageRequest);\nexport const decodeAbortCommand = Schema.decodeUnknownEffect(AbortCommand);\nexport const encodeAbortCommand = Schema.encodeEffect(AbortCommand);\nexport const decodeApprovalDecisionCommand = Schema.decodeUnknownEffect(ApprovalDecisionCommand);\nexport const encodeApprovalDecisionCommand = Schema.encodeEffect(ApprovalDecisionCommand);\nexport const decodeUnknownResolutionCommand = Schema.decodeUnknownEffect(UnknownResolutionCommand);\nexport const encodeUnknownResolutionCommand = Schema.encodeEffect(UnknownResolutionCommand);\nexport const encodeHostResponse = Schema.encodeEffect(HostResponse);\nexport const decodeHostResponse = Schema.decodeUnknownEffect(HostResponse);\n\n// ---------------------------------------------------------------------------\n// Worker-side client\n// ---------------------------------------------------------------------------\n\n/** Failure surface of `CloudflareConversationClient.submit`. */\nexport type ClientSubmitFailure =\n | AgentInputError\n | DigestError\n | AdmissionConflict\n | LedgerError\n | ConversationStoreError\n | ConversationNotMaterialized\n | AppendConflict\n | FenceRejected\n | DurableRuntimeFailpointError\n | AdmissionLimitExceeded\n | DurableAlarmError\n | HostProtocolError\n | ConversationClientError;\n\nexport type ClientAwaitFailure =\n | LedgerError\n | SettlementConflict\n | HostProtocolError\n | ConversationClientError;\n\nexport type ClientObserveFailure =\n | ConversationStoreError\n | ConversationNotMaterialized\n | HostProtocolError\n | ConversationClientError;\n\nexport type ClientAbortFailure =\n | LedgerError\n | SettlementConflict\n | JoinedToHost\n | DurableRuntimeFailpointError\n | DurableAlarmError\n | HostProtocolError\n | ConversationClientError;\n\nexport type ClientApprovalFailure =\n | LedgerError\n | SettlementConflict\n | ApprovalConflict\n | DurableAlarmError\n | HostProtocolError\n | ConversationClientError;\n\nexport type ClientUnknownFailure =\n | LedgerError\n | SettlementConflict\n | UnknownResolutionConflict\n | JoinedToHost\n | DurableRuntimeFailpointError\n | DurableAlarmError\n | HostProtocolError\n | ConversationClientError;\n\nconst SUBMIT_FAILURE_TAGS: ReadonlySet<string> = new Set([\n \"AgentInputError\",\n \"DigestError\",\n \"AdmissionConflict\",\n \"LedgerError\",\n \"ConversationStoreError\",\n \"ConversationNotMaterialized\",\n \"AppendConflict\",\n \"FenceRejected\",\n \"DurableRuntimeFailpointError\",\n \"AdmissionLimitExceeded\",\n \"DurableAlarmError\",\n \"HostProtocolError\",\n]);\nconst AWAIT_FAILURE_TAGS: ReadonlySet<string> = new Set([\n \"LedgerError\",\n \"SettlementConflict\",\n \"HostProtocolError\",\n]);\nconst OBSERVE_FAILURE_TAGS: ReadonlySet<string> = new Set([\n \"ConversationStoreError\",\n \"ConversationNotMaterialized\",\n \"HostProtocolError\",\n]);\nconst ABORT_FAILURE_TAGS: ReadonlySet<string> = new Set([\n \"LedgerError\",\n \"SettlementConflict\",\n \"JoinedToHost\",\n \"DurableRuntimeFailpointError\",\n \"DurableAlarmError\",\n \"HostProtocolError\",\n]);\nconst APPROVAL_FAILURE_TAGS: ReadonlySet<string> = new Set([\n \"LedgerError\",\n \"SettlementConflict\",\n \"ApprovalConflict\",\n \"DurableAlarmError\",\n \"HostProtocolError\",\n]);\nconst UNKNOWN_FAILURE_TAGS: ReadonlySet<string> = new Set([\n \"LedgerError\",\n \"SettlementConflict\",\n \"UnknownResolutionConflict\",\n \"JoinedToHost\",\n \"DurableRuntimeFailpointError\",\n \"DurableAlarmError\",\n \"HostProtocolError\",\n]);\n\nconst outOfContract = (\n conversationId: string,\n operation: string,\n observed: string,\n): ConversationClientError =>\n ConversationClientError.make({\n conversationId,\n message: boundHostDiagnostic(\n `The Conversation Object answered ${operation} with the out-of-contract ${observed}.`,\n ),\n });\n\n/**\n * Narrow one decoded `HostFailed.failure` to the operation's declared failure family; an\n * out-of-contract tag folds into `ConversationClientError` instead of being erased or\n * re-thrown raw (the WP2 discipline). The predicate is the single documented narrowing over\n * the closed `HostFailure` union.\n */\nconst narrowFailure =\n <Failure extends HostFailure>(tags: ReadonlySet<string>) =>\n (failure: HostFailure): failure is Failure =>\n tags.has(failure._tag);\n\n/** Worker-side client over the Conversation Object namespace (DEPLOY-010). */\nexport class CloudflareConversationClient extends Context.Service<\n CloudflareConversationClient,\n {\n /** Encode the input client-side, then durably submit to the owning Object. */\n readonly submit: <InputSchema extends Schema.Top>(\n agent: DurableSubmitAgent<InputSchema>,\n input: InputSchema[\"Type\"],\n options: DurableSubmitOptions,\n ) => Effect.Effect<Receipt, ClientSubmitFailure, InputSchema[\"EncodingServices\"]>;\n /** Wake-hinted, poll-guaranteed settlement wait executed inside the owning Object. */\n readonly awaitSettlement: (receipt: Receipt) => Effect.Effect<Settlement, ClientAwaitFailure>;\n /** One bounded page of canonical records. */\n readonly readPage: (\n conversationId: ConversationId,\n options?: {\n readonly afterSequence?: CanonicalSequence | undefined;\n readonly limit?: number | undefined;\n },\n ) => Effect.Effect<ReadonlyArray<CanonicalRecordEnvelope>, ClientObserveFailure>;\n /**\n * Every canonical record up to the CURRENT committed tail, via repeated pages. A\n * snapshot read, not a live observation — callers wanting liveness re-read after\n * `awaitSettlement`.\n */\n readonly readAll: (\n conversationId: ConversationId,\n ) => Effect.Effect<ReadonlyArray<CanonicalRecordEnvelope>, ClientObserveFailure>;\n /**\n * Submission-addressed operations take the owning Conversation explicitly (from the\n * Receipt): minted Submission identities stay OPAQUE outside the storage adapter that\n * minted them (D-P6-5), so the client never parses one to find the lane.\n */\n readonly abort: (\n conversationId: ConversationId,\n command: AbortCommand,\n ) => Effect.Effect<AbortIntent, ClientAbortFailure>;\n readonly resolveApproval: (\n conversationId: ConversationId,\n command: ApprovalDecisionCommand,\n ) => Effect.Effect<ApprovalDecisionIntent, ClientApprovalFailure>;\n readonly resolveUnknown: (\n conversationId: ConversationId,\n command: UnknownResolutionCommand,\n ) => Effect.Effect<UnknownResolutionIntent, ClientUnknownFailure>;\n }\n>()(\"@effect-agent/platform-cloudflare/CloudflareConversationClient\") {\n static readonly layer: Layer.Layer<\n CloudflareConversationClient,\n never,\n ConversationObjectNamespace\n > = Layer.effect(CloudflareConversationClient)(\n Effect.gen(function* () {\n const { namespace } = yield* ConversationObjectNamespace;\n\n const call = (\n conversationId: string,\n operation: string,\n invoke: (stub: DurableObjectStub<ConversationObjectRpc>) => Promise<unknown>,\n ): Effect.Effect<HostResponse, ConversationClientError | HostProtocolError> =>\n Effect.tryPromise({\n try: () => invoke(namespace.get(namespace.idFromName(conversationId))),\n catch: (cause) =>\n ConversationClientError.make({\n conversationId,\n message: boundHostDiagnostic(\n `${operation} did not reach the Conversation Object: ${\n cause instanceof Error ? cause.message : String(cause)\n }`,\n ),\n cause,\n }),\n }).pipe(\n Effect.flatMap((raw) =>\n decodeHostResponse(raw).pipe(\n Effect.mapError(\n (error): HostProtocolError =>\n HostProtocolError.make({\n message: boundHostDiagnostic(\n `The ${operation} answer could not be decoded: ${error.message}`,\n ),\n }),\n ),\n ),\n ),\n Effect.withSpan(\"CloudflareConversationClient.call\", {\n attributes: { conversationId, operation },\n }),\n );\n\n const expect = <\n Result extends Exclude<HostResponse, HostFailed>,\n Failure extends HostFailure,\n >(\n conversationId: string,\n operation: string,\n resultTag: Result[\"_tag\"],\n tags: ReadonlySet<string>,\n ) => {\n const isExpected = narrowFailure<Failure>(tags);\n return (\n response: HostResponse,\n ): Effect.Effect<Result, Failure | ConversationClientError> => {\n if (response._tag === \"HostFailed\") {\n const failure = response.failure;\n return isExpected(failure)\n ? Effect.fail(failure)\n : Effect.fail(outOfContract(conversationId, operation, `failure ${failure._tag}`));\n }\n if (response._tag !== resultTag) {\n return Effect.fail(outOfContract(conversationId, operation, `result ${response._tag}`));\n }\n return Effect.succeed(response as Result);\n };\n };\n\n const readPage = (\n conversationId: ConversationId,\n options?: {\n readonly afterSequence?: CanonicalSequence | undefined;\n readonly limit?: number | undefined;\n },\n ) =>\n Effect.gen(function* () {\n const request = ObservePageRequest.make({\n ...(options?.afterSequence === undefined\n ? {}\n : { afterSequence: options.afterSequence }),\n limit: options?.limit ?? 256,\n });\n const encoded = yield* encodeObservePageRequest(request).pipe(\n Effect.mapError((error) =>\n HostProtocolError.make({\n message: boundHostDiagnostic(`observePage request encode failed: ${error.message}`),\n }),\n ),\n );\n const response = yield* call(conversationId, \"observePage\", (stub) =>\n stub.observePage(encoded),\n );\n const page = yield* expect<ObservedPage, ClientObserveFailure & HostFailure>(\n conversationId,\n \"observePage\",\n \"ObservedPage\",\n OBSERVE_FAILURE_TAGS,\n )(response);\n return page.records;\n });\n\n return CloudflareConversationClient.of({\n submit: <InputSchema extends Schema.Top>(\n agent: DurableSubmitAgent<InputSchema>,\n input: InputSchema[\"Type\"],\n options: DurableSubmitOptions,\n ) =>\n Effect.gen(function* () {\n // Client-side half of `DurableAgentRuntime.submit`'s input boundary: encode\n // through the Agent's input schema and prove the canonical persistence bounds.\n const encodedInput = yield* Schema.encodeEffect(agent.definition.input)(input).pipe(\n Effect.mapError((cause) =>\n AgentInputError.make({ message: `Unable to encode Agent input: ${cause.message}` }),\n ),\n );\n const inputPayload = yield* Schema.decodeUnknownEffect(PersistedJson)(\n encodedInput,\n ).pipe(\n Effect.mapError(() =>\n AgentInputError.make({\n message: \"Agent input does not satisfy the canonical persistence bounds\",\n }),\n ),\n );\n const request = SubmitRequest.make({\n agentId: agent.definition.id,\n principal: options.principal,\n idempotencyKey: options.idempotencyKey,\n definitions: options.definitions,\n inputPayload,\n });\n const encoded = yield* encodeSubmitRequest(request).pipe(\n Effect.mapError((error) =>\n HostProtocolError.make({\n message: boundHostDiagnostic(`submit request encode failed: ${error.message}`),\n }),\n ),\n );\n const response = yield* call(options.conversationId, \"submit\", (stub) =>\n stub.submitEncoded(encoded),\n );\n const succeeded = yield* expect<SubmitSucceeded, ClientSubmitFailure & HostFailure>(\n options.conversationId,\n \"submit\",\n \"SubmitSucceeded\",\n SUBMIT_FAILURE_TAGS,\n )(response);\n return succeeded.receipt;\n }),\n\n awaitSettlement: (receipt) =>\n Effect.gen(function* () {\n const encoded = yield* encodeReceipt(receipt).pipe(\n Effect.mapError((error) =>\n HostProtocolError.make({\n message: boundHostDiagnostic(`receipt encode failed: ${error.message}`),\n }),\n ),\n );\n const response = yield* call(receipt.conversationId, \"awaitSettlement\", (stub) =>\n stub.awaitSettlementEncoded(encoded),\n );\n const settled = yield* expect<SettlementReached, ClientAwaitFailure & HostFailure>(\n receipt.conversationId,\n \"awaitSettlement\",\n \"SettlementReached\",\n AWAIT_FAILURE_TAGS,\n )(response);\n return settled.settlement;\n }),\n\n readPage,\n\n readAll: (conversationId) =>\n Effect.gen(function* () {\n const all: Array<CanonicalRecordEnvelope> = [];\n let after: CanonicalSequence | undefined;\n for (;;) {\n const page = yield* readPage(conversationId, { afterSequence: after, limit: 1_024 });\n all.push(...page);\n const last = page.at(-1);\n if (page.length < 1_024 || last === undefined) return all;\n after = last.sequence;\n }\n }),\n\n abort: (conversationId, command) =>\n Effect.gen(function* () {\n const encoded = yield* encodeAbortCommand(command).pipe(\n Effect.mapError((error) =>\n HostProtocolError.make({\n message: boundHostDiagnostic(`abort command encode failed: ${error.message}`),\n }),\n ),\n );\n const response = yield* call(conversationId, \"abort\", (stub) =>\n stub.abortEncoded(encoded),\n );\n const recorded = yield* expect<AbortRecorded, ClientAbortFailure & HostFailure>(\n conversationId,\n \"abort\",\n \"AbortRecorded\",\n ABORT_FAILURE_TAGS,\n )(response);\n return recorded.intent;\n }),\n\n resolveApproval: (conversationId, command) =>\n Effect.gen(function* () {\n const encoded = yield* encodeApprovalDecisionCommand(command).pipe(\n Effect.mapError((error) =>\n HostProtocolError.make({\n message: boundHostDiagnostic(`approval command encode failed: ${error.message}`),\n }),\n ),\n );\n const response = yield* call(conversationId, \"resolveApproval\", (stub) =>\n stub.resolveApprovalEncoded(encoded),\n );\n const recorded = yield* expect<ApprovalRecorded, ClientApprovalFailure & HostFailure>(\n conversationId,\n \"resolveApproval\",\n \"ApprovalRecorded\",\n APPROVAL_FAILURE_TAGS,\n )(response);\n return recorded.intent;\n }),\n\n resolveUnknown: (conversationId, command) =>\n Effect.gen(function* () {\n const encoded = yield* encodeUnknownResolutionCommand(command).pipe(\n Effect.mapError((error) =>\n HostProtocolError.make({\n message: boundHostDiagnostic(\n `resolution command encode failed: ${error.message}`,\n ),\n }),\n ),\n );\n const response = yield* call(conversationId, \"resolveUnknown\", (stub) =>\n stub.resolveUnknownEncoded(encoded),\n );\n const recorded = yield* expect<\n UnknownResolutionRecorded,\n ClientUnknownFailure & HostFailure\n >(\n conversationId,\n \"resolveUnknown\",\n \"UnknownResolutionRecorded\",\n UNKNOWN_FAILURE_TAGS,\n )(response);\n return recorded.intent;\n }),\n });\n }),\n );\n}\n","import type { AgentId } from \"@effect-agent/core\";\nimport { SubmissionId } from \"@effect-agent/core\";\nimport {\n AppendConflict,\n ConversationNotMaterialized,\n ConversationRead,\n ConversationStore,\n ConversationStoreError,\n DigestError,\n DurableAgentRuntime,\n DurableRuntimeFailpointError,\n FenceRejected,\n IntegrityReport,\n LedgerError,\n ObligationReport,\n ObligationThresholds,\n OperationAuthorizationRequest,\n OperationAuthorizer,\n OperationDenied,\n OwnershipLost,\n PersistedJson,\n RecoveryExplanation,\n RecoveryReport,\n RetryCommand,\n RetryRefused,\n RunJournalError,\n SettlementConflict,\n SubmissionLedger,\n SubmissionLookupByKey,\n type DurableSubmitAgent,\n} from \"@effect-agent/session\";\nimport { DurableObject } from \"cloudflare:workers\";\nimport { Effect, Layer, ManagedRuntime, Option, Schema, Stream } from \"effect\";\n\nimport { ConversationMaintenance, DurableAlarmError, DurableAlarmService } from \"./alarm.ts\";\nimport {\n ConversationObjectIdentity,\n DurableObjectContext,\n conversationNamespaceLayer,\n type CloudflareBindingError,\n} from \"./bindings.ts\";\nimport {\n AbortRecorded,\n ApprovalRecorded,\n HostFailed,\n HostProtocolError,\n ObservedPage,\n SettlementReached,\n SubmitSucceeded,\n UnknownResolutionRecorded,\n boundHostDiagnostic,\n decodeAbortCommand,\n decodeApprovalDecisionCommand,\n decodeObservePageRequest,\n decodeReceipt,\n decodeSubmitRequest,\n decodeUnknownResolutionCommand,\n encodeHostResponse,\n type HostFailure,\n type HostResponse,\n} from \"./client.ts\";\nimport { AdmissionLimitExceeded, CloudflareDurableRuntimeConfig } from \"./config.ts\";\nimport {\n CloudflareDurableRuntime,\n ConversationObjectPorts,\n type CloudflareDurableRuntimeInitializationError,\n type CloudflareDurableRuntimeOptions,\n type CloudflareDurableRuntimeServices,\n} from \"./layers.ts\";\n\n/**\n * `makeConversationObjectClass(options)` — the Conversation Durable Object (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 Conversation 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` + `processConversationResolved` pass, and the persisted alarm\n * (the single multiplexed slot, D-P6-2) finishes accepted work across evictions WITHOUT any\n * incoming request.\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 Conversation Object class. */\nexport interface ConversationObjectOptions extends CloudflareDurableRuntimeOptions {\n /**\n * Name of the Worker `env` binding carrying THIS class's `DurableObjectNamespace` — the\n * Object's route back to sibling Conversation 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}\n\ntype ConversationObjectError = CloudflareDurableRuntimeInitializationError | CloudflareBindingError;\n\ntype EndpointServices = CloudflareDurableRuntimeServices | DurableObjectContext;\n\n/** Port envelope tags whose owner-side execution durably mutates this Object's lane. */\nconst MUTATING_PORT_TAGS: ReadonlySet<string> = new Set([\n \"LedgerAdmit\",\n \"LedgerMarkReady\",\n \"LedgerRequestAbort\",\n \"LedgerRecordChildSettled\",\n \"StoreMaterialize\",\n \"StoreAppend\",\n]);\n\nconst isMutatingPortRequest = (encoded: unknown): boolean =>\n typeof encoded === \"object\" &&\n encoded !== null &&\n \"_tag\" in encoded &&\n typeof encoded._tag === \"string\" &&\n MUTATING_PORT_TAGS.has(encoded._tag);\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: unknown): 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(\"ConversationObject.gateAdmissionLimits\")(\n function* (request: {\n readonly principal: SubmissionLookupByKey[\"principal\"];\n readonly idempotencyKey: SubmissionLookupByKey[\"idempotencyKey\"];\n readonly inputPayload: PersistedJson;\n }) {\n const identity = yield* ConversationObjectIdentity;\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 conversationId: identity.conversationId,\n principal: request.principal,\n idempotencyKey: request.idempotencyKey,\n }),\n );\n if (Option.isSome(existing)) return;\n\n const inputBytes = utf8Bytes(request.inputPayload);\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 Conversation per Object (durability §5): the local scan IS this lane's queue.\n const nonterminal = yield* Stream.runCollect(ledger.scanNonterminal);\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 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/**\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* ConversationObjectIdentity;\n const maintenance = yield* ConversationMaintenance;\n const runtime = yield* DurableAgentRuntime;\n yield* gateAdmissionLimits(request);\n // Alarm invariant: the alarm commits BEFORE the admission it will finish (D-P6-2).\n yield* maintenance.preArm;\n const receipt = yield* runtime.submit(\n passthroughSubmitAgent(request.agentId),\n request.inputPayload,\n {\n conversationId: identity.conversationId,\n principal: request.principal,\n idempotencyKey: request.idempotencyKey,\n definitions: request.definitions,\n },\n );\n return SubmitSucceeded.make({ 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 return SettlementReached.make({ settlement });\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* ConversationObjectIdentity;\n const store = yield* ConversationStore;\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 yield* authorizer\n .authorize(\n OperationAuthorizationRequest.make({\n operation: \"observe\",\n conversationId: identity.conversationId,\n }),\n )\n .pipe(Effect.catchTag(\"OperationDenied\", deniedToProtocolFailure));\n const records = yield* Stream.runCollect(\n store.read(\n ConversationRead.make({\n conversationId: identity.conversationId,\n ...(request.afterSequence === undefined\n ? {}\n : { afterSequence: request.afterSequence }),\n limit: request.limit,\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* ConversationMaintenance;\n const runtime = yield* DurableAgentRuntime;\n yield* maintenance.preArm;\n const intent = yield* runtime.abort(command);\n return AbortRecorded.make({ intent });\n }),\n ),\n respond,\n Effect.flatMap(encodeResponse),\n );\n\n/**\n * The pre-P7 host protocol's failure union does not carry `OperationDenied` (the Worker client\n * predates the authorizer). This assembly always runs the default possession authorizer — no\n * `CloudflareDurableRuntimeOptions` authorizer lever exists yet — so a denial here is\n * unreachable today; if one ever surfaces it degrades to the protocol failure instead of an\n * out-of-contract throw. The four P7 admin entry points below carry `OperationDenied` typed.\n */\nconst deniedToProtocolFailure = (\n denied: OperationDenied,\n): Effect.Effect<never, HostProtocolError> =>\n Effect.fail(\n HostProtocolError.make({\n message: boundHostDiagnostic(\n `The ${denied.operation} operation was denied: ${denied.reason}`,\n ),\n }),\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* ConversationMaintenance;\n const runtime = yield* DurableAgentRuntime;\n yield* maintenance.preArm;\n const intent = yield* runtime\n .resolveApproval(command)\n .pipe(Effect.catchTag(\"OperationDenied\", deniedToProtocolFailure));\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* ConversationMaintenance;\n const runtime = yield* DurableAgentRuntime;\n yield* maintenance.preArm;\n const intent = yield* runtime\n .resolveUnknown(command)\n .pipe(Effect.catchTag(\"OperationDenied\", deniedToProtocolFailure));\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 OperationDenied,\n RetryRefused,\n LedgerError,\n RunJournalError,\n DigestError,\n OwnershipLost,\n SettlementConflict,\n ConversationStoreError,\n ConversationNotMaterialized,\n AppendConflict,\n FenceRejected,\n DurableRuntimeFailpointError,\n DurableAlarmError,\n HostProtocolError,\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]);\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* ConversationObjectIdentity;\n const runtime = yield* DurableAgentRuntime;\n const explanations =\n request.submissionId === undefined\n ? yield* runtime.explainConversation(identity.conversationId)\n : [yield* runtime.explain(request.submissionId)];\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* ConversationObjectIdentity;\n const runtime = yield* DurableAgentRuntime;\n const report = yield* runtime.verify(identity.conversationId);\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* ConversationMaintenance;\n const runtime = yield* DurableAgentRuntime;\n // Alarm invariant: retry may repair durable state, so the alarm that will finish the\n // lane commits BEFORE the mutation (D-P6-2), exactly like abort.\n yield* maintenance.preArm;\n const report = yield* runtime.retry(command);\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 return ObligationsScanned.make({ report });\n }),\n ),\n respondAdmin,\n Effect.flatMap(encodeAdminResponseTotal),\n );\n\n/**\n * Owner-side `portCall`: pre-arm before a mutating envelope (a routed admission committed by\n * THIS Object must already carry the alarm that will finish it), execute on the LOCAL facets\n * (never the routed decorators), then arm an immediate alarm so the mutated lane is\n * processed promptly. Protocol anomalies answer `PortFailed(PortProtocolError)`.\n */\nconst portCallEndpoint = (encoded: unknown): Effect.Effect<unknown, never, EndpointServices> =>\n Effect.gen(function* () {\n const ports = yield* ConversationObjectPorts;\n const maintenance = yield* ConversationMaintenance;\n const alarm = yield* DurableAlarmService;\n const mutating = isMutatingPortRequest(encoded);\n if (mutating) {\n const preArmed = yield* maintenance.preArm.pipe(Effect.exit);\n if (preArmed._tag === \"Failure\") {\n // Without the committed alarm the invariant cannot be promised; refuse the mutation.\n return encodedPortProtocolFailure(\n \"The owner Object could not arm its maintenance alarm before the mutation.\",\n );\n }\n }\n const response = yield* ports.handle(encoded);\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(\"ConversationObject.portCall: immediate re-arm failed\", error),\n ),\n );\n }\n return response;\n });\n\nconst wakeEndpoint: Effect.Effect<void, never, EndpointServices> = Effect.gen(function* () {\n const alarm = yield* DurableAlarmService;\n // Wake hints are droppable by contract: a failed alarm write is logged and swallowed; the\n // sender's own alarm/scan pairing (or this Object's next entry point) restores liveness.\n yield* alarm.scheduleNow.pipe(\n Effect.catch((error) => Effect.logWarning(\"ConversationObject.wake dropped\", error)),\n );\n});\n\nconst alarmEndpoint: Effect.Effect<void, unknown, EndpointServices> = Effect.gen(function* () {\n const maintenance = yield* ConversationMaintenance;\n // Typed pass failures propagate: the rejected promise makes workerd retry the alarm\n // (at-least-once delivery), and the pass's own pre-arm keeps the slot committed meanwhile.\n yield* maintenance.pass;\n});\n\nconst gateEndpoint: Effect.Effect<void, unknown, EndpointServices> = Effect.gen(function* () {\n // Forcing ConversationMaintenance 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* ConversationMaintenance;\n yield* maintenance.ensureAlarm;\n});\n\n/** The public endpoint surface of one Conversation Object instance. */\nexport interface ConversationObjectInstance extends DurableObject {\n submitEncoded(encoded: unknown): Promise<unknown>;\n awaitSettlementEncoded(encoded: unknown): Promise<unknown>;\n observePage(encoded: unknown): Promise<unknown>;\n abortEncoded(encoded: unknown): Promise<unknown>;\n resolveApprovalEncoded(encoded: unknown): Promise<unknown>;\n resolveUnknownEncoded(encoded: 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(): Promise<void>;\n}\n\n/** The constructor shape workerd instantiates for each Conversation Object. */\nexport interface ConversationObjectClass {\n new (ctx: DurableObjectState, env: Cloudflare.Env): ConversationObjectInstance;\n}\n\n/**\n * Build the application's Conversation Object class (export it from the\n * Worker entry). The explicit return type is what makes declaration emit\n * possible: the class body carries a private runtime field, and TS4094\n * rejects inferring an exported anonymous class type around it.\n */\nexport const makeConversationObjectClass = (\n options: ConversationObjectOptions,\n): ConversationObjectClass => {\n class ConversationObject extends DurableObject {\n readonly #runtime: ManagedRuntime.ManagedRuntime<EndpointServices, ConversationObjectError>;\n\n constructor(ctx: DurableObjectState, env: Cloudflare.Env) {\n super(ctx, env);\n this.#runtime = ManagedRuntime.make(\n CloudflareDurableRuntime.layer(options).pipe(\n Layer.provideMerge(\n Layer.mergeAll(\n DurableObjectContext.layer(ctx, env),\n conversationNamespaceLayer(env, options.namespaceBinding),\n ),\n ),\n ),\n );\n // The constructor gate: local-only checks; never the recovery pass (deadlock argument,\n // plan §1.4). A failure here fails every delivery with the typed construction error.\n ctx.blockConcurrencyWhile(() => this.#runtime.runPromise(gateEndpoint));\n }\n\n async submitEncoded(encoded: unknown): Promise<unknown> {\n return this.#runtime.runPromise(submitEndpoint(encoded));\n }\n\n async awaitSettlementEncoded(encoded: unknown): Promise<unknown> {\n return this.#runtime.runPromise(awaitSettlementEndpoint(encoded));\n }\n\n async observePage(encoded: unknown): Promise<unknown> {\n return this.#runtime.runPromise(observePageEndpoint(encoded));\n }\n\n async abortEncoded(encoded: unknown): Promise<unknown> {\n return this.#runtime.runPromise(abortEndpoint(encoded));\n }\n\n async resolveApprovalEncoded(encoded: unknown): Promise<unknown> {\n return this.#runtime.runPromise(resolveApprovalEndpoint(encoded));\n }\n\n async resolveUnknownEncoded(encoded: unknown): Promise<unknown> {\n return this.#runtime.runPromise(resolveUnknownEndpoint(encoded));\n }\n\n async explainEncoded(encoded: unknown): Promise<unknown> {\n return this.#runtime.runPromise(explainEndpoint(encoded));\n }\n\n async verifyEncoded(encoded: unknown): Promise<unknown> {\n return this.#runtime.runPromise(verifyEndpoint(encoded));\n }\n\n async retryEncoded(encoded: unknown): Promise<unknown> {\n return this.#runtime.runPromise(retryEndpoint(encoded));\n }\n\n async obligationsEncoded(encoded: unknown): Promise<unknown> {\n return this.#runtime.runPromise(obligationsEndpoint(encoded));\n }\n\n async portCall(encoded: unknown): Promise<unknown> {\n return this.#runtime.runPromise(portCallEndpoint(encoded));\n }\n\n async wake(): Promise<void> {\n await this.#runtime.runPromise(wakeEndpoint);\n }\n\n override async alarm(): Promise<void> {\n await this.#runtime.runPromise(alarmEndpoint);\n }\n }\n\n return ConversationObject;\n};\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@effect-agent/platform-cloudflare",
3
- "version": "0.0.1-beta.3",
3
+ "version": "0.0.1-beta.5",
4
4
  "description": "Class DC layer assembly for Effect Agent: SQLite-backed Conversation Durable Objects with alarm-driven recovery.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -28,20 +28,20 @@
28
28
  "test": "vitest run"
29
29
  },
30
30
  "dependencies": {
31
- "@effect-agent/core": "0.0.1-beta.3",
32
- "@effect-agent/session": "0.0.1-beta.3",
33
- "@effect-agent/storage-cloudflare": "0.0.1-beta.3",
34
- "@effect/platform-browser": "4.0.0-beta.102",
35
- "@effect/sql-sqlite-do": "4.0.0-beta.102",
36
- "effect": "4.0.0-beta.102"
31
+ "@effect-agent/core": "0.0.1-beta.5",
32
+ "@effect-agent/session": "0.0.1-beta.5",
33
+ "@effect-agent/storage-cloudflare": "0.0.1-beta.5",
34
+ "@effect/platform-browser": "4.0.0-beta.107",
35
+ "@effect/sql-sqlite-do": "4.0.0-beta.107",
36
+ "effect": "4.0.0-beta.107"
37
37
  },
38
38
  "devDependencies": {
39
39
  "@cloudflare/vitest-pool-workers": "0.21.3",
40
40
  "@cloudflare/workers-types": "5.20260813.1",
41
- "@effect-agent/capabilities": "0.0.1-beta.3",
42
- "@effect-agent/engine": "0.0.1-beta.3",
43
- "@effect-agent/testing": "0.0.1-beta.3",
44
- "@effect/vitest": "4.0.0-beta.102",
41
+ "@effect-agent/capabilities": "0.0.1-beta.4",
42
+ "@effect-agent/engine": "0.0.1-beta.4",
43
+ "@effect-agent/testing": "0.0.1-beta.4",
44
+ "@effect/vitest": "4.0.0-beta.107",
45
45
  "esbuild": "0.28.1",
46
46
  "miniflare": "4.20260730.0",
47
47
  "typescript": "7.0.2",
package/src/alarm.ts CHANGED
@@ -25,7 +25,7 @@ import { CloudflareDurableRuntimeConfig } from "./config.ts";
25
25
  */
26
26
 
27
27
  /** The Durable Object alarm API failed; surfaces on host entry points as a typed refusal. */
28
- export class DurableAlarmError extends Schema.TaggedErrorClass<DurableAlarmError>()(
28
+ export class DurableAlarmError extends Schema.TaggedError<DurableAlarmError>()(
29
29
  "DurableAlarmError",
30
30
  {
31
31
  operation: Schema.String,
package/src/bindings.ts CHANGED
@@ -10,7 +10,7 @@ import { Context, Effect, Layer, Schema } from "effect";
10
10
  */
11
11
 
12
12
  /** A Cloudflare platform binding was missing or carried the wrong shape (DEPLOY-003/010). */
13
- export class CloudflareBindingError extends Schema.TaggedErrorClass<CloudflareBindingError>()(
13
+ export class CloudflareBindingError extends Schema.TaggedError<CloudflareBindingError>()(
14
14
  "CloudflareBindingError",
15
15
  {
16
16
  binding: Schema.String,
package/src/client.ts CHANGED
@@ -59,7 +59,7 @@ export const boundHostDiagnostic = (value: string): string =>
59
59
  * The envelope itself could not be honored: the Object could not decode the request, or a
60
60
  * response could not be encoded/decoded. Never carries operation semantics.
61
61
  */
62
- export class HostProtocolError extends Schema.TaggedErrorClass<HostProtocolError>()(
62
+ export class HostProtocolError extends Schema.TaggedError<HostProtocolError>()(
63
63
  "HostProtocolError",
64
64
  {
65
65
  message: BoundedDiagnostic,
@@ -67,7 +67,7 @@ export class HostProtocolError extends Schema.TaggedErrorClass<HostProtocolError
67
67
  ) {}
68
68
 
69
69
  /** The Worker-side stub call itself failed (RPC rejection, overload, eviction mid-call). */
70
- export class ConversationClientError extends Schema.TaggedErrorClass<ConversationClientError>()(
70
+ export class ConversationClientError extends Schema.TaggedError<ConversationClientError>()(
71
71
  "ConversationClientError",
72
72
  {
73
73
  conversationId: Schema.String,
package/src/config.ts CHANGED
@@ -12,7 +12,7 @@ const PositiveMillis = Schema.Int.check(Schema.isGreaterThan(0));
12
12
  const NonNegativeMillis = Schema.Int.check(Schema.isGreaterThanOrEqualTo(0));
13
13
 
14
14
  /** The supplied Cloudflare durable runtime configuration failed validation (DEPLOY-003). */
15
- export class CloudflarePlatformConfigError extends Schema.TaggedErrorClass<CloudflarePlatformConfigError>()(
15
+ export class CloudflarePlatformConfigError extends Schema.TaggedError<CloudflarePlatformConfigError>()(
16
16
  "CloudflarePlatformConfigError",
17
17
  {
18
18
  message: Schema.String,
@@ -28,7 +28,7 @@ export class CloudflarePlatformConfigError extends Schema.TaggedErrorClass<Cloud
28
28
  * Conversation Object's submit entry point before `DurableAgentRuntime.submit` runs, and
29
29
  * nothing was admitted or written.
30
30
  */
31
- export class AdmissionLimitExceeded extends Schema.TaggedErrorClass<AdmissionLimitExceeded>()(
31
+ export class AdmissionLimitExceeded extends Schema.TaggedError<AdmissionLimitExceeded>()(
32
32
  "AdmissionLimitExceeded",
33
33
  {
34
34
  limit: Schema.Literals(["queue-depth", "input-bytes", "database-bytes"]),
package/src/layers.ts CHANGED
@@ -97,16 +97,35 @@ export interface CloudflareDurableRuntimeOptions {
97
97
  readonly toolReconciler?: Layer.Layer<ToolReconciler> | undefined;
98
98
  /**
99
99
  * Registered worker Bindings resolved at durable claim time (S2, spec/subagents.md §11):
100
- * build each with `DurableWorkerBinding.make(binding, digests)`. An Effect form is accepted
101
- * because the capture is effectful; it runs once per incarnation during Layer construction.
102
- * Defaults to the empty registration (every resolved claim fails closed).
100
+ * build each with `DurableWorkerBinding.make(binding, digests)`. An Effect or callback form is
101
+ * accepted because capture can be effectful. The callback receives the live Object context and
102
+ * derived identities and is evaluated once per incarnation during Layer construction. Defaults
103
+ * to the empty registration (every resolved claim fails closed).
103
104
  */
104
- readonly bindings?:
105
- | ReadonlyArray<ResolvedBinding>
106
- | Effect.Effect<ReadonlyArray<ResolvedBinding>>
107
- | undefined;
105
+ readonly bindings?: CloudflareBindingSource | undefined;
106
+ }
107
+
108
+ /** Per-incarnation host values available while registered worker Bindings are captured. */
109
+ export interface CloudflareBindingSourceContext {
110
+ readonly ctx: DurableObjectState;
111
+ readonly env: unknown;
112
+ readonly conversationId: ConversationId;
113
+ readonly producerId: ProducerId;
108
114
  }
109
115
 
116
+ /**
117
+ * Registered worker Bindings, or a closed Effect/callback that captures them once for each
118
+ * Durable Object incarnation. Callback Effects cannot require services or fail typed.
119
+ */
120
+ export type CloudflareBindingSource =
121
+ | ReadonlyArray<ResolvedBinding>
122
+ | Effect.Effect<ReadonlyArray<ResolvedBinding>, never, never>
123
+ | ((
124
+ context: CloudflareBindingSourceContext,
125
+ ) =>
126
+ | ReadonlyArray<ResolvedBinding>
127
+ | Effect.Effect<ReadonlyArray<ResolvedBinding>, never, never>);
128
+
110
129
  /** Every construction failure of the assembled Cloudflare durable runtime stack. */
111
130
  export type CloudflareDurableRuntimeInitializationError =
112
131
  | CloudflarePlatformConfigError
@@ -208,13 +227,19 @@ const conversationIdFromState = (
208
227
  );
209
228
 
210
229
  const resolveBindings = (
211
- bindings: CloudflareDurableRuntimeOptions["bindings"],
230
+ source: CloudflareDurableRuntimeOptions["bindings"],
231
+ context: CloudflareBindingSourceContext,
212
232
  ): Effect.Effect<ReadonlyArray<ResolvedBinding>> =>
213
- bindings === undefined
233
+ source === undefined
214
234
  ? Effect.succeed([])
215
- : Effect.isEffect(bindings)
216
- ? bindings
217
- : Effect.succeed(bindings);
235
+ : Effect.isEffect(source)
236
+ ? source
237
+ : typeof source === "function"
238
+ ? Effect.suspend(() => {
239
+ const bindings = source(context);
240
+ return Effect.isEffect(bindings) ? bindings : Effect.succeed(bindings);
241
+ })
242
+ : Effect.succeed(source);
218
243
 
219
244
  /**
220
245
  * The DC Layer assembly (deployment §12: a Layer-assembly library, not an app entrypoint;
@@ -243,7 +268,7 @@ export class CloudflareDurableRuntime {
243
268
  > {
244
269
  return Layer.unwrap(
245
270
  Effect.gen(function* () {
246
- const { ctx } = yield* DurableObjectContext;
271
+ const { ctx, env } = yield* DurableObjectContext;
247
272
  const config = yield* configFromOptions(options);
248
273
  const conversationId = yield* conversationIdFromState(ctx);
249
274
  const producerId = yield* decodeProducerId(
@@ -317,7 +342,10 @@ export class CloudflareDurableRuntime {
317
342
  : Layer.succeed(DurableRuntimeFailpoint)({ hit: options.runtimeFailpoint(ctx) });
318
343
  const reconcilerLayer = options.toolReconciler ?? ToolReconciler.uncertain;
319
344
  const bindingResolverLayer = Layer.effect(AgentBindingResolver)(
320
- Effect.map(resolveBindings(options.bindings), AgentBindingResolver.fromBindings),
345
+ Effect.map(
346
+ resolveBindings(options.bindings, { ctx, env, conversationId, producerId }),
347
+ (bindings) => AgentBindingResolver.fromBindings(bindings),
348
+ ),
321
349
  );
322
350
 
323
351
  const base = Layer.mergeAll(
@@ -14,7 +14,7 @@ import { ConversationObjectIdentity, ConversationObjectNamespace } from "./bindi
14
14
  const WAKE_BUFFER_CAPACITY = 1_024;
15
15
 
16
16
  /** A remote wake stub call failed; always swallowed and logged (hints are droppable). */
17
- class RemoteWakeDropped extends Schema.TaggedErrorClass<RemoteWakeDropped>()("RemoteWakeDropped", {
17
+ class RemoteWakeDropped extends Schema.TaggedError<RemoteWakeDropped>()("RemoteWakeDropped", {
18
18
  conversationId: Schema.String,
19
19
  message: Schema.String,
20
20
  cause: Schema.optionalKey(Schema.Defect()),