sootsim 0.1.85 → 0.1.87
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-cli/bin.js +4 -4
- package/dist-cli/chunks/{agent-T3DUH5YJ.js → agent-JVF2PSHI.js} +2 -2
- package/dist-cli/chunks/{agent-wrapper-NSBF4THI.js → agent-wrapper-F2F4AOBI.js} +2 -2
- package/dist-cli/chunks/{assert-X3F7TRCZ.js → assert-YYD6OU4X.js} +2 -2
- package/dist-cli/chunks/auto-bootstrap-NUDEO3WI.js +2 -0
- package/dist-cli/chunks/beta-KQR3AUDC.js +2 -0
- package/dist-cli/chunks/{chunk-EKXK3SWK.js → chunk-356M3TGV.js} +2 -2
- package/dist-cli/chunks/{chunk-Y5PLPEEU.js → chunk-4QWGWI5X.js} +2 -2
- package/dist-cli/chunks/{chunk-EFM53PZ5.js → chunk-5UEPOBEU.js} +1 -1
- package/dist-cli/chunks/{chunk-QLJNSOS7.js → chunk-6JITQIIF.js} +1 -1
- package/dist-cli/chunks/{chunk-DWTLRPEN.js → chunk-7KZTQHB3.js} +2 -2
- package/dist-cli/chunks/{chunk-OXOARRKR.js → chunk-7SX73XWN.js} +10 -10
- package/dist-cli/chunks/{chunk-5DIGWOY7.js → chunk-BDMAV7YE.js} +1 -1
- package/dist-cli/chunks/{chunk-CF2LPRXD.js → chunk-BGA7UNHQ.js} +2 -2
- package/dist-cli/chunks/{chunk-MAO7F5PH.js → chunk-BREFZK7S.js} +3 -3
- package/dist-cli/chunks/chunk-CIRLGKNJ.js +2 -0
- package/dist-cli/chunks/{chunk-KUSQ4NNJ.js → chunk-CQGEFQ2O.js} +1 -1
- package/dist-cli/chunks/{chunk-5S6D7K4L.js → chunk-F2V2RDSF.js} +2 -2
- package/dist-cli/chunks/chunk-FYFVAKLG.js +1 -0
- package/dist-cli/chunks/{chunk-E2QE5FFP.js → chunk-G4DPGAY7.js} +1 -1
- package/dist-cli/chunks/{chunk-5N3V7OCG.js → chunk-HSIKVDO7.js} +2 -2
- package/dist-cli/chunks/{chunk-RZHREO3M.js → chunk-HUL7SDXP.js} +2 -2
- package/dist-cli/chunks/{chunk-HQDJ5BOF.js → chunk-IFTNXJFC.js} +1 -1
- package/dist-cli/chunks/{chunk-OISHLFON.js → chunk-JIGBO7T2.js} +1 -1
- package/dist-cli/chunks/{chunk-NVTL3JQG.js → chunk-JNC2KM5L.js} +1 -1
- package/dist-cli/chunks/{chunk-ZO3VHP6W.js → chunk-KHCGD2SK.js} +22 -10
- package/dist-cli/chunks/chunk-KOJH7M2Y.js +24 -0
- package/dist-cli/chunks/{chunk-BZL6D4TV.js → chunk-KRG3TVPS.js} +63 -62
- package/dist-cli/chunks/{chunk-OUNLJM56.js → chunk-L7NMKMAC.js} +2 -2
- package/dist-cli/chunks/{chunk-4EVSIUNB.js → chunk-LAFA2UUY.js} +2 -2
- package/dist-cli/chunks/{chunk-SBGOUA6F.js → chunk-LKF24E4V.js} +2 -2
- package/dist-cli/chunks/{chunk-AFNDVS4E.js → chunk-MAFNPEGR.js} +2 -2
- package/dist-cli/chunks/{chunk-GTAD6IUV.js → chunk-MDZ6HMDB.js} +1 -1
- package/dist-cli/chunks/chunk-NNBW2HSI.js +1 -0
- package/dist-cli/chunks/{chunk-EBEL6TTJ.js → chunk-OB6UTULM.js} +2 -2
- package/dist-cli/chunks/{chunk-7LKUN46F.js → chunk-OOMEG6UD.js} +2 -2
- package/dist-cli/chunks/{chunk-UYRGCJ4N.js → chunk-P7TSRSCR.js} +45 -45
- package/dist-cli/chunks/{chunk-BESAZ2HA.js → chunk-PJA4MECT.js} +2 -2
- package/dist-cli/chunks/{chunk-4QZHZ6BC.js → chunk-PQ64ESHO.js} +2 -2
- package/dist-cli/chunks/{chunk-AC6QGW22.js → chunk-PQIWV724.js} +2 -2
- package/dist-cli/chunks/{chunk-H44IQHKZ.js → chunk-PRQGETWQ.js} +1 -1
- package/dist-cli/chunks/{chunk-BHZJ6RIH.js → chunk-PV7UPMMH.js} +2 -2
- package/dist-cli/chunks/{chunk-PHPXGLME.js → chunk-QFHW7D44.js} +1 -1
- package/dist-cli/chunks/{chunk-O6N2CEET.js → chunk-QI3CAQIS.js} +2 -2
- package/dist-cli/chunks/{chunk-G7CIZ5S3.js → chunk-RFES5JTB.js} +3 -3
- package/dist-cli/chunks/chunk-SFGIFF2S.js +2 -0
- package/dist-cli/chunks/chunk-TRLVCBYL.js +1 -0
- package/dist-cli/chunks/{chunk-WGDL5V6C.js → chunk-Y2H2L6L7.js} +1 -1
- package/dist-cli/chunks/{chunk-3WGHC7JN.js → chunk-ZKJ42ZMK.js} +2 -2
- package/dist-cli/chunks/cli-version-QYZHMOJT.js +2 -0
- package/dist-cli/chunks/{compat-PCXGGZBZ.js → compat-46LSYJLF.js} +3 -3
- package/dist-cli/chunks/{config-LULEVEYL.js → config-P5NLMUL2.js} +2 -2
- package/dist-cli/chunks/{control-6P6HY7UF.js → control-3O7JEUFC.js} +2 -2
- package/dist-cli/chunks/{cpu-profile-NOK73ZYW.js → cpu-profile-LDMMDC7S.js} +2 -2
- package/dist-cli/chunks/{daemon-4A3DMUYL.js → daemon-BL3MXXR3.js} +3 -3
- package/dist-cli/chunks/{debug-74BWB2ZG.js → debug-SQA6GG37.js} +3 -3
- package/dist-cli/chunks/{detox-HEOMINSC.js → detox-TY6AOSA7.js} +2 -2
- package/dist-cli/chunks/{device-TTXXBJFZ.js → device-QWFX4556.js} +2 -2
- package/dist-cli/chunks/{diagnose-QZ3GOHSE.js → diagnose-P2UVBUN6.js} +2 -2
- package/dist-cli/chunks/drivers-HPRXOC6D.js +2 -0
- package/dist-cli/chunks/{electron-QVOWV44R.js → electron-U3KDMBJM.js} +3 -3
- package/dist-cli/chunks/flow-XGMUH4JT.js +2 -0
- package/dist-cli/chunks/help-HZCKWAH5.js +2 -0
- package/dist-cli/chunks/{hints-YKWRNMJC.js → hints-2IYL3NF4.js} +2 -2
- package/dist-cli/chunks/{home-paths-SFADSTJM.js → home-paths-5SZOYDCC.js} +2 -2
- package/dist-cli/chunks/{inspect-LEWGQCIU.js → inspect-FA4L7WIE.js} +107 -107
- package/dist-cli/chunks/install-SYVS2T2T.js +2 -0
- package/dist-cli/chunks/{install-desktop-22HYQZ2G.js → install-desktop-OLT6LS5L.js} +3 -3
- package/dist-cli/chunks/{keys-3ZT3MICU.js → keys-3OXB23J4.js} +2 -2
- package/dist-cli/chunks/{launch-ZXW2NFLG.js → launch-HEXKSA3X.js} +3 -3
- package/dist-cli/chunks/{login-NJKJ7GZO.js → login-DKQYESDF.js} +4 -4
- package/dist-cli/chunks/{logout-VMMQL7CB.js → logout-FMJJ3BR2.js} +2 -2
- package/dist-cli/chunks/{maestro-OJY4MTI7.js → maestro-Z24ESGQW.js} +2 -2
- package/dist-cli/chunks/{preview-QU2GXTEV.js → preview-ODKBHTV5.js} +2 -2
- package/dist-cli/chunks/{profile-7APWK47T.js → profile-2PIY7B3L.js} +2 -2
- package/dist-cli/chunks/{react-RSVO5JZZ.js → react-HL4CHJS4.js} +2 -2
- package/dist-cli/chunks/{record-UWH4MDEO.js → record-4LYFSZUK.js} +2 -2
- package/dist-cli/chunks/runtime-JML6VARG.js +2 -0
- package/dist-cli/chunks/{runtime-delivery-QMKGRV7N.js → runtime-delivery-U7WIYI7J.js} +2 -2
- package/dist-cli/chunks/{screenshot-43M27ALE.js → screenshot-YUA2BHDF.js} +2 -2
- package/dist-cli/chunks/{screenshot-mode-EBYYN6TY.js → screenshot-mode-UIL75CHP.js} +2 -2
- package/dist-cli/chunks/{screenshots-7TQZL6Z6.js → screenshots-YJWODQGP.js} +2 -2
- package/dist-cli/chunks/server-J644PTIB.js +40 -0
- package/dist-cli/chunks/setup-repo-GSEZY74V.js +2 -0
- package/dist-cli/chunks/{skills-RQA6EJQL.js → skills-PEBZZZTL.js} +2 -2
- package/dist-cli/chunks/{start-ZT6MBYND.js → start-JCJQRDDQ.js} +4 -4
- package/dist-cli/chunks/store-XGTUSOGS.js +2 -0
- package/dist-cli/chunks/telemetry-Y3IESY7P.js +2 -0
- package/dist-cli/chunks/{test-RNRX5SWV.js → test-Z3NU6IN7.js} +3 -3
- package/dist-cli/chunks/{three-mode-TQZH25ZO.js → three-mode-CFSZ2ZOW.js} +2 -2
- package/dist-cli/chunks/{timeline-GGN3AY6P.js → timeline-GEND6OI3.js} +2 -2
- package/dist-cli/chunks/{upgrade-XT22D67C.js → upgrade-6GFR2ZB7.js} +3 -3
- package/dist-cli/chunks/upload-OPMPP35I.js +2 -0
- package/dist-cli/chunks/{web-KEHVF5MB.js → web-7A27OUAC.js} +2 -2
- package/dist-cli/chunks/{what-happened-PATQRJ5T.js → what-happened-57G5T2GM.js} +2 -2
- package/dist-cli/chunks/{whoami-CXVY26VV.js → whoami-3ICC26FV.js} +2 -2
- package/dist-lib/agent-daemon-client.cjs +1 -1
- package/dist-lib/agent-events.cjs +1 -1
- package/dist-lib/agent-sessions.cjs +1 -1
- package/dist-lib/attached-projects.cjs +1 -1
- package/dist-lib/auth/shared-session.cjs +1 -1
- package/dist-lib/backend-origin.cjs +1 -1
- package/dist-lib/beta.cjs +1 -1
- package/dist-lib/beta.mjs +15 -0
- package/dist-lib/bridge-constants.cjs +1 -1
- package/dist-lib/cli-constants.cjs +1 -1
- package/dist-lib/config.cjs +1 -1
- package/dist-lib/detox/index.cjs +1 -1
- package/dist-lib/dev-bundle-resolution.cjs +1 -1
- package/dist-lib/home-paths.cjs +1 -1
- package/dist-lib/host/bridge-host.cjs +244 -35
- package/dist-lib/host/fetch-proxy-handler.cjs +24 -4
- package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
- package/dist-lib/host/fetch-proxy-overrides.mjs +33 -0
- package/dist-lib/host/websocket-proxy.cjs +207 -0
- package/dist-lib/index.cjs +1 -1
- package/dist-lib/metro.cjs +1 -1
- package/dist-lib/profiles.cjs +1 -1
- package/dist-lib/render-mode.cjs +1 -1
- package/dist-lib/scripts/demo-app-registry.cjs +14 -3
- package/dist-lib/scripts/dev-server-scanner.cjs +14 -3
- package/dist-lib/skills.cjs +290 -73
- package/dist-lib/vite.cjs +1 -1
- package/package.json +7 -1
- package/scripts/demo-app-registry.ts +17 -1
- package/src/host/bridge-host.ts +8 -1
- package/src/host/fetch-proxy-handler.ts +26 -3
- package/src/host/websocket-proxy.ts +201 -0
- package/dist-cli/chunks/auto-bootstrap-47RN2V5G.js +0 -2
- package/dist-cli/chunks/beta-BRCGAF2N.js +0 -2
- package/dist-cli/chunks/chunk-36RPD6JI.js +0 -2
- package/dist-cli/chunks/chunk-4DBPNLGI.js +0 -1
- package/dist-cli/chunks/chunk-PQFFUJR6.js +0 -24
- package/dist-cli/chunks/chunk-QQAECG5B.js +0 -2
- package/dist-cli/chunks/chunk-SSCA2AEA.js +0 -1
- package/dist-cli/chunks/chunk-ZFAM4N5B.js +0 -1
- package/dist-cli/chunks/cli-version-WPFDM2A6.js +0 -2
- package/dist-cli/chunks/drivers-QRPWNOIT.js +0 -2
- package/dist-cli/chunks/flow-QMA7GVN6.js +0 -2
- package/dist-cli/chunks/install-7N2N7Q32.js +0 -2
- package/dist-cli/chunks/runtime-3FUENRHM.js +0 -2
- package/dist-cli/chunks/server-VCFM25Z6.js +0 -35
- package/dist-cli/chunks/setup-repo-HFH4VKJQ.js +0 -2
- package/dist-cli/chunks/store-BJBTDSZE.js +0 -2
- package/dist-cli/chunks/telemetry-ZZZKTILZ.js +0 -2
- package/dist-cli/chunks/upload-NC2AYLC5.js +0 -2
package/dist-lib/skills.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! sootsim v0.1.
|
|
1
|
+
/*! sootsim v0.1.87 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __create = Object.create;
|
|
@@ -10124,11 +10124,22 @@ var init_demo_app_registry = __esm({
|
|
|
10124
10124
|
// be holding pglite locks on ~/takeout/.orez (soot can attach takeout as
|
|
10125
10125
|
// a project and spin up its own orez against the same data dir).
|
|
10126
10126
|
readyTimeoutMs: 24e4,
|
|
10127
|
+
managedPorts: (p) => {
|
|
10128
|
+
const offset = p - 8081;
|
|
10129
|
+
return [5433 + offset, 4848 + offset, 9200 + offset];
|
|
10130
|
+
},
|
|
10127
10131
|
command: (p) => ({
|
|
10128
|
-
cmd: "bun lite",
|
|
10132
|
+
cmd: "bun lite:demo",
|
|
10129
10133
|
env: {
|
|
10134
|
+
TAKEOUT_ENV_MODE: "development",
|
|
10130
10135
|
PORT_OFFSET: String(p - 8081),
|
|
10131
|
-
OREZ_DATA_DIR: `${HOME}/.cache/sootsim-demo/takeout-orez
|
|
10136
|
+
OREZ_DATA_DIR: `${HOME}/.cache/sootsim-demo/takeout-orez`,
|
|
10137
|
+
VITE_DEMO_MODE: "1",
|
|
10138
|
+
ZERO_APP_ID: "takeout",
|
|
10139
|
+
ZERO_APP_PUBLICATIONS: "zero_takeout",
|
|
10140
|
+
ZERO_CVR_MAX_CONNS: "4",
|
|
10141
|
+
ZERO_NUM_SYNC_WORKERS: "2",
|
|
10142
|
+
ZERO_UPSTREAM_MAX_CONNS: "8"
|
|
10132
10143
|
}
|
|
10133
10144
|
})
|
|
10134
10145
|
},
|
|
@@ -12440,6 +12451,18 @@ function buildFetchProxyHeaders(reqHeaders, targetUrl) {
|
|
|
12440
12451
|
);
|
|
12441
12452
|
return headers;
|
|
12442
12453
|
}
|
|
12454
|
+
function buildAppApiProxyHeaders(reqHeaders, targetUrl) {
|
|
12455
|
+
const headers = {};
|
|
12456
|
+
for (const [key, value] of Object.entries(reqHeaders)) {
|
|
12457
|
+
if (!value) continue;
|
|
12458
|
+
if (APP_API_HEADER_REWRITES.has(key.toLowerCase())) continue;
|
|
12459
|
+
headers[key] = value;
|
|
12460
|
+
}
|
|
12461
|
+
headers.host = targetUrl.host;
|
|
12462
|
+
headers.origin = targetUrl.origin;
|
|
12463
|
+
headers.referer = `${targetUrl.origin}/`;
|
|
12464
|
+
return headers;
|
|
12465
|
+
}
|
|
12443
12466
|
function isFetchProxyRequestUrl(rawUrl) {
|
|
12444
12467
|
return rawUrl?.startsWith("/__fetch-proxy?") || rawUrl?.startsWith("/__proxy?") || false;
|
|
12445
12468
|
}
|
|
@@ -12550,9 +12573,7 @@ function handleAppApiRequest(req, res) {
|
|
|
12550
12573
|
return true;
|
|
12551
12574
|
}
|
|
12552
12575
|
const transport = targetUrl.protocol === "https:" ? import_https.default : import_http2.default;
|
|
12553
|
-
const fwdHeaders =
|
|
12554
|
-
delete fwdHeaders.host;
|
|
12555
|
-
fwdHeaders.host = targetUrl.host;
|
|
12576
|
+
const fwdHeaders = buildAppApiProxyHeaders(req.headers, targetUrl);
|
|
12556
12577
|
const proxyReq = transport.request(
|
|
12557
12578
|
{
|
|
12558
12579
|
hostname: targetUrl.hostname,
|
|
@@ -12582,7 +12603,7 @@ function handleAppApiRequest(req, res) {
|
|
|
12582
12603
|
req.pipe(proxyReq);
|
|
12583
12604
|
return true;
|
|
12584
12605
|
}
|
|
12585
|
-
var import_http2, import_https, STRIP_FETCH_PROXY_HEADERS, FETCH_PROXY_CORS_HEADERS;
|
|
12606
|
+
var import_http2, import_https, STRIP_FETCH_PROXY_HEADERS, FETCH_PROXY_CORS_HEADERS, APP_API_HEADER_REWRITES;
|
|
12586
12607
|
var init_fetch_proxy_handler = __esm({
|
|
12587
12608
|
"src/host/fetch-proxy-handler.ts"() {
|
|
12588
12609
|
"use strict";
|
|
@@ -12615,6 +12636,14 @@ var init_fetch_proxy_handler = __esm({
|
|
|
12615
12636
|
"access-control-expose-headers": "*",
|
|
12616
12637
|
"access-control-max-age": "3600"
|
|
12617
12638
|
};
|
|
12639
|
+
APP_API_HEADER_REWRITES = /* @__PURE__ */ new Set([
|
|
12640
|
+
"host",
|
|
12641
|
+
"origin",
|
|
12642
|
+
"referer",
|
|
12643
|
+
"sec-fetch-site",
|
|
12644
|
+
"sec-fetch-mode",
|
|
12645
|
+
"sec-fetch-dest"
|
|
12646
|
+
]);
|
|
12618
12647
|
}
|
|
12619
12648
|
});
|
|
12620
12649
|
|
|
@@ -12771,6 +12800,186 @@ var init_open_url = __esm({
|
|
|
12771
12800
|
}
|
|
12772
12801
|
});
|
|
12773
12802
|
|
|
12803
|
+
// src/host/websocket-proxy.ts
|
|
12804
|
+
function rejectUpgrade(socket, status, message) {
|
|
12805
|
+
try {
|
|
12806
|
+
socket.write(
|
|
12807
|
+
`HTTP/1.1 ${status} ${message}\r
|
|
12808
|
+
Connection: close\r
|
|
12809
|
+
Content-Type: text/plain\r
|
|
12810
|
+
Content-Length: ${message.length}\r
|
|
12811
|
+
\r
|
|
12812
|
+
${message}`
|
|
12813
|
+
);
|
|
12814
|
+
} catch {
|
|
12815
|
+
}
|
|
12816
|
+
socket.destroy();
|
|
12817
|
+
}
|
|
12818
|
+
function isSameOriginUpgrade(req) {
|
|
12819
|
+
const origin = req.headers.origin;
|
|
12820
|
+
const host = req.headers.host;
|
|
12821
|
+
if (!origin || !host) return false;
|
|
12822
|
+
try {
|
|
12823
|
+
return new URL(origin).host === host;
|
|
12824
|
+
} catch {
|
|
12825
|
+
return false;
|
|
12826
|
+
}
|
|
12827
|
+
}
|
|
12828
|
+
function decodeProxyHeaders(encoded) {
|
|
12829
|
+
if (!encoded) return {};
|
|
12830
|
+
const base64 = encoded.replace(/-/g, "+").replace(/_/g, "/");
|
|
12831
|
+
const padded = base64 + "=".repeat((4 - base64.length % 4) % 4);
|
|
12832
|
+
const parsed = JSON.parse(Buffer.from(padded, "base64").toString("utf8"));
|
|
12833
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return {};
|
|
12834
|
+
const headers = {};
|
|
12835
|
+
for (const [key, value] of Object.entries(parsed)) {
|
|
12836
|
+
if (value == null) continue;
|
|
12837
|
+
if (STRIP_UPSTREAM_HEADERS.has(key.toLowerCase())) continue;
|
|
12838
|
+
headers[key] = Array.isArray(value) ? value.join(", ") : String(value);
|
|
12839
|
+
}
|
|
12840
|
+
return headers;
|
|
12841
|
+
}
|
|
12842
|
+
function getDefaultWebSocketOrigin(targetUrl) {
|
|
12843
|
+
const origin = new URL(targetUrl.href);
|
|
12844
|
+
origin.protocol = targetUrl.protocol === "wss:" ? "https:" : "http:";
|
|
12845
|
+
return origin.origin;
|
|
12846
|
+
}
|
|
12847
|
+
function getRequestedProtocols(req) {
|
|
12848
|
+
const header = req.headers["sec-websocket-protocol"];
|
|
12849
|
+
const value = Array.isArray(header) ? header.join(",") : header || "";
|
|
12850
|
+
return value.split(",").map((part) => part.trim()).filter(Boolean);
|
|
12851
|
+
}
|
|
12852
|
+
function safeClose(ws, code, reason) {
|
|
12853
|
+
if (ws.readyState === import_ws.WebSocket.CLOSED || ws.readyState === import_ws.WebSocket.CLOSING) {
|
|
12854
|
+
return;
|
|
12855
|
+
}
|
|
12856
|
+
try {
|
|
12857
|
+
ws.close(code, reason);
|
|
12858
|
+
} catch {
|
|
12859
|
+
ws.terminate();
|
|
12860
|
+
}
|
|
12861
|
+
}
|
|
12862
|
+
function connectProxyPair(clientWs, upstream) {
|
|
12863
|
+
let closing = false;
|
|
12864
|
+
const closeBoth = (source, target, code, reason) => {
|
|
12865
|
+
if (closing) return;
|
|
12866
|
+
closing = true;
|
|
12867
|
+
safeClose(target, code, reason.toString());
|
|
12868
|
+
if (source.readyState === import_ws.WebSocket.OPEN) {
|
|
12869
|
+
safeClose(source, code, reason.toString());
|
|
12870
|
+
}
|
|
12871
|
+
};
|
|
12872
|
+
clientWs.on("message", (data, isBinary) => {
|
|
12873
|
+
if (upstream.readyState === import_ws.WebSocket.OPEN) {
|
|
12874
|
+
upstream.send(data, { binary: isBinary });
|
|
12875
|
+
}
|
|
12876
|
+
});
|
|
12877
|
+
upstream.on("message", (data, isBinary) => {
|
|
12878
|
+
if (clientWs.readyState === import_ws.WebSocket.OPEN) {
|
|
12879
|
+
clientWs.send(data, { binary: isBinary });
|
|
12880
|
+
}
|
|
12881
|
+
});
|
|
12882
|
+
clientWs.on("close", (code, reason) => closeBoth(clientWs, upstream, code, reason));
|
|
12883
|
+
upstream.on("close", (code, reason) => closeBoth(upstream, clientWs, code, reason));
|
|
12884
|
+
clientWs.on("error", () => safeClose(upstream, 1011, "proxy client error"));
|
|
12885
|
+
upstream.on("error", () => safeClose(clientWs, 1011, "upstream websocket error"));
|
|
12886
|
+
}
|
|
12887
|
+
function createUpstreamWebSocket(targetUrl, protocols, headers) {
|
|
12888
|
+
const upstreamHeaders = { ...headers };
|
|
12889
|
+
if (!Object.keys(upstreamHeaders).some((key) => key.toLowerCase() === "origin")) {
|
|
12890
|
+
upstreamHeaders.origin = getDefaultWebSocketOrigin(targetUrl);
|
|
12891
|
+
}
|
|
12892
|
+
return new import_ws.WebSocket(targetUrl.href, protocols, {
|
|
12893
|
+
headers: upstreamHeaders
|
|
12894
|
+
});
|
|
12895
|
+
}
|
|
12896
|
+
function isWebSocketProxyRequestUrl(rawUrl) {
|
|
12897
|
+
if (!rawUrl) return false;
|
|
12898
|
+
try {
|
|
12899
|
+
return new URL(rawUrl, "http://localhost").pathname === WEBSOCKET_PROXY_PATH;
|
|
12900
|
+
} catch {
|
|
12901
|
+
return false;
|
|
12902
|
+
}
|
|
12903
|
+
}
|
|
12904
|
+
function handleWebSocketProxyUpgrade(req, socket, head) {
|
|
12905
|
+
if (!isWebSocketProxyRequestUrl(req.url)) return false;
|
|
12906
|
+
if (!isSameOriginUpgrade(req)) {
|
|
12907
|
+
rejectUpgrade(socket, 403, "forbidden websocket proxy origin");
|
|
12908
|
+
return true;
|
|
12909
|
+
}
|
|
12910
|
+
let targetUrl;
|
|
12911
|
+
let headers;
|
|
12912
|
+
try {
|
|
12913
|
+
const requestUrl = new URL(req.url || "/", "http://localhost");
|
|
12914
|
+
const target = requestUrl.searchParams.get("url");
|
|
12915
|
+
if (!target) {
|
|
12916
|
+
rejectUpgrade(socket, 400, "missing websocket proxy url");
|
|
12917
|
+
return true;
|
|
12918
|
+
}
|
|
12919
|
+
targetUrl = new URL(target);
|
|
12920
|
+
if (targetUrl.protocol !== "ws:" && targetUrl.protocol !== "wss:") {
|
|
12921
|
+
rejectUpgrade(socket, 400, "invalid websocket proxy protocol");
|
|
12922
|
+
return true;
|
|
12923
|
+
}
|
|
12924
|
+
headers = decodeProxyHeaders(requestUrl.searchParams.get("headers"));
|
|
12925
|
+
} catch {
|
|
12926
|
+
rejectUpgrade(socket, 400, "invalid websocket proxy request");
|
|
12927
|
+
return true;
|
|
12928
|
+
}
|
|
12929
|
+
const protocols = getRequestedProtocols(req);
|
|
12930
|
+
const upstream = createUpstreamWebSocket(targetUrl, protocols, headers);
|
|
12931
|
+
let completed = false;
|
|
12932
|
+
socket.once("close", () => {
|
|
12933
|
+
if (!completed) upstream.terminate();
|
|
12934
|
+
});
|
|
12935
|
+
upstream.once("open", () => {
|
|
12936
|
+
if (completed) return;
|
|
12937
|
+
completed = true;
|
|
12938
|
+
const selectedProtocol = upstream.protocol;
|
|
12939
|
+
const proxyServer = new import_ws.WebSocketServer({
|
|
12940
|
+
noServer: true,
|
|
12941
|
+
clientTracking: false,
|
|
12942
|
+
handleProtocols(requestedProtocols) {
|
|
12943
|
+
return selectedProtocol || requestedProtocols.values().next().value || false;
|
|
12944
|
+
}
|
|
12945
|
+
});
|
|
12946
|
+
proxyServer.handleUpgrade(req, socket, head, (clientWs) => {
|
|
12947
|
+
connectProxyPair(clientWs, upstream);
|
|
12948
|
+
});
|
|
12949
|
+
});
|
|
12950
|
+
upstream.once("error", () => {
|
|
12951
|
+
if (completed) return;
|
|
12952
|
+
completed = true;
|
|
12953
|
+
rejectUpgrade(socket, 502, "upstream websocket error");
|
|
12954
|
+
});
|
|
12955
|
+
upstream.once("close", () => {
|
|
12956
|
+
if (completed) return;
|
|
12957
|
+
completed = true;
|
|
12958
|
+
rejectUpgrade(socket, 502, "upstream websocket closed");
|
|
12959
|
+
});
|
|
12960
|
+
return true;
|
|
12961
|
+
}
|
|
12962
|
+
var import_ws, WEBSOCKET_PROXY_PATH, STRIP_UPSTREAM_HEADERS;
|
|
12963
|
+
var init_websocket_proxy = __esm({
|
|
12964
|
+
"src/host/websocket-proxy.ts"() {
|
|
12965
|
+
"use strict";
|
|
12966
|
+
import_ws = require("ws");
|
|
12967
|
+
WEBSOCKET_PROXY_PATH = "/__websocket-proxy";
|
|
12968
|
+
STRIP_UPSTREAM_HEADERS = /* @__PURE__ */ new Set([
|
|
12969
|
+
"host",
|
|
12970
|
+
"connection",
|
|
12971
|
+
"upgrade",
|
|
12972
|
+
"transfer-encoding",
|
|
12973
|
+
"content-length",
|
|
12974
|
+
"sec-websocket-accept",
|
|
12975
|
+
"sec-websocket-extensions",
|
|
12976
|
+
"sec-websocket-key",
|
|
12977
|
+
"sec-websocket-protocol",
|
|
12978
|
+
"sec-websocket-version"
|
|
12979
|
+
]);
|
|
12980
|
+
}
|
|
12981
|
+
});
|
|
12982
|
+
|
|
12774
12983
|
// src/host/bridge-host.ts
|
|
12775
12984
|
var bridge_host_exports = {};
|
|
12776
12985
|
__export(bridge_host_exports, {
|
|
@@ -12804,7 +13013,7 @@ function unrefTimer(timer) {
|
|
|
12804
13013
|
timer.unref();
|
|
12805
13014
|
}
|
|
12806
13015
|
}
|
|
12807
|
-
var import_child_process4, import_fs3, import_http3, import_path3,
|
|
13016
|
+
var import_child_process4, import_fs3, import_http3, import_path3, import_ws2, WRITE_COMMAND_TYPES, FORCE_CLOSE_GRACE_MS, FORCE_CLOSE_TERMINATE_MS, DAEMON_HEARTBEAT_INTERVAL_MS, DEFAULT_RUNTIME_UPDATE_INTERVAL_MS, RUNTIME_UPDATE_INTERVAL_ENV, HTTP_MIME_TYPES, SootSimBridgeHost;
|
|
12808
13017
|
var init_bridge_host = __esm({
|
|
12809
13018
|
"src/host/bridge-host.ts"() {
|
|
12810
13019
|
"use strict";
|
|
@@ -12812,7 +13021,7 @@ var init_bridge_host = __esm({
|
|
|
12812
13021
|
import_fs3 = __toESM(require("fs"), 1);
|
|
12813
13022
|
import_http3 = require("http");
|
|
12814
13023
|
import_path3 = __toESM(require("path"), 1);
|
|
12815
|
-
|
|
13024
|
+
import_ws2 = require("ws");
|
|
12816
13025
|
init_dev_server_scanner();
|
|
12817
13026
|
init_bridge_constants();
|
|
12818
13027
|
init_cli_version();
|
|
@@ -12821,6 +13030,7 @@ var init_bridge_host = __esm({
|
|
|
12821
13030
|
init_agent_host();
|
|
12822
13031
|
init_fetch_proxy_handler();
|
|
12823
13032
|
init_open_url();
|
|
13033
|
+
init_websocket_proxy();
|
|
12824
13034
|
WRITE_COMMAND_TYPES = /* @__PURE__ */ new Set(["tap", "keyboard"]);
|
|
12825
13035
|
FORCE_CLOSE_GRACE_MS = 2e3;
|
|
12826
13036
|
FORCE_CLOSE_TERMINATE_MS = 1e3;
|
|
@@ -13006,8 +13216,14 @@ var init_bridge_host = __esm({
|
|
|
13006
13216
|
`);
|
|
13007
13217
|
});
|
|
13008
13218
|
this.httpServer = server;
|
|
13009
|
-
this.wss = new
|
|
13219
|
+
this.wss = new import_ws2.WebSocketServer({ noServer: true });
|
|
13010
13220
|
this.wireWebSocketServer();
|
|
13221
|
+
server.on("upgrade", (req, socket, head) => {
|
|
13222
|
+
if (handleWebSocketProxyUpgrade(req, socket, head)) return;
|
|
13223
|
+
this.wss?.handleUpgrade(req, socket, head, (ws) => {
|
|
13224
|
+
this.wss?.emit("connection", ws, req);
|
|
13225
|
+
});
|
|
13226
|
+
});
|
|
13011
13227
|
resolve7();
|
|
13012
13228
|
});
|
|
13013
13229
|
});
|
|
@@ -13171,7 +13387,7 @@ var init_bridge_host = __esm({
|
|
|
13171
13387
|
config: next
|
|
13172
13388
|
});
|
|
13173
13389
|
for (const peer of this.sims.values()) {
|
|
13174
|
-
if (peer.ws.readyState !==
|
|
13390
|
+
if (peer.ws.readyState !== import_ws2.WebSocket.OPEN) continue;
|
|
13175
13391
|
try {
|
|
13176
13392
|
peer.ws.send(payload);
|
|
13177
13393
|
} catch {
|
|
@@ -13227,7 +13443,7 @@ var init_bridge_host = __esm({
|
|
|
13227
13443
|
const entry = this.cliBySentId.get(msg.id);
|
|
13228
13444
|
if (entry) {
|
|
13229
13445
|
this.cliBySentId.delete(msg.id);
|
|
13230
|
-
if (entry.ws.readyState ===
|
|
13446
|
+
if (entry.ws.readyState === import_ws2.WebSocket.OPEN) {
|
|
13231
13447
|
const otherCliCount = this.getOtherCliIdentityCount(entry.ws, entry.simId);
|
|
13232
13448
|
const response = otherCliCount > 0 ? { ...msg, id: entry.originalId, _otherCliCount: otherCliCount } : { ...msg, id: entry.originalId };
|
|
13233
13449
|
entry.ws.send(JSON.stringify(response));
|
|
@@ -13255,7 +13471,7 @@ var init_bridge_host = __esm({
|
|
|
13255
13471
|
if (typeof msg.cliLabel === "string" && msg.cliLabel.trim()) {
|
|
13256
13472
|
this.cliLabelBySocket.set(ws, msg.cliLabel.trim());
|
|
13257
13473
|
}
|
|
13258
|
-
if (ws.readyState ===
|
|
13474
|
+
if (ws.readyState === import_ws2.WebSocket.OPEN) {
|
|
13259
13475
|
ws.send(
|
|
13260
13476
|
JSON.stringify({
|
|
13261
13477
|
id: msg.id,
|
|
@@ -13270,7 +13486,7 @@ var init_bridge_host = __esm({
|
|
|
13270
13486
|
return;
|
|
13271
13487
|
}
|
|
13272
13488
|
if (msg.type === "bridge:list-sims") {
|
|
13273
|
-
if (ws.readyState ===
|
|
13489
|
+
if (ws.readyState === import_ws2.WebSocket.OPEN) {
|
|
13274
13490
|
ws.send(
|
|
13275
13491
|
JSON.stringify({
|
|
13276
13492
|
id: msg.id,
|
|
@@ -13285,7 +13501,7 @@ var init_bridge_host = __esm({
|
|
|
13285
13501
|
throw new Error("bridge:open requires a url");
|
|
13286
13502
|
}
|
|
13287
13503
|
await this.openUrl(msg.url, { newWindow: msg.newWindow === true });
|
|
13288
|
-
if (ws.readyState ===
|
|
13504
|
+
if (ws.readyState === import_ws2.WebSocket.OPEN) {
|
|
13289
13505
|
ws.send(
|
|
13290
13506
|
JSON.stringify({
|
|
13291
13507
|
id: msg.id,
|
|
@@ -13301,7 +13517,7 @@ var init_bridge_host = __esm({
|
|
|
13301
13517
|
force: msg.force === true
|
|
13302
13518
|
});
|
|
13303
13519
|
if (!outcome.granted) {
|
|
13304
|
-
if (ws.readyState ===
|
|
13520
|
+
if (ws.readyState === import_ws2.WebSocket.OPEN) {
|
|
13305
13521
|
ws.send(
|
|
13306
13522
|
JSON.stringify({
|
|
13307
13523
|
id: msg.id,
|
|
@@ -13317,7 +13533,7 @@ var init_bridge_host = __esm({
|
|
|
13317
13533
|
targetSim2.id,
|
|
13318
13534
|
outcome.bootedCount > 0 ? `cli force-claimed sim (booted ${outcome.bootedCount})` : "cli claimed sim"
|
|
13319
13535
|
);
|
|
13320
|
-
if (ws.readyState ===
|
|
13536
|
+
if (ws.readyState === import_ws2.WebSocket.OPEN) {
|
|
13321
13537
|
ws.send(
|
|
13322
13538
|
JSON.stringify({
|
|
13323
13539
|
id: msg.id,
|
|
@@ -13336,7 +13552,7 @@ var init_bridge_host = __esm({
|
|
|
13336
13552
|
if (shouldAcquireLease(msg)) {
|
|
13337
13553
|
const outcome = this.tryAcquireLease(ws, targetSim);
|
|
13338
13554
|
if (!outcome.granted) {
|
|
13339
|
-
if (ws.readyState ===
|
|
13555
|
+
if (ws.readyState === import_ws2.WebSocket.OPEN) {
|
|
13340
13556
|
ws.send(
|
|
13341
13557
|
JSON.stringify({
|
|
13342
13558
|
id: msg.id,
|
|
@@ -13362,7 +13578,7 @@ var init_bridge_host = __esm({
|
|
|
13362
13578
|
targetSim.ws.send(JSON.stringify({ ...forwarded, id: sentId }));
|
|
13363
13579
|
if (forwarded.type === "close") {
|
|
13364
13580
|
this.cliBySentId.delete(sentId);
|
|
13365
|
-
if (ws.readyState ===
|
|
13581
|
+
if (ws.readyState === import_ws2.WebSocket.OPEN) {
|
|
13366
13582
|
ws.send(
|
|
13367
13583
|
JSON.stringify({
|
|
13368
13584
|
id: msg.id,
|
|
@@ -13377,7 +13593,7 @@ var init_bridge_host = __esm({
|
|
|
13377
13593
|
unrefTimer(closeTimer);
|
|
13378
13594
|
}
|
|
13379
13595
|
} catch (err) {
|
|
13380
|
-
if (ws.readyState ===
|
|
13596
|
+
if (ws.readyState === import_ws2.WebSocket.OPEN) {
|
|
13381
13597
|
ws.send(
|
|
13382
13598
|
JSON.stringify({
|
|
13383
13599
|
id: msg.id,
|
|
@@ -13402,7 +13618,7 @@ var init_bridge_host = __esm({
|
|
|
13402
13618
|
}
|
|
13403
13619
|
for (const [sentId, entry] of this.cliBySentId) {
|
|
13404
13620
|
if (entry.simId !== sim.id) continue;
|
|
13405
|
-
if (entry.ws.readyState ===
|
|
13621
|
+
if (entry.ws.readyState === import_ws2.WebSocket.OPEN) {
|
|
13406
13622
|
entry.ws.send(
|
|
13407
13623
|
JSON.stringify({
|
|
13408
13624
|
id: entry.originalId,
|
|
@@ -13608,7 +13824,7 @@ var init_bridge_host = __esm({
|
|
|
13608
13824
|
runtimeDir: this.activeRuntimeDirPath
|
|
13609
13825
|
});
|
|
13610
13826
|
for (const sim of this.sims.values()) {
|
|
13611
|
-
if (sim.ws.readyState ===
|
|
13827
|
+
if (sim.ws.readyState === import_ws2.WebSocket.OPEN) {
|
|
13612
13828
|
try {
|
|
13613
13829
|
sim.ws.send(payload);
|
|
13614
13830
|
} catch {
|
|
@@ -13933,7 +14149,7 @@ var init_bridge_host = __esm({
|
|
|
13933
14149
|
sweepDeadWebSockets() {
|
|
13934
14150
|
if (!this.wss) return;
|
|
13935
14151
|
for (const ws of this.wss.clients) {
|
|
13936
|
-
if (ws.readyState !==
|
|
14152
|
+
if (ws.readyState !== import_ws2.WebSocket.OPEN) continue;
|
|
13937
14153
|
const alive = this.wsIsAlive.get(ws);
|
|
13938
14154
|
if (alive === false) {
|
|
13939
14155
|
try {
|
|
@@ -13954,7 +14170,7 @@ var init_bridge_host = __esm({
|
|
|
13954
14170
|
}
|
|
13955
14171
|
}
|
|
13956
14172
|
closeSimSocketFromHost(ws) {
|
|
13957
|
-
if (ws.readyState !==
|
|
14173
|
+
if (ws.readyState !== import_ws2.WebSocket.OPEN) return;
|
|
13958
14174
|
try {
|
|
13959
14175
|
ws.close(SOOTSIM_BRIDGE_SIM_CLOSE_CODE, SOOTSIM_BRIDGE_SIM_CLOSE_REASON);
|
|
13960
14176
|
} catch {
|
|
@@ -13965,7 +14181,7 @@ var init_bridge_host = __esm({
|
|
|
13965
14181
|
return;
|
|
13966
14182
|
}
|
|
13967
14183
|
const terminateTimer = setTimeout(() => {
|
|
13968
|
-
if (ws.readyState ===
|
|
14184
|
+
if (ws.readyState === import_ws2.WebSocket.CLOSED) return;
|
|
13969
14185
|
try {
|
|
13970
14186
|
ws.terminate();
|
|
13971
14187
|
} catch {
|
|
@@ -14114,7 +14330,7 @@ var init_bridge_host = __esm({
|
|
|
14114
14330
|
try {
|
|
14115
14331
|
readyState = sim.ws.readyState;
|
|
14116
14332
|
} catch {
|
|
14117
|
-
readyState =
|
|
14333
|
+
readyState = import_ws2.WebSocket.CLOSED;
|
|
14118
14334
|
}
|
|
14119
14335
|
const lease = this.getActiveLease(sim);
|
|
14120
14336
|
return {
|
|
@@ -14127,7 +14343,7 @@ var init_bridge_host = __esm({
|
|
|
14127
14343
|
lastSeenAt: sim.lastSeenAt,
|
|
14128
14344
|
lastActiveAt: sim.lastActiveAt || void 0,
|
|
14129
14345
|
isPrimary: sim.id === this.primarySimId,
|
|
14130
|
-
readyState: readyState ===
|
|
14346
|
+
readyState: readyState === import_ws2.WebSocket.OPEN ? "open" : readyState === import_ws2.WebSocket.CLOSING ? "closing" : "closed",
|
|
14131
14347
|
attachedCliCount: this.getAttachedCliCount(sim.id),
|
|
14132
14348
|
lockedBy: lease ? lease.cliLabel || lease.cliIdentityKey : void 0,
|
|
14133
14349
|
lockedByKind: lease ? lease.kind : void 0,
|
|
@@ -14244,18 +14460,18 @@ var init_bridge_host = __esm({
|
|
|
14244
14460
|
getOpenSim(simId) {
|
|
14245
14461
|
if (simId) {
|
|
14246
14462
|
const sim = this.sims.get(simId);
|
|
14247
|
-
if (sim?.ws.readyState ===
|
|
14463
|
+
if (sim?.ws.readyState === import_ws2.WebSocket.OPEN) return sim;
|
|
14248
14464
|
return null;
|
|
14249
14465
|
}
|
|
14250
14466
|
const primary = this.primarySimId != null ? this.sims.get(this.primarySimId) : null;
|
|
14251
|
-
if (primary?.ws.readyState ===
|
|
14467
|
+
if (primary?.ws.readyState === import_ws2.WebSocket.OPEN && primary.url) return primary;
|
|
14252
14468
|
let pagelessFallback = null;
|
|
14253
14469
|
for (const sim of this.sims.values()) {
|
|
14254
|
-
if (sim.ws.readyState !==
|
|
14470
|
+
if (sim.ws.readyState !== import_ws2.WebSocket.OPEN) continue;
|
|
14255
14471
|
if (sim.url) return sim;
|
|
14256
14472
|
pagelessFallback ??= sim;
|
|
14257
14473
|
}
|
|
14258
|
-
if (primary?.ws.readyState ===
|
|
14474
|
+
if (primary?.ws.readyState === import_ws2.WebSocket.OPEN) return primary;
|
|
14259
14475
|
return pagelessFallback;
|
|
14260
14476
|
}
|
|
14261
14477
|
async waitForSim(simId, options = {}) {
|
|
@@ -14271,7 +14487,7 @@ var init_bridge_host = __esm({
|
|
|
14271
14487
|
shouldPromoteSim(sim) {
|
|
14272
14488
|
const current = this.primarySimId ? this.sims.get(this.primarySimId) : null;
|
|
14273
14489
|
if (!sim.url) return !current;
|
|
14274
|
-
const currentAlive = current?.ws.readyState ===
|
|
14490
|
+
const currentAlive = current?.ws.readyState === import_ws2.WebSocket.OPEN;
|
|
14275
14491
|
if (!current || !currentAlive || !current.url) return true;
|
|
14276
14492
|
const isPrimaryCandidate = sim.origin?.includes(":5173");
|
|
14277
14493
|
const currentIsPrimary = current.origin?.includes(":5173");
|
|
@@ -14279,7 +14495,7 @@ var init_bridge_host = __esm({
|
|
|
14279
14495
|
}
|
|
14280
14496
|
broadcastSimAssignments() {
|
|
14281
14497
|
for (const sim of this.sims.values()) {
|
|
14282
|
-
if (sim.ws.readyState !==
|
|
14498
|
+
if (sim.ws.readyState !== import_ws2.WebSocket.OPEN) continue;
|
|
14283
14499
|
sim.ws.send(
|
|
14284
14500
|
JSON.stringify({
|
|
14285
14501
|
type: "bridge:welcome",
|
|
@@ -14291,7 +14507,7 @@ var init_bridge_host = __esm({
|
|
|
14291
14507
|
}
|
|
14292
14508
|
broadcastSimClientStates() {
|
|
14293
14509
|
for (const sim of this.sims.values()) {
|
|
14294
|
-
if (sim.ws.readyState !==
|
|
14510
|
+
if (sim.ws.readyState !== import_ws2.WebSocket.OPEN) continue;
|
|
14295
14511
|
const lease = this.getActiveLease(sim);
|
|
14296
14512
|
const message = {
|
|
14297
14513
|
type: "bridge:client-state",
|
|
@@ -14356,7 +14572,7 @@ var init_bridge_host = __esm({
|
|
|
14356
14572
|
const keys = /* @__PURE__ */ new Set();
|
|
14357
14573
|
for (const [ws, attachedSimId] of this.cliSimBySocket) {
|
|
14358
14574
|
if (attachedSimId !== simId) continue;
|
|
14359
|
-
if (ws.readyState !==
|
|
14575
|
+
if (ws.readyState !== import_ws2.WebSocket.OPEN) continue;
|
|
14360
14576
|
const key = this.cliIdentityKeyBySocket.get(ws);
|
|
14361
14577
|
keys.add(key ?? `ws-unknown-${keys.size}`);
|
|
14362
14578
|
}
|
|
@@ -14369,7 +14585,7 @@ var init_bridge_host = __esm({
|
|
|
14369
14585
|
const keys = /* @__PURE__ */ new Set();
|
|
14370
14586
|
for (const [ws, attachedSimId] of this.cliSimBySocket) {
|
|
14371
14587
|
if (attachedSimId !== simId) continue;
|
|
14372
|
-
if (ws.readyState !==
|
|
14588
|
+
if (ws.readyState !== import_ws2.WebSocket.OPEN) continue;
|
|
14373
14589
|
const key = this.cliIdentityKeyBySocket.get(ws);
|
|
14374
14590
|
if (key && key === selfKey) continue;
|
|
14375
14591
|
keys.add(key ?? `ws-unknown-${keys.size}`);
|
|
@@ -14394,7 +14610,7 @@ var init_bridge_host = __esm({
|
|
|
14394
14610
|
const nextId = requestedId?.trim();
|
|
14395
14611
|
if (!nextId || nextId === sim.id) return false;
|
|
14396
14612
|
const existing = this.sims.get(nextId);
|
|
14397
|
-
if (existing && existing !== sim && existing.ws.readyState ===
|
|
14613
|
+
if (existing && existing !== sim && existing.ws.readyState === import_ws2.WebSocket.OPEN) {
|
|
14398
14614
|
return false;
|
|
14399
14615
|
}
|
|
14400
14616
|
const restorable = this.getRestorableSimState(nextId);
|
|
@@ -14772,7 +14988,7 @@ function createBridge(wsPort, opts = {}) {
|
|
|
14772
14988
|
let nextId = 1;
|
|
14773
14989
|
const commandTimeoutMs = opts.commandTimeoutMs ?? 15e3;
|
|
14774
14990
|
const pending = /* @__PURE__ */ new Map();
|
|
14775
|
-
const ws = new
|
|
14991
|
+
const ws = new import_ws3.WebSocket(`ws://localhost:${wsPort}`);
|
|
14776
14992
|
const identity = opts.simId ? {
|
|
14777
14993
|
key: `sim:${opts.simId}`,
|
|
14778
14994
|
source: "explicit-sim-id",
|
|
@@ -14925,14 +15141,14 @@ function createBridge(wsPort, opts = {}) {
|
|
|
14925
15141
|
},
|
|
14926
15142
|
close() {
|
|
14927
15143
|
try {
|
|
14928
|
-
if (ws.readyState ===
|
|
15144
|
+
if (ws.readyState === import_ws3.WebSocket.OPEN) {
|
|
14929
15145
|
ws.send(JSON.stringify({ type: "bridge:bye", id: 0 }));
|
|
14930
15146
|
}
|
|
14931
15147
|
} catch {
|
|
14932
15148
|
}
|
|
14933
15149
|
ws.close();
|
|
14934
15150
|
const terminateTimer = setTimeout(() => {
|
|
14935
|
-
if (ws.readyState !==
|
|
15151
|
+
if (ws.readyState !== import_ws3.WebSocket.CLOSED) {
|
|
14936
15152
|
ws.terminate();
|
|
14937
15153
|
}
|
|
14938
15154
|
}, 250);
|
|
@@ -15002,11 +15218,11 @@ async function callInBridge(bridge, path9, ...args) {
|
|
|
15002
15218
|
async function callInBridgeWrite(bridge, path9, ...args) {
|
|
15003
15219
|
return bridge.send({ type: "call", path: path9, args, acquireLock: true });
|
|
15004
15220
|
}
|
|
15005
|
-
var
|
|
15221
|
+
var import_ws3, BridgeSimLockedError;
|
|
15006
15222
|
var init_ws_bridge = __esm({
|
|
15007
15223
|
"cli/ws-bridge.ts"() {
|
|
15008
15224
|
"use strict";
|
|
15009
|
-
|
|
15225
|
+
import_ws3 = require("ws");
|
|
15010
15226
|
init_bridge_constants();
|
|
15011
15227
|
init_home_paths();
|
|
15012
15228
|
init_current_sim();
|
|
@@ -16806,25 +17022,15 @@ var init_bridge_flow_runner = __esm({
|
|
|
16806
17022
|
}
|
|
16807
17023
|
async startProfile() {
|
|
16808
17024
|
await this.evaluate(`((sessionKey) => {
|
|
16809
|
-
const host = window.__sootsimRenderHost
|
|
16810
|
-
if (host?.startPerfSession) {
|
|
16811
|
-
host.startPerfSession(sessionKey)
|
|
16812
|
-
window[sessionKey] = {
|
|
16813
|
-
active: true,
|
|
16814
|
-
mode: 'render-worker',
|
|
16815
|
-
startedAt: performance.now(),
|
|
16816
|
-
}
|
|
16817
|
-
return
|
|
16818
|
-
}
|
|
16819
|
-
|
|
16820
17025
|
const perf = window.__sootsimPerf
|
|
16821
17026
|
const a11y = window.__sootsimA11y
|
|
16822
|
-
perf?.enableFrameStats?.()
|
|
17027
|
+
perf?.enableFrameStats?.(true)
|
|
16823
17028
|
perf?.resetFrameStats?.()
|
|
16824
17029
|
a11y?.resetProfile?.()
|
|
16825
17030
|
window[sessionKey] = {
|
|
16826
17031
|
active: true,
|
|
16827
|
-
mode: 'main-thread',
|
|
17032
|
+
mode: window.__sootsimRenderHost ? 'render-worker' : 'main-thread',
|
|
17033
|
+
lastSamples: [],
|
|
16828
17034
|
startedAt: performance.now(),
|
|
16829
17035
|
}
|
|
16830
17036
|
})(${JSON.stringify(CLI_PERF_SESSION_GLOBAL)})`);
|
|
@@ -16833,13 +17039,24 @@ var init_bridge_flow_runner = __esm({
|
|
|
16833
17039
|
async stopProfile() {
|
|
16834
17040
|
const result = await this.evaluate(`(async (sessionKey) => {
|
|
16835
17041
|
const host = window.__sootsimRenderHost
|
|
16836
|
-
if (host?.
|
|
16837
|
-
const
|
|
16838
|
-
|
|
16839
|
-
|
|
17042
|
+
if (host?.flushSamples) {
|
|
17043
|
+
const perf = window.__sootsimPerf
|
|
17044
|
+
const session = window[sessionKey] || {}
|
|
17045
|
+
const priorSamples = session.active && Array.isArray(session.lastSamples)
|
|
17046
|
+
? session.lastSamples
|
|
17047
|
+
: []
|
|
17048
|
+
const flushedSamples = await host.flushSamples()
|
|
17049
|
+
await perf?.disableFrameStats?.()
|
|
17050
|
+
const samples = priorSamples.concat(flushedSamples)
|
|
17051
|
+
window[sessionKey] = {
|
|
17052
|
+
...session,
|
|
17053
|
+
active: false,
|
|
17054
|
+
mode: 'render-worker',
|
|
17055
|
+
lastSamples: samples,
|
|
17056
|
+
stoppedAt: performance.now(),
|
|
16840
17057
|
}
|
|
16841
|
-
|
|
16842
|
-
const frameTimes = samples.map((sample) => Number(sample?.[1]) || 0)
|
|
17058
|
+
|
|
17059
|
+
const frameTimes = samples.map((sample) => Number(sample?.[1]) || 0)
|
|
16843
17060
|
const sorted = [...frameTimes].sort((a, b) => a - b)
|
|
16844
17061
|
const worstFrames = samples
|
|
16845
17062
|
.slice()
|
|
@@ -16855,16 +17072,16 @@ var init_bridge_flow_runner = __esm({
|
|
|
16855
17072
|
|
|
16856
17073
|
return {
|
|
16857
17074
|
mode: 'render-worker',
|
|
16858
|
-
frames:
|
|
16859
|
-
totalMs:
|
|
16860
|
-
avgMs:
|
|
16861
|
-
maxMs:
|
|
16862
|
-
layoutTotalMs:
|
|
16863
|
-
renderTotalMs:
|
|
16864
|
-
copyTotalMs:
|
|
16865
|
-
layoutAvgMs: Number(
|
|
16866
|
-
renderAvgMs: Number(
|
|
16867
|
-
copyAvgMs: Number(
|
|
17075
|
+
frames: frameTimes.length,
|
|
17076
|
+
totalMs: frameTimes.reduce((sum, value) => sum + value, 0),
|
|
17077
|
+
avgMs: frameTimes.length ? frameTimes.reduce((sum, value) => sum + value, 0) / frameTimes.length : 0,
|
|
17078
|
+
maxMs: sorted[sorted.length - 1] || 0,
|
|
17079
|
+
layoutTotalMs: samples.reduce((sum, sample) => sum + (Number(sample?.[2]) || 0), 0),
|
|
17080
|
+
renderTotalMs: samples.reduce((sum, sample) => sum + (Number(sample?.[3]) || 0), 0),
|
|
17081
|
+
copyTotalMs: samples.reduce((sum, sample) => sum + (Number(sample?.[4]) || 0), 0),
|
|
17082
|
+
layoutAvgMs: frameTimes.length ? samples.reduce((sum, sample) => sum + (Number(sample?.[2]) || 0), 0) / frameTimes.length : 0,
|
|
17083
|
+
renderAvgMs: frameTimes.length ? samples.reduce((sum, sample) => sum + (Number(sample?.[3]) || 0), 0) / frameTimes.length : 0,
|
|
17084
|
+
copyAvgMs: frameTimes.length ? samples.reduce((sum, sample) => sum + (Number(sample?.[4]) || 0), 0) / frameTimes.length : 0,
|
|
16868
17085
|
p50: sorted[Math.floor(sorted.length * 0.5)] || 0,
|
|
16869
17086
|
p95: sorted[Math.floor(sorted.length * 0.95)] || 0,
|
|
16870
17087
|
p99: sorted[Math.floor(sorted.length * 0.99)] || 0,
|
|
@@ -16878,11 +17095,11 @@ var init_bridge_flow_runner = __esm({
|
|
|
16878
17095
|
const a11y = window.__sootsimA11y
|
|
16879
17096
|
if (!perf && !a11y) return { error: 'no perf globals available' }
|
|
16880
17097
|
|
|
16881
|
-
const
|
|
17098
|
+
const stoppedStats = await perf?.disableFrameStats?.()
|
|
17099
|
+
const frameStats = stoppedStats || await perf?.getFrameStats?.() || {}
|
|
16882
17100
|
const profile = a11y?.profile?.() || {}
|
|
16883
17101
|
const recent = Array.isArray(frameStats.recentFrames) ? frameStats.recentFrames : []
|
|
16884
17102
|
const sorted = [...recent].sort((a, b) => a - b)
|
|
16885
|
-
perf?.disableFrameStats?.()
|
|
16886
17103
|
|
|
16887
17104
|
return {
|
|
16888
17105
|
mode: 'main-thread',
|
package/dist-lib/vite.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! sootsim v0.1.
|
|
1
|
+
/*! sootsim v0.1.87 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __create = Object.create;
|