devframe 0.1.18 → 0.1.20

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 (67) hide show
  1. package/README.md +2 -2
  2. package/dist/{_shared-Bxa2_kq7.mjs → _shared-S-Ujqz_L.mjs} +1 -1
  3. package/dist/adapters/build.d.mts +1 -1
  4. package/dist/adapters/build.mjs +9 -5
  5. package/dist/adapters/cli.d.mts +2 -2
  6. package/dist/adapters/cli.mjs +78 -292
  7. package/dist/adapters/dev.d.mts +83 -0
  8. package/dist/adapters/dev.mjs +2 -0
  9. package/dist/adapters/embedded.d.mts +1 -1
  10. package/dist/adapters/kit.d.mts +1 -1
  11. package/dist/adapters/mcp.d.mts +1 -1
  12. package/dist/adapters/mcp.mjs +6 -3
  13. package/dist/adapters/vite.d.mts +1 -1
  14. package/dist/adapters/vite.mjs +1 -1
  15. package/dist/client/index.d.mts +41 -5
  16. package/dist/client/index.mjs +1673 -2
  17. package/dist/constants.d.mts +1 -1
  18. package/dist/{context-xQo1FcxX.mjs → context-BfvbAyGk.mjs} +429 -41
  19. package/dist/dev-B8i_CBlQ.mjs +325 -0
  20. package/dist/{devtool-CHT-4_OU.d.mts → devtool-Bm6zZAw5.d.mts} +371 -28
  21. package/dist/host-h3-BMvrFzIJ.mjs +24 -0
  22. package/dist/{index-Cei8vVcd.d.mts → index-BCo03GEF.d.mts} +1 -1
  23. package/dist/index.d.mts +4 -4
  24. package/dist/index.mjs +11 -2
  25. package/dist/node/index.d.mts +41 -53
  26. package/dist/node/index.mjs +5 -4
  27. package/dist/recipes/open-helpers.d.mts +1 -1
  28. package/dist/recipes/open-helpers.mjs +4 -2
  29. package/dist/rpc/index.d.mts +2 -2
  30. package/dist/rpc/index.mjs +3 -3
  31. package/dist/rpc/transports/ws-client.d.mts +1 -1
  32. package/dist/rpc/transports/ws-client.mjs +1 -1
  33. package/dist/rpc/transports/ws-server.d.mts +1 -1
  34. package/dist/rpc/transports/ws-server.mjs +1 -1
  35. package/dist/{rpc-hbRk8qtt.mjs → rpc-INbWfHoX.mjs} +1 -1
  36. package/dist/{serialization-CWcWE7x7.mjs → serialization-DwKi05Pn.mjs} +1 -1
  37. package/dist/server-DksyT-um.d.mts +54 -0
  38. package/dist/{server-DkJ2-s0Y.mjs → server-qRRM8t3v.mjs} +27 -2
  39. package/dist/{static-dump-DwFfj4U_.mjs → static-dump-C1aVSwxY.mjs} +2 -19
  40. package/dist/types/index.d.mts +4 -4
  41. package/dist/{types-BkyzI9r4.d.mts → types-ag029cAe.d.mts} +1 -1
  42. package/dist/utils/events.d.mts +1 -1
  43. package/dist/utils/shared-state.d.mts +2 -2
  44. package/dist/utils/shared-state.mjs +1 -1
  45. package/dist/utils/state.d.mts +2 -1
  46. package/dist/utils/state.mjs +1 -1
  47. package/dist/utils/streaming-channel.d.mts +2 -0
  48. package/dist/utils/streaming-channel.mjs +255 -0
  49. package/dist/{ws-client-CDGmViwt.d.mts → ws-client-DQySVfF_.d.mts} +1 -1
  50. package/dist/{ws-server-Cu8tmZcF.d.mts → ws-server-VQqESKAs.d.mts} +13 -1
  51. package/package.json +10 -17
  52. package/skills/devframe/README.md +13 -0
  53. package/skills/devframe/SKILL.md +452 -0
  54. package/skills/devframe/templates/counter-devtool.ts +29 -0
  55. package/skills/devframe/templates/spa-devtool.ts +33 -0
  56. package/skills/devframe/templates/vite-client.ts +11 -0
  57. package/dist/client-CsR1_h3o.mjs +0 -1569
  58. package/dist/helpers/nuxt/index.d.mts +0 -46
  59. package/dist/helpers/nuxt/index.mjs +0 -58
  60. package/dist/helpers/nuxt/runtime/plugin.client.d.mts +0 -8
  61. package/dist/helpers/nuxt/runtime/plugin.client.mjs +0 -12
  62. package/dist/immer-DEqg5kOd.mjs +0 -894
  63. package/dist/src-DIKqQIjp.mjs +0 -85
  64. /package/dist/{define-CW9gLnyG.mjs → define-Bb4zh-Dc.mjs} +0 -0
  65. /package/dist/{main-BJD9t8dk.mjs → main-DpINGndA.mjs} +0 -0
  66. /package/dist/{open-BMO2_-wC.mjs → open-BtOOEldu.mjs} +0 -0
  67. /package/dist/{transports-4bqw6Fqg.mjs → transports-BPUzHhI2.mjs} +0 -0
