fix(setup): install list reflects opt-outs + Store bundle
`compute_default_agent_prompt` (which renders the install commands in the setup prompt's marketplace block) was calling `resolve_allowed_plugins` — the admin-only feed that predates the v25 Store/opt-out layer. Result: a user with 2 opted-out curated plugins + 2 Store skills saw the original 4 admin grants in the install list (including the opted-out ones, with cross-marketplace duplicates), and no `agnes-store-bundle` install line for the skills. Now we call `resolve_user_marketplace` — the same resolver that `/marketplace.zip` + `/marketplace.git/` serve from. The install commands now match the served catalog exactly: admin grants minus the user's opt-outs, plus the `agnes-store-bundle` synth plugin (which wraps every installed Store skill + agent into one plugin entry) and any standalone Store plugin uploads. Dedup by `manifest_name` because two upstream marketplaces shipping a plugin with the same name collide in the synth marketplace.json by design (CLAUDE.md "Same-named plugins ... collide in the catalog by design"). A duplicate `claude plugin install <name>@agnes` would be a no-op anyway, so it's just visual noise to keep emitting both.
This commit is contained in:
parent
af72c5d259
commit
5372d65b26
1 changed files with 22 additions and 9 deletions
|
|
@ -154,19 +154,32 @@ def compute_default_agent_prompt(
|
||||||
_wheel = _find_wheel()
|
_wheel = _find_wheel()
|
||||||
_wheel_filename = _wheel.name if _wheel else "agnes.whl"
|
_wheel_filename = _wheel.name if _wheel else "agnes.whl"
|
||||||
|
|
||||||
# RBAC plugin resolution is unconditional — same code path for
|
# The install commands emitted in the marketplace block must match
|
||||||
# admin and non-admin. Users with no `resource_grants` rows get an
|
# exactly what /marketplace.zip + /marketplace.git/ serve. That's
|
||||||
# empty list and the no-marketplace layout; users with grants get
|
# the `resolve_user_marketplace` view: admin grants minus the
|
||||||
# the marketplace block. Admin-vs-analyst is no longer a layout
|
# user's opt-outs, plus their Store installs (skills + agents
|
||||||
# branch.
|
# rolled up into the synth `agnes-store-bundle` plugin, plugin-
|
||||||
|
# typed entities standalone). `resolve_allowed_plugins` was the
|
||||||
|
# pre-store admin-only feed and would emit installs for plugins
|
||||||
|
# the user has opted out of, while skipping the bundle entirely.
|
||||||
|
#
|
||||||
|
# Dedup by manifest_name handles the documented case where two
|
||||||
|
# upstream marketplaces ship a plugin with the same name (see
|
||||||
|
# CLAUDE.md "Same-named plugins ... collide in the catalog by
|
||||||
|
# design"). The synth marketplace.json carries one entry per
|
||||||
|
# name; a second `claude plugin install <name>@agnes` would be
|
||||||
|
# a no-op anyway.
|
||||||
plugin_install_names: list[str] = []
|
plugin_install_names: list[str] = []
|
||||||
if user and conn is not None:
|
if user and conn is not None:
|
||||||
try:
|
try:
|
||||||
from src import marketplace_filter
|
from src import marketplace_filter
|
||||||
plugin_install_names = [
|
seen: set[str] = set()
|
||||||
p["manifest_name"]
|
for p in marketplace_filter.resolve_user_marketplace(conn, user):
|
||||||
for p in marketplace_filter.resolve_allowed_plugins(conn, user)
|
name = p["manifest_name"]
|
||||||
]
|
if name in seen:
|
||||||
|
continue
|
||||||
|
seen.add(name)
|
||||||
|
plugin_install_names.append(name)
|
||||||
except Exception:
|
except Exception:
|
||||||
logger.exception("compute_default_agent_prompt: marketplace plugin resolution failed")
|
logger.exception("compute_default_agent_prompt: marketplace plugin resolution failed")
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue