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) }