Triple-C marketplace: agents, skills, commands, hooks and plugins for all or individual containers #65

Merged
jknapp merged 48 commits from feat/marketplace into main 2026-09-27 23:43:27 +00:00
2 changed files with 28 additions and 1 deletions
Showing only changes of commit 8ec033f923 - Show all commits
@@ -83,6 +83,31 @@ describe("InstalledPane", () => {
); );
}); });
it("PR review #8: an update belongs only to the install pinned at its commit", () => {
const C = "c".repeat(40);
// The same agent is installed globally at A and in p1 at C. Only the A
// install has an update (A → B); C is unchanged at head.
useAppState.setState({
projects: [
{
id: "p1",
name: "api",
status: "running",
marketplace_installs: [{ marketplace_id: "m1", kind: "agent", key: "rev", commit: C }],
marketplace_disabled: [],
},
] as unknown as Project[],
});
const mp = api({
updates: [{ item: { marketplace_id: "m1", kind: "agent", key: "rev" }, pinned: A, head: B }],
});
render(<InstalledPane mp={mp} />);
const global = screen.getByTestId("installed-global");
expect(within(global).getByRole("button", { name: "Review update for rev" })).toBeInTheDocument();
const proj = screen.getByTestId("installed-project-p1");
expect(within(proj).queryByRole("button", { name: "Review update for rev" })).not.toBeInTheDocument();
});
it("I2: accepts the head that was reviewed even if the update list moves on", async () => { it("I2: accepts the head that was reviewed even if the update list moves on", async () => {
const C = "c".repeat(40); const C = "c".repeat(40);
const item = { marketplace_id: "m1", kind: "agent" as const, key: "rev" }; const item = { marketplace_id: "m1", kind: "agent" as const, key: "rev" };
@@ -32,13 +32,15 @@ export default function InstalledPane({ mp }: { mp: MarketplaceApi }) {
const nameOf = (id: string) => marketplaces.find((m) => m.id === id)?.name ?? id; const nameOf = (id: string) => marketplaces.find((m) => m.id === id)?.name ?? id;
const globalInstalls = appSettings?.global_marketplace_installs ?? []; const globalInstalls = appSettings?.global_marketplace_installs ?? [];
/** The update for this very install: same item *and* pinned at the same
* commit (PR review #8) — updates are listed per (item, pinned commit). */
const updateFor = (i: MarketplaceInstall) => const updateFor = (i: MarketplaceInstall) =>
mp.updates.find( mp.updates.find(
(u) => (u) =>
u.item.marketplace_id === i.marketplace_id && u.item.marketplace_id === i.marketplace_id &&
u.item.kind === i.kind && u.item.kind === i.kind &&
u.item.key === i.key && u.item.key === i.key &&
u.head !== i.commit, u.pinned === i.commit,
); );
/** Hooks only (spec §3, preflight F8): the rendered commands at head, so the /** Hooks only (spec §3, preflight F8): the rendered commands at head, so the