diff --git a/todos/01-plugin-inspect.md b/todos/01-plugin-inspect.md new file mode 100644 index 0000000..b4f052e --- /dev/null +++ b/todos/01-plugin-inspect.md @@ -0,0 +1,110 @@ +# Plugin 01 — RPC & State self-inspector + +**Package:** `@devframes/plugin-inspect` · **Dir:** `plugins/inspect/` +**Inspiration:** port of the RPC + shared-state inspector panels from +`vitejs/devtools`. +**SPA stack (Axis B):** Vue + Vite (direct port). +**Diagnostics band:** `DP_INSPECT_00xx`. + +## Why first + +This is the scaffolding plugin. It is the lowest-risk port, it self-validates the +core wire (RPC registry, shared-state, dump, connection meta, agent surface), and +once it exists it becomes the debugger we use while building every other plugin. +Building it establishes the package/tsdown/alias/turbo scaffolding the rest copy. + +## What it does + +A devframe that introspects *its own connection* (and, when mounted in a hub, the +hub's): list every registered RPC function with metadata (name, `type`, +`jsonSerializable`, `snapshot`, arg schema), let the user invoke `query` functions +with arguments and inspect results, watch every shared-state key live, and browse +the agent-exposed surface. Essentially the devframe equivalent of the vitejs +DevTools "RPC" and "State" tabs. + +## Dogfooding intent + +Primary surface: **RPC introspection + shared-state + RPC dump + `connectionMeta` ++ agent host**. This is the most self-referential plugin — it consumes the exact +APIs every other plugin produces, so it is the fastest way to discover whether: + +- the RPC registry exposes enough metadata to render a useful inspector (names, + types, valibot arg schemas, `jsonSerializable` flags from `ConnectionMeta`); +- shared-state subscription/broadcast semantics are observable from the client; +- the static `rpc/dump` output round-trips for the `build`/`spa` modes; +- the agent surface (`ctx.agent`, the `BUILTIN_AGENT_RPC`) is browsable. + +Expected gaps: missing introspection getters (may need a built-in +`devframe:list-functions` style meta RPC in core), dump fidelity for non-JSON values, +and how a devframe inspects a connection it is *also* part of. + +## Host integrations (Axis A) + +- `.` — `createInspectDevframe()` factory + default `DevframeDefinition`. +- `/cli` — `npx @devframes/plugin-inspect` opens the inspector against a target. +- `/vite` — mount into a Vite host to inspect that host's devframe connection. +- `/client` — Vue mount helpers + any dock `custom-render` modules. + +## Package layout + +``` +plugins/inspect/ + src/ + index.ts # `.` default DevframeDefinition + factory + node/index.ts # `/node` setup(ctx): register introspection RPCs + docks + client/index.ts # `/client` Vue app mount + custom-render dock + cli.ts # `/cli` + vite.ts # `/vite` + rpc/ + index.ts # serverFunctions tuple + DevframeRpcServerFunctions augment + functions/ + list-functions.ts # devframes-plugin-inspect:list-functions (query, snapshot) + invoke.ts # devframes-plugin-inspect:invoke (action) — gated to query fns + list-state-keys.ts # devframes-plugin-inspect:list-state-keys (query) + describe-agent.ts # devframes-plugin-inspect:describe-agent (query, snapshot) + spa/ # Vue + Vite UI + bin.mjs + test/ +``` + +## Node side + +- RPC (namespaced `devframes-plugin-inspect:*`): + - `devframes-plugin-inspect:list-functions` — `query`, `snapshot: true`, `jsonSerializable: true`: + returns the registry with metadata. May need a core hook to read the registry; + if absent, that is a tracked gap to add to `devframe` core. + - `devframes-plugin-inspect:invoke` — `action`: invoke a named `query` function with validated args; + refuse `action`/mutating functions for safety. + - `devframes-plugin-inspect:list-state-keys` — enumerate shared-state keys + current snapshots. + - `devframes-plugin-inspect:describe-agent` — surface `ctx.agent` tools/resources. +- Docks: a single `iframe` (or `custom-render`) dock `devframes-plugin-inspect:inspector` titled + "RPC & State", icon e.g. `ph:plugs-duotone`. +- Shared state observed (read-only): all keys; no new keys written except a small + `devframes-plugin-inspect:inspector:ui` for persisted panel UI prefs (serializable). + +## Client side + +- Vue SPA: three views — Functions (list + invoke), State (live key watcher with + diff), Agent (tools/resources tree). Connects via `connectDevframe()`; derives + base from `document.baseURI`; handles both `websocket` and `static` backends + (degrade invoke to read-only when `backend === 'static'`). + +## Milestones + +1. Scaffold package + tsdown three-config + alias/turbo/workspace wiring (this is + the template all others copy). +2. `devframes-plugin-inspect:list-functions` + Functions view (read-only). +3. `devframes-plugin-inspect:invoke` for `query` functions + result rendering. +4. State view with live subscription + diff. +5. Agent view; `static`/`spa` degradation; tsnapi snapshot + e2e. + +## Open questions / risks + +- Does core expose (or should it expose) a registry-introspection API? If not, + decide whether to add a built-in meta RPC to `devframe` core vs. keep it in the + plugin. **This is likely the first real framework change the effort forces.** +- How much of the `vitejs/devtools` Vue code ports cleanly vs. needs a rewrite + against devframe's client (`connectDevframe`, `rpc.sharedState`) rather than + Vite DevTools' kit client. +- Safety model for `devframes-plugin-inspect:invoke` (which function types are invokable; argument + validation surface). diff --git a/todos/02-plugin-terminals.md b/todos/02-plugin-terminals.md new file mode 100644 index 0000000..9fd6c2e --- /dev/null +++ b/todos/02-plugin-terminals.md @@ -0,0 +1,102 @@ +# Plugin 02 — Terminals + +**Package:** `@devframes/plugin-terminals` · **Dir:** `plugins/terminals/` +**Inspiration:** replace Vite DevTools' built-in terminal panel with a portable, +hub-native one. +**SPA stack (Axis B):** Vanilla TS + Vite (+ `@xterm/xterm`). +**Diagnostics band:** `DP_TERMINALS_00xx`. + +## What it does + +A terminal panel: list registered terminal sessions, stream their live output, +spawn new child-process terminals (configurable allowed commands), and +terminate/restart them. The host already provides most of this — the hub +`terminals` host (`packages/hub/src/node/host-terminals.ts`) exposes `register`, +`update`, and `startChildProcess` (via `tinyexec`) and mirrors output into the +`devframe:terminals` streaming channel with `devframe:terminals:updated` +broadcasts. This plugin is the **reference UI + a thin spawn/control RPC** on top +of that subsystem. + +## Dogfooding intent + +Primary surface: **hub `terminals` host + `startChildProcess` + RPC streaming + +replay**. This is the first heavy consumer of streaming, so it will stress: + +- the `devframe:terminals` streaming channel (backpressure, replay window for + late-joining clients, ordering across stdout/stderr); +- session lifecycle (`terminate()`/`restart()`/`getChildProcess()`) and the + `terminal:session:updated` events; +- whether the existing host API is enough to drive a full UI, or needs additions + (resize/PTY, input/write-to-stdin, exit codes, env/cwd per session). + +Expected gaps: interactive input (the current host streams output; a real +terminal needs stdin + PTY/resize), and replay semantics for reconnects. + +## Host integrations (Axis A) + +- `.` — `createTerminalsDevframe(options)` (allowed commands, default cwd) + + default definition. +- `/cli` — standalone terminal panel bound to the launching shell's cwd. +- `/vite` — mount into a Vite host (the literal "replace Vite DevTools terminal" + use case). +- `/client` — xterm mount + dock `custom-render` module. + +## Package layout + +``` +plugins/terminals/ + src/ + index.ts + node/index.ts # setup(ctx): wire terminals host, register control RPCs + dock + client/index.ts # xterm.js renderer, attaches to devframe:terminals stream + cli.ts + vite.ts + rpc/ + index.ts + functions/ + spawn.ts # devframes-plugin-terminals:spawn (action) → ctx.terminals.startChildProcess + terminate.ts # devframes-plugin-terminals:terminate (action) + restart.ts # devframes-plugin-terminals:restart (action) + write.ts # devframes-plugin-terminals:write (action) — stdin, IF host gains support + list.ts # devframes-plugin-terminals:list (query) + spa/ + bin.mjs + test/ +``` + +## Node side + +- Uses `ctx.terminals` directly; control RPCs are thin wrappers that call into the + host and return session descriptors. +- `devframes-plugin-terminals:spawn` validates the requested command against an allow-list passed + to `createTerminalsDevframe` (security: never spawn arbitrary commands from the + client without opt-in). Diagnostics `DP_TERMINALS_00xx` for disallowed command / unknown + session / spawn failure. +- Subscribes the UI to the `devframe:terminals` streaming channel and + `devframe:terminals:updated` broadcast. + +## Client side + +- Vanilla TS + xterm.js. One xterm instance per session, fed from the streaming + channel reader; tabs/list driven by `devframes-plugin-terminals:list` + the updated broadcast. + Toolbar: spawn (from allow-list), terminate, restart, clear. + +## Milestones + +1. Scaffold (copy from #1). Dock + `devframes-plugin-terminals:list` + render existing sessions' + buffered output. +2. Live streaming via `devframe:terminals` channel into xterm; reconnect/replay. +3. `devframes-plugin-terminals:spawn` / `terminate` / `restart` with allow-list. +4. (If host extended) stdin `devframes-plugin-terminals:write` + resize/PTY. +5. tsnapi snapshot + Playwright e2e (spawn → output → terminate). + +## Open questions / risks + +- **Interactive input / PTY.** The hub host today is output-streaming. A genuine + replacement for the Vite DevTools terminal needs stdin and resize. Decide: + extend `@devframes/hub` `terminals` host (preferred, benefits all consumers) vs. + plugin-local PTY. This is the main framework-change candidate from this plugin. +- Replay window sizing for the streaming channel on reconnect. +- Security model for `spawn` (allow-list shape, default-deny). +- Overlap with code-server (#7), which also runs long-lived processes — keep the + spawn/stream primitives reusable. diff --git a/todos/03-plugin-git-dashboard.md b/todos/03-plugin-git-dashboard.md new file mode 100644 index 0000000..6e55f7c --- /dev/null +++ b/todos/03-plugin-git-dashboard.md @@ -0,0 +1,102 @@ +# Plugin 03 — Git Dashboard + +**Package:** `@devframes/plugin-git` · **Dir:** `plugins/git/` +**Inspiration:** GitLens — repository insight surfaced inline. +**SPA stack (Axis B):** Vue + Vite (reuses inspector UI primitives), vanilla +fallback acceptable. +**Diagnostics band:** `DP_GIT_00xx`. + +## What it does + +A repository dashboard for the workspace: current branch + status (staged/ +unstaged/untracked), recent commit log with author/date/message, per-file blame, +branch list, and a diff viewer. Read-only first; optional write actions +(stage/commit/checkout) behind explicit opt-in. The first "real product" tool, so +it exercises data-heavy RPC end to end. + +## Dogfooding intent + +Primary surface: **RPC `query`/`snapshot` + shared-state + long-lived file +watching + `json-render` + commands/docks**. Stresses: + +- larger / structured RPC payloads (commit lists, diffs) and whether `snapshot: + true` + the dump path handle them for `build`/`spa` modes; +- a long-lived watcher (repo HEAD / index changes) pushing shared-state updates, + and the debounce behavior `createHubContext` applies in `dev` mode; +- `json-render` driven docks (`ctx.createJsonRenderer`) as an alternative to a + full custom SPA for some panels; +- command-palette entries (`devframes-plugin-git:checkout`, `devframes-plugin-git:fetch`) via `ctx.commands`. + +Expected gaps: efficient diffing of large repos over RPC, incremental updates vs. +full snapshots, and error diagnostics for non-repo / detached-HEAD states. + +## Host integrations (Axis A) + +- `.` — `createGitDevframe(options)` (repo root override, write-enabled flag). +- `/cli` — `npx @devframes/plugin-git` → standalone dashboard for cwd repo. +- `/vite`, `/nuxt` — mount into a host dev server (in-IDE-like sidebar). +- `/client` — Vue app + dock renderers. + +## Package layout + +``` +plugins/git/ + src/ + index.ts + node/index.ts + client/index.ts + cli.ts + vite.ts + nuxt.ts # optional + rpc/ + index.ts + functions/ + status.ts # devframes-plugin-git:status (query, snapshot) + log.ts # devframes-plugin-git:log (query) — paginated + diff.ts # devframes-plugin-git:diff (query) + blame.ts # devframes-plugin-git:blame (query) + branches.ts # devframes-plugin-git:branches (query) + stage.ts # devframes-plugin-git:stage (action, write-gated) + commit.ts # devframes-plugin-git:commit (action, write-gated) + checkout.ts # devframes-plugin-git:checkout (action, write-gated) + watcher.ts # HEAD/index watcher → shared-state push + spa/ + bin.mjs + test/ # use a temp git repo fixture +``` + +## Node side + +- Git access via `simple-git` (or `isomorphic-git` for zero-binary portability — + decide in milestone 0; add to the `deps` catalog). Run commands relative to + `ctx.workspaceRoot` / `ctx.cwd`. +- Watcher updates `devframes-plugin-git:state` shared state (branch, ahead/behind, dirty counts) on + `.git/HEAD` / index changes; debounced. +- Write RPCs only registered when `createGitDevframe({ write: true })`; otherwise + omitted from the registry entirely (not just hidden). Diagnostics `DP_GIT_00xx`: + not-a-repo, dirty-tree-conflict, write-disabled. + +## Client side + +- Vue SPA: Status, History (commit graph/log), Diff, Branches, Blame views. + Reuses table/tree/diff primitives; consider sharing with #1 if a UI kit emerges. + +## Milestones + +1. Scaffold. `devframes-plugin-git:status` + Status view (read-only). +2. `devframes-plugin-git:log` (paginated) + History; `devframes-plugin-git:diff` + Diff viewer. +3. Live `devframes-plugin-git:state` watcher → shared state. +4. `devframes-plugin-git:branches` + `devframes-plugin-git:blame`. +5. Opt-in write actions + command-palette entries. +6. tsnapi snapshot + e2e against a temp-repo fixture. + +## Open questions / risks + +- **`simple-git` (spawns `git`) vs `isomorphic-git` (pure JS).** Portability and + the standalone `npx` story favor `isomorphic-git`; fidelity/perf favor + `simple-git`. Decide in milestone 0. +- Diff/log payload size — paginate and/or stream; revisit whether `snapshot` + scales for large repos. +- Whether to lean on `json-render` docks for simple panels (cheaper, no SPA build) + vs. the full Vue SPA — good place to dogfood `createJsonRenderer`. +- Write actions are a footgun; default read-only, gate explicitly. diff --git a/todos/04-plugin-og-viewer.md b/todos/04-plugin-og-viewer.md new file mode 100644 index 0000000..3c05c25 --- /dev/null +++ b/todos/04-plugin-og-viewer.md @@ -0,0 +1,98 @@ +# Plugin 04 — OG viewer + +**Package:** `@devframes/plugin-og` · **Dir:** `plugins/og/` +**Inspiration:** Nuxt DevTools' Open Graph image viewer. +**SPA stack (Axis B):** Nuxt (static export) — the marquee proof that a Nuxt-built +SPA is a drop-in devframe client. +**Diagnostics band:** `DP_OG_00xx`. + +## What it does + +Preview and debug Open Graph / social-card metadata and images for routes: +render the resolved OG/Twitter meta tags for a given URL, show a live preview of +the social card across platforms (Twitter, Facebook, Discord, Slack), and — when +the project generates OG images (e.g. satori-based) — preview/iterate those +images with parameter tweaking. + +## Dogfooding intent + +Primary surface: **`views.hostStatic` static serving + the `build` adapter + +`spa.loader` modes + Nuxt SPA neutrality**. This plugin is the reason to ship a +Nuxt-built SPA, so it validates: + +- a Nuxt `output: 'export'`-style static build mounting cleanly with relative + base + runtime base discovery (`document.baseURI`), per the standalone-SPA + principle in `AGENTS.md`; +- `createBuild` producing a self-contained static deploy of an OG report + (`__connection.json` static backend + `__rpc-dump/` + `spa-loader.json`); +- the `spa.loader` modes (`'query'` to load a target URL from search params, + `'none'` for a baked report) — the OG viewer is a natural `query`-loader SPA; +- serving generated image bytes through `ctx.views` / RPC. + +Expected gaps: serving binary/image payloads over RPC vs. static routes, and Nuxt +base-path discovery when mounted under `/__og/`. + +## Host integrations (Axis A) + +- `.` — `createOgDevframe(options)` (routes/globs to scan, image generator hook). +- `/cli` — `npx @devframes/plugin-og` → scan a built site / dev server. +- `/nuxt` — first-class Nuxt module (the SPA is Nuxt; the host integration is too). +- `/vite` — generic Vite host mount. +- `/client` — Nuxt-built SPA assets + connect glue. + +## Package layout + +``` +plugins/og/ + src/ + index.ts + node/index.ts + cli.ts + vite.ts + nuxt.ts + client/index.ts + rpc/ + index.ts + functions/ + scan-routes.ts # devframes-plugin-og:scan-routes (query, snapshot) + resolve-meta.ts # devframes-plugin-og:resolve-meta (query) — fetch+parse a URL's head + render-image.ts # devframes-plugin-og:render-image (query) — bytes / data URL + spa/ # Nuxt app, output: 'export', assetPrefix relative + bin.mjs + test/ +``` + +## Node side + +- `devframes-plugin-og:resolve-meta` fetches a target URL (or reads built HTML) and parses + `og:*` / `twitter:*` meta into a structured snapshot. +- `devframes-plugin-og:render-image` optionally renders via `satori` + `resvg` (add to catalog) or + defers to a project-provided generator hook. +- Build mode: emit a static OG report so `createBuild` output can be deployed and + shared. Diagnostics `DP_OG_00xx`: unfetchable URL, parse failure, render failure. + +## Client side + +- Nuxt SPA: URL/route picker, resolved meta table, multi-platform card preview, + image preview with parameter controls. Must build with relative base and + discover its mount base at runtime. + +## Milestones + +1. Scaffold + Nuxt SPA build wired to `cli.distDir` (prove Nuxt static export + mounts and connects). +2. `devframes-plugin-og:resolve-meta` + meta table + card preview. +3. `devframes-plugin-og:scan-routes` to populate the route picker. +4. `devframes-plugin-og:render-image` (satori) or generator-hook path. +5. `build` adapter snapshot (deployable report) + `spa.loader: 'query'`. +6. tsnapi snapshot + e2e. + +## Open questions / risks + +- **Binary image transport.** RPC dump is JSON/structured-clone oriented; decide + data-URL-over-RPC vs. a static route via `ctx.views` for image bytes. +- Nuxt static export base discovery under `/__og/` — the key neutrality test. +- Scope of the built-in renderer (satori) vs. relying on the host project's own OG + generation. Lean on a hook; bundle satori as opt-in. +- Porting effort from Nuxt DevTools' implementation (Vue/Nuxt → standalone Nuxt + app talking to devframe RPC instead of Nuxt DevTools RPC). diff --git a/todos/05-plugin-a11y-check.md b/todos/05-plugin-a11y-check.md new file mode 100644 index 0000000..9e62286 --- /dev/null +++ b/todos/05-plugin-a11y-check.md @@ -0,0 +1,101 @@ +# Plugin 05 — A11y check + +**Package:** `@devframes/plugin-a11y` · **Dir:** `plugins/a11y/` +**Inspiration:** axe-core powered accessibility auditing, surfaced as a devtool. +**SPA stack (Axis B):** React via **rspack** — the proof that an rspack build +produces a valid static devframe SPA. +**Diagnostics band:** `DP_A11Y_00xx`. + +## What it does + +Run accessibility audits against the app under development and present results: +violations grouped by impact (critical/serious/moderate/minor), the offending +DOM nodes + selectors, the failing WCAG rule, and remediation guidance. Two scan +modes: (a) in-page — `axe-core` runs inside the host app's window and reports +back; (b) headless — a node-side run against a URL via Playwright (reuse the +repo's existing Playwright dep). + +## Dogfooding intent + +Primary surface: **hub `messages` feed + client commands + `when`-clauses + +client↔server round-trips + rspack SPA neutrality**. Stresses: + +- the `messages` host (`ctx.messages.add/update/remove`) as a diagnostics feed — + violations map naturally onto message entries with `level`, file/element + positions, and auto-dismiss; this is the first heavy `messages` consumer and + will exercise FIFO eviction + the `devframe:messages:updated` broadcast; +- **client-side** command registration (`CommandsContext.register` from + `@devframes/hub/client`) and a `clientScript` dock entry that runs `axe-core` + inside the host page, then ships results back over RPC; +- `when`-clauses to show/hide actions based on scan state; +- an rspack-built React SPA mounting + connecting like any other. + +Expected gaps: client→server result transport size, the `clientScript` execution +context capabilities, and message-feed UX at volume. + +## Host integrations (Axis A) + +- `.` — `createA11yDevframe(options)` (rules config, scan targets). +- `/cli` — headless scan of a URL, report to terminal + static report. +- `/vite` — in-page scan of the Vite app (primary interactive mode). +- `/client` — React SPA + the in-page `axe-core` `clientScript` module. + +## Package layout + +``` +plugins/a11y/ + src/ + index.ts + node/index.ts + cli.ts + vite.ts + client/ + index.ts # React SPA mount + in-page-scan.ts # clientScript: runs axe-core in host window + rpc/ + index.ts + functions/ + report.ts # devframes-plugin-a11y:report (action) — client posts results + scan-headless.ts # devframes-plugin-a11y:scan-headless (action) — node+Playwright run + list-results.ts # devframes-plugin-a11y:list-results (query, snapshot) + spa/ # React, built with rspack + bin.mjs + test/ +``` + +## Node side + +- `devframes-plugin-a11y:report` receives results from the in-page `clientScript`, stores them in + `devframes-plugin-a11y:results` shared state, and fans violations into `ctx.messages` (one entry + per violation, deduped by rule+target). Diagnostics `DP_A11Y_00xx`: scan failure, + Playwright unavailable, invalid rule config. +- `devframes-plugin-a11y:scan-headless` runs axe via Playwright against a URL (node-side), for the + CLI/CI path. + +## Client side + +- React SPA (rspack): results dashboard grouped by impact, node highlighter + (postMessage to host frame), rule detail + docs links. +- `in-page-scan.ts` is the browser module referenced by a `clientScript` dock + entry — bundled by the browser tsdown config so no node imports leak. + +## Milestones + +1. Scaffold + rspack SPA build wired to `cli.distDir` (prove rspack static SPA + mounts + connects). +2. In-page `clientScript` scan → `devframes-plugin-a11y:report` → `devframes-plugin-a11y:results` shared state + + results dashboard. +3. Violations → `ctx.messages` feed; node highlighting. +4. `devframes-plugin-a11y:scan-headless` (Playwright) + CLI/CI report. +5. `when`-clause-driven actions; tsnapi snapshot + e2e. + +## Open questions / risks + +- **rspack → static SPA** is unproven in this repo; budget time for the build + config (relative base, output shape matching `cli.distDir`). This is the core + neutrality test for this plugin. +- `clientScript` execution context: confirm it can load `axe-core` and reach the + host document; if sandboxed, fall back to a postMessage bridge. +- Message-feed volume — a big page yields many violations; dedupe + cap, lean on + the host's FIFO eviction. +- Playwright as a (heavy, optional) peer for the headless path. diff --git a/todos/06-plugin-mcp-inspect.md b/todos/06-plugin-mcp-inspect.md new file mode 100644 index 0000000..60941b1 --- /dev/null +++ b/todos/06-plugin-mcp-inspect.md @@ -0,0 +1,107 @@ +# Plugin 06 — MCP inspector + +**Package:** `@devframes/plugin-mcp-inspect` · **Dir:** `plugins/mcp-inspect/` +**Inspiration:** the MCP inspector; optional Vercel AI SDK / evals integration. +**SPA stack (Axis B):** Next (static export) — React + the Vercel ecosystem. +**Diagnostics band:** `DP_MCP_00xx`. + +## What it does + +Inspect and exercise Model Context Protocol servers: connect to an MCP server +(stdio or HTTP), list its tools / resources / prompts, invoke tools with +arguments and inspect responses, browse resource contents, and view the request/ +response log. Two complementary angles: + +1. **Inspect external MCP servers** — a general MCP client UI. +2. **Inspect devframe's own MCP surface** — devframe already ships an MCP adapter + (`createMcpServer`, `packages/devframe/src/adapters/mcp/`) that maps a + devframe's `ctx.agent` surface to MCP tools/resources. This plugin can point at + *that*, closing the loop and dogfooding the adapter. +3. **Evals (stretch)** — optional Vercel AI SDK integration to run eval prompts + against tools and score responses. + +## Dogfooding intent + +Primary surface: **`createMcpServer` + the agent host + Next SPA neutrality + +evals path**. Stresses: + +- the MCP adapter end to end: does `ctx.agent` → MCP tool/resource mapping expose + enough for a real inspector? (`buildMcpServerFromContext` is `@internal`-exported + for exactly this kind of testing.); +- `exposeSharedState` MCP resources; +- a Next `output: 'export'` static SPA mounting + connecting (the second React + framework proof, distinct from a11y's rspack path); +- the agent-native story the docs describe (`docs/guide/agent-native.md`). + +Expected gaps: MCP transports beyond `stdio` (the adapter currently throws +`DF0017` for non-stdio — an HTTP/SSE client is likely needed here and may push a +core addition), and agent-surface metadata richness. + +## Host integrations (Axis A) + +- `.` — `createMcpInspectorDevframe(options)` (target server config). +- `/cli` — `npx @devframes/plugin-mcp-inspect` → connect to an MCP server from the terminal. +- `/next` — first-class Next integration (the SPA is Next; host integration too). +- `/vite` — generic Vite host mount. +- `/client` — Next-built SPA + connect glue. + +## Package layout + +``` +plugins/mcp-inspect/ + src/ + index.ts + node/index.ts + cli.ts + next.ts + vite.ts + client/index.ts + rpc/ + index.ts + functions/ + connect.ts # devframes-plugin-mcp-inspect:connect (action) — open a client to a server + list-tools.ts # devframes-plugin-mcp-inspect:list-tools (query, snapshot) + invoke-tool.ts # devframes-plugin-mcp-inspect:invoke-tool (action) + list-resources.ts # devframes-plugin-mcp-inspect:list-resources (query) + read-resource.ts # devframes-plugin-mcp-inspect:read-resource (query) + run-eval.ts # devframes-plugin-mcp-inspect:run-eval (action) — stretch, Vercel AI SDK + spa/ # Next, output: 'export', assetPrefix relative + bin.mjs + test/ +``` + +## Node side + +- MCP client via `@modelcontextprotocol/sdk` (already a catalog dep; optional peer + in core). Manage connections in `devframes-plugin-mcp-inspect:connections` shared state. +- Optional: expose devframe's *own* MCP server via `createMcpServer` and let the + inspector connect to it (self-inspection loop). +- Diagnostics `DP_MCP_00xx`: connect failure, unsupported transport, tool-invoke error, + eval-provider missing. + +## Client side + +- Next SPA: server connection manager, Tools / Resources / Prompts browser, tool + invoke form (schema-driven), response viewer, request log. Evals tab (stretch). + +## Milestones + +1. Scaffold + Next static-export SPA wired to `cli.distDir` (prove Next SPA mounts + + connects). +2. `devframes-plugin-mcp-inspect:connect` (stdio) + `devframes-plugin-mcp-inspect:list-tools` + Tools browser. +3. `devframes-plugin-mcp-inspect:invoke-tool` (schema-driven form) + response viewer. +4. Resources/prompts browse + read. +5. Point at devframe's own `createMcpServer` (self-inspection); request log. +6. (Stretch) Vercel AI SDK evals tab. +7. tsnapi snapshot + e2e. + +## Open questions / risks + +- **Transports.** The core MCP *server* adapter is stdio-only today (`DF0017`). + A *client* inspector likely needs HTTP/SSE + stdio. Decide whether transport + support lands in the plugin or pushes a core/adapter addition. +- Evals scope — keep behind a flag and an optional Vercel AI SDK peer; don't block + the core inspector on it. +- Next `output: 'export'` base discovery under `/__mcp/` (neutrality test). +- Security: connecting to / spawning arbitrary MCP servers — gate stdio spawn + behind explicit config, mirror the terminals allow-list approach. diff --git a/todos/07-plugin-code-server.md b/todos/07-plugin-code-server.md new file mode 100644 index 0000000..b4a91ed --- /dev/null +++ b/todos/07-plugin-code-server.md @@ -0,0 +1,108 @@ +# Plugin 07 — Code-server + +**Package:** `@devframes/plugin-code-server` · **Dir:** `plugins/code-server/` +**Inspiration:** embed [code-server](https://github.com/coder/code-server) (VS +Code in the browser) as a devframe panel. +**SPA stack (Axis B):** Vanilla TS + Vite (thin shell around an `