Files
Cyrene_v2/cmd/cyrene/vision.go
T
Aska eddb9b9891 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 干净。
2026-09-06 16:07:04 +08:00

43 lines
1.5 KiB
Go

package main
import (
"strings"
"git.yeij.top/AskaEth/Cyrene_v2/internal/logger"
"git.yeij.top/AskaEth/Cyrene_v2/internal/runtime/multimodal/vision"
)
// visionToolName and ocrToolName are the registered names of the vision and OCR
// tools. They are bound to the tool registration here and advertised to the
// agent by the tool dispatcher.
const (
visionToolName = "vision"
ocrToolName = "ocr"
)
// wireVision registers the vision and OCR tools and the vision model routing.
//
// The vision adapter is an OpenAI-compatible /chat/completions endpoint on the
// same base URL as the chat LLM (LLM_BASE_URL), using the dedicated model
// (LLM_VISION_MODEL) when set. When no base URL is configured the tools are
// skipped with a warning so startup never blocks; the model router is still
// bound to the vision model (in wireRuntime) whenever one is configured.
func (a *app) wireVision() {
log := logger.WithSource(a.log, "cmd/cyrene")
if strings.TrimSpace(a.cfg.LLM.BaseURL) == "" {
log.Warn("vision/ocr tools skipped: no LLM base url configured")
return
}
adapter := vision.NewOpenAICompatible(a.cfg.LLM,
vision.WithModel(a.cfg.LLM.VisionModel),
vision.WithLogger(a.log))
if err := vision.RegisterTools(a.caps,
vision.NewVisionTool(visionToolName, adapter),
vision.NewOCRTool(ocrToolName, adapter),
); err != nil {
log.Warn("vision/ocr tool register skipped", "error", err)
return
}
log.Info("vision/ocr tools registered", "vision_model", a.cfg.LLM.VisionModel)
}