devframe 0.8.2 → 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.
- package/dist/_shared-CttmCMBi.mjs +70 -0
- package/dist/_shared-DmpWW-HH.d.mts +43 -0
- package/dist/adapters/build.d.mts +1 -1
- package/dist/adapters/build.mjs +6 -5
- package/dist/adapters/cac.d.mts +1 -1
- package/dist/adapters/cac.mjs +157 -1
- package/dist/adapters/dev.d.mts +20 -42
- package/dist/adapters/dev.mjs +2 -1
- package/dist/adapters/embedded.d.mts +1 -1
- package/dist/adapters/initiate.d.mts +223 -0
- package/dist/adapters/initiate.mjs +2 -0
- package/dist/adapters/mcp.d.mts +26 -2
- package/dist/adapters/mcp.mjs +2 -2
- package/dist/cli/main.mjs +2 -2
- package/dist/client/index.d.mts +70 -6
- package/dist/client/index.mjs +743 -408
- package/dist/constants.d.mts +19 -6
- package/dist/constants.mjs +19 -6
- package/dist/{context-CBg8iRbQ.mjs → context-C33rR7n0.mjs} +1 -1
- package/dist/{context-DoSozfvx.d.mts → context-CSCwoABx.d.mts} +1 -1
- package/dist/{host-h3-D2hYZvDK.mjs → context-Du11TLcO.mjs} +5 -255
- package/dist/dev-BEveeA5H.mjs +233 -0
- package/dist/{devframe-mQ4qZAuo.d.mts → devframe-Bdd9YXTy.d.mts} +88 -25
- package/dist/{diagnostics-D7wM2cwM.mjs → diagnostics-DLYH5oD3.mjs} +16 -0
- package/dist/dist-D8jAMwxU.mjs +227 -0
- package/dist/helpers/vite.d.mts +43 -39
- package/dist/helpers/vite.mjs +26 -38
- package/dist/host-agent-CpbAoqBx.mjs +230 -0
- package/dist/host-h3-CzCZwtuV.mjs +26 -0
- package/dist/{fetch-BKaD0Vb3.mjs → http-DLr_cJZ7.mjs} +42 -4
- package/dist/{index-b64Uuhy2.d.mts → index-CZRd2K1C.d.mts} +2 -2
- package/dist/{index-Dbw1p5ch.d.mts → index-DSCq4M4q.d.mts} +2 -31
- package/dist/index.d.mts +9 -4
- package/dist/index.mjs +8 -1
- package/dist/{instance-registry-BnnA2Eoh.mjs → instance-registry-BQqGoDO9.mjs} +9 -2
- package/dist/instance-shell-DBTXTSjN.d.mts +264 -0
- package/dist/instance-shell-KRdee1QF.mjs +485 -0
- package/dist/internal/index.d.mts +150 -0
- package/dist/internal/index.mjs +7 -0
- package/dist/node/auth.d.mts +2 -2
- package/dist/node/hub-internals.d.mts +2 -14
- package/dist/node/hub-internals.mjs +2 -2
- package/dist/node/index.d.mts +3 -267
- package/dist/node/index.mjs +3 -5
- package/dist/recipes/common-rpc-functions.d.mts +3 -3
- package/dist/recipes/interactive-auth.d.mts +3 -3
- package/dist/recipes/interactive-auth.mjs +6 -6
- package/dist/rolldown-runtime-JspESFgx.mjs +35 -0
- package/dist/rpc/dump.d.mts +77 -1
- package/dist/rpc/dump.mjs +1 -1
- package/dist/rpc/index.d.mts +2 -2
- package/dist/rpc/index.mjs +3 -17
- package/dist/rpc/transports/sse-client.d.mts +2 -0
- package/dist/rpc/transports/sse-client.mjs +142 -0
- package/dist/rpc/transports/sse-server.d.mts +61 -0
- package/dist/rpc/transports/sse-server.mjs +209 -0
- package/dist/rpc/transports/ws-bun.d.mts +35 -0
- package/dist/rpc/transports/ws-bun.mjs +31 -0
- package/dist/rpc/transports/ws-client.d.mts +1 -1
- package/dist/rpc/transports/ws-client.mjs +10 -18
- package/dist/rpc/transports/ws-server.d.mts +2 -2
- package/dist/rpc/transports/ws-server.mjs +2 -235
- package/dist/rpc-core-CGctXToO.d.mts +48 -0
- package/dist/rpc-core-CqcJkAu9.mjs +81 -0
- package/dist/{serialization-C8Mnw9hK.mjs → serialization-BHY8M5NQ.mjs} +1 -1
- package/dist/{shared-state-6kHolYZy.mjs → shared-state-fRRbRUtD.mjs} +1 -1
- package/dist/sse-client-BsIK3hMD.d.mts +37 -0
- package/dist/{dump-CgZShDRB.mjs → static-CvjkO8QE.mjs} +2 -265
- package/dist/{storage-CTNVbuFB.mjs → storage-BcmVEJRc.mjs} +2 -2
- package/dist/types/index.d.mts +3 -3
- package/dist/types/index.mjs +1 -6
- package/dist/utils/events.d.mts +1 -1
- package/dist/utils/launch-editor.mjs +1 -25
- package/dist/utils/open.mjs +1 -1
- package/dist/utils/serve-static.mjs +1 -1
- package/dist/utils/shared-state.d.mts +1 -1
- package/dist/utils/shared-state.mjs +1 -1
- package/dist/utils/simple-schema.d.mts +101 -1
- package/dist/utils/streaming-channel.d.mts +1 -1
- package/dist/validation-BiuDXTKW.mjs +266 -0
- package/dist/wire-codec-9VhIKnyp.mjs +58 -0
- package/dist/{ws-client-B6Tnr0ic.d.mts → ws-client-CdNuATYa.d.mts} +6 -1
- package/dist/ws-server-Bk1hOG3X.mjs +267 -0
- package/dist/{ws-server-uKQcClcJ.d.mts → ws-server-Ces08fjP.d.mts} +89 -8
- package/package.json +10 -9
- package/skills/devframe/SKILL.md +84 -85
- package/dist/_shared-bWRzeSa0.mjs +0 -19
- package/dist/adapters/cli.d.mts +0 -11
- package/dist/adapters/cli.mjs +0 -6
- package/dist/cac-D4_9ok0z.mjs +0 -157
- package/dist/dev-Bc49u3qg.mjs +0 -439
- package/dist/http-C4T68YV6.mjs +0 -38
- package/dist/index-vAX6bYuc.d.mts +0 -78
- package/dist/recipes/open-helpers.d.mts +0 -6
- package/dist/recipes/open-helpers.mjs +0 -6
- package/dist/server-CD8XmBXl.mjs +0 -167
- package/dist/server-UHWae43Q.d.mts +0 -149
- package/dist/simple-schema-BDzLeJDk.d.mts +0 -102
- package/dist/utils/promise.d.mts +0 -8
- package/dist/utils/promise.mjs +0 -15
- package/dist/utils/scope.d.mts +0 -11
- package/dist/utils/scope.mjs +0 -15
- 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 {
|
|
3
|
-
import { n as DevframeNodeRpcSessionMeta } from "./ws-server-uKQcClcJ.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
|
|
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 `
|
|
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. `
|
|
1348
|
-
* resolved against `__connection.json`'s location; absolute paths (`/
|
|
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
|
-
|
|
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
|
-
* `
|
|
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
|
|
1465
|
-
* (
|
|
1466
|
-
*
|
|
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: (
|
|
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
|
-
* (`
|
|
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: `
|
|
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
|
|
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 `
|
|
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
|
-
|
|
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
|
-
* (`
|
|
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
|
|
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
|
-
* (`
|
|
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 {
|
|
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 };
|
|
@@ -91,6 +91,22 @@ const diagnostics = defineDiagnostics({
|
|
|
91
91
|
DF0052: {
|
|
92
92
|
why: (p) => `Failed to listen on ${p.host}:${p.port}: ${p.reason}`,
|
|
93
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."
|
|
94
110
|
}
|
|
95
111
|
}
|
|
96
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 };
|
package/dist/helpers/vite.d.mts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
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
|
|
16
|
-
*
|
|
17
|
-
*
|
|
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
|
|
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
|
-
/**
|
|
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
|
|
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
|
|
35
|
-
*
|
|
36
|
-
* default**: when unset, authentication resolves through
|
|
37
|
-
*
|
|
38
|
-
*
|
|
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
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
* through to it, `false` disables the route regardless. Only applies
|
|
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
|
|
83
|
-
*
|
|
84
|
-
*
|
|
85
|
-
*
|
|
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
|
|
89
|
-
*
|
|
90
|
-
*
|
|
91
|
-
*
|
|
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 };
|