aiwg
Version:
Deployment tool and support utility for AI context. Copies agents, skills, commands, rules, and behaviors into the paths each AI platform reads (Claude Code, Codex, Copilot, Cursor, Warp, OpenClaw, and 6 more) so one source of truth works across 10 platfo
200 lines • 6.58 kB
TypeScript
/**
* Ralph External Process Launcher
*
* Spawns the external Ralph supervisor as a detached background process
* that survives terminal closure and can be managed across sessions.
*
* @implements @.aiwg/working/issue-ralph-external-completion.md
* @issue #275
* @security docs/ralph-external-security.md
*
* SECURITY WARNING
* ================
* This module launches Claude Code sessions with --dangerously-skip-permissions.
* Spawned sessions can read/write ANY file and execute ANY command without
* user confirmation. Sessions run as detached daemons for extended periods
* without human oversight.
*
* BEFORE USING:
* - Read docs/ralph-external-security.md
* - Understand all security implications
* - Set appropriate limits (budget, iterations, timeout)
* - Ensure clean git state for rollback capability
* - Have monitoring and abort procedures ready
*/
/**
* Options for launching an external agent loop
*/
export interface RalphLaunchOptions {
objective: string;
completionCriteria: string;
maxIterations?: number;
model?: string;
budget?: number;
timeout?: number;
mcpConfig?: string;
giteaIssue?: boolean;
memory?: number | string;
crossTask?: boolean;
enableAnalytics?: boolean;
enableBestOutput?: boolean;
enableEarlyStopping?: boolean;
loopId?: string;
force?: boolean;
provider?: string;
/** Enable dangerous/unrestricted mode — passed to the orchestrator via env + flag */
dangerous?: boolean;
/** Raw args to append verbatim to the agent invocation inside the loop */
params?: string;
/** Enable verbose per-iteration detail (assessment, strategy, prompt preview) */
verbose?: boolean;
/** Write timestamped log to this file path (in addition to daemon-output.log) */
logFile?: string;
}
/**
* Result from launching a agent loop
*/
export interface RalphLaunchResult {
success: boolean;
loopId: string;
pid: number;
message: string;
registryPath: string;
}
/**
* Registry entry for a running loop
*/
export interface LoopRegistryEntry {
loopId: string;
pid: number;
objective: string;
completionCriteria: string;
status: 'running' | 'completed' | 'failed' | 'aborted';
startedAt: string;
lastUpdate: string;
iteration: number;
maxIterations: number;
outputFile: string;
sessionStdoutFile?: string;
sessionStderrFile?: string;
promptFile?: string;
provider?: string;
}
/**
* Get the path to the external Ralph orchestrator
*/
export declare function getOrchestratorPath(frameworkRoot: string): string;
/**
* Get the registry directory path
*/
export declare function getRegistryDir(projectRoot: string): string;
/**
* Get the registry file path
*/
export declare function getRegistryPath(projectRoot: string): string;
/**
* Generate a unique loop ID
*/
export declare function generateLoopId(objective: string): string;
/**
* Build command-line arguments for the external Ralph process
*/
export declare function buildArgs(options: RalphLaunchOptions): string[];
/**
* Enforce `parallelism.max_parallel_ralph_loops` from `.aiwg/aiwg.config`.
* Hard-fails (throws AiwgError) when the count of running + live Ralph loops
* already meets or exceeds the cap. Non-fatal when no config or config read
* fails — caller proceeds with launch.
*
* Extracted so the cap-check logic is unit-testable independently of the
* detached-process spawn machinery.
*
* @implements #1361
*/
export declare function assertRalphParallelismCap(projectRoot: string): Promise<void>;
/**
* Launch the external Ralph process as a detached daemon
*/
export declare function launchExternalRalph(frameworkRoot: string, projectRoot: string, options: RalphLaunchOptions): Promise<RalphLaunchResult>;
/**
* Launcher's own registry (supplement to external-multi-loop-state-manager)
*/
export interface LauncherRegistry {
version: string;
loops: Record<string, LoopRegistryEntry>;
updatedAt: string;
}
/**
* Load the launcher registry
*/
export declare function loadLauncherRegistry(projectRoot: string): LauncherRegistry;
/**
* Save the launcher registry
*/
export declare function saveLauncherRegistry(projectRoot: string, registry: LauncherRegistry): void;
/**
* Check if a process is still running
*/
export declare function isProcessAlive(pid: number): boolean;
/**
* Get status of all agent loops.
* Detects stale entries (>24h without heartbeat) and auto-cleans completed entries.
*/
export declare function getLoopStatuses(projectRoot: string, options?: {
autoCleanCompleted?: boolean;
}): LoopRegistryEntry[];
/**
* Abort a running agent loop by killing its process
*/
export declare function abortLoop(projectRoot: string, loopId?: string): {
success: boolean;
message: string;
};
/**
* Resume an interrupted agent loop
*/
export declare function resumeLoop(frameworkRoot: string, projectRoot: string, loopId?: string, overrides?: {
maxIterations?: number;
}): Promise<RalphLaunchResult>;
/**
* Clean up a completed loop: remove from launcher-registry and delete working state.
* Preserves completion reports by moving them to the ralph-external root before deletion.
*
* @param projectRoot - Project root directory
* @param loopId - Loop ID to clean up
* @param options - Cleanup options
* @returns Object with success status and details
*/
export declare function cleanupCompletedLoop(projectRoot: string, loopId: string, options?: {
archive?: boolean;
}): {
success: boolean;
message: string;
preserved: string[];
};
/**
* Clean up internal Ralph state after successful completion.
* Deletes current-loop.json, heartbeats, and iteration working state.
* Preserves completion report files.
*
* @param projectRoot - Project root directory
* @returns Object with success status and what was cleaned
*/
export declare function cleanupInternalRalph(projectRoot: string): {
success: boolean;
cleaned: string[];
preserved: string[];
};
/**
* Clean up completed/failed loops from registry
*/
export declare function cleanupRegistry(projectRoot: string, keepDays?: number): number;
/**
* Attach to a running agent loop's output stream.
*
* Tails the loop's daemon-output.log to stdout in real-time.
* Ctrl+C detaches (the background loop keeps running).
* Returns a Promise that resolves when the user detaches or the loop exits.
*/
export declare function attachToLoopOutput(projectRoot: string, loopId?: string): Promise<void>;
//# sourceMappingURL=ralph-launcher.d.ts.map