devframe 0.8.1 → 0.9.0-beta.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 (103) hide show
  1. package/dist/_shared-CttmCMBi.mjs +70 -0
  2. package/dist/_shared-DmpWW-HH.d.mts +43 -0
  3. package/dist/adapters/build.d.mts +1 -1
  4. package/dist/adapters/build.mjs +6 -5
  5. package/dist/adapters/cac.d.mts +1 -1
  6. package/dist/adapters/cac.mjs +157 -1
  7. package/dist/adapters/dev.d.mts +25 -34
  8. package/dist/adapters/dev.mjs +2 -1
  9. package/dist/adapters/embedded.d.mts +1 -1
  10. package/dist/adapters/initiate.d.mts +223 -0
  11. package/dist/adapters/initiate.mjs +2 -0
  12. package/dist/adapters/mcp.d.mts +26 -2
  13. package/dist/adapters/mcp.mjs +2 -2
  14. package/dist/cli/main.mjs +2 -2
  15. package/dist/client/index.d.mts +70 -6
  16. package/dist/client/index.mjs +743 -408
  17. package/dist/constants.d.mts +19 -6
  18. package/dist/constants.mjs +19 -6
  19. package/dist/{context-CQefP2jR.mjs → context-C33rR7n0.mjs} +1 -1
  20. package/dist/{context-DFzmxCLa.d.mts → context-CSCwoABx.d.mts} +1 -1
  21. package/dist/{host-h3-Kz7t5Xab.mjs → context-Du11TLcO.mjs} +5 -255
  22. package/dist/dev-BEveeA5H.mjs +233 -0
  23. package/dist/{devframe-qgCKL683.d.mts → devframe-Bdd9YXTy.d.mts} +88 -25
  24. package/dist/{diagnostics-B5-qHeqD.mjs → diagnostics-DLYH5oD3.mjs} +20 -0
  25. package/dist/dist-D8jAMwxU.mjs +227 -0
  26. package/dist/helpers/vite.d.mts +43 -39
  27. package/dist/helpers/vite.mjs +26 -38
  28. package/dist/host-agent-CpbAoqBx.mjs +230 -0
  29. package/dist/host-h3-CzCZwtuV.mjs +26 -0
  30. package/dist/{fetch-CK0S253E.mjs → http-DLr_cJZ7.mjs} +42 -4
  31. package/dist/{index-B7RgLw--.d.mts → index-CZRd2K1C.d.mts} +2 -2
  32. package/dist/{index-Dbw1p5ch.d.mts → index-DSCq4M4q.d.mts} +2 -31
  33. package/dist/index.d.mts +9 -4
  34. package/dist/index.mjs +8 -1
  35. package/dist/{instance-registry-D6fxYu36.mjs → instance-registry-BQqGoDO9.mjs} +9 -2
  36. package/dist/instance-shell-DBTXTSjN.d.mts +264 -0
  37. package/dist/instance-shell-KRdee1QF.mjs +485 -0
  38. package/dist/internal/index.d.mts +150 -0
  39. package/dist/internal/index.mjs +7 -0
  40. package/dist/node/auth.d.mts +2 -2
  41. package/dist/node/hub-internals.d.mts +2 -14
  42. package/dist/node/hub-internals.mjs +2 -2
  43. package/dist/node/index.d.mts +3 -267
  44. package/dist/node/index.mjs +3 -5
  45. package/dist/recipes/common-rpc-functions.d.mts +3 -3
  46. package/dist/recipes/interactive-auth.d.mts +3 -3
  47. package/dist/recipes/interactive-auth.mjs +6 -6
  48. package/dist/rolldown-runtime-JspESFgx.mjs +35 -0
  49. package/dist/rpc/dump.d.mts +77 -1
  50. package/dist/rpc/dump.mjs +1 -1
  51. package/dist/rpc/index.d.mts +2 -2
  52. package/dist/rpc/index.mjs +3 -17
  53. package/dist/rpc/transports/sse-client.d.mts +2 -0
  54. package/dist/rpc/transports/sse-client.mjs +142 -0
  55. package/dist/rpc/transports/sse-server.d.mts +61 -0
  56. package/dist/rpc/transports/sse-server.mjs +209 -0
  57. package/dist/rpc/transports/ws-bun.d.mts +35 -0
  58. package/dist/rpc/transports/ws-bun.mjs +31 -0
  59. package/dist/rpc/transports/ws-client.d.mts +1 -1
  60. package/dist/rpc/transports/ws-client.mjs +10 -18
  61. package/dist/rpc/transports/ws-server.d.mts +2 -2
  62. package/dist/rpc/transports/ws-server.mjs +2 -214
  63. package/dist/rpc-core-CGctXToO.d.mts +48 -0
  64. package/dist/rpc-core-CqcJkAu9.mjs +81 -0
  65. package/dist/{serialization-C8Mnw9hK.mjs → serialization-BHY8M5NQ.mjs} +1 -1
  66. package/dist/{shared-state-6kHolYZy.mjs → shared-state-fRRbRUtD.mjs} +1 -1
  67. package/dist/sse-client-BsIK3hMD.d.mts +37 -0
  68. package/dist/{dump-CgZShDRB.mjs → static-CvjkO8QE.mjs} +2 -265
  69. package/dist/{storage-Dzoc3NVC.mjs → storage-BcmVEJRc.mjs} +2 -2
  70. package/dist/types/index.d.mts +3 -3
  71. package/dist/types/index.mjs +1 -6
  72. package/dist/utils/events.d.mts +1 -1
  73. package/dist/utils/launch-editor.mjs +1 -25
  74. package/dist/utils/open.mjs +1 -1
  75. package/dist/utils/serve-static.mjs +1 -1
  76. package/dist/utils/shared-state.d.mts +1 -1
  77. package/dist/utils/shared-state.mjs +1 -1
  78. package/dist/utils/simple-schema.d.mts +101 -1
  79. package/dist/utils/streaming-channel.d.mts +1 -1
  80. package/dist/validation-BiuDXTKW.mjs +266 -0
  81. package/dist/wire-codec-9VhIKnyp.mjs +58 -0
  82. package/dist/{ws-client-B6Tnr0ic.d.mts → ws-client-CdNuATYa.d.mts} +6 -1
  83. package/dist/ws-server-Bk1hOG3X.mjs +267 -0
  84. package/dist/{ws-server-J-zkiOyp.d.mts → ws-server-Ces08fjP.d.mts} +102 -13
  85. package/package.json +10 -9
  86. package/skills/devframe/SKILL.md +84 -85
  87. package/dist/_shared-bWRzeSa0.mjs +0 -19
  88. package/dist/adapters/cli.d.mts +0 -11
  89. package/dist/adapters/cli.mjs +0 -6
  90. package/dist/cac-B1LM3zit.mjs +0 -157
  91. package/dist/dev-BSHFZGZr.mjs +0 -437
  92. package/dist/http-Dvgxujcu.mjs +0 -38
  93. package/dist/index-vAX6bYuc.d.mts +0 -78
  94. package/dist/recipes/open-helpers.d.mts +0 -6
  95. package/dist/recipes/open-helpers.mjs +0 -6
  96. package/dist/server-CXaDDUl0.mjs +0 -148
  97. package/dist/server-E9z4ZWbd.d.mts +0 -132
  98. package/dist/simple-schema-BDzLeJDk.d.mts +0 -102
  99. package/dist/utils/promise.d.mts +0 -8
  100. package/dist/utils/promise.mjs +0 -15
  101. package/dist/utils/scope.d.mts +0 -11
  102. package/dist/utils/scope.mjs +0 -15
  103. package/dist/{open-Deb5xmIT.mjs → open-Dz4V4irZ.mjs} +1 -1
