/** SDK-owned platform module. This implementation is maintained in goodvibes-sdk. */ /** * Live process registry, one queryable + subscribable aggregation * surface over the already-composed runtime managers. ZERO new store state: * every query is an aggregate-on-read over the managers' in-memory maps, and * the only registry-owned mutable state is the agent activity side-table fed * by EXISTING runtime-bus 'agents' events (no new event contract). * * Pattern precedent: platform/core/orchestrator-context-runtime.ts already * aggregates agentManager.list() + wrfcController.listChains() into a * read-only context; this module generalizes that into a durable registry. */ import type { AgentManager } from '../../tools/agent/manager.js'; import type { WrfcController } from '../../agents/wrfc-controller.js'; import type { ProcessManager } from '../../tools/shared/process-manager.js'; import type { WatcherRegistry } from '../../watchers/registry.js'; import type { ScheduleManager, TriggerManager, WorkflowManager } from '../../tools/workflow/index.js'; import type { AutomationManager } from '../../automation/index.js'; import type { ApprovalBroker } from '../../control-plane/approval-broker.js'; import type { SharedSessionBroker } from '../../control-plane/session-broker.js'; import type { AgentMessageBus } from '../../agents/message-bus.js'; import type { RuntimeEventBus } from '../events/index.js'; import type { ProcessRegistry, ProcessUsage } from './types.js'; import type { TriggerManager as WatcherTriggerManager } from '../../triggers/manager.js'; import type { CodeIndexProcessSource } from './adapters/code-index.js'; import type { ObservedAgentSource } from './observed/source.js'; import type { AcpHostService } from '../../acp/host.js'; import type { OrchestrationEngine } from '../../orchestration/engine.js'; /** Default stalled threshold: running agent with no bus activity for this long → 'stalled'. */ export declare const DEFAULT_STALLED_THRESHOLD_MS = 20000; /** Default coalesced tick interval for subscriber notification. */ export declare const DEFAULT_TICK_INTERVAL_MS = 750; /** * TTL for a steer message, deliberately much larger than * AgentMessageBus's own DEFAULT_TTL_MS (5 min, message-bus-core.ts). A * steer queued against an agent mid long-running tool call (build, test * suite) must survive the wait for that tool to return rather than * silently expiring before the agent reaches its next turn boundary. */ export declare const STEER_TTL_MS: number; /** Injectable timer seam so tests can drive/observe the coalesced tick. */ export interface RegistryTimers { setInterval(callback: () => void, intervalMs: number): unknown; clearInterval(handle: unknown): void; } /** * Narrow structural deps, a pick of each manager's read/control surface, NOT * the whole RuntimeServices, so the registry stays testable with stubs and * cannot participate in a construction cycle. */ export interface ProcessRegistryDeps { readonly agentManager: Pick & Partial>; readonly wrfcController: Pick; /** * Optional: folds workstream/phase/work-item nodes into * the fleet, nested workstream -> phase -> work-item, mirroring the * wrfc-chain/subtask nesting. Without this dep the registry degrades to * exactly today's behavior, no orchestration nodes, no new capability. * * `kill` is used (not a raw AgentManager.cancel cascade like the wrfc-chain * path) so a fleet-initiated kill goes through the SAME * engine.kill(itemId) path as an engine-internal caller: it aborts the * item's registered AbortController (reaching an in-flight exec/fetch * tool's child process, not just the agent's next turn-boundary poll) AND * updates the engine's own WorkItem.state bookkeeping. Bypassing it would * silently reopen the orphaned-child-process gap for this one kill path. */ readonly orchestrationEngine?: Pick | undefined; readonly processManager: Pick; readonly watcherRegistry: Pick; readonly workflow: { readonly workflowManager: Pick; /** `enable` backs ProcessRegistry.resume(), the inverse of `disable`'s interrupt/pause. */ readonly triggerManager: Pick; readonly scheduleManager: Pick; }; /** * Optional: the trigger family's supervisor (stream watchers, condition * checks, on-exit process triggers). When present its records fold in as * 'trigger' nodes alongside the workflow tool's event triggers, the two are * told apart by `isWatcherTriggerRaw`, never by kind alone, so a control verb * can never be routed to the wrong manager. Absent (the default, and the * case whenever watchers.triggers.enabled is false) ⇒ exactly today's * behavior: zero extra nodes, no new capability. */ readonly triggerSupervisor?: Pick | undefined; /** Optional: awaiting-approval derivation. Non-control-plane runtimes still build a fleet. */ readonly approvalBroker?: Pick | undefined; /** Optional: populates ProcessNode.sessionRef.sessionId (tab attach point). */ readonly sessionBroker?: Pick | undefined; /** * Optional: the repo source-tree code index (Stage A). * When present, its build/idle state surfaces as a single 'code-index' * ProcessNode. Without this dep the fleet degrades to exactly today's * behavior, zero code-index nodes, no new capability. */ readonly codeIndexService?: CodeIndexProcessSource | undefined; /** Optional: hosted third-party ACP agents fold in as 'acp-agent' nodes (steer = next prompt, kill = stop, permission ask = awaiting-approval). Absent ⇒ exactly today's behavior. */ readonly acpHost?: Pick | undefined; /** Optional: externally-launched agents observed read-only on the host fold in as 'observed-external' rows (steer = the foreign session's own channel, e.g. tmux; stop never offered; NOT counted against fleet.maxSize). Absent ⇒ exactly today's behavior. */ readonly observedAgents?: Pick | undefined; /** * Optional: folds `/schedule` automation jobs * (platform/automation, a SEPARATE subsystem from the workflow-tool's * ScheduleManager above) into the fleet as 'schedule'-kind nodes, see * adapters/automation.ts. Without this dep the fleet degrades to exactly * today's behavior, zero automation-job nodes, no new capability. */ readonly automationManager?: Pick | undefined; /** * Optional: backs `steer()` and the `steerable` capability. The * bus already exists in the composed runtime and already feeds every * in-process agent's per-turn inbox drain (orchestrator-runner.ts), this * just hands the registry a narrow `send`-only pick of it. Without this * dep, steer() always refuses and steerable is false everywhere * (graceful degrade, matches the approvalBroker/sessionBroker pattern). */ readonly messageBus?: Pick | undefined; /** Optional: feeds the fine-grained agent activity side-table. Without it the registry degrades to coarse states. */ readonly runtimeBus?: RuntimeEventBus | undefined; /** Optional: honest cost pricing. Return null when the model is unknown, NEVER fabricate. */ readonly priceUsage?: ((model: string | undefined, usage: ProcessUsage) => number | null) | undefined; /** Optional: provenance for the same resolution priceUsage prices with (costSource + as-of date on priced nodes). */ readonly priceProvenance?: ((model: string | undefined) => { readonly source: 'user' | 'provider' | 'catalog'; readonly asOf?: string | undefined; } | null) | undefined; readonly now?: (() => number) | undefined; readonly stalledThresholdMs?: number | undefined; /** Stall-tell threshold: a live node quiet this long gains the marker (default 5 min). */ readonly stallTellMs?: number | undefined; readonly tickIntervalMs?: number | undefined; readonly timers?: RegistryTimers | undefined; } /** Create the live process registry over the already-composed managers. */ export declare function createProcessRegistry(deps: ProcessRegistryDeps): ProcessRegistry; //# sourceMappingURL=registry.d.ts.map