devframe 0.7.16 → 0.8.1

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 (80) hide show
  1. package/bin/devframe.mjs +8 -0
  2. package/dist/adapters/build.d.mts +1 -1
  3. package/dist/adapters/build.mjs +4 -4
  4. package/dist/adapters/cac.d.mts +1 -1
  5. package/dist/adapters/cac.mjs +1 -1
  6. package/dist/adapters/cli.d.mts +1 -1
  7. package/dist/adapters/cli.mjs +1 -1
  8. package/dist/adapters/dev.d.mts +2 -2
  9. package/dist/adapters/dev.mjs +1 -1
  10. package/dist/adapters/embedded.d.mts +1 -1
  11. package/dist/adapters/mcp.d.mts +51 -3
  12. package/dist/adapters/mcp.mjs +2 -2
  13. package/dist/agent-tool-name-C3b5vEwJ.mjs +34 -0
  14. package/dist/{cac-CPaOy3LD.mjs → cac-B1LM3zit.mjs} +18 -13
  15. package/dist/cli/main.d.mts +11 -0
  16. package/dist/cli/main.mjs +284 -0
  17. package/dist/client/index.d.mts +40 -11
  18. package/dist/client/index.mjs +129 -19
  19. package/dist/constants.d.mts +13 -6
  20. package/dist/constants.mjs +13 -6
  21. package/dist/{context-DY72brRI.mjs → context-CQefP2jR.mjs} +3 -2
  22. package/dist/{context-CzqPrJSz.d.mts → context-DFzmxCLa.d.mts} +1 -1
  23. package/dist/{revoke-BtQDKTp7.mjs → crypto-token-XCqTSMg9.mjs} +1 -35
  24. package/dist/{dev-BCeaQuGE.mjs → dev-BSHFZGZr.mjs} +22 -11
  25. package/dist/{devframe-Ckhf3kFw.d.mts → devframe-qgCKL683.d.mts} +77 -15
  26. package/dist/diagnostics-B5-qHeqD.mjs +94 -0
  27. package/dist/{diagnostics-BXwBQmoN.mjs → diagnostics-hwjXp_UV.mjs} +8 -0
  28. package/dist/{dump-Cz7yVvsB.mjs → dump-CgZShDRB.mjs} +82 -6
  29. package/dist/fetch-CK0S253E.mjs +534 -0
  30. package/dist/helpers/vite.d.mts +15 -14
  31. package/dist/helpers/vite.mjs +8 -8
  32. package/dist/{host-h3-CgOetlNE.mjs → host-h3-Kz7t5Xab.mjs} +83 -28
  33. package/dist/http-Dvgxujcu.mjs +38 -0
  34. package/dist/{index-8dndvIxR.d.mts → index-B7RgLw--.d.mts} +11 -6
  35. package/dist/{index-DgsLFhZg.d.mts → index-Dbw1p5ch.d.mts} +27 -3
  36. package/dist/{index-YDSJgsyG.d.mts → index-vAX6bYuc.d.mts} +1 -1
  37. package/dist/index.d.mts +5 -5
  38. package/dist/instance-registry-D6fxYu36.mjs +190 -0
  39. package/dist/node/auth.d.mts +2 -2
  40. package/dist/node/auth.mjs +2 -2
  41. package/dist/node/hub-internals.d.mts +2 -2
  42. package/dist/node/hub-internals.mjs +1 -1
  43. package/dist/node/index.d.mts +124 -6
  44. package/dist/node/index.mjs +5 -4
  45. package/dist/recipes/common-rpc-functions.d.mts +33 -33
  46. package/dist/recipes/common-rpc-functions.mjs +6 -6
  47. package/dist/recipes/interactive-auth.d.mts +2 -2
  48. package/dist/recipes/interactive-auth.mjs +23 -15
  49. package/dist/revoke-DZbJ7Cl0.mjs +35 -0
  50. package/dist/rpc/dump.d.mts +1 -1
  51. package/dist/rpc/dump.mjs +1 -1
  52. package/dist/rpc/index.d.mts +3 -3
  53. package/dist/rpc/index.mjs +4 -4
  54. package/dist/rpc/transports/ws-client.d.mts +1 -1
  55. package/dist/rpc/transports/ws-client.mjs +1 -1
  56. package/dist/rpc/transports/ws-server.d.mts +2 -2
  57. package/dist/rpc/transports/ws-server.mjs +50 -3
  58. package/dist/{serialization-DpLXCy13.mjs → serialization-C8Mnw9hK.mjs} +1 -1
  59. package/dist/{server-DykHCza_.mjs → server-CXaDDUl0.mjs} +2 -2
  60. package/dist/{server-B0wiP_Oi.d.mts → server-E9z4ZWbd.d.mts} +4 -3
  61. package/dist/simple-schema-BDzLeJDk.d.mts +102 -0
  62. package/dist/simple-schema-DQPZrAaZ.mjs +154 -0
  63. package/dist/{state-WX3HT5a3.mjs → state-BeUHDDjk.mjs} +13 -6
  64. package/dist/{storage-gEnj9ASQ.mjs → storage-Dzoc3NVC.mjs} +2 -66
  65. package/dist/{transports-BmDVn4SF.mjs → transports-vhizgqXM.mjs} +1 -1
  66. package/dist/types/index.d.mts +4 -4
  67. package/dist/{types-CrzNxXKq.d.mts → types-CnJSgRVa.d.mts} +33 -19
  68. package/dist/utils/agent-tool-name.d.mts +27 -0
  69. package/dist/utils/agent-tool-name.mjs +34 -0
  70. package/dist/utils/events.d.mts +1 -1
  71. package/dist/utils/shared-state.d.mts +1 -1
  72. package/dist/utils/simple-schema.d.mts +2 -0
  73. package/dist/utils/simple-schema.mjs +154 -0
  74. package/dist/utils/streaming-channel.d.mts +1 -1
  75. package/dist/{ws-client-DSXiI2h7.d.mts → ws-client-B6Tnr0ic.d.mts} +1 -1
  76. package/dist/{ws-server-9-wn7MNQ.d.mts → ws-server-J-zkiOyp.d.mts} +24 -3
  77. package/package.json +18 -7
  78. package/skills/devframe/SKILL.md +4 -3
  79. package/dist/build-server-C7vTKjiQ.mjs +0 -359
  80. package/dist/http-_pPbryTQ.mjs +0 -114
