devframe 0.9.8 → 0.9.9

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 (116) hide show
  1. package/dist/{_shared-BM3PdYli.mjs → _shared-C08SdQRl.mjs} +15 -4
  2. package/dist/{_shared-mtXpcJIv.d.mts → _shared-CK3czkH4.d.mts} +25 -2
  3. package/dist/adapters/build.d.mts +6 -6
  4. package/dist/adapters/build.mjs +32 -22
  5. package/dist/adapters/cac.d.mts +16 -1
  6. package/dist/adapters/cac.mjs +8 -7
  7. package/dist/adapters/dev.d.mts +13 -13
  8. package/dist/adapters/dev.mjs +2 -2
  9. package/dist/adapters/embedded.d.mts +1 -1
  10. package/dist/adapters/initiate.d.mts +28 -26
  11. package/dist/adapters/initiate.mjs +1 -1
  12. package/dist/adapters/mcp.d.mts +28 -14
  13. package/dist/adapters/mcp.mjs +75 -39
  14. package/dist/{agent-tool-name-EgfoFO8C.mjs → agent-tool-name-DGzeuWcO.mjs} +2 -2
  15. package/dist/cli/main.d.mts +1 -1
  16. package/dist/cli/main.mjs +41 -17
  17. package/dist/client/index.d.mts +36 -36
  18. package/dist/client/index.mjs +83 -51
  19. package/dist/{client-assets-C7SXgTWY.mjs → client-assets-DNdhagGm.mjs} +2 -2
  20. package/dist/constants.d.mts +8 -7
  21. package/dist/constants.mjs +7 -6
  22. package/dist/{context-CLF4-8Pp.d.mts → context-4AIVRLYF.d.mts} +158 -122
  23. package/dist/{context-omlma_1n.mjs → context-CwPUinjn.mjs} +126 -88
  24. package/dist/{context-KUqAfawQ.mjs → context-DIUvJW4D.mjs} +3 -3
  25. package/dist/{context-DftYyXaR.d.mts → context-rgBSPFHS.d.mts} +5 -5
  26. package/dist/{crypto-token-XCqTSMg9.mjs → crypto-token-TVbGGFuj.mjs} +1 -1
  27. package/dist/{dev-CzkPCJwi.mjs → dev-Eqq5PX0k.mjs} +37 -18
  28. package/dist/{diagnostics-BXWW3VK-.mjs → diagnostics-BMfN8mb1.mjs} +30 -17
  29. package/dist/{diagnostics-CD8nlgll.mjs → diagnostics-D0EVm5M6.mjs} +2 -2
  30. package/dist/{events-4daw0uK9.mjs → events-BV4Dj59a.mjs} +2 -2
  31. package/dist/{host-h3-fRbF9yor.mjs → host-h3-BJ4siyz7.mjs} +1 -1
  32. package/dist/in-page-channel/index.d.mts +14 -14
  33. package/dist/in-page-channel/index.mjs +63 -54
  34. package/dist/{index-BzyopqxV.d.mts → index-pIVt92jP.d.mts} +9 -9
  35. package/dist/{index-D3k0BIhe.d.mts → index-pKl67H6w.d.mts} +4 -4
  36. package/dist/index.d.mts +8 -8
  37. package/dist/index.mjs +2 -2
  38. package/dist/{instance-registry-BjlMQbFB.mjs → instance-registry-C7-41RSp.mjs} +8 -8
  39. package/dist/{instance-shell-Tcp5hGoq.d.mts → instance-shell-7Z52PE4_.d.mts} +18 -18
  40. package/dist/{instance-shell-CpVW4zG0.mjs → instance-shell-cdVETpfz.mjs} +227 -58
  41. package/dist/internal/index.d.mts +40 -23
  42. package/dist/internal/index.mjs +10 -10
  43. package/dist/node/auth.d.mts +2 -2
  44. package/dist/node/auth.mjs +2 -2
  45. package/dist/node/hub-internals.d.mts +2 -2
  46. package/dist/node/hub-internals.mjs +2 -2
  47. package/dist/node/index.d.mts +5 -5
  48. package/dist/node/index.mjs +2 -2
  49. package/dist/{nostics-SPGDgHEP.d.mts → nostics-0sKe5HIj.d.mts} +2 -2
  50. package/dist/{nostics-CzECRXpE.mjs → nostics-D0PvLZsn.mjs} +1 -1
  51. package/dist/origin-DGDH8BI9.d.mts +45 -0
  52. package/dist/origin-DZit9g29.mjs +80 -0
  53. package/dist/recipes/common-rpc-functions.d.mts +5 -5
  54. package/dist/recipes/common-rpc-functions.mjs +3 -3
  55. package/dist/recipes/interactive-auth.d.mts +6 -6
  56. package/dist/recipes/interactive-auth.mjs +6 -6
  57. package/dist/{remote-assets-DezQmPQU.mjs → remote-assets-BIFWOlBW.mjs} +26 -6
  58. package/dist/{remote-assets-B13_vRkJ.d.mts → remote-assets-eBvSKZMS.d.mts} +7 -7
  59. package/dist/{revoke-COLW0cOi.mjs → revoke-cqztiCX4.mjs} +1 -1
  60. package/dist/rpc/dump.d.mts +2 -11
  61. package/dist/rpc/dump.mjs +1 -1
  62. package/dist/rpc/index.d.mts +2 -2
  63. package/dist/rpc/index.mjs +3 -3
  64. package/dist/rpc/transports/sse-client.d.mts +1 -1
  65. package/dist/rpc/transports/sse-client.mjs +30 -14
  66. package/dist/rpc/transports/sse-server.d.mts +4 -4
  67. package/dist/rpc/transports/sse-server.mjs +7 -7
  68. package/dist/rpc/transports/ws-bun.d.mts +5 -5
  69. package/dist/rpc/transports/ws-bun.mjs +8 -2
  70. package/dist/rpc/transports/ws-client.d.mts +1 -1
  71. package/dist/rpc/transports/ws-client.mjs +2 -2
  72. package/dist/rpc/transports/ws-deno.d.mts +4 -4
  73. package/dist/rpc/transports/ws-deno.mjs +8 -2
  74. package/dist/rpc/transports/ws-server.d.mts +2 -1
  75. package/dist/rpc/transports/ws-server.mjs +232 -1
  76. package/dist/{rpc-core-B3W3z9ff.d.mts → rpc-core-Ceu6AUz8.d.mts} +4 -4
  77. package/dist/{rpc-core-DlHd276T.mjs → rpc-core-DVQ7xi89.mjs} +14 -2
  78. package/dist/{serialization-BGzEwAdr.mjs → serialization-DTZnPQ1-.mjs} +20 -18
  79. package/dist/{services-install-CqqQVls5.mjs → services-install-P_DV7VYL.mjs} +32 -21
  80. package/dist/session-DPfj6zQG.mjs +16 -0
  81. package/dist/{shared-state--sduc6Xi.mjs → shared-state-CaxB1q0h.mjs} +2 -2
  82. package/dist/{simple-schema-DQPZrAaZ.mjs → simple-schema-Bi40l-P6.mjs} +2 -2
  83. package/dist/{sse-client-DwX021ST.d.mts → sse-client-BQ4jS3eO.d.mts} +4 -4
  84. package/dist/{state-CK9LjrnT.mjs → state-CeQQWzM-.mjs} +4 -4
  85. package/dist/{static-DV_qUSRS.mjs → static-DZ8P2Kn7.mjs} +130 -135
  86. package/dist/{storage-BXNVhKyR.mjs → storage-Dccf_IyD.mjs} +1 -1
  87. package/dist/types/index.d.mts +6 -6
  88. package/dist/{types-CMdPYhOx.d.mts → types-Dq4i156u.d.mts} +17 -17
  89. package/dist/utils/agent-tool-name.d.mts +2 -2
  90. package/dist/utils/agent-tool-name.mjs +2 -2
  91. package/dist/utils/colors.d.mts +1 -1
  92. package/dist/utils/crypto-token.d.mts +1 -1
  93. package/dist/utils/crypto-token.mjs +1 -1
  94. package/dist/utils/events.d.mts +1 -1
  95. package/dist/utils/nostics.d.mts +1 -1
  96. package/dist/utils/nostics.mjs +1 -1
  97. package/dist/utils/open.mjs +1 -1
  98. package/dist/utils/origin.d.mts +2 -0
  99. package/dist/utils/origin.mjs +80 -0
  100. package/dist/utils/remote-assets.d.mts +2 -2
  101. package/dist/utils/remote-assets.mjs +1 -1
  102. package/dist/utils/serve-static.d.mts +4 -4
  103. package/dist/utils/serve-static.mjs +56 -19
  104. package/dist/utils/shared-state.d.mts +1 -1
  105. package/dist/utils/shared-state.mjs +1 -1
  106. package/dist/utils/simple-schema.d.mts +5 -5
  107. package/dist/utils/simple-schema.mjs +2 -2
  108. package/dist/utils/streaming-channel.d.mts +1 -1
  109. package/dist/utils/streaming-channel.mjs +2 -2
  110. package/dist/utils/when.d.mts +5 -5
  111. package/dist/{validation-YrZH6atx.mjs → validation-BOy8IoFZ.mjs} +2 -2
  112. package/dist/{wire-codec-0K-o5MYW.mjs → wire-codec-dcCeXcSo.mjs} +3 -3
  113. package/dist/{ws-client-7_lZi-B9.d.mts → ws-client-Xpxt0oPA.d.mts} +3 -3
  114. package/dist/{ws-server-VyHlanzy.d.mts → ws-server-D2nv68Hg.d.mts} +13 -37
  115. package/package.json +2 -1
  116. package/dist/ws-server-Y_AumUQH.mjs +0 -294
