From bd04665fce5aa2292d4f9c3a2b5f5bf71fc281df Mon Sep 17 00:00:00 2001 From: Brett Chien Date: Sat, 29 Aug 2026 17:02:08 +0800 Subject: [PATCH] chore(console): remove dead compose-library frontend code (studio#128) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit compose.ts (Library/BundlePreview types, libraryNames, renderPreviewHtml) had exactly one caller left in the console — the New Fleet wizard's old Template/Overlay Step 2, replaced entirely in the vendor+chat-platform+ACP rewrite. Nothing else in the console imports it anymore (confirmed: only its own test file did). Removing both. Scoped to the frontend only — studio_compose::compose_named/Bundle (Rust) and the deploy_provision/compose_library_get/compose_library_set/ compose_preview MCP tools are untouched: they're still the live path for provision_from_library/provision_from_library_k8s (the compose-library provisioning flow itself still exists and works, the wizard just doesn't route through it anymore), and removing a still-registered, still-working MCP tool is a bigger call than cleaning up now-dead console code — not made here. Verification: npm run typecheck clean, npm test 100/100 passing (106 - compose.test.ts's 6), npm run build succeeds, bundle size unchanged (already tree-shaken, this is a source-hygiene cleanup not a size win). Ref #128. --- console/src/compose.test.ts | 65 --------------------------- console/src/compose.ts | 87 ------------------------------------- 2 files changed, 152 deletions(-) delete mode 100644 console/src/compose.test.ts delete mode 100644 console/src/compose.ts diff --git a/console/src/compose.test.ts b/console/src/compose.test.ts deleted file mode 100644 index fde8570..0000000 --- a/console/src/compose.test.ts +++ /dev/null @@ -1,65 +0,0 @@ -import { describe, it, expect } from "vitest"; -import { renderPreviewHtml, libraryNames, type BundlePreview, type Library } from "./compose"; - -const PREVIEW: BundlePreview = { - image_tag: "ghcr.io/openabdev/openab:0.9.0-claude", - digest: "sha256:abc123", - files: [ - { path: ".claude/skills/memory/SKILL.md", text: "# memory\n", bytes: 9, binary: false }, - { path: "CLAUDE.md", text: "# persona\n", bytes: 10, binary: false }, - ], -}; - -describe("renderPreviewHtml", () => { - it("shows the image tag, digest and file count", () => { - const html = renderPreviewHtml(PREVIEW); - expect(html).toContain("ghcr.io/openabdev/openab:0.9.0-claude"); - expect(html).toContain("sha256:abc123"); - // file count - expect(html).toContain("files 2"); - }); - - it("lists each file path with its content", () => { - const html = renderPreviewHtml(PREVIEW); - expect(html).toContain(".claude/skills/memory/SKILL.md"); - expect(html).toContain("CLAUDE.md"); - expect(html).toContain("# persona\n"); - }); - - it("escapes HTML in paths and content (no injection)", () => { - const html = renderPreviewHtml({ - image_tag: "img", - digest: "sha256:x", - files: [{ path: ".md", text: "", bytes: 5, binary: false }], - }); - expect(html).not.toContain(""); - expect(html).toContain("<script>"); - expect(html).toContain("<evil>.md"); - }); - - it("does not dump content for a binary file", () => { - const html = renderPreviewHtml({ - image_tag: "img", - digest: "sha256:x", - files: [{ path: "blob", text: "�", bytes: 3, binary: true }], - }); - expect(html).toContain("binary"); - expect(html).toContain("not shown"); - }); -}); - -describe("libraryNames", () => { - it("returns sorted template and overlay names", () => { - const lib: Library = { - templates: { zeta: {} as never, alpha: {} as never }, - overlays: { orca: {} as never }, - skills: { skills: {} }, - }; - expect(libraryNames(lib)).toEqual({ templates: ["alpha", "zeta"], overlays: ["orca"] }); - }); - - it("tolerates missing maps", () => { - const lib = { skills: { skills: {} } } as unknown as Library; - expect(libraryNames(lib)).toEqual({ templates: [], overlays: [] }); - }); -}); diff --git a/console/src/compose.ts b/console/src/compose.ts deleted file mode 100644 index 8342e37..0000000 --- a/console/src/compose.ts +++ /dev/null @@ -1,87 +0,0 @@ -// Compose: the template/overlay/skills library types + the composed -// `{path → bytes}` bundle preview (agent-deployment ADR, slice 1). The -// standalone authoring tab this module used to wire (`initComposeTab`) is -// gone — `[+ New fleet]`/`[+ Add instance]` (`deploy.ts`) reach the same -// compose→preview→deploy engine as an action instead, reusing the pure -// helpers below. Everything real runs through the backend: the library is -// persisted by `compose_library_set`, and the preview is composed by -// `compose_preview` (the pure Rust `studio-compose` seam). -// -// These types mirror `studio_compose`'s serde shapes 1:1. - -export interface Template { - name: string; - image_tag: string; - files: Record; - skills: string[]; -} -export interface Overlay { - name: string; - image_tag?: string | null; - files: Record; - skills: string[]; -} -export interface Skill { - files: Record; -} -export interface SkillsLibrary { - skills: Record; -} -export interface Library { - templates: Record; - overlays: Record; - skills: SkillsLibrary; -} -export interface FilePreview { - path: string; - text: string; - bytes: number; - binary: boolean; -} -export interface BundlePreview { - image_tag: string; - digest: string; - files: FilePreview[]; -} - -function escapeHtml(s: string): string { - return s - .replace(/&/g, "&") - .replace(//g, ">") - .replace(/"/g, """); -} - -/** Render the composed-bundle preview to HTML — a pure view (unit-tested). */ -export function renderPreviewHtml(preview: BundlePreview): string { - const rows = preview.files - .map((f) => { - const meta = f.binary ? `${f.bytes} bytes · binary` : `${f.bytes} bytes`; - const body = f.binary - ? `
(binary — ${f.bytes} bytes, not shown)
` - : `
${escapeHtml(f.text)}
`; - return ( - `
` + - `${escapeHtml(f.path)}${escapeHtml(meta)}` + - body + - `
` - ); - }) - .join(""); - const count = preview.files.length; - return ( - `
` + - `
image ${escapeHtml(preview.image_tag)}
` + - `
digest ${escapeHtml(preview.digest)}
` + - `
files ${count}
` + - `
` + - `
${rows}
` - ); -} - -/** Names present in the parsed library, sorted — drives the picker `