mirror of
https://github.com/backnotprop/plannotator.git
synced 2026-09-14 14:17:26 +08:00
a79e6b0efe
* fix(ai): stop leaking opencode serve processes Every server boot with the opencode CLI on PATH eagerly called the provider's fetchModels() to fill the Ask AI dropdown, which spawned (or attached to) an 'opencode serve' on the shared default port 4096. Dispose only ran on the clean decision path, so Ctrl-C orphaned the child, and every later session attached to the orphan and piled unevictable per-directory instances into it (multi-GB over a day of normal use). Three changes: - Lazy start: opencode model discovery moves onto the same deferred provider initializer Codex uses. Nothing spawns until the user activates opencode in Ask AI (?activate= from the model picker, or the first opencode session). The picker still lists the provider with an empty model list pre-activation, exactly like Codex. - Own server per process: spawn with port 0 (OS-assigned; the SDK reads the real URL from the child's listening line) and never attach to a server we did not spawn. An explicitly configured port is honored. - Exit cleanup: a process 'exit' handler closes the spawned server (SIGINT/SIGTERM are routed through process.exit by the CLI), removed again on dispose. No SIGHUP listener, preserving nohup. Both runtimes; regression tests mock the SDK so no real server spawns. * fix(ai): close review findings on the opencode lifecycle Independent review of the leak fix found two holes, both now closed and regression-tested against the mocked SDK: - A failure after the spawn (client construction) left the child running and its exit handler registered, and because the handler read this.server late instead of capturing its own server, a retry's second spawn made the first unreachable by any cleanup. doStart now captures the server in its handler closure and reaps child + handler on any post-spawn failure. - dispose() during an in-flight spawn was a no-op the completing spawn then undid, resurrecting a disposed provider with a live child and a fresh exit handler. dispose() now bumps a start epoch; a spawn that completes past its epoch reaps its own server and rejects, and the provider remains restartable afterwards. Also documents the OpenCode transport (per-process server, deferred discovery) beside the Codex note in AGENTS.md.