From 6afd6427a42e5bb0da33f92c91c81a7a890e27e7 Mon Sep 17 00:00:00 2001 From: Anthony Ettinger Date: Sun, 8 Nov 2026 16:38:49 +0000 Subject: [PATCH 1/3] plugins page: mark unbuilt plugins coming soon, honest install/default labels Co-Authored-By: Claude Opus 5.5 --- apps/web/src/app/api/plugins/route.ts | 16 ++++++- apps/web/src/app/plugins/page.tsx | 47 +++++++++++++++--- apps/web/src/lib/plugins.ts | 66 +++++++++++++++++++++++--- plugins/ad-generator-agent/module.toml | 1 + plugins/ads-manager/module.toml | 1 + plugins/coinpay/module.toml | 1 + plugins/crawl/module.toml | 28 +++++------ plugins/ctv-ads/module.toml | 1 + plugins/diffusion/module.toml | 2 + plugins/embed/module.toml | 1 + plugins/gameserver/module.toml | 1 + plugins/hosting/module.toml | 1 + plugins/infernet/module.toml | 2 + plugins/live-stream/module.toml | 1 + plugins/ocr/module.toml | 1 + plugins/podcast-ads/module.toml | 1 + plugins/podcasting/module.toml | 1 + plugins/podcasts/module.toml | 1 + plugins/render/module.toml | 1 + plugins/secure-chat/module.toml | 2 + plugins/storage/module.toml | 2 + plugins/train/module.toml | 1 + plugins/transcode/module.toml | 2 + plugins/tts/module.toml | 2 + plugins/video/module.toml | 2 + plugins/webhook/module.toml | 2 + plugins/whisper/module.toml | 2 + plugins/workflow-step/module.toml | 2 + 28 files changed, 159 insertions(+), 32 deletions(-) diff --git a/apps/web/src/app/api/plugins/route.ts b/apps/web/src/app/api/plugins/route.ts index cf89594b..f3c7073d 100644 --- a/apps/web/src/app/api/plugins/route.ts +++ b/apps/web/src/app/api/plugins/route.ts @@ -12,6 +12,7 @@ import { loadAllPlugins, tagline, installCommand, + installedByDefault, modelOptions, } from "@/lib/plugins"; @@ -20,19 +21,30 @@ export function GET() { // Omitted rather than sent as [] for the plugins that have no model to // choose, which is most of them. const models = modelOptions(p).map(({ id, model }) => ({ id, ...model })); + const install = installCommand(p); return { id: p.id, name: p.name, version: p.version, kind: p.kind, + // available | partial | coming-soon. A coming-soon plugin is a spec + // with no implementation behind it yet. + status: p.status, + status_note: p.statusNote, + builtin: p.builtin, + installed_by_default: installedByDefault(p), tagline: tagline(p), description: p.description, keywords: p.keywords ?? [], homepage: p.homepage, source: p.source, - install_command: installCommand(p), - install_url: `https://c0mpute.com/plugins/${p.id}/install.sh`, + // null when there is nothing to install: built in, coming soon, or no + // install.sh in the repo. + install_command: install, + install_url: install + ? `https://c0mpute.com/plugins/${p.id}/install.sh` + : null, web: `https://c0mpute.com/plugins/${p.id}`, models: models.length > 0 ? models : undefined, }; diff --git a/apps/web/src/app/plugins/page.tsx b/apps/web/src/app/plugins/page.tsx index 1bacaa1d..556f91b1 100644 --- a/apps/web/src/app/plugins/page.tsx +++ b/apps/web/src/app/plugins/page.tsx @@ -6,6 +6,7 @@ import { byCategory, tagline, installCommand, + installedByDefault, modelOptions, CATEGORY_LABELS, CATEGORY_BLURBS, @@ -64,6 +65,12 @@ export default function PluginsPage() { is a product built on{" "} c0mpute — useful, and not something the protocol depends on.

+

+ runs today with a caveat noted on the + card.{" "} + is a published spec with no + implementation yet — nothing to install or run. +

{groups.map(({ category, plugins }) => ( @@ -74,6 +81,8 @@ export default function PluginsPage() { {" "} · {plugins.length} + {comingSoonCount(plugins) > 0 && + ` (${comingSoonCount(plugins)} coming soon)`}

@@ -119,6 +128,10 @@ function kindLabel(p: PluginManifest): string { return p.category === "applications" ? "application" : "service"; } +function comingSoonCount(plugins: PluginManifest[]): number { + return plugins.filter((p) => p.status === "coming-soon").length; +} + function Badge({ label }: { label: string }) { return ( @@ -134,15 +147,27 @@ function PluginCard({ p }: { p: PluginManifest }) { : p.dispatch?.mode === "container" ? "container" : "subprocess"; + const comingSoon = p.status === "coming-soon"; + const install = installCommand(p); return ( -

+

[ {p.id} ]{" "} {p.name} + {p.status !== "available" && ( + <> + {" "} + + + + + )}

v{p.version} · {kindLabel(p)} · {dispatchLabel} @@ -161,14 +186,24 @@ function PluginCard({ p }: { p: PluginManifest }) { - {p.dispatch?.mode === "in-process" ? ( -

ships with c0mpute · installed by default

- ) : ( - {`$ ${installCommand(p)}`} + {p.status === "partial" && p.statusNote && ( +

+ partial: {p.statusNote} +

)} + {comingSoon ? ( +

+ coming soon · spec only, not yet implemented +

+ ) : installedByDefault(p) ? ( +

ships with c0mpute · installed by default

+ ) : install ? ( + {`$ ${install}`} + ) : null} +