Skip to content

Commit 665a3c9

Browse files
committed
Merge remote-tracking branch 'origin/main' into antfu/decouple-docks-terminals
# Conflicts: # AGENTS.md # devframe/docs/.vitepress/sidebar.ts # devframe/docs/guide/devtool-definition.md # devframe/docs/guide/dock-system.md # devframe/docs/guide/index.md # devframe/skills/devframe/SKILL.md # docs/.vitepress/config.ts
2 parents 5066a7e + ac27c6d commit 665a3c9

52 files changed

Lines changed: 182 additions & 178 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ packages/kit/skills
1818
devframe/packages/devframe/skills
1919
.rolldown
2020
*.tsbuildinfo
21-
docs/.vitepress/cache
21+
**/.vitepress/cache
2222
.turbo
2323
.context
2424

AGENTS.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@ Monorepo (`pnpm` workspaces + `turbo`). ESM TypeScript; bundled with `tsdown`. P
2121
| `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. |
2222
| `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. |
2323
| `packages/ui` | `@vitejs/devtools-ui` | Shared UI components, composables, and UnoCSS preset (`presetDevToolsUI`). Private, not published. |
24-
| `packages/rolldown` | `@vitejs/devtools-rolldown` | Nuxt UI for Rolldown build data. Hub-mounted via `Plugin.devtools.setup`. Serves at `/.devtools-rolldown/`. |
25-
| `packages/vite` | `@vitejs/devtools-vite` | Nuxt UI for Vite DevTools (WIP). Hub-mounted via `Plugin.devtools.setup`. Serves at `/.devtools-vite/`. |
26-
| `packages/self-inspect` | `@vitejs/devtools-self-inspect` | Meta-introspection — DevTools for the DevTools. Hub-mounted via `Plugin.devtools.setup`. Serves at `/.devtools-self-inspect/`. |
24+
| `packages/rolldown` | `@vitejs/devtools-rolldown` | Nuxt UI for Rolldown build data. Hub-mounted via `Plugin.devtools.setup`. Serves at `/__devtools-rolldown/`. |
25+
| `packages/vite` | `@vitejs/devtools-vite` | Nuxt UI for Vite DevTools (WIP). Hub-mounted via `Plugin.devtools.setup`. Serves at `/__devtools-vite/`. |
26+
| `packages/self-inspect` | `@vitejs/devtools-self-inspect` | Meta-introspection — DevTools for the DevTools. Hub-mounted via `Plugin.devtools.setup`. Serves at `/__devtools-self-inspect/`. |
2727
| `packages/webext` || Browser extension scaffolding (ancillary). |
2828

2929
Other top-level directories:
@@ -76,7 +76,7 @@ pnpm -C docs run docs # docs dev server
7676
- Use workspace aliases from `alias.ts`.
7777
- RPC functions must use `defineRpcFunction` from kit; always namespace IDs (`my-plugin:fn-name`).
7878
- Shared state via `devframe/utils/shared-state`; keep values serializable.
79-
- Nuxt UI base paths: `/.devtools-rolldown/`, `/.devtools-vite/`, `/.devtools-self-inspect/`.
79+
- Nuxt UI base paths: `/__devtools-rolldown/`, `/__devtools-vite/`, `/__devtools-self-inspect/`.
8080
- Shared UI components/preset in `packages/ui`; use `presetDevToolsUI` from `@vitejs/devtools-ui/unocss`.
8181
- Currently focused on Rolldown build-mode analysis; dev-mode support is deferred.
8282

