feat: opencode serve — постоянный сервер вместо разовых subprocess (вариант A)
Some checks failed
CI / test (push) Successful in 54s
CI / build-and-package (amd64, linux) (push) Failing after 1h58m55s
CI / build-and-package (amd64, windows) (push) Successful in 59s

Супервайзер Server spawn'ит opencode serve (или ходит на внешний URL),
Runner ходит к нему через 'opencode run --attach <url>'. По умолчанию
serve.enabled=false — историческая spawn-модель сохранена; наличие
serve.url переключает на внешний сервер.

- config: ServeCfg (enabled/hostname/port/url/password) + дефолты; лоадер
  научился int/bool (раньше только string/Duration/struct).
- opencode: Server (Start/Run/Close, /global/health, рестарт упавшего,
  reaper-горутина владеет Wait; .Exited() непригоден для SIGKILL).
- Runner.AttachURL: run --attach <url> при заданном URL, иначе как раньше.
- app: composition root — при включённом serve запускает супервайзер.
- тесты: TestRun_AttachMode, TestServer_{ExternalURL,OwnProcess,Restart}.
This commit is contained in:
Hermes
2026-08-18 08:35:09 +05:00
parent ed11879cbd
commit 2f26b6ae88
8 changed files with 618 additions and 1 deletions

View File

@@ -35,6 +35,11 @@ type Runner struct {
HardTimeout time.Duration // общий лимит на запуск
PollInterval time.Duration
// AttachURL — постоянный opencode serve (режим --attach). Непустое значение
// переключает команду на `run --attach <url> ...`: тёплые модели/MCP, без
// холодного старта на каждый вызов. Пусто — историческая spawn-модель.
AttachURL string
// Заменяемые для тестов:
Stdout io.Writer // диагностика (лог), по умолчанию os.Stderr
}
@@ -110,7 +115,11 @@ func (r *Runner) latestSession(ctx context.Context, worktree, agent string) (str
// дают rc=-1 в Result, а не error (класс O2).
func (r *Runner) Run(ctx context.Context, prompt, cwd, agent, sessionID string) (*Result, error) {
r.defaults()
cmd := []string{r.Bin, "run", "--agent", agent, "--format", "json", "--dir", cwd}
cmd := []string{r.Bin, "run"}
if r.AttachURL != "" {
cmd = append(cmd, "--attach", r.AttachURL)
}
cmd = append(cmd, "--agent", agent, "--format", "json", "--dir", cwd)
if sessionID != "" {
cmd = append(cmd, "--session", sessionID)
}