import { type ApprovalVerdict } from './approval-decider.js'; import * as approvalOps from './approvals.js'; import type { BrokerLease } from './broker.js'; import type { OrgBus } from './bus.js'; import * as crossOrg from './cross-org.js'; import type { DaemonLockHandle } from './daemon-lock.js'; import type { AgentRuntime, DaemonArgs, DaemonOpts, RunningOrg } from './daemon-types.js'; import * as decisionOps from './decisions.js'; import * as orgMemory from './org-memory.js'; import * as orgStart from './org-start.js'; import * as orgStateFile from './org-state-file.js'; import * as questionOps from './questions.js'; import type { RunSummary } from './reporting.js'; import * as roleIncarnation from './role-incarnation.js'; import type { ResetReceipt } from './role-reset.js'; import type { RespawnReceipt } from './role-slot.js'; import { type RoleTrace } from './role-trace.js'; import { type RuntimeOptionsReceipt } from './runtime-options.js'; import * as scheduler from './scheduler-integration.js'; import { ToolProviderHub } from './tool-providers.js'; import { type BusEvent, type DecisionGate, type OrgDef } from './types.js'; export { type AgentRuntime, activeRoleCount, type DaemonOpts, type RunningOrg, roleTokenBudget, ScrollbackBuffer, } from './daemon-types.js'; export { resolvedIdleNudgeCount } from './idle-watchdog.js'; export { resolveOrgComplete } from './role-session-opts.js'; export { type ProviderKind, type RuntimeKind, resolveRoleRunner, resolveRunner, } from './runner-resolve.js'; export { resolveAutoAssignee } from './task-match.js'; export declare class OrgDaemon { /** @internal */ root: string; /** @internal */ opts: DaemonOpts; /** @internal */ orgs: Map; /** @internal GA row R1: the OS-held owner lock of each running sections org. */ daemonLocks: Map; /** @internal */ waking: Set; /** @internal */ globalSubscribers: Set<(e: BusEvent) => void>; /** @internal */ leases: Map; /** @internal */ forwarders: Map Promise; unsubscribe: () => void; }>; /** @internal */ watchdogs: Map; /** @internal */ leadWatches: Map void>; /** @internal */ stopping: Map>; /** @internal Bug 2 (TOCTOU race): names currently reserved by an in-flight * startOrg() call, from the synchronous existence check through * registration in `orgs`. Closes the window where two concurrent * startOrg(name) calls could both pass the `orgs.has(name)` check before * either registered and spawn duplicate runs. */ /** @internal */ startingOrgs: Set; /** @internal */ approvals: Map; /** @internal #345: per org, the actions `org run --auto-approve` pre-approved * for the current run (approvals.ts's checkApproval). Kept across a boss * auto-restart, replaced by every other start. */ runAutoApprove: Map; /** @internal */ approvalLocks: Map>; /** @internal */ gatesLocks: Map>; /** @internal */ questionsLocks: Map>; /** @internal */ spawning: Map>; static readonly MAX_BOSS_RESTARTS = 2; static readonly BOSS_RESTART_BACKOFF_MS: number[]; /** @internal */ bossRestartCounts: Map; /** @internal */ restarting: Set; /** @internal */ static readonly CONTEXT_LIMIT_RE: RegExp; /** @internal */ recallUsage: Map>; /** @internal */ orgLearnedRuns: Set; /** @internal */ abandoned: Map>; /** #293: per-org reason the last run's cross-run memory was NOT stored. * persistState() writes it into runtime.json so `org status` can still * explain an empty org_recall long after the run. */ /** @internal */ memoryErrors: Map; /** M1: role tool-provider tool-list cache and live provider processes. */ /** @internal */ toolProviders: ToolProviderHub; constructor( /** @internal */ root: string, /** @internal */ opts?: DaemonOpts); /** Publish this daemon's inbox so orgs started AFTER this call register with the broker. */ setInboxUrl(url: string, operatorCredential?: string): void; /** subscribe to events from ALL running orgs (dashboard server uses this) */ subscribe(fn: (e: BusEvent) => void): () => void; listOrgs(): RunningOrg[]; getOrg(name: string): RunningOrg | undefined; /** Hot-reload an org definition from disk without stopping running sessions. * Applies: goal, run_config, schedule. New roles are added as pending (lazy-spawnable). * Removed roles are NOT killed — they finish their current work and won't be re-spawned. * Returns a summary of what changed. */ reloadOrgDef(name: string): { changed: string[]; newRoles: string[]; removedRoles: string[]; }; /** Names of the orgs this daemon currently has running. Snapshot — safe to * iterate while stopOrg() mutates the underlying map. */ listRunning(): string[]; /** M1: the chain trace a role's tool calls carry — from the most recent * message delivered to it with a `[trace chn_… hop=N]` line, otherwise a * fresh chain (hop 0) minted once and kept for the role — plus the role's * turn (#327, role-trace.ts). */ roleTrace(org: string, role: string): RoleTrace; /** Hook for the SSE server — registers a listener for all bus events across all orgs. */ onBusEvent?: (fn: (e: BusEvent) => void) => void; /** Snapshot of all running orgs for dashboard initial load. */ getStatusSnapshot?: () => Record; /** Resolve run_config.workspace to 'repo' | 'isolated' | an absolute path. * A relative path is resolved against the project root rather than the * daemon's cwd, which is not the same directory when `org serve` is started * from a subdirectory. */ /** @internal */ workspaceSetting(def: OrgDef): string; /** @internal Frees the sections owner lock of `name`, if this daemon holds one. */ releaseDaemonLock(name: string): void; startOrg(...args: DaemonArgs): Promise; /** Build one role incarnation: mailbox, policy, AgentRuntime, sessionOpts, * and the supervised crash-retry loop. Used by BOTH the startup lazy-spawn * path (generation 0, via the `spawnRole` closure inside startOrgInner) * and respawnRole() (generation N+1). Does not touch running.agents or * running.roleSlots — callers publish the result themselves. */ spawnRoleIncarnation(...args: DaemonArgs): { runtime: AgentRuntime; abort: AbortController; }; /** org_respawn_role's daemon-owned implementation. See the design doc's * "Replacement algorithm" (13 steps) — this method's body follows those * steps in order, numbered in comments. */ respawnRole(name: string, callerId: string, rawInput: unknown): Promise; /** org_compact_role's daemon-owned implementation (role-reset.ts). */ compactRole(name: string, callerId: string, rawInput: unknown): Promise; /** org_clear_role's daemon-owned implementation (role-reset.ts). */ clearRole(name: string, callerId: string, rawInput: unknown): Promise; /** @internal */ hasOrgDef(name: string): boolean; /** @param opts.drainMs how long to let in-flight agent sessions finish before * reaping. Defaults to the short abort bound; the planned-completion path * passes a far longer window (see COMPLETE_DRAIN_MS). * @param opts.closedBy #206: tags WHY the run ended, persisted into * runtime.json so `org run` can tell a clean, goal-driven end * (closedBy: 'org-complete') from every other kind of stop (idle * watchdog, boss-restart-exhausted, manual `org stop`) and exit non-zero * for the latter. Only the org_complete auto-stop path passes this. */ stopOrg(name: string, opts?: { drainMs?: number; closedBy?: string; }): Promise; stopAll(): Promise; /** @internal * @param closedBy #206: why the run ended — 'org-complete' for a clean, * goal-driven end (the only value any caller currently passes); absent for * every other stop (idle watchdog, boss-restart-exhausted, manual `org * stop`). Mirrors persistCrashStateAll()'s existing closedBy: 'crash-handler' * for the process-crash path, which org.ts already reads. */ persistState(...args: DaemonArgs): void; /** Mark every currently-running org as crashed in runtime.json. * Called from process-level crash handlers — must be synchronous and best-effort. * @param error the uncaught error/rejection reason, if known — without * this, `runOutcomeResult` (org.ts)'s "crashed: " message always * read "crashed: unknown error" regardless of what actually happened. */ persistCrashStateAll(error?: string): void; /** Write a heartbeat file so `org status` can distinguish "daemon alive" from * "daemon gone" even when runtime.json still says running. */ writeHeartbeat(): void; clearHeartbeat(): void; /** @internal */ checkApproval(org: string, role: string, action: string, input: Record): Promise; /** @internal #553: checkApproval that waits inline when a decider owns it. */ awaitApproval(org: string, role: string, action: string, input: Record): Promise; setApproval(...args: DaemonArgs): Promise<{ ok: true; } | { ok: false; error: string; }>; askHuman(org: string, role: string, question: string, blocking?: boolean): Promise; answerQuestion(...args: DaemonArgs): ReturnType; dismissQuestion(...args: DaemonArgs): ReturnType; /** @internal */ readGates(org: string): { gates: DecisionGate[]; }; createGate(org: string, role: string, name: string, description: string): Promise; resolveGate(...args: DaemonArgs): Promise<{ ok: true; } | { ok: false; error: string; }>; listGates(org: string, status?: 'pending' | 'approved' | 'rejected'): DecisionGate[]; /** @internal */ dagCreateTask(...args: DaemonArgs): string; /** @internal */ dagCompleteTask(...args: DaemonArgs): string; /** ADR-O001 D6 — see decisions.ts's dagRequestReview. */ dagRequestReview(...args: DaemonArgs): string; /** @internal */ dagSplitTask(...args: DaemonArgs): string; /** @internal */ dagMergeTask(org: string, role: string, sourceId: string, targetId: string): string; /** @internal */ dagCancelTask(org: string, role: string, taskId: string, reason?: string): string; /** @internal */ dagBlockTask(...args: DaemonArgs): string; /** @internal */ dagPlanGraph(org: string, role: string, specs: decisionOps.PlanTaskSpec[]): string; recordDecision(...args: DaemonArgs): void; deliver(fromOrg: string, fromRole: string, to: string, subject: string, body: string): Promise; receiveRemote(...args: DaemonArgs): Promise<{ ok: true; receipt: string; } | { ok: false; error: string; }>; listRuntimeOptions(): Promise; /** @internal */ autoWake(name: string): void; /** @internal */ scheduleBossRestart(name: string): void; /** @internal */ scheduleDeferredSpawn(...args: DaemonArgs): void; /** Bug 4: mirrors scheduleDeferredSpawn, but for a role deferred because the * org is already at run_config.max_concurrent_agents rather than under host * resource pressure — see scheduleConcurrencyDeferredSpawn's doc comment. */ /** @internal */ scheduleConcurrencyDeferredSpawn(...args: DaemonArgs): void; private orgMemoryNamespace; /** @internal */ orgMemoryDbPath(): string; /** @internal */ orgMemoryUsable(): Promise; /** @internal */ rememberOrgMemory(name: string, def: OrgDef, role: string, content: string, scope: 'org' | 'agent', run: string): Promise; /** @internal */ recallOrgMemory(...args: DaemonArgs): Promise<{ text: string; hits: number; }>; searchProjectKnowledge(query: string): Promise<{ text: string; hits: number; }>; /** @internal */ learnOrgKnowledge(...args: DaemonArgs): Promise; /** @internal */ storeRunMemory(name: string, def: OrgDef, run: string, summary: RunSummary, bus?: OrgBus): Promise; replayFrom(name: string, run: string): Promise; resumeOrg(name: string): Promise; } //# sourceMappingURL=daemon.d.ts.map