@@ -87,7 +87,7 @@ These apply to everything inside `devframe/packages/devframe` and reinforce its
8787
- **Single-integration scope.** Devframe describes one tool. If a feature only makes sense when multiple tools share a UI — docking, a unified command palette, cross-tool toasts, terminal aggregation — it lives in `@vitejs/devtools-kit`, not here.
8888
- **Headless by default.** No default startup banners, no opinionated logging to stdout, no default styling. Provide hooks (`onReady`, `cli.configure`, etc.); let the application print its own branding. Structured diagnostics via `logs-sdk` are fine — ad-hoc `console.log`s baked into adapters are not.
8989
- **File watching is the app's job, not devframe's.** Don't add a generic watcher primitive. Authors wire chokidar / fs.watch / watchman themselves and signal change via `ctx.rpc.sharedState.set(...)` or event-type RPCs. devframe stays out of the filesystem-observation business.
90-
- **Mount path depends on adapter context.** Given `id: 'foo'`, the default mount path is `/.foo/` for *hosted* adapters (`vite`, `embedded`, kit's `createPluginFromDevframe`) and `/` for *standalone* adapters (`cli`, `spa`, `build`). Authors override via `DevtoolDefinition.basePath`. Don't hardcode `DEVTOOLS_MOUNT_PATH` in adapter code paths that may run standalone.
90+
- **Mount path depends on adapter context.** Given `id: 'foo'`, the default mount path is `/__foo/` for *hosted* adapters (`vite`, `embedded`, kit's `createPluginFromDevframe`) and `/` for *standalone* adapters (`cli`, `spa`, `build`). Authors override via `DevtoolDefinition.basePath`. Don't hardcode `DEVTOOLS_MOUNT_PATH` in adapter code paths that may run standalone.
9191
- **SPAs own their basePath at runtime.** Build SPAs with relative asset paths (`vite.base: './'`); discover the effective base in the browser from the executing script's location / `document.baseURI`. `createBuild` / `createSpa` copy SPA output verbatim — no HTML rewriting, no build-time `--base` injection. The client (`connectDevtool`) resolves `.connection.json` relative to the runtime base automatically.
9292
- **CLI flags compose from both sides.** The `cac` instance backing `createCli` is exposed both to the `DevtoolDefinition` (`cli.configure(cli)`) — for capabilities contributed by the tool itself — and to the `createCli` caller — for flags added at the final assembly stage. Parsed flag values are forwarded to `setup(ctx, { flags })`. Never hardcode domain-specific flags into `createCli`.
9393

devframe/docs/.vitepress/config.ts

Lines changed: 55 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,66 @@
1+
import type { DefaultTheme } from 'vitepress'
2+
import { fileURLToPath } from 'node:url'
3+
import { globSync } from 'tinyglobby'
14
import { defineConfig } from 'vitepress'
25
import { withMermaid } from 'vitepress-plugin-mermaid'
3-
import devframeSidebar from './sidebar'
6+
7+
const errorsDir = fileURLToPath(new URL('../errors/', import.meta.url))
8+
9+
function listErrorCodes(prefix: string): string[] {
10+
return globSync(`${prefix}*.md`, { cwd: errorsDir })
11+
.map(f => f.replace(/\.md$/, ''))
12+
.sort()
13+
}
14+
15+
function guideItems(prefix: string): DefaultTheme.NavItemWithLink[] {
16+
return [
17+
{ text: 'Introduction', link: `${prefix}/guide/` },
18+
{ text: 'Devtool Definition', link: `${prefix}/guide/devtool-definition` },
19+
{ text: 'Adapters', link: `${prefix}/guide/adapters` },
20+
{ text: 'RPC', link: `${prefix}/guide/rpc` },
21+
{ text: 'Shared State', link: `${prefix}/guide/shared-state` },
22+
{ text: 'Streaming', link: `${prefix}/guide/streaming` },
23+
{ text: 'When Clauses', link: `${prefix}/guide/when-clauses` },
24+
{ text: 'Structured Diagnostics', link: `${prefix}/guide/diagnostics` },
25+
{ text: 'Client', link: `${prefix}/guide/client` },
26+
{ text: 'Standalone CLI', link: `${prefix}/guide/standalone-cli` },
27+
{ text: 'Nuxt Helper', link: `${prefix}/guide/nuxt` },
28+
{ text: 'Agent-Native (experimental)', link: `${prefix}/guide/agent-native` },
29+
]
30+
}
31+
32+
export function devframeSidebar(prefix = ''): DefaultTheme.SidebarItem[] {
33+
return [
34+
{
35+
text: 'Guide',
36+
items: guideItems(prefix),
37+
},
38+
{
39+
text: 'Error Reference',
40+
link: `${prefix}/errors/`,
41+
collapsed: true,
42+
items: listErrorCodes('DF').map(code => ({
43+
text: code,
44+
link: `${prefix}/errors/${code}`,
45+
})),
46+
},
47+
]
48+
}
49+
50+
export function devframeNav(prefix = ''): DefaultTheme.NavItemWithLink[] {
51+
return [
52+
...guideItems(prefix),
53+
{ text: 'Error Reference', link: `${prefix}/errors/` },
54+
]
55+
}
456

557
export default withMermaid(defineConfig({
658
title: 'DevFrame',
759
description: 'Framework-neutral foundation for building generic DevTools — RPC layer, hosts, and adapters.',
860
themeConfig: {
961
nav: [
10-
{ text: 'Guide', link: '/guide/' },
11-
{ text: 'Errors', link: '/errors/' },
62+
{ text: 'Guide', items: guideItems('') },
63+
{ text: 'Error Reference', link: '/errors/' },
1264
],
1365
sidebar: devframeSidebar(),
1466
search: {

devframe/docs/.vitepress/sidebar.ts

Lines changed: 0 additions & 56 deletions
This file was deleted.

devframe/docs/guide/adapters.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ my-devtool build --out-dir dist-static --base /devtools/
4848
my-devtool mcp # stdio MCP server (experimental)
4949
```
5050

51-
> Standalone CLI serves the SPA at `/` by default — no `/.devtools/` prefix. That prefix is reserved for *hosted* adapters where devframe mounts alongside an existing app. See [Mount paths](#mount-paths) below.
51+
> Standalone CLI serves the SPA at `/` by default — no `/__devtools/` prefix. That prefix is reserved for *hosted* adapters where devframe mounts alongside an existing app. See [Mount paths](#mount-paths) below.
5252
5353
### Options
5454

@@ -180,7 +180,7 @@ The basePath where a devtool's SPA is mounted depends on the adapter it's runnin
180180
| Adapter kind | Default basePath | Reason |
181181
|--------------|------------------|--------|
182182
| `cli`, `spa`, `build` (standalone) | `/` | The devtool is the only thing on the origin. |
183-
| `vite`, `kit`, `embedded` (hosted) | `/.<id>/` | The devtool shares the origin with a host app and must namespace itself. |
183+
| `vite`, `kit`, `embedded` (hosted) | `/__<id>/` | The devtool shares the origin with a host app and must namespace itself. |
184184

185185
Override either side explicitly with `DevtoolDefinition.basePath`:
186186

@@ -196,7 +196,7 @@ SPA authors should **build with relative asset paths** (`vite.base: './'`) rathe
196196

197197
## Vite
198198

199-
A thin Vite plugin that mounts a devtool's SPA into an existing Vite dev server as a *hosted* adapter — the mount path defaults to `/.<id>/` to avoid colliding with the app. It **does not** start an RPC WebSocket server — use `kit` or `cli` when you need RPC.
199+
A thin Vite plugin that mounts a devtool's SPA into an existing Vite dev server as a *hosted* adapter — the mount path defaults to `/__<id>/` to avoid colliding with the app. It **does not** start an RPC WebSocket server — use `kit` or `cli` when you need RPC.
200200

201201
```ts
202202
import { createVitePlugin } from 'devframe/adapters/vite'
@@ -210,7 +210,7 @@ export default defineConfig({
210210

211211
| Option | Default | Description |
212212
|--------|---------|-------------|
213-
| `base` | `def.basePath ?? '/.<id>/'` | Mount path inside the Vite dev server. |
213+
| `base` | `def.basePath ?? '/__<id>/'` | Mount path inside the Vite dev server. |
214214

215215
Use this adapter when a devtool's UI is purely static (no server calls) and you want to surface it during Vite `serve` without shipping a separate dev server. Set `DevtoolDefinition.basePath` on the definition if you want a custom path that stays consistent across adapters.
216216

@@ -221,7 +221,7 @@ Produces a self-contained static deploy of a devtool:
221221
1. Copies the author's SPA dist (`cli.distDir` or `options.distDir`) into `<outDir>`.
222222
2. Runs `setup(ctx)` with `mode: 'build'`.
223223
3. Collects RPC dumps for every `'static'` function and any `'query'` function with `dump.inputs` / `snapshot: true`.
224-
4. Writes `<outDir>/.connection.json` (`{ backend: 'static' }`) and sharded dump files under `<outDir>/.rpc-dump/` — both at the SPA root so the deployed client discovers them via relative paths from `document.baseURI`.
224+
4. Writes `<outDir>/__connection.json` (`{ backend: 'static' }`) and sharded dump files under `<outDir>/__rpc-dump/` — both at the SPA root so the deployed client discovers them via relative paths from `document.baseURI`.
225225
5. When `def.spa` is set, also writes `<outDir>/spa-loader.json` describing how the SPA hydrates its data.
226226

227227
```ts
@@ -240,7 +240,7 @@ await createBuild(devtool, {
240240
| `base` | `/` | Absolute URL base the output is served from. |
241241
| `distDir` | `def.cli?.distDir` | Override the SPA dist directory. |
242242

243-
The resulting directory can be hosted by any static web server (`serve`, nginx, GitHub Pages, …). The client auto-detects `static` mode via `./.connection.json` resolved against `document.baseURI` and runs in read-only form.
243+
The resulting directory can be hosted by any static web server (`serve`, nginx, GitHub Pages, …). The client auto-detects `static` mode via `./__connection.json` resolved against `document.baseURI` and runs in read-only form.
244244

245245
> [!TIP]
246246
> `createBuild` copies the SPA verbatim. To deploy under a custom URL base, build your SPA with relative asset paths (`vite.base: './'`) — the client discovers the effective base at runtime. No HTML rewriting is performed at build time.
@@ -278,7 +278,7 @@ The returned object has the shape `{ name, devtools: { setup, capabilities } }`.
278278

279279
## Embedded
280280

281-
Register a devtool into an already-running context at runtime. Mirrors the internal plugin-scan that Kit runs at startup, but exposes it for callers that need dynamic, post-startup registration. The host decides the mount path; `embedded` is treated as a hosted adapter and inherits the `/.<id>/` default when one is needed.
281+
Register a devtool into an already-running context at runtime. Mirrors the internal plugin-scan that Kit runs at startup, but exposes it for callers that need dynamic, post-startup registration. The host decides the mount path; `embedded` is treated as a hosted adapter and inherits the `/__<id>/` default when one is needed.
282282

283283
```ts
284284
import { createEmbedded } from 'devframe/adapters/embedded'

devframe/docs/guide/client.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,11 @@ const rpc = await connectDevtool()
1818
const modules = await rpc.call('my-devtool:get-modules', { limit: 10 })
1919
```
2020

21-
`connectDevtool` auto-detects the backend via `.devtools/.connection.json` and falls back through a sequence of base URLs. No arguments are needed when the client is hosted from the default mount path.
21+
`connectDevtool` auto-detects the backend via `__devtools/__connection.json` and falls back through a sequence of base URLs. No arguments are needed when the client is hosted from the default mount path.
2222

2323
### Runtime basePath discovery
2424

25-
SPAs built for devframe are designed to be **base-agnostic**: the same artifact can be served at `/`, at `/.<id>/`, or at any custom subpath, without rebuilding. `connectDevtool` resolves `.connection.json` relative to the page at runtime by reading `document.baseURI` and the executing script's URL.
25+
SPAs built for devframe are designed to be **base-agnostic**: the same artifact can be served at `/`, at `/__<id>/`, or at any custom subpath, without rebuilding. `connectDevtool` resolves `__connection.json` relative to the page at runtime by reading `document.baseURI` and the executing script's URL.
2626

2727
The practical consequence for SPA authors:
2828

@@ -46,16 +46,16 @@ await connectDevtool({
4646

4747
| Option | Description |
4848
|--------|-------------|
49-
| `baseURL` | Mount path to probe for `.connection.json`. Accepts an array for fallback. Default: `'./'` — resolved relative to `document.baseURI` so the SPA finds its meta wherever it was deployed. Pass an explicit absolute path (e.g. `'/.devtools/'`) when calling from outside the SPA — for instance, an embedded webcomponent injected into a host app. |
49+
| `baseURL` | Mount path to probe for `__connection.json`. Accepts an array for fallback. Default: `'./'` — resolved relative to `document.baseURI` so the SPA finds its meta wherever it was deployed. Pass an explicit absolute path (e.g. `'/__devtools/'`) when calling from outside the SPA — for instance, an embedded webcomponent injected into a host app. |
5050
| `authToken` | Override the auth token. Defaults to a locally-persisted human-readable id. |
5151
| `cacheOptions` | `true` to enable caching with defaults, or an options object. |
5252
| `wsOptions` | Forwarded to the WebSocket transport (reconnect, heartbeat, etc.). |
5353
| `rpcOptions` | Forwarded to `birpc`. |
54-
| `connectionMeta` | Skip the `.connection.json` fetch with a pre-known descriptor. |
54+
| `connectionMeta` | Skip the `__connection.json` fetch with a pre-known descriptor. |
5555

5656
## Modes
5757

58-
The client runs in one of two modes depending on what the server advertises in `.devtools/.connection.json`:
58+
The client runs in one of two modes depending on what the server advertises in `__devtools/__connection.json`:
5959

6060
| Backend | When | Capabilities |
6161
|---------|------|--------------|
@@ -156,9 +156,9 @@ const rpc = await connectDevtool({ cacheOptions: true })
156156

157157
With caching on, `query` / `static` function responses are memoized per argument hash. Server-side broadcasts like `rpc:cache:invalidate` clear entries automatically — plugins that mutate state should broadcast that message after the change.
158158

159-
## Discovery (`.connection.json`)
159+
## Discovery (`__connection.json`)
160160

161-
DevFrame writes a small JSON descriptor at `<base>/.connection.json` so the client knows where to connect:
161+
DevFrame writes a small JSON descriptor at `<base>/__connection.json` so the client knows where to connect:
162162

163163
```json
164164
{

devframe/docs/guide/nuxt.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ At build time the module:
6868
return { provide: { rpc } }
6969
```
7070

71-
At runtime the built SPA fetches `./.connection.json` (resolved against `document.baseURI`) and branches on the `backend` field — `websocket` in dev, `static` from a `createBuild` snapshot.
71+
At runtime the built SPA fetches `./__connection.json` (resolved against `document.baseURI`) and branches on the `backend` field — `websocket` in dev, `static` from a `createBuild` snapshot.
7272

7373
## Relationship to `createCli`
7474

devframe/docs/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
"devDependencies": {
1111
"devframe": "workspace:*",
1212
"mermaid": "catalog:docs",
13+
"tinyglobby": "catalog:deps",
1314
"vitepress": "catalog:docs",
1415
"vitepress-plugin-mermaid": "catalog:docs"
1516
}

devframe/examples/devframe-files-inspector/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,15 @@ A simplified [node-modules-inspector](https://github.com/antfu/node-modules-insp
88

99
The Preact client showcases two patterns relevant to devframe authors:
1010

11-
1. **Runtime base discovery.** The client is built with `vite.base: './'` and reads `document.baseURI` at runtime to resolve its mount path. The same `dist/client` works under any base path (`/.devframe-files-inspector/`, `/`, `/custom/`, …) without rebuilding.
11+
1. **Runtime base discovery.** The client is built with `vite.base: './'` and reads `document.baseURI` at runtime to resolve its mount path. The same `dist/client` works under any base path (`/__devframe-files-inspector/`, `/`, `/custom/`, …) without rebuilding.
1212
2. **Two RPC types.** `:list-files` is a `query` with `dump.inputs: [[]]` (live in dev, baked in static). `:get-cwd` is a `static` RPC.
1313

1414
## Run
1515

1616
```sh
1717
pnpm install
1818
pnpm -C examples/devframe-files-inspector run build # build the Preact client
19-
pnpm -C examples/devframe-files-inspector run dev # http://127.0.0.1:9876/.devframe-files-inspector/
19+
pnpm -C examples/devframe-files-inspector run dev # http://127.0.0.1:9876/__devframe-files-inspector/
2020
pnpm -C examples/devframe-files-inspector run cli:build # static deploy in ./dist/static
2121
serve examples/devframe-files-inspector/dist/static # any static host works (relative paths)
2222
pnpm -C examples/devframe-files-inspector run test # E2E tests

0 commit comments

Comments
 (0)