loadLLMRuntime loads tool defs from toolConfigPath, reads the app config from the user's default config path (applying the configured language to tpl — defaulting when the config file is absent), resolves the LLM endpoint (honoring modelOverride from --model when non-empty), and returns the runtime
(tpl *template.Template, toolConfigPath, modelOverride string)
| 150 | // endpoint (honoring modelOverride from --model when non-empty), and |
| 151 | // returns the runtime bundle. tpl is mutated in place. |
| 152 | func loadLLMRuntime(tpl *template.Template, toolConfigPath, modelOverride string) (*llmRuntime, error) { |
| 153 | toolEntries, err := toolsconfig.Load(toolConfigPath) |
| 154 | if err != nil { |
| 155 | return nil, fmt.Errorf("load tools: %w", err) |
| 156 | } |
| 157 | planToolDefs := agent.BuildToolDefs(toolEntries, true) |
| 158 | mainToolDefs := agent.BuildToolDefs(toolEntries, false) |
| 159 | |
| 160 | cfgPath, err := defaultConfigPath() |
| 161 | if err != nil { |
| 162 | return nil, err |
| 163 | } |
| 164 | appCfg, err := LoadAppConfig(cfgPath) |
| 165 | if err != nil { |
| 166 | return nil, fmt.Errorf("load app config: %w", err) |
| 167 | } |
| 168 | // Apply the language directive even when the config file is missing |
| 169 | // (upstream #fix: ApplyLanguage with empty lang falls back to default). |
| 170 | var lang, provider string |
| 171 | if appCfg != nil { |
| 172 | lang = appCfg.Language |
| 173 | provider = appCfg.Provider |
| 174 | } |
| 175 | tpl.ApplyLanguage(lang) |
| 176 | |
| 177 | ep, err := llm.ResolveEndpointWithModelOverride(cfgPath, modelOverride) |
| 178 | if err != nil { |
| 179 | return nil, fmt.Errorf("resolve LLM endpoint: %w", err) |
| 180 | } |
| 181 | |
| 182 | return &llmRuntime{ |
| 183 | Client: llm.NewLLMClient(ep), |
| 184 | Model: ep.Model, |
| 185 | Provider: provider, |
| 186 | PlanToolDefs: planToolDefs, |
| 187 | MainToolDefs: mainToolDefs, |
| 188 | Collector: tool.NewCommentCollector(), |
| 189 | AppCfg: appCfg, |
| 190 | RuntimeConfig: agent.RuntimeConfig{ |
| 191 | Protocol: ep.Protocol, |
| 192 | EndpointHost: sanitizeEndpointHost(ep.URL), |
| 193 | Language: lang, |
| 194 | Timeout: ep.Timeout, |
| 195 | }, |
| 196 | }, nil |
| 197 | } |
| 198 | |
| 199 | // sanitizeEndpointHost extracts the credential-free host[:port] from a full LLM |
| 200 | // endpoint URL, dropping scheme, any embedded userinfo, path, query and fragment |
no test coverage detected