Badge experimental bundled plugins

This commit is contained in:
Dotta committed 2026-05-26 13:04:29 +00:00
1 parent 773ced1bdb
commit 438c2c085c
4 files changed
+35

No files matched your search

@@ -146,11 +146,18 @@ describe.sequential("plugin install and upgrade authz", () => {
expect(res.status).toBe(200);
const packageNames = res.body.map((plugin: { packageName: string }) => plugin.packageName);
const byPackageName = new Map(
res.body.map((plugin: { packageName: string; experimental: boolean }) => [plugin.packageName, plugin]),
);
expect(packageNames).toContain("@paperclipai/plugin-workspace-diff");
expect(packageNames).toContain("@paperclipai/plugin-llm-wiki");
expect(packageNames).toContain("@paperclipai/plugin-modal");
expect(packageNames).toContain("@paperclipai/plugin-authoring-smoke-example");
expect(packageNames).not.toContain("@paperclipai/plugin-sdk");
expect(byPackageName.get("@paperclipai/plugin-workspace-diff")?.experimental).toBe(true);
expect(byPackageName.get("@paperclipai/plugin-llm-wiki")?.experimental).toBe(true);
expect(byPackageName.get("@paperclipai/plugin-modal")?.experimental).toBe(true);
expect(byPackageName.get("@paperclipai/plugin-authoring-smoke-example")?.experimental).toBe(false);
}, 20_000);
it("rejects plugin installation for non-admin board users", async () => {
+14
View File
@@ -121,6 +121,7 @@ interface AvailableBundledPlugin {
description: string;
localPath: string;
tag: "example" | "first-party";
experimental: boolean;
}
/** Response body for GET /api/plugins/:pluginId/health */
@@ -150,6 +151,10 @@ const PLUGIN_SCOPED_API_RESPONSE_HEADER_ALLOWLIST = new Set([
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const REPO_ROOT = path.resolve(__dirname, "../../..");
const EXPERIMENTAL_BUNDLED_PLUGIN_PACKAGE_NAMES = new Set([
"@paperclipai/plugin-llm-wiki",
"@paperclipai/plugin-workspace-diff",
]);
function titleCasePluginName(packageName: string): string {
const localName = packageName.split("/").pop() ?? packageName;
@@ -244,6 +249,14 @@ function bundledPluginMetadata(
}
}
function isExperimentalBundledPlugin(packageRoot: string, packageName: string): boolean {
return (
EXPERIMENTAL_BUNDLED_PLUGIN_PACKAGE_NAMES.has(packageName)
|| packageRoot.includes(`${path.sep}sandbox-providers${path.sep}`)
|| packageName.includes("sandbox")
);
}
function listBundledPlugins(): AvailableBundledPlugin[] {
const pluginRoot = path.resolve(REPO_ROOT, "packages/plugins");
return findPackageJsonFiles(pluginRoot)
@@ -274,6 +287,7 @@ function listBundledPlugins(): AvailableBundledPlugin[] {
?? `Bundled Paperclip plugin from ${path.relative(REPO_ROOT, packageRoot)}.`,
localPath: packageRoot,
tag,
experimental: isExperimentalBundledPlugin(packageRoot, packageName),
},
];
})
+1
View File
@@ -139,6 +139,7 @@ export interface AvailableBundledPlugin {
description: string;
localPath: string;
tag: "example" | "first-party";
experimental: boolean;
}
export interface PluginLocalFolderProblem {
+13
View File
@@ -43,6 +43,17 @@ function getPluginErrorSummary(plugin: PluginRecord): string {
return firstNonEmptyLine(plugin.lastError) ?? "Plugin entered an error state without a stored error message.";
}
function ExperimentalBadge() {
return (
<Badge
variant="outline"
className="border-amber-500/30 bg-amber-500/10 text-amber-700 hover:bg-amber-500/10 dark:text-amber-200"
>
Experimental
</Badge>
);
}
/**
* PluginManager page component.
*
@@ -249,6 +260,7 @@ export function PluginManager() {
<Badge variant="outline">
{bundledPlugin.tag === "first-party" ? "First-party" : "Example"}
</Badge>
{bundledPlugin.experimental && <ExperimentalBadge />}
{installedPlugin ? (
<Badge
variant={installedPlugin.status === "ready" ? "default" : "secondary"}
@@ -342,6 +354,7 @@ export function PluginManager() {
: "Example"}
</Badge>
)}
{bundledByPackageName.get(plugin.packageName)?.experimental && <ExperimentalBadge />}
</div>
<div>
<p className="text-xs text-muted-foreground mt-0.5 truncate" title={plugin.packageName}>