@effect-agent/platform-cloudflare 0.1.0-beta.96 → 0.1.0-beta.98
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/Alarm.mjs +10 -6
- package/dist/Alarm.mjs.map +1 -1
- package/dist/CloudflareThreadClient.d.mts +69 -48
- package/dist/{ThreadObject-DiqVDdJE.d.mts → ThreadObject-CMQiW2uX.d.mts} +20 -7
- package/dist/ThreadObject.d.mts +1 -1
- package/dist/index.d.mts +1 -1
- package/package.json +1 -1
- package/src/Alarm.ts +10 -5
package/dist/Alarm.mjs
CHANGED
|
@@ -196,12 +196,12 @@ const ensureTransactionAlarmBy = async (transaction, deadline) => {
|
|
|
196
196
|
if (scheduled === null || scheduled > deadline) await transaction.setAlarm(deadline);
|
|
197
197
|
};
|
|
198
198
|
const stableExternalWait = (snapshot, reports) => {
|
|
199
|
-
const
|
|
200
|
-
if (decision === "SettleAborted") return false;
|
|
199
|
+
const report = reports.get(snapshot.submissionId);
|
|
200
|
+
if (report?.decision._tag === "SettleAborted") return false;
|
|
201
201
|
switch (snapshot.state) {
|
|
202
202
|
case "suspended":
|
|
203
203
|
case "joined": return true;
|
|
204
|
-
case "unknown": return
|
|
204
|
+
case "unknown": return report?.disposition === "unknown";
|
|
205
205
|
case "admitted": return reports.get(snapshot.submissionId)?.decision._tag === "AwaitParentEstablishment";
|
|
206
206
|
case "input-applied":
|
|
207
207
|
case "joining":
|
|
@@ -431,7 +431,10 @@ var ThreadMaintenance = class ThreadMaintenance extends Context.Service()("@effe
|
|
|
431
431
|
const reports = new Map(recovered.map((report) => [report.submissionId, report]));
|
|
432
432
|
const current = yield* Stream.runCollect(ledger.scanNonterminal);
|
|
433
433
|
const heads = /* @__PURE__ */ new Map();
|
|
434
|
-
for (const row of current)
|
|
434
|
+
for (const row of current) {
|
|
435
|
+
if (row.state === "unknown" && stableExternalWait(row, reports)) continue;
|
|
436
|
+
if (!heads.has(row.threadId)) heads.set(row.threadId, row);
|
|
437
|
+
}
|
|
435
438
|
const eligible = [...heads.values()].filter((head) => !stableExternalWait(head, reports)).map((head) => head.threadId).sort();
|
|
436
439
|
const selectionTime = yield* Clock.currentTimeMillis;
|
|
437
440
|
yield* failpoint.hit("maintenance:select:before");
|
|
@@ -453,7 +456,7 @@ var ThreadMaintenance = class ThreadMaintenance extends Context.Service()("@effe
|
|
|
453
456
|
const selected = selection.selected === void 0 ? void 0 : heads.get(selection.selected);
|
|
454
457
|
let retries = selection.retries;
|
|
455
458
|
let bindingFailure;
|
|
456
|
-
const settlement = selected === void 0 ? Option.none() : yield* runtime.processThreadHead(selected.threadId, { yieldAfter }).pipe(Effect.catchTag(
|
|
459
|
+
const settlement = selected === void 0 ? Option.none() : yield* runtime.processThreadHead(selected.threadId, { yieldAfter }).pipe(Effect.catchTag("BindingUnavailable", (failure) => {
|
|
457
460
|
bindingFailure = failure;
|
|
458
461
|
return Effect.succeed(Option.none());
|
|
459
462
|
}));
|
|
@@ -486,13 +489,14 @@ var ThreadMaintenance = class ThreadMaintenance extends Context.Service()("@effe
|
|
|
486
489
|
}));
|
|
487
490
|
yield* failpoint.hit("maintenance:binding-retry:after");
|
|
488
491
|
}
|
|
489
|
-
if (bindingFailure !== void 0) yield* reportBindingFailure ? Effect.logError("Thread awaits a
|
|
492
|
+
if (bindingFailure !== void 0) yield* reportBindingFailure ? Effect.logError("Thread awaits a current agent binding; original work remains pending", Cause.fail(bindingFailure)) : Effect.logDebug("Thread binding retry remains pending", Cause.fail(bindingFailure));
|
|
490
493
|
}
|
|
491
494
|
observed.nativeOnly = false;
|
|
492
495
|
yield* finishAuxiliary;
|
|
493
496
|
const remaining = yield* Stream.runCollect(ledger.scanNonterminal);
|
|
494
497
|
const waitingHeads = /* @__PURE__ */ new Map();
|
|
495
498
|
const autonomous = remaining.some((snapshot) => {
|
|
499
|
+
if (snapshot.state === "unknown" && stableExternalWait(snapshot, reports)) return false;
|
|
496
500
|
const headWaiting = waitingHeads.get(snapshot.threadId);
|
|
497
501
|
if (headWaiting === void 0) waitingHeads.set(snapshot.threadId, stableExternalWait(snapshot, reports));
|
|
498
502
|
if (headWaiting === true && snapshot.state === "ready" && reports.get(snapshot.submissionId)?.decision._tag === "ApplyInput") return false;
|
package/dist/Alarm.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Alarm.mjs","names":[],"sources":["../src/Alarm.ts"],"sourcesContent":["import {\n Cause,\n Clock,\n Context,\n DateTime,\n Deferred,\n Effect,\n Exit,\n Fiber,\n Layer,\n Option,\n Random,\n Ref,\n Schema,\n Scope,\n Semaphore,\n Stream,\n Struct,\n} from \"effect\";\nimport { type DurableBindingFailure } from \"effect-agent/agent-registration\";\nimport {\n DurableAgentRuntime,\n type DurableWorkerFailure,\n type RecoveryReport,\n} from \"effect-agent/durable-agent-runtime\";\nimport { ThreadId, SubmissionId } from \"effect-agent/identifiers\";\nimport { SubmissionLedger, type SubmissionSnapshot } from \"effect-agent/submission-ledger\";\nimport {\n ThreadProjectionMaintenance,\n drainDue,\n type ThreadProjectionError,\n} from \"effect-agent/thread-projection-maintenance\";\nimport { SqlClient } from \"effect/unstable/sql/SqlClient\";\n\nimport { DurableObjectContext } from \"./CloudflareBindings.ts\";\nimport { AuxiliaryDispatchMillis, CloudflareDurableRuntimeConfig } from \"./CloudflareConfig.ts\";\nimport { safeCauseMessage } from \"./internal/boundary.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): every committed actionable mutation carries a newer durable\n * maintenance generation and a committed alarm. Stable externally-driven waits may be\n * nonterminal without retaining an alarm; their resolving mutation advances the generation and\n * restores the alarm atomically.\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: safeCauseMessage(cause, \"The Cloudflare alarm API failed without a diagnostic\"),\n cause,\n });\n\n// SQL and raw KV/alarm operations share one physical SQLite transaction. Reserve its\n// connection for each short storage operation, never around a mutation or snapshot body.\nconst makeStorageOperation = Effect.map(\n SqlClient,\n (sql) =>\n <A>(operation: string, execute: () => Promise<A>) =>\n Effect.flatMap(Effect.serviceOption(sql.transactionService), (current) => {\n const body = Effect.uninterruptible(\n Effect.tryPromise({ try: execute, catch: alarmFailure(operation) }),\n );\n\n return current._tag === \"Some\"\n ? body\n : Effect.scoped(\n Effect.andThen(sql.reserve.pipe(Effect.mapError(alarmFailure(operation))), body),\n );\n }),\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). The pass's durable generation check observes any racing mutation, so the\n * in-memory hint does not need to be flushed after a stable wait is acknowledged.\n */\n readonly scheduleNow: Effect.Effect<void, DurableAlarmError>;\n /**\n * Run one maintenance pass with wake deferral (see `scheduleNow`). Calls made while `body`\n * executes are droppable promptness hints; correctness rests on the durable generation.\n */\n readonly withWakesDeferred: <A, E, R>(body: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R>;\n /** Clear the slot; correctness-sensitive clears live in maintenance generation transactions. */\n readonly cancel: Effect.Effect<void, DurableAlarmError>;\n }\n>()(\"@effect-agent/platform-cloudflare/DurableAlarmService\") {\n static readonly layer: Layer.Layer<DurableAlarmService, never, DurableObjectContext | SqlClient> =\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\n const storageOperation = yield* makeStorageOperation;\n\n const scheduled = storageOperation(\"get alarm\", () => ctx.storage.getAlarm()).pipe(\n Effect.map((deadline) =>\n deadline === null ? Option.none<number>() : Option.some(deadline),\n ),\n );\n\n const scheduleAt = (epochMillis: number) =>\n storageOperation(\"set alarm\", () => ctx.storage.setAlarm(epochMillis));\n\n const ensureScheduledBy = (epochMillis: number) =>\n storageOperation(\"ensure alarm\", () =>\n ctx.storage.transaction(async (transaction) => {\n const existing = await transaction.getAlarm();\n\n if (existing === null || existing > epochMillis) {\n await transaction.setAlarm(epochMillis);\n }\n }),\n );\n\n const armNow = Clock.currentTimeMillis.pipe(\n Effect.flatMap((now) => ensureScheduledBy(now)),\n );\n\n const scheduleNow = Ref.get(runningPasses).pipe(\n Effect.flatMap((passes) => (passes > 0 ? Effect.void : armNow)),\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(Ref.update(runningPasses, (passes) => passes - 1)),\n );\n\n const cancel = storageOperation(\"delete alarm\", () => ctx.storage.deleteAlarm());\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 /** `caught-up` ran no runtime work (publication may be pending); `actionable` ran recovery. */\n phase: Schema.Literals([\"caught-up\", \"actionable\"]),\n /** Recovery decisions executed (or deferred) BEFORE any new claim in this pass. */\n recovered: Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)),\n /** Whether the head Attempt settled. Joined input may settle with that head. */\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` for dirty/autonomous work, `cleared` for stable waits or settlement. */\n alarm: Schema.Literals([\"rearmed\", \"cleared\"]),\n}) {}\n\n/** Fault boundaries around every maintenance-owned durable mutation. */\nexport type ThreadMaintenanceFailpointLocation =\n | \"maintenance:dirty:before\"\n | \"maintenance:dirty:after\"\n | \"maintenance:mutation:armed\"\n | \"maintenance:mutation:finished\"\n | \"maintenance:ensure:before\"\n | \"maintenance:ensure:after\"\n | \"maintenance:begin:before\"\n | \"maintenance:begin:after\"\n | \"maintenance:select:before\"\n | \"maintenance:select:after\"\n | \"maintenance:binding-retry:before\"\n | \"maintenance:binding-retry:after\"\n | \"maintenance:retry:before\"\n | \"maintenance:retry:after\"\n | \"maintenance:finish:before\"\n | \"maintenance:finish:after\";\n\nexport type ThreadMaintenanceFailpointHandler = (\n location: ThreadMaintenanceFailpointLocation,\n) => Effect.Effect<void>;\n\n/** Test-only fault authority; production uses the inert layer. */\nexport class ThreadMaintenanceFailpoint extends Context.Service<\n ThreadMaintenanceFailpoint,\n {\n readonly hit: ThreadMaintenanceFailpointHandler;\n }\n>()(\"@effect-agent/platform-cloudflare/ThreadMaintenanceFailpoint\") {\n static readonly layer = Layer.succeed(this)({ hit: () => Effect.void });\n}\n\n/**\n * Durable host publication of canonical records and ledger approval/abort/resolution intents.\n * The host owns schema-versioned cursors, destination idempotency and acknowledgement. Delivery\n * is at least once. Hooks must not write the alarm slot or mutate the supplied raw source ports.\n *\n * `invalidate`, `prepareGeneration` and `pendingDeadline` must be bounded local operations.\n * `prepareGeneration` durably invalidates a scan only when its generation changes; repeated\n * calls must preserve partial scan progress. It runs with no source mutation in flight.\n * Use this gate only for publication required before dependent native execution. Independent\n * UI relays and outboxes belong to ThreadHostMaintenance.\n * `drain` performs bounded delivery and persists retries before returning. A pending deadline\n * defers runtime recovery/Attempts, allowing committed host publications to drain first.\n * Unexpected hook failures leave the prearmed generation for retry. Hooks acquire per-call\n * resources with Effect.scoped; Layer construction owns incarnation resources (eviction need\n * not run finalizers). Do not hold a local hook behind network I/O or call back into producers.\n */\nexport interface ThreadPublicationService {\n readonly invalidate: Effect.Effect<void, DurableAlarmError>;\n readonly prepareGeneration: (generation: bigint) => Effect.Effect<void, DurableAlarmError>;\n readonly drain: Effect.Effect<void, DurableAlarmError>;\n readonly pendingDeadline: Effect.Effect<Option.Option<number>, DurableAlarmError>;\n}\n\n/** Opt in with `ThreadObject.layer(registrations, { publication: Layer.effect(ThreadPublication)(...) })`. */\nexport class ThreadPublication extends Context.Service<\n ThreadPublication,\n ThreadPublicationService\n>()(\"@effect-agent/platform-cloudflare/ThreadPublication\") {\n static readonly layer = Layer.succeed(this)({\n invalidate: Effect.void,\n prepareGeneration: () => Effect.void,\n drain: Effect.void,\n pendingDeadline: Effect.succeed(Option.none()),\n });\n}\n\n/**\n * Host-assembled native message recovery. The driver bounds each actual Claim and persists its\n * timeout/retry before this pump returns. Do not add a second timer starting at batch selection:\n * local Claim setup may take time, and expiration still owes the driver's local retry commit.\n */\nexport const ThreadMessageDelivery = Context.Reference<{\n readonly drainUntil: (\n sourceFinished: Effect.Effect<void>,\n dispatchUntil: DateTime.Utc,\n ) => Effect.Effect<void, DurableAlarmError, Scope.Scope>;\n readonly pendingDeadline: Effect.Effect<Option.Option<number>, DurableAlarmError>;\n}>(\"@effect-agent/platform-cloudflare/ThreadMessageDelivery\", {\n defaultValue: () => ({\n drainUntil: () => Effect.void,\n pendingDeadline: Effect.succeed(Option.none()),\n }),\n});\n\n/**\n * Application obligations sharing this Object's alarm. Admit one initial external wave even on\n * a caught-up pass, then respond to wakes while native work runs. sourceFinished closes only\n * admission of NEW external waves. Keep local admission/hub subscriptions in the supplied event\n * Scope until maintenance tears it down; do not scope them to sourceFinished or to this Effect.\n * No deadline sleeps or automatic retry loops. Return after already-admitted waves finish.\n *\n * Declare a finite whole-wave allowance (1..300000ms): maximum for parallel lanes, sum for\n * sequential operations. Admit a wave only if its allowance fits before dispatchUntil. Later\n * arrivals cannot renew the retirement window. Maintenance bounds the join after sourceFinished,\n * interrupts and joins event Scope, then reads local deadlines under the mutation gate.\n *\n * Setup and pendingDeadline are bounded local operations. Persist claims/envelopes before\n * dispatch; interrupted waits leave exact retries/receipts recoverable. Cancellation is local,\n * not remote rollback. Retry accounting is unchanged. Network waits/finalizers must be\n * interruptible; short local atomic commits may be uninterruptible. Hooks never write the raw\n * alarm slot. Required native publication gates belong to ThreadPublication.\n */\nexport const ThreadHostMaintenance = Context.Reference<{\n readonly dispatchTimeoutMillis: number;\n readonly drainUntil: (\n sourceFinished: Effect.Effect<void>,\n dispatchUntil: DateTime.Utc,\n ) => Effect.Effect<void, DurableAlarmError, Scope.Scope>;\n readonly pendingDeadline: Effect.Effect<Option.Option<number>, DurableAlarmError>;\n}>(\"@effect-agent/platform-cloudflare/ThreadHostMaintenance\", {\n defaultValue: () => ({\n dispatchTimeoutMillis: 1,\n drainUntil: () => Effect.void,\n pendingDeadline: Effect.succeed(Option.none()),\n }),\n});\n\nconst earliestDeadline = (\n left: Option.Option<number>,\n right: Option.Option<number>,\n): Option.Option<number> =>\n Option.isSome(left)\n ? Option.isSome(right)\n ? Option.some(Math.min(left.value, right.value))\n : left\n : right;\n\n/** @internal A committed source operation must not become a failed operation because delivery failed. */\nexport const publishCommitted = Effect.gen(function* () {\n const publication = yield* ThreadPublication;\n\n yield* publication.invalidate.pipe(Effect.andThen(publication.drain));\n}).pipe(\n Effect.catchCause((cause) =>\n Cause.hasInterrupts(cause)\n ? Effect.interrupt\n : Effect.logError(\"Thread publication deferred after source commit\", cause),\n ),\n);\n\nconst MaintenanceGeneration = Schema.BigIntFromString.check(\n Schema.isGreaterThanOrEqualToBigInt(0n),\n);\n\nclass BindingRetry extends Schema.Class<BindingRetry>(\"BindingRetry\")({\n threadId: ThreadId,\n submissionId: SubmissionId,\n attempts: Schema.Natural,\n notBefore: Schema.Finite,\n reportedAt: Schema.Finite,\n}) {}\n\ninterface MaintenanceObservation {\n generation?: bigint;\n nativeOnly: boolean;\n}\n\nclass MaintenanceRetry extends Schema.Class<MaintenanceRetry>(\"MaintenanceRetry\")({\n generation: MaintenanceGeneration,\n notBefore: Schema.Finite,\n nativeOnly: Schema.Boolean,\n stalls: Schema.Int.check(Schema.isGreaterThanOrEqualTo(0), Schema.isLessThanOrEqualTo(30)),\n}) {}\n\n/** Versioned, platform-private maintenance state stored through Durable Object KV. */\nclass ThreadMaintenanceState extends Schema.Class<ThreadMaintenanceState>(\n \"@effect-agent/platform-cloudflare/ThreadMaintenanceState\",\n)({\n schemaVersion: Schema.Literal(1),\n dirty: MaintenanceGeneration,\n processed: MaintenanceGeneration,\n nonterminal: Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)),\n /** One physical-owner cursor; old single-lane records need no conversion. */\n lastServedThreadId: Schema.optionalKey(ThreadId),\n bindingRetries: Schema.optionalKey(Schema.Array(BindingRetry)),\n /** Absent on older records. A newer mutation makes this retry obsolete. */\n retry: Schema.optionalKey(MaintenanceRetry),\n}) {}\n\nconst MAINTENANCE_STATE_KEY = \"effect-agent:thread-maintenance:v1\";\nconst decodeMaintenanceState = Schema.decodeUnknownSync(ThreadMaintenanceState);\nconst encodeMaintenanceState = Schema.encodeSync(ThreadMaintenanceState);\n\nconst initialMaintenanceState = (): ThreadMaintenanceState =>\n ThreadMaintenanceState.make({\n schemaVersion: 1,\n // Bootstrap Objects created by the pre-generation release without scanning the ledger in\n // the constructor. One useful pass classifies and acknowledges any existing obligation.\n dirty: 1n,\n processed: 0n,\n nonterminal: 0,\n });\n\nconst readMaintenanceState = async (\n transaction: DurableObjectTransaction,\n): Promise<{ readonly state: ThreadMaintenanceState; readonly initialized: boolean }> => {\n const encoded = await transaction.get(MAINTENANCE_STATE_KEY);\n\n return encoded === undefined\n ? { state: initialMaintenanceState(), initialized: false }\n : { state: decodeMaintenanceState(encoded), initialized: true };\n};\n\nconst ensureTransactionAlarmBy = async (\n transaction: DurableObjectTransaction,\n deadline: number,\n): Promise<void> => {\n const scheduled = await transaction.getAlarm();\n\n if (scheduled === null || scheduled > deadline) {\n await transaction.setAlarm(deadline);\n }\n};\n\nconst stableExternalWait = (\n snapshot: SubmissionSnapshot,\n reports: ReadonlyMap<string, RecoveryReport>,\n): boolean => {\n const decision = reports.get(snapshot.submissionId)?.decision._tag;\n\n // An accepted abort still owes cleanup/settlement even if its claim was deferred this pass.\n if (decision === \"SettleAborted\") return false;\n switch (snapshot.state) {\n case \"suspended\":\n case \"joined\":\n return true;\n case \"unknown\":\n return decision === \"AwaitUnknownResolution\" || decision === \"MarkUnknown\";\n case \"admitted\":\n return reports.get(snapshot.submissionId)?.decision._tag === \"AwaitParentEstablishment\";\n case \"input-applied\":\n case \"joining\":\n case \"ready\":\n case \"running\":\n case \"settled\":\n case \"terminalizing\":\n return false;\n }\n};\n\n/**\n * Shared prearm/acknowledgement boundary for ingress and runtime-owned producers.\n * `ThreadObject.layer` provides this same instance in its Services. Rebuilt runtime/maintenance\n * Layers must reuse that instance; a second gate cannot observe the native producers' activity.\n */\nexport class ThreadMutationGate extends Context.Service<\n ThreadMutationGate,\n {\n readonly withMutation: <A, E, R>(\n body: Effect.Effect<A, E, R>,\n /**\n * Native admission, approval, abort and unknown resolution keep the default true.\n * Projection/relay/reply receipt-only bookkeeping must use false: its local durable\n * pendingDeadline owns scheduling without creating native recovery debt.\n */\n options?: { readonly invalidatesRecovery: boolean },\n ) => Effect.Effect<A, E | DurableAlarmError, R>;\n readonly withSnapshot: <A, E, R>(\n body: (active: number) => Effect.Effect<A, E, R>,\n ) => Effect.Effect<A, E, R>;\n }\n>()(\"@effect-agent/platform-cloudflare/internal/ThreadMutationGate\") {\n static readonly layer = Layer.effect(this)(\n Effect.gen(function* () {\n const { ctx } = yield* DurableObjectContext;\n const config = yield* CloudflareDurableRuntimeConfig;\n const failpoint = yield* ThreadMaintenanceFailpoint;\n // A fresh incarnation has no live mutations; durable generations survive eviction.\n const activeMutations = yield* Ref.make(0);\n const generationGate = yield* Semaphore.make(1);\n const minimumAlarmDelay = Math.max(1, Math.ceil(config.alarmBackoffBase / 2));\n\n const runTransaction = yield* makeStorageOperation;\n\n const beginMutation = Effect.fn(\"ThreadMaintenance.beginMutation\")(function* (\n invalidatesRecovery: boolean,\n ) {\n yield* failpoint.hit(\"maintenance:dirty:before\");\n const now = yield* Clock.currentTimeMillis;\n\n yield* runTransaction(\"advance maintenance generation\", () =>\n ctx.storage.transaction(async (transaction) => {\n const { state, initialized } = await readMaintenanceState(transaction);\n\n const next = ThreadMaintenanceState.make({\n ...state,\n dirty: state.dirty + (invalidatesRecovery ? 1n : 0n),\n });\n\n if (invalidatesRecovery || !initialized)\n await transaction.put(MAINTENANCE_STATE_KEY, encodeMaintenanceState(next));\n // The earliest configured retry bounds a newly actionable mutation without relying\n // on its best-effort immediate wake hint.\n await ensureTransactionAlarmBy(transaction, now + minimumAlarmDelay);\n }),\n );\n yield* failpoint.hit(\"maintenance:dirty:after\");\n yield* Ref.update(activeMutations, (active) => active + 1);\n });\n\n const endMutation = generationGate.withPermit(\n Ref.update(activeMutations, (active) => Math.max(0, active - 1)),\n );\n\n const withMutation = <A, E, R>(\n body: Effect.Effect<A, E, R>,\n options?: { readonly invalidatesRecovery: boolean },\n ): Effect.Effect<A, E | DurableAlarmError, R> =>\n Effect.acquireUseRelease(\n generationGate.withPermit(beginMutation(options?.invalidatesRecovery ?? true)),\n () =>\n failpoint.hit(\"maintenance:mutation:armed\").pipe(\n Effect.andThen(body),\n Effect.tap(() => failpoint.hit(\"maintenance:mutation:finished\")),\n ),\n () => endMutation,\n );\n\n return ThreadMutationGate.of({\n withMutation,\n withSnapshot: (body) =>\n generationGate.withPermit(Effect.flatMap(Ref.get(activeMutations), body)),\n });\n }),\n );\n}\n\nexport type MaintenancePassFailure =\n | DurableWorkerFailure\n | DurableBindingFailure\n | DurableAlarmError\n | ThreadProjectionError;\n\n/**\n * Incremental, quiescent maintenance over a durable dirty/processed generation (issue #93).\n *\n * `pass` = generation snapshot/pre-arm → recovery → one head Attempt → generation acknowledgement:\n *\n * 1. One storage transaction reads dirty/processed and re-arms before work. A caught-up forced\n * alarm takes an O(1) path without recovery, ledger scans, or canonical-history reads.\n * 2. Recovery strictly precedes a new claim. One head Attempt advances the lane and requests\n * a safe yield after ten minutes. The whole event has a fourteen-minute cooperative timeout.\n * 3. Auxiliary dispatch and listeners belong to the event Scope. After native completion,\n * stop new external waves, join native delivery through its driver-owned Claim deadline,\n * and bound host/backfill work by explicit allowances before closing and joining Scope.\n * Ordinary auxiliary setup failures are reported after the one native opportunity.\n * 4. The final transaction acknowledges only the generation observed at pass start. A racing\n * mutation therefore remains `dirty > processed` and retains its atomically-established alarm.\n * 5. Stable external waits acknowledge and clear. Autonomous retry, indeterminate, and lease\n * recovery states leave their generation dirty and retain bounded backoff rearming.\n */\nexport class ThreadMaintenance extends Context.Service<\n ThreadMaintenance,\n {\n /** One idempotent pass; failures propagate after durably scheduling bounded recovery. */\n readonly pass: Effect.Effect<MaintenancePassReport, MaintenancePassFailure>;\n /**\n * Constructor gate: initialize/inspect only the O(1) maintenance record and ensure a dirty\n * generation has an alarm. It never scans the ledger or canonical history.\n */\n readonly ensureAlarm: Effect.Effect<void, MaintenancePassFailure>;\n /**\n * Serialize the pre-arm boundary with pass acknowledgement, advance the durable dirty\n * generation and arm the alarm in one transaction BEFORE running the caller's mutation.\n * A pass cannot acknowledge while that mutation remains in flight.\n */\n readonly withMutation: <A, E, R>(\n body: Effect.Effect<A, E, R>,\n ) => Effect.Effect<A, E | DurableAlarmError, R>;\n }\n>()(\"@effect-agent/platform-cloudflare/ThreadMaintenance\") {\n static readonly layer: Layer.Layer<\n ThreadMaintenance,\n never,\n | ThreadMutationGate\n | ThreadPublication\n | ThreadProjectionMaintenance\n | DurableAgentRuntime\n | SubmissionLedger\n | DurableAlarmService\n | ThreadMaintenanceFailpoint\n | CloudflareDurableRuntimeConfig\n | DurableObjectContext\n | SqlClient\n > = Layer.effect(ThreadMaintenance)(\n Effect.gen(function* () {\n const runtime = yield* DurableAgentRuntime;\n const ledger = yield* SubmissionLedger;\n const alarm = yield* DurableAlarmService;\n const config = yield* CloudflareDurableRuntimeConfig;\n const { ctx } = yield* DurableObjectContext;\n const failpoint = yield* ThreadMaintenanceFailpoint;\n\n const mutations = yield* ThreadMutationGate;\n const publication = yield* ThreadPublication;\n const projection = yield* ThreadProjectionMaintenance;\n const messages = yield* ThreadMessageDelivery;\n const host = yield* ThreadHostMaintenance;\n\n // A broken disposable index still needs a retry alarm and must not prevent startup.\n const projectionDeadline = projection.pendingDeadline.pipe(\n Effect.catchCauseIf(\n (cause) => !Cause.hasInterrupts(cause),\n (cause) =>\n Effect.logError(\"Thread projection deadline unavailable\", cause).pipe(\n Effect.as(Option.some(0)),\n ),\n ),\n );\n\n const pendingDeadline = Effect.gen(function* () {\n return earliestDeadline(\n earliestDeadline(yield* publication.pendingDeadline, yield* messages.pendingDeadline),\n earliestDeadline(yield* projectionDeadline, yield* host.pendingDeadline),\n );\n });\n\n const maintenancePassGate = yield* Semaphore.make(1);\n const minimumAlarmDelay = Math.max(1, Math.ceil(config.alarmBackoffBase / 2));\n\n const runTransaction = yield* makeStorageOperation;\n\n const ensureAlarm = Effect.fn(\"ThreadMaintenance.ensureAlarm\")(function* () {\n yield* failpoint.hit(\"maintenance:ensure:before\");\n const now = yield* Clock.currentTimeMillis;\n\n const retry = yield* runTransaction(\"ensure maintenance alarm\", () =>\n ctx.storage.transaction(async (transaction) => {\n const { state, initialized } = await readMaintenanceState(transaction);\n\n if (!initialized) {\n await transaction.put(MAINTENANCE_STATE_KEY, encodeMaintenanceState(state));\n }\n if (state.dirty > state.processed) {\n await ensureTransactionAlarmBy(\n transaction,\n state.retry?.generation === state.dirty\n ? Math.max(now + minimumAlarmDelay, state.retry.notBefore)\n : now + config.wakeScanInterval,\n );\n }\n\n return state.retry?.generation === state.dirty ? state.retry : undefined;\n }),\n );\n\n const deadline = yield* pendingDeadline;\n\n if (Option.isSome(deadline)) {\n yield* runTransaction(\"ensure publication alarm\", () =>\n ctx.storage.transaction((transaction) =>\n ensureTransactionAlarmBy(\n transaction,\n Math.max(\n now + minimumAlarmDelay,\n deadline.value <= now && retry !== undefined && !retry.nativeOnly\n ? Math.max(deadline.value, retry.notBefore)\n : deadline.value,\n ),\n ),\n ),\n );\n }\n yield* failpoint.hit(\"maintenance:ensure:after\");\n });\n\n const beginPass = Effect.fn(\"ThreadMaintenance.beginPass\")(function* (observed: {\n generation?: bigint;\n }) {\n yield* failpoint.hit(\"maintenance:begin:before\");\n const now = yield* Clock.currentTimeMillis;\n\n const result = yield* runTransaction(\"begin maintenance pass\", () =>\n ctx.storage.transaction(async (transaction) => {\n const { state, initialized } = await readMaintenanceState(transaction);\n\n observed.generation = state.dirty;\n if (!initialized) {\n await transaction.put(MAINTENANCE_STATE_KEY, encodeMaintenanceState(state));\n }\n const retryAt = state.retry?.generation === state.dirty ? state.retry.notBefore : 0;\n\n // Prearm before recovery or any host hook, including publication-only passes.\n // A completed pass may move this crash fallback later to its bounded retry.\n await ensureTransactionAlarmBy(transaction, now + minimumAlarmDelay);\n if (state.processed >= state.dirty || retryAt > now) {\n return {\n _tag: \"CaughtUp\" as const,\n nonterminal: state.nonterminal,\n };\n }\n\n return {\n _tag: \"Actionable\" as const,\n generation: state.dirty,\n nonterminal: state.nonterminal,\n stalls: state.retry?.generation === state.dirty ? state.retry.stalls : 0,\n };\n }),\n );\n\n yield* failpoint.hit(\"maintenance:begin:after\");\n\n return result;\n });\n\n const backoffDelay = (priorStalls: number, jitter: number) => {\n const backoff = Math.min(\n config.alarmBackoffCap,\n config.alarmBackoffBase * 2 ** Math.min(priorStalls, 30),\n );\n\n // Jitter over [backoff/2, backoff] spreads retries without exceeding the cap.\n return Math.ceil(backoff / 2 + (backoff / 2) * jitter);\n };\n\n const rearmDelay = Effect.fn(\"ThreadMaintenance.rearmDelay\")(function* (\n progressed: boolean,\n priorStalls: number,\n ) {\n return progressed ? config.alarmBackoffBase : backoffDelay(priorStalls, yield* Random.next);\n });\n\n const rearmFailure = Effect.fn(\"ThreadMaintenance.rearmFailure\")(function* (\n observed: MaintenanceObservation,\n ) {\n const { generation, nativeOnly } = observed;\n\n if (generation === undefined) return;\n yield* failpoint.hit(\"maintenance:retry:before\");\n yield* mutations.withSnapshot((active) =>\n Effect.gen(function* () {\n // A failed deadline read must not prevent committing the native retry.\n const deadline = yield* pendingDeadline.pipe(\n Effect.catchCause(() => Effect.succeed(Option.none<number>())),\n );\n\n const now = yield* Clock.currentTimeMillis;\n\n const jitter = yield* Random.next;\n\n yield* runTransaction(\"back off failed maintenance\", () =>\n ctx.storage.transaction(async (transaction) => {\n const { state } = await readMaintenanceState(transaction);\n\n const previous = state.retry?.generation === generation ? state.retry : undefined;\n\n const retry = MaintenanceRetry.make({\n generation,\n notBefore: Math.max(\n previous?.notBefore ?? 0,\n now + backoffDelay(previous?.stalls ?? 0, jitter),\n ),\n nativeOnly,\n stalls: Math.min(30, (previous?.stalls ?? 0) + 1),\n });\n\n await transaction.put(\n MAINTENANCE_STATE_KEY,\n encodeMaintenanceState(ThreadMaintenanceState.make({ ...state, retry })),\n );\n\n // Never postpone a producer that raced the failed observation. Host work\n // retains its own deadline; an early delivery skips native recovery below.\n const nativeDeadline =\n active > 0 || state.dirty !== generation\n ? now + minimumAlarmDelay\n : retry.notBefore;\n\n await transaction.setAlarm(\n Math.max(\n now + minimumAlarmDelay,\n Option.isSome(deadline) && (nativeOnly || deadline.value > now)\n ? Math.min(nativeDeadline, deadline.value)\n : nativeDeadline,\n ),\n );\n }),\n );\n }),\n );\n yield* failpoint.hit(\"maintenance:retry:after\");\n });\n\n const pass = Effect.fn(\"ThreadMaintenance.pass\")(function* (\n yieldAfter: DateTime.Utc,\n dispatchUntil: DateTime.Utc,\n observed: MaintenanceObservation,\n ): Effect.fn.Return<MaintenancePassReport, MaintenancePassFailure, Scope.Scope> {\n const annotate = (report: MaintenancePassReport) =>\n Effect.annotateCurrentSpan({\n phase: report.phase,\n recovered: report.recovered,\n settled: report.settled,\n nonterminal: report.nonterminal,\n alarm: report.alarm,\n }).pipe(Effect.as(report));\n\n const started = yield* mutations.withSnapshot((activeAtStart) =>\n Effect.gen(function* () {\n const generation = yield* beginPass(observed);\n\n if (generation._tag === \"Actionable\" && activeAtStart === 0) {\n // The gate excludes a producer starting between the snapshot and certification.\n yield* publication.prepareGeneration(generation.generation);\n }\n\n return { ...generation, activeAtStart };\n }),\n );\n\n // This scope owns auxiliary dispatch and listeners, independently of source completion.\n // Close it before acknowledgement, including on failure or event interruption.\n const auxiliaryScope = yield* Effect.acquireRelease(Scope.make(\"parallel\"), (scope, exit) =>\n Scope.close(scope, exit),\n );\n\n const sourceFinished = yield* Deferred.make<void>();\n const finished = Deferred.await(sourceFinished);\n\n // Fork setup too: an ordinary auxiliary setup failure is reported after native work,\n // rather than gating its opportunity. Event interruption still closes every fiber.\n const deliveryFiber = yield* Effect.forkIn(\n Scope.provide(auxiliaryScope)(messages.drainUntil(finished, dispatchUntil)),\n auxiliaryScope,\n );\n\n const hostFiber = yield* Effect.forkIn(\n Scope.provide(auxiliaryScope)(\n Effect.gen(function* () {\n yield* Schema.decodeEffect(AuxiliaryDispatchMillis)(host.dispatchTimeoutMillis).pipe(\n Effect.mapError((cause) =>\n DurableAlarmError.make({\n operation: \"host dispatch allowance\",\n message:\n \"Declare an integer whole-wave allowance between 1 and 300000 milliseconds\",\n cause,\n }),\n ),\n );\n yield* host.drainUntil(finished, dispatchUntil);\n }),\n ),\n auxiliaryScope,\n );\n\n // Backfill is one disposable wave; its timer starts beside native execution.\n const backfill = yield* Effect.forkIn(\n drainDue.pipe(\n Effect.provideService(ThreadProjectionMaintenance, projection),\n Effect.timeoutOption(config.projectionDispatchTimeoutMillis),\n ),\n auxiliaryScope,\n );\n\n const finishAuxiliary = Effect.gen(function* () {\n yield* Deferred.succeed(sourceFinished, undefined);\n\n const remaining = Math.max(\n 1,\n DateTime.toEpochMillis(dispatchUntil) - (yield* Clock.currentTimeMillis),\n );\n\n const hostJoin = yield* Effect.forkIn(\n Fiber.join(hostFiber).pipe(\n Effect.timeoutOption(Math.min(host.dispatchTimeoutMillis, remaining)),\n Effect.tap((result) =>\n Effect.annotateCurrentSpan({ \"host.timedOut\": Option.isNone(result) }),\n ),\n ),\n auxiliaryScope,\n );\n\n // Native transport uses the driver's actual Claim deadline, through Retry persistence.\n // Only our host/backfill timers suppress their own interruption. Earlier failed exits,\n // including pure self-interruption, remain failures while siblings are still blocked.\n yield* Fiber.joinAll([deliveryFiber, hostJoin, backfill]);\n yield* Scope.close(auxiliaryScope, Exit.void);\n });\n\n const deadline = yield* publication.pendingDeadline;\n\n if (\n started._tag === \"Actionable\" ||\n (Option.isSome(deadline) && deadline.value <= (yield* Clock.currentTimeMillis))\n ) {\n yield* publication.drain;\n }\n const pending = yield* publication.pendingDeadline;\n\n if (started._tag === \"CaughtUp\" || Option.isSome(pending)) {\n yield* finishAuxiliary;\n yield* failpoint.hit(\"maintenance:finish:before\");\n\n const disposition = yield* mutations.withSnapshot((active) =>\n Effect.gen(function* () {\n // Re-read under the producer gate: a concurrent append/host mutation cannot be\n // cleared using a stale empty deadline. Dirty generations bound all producer races.\n const latest = yield* pendingDeadline;\n const now = yield* Clock.currentTimeMillis;\n\n return yield* runTransaction(\"finish publication pass\", () =>\n ctx.storage.transaction(async (transaction) => {\n const { state } = await readMaintenanceState(transaction);\n\n const nativeDeadline =\n active > 0 || state.dirty > state.processed\n ? state.retry?.generation === state.dirty && active === 0\n ? Math.max(now + minimumAlarmDelay, state.retry.notBefore)\n : now + config.wakeScanInterval\n : Infinity;\n\n const next = Option.isSome(latest)\n ? Math.min(nativeDeadline, latest.value)\n : nativeDeadline;\n\n if (Number.isFinite(next)) {\n await transaction.setAlarm(Math.max(now + minimumAlarmDelay, next));\n\n return \"rearmed\" as const;\n }\n await transaction.deleteAlarm();\n\n return \"cleared\" as const;\n }),\n );\n }),\n );\n\n yield* failpoint.hit(\"maintenance:finish:after\");\n\n return yield* annotate(\n MaintenancePassReport.make({\n phase: \"caught-up\",\n recovered: 0,\n settled: 0,\n nonterminal: started.nonterminal,\n alarm: disposition,\n }),\n );\n }\n // Step 2 — reconciliation strictly precedes new work in this pass (exit gate).\n observed.nativeOnly = true;\n const recovered: ReadonlyArray<RecoveryReport> = yield* runtime.runRecovery;\n const reports = new Map(recovered.map((report) => [report.submissionId, report]));\n const current = yield* Stream.runCollect(ledger.scanNonterminal);\n const heads = new Map<ThreadId, SubmissionSnapshot>();\n\n for (const row of current) {\n if (!heads.has(row.threadId)) heads.set(row.threadId, row);\n }\n\n const eligible = [...heads.values()]\n .filter((head) => !stableExternalWait(head, reports))\n .map((head) => head.threadId)\n .sort();\n\n const selectionTime = yield* Clock.currentTimeMillis;\n\n yield* failpoint.hit(\"maintenance:select:before\");\n\n const selection = yield* runTransaction(\"select maintenance lane\", () =>\n ctx.storage.transaction(async (transaction) => {\n const { state } = await readMaintenanceState(transaction);\n\n const retries = (state.bindingRetries ?? []).filter(\n (retry) => heads.get(retry.threadId)?.submissionId === retry.submissionId,\n );\n\n const runnable = eligible.filter(\n (threadId) =>\n !retries.some(\n (retry) => retry.threadId === threadId && retry.notBefore > selectionTime,\n ),\n );\n\n const next =\n runnable.find(\n (threadId) =>\n state.lastServedThreadId === undefined || threadId > state.lastServedThreadId,\n ) ?? runnable[0];\n\n if (next !== undefined) {\n await transaction.put(\n MAINTENANCE_STATE_KEY,\n encodeMaintenanceState(\n ThreadMaintenanceState.make({ ...state, lastServedThreadId: next }),\n ),\n );\n }\n\n return { selected: next, retries };\n }),\n );\n\n yield* failpoint.hit(\"maintenance:select:after\");\n\n const selected =\n selection.selected === undefined ? undefined : heads.get(selection.selected);\n\n let retries = selection.retries;\n let bindingFailure: DurableBindingFailure | undefined;\n\n // One FIFO head per event. An unavailable contract is a durable wait for compatible code,\n // including for children; other local lanes and host deliveries remain independently due.\n const settlement =\n selected === undefined\n ? Option.none()\n : yield* runtime.processThreadHead(selected.threadId, { yieldAfter }).pipe(\n Effect.catchTag([\"BindingUnavailable\", \"BindingDigestMismatch\"], (failure) => {\n bindingFailure = failure;\n\n return Effect.succeed(Option.none());\n }),\n );\n\n if (selected !== undefined) {\n const previous = retries.find((retry) => retry.submissionId === selected.submissionId);\n let retry: BindingRetry | undefined;\n let reportBindingFailure = false;\n\n if (bindingFailure !== undefined) {\n const now = yield* Clock.currentTimeMillis;\n const attempts = Math.min(30, (previous?.attempts ?? 0) + 1);\n\n reportBindingFailure =\n previous === undefined || now - previous.reportedAt >= 15 * 60_000;\n retry = BindingRetry.make({\n threadId: selected.threadId,\n submissionId: selected.submissionId,\n attempts,\n notBefore: now + Math.min(60_000, 5_000 * 2 ** (attempts - 1)),\n reportedAt: reportBindingFailure ? now : (previous?.reportedAt ?? now),\n });\n }\n if (retry !== undefined || previous !== undefined) {\n // The Attempt released its Claim. Commit its binding wait (or clear) once,\n // before joining fallible auxiliary work. This local fact neither acknowledges\n // a generation nor changes the shared alarm; those require event retirement.\n yield* failpoint.hit(\"maintenance:binding-retry:before\");\n retries = yield* runTransaction(\"record submission binding retry\", () =>\n ctx.storage.transaction(async (transaction) => {\n const { state } = await readMaintenanceState(transaction);\n\n const bindingRetries = [\n ...(state.bindingRetries ?? []).filter(\n (entry) => entry.submissionId !== selected.submissionId,\n ),\n ...(retry === undefined ? [] : [retry]),\n ];\n\n await transaction.put(\n MAINTENANCE_STATE_KEY,\n encodeMaintenanceState(ThreadMaintenanceState.make({ ...state, bindingRetries })),\n );\n\n return bindingRetries;\n }),\n );\n yield* failpoint.hit(\"maintenance:binding-retry:after\");\n }\n if (bindingFailure !== undefined) {\n yield* reportBindingFailure\n ? Effect.logError(\n \"Thread awaits a compatible binding; original work remains pending\",\n Cause.fail(bindingFailure),\n )\n : Effect.logDebug(\"Thread binding retry remains pending\", Cause.fail(bindingFailure));\n }\n }\n\n observed.nativeOnly = false;\n yield* finishAuxiliary;\n const remaining = yield* Stream.runCollect(ledger.scanNonterminal);\n const waitingHeads = new Map<ThreadId, boolean>();\n\n const autonomous = remaining.some((snapshot) => {\n const headWaiting = waitingHeads.get(snapshot.threadId);\n\n if (headWaiting === undefined)\n waitingHeads.set(snapshot.threadId, stableExternalWait(snapshot, reports));\n // FIFO followers cannot execute through a stable external wait. Only plain queued\n // input is dormant here; admission repairs and accepted aborts still need a pass.\n if (\n headWaiting === true &&\n snapshot.state === \"ready\" &&\n reports.get(snapshot.submissionId)?.decision._tag === \"ApplyInput\"\n )\n return false;\n\n return !stableExternalWait(snapshot, reports);\n });\n\n const progressed =\n Option.isSome(settlement) ||\n recovered.some((report) => report.disposition === \"repaired\");\n\n const now = yield* Clock.currentTimeMillis;\n const ordinaryDelay = autonomous ? yield* rearmDelay(progressed, started.stalls) : 0;\n\n const nextEligible = eligible.map(\n (threadId) =>\n retries.find((retry) => retry.submissionId === heads.get(threadId)?.submissionId)\n ?.notBefore ?? now,\n );\n\n const bindingDelay =\n nextEligible.length === 0 ? 0 : Math.max(0, Math.min(...nextEligible) - now);\n\n const delay = Math.max(ordinaryDelay, bindingDelay);\n\n yield* failpoint.hit(\"maintenance:finish:before\");\n\n const alarmDisposition = yield* mutations.withSnapshot((active) =>\n Effect.gen(function* () {\n const publicationDeadline = yield* pendingDeadline;\n\n return yield* runTransaction(\"finish maintenance pass\", () =>\n ctx.storage.transaction(async (transaction) => {\n const { state } = await readMaintenanceState(transaction);\n\n // Autonomous work and in-flight mutations intentionally leave the observed\n // generation dirty. Otherwise acknowledge only the pass-start generation.\n const processed =\n autonomous || started.activeAtStart > 0 || active > 0\n ? state.processed\n : state.processed > started.generation\n ? state.processed\n : started.generation;\n\n const next = ThreadMaintenanceState.make({\n ...Struct.omit(state, [\"retry\"]),\n processed,\n nonterminal: remaining.length,\n bindingRetries: (state.bindingRetries ?? []).filter((retry) =>\n remaining.some((row) => row.submissionId === retry.submissionId),\n ),\n ...(autonomous && !progressed\n ? {\n retry: MaintenanceRetry.make({\n generation: started.generation,\n notBefore: now + delay,\n nativeOnly: true,\n stalls: Math.min(30, started.stalls + 1),\n }),\n }\n : {}),\n });\n\n await transaction.put(MAINTENANCE_STATE_KEY, encodeMaintenanceState(next));\n if (autonomous) {\n // Replace the crash-fallback slot with this pass's bounded backoff. The target\n // is never earlier than the begin-pass fallback, so workerd does not cancel\n // this running alarm handler before its report/span can complete.\n const nativeDeadline =\n started.activeAtStart > 0 || active > 0 || state.dirty !== started.generation\n ? now + minimumAlarmDelay\n : now + delay;\n\n await transaction.setAlarm(\n Option.isSome(publicationDeadline)\n ? Math.max(\n now + minimumAlarmDelay,\n Math.min(nativeDeadline, publicationDeadline.value),\n )\n : nativeDeadline,\n );\n\n return \"rearmed\" as const;\n }\n if (started.activeAtStart > 0 || active > 0 || next.dirty > next.processed) {\n // A mutation overlapped this pass's observation window or raced\n // acknowledgement. It stays dirty and its pre-armed bounded alarm survives;\n // unseen effects are never acknowledged. Do not accelerate that future alarm\n // from inside the current handler: workerd cancels a running handler when it\n // writes an earlier slot.\n await ensureTransactionAlarmBy(\n transaction,\n Option.isSome(publicationDeadline)\n ? Math.max(\n now + minimumAlarmDelay,\n Math.min(now + config.wakeScanInterval, publicationDeadline.value),\n )\n : now + config.wakeScanInterval,\n );\n\n return \"rearmed\" as const;\n }\n if (Option.isSome(publicationDeadline)) {\n await transaction.setAlarm(\n Math.max(now + minimumAlarmDelay, publicationDeadline.value),\n );\n\n return \"rearmed\" as const;\n }\n await transaction.deleteAlarm();\n\n return \"cleared\" as const;\n }),\n );\n }),\n );\n\n yield* failpoint.hit(\"maintenance:finish:after\");\n\n return yield* annotate(\n MaintenancePassReport.make({\n phase: \"actionable\",\n recovered: recovered.length,\n settled: Option.isSome(settlement) ? 1 : 0,\n nonterminal: remaining.length,\n alarm: alarmDisposition,\n }),\n );\n });\n\n return ThreadMaintenance.of({\n // A mid-pass immediate hint is droppable; durable dirty state decides the final alarm.\n pass: Effect.gen(function* () {\n const now = yield* Clock.currentTimeMillis;\n const yieldAfter = DateTime.makeUnsafe(now + 10 * 60_000);\n const dispatchUntil = DateTime.makeUnsafe(now + 14 * 60_000);\n const observed: MaintenanceObservation = { nativeOnly: false };\n\n return yield* alarm.withWakesDeferred(\n maintenancePassGate.withPermit(\n Effect.scoped(pass(yieldAfter, dispatchUntil, observed)).pipe(\n // Close event-owned auxiliary work and release Attempt ownership before\n // failure rearming, while still holding the pass permit.\n Effect.onErrorIf(\n () => true,\n () => rearmFailure(observed),\n ),\n ),\n ),\n );\n }).pipe(\n // Include permit waiting, recovery and acknowledgement in the event deadline.\n // Interruption releases Attempt ownership, leaving the prearmed dirty generation\n // for recovery. It never changes the logical Run duration or settles a policy failure.\n // This cooperative timer cannot preempt synchronous CPU work or stuck finalizers.\n Effect.timeoutOrElse({\n duration: \"14 minutes\",\n orElse: () =>\n DurableAlarmError.make({\n operation: \"maintenance pass deadline\",\n message:\n \"The maintenance event exceeded its 14 minute deadline; durable recovery remains pending\",\n }),\n }),\n ),\n ensureAlarm: mutations.withSnapshot(() => ensureAlarm()),\n withMutation: (body) =>\n mutations.withMutation(\n body.pipe(\n Effect.tap(() =>\n publishCommitted.pipe(Effect.provideService(ThreadPublication, publication)),\n ),\n ),\n ),\n });\n }),\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Alarm.mjs","names":[],"sources":["../src/Alarm.ts"],"sourcesContent":["import {\n Cause,\n Clock,\n Context,\n DateTime,\n Deferred,\n Effect,\n Exit,\n Fiber,\n Layer,\n Option,\n Random,\n Ref,\n Schema,\n Scope,\n Semaphore,\n Stream,\n Struct,\n} from \"effect\";\nimport { type DurableBindingFailure } from \"effect-agent/agent-registration\";\nimport {\n DurableAgentRuntime,\n type DurableWorkerFailure,\n type RecoveryReport,\n} from \"effect-agent/durable-agent-runtime\";\nimport { ThreadId, SubmissionId } from \"effect-agent/identifiers\";\nimport { SubmissionLedger, type SubmissionSnapshot } from \"effect-agent/submission-ledger\";\nimport {\n ThreadProjectionMaintenance,\n drainDue,\n type ThreadProjectionError,\n} from \"effect-agent/thread-projection-maintenance\";\nimport { SqlClient } from \"effect/unstable/sql/SqlClient\";\n\nimport { DurableObjectContext } from \"./CloudflareBindings.ts\";\nimport { AuxiliaryDispatchMillis, CloudflareDurableRuntimeConfig } from \"./CloudflareConfig.ts\";\nimport { safeCauseMessage } from \"./internal/boundary.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): every committed actionable mutation carries a newer durable\n * maintenance generation and a committed alarm. Stable externally-driven waits may be\n * nonterminal without retaining an alarm; their resolving mutation advances the generation and\n * restores the alarm atomically.\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: safeCauseMessage(cause, \"The Cloudflare alarm API failed without a diagnostic\"),\n cause,\n });\n\n// SQL and raw KV/alarm operations share one physical SQLite transaction. Reserve its\n// connection for each short storage operation, never around a mutation or snapshot body.\nconst makeStorageOperation = Effect.map(\n SqlClient,\n (sql) =>\n <A>(operation: string, execute: () => Promise<A>) =>\n Effect.flatMap(Effect.serviceOption(sql.transactionService), (current) => {\n const body = Effect.uninterruptible(\n Effect.tryPromise({ try: execute, catch: alarmFailure(operation) }),\n );\n\n return current._tag === \"Some\"\n ? body\n : Effect.scoped(\n Effect.andThen(sql.reserve.pipe(Effect.mapError(alarmFailure(operation))), body),\n );\n }),\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). The pass's durable generation check observes any racing mutation, so the\n * in-memory hint does not need to be flushed after a stable wait is acknowledged.\n */\n readonly scheduleNow: Effect.Effect<void, DurableAlarmError>;\n /**\n * Run one maintenance pass with wake deferral (see `scheduleNow`). Calls made while `body`\n * executes are droppable promptness hints; correctness rests on the durable generation.\n */\n readonly withWakesDeferred: <A, E, R>(body: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R>;\n /** Clear the slot; correctness-sensitive clears live in maintenance generation transactions. */\n readonly cancel: Effect.Effect<void, DurableAlarmError>;\n }\n>()(\"@effect-agent/platform-cloudflare/DurableAlarmService\") {\n static readonly layer: Layer.Layer<DurableAlarmService, never, DurableObjectContext | SqlClient> =\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\n const storageOperation = yield* makeStorageOperation;\n\n const scheduled = storageOperation(\"get alarm\", () => ctx.storage.getAlarm()).pipe(\n Effect.map((deadline) =>\n deadline === null ? Option.none<number>() : Option.some(deadline),\n ),\n );\n\n const scheduleAt = (epochMillis: number) =>\n storageOperation(\"set alarm\", () => ctx.storage.setAlarm(epochMillis));\n\n const ensureScheduledBy = (epochMillis: number) =>\n storageOperation(\"ensure alarm\", () =>\n ctx.storage.transaction(async (transaction) => {\n const existing = await transaction.getAlarm();\n\n if (existing === null || existing > epochMillis) {\n await transaction.setAlarm(epochMillis);\n }\n }),\n );\n\n const armNow = Clock.currentTimeMillis.pipe(\n Effect.flatMap((now) => ensureScheduledBy(now)),\n );\n\n const scheduleNow = Ref.get(runningPasses).pipe(\n Effect.flatMap((passes) => (passes > 0 ? Effect.void : armNow)),\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(Ref.update(runningPasses, (passes) => passes - 1)),\n );\n\n const cancel = storageOperation(\"delete alarm\", () => ctx.storage.deleteAlarm());\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 /** `caught-up` ran no runtime work (publication may be pending); `actionable` ran recovery. */\n phase: Schema.Literals([\"caught-up\", \"actionable\"]),\n /** Recovery decisions executed (or deferred) BEFORE any new claim in this pass. */\n recovered: Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)),\n /** Whether the head Attempt settled. Joined input may settle with that head. */\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` for dirty/autonomous work, `cleared` for stable waits or settlement. */\n alarm: Schema.Literals([\"rearmed\", \"cleared\"]),\n}) {}\n\n/** Fault boundaries around every maintenance-owned durable mutation. */\nexport type ThreadMaintenanceFailpointLocation =\n | \"maintenance:dirty:before\"\n | \"maintenance:dirty:after\"\n | \"maintenance:mutation:armed\"\n | \"maintenance:mutation:finished\"\n | \"maintenance:ensure:before\"\n | \"maintenance:ensure:after\"\n | \"maintenance:begin:before\"\n | \"maintenance:begin:after\"\n | \"maintenance:select:before\"\n | \"maintenance:select:after\"\n | \"maintenance:binding-retry:before\"\n | \"maintenance:binding-retry:after\"\n | \"maintenance:retry:before\"\n | \"maintenance:retry:after\"\n | \"maintenance:finish:before\"\n | \"maintenance:finish:after\";\n\nexport type ThreadMaintenanceFailpointHandler = (\n location: ThreadMaintenanceFailpointLocation,\n) => Effect.Effect<void>;\n\n/** Test-only fault authority; production uses the inert layer. */\nexport class ThreadMaintenanceFailpoint extends Context.Service<\n ThreadMaintenanceFailpoint,\n {\n readonly hit: ThreadMaintenanceFailpointHandler;\n }\n>()(\"@effect-agent/platform-cloudflare/ThreadMaintenanceFailpoint\") {\n static readonly layer = Layer.succeed(this)({ hit: () => Effect.void });\n}\n\n/**\n * Durable host publication of canonical records and ledger approval/abort/resolution intents.\n * The host owns schema-versioned cursors, destination idempotency and acknowledgement. Delivery\n * is at least once. Hooks must not write the alarm slot or mutate the supplied raw source ports.\n *\n * `invalidate`, `prepareGeneration` and `pendingDeadline` must be bounded local operations.\n * `prepareGeneration` durably invalidates a scan only when its generation changes; repeated\n * calls must preserve partial scan progress. It runs with no source mutation in flight.\n * Use this gate only for publication required before dependent native execution. Independent\n * UI relays and outboxes belong to ThreadHostMaintenance.\n * `drain` performs bounded delivery and persists retries before returning. A pending deadline\n * defers runtime recovery/Attempts, allowing committed host publications to drain first.\n * Unexpected hook failures leave the prearmed generation for retry. Hooks acquire per-call\n * resources with Effect.scoped; Layer construction owns incarnation resources (eviction need\n * not run finalizers). Do not hold a local hook behind network I/O or call back into producers.\n */\nexport interface ThreadPublicationService {\n readonly invalidate: Effect.Effect<void, DurableAlarmError>;\n readonly prepareGeneration: (generation: bigint) => Effect.Effect<void, DurableAlarmError>;\n readonly drain: Effect.Effect<void, DurableAlarmError>;\n readonly pendingDeadline: Effect.Effect<Option.Option<number>, DurableAlarmError>;\n}\n\n/** Opt in with `ThreadObject.layer(registrations, { publication: Layer.effect(ThreadPublication)(...) })`. */\nexport class ThreadPublication extends Context.Service<\n ThreadPublication,\n ThreadPublicationService\n>()(\"@effect-agent/platform-cloudflare/ThreadPublication\") {\n static readonly layer = Layer.succeed(this)({\n invalidate: Effect.void,\n prepareGeneration: () => Effect.void,\n drain: Effect.void,\n pendingDeadline: Effect.succeed(Option.none()),\n });\n}\n\n/**\n * Host-assembled native message recovery. The driver bounds each actual Claim and persists its\n * timeout/retry before this pump returns. Do not add a second timer starting at batch selection:\n * local Claim setup may take time, and expiration still owes the driver's local retry commit.\n */\nexport const ThreadMessageDelivery = Context.Reference<{\n readonly drainUntil: (\n sourceFinished: Effect.Effect<void>,\n dispatchUntil: DateTime.Utc,\n ) => Effect.Effect<void, DurableAlarmError, Scope.Scope>;\n readonly pendingDeadline: Effect.Effect<Option.Option<number>, DurableAlarmError>;\n}>(\"@effect-agent/platform-cloudflare/ThreadMessageDelivery\", {\n defaultValue: () => ({\n drainUntil: () => Effect.void,\n pendingDeadline: Effect.succeed(Option.none()),\n }),\n});\n\n/**\n * Application obligations sharing this Object's alarm. Admit one initial external wave even on\n * a caught-up pass, then respond to wakes while native work runs. sourceFinished closes only\n * admission of NEW external waves. Keep local admission/hub subscriptions in the supplied event\n * Scope until maintenance tears it down; do not scope them to sourceFinished or to this Effect.\n * No deadline sleeps or automatic retry loops. Return after already-admitted waves finish.\n *\n * Declare a finite whole-wave allowance (1..300000ms): maximum for parallel lanes, sum for\n * sequential operations. Admit a wave only if its allowance fits before dispatchUntil. Later\n * arrivals cannot renew the retirement window. Maintenance bounds the join after sourceFinished,\n * interrupts and joins event Scope, then reads local deadlines under the mutation gate.\n *\n * Setup and pendingDeadline are bounded local operations. Persist claims/envelopes before\n * dispatch; interrupted waits leave exact retries/receipts recoverable. Cancellation is local,\n * not remote rollback. Retry accounting is unchanged. Network waits/finalizers must be\n * interruptible; short local atomic commits may be uninterruptible. Hooks never write the raw\n * alarm slot. Required native publication gates belong to ThreadPublication.\n */\nexport const ThreadHostMaintenance = Context.Reference<{\n readonly dispatchTimeoutMillis: number;\n readonly drainUntil: (\n sourceFinished: Effect.Effect<void>,\n dispatchUntil: DateTime.Utc,\n ) => Effect.Effect<void, DurableAlarmError, Scope.Scope>;\n readonly pendingDeadline: Effect.Effect<Option.Option<number>, DurableAlarmError>;\n}>(\"@effect-agent/platform-cloudflare/ThreadHostMaintenance\", {\n defaultValue: () => ({\n dispatchTimeoutMillis: 1,\n drainUntil: () => Effect.void,\n pendingDeadline: Effect.succeed(Option.none()),\n }),\n});\n\nconst earliestDeadline = (\n left: Option.Option<number>,\n right: Option.Option<number>,\n): Option.Option<number> =>\n Option.isSome(left)\n ? Option.isSome(right)\n ? Option.some(Math.min(left.value, right.value))\n : left\n : right;\n\n/** @internal A committed source operation must not become a failed operation because delivery failed. */\nexport const publishCommitted = Effect.gen(function* () {\n const publication = yield* ThreadPublication;\n\n yield* publication.invalidate.pipe(Effect.andThen(publication.drain));\n}).pipe(\n Effect.catchCause((cause) =>\n Cause.hasInterrupts(cause)\n ? Effect.interrupt\n : Effect.logError(\"Thread publication deferred after source commit\", cause),\n ),\n);\n\nconst MaintenanceGeneration = Schema.BigIntFromString.check(\n Schema.isGreaterThanOrEqualToBigInt(0n),\n);\n\nclass BindingRetry extends Schema.Class<BindingRetry>(\"BindingRetry\")({\n threadId: ThreadId,\n submissionId: SubmissionId,\n attempts: Schema.Natural,\n notBefore: Schema.Finite,\n reportedAt: Schema.Finite,\n}) {}\n\ninterface MaintenanceObservation {\n generation?: bigint;\n nativeOnly: boolean;\n}\n\nclass MaintenanceRetry extends Schema.Class<MaintenanceRetry>(\"MaintenanceRetry\")({\n generation: MaintenanceGeneration,\n notBefore: Schema.Finite,\n nativeOnly: Schema.Boolean,\n stalls: Schema.Int.check(Schema.isGreaterThanOrEqualTo(0), Schema.isLessThanOrEqualTo(30)),\n}) {}\n\n/** Versioned, platform-private maintenance state stored through Durable Object KV. */\nclass ThreadMaintenanceState extends Schema.Class<ThreadMaintenanceState>(\n \"@effect-agent/platform-cloudflare/ThreadMaintenanceState\",\n)({\n schemaVersion: Schema.Literal(1),\n dirty: MaintenanceGeneration,\n processed: MaintenanceGeneration,\n nonterminal: Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)),\n /** One physical-owner cursor; old single-lane records need no conversion. */\n lastServedThreadId: Schema.optionalKey(ThreadId),\n bindingRetries: Schema.optionalKey(Schema.Array(BindingRetry)),\n /** Absent on older records. A newer mutation makes this retry obsolete. */\n retry: Schema.optionalKey(MaintenanceRetry),\n}) {}\n\nconst MAINTENANCE_STATE_KEY = \"effect-agent:thread-maintenance:v1\";\nconst decodeMaintenanceState = Schema.decodeUnknownSync(ThreadMaintenanceState);\nconst encodeMaintenanceState = Schema.encodeSync(ThreadMaintenanceState);\n\nconst initialMaintenanceState = (): ThreadMaintenanceState =>\n ThreadMaintenanceState.make({\n schemaVersion: 1,\n // Bootstrap Objects created by the pre-generation release without scanning the ledger in\n // the constructor. One useful pass classifies and acknowledges any existing obligation.\n dirty: 1n,\n processed: 0n,\n nonterminal: 0,\n });\n\nconst readMaintenanceState = async (\n transaction: DurableObjectTransaction,\n): Promise<{ readonly state: ThreadMaintenanceState; readonly initialized: boolean }> => {\n const encoded = await transaction.get(MAINTENANCE_STATE_KEY);\n\n return encoded === undefined\n ? { state: initialMaintenanceState(), initialized: false }\n : { state: decodeMaintenanceState(encoded), initialized: true };\n};\n\nconst ensureTransactionAlarmBy = async (\n transaction: DurableObjectTransaction,\n deadline: number,\n): Promise<void> => {\n const scheduled = await transaction.getAlarm();\n\n if (scheduled === null || scheduled > deadline) {\n await transaction.setAlarm(deadline);\n }\n};\n\nconst stableExternalWait = (\n snapshot: SubmissionSnapshot,\n reports: ReadonlyMap<string, RecoveryReport>,\n): boolean => {\n const report = reports.get(snapshot.submissionId);\n const decision = report?.decision._tag;\n\n // An accepted abort still owes cleanup/settlement even if its claim was deferred this pass.\n if (decision === \"SettleAborted\") return false;\n switch (snapshot.state) {\n case \"suspended\":\n case \"joined\":\n return true;\n case \"unknown\":\n return report?.disposition === \"unknown\";\n case \"admitted\":\n return reports.get(snapshot.submissionId)?.decision._tag === \"AwaitParentEstablishment\";\n case \"input-applied\":\n case \"joining\":\n case \"ready\":\n case \"running\":\n case \"settled\":\n case \"terminalizing\":\n return false;\n }\n};\n\n/**\n * Shared prearm/acknowledgement boundary for ingress and runtime-owned producers.\n * `ThreadObject.layer` provides this same instance in its Services. Rebuilt runtime/maintenance\n * Layers must reuse that instance; a second gate cannot observe the native producers' activity.\n */\nexport class ThreadMutationGate extends Context.Service<\n ThreadMutationGate,\n {\n readonly withMutation: <A, E, R>(\n body: Effect.Effect<A, E, R>,\n /**\n * Native admission, approval, abort and unknown resolution keep the default true.\n * Projection/relay/reply receipt-only bookkeeping must use false: its local durable\n * pendingDeadline owns scheduling without creating native recovery debt.\n */\n options?: { readonly invalidatesRecovery: boolean },\n ) => Effect.Effect<A, E | DurableAlarmError, R>;\n readonly withSnapshot: <A, E, R>(\n body: (active: number) => Effect.Effect<A, E, R>,\n ) => Effect.Effect<A, E, R>;\n }\n>()(\"@effect-agent/platform-cloudflare/internal/ThreadMutationGate\") {\n static readonly layer = Layer.effect(this)(\n Effect.gen(function* () {\n const { ctx } = yield* DurableObjectContext;\n const config = yield* CloudflareDurableRuntimeConfig;\n const failpoint = yield* ThreadMaintenanceFailpoint;\n // A fresh incarnation has no live mutations; durable generations survive eviction.\n const activeMutations = yield* Ref.make(0);\n const generationGate = yield* Semaphore.make(1);\n const minimumAlarmDelay = Math.max(1, Math.ceil(config.alarmBackoffBase / 2));\n\n const runTransaction = yield* makeStorageOperation;\n\n const beginMutation = Effect.fn(\"ThreadMaintenance.beginMutation\")(function* (\n invalidatesRecovery: boolean,\n ) {\n yield* failpoint.hit(\"maintenance:dirty:before\");\n const now = yield* Clock.currentTimeMillis;\n\n yield* runTransaction(\"advance maintenance generation\", () =>\n ctx.storage.transaction(async (transaction) => {\n const { state, initialized } = await readMaintenanceState(transaction);\n\n const next = ThreadMaintenanceState.make({\n ...state,\n dirty: state.dirty + (invalidatesRecovery ? 1n : 0n),\n });\n\n if (invalidatesRecovery || !initialized)\n await transaction.put(MAINTENANCE_STATE_KEY, encodeMaintenanceState(next));\n // The earliest configured retry bounds a newly actionable mutation without relying\n // on its best-effort immediate wake hint.\n await ensureTransactionAlarmBy(transaction, now + minimumAlarmDelay);\n }),\n );\n yield* failpoint.hit(\"maintenance:dirty:after\");\n yield* Ref.update(activeMutations, (active) => active + 1);\n });\n\n const endMutation = generationGate.withPermit(\n Ref.update(activeMutations, (active) => Math.max(0, active - 1)),\n );\n\n const withMutation = <A, E, R>(\n body: Effect.Effect<A, E, R>,\n options?: { readonly invalidatesRecovery: boolean },\n ): Effect.Effect<A, E | DurableAlarmError, R> =>\n Effect.acquireUseRelease(\n generationGate.withPermit(beginMutation(options?.invalidatesRecovery ?? true)),\n () =>\n failpoint.hit(\"maintenance:mutation:armed\").pipe(\n Effect.andThen(body),\n Effect.tap(() => failpoint.hit(\"maintenance:mutation:finished\")),\n ),\n () => endMutation,\n );\n\n return ThreadMutationGate.of({\n withMutation,\n withSnapshot: (body) =>\n generationGate.withPermit(Effect.flatMap(Ref.get(activeMutations), body)),\n });\n }),\n );\n}\n\nexport type MaintenancePassFailure =\n | DurableWorkerFailure\n | DurableBindingFailure\n | DurableAlarmError\n | ThreadProjectionError;\n\n/**\n * Incremental, quiescent maintenance over a durable dirty/processed generation (issue #93).\n *\n * `pass` = generation snapshot/pre-arm → recovery → one head Attempt → generation acknowledgement:\n *\n * 1. One storage transaction reads dirty/processed and re-arms before work. A caught-up forced\n * alarm takes an O(1) path without recovery, ledger scans, or canonical-history reads.\n * 2. Recovery strictly precedes a new claim. One head Attempt advances the lane and requests\n * a safe yield after ten minutes. The whole event has a fourteen-minute cooperative timeout.\n * 3. Auxiliary dispatch and listeners belong to the event Scope. After native completion,\n * stop new external waves, join native delivery through its driver-owned Claim deadline,\n * and bound host/backfill work by explicit allowances before closing and joining Scope.\n * Ordinary auxiliary setup failures are reported after the one native opportunity.\n * 4. The final transaction acknowledges only the generation observed at pass start. A racing\n * mutation therefore remains `dirty > processed` and retains its atomically-established alarm.\n * 5. Stable external waits acknowledge and clear. Autonomous retry, indeterminate, and lease\n * recovery states leave their generation dirty and retain bounded backoff rearming.\n */\nexport class ThreadMaintenance extends Context.Service<\n ThreadMaintenance,\n {\n /** One idempotent pass; failures propagate after durably scheduling bounded recovery. */\n readonly pass: Effect.Effect<MaintenancePassReport, MaintenancePassFailure>;\n /**\n * Constructor gate: initialize/inspect only the O(1) maintenance record and ensure a dirty\n * generation has an alarm. It never scans the ledger or canonical history.\n */\n readonly ensureAlarm: Effect.Effect<void, MaintenancePassFailure>;\n /**\n * Serialize the pre-arm boundary with pass acknowledgement, advance the durable dirty\n * generation and arm the alarm in one transaction BEFORE running the caller's mutation.\n * A pass cannot acknowledge while that mutation remains in flight.\n */\n readonly withMutation: <A, E, R>(\n body: Effect.Effect<A, E, R>,\n ) => Effect.Effect<A, E | DurableAlarmError, R>;\n }\n>()(\"@effect-agent/platform-cloudflare/ThreadMaintenance\") {\n static readonly layer: Layer.Layer<\n ThreadMaintenance,\n never,\n | ThreadMutationGate\n | ThreadPublication\n | ThreadProjectionMaintenance\n | DurableAgentRuntime\n | SubmissionLedger\n | DurableAlarmService\n | ThreadMaintenanceFailpoint\n | CloudflareDurableRuntimeConfig\n | DurableObjectContext\n | SqlClient\n > = Layer.effect(ThreadMaintenance)(\n Effect.gen(function* () {\n const runtime = yield* DurableAgentRuntime;\n const ledger = yield* SubmissionLedger;\n const alarm = yield* DurableAlarmService;\n const config = yield* CloudflareDurableRuntimeConfig;\n const { ctx } = yield* DurableObjectContext;\n const failpoint = yield* ThreadMaintenanceFailpoint;\n\n const mutations = yield* ThreadMutationGate;\n const publication = yield* ThreadPublication;\n const projection = yield* ThreadProjectionMaintenance;\n const messages = yield* ThreadMessageDelivery;\n const host = yield* ThreadHostMaintenance;\n\n // A broken disposable index still needs a retry alarm and must not prevent startup.\n const projectionDeadline = projection.pendingDeadline.pipe(\n Effect.catchCauseIf(\n (cause) => !Cause.hasInterrupts(cause),\n (cause) =>\n Effect.logError(\"Thread projection deadline unavailable\", cause).pipe(\n Effect.as(Option.some(0)),\n ),\n ),\n );\n\n const pendingDeadline = Effect.gen(function* () {\n return earliestDeadline(\n earliestDeadline(yield* publication.pendingDeadline, yield* messages.pendingDeadline),\n earliestDeadline(yield* projectionDeadline, yield* host.pendingDeadline),\n );\n });\n\n const maintenancePassGate = yield* Semaphore.make(1);\n const minimumAlarmDelay = Math.max(1, Math.ceil(config.alarmBackoffBase / 2));\n\n const runTransaction = yield* makeStorageOperation;\n\n const ensureAlarm = Effect.fn(\"ThreadMaintenance.ensureAlarm\")(function* () {\n yield* failpoint.hit(\"maintenance:ensure:before\");\n const now = yield* Clock.currentTimeMillis;\n\n const retry = yield* runTransaction(\"ensure maintenance alarm\", () =>\n ctx.storage.transaction(async (transaction) => {\n const { state, initialized } = await readMaintenanceState(transaction);\n\n if (!initialized) {\n await transaction.put(MAINTENANCE_STATE_KEY, encodeMaintenanceState(state));\n }\n if (state.dirty > state.processed) {\n await ensureTransactionAlarmBy(\n transaction,\n state.retry?.generation === state.dirty\n ? Math.max(now + minimumAlarmDelay, state.retry.notBefore)\n : now + config.wakeScanInterval,\n );\n }\n\n return state.retry?.generation === state.dirty ? state.retry : undefined;\n }),\n );\n\n const deadline = yield* pendingDeadline;\n\n if (Option.isSome(deadline)) {\n yield* runTransaction(\"ensure publication alarm\", () =>\n ctx.storage.transaction((transaction) =>\n ensureTransactionAlarmBy(\n transaction,\n Math.max(\n now + minimumAlarmDelay,\n deadline.value <= now && retry !== undefined && !retry.nativeOnly\n ? Math.max(deadline.value, retry.notBefore)\n : deadline.value,\n ),\n ),\n ),\n );\n }\n yield* failpoint.hit(\"maintenance:ensure:after\");\n });\n\n const beginPass = Effect.fn(\"ThreadMaintenance.beginPass\")(function* (observed: {\n generation?: bigint;\n }) {\n yield* failpoint.hit(\"maintenance:begin:before\");\n const now = yield* Clock.currentTimeMillis;\n\n const result = yield* runTransaction(\"begin maintenance pass\", () =>\n ctx.storage.transaction(async (transaction) => {\n const { state, initialized } = await readMaintenanceState(transaction);\n\n observed.generation = state.dirty;\n if (!initialized) {\n await transaction.put(MAINTENANCE_STATE_KEY, encodeMaintenanceState(state));\n }\n const retryAt = state.retry?.generation === state.dirty ? state.retry.notBefore : 0;\n\n // Prearm before recovery or any host hook, including publication-only passes.\n // A completed pass may move this crash fallback later to its bounded retry.\n await ensureTransactionAlarmBy(transaction, now + minimumAlarmDelay);\n if (state.processed >= state.dirty || retryAt > now) {\n return {\n _tag: \"CaughtUp\" as const,\n nonterminal: state.nonterminal,\n };\n }\n\n return {\n _tag: \"Actionable\" as const,\n generation: state.dirty,\n nonterminal: state.nonterminal,\n stalls: state.retry?.generation === state.dirty ? state.retry.stalls : 0,\n };\n }),\n );\n\n yield* failpoint.hit(\"maintenance:begin:after\");\n\n return result;\n });\n\n const backoffDelay = (priorStalls: number, jitter: number) => {\n const backoff = Math.min(\n config.alarmBackoffCap,\n config.alarmBackoffBase * 2 ** Math.min(priorStalls, 30),\n );\n\n // Jitter over [backoff/2, backoff] spreads retries without exceeding the cap.\n return Math.ceil(backoff / 2 + (backoff / 2) * jitter);\n };\n\n const rearmDelay = Effect.fn(\"ThreadMaintenance.rearmDelay\")(function* (\n progressed: boolean,\n priorStalls: number,\n ) {\n return progressed ? config.alarmBackoffBase : backoffDelay(priorStalls, yield* Random.next);\n });\n\n const rearmFailure = Effect.fn(\"ThreadMaintenance.rearmFailure\")(function* (\n observed: MaintenanceObservation,\n ) {\n const { generation, nativeOnly } = observed;\n\n if (generation === undefined) return;\n yield* failpoint.hit(\"maintenance:retry:before\");\n yield* mutations.withSnapshot((active) =>\n Effect.gen(function* () {\n // A failed deadline read must not prevent committing the native retry.\n const deadline = yield* pendingDeadline.pipe(\n Effect.catchCause(() => Effect.succeed(Option.none<number>())),\n );\n\n const now = yield* Clock.currentTimeMillis;\n\n const jitter = yield* Random.next;\n\n yield* runTransaction(\"back off failed maintenance\", () =>\n ctx.storage.transaction(async (transaction) => {\n const { state } = await readMaintenanceState(transaction);\n\n const previous = state.retry?.generation === generation ? state.retry : undefined;\n\n const retry = MaintenanceRetry.make({\n generation,\n notBefore: Math.max(\n previous?.notBefore ?? 0,\n now + backoffDelay(previous?.stalls ?? 0, jitter),\n ),\n nativeOnly,\n stalls: Math.min(30, (previous?.stalls ?? 0) + 1),\n });\n\n await transaction.put(\n MAINTENANCE_STATE_KEY,\n encodeMaintenanceState(ThreadMaintenanceState.make({ ...state, retry })),\n );\n\n // Never postpone a producer that raced the failed observation. Host work\n // retains its own deadline; an early delivery skips native recovery below.\n const nativeDeadline =\n active > 0 || state.dirty !== generation\n ? now + minimumAlarmDelay\n : retry.notBefore;\n\n await transaction.setAlarm(\n Math.max(\n now + minimumAlarmDelay,\n Option.isSome(deadline) && (nativeOnly || deadline.value > now)\n ? Math.min(nativeDeadline, deadline.value)\n : nativeDeadline,\n ),\n );\n }),\n );\n }),\n );\n yield* failpoint.hit(\"maintenance:retry:after\");\n });\n\n const pass = Effect.fn(\"ThreadMaintenance.pass\")(function* (\n yieldAfter: DateTime.Utc,\n dispatchUntil: DateTime.Utc,\n observed: MaintenanceObservation,\n ): Effect.fn.Return<MaintenancePassReport, MaintenancePassFailure, Scope.Scope> {\n const annotate = (report: MaintenancePassReport) =>\n Effect.annotateCurrentSpan({\n phase: report.phase,\n recovered: report.recovered,\n settled: report.settled,\n nonterminal: report.nonterminal,\n alarm: report.alarm,\n }).pipe(Effect.as(report));\n\n const started = yield* mutations.withSnapshot((activeAtStart) =>\n Effect.gen(function* () {\n const generation = yield* beginPass(observed);\n\n if (generation._tag === \"Actionable\" && activeAtStart === 0) {\n // The gate excludes a producer starting between the snapshot and certification.\n yield* publication.prepareGeneration(generation.generation);\n }\n\n return { ...generation, activeAtStart };\n }),\n );\n\n // This scope owns auxiliary dispatch and listeners, independently of source completion.\n // Close it before acknowledgement, including on failure or event interruption.\n const auxiliaryScope = yield* Effect.acquireRelease(Scope.make(\"parallel\"), (scope, exit) =>\n Scope.close(scope, exit),\n );\n\n const sourceFinished = yield* Deferred.make<void>();\n const finished = Deferred.await(sourceFinished);\n\n // Fork setup too: an ordinary auxiliary setup failure is reported after native work,\n // rather than gating its opportunity. Event interruption still closes every fiber.\n const deliveryFiber = yield* Effect.forkIn(\n Scope.provide(auxiliaryScope)(messages.drainUntil(finished, dispatchUntil)),\n auxiliaryScope,\n );\n\n const hostFiber = yield* Effect.forkIn(\n Scope.provide(auxiliaryScope)(\n Effect.gen(function* () {\n yield* Schema.decodeEffect(AuxiliaryDispatchMillis)(host.dispatchTimeoutMillis).pipe(\n Effect.mapError((cause) =>\n DurableAlarmError.make({\n operation: \"host dispatch allowance\",\n message:\n \"Declare an integer whole-wave allowance between 1 and 300000 milliseconds\",\n cause,\n }),\n ),\n );\n yield* host.drainUntil(finished, dispatchUntil);\n }),\n ),\n auxiliaryScope,\n );\n\n // Backfill is one disposable wave; its timer starts beside native execution.\n const backfill = yield* Effect.forkIn(\n drainDue.pipe(\n Effect.provideService(ThreadProjectionMaintenance, projection),\n Effect.timeoutOption(config.projectionDispatchTimeoutMillis),\n ),\n auxiliaryScope,\n );\n\n const finishAuxiliary = Effect.gen(function* () {\n yield* Deferred.succeed(sourceFinished, undefined);\n\n const remaining = Math.max(\n 1,\n DateTime.toEpochMillis(dispatchUntil) - (yield* Clock.currentTimeMillis),\n );\n\n const hostJoin = yield* Effect.forkIn(\n Fiber.join(hostFiber).pipe(\n Effect.timeoutOption(Math.min(host.dispatchTimeoutMillis, remaining)),\n Effect.tap((result) =>\n Effect.annotateCurrentSpan({ \"host.timedOut\": Option.isNone(result) }),\n ),\n ),\n auxiliaryScope,\n );\n\n // Native transport uses the driver's actual Claim deadline, through Retry persistence.\n // Only our host/backfill timers suppress their own interruption. Earlier failed exits,\n // including pure self-interruption, remain failures while siblings are still blocked.\n yield* Fiber.joinAll([deliveryFiber, hostJoin, backfill]);\n yield* Scope.close(auxiliaryScope, Exit.void);\n });\n\n const deadline = yield* publication.pendingDeadline;\n\n if (\n started._tag === \"Actionable\" ||\n (Option.isSome(deadline) && deadline.value <= (yield* Clock.currentTimeMillis))\n ) {\n yield* publication.drain;\n }\n const pending = yield* publication.pendingDeadline;\n\n if (started._tag === \"CaughtUp\" || Option.isSome(pending)) {\n yield* finishAuxiliary;\n yield* failpoint.hit(\"maintenance:finish:before\");\n\n const disposition = yield* mutations.withSnapshot((active) =>\n Effect.gen(function* () {\n // Re-read under the producer gate: a concurrent append/host mutation cannot be\n // cleared using a stale empty deadline. Dirty generations bound all producer races.\n const latest = yield* pendingDeadline;\n const now = yield* Clock.currentTimeMillis;\n\n return yield* runTransaction(\"finish publication pass\", () =>\n ctx.storage.transaction(async (transaction) => {\n const { state } = await readMaintenanceState(transaction);\n\n const nativeDeadline =\n active > 0 || state.dirty > state.processed\n ? state.retry?.generation === state.dirty && active === 0\n ? Math.max(now + minimumAlarmDelay, state.retry.notBefore)\n : now + config.wakeScanInterval\n : Infinity;\n\n const next = Option.isSome(latest)\n ? Math.min(nativeDeadline, latest.value)\n : nativeDeadline;\n\n if (Number.isFinite(next)) {\n await transaction.setAlarm(Math.max(now + minimumAlarmDelay, next));\n\n return \"rearmed\" as const;\n }\n await transaction.deleteAlarm();\n\n return \"cleared\" as const;\n }),\n );\n }),\n );\n\n yield* failpoint.hit(\"maintenance:finish:after\");\n\n return yield* annotate(\n MaintenancePassReport.make({\n phase: \"caught-up\",\n recovered: 0,\n settled: 0,\n nonterminal: started.nonterminal,\n alarm: disposition,\n }),\n );\n }\n // Step 2 — reconciliation strictly precedes new work in this pass (exit gate).\n observed.nativeOnly = true;\n const recovered: ReadonlyArray<RecoveryReport> = yield* runtime.runRecovery;\n const reports = new Map(recovered.map((report) => [report.submissionId, report]));\n const current = yield* Stream.runCollect(ledger.scanNonterminal);\n const heads = new Map<ThreadId, SubmissionSnapshot>();\n\n for (const row of current) {\n // Parked uncertainty keeps its settlement obligation, but later input can run.\n // Accepted aborts and every other wait remain subject to the lane's FIFO barrier.\n if (row.state === \"unknown\" && stableExternalWait(row, reports)) continue;\n if (!heads.has(row.threadId)) heads.set(row.threadId, row);\n }\n\n const eligible = [...heads.values()]\n .filter((head) => !stableExternalWait(head, reports))\n .map((head) => head.threadId)\n .sort();\n\n const selectionTime = yield* Clock.currentTimeMillis;\n\n yield* failpoint.hit(\"maintenance:select:before\");\n\n const selection = yield* runTransaction(\"select maintenance lane\", () =>\n ctx.storage.transaction(async (transaction) => {\n const { state } = await readMaintenanceState(transaction);\n\n const retries = (state.bindingRetries ?? []).filter(\n (retry) => heads.get(retry.threadId)?.submissionId === retry.submissionId,\n );\n\n const runnable = eligible.filter(\n (threadId) =>\n !retries.some(\n (retry) => retry.threadId === threadId && retry.notBefore > selectionTime,\n ),\n );\n\n const next =\n runnable.find(\n (threadId) =>\n state.lastServedThreadId === undefined || threadId > state.lastServedThreadId,\n ) ?? runnable[0];\n\n if (next !== undefined) {\n await transaction.put(\n MAINTENANCE_STATE_KEY,\n encodeMaintenanceState(\n ThreadMaintenanceState.make({ ...state, lastServedThreadId: next }),\n ),\n );\n }\n\n return { selected: next, retries };\n }),\n );\n\n yield* failpoint.hit(\"maintenance:select:after\");\n\n const selected =\n selection.selected === undefined ? undefined : heads.get(selection.selected);\n\n let retries = selection.retries;\n let bindingFailure: DurableBindingFailure | undefined;\n\n // One runnable FIFO head per event. An absent agent is a durable wait for a deployment,\n // including for children; other local lanes and host deliveries remain independently due.\n const settlement =\n selected === undefined\n ? Option.none()\n : yield* runtime.processThreadHead(selected.threadId, { yieldAfter }).pipe(\n Effect.catchTag(\"BindingUnavailable\", (failure) => {\n bindingFailure = failure;\n\n return Effect.succeed(Option.none());\n }),\n );\n\n if (selected !== undefined) {\n const previous = retries.find((retry) => retry.submissionId === selected.submissionId);\n let retry: BindingRetry | undefined;\n let reportBindingFailure = false;\n\n if (bindingFailure !== undefined) {\n const now = yield* Clock.currentTimeMillis;\n const attempts = Math.min(30, (previous?.attempts ?? 0) + 1);\n\n reportBindingFailure =\n previous === undefined || now - previous.reportedAt >= 15 * 60_000;\n retry = BindingRetry.make({\n threadId: selected.threadId,\n submissionId: selected.submissionId,\n attempts,\n notBefore: now + Math.min(60_000, 5_000 * 2 ** (attempts - 1)),\n reportedAt: reportBindingFailure ? now : (previous?.reportedAt ?? now),\n });\n }\n if (retry !== undefined || previous !== undefined) {\n // The Attempt released its Claim. Commit its binding wait (or clear) once,\n // before joining fallible auxiliary work. This local fact neither acknowledges\n // a generation nor changes the shared alarm; those require event retirement.\n yield* failpoint.hit(\"maintenance:binding-retry:before\");\n retries = yield* runTransaction(\"record submission binding retry\", () =>\n ctx.storage.transaction(async (transaction) => {\n const { state } = await readMaintenanceState(transaction);\n\n const bindingRetries = [\n ...(state.bindingRetries ?? []).filter(\n (entry) => entry.submissionId !== selected.submissionId,\n ),\n ...(retry === undefined ? [] : [retry]),\n ];\n\n await transaction.put(\n MAINTENANCE_STATE_KEY,\n encodeMaintenanceState(ThreadMaintenanceState.make({ ...state, bindingRetries })),\n );\n\n return bindingRetries;\n }),\n );\n yield* failpoint.hit(\"maintenance:binding-retry:after\");\n }\n if (bindingFailure !== undefined) {\n yield* reportBindingFailure\n ? Effect.logError(\n \"Thread awaits a current agent binding; original work remains pending\",\n Cause.fail(bindingFailure),\n )\n : Effect.logDebug(\"Thread binding retry remains pending\", Cause.fail(bindingFailure));\n }\n }\n\n observed.nativeOnly = false;\n yield* finishAuxiliary;\n const remaining = yield* Stream.runCollect(ledger.scanNonterminal);\n const waitingHeads = new Map<ThreadId, boolean>();\n\n const autonomous = remaining.some((snapshot) => {\n if (snapshot.state === \"unknown\" && stableExternalWait(snapshot, reports)) return false;\n const headWaiting = waitingHeads.get(snapshot.threadId);\n\n if (headWaiting === undefined)\n waitingHeads.set(snapshot.threadId, stableExternalWait(snapshot, reports));\n // FIFO followers cannot execute through a stable external wait. Only plain queued\n // input is dormant here; admission repairs and accepted aborts still need a pass.\n if (\n headWaiting === true &&\n snapshot.state === \"ready\" &&\n reports.get(snapshot.submissionId)?.decision._tag === \"ApplyInput\"\n )\n return false;\n\n return !stableExternalWait(snapshot, reports);\n });\n\n const progressed =\n Option.isSome(settlement) ||\n recovered.some((report) => report.disposition === \"repaired\");\n\n const now = yield* Clock.currentTimeMillis;\n const ordinaryDelay = autonomous ? yield* rearmDelay(progressed, started.stalls) : 0;\n\n const nextEligible = eligible.map(\n (threadId) =>\n retries.find((retry) => retry.submissionId === heads.get(threadId)?.submissionId)\n ?.notBefore ?? now,\n );\n\n const bindingDelay =\n nextEligible.length === 0 ? 0 : Math.max(0, Math.min(...nextEligible) - now);\n\n const delay = Math.max(ordinaryDelay, bindingDelay);\n\n yield* failpoint.hit(\"maintenance:finish:before\");\n\n const alarmDisposition = yield* mutations.withSnapshot((active) =>\n Effect.gen(function* () {\n const publicationDeadline = yield* pendingDeadline;\n\n return yield* runTransaction(\"finish maintenance pass\", () =>\n ctx.storage.transaction(async (transaction) => {\n const { state } = await readMaintenanceState(transaction);\n\n // Autonomous work and in-flight mutations intentionally leave the observed\n // generation dirty. Otherwise acknowledge only the pass-start generation.\n const processed =\n autonomous || started.activeAtStart > 0 || active > 0\n ? state.processed\n : state.processed > started.generation\n ? state.processed\n : started.generation;\n\n const next = ThreadMaintenanceState.make({\n ...Struct.omit(state, [\"retry\"]),\n processed,\n nonterminal: remaining.length,\n bindingRetries: (state.bindingRetries ?? []).filter((retry) =>\n remaining.some((row) => row.submissionId === retry.submissionId),\n ),\n ...(autonomous && !progressed\n ? {\n retry: MaintenanceRetry.make({\n generation: started.generation,\n notBefore: now + delay,\n nativeOnly: true,\n stalls: Math.min(30, started.stalls + 1),\n }),\n }\n : {}),\n });\n\n await transaction.put(MAINTENANCE_STATE_KEY, encodeMaintenanceState(next));\n if (autonomous) {\n // Replace the crash-fallback slot with this pass's bounded backoff. The target\n // is never earlier than the begin-pass fallback, so workerd does not cancel\n // this running alarm handler before its report/span can complete.\n const nativeDeadline =\n started.activeAtStart > 0 || active > 0 || state.dirty !== started.generation\n ? now + minimumAlarmDelay\n : now + delay;\n\n await transaction.setAlarm(\n Option.isSome(publicationDeadline)\n ? Math.max(\n now + minimumAlarmDelay,\n Math.min(nativeDeadline, publicationDeadline.value),\n )\n : nativeDeadline,\n );\n\n return \"rearmed\" as const;\n }\n if (started.activeAtStart > 0 || active > 0 || next.dirty > next.processed) {\n // A mutation overlapped this pass's observation window or raced\n // acknowledgement. It stays dirty and its pre-armed bounded alarm survives;\n // unseen effects are never acknowledged. Do not accelerate that future alarm\n // from inside the current handler: workerd cancels a running handler when it\n // writes an earlier slot.\n await ensureTransactionAlarmBy(\n transaction,\n Option.isSome(publicationDeadline)\n ? Math.max(\n now + minimumAlarmDelay,\n Math.min(now + config.wakeScanInterval, publicationDeadline.value),\n )\n : now + config.wakeScanInterval,\n );\n\n return \"rearmed\" as const;\n }\n if (Option.isSome(publicationDeadline)) {\n await transaction.setAlarm(\n Math.max(now + minimumAlarmDelay, publicationDeadline.value),\n );\n\n return \"rearmed\" as const;\n }\n await transaction.deleteAlarm();\n\n return \"cleared\" as const;\n }),\n );\n }),\n );\n\n yield* failpoint.hit(\"maintenance:finish:after\");\n\n return yield* annotate(\n MaintenancePassReport.make({\n phase: \"actionable\",\n recovered: recovered.length,\n settled: Option.isSome(settlement) ? 1 : 0,\n nonterminal: remaining.length,\n alarm: alarmDisposition,\n }),\n );\n });\n\n return ThreadMaintenance.of({\n // A mid-pass immediate hint is droppable; durable dirty state decides the final alarm.\n pass: Effect.gen(function* () {\n const now = yield* Clock.currentTimeMillis;\n const yieldAfter = DateTime.makeUnsafe(now + 10 * 60_000);\n const dispatchUntil = DateTime.makeUnsafe(now + 14 * 60_000);\n const observed: MaintenanceObservation = { nativeOnly: false };\n\n return yield* alarm.withWakesDeferred(\n maintenancePassGate.withPermit(\n Effect.scoped(pass(yieldAfter, dispatchUntil, observed)).pipe(\n // Close event-owned auxiliary work and release Attempt ownership before\n // failure rearming, while still holding the pass permit.\n Effect.onErrorIf(\n () => true,\n () => rearmFailure(observed),\n ),\n ),\n ),\n );\n }).pipe(\n // Include permit waiting, recovery and acknowledgement in the event deadline.\n // Interruption releases Attempt ownership, leaving the prearmed dirty generation\n // for recovery. It never changes the logical Run duration or settles a policy failure.\n // This cooperative timer cannot preempt synchronous CPU work or stuck finalizers.\n Effect.timeoutOrElse({\n duration: \"14 minutes\",\n orElse: () =>\n DurableAlarmError.make({\n operation: \"maintenance pass deadline\",\n message:\n \"The maintenance event exceeded its 14 minute deadline; durable recovery remains pending\",\n }),\n }),\n ),\n ensureAlarm: mutations.withSnapshot(() => ensureAlarm()),\n withMutation: (body) =>\n mutations.withMutation(\n body.pipe(\n Effect.tap(() =>\n publishCommitted.pipe(Effect.provideService(ThreadPublication, publication)),\n ),\n ),\n ),\n });\n }),\n );\n}\n"],"mappings":"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"}
|
|
@@ -266,6 +266,7 @@ declare const encodeSubmitRequest: (input: SubmitRequest, options?: import("effe
|
|
|
266
266
|
readonly tools: string;
|
|
267
267
|
readonly replay?: {
|
|
268
268
|
readonly agent: string;
|
|
269
|
+
readonly agentBehavior?: string | undefined;
|
|
269
270
|
readonly tools: {
|
|
270
271
|
readonly [x: string]: string;
|
|
271
272
|
};
|
|
@@ -313,6 +314,7 @@ declare const encodeSubmitRequest: (input: SubmitRequest, options?: import("effe
|
|
|
313
314
|
readonly tools: string;
|
|
314
315
|
readonly replay?: {
|
|
315
316
|
readonly agent: string;
|
|
317
|
+
readonly agentBehavior?: string | undefined;
|
|
316
318
|
readonly tools: {
|
|
317
319
|
readonly [x: string]: string;
|
|
318
320
|
};
|
|
@@ -423,6 +425,7 @@ declare const encodeSubmitRequest: (input: SubmitRequest, options?: import("effe
|
|
|
423
425
|
readonly tools: string;
|
|
424
426
|
readonly replay?: {
|
|
425
427
|
readonly agent: string;
|
|
428
|
+
readonly agentBehavior?: string | undefined;
|
|
426
429
|
readonly tools: {
|
|
427
430
|
readonly [x: string]: string;
|
|
428
431
|
};
|
|
@@ -472,13 +475,13 @@ declare const encodeUnknownResolutionCommand: (input: UnknownResolutionCommand,
|
|
|
472
475
|
readonly author: string;
|
|
473
476
|
readonly reason: string;
|
|
474
477
|
readonly resolution: {
|
|
475
|
-
readonly _tag: "SafeToRetry";
|
|
476
|
-
} | {
|
|
477
478
|
readonly _tag: "CompletedWithResult";
|
|
478
479
|
readonly result: Schema.Json;
|
|
479
480
|
readonly isFailure: boolean;
|
|
480
481
|
} | {
|
|
481
482
|
readonly _tag: "NeverHappened";
|
|
483
|
+
} | {
|
|
484
|
+
readonly _tag: "SafeToRetry";
|
|
482
485
|
} | {
|
|
483
486
|
readonly _tag: "AbortSubmission";
|
|
484
487
|
};
|
|
@@ -614,11 +617,6 @@ declare const encodeHostResponse: (input: AbortRecorded | ApprovalRecorded | Hos
|
|
|
614
617
|
readonly createdAt: string;
|
|
615
618
|
readonly deploymentId: string;
|
|
616
619
|
readonly payload: {
|
|
617
|
-
readonly _tag: "AbortRequested";
|
|
618
|
-
readonly submissionId: string;
|
|
619
|
-
readonly author: string;
|
|
620
|
-
readonly reason: string;
|
|
621
|
-
} | {
|
|
622
620
|
readonly _tag: "ThreadCreated";
|
|
623
621
|
readonly agentId: string;
|
|
624
622
|
readonly definitions: {
|
|
@@ -627,6 +625,7 @@ declare const encodeHostResponse: (input: AbortRecorded | ApprovalRecorded | Hos
|
|
|
627
625
|
readonly tools: string;
|
|
628
626
|
readonly replay?: {
|
|
629
627
|
readonly agent: string;
|
|
628
|
+
readonly agentBehavior?: string | undefined;
|
|
630
629
|
readonly tools: {
|
|
631
630
|
readonly [x: string]: string;
|
|
632
631
|
};
|
|
@@ -747,6 +746,13 @@ declare const encodeHostResponse: (input: AbortRecorded | ApprovalRecorded | Hos
|
|
|
747
746
|
readonly messages?: Schema.Json | undefined;
|
|
748
747
|
} | {
|
|
749
748
|
readonly _tag: "ModelResponseRecorded";
|
|
749
|
+
readonly toolOperations?: readonly {
|
|
750
|
+
readonly toolCallId: string;
|
|
751
|
+
readonly toolName: string;
|
|
752
|
+
readonly executionClass: "idempotent" | "readonly" | "uncertain";
|
|
753
|
+
readonly executionKind: "delegation" | "orchestration" | "ordinary";
|
|
754
|
+
readonly replay: string;
|
|
755
|
+
}[] | undefined;
|
|
750
756
|
readonly toolParameterRejections?: readonly {
|
|
751
757
|
readonly toolCallId: string;
|
|
752
758
|
readonly parameters: Schema.Json;
|
|
@@ -812,6 +818,8 @@ declare const encodeHostResponse: (input: AbortRecorded | ApprovalRecorded | Hos
|
|
|
812
818
|
readonly parameters: Schema.Json;
|
|
813
819
|
readonly parametersDigest: string;
|
|
814
820
|
readonly executionKind?: "delegation" | "orchestration" | "ordinary" | undefined;
|
|
821
|
+
readonly executionClass?: "idempotent" | "readonly" | "uncertain" | undefined;
|
|
822
|
+
readonly replay?: string | undefined;
|
|
815
823
|
} | {
|
|
816
824
|
readonly _tag: "ToolCallSettled";
|
|
817
825
|
readonly toolSelection?: {
|
|
@@ -882,9 +890,15 @@ declare const encodeHostResponse: (input: AbortRecorded | ApprovalRecorded | Hos
|
|
|
882
890
|
readonly _tag: "RunCompleted";
|
|
883
891
|
readonly runId: string;
|
|
884
892
|
readonly output: Schema.Json;
|
|
893
|
+
readonly resultDigest?: string | undefined;
|
|
885
894
|
readonly runDisposition?: Schema.Json | undefined;
|
|
886
895
|
readonly finishReason?: "budget-exhausted" | undefined;
|
|
887
896
|
readonly exhausted?: "tokens" | "tool-calls" | "turns" | undefined;
|
|
897
|
+
} | {
|
|
898
|
+
readonly _tag: "AbortRequested";
|
|
899
|
+
readonly submissionId: string;
|
|
900
|
+
readonly author: string;
|
|
901
|
+
readonly reason: string;
|
|
888
902
|
} | {
|
|
889
903
|
readonly _tag: "SubmissionSettled";
|
|
890
904
|
readonly submissionId: string;
|
|
@@ -974,6 +988,7 @@ declare const encodeHostResponse: (input: AbortRecorded | ApprovalRecorded | Hos
|
|
|
974
988
|
readonly tools: string;
|
|
975
989
|
readonly replay?: {
|
|
976
990
|
readonly agent: string;
|
|
991
|
+
readonly agentBehavior?: string | undefined;
|
|
977
992
|
readonly tools: {
|
|
978
993
|
readonly [x: string]: string;
|
|
979
994
|
};
|
|
@@ -1073,6 +1088,7 @@ declare const encodeHostResponse: (input: AbortRecorded | ApprovalRecorded | Hos
|
|
|
1073
1088
|
readonly tools: string;
|
|
1074
1089
|
readonly replay?: {
|
|
1075
1090
|
readonly agent: string;
|
|
1091
|
+
readonly agentBehavior?: string | undefined;
|
|
1076
1092
|
readonly tools: {
|
|
1077
1093
|
readonly [x: string]: string;
|
|
1078
1094
|
};
|
|
@@ -1138,6 +1154,7 @@ declare const encodeHostResponse: (input: AbortRecorded | ApprovalRecorded | Hos
|
|
|
1138
1154
|
readonly tools: string;
|
|
1139
1155
|
readonly replay?: {
|
|
1140
1156
|
readonly agent: string;
|
|
1157
|
+
readonly agentBehavior?: string | undefined;
|
|
1141
1158
|
readonly tools: {
|
|
1142
1159
|
readonly [x: string]: string;
|
|
1143
1160
|
};
|
|
@@ -1185,6 +1202,7 @@ declare const encodeHostResponse: (input: AbortRecorded | ApprovalRecorded | Hos
|
|
|
1185
1202
|
readonly tools: string;
|
|
1186
1203
|
readonly replay?: {
|
|
1187
1204
|
readonly agent: string;
|
|
1205
|
+
readonly agentBehavior?: string | undefined;
|
|
1188
1206
|
readonly tools: {
|
|
1189
1207
|
readonly [x: string]: string;
|
|
1190
1208
|
};
|
|
@@ -1228,6 +1246,7 @@ declare const encodeHostResponse: (input: AbortRecorded | ApprovalRecorded | Hos
|
|
|
1228
1246
|
readonly tools: string;
|
|
1229
1247
|
readonly replay?: {
|
|
1230
1248
|
readonly agent: string;
|
|
1249
|
+
readonly agentBehavior?: string | undefined;
|
|
1231
1250
|
readonly tools: {
|
|
1232
1251
|
readonly [x: string]: string;
|
|
1233
1252
|
};
|
|
@@ -1275,6 +1294,7 @@ declare const encodeHostResponse: (input: AbortRecorded | ApprovalRecorded | Hos
|
|
|
1275
1294
|
readonly tools: string;
|
|
1276
1295
|
readonly replay?: {
|
|
1277
1296
|
readonly agent: string;
|
|
1297
|
+
readonly agentBehavior?: string | undefined;
|
|
1278
1298
|
readonly tools: {
|
|
1279
1299
|
readonly [x: string]: string;
|
|
1280
1300
|
};
|
|
@@ -1316,6 +1336,7 @@ declare const encodeHostResponse: (input: AbortRecorded | ApprovalRecorded | Hos
|
|
|
1316
1336
|
readonly tools: string;
|
|
1317
1337
|
readonly replay?: {
|
|
1318
1338
|
readonly agent: string;
|
|
1339
|
+
readonly agentBehavior?: string | undefined;
|
|
1319
1340
|
readonly tools: {
|
|
1320
1341
|
readonly [x: string]: string;
|
|
1321
1342
|
};
|
|
@@ -1415,13 +1436,13 @@ declare const encodeHostResponse: (input: AbortRecorded | ApprovalRecorded | Hos
|
|
|
1415
1436
|
readonly author: string;
|
|
1416
1437
|
readonly reason: string;
|
|
1417
1438
|
readonly resolution: {
|
|
1418
|
-
readonly _tag: "SafeToRetry";
|
|
1419
|
-
} | {
|
|
1420
1439
|
readonly _tag: "CompletedWithResult";
|
|
1421
1440
|
readonly result: Schema.Json;
|
|
1422
1441
|
readonly isFailure: boolean;
|
|
1423
1442
|
} | {
|
|
1424
1443
|
readonly _tag: "NeverHappened";
|
|
1444
|
+
} | {
|
|
1445
|
+
readonly _tag: "SafeToRetry";
|
|
1425
1446
|
} | {
|
|
1426
1447
|
readonly _tag: "AbortSubmission";
|
|
1427
1448
|
};
|
|
@@ -1431,42 +1452,13 @@ declare const encodeHostResponse: (input: AbortRecorded | ApprovalRecorded | Hos
|
|
|
1431
1452
|
} | {
|
|
1432
1453
|
readonly _tag: "HostFailed";
|
|
1433
1454
|
readonly failure: {
|
|
1434
|
-
readonly _tag: "
|
|
1435
|
-
readonly operation: string;
|
|
1455
|
+
readonly _tag: "HostProtocolError";
|
|
1436
1456
|
readonly message: string;
|
|
1437
|
-
readonly cause?: Schema.Json | undefined;
|
|
1438
|
-
} | {
|
|
1439
|
-
readonly _tag: "AdmissionConflict";
|
|
1440
|
-
readonly threadId: string;
|
|
1441
|
-
readonly principal: string;
|
|
1442
|
-
readonly idempotencyKey: string;
|
|
1443
|
-
readonly existingInputDigest: string;
|
|
1444
|
-
readonly attemptedInputDigest: string;
|
|
1445
|
-
} | {
|
|
1446
|
-
readonly _tag: "AdmissionPolicyError";
|
|
1447
|
-
readonly reason: "occupied" | "refused" | "unavailable";
|
|
1448
|
-
readonly code: string;
|
|
1449
|
-
} | {
|
|
1450
|
-
readonly _tag: "SettlementConflict";
|
|
1451
|
-
readonly submissionId: string;
|
|
1452
|
-
readonly existingOutcome: "aborted" | "completed" | "failed";
|
|
1453
|
-
} | {
|
|
1454
|
-
readonly _tag: "JoinedToHost";
|
|
1455
|
-
readonly submissionId: string;
|
|
1456
|
-
readonly hostSubmissionId: string;
|
|
1457
1457
|
} | {
|
|
1458
1458
|
readonly _tag: "LedgerError";
|
|
1459
1459
|
readonly operation: string;
|
|
1460
1460
|
readonly message: string;
|
|
1461
1461
|
readonly cause?: Schema.Json | undefined;
|
|
1462
|
-
} | {
|
|
1463
|
-
readonly _tag: "ThreadStoreError";
|
|
1464
|
-
readonly operation: string;
|
|
1465
|
-
readonly message: string;
|
|
1466
|
-
readonly cause?: Schema.Json | undefined;
|
|
1467
|
-
} | {
|
|
1468
|
-
readonly _tag: "ThreadNotMaterialized";
|
|
1469
|
-
readonly threadId: string;
|
|
1470
1462
|
} | {
|
|
1471
1463
|
readonly _tag: "AppendConflict";
|
|
1472
1464
|
readonly threadId: string;
|
|
@@ -1480,8 +1472,30 @@ declare const encodeHostResponse: (input: AbortRecorded | ApprovalRecorded | Hos
|
|
|
1480
1472
|
readonly actualEpoch: number;
|
|
1481
1473
|
readonly attemptedEpoch: number;
|
|
1482
1474
|
} | {
|
|
1483
|
-
readonly _tag: "
|
|
1475
|
+
readonly _tag: "ThreadNotMaterialized";
|
|
1476
|
+
readonly threadId: string;
|
|
1477
|
+
} | {
|
|
1478
|
+
readonly _tag: "ThreadStoreError";
|
|
1479
|
+
readonly operation: string;
|
|
1484
1480
|
readonly message: string;
|
|
1481
|
+
readonly cause?: Schema.Json | undefined;
|
|
1482
|
+
} | {
|
|
1483
|
+
readonly _tag: "OperationDenied";
|
|
1484
|
+
readonly operation: "abort" | "awaitSettlement" | "explain" | "observe" | "resolveApproval" | "resolveUnknown" | "retry" | "scanObligations" | "verify" | "wake";
|
|
1485
|
+
readonly reason: string;
|
|
1486
|
+
readonly threadId?: string | undefined;
|
|
1487
|
+
readonly submissionId?: string | undefined;
|
|
1488
|
+
} | {
|
|
1489
|
+
readonly _tag: "AdmissionConflict";
|
|
1490
|
+
readonly threadId: string;
|
|
1491
|
+
readonly principal: string;
|
|
1492
|
+
readonly idempotencyKey: string;
|
|
1493
|
+
readonly existingInputDigest: string;
|
|
1494
|
+
readonly attemptedInputDigest: string;
|
|
1495
|
+
} | {
|
|
1496
|
+
readonly _tag: "AdmissionPolicyError";
|
|
1497
|
+
readonly reason: "occupied" | "refused" | "unavailable";
|
|
1498
|
+
readonly code: string;
|
|
1485
1499
|
} | {
|
|
1486
1500
|
readonly _tag: "AgentInputError";
|
|
1487
1501
|
readonly message: string;
|
|
@@ -1489,6 +1503,17 @@ declare const encodeHostResponse: (input: AbortRecorded | ApprovalRecorded | Hos
|
|
|
1489
1503
|
readonly _tag: "DigestError";
|
|
1490
1504
|
readonly message: string;
|
|
1491
1505
|
readonly cause?: Schema.Json | undefined;
|
|
1506
|
+
} | {
|
|
1507
|
+
readonly _tag: "DurableRuntimeFailpointError";
|
|
1508
|
+
readonly location: "abort:after-intent" | "approval:after-request-append" | "approval:after-suspend" | "checkpoint:after-save" | "checkpoint:before-save" | "claim:after-claim" | "compaction:after-canonical-append" | "compaction:before-canonical-append" | "input:after-canonical-append" | "join:after-canonical-append" | "join:after-claim" | "policy:after-reservation-append" | "policy:before-reservation-append" | "resolve:after-intent" | "run:after-duration-append" | "run:after-start-append" | "run:before-duration-append" | "run:before-start-append" | "step:after-step-append" | "subagent:after-admit" | "subagent:after-child-abort-intent" | "subagent:after-child-ready" | "subagent:after-join-append" | "subagent:after-release" | "subagent:after-release-pending" | "subagent:after-request-append" | "subagent:after-reserve" | "subagent:after-sibling-settle" | "subagent:after-start-append" | "subagent:after-suspend" | "subagent:before-join-append" | "submit:after-admit" | "submit:after-materialize" | "terminalize:after-canonical-append" | "terminalize:after-reserve" | "tools:after-prepared-append" | "tools:after-unavailable-append" | "tools:before-prepared-append" | "tools:before-unavailable-append" | "turn:after-canonical-append" | "turn:after-response-append" | "turn:after-results-append" | "update:after-canonical-append" | "update:after-delivery-insert" | "update:before-canonical-append" | "update:before-delivery-insert" | "worker:after-completion-append" | "worker:after-origin-append" | "worker:after-report-append" | "worker:after-report-delivery" | "worker:after-source-append" | "worker:after-subtree-append" | "worker:before-completion-append" | "worker:before-origin-append" | "worker:before-report-append" | "worker:before-report-delivery" | "worker:before-source-append" | "worker:before-subtree-append";
|
|
1509
|
+
} | {
|
|
1510
|
+
readonly _tag: "SettlementConflict";
|
|
1511
|
+
readonly submissionId: string;
|
|
1512
|
+
readonly existingOutcome: "aborted" | "completed" | "failed";
|
|
1513
|
+
} | {
|
|
1514
|
+
readonly _tag: "JoinedToHost";
|
|
1515
|
+
readonly submissionId: string;
|
|
1516
|
+
readonly hostSubmissionId: string;
|
|
1492
1517
|
} | {
|
|
1493
1518
|
readonly _tag: "ApprovalConflict";
|
|
1494
1519
|
readonly submissionId: string;
|
|
@@ -1498,20 +1523,16 @@ declare const encodeHostResponse: (input: AbortRecorded | ApprovalRecorded | Hos
|
|
|
1498
1523
|
readonly _tag: "UnknownResolutionConflict";
|
|
1499
1524
|
readonly submissionId: string;
|
|
1500
1525
|
readonly toolCallId: string;
|
|
1501
|
-
} | {
|
|
1502
|
-
readonly _tag: "DurableRuntimeFailpointError";
|
|
1503
|
-
readonly location: "abort:after-intent" | "approval:after-request-append" | "approval:after-suspend" | "checkpoint:after-save" | "checkpoint:before-save" | "claim:after-claim" | "compaction:after-canonical-append" | "compaction:before-canonical-append" | "input:after-canonical-append" | "join:after-canonical-append" | "join:after-claim" | "policy:after-reservation-append" | "policy:before-reservation-append" | "resolve:after-intent" | "run:after-duration-append" | "run:after-start-append" | "run:before-duration-append" | "run:before-start-append" | "step:after-step-append" | "subagent:after-admit" | "subagent:after-child-abort-intent" | "subagent:after-child-ready" | "subagent:after-join-append" | "subagent:after-release" | "subagent:after-release-pending" | "subagent:after-request-append" | "subagent:after-reserve" | "subagent:after-sibling-settle" | "subagent:after-start-append" | "subagent:after-suspend" | "subagent:before-join-append" | "submit:after-admit" | "submit:after-materialize" | "terminalize:after-canonical-append" | "terminalize:after-reserve" | "tools:after-prepared-append" | "tools:before-prepared-append" | "turn:after-canonical-append" | "turn:after-response-append" | "turn:after-results-append" | "update:after-canonical-append" | "update:after-delivery-insert" | "update:before-canonical-append" | "update:before-delivery-insert" | "worker:after-completion-append" | "worker:after-origin-append" | "worker:after-report-append" | "worker:after-report-delivery" | "worker:after-source-append" | "worker:after-subtree-append" | "worker:before-completion-append" | "worker:before-origin-append" | "worker:before-report-append" | "worker:before-report-delivery" | "worker:before-source-append" | "worker:before-subtree-append";
|
|
1504
1526
|
} | {
|
|
1505
1527
|
readonly _tag: "AdmissionLimitExceeded";
|
|
1506
1528
|
readonly limit: "database-bytes" | "input-bytes" | "queue-depth";
|
|
1507
1529
|
readonly actual: number;
|
|
1508
1530
|
readonly maximum: number;
|
|
1509
1531
|
} | {
|
|
1510
|
-
readonly _tag: "
|
|
1511
|
-
readonly operation:
|
|
1512
|
-
readonly
|
|
1513
|
-
readonly
|
|
1514
|
-
readonly submissionId?: string | undefined;
|
|
1532
|
+
readonly _tag: "DurableAlarmError";
|
|
1533
|
+
readonly operation: string;
|
|
1534
|
+
readonly message: string;
|
|
1535
|
+
readonly cause?: Schema.Json | undefined;
|
|
1515
1536
|
};
|
|
1516
1537
|
}, Schema.SchemaError, never>;
|
|
1517
1538
|
declare const decodeHostResponse: (input: unknown, options?: import("effect/SchemaAST").ParseOptions) => Effect.Effect<AbortRecorded | ApprovalRecorded | HostFailed | ObservedPage | ProgressCancelled | ProgressObserved | SettlementReached | SubmissionStatusResponse | SubmitSucceeded | UnknownResolutionRecorded, Schema.SchemaError, never>;
|
|
@@ -309,6 +309,19 @@ declare const encodeAdminResponse: (input: AdminFailed | ExplainedRecovery | Obl
|
|
|
309
309
|
readonly toolName: string;
|
|
310
310
|
readonly turn: number;
|
|
311
311
|
}[];
|
|
312
|
+
readonly pendingOperations: readonly {
|
|
313
|
+
readonly _tag: "ToolCallPrepared";
|
|
314
|
+
readonly runId: string;
|
|
315
|
+
readonly turnId: string;
|
|
316
|
+
readonly turn: number;
|
|
317
|
+
readonly toolCallId: string;
|
|
318
|
+
readonly toolName: string;
|
|
319
|
+
readonly parameters: Schema.Json;
|
|
320
|
+
readonly parametersDigest: string;
|
|
321
|
+
readonly executionKind?: "delegation" | "orchestration" | "ordinary" | undefined;
|
|
322
|
+
readonly executionClass?: "idempotent" | "readonly" | "uncertain" | undefined;
|
|
323
|
+
readonly replay?: string | undefined;
|
|
324
|
+
}[];
|
|
312
325
|
readonly openDelegationCalls: readonly {
|
|
313
326
|
readonly toolCallId: string;
|
|
314
327
|
readonly toolName: string;
|
|
@@ -692,6 +705,11 @@ declare const encodeAdminResponse: (input: AdminFailed | ExplainedRecovery | Obl
|
|
|
692
705
|
} | {
|
|
693
706
|
readonly _tag: "AdminFailed";
|
|
694
707
|
readonly failure: {
|
|
708
|
+
readonly _tag: "DurableAlarmError";
|
|
709
|
+
readonly operation: string;
|
|
710
|
+
readonly message: string;
|
|
711
|
+
readonly cause?: Schema.Json | undefined;
|
|
712
|
+
} | {
|
|
695
713
|
readonly _tag: "HostProtocolError";
|
|
696
714
|
readonly message: string;
|
|
697
715
|
} | {
|
|
@@ -714,14 +732,9 @@ declare const encodeAdminResponse: (input: AdminFailed | ExplainedRecovery | Obl
|
|
|
714
732
|
readonly _tag: "DigestError";
|
|
715
733
|
readonly message: string;
|
|
716
734
|
readonly cause?: Schema.Json | undefined;
|
|
717
|
-
} | {
|
|
718
|
-
readonly _tag: "DurableAlarmError";
|
|
719
|
-
readonly operation: string;
|
|
720
|
-
readonly message: string;
|
|
721
|
-
readonly cause?: Schema.Json | undefined;
|
|
722
735
|
} | {
|
|
723
736
|
readonly _tag: "DurableRuntimeFailpointError";
|
|
724
|
-
readonly location: "abort:after-intent" | "approval:after-request-append" | "approval:after-suspend" | "checkpoint:after-save" | "checkpoint:before-save" | "claim:after-claim" | "compaction:after-canonical-append" | "compaction:before-canonical-append" | "input:after-canonical-append" | "join:after-canonical-append" | "join:after-claim" | "policy:after-reservation-append" | "policy:before-reservation-append" | "resolve:after-intent" | "run:after-duration-append" | "run:after-start-append" | "run:before-duration-append" | "run:before-start-append" | "step:after-step-append" | "subagent:after-admit" | "subagent:after-child-abort-intent" | "subagent:after-child-ready" | "subagent:after-join-append" | "subagent:after-release" | "subagent:after-release-pending" | "subagent:after-request-append" | "subagent:after-reserve" | "subagent:after-sibling-settle" | "subagent:after-start-append" | "subagent:after-suspend" | "subagent:before-join-append" | "submit:after-admit" | "submit:after-materialize" | "terminalize:after-canonical-append" | "terminalize:after-reserve" | "tools:after-prepared-append" | "tools:before-prepared-append" | "turn:after-canonical-append" | "turn:after-response-append" | "turn:after-results-append" | "update:after-canonical-append" | "update:after-delivery-insert" | "update:before-canonical-append" | "update:before-delivery-insert" | "worker:after-completion-append" | "worker:after-origin-append" | "worker:after-report-append" | "worker:after-report-delivery" | "worker:after-source-append" | "worker:after-subtree-append" | "worker:before-completion-append" | "worker:before-origin-append" | "worker:before-report-append" | "worker:before-report-delivery" | "worker:before-source-append" | "worker:before-subtree-append";
|
|
737
|
+
readonly location: "abort:after-intent" | "approval:after-request-append" | "approval:after-suspend" | "checkpoint:after-save" | "checkpoint:before-save" | "claim:after-claim" | "compaction:after-canonical-append" | "compaction:before-canonical-append" | "input:after-canonical-append" | "join:after-canonical-append" | "join:after-claim" | "policy:after-reservation-append" | "policy:before-reservation-append" | "resolve:after-intent" | "run:after-duration-append" | "run:after-start-append" | "run:before-duration-append" | "run:before-start-append" | "step:after-step-append" | "subagent:after-admit" | "subagent:after-child-abort-intent" | "subagent:after-child-ready" | "subagent:after-join-append" | "subagent:after-release" | "subagent:after-release-pending" | "subagent:after-request-append" | "subagent:after-reserve" | "subagent:after-sibling-settle" | "subagent:after-start-append" | "subagent:after-suspend" | "subagent:before-join-append" | "submit:after-admit" | "submit:after-materialize" | "terminalize:after-canonical-append" | "terminalize:after-reserve" | "tools:after-prepared-append" | "tools:after-unavailable-append" | "tools:before-prepared-append" | "tools:before-unavailable-append" | "turn:after-canonical-append" | "turn:after-response-append" | "turn:after-results-append" | "update:after-canonical-append" | "update:after-delivery-insert" | "update:before-canonical-append" | "update:before-delivery-insert" | "worker:after-completion-append" | "worker:after-origin-append" | "worker:after-report-append" | "worker:after-report-delivery" | "worker:after-source-append" | "worker:after-subtree-append" | "worker:before-completion-append" | "worker:before-origin-append" | "worker:before-report-append" | "worker:before-report-delivery" | "worker:before-source-append" | "worker:before-subtree-append";
|
|
725
738
|
} | {
|
|
726
739
|
readonly _tag: "FenceRejected";
|
|
727
740
|
readonly threadId: string;
|
|
@@ -811,4 +824,4 @@ interface Class<EventServices = never> {
|
|
|
811
824
|
declare const make: <ApplicationServices, ApplicationError, EventServices = never, EventLayerError = never>(applicationLayer: Layer.Layer<CloudflareDurableRuntimeServices | ApplicationServices, ApplicationError, CloudflareBootstrapServices | DurableObjectState$1.DurableObjectState | WorkerEnvironment | DurableObjectContext | ThreadObjectNamespace>, options: Options<ApplicationServices, EventServices, EventLayerError>) => Class<ApplicationServices | EventServices>;
|
|
812
825
|
//#endregion
|
|
813
826
|
export { ThreadPublicationOptions as A, portCall as C, CloudflareDurableRuntimeOptions as D, CloudflareDurableRuntimeInitializationError as E, layerConfig as M, layerHostConfig as N, CloudflareDurableRuntimeServices as O, layerInHost as P, make as S, CloudflareBootstrapServices as T, decodeAdminVerifyRequest as _, AdminVerifyRequest as a, encodeAdminResponse as b, Instance as c, RetryExecuted as d, ThreadObject_d_exports as f, decodeAdminResponse as g, decodeAdminExplainRequest as h, AdminResponse as i, layer as j, ThreadObjectPorts as k, ObligationsScanned as l, VerifiedIntegrity as m, AdminFailed as n, Class as o, ThreadRpcOperation as p, AdminFailure as r, ExplainedRecovery as s, AdminExplainRequest as t, Options as u, decodeObligationThresholds as v, submit as w, handleRpc as x, decodeRetryCommand as y };
|
|
814
|
-
//# sourceMappingURL=ThreadObject-
|
|
827
|
+
//# sourceMappingURL=ThreadObject-CMQiW2uX.d.mts.map
|
package/dist/ThreadObject.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { A as ThreadPublicationOptions, C as portCall, D as CloudflareDurableRuntimeOptions, E as CloudflareDurableRuntimeInitializationError, M as layerConfig, N as layerHostConfig, O as CloudflareDurableRuntimeServices, P as layerInHost, S as make, T as CloudflareBootstrapServices, _ as decodeAdminVerifyRequest, a as AdminVerifyRequest, b as encodeAdminResponse, c as Instance, d as RetryExecuted, g as decodeAdminResponse, h as decodeAdminExplainRequest, i as AdminResponse, j as layer, k as ThreadObjectPorts, l as ObligationsScanned, m as VerifiedIntegrity, n as AdminFailed, o as Class, p as ThreadRpcOperation, r as AdminFailure, s as ExplainedRecovery, t as AdminExplainRequest, u as Options, v as decodeObligationThresholds, w as submit, x as handleRpc, y as decodeRetryCommand } from "./ThreadObject-
|
|
1
|
+
import { A as ThreadPublicationOptions, C as portCall, D as CloudflareDurableRuntimeOptions, E as CloudflareDurableRuntimeInitializationError, M as layerConfig, N as layerHostConfig, O as CloudflareDurableRuntimeServices, P as layerInHost, S as make, T as CloudflareBootstrapServices, _ as decodeAdminVerifyRequest, a as AdminVerifyRequest, b as encodeAdminResponse, c as Instance, d as RetryExecuted, g as decodeAdminResponse, h as decodeAdminExplainRequest, i as AdminResponse, j as layer, k as ThreadObjectPorts, l as ObligationsScanned, m as VerifiedIntegrity, n as AdminFailed, o as Class, p as ThreadRpcOperation, r as AdminFailure, s as ExplainedRecovery, t as AdminExplainRequest, u as Options, v as decodeObligationThresholds, w as submit, x as handleRpc, y as decodeRetryCommand } from "./ThreadObject-CMQiW2uX.mjs";
|
|
2
2
|
export { AdminExplainRequest, AdminFailed, AdminFailure, AdminResponse, AdminVerifyRequest, type CloudflareBootstrapServices as BootstrapServices, Class, ExplainedRecovery, type CloudflareDurableRuntimeInitializationError as InitializationError, Instance, ObligationsScanned, Options, type ThreadPublicationOptions as PublicationOptions, RetryExecuted, type CloudflareDurableRuntimeOptions as RuntimeOptions, type CloudflareDurableRuntimeServices as Services, ThreadObjectPorts, ThreadRpcOperation, VerifiedIntegrity, decodeAdminExplainRequest, decodeAdminResponse, decodeAdminVerifyRequest, decodeObligationThresholds, decodeRetryCommand, encodeAdminResponse, handleRpc, layer, layerConfig, layerHostConfig, layerInHost, make, portCall, submit };
|
package/dist/index.d.mts
CHANGED
|
@@ -8,6 +8,6 @@ import { t as CloudflareMemory_d_exports } from "./CloudflareMemory.mjs";
|
|
|
8
8
|
import { t as CloudflareScheduling_d_exports } from "./CloudflareScheduling.mjs";
|
|
9
9
|
import { t as CloudflareSubscriptions_d_exports } from "./CloudflareSubscriptions.mjs";
|
|
10
10
|
import { t as CloudflareThreadClient_d_exports } from "./CloudflareThreadClient.mjs";
|
|
11
|
-
import { f as ThreadObject_d_exports } from "./ThreadObject-
|
|
11
|
+
import { f as ThreadObject_d_exports } from "./ThreadObject-CMQiW2uX.mjs";
|
|
12
12
|
import { t as WakeScheduler_d_exports } from "./WakeScheduler.mjs";
|
|
13
13
|
export { Alarm_d_exports as Alarm, CloudflareAiGateway_d_exports as CloudflareAiGateway, CloudflareBindings_d_exports as CloudflareBindings, CloudflareBrowser_d_exports as CloudflareBrowser, CloudflareCodeMode_d_exports as CloudflareCodeMode, CloudflareConfig_d_exports as CloudflareConfig, CloudflareMemory_d_exports as CloudflareMemory, CloudflareScheduling_d_exports as CloudflareScheduling, CloudflareSubscriptions_d_exports as CloudflareSubscriptions, CloudflareThreadClient_d_exports as CloudflareThreadClient, ThreadObject_d_exports as ThreadObject, WakeScheduler_d_exports as WakeScheduler };
|
package/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name":"@effect-agent/platform-cloudflare","version":"0.1.0-beta.
|
|
1
|
+
{"name":"@effect-agent/platform-cloudflare","version":"0.1.0-beta.98","dependencies":{"@effect-agent/storage-cloudflare":"0.1.0-beta.98","@effect/platform-browser":"4.0.0-rc.115","@effect/sql-sqlite-do":"4.0.0-rc.115","effect-agent":"0.1.0-beta.98"},"devDependencies":{"@cloudflare/puppeteer":"1.1.0","@cloudflare/vitest-pool-workers":"0.21.3","@cloudflare/workers-types":"5.20260825.1","@effect-agent/testing":"0.1.0-beta.98","@effect/platform-node":"4.0.0-rc.115","@effect/sql-d1":"4.0.0-rc.115","@effect/vitest":"4.0.0-rc.115","effect":"4.0.0-rc.115","effect-cf":"0.44.1","esbuild":"0.28.1","miniflare":"5.20260811.1-alpha","typescript":"7.0.2","vite-plus":"0.3.0","vitest":"4.1.11"},"peerDependencies":{"@cloudflare/puppeteer":"^1.1.0","effect":"^4.0.0-rc.115","effect-cf":"^0.44.1"},"exports":{".":{"types":"./dist/index.d.mts","default":"./dist/index.mjs"},"./alarm":{"types":"./dist/Alarm.d.mts","default":"./dist/Alarm.mjs"},"./browser-rest-capture":{"types":"./dist/BrowserRestCapture.d.mts","default":"./dist/BrowserRestCapture.mjs"},"./browser-rest-crawl":{"types":"./dist/BrowserRestCrawl.d.mts","default":"./dist/BrowserRestCrawl.mjs"},"./cloudflare-bindings":{"types":"./dist/CloudflareBindings.d.mts","default":"./dist/CloudflareBindings.mjs"},"./cloudflare-browser":{"types":"./dist/CloudflareBrowser.d.mts","default":"./dist/CloudflareBrowser.mjs"},"./cloudflare-code-mode":{"types":"./dist/CloudflareCodeMode.d.mts","default":"./dist/CloudflareCodeMode.mjs"},"./cloudflare-config":{"types":"./dist/CloudflareConfig.d.mts","default":"./dist/CloudflareConfig.mjs"},"./cloudflare-memory":{"types":"./dist/CloudflareMemory.d.mts","default":"./dist/CloudflareMemory.mjs"},"./cloudflare-scheduling":{"types":"./dist/CloudflareScheduling.d.mts","default":"./dist/CloudflareScheduling.mjs"},"./cloudflare-subscriptions":{"types":"./dist/CloudflareSubscriptions.d.mts","default":"./dist/CloudflareSubscriptions.mjs"},"./cloudflare-thread-client":{"types":"./dist/CloudflareThreadClient.d.mts","default":"./dist/CloudflareThreadClient.mjs"},"./interactive-browser":{"types":"./dist/InteractiveBrowser.d.mts","default":"./dist/InteractiveBrowser.mjs"},"./protected-browser":{"types":"./dist/ProtectedBrowser.d.mts","default":"./dist/ProtectedBrowser.mjs"},"./thread-object":{"types":"./dist/ThreadObject.d.mts","default":"./dist/ThreadObject.mjs"},"./wake-scheduler":{"types":"./dist/WakeScheduler.d.mts","default":"./dist/WakeScheduler.mjs"},"./cloudflare-ai-gateway":{"types":"./dist/CloudflareAiGateway.d.mts","default":"./dist/CloudflareAiGateway.mjs"}},"description":"Cloudflare Layer assembly for Effect Agent: Durable Objects and Browser Run adapters.","license":"MIT","repository":{"type":"git","url":"git+https://github.com/danieljvdm/effect-agent.git","directory":"packages/platform-cloudflare"},"files":["dist","src"],"type":"module","sideEffects":[],"publishConfig":{"access":"public"},"scripts":{"build":"vp pack","check":"tsc --noEmit -p tsconfig.json"},"peerDependenciesMeta":{"@cloudflare/puppeteer":{"optional":true}}}
|
package/src/Alarm.ts
CHANGED
|
@@ -417,7 +417,8 @@ const stableExternalWait = (
|
|
|
417
417
|
snapshot: SubmissionSnapshot,
|
|
418
418
|
reports: ReadonlyMap<string, RecoveryReport>,
|
|
419
419
|
): boolean => {
|
|
420
|
-
const
|
|
420
|
+
const report = reports.get(snapshot.submissionId);
|
|
421
|
+
const decision = report?.decision._tag;
|
|
421
422
|
|
|
422
423
|
// An accepted abort still owes cleanup/settlement even if its claim was deferred this pass.
|
|
423
424
|
if (decision === "SettleAborted") return false;
|
|
@@ -426,7 +427,7 @@ const stableExternalWait = (
|
|
|
426
427
|
case "joined":
|
|
427
428
|
return true;
|
|
428
429
|
case "unknown":
|
|
429
|
-
return
|
|
430
|
+
return report?.disposition === "unknown";
|
|
430
431
|
case "admitted":
|
|
431
432
|
return reports.get(snapshot.submissionId)?.decision._tag === "AwaitParentEstablishment";
|
|
432
433
|
case "input-applied":
|
|
@@ -948,6 +949,9 @@ export class ThreadMaintenance extends Context.Service<
|
|
|
948
949
|
const heads = new Map<ThreadId, SubmissionSnapshot>();
|
|
949
950
|
|
|
950
951
|
for (const row of current) {
|
|
952
|
+
// Parked uncertainty keeps its settlement obligation, but later input can run.
|
|
953
|
+
// Accepted aborts and every other wait remain subject to the lane's FIFO barrier.
|
|
954
|
+
if (row.state === "unknown" && stableExternalWait(row, reports)) continue;
|
|
951
955
|
if (!heads.has(row.threadId)) heads.set(row.threadId, row);
|
|
952
956
|
}
|
|
953
957
|
|
|
@@ -1002,13 +1006,13 @@ export class ThreadMaintenance extends Context.Service<
|
|
|
1002
1006
|
let retries = selection.retries;
|
|
1003
1007
|
let bindingFailure: DurableBindingFailure | undefined;
|
|
1004
1008
|
|
|
1005
|
-
// One FIFO head per event. An
|
|
1009
|
+
// One runnable FIFO head per event. An absent agent is a durable wait for a deployment,
|
|
1006
1010
|
// including for children; other local lanes and host deliveries remain independently due.
|
|
1007
1011
|
const settlement =
|
|
1008
1012
|
selected === undefined
|
|
1009
1013
|
? Option.none()
|
|
1010
1014
|
: yield* runtime.processThreadHead(selected.threadId, { yieldAfter }).pipe(
|
|
1011
|
-
Effect.catchTag(
|
|
1015
|
+
Effect.catchTag("BindingUnavailable", (failure) => {
|
|
1012
1016
|
bindingFailure = failure;
|
|
1013
1017
|
|
|
1014
1018
|
return Effect.succeed(Option.none());
|
|
@@ -1063,7 +1067,7 @@ export class ThreadMaintenance extends Context.Service<
|
|
|
1063
1067
|
if (bindingFailure !== undefined) {
|
|
1064
1068
|
yield* reportBindingFailure
|
|
1065
1069
|
? Effect.logError(
|
|
1066
|
-
"Thread awaits a
|
|
1070
|
+
"Thread awaits a current agent binding; original work remains pending",
|
|
1067
1071
|
Cause.fail(bindingFailure),
|
|
1068
1072
|
)
|
|
1069
1073
|
: Effect.logDebug("Thread binding retry remains pending", Cause.fail(bindingFailure));
|
|
@@ -1076,6 +1080,7 @@ export class ThreadMaintenance extends Context.Service<
|
|
|
1076
1080
|
const waitingHeads = new Map<ThreadId, boolean>();
|
|
1077
1081
|
|
|
1078
1082
|
const autonomous = remaining.some((snapshot) => {
|
|
1083
|
+
if (snapshot.state === "unknown" && stableExternalWait(snapshot, reports)) return false;
|
|
1079
1084
|
const headWaiting = waitingHeads.get(snapshot.threadId);
|
|
1080
1085
|
|
|
1081
1086
|
if (headWaiting === undefined)
|