@@ -1,5 +1,6 @@
1
- import { $ as DevframeRpcServerFunctions, Q as DevframeRpcClientFunctions, W as DevframeNodeRpcSession, _ as ConnectionMeta, b as DevframeNodeContext, p as DevframeAuthHandler } from "./devframe-Ckhf3kFw.mjs";
2
- import "./index-8dndvIxR.mjs";
1
+ import { $ as DevframeRpcServerFunctions, Q as DevframeRpcClientFunctions, W as DevframeNodeRpcSession, _ as ConnectionMeta, b as DevframeNodeContext, p as DevframeAuthHandler } from "./devframe-qgCKL683.mjs";
2
+ import { r as WsOriginRegistry } from "./ws-server-J-zkiOyp.mjs";
3
+ import "./index-B7RgLw--.mjs";
3
4
  import { Peer } from "crossws";
4
5
  import { BirpcGroup, EventOptions } from "birpc";
5
6
  import { NodeAdapter } from "crossws/adapters/node";
@@ -91,7 +92,7 @@ interface StartHttpAndWsOptions {
91
92
  * from another host. Pass `false` to disable origin checking entirely
92
93
  * (not recommended). Default: loopback-only.
93
94
  */
94
- allowedOrigins?: readonly string[] | false;
95
+ allowedOrigins?: readonly string[] | WsOriginRegistry | false;
95
96
  /**
96
97
  * Called once the WS server is bound so callers can mount static
97
98
  * handlers whose origin depends on the resolved port, or print their
@@ -0,0 +1,102 @@
1
+ import { StandardSchemaV1 } from "@standard-schema/spec";
2
+ //#region src/utils/simple-schema.d.ts
3
+ /**
4
+ * A tiny, zero-dependency [Standard Schema](https://standardschema.dev/)
5
+ * builder.
6
+ *
7
+ * ⚠️ **Discouraged for app code.** This is a deliberately minimal,
8
+ * best-effort validator that exists only so devframe's own first-party
9
+ * packages (recipes, built-in plugins) can declare `args`/`returns`/flag
10
+ * schemas without taking on a validator dependency. It implements a small
11
+ * subset of primitives and approximates refinements — it is not a
12
+ * general-purpose validator.
13
+ *
14
+ * For your own code, prefer a real Standard Schema validator — **valibot**,
15
+ * **zod**, or **arktype**. Devframe's RPC and CLI-flag layers accept any of
16
+ * them; install the one you like and use it directly:
17
+ *
18
+ * ```ts
19
+ * import * as v from 'valibot' // npm i valibot
20
+ *
21
+ * defineRpcFunction({
22
+ * name: 'greet',
23
+ * args: [v.object({ name: v.string() })],
24
+ * returns: v.string(),
25
+ * handler: ({ name }) => `hi ${name}`,
26
+ * })
27
+ * ```
28
+ */
29
+ /**
30
+ * A Standard Schema produced by the {@link s} builder. It carries a
31
+ * duck-typed `type` marker (and `wrapped` for wrappers) alongside the
32
+ * standard `~standard` prop so the CLI-flags adapter can introspect the
33
+ * schema kind without importing any validator.
34
+ */
35
+ interface SimpleSchema<Input, Output = Input> extends StandardSchemaV1<Input, Output> {
36
+ /** Schema kind marker, e.g. `'string'`, `'boolean'`, `'optional'`. */
37
+ readonly type: string;
38
+ /** Inner schema for wrapper kinds (`optional` / `nullable`). */
39
+ readonly wrapped?: StandardSchemaV1;
40
+ /** Optional human description (surfaced as CLI option help). */
41
+ readonly description?: string;
42
+ }
43
+ /** Any string. */
44
+ declare function string(): SimpleSchema<string>;
45
+ /** A finite number (rejects `NaN`). */
46
+ declare function number(): SimpleSchema<number>;
47
+ /** A boolean. */
48
+ declare function boolean(): SimpleSchema<boolean>;
49
+ /** `undefined` — mirrors valibot's `void`. */
50
+ declare function voidType(): SimpleSchema<void>;
51
+ /** `null`. */
52
+ declare function nullType(): SimpleSchema<null>;
53
+ /** One of a fixed set of literal values. */
54
+ declare function picklist<const T extends readonly (string | number | boolean)[]>(values: T): SimpleSchema<T[number]>;
55
+ /** A single literal value (string / number / boolean). */
56
+ declare function literal<const T extends string | number | boolean>(value: T): SimpleSchema<T>;
57
+ /** A value matching any one of the given schemas. */
58
+ declare function union<const T extends readonly StandardSchemaV1[]>(options: T): SimpleSchema<StandardSchemaV1.InferInput<T[number]>, StandardSchemaV1.InferOutput<T[number]>>;
59
+ /** A record with string keys whose values each satisfy the value schema. */
60
+ declare function record<V extends StandardSchemaV1>(_key: StandardSchemaV1, value: V): SimpleSchema<Record<string, StandardSchemaV1.InferInput<V>>, Record<string, StandardSchemaV1.InferOutput<V>>>;
61
+ /** An array whose every element satisfies the item schema. */
62
+ declare function array<T extends StandardSchemaV1>(item: T): SimpleSchema<StandardSchemaV1.InferInput<T>[], StandardSchemaV1.InferOutput<T>[]>;
63
+ /** Flatten an intersection into a single object literal for readable types. */
64
+ type Prettify<T> = { [K in keyof T]: T[K]; } & {};
65
+ /**
66
+ * Map a shape to its object type, turning fields whose type includes
67
+ * `undefined` (i.e. `optional()`) into optional keys — mirroring how
68
+ * valibot/zod render `optional` object entries.
69
+ */
70
+ type InferField<T extends StandardSchemaV1, Mode extends 'input' | 'output'> = Mode extends 'input' ? StandardSchemaV1.InferInput<T> : StandardSchemaV1.InferOutput<T>;
71
+ type InferObject<T extends Record<string, StandardSchemaV1>, Mode extends 'input' | 'output'> = Prettify<{ [K in keyof T as undefined extends InferField<T[K], Mode> ? never : K]: InferField<T[K], Mode>; } & { [K in keyof T as undefined extends InferField<T[K], Mode> ? K : never]?: InferField<T[K], Mode>; }>;
72
+ /** An object whose known keys each satisfy their schema (extra keys are kept). */
73
+ declare function object<T extends Record<string, StandardSchemaV1>>(shape: T): SimpleSchema<InferObject<T, 'input'>, InferObject<T, 'output'>>;
74
+ /** Allow `undefined` in addition to the inner schema. */
75
+ declare function optional<T extends StandardSchemaV1>(inner: T): SimpleSchema<StandardSchemaV1.InferInput<T> | undefined, StandardSchemaV1.InferOutput<T> | undefined>;
76
+ /** Allow `null` in addition to the inner schema. */
77
+ declare function nullable<T extends StandardSchemaV1>(inner: T): SimpleSchema<StandardSchemaV1.InferInput<T> | null, StandardSchemaV1.InferOutput<T> | null>;
78
+ /** Attach a human-readable description (used for CLI option help). */
79
+ declare function describe<T extends SimpleSchema<any, any>>(schema: T, description: string): T;
80
+ /**
81
+ * Grouped access to every builder — `s.string()`, `s.object({ ... })`,
82
+ * `s.void()`, etc. Handy for a valibot-like `import { s } from
83
+ * 'devframe/utils/simple-schema'` call site.
84
+ */
85
+ declare const s: {
86
+ readonly string: typeof string;
87
+ readonly number: typeof number;
88
+ readonly boolean: typeof boolean;
89
+ readonly void: typeof voidType;
90
+ readonly null: typeof nullType;
91
+ readonly literal: typeof literal;
92
+ readonly picklist: typeof picklist;
93
+ readonly union: typeof union;
94
+ readonly record: typeof record;
95
+ readonly array: typeof array;
96
+ readonly object: typeof object;
97
+ readonly optional: typeof optional;
98
+ readonly nullable: typeof nullable;
99
+ readonly describe: typeof describe;
100
+ };
101
+ //#endregion
102
+ export { literal as a, number as c, picklist as d, record as f, voidType as g, union as h, describe as i, object as l, string as m, array as n, nullType as o, s as p, boolean as r, nullable as s, SimpleSchema as t, optional as u };
@@ -0,0 +1,154 @@
1
+ //#region src/utils/simple-schema.ts
2
+ function ok(value) {
3
+ return { value };
4
+ }
5
+ function fail(message, path) {
6
+ return { issues: [path ? {
7
+ message,
8
+ path
9
+ } : { message }] };
10
+ }
11
+ function make(type, validate, extra) {
12
+ return {
13
+ type,
14
+ ...extra,
15
+ "~standard": {
16
+ version: 1,
17
+ vendor: "devframe",
18
+ validate
19
+ }
20
+ };
21
+ }
22
+ /** Run a Standard Schema synchronously, rejecting async validators. */
23
+ function runSync(schema, value) {
24
+ const result = schema["~standard"].validate(value);
25
+ if (result instanceof Promise) throw new TypeError("[devframe/utils/simple-schema] async validators are not supported inside object()/optional()/nullable()");
26
+ return result;
27
+ }
28
+ /** Any string. */
29
+ function string() {
30
+ return make("string", (v) => typeof v === "string" ? ok(v) : fail("Expected a string"));
31
+ }
32
+ /** A finite number (rejects `NaN`). */
33
+ function number() {
34
+ return make("number", (v) => typeof v === "number" && !Number.isNaN(v) ? ok(v) : fail("Expected a number"));
35
+ }
36
+ /** A boolean. */
37
+ function boolean() {
38
+ return make("boolean", (v) => typeof v === "boolean" ? ok(v) : fail("Expected a boolean"));
39
+ }
40
+ /** `undefined` — mirrors valibot's `void`. */
41
+ function voidType() {
42
+ return make("void", (v) => v === void 0 ? ok(void 0) : fail("Expected undefined"));
43
+ }
44
+ /** `null`. */
45
+ function nullType() {
46
+ return make("null", (v) => v === null ? ok(null) : fail("Expected null"));
47
+ }
48
+ /** One of a fixed set of literal values. */
49
+ function picklist(values) {
50
+ const set = new Set(values);
51
+ return make("picklist", (v) => set.has(v) ? ok(v) : fail(`Expected one of: ${values.join(", ")}`), { values });
52
+ }
53
+ /** A single literal value (string / number / boolean). */
54
+ function literal(value) {
55
+ return make("literal", (v) => v === value ? ok(v) : fail(`Expected ${JSON.stringify(value)}`), { value });
56
+ }
57
+ /** A value matching any one of the given schemas. */
58
+ function union(options) {
59
+ return make("union", (v) => {
60
+ const issues = [];
61
+ for (const option of options) {
62
+ const result = runSync(option, v);
63
+ if (!result.issues) return ok(v);
64
+ issues.push(...result.issues);
65
+ }
66
+ return { issues };
67
+ }, { options });
68
+ }
69
+ /** A record with string keys whose values each satisfy the value schema. */
70
+ function record(_key, value) {
71
+ return make("record", (v) => {
72
+ if (typeof v !== "object" || v === null || Array.isArray(v)) return fail("Expected an object");
73
+ const obj = v;
74
+ const issues = [];
75
+ for (const key of Object.keys(obj)) {
76
+ const result = runSync(value, obj[key]);
77
+ if (result.issues) for (const issue of result.issues) issues.push({
78
+ message: issue.message,
79
+ path: [key, ...issue.path ?? []]
80
+ });
81
+ }
82
+ return issues.length ? { issues } : ok(v);
83
+ });
84
+ }
85
+ /** An array whose every element satisfies the item schema. */
86
+ function array(item) {
87
+ return make("array", (v) => {
88
+ if (!Array.isArray(v)) return fail("Expected an array");
89
+ const issues = [];
90
+ for (let i = 0; i < v.length; i++) {
91
+ const result = runSync(item, v[i]);
92
+ if (result.issues) for (const issue of result.issues) issues.push({
93
+ message: issue.message,
94
+ path: [i, ...issue.path ?? []]
95
+ });
96
+ }
97
+ return issues.length ? { issues } : ok(v);
98
+ });
99
+ }
100
+ /** An object whose known keys each satisfy their schema (extra keys are kept). */
101
+ function object(shape) {
102
+ const entries = Object.entries(shape);
103
+ return make("object", (v) => {
104
+ if (typeof v !== "object" || v === null || Array.isArray(v)) return fail("Expected an object");
105
+ const obj = v;
106
+ const issues = [];
107
+ for (const [key, schema] of entries) {
108
+ const result = runSync(schema, obj[key]);
109
+ if (result.issues) for (const issue of result.issues) issues.push({
110
+ message: issue.message,
111
+ path: [key, ...issue.path ?? []]
112
+ });
113
+ }
114
+ return issues.length ? { issues } : ok(v);
115
+ });
116
+ }
117
+ /** Allow `undefined` in addition to the inner schema. */
118
+ function optional(inner) {
119
+ return make("optional", (v) => v === void 0 ? ok(void 0) : runSync(inner, v), { wrapped: inner });
120
+ }
121
+ /** Allow `null` in addition to the inner schema. */
122
+ function nullable(inner) {
123
+ return make("nullable", (v) => v === null ? ok(null) : runSync(inner, v), { wrapped: inner });
124
+ }
125
+ /** Attach a human-readable description (used for CLI option help). */
126
+ function describe(schema, description) {
127
+ return {
128
+ ...schema,
129
+ description
130
+ };
131
+ }
132
+ /**
133
+ * Grouped access to every builder — `s.string()`, `s.object({ ... })`,
134
+ * `s.void()`, etc. Handy for a valibot-like `import { s } from
135
+ * 'devframe/utils/simple-schema'` call site.
136
+ */
137
+ const s = {
138
+ string,
139
+ number,
140
+ boolean,
141
+ void: voidType,
142
+ null: nullType,
143
+ literal,
144
+ picklist,
145
+ union,
146
+ record,
147
+ array,
148
+ object,
149
+ optional,
150
+ nullable,
151
+ describe
152
+ };
153
+ //#endregion
154
+ export { s as t };
@@ -1,5 +1,5 @@
1
1
  import { DEVFRAME_OTP_URL_PARAM } from "./constants.mjs";
2
- import { a as timingSafeEqual, i as randomToken, r as randomDigits } from "./revoke-BtQDKTp7.mjs";
2
+ import { n as randomToken, r as timingSafeEqual, t as randomDigits } from "./crypto-token-XCqTSMg9.mjs";
3
3
  //#region src/node/auth/state.ts
4
4
  /** Number of decimal digits in a human-typed one-time authentication code. */
5
5
  const TEMP_AUTH_CODE_LENGTH = 6;
@@ -37,14 +37,21 @@ function refreshTempAuthCode() {
37
37
  return tempAuthCode;
38
38
  }
39
39
  /**
40
- * Build a "magic link" authentication URL that embeds a one-time code (OTP) as
41
- * a query parameter. Opening it authenticates the client without typing — print
42
- * it on startup (devframe stays headless, so the host prints its own banner).
43
- * Defaults to the current code; the link is subject to the same TTL.
40
+ * Build a "magic link" authentication URL that embeds a one-time code (OTP) in
41
+ * the URL **fragment**. Opening it authenticates the client without typing —
42
+ * print it on startup (devframe stays headless, so the host prints its own
43
+ * banner). Defaults to the current code; the link is subject to the same TTL.
44
+ *
45
+ * The code rides the fragment (`#devframe_otp=…`), not the query string, so it
46
+ * is never sent to the server, written to an access log, or leaked in a
47
+ * `Referer` header — the browser client reads it locally (see
48
+ * `consumeOtpFromUrl`). Any existing fragment parameters are preserved.
44
49
  */
45
50
  function buildOtpAuthUrl(baseUrl, code = tempAuthCode) {
46
51
  const url = new URL(baseUrl);
47
- url.searchParams.set(DEVFRAME_OTP_URL_PARAM, code);
52
+ const fragment = new URLSearchParams(url.hash.replace(/^#/, ""));
53
+ fragment.set(DEVFRAME_OTP_URL_PARAM, code);
54
+ url.hash = fragment.toString();
48
55
  return url.href;
49
56
  }
50
57
  /**
@@ -1,72 +1,8 @@
1
- import { t as devframeReporter } from "./diagnostics-reporter-CsIG85Q5.mjs";
2
- import { defineDiagnostics } from "nostics";
1
+ import { t as diagnostics } from "./diagnostics-B5-qHeqD.mjs";
3
2
  import fs from "node:fs";
4
3
  import { dirname } from "pathe";
5
4
  import process$1 from "node:process";
6
5
  import { destr } from "destr";
7
- //#region src/node/diagnostics.ts
8
- const diagnostics = defineDiagnostics({
9
- docsBase: "https://devfra.me/errors",
10
- reporters: [devframeReporter],
11
- codes: {
12
- DF0006: { why: (p) => `RPC function "${p.name}" is not registered` },
13
- DF0007: { why: "AsyncLocalStorage is not set, it likely to be an internal bug of the Devframe foundation" },
14
- DF0008: { why: (p) => `distDir ${p.distDir} does not exist` },
15
- DF0012: { why: (p) => `Failed to parse storage file: ${p.filepath}, falling back to defaults.` },
16
- DF0013: { why: (p) => `Shared state of "${p.key}" is not found, please provide an initial value for the first time` },
17
- DF0014: {
18
- why: (p) => `RPC function "${p.name}" has an invalid \`agent\` field — \`description\` must be a non-empty string.`,
19
- fix: "Provide a short description (~1–3 sentences) explaining what the tool does and when agents should invoke it."
20
- },
21
- DF0015: {
22
- why: (p) => `Agent tool "${p.id}" is already registered.`,
23
- fix: "Tool ids must be unique across RPC functions with an `agent` field and tools registered via `ctx.agent.registerTool()`."
24
- },
25
- DF0016: { why: (p) => `Agent resource "${p.id}" is already registered.` },
26
- DF0017: { why: (p) => `Failed to start MCP server (${p.transport}): ${p.reason}` },
27
- DF0029: {
28
- why: (p) => `Stream "${p.channel}#${p.id}" dropped ${p.dropped} chunk(s) after exceeding the client high-water mark.`,
29
- fix: "The consumer is too slow for the producer. Raise `highWaterMark` on the subscription, slow the producer, or batch chunks."
30
- },
31
- DF0030: {
32
- why: (p) => `Stream "${p.channel}#${p.id}" is unknown — no producer has called \`channel.start({ id: "${p.id}" })\`.`,
33
- fix: "Ensure the server-side producer is running before clients subscribe, or check for typos in the stream id."
34
- },
35
- DF0031: {
36
- why: (p) => `Cannot write to closed stream "${p.channel}#${p.id}".`,
37
- fix: "Track the producer lifecycle — guard writes with the `stream.signal.aborted` flag."
38
- },
39
- DF0032: {
40
- why: (p) => `Streaming channel "${p.channel}" is already registered.`,
41
- fix: "Each channel name must be unique within a context. Pick a different name or reuse the existing channel handle."
42
- },
43
- DF0033: {
44
- why: (p) => `Failed to start dev RPC bridge for "${p.id}": ${p.reason}`,
45
- fix: "Verify the bridge port is free and the devframe setup function does not throw. Pin a port via `cli.port` / `cli.portRange` on the definition, or via `devMiddleware.port` on `viteDevBridge`."
46
- },
47
- DF0034: {
48
- why: (p) => `Scoped RPC registration for namespace "${p.namespace}" received an already-namespaced function name "${p.name}".`,
49
- fix: "A scoped context auto-namespaces ids. Pass a bare name without a \":\" separator (e.g. `register({ name: \"get-cwd\" })`), or use the unscoped `ctx.base.rpc.register` for a fully-qualified name."
50
- },
51
- DF0035: {
52
- why: (p) => `Failed to persist storage file: ${p.filepath}`,
53
- fix: "Check that the storage directory is writable and has free space."
54
- },
55
- DF0036: {
56
- why: (p) => `RPC call to "${p.name}" was rejected: the caller is not authorized.`,
57
- fix: "Complete the auth handshake (or connect with a static/pre-shared token) before calling a trusted method. Untrusted callers may only call `anonymous:`-prefixed methods — see `isAnonymousRpcMethod`."
58
- },
59
- DF0037: {
60
- why: (p) => `A service is already provided under "${p.id}".`,
61
- fix: "Service ids are unique per context. Revoke the existing provider first (the `provide()` call returns a revoke function), or namespace the id with your plugin id to avoid collisions."
62
- },
63
- DF0042: {
64
- why: (p) => `"${p.id}" declares \`capabilities.build: false\` — its static export is not meaningful (writes are excluded and any live-served data won't be there).`,
65
- fix: "Pass `{ force: true }` to `createBuild()` if the degraded export is still useful to you, or drop `capabilities.build: false` on the definition."
66
- }
67
- }
68
- });
69
- //#endregion
70
6
  //#region src/utils/events.ts
71
7
  /**
72
8
  * Create event emitter.
@@ -1183,4 +1119,4 @@ function createStorage(options) {
1183
1119
  return state;
1184
1120
  }
1185
1121
  //#endregion
1186
- export { diagnostics as a, createEventEmitter as i, createSharedState as n, nanoid as r, createStorage as t };
1122
+ export { createEventEmitter as i, createSharedState as n, nanoid as r, createStorage as t };
@@ -1,4 +1,4 @@
1
- import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
1
+ import { StdioServerTransport } from "@modelcontextprotocol/server/stdio";
2
2
  //#region src/adapters/mcp/transports.ts
3
3
  /**
4
4
  * Start the MCP server on stdio. Returns a stop function.
@@ -1,4 +1,4 @@
1
- import { $ as DevframeRpcServerFunctions, A as DevframeSettingsStore, At as EventUnsubscribe, B as DevframeDefineDiagnosticsOptions, C as DevframeServicesHost, Ct as AgentResourceContent, D as DevframeScopedStreamingHost, Dt as DevframeAgentHost, E as DevframeScopedNodeRpc, Et as AgentToolInput, F as ScopedSharedStates, G as RpcBroadcastOptions, H as DevframeDiagnosticsHost, I as SettingsForNamespace, J as RpcSharedStateHost, K as RpcFunctionsHost, L as DevframeViewHost, M as ScopedClientFunctions, N as ScopedRpcFn, O as DevframeSettings, Ot as DevframeAgentHostEvents, P as ScopedServerFunctions, Q as DevframeRpcClientFunctions, R as DevframeHost, S as DevframeServiceOf, St as AgentResource, T as DevframeScopedNodeContext, Tt as AgentTool, U as DevframeDiagnosticsLogger, V as DevframeDiagnosticsDefinition, W as DevframeNodeRpcSession, X as RpcStreamingChannelOptions, Y as RpcStreamingChannel, Z as RpcStreamingHost, _ as ConnectionMeta, a as DevframeDockDefaults, b as DevframeNodeContext, bt as AgentHandle, c as DevframeSetupInfo, d as McpRouteOptions, et as DevframeRpcSharedStates, f as defineDevframe, g as Thenable, h as PartialWithoutId, i as DevframeDeploymentKind, j as ScopedBroadcastOptions, jt as EventsMap, k as DevframeSettingsRegistry, kt as EventEmitter, l as DevframeSpaOptions, m as EntriesToObject, n as DevframeCliOptions, o as DevframeDuplicationStrategy, q as RpcSharedStateGetOptions, r as DevframeDefinition, s as DevframeRuntime, t as DevframeBrowserContext, u as DevframeWsOptions, v as ConnectionMetaWebsocket, w as DevframeServicesRegistry, wt as AgentResourceInput, x as DevframeServiceId, xt as AgentManifest, y as DevframeCapabilities, z as DevframeStorageScope } from "../devframe-Ckhf3kFw.mjs";
2
- import { g as RpcFunctionAgentOptions } from "../types-CrzNxXKq.mjs";
3
- import { t as DevframeNodeRpcSessionMeta } from "../ws-server-9-wn7MNQ.mjs";
4
- export { AgentHandle, AgentManifest, AgentResource, AgentResourceContent, AgentResourceInput, AgentTool, AgentToolInput, ConnectionMeta, ConnectionMetaWebsocket, DevframeAgentHost, DevframeAgentHostEvents, DevframeBrowserContext, DevframeCapabilities, DevframeCliOptions, DevframeDefineDiagnosticsOptions, DevframeDefinition, DevframeDeploymentKind, DevframeDiagnosticsDefinition, DevframeDiagnosticsHost, DevframeDiagnosticsLogger, DevframeDockDefaults, DevframeDuplicationStrategy, DevframeHost, DevframeNodeContext, DevframeNodeRpcSession, type DevframeNodeRpcSessionMeta, DevframeRpcClientFunctions, DevframeRpcServerFunctions, DevframeRpcSharedStates, DevframeRuntime, DevframeScopedNodeContext, DevframeScopedNodeRpc, DevframeScopedStreamingHost, DevframeServiceId, DevframeServiceOf, DevframeServicesHost, DevframeServicesRegistry, DevframeSettings, DevframeSettingsRegistry, DevframeSettingsStore, DevframeSetupInfo, DevframeSpaOptions, DevframeStorageScope, DevframeViewHost, DevframeWsOptions, EntriesToObject, EventEmitter, EventUnsubscribe, EventsMap, McpRouteOptions, PartialWithoutId, RpcBroadcastOptions, type RpcFunctionAgentOptions, RpcFunctionsHost, RpcSharedStateGetOptions, RpcSharedStateHost, RpcStreamingChannel, RpcStreamingChannelOptions, RpcStreamingHost, ScopedBroadcastOptions, ScopedClientFunctions, ScopedRpcFn, ScopedServerFunctions, ScopedSharedStates, SettingsForNamespace, Thenable, defineDevframe };
1
+ import { $ as DevframeRpcServerFunctions, A as DevframeSettingsStore, At as DevframeAgentHostEvents, B as DevframeDefineDiagnosticsOptions, C as DevframeServicesHost, Ct as AgentResourceContent, D as DevframeScopedStreamingHost, Dt as AgentToolProvider, E as DevframeScopedNodeRpc, Et as AgentToolInput, F as ScopedSharedStates, G as RpcBroadcastOptions, H as DevframeDiagnosticsHost, I as SettingsForNamespace, J as RpcSharedStateHost, K as RpcFunctionsHost, L as DevframeViewHost, M as ScopedClientFunctions, Mt as EventUnsubscribe, N as ScopedRpcFn, Nt as EventsMap, O as DevframeSettings, Ot as AgentToolProviderHandle, P as ScopedServerFunctions, Q as DevframeRpcClientFunctions, R as DevframeHost, S as DevframeServiceOf, St as AgentResource, T as DevframeScopedNodeContext, Tt as AgentTool, U as DevframeDiagnosticsLogger, V as DevframeDiagnosticsDefinition, W as DevframeNodeRpcSession, X as RpcStreamingChannelOptions, Y as RpcStreamingChannel, Z as RpcStreamingHost, _ as ConnectionMeta, a as DevframeDockDefaults, b as DevframeNodeContext, bt as AgentHandle, c as DevframeSetupInfo, d as McpRouteOptions, et as DevframeRpcSharedStates, f as defineDevframe, g as Thenable, h as PartialWithoutId, i as DevframeDeploymentKind, j as ScopedBroadcastOptions, jt as EventEmitter, k as DevframeSettingsRegistry, kt as DevframeAgentHost, l as DevframeSpaOptions, m as EntriesToObject, n as DevframeCliOptions, o as DevframeDuplicationStrategy, q as RpcSharedStateGetOptions, r as DevframeDefinition, s as DevframeRuntime, t as DevframeBrowserContext, u as DevframeWsOptions, v as ConnectionMetaWebsocket, w as DevframeServicesRegistry, wt as AgentResourceInput, x as DevframeServiceId, xt as AgentManifest, y as DevframeCapabilities, z as DevframeStorageScope } from "../devframe-qgCKL683.mjs";
2
+ import { g as RpcFunctionAgentOptions } from "../types-CnJSgRVa.mjs";
3
+ import { n as DevframeNodeRpcSessionMeta } from "../ws-server-J-zkiOyp.mjs";
4
+ export { AgentHandle, AgentManifest, AgentResource, AgentResourceContent, AgentResourceInput, AgentTool, AgentToolInput, AgentToolProvider, AgentToolProviderHandle, ConnectionMeta, ConnectionMetaWebsocket, DevframeAgentHost, DevframeAgentHostEvents, DevframeBrowserContext, DevframeCapabilities, DevframeCliOptions, DevframeDefineDiagnosticsOptions, DevframeDefinition, DevframeDeploymentKind, DevframeDiagnosticsDefinition, DevframeDiagnosticsHost, DevframeDiagnosticsLogger, DevframeDockDefaults, DevframeDuplicationStrategy, DevframeHost, DevframeNodeContext, DevframeNodeRpcSession, type DevframeNodeRpcSessionMeta, DevframeRpcClientFunctions, DevframeRpcServerFunctions, DevframeRpcSharedStates, DevframeRuntime, DevframeScopedNodeContext, DevframeScopedNodeRpc, DevframeScopedStreamingHost, DevframeServiceId, DevframeServiceOf, DevframeServicesHost, DevframeServicesRegistry, DevframeSettings, DevframeSettingsRegistry, DevframeSettingsStore, DevframeSetupInfo, DevframeSpaOptions, DevframeStorageScope, DevframeViewHost, DevframeWsOptions, EntriesToObject, EventEmitter, EventUnsubscribe, EventsMap, McpRouteOptions, PartialWithoutId, RpcBroadcastOptions, type RpcFunctionAgentOptions, RpcFunctionsHost, RpcSharedStateGetOptions, RpcSharedStateHost, RpcStreamingChannel, RpcStreamingChannelOptions, RpcStreamingHost, ScopedBroadcastOptions, ScopedClientFunctions, ScopedRpcFn, ScopedServerFunctions, ScopedSharedStates, SettingsForNamespace, Thenable, defineDevframe };
@@ -1,10 +1,10 @@
1
- import { GenericSchema, InferInput } from "valibot";
1
+ import { StandardSchemaV1 } from "@standard-schema/spec";
2
2
  import { BirpcFn, BirpcReturn as BirpcReturn$1 } from "birpc";
3
3
  //#region src/rpc/utils.d.ts
4
- /** Infers TypeScript tuple type from Valibot schema array */
5
- type InferArgsType<S extends RpcArgsSchema | undefined> = S extends readonly [] ? [] : S extends readonly [infer H, ...infer T] ? H extends GenericSchema ? T extends readonly GenericSchema[] ? [InferInput<H>, ...InferArgsType<T>] : never : never : never;
6
- /** Infers TypeScript return type from Valibot return schema */
7
- type InferReturnType<S extends RpcReturnSchema | undefined> = S extends RpcReturnSchema ? InferInput<S> : void;
4
+ /** Infers a TypeScript argument tuple from a Standard Schema array */
5
+ type InferArgsType<S extends RpcArgsSchema | undefined> = S extends readonly [] ? [] : S extends readonly [infer H, ...infer T] ? H extends StandardSchemaV1 ? T extends readonly StandardSchemaV1[] ? [StandardSchemaV1.InferInput<H>, ...InferArgsType<T>] : never : never : never;
6
+ /** Infers a TypeScript return type from a Standard Schema */
7
+ type InferReturnType<S extends RpcReturnSchema | undefined> = S extends StandardSchemaV1 ? StandardSchemaV1.InferInput<S> : void;
8
8
  //#endregion
9
9
  //#region src/rpc/types.d.ts
10
10
  type Thenable<T> = T | Promise<T>;
@@ -89,10 +89,20 @@ interface RpcFunctionSetupResult<ARGS extends any[], RETURN = void> {
89
89
  /** Optional dump definition (overrides definition-level dump) */
90
90
  dump?: RpcDumpDefinition<ARGS, RETURN>;
91
91
  }
92
- /** Valibot schema array for validating function arguments */
93
- type RpcArgsSchema = readonly GenericSchema[];
94
- /** Valibot schema for validating function return value */
95
- type RpcReturnSchema = GenericSchema;
92
+ /**
93
+ * Positional argument schemas for an RPC function. Each entry is any
94
+ * [Standard Schema](https://standardschema.dev)-compliant validator
95
+ * (valibot, zod, arktype, …); the entry at index `i` validates argument
96
+ * `i` at call time and drives that argument's inferred type.
97
+ */
98
+ type RpcArgsSchema = readonly StandardSchemaV1[];
99
+ /**
100
+ * Return-value schema for an RPC function. Any
101
+ * [Standard Schema](https://standardschema.dev)-compliant validator; it
102
+ * validates the handler's resolved return value and drives its inferred
103
+ * type.
104
+ */
105
+ type RpcReturnSchema = StandardSchemaV1;
96
106
  /**
97
107
  * Serialized representation of a thrown value in a dump record.
98
108
  *
@@ -206,9 +216,9 @@ type RpcFunctionDefinition<NAME extends string, TYPE extends RpcFunctionType = '
206
216
  type?: TYPE;
207
217
  /** Whether the function results should be cached */
208
218
  cacheable?: boolean;
209
- /** Valibot schema array for validating function arguments */
219
+ /** Standard Schema array validating (and typing) the arguments */
210
220
  args?: AS;
211
- /** Valibot schema for validating function return value */
221
+ /** Standard Schema validating (and typing) the return value */
212
222
  returns?: RS;
213
223
  /**
214
224
  * Declares whether this function's args/return are JSON-serializable
@@ -253,9 +263,9 @@ type RpcFunctionDefinition<NAME extends string, TYPE extends RpcFunctionType = '
253
263
  type?: TYPE;
254
264
  /** Whether the function results should be cached */
255
265
  cacheable?: boolean;
256
- /** Valibot schema array for validating function arguments */
266
+ /** Standard Schema array validating (and typing) the arguments */
257
267
  args: AS;
258
- /** Valibot schema for validating function return value */
268
+ /** Standard Schema validating (and typing) the return value */
259
269
  returns: RS;
260
270
  /**
261
271
  * Declares whether this function's args/return are JSON-serializable
@@ -275,11 +285,15 @@ type RpcFunctionDefinition<NAME extends string, TYPE extends RpcFunctionType = '
275
285
  */
276
286
  agent?: RpcFunctionAgentOptions;
277
287
  /** Setup function called with context to initialize handler and dump */
278
- setup?: (context: CONTEXT) => Thenable<RpcFunctionSetupResult<InferArgsType<AS>, InferReturnType<RS>>>;
279
- /** Function implementation (required if setup doesn't provide one) */
280
- handler?: (...args: InferArgsType<AS>) => InferReturnType<RS>;
288
+ setup?: (context: CONTEXT) => Thenable<RpcFunctionSetupResult<InferArgsType<AS>, Thenable<InferReturnType<RS>>>>;
289
+ /**
290
+ * Function implementation (required if setup doesn't provide one).
291
+ * The declared `returns` schema describes the *resolved* value —
292
+ * async handlers return a promise of it (the runtime always awaits).
293
+ */
294
+ handler?: (...args: InferArgsType<AS>) => Thenable<InferReturnType<RS>>;
281
295
  /** Dump definition (setup dump takes priority) */
282
- dump?: RpcDump<InferArgsType<AS>, InferReturnType<RS>, CONTEXT>;
296
+ dump?: RpcDump<InferArgsType<AS>, Thenable<InferReturnType<RS>>, CONTEXT>;
283
297
  /**
284
298
  * Sugar for "query in dev, single baked snapshot in build": when
285
299
  * `true` and no `dump` is provided, the build adapter runs the
@@ -290,9 +304,9 @@ type RpcFunctionDefinition<NAME extends string, TYPE extends RpcFunctionType = '
290
304
  */
291
305
  snapshot?: boolean;
292
306
  /** Per-context setup-result cache, populated by `getRpcResolvedSetupResult`. @internal */
293
- __cache?: WeakMap<object, Thenable<RpcFunctionSetupResult<InferArgsType<AS>, InferReturnType<RS>>>>;
307
+ __cache?: WeakMap<object, Thenable<RpcFunctionSetupResult<InferArgsType<AS>, Thenable<InferReturnType<RS>>>>>;
294
308
  /** Single-slot fallback for primitive contexts. @internal */
295
- __promise?: Thenable<RpcFunctionSetupResult<InferArgsType<AS>, InferReturnType<RS>>>;
309
+ __promise?: Thenable<RpcFunctionSetupResult<InferArgsType<AS>, Thenable<InferReturnType<RS>>>>;
296
310
  };
297
311
  type RpcFunctionDefinitionToFunction<T extends RpcFunctionDefinitionAny> = T extends {
298
312
  args: infer AS;
@@ -0,0 +1,27 @@
1
+ //#region src/utils/agent-tool-name.d.ts
2
+ /**
3
+ * Derive the wire-safe agent tool name for an internal tool id.
4
+ *
5
+ * Devframe tool ids are colon-namespaced — `devframe:<area>:<fn>` for
6
+ * built-ins, `devframes:plugin:<slug>:<fn>` for plugin RPCs, and hub
7
+ * command ids for command-derived tools. MCP clients constrain tool names
8
+ * to `^[a-zA-Z0-9_-]{1,128}$`, so the agent/MCP boundary derives the wire
9
+ * name automatically: every run of characters outside `[a-zA-Z0-9_-]`
10
+ * becomes a single `_`, truncated to 128 characters. Internal ids never
11
+ * change — resolution back to the id happens at the boundary.
12
+ *
13
+ * ```
14
+ * devframe:state:read → devframe_state_read
15
+ * devframes:plugin:git:status → devframes_plugin_git_status
16
+ * ```
17
+ *
18
+ * A plain string transform with no node dependency, so browser-side UIs
19
+ * that display a tool's id (e.g. the inspect plugin's agent view) can
20
+ * import it too and show the name a client actually calls.
21
+ *
22
+ * @experimental The agent-native surface is experimental and may change
23
+ * without a major version bump until it stabilizes.
24
+ */
25
+ declare function toAgentToolName(id: string): string;
26
+ //#endregion
27
+ export { toAgentToolName };
@@ -0,0 +1,34 @@
1
+ //#region src/utils/agent-tool-name.ts
2
+ /**
3
+ * Maximum tool-name length several MCP clients enforce (the Anthropic API
4
+ * pattern is `^[a-zA-Z0-9_-]{1,128}$`).
5
+ */
6
+ const MAX_TOOL_NAME_LENGTH = 128;
7
+ /**
8
+ * Derive the wire-safe agent tool name for an internal tool id.
9
+ *
10
+ * Devframe tool ids are colon-namespaced — `devframe:<area>:<fn>` for
11
+ * built-ins, `devframes:plugin:<slug>:<fn>` for plugin RPCs, and hub
12
+ * command ids for command-derived tools. MCP clients constrain tool names
13
+ * to `^[a-zA-Z0-9_-]{1,128}$`, so the agent/MCP boundary derives the wire
14
+ * name automatically: every run of characters outside `[a-zA-Z0-9_-]`
15
+ * becomes a single `_`, truncated to 128 characters. Internal ids never
16
+ * change — resolution back to the id happens at the boundary.
17
+ *
18
+ * ```
19
+ * devframe:state:read → devframe_state_read
20
+ * devframes:plugin:git:status → devframes_plugin_git_status
21
+ * ```
22
+ *
23
+ * A plain string transform with no node dependency, so browser-side UIs
24
+ * that display a tool's id (e.g. the inspect plugin's agent view) can
25
+ * import it too and show the name a client actually calls.
26
+ *
27
+ * @experimental The agent-native surface is experimental and may change
28
+ * without a major version bump until it stabilizes.
29
+ */
30
+ function toAgentToolName(id) {
31
+ return id.replace(/[^\w-]+/g, "_").slice(0, MAX_TOOL_NAME_LENGTH);
32
+ }
33
+ //#endregion
34
+ export { toAgentToolName };
@@ -1,4 +1,4 @@
1
- import { jt as EventsMap, kt as EventEmitter } from "../devframe-Ckhf3kFw.mjs";
1
+ import { Nt as EventsMap, jt as EventEmitter } from "../devframe-qgCKL683.mjs";
2
2
  //#region src/utils/events.d.ts
3
3
  /**
4
4
  * Create event emitter.
@@ -1,2 +1,2 @@
1
- import { _t as SharedStateOptions, dt as ImmutableArray, ft as ImmutableMap, gt as SharedStateEvents, ht as SharedState, mt as ImmutableSet, pt as ImmutableObject, ut as Immutable, vt as SharedStatePatch, yt as createSharedState } from "../devframe-Ckhf3kFw.mjs";
1
+ import { _t as SharedStateOptions, dt as ImmutableArray, ft as ImmutableMap, gt as SharedStateEvents, ht as SharedState, mt as ImmutableSet, pt as ImmutableObject, ut as Immutable, vt as SharedStatePatch, yt as createSharedState } from "../devframe-qgCKL683.mjs";
2
2
  export { Immutable, ImmutableArray, ImmutableMap, ImmutableObject, ImmutableSet, SharedState, SharedStateEvents, SharedStateOptions, SharedStatePatch, createSharedState };
@@ -0,0 +1,2 @@
1
+ import { a as literal, c as number, d as picklist, f as record, g as voidType, h as union, i as describe, l as object, m as string, n as array, o as nullType, p as s, r as boolean, s as nullable, t as SimpleSchema, u as optional } from "../simple-schema-BDzLeJDk.mjs";
2
+ export { SimpleSchema, array, boolean, describe, literal, nullType, nullable, number, object, optional, picklist, record, s, string, union, voidType };