/** * Agent Orchestrator — Core Type Definitions * * This file defines ALL interfaces and types that the system uses. * Every plugin, CLI command, and web API route builds against these. * * Architecture: 8 plugin slots + core services * 1. Runtime — where sessions execute (tmux, docker, k8s, process) * 2. Agent — AI coding tool (claude-code, codex, aider) * 3. Workspace — code isolation (worktree, clone) * 4. Tracker — issue tracking (github, linear, jira) * 5. SCM — source platform + PR/CI/reviews (github, gitlab) * 6. Notifier — push notifications (desktop, slack, webhook) * 7. Terminal — human interaction UI (iterm2, web, none) * 8. Lifecycle Manager (core, not pluggable) */ /** Unique session identifier, e.g. "my-app-1", "backend-12" */ export type SessionId = string; /** Session lifecycle states */ export type SessionStatus = "spawning" | "working" | "pr_open" | "ci_failed" | "review_pending" | "changes_requested" | "approved" | "mergeable" | "merged" | "cleanup" | "needs_input" | "stuck" | "errored" | "killed" | "idle" | "done" | "terminated"; /** Activity state as detected by the agent plugin */ export type ActivityState = "active" | "ready" | "idle" | "waiting_input" | "blocked" | "exited"; /** Activity state constants */ export declare const ACTIVITY_STATE: { ACTIVE: "active"; READY: "ready"; IDLE: "idle"; WAITING_INPUT: "waiting_input"; BLOCKED: "blocked"; EXITED: "exited"; }; /** Result of activity detection, carrying both the state and an optional timestamp. */ export interface ActivityDetection { state: ActivityState; /** When activity was last observed (e.g., agent log file mtime) */ timestamp?: Date; } /** Default threshold (ms) before a "ready" session becomes "idle". */ export declare const DEFAULT_READY_THRESHOLD_MS = 300000; /** Session status constants */ export declare const SESSION_STATUS: { SPAWNING: "spawning"; WORKING: "working"; PR_OPEN: "pr_open"; CI_FAILED: "ci_failed"; REVIEW_PENDING: "review_pending"; CHANGES_REQUESTED: "changes_requested"; APPROVED: "approved"; MERGEABLE: "mergeable"; MERGED: "merged"; CLEANUP: "cleanup"; NEEDS_INPUT: "needs_input"; STUCK: "stuck"; ERRORED: "errored"; IDLE: "idle"; KILLED: "killed"; DONE: "done"; TERMINATED: "terminated"; }; /** Statuses that indicate the session is in a terminal (dead) state. */ export declare const TERMINAL_STATUSES: ReadonlySet; /** Activity states that indicate the session is no longer running. */ export declare const TERMINAL_ACTIVITIES: ReadonlySet; /** Statuses that must never be restored (e.g. already merged). */ export declare const NON_RESTORABLE_STATUSES: ReadonlySet; /** Check if a session is in a terminal (dead) state. */ export declare function isTerminalSession(session: { status: SessionStatus; activity: ActivityState | null; }): boolean; /** Check if a session can be restored. */ export declare function isRestorable(session: { status: SessionStatus; activity: ActivityState | null; }): boolean; /** A running agent session */ export interface Session { /** Unique session ID, e.g. "my-app-3" */ id: SessionId; /** Which project this session belongs to */ projectId: string; /** Current lifecycle status */ status: SessionStatus; /** Activity state from agent plugin (null = not yet determined) */ activity: ActivityState | null; /** Git branch name */ branch: string | null; /** Issue identifier (if working on an issue) */ issueId: string | null; /** PR info (once PR is created) */ pr: PRInfo | null; /** Workspace path on disk */ workspacePath: string | null; /** Runtime handle for communicating with the session */ runtimeHandle: RuntimeHandle | null; /** Agent session info (summary, cost, etc.) */ agentInfo: AgentSessionInfo | null; /** When the session was created */ createdAt: Date; /** Last activity timestamp */ lastActivityAt: Date; /** When this session was last restored (undefined if never restored) */ restoredAt?: Date; /** Metadata key-value pairs */ metadata: Record; } export declare function isOrchestratorSession(session: { id: SessionId; metadata?: Record; }): boolean; /** Config for creating a new session */ export interface SessionSpawnConfig { projectId: string; issueId?: string; branch?: string; prompt?: string; /** Override the agent plugin for this session (e.g. "codex", "claude-code") */ agent?: string; /** Override the OpenCode subagent for this session (e.g. "sisyphus", "oracle") */ subagent?: string; /** Decomposition context — ancestor task chain (passed to prompt builder) */ lineage?: string[]; /** Decomposition context — sibling task descriptions (passed to prompt builder) */ siblings?: string[]; } /** Config for creating an orchestrator session */ export interface OrchestratorSpawnConfig { projectId: string; systemPrompt?: string; } /** * Runtime determines WHERE and HOW agent sessions execute. * tmux, docker, kubernetes, child processes, SSH, cloud sandboxes, etc. */ export interface Runtime { readonly name: string; /** Create a new session environment and return a handle */ create(config: RuntimeCreateConfig): Promise; /** Destroy a session environment */ destroy(handle: RuntimeHandle): Promise; /** Send a text message/prompt to the running agent */ sendMessage(handle: RuntimeHandle, message: string): Promise; /** Capture recent output from the session */ getOutput(handle: RuntimeHandle, lines?: number): Promise; /** Check if the session environment is still alive */ isAlive(handle: RuntimeHandle): Promise; /** Get resource metrics (uptime, memory, etc.) */ getMetrics?(handle: RuntimeHandle): Promise; /** Get info needed to attach a human to this session (for Terminal plugin) */ getAttachInfo?(handle: RuntimeHandle): Promise; } export interface RuntimeCreateConfig { sessionId: SessionId; workspacePath: string; launchCommand: string; environment: Record; } /** Opaque handle returned by runtime.create() */ export interface RuntimeHandle { /** Runtime-specific identifier (tmux session name, container ID, pod name, etc.) */ id: string; /** Which runtime created this handle */ runtimeName: string; /** Runtime-specific data */ data: Record; } export interface RuntimeMetrics { uptimeMs: number; memoryMb?: number; cpuPercent?: number; } export interface AttachInfo { /** How to connect: tmux attach, docker exec, SSH, web URL, etc. */ type: "tmux" | "docker" | "ssh" | "web" | "process"; /** For tmux: session name. For docker: container ID. For web: URL. */ target: string; /** Optional: command to run to attach */ command?: string; } /** * Agent adapter for a specific AI coding tool. * Knows how to launch, detect activity, and extract session info. */ export interface Agent { readonly name: string; /** Process name to look for (e.g. "claude", "codex", "aider") */ readonly processName: string; /** * How the initial prompt should be delivered to the agent. * - "inline" (default): prompt is included in the launch command (e.g. -p flag) * - "post-launch": prompt is sent via runtime.sendMessage() after the agent starts, * keeping the agent in interactive mode. Use this for agents where inlining * the prompt causes one-shot/exit behavior (e.g. Claude Code's -p flag). */ readonly promptDelivery?: "inline" | "post-launch"; /** Get the shell command to launch this agent */ getLaunchCommand(config: AgentLaunchConfig): string; /** Get environment variables for the agent process */ getEnvironment(config: AgentLaunchConfig): Record; /** * Detect what the agent is currently doing from terminal output. * @deprecated Use getActivityState() instead - this uses hacky terminal parsing. */ detectActivity(terminalOutput: string): ActivityState; /** * Get current activity state using agent-native mechanism (JSONL, SQLite, etc.). * This is the preferred method for activity detection. * @param readyThresholdMs - ms before "ready" becomes "idle" (default: DEFAULT_READY_THRESHOLD_MS) */ getActivityState(session: Session, readyThresholdMs?: number): Promise; /** Check if agent process is running (given runtime handle) */ isProcessRunning(handle: RuntimeHandle): Promise; /** Extract information from agent's internal data (summary, cost, session ID) */ getSessionInfo(session: Session): Promise; /** * Optional: get a launch command that resumes a previous session. * Returns null if no previous session is found (caller falls back to getLaunchCommand). */ getRestoreCommand?(session: Session, project: ProjectConfig): Promise; /** Optional: run setup after agent is launched (e.g. configure MCP servers) */ postLaunchSetup?(session: Session): Promise; /** * Optional: Set up agent-specific hooks/config in the workspace for automatic metadata updates. * Called once per workspace during ao init/start and when creating new worktrees. * * Each agent plugin implements this for their own config format: * - Claude Code: writes .claude/settings.json with PostToolUse hook * - Codex: whatever config mechanism Codex uses * - Aider: .aider.conf.yml or similar * - OpenCode: its own config * * CRITICAL: The dashboard depends on metadata being auto-updated when agents * run git/gh commands. Without this, PRs created by agents never show up. */ setupWorkspaceHooks?(workspacePath: string, config: WorkspaceHooksConfig): Promise; } export interface AgentLaunchConfig { sessionId: SessionId; projectConfig: ProjectConfig; issueId?: string; prompt?: string; permissions?: AgentPermissionInput; model?: string; /** * System prompt to pass to the agent for orchestrator context. * - Claude Code: --append-system-prompt * - Codex: --system-prompt or AGENTS.md * - Aider: --system-prompt flag * - OpenCode: equivalent mechanism * * For short prompts only. For long prompts, use systemPromptFile instead * to avoid shell/tmux truncation issues. */ systemPrompt?: string; /** * Path to a file containing the system prompt. * Preferred over systemPrompt for long prompts (e.g. orchestrator prompts) * because inlining 2000+ char prompts in shell commands causes truncation. * * When set, takes precedence over systemPrompt. * - Claude Code: --append-system-prompt "$(cat /path/to/file)" * - Codex/Aider: similar shell substitution */ systemPromptFile?: string; /** * Specialized OpenCode subagent to use (e.g., sisyphus, oracle, librarian). * Requires oh-my-opencode to be installed. * Use --subagent flag to select the subagent. */ subagent?: string; } export interface WorkspaceHooksConfig { /** Data directory where session metadata files are stored */ dataDir: string; /** Optional session ID (may not be known at ao init time) */ sessionId?: string; } export interface AgentSessionInfo { /** Agent's auto-generated summary of what it's working on */ summary: string | null; /** True when summary is a fallback (e.g. truncated first user message), not a real agent summary */ summaryIsFallback?: boolean; /** Agent's internal session ID (for resume) */ agentSessionId: string | null; /** Estimated cost so far */ cost?: CostEstimate; } export interface CostEstimate { inputTokens: number; outputTokens: number; estimatedCostUsd: number; } /** * Workspace manages code isolation — how each session gets its own copy of the repo. */ export interface Workspace { readonly name: string; /** Create an isolated workspace for a session */ create(config: WorkspaceCreateConfig): Promise; /** Destroy a workspace */ destroy(workspacePath: string): Promise; /** List existing workspaces for a project */ list(projectId: string): Promise; /** Optional: run hooks after workspace creation (symlinks, installs, etc.) */ postCreate?(info: WorkspaceInfo, project: ProjectConfig): Promise; /** Optional: check if a workspace exists and is a valid git repo */ exists?(workspacePath: string): Promise; /** Optional: restore a workspace (e.g. recreate a worktree for an existing branch) */ restore?(config: WorkspaceCreateConfig, workspacePath: string): Promise; } export interface WorkspaceCreateConfig { projectId: string; project: ProjectConfig; sessionId: SessionId; branch: string; } export interface WorkspaceInfo { path: string; branch: string; sessionId: SessionId; projectId: string; } /** * Issue/task tracker integration — GitHub Issues, Linear, Jira, etc. */ export interface Tracker { readonly name: string; /** Fetch issue details */ getIssue(identifier: string, project: ProjectConfig): Promise; /** Check if issue is completed/closed */ isCompleted(identifier: string, project: ProjectConfig): Promise; /** Generate a URL for the issue */ issueUrl(identifier: string, project: ProjectConfig): string; /** Extract a human-readable label from an issue URL (e.g., "INT-1327", "#42") */ issueLabel?(url: string, project: ProjectConfig): string; /** Generate a git branch name for the issue */ branchName(identifier: string, project: ProjectConfig): string; /** Generate a prompt for the agent to work on this issue */ generatePrompt(identifier: string, project: ProjectConfig): Promise; /** Optional: list issues with filters */ listIssues?(filters: IssueFilters, project: ProjectConfig): Promise; /** Optional: update issue state */ updateIssue?(identifier: string, update: IssueUpdate, project: ProjectConfig): Promise; /** Optional: create a new issue */ createIssue?(input: CreateIssueInput, project: ProjectConfig): Promise; } export interface Issue { id: string; title: string; description: string; url: string; state: "open" | "in_progress" | "closed" | "cancelled"; labels: string[]; assignee?: string; priority?: number; } export interface IssueFilters { state?: "open" | "closed" | "all"; labels?: string[]; assignee?: string; limit?: number; } export interface IssueUpdate { state?: "open" | "in_progress" | "closed"; labels?: string[]; removeLabels?: string[]; assignee?: string; comment?: string; } export interface CreateIssueInput { title: string; description: string; labels?: string[]; assignee?: string; priority?: number; } /** * Source code management platform — PR lifecycle, CI checks, code reviews. * This is the richest plugin interface, covering the full PR pipeline. */ export interface SCM { readonly name: string; verifyWebhook?(request: SCMWebhookRequest, project: ProjectConfig): Promise; parseWebhook?(request: SCMWebhookRequest, project: ProjectConfig): Promise; /** Detect if a session has an open PR (by branch name) */ detectPR(session: Session, project: ProjectConfig): Promise; /** Resolve a PR reference (number or URL) into canonical PR metadata. */ resolvePR?(reference: string, project: ProjectConfig): Promise; /** Assign a PR to the currently authenticated user, if supported. */ assignPRToCurrentUser?(pr: PRInfo): Promise; /** Check out the PR branch into a workspace. Returns true if branch changed. */ checkoutPR?(pr: PRInfo, workspacePath: string): Promise; /** Get current PR state */ getPRState(pr: PRInfo): Promise; /** Get PR summary with stats (state, title, additions, deletions). Optional. */ getPRSummary?(pr: PRInfo): Promise<{ state: PRState; title: string; additions: number; deletions: number; }>; /** Merge a PR */ mergePR(pr: PRInfo, method?: MergeMethod): Promise; /** Close a PR without merging */ closePR(pr: PRInfo): Promise; /** Get individual CI check statuses */ getCIChecks(pr: PRInfo): Promise; /** Get overall CI summary */ getCISummary(pr: PRInfo): Promise; /** Get all reviews on a PR */ getReviews(pr: PRInfo): Promise; /** Get the overall review decision */ getReviewDecision(pr: PRInfo): Promise; /** Get pending (unresolved) review comments */ getPendingComments(pr: PRInfo): Promise; /** Get automated review comments (bots, linters, security scanners) */ getAutomatedComments(pr: PRInfo): Promise; /** Check if PR is ready to merge */ getMergeability(pr: PRInfo): Promise; } export interface PRInfo { number: number; url: string; title: string; owner: string; repo: string; branch: string; baseBranch: string; isDraft: boolean; } export type PRState = "open" | "merged" | "closed"; /** PR state constants */ export declare const PR_STATE: { OPEN: "open"; MERGED: "merged"; CLOSED: "closed"; }; export type MergeMethod = "merge" | "squash" | "rebase"; export interface SCMWebhookRequest { method: string; headers: Record; body: string; rawBody?: Uint8Array; path?: string; query?: Record; } export interface SCMWebhookVerificationResult { ok: boolean; reason?: string; deliveryId?: string; eventType?: string; } export type SCMWebhookEventKind = "pull_request" | "ci" | "review" | "comment" | "push" | "unknown"; export interface SCMWebhookEvent { provider: string; kind: SCMWebhookEventKind; action: string; rawEventType: string; deliveryId?: string; projectId?: string; repository?: { owner: string; name: string; }; prNumber?: number; branch?: string; sha?: string; timestamp?: Date; data: Record; } export interface CICheck { name: string; status: "pending" | "running" | "passed" | "failed" | "skipped"; url?: string; conclusion?: string; startedAt?: Date; completedAt?: Date; } export type CIStatus = "pending" | "passing" | "failing" | "none"; /** CI status constants */ export declare const CI_STATUS: { PENDING: "pending"; PASSING: "passing"; FAILING: "failing"; NONE: "none"; }; export interface Review { author: string; state: "approved" | "changes_requested" | "commented" | "dismissed" | "pending"; body?: string; submittedAt: Date; } export type ReviewDecision = "approved" | "changes_requested" | "pending" | "none"; export interface ReviewComment { id: string; author: string; body: string; path?: string; line?: number; isResolved: boolean; createdAt: Date; url: string; } export interface AutomatedComment { id: string; botName: string; body: string; path?: string; line?: number; severity: "error" | "warning" | "info"; createdAt: Date; url: string; } export interface MergeReadiness { mergeable: boolean; ciPassing: boolean; approved: boolean; noConflicts: boolean; blockers: string[]; } /** * Notifier is the PRIMARY interface between the orchestrator and the human. * The human walks away after spawning agents. Notifications bring them back. * * Push, not pull. The human never polls. */ export interface Notifier { readonly name: string; /** Push a notification to the human */ notify(event: OrchestratorEvent): Promise; /** Push a notification with actionable buttons/links */ notifyWithActions?(event: OrchestratorEvent, actions: NotifyAction[]): Promise; /** Post a message to a channel (for team-visible notifiers like Slack) */ post?(message: string, context?: NotifyContext): Promise; } export interface NotifyAction { label: string; url?: string; callbackEndpoint?: string; } export interface NotifyContext { sessionId?: SessionId; projectId?: string; prUrl?: string; channel?: string; } /** * Terminal manages how humans view/interact with running sessions. * Opens IDE tabs, browser windows, or terminal sessions. */ export interface Terminal { readonly name: string; /** Open a session for human interaction */ openSession(session: Session): Promise; /** Open all sessions for a project */ openAll(sessions: Session[]): Promise; /** Check if a session is already open in a tab/window */ isSessionOpen?(session: Session): Promise; } /** Priority levels for events — determines notification routing */ export type EventPriority = "urgent" | "action" | "warning" | "info"; /** All orchestrator event types */ export type EventType = "session.spawned" | "session.working" | "session.exited" | "session.killed" | "session.idle" | "session.stuck" | "session.needs_input" | "session.errored" | "pr.created" | "pr.updated" | "pr.merged" | "pr.closed" | "ci.passing" | "ci.failing" | "ci.fix_sent" | "ci.fix_failed" | "review.pending" | "review.approved" | "review.changes_requested" | "review.comments_sent" | "review.comments_unresolved" | "automated_review.found" | "automated_review.fix_sent" | "merge.ready" | "merge.conflicts" | "merge.completed" | "reaction.triggered" | "reaction.escalated" | "summary.all_complete"; /** An event emitted by the orchestrator */ export interface OrchestratorEvent { id: string; type: EventType; priority: EventPriority; sessionId: SessionId; projectId: string; timestamp: Date; message: string; data: Record; } /** A configured automatic reaction to an event */ export interface ReactionConfig { /** Whether this reaction is enabled */ auto: boolean; /** What to do: send message to agent, notify human, auto-merge */ action: "send-to-agent" | "notify" | "auto-merge"; /** Message to send (for send-to-agent) */ message?: string; /** Priority for notifications */ priority?: EventPriority; /** How many times to retry send-to-agent before escalating */ retries?: number; /** Escalate to human notification after this many failures or this duration */ escalateAfter?: number | string; /** Threshold duration for time-based triggers (e.g. "10m" for stuck detection) */ threshold?: string; /** Whether to include a summary in the notification */ includeSummary?: boolean; } export interface ReactionResult { reactionType: string; success: boolean; action: string; message?: string; escalated: boolean; } /** Top-level orchestrator configuration (from agent-orchestrator.yaml) */ export interface OrchestratorConfig { /** * Path to the config file (set automatically during load). * Used for hash-based directory structure. * All paths are auto-derived from this location. */ configPath: string; /** Web dashboard port (defaults to 3000) */ port?: number; /** Terminal WebSocket server port (defaults to 3001) */ terminalPort?: number; /** Direct terminal WebSocket server port (defaults to 3003) */ directTerminalPort?: number; /** Milliseconds before a "ready" session becomes "idle" (default: 300000 = 5 min) */ readyThresholdMs: number; /** Default plugin selections */ defaults: DefaultPlugins; /** Project configurations */ projects: Record; /** Notification channel configs */ notifiers: Record; /** Notification routing by priority */ notificationRouting: Record; /** Default reaction configs */ reactions: Record; } export interface DefaultPlugins { runtime: string; agent: string; workspace: string; notifiers: string[]; orchestrator?: { agent?: string; }; worker?: { agent?: string; }; } export interface RoleAgentConfig { agent?: string; agentConfig?: AgentSpecificConfig; } export interface ProjectConfig { /** Display name */ name: string; /** GitHub repo in "owner/repo" format */ repo: string; /** Local path to the repo */ path: string; /** Default branch (main, master, next, develop, etc.) */ defaultBranch: string; /** Session name prefix (e.g. "app" → "app-1", "app-2") */ sessionPrefix: string; /** Override default runtime */ runtime?: string; /** Override default agent */ agent?: string; /** Override default workspace */ workspace?: string; /** Issue tracker configuration */ tracker?: TrackerConfig; /** SCM configuration (usually inferred from repo) */ scm?: SCMConfig; /** Files/dirs to symlink into workspaces */ symlinks?: string[]; /** Commands to run after workspace creation */ postCreate?: string[]; /** Agent-specific configuration */ agentConfig?: AgentSpecificConfig; orchestrator?: RoleAgentConfig; worker?: RoleAgentConfig; /** Per-project reaction overrides */ reactions?: Record>; /** Inline rules/instructions passed to every agent prompt */ agentRules?: string; /** Path to a file containing agent rules (relative to project path) */ agentRulesFile?: string; /** Rules for the orchestrator agent (stored, reserved for future use) */ orchestratorRules?: string; orchestratorSessionStrategy?: "reuse" | "delete" | "ignore" | "delete-new" | "ignore-new" | "kill-previous"; opencodeIssueSessionStrategy?: "reuse" | "delete" | "ignore"; /** Task decomposition configuration */ decomposer?: { /** Enable auto-decomposition for backlog issues (default: false) */ enabled: boolean; /** Max recursion depth (default: 3) */ maxDepth: number; /** Model to use for decomposition (default: claude-sonnet-4-20250514) */ model: string; /** Require human approval before executing decomposed plans (default: true) */ requireApproval: boolean; }; } export interface TrackerConfig { plugin: string; /** Plugin-specific config (e.g. teamId for Linear) */ [key: string]: unknown; } export interface SCMConfig { plugin: string; webhook?: SCMWebhookConfig; [key: string]: unknown; } export interface SCMWebhookConfig { enabled?: boolean; path?: string; secretEnvVar?: string; signatureHeader?: string; eventHeader?: string; deliveryHeader?: string; maxBodyBytes?: number; } export interface NotifierConfig { plugin: string; [key: string]: unknown; } export interface AgentSpecificConfig { permissions?: AgentPermissionMode; model?: string; orchestratorModel?: string; [key: string]: unknown; } export interface OpenCodeAgentConfig extends AgentSpecificConfig { opencodeSessionId?: string; } /** * Canonical cross-agent permission policy mode. * * Semantics: * - permissionless: run without interactive permission prompts (most permissive mode). * - default: use the agent's normal/default permission model. * - auto-edit: automatically approve edit actions where the agent supports granular approval policies. * - suggest: conservative mode that asks for approval on higher-risk/untrusted actions where supported. * * Note: Not every agent exposes all granular policies; plugins map these modes to * their closest supported behavior. */ export type AgentPermissionMode = "permissionless" | "default" | "auto-edit" | "suggest"; /** Backward-compatible legacy alias accepted in config parsing. */ export type LegacyAgentPermissionMode = "skip"; /** Raw permission input (supports legacy aliases). */ export type AgentPermissionInput = AgentPermissionMode | LegacyAgentPermissionMode; /** Normalize legacy aliases to canonical permission modes. */ export declare function normalizeAgentPermissionMode(mode: string | undefined): AgentPermissionMode | undefined; /** Plugin slot types */ export type PluginSlot = "runtime" | "agent" | "workspace" | "tracker" | "scm" | "notifier" | "terminal"; /** Plugin manifest — what every plugin exports */ export interface PluginManifest { /** Plugin name (e.g. "tmux", "claude-code", "github") */ name: string; /** Which slot this plugin fills */ slot: PluginSlot; /** Human-readable description */ description: string; /** Version */ version: string; /** Human-readable display name (e.g. "Claude Code") */ displayName?: string; } /** What a plugin module must export */ export interface PluginModule { manifest: PluginManifest; create(config?: Record): T; /** Optional: detect whether this plugin's runtime/binary is available on the system. */ detect?(): boolean; } /** * Session metadata stored as flat key=value files. * Matches the existing bash script format for backwards compatibility. * * Note: In the new architecture, session files are named with user-facing names * (e.g., "int-1") and contain a tmuxName field for the globally unique tmux name * (e.g., "a3b4c5d6e7f8-int-1"). */ export interface SessionMetadata { worktree: string; branch: string; status: string; tmuxName?: string; issue?: string; pr?: string; prAutoDetect?: "on" | "off"; summary?: string; project?: string; agent?: string; createdAt?: string; runtimeHandle?: string; restoredAt?: string; role?: string; dashboardPort?: number; terminalWsPort?: number; directTerminalWsPort?: number; opencodeSessionId?: string; } /** Session manager — CRUD for sessions */ export interface SessionManager { spawn(config: SessionSpawnConfig): Promise; spawnOrchestrator(config: OrchestratorSpawnConfig): Promise; restore(sessionId: SessionId): Promise; list(projectId?: string): Promise; get(sessionId: SessionId): Promise; kill(sessionId: SessionId, options?: { purgeOpenCode?: boolean; }): Promise; cleanup(projectId?: string, options?: { dryRun?: boolean; purgeOpenCode?: boolean; }): Promise; send(sessionId: SessionId, message: string): Promise; claimPR(sessionId: SessionId, prRef: string, options?: ClaimPROptions): Promise; } /** OpenCode-specific session manager with remap capability */ export interface OpenCodeSessionManager extends SessionManager { /** Remap session to OpenCode session ID, returns the mapped OpenCode session ID */ remap(sessionId: SessionId, force?: boolean): Promise; } export interface ClaimPROptions { assignOnGithub?: boolean; takeover?: boolean; } export interface ClaimPRResult { sessionId: SessionId; projectId: string; pr: PRInfo; branchChanged: boolean; githubAssigned: boolean; githubAssignmentError?: string; takenOverFrom: SessionId[]; } /** Type guard to check if a SessionManager supports OpenCode-specific remap operation */ export declare function isOpenCodeSessionManager(sm: SessionManager): sm is OpenCodeSessionManager; export interface CleanupResult { killed: string[]; skipped: string[]; errors: Array<{ sessionId: string; error: string; }>; } /** Lifecycle manager — state machine + reaction engine */ export interface LifecycleManager { /** Start the lifecycle polling loop */ start(intervalMs?: number): void; /** Stop the lifecycle polling loop */ stop(): void; /** Get current state for all sessions */ getStates(): Map; /** Force-check a specific session now */ check(sessionId: SessionId): Promise; } /** Plugin registry — discovery + loading */ export interface PluginRegistry { /** Register a plugin, optionally with config to pass to create() */ register(plugin: PluginModule, config?: Record): void; /** Get a plugin by slot and name */ get(slot: PluginSlot, name: string): T | null; /** List plugins for a slot */ list(slot: PluginSlot): PluginManifest[]; /** Load built-in plugins, optionally with orchestrator config for plugin settings */ loadBuiltins(config?: OrchestratorConfig, importFn?: (pkg: string) => Promise): Promise; /** Load plugins from config (npm packages, local paths) */ loadFromConfig(config: OrchestratorConfig, importFn?: (pkg: string) => Promise): Promise; } /** * Detect if an error indicates that an issue was not found in the tracker. * Used by spawn validation to distinguish "not found" from other errors (auth, network, etc). * * Uses specific patterns to avoid matching infrastructure errors like "API key not found", * "Team not found", "Configuration not found", etc. */ export declare function isIssueNotFoundError(err: unknown): boolean; /** Thrown when a session cannot be restored (e.g. merged, still working). */ export declare class SessionNotRestorableError extends Error { readonly sessionId: string; readonly reason: string; constructor(sessionId: string, reason: string); } /** Thrown when a workspace is missing and cannot be recreated. */ export declare class WorkspaceMissingError extends Error { readonly path: string; readonly detail?: string | undefined; constructor(path: string, detail?: string | undefined); } /** Thrown when a session lookup fails (session does not exist). */ export declare class SessionNotFoundError extends Error { readonly sessionId: string; constructor(sessionId: string); } /** Thrown when no agent-orchestrator.yaml config file can be found. */ export declare class ConfigNotFoundError extends Error { constructor(message?: string); } //# sourceMappingURL=types.d.ts.map