feat(wire): 地基④ wire.go 接 vision/voice/mcp/skill/exec 五个子系统,从死代码变可用

- vision:model.Router 绑 WithVisionModel(LLM_VISION_MODEL);vision.RegisterTools(VisualTool/OCRTool)
  用同一 OpenAICompatibleAdapter(LLM_BASE_URL 为空则跳过并 Warn)。
- voice:voice.New(cfg.Voice) Chain(cloud→local→edge-tts/espeak→silent)存 a.voice。
- mcp:读 cfg.MCP.ServersJSON → 逐 Enabled server mcp.NewRegistry(...).Register(ctx)(Connect+
  DiscoverTools+RegisterTool),注册 KindMCP 能力 mcp:<name> 供 adminListPlugins 枚举;
  close() 中 Unregister 防 stdio 子进程孤儿;每 server 15s connect 超时,失败 Warn 跳过。
- skills:LoadDir(configs/skills) → skills.Register 为 KindSkill(Runner.Run 仍 ErrRunPending,
  执行留后续)。
- exec/terminal:新 terminalTool(sdk.Tool) 内部调 execProv.Execute,注册进 dispatcher;
  ExecSandbox.Enabled=false 默认拦截(授权默认关)。
- config:LLMConfig 增 VisionModel(LLM_VISION_MODEL);新增 MCPConfig/ServersJSON(MCPSERVERS_JSON)。
- 拆 5 个辅助文件(vision.go/voice.go/mcp.go/skills.go/terminal_tool.go)避免 wire.go 膨胀;
  wire.go 最终 535 行。

默认配置下各子系统干净跳过不阻断启动(LLM_BASE_URL 已配则 vision 用主模型降级)。
go build/vet/test 全绿(46 包),gofmt 干净。
This commit is contained in:
Aska committed 2026-09-06 16:07:04 +08:00
1 parent 9b207a31e8
commit eddb9b9891
8 files changed
+362 -1

No files matched your search

+17 -1
View File
@@ -12,6 +12,7 @@ import (
"git.yeij.top/AskaEth/Cyrene_v2/internal/auth"
"git.yeij.top/AskaEth/Cyrene_v2/internal/bus"
"git.yeij.top/AskaEth/Cyrene_v2/internal/capability/mcp"
"git.yeij.top/AskaEth/Cyrene_v2/internal/capability/registry"
"git.yeij.top/AskaEth/Cyrene_v2/internal/channel/session"
"git.yeij.top/AskaEth/Cyrene_v2/internal/config"
@@ -30,6 +31,7 @@ import (
"git.yeij.top/AskaEth/Cyrene_v2/internal/runtime/memory/projectindex"
"git.yeij.top/AskaEth/Cyrene_v2/internal/runtime/memory/vector"
"git.yeij.top/AskaEth/Cyrene_v2/internal/runtime/model"
"git.yeij.top/AskaEth/Cyrene_v2/internal/runtime/multimodal/voice"
"git.yeij.top/AskaEth/Cyrene_v2/internal/runtime/orchestration"
"git.yeij.top/AskaEth/Cyrene_v2/internal/runtime/orchestration/audit"
"git.yeij.top/AskaEth/Cyrene_v2/internal/runtime/persist"
@@ -79,7 +81,10 @@ type app struct {
loop *loop.Loop
scheduler *orchestration.Scheduler
tasks *task.Manager
execProv exec.Provider
iot *iot.Manager
voice *voice.Chain
mcpRegs []*mcp.Registry
sessions *session.SessionManager
automation *automations.Service
backthink *backthink.Backthink
@@ -251,7 +256,8 @@ func (a *app) wireRuntime() error {
a.log.Warn("llm adapter unavailable", "error", aerr)
adapter = nil
}
router := model.NewRouter(model.DefaultModelForProvider(a.cfg.LLM))
router := model.NewRouter(model.DefaultModelForProvider(a.cfg.LLM),
model.WithVisionModel(a.cfg.LLM.VisionModel))
dispatcher, derr := tool.New(a.caps, tool.WithDefaultTimeout(defaultToolTimeout))
if derr != nil {
@@ -271,6 +277,7 @@ func (a *app) wireRuntime() error {
a.log.Warn("io tool register skipped", "tool", t.Name(), "error", rerr)
}
}
a.wireVision()
guards := guardrail.New()
instructions := a.defaultInstructions()
@@ -326,6 +333,7 @@ func (a *app) wireAuxiliary() error {
if err != nil {
return fmt.Errorf("exec provider: %w", err)
}
a.execProv = provider
tmgr, err := task.New(a.cfg, provider, a.log, task.WithBus(a.bus))
if err != nil {
return fmt.Errorf("task manager: %w", err)
@@ -365,6 +373,11 @@ func (a *app) wireAuxiliary() error {
return fmt.Errorf("backthink: %w", err)
}
a.backthink = bt
a.wireVoice()
a.wireMCP()
a.wireSkills()
a.wireTerminalTool()
return nil
}
@@ -473,6 +486,9 @@ func (a *app) close(ctx context.Context) {
if a.gw != nil {
a.gw.Close()
}
for _, reg := range a.mcpRegs {
_ = reg.Unregister(ctx)
}
if a.tasks != nil {
_ = a.tasks.Close()
}