@effect-agent/platform-cloudflare 0.1.0-beta.38 → 0.1.0-beta.39

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.
@@ -1,15 +1,13 @@
1
- import { Clock, Context, Crypto, DateTime, Duration, Effect, Layer, Option, Predicate, Random, Ref, Schema, Semaphore, Stream } from "effect";
2
- import { AbortCommand, AbortIntent, AdmissionConflict, AgentBindingResolver, AppendConflict, ApprovalConflict, ApprovalDecisionCommand, ApprovalDecisionIntent, CanonicalRecordEnvelope, CanonicalSequence, ConversationNotMaterialized, ConversationStoreError, DEFAULT_OWNERSHIP_LEASE_DURATION, DefinitionDigests, DeploymentId, DigestError, DurableAgentRuntime, DurableRuntimeFailpointError, FenceRejected, IdempotencyKey, JoinedToHost, LedgerError, OperationDenied, PersistedJson, Principal, Receipt, ScheduleAuthorizationError, ScheduleCapacityError, ScheduleConflict, ScheduleDestination, ScheduleDriver, ScheduleFailpointError, ScheduleId, ScheduleNotFound, ScheduleOwner, ScheduleScope, ScheduleSnapshot, ScheduleSnapshotPage, ScheduleStorageError, ScheduleTimingRequest, ScheduleValidationError, ScheduleWakeNoop, ScheduledInputAdmission, ScheduledInputRetryable, Scheduling, Settlement, SettlementConflict, SubmissionLedger, UnknownResolutionCommand, UnknownResolutionConflict, UnknownResolutionIntent, defaultSchedulingLimits, scheduleOwnerKey } from "@effect-agent/session";
3
- import { DEFAULT_MAX_STORED_VALUE_BYTES, DoScheduleAlarmControl, DoScheduleTransaction, scheduleStoreLayer } from "@effect-agent/storage-cloudflare";
1
+ import { Clock, Context, Crypto, Duration, Effect, Layer, Option, Predicate, Random, Ref, Schema, Semaphore, Stream } from "effect";
2
+ import { DEFAULT_MAX_STORED_VALUE_BYTES } from "@effect-agent/storage-cloudflare";
3
+ import { AbortCommand, AbortIntent, AdmissionConflict, AppendConflict, ApprovalConflict, ApprovalDecisionCommand, ApprovalDecisionIntent, CanonicalRecordEnvelope, CanonicalSequence, DEFAULT_OWNERSHIP_LEASE_DURATION, DefinitionDigests, DeploymentId, DigestError, DurableAgentRuntime, DurableRuntimeFailpointError, FenceRejected, IdempotencyKey, JoinedToHost, LedgerError, OperationDenied, PersistedJson, PreparedInputAdmission, Principal, Receipt, ScheduleStorageError, ScheduledInputAdmission, ScheduledInputRetryable, Settlement, SettlementConflict, SubmissionLedger, ThreadNotMaterialized, ThreadStoreError, UnknownResolutionCommand, UnknownResolutionConflict, UnknownResolutionIntent } from "@effect-agent/thread";
4
4
  import { AgentId, AgentInputError } from "@effect-agent/core";
5
- import { BrowserCrypto } from "@effect/platform-browser";
6
- import { SqliteClient } from "@effect/sql-sqlite-do";
7
- import { DurableObject, DurableObjectAlarm, DurableObjectState, RpcTracing } from "effect-cf";
5
+ import { RpcTracing } from "effect-cf";
8
6
  //#region src/bindings.ts
9
7
  /**
10
8
  * Cloudflare platform bindings as Effect services (DEPLOY-010: "Cloudflare platform bindings
11
9
  * are supplied as Effect services/Layers"). Application code never reads `env` or touches a
12
- * `DurableObjectState` directly — the Conversation Object class constructs these Layers once
10
+ * `DurableObjectState` directly — the Thread Object class constructs these Layers once
13
11
  * per incarnation and everything downstream consumes the services.
14
12
  */
15
13
  /** A Cloudflare platform binding was missing or carried the wrong shape (DEPLOY-003/010). */
@@ -18,13 +16,13 @@ var CloudflareBindingError = class extends Schema.TaggedError()("CloudflareBindi
18
16
  message: Schema.String
19
17
  }) {};
20
18
  /**
21
- * The `DurableObjectNamespace` binding that addresses Conversation Objects. The Object
22
- * identity rule is `namespace.idFromName(conversationId)` (plan §1.2): Conversation IDs are
19
+ * The `DurableObjectNamespace` binding that addresses Thread Objects. The Object
20
+ * identity rule is `namespace.idFromName(threadId)` (plan §1.2): Thread IDs are
23
21
  * globally unique, so the mapping is total and deterministic and no directory service exists.
24
22
  */
