Commit Graph

2 Commits

Author SHA1 Message Date
Magnus Hedemark 79c11aea7a fix(plugins): complete task-routed LLM integration 2026-08-12 16:25:20 -07:00
hans 1176222b7c feat(plugins): route ctx.llm.complete(task=) through registered aux slots
Wire an optional `task=<key>` kwarg through the PluginLlm facade so a
plugin can route an LLM call through an auxiliary model slot it
registered via `ctx.register_auxiliary_task`. Registration already
existed; this adds the missing consumption half. Closes #44673.
Sub-issue 08/14 of the plugin-interface expansion tracking issue #64182.

- New optional `task:` kwarg on complete/acomplete/complete_structured/
  acomplete_structured. Unset or "auto" keeps today's main-model path
  byte-for-byte (task=None reaches call_llm exactly as before), so no
  prompt-cache or default-behavior change.
- A set task resolves provider/model through `auxiliary.<task>` via the
  existing auxiliary_client path, identical to built-in aux tasks.
- Trust gate (per the round-2 design correction): a plugin may only pass
  a key it registered itself; a built-in key additionally requires
  `plugins.entries.<id>.llm.allow_task_override: true`. A foreign or
  unknown key is rejected with a PluginLlmTrustError and a logged warning
  naming the offending plugin and key -- fail loud, NOT a silent fallback
  to auto (which would mask misconfiguration and could route to the main
  model the user steered elsewhere).
- The plugin_llm audit dict and audit-log line gain a `task` field.
- register_auxiliary_task now stores the plugin's canonical id
  (`key or name`, the same id ctx.llm is bound to) as the slot owner, so
  the trust gate matches ownership even when a manifest sets a distinct
  key. For the common no-key case this equals the name (unchanged).

Tests (tests/agent/test_plugin_llm_task_routing.py, 24): _check_task
resolution incl. own/foreign/unknown/built-in-gated keys and loud
rejection; end-to-end routing sync+async+structured; production-path
forwarding into call_llm/async_call_llm (covers the task=None->task line);
and ownership resolution against the real plugin registry incl. the
name/key reconciliation.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013b1XyXitAxV7phGmKWigJX
2026-08-12 16:25:20 -07:00