@@ -1,8 +1,8 @@
1
- import { t as DEVFRAME_EVENTS } from "../events-4daw0uK9.mjs";
1
+ import { t as DEVFRAME_EVENTS } from "../events-BV4Dj59a.mjs";
2
2
  import { t as hash } from "../hash-DdPnc4k3.mjs";
3
3
  import { colors } from "../utils/colors.mjs";
4
4
  import { createEventEmitter } from "../utils/events.mjs";
5
- import { t as createSharedState } from "../shared-state--sduc6Xi.mjs";
5
+ import { t as createSharedState } from "../shared-state-CaxB1q0h.mjs";
6
6
  import { i as structuredCloneStringify, n as structuredCloneParse, t as structuredCloneDeserialize } from "../structured-clone-CgtQ61SA.mjs";
7
7
  import { createStreamReader, createStreamSink } from "../utils/streaming-channel.mjs";
8
8
  import { defineDiagnostics } from "nostics";
@@ -10,6 +10,7 @@ import { ansiFormatter } from "nostics/formatters/ansi";
10
10
  import { withBase, withProtocol } from "ufo";
11
11
  import { createBirpc } from "birpc";
12
12
  //#region src/constants.ts
13
+ /** Devframe runtime routes and static output conventions. */
13
14
  const DEVFRAME_CONNECTION_META_FILENAME = "__connection.json";
