Replace bare `new Error("Command lane cleared")` with a dedicated
`CommandLaneClearedError` class so callers that fire-and-forget
enqueued tasks can catch this specific type and avoid surfacing
unhandled rejection warnings.
clearCommandLane() was truncating the queue array without calling
resolve/reject on pending entries, causing never-settling promises
and memory leaks when upstream callers await enqueueCommandInLane().
Splice entries and reject each before clearing so callers can handle
the cancellation gracefully.
* fix(gateway): drain active turns before restart to prevent message loss
On SIGUSR1 restart, the gateway now waits up to 30s for in-flight agent
turns to complete before tearing down the server. This prevents buffered
messages from being dropped when config.patch or update triggers a restart
while agents are mid-turn.
Changes:
- command-queue.ts: add getActiveTaskCount() and waitForActiveTasks()
helpers to track and wait on active lane tasks
- run-loop.ts: on restart signal, drain active tasks before server.close()
with a 30s timeout; extend force-exit timer accordingly
- command-queue.test.ts: update imports for new exports
Fixes#13883
* fix(queue): snapshot active tasks for restart drain
---------
Co-authored-by: Elonito <0xRaini@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
On Windows, non-.exe commands like npm, pnpm, yarn, npx require
their .cmd extension when using spawn(). This adds a resolveCommand()
helper that automatically appends .cmd on Windows for these commands.
Fixes#5773
When the update runner passes custom env vars (like CLAWDBOT_UPDATE_IN_PROGRESS),
the current code uses `env ?? process.env` which replaces the entire environment
instead of merging — losing PATH, HOME, etc.
This causes the doctor step to fail with 'node: No such file or directory'.
Fix: merge custom env with process.env instead of replacing it.