devframe 0.1.21 → 0.1.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. package/README.md +41 -18
  2. package/dist/{_shared-iZy45oG3.mjs → _shared-DcJX9-Az.mjs} +2 -2
  3. package/dist/adapters/build.d.mts +5 -5
  4. package/dist/adapters/build.mjs +13 -12
  5. package/dist/adapters/cli.d.mts +2 -2
  6. package/dist/adapters/cli.mjs +5 -5
  7. package/dist/adapters/dev.d.mts +18 -9
  8. package/dist/adapters/dev.mjs +1 -1
  9. package/dist/adapters/embedded.d.mts +5 -5
  10. package/dist/adapters/embedded.mjs +2 -2
  11. package/dist/adapters/mcp.d.mts +3 -3
  12. package/dist/adapters/mcp.mjs +5 -5
  13. package/dist/adapters/vite.d.mts +45 -12
  14. package/dist/adapters/vite.mjs +81 -18
  15. package/dist/chunk-e9Ob2GDo.mjs +26 -0
  16. package/dist/client/index.d.mts +10 -5
  17. package/dist/client/index.mjs +19 -10
  18. package/dist/colors-Bl4W18Mh.mjs +123 -0
  19. package/dist/{context-internal-saIAfNVw.d.mts → context-DBd794Rn.d.mts} +2 -2
  20. package/dist/{context-BJ4r2SmR.mjs → context-DUibxhrR.mjs} +14 -31
  21. package/dist/{dev-CdAy400a.mjs → dev-BGpTpYiR.mjs} +19 -20
  22. package/dist/{devtool-CNvLs2_Y.d.mts → devframe-DulcIxwu.d.mts} +49 -58
  23. package/dist/{diagnostics-DxPnRoXO.mjs → diagnostics-BFhNNmST.mjs} +7 -2
  24. package/dist/hash-BHZbo80D.mjs +126 -0
  25. package/dist/{human-id-BLoGo_e5.mjs → human-id-adtUWQLr.mjs} +12 -3
  26. package/dist/{index-CuLRIMto.d.mts → index-DB2Ie0Or.d.mts} +2 -3
  27. package/dist/index.d.mts +4 -5
  28. package/dist/index.mjs +2 -5
  29. package/dist/launch-editor-KA_21J1T.mjs +581 -0
  30. package/dist/node/auth.d.mts +44 -0
  31. package/dist/node/auth.mjs +55 -0
  32. package/dist/node/index.d.mts +10 -51
  33. package/dist/node/index.mjs +6 -62
  34. package/dist/{internal/index.d.mts → node/internal.d.mts} +5 -5
  35. package/dist/node/internal.mjs +50 -0
  36. package/dist/{open-Dede_w9r.mjs → open-DmFp0qZA.mjs} +12 -3
  37. package/dist/recipes/open-helpers.d.mts +4 -9
  38. package/dist/recipes/open-helpers.mjs +7 -12
  39. package/dist/revoke-DIMz1r7-.mjs +35 -0
  40. package/dist/rpc/index.d.mts +3 -3
  41. package/dist/rpc/index.mjs +4 -4
  42. package/dist/rpc/transports/ws-client.d.mts +1 -1
  43. package/dist/rpc/transports/ws-client.mjs +2 -1
  44. package/dist/rpc/transports/ws-server.d.mts +1 -1
  45. package/dist/rpc/transports/ws-server.mjs +2 -1
  46. package/dist/{rpc-INbWfHoX.mjs → rpc-CkZuoz-m.mjs} +3 -2
  47. package/dist/{serialization-DwKi05Pn.mjs → serialization-CwO31axa.mjs} +1 -2
  48. package/dist/{server-CBsxXIH5.mjs → server-ma8-ZVyX.mjs} +1 -1
  49. package/dist/{server-BAqOajx_.d.mts → server-zKEDxgqD.d.mts} +4 -3
  50. package/dist/shared-state-DCDs0e7y.mjs +928 -0
  51. package/dist/{static-dump-D5VH8Iqk.mjs → static-dump-D7AvjrgL.mjs} +1 -1
  52. package/dist/{context-internal-Dx_NoSv1.mjs → storage-CNC38eU-.mjs} +4 -86
  53. package/dist/structured-clone-DcDc2Dds.mjs +221 -0
  54. package/dist/types/index.d.mts +4 -4
  55. package/dist/types/index.mjs +11 -2
  56. package/dist/utils/colors.d.mts +28 -0
  57. package/dist/utils/colors.mjs +2 -0
  58. package/dist/utils/events.d.mts +1 -1
  59. package/dist/utils/hash.d.mts +7 -0
  60. package/dist/utils/hash.mjs +2 -0
  61. package/dist/utils/human-id.d.mts +6 -8
  62. package/dist/utils/human-id.mjs +1 -2
  63. package/dist/utils/launch-editor.d.mts +13 -0
  64. package/dist/utils/launch-editor.mjs +2 -0
  65. package/dist/utils/open.d.mts +16 -0
  66. package/dist/utils/open.mjs +2 -0
  67. package/dist/utils/serve-static.d.mts +30 -0
  68. package/dist/utils/serve-static.mjs +152 -0
  69. package/dist/utils/shared-state.d.mts +1 -1
  70. package/dist/utils/shared-state.mjs +1 -35
  71. package/dist/utils/streaming-channel.d.mts +1 -1
  72. package/dist/utils/structured-clone.d.mts +21 -0
  73. package/dist/utils/structured-clone.mjs +2 -0
  74. package/dist/utils/when.d.mts +32 -49
  75. package/dist/utils/when.mjs +20 -2
  76. package/dist/{ws-client-CjPuPFbA.d.mts → ws-client-Bavoya6-.d.mts} +1 -1
  77. package/dist/{ws-server-C7LnhOHi.d.mts → ws-server-DjvlwLuM.d.mts} +1 -1
  78. package/package.json +23 -10
  79. package/skills/devframe/SKILL.md +45 -23
  80. package/skills/devframe/templates/{counter-devtool.ts → counter-devframe.ts} +4 -4
  81. package/skills/devframe/templates/{spa-devtool.ts → spa-devframe.ts} +3 -3
  82. package/skills/devframe/templates/vite-client.ts +2 -2
  83. package/dist/internal/index.mjs +0 -3
  84. package/dist/utils/state.d.mts +0 -50
  85. package/dist/utils/state.mjs +0 -26
  86. package/dist/{define-Bb4zh-Dc.mjs → define-CW9gLnyG.mjs} +0 -0
  87. package/dist/{host-h3-9jeHcltx.mjs → host-h3-Dz8YnFgu.mjs} +1 -1
  88. /package/dist/{transports-DSV5_5QM.mjs → transports-BnCs4rj9.mjs} +0 -0
  89. /package/dist/{types-C5OVe4AC.d.mts → types-4rdUEi2R.d.mts} +0 -0