@@ -1,9 +1,8 @@
1
+ import { d as RpcFunctionsCollectorBase } from "./index-DSCq4M4q.mjs";
1
2
  import { _ as RpcFunctionDefinition, v as RpcFunctionDefinitionAny } from "./types-CnJSgRVa.mjs";
2
- import { w as RpcFunctionsCollectorBase } from "./index-Dbw1p5ch.mjs";
3
- import { n as DevframeNodeRpcSessionMeta } from "./ws-server-J-zkiOyp.mjs";
3
+ import { d as DevframeRpcConnection, u as DevframeNodeRpcSessionMeta } from "./ws-server-Ces08fjP.mjs";
4
4
  import { CAC } from "cac";
5
5
  import { StandardSchemaV1 } from "@standard-schema/spec";
6
- import { Peer } from "crossws";
7
6
  import { BirpcReturn } from "birpc";
8
7
  import { Diagnostic, DiagnosticDefinition, defineDiagnostics } from "nostics";
9
8
  //#region src/adapters/flags.d.ts
@@ -852,7 +851,7 @@ interface RpcStreamingHost {
852
851
  /**
853
852
  * Adapters call this when a session disconnects so the host can drop
854
853
  * subscribers and abort orphaned streams. Most users do not need this;
855
- * it's wired by `startHttpAndWs` automatically.
854
+ * it's wired by the RPC server binding automatically.
856
855
  *
857
856
  * @internal
858
857
  */
@@ -948,7 +947,7 @@ interface DevframeHost {
948
947
  * base, so a devframe SPA mounted there can discover the RPC/WS endpoint
949
948
  * via `connectDevframe()`'s relative `./__connection.json` fetch.
950
949
  *
951
- * Called by `mountDevframe` for each mounted devframe (alongside
950
+ * Called by `ctx.install` for each mounted devframe (alongside
952
951
  * `mountStatic`). Without it, an embedded SPA can only discover the
953
952
  * endpoint by inheriting it from a same-origin parent window — which fails
954
953
  * for cross-origin or sandboxed iframes. Implementations serve the same
@@ -1344,8 +1343,8 @@ interface DevframeNodeContext {
1344
1343
  */
1345
1344
  interface ConnectionMetaWebsocket {
1346
1345
  /**
1347
- * Path to the WS endpoint. Relative paths (the default, e.g. `__devframe_ws`) are
1348
- * resolved against `__connection.json`'s location; absolute paths (`/__devframe_ws`)
1346
+ * Path to the WS endpoint. Relative paths (the default, e.g. `__ws`) are
1347
+ * resolved against `__connection.json`'s location; absolute paths (`/__ws`)
1349
1348
  * resolve against the page origin.
1350
1349
  */
1351
1350
  path?: string;
@@ -1354,8 +1353,32 @@ interface ConnectionMetaWebsocket {
1354
1353
  /** Override the host (`hostname[:port]`). Use for a fully cross-origin endpoint. */
1355
1354
  host?: string;
1356
1355
  }
1356
+ /**
1357
+ * Object form of {@link ConnectionMeta.sse} — the same proxy-safe shape and
1358
+ * resolution rules as {@link ConnectionMetaWebsocket}, producing an
1359
+ * `http(s)://` endpoint instead of a `ws(s)://` one. Set `port` (and/or
1360
+ * `host`) only when the SSE endpoint genuinely lives on a different origin
1361
+ * than the page, e.g. a side-car server on its own port.
1362
+ */
1363
+ interface ConnectionMetaSse {
1364
+ /**
1365
+ * Path to the SSE endpoint. Relative paths (the default, e.g. `__sse`)
1366
+ * are resolved against `__connection.json`'s location; absolute paths
1367
+ * (`/__sse`) resolve against the page origin.
1368
+ */
1369
+ path?: string;
1370
+ /** Override the port. Combined with the page hostname unless `host` is set. */
1371
+ port?: number;
1372
+ /** Override the host (`hostname[:port]`). Use for a fully cross-origin endpoint. */
1373
+ host?: string;
1374
+ }
1357
1375
  interface ConnectionMeta {
1358
- backend: 'websocket' | 'static';
1376
+ /**
1377
+ * The server's primary live-RPC transport (`websocket` / `sse`), `static`
1378
+ * for a pre-computed RPC dump with no live server, or `none` for a server
1379
+ * exposing no RPC transport at all (e.g. an MCP-only deployment).
1380
+ */
1381
+ backend: 'websocket' | 'sse' | 'static' | 'none';
1359
1382
  /**
1360
1383
  * WebSocket endpoint, resolved by the client into a `ws(s)://` URL:
1361
1384
  *
@@ -1366,6 +1389,17 @@ interface ConnectionMeta {
1366
1389
  * URL with its protocol swapped, or a path resolved same-origin.
1367
1390
  */
1368
1391
  websocket?: number | string | ConnectionMetaWebsocket;
1392
+ /**
1393
+ * SSE endpoint (`GET` opens the event stream, `POST` carries RPC calls),
1394
+ * resolved by the client into an `http(s)://` URL with the same
1395
+ * proxy-safe rules as {@link ConnectionMeta.websocket}:
1396
+ *
1397
+ * - {@link ConnectionMetaSse} — the proxy-flexible default; a
1398
+ * same-origin path relative to `__connection.json`.
1399
+ * - `string` — a full `http(s)://` URL used verbatim, or a path
1400
+ * resolved same-origin.
1401
+ */
1402
+ sse?: string | ConnectionMetaSse;
1369
1403
  /**
1370
1404
  * Present when the dev server exposes a route-based MCP endpoint
1371
1405
  * (`cli.mcp`). Advertises the MCP Streamable-HTTP route so in-browser
@@ -1442,7 +1476,7 @@ type PartialWithoutId<T extends {
1442
1476
  * the handshake RPC functions, the resolver gate, the connect-time trust
1443
1477
  * hook, and the startup banner.
1444
1478
  *
1445
- * `startHttpAndWs` accepts one of these directly via its `auth` option —
1479
+ * `initDevframe` / `initHub` accept one of these directly via their `auth` option —
1446
1480
  * see {@link https://devfra.me | devframe}'s server docs — or a host can
1447
1481
  * wire the four pieces itself against a lower-level transport.
1448
1482
  */
@@ -1461,12 +1495,12 @@ interface DevframeAuthHandler {
1461
1495
  */
1462
1496
  authorize: (methodName: string, session: DevframeNodeRpcSession) => boolean;
1463
1497
  /**
1464
- * Connect-time trust: reads a bearer token off the peer's upgrade request
1465
- * (an `Authorization: Bearer <token>` header, or a static/pre-shared
1466
- * token from `clientAuthTokens`) and, when valid, marks the session
1498
+ * Connect-time trust: reads a bearer token off the connection's initial
1499
+ * request (a static/pre-shared token from `clientAuthTokens`, or a token
1500
+ * minted by the code exchange) and, when valid, marks the session
1467
1501
  * trusted immediately — before the client's own handshake call.
1468
1502
  */
1469
- onConnect: (peer: Peer, session: DevframeNodeRpcSession) => void;
1503
+ onConnect: (connection: DevframeRpcConnection, session: DevframeNodeRpcSession) => void;
1470
1504
  /**
1471
1505
  * Print the current one-time code and its magic-link URL. Devframe stays
1472
1506
  * headless — call this yourself once the server is listening. Safe to
@@ -1512,7 +1546,7 @@ type DevframeDuplicationStrategy = 'warn' | 'silent' | 'throw' | 'duplicate';
1512
1546
  *
1513
1547
  * 1. **Same server, different route** (default) — leave `port`/`url` unset.
1514
1548
  * The socket shares the HTTP server's port and binds to `route`
1515
- * (`__devframe_ws`). The client connects to its own origin, so the link
1549
+ * (`__ws`). The client connects to its own origin, so the link
1516
1550
  * survives a reverse proxy that rewrites the host/port/subpath.
1517
1551
  *
1518
1552
  * 2. **Different port** — set `port`. The socket binds on its own port on the
@@ -1524,20 +1558,43 @@ type DevframeDuplicationStrategy = 'warn' | 'silent' | 'throw' | 'duplicate';
1524
1558
  interface DevframeWsOptions {
1525
1559
  /**
1526
1560
  * Upgrade route segment the socket binds to and is advertised at, relative
1527
- * to the SPA base. Default: `__devframe_ws`.
1561
+ * to the SPA base. Default: `__ws`.
1528
1562
  */
1529
1563
  route?: string;
1530
1564
  /**
1531
1565
  * Bind the socket on its own port instead of sharing the HTTP port. The
1532
- * browser connects to this port on the page's hostname.
1566
+ * browser connects to this port on the page's hostname. Implies
1567
+ * {@link DevframeWsOptions.sidecar}.
1533
1568
  */
1534
1569
  port?: number;
1570
+ /**
1571
+ * Start a side-car WebSocket server on a free port, for hosts whose request
1572
+ * handlers can't accept upgrades (Next.js route handlers, Nitro, Rsbuild).
1573
+ * The resolved port is advertised in `__connection.json`, so the browser
1574
+ * finds it without any further wiring. Set `port` instead to pin it.
1575
+ */
1576
+ sidecar?: boolean;
1535
1577
  /**
1536
1578
  * Advertise a fixed, fully-qualified endpoint on another origin (a full
1537
1579
  * `ws://`/`wss://` URL). Takes precedence over `port`/`route` in the meta.
1538
1580
  */
1539
1581
  url?: string;
1540
1582
  }
1583
+ /**
1584
+ * Controls the SSE RPC endpoint — the WebSocket-free transport for hosts
1585
+ * and proxies where the upgrade isn't available. It rides whatever HTTP
1586
+ * surface serves the instance (the same one serving `__connection.json`),
1587
+ * so a relative `route` always resolves; there is no port plumbing of its
1588
+ * own. Enabled by default alongside the WebSocket; pass `sse: false` to
1589
+ * disable, or `ws: false` to run SSE-only (`backend: 'sse'`).
1590
+ */
1591
+ interface DevframeSseOptions {
1592
+ /**
1593
+ * Route segment the SSE endpoint binds to and is advertised at, relative
1594
+ * to the SPA base. Default: `__sse`.
1595
+ */
1596
+ route?: string;
1597
+ }
1541
1598
  /**
1542
1599
  * Configuration for the route-based MCP server mounted alongside the dev
1543
1600
  * server (opt-in via {@link DevframeCliOptions.mcp}). The endpoint speaks
@@ -1599,7 +1656,7 @@ interface DevframeCliOptions {
1599
1656
  * The `--no-auth` CLI flag maps here for one-off runs.
1600
1657
  * - A {@link DevframeAuthHandler} — a custom handler (e.g. a tuned
1601
1658
  * `createInteractiveAuth`, or an entirely different scheme) passed
1602
- * straight through to `startHttpAndWs`.
1659
+ * straight through to the RPC transport binding.
1603
1660
  *
1604
1661
  * Hosted adapters (`vite`, `embedded`) ignore this and defer to the host's
1605
1662
  * auth; `@vitejs/devtools` honors the equivalent `devtools.clientAuth`.
@@ -1627,10 +1684,17 @@ interface DevframeCliOptions {
1627
1684
  distDir?: string;
1628
1685
  /**
1629
1686
  * How the browser reaches the RPC WebSocket. Defaults to sharing the HTTP
1630
- * port on the `__devframe_ws` route. See {@link DevframeWsOptions} for the
1631
- * different-port and remote-origin variants.
1687
+ * port on the `__ws` route. See {@link DevframeWsOptions} for the
1688
+ * different-port and remote-origin variants. Pass `false` to serve no
1689
+ * WebSocket at all — clients connect over SSE instead (`backend: 'sse'`).
1690
+ */
1691
+ ws?: DevframeWsOptions | false;
1692
+ /**
1693
+ * How the browser reaches the SSE RPC endpoint — enabled by default
1694
+ * alongside the WebSocket as the more portable transport. Pass `false`
1695
+ * to disable, or a {@link DevframeSseOptions} to change its route.
1632
1696
  */
1633
- ws?: DevframeWsOptions;
1697
+ sse?: boolean | DevframeSseOptions;
1634
1698
  /**
1635
1699
  * Capability-side CAC hook. Called with the CAC instance after the
1636
1700
  * adapter registers its built-in commands (`build` / `spa` / `mcp`)
@@ -1669,7 +1733,7 @@ interface DevframeCliOptions {
1669
1733
  /**
1670
1734
  * Default dock attributes for the iframe entry a hub synthesizes when it
1671
1735
  * mounts this devframe. Framework-neutral metadata only — the hub layer
1672
- * (`mountDevframe`) merges these beneath its per-mount `dock` overrides,
1736
+ * (`ctx.install`) merges these beneath its per-mount `dock` overrides,
1673
1737
  * which in turn sit beneath the locked, derived `id` / `type` / `url`.
1674
1738
  *
1675
1739
  * Every field is optional. `title` / `icon` default to the definition's
@@ -1753,7 +1817,7 @@ interface DevframeDefinition {
1753
1817
  };
1754
1818
  /**
1755
1819
  * Default dock attributes applied when a hub mounts this devframe as an
1756
- * iframe dock entry. Consulted only by hub adapters (`mountDevframe`),
1820
+ * iframe dock entry. Consulted only by the hub install path (`ctx.install`),
1757
1821
  * which merge these beneath the per-mount `dock` overrides; standalone
1758
1822
  * adapters (`cli` / `spa` / `build`) ignore it.
1759
1823
  *
@@ -1769,7 +1833,7 @@ interface DevframeDefinition {
1769
1833
  /**
1770
1834
  * How a hub reacts when another devframe sharing this one's `id` is
1771
1835
  * mounted onto the same hub. Consulted only by hub adapters
1772
- * (`mountDevframe`); standalone adapters (`cli` / `spa` / `build`)
1836
+ * (`ctx.install`); standalone adapters (`cli` / `spa` / `build`)
1773
1837
  * ignore it.
1774
1838
  *
1775
1839
  * @default 'warn'
@@ -1797,6 +1861,5 @@ interface DevframeDefinition {
1797
1861
  cli?: DevframeCliOptions;
1798
1862
  spa?: DevframeSpaOptions;
1799
1863
  }
1800
- declare function defineDevframe(d: DevframeDefinition): DevframeDefinition;
1801
1864
  //#endregion
1802
- export { DevframeRpcServerFunctions as $, DevframeSettingsStore as A, DevframeAgentHostEvents as At, DevframeDefineDiagnosticsOptions as B, DevframeServicesHost as C, AgentResourceContent as Ct, DevframeScopedStreamingHost as D, AgentToolProvider as Dt, DevframeScopedNodeRpc as E, AgentToolInput as Et, ScopedSharedStates as F, InferCliFlags as Ft, RpcBroadcastOptions as G, DevframeDiagnosticsHost as H, SettingsForNamespace as I, defineCliFlags as It, RpcSharedStateHost as J, RpcFunctionsHost as K, DevframeViewHost as L, parseCliFlags as Lt, ScopedClientFunctions as M, EventUnsubscribe as Mt, ScopedRpcFn as N, EventsMap as Nt, DevframeSettings as O, AgentToolProviderHandle as Ot, ScopedServerFunctions as P, CliFlagsSchema as Pt, DevframeRpcClientFunctions as Q, DevframeHost as R, DevframeServiceOf as S, AgentResource as St, DevframeScopedNodeContext as T, AgentTool as Tt, DevframeDiagnosticsLogger as U, DevframeDiagnosticsDefinition as V, DevframeNodeRpcSession as W, RpcStreamingChannelOptions as X, RpcStreamingChannel as Y, RpcStreamingHost as Z, ConnectionMeta as _, SharedStateOptions as _t, DevframeDockDefaults as a, StreamReader as at, DevframeNodeContext as b, AgentHandle as bt, DevframeSetupInfo as c, createStreamReader as ct, McpRouteOptions as d, ImmutableArray as dt, DevframeRpcSharedStates as et, defineDevframe as f, ImmutableMap as ft, Thenable as g, SharedStateEvents as gt, PartialWithoutId as h, SharedState as ht, DevframeDeploymentKind as i, StreamErrorPayload as it, ScopedBroadcastOptions as j, EventEmitter as jt, DevframeSettingsRegistry as k, DevframeAgentHost as kt, DevframeSpaOptions as l, createStreamSink as lt, EntriesToObject as m, ImmutableSet as mt, DevframeCliOptions as n, CreateStreamReaderOptions as nt, DevframeDuplicationStrategy as o, StreamSink as ot, DevframeAuthHandler as p, ImmutableObject as pt, RpcSharedStateGetOptions as q, DevframeDefinition as r, CreateStreamSinkOptions as rt, DevframeRuntime as s, StreamSinkEvents as st, DevframeBrowserContext as t, BufferedChunk as tt, DevframeWsOptions as u, Immutable as ut, ConnectionMetaWebsocket as v, SharedStatePatch as vt, DevframeServicesRegistry as w, AgentResourceInput as wt, DevframeServiceId as x, AgentManifest as xt, DevframeCapabilities as y, createSharedState as yt, DevframeStorageScope as z };
1865
+ export { DevframeRpcClientFunctions as $, DevframeSettingsRegistry as A, DevframeAgentHost as At, DevframeStorageScope as B, DevframeServiceOf as C, AgentResource as Ct, DevframeScopedNodeRpc as D, AgentToolInput as Dt, DevframeScopedNodeContext as E, AgentTool as Et, ScopedServerFunctions as F, CliFlagsSchema as Ft, DevframeNodeRpcSession as G, DevframeDiagnosticsDefinition as H, ScopedSharedStates as I, InferCliFlags as It, RpcSharedStateGetOptions as J, RpcBroadcastOptions as K, SettingsForNamespace as L, defineCliFlags as Lt, ScopedBroadcastOptions as M, EventEmitter as Mt, ScopedClientFunctions as N, EventUnsubscribe as Nt, DevframeScopedStreamingHost as O, AgentToolProvider as Ot, ScopedRpcFn as P, EventsMap as Pt, RpcStreamingHost as Q, DevframeViewHost as R, parseCliFlags as Rt, DevframeServiceId as S, AgentManifest as St, DevframeServicesRegistry as T, AgentResourceInput as Tt, DevframeDiagnosticsHost as U, DevframeDefineDiagnosticsOptions as V, DevframeDiagnosticsLogger as W, RpcStreamingChannel as X, RpcSharedStateHost as Y, RpcStreamingChannelOptions as Z, ConnectionMeta as _, SharedStateEvents as _t, DevframeDockDefaults as a, StreamErrorPayload as at, DevframeCapabilities as b, createSharedState as bt, DevframeSetupInfo as c, StreamSinkEvents as ct, DevframeWsOptions as d, Immutable as dt, DevframeRpcServerFunctions as et, McpRouteOptions as f, ImmutableArray as ft, Thenable as g, SharedState as gt, PartialWithoutId as h, ImmutableSet as ht, DevframeDeploymentKind as i, CreateStreamSinkOptions as it, DevframeSettingsStore as j, DevframeAgentHostEvents as jt, DevframeSettings as k, AgentToolProviderHandle as kt, DevframeSpaOptions as l, createStreamReader as lt, EntriesToObject as m, ImmutableObject as mt, DevframeCliOptions as n, BufferedChunk as nt, DevframeDuplicationStrategy as o, StreamReader as ot, DevframeAuthHandler as p, ImmutableMap as pt, RpcFunctionsHost as q, DevframeDefinition as r, CreateStreamReaderOptions as rt, DevframeRuntime as s, StreamSink as st, DevframeBrowserContext as t, DevframeRpcSharedStates as tt, DevframeSseOptions as u, createStreamSink as ut, ConnectionMetaSse as v, SharedStateOptions as vt, DevframeServicesHost as w, AgentResourceContent as wt, DevframeNodeContext as x, AgentHandle as xt, ConnectionMetaWebsocket as y, SharedStatePatch as yt, DevframeHost as z };
@@ -87,6 +87,26 @@ const diagnostics = defineDiagnostics({
87
87
  DF0051: {
88
88
  why: (p) => `The devframe instance on port ${p.port} has no MCP endpoint.`,
89
89
  fix: "Restart the instance with the --mcp flag (or set `cli.mcp: true` on its definition) to expose its tools, then list instances again."
90
+ },
91
+ DF0052: {
92
+ why: (p) => `Failed to listen on ${p.host}:${p.port}: ${p.reason}`,
93
+ fix: "The port is likely already taken by another process (often a previous devframe instance). Free it, or pick another via `--port`, `cli.port` / `cli.portRange` on the definition, or `devMiddleware.port` on `viteDevBridge`. The original node error is available as `error.cause`."
94
+ },
95
+ DF0054: {
96
+ why: (p) => `connectionMeta() was called before initDevframe("${p.id}") finished initializing.`,
97
+ fix: "Await `instance.ready` (or any request through `instance.handler`) before reading `connectionMeta()` — the WebSocket binding it describes is only known once initialization completes."
98
+ },
99
+ DF0055: {
100
+ why: (p) => `This instance already owns its WebSocket transport (${p.tier}), so it cannot take over the host's upgrade events.`,
101
+ fix: "Drop `handleUpgrade`/`attach` and let the configured transport serve the socket, or remove `server` / `ws.port` / `ws.sidecar` from the options so the instance leaves the binding to you."
102
+ },
103
+ DF0056: {
104
+ why: (p) => `This instance advertises an external WebSocket endpoint (${p.url}), so it serves no socket of its own.`,
105
+ fix: "The server behind `ws.url` owns the transport (and its auth). Drop `ws.url` to have the instance serve the socket, or pair it with `server` / `ws.port` / `ws.sidecar` for the tunnel pattern, where a local binding is advertised through the relay."
106
+ },
107
+ DF0057: {
108
+ why: () => "This instance disables its WebSocket transport (`ws: false`), so there is no socket to drive upgrades into.",
109
+ fix: "Clients connect over the SSE endpoint instead — no upgrade wiring is needed. Remove `ws: false` if the instance should serve a WebSocket after all."
90
110
  }
91
111
  }
92
112
  });
@@ -0,0 +1,227 @@
1
+ import { n as __exportAll } from "./rolldown-runtime-JspESFgx.mjs";
2
+ import { createServer } from "node:net";
3
+ import { networkInterfaces } from "node:os";
4
+ //#region ../../node_modules/.pnpm/get-port-please@3.2.0/node_modules/get-port-please/dist/index.mjs
5
+ var dist_exports = /* @__PURE__ */ __exportAll({
6
+ checkPort: () => checkPort,
7
+ getPort: () => getPort,
8
+ getRandomPort: () => getRandomPort,
9
+ isSafePort: () => isSafePort,
10
+ isUnsafePort: () => isUnsafePort
11
+ });
12
+ const unsafePorts = /* @__PURE__ */ new Set([
13
+ 1,
14
+ 7,
15
+ 9,
16
+ 11,
17
+ 13,
18
+ 15,
19
+ 17,
20
+ 19,
21
+ 20,
22
+ 21,
23
+ 22,
24
+ 23,
25
+ 25,
26
+ 37,
27
+ 42,
28
+ 43,
29
+ 53,
30
+ 69,
31
+ 77,
32
+ 79,
33
+ 87,
34
+ 95,
35
+ 101,
36
+ 102,
37
+ 103,
38
+ 104,
39
+ 109,
40
+ 110,
41
+ 111,
42
+ 113,
43
+ 115,
44
+ 117,
45
+ 119,
46
+ 123,
47
+ 135,
48
+ 137,
49
+ 139,
50
+ 143,
51
+ 161,
52
+ 179,
53
+ 389,
54
+ 427,
55
+ 465,
56
+ 512,
57
+ 513,
58
+ 514,
59
+ 515,
60
+ 526,
61
+ 530,
62
+ 531,
63
+ 532,
64
+ 540,
65
+ 548,
66
+ 554,
67
+ 556,
68
+ 563,
69
+ 587,
70
+ 601,
71
+ 636,
72
+ 989,
73
+ 990,
74
+ 993,
75
+ 995,
76
+ 1719,
77
+ 1720,
78
+ 1723,
79
+ 2049,
80
+ 3659,
81
+ 4045,
82
+ 5060,
83
+ 5061,
84
+ 6e3,
85
+ 6566,
86
+ 6665,
87
+ 6666,
88
+ 6667,
89
+ 6668,
90
+ 6669,
91
+ 6697,
92
+ 10080
93
+ ]);
94
+ function isUnsafePort(port) {
95
+ return unsafePorts.has(port);
96
+ }
97
+ function isSafePort(port) {
98
+ return !isUnsafePort(port);
99
+ }
100
+ var GetPortError = class extends Error {
101
+ constructor(message, opts) {
102
+ super(message, opts);
103
+ this.message = message;
104
+ }
105
+ name = "GetPortError";
106
+ };
107
+ function _log(verbose, message) {
108
+ if (verbose) console.log(`[get-port] ${message}`);
109
+ }
110
+ function _generateRange(from, to) {
111
+ if (to < from) return [];
112
+ const r = [];
113
+ for (let index = from; index <= to; index++) r.push(index);
114
+ return r;
115
+ }
116
+ function _tryPort(port, host) {
117
+ return new Promise((resolve) => {
118
+ const server = createServer();
119
+ server.unref();
120
+ server.on("error", () => {
121
+ resolve(false);
122
+ });
123
+ server.listen({
124
+ port,
125
+ host
126
+ }, () => {
127
+ const { port: port2 } = server.address();
128
+ server.close(() => {
129
+ resolve(isSafePort(port2) && port2);
130
+ });
131
+ });
132
+ });
133
+ }
134
+ function _getLocalHosts(additional) {
135
+ const hosts = new Set(additional);
136
+ for (const _interface of Object.values(networkInterfaces())) for (const config of _interface || []) if (config.address && !config.internal && !config.address.startsWith("fe80::") && !config.address.startsWith("169.254")) hosts.add(config.address);
137
+ return [...hosts];
138
+ }
139
+ async function _findPort(ports, host) {
140
+ for (const port of ports) {
141
+ const r = await _tryPort(port, host);
142
+ if (r) return r;
143
+ }
144
+ }
145
+ function _fmtOnHost(hostname) {
146
+ return hostname ? `on host ${JSON.stringify(hostname)}` : "on any host";
147
+ }
148
+ const HOSTNAME_RE = /^(?!-)[\d.:A-Za-z-]{1,63}(?<!-)$/;
149
+ function _validateHostname(hostname, _public, verbose) {
150
+ if (hostname && !HOSTNAME_RE.test(hostname)) {
151
+ const fallbackHost = _public ? "0.0.0.0" : "127.0.0.1";
152
+ _log(verbose, `Invalid hostname: ${JSON.stringify(hostname)}. Using ${JSON.stringify(fallbackHost)} as fallback.`);
153
+ return fallbackHost;
154
+ }
155
+ return hostname;
156
+ }
157
+ async function getPort(_userOptions = {}) {
158
+ if (typeof _userOptions === "number" || typeof _userOptions === "string") _userOptions = { port: Number.parseInt(_userOptions + "") || 0 };
159
+ const _port = Number(_userOptions.port ?? process.env.PORT);
160
+ const _userSpecifiedAnyPort = Boolean(_userOptions.port || _userOptions.ports?.length || _userOptions.portRange?.length);
161
+ const options = {
162
+ random: _port === 0,
163
+ ports: [],
164
+ portRange: [],
165
+ alternativePortRange: _userSpecifiedAnyPort ? [] : [3e3, 3100],
166
+ verbose: false,
167
+ ..._userOptions,
168
+ port: _port,
169
+ host: _validateHostname(_userOptions.host ?? process.env.HOST, _userOptions.public, _userOptions.verbose)
170
+ };
171
+ if (options.random && !_userSpecifiedAnyPort) return getRandomPort(options.host);
172
+ const portsToCheck = [
173
+ options.port,
174
+ ...options.ports,
175
+ ..._generateRange(...options.portRange)
176
+ ].filter((port) => {
177
+ if (!port) return false;
178
+ if (!isSafePort(port)) {
179
+ _log(options.verbose, `Ignoring unsafe port: ${port}`);
180
+ return false;
181
+ }
182
+ return true;
183
+ });
184
+ if (portsToCheck.length === 0) portsToCheck.push(3e3);
185
+ let availablePort = await _findPort(portsToCheck, options.host);
186
+ if (!availablePort && options.alternativePortRange.length > 0) {
187
+ availablePort = await _findPort(_generateRange(...options.alternativePortRange), options.host);
188
+ if (portsToCheck.length > 0) {
189
+ let message = `Unable to find an available port (tried ${portsToCheck.join("-")} ${_fmtOnHost(options.host)}).`;
190
+ if (availablePort) message += ` Using alternative port ${availablePort}.`;
191
+ _log(options.verbose, message);
192
+ }
193
+ }
194
+ if (!availablePort && _userOptions.random !== false) {
195
+ availablePort = await getRandomPort(options.host);
196
+ if (availablePort) _log(options.verbose, `Using random port ${availablePort}`);
197
+ }
198
+ if (!availablePort) {
199
+ const triedRanges = [
200
+ options.port,
201
+ options.portRange.join("-"),
202
+ options.alternativePortRange.join("-")
203
+ ].filter(Boolean).join(", ");
204
+ throw new GetPortError(`Unable to find an available port ${_fmtOnHost(options.host)} (tried ${triedRanges})`);
205
+ }
206
+ return availablePort;
207
+ }
208
+ async function getRandomPort(host) {
209
+ const port = await checkPort(0, host);
210
+ if (port === false) throw new GetPortError(`Unable to find a random port ${_fmtOnHost(host)}`);
211
+ return port;
212
+ }
213
+ async function checkPort(port, host = process.env.HOST, verbose) {
214
+ if (!host) host = _getLocalHosts([void 0, "0.0.0.0"]);
215
+ if (!Array.isArray(host)) return _tryPort(port, host);
216
+ for (const _host of host) {
217
+ const _port = await _tryPort(port, _host);
218
+ if (_port === false) {
219
+ if (port < 1024 && verbose) _log(verbose, `Unable to listen to the privileged port ${port} ${_fmtOnHost(_host)}`);
220
+ return false;
221
+ }
222
+ if (port === 0 && _port !== 0) port = _port;
223
+ }
224
+ return port;
225
+ }
226
+ //#endregion
227
+ export { getPort as n, dist_exports as t };
@@ -1,4 +1,5 @@
1
- import { d as McpRouteOptions, p as DevframeAuthHandler, r as DevframeDefinition } from "../devframe-qgCKL683.mjs";
1
+ import { f as McpRouteOptions, p as DevframeAuthHandler, r as DevframeDefinition } from "../devframe-Bdd9YXTy.mjs";
2
+ import { IncomingMessage, Server, ServerResponse } from "node:http";
2
3
  //#region src/helpers/vite.d.ts
3
4
  interface ViteDevBridgeOptions {
4
5
  /**
@@ -12,30 +13,36 @@ interface ViteDevBridgeOptions {
12
13
  base?: string;
13
14
  /**
14
15
  * Dev-time middleware mode. When set, the host app owns the SPA and
15
- * devframe spins up a separate RPC + WS server on a resolved port,
16
- * registering Vite middleware at `<base>__connection.json` so the
17
- * host-served SPA can discover the WS endpoint.
16
+ * devframe serves the RPC surface through the Vite dev server itself —
17
+ * `<base>__connection.json` for discovery and the WebSocket upgrade at
18
+ * `<base>__ws` on Vite's own HTTP server (zero extra ports, proxy/HTTPS
19
+ * friendly). When Vite runs in middleware mode (no `httpServer`) — or a
20
+ * `port` is pinned — the socket falls back to a side-car server on its
21
+ * own port instead.
18
22
  *
19
23
  * - `false` (default) — static-mount the SPA at `base` with SPA
20
24
  * fallback. No RPC server is started.
21
- * - `true` — bridge mode with all defaults (port from
22
- * {@link resolveDevServerPort}, host from `def.cli?.host`).
25
+ * - `true` — bridge mode with all defaults.
23
26
  * - object — bridge mode with explicit overrides.
24
27
  */
25
28
  devMiddleware?: boolean | {
26
- /** Override the bridge port. Default: {@link resolveDevServerPort}. */
29
+ /**
30
+ * Pin a side-car port for the RPC socket instead of sharing Vite's
31
+ * server. Default: share Vite's HTTP server (side-car only when Vite
32
+ * has none).
33
+ */
27
34
  port?: number;
28
- /** Override the bridge bind host. Default: `def.cli?.host ?? 'localhost'`. */
35
+ /** Override the side-car bind host. Default: `def.cli?.host ?? 'localhost'`. */
29
36
  host?: string;
30
37
  /** Flag bag forwarded to `def.setup(ctx, { flags })`. */
31
38
  flags?: Record<string, unknown>;
32
39
  };
33
40
  /**
34
- * Whether the bridged devframe runs its own auth gate. The side-car RPC
35
- * server is reachable by anything that can open its socket, so it **gates by
36
- * default**: when unset, authentication resolves through `createDevServer`
37
- * (devframe's interactive OTP gate unless the definition's `cli.auth` opts
38
- * out), and the side-car prints its code/link banner to stdout. Pass a
41
+ * Whether the bridged devframe runs its own auth gate. The RPC endpoint is
42
+ * reachable by anything that can open its socket, so it **gates by
43
+ * default**: when unset, authentication resolves through devframe's
44
+ * interactive OTP gate (unless the definition's `cli.auth` opts out), and
45
+ * the bridge prints its code/link banner to stdout. Pass a
39
46
  * {@link DevframeAuthHandler} to install a custom scheme, or `false` to opt
40
47
  * out for a single-user localhost host that owns the trust boundary another
41
48
  * way. Only applies in bridge mode (`devMiddleware`); the static-mount mode
@@ -45,30 +52,27 @@ interface ViteDevBridgeOptions {
45
52
  */
46
53
  auth?: boolean | DevframeAuthHandler;
47
54
  /**
48
- * Expose the side-car's route-based MCP server (Streamable-HTTP) and
49
- * advertise it in the bridge's `__connection.json`. Forwarded to
50
- * {@link createDevServer}: overrides `def.cli?.mcp`, `undefined` falls
51
- * through to it, `false` disables the route regardless. Only applies in
52
- * bridge mode (`devMiddleware`); the static-mount mode starts no server.
53
- *
54
- * The endpoint lives on the side-car's own port, so the advertised meta
55
- * carries `{ port, path }` — see `ConnectionMeta['mcp']`.
55
+ * Expose the bridge's route-based MCP server (Streamable-HTTP) at
56
+ * `<base>__mcp` — on the Vite app's own origin — and advertise it in the
57
+ * bridge's `__connection.json`. Overrides `def.cli?.mcp`, `undefined`
58
+ * falls through to it, `false` disables the route regardless. Only applies
59
+ * in bridge mode (`devMiddleware`); the static-mount mode starts no server.
56
60
  *
57
61
  * @experimental
58
62
  */
59
63
  mcp?: boolean | McpRouteOptions;
60
64
  }
65
+ /** The slice of a Vite dev server the bridge plugin touches. */
66
+ interface DevframeViteDevServerLike {
67
+ middlewares: {
68
+ use: ((path: string, handler: (req: IncomingMessage, res: ServerResponse, next?: (err?: unknown) => void) => void) => void) & ((handler: (req: IncomingMessage, res: ServerResponse, next?: (err?: unknown) => void) => void) => void);
69
+ };
70
+ httpServer?: Server | null;
71
+ }
61
72
  interface DevframeVitePlugin {
62
73
  name: string;
63
74
  apply: 'serve';
64
- configureServer: (server: {
65
- middlewares: {
66
- use: (path: string, handler: any) => void;
67
- };
68
- httpServer?: {
69
- once: (event: 'close', cb: () => void) => void;
70
- } | null;
71
- }) => void | Promise<void>;
75
+ configureServer: (server: DevframeViteDevServerLike) => void | Promise<void>;
72
76
  closeBundle?: () => void | Promise<void>;
73
77
  }
74
78
  /**
@@ -79,16 +83,16 @@ interface DevframeVitePlugin {
79
83
  * `options.base` with SPA fallback enabled. No RPC server is started.
80
84
  *
81
85
  * - **bridge mode** (`devMiddleware: true | {…}`) — skips the static
82
- * mount; the host app owns the SPA. Devframe starts a separate
83
- * RPC + WS dev server (via {@link createDevServer} in bridge mode)
84
- * and registers Vite middleware at `<base>__connection.json` so the
85
- * host-served SPA can discover the WS endpoint via
86
- * {@link connectDevframe}.
86
+ * mount; the host app owns the SPA. Devframe serves discovery
87
+ * (`<base>__connection.json`), the WebSocket RPC upgrade
88
+ * (`<base>__ws`, shared on Vite's own HTTP server), and the optional
89
+ * MCP route through {@link initDevframe}'s node middleware, so the
90
+ * host-served SPA can discover the endpoint via {@link connectDevframe}.
87
91
  *
88
- * The side-car RPC server **gates by default** (devframe's interactive OTP
89
- * unless the definition's `cli.auth` opts out), printing its code/link banner
90
- * to stdout, so a bridged devframe isn't silently reachable by anything that
91
- * can open its socket. Pass `options.auth: false` to opt out for a single-user
92
+ * The bridge **gates by default** (devframe's interactive OTP unless the
93
+ * definition's `cli.auth` opts out), printing its code/link banner to stdout,
94
+ * so a bridged devframe isn't silently reachable by anything that can open
95
+ * its socket. Pass `options.auth: false` to opt out for a single-user
92
96
  * localhost host, or a {@link DevframeAuthHandler} for a custom scheme.
93
97
  *
94
98
  * Use bridge mode when integrating with frameworks that own the SPA
@@ -97,4 +101,4 @@ interface DevframeVitePlugin {
97
101
  */
98
102
  declare function viteDevBridge(d: DevframeDefinition, options?: ViteDevBridgeOptions): DevframeVitePlugin;
99
103
  //#endregion
100
- export { DevframeVitePlugin, ViteDevBridgeOptions, viteDevBridge };
104
+ export { DevframeViteDevServerLike, DevframeVitePlugin, ViteDevBridgeOptions, viteDevBridge };