* fix(agent): propagate explicit provider/model config into agent execution (#2962)
`providers configure` and `agent spawn --provider/--model` persisted user
intent but the execution path (callAnthropicMessages, executeAgentTask,
determineAgentModel) only ever consulted env vars and a 5-alias model list,
silently discarding both. A local Ollama/OpenRouter setup with explicit
config would either fail closed or fall back to whatever provider the
env vars happened to select.
- determineAgentModel(): treat any non-alias config.model string as an
explicit selection via the existing modelId fast-path, instead of
falling through to task-based routing / agent-type defaults.
- agent_spawn: forward config.provider to the stored (and returned) agent
record when it's an unambiguous explicit choice ('ollama'/'openrouter';
'anthropic' is excluded since the CLI silently defaults to it when
--provider isn't passed).
- callAnthropicMessages(): accept an optional provider param and consult
the persisted `agents.providers` config for baseUrl/apiKey/model when
env vars are absent. A self-hosted Ollama baseUrl no longer requires
the undocumented OLLAMA_API_KEY='local' sentinel.
- executeAgentTask(): forward agent.provider into the first dispatch call.
Precedence: explicit per-agent flag > env vars > persisted config >
key-presence inference (unchanged, last resort).
Co-Authored-By: RuFlo <ruv@ruv.net>
* fix(ci): update #2042 smoke to match the widened OpenRouter branch shape
The #2042 regression smoke statically matched the literal token sequence
`useOpenRouter && openrouterKey`. #2962 widened that condition to
`if (useOpenRouter) { const apiKey = openrouterKey || persistedOpenRouter?.apiKey; ... }`
so a persisted `agents.providers` config can supply the key when no env
var is set — the smoke's ordering guarantee (OpenRouter branch reachable
before the Anthropic-key early-return) still holds, only the literal
pattern needed updating.
Co-Authored-By: RuFlo <ruv@ruv.net>
CI failed because `npm install` from `v3/@claude-flow/cli` directly
chokes on `workspace:*` deps that only resolve from the monorepo root.
The smoke's behavioral check (importing the built dist) required a
build, which required the install, which failed.
Drop the dist-import behavioral check entirely. Replace it with a
stronger static-contract assertion: the OpenRouter dispatch must come
BEFORE the Anthropic-key early-return in `callAnthropicMessages`. That
catches the actual regression class (`#2042` was the OpenRouter branch
being unreachable) without requiring a build artifact.
Workflow steps revert to the same shape as the ruvllm-wasm-auto-init
smoke — checkout + setup-node + run smoke. No install, no build.
Verified locally: 5/5 checks PASS.
Co-Authored-By: RuFlo <ruflo-bot@users.noreply.github.com>
Reporter: @ummcke00. `agent_execute` and the underlying
`executeAgentTask()` runtime hardcoded a `fetch` to
`https://api.anthropic.com/v1/messages` and required
`ANTHROPIC_API_KEY` in the environment — even when the user had
configured OpenRouter, Ollama, or another OpenAI-compatible
endpoint via `.claude-flow/config.yaml`. Result: Ruflo was
unusable for every non-Anthropic deployment.
The companion `callAnthropicMessages()` helper already had a
two-branch dispatch (Anthropic + Ollama via #1725) but
`executeAgentTask()` predated it and never delegated.
## Fix
1. `callAnthropicMessages()` (the router):
- Add OpenRouter branch detected via `RUFLO_PROVIDER=openrouter`
or `OPENROUTER_API_KEY` set when Anthropic key absent. Mirrors
the existing Ollama branch precedence.
- New `callOpenAICompat()` helper — OpenAI-compat shape with
`Authorization: Bearer <key>`, OpenRouter analytics headers,
and logical model name translation (haiku/sonnet/opus →
anthropic/claude-3.5-haiku/sonnet/3-opus).
- Updated "no provider configured" error lists all three options.
2. `executeAgentTask()`:
- Replace the inline Anthropic fetch with `await
callAnthropicMessages({...})`. The agent registry coupling
(store load, status updates, lastResult persistence) stays.
- Surface a #2042-aware remediation pointer when the router
reports no provider is configured.
3. New CI smoke `scripts/smoke-agent-execute-providers.mjs` (5
checks):
- executeAgentTask no longer contains the bypass fetch
- OPENROUTER_API_KEY env var is referenced
- callOpenAICompat helper exists
- No-provider error lists Anthropic + OpenRouter + Ollama
- Behavioral: OPENROUTER_API_KEY set → dispatch reaches the
openrouter branch (auth error names openrouter, not Anthropic)
Wired into v3-ci.yml as `agent-execute-providers-smoke` with
path-filter on `agent-execute-core.ts` and the smoke itself.
Local validation (against built dist):
- No provider set → "No LLM provider configured..."
- OPENROUTER_API_KEY only → "openrouter API error 401: Missing
Authentication header"
- RUFLO_PROVIDER=openrouter
+ both keys → "openrouter API error 401..."
(Anthropic key is bypassed — explicit RUFLO_PROVIDER wins)
`workflow-tools.ts` `workflow_execute` also calls
`executeAgentTask()` and gets the fix transitively with no
direct edits.
Co-Authored-By: RuFlo <ruflo-bot@users.noreply.github.com>