diff --git a/config.yaml.example b/config.yaml.example index bbb27c3..1ef1e6c 100644 --- a/config.yaml.example +++ b/config.yaml.example @@ -9,6 +9,8 @@ telegram: # Всё ниже — опционально, показаны дефолты: # opencode: # bin: "opencode" +# config: "/путь/к/opencode.json" # файл-конфиг модели (OPENCODE_CONFIG) +# config_dir: "./agents" # каталог с агентами (OPENCODE_CONFIG_DIR) # hard_timeout: "20m" # idle_timeout: "2m" diff --git a/internal/app/app.go b/internal/app/app.go index e09800a..db511fd 100644 --- a/internal/app/app.go +++ b/internal/app/app.go @@ -57,6 +57,7 @@ func New(configPath string) (*App, error) { Bin: cfg.OpenCode.Bin, DBPath: cfg.OpenCode.DBPath, Config: cfg.OpenCode.Config, + ConfigDir: cfg.OpenCode.ConfigDir, IdleTimeout: cfg.OpenCode.IdleTimeout.Duration(), HardTimeout: cfg.OpenCode.HardTimeout.Duration(), PollInterval: cfg.OpenCode.PollMs.Duration(), diff --git a/internal/config/config_test.go b/internal/config/config_test.go index 287c721..b1d6d71 100644 --- a/internal/config/config_test.go +++ b/internal/config/config_test.go @@ -80,6 +80,34 @@ telegram: } } +func TestLoad_OpenCodeConfigDir(t *testing.T) { + t.Setenv("TG_TOKEN", "tok") + t.Setenv("TG_CHAT_ID", "42") + + // без config_dir — пусто + yaml := `telegram: + token: "${TG_TOKEN}" + chat_id: "${TG_CHAT_ID}" +` + cfg, err := Load(writeCfg(t, yaml)) + if err != nil { + t.Fatalf("Load: %v", err) + } + if cfg.OpenCode.ConfigDir != "" { + t.Errorf("config_dir = %q, want пусто", cfg.OpenCode.ConfigDir) + } + + // через env OPENCODE_CONFIG_DIR + t.Setenv("OPENCODE_CONFIG_DIR", "/opt/agents") + cfg, err = Load(writeCfg(t, yaml)) + if err != nil { + t.Fatalf("Load: %v", err) + } + if cfg.OpenCode.ConfigDir != "/opt/agents" { + t.Errorf("config_dir = %q, want /opt/agents", cfg.OpenCode.ConfigDir) + } +} + func TestLoad_EnvOverride(t *testing.T) { t.Setenv("TG_TOKEN", "tok") t.Setenv("TG_CHAT_ID", "42") diff --git a/internal/config/types.go b/internal/config/types.go index 2cc3186..d8367f7 100644 --- a/internal/config/types.go +++ b/internal/config/types.go @@ -49,6 +49,7 @@ type OpenCodeCfg struct { Bin string `yaml:"bin" default:"opencode"` DBPath string `yaml:"db_path" default:""` Config string `yaml:"config" env:"OPENCODE_CONFIG"` + ConfigDir string `yaml:"config_dir" env:"OPENCODE_CONFIG_DIR"` HardTimeout Duration `yaml:"hard_timeout" default:"20m"` IdleTimeout Duration `yaml:"idle_timeout" default:"2m"` PollMs Duration `yaml:"poll_ms" default:"2s"` diff --git a/internal/opencode/runner.go b/internal/opencode/runner.go index e20feb8..fc999d1 100644 --- a/internal/opencode/runner.go +++ b/internal/opencode/runner.go @@ -29,6 +29,7 @@ type Runner struct { Bin string // путь к opencode (по умолчанию "opencode") DBPath string // путь к opencode.db (idle-детекция активности) Config string // путь к opencode.json (OPENCODE_CONFIG) + ConfigDir string // путь к каталогу с агентами (OPENCODE_CONFIG_DIR) IdleTimeout time.Duration // нет новых сообщений в БД → зависание HardTimeout time.Duration // общий лимит на запуск PollInterval time.Duration @@ -120,6 +121,9 @@ func (r *Runner) Run(ctx context.Context, prompt, cwd, agent, sessionID string) if r.Config != "" { env = append(env, "OPENCODE_CONFIG="+r.Config) } + if r.ConfigDir != "" { + env = append(env, "OPENCODE_CONFIG_DIR="+r.ConfigDir) + } proc := exec.CommandContext(ctx, cmd[0], cmd[1:]...) proc.Env = env