package/README.md CHANGED
@@ -10,7 +10,7 @@ pnpm add devframe
10
10
 
11
11
  ## Docs
12
12
 
13
- See the [DevFrame documentation](https://devtools.vite.dev/devframe/) for the full guide and API reference.
13
+ See the [DevFrame documentation](https://devfra.me/) for the full guide and API reference.
14
14
 
15
15
  ## Agent-Native (experimental)
16
16
 
@@ -55,7 +55,7 @@ devframe mcp
55
55
 
56
56
  `@modelcontextprotocol/sdk` is a peer dependency — add it to your package when you want to ship MCP support.
57
57
 
58
- See the [Agent-Native guide](https://devtools.vite.dev/devframe/agent-native) for the full API, safety model, and Claude Desktop integration example.
58
+ See the [Agent-Native guide](https://devfra.me/agent-native) for the full API, safety model, and Claude Desktop integration example.
59
59
 
60
60
  ## License
61
61
 
@@ -17,4 +17,4 @@ function normalizeBasePath(base) {
17
17
  return out.replace(/\/+/g, "/");
18
18
  }
19
19
  //#endregion
20
- export { resolveBasePath as t };
20
+ export { resolveBasePath as n, normalizeBasePath as t };
@@ -1,4 +1,4 @@
1
- import { r as DevtoolDefinition } from "../devtool-CHT-4_OU.mjs";
1
+ import { r as DevtoolDefinition } from "../devtool-Bm6zZAw5.mjs";
2
2
 
3
3
  //#region src/adapters/build.d.ts
4
4
  interface CreateBuildOptions {
@@ -1,8 +1,9 @@
1
- import { n as strictJsonStringify, o as structuredCloneStringify } from "../serialization-CWcWE7x7.mjs";
2
- import { t as createHostContext } from "../context-xQo1FcxX.mjs";
1
+ import { n as strictJsonStringify, o as structuredCloneStringify } from "../serialization-DwKi05Pn.mjs";
2
+ import { t as createHostContext } from "../context-BfvbAyGk.mjs";
3
3
  import { DEVTOOLS_CONNECTION_META_FILENAME, DEVTOOLS_RPC_DUMP_DIRNAME, DEVTOOLS_RPC_DUMP_MANIFEST_FILENAME } from "../constants.mjs";
4
- import { n as createH3DevToolsHost, t as collectStaticRpcDump } from "../static-dump-DwFfj4U_.mjs";
5
- import { t as resolveBasePath } from "../_shared-Bxa2_kq7.mjs";
4
+ import { t as createH3DevToolsHost } from "../host-h3-BMvrFzIJ.mjs";
5
+ import { t as collectStaticRpcDump } from "../static-dump-C1aVSwxY.mjs";
6
+ import { n as resolveBasePath } from "../_shared-S-Ujqz_L.mjs";
6
7
  import { existsSync } from "node:fs";
7
8
  import { dirname, resolve } from "pathe";
8
9
  import process from "node:process";
@@ -33,7 +34,10 @@ async function createBuild(d, options = {}) {
33
34
  const ctx = await createHostContext({
34
35
  cwd: process.cwd(),
35
36
  mode: "build",
36
- host: createH3DevToolsHost({ origin: "http://localhost" })
37
+ host: createH3DevToolsHost({
38
+ origin: "http://localhost",
39
+ appName: d.id
40
+ })
37
41
  });
38
42
  await d.setup(ctx);
39
43
  await fs$1.mkdir(resolve(outDir, DEVTOOLS_RPC_DUMP_DIRNAME), { recursive: true });
@@ -1,4 +1,4 @@
1
- import { r as DevtoolDefinition } from "../devtool-CHT-4_OU.mjs";
1
+ import { dn as InferCliFlags, fn as defineCliFlags, pn as parseCliFlags, r as DevtoolDefinition, un as CliFlagsSchema } from "../devtool-Bm6zZAw5.mjs";
2
2
  import { App } from "h3";
3
3
  import { CAC } from "cac";
4
4
 
@@ -32,4 +32,4 @@ interface CliHandle {
32
32
  }
33
33
  declare function createCli(d: DevtoolDefinition, options?: CreateCliOptions): CliHandle;
34
34
  //#endregion
35
- export { CliHandle, CreateCliOptions, createCli };
35
+ export { type CliFlagsSchema, CliHandle, CreateCliOptions, type InferCliFlags, createCli, defineCliFlags, parseCliFlags };
@@ -1,232 +1,80 @@
1
- import { a as flagKeyToOption, o as isBooleanFlag, s as parseCliFlags } from "../src-DIKqQIjp.mjs";
2
- import { t as createHostContext } from "../context-xQo1FcxX.mjs";
3
- import { DEVTOOLS_CONNECTION_META_FILENAME } from "../constants.mjs";
4
- import { n as createH3DevToolsHost } from "../static-dump-DwFfj4U_.mjs";
5
- import { t as startHttpAndWs } from "../server-DkJ2-s0Y.mjs";
6
- import { t as resolveBasePath } from "../_shared-Bxa2_kq7.mjs";
7
1
  import { createBuild } from "./build.mjs";
8
- import { resolve } from "pathe";
9
- import process$1 from "node:process";
2
+ import { n as resolveDevServerPort, t as createDevServer } from "../dev-B8i_CBlQ.mjs";
3
+ import process from "node:process";
10
4
  import c from "ansis";
11
- import { networkInterfaces } from "node:os";
12
- import { createApp, eventHandler, fromNodeMiddleware } from "h3";
13
- import { createServer } from "node:net";
14
5
  import cac from "cac";
15
- import sirv from "sirv";
16
- //#region ../../../node_modules/.pnpm/get-port-please@3.2.0/node_modules/get-port-please/dist/index.mjs
17
- const unsafePorts = /* @__PURE__ */ new Set([
18
- 1,
19
- 7,
20
- 9,
21
- 11,
22
- 13,
23
- 15,
24
- 17,
25
- 19,
26
- 20,
27
- 21,
28
- 22,
29
- 23,
30
- 25,
31
- 37,
32
- 42,
33
- 43,
34
- 53,
35
- 69,
36
- 77,
37
- 79,
38
- 87,
39
- 95,
40
- 101,
41
- 102,
42
- 103,
43
- 104,
44
- 109,
45
- 110,
46
- 111,
47
- 113,
48
- 115,
49
- 117,
50
- 119,
51
- 123,
52
- 135,
53
- 137,
54
- 139,
55
- 143,
56
- 161,
57
- 179,
58
- 389,
59
- 427,
60
- 465,
61
- 512,
62
- 513,
63
- 514,
64
- 515,
65
- 526,
66
- 530,
67
- 531,
68
- 532,
69
- 540,
70
- 548,
71
- 554,
72
- 556,
73
- 563,
74
- 587,
75
- 601,
76
- 636,
77
- 989,
78
- 990,
79
- 993,
80
- 995,
81
- 1719,
82
- 1720,
83
- 1723,
84
- 2049,
85
- 3659,
86
- 4045,
87
- 5060,
88
- 5061,
89
- 6e3,
90
- 6566,
91
- 6665,
92
- 6666,
93
- 6667,
94
- 6668,
95
- 6669,
96
- 6697,
97
- 10080
98
- ]);
99
- function isUnsafePort(port) {
100
- return unsafePorts.has(port);
101
- }
102
- function isSafePort(port) {
103
- return !isUnsafePort(port);
104
- }
105
- var GetPortError = class extends Error {
106
- constructor(message, opts) {
107
- super(message, opts);
108
- this.message = message;
109
- }
110
- name = "GetPortError";
111
- };
112
- function _log(verbose, message) {
113
- if (verbose) console.log(`[get-port] ${message}`);
114
- }
115
- function _generateRange(from, to) {
116
- if (to < from) return [];
117
- const r = [];
118
- for (let index = from; index <= to; index++) r.push(index);
119
- return r;
120
- }
121
- function _tryPort(port, host) {
122
- return new Promise((resolve) => {
123
- const server = createServer();
124
- server.unref();
125
- server.on("error", () => {
126
- resolve(false);
127
- });
128
- server.listen({
129
- port,
130
- host
131
- }, () => {
132
- const { port: port2 } = server.address();
133
- server.close(() => {
134
- resolve(isSafePort(port2) && port2);
135
- });
136
- });
137
- });
138
- }
139
- function _getLocalHosts(additional) {
140
- const hosts = new Set(additional);
141
- for (const _interface of Object.values(networkInterfaces())) for (const config of _interface || []) if (config.address && !config.internal && !config.address.startsWith("fe80::") && !config.address.startsWith("169.254")) hosts.add(config.address);
142
- return [...hosts];
143
- }
144
- async function _findPort(ports, host) {
145
- for (const port of ports) {
146
- const r = await _tryPort(port, host);
147
- if (r) return r;
148
- }
149
- }
150
- function _fmtOnHost(hostname) {
151
- return hostname ? `on host ${JSON.stringify(hostname)}` : "on any host";
152
- }
153
- const HOSTNAME_RE = /^(?!-)[\d.:A-Za-z-]{1,63}(?<!-)$/;
154
- function _validateHostname(hostname, _public, verbose) {
155
- if (hostname && !HOSTNAME_RE.test(hostname)) {
156
- const fallbackHost = _public ? "0.0.0.0" : "127.0.0.1";
157
- _log(verbose, `Invalid hostname: ${JSON.stringify(hostname)}. Using ${JSON.stringify(fallbackHost)} as fallback.`);
158
- return fallbackHost;
159
- }
160
- return hostname;
6
+ import { safeParse } from "valibot";
7
+ //#region src/adapters/flags.ts
8
+ /**
9
+ * Identity helper that preserves the literal schema-map type — use this
10
+ * so `InferCliFlags<typeof myFlags>` resolves to the right object shape.
11
+ *
12
+ * ```ts
13
+ * const appFlags = defineCliFlags({
14
+ * depth: v.pipe(v.number(), v.integer()),
15
+ * config: v.optional(v.string()),
16
+ * })
17
+ *
18
+ * defineDevtool({
19
+ * cli: { flags: appFlags },
20
+ * setup(ctx, info) {
21
+ * const flags = info.flags as InferCliFlags<typeof appFlags>
22
+ * flags.depth // number
23
+ * flags.config // string | undefined
24
+ * },
25
+ * })
26
+ * ```
27
+ */
28
+ function defineCliFlags(flags) {
29
+ return flags;
161
30
  }
162
- async function getPort(_userOptions = {}) {
163
- if (typeof _userOptions === "number" || typeof _userOptions === "string") _userOptions = { port: Number.parseInt(_userOptions + "") || 0 };
164
- const _port = Number(_userOptions.port ?? process.env.PORT);
165
- const _userSpecifiedAnyPort = Boolean(_userOptions.port || _userOptions.ports?.length || _userOptions.portRange?.length);
166
- const options = {
167
- random: _port === 0,
168
- ports: [],
169
- portRange: [],
170
- alternativePortRange: _userSpecifiedAnyPort ? [] : [3e3, 3100],
171
- verbose: false,
172
- ..._userOptions,
173
- port: _port,
174
- host: _validateHostname(_userOptions.host ?? process.env.HOST, _userOptions.public, _userOptions.verbose)
175
- };
176
- if (options.random && !_userSpecifiedAnyPort) return getRandomPort(options.host);
177
- const portsToCheck = [
178
- options.port,
179
- ...options.ports,
180
- ..._generateRange(...options.portRange)
181
- ].filter((port) => {
182
- if (!port) return false;
183
- if (!isSafePort(port)) {
184
- _log(options.verbose, `Ignoring unsafe port: ${port}`);
185
- return false;
31
+ /**
32
+ * Best-effort probe of a valibot schema to decide whether the
33
+ * corresponding CAC option takes a value. Unwraps `optional` / `nullable`
34
+ * / `nullish` / `default` / `pipe` wrappers then matches on the inner
35
+ * type's kind.
36
+ */
37
+ function getSchemaKind(schema) {
38
+ let current = schema;
39
+ while (current) {
40
+ const kind = current.type;
41
+ if (kind === "optional" || kind === "nullable" || kind === "nullish" || kind === "undefined") {
42
+ current = current.wrapped ?? current.inner;
43
+ continue;
186
44
  }
187
- return true;
188
- });
189
- if (portsToCheck.length === 0) portsToCheck.push(3e3);
190
- let availablePort = await _findPort(portsToCheck, options.host);
191
- if (!availablePort && options.alternativePortRange.length > 0) {
192
- availablePort = await _findPort(_generateRange(...options.alternativePortRange), options.host);
193
- if (portsToCheck.length > 0) {
194
- let message = `Unable to find an available port (tried ${portsToCheck.join("-")} ${_fmtOnHost(options.host)}).`;
195
- if (availablePort) message += ` Using alternative port ${availablePort}.`;
196
- _log(options.verbose, message);
45
+ if (kind === "pipe" && Array.isArray(current.pipe) && current.pipe.length > 0) {
46
+ current = current.pipe[0];
47
+ continue;
197
48
  }
49
+ return kind;
198
50
  }
199
- if (!availablePort && _userOptions.random !== false) {
200
- availablePort = await getRandomPort(options.host);
201
- if (availablePort) _log(options.verbose, `Using random port ${availablePort}`);
51
+ return "unknown";
52
+ }
53
+ /** Whether the CAC option for this schema should be a boolean flag. */
54
+ function isBooleanFlag(schema) {
55
+ return getSchemaKind(schema) === "boolean";
56
+ }
57
+ /** Validate and coerce the raw cac-parsed bag against a {@link CliFlagsSchema}. */
58
+ function parseCliFlags(schema, raw) {
59
+ const flags = {};
60
+ const issues = [];
61
+ for (const [key, fieldSchema] of Object.entries(schema)) {
62
+ const result = safeParse(fieldSchema, raw[key]);
63
+ if (result.success) flags[key] = result.output;
64
+ else issues.push(`--${toKebab(key)}: ${result.issues.map((i) => i.message).join(", ")}`);
202
65
  }
203
- if (!availablePort) {
204
- const triedRanges = [
205
- options.port,
206
- options.portRange.join("-"),
207
- options.alternativePortRange.join("-")
208
- ].filter(Boolean).join(", ");
209
- throw new GetPortError(`Unable to find an available port ${_fmtOnHost(options.host)} (tried ${triedRanges})`);
210
- }
211
- return availablePort;
66
+ for (const [key, value] of Object.entries(raw)) if (!(key in schema) && !(key in flags)) flags[key] = value;
67
+ return issues.length ? {
68
+ flags,
69
+ issues
70
+ } : { flags };
212
71
  }
213
- async function getRandomPort(host) {
214
- const port = await checkPort(0, host);
215
- if (port === false) throw new GetPortError(`Unable to find a random port ${_fmtOnHost(host)}`);
216
- return port;
72
+ function toKebab(camel) {
73
+ return camel.replaceAll(/([a-z])([A-Z])/g, "$1-$2").toLowerCase();
217
74
  }
218
- async function checkPort(port, host = process.env.HOST, verbose) {
219
- if (!host) host = _getLocalHosts([void 0, "0.0.0.0"]);
220
- if (!Array.isArray(host)) return _tryPort(port, host);
221
- for (const _host of host) {
222
- const _port = await _tryPort(port, _host);
223
- if (_port === false) {
224
- if (port < 1024 && verbose) _log(verbose, `Unable to listen to the privileged port ${port} ${_fmtOnHost(_host)}`);
225
- return false;
226
- }
227
- if (port === 0 && _port !== 0) port = _port;
228
- }
229
- return port;
75
+ /** Kebab-case a schema key for CAC option registration. */
76
+ function flagKeyToOption(camel) {
77
+ return toKebab(camel);
230
78
  }
231
79
  //#endregion
232
80
  //#region src/adapters/cli.ts
@@ -244,17 +92,15 @@ function createCli(d, options = {}) {
244
92
  devCommand.action(async (_args, rawFlags) => {
245
93
  const flags = resolveTypedFlags(d, rawFlags);
246
94
  const host = flags.host ?? defaultHost;
247
- const portOptions = {
248
- port: defaultPort,
249
- host
250
- };
251
- if (d.cli?.portRange) portOptions.portRange = d.cli.portRange;
252
- if (d.cli?.random) portOptions.random = d.cli.random;
253
- await runDevServer(d, {
95
+ await createDevServer(d, {
254
96
  host,
255
- port: flags.port ?? await getPort(portOptions),
256
- flags
257
- }, options);
97
+ port: flags.port ?? await resolveDevServerPort(d, {
98
+ host,
99
+ defaultPort
100
+ }),
101
+ flags,
102
+ onReady: options.onReady
103
+ });
258
104
  });
259
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) => {
260
106
  await createBuild(d, {
@@ -278,7 +124,7 @@ function createCli(d, options = {}) {
278
124
  cli.version("0.0.0");
279
125
  return {
280
126
  cli,
281
- async parse(argv = process$1.argv) {
127
+ async parse(argv = process.argv) {
282
128
  cli.parse(argv, { run: false });
283
129
  await cli.runMatchedCommand();
284
130
  }
@@ -289,69 +135,9 @@ function resolveTypedFlags(d, raw) {
289
135
  const { flags, issues } = parseCliFlags(d.cli.flags, raw);
290
136
  if (issues?.length) {
291
137
  for (const issue of issues) console.error(c.red`[devframe] invalid flag — ${issue}`);
292
- process$1.exit(1);
138
+ process.exit(1);
293
139
  }
294
140
  return flags;
295
141
  }
296
- async function runDevServer(d, serverOptions, cliOptions) {
297
- const distDir = d.cli?.distDir;
298
- if (!distDir) throw new Error(`[devframe] dev: no cli.distDir for "${d.id}". Set \`cli.distDir\` on the definition.`);
299
- const app = createApp();
300
- const origin = `http://${serverOptions.host}:${serverOptions.port}`;
301
- const basePath = resolveBasePath(d, "standalone");
302
- const host = createH3DevToolsHost({
303
- origin,
304
- mount: (base, dir) => {
305
- app.use(base, fromNodeMiddleware(sirv(dir, {
306
- dev: true,
307
- single: true
308
- })));
309
- }
310
- });
311
- const ctx = await createHostContext({
312
- cwd: process$1.cwd(),
313
- mode: "dev",
314
- host
315
- });
316
- const setupInfo = { flags: serverOptions.flags };
317
- await d.setup(ctx, setupInfo);
318
- const connectionMetaPath = `${basePath}${DEVTOOLS_CONNECTION_META_FILENAME}`;
319
- app.use(connectionMetaPath, eventHandler((event) => {
320
- event.node.res.setHeader("Content-Type", "application/json");
321
- return event.node.res.end(JSON.stringify({
322
- backend: "websocket",
323
- websocket: serverOptions.port
324
- }));
325
- }));
326
- app.use(basePath, fromNodeMiddleware(sirv(resolve(distDir), {
327
- dev: true,
328
- single: true
329
- })));
330
- await startHttpAndWs({
331
- context: ctx,
332
- host: serverOptions.host,
333
- port: serverOptions.port,
334
- app,
335
- auth: d.cli?.auth,
336
- onReady: async (info) => {
337
- await cliOptions.onReady?.(info);
338
- await maybeOpenBrowser(d, serverOptions.flags, `${info.origin}${basePath}`);
339
- }
340
- });
341
- }
342
- async function maybeOpenBrowser(d, flags, origin) {
343
- const cliOpen = d.cli?.open;
344
- if (!(flags.open ?? (cliOpen !== void 0 && cliOpen !== false))) return;
345
- const target = typeof flags.open === "string" ? resolveOpenTarget(origin, flags.open) : typeof cliOpen === "string" ? resolveOpenTarget(origin, cliOpen) : origin;
346
- try {
347
- const { default: open } = await import("../open-BMO2_-wC.mjs");
348
- await open(target);
349
- } catch {}
350
- }
351
- function resolveOpenTarget(origin, target) {
352
- if (/^https?:/.test(target)) return target;
353
- if (target.startsWith("/")) return origin.replace(/\/$/, "") + target;
354
- return origin.replace(/\/$/, "") + (target ? `/${target}` : "");
355
- }
356
142
  //#endregion
357
- export { createCli };
143
+ export { createCli, defineCliFlags, parseCliFlags };
@@ -0,0 +1,83 @@
1
+ import { r as DevtoolDefinition } from "../devtool-Bm6zZAw5.mjs";
2
+ import { n as StartedServer } from "../server-DksyT-um.mjs";
3
+ import { App } from "h3";
4
+
5
+ //#region src/adapters/dev.d.ts
6
+ interface CreateDevServerOptions {
7
+ /** Bind host. Default: `def.cli?.host ?? 'localhost'`. */
8
+ host?: string;
9
+ /**
10
+ * Port to listen on. When omitted, falls back to
11
+ * {@link resolveDevServerPort}, which respects `def.cli?.port` /
12
+ * `portRange` / `random`.
13
+ */
14
+ port?: number;
15
+ /**
16
+ * Parsed flag bag forwarded to `setup(ctx, { flags })`. The dev
17
+ * server itself only reads `flags.open` from this bag, and only when
18
+ * {@link CreateDevServerOptions.openBrowser} is left undefined.
19
+ */
20
+ flags?: Record<string, unknown>;
21
+ /**
22
+ * Override `def.cli?.distDir`. Throws when neither is set — the dev
23
+ * server has nothing to mount otherwise.
24
+ */
25
+ distDir?: string;
26
+ /**
27
+ * Override the SPA mount path. Defaults to
28
+ * `resolveBasePath(def, 'standalone')` (i.e. `def.basePath` or `/`).
29
+ */
30
+ basePath?: string;
31
+ /**
32
+ * h3 app to mount the SPA + connection-meta routes on. When omitted
33
+ * a fresh app is created. Pass a pre-configured app to attach custom
34
+ * middleware (auth, logging, extra static assets) before devframe's
35
+ * own handlers.
36
+ */
37
+ app?: App;
38
+ /**
39
+ * Auto-open the browser. When `undefined` the resolution falls
40
+ * through to `flags.open` (incl. string path) and finally
41
+ * `def.cli?.open`. `false` disables the open regardless of the other
42
+ * sources; a string opens that relative path.
43
+ */
44
+ openBrowser?: boolean | string;
45
+ /**
46
+ * Called once the WS server is bound. Devframe stays headless
47
+ * otherwise — wire this if you want a startup banner.
48
+ */
49
+ onReady?: (info: {
50
+ origin: string;
51
+ port: number;
52
+ app: App;
53
+ }) => void | Promise<void>;
54
+ }
55
+ interface ResolveDevServerPortOptions {
56
+ /** Bind host (passed to `get-port-please` for in-use detection). */
57
+ host?: string;
58
+ /** Override the preferred port. Default: `def.cli?.port ?? 9999`. */
59
+ defaultPort?: number;
60
+ }
61
+ /**
62
+ * Resolve the listening port for {@link createDevServer}, honoring the
63
+ * definition's `cli.port` / `cli.portRange` / `cli.random` settings.
64
+ * Exposed separately so authors who run their own argv parsing can
65
+ * resolve a port up-front (to print it, log it, etc.) before starting
66
+ * the server.
67
+ */
68
+ declare function resolveDevServerPort(def: DevtoolDefinition, options?: ResolveDevServerPortOptions): Promise<number>;
69
+ /**
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
+ *
74
+ * Returns the underlying {@link StartedServer} handle so callers can
75
+ * close it gracefully (SIGINT, hot-reload, test teardown).
76
+ *
77
+ * Use this directly when integrating devframe into an existing CLI
78
+ * framework (commander, yargs, hand-rolled CAC). For the all-in-one
79
+ * `dev` / `build` / `mcp` shell, reach for {@link createCli} instead.
80
+ */
81
+ declare function createDevServer(def: DevtoolDefinition, options?: CreateDevServerOptions): Promise<StartedServer>;
82
+ //#endregion
83
+ export { CreateDevServerOptions, ResolveDevServerPortOptions, createDevServer, resolveDevServerPort };
@@ -0,0 +1,2 @@
1
+ import { n as resolveDevServerPort, t as createDevServer } from "../dev-B8i_CBlQ.mjs";
2
+ export { createDevServer, resolveDevServerPort };
@@ -1,4 +1,4 @@
1
- import { d as DevToolsNodeContext, r as DevtoolDefinition } from "../devtool-CHT-4_OU.mjs";
1
+ import { d as DevToolsNodeContext, r as DevtoolDefinition } from "../devtool-Bm6zZAw5.mjs";
2
2
 
3
3
  //#region src/adapters/embedded.d.ts
4
4
  interface CreateEmbeddedOptions {
@@ -1,4 +1,4 @@
1
- import { r as DevtoolDefinition } from "../devtool-CHT-4_OU.mjs";
1
+ import { r as DevtoolDefinition } from "../devtool-Bm6zZAw5.mjs";
2
2
 
3
3
  //#region src/adapters/kit.d.ts
4
4
  interface CreateKitPluginOptions {
@@ -1,4 +1,4 @@
1
- import { r as DevtoolDefinition } from "../devtool-CHT-4_OU.mjs";
1
+ import { r as DevtoolDefinition } from "../devtool-Bm6zZAw5.mjs";
2
2
  import { Server } from "@modelcontextprotocol/sdk/server/index.js";
3
3
 
4
4
  //#region src/node/mcp/build-server.d.ts
@@ -1,5 +1,7 @@
1
- import { m as logger, t as createHostContext } from "../context-xQo1FcxX.mjs";
1
+ import { h as logger, t as createHostContext } from "../context-BfvbAyGk.mjs";
2
+ import { join } from "pathe";
2
3
  import process from "node:process";
4
+ import { homedir } from "node:os";
3
5
  import { Server } from "@modelcontextprotocol/sdk/server/index.js";
4
6
  import { CallToolRequestSchema, ListResourcesRequestSchema, ListToolsRequestSchema, ReadResourceRequestSchema } from "@modelcontextprotocol/sdk/types.js";
5
7
  import { toJsonSchema } from "@valibot/to-json-schema";
@@ -127,7 +129,8 @@ async function createMcpServer(definition, options = {}) {
127
129
  mode: "dev",
128
130
  host: {
129
131
  mountStatic: () => {},
130
- resolveOrigin: () => "mcp://devframe"
132
+ resolveOrigin: () => "mcp://devframe",
133
+ getStorageDir: (scope) => scope === "workspace" ? join(process.cwd(), `node_modules/.${definition.id}/devtools`) : join(homedir(), `.${definition.id}/devtools`)
131
134
  }
132
135
  });
133
136
  await definition.setup(ctx);
@@ -136,7 +139,7 @@ async function createMcpServer(definition, options = {}) {
136
139
  serverVersion: options.serverVersion ?? definition.version ?? "0.0.0",
137
140
  exposeSharedState: options.exposeSharedState ?? true
138
141
  });
139
- const { startStdioTransport } = await import("../transports-4bqw6Fqg.mjs");
142
+ const { startStdioTransport } = await import("../transports-BPUzHhI2.mjs");
140
143
  let stop;
141
144
  try {
142
145
  stop = await startStdioTransport(server);
@@ -1,4 +1,4 @@
1
- import { r as DevtoolDefinition } from "../devtool-CHT-4_OU.mjs";
1
+ import { r as DevtoolDefinition } from "../devtool-Bm6zZAw5.mjs";
2
2
 
3
3
  //#region src/adapters/vite.d.ts
4
4
  interface CreateVitePluginOptions {
@@ -1,4 +1,4 @@
1
- import { t as resolveBasePath } from "../_shared-Bxa2_kq7.mjs";
1
+ import { n as resolveBasePath } from "../_shared-S-Ujqz_L.mjs";
2
2
  import { resolve } from "pathe";
3
3
  import sirv from "sirv";
4
4
  //#region src/adapters/vite.ts