BUG/ARCH: WebUI extension discovery ignores the active agent/project context #172

Open
opened 2026-09-09 15:05:22 +00:00 by nsaspy · 0 comments
Owner

Finding

The backend extension resolver is designed to be context-aware: helpers.extension.get_webui_extensions(agent, ...) and get_webui_extension_manifest(agent) both accept an Agent, and subagents.get_paths(agent, ...) adds project/profile-specific roots when an agent is provided.

But both WebUI discovery entry points currently hard-code agent=None:

  • helpers/ui_server.py::serve_index() embeds get_webui_extension_manifest(agent=None) into runtimeInfo.webuiExtensions.
  • api/load_webui_extensions.py calls extension.get_webui_extensions(agent=None, ...) as its compatibility fallback.

The frontend then prefers the bootstrap manifest whenever it exists. manifestExtensionPaths() returns an empty list, not null, for an extension point absent from that global manifest, so it will not even try the API fallback in that case.

Result: profile/project-specific extensions/webui roots that the backend path model is capable of resolving cannot follow the selected chat/agent/project in the live WebUI.

This is directly at odds with the goal that plugins/agents can fully modify the UI and will become more visible under the modern shell work (#23).

Direction

Make WebUI extension capability resolution explicitly scoped/versioned to the active UI context:

  • active context ID / project / agent profile
  • enabled plugin set for that scope
  • manifest version
  • clear transition event when the selected context changes effective extension scope

Do not fetch/execute arbitrary user paths from the browser; keep backend canonical path resolution.

Acceptance

  • Selecting a chat with project/profile-specific WebUI extensions activates the correct scoped extension set.
  • Switching between chats/projects/profiles removes/replaces extensions that are no longer effective and loads newly effective ones deterministically.
  • Global/default extensions remain available.
  • Bootstrap manifest and API fallback use the same resolution contract.
  • Missing extension point is distinguishable from “manifest has authoritative empty result,” so stale/global manifests cannot suppress scoped discovery.
  • Extension cache keys include the effective scope/version and cannot leak one project's UI into another.
  • Plugin/agent/project extension changes invalidate the relevant manifest/frontend cache without requiring a server restart.
  • Tests cover global, agent, project, project+agent and plugin override precedence.
  • Existing x-extension IDs remain compatible.

Mirrored from lost-rob0t/a0-symbolics#34 via tracker sync.

## Finding The backend extension resolver is designed to be context-aware: `helpers.extension.get_webui_extensions(agent, ...)` and `get_webui_extension_manifest(agent)` both accept an `Agent`, and `subagents.get_paths(agent, ...)` adds project/profile-specific roots when an agent is provided. But both WebUI discovery entry points currently hard-code `agent=None`: - `helpers/ui_server.py::serve_index()` embeds `get_webui_extension_manifest(agent=None)` into `runtimeInfo.webuiExtensions`. - `api/load_webui_extensions.py` calls `extension.get_webui_extensions(agent=None, ...)` as its compatibility fallback. The frontend then prefers the bootstrap manifest whenever it exists. `manifestExtensionPaths()` returns an empty list, not `null`, for an extension point absent from that global manifest, so it will not even try the API fallback in that case. Result: profile/project-specific `extensions/webui` roots that the backend path model is capable of resolving cannot follow the selected chat/agent/project in the live WebUI. This is directly at odds with the goal that plugins/agents can fully modify the UI and will become more visible under the modern shell work (#23). ## Direction Make WebUI extension capability resolution explicitly scoped/versioned to the active UI context: - active context ID / project / agent profile - enabled plugin set for that scope - manifest version - clear transition event when the selected context changes effective extension scope Do not fetch/execute arbitrary user paths from the browser; keep backend canonical path resolution. ## Acceptance - [ ] Selecting a chat with project/profile-specific WebUI extensions activates the correct scoped extension set. - [ ] Switching between chats/projects/profiles removes/replaces extensions that are no longer effective and loads newly effective ones deterministically. - [ ] Global/default extensions remain available. - [ ] Bootstrap manifest and API fallback use the same resolution contract. - [ ] Missing extension point is distinguishable from “manifest has authoritative empty result,” so stale/global manifests cannot suppress scoped discovery. - [ ] Extension cache keys include the effective scope/version and cannot leak one project's UI into another. - [ ] Plugin/agent/project extension changes invalidate the relevant manifest/frontend cache without requiring a server restart. - [ ] Tests cover global, agent, project, project+agent and plugin override precedence. - [ ] Existing `x-extension` IDs remain compatible. --- *Mirrored from [`lost-rob0t/a0-symbolics#34`](https://github.com/lost-rob0t/a0-symbolics/issues/34)* via tracker sync.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
nsaspy/a0-symbolics#172
No description provided.