Extend the local plugin system's host<->plugin contract with generic,
capability-neutral facilities, so transport plugins can be built on top
without embedding plugin-specific logic in the host.
Host services (plugin dials a broker-provided HostService gRPC):
- per-plugin namespaced KV store (key/value size and TTL bounded)
- account directory: ListAccounts + ResolveOutboundIdentity, restricted to
the accounts a plugin's declared capability already covers
- InitHostServices lifecycle hook; plugins that don't implement it run
unchanged and are simply offered no host services
Read-only runtime status channel:
- HealthResponse gains an opaque, plugin-defined status_json produced
passively (no config apply, no upstream call, no side effects)
- GET /admin/plugins/:id/status (ungated) and the plugin.status UI-bridge
verb map to Health, so a status UI can poll live state without a step-up
prompt or a "test" side effect
- config.test no longer force-shows a host success toast; the plugin UI owns
result presentation, so plugins that read status do not spam toasts
Document the UI-bridge verb taxonomy (read vs mutate/test gating) and the
status contract under pkg/pluginapi.
DeepSeek native Responses rejects Codex view_image results when function_call_output.output contains input_image parts. Move media into a following user message and keep the tool output as a string so call_id pairing remains valid.
Paused (schedulable=false) active accounts were excluded from the
background token refresh candidates, so their stored access_token
silently expired. The admin usage-window quota probe uses the stored
token verbatim (no token provider / no refresh), so the probe then gets
HTTP 401 UNAUTHENTICATED and the dashboard reports a false "needs
re-auth" for a perfectly healthy account, while Test Connection and live
traffic (which refresh on demand via the token provider) keep working.
Pause is not permanent rejection: error accounts are already excluded by
the status = 'active' filter, and accounts whose refresh genuinely fails
are rate-limited by the retry-cooldown exclusion (10-minute retry-
exhausted cooldown). Refresh success only persists credentials and never
touches schedulable, so a paused account cannot be silently un-paused.
Drop the schedulable filter and update the SQL-filter test, the
integration pagination test, and the service-level candidate fake.
The Responses to Chat Completions bridge mapped both the instructions field and role developer items to system messages. Codex always sends both, and also injects developer notices mid-conversation when switching models, so the forwarded request contained consecutive leading system messages and mid-conversation system messages. Strict Qwen-family upstreams reject this with HTTP 400 "System message must be at the beginning."
Leading system/developer messages are now merged into a single leading system message, and later system/developer messages are downgraded to user so the content is preserved without violating upstream role ordering.
Real Ollama Cloud 429s are driven by ollama.com usage windows, not by
response headers that OpenAI/Anthropic/CN rate-limit parsing understands.
Handle them separately: apply a never-shortening temporary cooldown first,
then schedule an async probe that learns the true usage-window reset point
with a controlled, coalesced per-api_key refresh.
- ratelimit_service: route real Ollama Cloud usage accounts to a dedicated
429 path before the CN-provider branch.
- ollama_cloud_usage: add a background probe coordinator (started in Start,
waited by Stop) that fans out model-429 probes to one controlled refresh
per api_key group, reusing the recent group snapshot for coalesced members.
- repository/account_repo: add SetRateLimitedIfUnchanged, a write-back CAS
counterpart to ClearRateLimitIfObserved, so an async reset never overwrites
a newer 429, an admin clear, a re-armed generation, or a key/state change
observed by another writer between read and write.
- wire: inject OllamaCloudUsageService into RateLimitService.
Tests: unit tests for service and repository pass; targeted race tests pass;
build and vet clean; git diff --check clean. The CAS integration test compiles
but is not run (no Docker available).