iop/packages/config/config.go
toki b4124f0bd6 feat: CLI setup, edge/node transport refactor, and infrastructure updates
- Add CLI core setup for edge and node services
- Refactor edge transport layer (server, integration tests)
- Refactor node transport layer (parser, session, heartbeat, client)
- Add main_test.go files for edge and node commands
- Add input package for edge service
- Add go.work and go.work.sum for workspace support
- Update configs, docs, and project rules
2026-05-20 16:37:42 +09:00

235 lines
8.4 KiB
Go

package config
import (
"github.com/spf13/viper"
)
type NodeConfig struct {
Transport TransportConf `mapstructure:"transport" yaml:"transport"`
Logging LoggingConf `mapstructure:"logging" yaml:"logging"`
Metrics MetricsConf `mapstructure:"metrics" yaml:"metrics"`
}
type EdgeConfig struct {
Edge EdgeInfo `mapstructure:"edge" yaml:"edge"`
Server EdgeServerConf `mapstructure:"server" yaml:"server"`
OpenAI EdgeOpenAIConf `mapstructure:"openai" yaml:"openai"`
A2A EdgeA2AConf `mapstructure:"a2a" yaml:"a2a"`
TLS TLSConf `mapstructure:"tls" yaml:"tls"`
Logging LoggingConf `mapstructure:"logging" yaml:"logging"`
Metrics MetricsConf `mapstructure:"metrics" yaml:"metrics"`
Console EdgeConsoleConf `mapstructure:"console" yaml:"console"`
Nodes []NodeDefinition `mapstructure:"nodes" yaml:"nodes"`
}
// EdgeInfo carries this edge instance's stable identity for loading and logging.
// It is not used for Control Plane registration.
type EdgeInfo struct {
ID string `mapstructure:"id" yaml:"id"`
Name string `mapstructure:"name" yaml:"name"`
}
// NodeDefinition is the edge-side record for a pre-registered node.
type NodeDefinition struct {
ID string `mapstructure:"id" yaml:"id"` // stable node identity; if empty, a UUID v4 is auto-assigned (dev fallback only)
Alias string `mapstructure:"alias" yaml:"alias"`
Token string `mapstructure:"token" yaml:"token"`
Adapters AdaptersConf `mapstructure:"adapters" yaml:"adapters"`
Runtime RuntimeConf `mapstructure:"runtime" yaml:"runtime"`
}
type NodeInfo struct {
ID string `mapstructure:"id" yaml:"id"`
Name string `mapstructure:"name" yaml:"name"`
}
type EdgeServerConf struct {
Listen string `mapstructure:"listen" yaml:"listen"`
}
type EdgeOpenAIConf struct {
Enabled bool `mapstructure:"enabled" yaml:"enabled"`
Listen string `mapstructure:"listen" yaml:"listen"`
NodeRef string `mapstructure:"node" yaml:"node"`
Adapter string `mapstructure:"adapter" yaml:"adapter"`
Target string `mapstructure:"target" yaml:"target"`
Models []string `mapstructure:"models" yaml:"models"`
SessionID string `mapstructure:"session_id" yaml:"session_id"`
TimeoutSec int `mapstructure:"timeout_sec" yaml:"timeout_sec"`
}
type EdgeA2AConf struct {
Enabled bool `mapstructure:"enabled" yaml:"enabled"`
Listen string `mapstructure:"listen" yaml:"listen"`
Path string `mapstructure:"path" yaml:"path"`
NodeRef string `mapstructure:"node" yaml:"node"`
Adapter string `mapstructure:"adapter" yaml:"adapter"`
Target string `mapstructure:"target" yaml:"target"`
SessionID string `mapstructure:"session_id" yaml:"session_id"`
TimeoutSec int `mapstructure:"timeout_sec" yaml:"timeout_sec"`
BearerToken string `mapstructure:"bearer_token" yaml:"bearer_token"`
}
type EdgeConsoleConf struct {
Adapter string `mapstructure:"adapter" yaml:"adapter"`
Target string `mapstructure:"target" yaml:"target"`
Agent string `mapstructure:"agent" yaml:"agent"` // legacy alias for target
Model string `mapstructure:"model" yaml:"model"` // legacy alias for target
SessionID string `mapstructure:"session_id" yaml:"session_id"`
Background bool `mapstructure:"background" yaml:"background"`
TimeoutSec int `mapstructure:"timeout_sec" yaml:"timeout_sec"`
}
func (c EdgeConsoleConf) ResolveTarget() string {
if c.Target != "" {
return c.Target
}
if c.Agent != "" {
return c.Agent
}
return c.Model
}
// ResolveAgent is kept for callers still using the legacy console.agent name.
func (c EdgeConsoleConf) ResolveAgent() string {
return c.ResolveTarget()
}
type TransportConf struct {
EdgeAddr string `mapstructure:"edge_addr" yaml:"edge_addr"`
Token string `mapstructure:"token" yaml:"token"`
}
type TLSConf struct {
Enabled bool `mapstructure:"enabled" yaml:"enabled"`
Cert string `mapstructure:"cert" yaml:"cert"`
Key string `mapstructure:"key" yaml:"key"`
CA string `mapstructure:"ca" yaml:"ca"`
}
type RuntimeConf struct {
Concurrency int `mapstructure:"concurrency" yaml:"concurrency"`
WorkspaceRoot string `mapstructure:"workspace_root" yaml:"workspace_root"`
}
type SQLiteConf struct {
DSN string `mapstructure:"dsn" yaml:"dsn"`
}
type LoggingConf struct {
Level string `mapstructure:"level" yaml:"level"`
Pretty bool `mapstructure:"pretty" yaml:"pretty"`
}
type MetricsConf struct {
Port int `mapstructure:"port" yaml:"port"`
}
type AdaptersConf struct {
Ollama OllamaConf `mapstructure:"ollama" yaml:"ollama"`
Vllm VllmConf `mapstructure:"vllm" yaml:"vllm"`
CLI CLIConf `mapstructure:"cli" yaml:"cli"`
}
type OllamaConf struct {
Enabled bool `mapstructure:"enabled" yaml:"enabled"`
BaseURL string `mapstructure:"base_url" yaml:"base_url"`
ContextSize int `mapstructure:"context_size" yaml:"context_size"`
}
type VllmConf struct {
Enabled bool `mapstructure:"enabled" yaml:"enabled"`
Endpoint string `mapstructure:"endpoint" yaml:"endpoint"`
}
type CLIConf struct {
Enabled bool `mapstructure:"enabled" yaml:"enabled"`
Profiles map[string]CLIProfileConf `mapstructure:"profiles" yaml:"profiles"`
}
type CLIProfileConf struct {
Command string `mapstructure:"command" yaml:"command"`
Args []string `mapstructure:"args" yaml:"args"`
Env []string `mapstructure:"env" yaml:"env"`
Persistent bool `mapstructure:"persistent" yaml:"persistent"`
Terminal bool `mapstructure:"terminal" yaml:"terminal"`
ResponseIdleTimeoutMS int `mapstructure:"response_idle_timeout_ms" yaml:"response_idle_timeout_ms"`
StartupIdleTimeoutMS int `mapstructure:"startup_idle_timeout_ms" yaml:"startup_idle_timeout_ms"`
OutputFormat string `mapstructure:"output_format" yaml:"output_format"`
CompletionMarker CompletionMarkerConf `mapstructure:"completion_marker" yaml:"completion_marker"`
Mode string `mapstructure:"mode" yaml:"mode"`
ResumeArgs []string `mapstructure:"resume_args" yaml:"resume_args"`
}
type CompletionMarkerConf struct {
Line string `mapstructure:"line" yaml:"line"`
Regex string `mapstructure:"regex" yaml:"regex"`
}
func (m CompletionMarkerConf) Empty() bool {
return m.Line == "" && m.Regex == ""
}
func Load(cfgFile string) (*NodeConfig, error) {
v := viper.New()
v.SetConfigFile(cfgFile)
setDefaults(v)
if err := v.ReadInConfig(); err != nil {
return nil, err
}
var cfg NodeConfig
if err := v.Unmarshal(&cfg); err != nil {
return nil, err
}
return &cfg, nil
}
func LoadEdge(cfgFile string) (*EdgeConfig, error) {
v := viper.New()
v.SetConfigFile(cfgFile)
setEdgeDefaults(v)
if err := v.ReadInConfig(); err != nil {
return nil, err
}
var cfg EdgeConfig
if err := v.Unmarshal(&cfg); err != nil {
return nil, err
}
if !v.InConfig("console.target") {
if v.InConfig("console.agent") {
cfg.Console.Target = cfg.Console.Agent
} else if v.InConfig("console.model") {
cfg.Console.Target = cfg.Console.Model
}
}
return &cfg, nil
}
func setDefaults(v *viper.Viper) {
v.SetDefault("transport.edge_addr", "localhost:9090")
v.SetDefault("logging.level", "info")
v.SetDefault("metrics.port", 9091)
}
func setEdgeDefaults(v *viper.Viper) {
v.SetDefault("server.listen", "0.0.0.0:9090")
v.SetDefault("openai.enabled", false)
v.SetDefault("openai.listen", "0.0.0.0:8080")
v.SetDefault("openai.adapter", "ollama")
v.SetDefault("openai.session_id", "openai")
v.SetDefault("openai.timeout_sec", 120)
v.SetDefault("a2a.enabled", false)
v.SetDefault("a2a.listen", "0.0.0.0:8081")
v.SetDefault("a2a.path", "/a2a")
v.SetDefault("a2a.adapter", "cli")
v.SetDefault("a2a.session_id", "a2a")
v.SetDefault("a2a.timeout_sec", 120)
v.SetDefault("logging.level", "info")
v.SetDefault("metrics.port", 9092)
v.SetDefault("tls.enabled", false)
v.SetDefault("console.adapter", "cli")
v.SetDefault("console.target", "claude")
v.SetDefault("console.session_id", "default")
v.SetDefault("console.background", false)
v.SetDefault("console.timeout_sec", 120)
}