diff --git a/docs/canvases-feature.html b/docs/canvases-feature.html index a90f7a94b..ca665a8fe 100644 --- a/docs/canvases-feature.html +++ b/docs/canvases-feature.html @@ -189,7 +189,7 @@ v0.1 — file-based + synthesized git diff 4 renderer types 13 codex review passes - no new plugin slot + v0.4: renderer plugins
@@ -435,24 +435,47 @@
TIER 3 -

Add a new CanvasType

- ~half a day · core PR required +

Ship a renderer plugin

+ ~half a day · v0.4 · no core PR
-

For data that genuinely doesn't fit the 4 existing renderers (flame graphs, Gantt charts, network topologies):

-
    -
  1. Extend the CanvasArtifact discriminated union in types.ts.
  2. -
  3. Extend the matching Zod schema in canvas-schema.ts.
  4. -
  5. Write a Canvas{NewType}.tsx renderer in packages/web/src/components/.
  6. -
  7. Add a case to the switch in CanvasRail.tsx.
  8. -
  9. Tests + docs paragraph.
  10. -
-

Gated behind a core PR because the renderer ships in the supervisor dashboard. Worth it once at least two real callers need the same shape.

+

For data that genuinely doesn't fit the 4 existing renderers (flame graphs, Gantt charts, network topologies), publish your own renderer as @aoagents/ao-plugin-canvas-{name} — the same package convention as every other AO plugin. The plugin declares its own canvasType id, payload schema (Zod), and React component.

+

At AO build time the plugin registry walks installed @aoagents/ao-plugin-canvas-* packages, generates a TypeScript file that imports each renderer plus extends the CanvasArtifact discriminated union, and the web build bundles them. The dashboard's CanvasRail switch dispatches to the plugin's renderer when it sees the new type.

+
@aoagents/ao-plugin-canvas-flamegraph/
+├── package.json          # name: @aoagents/ao-plugin-canvas-flamegraph
+├── src/
+│   ├── index.ts          # manifest + payload schema (Zod)
+│   └── renderer.tsx      # React component, default export
+
// src/index.ts
+import { z } from "zod";
+export const manifest = {
+  name: "flamegraph",
+  slot: "canvas-renderer" as const,
+  canvasType: "flamegraph",         // new CanvasType id
+  version: "0.1.0",
+};
+export const payloadSchema = z.object({
+  samples: z.array(z.object({
+    name: z.string(),
+    value: z.number(),
+  })).max(10_000),
+  unit: z.enum(["ms", "samples"]),
+});
+

No core PR needed. Trust boundary: npm install. Same trust check as adding any other AO plugin. No runtime code injection — plugins are bundled at build time, not loaded dynamically. v0.1 ships the 4 built-ins; v0.4 (queued) ships the plugin loader.

+
+ +
+
+ TIER 4 +

Promote a renderer plugin into core

+ rare · core PR · ecosystem consensus +
+

Once a renderer plugin has multiple production callers and the type is genuinely general (not specific to your stack), propose promoting it into core's built-in set via PR. The bar here is "this is now standard infrastructure", not "this is a new idea worth trying". Tier 3 is for trying ideas; Tier 4 is for blessing what already worked.

- The contract — expressive data, constrained UI. Anyone supplies any data in any supported type (no permission needed). New types come from PRs (UI in core needs review). No third party ships JS into the supervisor dashboard (never planned). Keeps install one-step, the renderer set consistent across every AO instance, and the supervisor sandbox-safe. + The contract — three rules across all four tiers. Anyone supplies any data, in any supported type (no permission needed). Anyone ships a new type via plugin (same npm install trust as any other AO plugin). Nobody dynamically loads JS at runtime (no remote code, no agent-emitted React). This keeps the trust boundary at install time where it belongs, the renderer set consistent within a given AO build, and the supervisor sandbox-safe.

6. Built with paranoia

@@ -549,19 +572,20 @@ EOF VersionAddsStatus v0.1File reader, GET endpoint, 4 renderers, synthesized git-diff, right-rail with auto-expand, 5s REST pollShipped - v0.2CanvasProducer.listCanvases invoked on agent / scm / tracker pluginsQueued + v0.2CanvasProducer.listCanvases invoked on agent / scm / tracker plugins (Tier 2 above)Queued v0.3Mux WebSocket topic for live updates, replacing 5s pollQueued + v0.4canvas-renderer plugin slot (Tier 3 above). Build-time bundling of @aoagents/ao-plugin-canvas-*, dynamic discriminated-union extension, type-id collision detectionQueued — the OSS extensibility unlock MobileBottom-sheet or full-screen takeover for canvases on small viewportsDeferred - Custom UISandboxed iframe escape hatch, build-time allowlisted renderer packagesOnly if justified + Sandboxed iframeRuntime-isolated escape hatch for genuinely-untrusted content (e.g. third-party HTML emitted by an agent we can't trust)Only if a real use case shows up

10. Deliberate non-goals