14
15
  /**
15
16
  * Global key holding the serializable connection prepared by
@@ -110,7 +111,7 @@ function devframeReporter(d, { method = "warn" } = {}) {
110
111
  * ANSI console reporter pre-wired ahead of any `reporters` passed in. Every
111
112
  * `diagnostics.ts` in devframe core, `@devframes/hub`, `@devframes/json-render`,
112
113
  * and the built-in plugins defines its codes through this instead of
113
- * `nostics`'s own `defineDiagnostics` — the reporter registration lives
114
+ * `nostics`'s own `defineDiagnostics`; the reporter registration lives
114
115
  * here, once, so none of them need to build their own reporter (`colors`,
115
116
  * `ansiFormatter`) or take a direct dependency on `nostics` themselves.
116
117
  */
@@ -126,7 +127,7 @@ const diagnostics = defineDiagnostics$1({
126
127
  docsBase: "https://devfra.me/errors",
127
128
  codes: {
128
129
  DF0019: {
129
- why: (p) => `RPC function "${p.name}" has \`agent\` set but \`jsonSerializable\` is not \`true\` — MCP requires JSON-serializable data.`,
130
+ why: (p) => `RPC function "${p.name}" has \`agent\` set but \`jsonSerializable\` is not \`true\`; MCP requires JSON-serializable data.`,
130
131
  fix: "Set `jsonSerializable: true` if the payload is JSON-safe, or remove `agent` to keep it RPC-only."
131
132
  },
132
133
  DF0020: {
@@ -207,7 +208,7 @@ async function validateRpcArgs(name, argsSchema, args) {
207
208
  /**
208
209
  * Validate a handler's resolved return value against its declared schema.
209
210
  * Throws `DF0039` when the value fails the schema, otherwise returns the
210
- * original value unchanged (guard-only, never rewriting the payload — see
211
+ * original value unchanged (guard-only, never rewriting the payload; see
211
212
  * {@link validateRpcArgs}). Passes through when no return schema is set.
212
213
  *
213
214
  * @internal
@@ -350,16 +351,16 @@ function assertAgentJsonSerializable(fn) {
350
351
  * instances, or `undefined` inside an array (silently becomes `null`).
351
352
  *
352
353
  * Native pass-throughs (no extra work needed):
353
- * - circular references — `JSON.stringify` raises `TypeError`.
354
- * - `BigInt` at top level — caught here for a friendlier error path.
354
+ * - circular references: `JSON.stringify` raises `TypeError`.
355
+ * - `BigInt` at top level: caught here for a friendlier error path.
355
356
  *
356
357
  * Lenient cases (allowed without throwing):
357
- * - `undefined` as an object property — legitimate optional field;
358
+ * - `undefined` as an object property: legitimate optional field;
358
359
  * JSON.stringify just omits it.
359
- * - `undefined` at the root — legitimate "action returned nothing".
360
- * - `Symbol` / `Function` values — semantically "drop me" in JSON.
360
+ * - `undefined` at the root: legitimate "action returned nothing".
361
+ * - `Symbol` / `Function` values: semantically "drop me" in JSON.
361
362
  *
362
- * `fnName` is used only for the diagnostic message — pass the RPC
363
+ * `fnName` is used only for the diagnostic message; pass the RPC
363
364
  * function name when calling from a wire serializer / dump writer so
364
365
  * the error points at the offending function.
365
366
  */
@@ -371,19 +372,21 @@ function strictJsonStringify(value, fnName = "") {
371
372
  if (Array.isArray(holder)) throw nonJsonAt(fnName, "undefined", holder, key);
372
373
  return val;
373
374
  }
374
- if (original === null) return val;
375
- if (typeof original === "bigint") throw nonJsonAt(fnName, "BigInt", holder, key);
376
- if (typeof original === "object") {
377
- if (original instanceof Map) throw nonJsonAt(fnName, "Map", holder, key);
378
- if (original instanceof Set) throw nonJsonAt(fnName, "Set", holder, key);
379
- if (original instanceof Date) throw nonJsonAt(fnName, "Date", holder, key);
380
- if (Array.isArray(original)) return val;
381
- const proto = Object.getPrototypeOf(original);
382
- if (proto !== null && proto !== Object.prototype) throw nonJsonAt(fnName, original.constructor?.name ?? "class instance", holder, key);
383
- }
375
+ if (original !== null) assertJsonSafe(original, holder, key, fnName);
384
376
  return val;
385
377
  });
386
378
  }
379
+ /** Throw `DF0020` when `original` is a type JSON can't round-trip losslessly. */
380
+ function assertJsonSafe(original, holder, key, fnName) {
381
+ if (typeof original === "bigint") throw nonJsonAt(fnName, "BigInt", holder, key);
382
+ if (typeof original !== "object") return;
383
+ if (original instanceof Map) throw nonJsonAt(fnName, "Map", holder, key);
384
+ if (original instanceof Set) throw nonJsonAt(fnName, "Set", holder, key);
385
+ if (original instanceof Date) throw nonJsonAt(fnName, "Date", holder, key);
386
+ if (Array.isArray(original)) return;
387
+ const proto = Object.getPrototypeOf(original);
388
+ if (proto !== null && proto !== Object.prototype) throw nonJsonAt(fnName, original.constructor?.name ?? "class instance", holder, key);
389
+ }
387
390
  function nonJsonAt(fnName, type, parent, key) {
388
391
  const path = formatPath(parent, key);
389
392
  return diagnostics.DF0020({
@@ -506,6 +509,10 @@ async function setupDevframeConnection(options = {}) {
506
509
  if (options.connectionMeta) {
507
510
  const connection = {
508
511
  connectionMeta: options.connectionMeta,
512
+ /**
513
+ * Preserve the established connectionMeta behavior: an explicitly
514
+ * supplied descriptor resolves from the caller's explicit base.
515
+ */
509
516
  metaBaseUrl: resolveMetaBaseUrl(bases[0] ?? "./"),
510
517
  authToken: readStoredAuthToken(options.authToken ?? options.connectionMeta.authToken)
511
518
  };
@@ -605,7 +612,7 @@ function consumeOtpFromUrl(param = DEVFRAME_OTP_URL_PARAM) {
605
612
  *
606
613
  * Higher-level integrations (e.g. Vite DevTools) that want to drive their own
607
614
  * authentication UI can disable `connectDevframe`'s built-in handling with
608
- * `otpParam: false` and call this — or {@link consumeOtpFromUrl} — themselves.
615
+ * `otpParam: false` and call this (or {@link consumeOtpFromUrl}) themselves.
609
616
  */
610
617
  async function authenticateWithUrlOtp(rpc, options = {}) {
611
618
  const code = consumeOtpFromUrl(options.param ?? "devframe_otp");
@@ -763,7 +770,7 @@ const EMPTY_WIRE_DEFS = /* @__PURE__ */ new Map();
763
770
  * JSON (methods declared `jsonSerializable: true`) and `s:`-prefixed
764
771
  * structured-clone (everything else, including all error envelopes), with a
765
772
  * request-id → method map so a response independently picks the same
766
- * encoder as its request. One codec per connection — request-id spaces
773
+ * encoder as its request. One codec per connection; request-id spaces
767
774
  * don't collide across connections.
768
775
  *
769
776
  * @internal
@@ -791,9 +798,32 @@ function createRpcWireCodec(definitions = EMPTY_WIRE_DEFS) {
791
798
  //#endregion
792
799
  //#region src/rpc/transports/sse-client.ts
793
800
  function NOOP$1() {}
801
+ /** Split the next complete SSE frame (up to a blank line) off the buffer. */
802
+ function takeFrame(buffer) {
803
+ const boundary = buffer.search(/\n\n|\r\n\r\n/);
804
+ if (boundary < 0) return void 0;
805
+ return {
806
+ frame: buffer.slice(0, boundary),
807
+ rest: buffer.slice(boundary + (buffer[boundary] === "\r" ? 4 : 2))
808
+ };
809
+ }
810
+ /** Parse one SSE frame's lines into its event name and data lines. */
811
+ function parseFrame(frame) {
812
+ let event = "message";
813
+ const data = [];
814
+ for (const rawLine of frame.split(/\r?\n/)) {
815
+ if (rawLine.startsWith(":")) continue;
816
+ if (rawLine.startsWith("event:")) event = rawLine.slice(6).trimStart();
817
+ else if (rawLine.startsWith("data:")) data.push(rawLine.slice(5).replace(/^ /, ""));
818
+ }
819
+ return {
820
+ event,
821
+ data
822
+ };
823
+ }
794
824
  /**
795
825
  * Build a birpc `ChannelOptions` object backed by an SSE stream (server →
796
- * client) and HTTP `POST` (client → server) — the WebSocket-free counterpart
826
+ * client) and HTTP `POST` (client → server): the WebSocket-free counterpart
797
827
  * to `createWsRpcChannel`, wire-compatible with `attachSseRpcTransport`.
798
828
  *
799
829
  * The stream is consumed via `fetch` streaming (not `EventSource`), so it
@@ -801,7 +831,7 @@ function NOOP$1() {}
801
831
  * (`event: session`) carries the session id; every `POST` echoes it in the
802
832
  * `x-birpc-session` header. A response to a client-initiated request comes
803
833
  * back in the `POST`'s own body and is re-injected into the channel; a
804
- * dropped stream terminates the channel — there is no reconnect, matching
834
+ * dropped stream terminates the channel; there is no reconnect, matching
805
835
  * the WS channel's closed-is-done semantics.
806
836
  */
807
837
  function createSseRpcChannel(options) {
@@ -852,17 +882,10 @@ function createSseRpcChannel(options) {
852
882
  if (done) break;
853
883
  buffer += decoder.decode(value, { stream: true });
854
884
  for (;;) {
855
- const boundary = buffer.search(/\n\n|\r\n\r\n/);
856
- if (boundary < 0) break;
857
- const frame = buffer.slice(0, boundary);
858
- buffer = buffer.slice(boundary + (buffer[boundary] === "\r" ? 4 : 2));
859
- let event = "message";
860
- const data = [];
861
- for (const rawLine of frame.split(/\r?\n/)) {
862
- if (rawLine.startsWith(":")) continue;
863
- if (rawLine.startsWith("event:")) event = rawLine.slice(6).trimStart();
864
- else if (rawLine.startsWith("data:")) data.push(rawLine.slice(5).replace(/^ /, ""));
865
- }
885
+ const taken = takeFrame(buffer);
886
+ if (!taken) break;
887
+ buffer = taken.rest;
888
+ const { event, data } = parseFrame(taken.frame);
866
889
  if (data.length > 0) dispatch(event, data.join("\n"));
867
890
  }
868
891
  }
@@ -955,8 +978,8 @@ function promiseWithResolver() {
955
978
  //#endregion
956
979
  //#region src/client/rpc-live.ts
957
980
  /**
958
- * The transport-independent half of a live RPC client mode — connection
959
- * status, pending-call guarding, and the trust handshake — shared by the
981
+ * The transport-independent half of a live RPC client mode (connection
982
+ * status, pending-call guarding, and the trust handshake), shared by the
960
983
  * WebSocket and SSE modes. Each transport supplies only its channel.
961
984
  */
962
985
  function createLiveRpcClientMode(options) {
@@ -984,7 +1007,7 @@ function createLiveRpcClientMode(options) {
984
1007
  }
985
1008
  /**
986
1009
  * Wrap an in-flight call promise so it settles on server response, on an
987
- * optional wall-clock timeout, or when the connection drops — never hangs.
1010
+ * optional wall-clock timeout, or when the connection drops, so it never hangs.
988
1011
  */
989
1012
  function guardCall(promise, method) {
990
1013
  return new Promise((resolve, reject) => {
@@ -1053,6 +1076,11 @@ function createLiveRpcClientMode(options) {
1053
1076
  currentAuthToken = token;
1054
1077
  const result = await serverRpc.$call("anonymous:devframe:auth", {
1055
1078
  authToken: token,
1079
+ /**
1080
+ * Sent raw; the server parses it into a display label (see
1081
+ * `describeUA` in `node/auth/state.ts`) so `ua-parser-modern` stays
1082
+ * out of the browser bundle.
1083
+ */
1056
1084
  ua: navigator.userAgent,
1057
1085
  origin: location.origin
1058
1086
  });
@@ -1175,7 +1203,7 @@ function resolveSseUrl(sse, metaBaseUrl, loc) {
1175
1203
  return new URL(str, base).href;
1176
1204
  }
1177
1205
  /**
1178
- * The SSE-backed live client mode — picked by `connectDevframe` when the
1206
+ * The SSE-backed live client mode, picked by `connectDevframe` when the
1179
1207
  * server advertises SSE as its primary transport (`backend: 'sse'`) or when
1180
1208
  * the caller pins `transport: 'sse'`. Same status machine, call guarding,
1181
1209
  * and trust handshake as the WebSocket mode, over `createSseRpcChannel`.
@@ -1218,13 +1246,11 @@ function createSseRpcClientMode(options) {
1218
1246
  * the original `name`, and re-attaches any custom own properties.
1219
1247
  */
1220
1248
  function reviveDumpError(stored) {
1221
- const cause = stored.cause instanceof Error ? stored.cause : isPlainErrorShape(stored.cause) ? reviveDumpError(stored.cause) : stored.cause;
1222
- const error = cause !== void 0 ? new Error(stored.message, { cause }) : new Error(stored.message);
1223
- error.name = stored.name;
1224
- for (const key of Object.keys(stored)) {
1225
- if (key === "name" || key === "message" || key === "cause") continue;
1226
- error[key] = stored[key];
1227
- }
1249
+ const { name, message, cause: rawCause, ...extras } = stored;
1250
+ const cause = rawCause instanceof Error ? rawCause : isPlainErrorShape(rawCause) ? reviveDumpError(rawCause) : rawCause;
1251
+ const error = cause !== void 0 ? new Error(message, { cause }) : new Error(message);
1252
+ error.name = name;
1253
+ Object.assign(error, extras);
1228
1254
  return error;
1229
1255
  }
1230
1256
  function isPlainErrorShape(value) {
@@ -1305,15 +1331,21 @@ async function createStaticRpcClientMode(options) {
1305
1331
  return {
1306
1332
  transport: "static",
1307
1333
  isTrusted: true,
1334
+ /**
1335
+ * A static backend has no live socket; every call is a local fetch, so it
1336
+ * is "connected" for its whole life.
1337
+ */
1308
1338
  status: "connected",
1309
1339
  connectionError: null,
1310
1340
  requestTrust: async () => true,
1311
1341
  requestTrustWithToken: async () => true,
1342
+ /** Static backends are always trusted, so there's nothing to exchange. */
1312
1343
  requestTrustWithCode: async () => null,
1313
1344
  ensureTrusted: async () => true,
1314
1345
  call: (...args) => staticCaller.call(args[0], args.slice(1)),
1315
1346
  callEvent: (...args) => staticCaller.callEvent(args[0], args.slice(1)),
1316
1347
  callOptional: (...args) => staticCaller.callOptional(args[0], args.slice(1)),
1348
+ /** No live socket to close; every call is a local fetch. */
1317
1349
  close: () => {}
1318
1350
  };
1319
1351
  }
@@ -1426,7 +1458,7 @@ const EMPTY_DEFS = /* @__PURE__ */ new Map();
1426
1458
  * Build a birpc `ChannelOptions` object backed by a browser `WebSocket`.
1427
1459
  * Pass the result straight to `createRpcClient`'s `channel` option.
1428
1460
  *
1429
- * Also returns `close()`, closing the underlying socket — mirroring the server transport's
1461
+ * Also returns `close()`, closing the underlying socket, mirroring the server transport's
1430
1462
  * existing `WsRpcTransport.close()`. `birpc`'s own `ChannelOptions` has no teardown of its own.
1431
1463
  */
1432
1464
  function createWsRpcChannel(options) {
@@ -1488,7 +1520,7 @@ function createWsRpcChannel(options) {
1488
1520
  * The object / relative-path forms connect to the page's own origin (only the
1489
1521
  * `http`→`ws` protocol swap is applied), resolving the path against where
1490
1522
  * `__connection.json` was loaded. This is deliberately host-agnostic so the
1491
- * connection survives a reverse proxy that changes the domain or port — the
1523
+ * connection survives a reverse proxy that changes the domain or port, since the
1492
1524
  * client trusts its own location, never a server-baked hostname. An explicit
1493
1525
  * `port`/`host` (or a full `ws(s)://` URL string) opts into a cross-origin
1494
1526
  * endpoint, e.g. a side-car server on its own port.
@@ -1643,7 +1675,7 @@ function createScopedClientContext(rpc, namespace) {
1643
1675
  //#region src/client/rpc.ts
1644
1676
  /**
1645
1677
  * Resolve the requested `transport` option against what the server
1646
- * advertises. `'auto'` trusts the advertisement — the server's declared
1678
+ * advertises. `'auto'` trusts the advertisement: the server's declared
1647
1679
  * primary (`backend`), preferring the WebSocket when both endpoints are
1648
1680
  * present; an explicit `'websocket'` / `'sse'` pins that transport and
1649
1681
  * throws when the server doesn't advertise it.
@@ -1663,7 +1695,7 @@ function resolveClientTransport(requested, meta) {
1663
1695
  if (meta.backend === "sse" && hasSse) return "sse";
1664
1696
  if (hasWebsocket) return "websocket";
1665
1697
  if (hasSse) return "sse";
1666
- throw new Error("[devframe] This server advertises no RPC transport (backend \"none\") — nothing to connect to. Enable the WebSocket or SSE endpoint on the server, or use its static/MCP surfaces instead.");
1698
+ throw new Error("[devframe] This server advertises no RPC transport (backend \"none\"), so there is nothing to connect to. Enable the WebSocket or SSE endpoint on the server, or use its static/MCP surfaces instead.");
1667
1699
  }
1668
1700
  async function getDevframeRpcClient(options = {}) {
1669
1701
  const { baseURL = "./", rpcOptions = {}, cacheOptions = false } = options;
@@ -1,9 +1,9 @@
1
1
  //#region src/client-assets.ts
2
2
  /**
3
- * Resolve a definition's client assets source — the built SPA served as its
3
+ * Resolve a definition's client assets source: the built SPA served as its
4
4
  * UI. Prefers the top-level {@link DevframeDefinition.clientAssets} and falls
5
5
  * back to the deprecated `cli.distDir`, so both the new and legacy shapes
6
- * resolve. Returns `undefined` when neither is set (bridge mode — the SPA is
6
+ * resolve. Returns `undefined` when neither is set (bridge mode, where the SPA is
7
7
  * hosted elsewhere).
8
8
  *
9
9
  * Internal: exposed to first-party integrations via `devframe/internal`, not
@@ -1,8 +1,8 @@
1
1
  //#region src/events.d.ts
2
2
  /**
3
- * Centralized registry of the core devframe event names — the node-side host
3
+ * Centralized registry of the core devframe event names: the node-side host
4
4
  * bus events, the client RPC connection events, and the server→client
5
- * broadcast notifications — so these names live in one place instead of
5
+ * broadcast notifications, so these names live in one place instead of
6
6
  * scattered string literals.
7
7
  *
8
8
  * **Keep this in sync with [`docs/content/8.references/3.events.md`](../../../docs/content/8.references/3.events.md)**
@@ -77,6 +77,7 @@ declare const DEVFRAME_EVENTS: {
77
77
  };
78
78
  //#endregion
79
79
  //#region src/constants.d.ts
80
+ /** Devframe runtime routes and static output conventions. */
80
81
  declare const DEVFRAME_CONNECTION_META_FILENAME = "__connection.json";
81
82
  /**
82
83
  * Global key holding the serializable connection prepared by
@@ -87,7 +88,7 @@ declare const DEVFRAME_CONNECTION_KEY = "__DEVFRAME_CONNECTION__";
87
88
  /**
88
89
  * Route the WebSocket RPC endpoint is bound to, relative to a devframe's
89
90
  * base path. Sits next to `__connection.json` so the deployed SPA can reach
90
- * it on the same origin it loaded from — the dev server shares one port for
91
+ * it on the same origin it loaded from: the dev server shares one port for
91
92
  * both HTTP and WS, and a host server (Vite, etc.) can mount the WS upgrade
92
93
  * handler here without colliding with its own routes (HMR, asset serving).
93
94
  */
@@ -97,7 +98,7 @@ declare const DEVFRAME_WS_ROUTE = "__ws";
97
98
  * path. A single method-dispatched route: `GET` opens the event stream
98
99
  * (server→client), `POST` carries RPC frames (client→server). Sits next to
99
100
  * `__connection.json` so the deployed SPA reaches it on the same origin it
100
- * loaded from — the transport for hosts and proxies where the WebSocket
101
+ * loaded from; the transport for hosts and proxies where the WebSocket
101
102
  * upgrade isn't available.
102
103
  */
103
104
  declare const DEVFRAME_SSE_ROUTE = "__sse";
@@ -111,7 +112,7 @@ declare const DEVFRAME_SSE_SESSION_HEADER = "x-birpc-session";
111
112
  /**
112
113
  * Route the Streamable-HTTP MCP endpoint is bound to, relative to a
113
114
  * devframe's base path. Sits next to `__connection.json` and the WS route
114
- * so an MCP client reaches it on the same origin the SPA loaded from — the
115
+ * so an MCP client reaches it on the same origin the SPA loaded from; the
115
116
  * dev server shares one port for HTTP, WS, and MCP. Opt-in via `cli.mcp`.
116
117
  */
117
118
  declare const DEVFRAME_MCP_ROUTE = "__mcp";
@@ -156,7 +157,7 @@ declare const DEVFRAME_VIEWER_ORIGIN_TOKEN_QUERY_PARAM = "devframe_viewer_origin
156
157
  /**
157
158
  * `postMessage` type the remote-assets fallback page posts to `window.parent`
158
159
  * on load. That page is what a devframe serves (with a 502) when its client
159
- * assets can be reached neither locally nor through their CDN provider — the
160
+ * assets can be reached neither locally nor through their CDN provider; the
160
161
  * message lets an embedding viewer replace the bare page with its own UI
161
162
  * (`@devframes/hub-ui` does, in its iframe view). Payload shape:
162
163
  * `RemoteAssetsErrorMessage` (`devframe/types`).
@@ -164,7 +165,7 @@ declare const DEVFRAME_VIEWER_ORIGIN_TOKEN_QUERY_PARAM = "devframe_viewer_origin
164
165
  declare const DEVFRAME_REMOTE_ASSETS_ERROR_MESSAGE_TYPE: string;
165
166
  /**
166
167
  * Prefix that marks an RPC method as callable before a connection is
167
- * trusted. This is the *only* rule the pre-trust gate applies — there is no
168
+ * trusted. This is the *only* rule the pre-trust gate applies; there is no
168
169
  * per-method allowlist. Any handshake method a host adapter needs to reach
169
170
  * before authentication must be named `anonymous:<rest>` (e.g.
170
171
  * `anonymous:devframe:auth`).
@@ -1,5 +1,6 @@
1
- import { t as DEVFRAME_EVENTS } from "./events-4daw0uK9.mjs";
1
+ import { t as DEVFRAME_EVENTS } from "./events-BV4Dj59a.mjs";
2
2
  //#region src/constants.ts
3
+ /** Devframe runtime routes and static output conventions. */
3
4
  const DEVFRAME_CONNECTION_META_FILENAME = "__connection.json";
4
5
  /**
5
6
  * Global key holding the serializable connection prepared by
@@ -10,7 +11,7 @@ const DEVFRAME_CONNECTION_KEY = "__DEVFRAME_CONNECTION__";
10
11
  /**
11
12
  * Route the WebSocket RPC endpoint is bound to, relative to a devframe's
12
13
  * base path. Sits next to `__connection.json` so the deployed SPA can reach
13
- * it on the same origin it loaded from — the dev server shares one port for
14
+ * it on the same origin it loaded from: the dev server shares one port for
14
15
  * both HTTP and WS, and a host server (Vite, etc.) can mount the WS upgrade
15
16
  * handler here without colliding with its own routes (HMR, asset serving).
16
17
  */
@@ -20,7 +21,7 @@ const DEVFRAME_WS_ROUTE = "__ws";
20
21
  * path. A single method-dispatched route: `GET` opens the event stream
21
22
  * (server→client), `POST` carries RPC frames (client→server). Sits next to
22
23
  * `__connection.json` so the deployed SPA reaches it on the same origin it
23
- * loaded from — the transport for hosts and proxies where the WebSocket
24
+ * loaded from; the transport for hosts and proxies where the WebSocket
24
25
  * upgrade isn't available.
25
26
  */
26
27
  const DEVFRAME_SSE_ROUTE = "__sse";
@@ -34,7 +35,7 @@ const DEVFRAME_SSE_SESSION_HEADER = "x-birpc-session";
34
35
  /**
35
36
  * Route the Streamable-HTTP MCP endpoint is bound to, relative to a
36
37
  * devframe's base path. Sits next to `__connection.json` and the WS route
37
- * so an MCP client reaches it on the same origin the SPA loaded from — the
38
+ * so an MCP client reaches it on the same origin the SPA loaded from; the
38
39
  * dev server shares one port for HTTP, WS, and MCP. Opt-in via `cli.mcp`.
39
40
  */
40
41
  const DEVFRAME_MCP_ROUTE = "__mcp";
@@ -79,7 +80,7 @@ const DEVFRAME_VIEWER_ORIGIN_TOKEN_QUERY_PARAM = "devframe_viewer_origin_token";
79
80
  /**
80
81
  * `postMessage` type the remote-assets fallback page posts to `window.parent`
81
82
  * on load. That page is what a devframe serves (with a 502) when its client
82
- * assets can be reached neither locally nor through their CDN provider — the
83
+ * assets can be reached neither locally nor through their CDN provider; the
83
84
  * message lets an embedding viewer replace the bare page with its own UI
84
85
  * (`@devframes/hub-ui` does, in its iframe view). Payload shape:
85
86
  * `RemoteAssetsErrorMessage` (`devframe/types`).
@@ -87,7 +88,7 @@ const DEVFRAME_VIEWER_ORIGIN_TOKEN_QUERY_PARAM = "devframe_viewer_origin_token";
87
88
  const DEVFRAME_REMOTE_ASSETS_ERROR_MESSAGE_TYPE = DEVFRAME_EVENTS.postMessage.remoteAssetsError;
88
89
  /**
89
90
  * Prefix that marks an RPC method as callable before a connection is
90
- * trusted. This is the *only* rule the pre-trust gate applies — there is no
91
+ * trusted. This is the *only* rule the pre-trust gate applies; there is no
91
92
  * per-method allowlist. Any handshake method a host adapter needs to reach
92
93
  * before authentication must be named `anonymous:<rest>` (e.g.
93
94
  * `anonymous:devframe:auth`).