feat: opencode serve — постоянный сервер вместо разовых subprocess (вариант A)
Супервайзер 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:
@@ -5,6 +5,7 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
@@ -133,6 +134,18 @@ func applyDefaults(cfg *Config) {
|
||||
if fv.Kind() == reflect.String {
|
||||
fv.SetString(meta.defaultVal)
|
||||
}
|
||||
// int (значение по умолчанию, напр. port)
|
||||
if fv.Kind() == reflect.Int {
|
||||
if n, err := strconv.Atoi(meta.defaultVal); err == nil {
|
||||
fv.SetInt(int64(n))
|
||||
}
|
||||
}
|
||||
// bool (по умолчанию false/true)
|
||||
if fv.Kind() == reflect.Bool {
|
||||
if b, err := strconv.ParseBool(meta.defaultVal); err == nil {
|
||||
fv.SetBool(b)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -156,6 +169,16 @@ func applyEnvOverrides(cfg *Config) {
|
||||
if fv.Kind() == reflect.String {
|
||||
fv.SetString(envVal)
|
||||
}
|
||||
if fv.Kind() == reflect.Int {
|
||||
if n, err := strconv.Atoi(envVal); err == nil {
|
||||
fv.SetInt(int64(n))
|
||||
}
|
||||
}
|
||||
if fv.Kind() == reflect.Bool {
|
||||
if b, err := strconv.ParseBool(envVal); err == nil {
|
||||
fv.SetBool(b)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -173,6 +196,10 @@ func walk(v reflect.Value, fn func(reflect.Value, fieldMeta)) {
|
||||
fn(fv, collectMeta(f))
|
||||
} else if fv.Type() == durType {
|
||||
fn(fv, collectMeta(f))
|
||||
} else if fv.Kind() == reflect.Int {
|
||||
fn(fv, collectMeta(f))
|
||||
} else if fv.Kind() == reflect.Bool {
|
||||
fn(fv, collectMeta(f))
|
||||
} else if fv.Kind() == reflect.Struct {
|
||||
walk(fv, fn)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user