devframe 0.8.2 → 0.9.0-beta.10

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 (127) hide show
  1. package/dist/_shared-BPmX9fqK.d.mts +41 -0
  2. package/dist/_shared-CbZ_yhbz.mjs +68 -0
  3. package/dist/adapters/build.d.mts +10 -12
  4. package/dist/adapters/build.mjs +26 -29
  5. package/dist/adapters/cac.d.mts +1 -1
  6. package/dist/adapters/cac.mjs +156 -1
  7. package/dist/adapters/dev.d.mts +38 -46
  8. package/dist/adapters/dev.mjs +2 -1
  9. package/dist/adapters/embedded.d.mts +1 -1
  10. package/dist/adapters/initiate.d.mts +224 -0
  11. package/dist/adapters/initiate.mjs +2 -0
  12. package/dist/adapters/mcp.d.mts +24 -7
  13. package/dist/adapters/mcp.mjs +2 -2
  14. package/dist/{agent-tool-name-C3b5vEwJ.mjs → agent-tool-name-EgfoFO8C.mjs} +0 -3
  15. package/dist/cli/main.d.mts +0 -2
  16. package/dist/cli/main.mjs +4 -8
  17. package/dist/client/index.d.mts +71 -7
  18. package/dist/client/index.mjs +720 -1540
  19. package/dist/constants.d.mts +28 -7
  20. package/dist/constants.mjs +28 -7
  21. package/dist/{context-DoSozfvx.d.mts → context-B3YUu_95.d.mts} +19 -1
  22. package/dist/{host-h3-D2hYZvDK.mjs → context-CEe4PBz1.mjs} +25 -557
  23. package/dist/{context-CBg8iRbQ.mjs → context-xdynGSLP.mjs} +10 -1
  24. package/dist/dev--rAPzbvO.mjs +239 -0
  25. package/dist/{devframe-mQ4qZAuo.d.mts → devframe-DJMg0WLe.d.mts} +181 -134
  26. package/dist/{diagnostics-hwjXp_UV.mjs → diagnostics-CD8nlgll.mjs} +1 -3
  27. package/dist/{diagnostics-D7wM2cwM.mjs → diagnostics-DOQPnQmX.mjs} +51 -5
  28. package/dist/dist-eNI9qM_I.mjs +228 -0
  29. package/dist/host-agent-xLCSe65D.mjs +264 -0
  30. package/dist/host-h3-Crkzm42q.mjs +26 -0
  31. package/dist/{fetch-BKaD0Vb3.mjs → http-DYpK0cUi.mjs} +42 -11
  32. package/dist/{index-b64Uuhy2.d.mts → index-CB-fSUyn.d.mts} +2 -2
  33. package/dist/{index-Dbw1p5ch.d.mts → index-tdrk1bzV.d.mts} +3 -32
  34. package/dist/index.d.mts +12 -5
  35. package/dist/index.mjs +8 -1
  36. package/dist/{instance-registry-BnnA2Eoh.mjs → instance-registry-WvQkt42E.mjs} +9 -8
  37. package/dist/instance-shell-CMFyszWJ.mjs +486 -0
  38. package/dist/instance-shell-CljiKq1c.d.mts +255 -0
  39. package/dist/internal/index.d.mts +397 -0
  40. package/dist/internal/index.mjs +9 -0
  41. package/dist/node/auth.d.mts +2 -2
  42. package/dist/node/auth.mjs +1 -1
  43. package/dist/node/hub-internals.d.mts +2 -14
  44. package/dist/node/hub-internals.mjs +2 -2
  45. package/dist/node/index.d.mts +4 -268
  46. package/dist/node/index.mjs +3 -5
  47. package/dist/nostics-CzECRXpE.mjs +59 -0
  48. package/dist/nostics-SPGDgHEP.d.mts +33 -0
  49. package/dist/recipes/common-rpc-functions.d.mts +4 -4
  50. package/dist/recipes/interactive-auth.d.mts +3 -3
  51. package/dist/recipes/interactive-auth.mjs +8 -8
  52. package/dist/remote-assets-Bg4gCUZ_.d.mts +123 -0
  53. package/dist/remote-assets-nTTxY2MU.mjs +636 -0
  54. package/dist/rolldown-runtime-JspESFgx.mjs +35 -0
  55. package/dist/rpc/dump.d.mts +77 -1
  56. package/dist/rpc/dump.mjs +1 -1
  57. package/dist/rpc/index.d.mts +3 -3
  58. package/dist/rpc/index.mjs +4 -18
  59. package/dist/rpc/transports/sse-client.d.mts +2 -0
  60. package/dist/rpc/transports/sse-client.mjs +142 -0
  61. package/dist/rpc/transports/sse-server.d.mts +61 -0
  62. package/dist/rpc/transports/sse-server.mjs +209 -0
  63. package/dist/rpc/transports/ws-bun.d.mts +35 -0
  64. package/dist/rpc/transports/ws-bun.mjs +31 -0
  65. package/dist/rpc/transports/ws-client.d.mts +1 -1
  66. package/dist/rpc/transports/ws-client.mjs +10 -18
  67. package/dist/rpc/transports/ws-server.d.mts +2 -2
  68. package/dist/rpc/transports/ws-server.mjs +2 -235
  69. package/dist/rpc-core-Cc4lucI0.d.mts +48 -0
  70. package/dist/rpc-core-DMTe-hLo.mjs +81 -0
  71. package/dist/{serialization-C8Mnw9hK.mjs → serialization-BGzEwAdr.mjs} +2 -2
  72. package/dist/{shared-state-6kHolYZy.mjs → shared-state-fRRbRUtD.mjs} +1 -1
  73. package/dist/sse-client-CFBOIaUi.d.mts +37 -0
  74. package/dist/state-Cc1IeSmQ.mjs +1291 -0
  75. package/dist/{dump-CgZShDRB.mjs → static-BPZ1_OPA.mjs} +3 -266
  76. package/dist/storage-CYye7P7L.mjs +137 -0
  77. package/dist/types/index.d.mts +6 -4
  78. package/dist/types/index.mjs +1 -6
  79. package/dist/{types-CnJSgRVa.d.mts → types-Djq7CBXh.d.mts} +0 -7
  80. package/dist/utils/agent-tool-name.d.mts +0 -3
  81. package/dist/utils/agent-tool-name.mjs +0 -3
  82. package/dist/utils/events.d.mts +1 -1
  83. package/dist/utils/get-port.d.mts +17 -0
  84. package/dist/utils/get-port.mjs +2 -0
  85. package/dist/utils/launch-editor.mjs +1 -25
  86. package/dist/utils/nostics.d.mts +2 -0
  87. package/dist/utils/nostics.mjs +2 -0
  88. package/dist/utils/open.d.mts +2 -10
  89. package/dist/utils/open.mjs +56 -1
  90. package/dist/utils/remote-assets.d.mts +15 -0
  91. package/dist/utils/remote-assets.mjs +2 -0
  92. package/dist/utils/serve-static.d.mts +13 -5
  93. package/dist/utils/serve-static.mjs +119 -9
  94. package/dist/utils/shared-state.d.mts +1 -1
  95. package/dist/utils/shared-state.mjs +1 -1
  96. package/dist/utils/simple-schema.d.mts +101 -1
  97. package/dist/utils/streaming-channel.d.mts +1 -1
  98. package/dist/validation-CpXFB6Dz.mjs +266 -0
  99. package/dist/wire-codec-0K-o5MYW.mjs +56 -0
  100. package/dist/{ws-client-B6Tnr0ic.d.mts → ws-client-DhjNyQo3.d.mts} +7 -2
  101. package/dist/ws-server-BdSLrhxE.mjs +267 -0
  102. package/dist/{ws-server-uKQcClcJ.d.mts → ws-server-D1d3QM9f.d.mts} +90 -9
  103. package/package.json +13 -12
  104. package/skills/devframe/SKILL.md +91 -93
  105. package/dist/_shared-bWRzeSa0.mjs +0 -19
  106. package/dist/adapters/cli.d.mts +0 -11
  107. package/dist/adapters/cli.mjs +0 -6
  108. package/dist/cac-D4_9ok0z.mjs +0 -157
  109. package/dist/dev-Bc49u3qg.mjs +0 -439
  110. package/dist/diagnostics-reporter-CsIG85Q5.mjs +0 -38
  111. package/dist/helpers/vite.d.mts +0 -100
  112. package/dist/helpers/vite.mjs +0 -105
  113. package/dist/http-C4T68YV6.mjs +0 -38
  114. package/dist/index-vAX6bYuc.d.mts +0 -78
  115. package/dist/open-Deb5xmIT.mjs +0 -547
  116. package/dist/recipes/open-helpers.d.mts +0 -6
  117. package/dist/recipes/open-helpers.mjs +0 -6
  118. package/dist/server-CD8XmBXl.mjs +0 -167
  119. package/dist/server-UHWae43Q.d.mts +0 -149
  120. package/dist/simple-schema-BDzLeJDk.d.mts +0 -102
  121. package/dist/state-BeUHDDjk.mjs +0 -108
  122. package/dist/storage-CTNVbuFB.mjs +0 -1122
  123. package/dist/utils/promise.d.mts +0 -8
  124. package/dist/utils/promise.mjs +0 -15
  125. package/dist/utils/scope.d.mts +0 -11
  126. package/dist/utils/scope.mjs +0 -15
  127. package/skills/devframe/templates/spa-devframe.ts +0 -38