package/README.md CHANGED
@@ -1,6 +1,8 @@
1
1
  # devframe
2
2
 
3
- Framework-neutral foundation for building generic DevTools RPC layer (birpc + valibot + WS presets), six hosts (RPC / docks / views / terminals / logs / commands / agent), and adapters under `devframe/adapters/*` (cli / build / spa / vite / kit / embedded / mcp). Part of the [Vite DevTools](https://devtools.vite.dev) monorepo.
3
+ Framework-neutral foundation for building generic DevTools. Describe one devframe its RPC, its data, its SPA, its CLI shape and deploy the same definition through any of seven adapters.
4
+
5
+ Part of the [Vite DevTools](https://devtools.vite.dev) monorepo. Full documentation: [https://devfra.me/](https://devfra.me/).
4
6
 
5
7
  ## Install
6
8
 
@@ -8,18 +10,48 @@ Framework-neutral foundation for building generic DevTools — RPC layer (birpc
8
10
  pnpm add devframe
9
11
  ```
10
12
 
11
- ## Docs
13
+ ## Hello, Devframe
14
+
15
+ ```ts
16
+ import { defineDevframe, defineRpcFunction } from 'devframe'
17
+ import { createCli } from 'devframe/adapters/cli'
18
+
19
+ const devframe = defineDevframe({
20
+ id: 'my-devframe',
21
+ name: 'My Devframe',
22
+ setup(ctx) {
23
+ ctx.rpc.register(defineRpcFunction({
24
+ name: 'my-devframe:hello',
25
+ type: 'static',
26
+ jsonSerializable: true,
27
+ handler: () => ({ message: 'hello' }),
28
+ }))
29
+ },
30
+ })
12
31
 
13
- See the [DevFrame documentation](https://devfra.me/) for the full guide and API reference.
32
+ await createCli(devframe).parse()
33
+ ```
34
+
35
+ ## Adapters
36
+
37
+ | Adapter | Use case |
38
+ |---------|----------|
39
+ | `cli` | Standalone CLI tool with `dev` / `build` / `mcp` subcommands. |
40
+ | `build` | Generates a static, self-contained SPA snapshot. |
41
+ | `vite` | Runs as a Vite plugin alongside the host app's dev server. |
42
+ | `kit` | Mounts into the DevTools Kit aggregator. |
43
+ | `embedded` | Overlays inside another devtool's UI. |
44
+ | `mcp` | Surfaces the devframe's RPC to coding agents over MCP. |
14
45
 
15
46
  ## Agent-Native (experimental)
16
47
 
17
- > ⚠️ **Experimental.** The agent-native surface — the `agent` field on `defineRpcFunction`, `DevToolsAgentHost`, and the `devframe/adapters/mcp` adapter — is experimental and may change without a major version bump until it stabilizes.
48
+ > [!WARNING]
49
+ > The agent-native surface — the `agent` field on `defineRpcFunction`, `DevToolsAgentHost`, and the `devframe/adapters/mcp` adapter — may change without a major version bump until it stabilizes.
18
50
 
19
- DevFrame can expose a devtool's RPC functions, tools, and resources to coding agents over [MCP](https://modelcontextprotocol.io). Flag an RPC function with `agent: { description }` to surface it, then spin up an MCP server:
51
+ Devframe surfaces a devframe's RPC functions, tools, and resources to coding agents over [MCP](https://modelcontextprotocol.io). Flag an RPC function with `agent: { description }` to expose it, then spin up an MCP server:
20
52
 
21
53
  ```ts
22
- import { defineDevtool, defineRpcFunction } from 'devframe'
54
+ import { defineDevframe, defineRpcFunction } from 'devframe'
23
55
  import { createMcpServer } from 'devframe/adapters/mcp'
24
56
 
25
57
  const getSummary = defineRpcFunction({
@@ -31,11 +63,10 @@ const getSummary = defineRpcFunction({
31
63
  setup: ctx => ({ handler: async () => buildSummary() }),
32
64
  })
33
65
 
34
- const devtool = defineDevtool({
66
+ const devframe = defineDevframe({
35
67
  id: 'my-plugin',
36
68
  setup(ctx) {
37
69
  ctx.rpc.register(getSummary)
38
- // Optional: register tools or resources directly.
39
70
  ctx.agent.registerResource({
40
71
  id: 'latest-build',
41
72
  name: 'Latest build',
@@ -44,18 +75,10 @@ const devtool = defineDevtool({
44
75
  },
45
76
  })
46
77
 
47
- await createMcpServer(devtool, { transport: 'stdio' })
78
+ await createMcpServer(devframe, { transport: 'stdio' })
48
79
  ```
49
80
 
50
- Or via the CLI:
51
-
52
- ```sh
53
- devframe mcp
54
- ```
55
-
56
- `@modelcontextprotocol/sdk` is a peer dependency — add it to your package when you want to ship MCP support.
57
-
58
- See the [Agent-Native guide](https://devfra.me/agent-native) for the full API, safety model, and Claude Desktop integration example.
81
+ Or via the CLI: `devframe mcp`. `@modelcontextprotocol/sdk` is a peer dependency — add it when you want MCP support. See the [Agent-Native guide](https://devfra.me/guide/agent-native) for the full API and Claude Desktop integration example.
59
82
 
60
83
  ## License
61
84
 
@@ -1,11 +1,11 @@
1
1
  //#region src/adapters/_shared.ts
2
2
  /**
3
- * Resolve the mount base path for a devtool's SPA. Hosted adapters
3
+ * Resolve the mount base path for a devframe's SPA. Hosted adapters
4
4
  * (`vite`, `kit`, `embedded`) default to `/__<id>/` so they don't
5
5
  * collide with the host app; standalone adapters (`cli`, `spa`,
6
6
  * `build`) default to `/` because they own the origin.
7
7
  *
8
- * The devtool author can override with `basePath` on the definition.
8
+ * The devframe author can override with `basePath` on the definition.
9
9
  */
10
10
  function resolveBasePath(def, kind) {
11
11
  if (def.basePath) return normalizeBasePath(def.basePath);
@@ -1,4 +1,4 @@
1
- import { r as DevtoolDefinition } from "../devtool-CNvLs2_Y.mjs";
1
+ import { r as DevframeDefinition } from "../devframe-DulcIxwu.mjs";
2
2
 
3
3
  //#region src/adapters/build.d.ts
4
4
  interface CreateBuildOptions {
@@ -8,7 +8,7 @@ interface CreateBuildOptions {
8
8
  base?: string;
9
9
  /**
10
10
  * Override the SPA dist directory to copy into `outDir`. When omitted
11
- * the adapter reads `devtool.cli?.distDir` — authors typically set this
11
+ * the adapter reads `devframe.cli?.distDir` — authors typically set this
12
12
  * once on the definition itself.
13
13
  */
14
14
  distDir?: string;
@@ -20,9 +20,9 @@ interface CreateBuildOptions {
20
20
  pretty?: boolean;
21
21
  }
22
22
  /**
23
- * Produce a self-contained static deploy of a devtool:
23
+ * Produce a self-contained static deploy of a devframe:
24
24
  *
25
- * - Build a `mode: 'build'` context and run `devtool.setup(ctx)`.
25
+ * - Build a `mode: 'build'` context and run `devframe.setup(ctx)`.
26
26
  * - Copy the author's SPA dist into `<outDir>/`.
27
27
  * - Write `<outDir>/__connection.json` (`{ backend: 'static' }`) and the
28
28
  * sharded RPC dump under `<outDir>/__rpc-dump/` so the deployed SPA
@@ -32,6 +32,6 @@ interface CreateBuildOptions {
32
32
  * `'none'`). The output is mount-path agnostic — the same bundle
33
33
  * works at `/`, `/devtools/`, or any base, no rewriting required.
34
34
  */
35
- declare function createBuild(d: DevtoolDefinition, options?: CreateBuildOptions): Promise<void>;
35
+ declare function createBuild(d: DevframeDefinition, options?: CreateBuildOptions): Promise<void>;
36
36
  //#endregion
37
37
  export { CreateBuildOptions, createBuild };
@@ -1,19 +1,20 @@
1
- import { n as strictJsonStringify, o as structuredCloneStringify } from "../serialization-DwKi05Pn.mjs";
2
- import { t as createHostContext } from "../context-BJ4r2SmR.mjs";
3
- import { t as createH3DevToolsHost } from "../host-h3-9jeHcltx.mjs";
1
+ import { n as strictJsonStringify } from "../serialization-CwO31axa.mjs";
2
+ import { i as structuredCloneStringify } from "../structured-clone-DcDc2Dds.mjs";
3
+ import { t as colors } from "../colors-Bl4W18Mh.mjs";
4
+ import { t as createHostContext } from "../context-DUibxhrR.mjs";
5
+ import { t as createH3DevToolsHost } from "../host-h3-Dz8YnFgu.mjs";
4
6
  import { DEVTOOLS_CONNECTION_META_FILENAME, DEVTOOLS_RPC_DUMP_DIRNAME, DEVTOOLS_RPC_DUMP_MANIFEST_FILENAME } from "../constants.mjs";
5
- import { t as collectStaticRpcDump } from "../static-dump-D5VH8Iqk.mjs";
6
- import { n as resolveBasePath } from "../_shared-iZy45oG3.mjs";
7
- import c from "ansis";
7
+ import { t as collectStaticRpcDump } from "../static-dump-D7AvjrgL.mjs";
8
+ import { n as resolveBasePath } from "../_shared-DcJX9-Az.mjs";
8
9
  import { existsSync } from "node:fs";
9
- import { dirname, resolve } from "pathe";
10
10
  import process from "node:process";
11
+ import { dirname, resolve } from "pathe";
11
12
  import fs$1 from "node:fs/promises";
12
13
  //#region src/adapters/build.ts
13
14
  /**
14
- * Produce a self-contained static deploy of a devtool:
15
+ * Produce a self-contained static deploy of a devframe:
15
16
  *
16
- * - Build a `mode: 'build'` context and run `devtool.setup(ctx)`.
17
+ * - Build a `mode: 'build'` context and run `devframe.setup(ctx)`.
17
18
  * - Copy the author's SPA dist into `<outDir>/`.
18
19
  * - Write `<outDir>/__connection.json` (`{ backend: 'static' }`) and the
19
20
  * sharded RPC dump under `<outDir>/__rpc-dump/` so the deployed SPA
@@ -29,7 +30,7 @@ async function createBuild(d, options = {}) {
29
30
  if (!distDir) throw new Error(`[devframe] createBuild: no distDir for "${d.id}". Set \`cli.distDir\` on the definition or pass it as an option.`);
30
31
  if (existsSync(outDir)) await fs$1.rm(outDir, { recursive: true });
31
32
  await fs$1.mkdir(outDir, { recursive: true });
32
- console.log(c.cyan`[devframe] copying SPA from ${distDir} -> ${outDir}`);
33
+ console.log(colors.cyan`[devframe] copying SPA from ${distDir} -> ${outDir}`);
33
34
  await fs$1.cp(distDir, outDir, { recursive: true });
34
35
  const ctx = await createHostContext({
35
36
  cwd: process.cwd(),
@@ -47,7 +48,7 @@ async function createBuild(d, options = {}) {
47
48
  backend: "static",
48
49
  jsonSerializableMethods
49
50
  }, null, 2), "utf-8");
50
- console.log(c.cyan`[devframe] writing RPC dump to ${resolve(outDir, DEVTOOLS_RPC_DUMP_MANIFEST_FILENAME)}`);
51
+ console.log(colors.cyan`[devframe] writing RPC dump to ${resolve(outDir, DEVTOOLS_RPC_DUMP_MANIFEST_FILENAME)}`);
51
52
  const dump = await collectStaticRpcDump(ctx.rpc.definitions.values(), ctx);
52
53
  const indent = options.pretty ? 2 : void 0;
53
54
  for (const [filepath, file] of Object.entries(dump.files)) {
@@ -66,7 +67,7 @@ async function createBuild(d, options = {}) {
66
67
  };
67
68
  await fs$1.writeFile(resolve(outDir, "spa-loader.json"), JSON.stringify(spaLoader, null, 2), "utf-8");
68
69
  }
69
- console.log(c.green`[devframe] built "${d.id}" -> ${outDir}`);
70
+ console.log(colors.green`[devframe] built "${d.id}" -> ${outDir}`);
70
71
  }
71
72
  //#endregion
72
73
  export { createBuild };
@@ -1,4 +1,4 @@
1
- import { dt as CliFlagsSchema, ft as InferCliFlags, mt as parseCliFlags, pt as defineCliFlags, r as DevtoolDefinition } from "../devtool-CNvLs2_Y.mjs";
1
+ import { _t as InferCliFlags, gt as CliFlagsSchema, r as DevframeDefinition, vt as defineCliFlags, yt as parseCliFlags } from "../devframe-DulcIxwu.mjs";
2
2
  import { App } from "h3";
3
3
  import { CAC } from "cac";
4
4
 
@@ -30,6 +30,6 @@ interface CliHandle {
30
30
  cli: CAC;
31
31
  parse: (argv?: string[]) => Promise<void>;
32
32
  }
33
- declare function createCli(d: DevtoolDefinition, options?: CreateCliOptions): CliHandle;
33
+ declare function createCli(d: DevframeDefinition, options?: CreateCliOptions): CliHandle;
34
34
  //#endregion
35
35
  export { type CliFlagsSchema, CliHandle, CreateCliOptions, type InferCliFlags, createCli, defineCliFlags, parseCliFlags };
@@ -1,6 +1,6 @@
1
+ import { t as colors } from "../colors-Bl4W18Mh.mjs";
1
2
  import { createBuild } from "./build.mjs";
2
- import { n as resolveDevServerPort, t as createDevServer } from "../dev-CdAy400a.mjs";
3
- import c from "ansis";
3
+ import { n as resolveDevServerPort, t as createDevServer } from "../dev-BGpTpYiR.mjs";
4
4
  import process from "node:process";
5
5
  import cac from "cac";
6
6
  import { safeParse } from "valibot";
@@ -15,7 +15,7 @@ import { safeParse } from "valibot";
15
15
  * config: v.optional(v.string()),
16
16
  * })
17
17
  *
18
- * defineDevtool({
18
+ * defineDevframe({
19
19
  * cli: { flags: appFlags },
20
20
  * setup(ctx, info) {
21
21
  * const flags = info.flags as InferCliFlags<typeof appFlags>
@@ -102,7 +102,7 @@ function createCli(d, options = {}) {
102
102
  onReady: options.onReady
103
103
  });
104
104
  });
105
- cli.command("build", "Build a self-contained static deploy of the devtool").option("--out-dir <outDir>", "Output directory", { default: "dist-static" }).option("--base <base>", "URL base", { default: "/" }).option("--pretty", "Pretty-print dump JSON (larger on disk)").action(async (flags) => {
105
+ cli.command("build", "Build a self-contained static deploy of the devframe").option("--out-dir <outDir>", "Output directory", { default: "dist-static" }).option("--base <base>", "URL base", { default: "/" }).option("--pretty", "Pretty-print dump JSON (larger on disk)").action(async (flags) => {
106
106
  await createBuild(d, {
107
107
  outDir: flags.outDir,
108
108
  base: flags.base,
@@ -134,7 +134,7 @@ function resolveTypedFlags(d, raw) {
134
134
  if (!d.cli?.flags) return raw;
135
135
  const { flags, issues } = parseCliFlags(d.cli.flags, raw);
136
136
  if (issues?.length) {
137
- for (const issue of issues) console.error(c.red`[devframe] invalid flag — ${issue}`);
137
+ for (const issue of issues) console.error(colors.red`[devframe] invalid flag — ${issue}`);
138
138
  process.exit(1);
139
139
  }
140
140
  return flags;
@@ -1,5 +1,5 @@
1
- import { r as DevtoolDefinition } from "../devtool-CNvLs2_Y.mjs";
2
- import { n as StartedServer } from "../server-BAqOajx_.mjs";
1
+ import { r as DevframeDefinition } from "../devframe-DulcIxwu.mjs";
2
+ import { n as StartedServer } from "../server-zKEDxgqD.mjs";
3
3
  import { App } from "h3";
4
4
 
5
5
  //#region src/adapters/dev.d.ts
@@ -19,8 +19,11 @@ interface CreateDevServerOptions {
19
19
  */
20
20
  flags?: Record<string, unknown>;
21
21
  /**
22
- * Override `def.cli?.distDir`. Throws when neither is set — the dev
23
- * server has nothing to mount otherwise.
22
+ * Override `def.cli?.distDir`. When neither this option nor
23
+ * `def.cli?.distDir` is set, the dev server runs in **bridge mode**
24
+ * only `__connection.json` and the WS endpoint are mounted; the SPA
25
+ * is expected to be hosted elsewhere (e.g. by a parent Vite/Nuxt
26
+ * dev server via `createVitePlugin({ devMiddleware })`).
24
27
  */
25
28
  distDir?: string;
26
29
  /**
@@ -65,11 +68,17 @@ interface ResolveDevServerPortOptions {
65
68
  * resolve a port up-front (to print it, log it, etc.) before starting
66
69
  * the server.
67
70
  */
68
- declare function resolveDevServerPort(def: DevtoolDefinition, options?: ResolveDevServerPortOptions): Promise<number>;
71
+ declare function resolveDevServerPort(def: DevframeDefinition, options?: ResolveDevServerPortOptions): Promise<number>;
69
72
  /**
70
- * Start a devframe dev server for a {@link DevtoolDefinition} —
71
- * h3 + WebSocket RPC + the author's SPA mounted at the resolved base
72
- * path.
73
+ * Start a devframe dev server for a {@link DevframeDefinition} —
74
+ * h3 + WebSocket RPC + (optionally) the author's SPA mounted at the
75
+ * resolved base path.
76
+ *
77
+ * When `distDir` is omitted (and `def.cli?.distDir` is unset) the
78
+ * server runs in **bridge mode**: only `__connection.json` and the WS
79
+ * endpoint are mounted, with no SPA mount. The SPA is expected to be
80
+ * hosted elsewhere (e.g. by a parent Vite/Nuxt dev server) — see
81
+ * `createVitePlugin({ devMiddleware })`.
73
82
  *
74
83
  * Returns the underlying {@link StartedServer} handle so callers can
75
84
  * close it gracefully (SIGINT, hot-reload, test teardown).
@@ -78,6 +87,6 @@ declare function resolveDevServerPort(def: DevtoolDefinition, options?: ResolveD
78
87
  * framework (commander, yargs, hand-rolled CAC). For the all-in-one
79
88
  * `dev` / `build` / `mcp` shell, reach for {@link createCli} instead.
80
89
  */
81
- declare function createDevServer(def: DevtoolDefinition, options?: CreateDevServerOptions): Promise<StartedServer>;
90
+ declare function createDevServer(def: DevframeDefinition, options?: CreateDevServerOptions): Promise<StartedServer>;
82
91
  //#endregion
83
92
  export { CreateDevServerOptions, ResolveDevServerPortOptions, createDevServer, resolveDevServerPort };
@@ -1,2 +1,2 @@
1
- import { n as resolveDevServerPort, t as createDevServer } from "../dev-CdAy400a.mjs";
1
+ import { n as resolveDevServerPort, t as createDevServer } from "../dev-BGpTpYiR.mjs";
2
2
  export { createDevServer, resolveDevServerPort };
@@ -1,19 +1,19 @@
1
- import { d as DevToolsNodeContext, r as DevtoolDefinition } from "../devtool-CNvLs2_Y.mjs";
1
+ import { r as DevframeDefinition, y as DevToolsNodeContext } from "../devframe-DulcIxwu.mjs";
2
2
 
3
3
  //#region src/adapters/embedded.d.ts
4
4
  interface CreateEmbeddedOptions {
5
- /** Target context the devtool is registered into. Required. */
5
+ /** Target context the devframe is registered into. Required. */
6
6
  ctx: DevToolsNodeContext;
7
7
  }
8
8
  /**
9
- * Register a devtool into an already-running devframe/Kit context at
10
- * runtime. Mirrors what the Vite plugin scan does for devtools passed
9
+ * Register a devframe into an already-running devframe/Kit context at
10
+ * runtime. Mirrors what the Vite plugin scan does for devframes passed
11
11
  * as plugin options, but exposes the same flow to callers that need
12
12
  * dynamic, post-startup registration.
13
13
  *
14
14
  * The host owns the mount path; when a hosted mount is needed the
15
15
  * effective default follows the hosted rule of `def.basePath ?? '/__<id>/'`.
16
16
  */
17
- declare function createEmbedded(d: DevtoolDefinition, options: CreateEmbeddedOptions): Promise<void>;
17
+ declare function createEmbedded(d: DevframeDefinition, options: CreateEmbeddedOptions): Promise<void>;
18
18
  //#endregion
19
19
  export { CreateEmbeddedOptions, createEmbedded };
@@ -1,7 +1,7 @@
1
1
  //#region src/adapters/embedded.ts
2
2
  /**
3
- * Register a devtool into an already-running devframe/Kit context at
4
- * runtime. Mirrors what the Vite plugin scan does for devtools passed
3
+ * Register a devframe into an already-running devframe/Kit context at
4
+ * runtime. Mirrors what the Vite plugin scan does for devframes passed
5
5
  * as plugin options, but exposes the same flow to callers that need
6
6
  * dynamic, post-startup registration.
7
7
  *
@@ -1,4 +1,4 @@
1
- import { r as DevtoolDefinition } from "../devtool-CNvLs2_Y.mjs";
1
+ import { r as DevframeDefinition } from "../devframe-DulcIxwu.mjs";
2
2
  import { Server } from "@modelcontextprotocol/sdk/server/index.js";
3
3
 
4
4
  //#region src/node/mcp/build-server.d.ts
@@ -28,12 +28,12 @@ interface McpServerHandle {
28
28
  stop: () => Promise<void>;
29
29
  }
30
30
  /**
31
- * Build an MCP server over the agent surface of a devtool definition.
31
+ * Build an MCP server over the agent surface of a devframe definition.
32
32
  * Currently supports `stdio` transport only.
33
33
  *
34
34
  * @experimental The agent-native surface is experimental and may change
35
35
  * without a major version bump until it stabilizes.
36
36
  */
37
- declare function createMcpServer(definition: DevtoolDefinition, options?: CreateMcpServerOptions): Promise<McpServerHandle>;
37
+ declare function createMcpServer(definition: DevframeDefinition, options?: CreateMcpServerOptions): Promise<McpServerHandle>;
38
38
  //#endregion
39
39
  export { type CreateMcpServerOptions, type McpServerHandle, createMcpServer };
@@ -1,8 +1,8 @@
1
- import { n as logger } from "../diagnostics-DxPnRoXO.mjs";
2
- import { t as createHostContext } from "../context-BJ4r2SmR.mjs";
3
- import { join } from "pathe";
1
+ import { n as logger } from "../diagnostics-BFhNNmST.mjs";
2
+ import { t as createHostContext } from "../context-DUibxhrR.mjs";
4
3
  import { homedir } from "node:os";
5
4
  import process from "node:process";
5
+ import { join } from "pathe";
6
6
  import { Server } from "@modelcontextprotocol/sdk/server/index.js";
7
7
  import { CallToolRequestSchema, ListResourcesRequestSchema, ListToolsRequestSchema, ReadResourceRequestSchema } from "@modelcontextprotocol/sdk/types.js";
8
8
  import { toJsonSchema } from "@valibot/to-json-schema";
@@ -113,7 +113,7 @@ function buildMcpServerFromContext(ctx, options) {
113
113
  };
114
114
  }
115
115
  /**
116
- * Build an MCP server over the agent surface of a devtool definition.
116
+ * Build an MCP server over the agent surface of a devframe definition.
117
117
  * Currently supports `stdio` transport only.
118
118
  *
119
119
  * @experimental The agent-native surface is experimental and may change
@@ -140,7 +140,7 @@ async function createMcpServer(definition, options = {}) {
140
140
  serverVersion: options.serverVersion ?? definition.version ?? "0.0.0",
141
141
  exposeSharedState: options.exposeSharedState ?? true
142
142
  });
143
- const { startStdioTransport } = await import("../transports-DSV5_5QM.mjs");
143
+ const { startStdioTransport } = await import("../transports-BnCs4rj9.mjs");
144
144
  let stop;
145
145
  try {
146
146
  stop = await startStdioTransport(server);
@@ -1,12 +1,33 @@
1
- import { r as DevtoolDefinition } from "../devtool-CNvLs2_Y.mjs";
1
+ import { r as DevframeDefinition } from "../devframe-DulcIxwu.mjs";
2
2
 
3
3
  //#region src/adapters/vite.d.ts
4
4
  interface CreateVitePluginOptions {
5
5
  /**
6
6
  * Mount base. Defaults to `def.basePath ?? '/__<id>/'` for this hosted
7
- * adapter — the devtool shares the origin with the host Vite app.
7
+ * adapter — the devframe shares the origin with the host Vite app.
8
+ *
9
+ * Relative spellings like `'./'` (common for base-agnostic Nuxt builds)
10
+ * are normalized to absolute paths so they compose with Vite's connect
11
+ * router.
8
12
  */
9
13
  base?: string;
14
+ /**
15
+ * Dev-time middleware mode. When set, the host app owns the SPA and
16
+ * devframe spins up a separate RPC + WS server on a resolved port,
17
+ * registering Vite middleware at `<base>__connection.json` so the
18
+ * host-served SPA can discover the WS endpoint.
19
+ *
20
+ * - `false` (default) — static-mount the SPA at `base` with SPA
21
+ * fallback. No RPC server is started.
22
+ * - `true` — bridge mode with all defaults (port from
23
+ * {@link resolveDevServerPort}, host from `def.cli?.host`).
24
+ * - object — bridge mode with explicit overrides.
25
+ */
26
+ devMiddleware?: boolean | {
27
+ /** Override the bridge port. Default: {@link resolveDevServerPort}. */port?: number; /** Override the bridge bind host. Default: `def.cli?.host ?? 'localhost'`. */
28
+ host?: string; /** Flag bag forwarded to `def.setup(ctx, { flags })`. */
29
+ flags?: Record<string, unknown>;
30
+ };
10
31
  }
11
32
  interface DevframeVitePlugin {
12
33
  name: string;
@@ -15,19 +36,31 @@ interface DevframeVitePlugin {
15
36
  middlewares: {
16
37
  use: (path: string, handler: any) => void;
17
38
  };
18
- }) => void;
39
+ httpServer?: {
40
+ once: (event: 'close', cb: () => void) => void;
41
+ } | null;
42
+ }) => void | Promise<void>;
43
+ closeBundle?: () => void | Promise<void>;
19
44
  }
20
45
  /**
21
- * Plain Vite plugin mounts a devframe devtool's SPA into a user's
22
- * Vite dev server at `options.base` (default: `def.basePath ?? '/__<id>/'`).
23
- * Use this for tools that want the Vite dev experience without
24
- * pulling the full Vite DevTools Kit.
46
+ * Vite plugin for hosting a devframe inside a Vite dev server.
47
+ *
48
+ * Two modes, picked via `options.devMiddleware`:
49
+ *
50
+ * - **static-mount mode** (default) — mounts `def.cli.distDir` at
51
+ * `options.base` with SPA fallback enabled. No RPC server is started.
52
+ *
53
+ * - **bridge mode** (`devMiddleware: true | {…}`) — skips the static
54
+ * mount; the host app owns the SPA. Devframe starts a separate
55
+ * RPC + WS dev server (via {@link createDevServer} in bridge mode)
56
+ * and registers Vite middleware at `<base>__connection.json` so the
57
+ * host-served SPA can discover the WS endpoint via
58
+ * {@link connectDevframe}.
25
59
  *
26
- * Note: this does not yet spin up the RPC WS server — for the full
27
- * RPC path, use `createPluginFromDevframe` from
28
- * `@vitejs/devtools-kit/node` alongside `@vitejs/devtools`, or the
29
- * standalone `createCli`.
60
+ * Use bridge mode when integrating with frameworks that own the SPA
61
+ * (Nuxt, Astro, SolidStart, plain Vite apps). For the all-in-one
62
+ * `dev` / `build` / `mcp` shell, reach for {@link createCli} instead.
30
63
  */
31
- declare function createVitePlugin(d: DevtoolDefinition, options?: CreateVitePluginOptions): DevframeVitePlugin;
64
+ declare function createVitePlugin(d: DevframeDefinition, options?: CreateVitePluginOptions): DevframeVitePlugin;
32
65
  //#endregion
33
66
  export { CreateVitePluginOptions, DevframeVitePlugin, createVitePlugin };
@@ -1,32 +1,95 @@
1
- import { n as resolveBasePath } from "../_shared-iZy45oG3.mjs";
1
+ import { n as logger } from "../diagnostics-BFhNNmST.mjs";
2
+ import { DEVTOOLS_CONNECTION_META_FILENAME } from "../constants.mjs";
3
+ import { n as resolveBasePath } from "../_shared-DcJX9-Az.mjs";
4
+ import { serveStaticNodeMiddleware } from "../utils/serve-static.mjs";
5
+ import { n as resolveDevServerPort, t as createDevServer } from "../dev-BGpTpYiR.mjs";
2
6
  import { resolve } from "pathe";
3
- import sirv from "sirv";
4
7
  //#region src/adapters/vite.ts
5
8
  /**
6
- * Plain Vite plugin mounts a devframe devtool's SPA into a user's
7
- * Vite dev server at `options.base` (default: `def.basePath ?? '/__<id>/'`).
8
- * Use this for tools that want the Vite dev experience without
9
- * pulling the full Vite DevTools Kit.
9
+ * Vite plugin for hosting a devframe inside a Vite dev server.
10
10
  *
11
- * Note: this does not yet spin up the RPC WS server — for the full
12
- * RPC path, use `createPluginFromDevframe` from
13
- * `@vitejs/devtools-kit/node` alongside `@vitejs/devtools`, or the
14
- * standalone `createCli`.
11
+ * Two modes, picked via `options.devMiddleware`:
12
+ *
13
+ * - **static-mount mode** (default) mounts `def.cli.distDir` at
14
+ * `options.base` with SPA fallback enabled. No RPC server is started.
15
+ *
16
+ * - **bridge mode** (`devMiddleware: true | {…}`) — skips the static
17
+ * mount; the host app owns the SPA. Devframe starts a separate
18
+ * RPC + WS dev server (via {@link createDevServer} in bridge mode)
19
+ * and registers Vite middleware at `<base>__connection.json` so the
20
+ * host-served SPA can discover the WS endpoint via
21
+ * {@link connectDevframe}.
22
+ *
23
+ * Use bridge mode when integrating with frameworks that own the SPA
24
+ * (Nuxt, Astro, SolidStart, plain Vite apps). For the all-in-one
25
+ * `dev` / `build` / `mcp` shell, reach for {@link createCli} instead.
15
26
  */
16
27
  function createVitePlugin(d, options = {}) {
17
- const base = options.base ?? resolveBasePath(d, "hosted");
18
- const distDir = d.cli?.distDir;
28
+ const base = normalizeMountBase(options.base ?? resolveBasePath(d, "hosted"));
29
+ if (!options.devMiddleware) {
30
+ const distDir = d.cli?.distDir;
31
+ return {
32
+ name: `devframe:${d.id}`,
33
+ apply: "serve",
34
+ configureServer(server) {
35
+ if (!distDir) return;
36
+ server.middlewares.use(base, serveStaticNodeMiddleware(resolve(distDir)));
37
+ }
38
+ };
39
+ }
40
+ const mw = options.devMiddleware === true ? {} : options.devMiddleware;
41
+ let started;
19
42
  return {
20
43
  name: `devframe:${d.id}`,
21
44
  apply: "serve",
22
- configureServer(server) {
23
- if (!distDir) return;
24
- server.middlewares.use(base, sirv(resolve(distDir), {
25
- dev: true,
26
- single: true
27
- }));
45
+ async configureServer(server) {
46
+ await started?.close().catch(() => {});
47
+ started = void 0;
48
+ let port;
49
+ try {
50
+ port = mw.port ?? await resolveDevServerPort(d, { host: mw.host });
51
+ started = await createDevServer(d, {
52
+ host: mw.host,
53
+ port,
54
+ flags: mw.flags,
55
+ openBrowser: false
56
+ });
57
+ } catch (e) {
58
+ logger.DF0033({
59
+ id: d.id,
60
+ reason: String(e)
61
+ }, { cause: e }).log();
62
+ return;
63
+ }
64
+ const metaPath = `${base}${DEVTOOLS_CONNECTION_META_FILENAME}`;
65
+ server.middlewares.use(metaPath, (_req, res) => {
66
+ res.setHeader("Content-Type", "application/json");
67
+ res.end(JSON.stringify({
68
+ backend: "websocket",
69
+ websocket: port
70
+ }));
71
+ });
72
+ server.httpServer?.once("close", () => {
73
+ started?.close().catch(() => {});
74
+ });
75
+ },
76
+ async closeBundle() {
77
+ await started?.close().catch(() => {});
78
+ started = void 0;
28
79
  }
29
80
  };
30
81
  }
82
+ /**
83
+ * Make `base` safe for `server.middlewares.use(path, …)`. Vite's connect
84
+ * router matches by absolute URL prefix, so relative spellings like
85
+ * `'./'` (commonly used for base-agnostic Nuxt builds) need to be
86
+ * converted to `/` first.
87
+ */
88
+ function normalizeMountBase(base) {
89
+ let out = base.replace(/^\.\/?/, "/");
90
+ if (!out.startsWith("/")) out = `/${out}`;
91
+ if (!out.endsWith("/")) out = `${out}/`;
92
+ return out.replace(/\/+/g, "/");
93
+ }
31
94
  //#endregion
32
95
  export { createVitePlugin };
@@ -0,0 +1,26 @@
1
+ import { createRequire } from "node:module";
2
+ //#region \0rolldown/runtime.js
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports);
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
12
+ key = keys[i];
13
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
14
+ get: ((k) => from[k]).bind(null, key),
15
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
16
+ });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
21
+ value: mod,
22
+ enumerable: true
23
+ }) : target, mod));
24
+ var __require = /* @__PURE__ */ createRequire(import.meta.url);
25
+ //#endregion
26
+ export { __require as n, __toESM as r, __commonJSMin as t };
@@ -1,7 +1,7 @@
1
- import { T as StreamSink, U as DevToolsRpcClientFunctions, W as DevToolsRpcServerFunctions, ct as EventEmitter, g as RpcSharedStateHost, l as ConnectionMeta, w as StreamReader } from "../devtool-CNvLs2_Y.mjs";
2
- import { _ as RpcCacheManager, v as RpcCacheOptions } from "../index-CuLRIMto.mjs";
3
- import { S as RpcFunctionsCollector } from "../types-C5OVe4AC.mjs";
4
- import { t as WsRpcChannelOptions } from "../ws-client-CjPuPFbA.mjs";
1
+ import { M as StreamReader, N as StreamSink, Q as DevToolsRpcServerFunctions, Z as DevToolsRpcClientFunctions, _ as ConnectionMeta, pt as EventEmitter, w as RpcSharedStateHost } from "../devframe-DulcIxwu.mjs";
2
+ import { m as RpcCacheOptions, p as RpcCacheManager } from "../index-DB2Ie0Or.mjs";
3
+ import { S as RpcFunctionsCollector } from "../types-4rdUEi2R.mjs";
4
+ import { t as WsRpcChannelOptions } from "../ws-client-Bavoya6-.mjs";
5
5
  import { BirpcOptions, BirpcReturn } from "birpc";
6
6
 
7
7
  //#region src/client/rpc-streaming.d.ts
@@ -131,4 +131,9 @@ interface DevToolsRpcClientMode {
131
131
  }
132
132
  declare function getDevToolsRpcClient(options?: DevToolsRpcClientOptions): Promise<DevToolsRpcClient>;
133
133
  //#endregion
134
- export { DevToolsClientRpcHost, DevToolsRpcClient, DevToolsRpcClientCall, DevToolsRpcClientCallEvent, DevToolsRpcClientCallOptional, DevToolsRpcClientMode, DevToolsRpcClientOptions, DevToolsRpcContext, RpcClientEvents, RpcStreamingClientHost, StreamingSubscribeOptions, getDevToolsRpcClient as connectDevtool, getDevToolsRpcClient, createRpcStreamingClientHost };
134
+ //#region src/client/index.d.ts
135
+ declare const connectDevframe: typeof getDevToolsRpcClient;
136
+ /** @deprecated Use `connectDevframe`. */
137
+ declare function connectDevtool(...args: Parameters<typeof getDevToolsRpcClient>): ReturnType<typeof getDevToolsRpcClient>;
138
+ //#endregion
139
+ export { DevToolsClientRpcHost, DevToolsRpcClient, DevToolsRpcClientCall, DevToolsRpcClientCallEvent, DevToolsRpcClientCallOptional, DevToolsRpcClientMode, DevToolsRpcClientOptions, DevToolsRpcContext, RpcClientEvents, RpcStreamingClientHost, StreamingSubscribeOptions, connectDevframe, connectDevtool, createRpcStreamingClientHost, getDevToolsRpcClient };