UNPKG

agents

Version:

A home for your AI agents

1,314 lines 62 kB
import { i as runWithoutCurrentAgent, r as runInLifecycleHostContext } from "./current-agent-DhoDkSnH.js";
import { i as _classPrivateFieldInitSpec, n as _classPrivateFieldSet2, r as _assertClassBrand, t as _classPrivateFieldGet2 } from "./classPrivateFieldGet2-DZBYAB34.js";
import { n as bindLifecycleCapability, r as lifecycleCapabilityId, t as LifecycleCapability } from "./capability-B4WbF81e.js";
import { t as _classPrivateMethodInitSpec } from "./classPrivateMethodInitSpec-qMjJ6sHQ.js";
import { n as publishDiagnosticsEvent } from "./diagnostics-BzvaX2UT.js";
import { isDurableObjectCodeUpdateReset, isDurableObjectMemoryLimitReset, isPlatformFailure, tryN } from "./retries.js";
import { SqlError } from "./sql-error.js";
import { AsyncLocalStorage } from "node:async_hooks";
import "cloudflare:workers";
import { nanoid } from "nanoid";
//#region src/lifecycle/capability-runner.ts
var _resolveCapabilities = /* @__PURE__ */ new WeakMap();
var _capabilities$1 = /* @__PURE__ */ new WeakMap();
var _startPromise = /* @__PURE__ */ new WeakMap();
var _started = /* @__PURE__ */ new WeakMap();
var _CapabilityRunner_brand = /* @__PURE__ */ new WeakSet();
/**
* Runs ordered lifecycle phases for capabilities installed in a Durable Object.
*
* Capabilities are resolved lazily on the first phase and retained for the
* lifetime of this runner. Startup runs in declaration order.
* Requests dispatch as a middleware chain: the first capability to return a
* response handles the request.
*/
var CapabilityRunner = class {
	/**
	* Create a lifecycle whose capabilities are resolved immediately before the
	* first phase.
	*
	* @param resolveCapabilities - Returns capabilities in their startup order.
	*/
	constructor(resolveCapabilities) {
		_classPrivateMethodInitSpec(this, _CapabilityRunner_brand);
		_classPrivateFieldInitSpec(this, _resolveCapabilities, void 0);
		_classPrivateFieldInitSpec(this, _capabilities$1, void 0);
		_classPrivateFieldInitSpec(this, _startPromise, void 0);
		_classPrivateFieldInitSpec(this, _started, false);
		_classPrivateFieldSet2(_resolveCapabilities, this, resolveCapabilities);
	}
	/**
	* Start every capability sequentially.
	*
	* Concurrent callers share one startup attempt. A failed attempt is not
	* cached, allowing the host to retry its complete startup phase.
	*
	* @param context - Properties supplied while resolving the Durable Object.
	*/
	async start(context) {
		if (_classPrivateFieldGet2(_started, this)) return;
		const pending = _classPrivateFieldGet2(_startPromise, this);
		if (pending) {
			await pending;
			return;
		}
		const attempt = _assertClassBrand(_CapabilityRunner_brand, this, _runStart).call(this, context);
		_classPrivateFieldSet2(_startPromise, this, attempt);
		try {
			await attempt;
		} catch (error) {
			if (_classPrivateFieldGet2(_startPromise, this) === attempt) _classPrivateFieldSet2(_startPromise, this, void 0);
			throw error;
		}
	}
	/**
	* Offer a request to each capability middleware in registration order.
	*
	* @param context - The request entering the Durable Object.
	* @returns The first capability response, or `undefined` when no
	* capability claimed the request.
	*/
	async request(context) {
		await _assertClassBrand(_CapabilityRunner_brand, this, _ensureReady).call(this, "handle a request");
		for (const capability of _assertClassBrand(_CapabilityRunner_brand, this, _getCapabilities).call(this)) {
			const response = await capability.onRequest?.(context);
			if (response !== void 0) return response;
		}
	}
	/**
	* Offer a WebSocket upgrade to each capability in declaration order.
	*
	* @param context - The upgrade request entering the Durable Object.
	* @returns The first capability response, or `undefined` when unclaimed.
	*/
	async webSocketUpgrade(context) {
		await _assertClassBrand(_CapabilityRunner_brand, this, _ensureReady).call(this, "handle a WebSocket upgrade");
		for (const capability of _assertClassBrand(_CapabilityRunner_brand, this, _getCapabilities).call(this)) {
			const response = await capability.onWebSocketUpgrade?.(context);
			if (response !== void 0) return response;
		}
	}
	/**
	* Offer a platform `webSocketMessage` wake to each capability in
	* declaration order.
	*
	* @returns Whether a capability consumed the event.
	*/
	async webSocketMessage(ws, message) {
		await _assertClassBrand(_CapabilityRunner_brand, this, _ensureReady).call(this, "handle a WebSocket message");
		for (const capability of _assertClassBrand(_CapabilityRunner_brand, this, _getCapabilities).call(this)) if (await capability.onWebSocketMessage?.(ws, message) === true) return true;
		return false;
	}
	/** Offer a platform `webSocketClose` wake to each capability. */
	async webSocketClose(ws, code, reason, wasClean) {
		await _assertClassBrand(_CapabilityRunner_brand, this, _ensureReady).call(this, "handle a WebSocket close");
		for (const capability of _assertClassBrand(_CapabilityRunner_brand, this, _getCapabilities).call(this)) if (await capability.onWebSocketClose?.(ws, code, reason, wasClean) === true) return true;
		return false;
	}
	/** Offer a platform `webSocketError` wake to each capability. */
	async webSocketError(ws, error) {
		await _assertClassBrand(_CapabilityRunner_brand, this, _ensureReady).call(this, "handle a WebSocket error");
		for (const capability of _assertClassBrand(_CapabilityRunner_brand, this, _getCapabilities).call(this)) if (await capability.onWebSocketError?.(ws, error) === true) return true;
		return false;
	}
	/** Find one installed capability by its stable id. */
	async findById(capabilityId) {
		await _assertClassBrand(_CapabilityRunner_brand, this, _ensureReady).call(this, "dispatch capability work");
		return _assertClassBrand(_CapabilityRunner_brand, this, _getCapabilities).call(this).find((candidate) => lifecycleCapabilityId(candidate) === capabilityId);
	}
	/** Route one message to an installed named capability. */
	async route(capabilityId, context) {
		await _assertClassBrand(_CapabilityRunner_brand, this, _ensureReady).call(this, "route a capability message");
		const capability = _assertClassBrand(_CapabilityRunner_brand, this, _getCapabilities).call(this).find((candidate) => lifecycleCapabilityId(candidate) === capabilityId);
		if (!capability?.onRoute) throw new Error(`Lifecycle capability ${JSON.stringify(capabilityId)} cannot receive routed messages`);
		return capability.onRoute(context);
	}
	/**
	* Offer a memory-limit strike to every capability, best-effort.
	*
	* Deliberately not gated on startup: a strike can land while startup
	* itself is the work that exceeded the memory limit, and the breaker's
	* policy must still reach capabilities. One capability's failure does not
	* stop the next — the isolate is about to reset either way.
	*/
	async memoryLimit(context) {
		for (const capability of _assertClassBrand(_CapabilityRunner_brand, this, _getCapabilities).call(this)) try {
			await capability.onMemoryLimit?.(context);
		} catch (error) {
			console.error("Lifecycle capability memory-limit policy failed", error);
		}
	}
	/** Dispose installed capabilities in reverse registration order. */
	async dispose() {
		for (const capability of [..._assertClassBrand(_CapabilityRunner_brand, this, _getCapabilities).call(this)].reverse()) try {
			await capability.dispose?.();
		} catch (error) {
			console.error("Lifecycle capability disposal failed", error);
		}
	}
};
async function _runStart(context) {
	for (const capability of _assertClassBrand(_CapabilityRunner_brand, this, _getCapabilities).call(this)) await capability.onStart?.(context);
	_classPrivateFieldSet2(_started, this, true);
}
async function _ensureReady(operation) {
	const pending = _classPrivateFieldGet2(_startPromise, this);
	if (pending) await pending;
	if (!_classPrivateFieldGet2(_started, this)) throw new Error(`Cannot ${operation} before the Durable Object lifecycle has started`);
}
function _getCapabilities() {
	if (!_classPrivateFieldGet2(_capabilities$1, this)) _classPrivateFieldSet2(_capabilities$1, this, Object.freeze([..._classPrivateFieldGet2(_resolveCapabilities, this).call(this)]));
	return _classPrivateFieldGet2(_capabilities$1, this);
}
//#endregion
//#region src/lifecycle/abort.ts
/**
* Reset the Durable Object instance without the platform retrying the alarm
* this invocation was handling. Never returns: `abort()` terminates
* execution.
*/
function abortWithoutAlarmRetry(ctx, reason) {
	ctx.abort(reason, { retryAlarm: false });
}
//#endregion
//#region src/lifecycle/job-queue.ts
/**
* Durable job queue owned by Lifecycle.
*
* One timestamp-ordered table holds every pending job for the Durable
* Object. A job is a serialisable callback address — owning capability plus
* function name — with a due time and a payload. Capabilities and the host
* push jobs through their scoped `LifecycleJobs` surface; Lifecycle's alarm
* event loop drives due jobs and derives the physical alarm from queue
* state. Payloads are opaque to the queue.
*/
/** Capability id under which host-owned jobs are stored. */
const HOST_JOB_CAPABILITY = "host";
/** Seconds before an in-flight single-flight job is treated as hung. */
const DEFAULT_HUNG_TIMEOUT_SECONDS = 30;
/** @internal Convert one raw queue row into its public job shape. */
function jobFromRow(row) {
	return {
		id: row.id,
		capability: row.capability,
		fn: row.fn,
		time: row.time,
		payload: typeof row.payload === "string" ? JSON.parse(row.payload) : void 0,
		retry: typeof row.retry_options === "string" ? JSON.parse(row.retry_options) : void 0,
		singleflight: row.singleflight === 1,
		exclusive: row.exclusive === 1,
		recoveryLoop: row.recovery_loop === 1,
		createdAt: row.created_at
	};
}
/** @internal One row's hung/slow-dispatch threshold in milliseconds. */
function hungTimeoutMs(row) {
	return (row.hung_timeout_seconds ?? DEFAULT_HUNG_TIMEOUT_SECONDS) * 1e3;
}
/** Whether an in-flight single-flight job has crossed its hung timeout. */
function isHungRow(row, nowMs) {
	return nowMs - (row.execution_started_at ?? 0) >= hungTimeoutMs(row);
}
var _storage = /* @__PURE__ */ new WeakMap();
var _tableEnsured = /* @__PURE__ */ new WeakMap();
var _JobQueue_brand = /* @__PURE__ */ new WeakSet();
/**
* @internal SQL-backed job queue. Lifecycle owns the single instance; the
* scoped `LifecycleJobs` surfaces delegate here with a fixed capability id.
*/
var JobQueue = class {
	constructor(storage) {
		_classPrivateMethodInitSpec(this, _JobQueue_brand);
		_classPrivateFieldInitSpec(this, _storage, void 0);
		_classPrivateFieldInitSpec(this, _tableEnsured, false);
		_classPrivateFieldSet2(_storage, this, storage);
	}
	push(capability, options) {
		if (!Number.isFinite(options.time) || options.time < 0) throw new Error(`Invalid job time: ${String(options.time)}`);
		if (typeof options.fn !== "string" || options.fn.trim() === "") throw new Error("Jobs require a non-empty fn");
		const id = options.id ?? nanoid(9);
		_assertClassBrand(_JobQueue_brand, this, _sql).call(this, `INSERT INTO cf_agents_jobs
        (id, capability, fn, time, payload, retry_options, singleflight,
         hung_timeout_seconds, exclusive, recovery_loop, running,
         execution_started_at)
       VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 0, NULL)
       ON CONFLICT(id) DO UPDATE SET
         fn = excluded.fn,
         time = excluded.time,
         payload = excluded.payload,
         retry_options = excluded.retry_options,
         singleflight = excluded.singleflight,
         hung_timeout_seconds = excluded.hung_timeout_seconds,
         exclusive = excluded.exclusive,
         recovery_loop = excluded.recovery_loop,
         running = 0,
         execution_started_at = NULL
       WHERE cf_agents_jobs.capability = excluded.capability`, id, capability, options.fn, Math.floor(options.time), options.payload === void 0 ? null : JSON.stringify(options.payload), options.retry ? JSON.stringify(options.retry) : null, options.singleflight ? 1 : 0, options.hungTimeoutSeconds ?? null, options.exclusive ? 1 : 0, options.recoveryLoop ? 1 : 0);
		const job = this.get(capability, id);
		if (!job) {
			const owner = _assertClassBrand(_JobQueue_brand, this, _sql).call(this, "SELECT capability FROM cf_agents_jobs WHERE id = ?", id)[0]?.capability;
			throw new Error(owner !== void 0 ? `Job id ${JSON.stringify(id)} already belongs to ${JSON.stringify(owner)}; job ids are scoped to their owner` : `Failed to persist job ${id}`);
		}
		return job;
	}
	cancel(capability, id) {
		if (_assertClassBrand(_JobQueue_brand, this, _sql).call(this, "SELECT id FROM cf_agents_jobs WHERE id = ? AND capability = ?", id, capability).length === 0) return false;
		_assertClassBrand(_JobQueue_brand, this, _sql).call(this, "DELETE FROM cf_agents_jobs WHERE id = ? AND capability = ?", id, capability);
		return true;
	}
	reschedule(capability, id, time) {
		if (!Number.isFinite(time) || time < 0) throw new Error(`Invalid job time: ${String(time)}`);
		if (_assertClassBrand(_JobQueue_brand, this, _sql).call(this, "SELECT id FROM cf_agents_jobs WHERE id = ? AND capability = ?", id, capability).length === 0) return false;
		_assertClassBrand(_JobQueue_brand, this, _sql).call(this, `UPDATE cf_agents_jobs
       SET time = ?, running = 0, execution_started_at = NULL
       WHERE id = ? AND capability = ?`, Math.floor(time), id, capability);
		return true;
	}
	get(capability, id) {
		const rows = _assertClassBrand(_JobQueue_brand, this, _sql).call(this, "SELECT * FROM cf_agents_jobs WHERE id = ? AND capability = ?", id, capability);
		return rows[0] ? jobFromRow(rows[0]) : void 0;
	}
	list(capability) {
		return _assertClassBrand(_JobQueue_brand, this, _sql).call(this, "SELECT * FROM cf_agents_jobs WHERE capability = ? ORDER BY time ASC", capability).map(jobFromRow);
	}
	/** Raw due rows at `nowMs`, ordered by due time. */
	due(nowMs) {
		return _assertClassBrand(_JobQueue_brand, this, _sql).call(this, "SELECT * FROM cf_agents_jobs WHERE time <= ? ORDER BY time ASC", Math.floor(nowMs));
	}
	/** One job's current row when it still exists and is still due. */
	dueRow(id, nowMs) {
		return _assertClassBrand(_JobQueue_brand, this, _sql).call(this, "SELECT * FROM cf_agents_jobs WHERE id = ? AND time <= ?", id, Math.floor(nowMs))[0];
	}
	markRunning(id, nowMs) {
		_assertClassBrand(_JobQueue_brand, this, _sql).call(this, `UPDATE cf_agents_jobs
       SET running = 1, execution_started_at = ?
       WHERE id = ?`, Math.floor(nowMs), id);
	}
	clearRunning(id) {
		_assertClassBrand(_JobQueue_brand, this, _sql).call(this, `UPDATE cf_agents_jobs
       SET running = 0, execution_started_at = NULL
       WHERE id = ?`, id);
	}
	delete(id) {
		_assertClassBrand(_JobQueue_brand, this, _sql).call(this, "DELETE FROM cf_agents_jobs WHERE id = ?", id);
	}
	/**
	* Unguarded retime for the alarm memory-limit breaker's backoff: the
	* platform-failure path clears the dispatch marker before the breaker
	* runs, so the guarded {@link applyOutcome} would no-op — and the
	* breaker's backoff must land regardless, it is protecting the object.
	*/
	retime(id, time) {
		_assertClassBrand(_JobQueue_brand, this, _sql).call(this, `UPDATE cf_agents_jobs
       SET time = ?, running = 0, execution_started_at = NULL
       WHERE id = ?`, Math.floor(time), id);
	}
	/**
	* Back off every pending recovery-loop job that would fire before the
	* breaker's backoff time (#1825), so a doomed loop's sibling rows cannot
	* re-trigger it on the next wake. Unguarded like {@link retime}: the
	* breaker's backoff must land regardless of dispatch markers.
	*/
	delayRecoveryLoopJobs(time) {
		_assertClassBrand(_JobQueue_brand, this, _sql).call(this, `UPDATE cf_agents_jobs
       SET time = ?, running = 0, execution_started_at = NULL
       WHERE recovery_loop = 1 AND time <= ?`, Math.floor(time), Math.floor(time));
	}
	/**
	* Read every recovery-loop job before breaker sealing. The memory-limit
	* policy phase uses this snapshot after the rows are purged so routed owners
	* can terminalize their own durable recovery state.
	*/
	recoveryLoopJobs() {
		return _assertClassBrand(_JobQueue_brand, this, _sql).call(this, "SELECT * FROM cf_agents_jobs WHERE recovery_loop = 1 ORDER BY time ASC").map(jobFromRow);
	}
	/**
	* Purge every recovery-loop job when the breaker seals at its strike
	* budget (#1825). Unrelated jobs are untouched.
	*/
	purgeRecoveryLoopJobs() {
		_assertClassBrand(_JobQueue_brand, this, _sql).call(this, "DELETE FROM cf_agents_jobs WHERE recovery_loop = 1");
	}
	/**
	* Apply one drive result, guarded on the dispatch marker: every driven
	* job carries `running = 1` for the duration of its dispatch, and a
	* same-id `push()` or `reschedule()` made meanwhile clears it. A cleared
	* marker means newer durable intent exists, so the outcome quietly
	* defers to it instead of deleting or retiming the fresher job.
	*/
	applyOutcome(id, outcome) {
		if (outcome === void 0) {
			_assertClassBrand(_JobQueue_brand, this, _sql).call(this, "DELETE FROM cf_agents_jobs WHERE id = ? AND running = 1", id);
			return;
		}
		if (outcome === "yield") {
			this.clearRunning(id);
			return;
		}
		if (typeof outcome === "object" && Number.isFinite(outcome.rescheduleAt) && outcome.rescheduleAt >= 0) {
			_assertClassBrand(_JobQueue_brand, this, _sql).call(this, `UPDATE cf_agents_jobs
         SET time = ?, running = 0, execution_started_at = NULL
         WHERE id = ? AND running = 1`, Math.floor(outcome.rescheduleAt), id);
			return;
		}
		throw new Error(`Invalid job outcome for ${id}`);
	}
	/**
	* The next physical alarm time derived from queue state, or `null` when
	* the queue holds nothing to wake for.
	*
	* Exclusive jobs suppress ordinary candidates. An ordinary candidate is
	* the earliest ready job clamped to the future (overdue rows survive
	* restarts and must re-fire immediately), merged with the earliest
	* hung-timeout recheck for in-flight single-flight jobs.
	*/
	nextAlarmTime(nowMs) {
		const exclusive = _assertClassBrand(_JobQueue_brand, this, _sql).call(this, "SELECT MIN(time) AS time FROM cf_agents_jobs WHERE exclusive = 1");
		if (exclusive[0]?.time !== null && exclusive[0]?.time !== void 0) return exclusive[0].time;
		const now = Math.floor(nowMs);
		let candidate = null;
		const ready = _assertClassBrand(_JobQueue_brand, this, _sql).call(this, `SELECT MIN(time) AS time FROM cf_agents_jobs
       WHERE singleflight = 0
          OR running = 0
          OR coalesce(execution_started_at, 0) + coalesce(hung_timeout_seconds, ?) * 1000 <= ?`, DEFAULT_HUNG_TIMEOUT_SECONDS, now);
		if (ready[0]?.time !== null && ready[0]?.time !== void 0) candidate = Math.max(ready[0].time, now + 1);
		const recheck = _assertClassBrand(_JobQueue_brand, this, _sql).call(this, `SELECT MIN(coalesce(execution_started_at, 0) + coalesce(hung_timeout_seconds, ?) * 1000) AS recheck
       FROM cf_agents_jobs
       WHERE singleflight = 1
         AND running = 1
         AND coalesce(execution_started_at, 0) + coalesce(hung_timeout_seconds, ?) * 1000 > ?`, DEFAULT_HUNG_TIMEOUT_SECONDS, DEFAULT_HUNG_TIMEOUT_SECONDS, now)[0]?.recheck;
		if (recheck !== null && recheck !== void 0) candidate = candidate === null ? recheck : Math.min(candidate, recheck);
		return candidate;
	}
};
function _sql(query, ...params) {
	_assertClassBrand(_JobQueue_brand, this, _ensureTable).call(this);
	try {
		return [..._classPrivateFieldGet2(_storage, this).sql.exec(query, ...params)];
	} catch (cause) {
		throw new SqlError(query, cause);
	}
}
function _ensureTable() {
	if (_classPrivateFieldGet2(_tableEnsured, this)) return;
	_classPrivateFieldGet2(_storage, this).sql.exec(`
      CREATE TABLE IF NOT EXISTS cf_agents_jobs (
        id TEXT PRIMARY KEY NOT NULL,
        capability TEXT NOT NULL,
        fn TEXT NOT NULL,
        time INTEGER NOT NULL,
        payload TEXT,
        retry_options TEXT,
        singleflight INTEGER NOT NULL DEFAULT 0,
        hung_timeout_seconds INTEGER,
        exclusive INTEGER NOT NULL DEFAULT 0,
        recovery_loop INTEGER NOT NULL DEFAULT 0,
        running INTEGER NOT NULL DEFAULT 0,
        execution_started_at INTEGER,
        created_at INTEGER NOT NULL DEFAULT (unixepoch())
      ) WITHOUT ROWID`);
	_classPrivateFieldSet2(_tableEnsured, this, true);
}
//#endregion
//#region src/lifecycle/job-driver.ts
/**
* Alarm event loop for the Lifecycle job queue.
*
* The driver owns everything that happens when the physical alarm fires:
* the deadman pre-arm, driving due jobs in due order (single-flight skip and
* hung recovery, per-job retries, platform-failure deferral, terminal
* failure hooks), the backlog warning, and the alarm memory-limit circuit
* breaker (#1825). Lifecycle wires it to the host and capabilities through
* the narrow {@link JobDriverOptions} contract and keeps only the alarm
* entry point itself.
*/
/** Default consecutive memory-limit strikes tolerated before sealing. */
const DEFAULT_MAX_ALARM_MEMORY_LIMIT_STRIKES = 3;
/** Durable storage key for the alarm memory-limit strike counter (#1825). */
const OOM_ALARM_STRIKES_KEY = "cf_agents:oom_alarm_strikes";
/** Default retry policy applied to jobs pushed without one. */
const DEFAULT_JOB_RETRY = {
	maxAttempts: 3,
	baseDelayMs: 100,
	maxDelayMs: 3e3
};
/** Due jobs for one capability above this count log a backlog warning. */
const JOB_BACKLOG_WARNING_THRESHOLD = 10;
/**
* Deadman pre-arm delay: armed before the event loop drives due jobs so an
* isolate death mid-drive still wakes this object to resume its queue.
*/
const DEADMAN_ALARM_DELAY_MS = 3e4;
/**
* Carries the row a platform failure escaped from out to `runAlarm`'s catch,
* across the rethrow from `#driveJob`. Attribution must not live in a shared
* instance field: overlapping `alarm()` invocations (a deadman or the
* platform's own re-fire racing a still-running invocation) dispatch jobs
* concurrently, and a field would let a later dispatch overwrite the row an
* earlier one is still unwinding for.
*/
var AttributedPlatformFailure = class {
	constructor(row, cause) {
		this.row = row;
		this.cause = cause;
	}
};
var _options = /* @__PURE__ */ new WeakMap();
var _alarmScope = /* @__PURE__ */ new WeakMap();
var _alarmsInFlight = /* @__PURE__ */ new WeakMap();
var _outstandingAlarmWork = /* @__PURE__ */ new WeakMap();
var _strike = /* @__PURE__ */ new WeakMap();
var _strikeRecordedThisIsolate = /* @__PURE__ */ new WeakMap();
var _JobDriver_brand = /* @__PURE__ */ new WeakSet();
/** @internal Drives the job queue when the Durable Object alarm fires. */
var JobDriver = class {
	constructor(options) {
		_classPrivateMethodInitSpec(this, _JobDriver_brand);
		_classPrivateFieldInitSpec(this, _options, void 0);
		_classPrivateFieldInitSpec(this, _alarmScope, new AsyncLocalStorage());
		_classPrivateFieldInitSpec(this, _alarmsInFlight, 0);
		_classPrivateFieldInitSpec(this, _outstandingAlarmWork, /* @__PURE__ */ new Set());
		_classPrivateFieldInitSpec(this, _strike, void 0);
		_classPrivateFieldInitSpec(this, _strikeRecordedThisIsolate, false);
		_classPrivateFieldSet2(_options, this, options);
	}
	/**
	* Run one alarm invocation: initialize the lifecycle, drive due jobs, run
	* the host's alarm callback, and re-arm the physical alarm from queue
	* state — all inside the alarm memory-limit circuit breaker (#1825). A
	* memory-limit reset that propagates here is intercepted — every other
	* error re-throws unchanged so platform alarm-retry semantics hold — and
	* broken from this outermost frame, where the heavy turn has unwound and
	* small writes can land. Initialization runs inside the breaker because a
	* severe reset can be thrown before any job runs (boot hydration, #1825);
	* left unhandled it would re-throw to the platform, which auto-retries
	* the alarm forever.
	*/
	async runAlarm(initialize, runHostAlarm) {
		var _this$alarmsInFlight;
		_classPrivateFieldSet2(_alarmsInFlight, this, (_this$alarmsInFlight = _classPrivateFieldGet2(_alarmsInFlight, this), _this$alarmsInFlight++, _this$alarmsInFlight));
		let clean = false;
		try {
			try {
				await initialize();
				await _assertClassBrand(_JobDriver_brand, this, _driveDueJobs).call(this);
				await _classPrivateFieldGet2(_alarmScope, this).run({ executing: void 0 }, runHostAlarm);
				clean = true;
			} catch (error) {
				const attributed = error instanceof AttributedPlatformFailure;
				const cause = attributed ? error.cause : error;
				if (!isDurableObjectMemoryLimitReset(cause)) throw attributed ? cause : error;
				await _assertClassBrand(_JobDriver_brand, this, _handleMemoryLimitReset).call(this, cause, attributed ? error.row : void 0);
				return;
			}
		} finally {
			var _this$alarmsInFlight3;
			_classPrivateFieldSet2(_alarmsInFlight, this, (_this$alarmsInFlight3 = _classPrivateFieldGet2(_alarmsInFlight, this), _this$alarmsInFlight3--, _this$alarmsInFlight3));
			if (clean) await _assertClassBrand(_JobDriver_brand, this, _clearMemoryLimitStrikesWhenQuiescent).call(this);
		}
		await _classPrivateFieldGet2(_options, this).rearm();
	}
	/**
	* Keep work a job handed off at a bounded return inside this alarm's
	* memory-limit breaker domain (#1825). The alarm itself returns promptly,
	* so other jobs stay live; the handoff is classified when it settles. A
	* memory-limit reset it reports records a strike against the job that
	* handed it off, exactly as an in-alarm reset would. Strikes clear only
	* once no handed-off work is outstanding and the last of it settled clean.
	*
	* @returns True when called from an alarm-driven dispatch or the host
	* alarm hook; false otherwise, in which case nothing is tracked. Tracking
	* the same promise again (a claim-backstop wake for an attempt already
	* handed off) is a no-op.
	*/
	trackAlarmWork(work) {
		const scope = _classPrivateFieldGet2(_alarmScope, this).getStore();
		if (!scope) return false;
		if (_classPrivateFieldGet2(_outstandingAlarmWork, this).has(work)) return true;
		_classPrivateFieldGet2(_outstandingAlarmWork, this).add(work);
		work.then(() => _assertClassBrand(_JobDriver_brand, this, _settleAlarmWork).call(this, work, void 0, scope.executing), (error) => _assertClassBrand(_JobDriver_brand, this, _settleAlarmWork).call(this, work, error, scope.executing));
		return true;
	}
};
async function _settleAlarmWork(work, error, executing) {
	try {
		if (_classPrivateFieldGet2(_options, this).disabled()) return;
		if (isDurableObjectMemoryLimitReset(error)) {
			await _assertClassBrand(_JobDriver_brand, this, _handleMemoryLimitReset).call(this, error, executing);
			return;
		}
	} finally {
		_classPrivateFieldGet2(_outstandingAlarmWork, this).delete(work);
	}
	await _assertClassBrand(_JobDriver_brand, this, _clearMemoryLimitStrikesWhenQuiescent).call(this);
}
/**
* Clear the strike counter once the alarm domain is fully quiescent: no
* alarm invocation in flight, no handed-off work outstanding, and no
* strike recorded in this isolate that a fresh isolate hasn't yet
* superseded. Called at every transition that could make either counter
* newly zero (an alarm ending, a handoff settling) — each call re-reads
* both fresh, so whichever transition happens last is the one that
* performs the clear. Idempotent: redundant calls no-op.
*/
async function _clearMemoryLimitStrikesWhenQuiescent() {
	if (_classPrivateFieldGet2(_alarmsInFlight, this) > 0) return;
	if (_classPrivateFieldGet2(_outstandingAlarmWork, this).size > 0) return;
	if (_classPrivateFieldGet2(_strikeRecordedThisIsolate, this)) return;
	_classPrivateFieldSet2(_strike, this, void 0);
	await _assertClassBrand(_JobDriver_brand, this, _clearMemoryLimitStrikes).call(this);
}
/** Drive every due job once, in due-time order. */
async function _driveDueJobs() {
	const nowMs = Date.now();
	const due = _classPrivateFieldGet2(_options, this).queue.due(nowMs);
	if (due.length === 0) return;
	_assertClassBrand(_JobDriver_brand, this, _warnBacklog).call(this, due);
	if (!_classPrivateFieldGet2(_options, this).disabled()) await _classPrivateFieldGet2(_options, this).storage.setAlarm(nowMs + DEADMAN_ALARM_DELAY_MS);
	for (const stale of due) {
		if (_classPrivateFieldGet2(_options, this).disabled()) return;
		const row = _classPrivateFieldGet2(_options, this).queue.dueRow(stale.id, nowMs);
		if (!row) continue;
		if (row.singleflight === 1 && row.running === 1) {
			if (!isHungRow(row, nowMs)) {
				console.warn(`Skipping job ${row.id}: previous execution still running`);
				continue;
			}
			console.warn(`Forcing reset of hung job ${row.id} (started ${Math.round((nowMs - (row.execution_started_at ?? 0)) / 1e3)}s ago)`);
		}
		_classPrivateFieldGet2(_options, this).queue.markRunning(row.id, nowMs);
		await _assertClassBrand(_JobDriver_brand, this, _driveJob).call(this, row);
	}
}
/** Dispatch one due row to its owner with retry and failure policy. */
async function _driveJob(row) {
	const { queue, resolveDispatch, disabled } = _classPrivateFieldGet2(_options, this);
	const job = jobFromRow(row);
	const dispatch = await resolveDispatch(row.capability);
	if (!dispatch) {
		console.error(`No installed capability or host handler for job ${row.id} (owner ${JSON.stringify(row.capability)}); dropping it`);
		queue.delete(row.id);
		return;
	}
	const maxAttempts = job.retry?.maxAttempts ?? DEFAULT_JOB_RETRY.maxAttempts;
	const slowWatchdog = setTimeout(() => {
		const seconds = Math.round(hungTimeoutMs(row) / 1e3);
		console.warn(`Job ${row.id} (${row.capability}/${row.fn}) has been dispatching for over ${seconds}s. Long dispatches starve every other job on this object; onJob must detach unbounded work and return.`);
		try {
			_classPrivateFieldGet2(_options, this).emit("job:slow_dispatch", {
				capability: row.capability,
				fn: row.fn,
				id: row.id,
				thresholdMs: hungTimeoutMs(row)
			});
		} catch {}
	}, hungTimeoutMs(row));
	let outcome;
	try {
		outcome = await _classPrivateFieldGet2(_alarmScope, this).run({ executing: row }, () => tryN(maxAttempts, (attempt) => dispatch.onJob({
			job,
			attempt
		}), {
			baseDelayMs: job.retry?.baseDelayMs ?? DEFAULT_JOB_RETRY.baseDelayMs,
			maxDelayMs: job.retry?.maxDelayMs ?? DEFAULT_JOB_RETRY.maxDelayMs,
			shouldRetry: (error) => !isDurableObjectCodeUpdateReset(error) && !isDurableObjectMemoryLimitReset(error)
		}));
	} catch (error) {
		if (disabled()) return;
		if (isPlatformFailure(error)) {
			try {
				queue.clearRunning(row.id);
			} catch {}
			console.warn(`Deferring job ${row.id} to a fresh invocation after a platform failure; the job is preserved.`);
			throw new AttributedPlatformFailure(row, error);
		}
		try {
			outcome = await dispatch.onJobError?.({
				job,
				attempt: maxAttempts
			}, error);
		} catch (hookError) {
			console.error(`Job failure hook threw for ${row.id}`, hookError);
		}
	} finally {
		clearTimeout(slowWatchdog);
	}
	if (disabled()) return;
	queue.applyOutcome(row.id, outcome ?? void 0);
}
function _warnBacklog(due) {
	const counts = /* @__PURE__ */ new Map();
	for (const row of due) counts.set(row.capability, (counts.get(row.capability) ?? 0) + 1);
	for (const [owner, count] of counts) {
		if (count < JOB_BACKLOG_WARNING_THRESHOLD) continue;
		try {
			console.warn(`Processing ${count} due jobs for ${JSON.stringify(owner)} in a single alarm cycle. This usually means one-shot jobs are pushed repeatedly without a stable id.`);
			_classPrivateFieldGet2(_options, this).emit("job:backlog_warning", {
				capability: owner,
				count
			});
		} catch {}
	}
}
/**
* Clear the durable memory-limit strike counter after a clean alarm so the
* breaker counts CONSECUTIVE resets rather than lifetime ones (#1825).
* Reads first and only writes when a strike is recorded. Best-effort.
*/
async function _clearMemoryLimitStrikes() {
	const { storage } = _classPrivateFieldGet2(_options, this);
	try {
		const prior = await storage.get(OOM_ALARM_STRIKES_KEY);
		if (typeof prior === "number" && prior > 0) await storage.delete(OOM_ALARM_STRIKES_KEY);
	} catch {}
}
/**
* Alarm-boundary circuit breaker for Durable Object memory-limit resets
* (#1825). Unhandled, the platform would auto-retry the alarm forever,
* re-running the doomed work each cycle. A durable strike counter
* tolerates a few consecutive resets — backing off the executing job and
* every pending recovery-loop job so the retry is not a hot loop — then
* seals: those jobs are purged and the capability + host memory-limit
* policy hooks run.
*
* One reset is one event even when several flows observe it. The strike
* is recorded once per event ({@link #recordMemoryLimitStrike}); every
* observer then applies the per-job policy for the job it belongs to, and
* the first observer finishes the event by re-arming, syncing, and
* resetting the isolate. Each step is best-effort: even these small writes
* can OOM, but swallowing still halts the platform's auto-retry, and a
* later wake re-arms legitimate work.
*/
async function _handleMemoryLimitReset(error, executing) {
	const { queue } = _classPrivateFieldGet2(_options, this);
	const first = _classPrivateFieldGet2(_strike, this) === void 0;
	_classPrivateFieldSet2(_strikeRecordedThisIsolate, this, true);
	_classPrivateFieldGet2(_strike, this) ?? _classPrivateFieldSet2(_strike, this, _assertClassBrand(_JobDriver_brand, this, _recordMemoryLimitStrike).call(this, error));
	const strike = await _classPrivateFieldGet2(_strike, this);
	try {
		if (executing) {
			if (strike.sealed) queue.delete(executing.id);
			else if (strike.nextTime !== void 0) queue.retime(executing.id, strike.nextTime);
		}
	} catch {}
	try {
		await _classPrivateFieldGet2(_options, this).onMemoryLimit({
			sealed: strike.sealed,
			nextTime: strike.nextTime,
			executing: executing ? jobFromRow(executing) : void 0,
			purgedRecoveryLoopJobs: first ? strike.purgedRecoveryLoopJobs : void 0
		});
	} catch {}
	if (!first) return;
	try {
		await _classPrivateFieldGet2(_options, this).rearm();
	} catch {}
	try {
		await _classPrivateFieldGet2(_options, this).storage.sync();
		_classPrivateFieldGet2(_options, this).reset(`Alarm memory-limit strike ${strike.strikes}/${strike.limit}${strike.sealed ? " (sealed)" : ""}; resetting isolate (#1825)`);
	} catch {}
}
/**
* Record one strike durably and apply the queue-wide policy that belongs
* to the event rather than to any one job: recovery-loop rows back off (or
* purge) as a pack, a sealing strike resets the counter, and the event is
* emitted once.
*/
async function _recordMemoryLimitStrike(error) {
	const { queue, storage } = _classPrivateFieldGet2(_options, this);
	let strikes = 1;
	try {
		const prior = await storage.get(OOM_ALARM_STRIKES_KEY);
		strikes = (typeof prior === "number" ? prior : 0) + 1;
		await storage.put(OOM_ALARM_STRIKES_KEY, strikes);
	} catch {}
	const limit = _classPrivateFieldGet2(_options, this).maxMemoryLimitStrikes() ?? DEFAULT_MAX_ALARM_MEMORY_LIMIT_STRIKES;
	const sealed = strikes >= limit;
	console.error(`Alarm hit a Durable Object memory-limit reset (strike ${strikes}/${limit}${sealed ? ", sealing recovery" : ", will retry with backoff"}). Breaking the platform alarm-retry loop (#1825).`, error instanceof Error ? error.message : String(error));
	const nextTime = sealed ? void 0 : Date.now() + Math.min(300, 30 * strikes) * 1e3;
	let purgedRecoveryLoopJobs;
	try {
		if (sealed) purgedRecoveryLoopJobs = queue.recoveryLoopJobs();
	} catch {}
	try {
		if (sealed) queue.purgeRecoveryLoopJobs();
		else if (nextTime !== void 0) queue.delayRecoveryLoopJobs(nextTime);
	} catch {}
	if (sealed) try {
		await storage.delete(OOM_ALARM_STRIKES_KEY);
	} catch {}
	try {
		_classPrivateFieldGet2(_options, this).emit("alarm:memory_limit_reset", {
			strikes,
			limit,
			sealed,
			error: error instanceof Error ? error.message : String(error)
		});
	} catch {}
	return {
		strikes,
		limit,
		sealed,
		nextTime,
		purgedRecoveryLoopJobs
	};
}
//#endregion
//#region src/lifecycle/transport-errors.ts
/** Standard `WebSocket.readyState` values. */
const CLOSING = 2;
const CLOSED = 3;
/**
* A retryable transport-teardown error ("Network connection lost" /
* "WebSocket peer disconnected") that fires on a connection which is already
* CLOSING/CLOSED is just the socket going away during or right after the close
* handshake - not an application error. Surfacing it via `onError` spams logs
* on every abrupt client disconnect, and even on clean closes when the peer
* tears down its transport before our reciprocal Close frame lands. Suppress
* it in that specific case only; genuine mid-connection (OPEN) errors still
* reach `onError`.
*
* Detection prefers the structured `retryable` flag over message text so it
* stays correct across `enhanced-error-serialization` (compat date
* >= 2026-04-21), with a substring fallback for older error shapes.
*/
function isBenignTeardownError(ws, error) {
	const state = ws.readyState;
	if (state !== CLOSING && state !== CLOSED) return false;
	if (typeof error !== "object" || error === null) return false;
	const typed = error;
	if (typed.retryable === true) return true;
	const message = typeof typed.message === "string" ? typed.message : "";
	return /Network connection lost|WebSocket peer disconnected/i.test(message);
}
//#endregion
//#region src/lifecycle/durable-object-lifecycle.ts
const LEGACY_NAME_STORAGE_KEY = "__ps_name";
function mutableRequest(request) {
	return new Request(request);
}
/**
* Decode props from the internal lifecycle props header.
*
* Handles both base64-encoded lifecycle props and, for
* backwards compatibility with stubs/requests created by older versions,
* raw JSON. Base64 never starts with `{` or `[`, so a leading brace/bracket
* unambiguously identifies the legacy raw-JSON form.
*/
function decodeProps(header) {
	const trimmed = header.trim();
	if (trimmed.startsWith("{") || trimmed.startsWith("[")) return JSON.parse(trimmed);
	const binary = atob(header);
	const bytes = new Uint8Array(binary.length);
	for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
	return JSON.parse(new TextDecoder().decode(bytes));
}
const lifecycleEventSinks = /* @__PURE__ */ new WeakMap();
const lifecycleRouteTransports = /* @__PURE__ */ new WeakMap();
const lifecycleHostInvokers = /* @__PURE__ */ new WeakMap();
/** @internal Adapt the host invocation boundary at a composition root. */
function setLifecycleHostInvoker(lifecycle, invoker) {
	lifecycleHostInvokers.set(lifecycle, invoker);
}
/** @internal Supply a host's routed Lifecycle transport. */
function setLifecycleRouteTransport(lifecycle, transport) {
	lifecycleRouteTransports.set(lifecycle, transport);
}
/** @internal Adapt Lifecycle's default diagnostics sink at a composition root. */
function setLifecycleEventSink(lifecycle, sink) {
	lifecycleEventSinks.set(lifecycle, sink);
}
/**
* Installs and coordinates the runtime lifecycle for a Durable Object.
*
* Construct this as an instance field on a class that directly extends
* `DurableObject`, then call {@link Lifecycle.installHandlers}
* from that class's constructor.
*
* @experimental The API surface may change before stabilizing.
*/
/** The dispatch hooks a catch-all can monopolize; uniqueness is per hook. */
const CATCH_ALL_HOOKS = ["onRequest", "onWebSocketUpgrade"];
var _host = /* @__PURE__ */ new WeakMap();
var _ctx = /* @__PURE__ */ new WeakMap();
var _parentClassName = /* @__PURE__ */ new WeakMap();
var _capabilities = /* @__PURE__ */ new WeakMap();
var _capabilityRunner = /* @__PURE__ */ new WeakMap();
var _jobQueue = /* @__PURE__ */ new WeakMap();
var _jobDriver = /* @__PURE__ */ new WeakMap();
var _status = /* @__PURE__ */ new WeakMap();
var _alarmRearmQueue = /* @__PURE__ */ new WeakMap();
var _rearmRequestedDuringStart = /* @__PURE__ */ new WeakMap();
var _pendingEvents = /* @__PURE__ */ new WeakMap();
var _alarmsDisabled = /* @__PURE__ */ new WeakMap();
var _capabilitiesLocked = /* @__PURE__ */ new WeakMap();
var _handlersInstalled = /* @__PURE__ */ new WeakMap();
var _Lifecycle_brand = /* @__PURE__ */ new WeakSet();
var _legacyName = /* @__PURE__ */ new WeakMap();
var _props = /* @__PURE__ */ new WeakMap();
var Lifecycle = class Lifecycle {
	/**
	* Construct and install a lifecycle in one explicit operation.
	*
	* @param host - The Durable Object whose runtime handlers the lifecycle owns.
	* @returns The installed lifecycle.
	*/
	static install(host, options) {
		const lifecycle = new Lifecycle(host, options);
		lifecycle.installHandlers();
		return lifecycle;
	}
	/**
	* Bind a lifecycle to a Durable Object instance without mutating its handlers.
	*
	* @param host - The Durable Object whose runtime lifecycle this object owns.
	* @param options - Policy configuration for this lifecycle.
	*/
	constructor(host, options) {
		_classPrivateMethodInitSpec(this, _Lifecycle_brand);
		_classPrivateFieldInitSpec(this, _host, void 0);
		_classPrivateFieldInitSpec(this, _ctx, void 0);
		_classPrivateFieldInitSpec(this, _parentClassName, void 0);
		_classPrivateFieldInitSpec(this, _capabilities, []);
		_classPrivateFieldInitSpec(this, _capabilityRunner, new CapabilityRunner(() => _classPrivateFieldGet2(_capabilities, this)));
		_classPrivateFieldInitSpec(this, _jobQueue, void 0);
		_classPrivateFieldInitSpec(this, _jobDriver, void 0);
		_classPrivateFieldInitSpec(this, _status, "zero");
		_classPrivateFieldInitSpec(this, _alarmRearmQueue, Promise.resolve());
		_classPrivateFieldInitSpec(this, _rearmRequestedDuringStart, false);
		_classPrivateFieldInitSpec(this, _pendingEvents, []);
		_classPrivateFieldInitSpec(this, _alarmsDisabled, false);
		_classPrivateFieldInitSpec(this, _capabilitiesLocked, false);
		_classPrivateFieldInitSpec(this, _handlersInstalled, false);
		_classPrivateFieldInitSpec(this, _legacyName, void 0);
		_classPrivateFieldInitSpec(this, _props, void 0);
		_classPrivateFieldSet2(_host, this, host);
		_classPrivateFieldSet2(_ctx, this, _classPrivateFieldGet2(_host, this).ctx);
		_classPrivateFieldSet2(_parentClassName, this, _classPrivateFieldGet2(_host, this).constructor.name);
		_classPrivateFieldSet2(_jobQueue, this, new JobQueue(_classPrivateFieldGet2(_ctx, this).storage));
		_classPrivateFieldSet2(_jobDriver, this, new JobDriver({
			queue: _classPrivateFieldGet2(_jobQueue, this),
			storage: _classPrivateFieldGet2(_ctx, this).storage,
			disabled: () => _classPrivateFieldGet2(_alarmsDisabled, this),
			resolveDispatch: (owner) => _assertClassBrand(_Lifecycle_brand, this, _resolveJobDispatch).call(this, owner),
			maxMemoryLimitStrikes: () => options?.maxAlarmMemoryLimitStrikes,
			onMemoryLimit: async (context) => {
				await _classPrivateFieldGet2(_capabilityRunner, this).memoryLimit(context);
				await runInLifecycleHostContext({ host: _classPrivateFieldGet2(_host, this) }, () => _classPrivateFieldGet2(_host, this).onAlarmMemoryLimit?.(context));
			},
			emit: (type, payload) => _assertClassBrand(_Lifecycle_brand, this, _emitCapabilityEvent).call(this, {
				source: "lifecycle",
				type,
				payload
			}),
			rearm: () => this.rearmAlarm(),
			reset: (reason) => {
				setTimeout(() => abortWithoutAlarmRetry(_classPrivateFieldGet2(_ctx, this), reason), 0);
			}
		}));
	}
	/**
	* Install platform fetch, alarm, and hibernating WebSocket handlers.
	*
	* Existing handlers are preserved for framework-owned dispatch such as the
	* Agent's sub-agent router and alarm circuit breaker. Calling this method
	* more than once is an error.
	*/
	installHandlers() {
		if (_classPrivateFieldGet2(_handlersInstalled, this)) throw new Error("Durable Object lifecycle handlers are already installed");
		_classPrivateFieldSet2(_handlersInstalled, this, true);
		const handlers = {
			fetch: this.fetch.bind(this),
			alarm: this.alarm.bind(this),
			webSocketMessage: this.webSocketMessage.bind(this),
			webSocketClose: this.webSocketClose.bind(this),
			webSocketError: this.webSocketError.bind(this)
		};
		for (const [name, handler] of Object.entries(handlers)) {
			if (name in _classPrivateFieldGet2(_host, this)) continue;
			Object.defineProperty(_classPrivateFieldGet2(_host, this), name, {
				value: handler,
				configurable: true
			});
		}
	}
	/**
	* Add a reusable capability before this lifecycle starts.
	*
	* Capabilities dispatch in registration order, except that a capability
	* declaring `claims: "catch-all"` always comes last, whenever it was
	* installed. Catch-alls are unique per dispatch hook: two may coexist
	* when they claim disjoint traffic (one `onRequest`, one
	* `onWebSocketUpgrade`), but a second catch-all for the same hook could
	* never be reached and is refused.
	*
	* @param capability - The capability to add.
	* @returns This lifecycle.
	*/
	use(capability) {
		if (_classPrivateFieldGet2(_capabilitiesLocked, this)) throw new Error("Lifecycle capabilities must be added before startup");
		const capabilityId = lifecycleCapabilityId(capability);
		if (capabilityId && _classPrivateFieldGet2(_capabilities, this).some((candidate) => lifecycleCapabilityId(candidate) === capabilityId)) throw new Error(`Lifecycle capability ${JSON.stringify(capabilityId)} is already installed`);
		const catchAllIndex = _classPrivateFieldGet2(_capabilities, this).findIndex((candidate) => candidate.claims === "catch-all");
		if (capability.claims === "catch-all") {
			for (const hook of CATCH_ALL_HOOKS) {
				if (!capability[hook]) continue;
				const rival = _classPrivateFieldGet2(_capabilities, this).find((candidate) => candidate.claims === "catch-all" && candidate[hook]);
				if (!rival) continue;
				const installed = lifecycleCapabilityId(rival);
				throw new Error(`Lifecycle already has a catch-all for ${hook}${installed ? ` (${JSON.stringify(installed)})` : ""}; a second one could never be reached`);
			}
			_classPrivateFieldGet2(_capabilities, this).push(capability);
		} else _classPrivateFieldGet2(_capabilities, this).splice(catchAllIndex === -1 ? _classPrivateFieldGet2(_capabilities, this).length : catchAllIndex, 0, capability);
		if (capability instanceof LifecycleCapability) bindLifecycleCapability(capability, _assertClassBrand(_Lifecycle_brand, this, _servicesForCapability).call(this, capability.capabilityId));
		return this;
	}
	/** @internal Deliver a generic capability envelope to this Lifecycle. */
	route(envelope) {
		return _assertClassBrand(_Lifecycle_brand, this, _dispatchRoute).call(this, envelope);
	}
	/**
	* Execute SQL queries against the Durable Object's database
	* @template T Type of the returned rows
	* @param strings SQL query template strings
	* @param values Values to be inserted into the query
	* @returns Array of query results
	*/
	sql(strings, ...values) {
		let query = "";
		try {
			query = strings.reduce((acc, str, i) => acc + str + (i < values.length ? "?" : ""), "");
			return [..._classPrivateFieldGet2(_ctx, this).storage.sql.exec(query, ...values)];
		} catch (error) {
			console.error(`failed to execute sql query: ${query}`, error);
			throw error;
		}
	}
	/**
	* Handle an incoming request for the owning Durable Object.
	*
	* Non-upgrade requests run through the capability middleware chain first,
	* then fall through to the host's `onRequest`.
	*/
	async fetch(request) {
		try {
			const encodedProps = request.headers.get("x-agents-lifecycle-props");
			if (encodedProps) {
				_classPrivateFieldSet2(_props, this, decodeProps(encodedProps));
				request = mutableRequest(request);
				request.headers.delete("x-agents-lifecycle-props");
			}
			await _assertClassBrand(_Lifecycle_brand, this, _ensureInitialized).call(this);
			if (request.headers.get("Upgrade")?.toLowerCase() !== "websocket") {
				const capabilityResponse = await runWithoutCurrentAgent(() => _classPrivateFieldGet2(_capabilityRunner, this).request({ request }));
				if (capabilityResponse !== void 0) return capabilityResponse;
				if (_classPrivateFieldGet2(_host, this).onRequest) return await runInLifecycleHostContext({
					host: _classPrivateFieldGet2(_host, this),
					request
				}, () => _classPrivateFieldGet2(_host, this).onRequest(request));
				return new Response("Not implemented", { status: 404 });
			} else {
				const upgradeResponse = await runWithoutCurrentAgent(() => _classPrivateFieldGet2(_capabilityRunner, this).webSocketUpgrade({ request }));
				if (upgradeResponse !== void 0) return upgradeResponse;
				return new Response("WebSocket upgrades are not enabled on this Durable Object. Install a capability that claims them (e.g. WebSockets).", { status: 404 });
			}
		} catch (err) {
			console.error(`Error in ${_classPrivateFieldGet2(_parentClassName, this)}:${_classPrivateFieldGet2(_ctx, this).id.name ?? "<unnamed>"} fetch:`, err);
			if (!(err instanceof Error)) throw err;
			if (request.headers.get("Upgrade") === "websocket") {
				const pair = new WebSocketPair();
				pair[1].accept();
				pair[1].send(JSON.stringify({ error: err.stack }));
				pair[1].close(1011, "Uncaught exception during session setup");
				return new Response(null, {
					status: 101,
					webSocket: pair[0]
				});
			} else return new Response(err.stack, { status: 500 });
		}
	}
	/** @internal Dispatch a hibernating WebSocket message. */
	async webSocketMessage(ws, message) {
		try {
			await _assertClassBrand(_Lifecycle_brand, this, _ensureInitialized).call(this);
			await runWithoutCurrentAgent(() => _classPrivateFieldGet2(_capabilityRunner, this).webSocketMessage(ws, message));
		} catch (e) {
			console.error(`Error in ${_classPrivateFieldGet2(_parentClassName, this)}:${_classPrivateFieldGet2(_ctx, this).id.name ?? "<unnamed>"} webSocketMessage:`, e);
		}
	}
	/** @internal Dispatch a hibernating WebSocket close. */
	async webSocketClose(ws, code, reason, wasClean) {
		try {
			await _assertClassBrand(_Lifecycle_brand, this, _ensureInitialized).call(this);
			await runWithoutCurrentAgent(() => _classPrivateFieldGet2(_capabilityRunner, this).webSocketClose(ws, code, reason, wasClean));
		} catch (e) {
			console.error(`Error in ${_classPrivateFieldGet2(_parentClassName, this)}:${_classPrivateFieldGet2(_ctx, this).id.name ?? "<unnamed>"} webSocketClose:`, e);
		}
	}
	/** @internal Dispatch a hibernating WebSocket error. */
	async webSocketError(ws, error) {
		if (isBenignTeardownError(ws, error)) return;
		try {
			await _assertClassBrand(_Lifecycle_brand, this, _ensureInitialized).call(this);
			await runWithoutCurrentAgent(() => _classPrivateFieldGet2(_capabilityRunner, this).webSocketError(ws, error));
		} catch (e) {
			console.error(`Error in ${_classPrivateFieldGet2(_parentClassName, this)}:${_classPrivateFieldGet2(_ctx, this).id.name ?? "<unnamed>"} webSocketError:`, e);
		}
	}
	/**
	* Start lifecycle capabilities and the owning Durable Object.
	*
	* Runtime fetch, alarm, and WebSocket entry points call this automatically.
	* RPC methods may call it explicitly because native RPC bypasses fetch.
	*
	* @param props - Optional properties supplied to capability and host startup.
	*/
	async start(props) {
		if (props !== void 0) _classPrivateFieldSet2(_props, this, props);
		await _assertClassBrand(_Lifecycle_brand, this, _ensureInitialized).call(this);
	}
	/**
	* The name used to address this Durable Object.
	*
	* Native `ctx.id.name` is authoritative. A read-only legacy storage fallback
	* lets objects created by older PartyServer releases migrate without new
	* name writes.
	*/
	get name() {
		const name = _classPrivateFieldGet2(_ctx, this).id.name ?? _classPrivateFieldGet2(_legacyName, this);
		if (name !== void 0) return name;
		throw new Error(`${_classPrivateFieldGet2(_parentClassName, this)} could not determine its Durable Object name. Address it with idFromName() or getByName(). In local development, update Wrangler/workerd and use a current compatibility_date. newUniqueId(), idFromString(), and names over 1,024 bytes do not expose ctx.id.name. Alarms created before 2026-03-15 must be rescheduled from a named fetch or RPC handler.`);
	}
	/**
	* The host's scoped access to the Lifecycle work queue. Items pushed here
	* are dispatched to the host's `onJob` inside the host invocation
	* boundary.
	*/
	get jobs() {
		return _assertClassBrand(_Lifecycle_brand, this, _jobsForOwner).call(this, HOST_JOB_CAPABILITY);
	}
	/**
	* Recompute the physical Durable Object alarm from job-queue state.
	*
	* Concurrent requests are serialized so a later durable-state change cannot
	* be overwritten by an earlier alarm calculation. Queue mutations call this
	* automatically; it stays public for composition roots and tests.
	*/
	async rearmAlarm() {
		if (_classPrivateFieldGet2(_alarmsDisabled, this)) return;
		if (_classPrivateFieldGet2(_status, this) === "starting") {
			_classPrivateFieldSet2(_rearmRequestedDuringStart, this, true);
			return;
		}
		const next = _classPrivateFieldGet2(_alarmRearmQueue, this).catch(() => {}).then(async () => {
			if (_classPrivateFieldGet2(_alarmsDisabled, this)) return;
			const alarm = _classPrivateFieldGet2(_jobQueue, this).nextAlarmTime(Date.now());
			if (alarm === null) await _classPrivateFieldGet2(_ctx, this).storage.deleteAlarm();
			else await _classPrivateFieldGet2(_ctx, this).storage.setAlarm(alarm);
		});
		_classPrivateFieldSet2(_alarmRearmQueue, this, next);
		await next;
	}
	/**
	* Keep work a job handed off at a bounded return inside the current
	* alarm's memory-limit breaker domain (#1825). Hosts call this where a
	* queue-driven callback detaches long work and returns.
	*
	* @returns True when called during an alarm invocation; false otherwise.
	*/
	trackAlarmWork(work) {
		return _classPrivateFieldGet2(_jobDriver, this).trackAlarmWork(work);
	}
	/** Dispose installed capabilities in reverse registration order. */
	async dispose() {
		await runWithoutCurrentAgent(() => _classPrivateFieldGet2(_capabilityRunner, this).dispose());
	}
	/** Permanently disable and clear alarms during explicit object teardown. */
	async disableAlarms() {
		_classPrivateFieldSet2(_alarmsDisabled, this, true);
		await _classPrivateFieldGet2(_alarmRearmQueue, this).catch(() => {});
		await _classPrivateFieldGet2(_ctx, this).storage.deleteAlarm();
	}
	/**
	* Run one alarm invocation. The job driver owns the event loop — deadman
	* pre-arm, due-job dispatch with retry and deferral policy, the alarm
	* memory-limit circuit breaker (#1825) — and re-arms the physical alarm
	* from queue state. The host's `onAlarm()` runs after due jobs, inside
	* the host invocation boundary.
	*/
	async alarm() {
		await _classPrivateFieldGet2(_jobDriver, this).runAlarm(() => _assertClassBrand(_Lifecycle_brand, this, _ensureInitialized).call(this), () => runInLifecycleHostContext({ host: _classPrivateFieldGet2(_host, this) }, async () => {
			await _classPrivateFieldGet2(_host, this).onAlarm?.();
		}));
	}
};
function _servicesForCapability(capabilityId) {
	const lifecycle = this;
	const envelope = (payload) => ({
		capability: capabilityId,
		source: lifecycleRouteTransports.get(lifecycle)?.source,
		payload
	});
	return Object.freeze({
		get name() {
			return lifecycle.name;
		},
		className: _classPrivateFieldGet2(_parentClassName, this),
		storage: _classPrivateFieldGet2(_ctx, this).storage,
		sockets: Object.freeze({
			accept: (ws, tags) => _classPrivateFieldGet2(_ctx, this).acceptWebSocket(ws, tags),
			get: (tag) => _classPrivateFieldGet2(_ctx, this).getWebSockets(tag)
		}),
		ready: () => _assertClassBrand(_Lifecycle_brand, this, _readyForCapabilityOperation).call(this),
		status: () => _classPrivateFieldGet2(_status, this),
		jobs: _assertClassBrand(_Lifecycle_brand, this, _jobsForOwner).call(this, capabilityId),
		trackAlarmWork: (work) => _classPrivateFieldGet2(_jobDriver, this).trackAlarmWork(work),
		runInHostContext: async (fn, scope) => _assertClassBrand(_Lifecycle_brand, this, _runInHostBoundary).call(this, fn, scope),
		events: Object.freeze({ emit: (type, payload) => _assertClassBrand(_Lifecycle_brand, this, _emitCapabilityEvent).call(this, {
			source: capabilityId,
			type,
			payload
		}) }),
		routes: Object.freeze({
			get source() {
				return lifecycleRouteTransports.get(lifecycle)?.source;
			},
			toRoot: (payload) => {
				const transport = lifecycleRouteTransports.get(lifecycle);
				return transport ? transport.toRoot(envelope(payload)) : _assertClassBrand(_Lifecycle_brand, this, _dispatchRoute).call(this, envelope(payload));
			},
			to: (target, payload) => {
				const transport = lifecycleRouteTransports.get(lifecycle);
				if (!transport) throw new Error("Lifecycle has no transport for routed capabilities");
				return transport.to(target, envelope(payload));
			}
		})
	});
}
/**
* Run a user callback inside the host invocation boundary — plain host
* context by default, or the composition root's substitute (Agent installs
* its tracing invocation scope).
*/
function _runInHostBoundary(fn, scope) {
	const boundary = lifecycleHostInvokers.get(this);
	return Promise.resolve(boundary ? boundary(fn, scope) : runInLifecycleHostContext({
		host: _classPrivateFieldGet2(_host, this),
		connection: scope?.connection,
		request: scope?.request
	}, fn));
}
async function _readyForCapabilityOperation() {
	if (_classPrivateFieldGet2(_status, this) === "starting" || _classPrivateFieldGet2(_status, this) === "started") return;
	await this.start();
}
async function _dispatchRoute(envelope) {
	await _assertClassBrand(_Lifecycle_brand, this, _ensureInitialized).call(this);
	return runWithoutCurrentAgent(() => _classPrivateFieldGet2(_capabilityRunner, this).route(envelope.capability, {
		source: envelope.source,
		payload: envelope.payload
	}));
}
function _emitCapabilityEvent(event) {
	if (event.source.trim() === "" || event.type.trim() === "") throw new Error("Lifecycle events require non-empty source and type");
	if (_classPrivateFieldGet2(_status, this) !== "started") {
		_classPrivateFieldGet2(_pendingEvents, this).push(event);
		return;
	}
	_assertClassBrand(_Lifecycle_brand, this, _publishCapabilityEvent).call(this, event);
}
function _publishCapabilityEvent(event) {
	runWithoutCurrentAgent(() => {
		const sink = lifecycleEventSinks.get(this);
		try {
			if (!sink) {
				publishDiagnosticsEvent({
					source: event.source,
					type: event.type,
					agent: _classPrivateFieldGet2(_parentClassName, this),
					name: this.name,
					payload: event.payload,
					timestamp: Date.now()
				});
				return;
			}
			const pending = sink(event);
			if (pending !== void 0) _classPrivateFieldGet2(_ctx, this).waitUntil(Promise.resolve(pending).catch((error) => {
				_assertClassBrand(_Lifecycle_brand, this, _reportEventSinkFailure).call(this, event, error);
			}));
		} catch (error) {
			_assertClassBrand(_Lifecycle_brand, this, _reportEventSinkFailure).call(this, event, error);
		}
	});
}
function _reportEventSinkFailure(event, error) {
	console.error(`Lifecycle event sink failed for ${event.source}:${event.type}`, error);
}
function _deliverPendingEvents() {
	for (const event of _classPrivateFieldGet2(_pendingEvents, this).splice(0)) _assertClassBrand(_Lifecycle_brand, this, _publishCapabilityEvent).call(this, event);
}
async function _ensureInitialized() {
	if (_classPrivateFieldGet2(_status, this) === "started") return;
	if (_classPrivateFieldGet2(_ctx, this).id.name === void 0 && _classPrivateFieldGet2(_legacyName, this) === void 0) _classPrivateFieldSet2(_legacyName, this, await _classPrivateFieldGet2(_ctx, this).storage.get(LEGACY_NAME_STORAGE_KEY));
	this.name;
	_classPrivateFieldSet2(_capabilitiesLocked, this, true);
	let error;
	await _classPrivateFieldGet2(_ctx, this).blockConcurrencyWhile(async () => {
		_classPrivateFieldSet2(_status, this, "starting");
		try {
			await runWithoutCurrentAgent(() => _classPrivateFieldGet2(_capabilityRunner, this).start({ props: _classPrivateFieldGet2(_props, this) }));
			await runInLifecycleHostContext({ host: _classPrivateFieldGet2(_host, this) }, () => _classPrivateFieldGet2(_host, this).onStart?.(_classPrivateFieldGet2(_props, this)));
			_classPrivateFieldSet2(_status, this, "started");
		} catch (cause) {
			_classPrivateFieldSet2(_status, this, "zero");
			error = cause;
		}
	});
	if (error) {
		_classPrivateFieldSet2(_rearmRequestedDuringStart, this, false);
		_classPrivateFieldGet2(_pendingEvents, this).length = 0;
		throw error;
	}
	_assertClassBrand(_Lifecycle_brand, this, _deliverPendingEvents).call(this);
	if (_classPrivateFieldGet2(_rearmRequestedDuringStart, this)) {
		_classPrivateFieldSet2(_rearmRequestedDuringStart, this, false);
		await this.rearmAlarm();
	}
}
function _jobsForOwner(owner) {
	const rearmAfter = async (mutate) => {
		const result = mutate();
		await this.rearmAlarm();
		return result;
	};
	return Object.freeze({
		push: (options) => rearmAfter(() => _classPrivateFieldGet2(_jobQueue, this).push(owner, options)),
		cancel: (id) => rearmAfter(() => _classPrivateFieldGet2(_jobQueue, this).cancel(owner, id)),
		reschedule: (id, time) => rearmAfter(() => _classPrivateFieldGet2(_jobQueue, this).reschedule(owner, id, time)),
		get: (id) => _classPrivateFieldGet2(_jobQueue, this).get(owner, id),
		list: () => _classPrivateFieldGet2(_jobQueue, this).list(owner),
		rearm: () => this.rearmAlarm()
	});
}
/**
* Resolve a job owner to its dispatch hooks. Host jobs run inside the
* host invocation boundary; capability jobs run outside ambient host
* context, like every other capability hook.
*/
async function _resolveJobDispatch(owner) {
	if (owner === "host") {
		const host = _classPrivateFieldGet2(_host, this);
		if (!host.onJob) return void 0;
		return { onJob: async (context) => runInLifecycleHostContext({ host }, () => host.onJob(context)) };
	}
	const capability = await _classPrivateFieldGet2(_capabilityRunner, this).findById(owner);
	if (!capability?.onJob) return void 0;
	return {
		onJob: async (context) => runWithoutCurrentAgent(() => capability.onJob(context)),
		onJobError: capability.onJobError ? async (context, error) => runWithoutCurrentAgent(() => capability.onJobError(context, error)) : void 0
	};
}
//#endregion
export { abortWithoutAlarmRetry as a, setLifecycleRouteTransport as i, setLifecycleEventSink as n, setLifecycleHostInvoker as r, Lifecycle as t };

//# sourceMappingURL=lifecycle-Mm_jQh7r.js.map