(options: SupervisorOptions)
| 59 | /** |
| 60 | * Runs immediately before every spawn, including restarts. Use for |
| 61 | * self-healing work that must happen on each attempt rather than once at |
| 62 | * bootstrap. Failures are logged and ignored so the spawn still proceeds. |
| 63 | */ |
| 64 | beforeSpawn?: () => void | Promise<void>; |
| 65 | }; |
| 66 | |
| 67 | export function createSupervisor(options: SupervisorOptions): Supervisor { |
| 68 | const { |
| 69 | args, |
| 70 | command = 'openclaw', |
| 71 | backoffInitialMs = BACKOFF_INITIAL_MS, |
| 72 | backoffMaxMs = BACKOFF_MAX_MS, |
| 73 | backoffMultiplier = BACKOFF_MULTIPLIER, |
| 74 | healthyThresholdMs = HEALTHY_THRESHOLD_MS, |
| 75 | shutdownTimeoutMs = SHUTDOWN_TIMEOUT_MS, |
| 76 | now = () => Date.now(), |
| 77 | spawnImpl = spawn, |
| 78 | setTimeoutImpl = setTimeout, |
| 79 | clearTimeoutImpl = clearTimeout, |
| 80 | onStdoutLine, |
| 81 | beforeSpawn, |
| 82 | } = options; |
| 83 | |
| 84 | let state: SupervisorState = 'stopped'; |
| 85 | let child: ReturnType<SpawnLike> | null = null; |
| 86 | let restartTimer: TimerLike | null = null; |
| 87 | let backoffMs = backoffInitialMs; |
| 88 | let runningSinceMs: number | null = null; |
| 89 | let restarts = 0; |
| 90 | let lastExit: SupervisorLastExit | null = null; |
| 91 | let stopRequested = false; |
| 92 | let manualStop = false; |
| 93 | let shuttingDown = false; |
| 94 | |
| 95 | let childExitPromise: Promise<void> | null = null; |
| 96 | let resolveChildExit: (() => void) | null = null; |
| 97 | let opQueue: Promise<void> = Promise.resolve(); |
| 98 | let lineBuf = ''; |
| 99 | |
| 100 | const clearRestartTimer = () => { |
| 101 | if (restartTimer) { |
| 102 | clearTimeoutImpl(restartTimer); |
| 103 | restartTimer = null; |
| 104 | } |
| 105 | }; |
| 106 | |
| 107 | const resetBackoff = () => { |
| 108 | backoffMs = backoffInitialMs; |
| 109 | }; |
| 110 | |
| 111 | const resolveExitWaiters = () => { |
| 112 | if (resolveChildExit) { |
| 113 | resolveChildExit(); |
| 114 | resolveChildExit = null; |
| 115 | } |
| 116 | childExitPromise = null; |
| 117 | }; |
| 118 |
no test coverage detected