25
- var ConversationObjectNamespace = class ConversationObjectNamespace extends Context.Service()("@effect-agent/platform-cloudflare/ConversationObjectNamespace") {
23
+ var ThreadObjectNamespace = class ThreadObjectNamespace extends Context.Service()("@effect-agent/platform-cloudflare/ThreadObjectNamespace") {
26
24
  static layer(namespace) {
27
- return Layer.succeed(ConversationObjectNamespace)({ namespace });
25
+ return Layer.succeed(ThreadObjectNamespace)({ namespace });
28
26
  }
29
27
  };
30
28
  /**
@@ -33,7 +31,7 @@ var ConversationObjectNamespace = class ConversationObjectNamespace extends Cont
33
31
  * narrowest-boundary check (structural probe for the namespace surface the transport uses);
34
32
  * a missing or misshaped binding fails typed before any Layer is built.
35
33
  */
36
- const conversationNamespaceFromEnv = Effect.fn("conversationNamespaceFromEnv")(function* (env, binding) {
34
+ const threadNamespaceFromEnv = Effect.fn("threadNamespaceFromEnv")(function* (env, binding) {
37
35
  if (!Predicate.isObjectKeyword(env)) return yield* CloudflareBindingError.make({
38
36
  binding,
39
37
  message: "The Worker environment is not an object; no bindings are available."
@@ -54,14 +52,14 @@ const conversationNamespaceFromEnv = Effect.fn("conversationNamespaceFromEnv")(f
54
52
  if (candidate !== void 0) return candidate;
55
53
  return yield* CloudflareBindingError.make({
56
54
  binding,
57
- message: `env.${binding} is not a DurableObjectNamespace binding; declare the Conversation Object class under this binding in the Worker configuration.`
55
+ message: `env.${binding} is not a DurableObjectNamespace binding; declare the Thread Object class under this binding in the Worker configuration.`
58
56
  });
59
57
  });
60
58
  /**
61
59
  * Build the namespace from Worker `env` (fails typed). Enable `rpcTracing` only when the
62
60
  * receiver also opts into the effect-cf native RPC trace-context contract.
63
61
  */
64
- const conversationNamespaceLayer = (env, binding, options = {}) => Layer.effect(ConversationObjectNamespace)(Effect.map(conversationNamespaceFromEnv(env, binding), (namespace) => ({
62
+ const threadNamespaceLayer = (env, binding, options = {}) => Layer.effect(ThreadObjectNamespace)(Effect.map(threadNamespaceFromEnv(env, binding), (namespace) => ({
65
63
  namespace,
66
64
  ...options.rpcTracing === true ? { rpcTracing: binding } : {}
67
65
  })));
@@ -79,11 +77,11 @@ var DurableObjectContext = class DurableObjectContext extends Context.Service()(
79
77
  }
80
78
  };
81
79
  /**
82
- * The Conversation identity this Object serializes and the producer identity its Attempts
83
- * write with (`{producerPrefix}:{conversationId}`, plan §1.4). Derived once per incarnation
84
- * from `ctx.id.name` — the Object identity rule guarantees the name IS the Conversation ID.
80
+ * The Thread identity this Object serializes and the producer identity its Attempts
81
+ * write with (`{producerPrefix}:{threadId}`, plan §1.4). Derived once per incarnation
82
+ * from `ctx.id.name` — the Object identity rule guarantees the name IS the Thread ID.
85
83
  */
86
- var ConversationObjectIdentity = class extends Context.Service()("@effect-agent/platform-cloudflare/ConversationObjectIdentity") {};
84
+ var ThreadObjectIdentity = class extends Context.Service()("@effect-agent/platform-cloudflare/ThreadObjectIdentity") {};
87
85
  //#endregion
88
86
  //#region src/config.ts
89
87
  /**
@@ -103,7 +101,7 @@ var CloudflarePlatformConfigError = class extends Schema.TaggedError()("Cloudfla
103
101
  * (deployment spec §8, DEPLOY-007: "Admission has explicit bounded quota and overload
104
102
  * behavior... a typed rejection"). This is the DC analogue of `NodeDurableHost`'s
105
103
  * `AdmissionClosed` host gate: the port surface stays untouched, the refusal happens in the
106
- * Conversation Object's submit entry point before `DurableAgentRuntime.submit` runs, and
104
+ * Thread Object's submit entry point before `DurableAgentRuntime.submit` runs, and
107
105
  * nothing was admitted or written.
108
106
  */
109
107
  var AdmissionLimitExceeded = class extends Schema.TaggedError()("AdmissionLimitExceeded", {
@@ -124,11 +122,11 @@ const CLOUDFLARE_DATABASE_CAP_BYTES = 1e10;
124
122
  /** Default database-size admission ceiling: a 1 GB safety margin under the platform cap. */
125
123
  const DEFAULT_MAX_DATABASE_BYTES = 9e9;
126
124
  /**
127
- * Explicit bounded admission quotas checked by the Conversation Object BEFORE admission
125
+ * Explicit bounded admission quotas checked by the Thread Object BEFORE admission
128
126
  * (exit gate "resource limits are checked before admission").
129
127
  */
130
128
  var CloudflareAdmissionLimitsValue = class extends Schema.Class("@effect-agent/platform-cloudflare/CloudflareAdmissionLimitsValue")({
131
- /** Maximum nonterminal Submissions per Conversation lane before new admissions refuse. */
129
+ /** Maximum nonterminal Submissions per Thread lane before new admissions refuse. */
132
130
  maxQueueDepthPerLane: Schema.Int.check(Schema.isGreaterThan(0), Schema.isLessThanOrEqualTo(1e5)),
133
131
  /** Maximum encoded input bytes; never above the storage per-value bound. */
134
132
  maxInputBytes: Schema.Int.check(Schema.isGreaterThan(0), Schema.isLessThanOrEqualTo(2e6)),
@@ -137,13 +135,13 @@ var CloudflareAdmissionLimitsValue = class extends Schema.Class("@effect-agent/p
137
135
  }) {};
138
136
  /**
139
137
  * Validated Cloudflare durable runtime configuration. The producer identity of one
140
- * Conversation Object is `{producerPrefix}:{conversationId}` — stable across incarnations of
138
+ * Thread Object is `{producerPrefix}:{threadId}` — stable across incarnations of
141
139
  * the same deployment, distinct across deployments — and producer-epoch fencing (not the
142
140
  * producer name) remains the correctness authority (DUR-006).
143
141
  */
144
142
  var CloudflareDurableRuntimeConfigValue = class extends Schema.Class("@effect-agent/platform-cloudflare/CloudflareDurableRuntimeConfigValue")({
145
143
  deploymentId: DeploymentId,
146
- /** Head of the minted producer identity `{producerPrefix}:{conversationId}`. */
144
+ /** Head of the minted producer identity `{producerPrefix}:{threadId}`. */
147
145
  producerPrefix: Schema.NonEmptyString.check(Schema.isMaxLength(256)),
148
146
  /** Submission ownership lease duration (D5); fences work across Object incarnations. */
149
147
  ownershipLeaseDuration: PositiveMillis,
@@ -172,7 +170,7 @@ var CloudflareDurableRuntimeConfigValue = class extends Schema.Class("@effect-ag
172
170
  }) {};
173
171
  /** Explicit configuration authority for the assembled Cloudflare durable runtime. */
174
172
  var CloudflareDurableRuntimeConfig = class extends Context.Service()("@effect-agent/platform-cloudflare/CloudflareDurableRuntimeConfig") {};
175
- /** Documented production defaults applied by `CloudflareDurableRuntime.layer`. */
173
+ /** Documented production defaults applied by `ThreadObject.layer`. */
176
174
  const CLOUDFLARE_RUNTIME_DEFAULTS = {
177
175
  ownershipLeaseDuration: Duration.toMillis(DEFAULT_OWNERSHIP_LEASE_DURATION),
178
176
  alarmBackoffBase: 100,
@@ -300,21 +298,21 @@ var MaintenancePassReport = class extends Schema.Class("@effect-agent/platform-c
300
298
  alarm: Schema.Literals(["rearmed", "cleared"])
301
299
  }) {};
302
300
  /** Test-only fault authority; production uses the inert layer. */
303
- var ConversationMaintenanceFailpoint = class extends Context.Service()("@effect-agent/platform-cloudflare/ConversationMaintenanceFailpoint") {
301
+ var ThreadMaintenanceFailpoint = class extends Context.Service()("@effect-agent/platform-cloudflare/ThreadMaintenanceFailpoint") {
304
302
  static layer = Layer.succeed(this)({ hit: () => Effect.void });
305
303
  };
306
304
  const MaintenanceGeneration = Schema.BigIntFromString.check(Schema.isGreaterThanOrEqualToBigInt(0n));
307
305
  /** Versioned, platform-private maintenance state stored through Durable Object KV. */
308
- var ConversationMaintenanceState = class extends Schema.Class("@effect-agent/platform-cloudflare/ConversationMaintenanceState")({
306
+ var ThreadMaintenanceState = class extends Schema.Class("@effect-agent/platform-cloudflare/ThreadMaintenanceState")({
309
307
  schemaVersion: Schema.Literal(1),
310
308
  dirty: MaintenanceGeneration,
311
309
  processed: MaintenanceGeneration,
312
310
  nonterminal: Schema.Int.check(Schema.isGreaterThanOrEqualTo(0))
313
311
  }) {};
314
- const MAINTENANCE_STATE_KEY = "effect-agent:conversation-maintenance:v1";
315
- const decodeMaintenanceState = Schema.decodeUnknownSync(ConversationMaintenanceState);
316
- const encodeMaintenanceState = Schema.encodeSync(ConversationMaintenanceState);
317
- const initialMaintenanceState = () => ConversationMaintenanceState.make({
312
+ const MAINTENANCE_STATE_KEY = "effect-agent:thread-maintenance:v1";
313
+ const decodeMaintenanceState = Schema.decodeUnknownSync(ThreadMaintenanceState);
314
+ const encodeMaintenanceState = Schema.encodeSync(ThreadMaintenanceState);
315
+ const initialMaintenanceState = () => ThreadMaintenanceState.make({
318
316
  schemaVersion: 1,
319
317
  dirty: 1n,
320
318
  processed: 0n,
@@ -363,16 +361,15 @@ const stableExternalWait = (snapshot, reports) => {
363
361
  * 4. Stable external waits acknowledge and clear. Autonomous retry, indeterminate, and lease
364
362
  * recovery states leave their generation dirty and retain bounded backoff rearming.
365
363
  */
366
- var ConversationMaintenance = class ConversationMaintenance extends Context.Service()("@effect-agent/platform-cloudflare/ConversationMaintenance") {
367
- static layer = Layer.effect(ConversationMaintenance)(Effect.gen(function* () {
364
+ var ThreadMaintenance = class ThreadMaintenance extends Context.Service()("@effect-agent/platform-cloudflare/ThreadMaintenance") {
365
+ static layer = (bindings) => Layer.effect(ThreadMaintenance)(Effect.gen(function* () {
368
366
  const runtime = yield* DurableAgentRuntime;
369
- const resolver = yield* AgentBindingResolver;
370
367
  const ledger = yield* SubmissionLedger;
371
368
  const alarm = yield* DurableAlarmService;
372
369
  const config = yield* CloudflareDurableRuntimeConfig;
373
- const identity = yield* ConversationObjectIdentity;
370
+ const identity = yield* ThreadObjectIdentity;
374
371
  const { ctx } = yield* DurableObjectContext;
375
- const failpoint = yield* ConversationMaintenanceFailpoint;
372
+ const failpoint = yield* ThreadMaintenanceFailpoint;
376
373
  /**
377
374
  * Consecutive no-progress passes — an in-memory CACHE, not state: a fresh incarnation
378
375
  * restarts at zero and merely re-arms sooner than a long-lived one would have.
@@ -392,12 +389,12 @@ var ConversationMaintenance = class ConversationMaintenance extends Context.Serv
392
389
  try: transaction,
393
390
  catch: alarmFailure(operation)
394
391
  });
395
- const beginMutation = Effect.fn("ConversationMaintenance.beginMutation")(function* () {
392
+ const beginMutation = Effect.fn("ThreadMaintenance.beginMutation")(function* () {
396
393
  yield* failpoint.hit("maintenance:dirty:before");
397
394
  const now = yield* Clock.currentTimeMillis;
398
395
  yield* runTransaction("advance maintenance generation", () => ctx.storage.transaction(async (transaction) => {
399
396
  const { state } = await readMaintenanceState(transaction);
400
- const next = ConversationMaintenanceState.make({
397
+ const next = ThreadMaintenanceState.make({
401
398
  ...state,
402
399
  dirty: state.dirty + 1n
403
400
  });
@@ -409,7 +406,7 @@ var ConversationMaintenance = class ConversationMaintenance extends Context.Serv
409
406
  });
410
407
  const endMutation = generationGate.withPermit(Ref.update(activeMutations, (active) => Math.max(0, active - 1)));
411
408
  const withMutation = (body) => Effect.acquireUseRelease(generationGate.withPermit(beginMutation()), () => failpoint.hit("maintenance:mutation:armed").pipe(Effect.andThen(body), Effect.tap(() => failpoint.hit("maintenance:mutation:finished"))), () => endMutation);
412
- const ensureAlarm = Effect.fn("ConversationMaintenance.ensureAlarm")(function* () {
409
+ const ensureAlarm = Effect.fn("ThreadMaintenance.ensureAlarm")(function* () {
413
410
  yield* failpoint.hit("maintenance:ensure:before");
414
411
  const now = yield* Clock.currentTimeMillis;
415
412
  yield* runTransaction("ensure maintenance alarm", () => ctx.storage.transaction(async (transaction) => {
@@ -419,7 +416,7 @@ var ConversationMaintenance = class ConversationMaintenance extends Context.Serv
419
416
  }));
420
417
  yield* failpoint.hit("maintenance:ensure:after");
421
418
  });
422
- const beginPass = Effect.fn("ConversationMaintenance.beginPass")(function* () {
419
+ const beginPass = Effect.fn("ThreadMaintenance.beginPass")(function* () {
423
420
  yield* failpoint.hit("maintenance:begin:before");
424
421
  const now = yield* Clock.currentTimeMillis;
425
422
  const result = yield* runTransaction("begin maintenance pass", () => ctx.storage.transaction(async (transaction) => {
@@ -441,7 +438,7 @@ var ConversationMaintenance = class ConversationMaintenance extends Context.Serv
441
438
  yield* failpoint.hit("maintenance:begin:after");
442
439
  return result;
443
440
  });
444
- const rearmDelay = Effect.fn("ConversationMaintenance.rearmDelay")(function* (progressed) {
441
+ const rearmDelay = Effect.fn("ThreadMaintenance.rearmDelay")(function* (progressed) {
445
442
  const priorStalls = yield* Ref.getAndUpdate(stalls, (count) => progressed ? 0 : count + 1);
446
443
  if (progressed) return config.alarmBackoffBase;
447
444
  const exponent = Math.min(priorStalls, 30);
@@ -450,7 +447,7 @@ var ConversationMaintenance = class ConversationMaintenance extends Context.Serv
450
447
  const jittered = Math.ceil(backoff / 2 + backoff / 2 * jitter);
451
448
  return Math.min(jittered, config.wakeScanInterval);
452
449
  });
453
- const pass = Effect.fn("ConversationMaintenance.pass")(function* () {
450
+ const pass = Effect.fn("ThreadMaintenance.pass")(function* () {
454
451
  const annotate = (report) => Effect.annotateCurrentSpan({
455
452
  phase: report.phase,
456
453
  recovered: report.recovered,
@@ -473,7 +470,7 @@ var ConversationMaintenance = class ConversationMaintenance extends Context.Serv
473
470
  alarm: "cleared"
474
471
  }));
475
472
  const recovered = yield* runtime.runRecovery;
476
- const settlements = yield* runtime.processConversationResolved(identity.conversationId).pipe(Effect.provideService(AgentBindingResolver, resolver));
473
+ const settlements = yield* runtime.processThreadResolved(identity.threadId, bindings);
477
474
  const remaining = yield* Stream.runCollect(ledger.scanNonterminal);
478
475
  const reports = new Map(recovered.map((report) => [report.submissionId, report]));
479
476
  const head = remaining[0];
@@ -491,7 +488,7 @@ var ConversationMaintenance = class ConversationMaintenance extends Context.Serv
491
488
  return yield* runTransaction("finish maintenance pass", () => ctx.storage.transaction(async (transaction) => {
492
489
  const { state } = await readMaintenanceState(transaction);
493
490
  const processed = autonomous || started.activeAtStart > 0 || active > 0 ? state.processed : state.processed > started.generation ? state.processed : started.generation;
494
- const next = ConversationMaintenanceState.make({
491
+ const next = ThreadMaintenanceState.make({
495
492
  ...state,
496
493
  processed,
497
494
  nonterminal: remaining.length
@@ -519,7 +516,7 @@ var ConversationMaintenance = class ConversationMaintenance extends Context.Serv
519
516
  alarm: alarmDisposition
520
517
  }));
521
518
  });
522
- return ConversationMaintenance.of({
519
+ return ThreadMaintenance.of({
523
520
  pass: alarm.withWakesDeferred(maintenancePassGate.withPermit(pass())),
524
521
  ensureAlarm: ensureAlarm(),
525
522
  withMutation
@@ -529,7 +526,7 @@ var ConversationMaintenance = class ConversationMaintenance extends Context.Serv
529
526
  //#endregion
530
527
  //#region src/client.ts
531
528
  /**
532
- * The Worker↔Conversation-Object host protocol (plan §1.4): Schema envelopes for the host
529
+ * The Worker↔Thread-Object host protocol (plan §1.4): Schema envelopes for the host
533
530
  * entry points (`submitEncoded`, `awaitSettlementEncoded`, `observePage`, `abortEncoded`,
534
531
  * `resolveApprovalEncoded`, `resolveUnknownEncoded`) plus the Worker-side client that speaks
535
532
  * it. Mirrors the WP2 port protocol: requests and responses are closed Schema unions, typed
@@ -547,8 +544,8 @@ const boundHostDiagnostic = (value) => value.length > MAX_HOST_DIAGNOSTIC_LENGTH
547
544
  */
548
545
  var HostProtocolError = class extends Schema.TaggedError()("HostProtocolError", { message: BoundedDiagnostic }) {};
549
546
  /** The Worker-side stub call itself failed (RPC rejection, overload, eviction mid-call). */
550
- var ConversationClientError = class extends Schema.TaggedError()("ConversationClientError", {
551
- conversationId: Schema.String,
547
+ var ThreadClientError = class extends Schema.TaggedError()("ThreadClientError", {
548
+ threadId: Schema.String,
552
549
  message: Schema.String,
553
550
  cause: Schema.optionalKey(Schema.Defect()),
554
551
  /** Cloudflare's own classification for a failure safe to retry with a fresh stub. */
@@ -560,7 +557,7 @@ var ConversationClientError = class extends Schema.TaggedError()("ConversationCl
560
557
  * One durable submission, input ALREADY encoded by the caller through the Agent Binding's
561
558
  * input schema (the Worker bundles the same Agent definitions as the Object, so schema
562
559
  * validation happens client-side; the resolved Binding re-validates at claim time). The
563
- * Conversation identity is deliberately absent — the addressed Object IS the lane.
560
+ * Thread identity is deliberately absent — the addressed Object IS the lane.
564
561
  */
565
562
  var SubmitRequest = class extends Schema.Class("@effect-agent/platform-cloudflare/SubmitRequest")({
566
563
  agentId: AgentId,
@@ -596,8 +593,8 @@ const HostFailure = Schema.Union([
596
593
  UnknownResolutionConflict,
597
594
  JoinedToHost,
598
595
  LedgerError,
599
- ConversationStoreError,
600
- ConversationNotMaterialized,
596
+ ThreadStoreError,
597
+ ThreadNotMaterialized,
601
598
  AppendConflict,
602
599
  FenceRejected,
603
600
  DurableRuntimeFailpointError,
@@ -647,14 +644,14 @@ const decodeUnknownResolutionCommand = Schema.decodeUnknownEffect(UnknownResolut
647
644
  const encodeUnknownResolutionCommand = Schema.encodeEffect(UnknownResolutionCommand);
648
645
  const encodeHostResponse = Schema.encodeEffect(HostResponse);
649
646
  const decodeHostResponse = Schema.decodeUnknownEffect(HostResponse);
650
- /** Failure surface of `CloudflareConversationClient.submit`. */
647
+ /** Failure surface of `CloudflareThreadClient.submit`. */
651
648
  const ClientSubmitHostFailure = Schema.Union([
652
649
  AgentInputError,
653
650
  DigestError,
654
651
  AdmissionConflict,
655
652
  LedgerError,
656
- ConversationStoreError,
657
- ConversationNotMaterialized,
653
+ ThreadStoreError,
654
+ ThreadNotMaterialized,
658
655
  AppendConflict,
659
656
  FenceRejected,
660
657
  DurableRuntimeFailpointError,
@@ -665,15 +662,17 @@ const ClientSubmitHostFailure = Schema.Union([
665
662
  const ClientAwaitHostFailure = Schema.Union([
666
663
  LedgerError,
667
664
  SettlementConflict,
665
+ OperationDenied,
668
666
  HostProtocolError
669
667
  ]);
670
668
  const ClientObserveHostFailure = Schema.Union([
671
- ConversationStoreError,
672
- ConversationNotMaterialized,
669
+ ThreadStoreError,
670
+ ThreadNotMaterialized,
673
671
  OperationDenied,
674
672
  HostProtocolError
675
673
  ]);
676
674
  const ClientAbortHostFailure = Schema.Union([
675
+ OperationDenied,
677
676
  LedgerError,
678
677
  SettlementConflict,
679
678
  JoinedToHost,
@@ -699,9 +698,9 @@ const ClientUnknownHostFailure = Schema.Union([
699
698
  DurableAlarmError,
700
699
  HostProtocolError
701
700
  ]);
702
- const outOfContract = (conversationId, operation, observed) => ConversationClientError.make({
703
- conversationId,
704
- message: boundHostDiagnostic(`The Conversation Object answered ${operation} with the out-of-contract ${observed}.`)
701
+ const outOfContract = (threadId, operation, observed) => ThreadClientError.make({
702
+ threadId,
703
+ message: boundHostDiagnostic(`The Thread Object answered ${operation} with the out-of-contract ${observed}.`)
705
704
  });
706
705
  const hostRpcMethods = {
707
706
  submit: "submitEncoded",
@@ -713,52 +712,52 @@ const hostRpcMethods = {
713
712
  resolveApproval: "resolveApprovalEncoded",
714
713
  resolveUnknown: "resolveUnknownEncoded"
715
714
  };
716
- /** Worker-side client over the Conversation Object namespace (DEPLOY-010). */
717
- var CloudflareConversationClient = class CloudflareConversationClient extends Context.Service()("@effect-agent/platform-cloudflare/CloudflareConversationClient") {
718
- static layer = Layer.effect(CloudflareConversationClient)(Effect.gen(function* () {
719
- const { namespace, rpcTracing } = yield* ConversationObjectNamespace;
715
+ /** Worker-side client over the Thread Object namespace (DEPLOY-010). */
716
+ var CloudflareThreadClient = class CloudflareThreadClient extends Context.Service()("@effect-agent/platform-cloudflare/CloudflareThreadClient") {
717
+ static layer = Layer.effect(CloudflareThreadClient)(Effect.gen(function* () {
718
+ const { namespace, rpcTracing } = yield* ThreadObjectNamespace;
720
719
  const crypto = yield* Crypto.Crypto;
721
- const call = Effect.fn(function* (conversationId, operation, encoded) {
720
+ const call = Effect.fn(function* (threadId, operation, encoded) {
722
721
  const traceArgs = rpcTracing === void 0 ? [] : yield* RpcTracing.withRpcTraceContext([]);
723
722
  const raw = yield* Effect.tryPromise({
724
723
  try: () => {
725
- return namespace.get(namespace.idFromName(conversationId))[hostRpcMethods[operation]](encoded, ...traceArgs);
724
+ return namespace.get(namespace.idFromName(threadId))[hostRpcMethods[operation]](encoded, ...traceArgs);
726
725
  },
727
- catch: (cause) => ConversationClientError.make({
728
- conversationId,
729
- message: boundHostDiagnostic(`${operation} did not reach the Conversation Object: ${safeCauseMessage(cause, "the RPC failed without a diagnostic")}`),
726
+ catch: (cause) => ThreadClientError.make({
727
+ threadId,
728
+ message: boundHostDiagnostic(`${operation} did not reach the Thread Object: ${safeCauseMessage(cause, "the RPC failed without a diagnostic")}`),
730
729
  cause,
731
730
  ...cloudflareFailureSignals(cause)
732
731
  })
733
732
  });
734
733
  return yield* decodeHostResponse(raw).pipe(Effect.mapError((error) => HostProtocolError.make({ message: boundHostDiagnostic(`The ${operation} answer could not be decoded: ${error.message}`) })));
735
- }, (effect, conversationId, operation) => rpcTracing === void 0 ? Effect.withSpan(effect, "CloudflareConversationClient.call", { attributes: {
736
- conversationId,
734
+ }, (effect, threadId, operation) => rpcTracing === void 0 ? Effect.withSpan(effect, "CloudflareThreadClient.call", { attributes: {
735
+ threadId,
737
736
  operation
738
737
  } }) : RpcTracing.withRpcClientSpan(effect, rpcTracing, hostRpcMethods[operation]));
739
- const expect = (conversationId, operation, resultSchema, failureSchema) => {
738
+ const expect = (threadId, operation, resultSchema, failureSchema) => {
740
739
  const isExpectedResult = Schema.is(resultSchema);
741
740
  const isExpectedFailure = Schema.is(failureSchema);
742
741
  return (response) => {
743
742
  if (response._tag === "HostFailed") {
744
743
  const failure = response.failure;
745
- return isExpectedFailure(failure) ? Effect.fail(failure) : Effect.fail(outOfContract(conversationId, operation, `failure ${failure._tag}`));
744
+ return isExpectedFailure(failure) ? Effect.fail(failure) : Effect.fail(outOfContract(threadId, operation, `failure ${failure._tag}`));
746
745
  }
747
- if (!isExpectedResult(response)) return Effect.fail(outOfContract(conversationId, operation, `result ${response._tag}`));
746
+ if (!isExpectedResult(response)) return Effect.fail(outOfContract(threadId, operation, `result ${response._tag}`));
748
747
  return Effect.succeed(response);
749
748
  };
750
749
  };
751
- const readPage = (conversationId, options) => Effect.gen(function* () {
750
+ const readPage = (threadId, options) => Effect.gen(function* () {
752
751
  const request = ObservePageRequest.make({
753
752
  ...options?.afterSequence === void 0 ? {} : { afterSequence: options.afterSequence },
754
753
  limit: options?.limit ?? 256
755
754
  });
756
755
  const encoded = yield* encodeObservePageRequest(request).pipe(Effect.mapError((error) => HostProtocolError.make({ message: boundHostDiagnostic(`observePage request encode failed: ${error.message}`) })));
757
- const response = yield* call(conversationId, "observePage", encoded);
758
- return (yield* expect(conversationId, "observePage", ObservedPage, ClientObserveHostFailure)(response)).records;
756
+ const response = yield* call(threadId, "observePage", encoded);
757
+ return (yield* expect(threadId, "observePage", ObservedPage, ClientObserveHostFailure)(response)).records;
759
758
  });
760
- const cancelProgress = (conversationId, waiterId) => encodeCancelProgressRequest(CancelProgressRequest.make({ waiterId })).pipe(Effect.mapError(() => void 0), Effect.flatMap((encoded) => call(conversationId, "cancelProgress", encoded)), Effect.asVoid, Effect.ignore);
761
- return CloudflareConversationClient.of({
759
+ const cancelProgress = (threadId, waiterId) => encodeCancelProgressRequest(CancelProgressRequest.make({ waiterId })).pipe(Effect.mapError(() => void 0), Effect.flatMap((encoded) => call(threadId, "cancelProgress", encoded)), Effect.asVoid, Effect.ignore);
760
+ return CloudflareThreadClient.of({
762
761
  submit: (agent, input, options) => Effect.gen(function* () {
763
762
  const encodedInput = yield* Schema.encodeEffect(agent.definition.input)(input).pipe(Effect.mapError((cause) => AgentInputError.make({ message: `Unable to encode Agent input: ${cause.message}` })));
764
763
  const inputPayload = yield* Schema.decodeUnknownEffect(PersistedJson)(encodedInput).pipe(Effect.mapError(() => AgentInputError.make({ message: "Agent input does not satisfy the canonical persistence bounds" })));
@@ -770,30 +769,30 @@ var CloudflareConversationClient = class CloudflareConversationClient extends Co
770
769
  inputPayload
771
770
  });
772
771
  const encoded = yield* encodeSubmitRequest(request).pipe(Effect.mapError((error) => HostProtocolError.make({ message: boundHostDiagnostic(`submit request encode failed: ${error.message}`) })));
773
- const response = yield* call(options.conversationId, "submit", encoded);
774
- return (yield* expect(options.conversationId, "submit", SubmitSucceeded, ClientSubmitHostFailure)(response)).receipt;
772
+ const response = yield* call(options.threadId, "submit", encoded);
773
+ return (yield* expect(options.threadId, "submit", SubmitSucceeded, ClientSubmitHostFailure)(response)).receipt;
775
774
  }),
776
775
  awaitSettlement: (receipt) => Effect.gen(function* () {
777
776
  const encoded = yield* encodeReceipt(receipt).pipe(Effect.mapError((error) => HostProtocolError.make({ message: boundHostDiagnostic(`receipt encode failed: ${error.message}`) })));
778
- const response = yield* call(receipt.conversationId, "awaitSettlement", encoded);
779
- return (yield* expect(receipt.conversationId, "awaitSettlement", SettlementReached, ClientAwaitHostFailure)(response)).settlement;
777
+ const response = yield* call(receipt.threadId, "awaitSettlement", encoded);
778
+ return (yield* expect(receipt.threadId, "awaitSettlement", SettlementReached, ClientAwaitHostFailure)(response)).settlement;
780
779
  }),
781
- awaitProgress: (conversationId, afterSequence) => Effect.gen(function* () {
780
+ awaitProgress: (threadId, afterSequence) => Effect.gen(function* () {
782
781
  const waiterId = yield* crypto.randomUUIDv4.pipe(Effect.mapError((error) => HostProtocolError.make({ message: boundHostDiagnostic(`awaitProgress cancellation identity generation failed: ${error.message}`) })));
783
782
  const request = AwaitProgressRequest.make({
784
783
  afterSequence,
785
784
  waiterId
786
785
  });
787
786
  const encoded = yield* encodeAwaitProgressRequest(request).pipe(Effect.mapError((error) => HostProtocolError.make({ message: boundHostDiagnostic(`awaitProgress request encode failed: ${error.message}`) })));
788
- const attempt = (retry) => call(conversationId, "awaitProgress", encoded).pipe(Effect.flatMap(expect(conversationId, "awaitProgress", ProgressObserved, ClientObserveHostFailure)), Effect.asVoid, Effect.catchTag("ConversationClientError", (error) => error.retryable === true && error.overloaded !== true && retry < 5 ? Effect.sleep(Duration.millis(10 * 2 ** retry)).pipe(Effect.andThen(attempt(retry + 1))) : Effect.fail(error)));
789
- yield* attempt(0).pipe(Effect.onInterrupt(() => cancelProgress(conversationId, waiterId)));
787
+ const attempt = (retry) => call(threadId, "awaitProgress", encoded).pipe(Effect.flatMap(expect(threadId, "awaitProgress", ProgressObserved, ClientObserveHostFailure)), Effect.asVoid, Effect.catchTag("ThreadClientError", (error) => error.retryable === true && error.overloaded !== true && retry < 5 ? Effect.sleep(Duration.millis(10 * 2 ** retry)).pipe(Effect.andThen(attempt(retry + 1))) : Effect.fail(error)));
788
+ yield* attempt(0).pipe(Effect.onInterrupt(() => cancelProgress(threadId, waiterId)));
790
789
  }),
791
790
  readPage,
792
- readAll: (conversationId) => Effect.gen(function* () {
791
+ readAll: (threadId) => Effect.gen(function* () {
793
792
  const all = [];
794
793
  let after;
795
794
  for (;;) {
796
- const page = yield* readPage(conversationId, {
795
+ const page = yield* readPage(threadId, {
797
796
  afterSequence: after,
798
797
  limit: 1024
799
798
  });
@@ -803,387 +802,77 @@ var CloudflareConversationClient = class CloudflareConversationClient extends Co
803
802
  after = last.sequence;
804
803
  }
805
804
  }),
806
- abort: (conversationId, command) => Effect.gen(function* () {
805
+ abort: (threadId, command) => Effect.gen(function* () {
807
806
  const encoded = yield* encodeAbortCommand(command).pipe(Effect.mapError((error) => HostProtocolError.make({ message: boundHostDiagnostic(`abort command encode failed: ${error.message}`) })));
808
- const response = yield* call(conversationId, "abort", encoded);
809
- return (yield* expect(conversationId, "abort", AbortRecorded, ClientAbortHostFailure)(response)).intent;
807
+ const response = yield* call(threadId, "abort", encoded);
808
+ return (yield* expect(threadId, "abort", AbortRecorded, ClientAbortHostFailure)(response)).intent;
810
809
  }),
811
- resolveApproval: (conversationId, command) => Effect.gen(function* () {
810
+ resolveApproval: (threadId, command) => Effect.gen(function* () {
812
811
  const encoded = yield* encodeApprovalDecisionCommand(command).pipe(Effect.mapError((error) => HostProtocolError.make({ message: boundHostDiagnostic(`approval command encode failed: ${error.message}`) })));
813
- const response = yield* call(conversationId, "resolveApproval", encoded);
814
- return (yield* expect(conversationId, "resolveApproval", ApprovalRecorded, ClientApprovalHostFailure)(response)).intent;
812
+ const response = yield* call(threadId, "resolveApproval", encoded);
813
+ return (yield* expect(threadId, "resolveApproval", ApprovalRecorded, ClientApprovalHostFailure)(response)).intent;
815
814
  }),
816
- resolveUnknown: (conversationId, command) => Effect.gen(function* () {
815
+ resolveUnknown: (threadId, command) => Effect.gen(function* () {
817
816
  const encoded = yield* encodeUnknownResolutionCommand(command).pipe(Effect.mapError((error) => HostProtocolError.make({ message: boundHostDiagnostic(`resolution command encode failed: ${error.message}`) })));
818
- const response = yield* call(conversationId, "resolveUnknown", encoded);
819
- return (yield* expect(conversationId, "resolveUnknown", UnknownResolutionRecorded, ClientUnknownHostFailure)(response)).intent;
817
+ const response = yield* call(threadId, "resolveUnknown", encoded);
818
+ return (yield* expect(threadId, "resolveUnknown", UnknownResolutionRecorded, ClientUnknownHostFailure)(response)).intent;
820
819
  })
821
820
  });
822
821
  }));
823
822
  };
824
823
  //#endregion
825
- //#region src/scheduling.ts
826
- const SCHEDULE_ALARM_TAG = "effect-agent/ScheduleOwnerWake";
827
- const SCHEDULE_ALARM_ID = "driver";
828
- const ScheduleAlarmPayload = Schema.Struct({
829
- schemaVersion: Schema.Literal(1),
830
- generation: Schema.Int.check(Schema.isGreaterThan(0))
831
- });
832
- var ScheduleAlarmProtocolError = class extends Schema.TaggedError()("ScheduleAlarmProtocolError", { message: Schema.String }) {};
833
- const boundedProtocolMessage = (message) => message.length <= 4096 ? message : `${message.slice(0, 4093)}...`;
834
- var ScheduleOwnerProtocolError = class extends Schema.TaggedError()("ScheduleOwnerProtocolError", { message: Schema.String.check(Schema.isMaxLength(4096)) }) {};
835
- const ScheduleMutationRequestFields = {
836
- schemaVersion: Schema.Literal(1),
837
- agentId: AgentId,
838
- input: PersistedJson,
839
- scope: ScheduleScope,
840
- scheduleId: ScheduleId,
841
- timing: ScheduleTimingRequest,
842
- destination: ScheduleDestination,
843
- deliveryPrincipal: ScheduleScope.fields.principal,
844
- definitions: DefinitionDigests
845
- };
846
- const ScheduleCreateRequest = Schema.TaggedStruct("Create", ScheduleMutationRequestFields);
847
- const ScheduleUpdateRequest = Schema.TaggedStruct("Update", {
848
- ...ScheduleMutationRequestFields,
849
- expectedRevision: Schema.Int.check(Schema.isGreaterThan(0))
850
- });
851
- const ScheduleGetRequest = Schema.TaggedStruct("Get", {
852
- schemaVersion: Schema.Literal(1),
853
- scope: ScheduleScope,
854
- scheduleId: ScheduleId
855
- });
856
- const ScheduleListRequest = Schema.TaggedStruct("List", {
857
- schemaVersion: Schema.Literal(1),
858
- scope: ScheduleScope,
859
- after: Schema.optionalKey(ScheduleId),
860
- limit: Schema.optionalKey(Schema.Int.check(Schema.isGreaterThan(0), Schema.isLessThanOrEqualTo(100)))
861
- });
862
- const ScheduleControlRequest = Schema.TaggedStruct("Control", {
863
- schemaVersion: Schema.Literal(1),
864
- operation: Schema.Literals([
865
- "pause",
866
- "resume",
867
- "cancel"
868
- ]),
869
- scope: ScheduleScope,
870
- scheduleId: ScheduleId,
871
- expectedRevision: Schema.Int.check(Schema.isGreaterThan(0))
872
- });
873
- const ScheduleOwnerRequest = Schema.Union([
874
- ScheduleCreateRequest,
875
- ScheduleUpdateRequest,
876
- ScheduleGetRequest,
877
- ScheduleListRequest,
878
- ScheduleControlRequest
879
- ]);
880
- const ScheduleOwnerFailure = Schema.Union([
881
- ScheduleValidationError,
882
- ScheduleAuthorizationError,
883
- ScheduleConflict,
884
- ScheduleNotFound,
885
- ScheduleCapacityError,
886
- ScheduleStorageError,
887
- ScheduleFailpointError,
888
- ScheduleOwnerProtocolError
889
- ]);
890
- const ScheduleOwnerResponse = Schema.Union([
891
- Schema.TaggedStruct("Snapshot", { value: ScheduleSnapshot }),
892
- Schema.TaggedStruct("Page", { value: ScheduleSnapshotPage }),
893
- Schema.TaggedStruct("Failed", { failure: ScheduleOwnerFailure })
894
- ]);
895
- const decodeScheduleOwnerRequest = Schema.decodeUnknownEffect(ScheduleOwnerRequest);
896
- const encodeScheduleOwnerRequest = Schema.encodeEffect(ScheduleOwnerRequest);
897
- const decodeScheduleOwnerResponse = Schema.decodeUnknownEffect(ScheduleOwnerResponse);
898
- const encodeScheduleOwnerResponse = Schema.encodeEffect(ScheduleOwnerResponse);
899
- const scheduleProtocolFailure = (message) => ({
900
- _tag: "Failed",
901
- failure: ScheduleOwnerProtocolError.make({ message: boundedProtocolMessage(message) })
902
- });
903
- var ScheduleOwnerNamespace = class extends Context.Service()("@effect-agent/platform-cloudflare/ScheduleOwnerNamespace") {};
824
+ //#region src/prepared-admission.ts
904
825
  const passthroughAgent = (agentId) => ({ definition: {
905
826
  id: agentId,
906
827
  input: PersistedJson
907
828
  } });
908
- const requestOwner = (request) => request.scope.owner;
909
- /** Provides the same authorized management service as NodeScheduling.layer. */
910
- var CloudflareSchedulingClient = class {
911
- static layer = Layer.effect(Scheduling, Effect.gen(function* () {
912
- const { namespace } = yield* ScheduleOwnerNamespace;
913
- const call = Effect.fn("CloudflareSchedulingClient.call")(function* (owner, request) {
914
- const encoded = yield* encodeScheduleOwnerRequest(request).pipe(Effect.mapError(() => ScheduleStorageError.make({
915
- operation: "Schedule Owner protocol",
916
- reason: "corrupt"
917
- })));
918
- const raw = yield* Effect.tryPromise({
919
- try: () => namespace.get(namespace.idFromName(scheduleOwnerKey(owner))).schedule(encoded),
920
- catch: () => ScheduleStorageError.make({
921
- operation: "call Schedule Owner",
922
- reason: "unavailable"
923
- })
924
- });
925
- const response = yield* decodeScheduleOwnerResponse(raw).pipe(Effect.mapError(() => ScheduleStorageError.make({
926
- operation: "Schedule Owner protocol",
927
- reason: "corrupt"
928
- })));
929
- if (response._tag !== "Failed") return response;
930
- return yield* response.failure._tag === "ScheduleOwnerProtocolError" ? ScheduleStorageError.make({
931
- operation: "Schedule Owner protocol",
932
- reason: "corrupt"
933
- }) : response.failure;
934
- });
935
- const encodeInput = Effect.fn("CloudflareSchedulingClient.encodeInput")(function* (agent, input) {
936
- const encoded = yield* Schema.encodeEffect(agent.definition.input)(input).pipe(Effect.mapError(() => ScheduleValidationError.make({ message: "Unable to encode Agent input" })));
937
- return yield* Schema.decodeUnknownEffect(PersistedJson)(encoded).pipe(Effect.mapError(() => ScheduleValidationError.make({ message: "Agent input does not satisfy the canonical persistence bounds" })));
938
- });
939
- const create = (agent, input, options) => Effect.gen(function* () {
940
- const payload = yield* encodeInput(agent, input);
941
- const response = yield* call(options.scope.owner, {
942
- _tag: "Create",
943
- schemaVersion: 1,
944
- agentId: agent.definition.id,
945
- input: payload,
946
- ...options
947
- });
948
- return response._tag === "Snapshot" ? response.value : yield* ScheduleStorageError.make({
949
- operation: "Schedule Owner protocol",
950
- reason: "corrupt"
951
- });
952
- });
953
- const update = (agent, input, options) => Effect.gen(function* () {
954
- const payload = yield* encodeInput(agent, input);
955
- const response = yield* call(options.scope.owner, {
956
- _tag: "Update",
957
- schemaVersion: 1,
958
- agentId: agent.definition.id,
959
- input: payload,
960
- ...options
961
- });
962
- return response._tag === "Snapshot" ? response.value : yield* ScheduleStorageError.make({
963
- operation: "Schedule Owner protocol",
964
- reason: "corrupt"
965
- });
966
- });
967
- const get = (scope, scheduleId) => Effect.gen(function* () {
968
- const response = yield* call(scope.owner, {
969
- _tag: "Get",
970
- schemaVersion: 1,
971
- scope,
972
- scheduleId
973
- });
974
- return response._tag === "Snapshot" ? response.value : yield* ScheduleStorageError.make({
975
- operation: "Schedule Owner protocol",
976
- reason: "corrupt"
977
- });
978
- });
979
- const list = (scope, options = {}) => Effect.gen(function* () {
980
- const response = yield* call(scope.owner, {
981
- _tag: "List",
982
- schemaVersion: 1,
983
- scope,
984
- ...options.after === void 0 ? {} : { after: options.after },
985
- ...options.limit === void 0 ? {} : { limit: options.limit }
986
- });
987
- return response._tag === "Page" ? response.value : yield* ScheduleStorageError.make({
988
- operation: "Schedule Owner protocol",
989
- reason: "corrupt"
990
- });
991
- });
992
- const control = (operation, scope, scheduleId, expectedRevision) => Effect.gen(function* () {
993
- const response = yield* call(scope.owner, {
994
- _tag: "Control",
995
- schemaVersion: 1,
996
- operation,
997
- scope,
998
- scheduleId,
999
- expectedRevision
1000
- });
1001
- return response._tag === "Snapshot" ? response.value : yield* ScheduleStorageError.make({
1002
- operation: "Schedule Owner protocol",
1003
- reason: "corrupt"
1004
- });
1005
- });
1006
- return Scheduling.of({
1007
- create,
1008
- update,
1009
- get,
1010
- list,
1011
- pause: (scope, id, revision) => control("pause", scope, id, revision),
1012
- resume: (scope, id, revision) => control("resume", scope, id, revision),
1013
- cancel: (scope, id, revision) => control("cancel", scope, id, revision)
1014
- });
1015
- }));
1016
- };
1017
- var ScheduleOwnerIdentity = class extends Context.Service()("@effect-agent/platform-cloudflare/ScheduleOwnerIdentity") {};
1018
- const decodeOwnerName = Effect.fn("decodeScheduleOwnerName")(function* (name) {
1019
- if (name === null || name === void 0) return yield* ScheduleOwnerProtocolError.make({ message: "Schedule Owner objects require an idFromName identity" });
1020
- const tuple = yield* Schema.decodeUnknownEffect(Schema.fromJsonString(Schema.Tuple([Schema.String, Schema.String])))(name).pipe(Effect.mapError(() => ScheduleOwnerProtocolError.make({ message: "Schedule Owner object name is malformed" })));
1021
- return yield* Schema.decodeUnknownEffect(ScheduleOwner)({
1022
- tenantId: tuple[0],
1023
- ownerId: tuple[1]
1024
- }).pipe(Effect.mapError(() => ScheduleOwnerProtocolError.make({ message: "Schedule Owner object identity is invalid" })));
1025
- });
1026
- const alarmStorageError = (operation) => (error) => ScheduleStorageError.make({
1027
- operation,
1028
- reason: error._tag === "StorageOperationError" ? "unavailable" : "corrupt"
1029
- });
1030
- const transactionLayer = Layer.effect(DoScheduleTransaction, Effect.gen(function* () {
1031
- const alarms = yield* DurableObjectAlarm.DurableObjectAlarm;
1032
- return DoScheduleTransaction.of({ run: (body) => Effect.gen(function* () {
1033
- const nowMillis = yield* Clock.currentTimeMillis;
1034
- return yield* alarms.transaction((transaction) => body((replacement) => replacement.deadlineAtMillis === null ? transaction.cancelAlarm({
1035
- id: SCHEDULE_ALARM_ID,
1036
- tag: SCHEDULE_ALARM_TAG
1037
- }).pipe(Effect.mapError(alarmStorageError("cancel Schedule Owner alarm"))) : Effect.fromOption(DateTime.make(Math.max(replacement.deadlineAtMillis, nowMillis + 1))).pipe(Effect.mapError(() => ScheduleStorageError.make({
1038
- operation: "validate Schedule Owner alarm deadline",
1039
- reason: "corrupt"
1040
- })), Effect.flatMap((runAt) => transaction.scheduleAlarm({
1041
- id: SCHEDULE_ALARM_ID,
1042
- tag: SCHEDULE_ALARM_TAG,
1043
- runAt,
1044
- payload: {
1045
- schemaVersion: 1,
1046
- generation: replacement.generation
1047
- }
1048
- }).pipe(Effect.mapError(alarmStorageError("schedule Schedule Owner alarm"))))))).pipe(Effect.catchTag("StorageOperationError", () => ScheduleStorageError.make({
1049
- operation: "commit Schedule Owner transaction",
1050
- reason: "unavailable"
1051
- })));
1052
- }) });
1053
- }));
1054
- const admissionLayer = Layer.effect(ScheduledInputAdmission, Effect.gen(function* () {
1055
- const client = yield* CloudflareConversationClient;
1056
- const submit = (envelope) => client.submit(passthroughAgent(envelope.agentId), envelope.input, {
1057
- conversationId: envelope.conversationId,
829
+ /** Ordinary prepared admission through one freshly addressed Thread Object call. */
830
+ const cloudflarePreparedInputAdmissionLayer = Layer.effect(PreparedInputAdmission, Effect.gen(function* () {
831
+ const client = yield* CloudflareThreadClient;
832
+ return PreparedInputAdmission.of({ submit: (envelope) => client.submit(passthroughAgent(envelope.agentId), envelope.input, {
833
+ threadId: envelope.threadId,
1058
834
  principal: envelope.deliveryPrincipal,
1059
835
  idempotencyKey: envelope.admissionKey,
1060
836
  definitions: envelope.definitions
1061
837
  }).pipe(Effect.catchTags({
1062
838
  AdmissionConflict: () => ScheduleStorageError.make({
1063
- operation: "scheduled admission",
839
+ operation: "prepared admission",
1064
840
  reason: "corrupt"
1065
841
  }),
1066
842
  AdmissionLimitExceeded: () => ScheduledInputRetryable.make({ reason: "capacity" }),
1067
- ConversationClientError: (error) => ScheduledInputRetryable.make({ reason: error.overloaded === true ? "capacity" : "transport" }),
843
+ ThreadClientError: (error) => ScheduledInputRetryable.make({ reason: error.overloaded === true ? "capacity" : "transport" }),
1068
844
  HostProtocolError: () => ScheduledInputRetryable.make({ reason: "ambiguous" }),
1069
845
  LedgerError: () => ScheduledInputRetryable.make({ reason: "storage" }),
1070
- ConversationStoreError: () => ScheduledInputRetryable.make({ reason: "storage" }),
846
+ ThreadStoreError: () => ScheduledInputRetryable.make({ reason: "storage" }),
1071
847
  DurableAlarmError: () => ScheduledInputRetryable.make({ reason: "storage" }),
1072
848
  AgentInputError: () => ScheduleStorageError.make({
1073
- operation: "scheduled admission",
849
+ operation: "prepared admission",
1074
850
  reason: "corrupt"
1075
851
  }),
1076
852
  DigestError: () => ScheduleStorageError.make({
1077
- operation: "scheduled admission",
853
+ operation: "prepared admission",
1078
854
  reason: "corrupt"
1079
855
  }),
1080
- ConversationNotMaterialized: () => ScheduledInputRetryable.make({ reason: "storage" }),
856
+ ThreadNotMaterialized: () => ScheduledInputRetryable.make({ reason: "storage" }),
1081
857
  AppendConflict: () => ScheduledInputRetryable.make({ reason: "ambiguous" }),
1082
858
  FenceRejected: () => ScheduledInputRetryable.make({ reason: "ambiguous" }),
1083
859
  DurableRuntimeFailpointError: () => ScheduledInputRetryable.make({ reason: "ambiguous" })
1084
- }));
1085
- return ScheduledInputAdmission.of({ submit });
860
+ })) });
1086
861
  }));
1087
- const ensureOwner = (expected, request) => {
1088
- const observed = requestOwner(request);
1089
- return observed.tenantId === expected.tenantId && observed.ownerId === expected.ownerId ? Effect.void : Effect.fail(ScheduleOwnerProtocolError.make({ message: "The request owner does not match the addressed Schedule Owner object" }));
1090
- };
1091
- const handleScheduleRequest = Effect.fn("ScheduleOwner.handleRequest")(function* (encoded) {
1092
- const decoded = yield* decodeScheduleOwnerRequest(encoded).pipe(Effect.result);
1093
- if (decoded._tag === "Failure") return yield* encodeScheduleOwnerResponse(scheduleProtocolFailure("The Schedule request could not be decoded")).pipe(Effect.orDie);
1094
- const request = decoded.success;
1095
- const { owner } = yield* ScheduleOwnerIdentity;
1096
- const scheduling = yield* Scheduling;
1097
- const response = yield* Effect.gen(function* () {
1098
- yield* ensureOwner(owner, request);
1099
- switch (request._tag) {
1100
- case "Create": return {
1101
- _tag: "Snapshot",
1102
- value: yield* scheduling.create(passthroughAgent(request.agentId), request.input, {
1103
- scope: request.scope,
1104
- scheduleId: request.scheduleId,
1105
- timing: request.timing,
1106
- destination: request.destination,
1107
- deliveryPrincipal: request.deliveryPrincipal,
1108
- definitions: request.definitions
1109
- })
1110
- };
1111
- case "Update": return {
1112
- _tag: "Snapshot",
1113
- value: yield* scheduling.update(passthroughAgent(request.agentId), request.input, {
1114
- scope: request.scope,
1115
- scheduleId: request.scheduleId,
1116
- timing: request.timing,
1117
- destination: request.destination,
1118
- deliveryPrincipal: request.deliveryPrincipal,
1119
- definitions: request.definitions,
1120
- expectedRevision: request.expectedRevision
1121
- })
1122
- };
1123
- case "Get": return {
1124
- _tag: "Snapshot",
1125
- value: yield* scheduling.get(request.scope, request.scheduleId)
1126
- };
1127
- case "List": return {
1128
- _tag: "Page",
1129
- value: yield* scheduling.list(request.scope, {
1130
- ...request.after === void 0 ? {} : { after: request.after },
1131
- ...request.limit === void 0 ? {} : { limit: request.limit }
1132
- })
1133
- };
1134
- case "Control": return {
1135
- _tag: "Snapshot",
1136
- value: request.operation === "pause" ? yield* scheduling.pause(request.scope, request.scheduleId, request.expectedRevision) : request.operation === "resume" ? yield* scheduling.resume(request.scope, request.scheduleId, request.expectedRevision) : yield* scheduling.cancel(request.scope, request.scheduleId, request.expectedRevision)
1137
- };
1138
- }
1139
- }).pipe(Effect.map((value) => value), Effect.catch((failure) => Schema.is(ScheduleOwnerFailure)(failure) ? Effect.succeed({
1140
- _tag: "Failed",
1141
- failure
1142
- }) : Effect.succeed(scheduleProtocolFailure("The Schedule operation failed outside its public contract"))));
1143
- return yield* encodeScheduleOwnerResponse(response).pipe(Effect.orDie);
862
+ const preparedFromSchedule = (envelope) => ({
863
+ schemaVersion: 1,
864
+ threadId: envelope.threadId,
865
+ deliveryPrincipal: envelope.deliveryPrincipal,
866
+ agentId: envelope.agentId,
867
+ definitions: envelope.definitions,
868
+ input: envelope.input,
869
+ inputDigest: envelope.inputDigest,
870
+ admissionKey: envelope.admissionKey,
871
+ authorization: envelope.authorization
1144
872
  });
1145
- const scheduleAlarmHandler = (limits) => DurableObjectAlarm.processDue((event) => Effect.gen(function* () {
1146
- if (event.tag !== SCHEDULE_ALARM_TAG || event.id !== SCHEDULE_ALARM_ID) return yield* ScheduleAlarmProtocolError.make({ message: `Unsupported Schedule Owner alarm ${event.tag}/${event.id}` });
1147
- yield* Schema.decodeUnknownEffect(ScheduleAlarmPayload)(event.payload).pipe(Effect.mapError(() => ScheduleAlarmProtocolError.make({ message: "Unsupported Schedule Owner alarm payload version" })));
1148
- const scheduling = yield* ScheduleDriver;
1149
- const alarmControl = yield* DoScheduleAlarmControl;
1150
- const { owner } = yield* ScheduleOwnerIdentity;
1151
- const nowMillis = yield* Clock.currentTimeMillis;
1152
- yield* alarmControl.prearm(nowMillis + limits.recoveryPollMillis);
1153
- if ((yield* scheduling.runDue(owner)).failed > 0) yield* alarmControl.prearm((yield* Clock.currentTimeMillis) + limits.recoveryPollMillis);
1154
- else yield* alarmControl.reconcile;
1155
- }), { mode: "ordered" }).pipe(Effect.asVoid);
1156
- /**
1157
- * The host Layer supplies authorization and routing and is cached for the object incarnation.
1158
- * Cloudflare eviction does not guarantee its finalizers run. Do not acquire resources requiring
1159
- * cleanup in this Layer; acquire them inside scoped `manage` / `prepare` operations instead.
1160
- * Native services belong to effect-cf; the database and alarm runtime remain instance-owned.
1161
- */
1162
- const makeScheduleOwnerObjectClass = (host, limits = defaultSchedulingLimits) => {
1163
- const ownerLayer = Layer.effect(ScheduleOwnerIdentity, Effect.gen(function* () {
1164
- const state = yield* DurableObjectState.DurableObjectState;
1165
- return ScheduleOwnerIdentity.of({ owner: yield* decodeOwnerName(state.raw.id.name) });
1166
- }));
1167
- const sqlLayer = Layer.unwrap(Effect.map(DurableObjectState.DurableObjectState, (state) => SqliteClient.layer({ storage: state.raw.storage })));
1168
- const application = Layer.merge(Scheduling.layer(limits), ScheduleDriver.layer(limits)).pipe(Layer.provideMerge(scheduleStoreLayer.pipe(Layer.provide(transactionLayer), Layer.provide(sqlLayer))), Layer.provide(admissionLayer.pipe(Layer.provide(CloudflareConversationClient.layer))), Layer.provide(ScheduleWakeNoop), Layer.provide(BrowserCrypto.layer), Layer.provideMerge(DurableObjectAlarm.DurableObjectAlarm.layer), Layer.provide(host), Layer.provideMerge(ownerLayer));
1169
- const runtime = Layer.effectContext(Effect.gen(function* () {
1170
- const state = yield* DurableObjectState.DurableObjectState;
1171
- const scope = yield* Effect.scope;
1172
- return yield* state.blockConcurrencyWhile(Layer.buildWithScope(application, scope));
1173
- }));
1174
- const Base = DurableObject.make(runtime, {
1175
- initialize: Effect.void,
1176
- rpc: { schedule: (encoded) => handleScheduleRequest(encoded) },
1177
- alarms: scheduleAlarmHandler(limits)
1178
- });
1179
- class ScheduleOwnerObject extends Base {
1180
- alarm(alarmInfo) {
1181
- return super.alarm?.(alarmInfo);
1182
- }
1183
- }
1184
- return ScheduleOwnerObject;
1185
- };
873
+ /** Compatibility adapter retaining Scheduling's public admission port. */
874
+ const cloudflareScheduledInputAdmissionLayer = Layer.effect(ScheduledInputAdmission, Effect.map(PreparedInputAdmission, (admission) => ScheduledInputAdmission.of({ submit: (envelope) => admission.submit(preparedFromSchedule(envelope)) })));
1186
875
  //#endregion
1187
- export { CLOUDFLARE_RUNTIME_DEFAULTS as $, decodeHostResponse as A, encodeObservePageRequest as B, SubmitSucceeded as C, decodeApprovalDecisionCommand as D, decodeAbortCommand as E, encodeAbortCommand as F, ConversationMaintenanceFailpoint as G, encodeSubmitRequest as H, encodeApprovalDecisionCommand as I, MaintenancePassReport as J, DurableAlarmError as K, encodeAwaitProgressRequest as L, decodeReceipt as M, decodeSubmitRequest as N, decodeAwaitProgressRequest as O, decodeUnknownResolutionCommand as P, CLOUDFLARE_DATABASE_CAP_BYTES as Q, encodeCancelProgressRequest as R, SubmitRequest as S, boundHostDiagnostic as T, encodeUnknownResolutionCommand as U, encodeReceipt as V, ConversationMaintenance as W, safeCauseMessage as X, safeCauseDiagnostic as Y, AdmissionLimitExceeded as Z, ObservePageRequest as _, ScheduleOwnerProtocolError as a, CloudflareBindingError as at, ProgressObserved as b, ApprovalRecorded as c, DurableObjectContext as ct, CloudflareConversationClient as d, CloudflareAdmissionLimitsValue as et, ConversationClientError as f, HostResponse as g, HostProtocolError as h, ScheduleOwnerNamespace as i, DEFAULT_MAX_DATABASE_BYTES as it, decodeObservePageRequest as j, decodeCancelProgressRequest as k, AwaitProgressRequest as l, conversationNamespaceFromEnv as lt, HostFailure as m, ScheduleAlarmProtocolError as n, CloudflareDurableRuntimeConfigValue as nt, makeScheduleOwnerObjectClass as o, ConversationObjectIdentity as ot, HostFailed as p, DurableAlarmService as q, ScheduleOwnerIdentity as r, CloudflarePlatformConfigError as rt, AbortRecorded as s, ConversationObjectNamespace as st, CloudflareSchedulingClient as t, CloudflareDurableRuntimeConfig as tt, CancelProgressRequest as u, conversationNamespaceLayer as ut, ObservedPage as v, UnknownResolutionRecorded as w, SettlementReached as x, ProgressCancelled as y, encodeHostResponse as z };
876
+ export { CloudflarePlatformConfigError as $, decodeUnknownResolutionCommand as A, DurableAlarmError as B, decodeApprovalDecisionCommand as C, decodeObservePageRequest as D, decodeHostResponse as E, encodeHostResponse as F, safeCauseDiagnostic as G, MaintenancePassReport as H, encodeObservePageRequest as I, CLOUDFLARE_DATABASE_CAP_BYTES as J, safeCauseMessage as K, encodeReceipt as L, encodeApprovalDecisionCommand as M, encodeAwaitProgressRequest as N, decodeReceipt as O, encodeCancelProgressRequest as P, CloudflareDurableRuntimeConfigValue as Q, encodeSubmitRequest as R, decodeAbortCommand as S, decodeCancelProgressRequest as T, ThreadMaintenance as U, DurableAlarmService as V, ThreadMaintenanceFailpoint as W, CloudflareAdmissionLimitsValue as X, CLOUDFLARE_RUNTIME_DEFAULTS as Y, CloudflareDurableRuntimeConfig as Z, SubmitRequest as _, AwaitProgressRequest as a, threadNamespaceFromEnv as at, UnknownResolutionRecorded as b, HostFailed as c, HostResponse as d, DEFAULT_MAX_DATABASE_BYTES as et, ObservePageRequest as f, SettlementReached as g, ProgressObserved as h, ApprovalRecorded as i, ThreadObjectNamespace as it, encodeAbortCommand as j, decodeSubmitRequest as k, HostFailure as l, ProgressCancelled as m, cloudflareScheduledInputAdmissionLayer as n, DurableObjectContext as nt, CancelProgressRequest as o, threadNamespaceLayer as ot, ObservedPage as p, AdmissionLimitExceeded as q, AbortRecorded as r, ThreadObjectIdentity as rt, CloudflareThreadClient as s, cloudflarePreparedInputAdmissionLayer as t, CloudflareBindingError as tt, HostProtocolError as u, SubmitSucceeded as v, decodeAwaitProgressRequest as w, boundHostDiagnostic as x, ThreadClientError as y, encodeUnknownResolutionCommand as z };
1188
877
 
1189
- //# sourceMappingURL=scheduling-B-OFqoS9.mjs.map
878
+ //# sourceMappingURL=prepared-admission-D5hQ-ofV.mjs.map