@@ -0,0 +1,224 @@
1
+ import { F as DevframeStorageScope, R as DevframeNodeRpcSession, c as DevframeWsOptions, d as ConnectionMeta, g as DevframeNodeContext, l as McpRouteOptions, n as DevframeDefinition, s as DevframeSseOptions, u as DevframeAuthHandler } from "../devframe-DJMg0WLe.mjs";
2
+ import { d as DevframeRpcConnection, n as WsOriginRegistry, u as DevframeNodeRpcSessionMeta } from "../ws-server-D1d3QM9f.mjs";
3
+ import { o as StaticAssetsSource } from "../remote-assets-Bg4gCUZ_.mjs";
4
+ import { c as StartedServer, f as DevframeInstanceRecord } from "../instance-shell-CljiKq1c.mjs";
5
+ import { Buffer } from "node:buffer";
6
+ import { IncomingMessage, Server, ServerResponse } from "node:http";
7
+ import { Duplex } from "node:stream";
8
+ import { H3 } from "h3";
9
+ //#region src/adapters/initiate.d.ts
10
+ interface InitDevframeOptions {
11
+ /**
12
+ * Mount base the handler answers under (e.g. `/__my-tool/`) — required so
13
+ * the mount path is explicit at the call site. A handler is by definition
14
+ * mounted *inside* a host app's origin; the resolved value is echoed back
15
+ * as {@link DevframeInstance.base} so route/middleware code references it
16
+ * instead of repeating the string. `resolveBasePath(def, 'hosted')` gives
17
+ * the conventional `def.basePath ?? /__<id>/`.
18
+ */
19
+ base: string;
20
+ /**
21
+ * Override `def.cli?.distDir`. When neither is set — or `false` is passed
22
+ * to suppress the definition's own `distDir` — the handler runs in
23
+ * **bridge mode**: only `__connection.json`, the WS endpoint, and the MCP
24
+ * route (when enabled) are served; the SPA is hosted elsewhere.
25
+ */
26
+ distDir?: StaticAssetsSource | false;
27
+ /**
28
+ * Share the host's `node:http` server for the WebSocket RPC endpoint: the
29
+ * upgrade listener binds to `<base>__ws` on this server, so no extra port
30
+ * is needed and the socket follows the app through proxies/HTTPS. Hosts
31
+ * whose handlers never see upgrades (Next.js route handlers, Nitro,
32
+ * Rsbuild) ask for a side-car instead with `ws: { sidecar: true }`; hosts
33
+ * that own their upgrade routing wire {@link DevframeInstance.attach} /
34
+ * {@link DevframeInstance.handleUpgrade} themselves.
35
+ */
36
+ server?: Server;
37
+ /**
38
+ * Explicit control over how the browser reaches the RPC WebSocket —
39
+ * advertised in `__connection.json`. The **local binding** resolves in
40
+ * precedence order `ws.port` (pinned side-car) > `server` (shared upgrade)
41
+ * > `ws.sidecar` (auto-port side-car) > none (the host drives the socket
42
+ * through {@link DevframeInstance.attach}). `ws.url` controls the
43
+ * advertisement* only: the browser dials it verbatim (a tunnel/relay),
44
+ * while the local binding keeps following the options above — and on its
45
+ * own it means an external server owns both the transport and its auth.
46
+ * Pass `false` to serve no WebSocket at all — clients connect over the
47
+ * SSE endpoint instead (`backend: 'sse'`).
48
+ */
49
+ ws?: DevframeWsOptions | false;
50
+ /**
51
+ * SSE RPC endpoint control — enabled by default at `<base>__sse` as the
52
+ * more portable transport alongside the WebSocket. Pass `false` to
53
+ * disable, or a {@link DevframeSseOptions} to rename the route.
54
+ */
55
+ sse?: boolean | DevframeSseOptions;
56
+ /**
57
+ * Bind host for a side-car WebSocket server (default: `def.cli?.host ??
58
+ * 'localhost'`). Irrelevant for the `server` / `ws.url` tiers.
59
+ */
60
+ host?: string;
61
+ /**
62
+ * Authentication for the RPC endpoint. A handler mounted inside an app
63
+ * server is reachable by anything that can open its socket, so it **gates
64
+ * by default**: when unset (or `true`), devframe's interactive OTP handler
65
+ * is wired and its code/link banner prints once the public origin is known
66
+ * (derived from the first request, or `origin`). Pass a
67
+ * {@link DevframeAuthHandler} for a custom scheme, or `false` to opt out
68
+ * for a single-user localhost setup that owns the trust boundary another
69
+ * way. Ignored for the `ws.url` tier — the server behind that URL owns auth.
70
+ */
71
+ auth?: boolean | DevframeAuthHandler;
72
+ /**
73
+ * Expose a route-based MCP server (Streamable-HTTP) at `<base>__mcp` and
74
+ * advertise it in `__connection.json`. Overrides `def.cli?.mcp`;
75
+ * `undefined` falls through to it. See {@link McpRouteOptions}.
76
+ */
77
+ mcp?: boolean | McpRouteOptions;
78
+ /**
79
+ * Public origin the host app is reachable at (e.g. `http://localhost:3000`),
80
+ * or a getter for hosts that resolve it late. When omitted (or the getter
81
+ * returns a falsy value), it is derived lazily from the first request the
82
+ * handler serves — used for the auth banner's magic link and absolute dock
83
+ * URLs.
84
+ */
85
+ origin?: string | (() => string);
86
+ /**
87
+ * Publish this instance in the global registry (`~/.devframe/instances/`)
88
+ * so discovery tooling (`devframe connect`, the inspect plugin's Instances
89
+ * tab) finds it without port guessing. Registration is a dynamic import
90
+ * that fires once the public origin resolves and is torn down on
91
+ * {@link DevframeInstance.close}. Defaults to off; pass `true` to enable, or
92
+ * an object to override individual record fields (`id`, `name`, `mcp`, …).
93
+ */
94
+ register?: boolean | Partial<DevframeInstanceRecord>;
95
+ /** Parsed flag bag forwarded to `def.setup(ctx, { flags })`. */
96
+ flags?: Record<string, unknown>;
97
+ /**
98
+ * Extra origins to accept on the WS upgrade beyond the loopback default.
99
+ * Add your LAN/tunnel origin here when reaching the tool from another
100
+ * host. Pass `false` to disable origin checking entirely (not
101
+ * recommended). Default: loopback-only.
102
+ */
103
+ allowedOrigins?: readonly string[] | WsOriginRegistry | false;
104
+ /**
105
+ * h3 app to mount the handler's routes on. When omitted a fresh internal
106
+ * app is created — the common middleware case. An adapter that owns the
107
+ * whole server (e.g. `createDevServer`) passes its own app so callers can
108
+ * compose custom routes ahead of devframe's.
109
+ */
110
+ app?: H3;
111
+ /**
112
+ * Override where persisted devframe state lives, per
113
+ * `DevframeHost.getStorageDir`. Defaults to the standalone host layout
114
+ * (`.devframe/`, `node_modules/.<id>/devframe/`, `~/.<id>/devframe/`).
115
+ */
116
+ getStorageDir?: (scope: DevframeStorageScope) => string;
117
+ /**
118
+ * Destroy upgrade requests on a shared `server` that don't match the WS
119
+ * route, instead of leaving them for the host's own upgrade handlers.
120
+ * Enable when devframe's adapter owns the server outright (nothing else
121
+ * handles its upgrades) so off-route clients are rejected promptly.
122
+ * Default: `false` (coexist-friendly).
123
+ */
124
+ destroyUnmatchedUpgrades?: boolean;
125
+ /**
126
+ * Called once per new RPC connection, right after its session is created.
127
+ * Forwarded verbatim to the underlying transport.
128
+ */
129
+ onPeerConnect?: (connection: DevframeRpcConnection, session: DevframeNodeRpcSession) => void;
130
+ /**
131
+ * Called once per closed RPC connection, right after the transport's own
132
+ * disconnect bookkeeping runs.
133
+ */
134
+ onPeerDisconnect?: (connection: DevframeRpcConnection, meta: DevframeNodeRpcSessionMeta) => void;
135
+ }
136
+ interface DevframeInstance {
137
+ /**
138
+ * The normalized mount base this instance answers under (leading and
139
+ * trailing slash, e.g. `/__my-tool/`). Reference it when wiring the mount
140
+ * — route guards, middleware path checks — instead of repeating the
141
+ * string.
142
+ */
143
+ base: string;
144
+ /**
145
+ * Web-standard request handler — mount it on a catch-all route under
146
+ * {@link DevframeInstance.base} (Next.js route handler, SvelteKit
147
+ * `+server.ts`, Hono `c.req.raw`, Nitro `toWebRequest(event)`, …).
148
+ * Requests outside the base 404.
149
+ */
150
+ handler: (request: Request) => Promise<Response>;
151
+ /**
152
+ * Connect/Express-style middleware over the same surface — for
153
+ * `viteServer.middlewares.use(handler.nodeMiddleware)` or any other
154
+ * node middleware stack. Mount it un-prefixed: paths outside the base
155
+ * call `next()` so the rest of the stack keeps working.
156
+ */
157
+ nodeMiddleware: (req: IncomingMessage, res: ServerResponse, next?: (err?: unknown) => void) => void;
158
+ /**
159
+ * Route a host server's `upgrade` events to the RPC socket, returning a
160
+ * detach function — the manual counterpart to the `server` option, for
161
+ * hosts that get their `node:http` server only after the instance exists.
162
+ * Available on the default tier; a configured transport (`server`,
163
+ * `ws.port`, `ws.sidecar`, `ws.url`) already owns the socket and reports
164
+ * `DF0055` / `DF0056` instead.
165
+ */
166
+ attach: (server: Server) => () => void;
167
+ /**
168
+ * Complete a single `upgrade` event on the RPC socket, for hosts that
169
+ * already own an `upgrade` listener: `server.on('upgrade',
170
+ * instance.handleUpgrade)`. Same availability as
171
+ * {@link DevframeInstance.attach}.
172
+ */
173
+ handleUpgrade: (req: IncomingMessage, socket: Duplex, head: Buffer) => void;
174
+ /**
175
+ * Resolves once `def.setup` has run and the WebSocket binding is live.
176
+ * `handler`/`nodeMiddleware` await it internally, so hosts never race
177
+ * initialization — await it yourself only when you need the timing.
178
+ */
179
+ ready: Promise<void>;
180
+ /** The node context, once initialized — for advanced wiring (own WS transport, extra RPC registration). */
181
+ context: Promise<DevframeNodeContext>;
182
+ /**
183
+ * The `ConnectionMeta` this handler serves at `<base>__connection.json`.
184
+ * Only readable after initialization (`DF0054` otherwise).
185
+ */
186
+ connectionMeta: () => ConnectionMeta;
187
+ /** Tear down: WS transport/side-car, MCP sessions. */
188
+ close: () => Promise<void>;
189
+ }
190
+ /**
191
+ * Live internals of a handler, for the first-party adapters built on it
192
+ * (`createDevServer` exposes the transport's `ws`/`rpcGroup` through its
193
+ * `StartedServer` contract).
194
+ *
195
+ * @internal
196
+ */
197
+ interface DevframeInstanceInternals {
198
+ /** The bound HTTP+WS server handle backing the side-car / shared-server WS tiers. */
199
+ readonly started?: StartedServer;
200
+ /** The resolved auth handler when the gate is active. */
201
+ readonly authHandler?: DevframeAuthHandler;
202
+ }
203
+ /** @internal */
204
+ declare function getInstanceInternals(handler: object): DevframeInstanceInternals;
205
+ /**
206
+ * Serve a devframe through one framework-agnostic, web-standard handler —
207
+ * the SPA, `__connection.json` discovery, the WebSocket RPC endpoint, the
208
+ * auth gate, and the optional MCP route, all under a single mount base.
209
+ * Mount `handler` on any framework's catch-all route (or `nodeMiddleware` on
210
+ * a connect stack) and the devframe is live inside that app.
211
+ *
212
+ * The factory is synchronous and kicks off initialization eagerly;
213
+ * `handler`/`nodeMiddleware` await readiness internally. Nothing binds a port
214
+ * on its own: the WebSocket resolves in precedence order — `ws.port` (pinned
215
+ * side-car) > `server` (shared upgrade at `<base>__ws`) > `ws.sidecar`
216
+ * (auto-port side-car) > the host driving upgrades itself through
217
+ * {@link DevframeInstance.attach} — while `ws.url`, when set, overrides the
218
+ * advertised* endpoint (the tunnel pattern) and on its own hands the whole
219
+ * transport to an external server. `__connection.json` reflects whichever
220
+ * combination is active.
221
+ */
222
+ declare function initDevframe(def: DevframeDefinition, options: InitDevframeOptions): DevframeInstance;
223
+ //#endregion
224
+ export { DevframeInstance, DevframeInstanceInternals, InitDevframeOptions, getInstanceInternals, initDevframe };
@@ -0,0 +1,2 @@
1
+ import { n as getInstanceInternals, r as initDevframe } from "../dev--rAPzbvO.mjs";
2
+ export { getInstanceInternals, initDevframe };
@@ -1,4 +1,5 @@
1
- import { b as DevframeNodeContext, r as DevframeDefinition } from "../devframe-mQ4qZAuo.mjs";
1
+ import { g as DevframeNodeContext, n as DevframeDefinition } from "../devframe-DJMg0WLe.mjs";
2
+ import { H3 } from "h3";
2
3
  import "@modelcontextprotocol/server";
