Repository navigation
The agent picker reads AiSettings.AgentQueries — plugin agents surface everywhere - #930
Conversation
…read-side methods
…e everywhere Fixes #901. PR #858 wired the WRITE side (AiSourcesInstallHook registers each installed package's {partition}/Agent source into every user's AiSettings.AgentQueries) and the SKILLS read side — but nothing ever READ AgentQueries: every picker surface issued the fixed namespace:{user}/Agent|{space}/Agent|Agent union, so plugin-shipped agents stayed invisible unless the chat happened to run inside the plugin's own partition (empty picker; "the agent catalog is empty" on selection). The read side now mirrors the skills read side: - AiSettingsNodeType.ResolveAgentQueries — the canonical base union (BuildAgentQuery: platform + user + space) stays ALWAYS FIRST (the only row guaranteed to resolve — same rule as the skills platform row), settings rows follow token-substituted, deduped case-insensitively. The fused default template dedupes into the base when its tokens resolve and drops harmlessly on a null context — the base already covers those layers, so package rows can never displace platform/user agents. - ObserveAgentQueries (live, mirrors ObserveSkillQueries) and ResolveAgentQueriesOnce (click-time one-shot against the FIRST live settings snapshot — not Observe's immediate defaults emission, which would miss package rows — degrading to the base after a 2s bound so the picker never hangs). - AgentPickerProjection.ObserveAgents is now settings-aware via ObserveAgentQueries + Switch — one change, every consumer fixed: the combobox/@-detection (ThreadChatView), ObserveDefaultComposer, and AgentChatClient's execution-side resolution all ride this pipe, so the picker offers exactly what execution resolves. The synced-query id carries a SHA-256 fingerprint of the resolved set: hub.GetQuery caches the shared upstream by id, so a settings change must mint a new id or the old subscription serves stale queries forever. - ThreadChatView.OpenPicker's /agent branch resolves through ResolveAgentQueriesOnce composed into its existing timing-safe chain. Verified: AgentPickerQueriesTest 40/40 (4 new ResolveAgentQueries cases: defaults ≡ canonical base bit-for-bit, package row appends after base, null context keeps platform+user via the base, reserved context nulled) and AgentPickerProjectionTest 6/6 including the new end-to-end ObserveAgents_PackageSourceInSettings_SurfacesPackageAgent (package agent in a foreign-space chat context). Release -warnaserror builds clean. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR wires the agent picker and related chat surfaces to read AiSettings.AgentQueries (the per-user registry sources written at package install time), so package/plugin-shipped agents become visible and selectable regardless of the current chat space.
Changes:
- Added
ResolveAgentQueriesplus live/one-shot settings readers (ObserveAgentQueries,ResolveAgentQueriesOnce) inAiSettingsNodeType. - Updated
AgentPickerProjection.ObserveAgentsto become settings-aware and cache-safe by incorporating a fingerprinted query-id. - Updated the
/agentpicker path inThreadChatViewto resolve agent queries via the new one-shot settings read, and added/extended tests + a What’s New entry.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
src/MeshWeaver.AI/AiSettingsNodeType.cs |
Adds the agent-query resolution + live/one-shot settings-based query sources to mirror the existing skills path. |
src/MeshWeaver.AI/AgentPickerProjection.cs |
Makes the agent observation pipeline settings-aware and ensures query-cache invalidation via a resolved-query fingerprint in the query id. |
src/MeshWeaver.Blazor.Portal/Chat/ThreadChatView.razor.cs |
Updates the /agent picker branch to use the settings-aware, bounded one-shot agent-query resolver. |
test/MeshWeaver.AI.Test/AgentPickerQueriesTest.cs |
Adds targeted unit tests for the new ResolveAgentQueries behavior and edge cases. |
test/MeshWeaver.Hosting.Monolith.Test/AgentPickerProjectionTest.cs |
Adds an end-to-end monolith test ensuring package agents surface via the settings-aware pipeline outside the package partition. |
src/MeshWeaver.Documentation/Data/WhatsNew/2026-08-08-plugin-agents-in-picker.md |
Adds a user-facing What’s New entry describing the fixed agent picker behavior for package-installed agents. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Test Results (shard 5)1 676 tests 1 485 ✅ 5m 42s ⏱️ Results for commit 648ed61. |
Test Results (shard 4)1 211 tests 1 206 ✅ 5m 27s ⏱️ Results for commit 648ed61. ♻️ This comment has been updated with latest results. |
Test Results (shard 3) 11 files 11 suites 5m 49s ⏱️ Results for commit 648ed61. |
Test Results (shard 0)673 tests 673 ✅ 5m 16s ⏱️ Results for commit 648ed61. |
Test Results (shard 2)1 789 tests 1 787 ✅ 6m 16s ⏱️ Results for commit 648ed61. |
Test Results (shard 1)1 186 tests 1 186 ✅ 8m 9s ⏱️ Results for commit 648ed61. |
Test Results 65 files 65 suites 36m 42s ⏱️ Results for commit 648ed61. ♻️ This comment has been updated with latest results. |
Fixes #901.
The defect
#858 wired the write side (install hook registers
{partition}/Agentinto every user'sAiSettings.AgentQueries) and the skills read side — but nothing ever readAgentQueries. Every picker surface issued the fixednamespace:{user}/Agent|{space}/Agent|Agentunion, so plugin-shipped agents stayed invisible (empty picker, "the agent catalog is empty" on selection) unless the chat ran inside the plugin's own partition.The fix — mirror the skills read side, one pipeline
ResolveAgentQueries: canonical base union always first (the only row guaranteed to resolve — the skills platform-row rule), settings rows follow token-substituted and deduped. The fused default template dedupes into the base when its tokens resolve and drops harmlessly on a null context — package rows can never displace platform/user agents.ObserveAgentQueries(live) +ResolveAgentQueriesOnce(click-time one-shot against the first live settings snapshot, 2 s bound → degrades to the base, never hangs the picker).AgentPickerProjection.ObserveAgentsis now settings-aware (ObserveAgentQueries+Switch) — one change fixes every consumer: combobox/@-detection,ObserveDefaultComposer, andAgentChatClient's execution-side resolution, so the picker offers exactly what execution resolves. The synced-query id carries a SHA-256 fingerprint of the resolved set (the shared upstream is cached by id — a settings change must mint a new id).OpenPicker's/agentbranch resolves throughResolveAgentQueriesOncein its existing timing-safe chain.Verification
AgentPickerQueriesTest40/40 — 4 newResolveAgentQueriescases: defaults ≡ canonical base bit-for-bit (pre-fix behavior preserved for users with no packages), package row appends after base, null context keeps platform+user via the base, reserved context nulled.AgentPickerProjectionTest6/6 — new end-to-end: a package agent seeded underPickerPkg/Agent+ the exact settings write the install hook performs surfaces throughObserveAgentswhile chatting in a different space.-warnaserrorbuilds clean (MeshWeaver.AI, MeshWeaver.Blazor.Portal, both test projects).What's New entry included (user-facing).
🤖 Generated with Claude Code