import { type ConfigDiagnostic, type YamlMode } from './config-yaml.js'; import type { IsolationConfig, WrapContext } from './isolation/types.js'; import type { ResolvedWatchdog } from './watchdog/config.js'; import type { AgentLoopsConfig, ResolvedLoop, ResolvedRoleLoop } from './loops/config.js'; export interface OverseeEntry { agent: string; interval: string; } export interface WorklogPolicy { max_kb: number; keep_tail_kb: number; max_archives: number; } export type WorklogPolicyInput = Partial | false; /** Conservative built-in policy; `worklog: false` is the explicit opt-out. */ export declare const DEFAULT_WORKLOG_POLICY: Readonly; export interface AuthProxyConfig { kind: 'anthropic'; base_url: string; required: boolean; health_url: string; } /** The 8 content-free event types the ours daemon appends to notifications.log. */ export declare const NOTIFY_EVENT_TYPES: readonly ["message_received", "file_received", "sibling_contact_added", "local_contact_request", "pending_message", "contact_restored", "inbound_error", "state_import_failed"]; export type NotifyEventType = (typeof NOTIFY_EVENT_TYPES)[number]; export type InjectMode = 'notification' | 'full'; export type MonitorMode = 'fleet' | 'native'; /** Concrete transport selected for a role. Keep provider-native transports explicit. */ export type SessionBackendId = 'acp' | 'codex-app-server'; /** Public, harness-neutral permission policy. */ export type FleetPermissionMode = 'ask' | 'auto' | 'allow'; /** `deny` is a deprecated, fail-closed compatibility alias retained for old fleet files. */ export type ApprovalMode = FleetPermissionMode | 'deny'; export type FilesystemMode = 'read-only' | 'workspace' | 'unrestricted'; export type UnattendedMode = 'deny' | 'wait'; /** Monitor wake policy: preserve legacy booleans and add one explicit safe boundary. */ export type MonitorInterrupt = boolean | 'after_tool'; export interface CommonPermissions { approval: ApprovalMode; filesystem: FilesystemMode; unattended: UnattendedMode; } export interface SessionOptions { acp?: { /** ACP agent command and arguments. Defaults are supplied by the harness adapter. */ command?: string | string[]; }; codex_app_server?: { /** App-server command and arguments. Defaults to `codex app-server`. */ command?: string | string[]; }; } /** Resolved per-role supervisor-monitor config. */ export interface MonitorConfig { /** Who owns mail wake delivery: ours-fleet supervisor or the native harness. */ mode: MonitorMode; /** @deprecated Legacy alias retained in resolved snapshots; use mode. */ enabled: boolean; wake_sources: string[]; batch_ms: number; inject: InjectMode; /** Immediate cancel, ordinary non-cancelling delivery, or ACP tool-boundary steering. */ interrupt: MonitorInterrupt; /** * Consecutive delivered wakes that must end in an `API Error:`-terminated turn * (with no completed turn in between) before `.monitor-status` degrades to * `turns failing (api error)` — the refusal-wedge detector (issue #19). Must be * a positive integer; resolved default is 3. Optional so old snapshots resolve. */ turn_fail_threshold?: number; /** Opt-in bounded ACP no-progress recovery; independent of mail interruption policy. */ stall_recovery?: boolean; /** Progress silence window; default 15 minutes. Generic silence requires two windows. */ stall_timeout_ms?: number; } /** A trusted, fleet-owned ours mailbox which is never bound inside the agent. */ export interface OwnerChannelConfig { /** Existing ours identity exclusively bound by the fleet supervisor. */ identity: string; /** Authenticated ours contact IDs allowed to issue owner instructions. */ owners: string[]; /** Exact managed-agent CID whose messages may be relayed outward. */ agent?: string; /** Cancel active work before each owner request instead of queueing it. */ interrupt: boolean; /** Deterministic in-progress notice interval; 0 disables progress notices. */ progress_interval_ms: number; /** * Relay the agent's live ACP commentary to the owner while a turn runs. * This is the RESTART BASELINE only: `/comments on|off` changes the running * session's effective value, and a restart returns to this one. */ comments: boolean; attachments: OwnerAttachmentConfig; } export interface OwnerAttachmentConfig { enabled: boolean; max_files_per_request: number; max_file_bytes: number; max_request_bytes: number; retention_ms: number; } type OwnerAttachmentConfigInput = Partial & { /** @deprecated Accepted only so existing configs keep loading; ignored. */ allowed_mime?: unknown; }; export type OwnerChannelConfigInput = Omit, 'attachments'> & { attachments?: OwnerAttachmentConfigInput; }; /** Default wake sources when a role does not list its own. */ export declare const DEFAULT_WAKE_SOURCES: NotifyEventType[]; /** * Validate a raw (role-level or merged) `monitor:` block; returns human-readable problems. * * `capabilities` defaults to what this build declares. A value is rejected in two * distinct ways: unknown to every build (a typo), or known but absent from the * artifact doing the validating — the second names the capability and the build, * because the same fleet.yaml may well be accepted by another install on the host. */ export declare function validateMonitorConfig(raw: unknown, capabilities?: readonly string[]): string[]; export interface RoleConfig { harness?: string; session?: SessionBackendId; session_options?: SessionOptions; permissions?: Partial; identity?: string; cwd?: string; coordinator?: string; mission?: string; persona?: string; bio?: string; briefing_file?: string; /** Explicit null means use the selected harness's own default, bypassing fleet defaults. */ model?: string | null; /** Neutral Brain reasoning effort, retained for inspection after adapter translation. */ effort?: string; model_chain?: string[]; max_tokens?: number; autocompact_pct?: number; env?: Record; oversee?: OverseeEntry[]; harness_options?: Record; isolation?: IsolationConfig; monitor?: Partial; owner_channel?: OwnerChannelConfigInput; worklog?: WorklogPolicyInput; auth_proxy?: Partial; } export type AgentSelection = Record> = { ref: string; } | { inline: T; }; /** Canonical authoring contract shared by configured, spawned, and room agents. */ export interface AgentDefinition { role: AgentSelection; brain: AgentSelection; permissions?: Partial; identity?: string; cwd?: string; coordinator?: string; env?: Record; oversee?: OverseeEntry[]; isolation?: IsolationConfig; monitor?: Partial; owner_channel?: OwnerChannelConfigInput; worklog?: WorklogPolicyInput; auth_proxy?: Partial; /** Scheduled turns scoped only to temporary launches; persistent Agents reject this field. */ loops?: AgentLoopsConfig; } /** Inert, reusable launch definition. It never owns an identity or runtime state. */ export type AgentTemplateDefinition = Omit; /** Explicit persistent instance reusing an inert template. */ export interface AgentTemplateInstance { template: string; overrides?: Partial; } /** Internal first-boot payload for a Fleet-provisioned Cowork room member. */ export interface RoomMemberStartup { room_id: string; room_identity_cid: string; identity_name: string; invite_id: string; invite: string; role: string; task: string; owner_seat_cid: string | null; anonymous?: boolean; } export interface ResolvedRole extends Omit { name: string; harness: string; session: SessionBackendId; permissions: CommonPermissions; /** * Whether `permissions:` was actually written by the operator (on the role or * in defaults), as opposed to resolved from built-in defaults. A role that * states its intent only once — neutrally OR natively — has nothing to * contradict, and must not be warned at. */ permissionsDeclared: boolean; identity: string; model?: string; sourceFile: string; monitor: MonitorConfig; owner_channel?: OwnerChannelConfig; worklog?: WorklogPolicy; auth_proxy?: AuthProxyConfig; loops?: ResolvedRoleLoop[]; /** Agent Template-local loops, kept separate from manifest loops until a temp launch. */ temporaryLoops?: ResolvedRoleLoop[]; /** Durable source of the temporary loop policy; internal and never user-authored. */ temporaryLoopSource?: 'agent-template' | 'cli' | 'omitted'; provenance?: Record; /** Internal/transient: never accepted as a user-authored RoleConfig key. */ roomMemberStartup?: RoomMemberStartup; /** Original unresolved selections only; denied operational fields never enter inheritance state. */ agentSelections?: Pick; agentTemplate?: { id: string; sourceFile: string; contentHash: string; }; } export interface FieldProvenance { sourceFile: string; sourcePointer: string; sourceKind: 'Agent' | 'Role' | 'Brain' | 'Manifest' | 'built-in'; sourceId?: string; origin: 'explicit' | 'typed-default' | 'built-in'; viaReference?: { sourcePointer: string; kind: 'Role' | 'Brain'; id: string; }; transforms: Array<{ kind: 'substitution' | 'adapter-normalization' | 'validation-default'; detail: string; }>; } export interface FleetConfig { roles: ResolvedRole[]; /** Canonical, variable-resolved Agent authoring documents keyed by stable Agent ID. */ agentDefinitions?: Record; /** Canonical inert templates keyed by stable template ID. */ agentTemplates?: Record; rolePresets?: Record>; brainPresets?: Record>; /** Required launch-boundary resolver for effective temporary Agent definitions. */ resolveAgentDefinition?: (id: string, definition: AgentDefinition) => ResolvedRole; vars: Record; defaults: Record; files: string[]; configMode?: 'split-v2'; sourceDocuments?: Array<{ kind: 'Manifest' | 'Agent' | 'AgentTemplate' | 'Role' | 'Brain' | 'RoomTemplate'; id?: string; path: string; }>; /** Fleet-wide delay (ms) enforced between agent launches to avoid boot bursts (0 = none). */ startStaggerMs: number; /** Warning-first non-plain YAML migration diagnostics, in source order. */ diagnostics: ConfigDiagnostic[]; watchdogs: ResolvedWatchdog[]; loops: ResolvedLoop[]; rooms?: import('./rooms-tasks/types.js').RoomsConfig; roomTemplates?: import('./rooms-tasks/types.js').RoomTemplatesConfig; tasks?: import('./rooms-tasks/types.js').TasksConfig; /** SHA-256 fingerprint of the resolved owner invite (never the invite itself). */ ownerInviteFingerprint?: string; /** * Resolved owner invite for immediate private-IPC use only. This property is * deliberately non-enumerable so config dumps and JSON output cannot expose * the bearer credential. */ ownerInvite?: string; } export declare class ConfigError extends Error { } /** Resolve a model without leaking a default that belongs to another harness. */ export declare function resolveRoleModel(model: string | null | undefined, harness: string | undefined, defaults: Record): string | undefined; /** * The runtime facts the isolation resolver needs for a role. Single-sourced so * config validation, doctor, and the runner all judge the SAME mount set — a * policy checked against a different context than the one that launches is not * a check at all. */ export declare function isolationContextFor(role: ResolvedRole): WrapContext; export declare const ROLE_NAME_RE: RegExp; export declare const ROLE_PRESET_KEYS: string[]; export declare const BRAIN_PRESET_KEYS: string[]; export declare const AGENT_KEYS: string[]; type BarePreset = Record; export declare function validateRoleValue(value: BarePreset, file: string, pointer: string): void; export declare function validateBrainValue(value: BarePreset, file: string, pointer: string): void; /** Pure launch-boundary validation for a fully resolved temporary Agent definition. */ export declare function validateEffectiveAgentTemplate(definition: AgentTemplateDefinition, id?: string): AgentTemplateDefinition; export declare function assertBareKeys(value: unknown, allowed: string[], label: string): BarePreset; export declare function splitRootFor(base: string): string; /** Load a v2 manifest and bare Agent/Role/Brain documents from its stem directory. */ export declare function loadConfig(configPath?: string, options?: { yamlMode?: YamlMode; additionalAgent?: { id: string; definition: AgentDefinition; temporary?: boolean; }; skipWatchdogs?: boolean; }): FleetConfig; /** Full read-only Agent resolution used by launch dry-runs and room plan validation. */ export declare function resolveAgentDefinitionDryRun(configPath: string, id: string, definition: AgentDefinition): ResolvedRole; /** * Canonical form of a 64-hex container ID for authorization decisions. Hex * case is not identity: two casings of one CID are the same peer, so every * comparison must use this form. Addressing is the opposite — the daemon's * contact resolution is case-exact, so daemon-delivered forms must be sent * back verbatim and never rewritten to canonical case. */ export declare function canonicalCid(value: string): string; export declare function resolveOwnerChannelConfig(defaults: unknown, role: OwnerChannelConfigInput | undefined, session: SessionBackendId, file?: string, name?: string): OwnerChannelConfig | undefined; export declare function resolveModelChain(model: string | undefined, chain: string[] | undefined, file?: string, name?: string): string[] | undefined; export declare function resolveAuthProxy(defaults: unknown, role: Partial | undefined, file?: string, name?: string): AuthProxyConfig | undefined; export declare function resolveWorklogPolicy(defaults: unknown, role: WorklogPolicyInput | undefined, file?: string, name?: string): WorklogPolicy | undefined; export declare function resolvePermissions(defaults: unknown, role: Partial | undefined, file?: string, name?: string): CommonPermissions; /** * Merge `defaults.monitor` under the role's own `monitor:` key-by-key, validate the * result, and fill code-constant defaults. `monitor.mode` selects * fleet-owned or native-harness monitoring; absent everywhere ⇒ fleet. The old * `enabled` boolean remains a compatibility alias. Throws ConfigError on a * malformed block so a typo fails loudly rather than silently disarming a monitor. * Exported so temp-spawn (which builds a ResolvedRole by hand) resolves identically. */ export declare function resolveMonitorConfig(defMonitor: unknown, roleMonitor?: Partial, labels?: { base?: string; file?: string; name?: string; }): MonitorConfig; export declare function findRole(cfg: FleetConfig, name: string): ResolvedRole; export {};