3
4
  //#region src/adapters/mcp/build-server.d.ts
4
5
  interface CreateMcpServerOptions {
@@ -31,9 +32,6 @@ interface McpServerHandle {
31
32
  /**
32
33
  * Build an MCP server over the agent surface of a devframe definition.
33
34
  * Currently supports `stdio` transport only.
34
- *
35
- * @experimental The agent-native surface is experimental and may change
36
- * without a major version bump until it stabilizes.
37
35
  */
38
36
  declare function createMcpServer(definition: DevframeDefinition, options?: CreateMcpServerOptions): Promise<McpServerHandle>;
39
37
  //#endregion
@@ -80,9 +78,28 @@ interface McpFetchHandler {
80
78
  * loopback-default DNS-rebinding protection that — unlike the WS upgrade's
81
79
  * `isAllowedOrigin` — also rejects `Origin`-less requests, so a route-based
82
80
  * endpoint isn't reachable by an arbitrary local process.
83
- *
84
- * @experimental
85
81
  */
86
82
  declare function createMcpFetchHandler(ctx: DevframeNodeContext, options: CreateMcpFetchHandlerOptions): McpFetchHandler;
87
83
  //#endregion
88
- export { type CreateMcpFetchHandlerOptions, type CreateMcpServerOptions, type McpFetchHandler, type McpServerHandle, createMcpFetchHandler, createMcpServer };
84
+ //#region src/adapters/mcp/http.d.ts
85
+ interface MountMcpHttpOptions extends CreateMcpFetchHandlerOptions {}
86
+ interface MountedMcpHttp {
87
+ /** Tear down every live MCP session (closes servers, drops subscriptions). */
88
+ dispose: () => Promise<void>;
89
+ }
90
+ /**
91
+ * Mount an MCP Streamable-HTTP endpoint on an h3 app at `path` — the h3
92
+ * binding over {@link createMcpFetchHandler}, which owns the sessions, the
93
+ * origin gate, and the transport plumbing.
94
+ *
95
+ * The handler is web-standard — it takes the h3 event's web `Request` and
96
+ * returns a web `Response` (an SSE `ReadableStream` body for the
97
+ * server→client stream). We copy that response onto `event.res` and return
98
+ * its body rather than returning the `Response` object directly, so a
99
+ * legitimate MCP 404 (unknown session) isn't swallowed by h3's
100
+ * "Response-with-404 falls through to the next handler" rule (which would
101
+ * otherwise hand the request to the SPA static catch-all).
102
+ */
103
+ declare function mountMcpHttp(app: H3, ctx: DevframeNodeContext, path: string, options: MountMcpHttpOptions): MountedMcpHttp;
104
+ //#endregion
105
+ export { type CreateMcpFetchHandlerOptions, type CreateMcpServerOptions, type McpFetchHandler, type McpServerHandle, type MountMcpHttpOptions, type MountedMcpHttp, createMcpFetchHandler, createMcpServer, mountMcpHttp };
@@ -1,2 +1,2 @@
1
- import { n as createMcpServer, t as createMcpFetchHandler } from "../fetch-BKaD0Vb3.mjs";
2
- export { createMcpFetchHandler, createMcpServer };
1
+ import { i as createMcpServer, n as mountMcpHttp, r as createMcpFetchHandler } from "../http-DYpK0cUi.mjs";
2
+ export { createMcpFetchHandler, createMcpServer, mountMcpHttp };
@@ -23,9 +23,6 @@ const MAX_TOOL_NAME_LENGTH = 128;
23
23
  * A plain string transform with no node dependency, so browser-side UIs
24
24
  * that display a tool's id (e.g. the inspect plugin's agent view) can
25
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
26
  */
30
27
  function toAgentToolName(id) {
31
28
  return id.replace(/[^\w-]+/g, "_").slice(0, MAX_TOOL_NAME_LENGTH);
@@ -3,8 +3,6 @@
3
3
  * The `devframe` bin — the framework's own CLI, distinct from the per-app
4
4
  * CLI shells authors build with `createCac(definition)`. It hosts the
5
5
  * app-independent commands; today that is `connect`, the MCP connector.
6
- *
7
- * @experimental
8
6
  */
9
7
  declare function runDevframeCli(argv?: string[]): Promise<void>;
10
8
  //#endregion
package/dist/cli/main.mjs CHANGED
@@ -1,7 +1,7 @@
1
- import { t as diagnostics } from "../diagnostics-D7wM2cwM.mjs";
2
- import { n as probeDevframeOrigin, t as listLiveDevframeInstances } from "../instance-registry-BnnA2Eoh.mjs";
3
- import { t as toAgentToolName } from "../agent-tool-name-C3b5vEwJ.mjs";
4
- import { Diagnostic } from "nostics";
1
+ import { t as Diagnostic } from "../nostics-CzECRXpE.mjs";
2
+ import { t as diagnostics } from "../diagnostics-DOQPnQmX.mjs";
3
+ import { n as listLiveDevframeInstances, r as probeDevframeOrigin } from "../instance-registry-WvQkt42E.mjs";
4
+ import { t as toAgentToolName } from "../agent-tool-name-EgfoFO8C.mjs";
5
5
  import process from "node:process";
6
6
  import { joinURL } from "ufo";
7
7
  import { cac } from "cac";
@@ -54,8 +54,6 @@ const GATEWAY_TOOLS = [{
54
54
  * the instance registry and list each one's MCP tools) and
55
55
  * `devframe_connect_call-tool` (invoke one tool on one instance over its
56
56
  * Streamable-HTTP endpoint) — and holds no domain knowledge of its own.
57
- *
58
- * @experimental
59
57
  */
60
58
  async function startConnectServer(options = {}) {
61
59
  const sdk = await importSdk();
@@ -259,8 +257,6 @@ function keepAlive() {
259
257
  * The `devframe` bin — the framework's own CLI, distinct from the per-app
260
258
  * CLI shells authors build with `createCac(definition)`. It hosts the
261
259
  * app-independent commands; today that is `connect`, the MCP connector.
262
- *
263
- * @experimental
264
260
  */
265
261
  async function runDevframeCli(argv = process.argv) {
266
262
  const cli = cac("devframe");
@@ -1,7 +1,8 @@
1
- import { $ as DevframeRpcServerFunctions, F as ScopedSharedStates, I as SettingsForNamespace, J as RpcSharedStateHost, N as ScopedRpcFn, O as DevframeSettings, P as ScopedServerFunctions, Q as DevframeRpcClientFunctions, _ as ConnectionMeta, at as StreamReader, ht as SharedState, jt as EventEmitter, ot as StreamSink, q as RpcSharedStateGetOptions } from "../devframe-mQ4qZAuo.mjs";
2
- import { _ as RpcFunctionDefinition, w as RpcFunctionsCollector } from "../types-CnJSgRVa.mjs";
3
- import { E as RpcCacheOptions, T as RpcCacheManager } from "../index-Dbw1p5ch.mjs";
4
- import { t as WsRpcChannelOptions } from "../ws-client-B6Tnr0ic.mjs";
1
+ import { $ as StreamReader, A as ScopedServerFunctions, H as RpcSharedStateHost, K as DevframeRpcClientFunctions, M as SettingsForNamespace, Tt as EventEmitter, V as RpcSharedStateGetOptions, d as ConnectionMeta, et as StreamSink, j as ScopedSharedStates, k as ScopedRpcFn, lt as SharedState, q as DevframeRpcServerFunctions, w as DevframeSettings } from "../devframe-DJMg0WLe.mjs";
2
+ import { f as RpcCacheManager, p as RpcCacheOptions } from "../index-tdrk1bzV.mjs";
3
+ import { _ as RpcFunctionDefinition, w as RpcFunctionsCollector } from "../types-Djq7CBXh.mjs";
4
+ import { t as SseRpcChannelOptions } from "../sse-client-CFBOIaUi.mjs";
5
+ import { t as WsRpcChannelOptions } from "../ws-client-DhjNyQo3.mjs";
5
6
  import { BirpcOptions, BirpcReturn } from "birpc";
6
7
  //#region src/client/connection.d.ts
7
8
  interface DevframeConnection {
@@ -251,7 +252,24 @@ interface DevframeRpcClientOptions extends SetupDevframeConnectionOptions {
251
252
  * @default true
252
253
  */
253
254
  simpleAuth?: boolean;
255
+ /**
256
+ * Which live transport to connect over:
257
+ *
258
+ * - `'auto'` (default) — trust the server's advertisement: its declared
259
+ * primary (`backend`), preferring the WebSocket when both endpoints are
260
+ * present. A server that couldn't bind a socket advertises SSE as its
261
+ * primary, so no client-side fallback probing is needed.
262
+ * - `'websocket'` / `'sse'` — pin one transport; connecting fails with a
263
+ * clear error when the server doesn't advertise it. Reach for
264
+ * `transport: 'sse'` when an intermediary silently strips WS upgrades —
265
+ * something the server cannot detect.
266
+ *
267
+ * A `static` backend ignores this option (there is no live transport).
268
+ */
269
+ transport?: 'auto' | 'websocket' | 'sse';
254
270
  wsOptions?: Partial<WsRpcChannelOptions>;
271
+ /** Channel overrides for the SSE transport — the `wsOptions` counterpart. */
272
+ sseOptions?: Partial<SseRpcChannelOptions>;
255
273
  rpcOptions?: Partial<BirpcOptions<DevframeRpcServerFunctions, DevframeRpcClientFunctions, boolean>>;
256
274
  cacheOptions?: boolean | Partial<RpcCacheOptions>;
257
275
  /**
@@ -282,10 +300,16 @@ interface DevframeRpcClient {
282
300
  */
283
301
  readonly status: DevframeConnectionStatus;
284
302
  /**
285
- * The most recent connection-level error (WebSocket error, refused trust, or
286
- * failed connection-meta load), or `null` when the connection is healthy.
303
+ * The most recent connection-level error (transport error, refused trust,
304
+ * or failed connection-meta load), or `null` when the connection is healthy.
287
305
  */
288
306
  readonly connectionError: Error | null;
307
+ /**
308
+ * The transport this client is actually connected over — `'websocket'`,
309
+ * `'sse'`, or `'static'`. Reflects the resolution of the `transport`
310
+ * option against the server's advertisement.
311
+ */
312
+ readonly transport: 'websocket' | 'sse' | 'static';
289
313
  /**
290
314
  * The complete connection used by this client, including the metadata source
291
315
  * URL external viewers use to resolve relative resources.
@@ -362,8 +386,27 @@ interface DevframeRpcClient {
362
386
  <NS extends string>(namespace: NS): DevframeScopedClientContext<NS, SettingsForNamespace<NS>>;
363
387
  (namespace?: null | ''): DevframeRpcClient;
364
388
  };
389
+ /**
390
+ * Close the connection. A `static` backend is a no-op (there is no live socket to close);
391
+ * a `websocket` backend closes the underlying `WebSocket`, which the server observes as a
392
+ * normal disconnect. Mirrors {@link WsRpcTransport.close} on the server side.
393
+ *
394
+ * There is no corresponding "reconnect" — a closed client is done. Discard it and call
395
+ * {@link getDevframeRpcClient} again to reconnect.
396
+ *
397
+ * Optional so a `DevframeRpcClientMode` implemented before this method existed — a custom
398
+ * transport, a hand-typed mock — still satisfies the interface; an absent `close` is treated
399
+ * as nothing to close.
400
+ */
401
+ close?: () => void;
365
402
  }
366
403
  interface DevframeRpcClientMode {
404
+ /**
405
+ * The transport this mode speaks. Optional so a mode implemented before
406
+ * this field existed — a custom transport, a hand-typed mock — still
407
+ * satisfies the interface; an absent value reads as `'websocket'`.
408
+ */
409
+ readonly transport?: 'websocket' | 'sse' | 'static';
367
410
  readonly isTrusted: boolean;
368
411
  readonly status: DevframeConnectionStatus;
369
412
  readonly connectionError: Error | null;
@@ -378,7 +421,17 @@ interface DevframeRpcClientMode {
378
421
  call: DevframeRpcClient['call'];
379
422
  callEvent: DevframeRpcClient['callEvent'];
380
423
  callOptional: DevframeRpcClient['callOptional'];
424
+ /** See {@link DevframeRpcClient.close}. */
425
+ close?: () => void;
381
426
  }
427
+ /**
428
+ * Resolve the requested `transport` option against what the server
429
+ * advertises. `'auto'` trusts the advertisement — the server's declared
430
+ * primary (`backend`), preferring the WebSocket when both endpoints are
431
+ * present; an explicit `'websocket'` / `'sse'` pins that transport and
432
+ * throws when the server doesn't advertise it.
433
+ */
434
+ declare function resolveClientTransport(requested: 'auto' | 'websocket' | 'sse', meta: ConnectionMeta): 'websocket' | 'sse' | 'static';
382
435
  declare function getDevframeRpcClient(options?: DevframeRpcClientOptions): Promise<DevframeRpcClient>;
383
436
  //#endregion
384
437
  //#region src/client/otp.d.ts
@@ -431,6 +484,17 @@ interface WsUrlLocation {
431
484
  */
432
485
  declare function resolveWsUrl(websocket: ConnectionMeta['websocket'], metaBaseUrl: string, loc: WsUrlLocation): string;
433
486
  //#endregion
487
+ //#region src/client/rpc-sse.d.ts
488
+ /**
489
+ * Resolve a {@link ConnectionMeta.sse} descriptor into a concrete
490
+ * `http(s)://` URL, with the same proxy-safe rules as `resolveWsUrl`: the
491
+ * object / relative-path forms resolve against where `__connection.json`
492
+ * was loaded (the client trusts its own location, never a server-baked
493
+ * hostname), while an explicit `port`/`host` (or a full `http(s)://` URL
494
+ * string) opts into a cross-origin endpoint.
495
+ */
496
+ declare function resolveSseUrl(sse: ConnectionMeta['sse'], metaBaseUrl: string, loc: WsUrlLocation): string;
497
+ //#endregion
434
498
  //#region src/client/settings.d.ts
435
499
  /**
436
500
  * Build the client-side `settings` surface for a scope namespace. Mirrors
@@ -441,4 +505,4 @@ declare function createClientSettings<T extends Record<string, any> = Record<str
441
505
  //#region src/client/index.d.ts
442
506
  declare const connectDevframe: typeof getDevframeRpcClient;
443
507
  //#endregion
444
- export { DevframeClientRpcHost, DevframeConnection, DevframeConnectionError, DevframeConnectionErrorKind, DevframeConnectionStatus, DevframeRpcClient, DevframeRpcClientCall, DevframeRpcClientCallEvent, DevframeRpcClientCallOptional, DevframeRpcClientMode, DevframeRpcClientOptions, DevframeRpcContext, DevframeScopedClientContext, DevframeScopedClientRpc, DevframeScopedClientStreamingHost, RpcClientEvents, RpcStreamingClientHost, SetupDevframeConnectionOptions, StreamingSubscribeOptions, type WsUrlLocation, authenticateWithUrlOtp, connectDevframe, consumeOtpFromUrl, createClientSettings, createRpcStreamingClientHost, createScopedClientContext, getDevframeConnection, getDevframeRpcClient, isCallableStatus, readOtpFromUrl, registerDevframeViewerOrigin, resolveWsUrl, setupDevframeConnection };
508
+ export { DevframeClientRpcHost, DevframeConnection, DevframeConnectionError, DevframeConnectionErrorKind, DevframeConnectionStatus, DevframeRpcClient, DevframeRpcClientCall, DevframeRpcClientCallEvent, DevframeRpcClientCallOptional, DevframeRpcClientMode, DevframeRpcClientOptions, DevframeRpcContext, DevframeScopedClientContext, DevframeScopedClientRpc, DevframeScopedClientStreamingHost, RpcClientEvents, RpcStreamingClientHost, SetupDevframeConnectionOptions, StreamingSubscribeOptions, type WsUrlLocation, authenticateWithUrlOtp, connectDevframe, consumeOtpFromUrl, createClientSettings, createRpcStreamingClientHost, createScopedClientContext, getDevframeConnection, getDevframeRpcClient, isCallableStatus, readOtpFromUrl, registerDevframeViewerOrigin, resolveClientTransport, resolveSseUrl, resolveWsUrl, setupDevframeConnection };