/** * MissionRegistry — Phase 1.f in-process tracker for active missions. * * Each adapter (Claude Code MCP server, OpenClaw plugin, Gemini CLI) * keeps a module-level registry. When `run_mission` starts, the adapter * registers a fresh cancellation token under a unique `mission_id` and * returns the id in the tool response. A sibling `mission_cancel` tool * call then looks up the token by id and flips `cancelled = true` — the * mission runner picks that up at the next step boundary and stops * gracefully. * * Lifetime semantics: * - `register()` returns the cancellation token AND a `dispose()` * callback the caller is expected to invoke in a `finally` block * once the mission ends (regardless of outcome). Disposal removes * the entry so a subsequent cancel doesn't silently target a * completed mission and the in-memory map stays small. * - `cancel()` is idempotent — calling it on a missing id returns * `{ found: false }`; calling it twice on the same id is a no-op * after the first. * * Why in-process (not cross-process)? Cancellation is fundamentally * "stop the dispatcher I'm running"; that dispatcher is local to the * adapter process. Cross-agent coordination is Phase 4. The transcript * subsystem (memory) handles the "different agent reads what I did" * story orthogonally. */ import type { MissionCancellationToken } from "./mission.js"; /** One registered mission. */ export interface MissionRegistryEntry { mission_id: string; /** Adapter-supplied label for diagnostics (e.g. mission.name). */ name?: string; /** ms since epoch when the mission was registered. */ started_at: number; /** The token the mission runner reads each step (cancel + pause). */ cancellation: MissionCancellationToken; } /** * Generate a stable, URL-safe mission identifier. * * Uses `crypto.randomUUID()` when available (Node 14.17+, Bun, modern * browsers); falls back to a Math.random hex string with a `mns_` prefix. * Either way the id is opaque to downstream consumers — they just echo * it back to `mission_cancel` / `mission_pause` / `memory_recall`. */ export declare function generateMissionId(): string; /** * Compute the canonical memory namespace for a mission's transcripts. * * The convention is `mission:` so a downstream agent can recall * every step the first agent ran via * `memory_recall({ namespace: "mission:", query: "" })`. This lives * here (not in the memory module) because the adapter's transcript * sink uses it and we want exactly one source of truth. */ export declare function missionTranscriptNamespace(missionId: string): string; export declare class MissionRegistry { private readonly entries; /** * Register a fresh mission, returning the entry (with the * cancellation token to hand to `runMission`) and a `dispose` hook * to invoke when the mission ends. The id is caller-supplied so * adapters can echo it in the tool response before this point. */ register(missionId: string, opts?: { name?: string; }): { entry: MissionRegistryEntry; dispose: () => void; }; /** * Flip the cancellation token for the named mission. * * Returns `{ found: true }` when the mission existed (whether it was * already cancelled or not), `{ found: false }` when the id is * unknown (e.g. mission already finished + disposed). */ cancel(missionId: string, reason?: string): { found: boolean; alreadyCancelled: boolean; }; /** * Pause the named mission at the next step boundary. * Idempotent — pausing an already-paused mission is a no-op. */ pause(missionId: string, reason?: string): { found: boolean; alreadyPaused: boolean; }; /** * Resume a paused mission. Idempotent when not paused. */ resume(missionId: string): { found: boolean; wasPaused: boolean; }; /** True when the named mission is currently registered. */ has(missionId: string): boolean; /** * Snapshot of the active mission set (for diagnostics / mission_list * tools down the road). Returns a shallow copy so callers can't * mutate internal state. */ list(): MissionRegistryEntry[]; /** Test-only: drop every registered mission. */ _clear(): void; } //# sourceMappingURL=mission-registry.d.ts.map