UNPKG

agents

Version:

A home for your AI agents

137 lines (136 loc) 5.63 kB
import { i as _classPrivateFieldInitSpec, n as _classPrivateFieldSet2, r as _assertClassBrand, t as _classPrivateFieldGet2 } from "../classPrivateFieldGet2-DZBYAB34.js"; import { t as LifecycleCapability } from "../capability-B4WbF81e.js"; import { t as _classPrivateMethodInitSpec } from "../classPrivateMethodInitSpec-qMjJ6sHQ.js"; //#region src/state/index.ts /** * Namespaced KV key holding this capability's schema version. Kept separate * from the host's global schema version so State owns its own migrations * without gating the host's DDL. */ const STATE_SCHEMA_VERSION_KEY = "cf_agents:state_schema_version"; const CURRENT_STATE_SCHEMA_VERSION = 1; /** Row id under which the single state value is stored in `cf_agents_state`. */ const STATE_ROW_ID = "cf_state_row_id"; /** * Legacy row written by SDKs that predate the single-row state optimization. * Never written now; the v1 migration deletes it. */ const LEGACY_WAS_CHANGED_ROW_ID = "cf_state_was_changed"; /** * Sentinel distinguishing "state not yet loaded / never set" from a stored * value. A distinct object reference means falsy states (null, 0, false, "") * still read back as set. */ const DEFAULT_STATE = {}; var _state = /* @__PURE__ */ new WeakMap(); var _tableEnsured = /* @__PURE__ */ new WeakMap(); var _options = /* @__PURE__ */ new WeakMap(); var _State_brand = /* @__PURE__ */ new WeakSet(); /** * Durable state storage for a Lifecycle Object. * * Owns the `cf_agents_state` state row, lazy load with an in-memory cache, and * validated persistence. Install the instance with `Lifecycle.use()`. State * validation and the post-change notification hook stay on the host, which * injects both callbacks. This capability never touches connections. * * @experimental The API surface may change before stabilizing. */ var State = class extends LifecycleCapability { /** * Create a durable state capability. * * @param options - Optional initial state and a synchronous validation hook * injected by the host. */ constructor(options = {}) { super("state"); _classPrivateMethodInitSpec(this, _State_brand); _classPrivateFieldInitSpec(this, _state, DEFAULT_STATE); _classPrivateFieldInitSpec(this, _tableEnsured, false); _classPrivateFieldInitSpec(this, _options, void 0); _classPrivateFieldSet2(_options, this, options); } /** Initialize state storage during Lifecycle startup. */ async onStart() { if ((await this.lifecycle.storage.get(STATE_SCHEMA_VERSION_KEY) ?? 0) >= CURRENT_STATE_SCHEMA_VERSION) { _classPrivateFieldSet2(_tableEnsured, this, true); return; } _assertClassBrand(_State_brand, this, _ensureTable).call(this); this.lifecycle.storage.sql.exec("DELETE FROM cf_agents_state WHERE id = ?", LEGACY_WAS_CHANGED_ROW_ID); await this.lifecycle.storage.put(STATE_SCHEMA_VERSION_KEY, CURRENT_STATE_SCHEMA_VERSION); } /** * Current state. * * Loads lazily from storage on first access and caches in memory. Row * existence in `cf_agents_state` is the signal that state was previously * set, so falsy values persist correctly. On a corrupt row, falls back to * the initial state (re-persisting it) or clears the row. */ get() { if (_classPrivateFieldGet2(_state, this) !== DEFAULT_STATE) return _classPrivateFieldGet2(_state, this); _assertClassBrand(_State_brand, this, _ensureTable).call(this); const result = this.lifecycle.storage.sql.exec("SELECT state FROM cf_agents_state WHERE id = ?", STATE_ROW_ID).toArray(); if (result.length > 0) { const state = result[0].state; try { _classPrivateFieldSet2(_state, this, JSON.parse(state)); } catch (e) { console.error("Failed to parse stored state, falling back to initialState:", e); const initial = _classPrivateFieldGet2(_options, this).initialState; if (initial !== void 0) { _classPrivateFieldSet2(_state, this, initial); this.set(initial, "server"); } else { this.lifecycle.storage.sql.exec("DELETE FROM cf_agents_state WHERE id = ?", STATE_ROW_ID); return; } } return _classPrivateFieldGet2(_state, this); } const initial = _classPrivateFieldGet2(_options, this).initialState; if (initial === void 0) return; this.set(initial, "server"); return initial; } /** * Validate and persist a state change, then call the change hook. * * @param nextState - The new state to persist. * @param source - `"server"` for host-originated changes, or the originating * connection for client-originated changes. * @throws Whatever the injected `validateStateChange` throws. */ set(nextState, source = "server") { _classPrivateFieldGet2(_options, this).validateStateChange?.(nextState, source); _assertClassBrand(_State_brand, this, _ensureTable).call(this); const serialized = JSON.stringify(nextState); this.lifecycle.storage.sql.exec("INSERT OR REPLACE INTO cf_agents_state (id, state) VALUES (?, ?)", STATE_ROW_ID, serialized); _classPrivateFieldSet2(_state, this, nextState); let pending; try { pending = _classPrivateFieldGet2(_options, this).onChanged?.(nextState, source); } catch (error) { console.error("State onChanged hook failed:", error); return; } if (pending) Promise.resolve(pending).catch((error) => { console.error("State onChanged hook failed:", error); }); } }; function _ensureTable() { if (_classPrivateFieldGet2(_tableEnsured, this)) return; this.lifecycle.storage.sql.exec(` CREATE TABLE IF NOT EXISTS cf_agents_state ( id TEXT PRIMARY KEY NOT NULL, state TEXT ) `); _classPrivateFieldSet2(_tableEnsured, this, true); } //#endregion export { State }; //# sourceMappingURL=index.js.map