Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 16 additions & 13 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@

## Positioning

Two layers, one mental model:
Three layers, one mental model:

- **`devframe`** — *the container for one devtool integration, portable across viewers.* External project; lives at [`github.com/devframes/devframe`](https://github.com/devframes/devframe), docs at [`devfra.me`](https://devfra.me). Consumed here as an npm dependency (`catalog:deps`).
- **`@vitejs/devtools-kit`** — *the hub that unites many devtools integrations.* Owns docking, the command palette, toasts, terminal sessions — anything that only makes sense when more than one tool shares a UI. Provides `createPluginFromDevframe(devframeApp)` so a portable devframe definition drops into Vite DevTools as a Vite plugin, with the dock entry auto-derived from the definition's metadata.
- **`@devframes/hub`** — *the framework-neutral hub layer on top of devframe.* Owns docks, terminals, messages, commands, the `mountDevframe` primitive, and the json-render factory — anything that only matters once a host wants to combine multiple devframes into one UI. External project, same repo as devframe; consumed via npm.
- **`@vitejs/devtools-kit`** — *the Vite-flavored skin over `@devframes/hub`.* Re-exports hub's hosts and primitives under the kit's `DevTools*` names, adds the Vite-specific extensions (`ViteDevToolsNodeContext`, `PluginWithDevTools`, `DevToolsPluginOptions`, `createViteDevToolsHost`, the `~viteplus` dock category), pins the kit-side mount path at `/__devtools/`, and ships `createPluginFromDevframe` to drop a portable devframe into Vite DevTools as a Vite plugin.

When deciding where something belongs: if a single-app standalone CLI would still need it, it belongs upstream in devframe; if it only matters once you have multiple integrations or a host UI, it lives in the kit.
When deciding where something belongs: if a single-app standalone CLI would still need it, it belongs upstream in devframe; if it only matters once a host combines multiple integrations, it belongs in `@devframes/hub` (or in `@vitejs/devtools-kit` if it's Vite-specific).

## Stack & Structure

Expand All @@ -17,7 +18,7 @@ Monorepo (`pnpm` workspaces + `turbo`). ESM TypeScript; bundled with `tsdown`. P

| Package | npm | Description |
|---------|-----|-------------|
| `packages/kit` | `@vitejs/devtools-kit` | The hub. `createKitContext` wraps devframe's context with `docks` / `terminals` / `messages` / `commands` host subsystems plus the Vite-augmented context type. `createPluginFromDevframe` bridges a portable devframe app into a `Plugin.devtools.setup` Vite plugin, auto-deriving its iframe dock entry from the definition. |
| `packages/kit` | `@vitejs/devtools-kit` | Vite-flavored skin over `@devframes/hub`. `createKitContext` wraps hub's `createHubContext` and surfaces the Vite-augmented context type (`viteConfig`/`viteServer`); hub hosts (`docks` / `terminals` / `messages` / `commands`) and the `mountDevframe` primitive are re-exported under the kit's `DevTools*` aliases. `createPluginFromDevframe` delegates to `mountDevframe` and wraps it in a `Plugin.devtools.setup` Vite plugin shell. |
| `packages/core` | `@vitejs/devtools` | Vite plugin + CLI + standalone/webcomponents client for Vite DevTools itself. Calls kit's `createKitContext`, scans Vite plugins for `.devtools.setup`, and serves the dock UI. |
| `packages/ui` | `@vitejs/devtools-ui` | Shared UI components, composables, and UnoCSS preset (`presetDevToolsUI`). Private, not published. |
| `packages/rolldown` | `@vitejs/devtools-rolldown` | Nuxt UI for Rolldown build data. Hub-mounted via `Plugin.devtools.setup`. Serves at `/__devtools-rolldown/`. |
Expand All @@ -31,7 +32,8 @@ Other top-level directories:

```mermaid
flowchart TD
kit --> devframe
hub --> devframe
kit --> hub
core --> kit
core --> rolldown & vite & self-inspect
rolldown --> kit & ui
Expand All @@ -42,15 +44,16 @@ flowchart TD

## Dep Boundary

`devframe` is an external package consumed via `catalog:deps` — contribute upstream at [github.com/devframes/devframe](https://github.com/devframes/devframe). `packages/kit` and above build on top of it. Features that require multi-integration awareness (docks, terminals, messages, commands) belong in kit.
`devframe` and `@devframes/hub` are external packages consumed via `catalog:deps` — contribute upstream at [github.com/devframes/devframe](https://github.com/devframes/devframe). `packages/kit` and above build on top of them. Features that require multi-integration awareness (docks, terminals, messages, commands) belong upstream in `@devframes/hub`. Features that only matter to Vite — `ViteDevToolsNodeContext`, `PluginWithDevTools`, the `~viteplus` category, the kit-pinned `/__devtools/` mount path, the `vite:open-in-editor`/`vite:open-in-finder` commands — stay in `@vitejs/devtools-kit` and `@vitejs/devtools`.

`devframe/node/internal` is a marked-internal subpath exposing a small set of helpers (`getInternalContext`, `resolveBasePath`) for first-party adapters reaching into devframe's private machinery — kit's `DocksHost` uses it for remote-dock token allocation. End users should not import it.
`devframe/node/hub-internals` is a marked-public-but-low-level subpath exposing a small set of helpers (`getInternalContext`, `resolveBasePath`) for first-party adapters reaching into devframe's hub-side machinery — kit's adapters use `getInternalContext` for remote-dock token allocation and WS-endpoint metadata. End users should not import it.

## Architecture

- **Devframe context** (external — see [devfra.me](https://devfra.me)): `createHostContext` returns a `DevToolsNodeContext` carrying `rpc`, `views` (HTTP file-serving via `hostStatic`), `diagnostics`, `agent`, plus `cwd`/`workspaceRoot`/`mode`/`host`. No docks, no terminals, no json-render.
- **Kit context** (`packages/kit/src/node/context.ts`): `createKitContext` wraps `createHostContext` and attaches the four hub hosts — `docks`, `terminals`, `messages`, `commands` — plus the `createJsonRenderer` factory. Optionally surfaces `viteConfig`/`viteServer` when mounted inside Vite DevTools. Wires the `'devframe:docks'` / `'devframe:commands'` shared-state sync.
- **Bridge** (`packages/kit/src/node/create-plugin-from-devframe.ts`): `createPluginFromDevframe(d, opts?)` returns `PluginWithDevTools`; in its `setup`, mounts the SPA via `views.hostStatic`, auto-registers an iframe dock entry from `id`/`name`/`icon`/`basePath`, runs `d.setup(ctx)` for the devframe-level wiring, then runs `opts.setup?.(ctx)` for kit-only extensions.
- **Devframe context** (external — see [devfra.me](https://devfra.me)): `createHostContext` returns a `DevframeNodeContext` carrying `rpc`, `views` (HTTP file-serving via `hostStatic`), `diagnostics`, `agent`, plus `cwd`/`workspaceRoot`/`mode`/`host`. No docks, no terminals, no json-render.
- **Hub context** (external `@devframes/hub/node`): `createHubContext` wraps `createHostContext` and attaches the four hub hosts — `docks`, `terminals`, `messages`, `commands` — plus the `createJsonRenderer` factory. Wires the `'devframe:docks'` / `'devframe:commands'` shared-state sync and seeds the built-in `~terminals` / `~messages` / `~settings` docks. Also ships `mountDevframe(ctx, def)` — the framework-neutral primitive that registers any `DevframeDefinition` as a dock.
- **Kit context** (`packages/kit/src/node/context.ts`): `createKitContext` wraps `createHubContext` and surfaces Vite-specific `viteConfig`/`viteServer` slots when mounted inside Vite DevTools. `KitNodeContext` extends `DevframeHubContext` so all the hub hosts come along for free.
- **Bridge** (`packages/kit/src/node/create-plugin-from-devframe.ts`): `createPluginFromDevframe(d, opts?)` returns `PluginWithDevTools`; in its `setup`, delegates to `mountDevframe(ctx, d, opts)` to mount the SPA, register the auto-derived iframe dock entry, and run `d.setup(ctx)`, then runs `opts.setup?.(ctx)` for kit-only extensions.
- **Vite DevTools entry** (`packages/core/src/node/context.ts`): `createDevToolsContext` calls `createKitContext`, registers Vite-specific commands (`vite:open-in-editor`, `vite:open-in-finder`), then scans Vite plugins for `.devtools.setup` hooks (which now receive the kit-augmented context).
- **Client context**: webcomponents/Nuxt UI state (`packages/core/src/client/webcomponents/state/*`) — dock entries, panels, RPC client. Two modes: `embedded` (overlay in host app) and `standalone` (independent page).
- **WS server** (`packages/core/src/node/ws.ts`): RPC via `devframe/rpc/transports/ws-server`. Auth skipped in build mode or when `devtools.clientAuth` is `false`.
Expand Down Expand Up @@ -97,13 +100,13 @@ All node-side warnings and errors use structured diagnostics via [`nostics`](htt

| Prefix | Package(s) | Diagnostics file |
|--------|-----------|-----------------|
| `DTK` | `packages/kit` + `packages/core` (shared codespace, hub-side) | `packages/kit/src/node/diagnostics.ts`, `packages/core/src/node/diagnostics.ts` |
| `DTK` | `packages/kit` + `packages/core` (shared codespace, Vite-side) | `packages/kit/src/node/diagnostics.ts`, `packages/core/src/node/diagnostics.ts` |
| `RDDT` | `packages/rolldown` | `packages/rolldown/src/node/diagnostics.ts` |
| `VDT` | `packages/vite` (reserved) | — |

`DF` codes belong to the upstream devframe project — file new ones there.
`DF` codes belong to the upstream devframe/hub projects — file new ones there. The `DF8xxx` sub-range covers `@devframes/hub` (DF8100–DF8199 docks, DF8200–DF8299 terminals, DF8300–DF8399 messages, DF8400–DF8499 commands).

`DTK` is shared between core and kit because they're sibling layers of the Vite DevTools hub. Coordinate code numbers across both files: kit currently reserves `DTK0050+`; core's existing codes top out below that.
`DTK` is shared between core and kit because they're sibling layers of Vite DevTools. Coordinate code numbers across both files: kit reserves `DTK0050+` for Vite-specific kit codes; core's existing codes top out below that. The hub-domain DTK codes (DTK0050–DTK0057) retired when their conditions moved upstream to `DF8100`–`DF8403`.

Codes are sequential 4-digit numbers per prefix (e.g. `DTK0033`, `RDDT0003`). Check the existing diagnostics file to find the next available number.

Expand Down
34 changes: 34 additions & 0 deletions MIGRATION.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,39 @@
# Migration Guide

## 0.2 → 0.3 (devframe 0.5.x + `@devframes/hub`)

`@vitejs/devtools-kit` now thins onto [`@devframes/hub`](https://www.npmjs.com/package/@devframes/hub) for the hub primitives (docks, terminals, messages, commands, `mountDevframe`, json-render factory). The kit's public `DevTools*` surface stays in place via re-export aliases — most plugin authors don't need to change anything.

### What changes for plugin authors

- **Nothing at the import level.** `DevToolsRpcClient`, `DevToolsDockEntry`, `DevToolsNodeContext`, `PluginWithDevTools`, `defineRpcFunction`, `getDevToolsRpcClient`, `connectRemoteDevTools`, the `DEVTOOLS_MOUNT_PATH` constant — all keep their `@vitejs/devtools-kit` import paths and identifier names.
- **One-time re-auth.** The anonymous-auth RPC scope moved from `vite:anonymous:` to `devframe:anonymous:` and the WebSocket auth-token query parameter from `vite_devtools_auth_token` to `devframe_auth_token` (both following devframe's internal rename). Auth tokens stored by older clients become invalid — users re-authorize once on first connect after upgrading.
- **`DTK0050`–`DTK0057` retire.** These dock/terminal/command diagnostic codes now ship from `@devframes/hub` as `DF8100`–`DF8403`. Error messages and docs URLs change accordingly; the conditions that trigger them are unchanged.

### What stays the same

- The Vite DevTools SPA continues to serve at **`/__devtools/`**. The kit pins this mount path independently of devframe's new `/__devframe/` default.
- `~viteplus` remains a valid dock category.
- `vite:open-in-editor` and `vite:open-in-finder` server commands keep their existing IDs.

### If you import from `devframe` directly

The `devframe/node/internal` subpath was renamed to `devframe/node/hub-internals` in devframe v0.5.x. Update direct imports:

```diff
- import { getInternalContext } from 'devframe/node/internal'
+ import { getInternalContext } from 'devframe/node/hub-internals'
```

And the type rename:

```diff
- import type { DevToolsInternalContext } from 'devframe/node/internal'
+ import type { DevframeInternalContext } from 'devframe/node/hub-internals'
```

Inside the kit's own re-export (`@vitejs/devtools/internal`), the alias `DevToolsInternalContext` remains.

## 0.1 → 0.2

### `@vitejs/devtools-kit`
Expand Down
8 changes: 4 additions & 4 deletions docs/errors/DTK0013.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ outline: deep
## Cause

This error is thrown by the RPC resolver in `createWsServer()` when an untrusted WebSocket client attempts to call a non-anonymous RPC method. Methods whose names start with `vite:anonymous:` are exempt from authentication and can be called by any client; all other methods require the client to be trusted.
This error is thrown by the RPC resolver in `createWsServer()` when an untrusted WebSocket client attempts to call a non-anonymous RPC method. Methods whose names start with `devframe:anonymous:` are exempt from authentication and can be called by any client; all other methods require the client to be trusted.

A client becomes trusted through one of these mechanisms:

1. **Client auth is disabled** (build mode, `clientAuth: false`, or `VITE_DEVTOOLS_DISABLE_CLIENT_AUTH=true`) -- all clients are auto-trusted.
2. **Auth token in storage** -- the client provides a `vite_devtools_auth_token` query parameter that matches a token stored in `node_modules/.vite/devtools/auth.json`.
2. **Auth token in storage** -- the client provides a `devframe_auth_token` query parameter that matches a token stored in `node_modules/.vite/devtools/auth.json`.
3. **Static auth tokens** -- the token matches one of the tokens listed in `devtools.config.clientAuthTokens`.

If none of these conditions are met, the client is untrusted and any call to a non-anonymous method triggers this error.
Expand All @@ -41,7 +41,7 @@ Provide a valid authentication token when connecting:
```ts
// Client-side: connecting with a valid auth token
const ws = new WebSocket(
'ws://localhost:7812?vite_devtools_auth_token=your-token-here'
'ws://localhost:7812?devframe_auth_token=your-token-here'
)
```

Expand All @@ -67,4 +67,4 @@ If you are developing locally and want to skip authentication entirely, see [DTK

## Source

- [`packages/core/src/node/ws.ts`](https://github.com/vitejs/devtools/blob/main/packages/core/src/node/ws.ts) — the WebSocket RPC resolver in `createWsServer()` throws `DTK0013` when an untrusted client invokes a method whose name is not prefixed with `vite:anonymous:`.
- [`packages/core/src/node/ws.ts`](https://github.com/vitejs/devtools/blob/main/packages/core/src/node/ws.ts) — the WebSocket RPC resolver in `createWsServer()` throws `DTK0013` when an untrusted client invokes a method whose name is not prefixed with `devframe:anonymous:`.
29 changes: 0 additions & 29 deletions docs/errors/DTK0050.md

This file was deleted.

27 changes: 0 additions & 27 deletions docs/errors/DTK0051.md

This file was deleted.

26 changes: 0 additions & 26 deletions docs/errors/DTK0052.md

This file was deleted.

21 changes: 0 additions & 21 deletions docs/errors/DTK0053.md

This file was deleted.

21 changes: 0 additions & 21 deletions docs/errors/DTK0054.md

This file was deleted.

26 changes: 0 additions & 26 deletions docs/errors/DTK0055.md

This file was deleted.

Loading
Loading