sootsim 0.1.251 → 0.1.252
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/README.md +8 -5
- package/dist-cli/bin.js +4 -4
- package/dist-cli/chunks/{agent-OS5AFMNY.js → agent-JRN5KS75.js} +2 -2
- package/dist-cli/chunks/{agent-wrapper-JXCJFH4J.js → agent-wrapper-2ZH2WQ2L.js} +2 -2
- package/dist-cli/chunks/{app-fonts-KM5VGTPQ.js → app-fonts-LBQ7A7LL.js} +2 -2
- package/dist-cli/chunks/{assert-IWDBWZA3.js → assert-XFQCRREO.js} +2 -2
- package/dist-cli/chunks/{auth-GGWN2KHL.js → auth-DAMRQQ53.js} +2 -2
- package/dist-cli/chunks/beta-JJ4YSCOE.js +2 -0
- package/dist-cli/chunks/{camera-W5JQ5P6L.js → camera-NQWFOHXI.js} +2 -2
- package/dist-cli/chunks/chunk-25FMG2DR.js +1 -0
- package/dist-cli/chunks/{chunk-KEJB5OS5.js → chunk-4P7EXY3Q.js} +2 -2
- package/dist-cli/chunks/{chunk-37PWKV2H.js → chunk-54RVP6DQ.js} +1 -1
- package/dist-cli/chunks/{chunk-MK5FIMS5.js → chunk-56CSO42W.js} +2 -2
- package/dist-cli/chunks/{chunk-KEBLYJBJ.js → chunk-5PVVFMLA.js} +2 -2
- package/dist-cli/chunks/{chunk-H3YZXLYR.js → chunk-677KF26C.js} +1 -1
- package/dist-cli/chunks/{chunk-XJYAJ5C3.js → chunk-AJVA4XFD.js} +2 -2
- package/dist-cli/chunks/{chunk-ULYIJUKO.js → chunk-BU4QJGYM.js} +2 -2
- package/dist-cli/chunks/{chunk-HLD3JMUC.js → chunk-F2DZ3EHN.js} +2 -2
- package/dist-cli/chunks/chunk-F7NVK7U5.js +29 -0
- package/dist-cli/chunks/{chunk-CDZTB6JX.js → chunk-FCNI6ZWQ.js} +2 -2
- package/dist-cli/chunks/{chunk-TQJZ2AP4.js → chunk-GBJS3QVL.js} +2 -2
- package/dist-cli/chunks/{chunk-UTNAJIRM.js → chunk-GPECMCCD.js} +2 -2
- package/dist-cli/chunks/{chunk-PZZPL7XB.js → chunk-GRPNPAFQ.js} +1 -1
- package/dist-cli/chunks/{chunk-KD347J3Y.js → chunk-HERRSHL3.js} +2 -2
- package/dist-cli/chunks/{chunk-NQCAEFUQ.js → chunk-HNYCB3ZY.js} +1 -1
- package/dist-cli/chunks/chunk-HV773SED.js +4 -0
- package/dist-cli/chunks/{chunk-X4HNMVAY.js → chunk-J4XJHPJV.js} +2 -2
- package/dist-cli/chunks/{chunk-55GPRX3M.js → chunk-JYJ37QKN.js} +2 -2
- package/dist-cli/chunks/chunk-K5UURTEB.js +1 -0
- package/dist-cli/chunks/{chunk-Z6ZYU2VN.js → chunk-LHAUZJH5.js} +1 -1
- package/dist-cli/chunks/{chunk-DVLNBQO6.js → chunk-LL7KIGNG.js} +2 -2
- package/dist-cli/chunks/{chunk-FBAFTRKJ.js → chunk-LXRPMNYD.js} +2 -2
- package/dist-cli/chunks/{chunk-RBHEKEEX.js → chunk-LYIN47A5.js} +2 -2
- package/dist-cli/chunks/{chunk-WD4B3KV6.js → chunk-MJU6KNLI.js} +3 -3
- package/dist-cli/chunks/{chunk-YJEU2B3D.js → chunk-MMCNYDBD.js} +1 -1
- package/dist-cli/chunks/{chunk-LETXRLKY.js → chunk-NADQK2CU.js} +1 -1
- package/dist-cli/chunks/{chunk-ZL3QAP5O.js → chunk-NB6RTLLI.js} +3 -3
- package/dist-cli/chunks/{chunk-5T62AM5W.js → chunk-NNEUAQME.js} +3 -3
- package/dist-cli/chunks/{chunk-LJKL5JQ7.js → chunk-NTZYSZ3Q.js} +2 -2
- package/dist-cli/chunks/{chunk-7JTW5KO4.js → chunk-NYKHYDBN.js} +1 -1
- package/dist-cli/chunks/{chunk-63FDEQKS.js → chunk-OSPFE643.js} +1 -1
- package/dist-cli/chunks/{chunk-VO5UXLRE.js → chunk-PLK4SCBY.js} +2 -2
- package/dist-cli/chunks/{chunk-IC4GREHT.js → chunk-PVDPE5BH.js} +1 -1
- package/dist-cli/chunks/{chunk-IYPXOVE4.js → chunk-QHNYUT7D.js} +1 -1
- package/dist-cli/chunks/{chunk-GMJ3ROI3.js → chunk-S6DIPG7L.js} +2 -2
- package/dist-cli/chunks/{chunk-7HCKUJ5R.js → chunk-T2BJFGBC.js} +1 -1
- package/dist-cli/chunks/{chunk-EY5V6OC5.js → chunk-TDWFR6H5.js} +2 -2
- package/dist-cli/chunks/{chunk-CQKALFGJ.js → chunk-U5JMZPBD.js} +1 -1
- package/dist-cli/chunks/{chunk-OOLWKYWS.js → chunk-UA5FVOEO.js} +1 -1
- package/dist-cli/chunks/chunk-UVE2LY6V.js +7 -0
- package/dist-cli/chunks/{chunk-7MEV3VTL.js → chunk-WS3DDBN3.js} +1 -1
- package/dist-cli/chunks/{chunk-Z7IG2OVW.js → chunk-X2IKDV5A.js} +1 -1
- package/dist-cli/chunks/{chunk-PM3MMXYH.js → chunk-ZKN7GCX4.js} +2 -2
- package/dist-cli/chunks/cli-version-OZF5OMW4.js +2 -0
- package/dist-cli/chunks/{compat-Q7NF5FGR.js → compat-ME4QWRZ6.js} +3 -3
- package/dist-cli/chunks/{config-CHFGC57H.js → config-TMMSBXDV.js} +2 -2
- package/dist-cli/chunks/{control-GMXYQHOC.js → control-QGYYWKJP.js} +2 -2
- package/dist-cli/chunks/daemon-6NBHEVXS.js +2 -0
- package/dist-cli/chunks/{debug-JVFKA6ZJ.js → debug-LFJ46Q45.js} +3 -3
- package/dist-cli/chunks/{desktop-DT6WBVHN.js → desktop-W5GPU7JA.js} +3 -3
- package/dist-cli/chunks/{detox-OQ3DVIZB.js → detox-U3B3N3K7.js} +2 -2
- package/dist-cli/chunks/{device-XBBNWO67.js → device-I2WVQFXL.js} +2 -2
- package/dist-cli/chunks/{diagnose-JFWKSZI6.js → diagnose-6TQOA4QJ.js} +2 -2
- package/dist-cli/chunks/drivers-5J25VDIG.js +2 -0
- package/dist-cli/chunks/{film-3BI63O2P.js → film-P5E64XQH.js} +3 -3
- package/dist-cli/chunks/flow-LD6MOZQC.js +2 -0
- package/dist-cli/chunks/help-VCWJZBQU.js +2 -0
- package/dist-cli/chunks/{hidden-runtime-alias-JGY2SN3U.js → hidden-runtime-alias-ICP5W4W5.js} +2 -2
- package/dist-cli/chunks/home-paths-MCD3DISJ.js +2 -0
- package/dist-cli/chunks/inspect-VF575AD3.js +2 -0
- package/dist-cli/chunks/install-desktop-Q4Y6FTSA.js +2 -0
- package/dist-cli/chunks/{login-QT6OUDLD.js → login-A5LRYTNO.js} +4 -4
- package/dist-cli/chunks/{logout-QM7I6EYI.js → logout-M3HFZGFU.js} +2 -2
- package/dist-cli/chunks/{maestro-YU5YDZ44.js → maestro-HNREOYXF.js} +3 -3
- package/dist-cli/chunks/{maestro-generate-YQ5GE6LW.js → maestro-generate-BEEDUOOJ.js} +3 -3
- package/dist-cli/chunks/{mode-MHOIKOWG.js → mode-IBFHS3G2.js} +2 -2
- package/dist-cli/chunks/optional-demo-registry-6XYQJXI5.js +2 -0
- package/dist-cli/chunks/{perf-UDWM5CLN.js → perf-62BD5VIU.js} +2 -2
- package/dist-cli/chunks/{record-EEYIMPNW.js → record-2ILPO4XB.js} +3 -3
- package/dist-cli/chunks/runtime-WCDQFR7G.js +2 -0
- package/dist-cli/chunks/{screenshot-command-MDOO4W2M.js → screenshot-command-YZR5KVV2.js} +3 -3
- package/dist-cli/chunks/{screenshots-capture-MYFBKRYI.js → screenshots-capture-QHQ43OBD.js} +2 -2
- package/dist-cli/chunks/{serve-TFGKULND.js → serve-GQ4PUD5P.js} +15 -15
- package/dist-cli/chunks/{setup-WOB5DERX.js → setup-C74I2RO3.js} +3 -3
- package/dist-cli/chunks/{skills-MFFPTR5A.js → skills-I7EVR3MU.js} +2 -2
- package/dist-cli/chunks/{storage-6IZXGU2O.js → storage-CH6BAYB4.js} +2 -2
- package/dist-cli/chunks/store-PTQ4QMFA.js +2 -0
- package/dist-cli/chunks/telemetry-AJDAGOFX.js +2 -0
- package/dist-cli/chunks/{timeline-BRXK7M5J.js → timeline-FUS7F5LI.js} +2 -2
- package/dist-cli/chunks/{upgrade-K6A4PITT.js → upgrade-DHMZFD5R.js} +4 -4
- package/dist-cli/chunks/upload-XJXPQMKX.js +2 -0
- package/dist-cli/chunks/version-M2GSAVKM.js +4 -0
- package/dist-cli/chunks/{web-P3ANEMOL.js → web-NV7UM2T7.js} +2 -2
- package/dist-cli/chunks/{what-happened-OFMSOZZB.js → what-happened-VRDDXQWR.js} +2 -2
- package/dist-lib/agent-daemon-client.cjs +1 -1
- package/dist-lib/agent-events.cjs +1 -1
- package/dist-lib/agent-identity.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 +1 -1
- 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 -33
- package/dist-lib/host/bridge-host.cjs +396 -329
- package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
- package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
- package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
- package/dist-lib/host/websocket-proxy.cjs +1 -1
- package/dist-lib/index.cjs +1 -1
- package/dist-lib/jump-to-source-babel.cjs +1 -1
- package/dist-lib/menu.cjs +1 -1
- package/dist-lib/menu.mjs +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/dev-server-scanner.cjs +1 -1
- package/dist-lib/sdk.cjs +1 -1
- package/dist-lib/sdk.mjs +1 -1
- package/dist-lib/skills.cjs +515 -435
- package/dist-lib/vite.cjs +1 -1
- package/package.json +2 -1
- package/src/home-paths.ts +5 -40
- package/src/host/bridge-host.ts +4 -5
- package/src/runtime-delivery.ts +32 -377
- package/dist-cli/chunks/beta-LVHWRJCU.js +0 -2
- package/dist-cli/chunks/chunk-2273TU3I.js +0 -1
- package/dist-cli/chunks/chunk-6ACR2P3U.js +0 -1
- package/dist-cli/chunks/chunk-HMOZ6UBM.js +0 -29
- package/dist-cli/chunks/chunk-JFXVQVXW.js +0 -4
- package/dist-cli/chunks/chunk-OLCSJXAQ.js +0 -7
- package/dist-cli/chunks/cli-version-Z2MVFJOA.js +0 -2
- package/dist-cli/chunks/daemon-NM537LET.js +0 -2
- package/dist-cli/chunks/drivers-NOJ7CRI4.js +0 -2
- package/dist-cli/chunks/flow-7ETXJJ6C.js +0 -2
- package/dist-cli/chunks/help-FE5IIJIM.js +0 -2
- package/dist-cli/chunks/home-paths-BLOAGTA2.js +0 -2
- package/dist-cli/chunks/inspect-UA376AF4.js +0 -2
- package/dist-cli/chunks/install-desktop-KBXAATJW.js +0 -2
- package/dist-cli/chunks/optional-demo-registry-RF4SZYRO.js +0 -2
- package/dist-cli/chunks/runtime-UJOIMMBS.js +0 -2
- package/dist-cli/chunks/store-JG2JCUFN.js +0 -2
- package/dist-cli/chunks/telemetry-HI4GNTOS.js +0 -2
- package/dist-cli/chunks/upload-ZNSE6XIN.js +0 -2
- package/dist-cli/chunks/version-4HZWAXW3.js +0 -4
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! sootsim v0.1.
|
|
1
|
+
/*! sootsim v0.1.252 | (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;
|
|
@@ -70,10 +70,10 @@ __export(bridge_host_exports, {
|
|
|
70
70
|
injectSharedConfigIntoHtml: () => injectSharedConfigIntoHtml
|
|
71
71
|
});
|
|
72
72
|
module.exports = __toCommonJS(bridge_host_exports);
|
|
73
|
-
var
|
|
74
|
-
var
|
|
73
|
+
var import_child_process3 = require("child_process");
|
|
74
|
+
var import_fs3 = __toESM(require("fs"), 1);
|
|
75
75
|
var import_http3 = require("http");
|
|
76
|
-
var
|
|
76
|
+
var import_path3 = __toESM(require("path"), 1);
|
|
77
77
|
var import_ws2 = require("ws");
|
|
78
78
|
|
|
79
79
|
// scripts/dev-server-scanner.ts
|
|
@@ -156,10 +156,10 @@ function tcpPing(port, timeout = TCP_GATE_MS) {
|
|
|
156
156
|
sock.connect(port, "localhost");
|
|
157
157
|
});
|
|
158
158
|
}
|
|
159
|
-
function httpGet(port,
|
|
159
|
+
function httpGet(port, path10, method = "GET", timeout = TIMEOUT_MS, headers = {}) {
|
|
160
160
|
return new Promise((resolve) => {
|
|
161
161
|
const req = import_http.default.request(
|
|
162
|
-
{ hostname: "localhost", port, path:
|
|
162
|
+
{ hostname: "localhost", port, path: path10, method, timeout, headers },
|
|
163
163
|
(res) => {
|
|
164
164
|
let body = "";
|
|
165
165
|
res.on("data", (c) => body += c.toString());
|
|
@@ -706,34 +706,6 @@ function writeActiveRuntime(version) {
|
|
|
706
706
|
import_node_fs2.default.writeFileSync(activeRuntimeFile(), `${version}
|
|
707
707
|
`, "utf8");
|
|
708
708
|
}
|
|
709
|
-
function listInstalledRuntimes() {
|
|
710
|
-
try {
|
|
711
|
-
return import_node_fs2.default.readdirSync(runtimesDir(), { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name).sort(compareSemver);
|
|
712
|
-
} catch {
|
|
713
|
-
return [];
|
|
714
|
-
}
|
|
715
|
-
}
|
|
716
|
-
function compareSemver(a, b) {
|
|
717
|
-
const parse = (v) => {
|
|
718
|
-
const hyphen = v.indexOf("-");
|
|
719
|
-
const core = hyphen >= 0 ? v.slice(0, hyphen) : v;
|
|
720
|
-
const pre = hyphen >= 0 ? v.slice(hyphen + 1) : "";
|
|
721
|
-
const parts = core.split(".").map((n) => Number.parseInt(n, 10));
|
|
722
|
-
if (parts.some((n) => !Number.isFinite(n))) return [[Number.POSITIVE_INFINITY], v];
|
|
723
|
-
return [parts, pre];
|
|
724
|
-
};
|
|
725
|
-
const [an, ap] = parse(a);
|
|
726
|
-
const [bn, bp] = parse(b);
|
|
727
|
-
for (let i = 0; i < Math.max(an.length, bn.length); i++) {
|
|
728
|
-
const av = an[i] ?? 0;
|
|
729
|
-
const bv = bn[i] ?? 0;
|
|
730
|
-
if (av !== bv) return av - bv;
|
|
731
|
-
}
|
|
732
|
-
if (ap === bp) return 0;
|
|
733
|
-
if (!ap) return 1;
|
|
734
|
-
if (!bp) return -1;
|
|
735
|
-
return ap < bp ? -1 : 1;
|
|
736
|
-
}
|
|
737
709
|
function activeRuntimeDir() {
|
|
738
710
|
const version = readActiveRuntime();
|
|
739
711
|
if (!version) return null;
|
|
@@ -839,149 +811,239 @@ function resolveDevCheckoutRuntimeRoot() {
|
|
|
839
811
|
return null;
|
|
840
812
|
}
|
|
841
813
|
|
|
842
|
-
//
|
|
843
|
-
var
|
|
844
|
-
var
|
|
845
|
-
var
|
|
846
|
-
var
|
|
847
|
-
var
|
|
848
|
-
var import_promises = require("stream/promises");
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
var
|
|
852
|
-
var
|
|
853
|
-
function
|
|
814
|
+
// ../contrast-runtime-delivery/src/index.ts
|
|
815
|
+
var import_node_child_process = require("node:child_process");
|
|
816
|
+
var import_node_crypto = __toESM(require("node:crypto"), 1);
|
|
817
|
+
var import_node_fs4 = __toESM(require("node:fs"), 1);
|
|
818
|
+
var import_node_path3 = __toESM(require("node:path"), 1);
|
|
819
|
+
var import_node_stream = require("node:stream");
|
|
820
|
+
var import_promises = require("node:stream/promises");
|
|
821
|
+
|
|
822
|
+
// ../contrast-runtime-delivery/src/product.ts
|
|
823
|
+
var import_node_fs3 = __toESM(require("node:fs"), 1);
|
|
824
|
+
var import_node_path2 = __toESM(require("node:path"), 1);
|
|
825
|
+
function listInstalledRuntimes(product) {
|
|
854
826
|
try {
|
|
855
|
-
|
|
856
|
-
return parsed && typeof parsed === "object" ? parsed : {};
|
|
827
|
+
return import_node_fs3.default.readdirSync(product.runtimesDir(), { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name).sort(compareSemver);
|
|
857
828
|
} catch {
|
|
858
|
-
return
|
|
829
|
+
return [];
|
|
859
830
|
}
|
|
860
831
|
}
|
|
861
|
-
function
|
|
862
|
-
|
|
863
|
-
const value = input || process.env[RUNTIME_CDN_ORIGIN_ENV] || config.cdnOrigin || DEFAULT_RUNTIME_CDN_ORIGIN;
|
|
864
|
-
return value.replace(/\/+$/, "");
|
|
865
|
-
}
|
|
866
|
-
function resolveRuntimeChannel(input) {
|
|
867
|
-
const config = readConfig();
|
|
868
|
-
return input || process.env[RUNTIME_CHANNEL_ENV] || config.runtimeChannel || "stable";
|
|
832
|
+
function runtimeTarballCacheName(product, version) {
|
|
833
|
+
return import_node_path2.default.posix.basename(product.tarballPath(version));
|
|
869
834
|
}
|
|
870
|
-
function
|
|
871
|
-
const
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
const url = runtimeManifestUrl(cdnOrigin);
|
|
886
|
-
const res = await fetch(url, { headers: { Accept: "application/json" } });
|
|
887
|
-
if (!res.ok) {
|
|
888
|
-
throw new Error(`manifest fetch failed: ${res.status} ${res.statusText} (${url})`);
|
|
835
|
+
function compareSemver(a, b) {
|
|
836
|
+
const parse = (v) => {
|
|
837
|
+
const hyphen = v.indexOf("-");
|
|
838
|
+
const core = hyphen >= 0 ? v.slice(0, hyphen) : v;
|
|
839
|
+
const pre = hyphen >= 0 ? v.slice(hyphen + 1) : "";
|
|
840
|
+
const parts = core.split(".").map((n) => Number.parseInt(n, 10));
|
|
841
|
+
if (parts.some((n) => !Number.isFinite(n))) return [[Number.POSITIVE_INFINITY], v];
|
|
842
|
+
return [parts, pre];
|
|
843
|
+
};
|
|
844
|
+
const [an, ap] = parse(a);
|
|
845
|
+
const [bn, bp] = parse(b);
|
|
846
|
+
for (let i = 0; i < Math.max(an.length, bn.length); i++) {
|
|
847
|
+
const av = an[i] ?? 0;
|
|
848
|
+
const bv = bn[i] ?? 0;
|
|
849
|
+
if (av !== bv) return av - bv;
|
|
889
850
|
}
|
|
890
|
-
|
|
851
|
+
if (ap === bp) return 0;
|
|
852
|
+
if (!ap) return 1;
|
|
853
|
+
if (!bp) return -1;
|
|
854
|
+
return ap < bp ? -1 : 1;
|
|
891
855
|
}
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
856
|
+
|
|
857
|
+
// ../contrast-runtime-delivery/src/index.ts
|
|
858
|
+
function createRuntimeDelivery(product) {
|
|
859
|
+
function readConfig() {
|
|
860
|
+
try {
|
|
861
|
+
const parsed = JSON.parse(
|
|
862
|
+
import_node_fs4.default.readFileSync(product.configFile(), "utf8")
|
|
863
|
+
);
|
|
864
|
+
return parsed && typeof parsed === "object" ? parsed : {};
|
|
865
|
+
} catch {
|
|
866
|
+
return {};
|
|
867
|
+
}
|
|
868
|
+
}
|
|
869
|
+
function resolveCdnOrigin(input) {
|
|
870
|
+
const config = readConfig();
|
|
871
|
+
const value = input || process.env[product.env.cdnOrigin] || config.cdnOrigin || product.defaultCdnOrigin;
|
|
872
|
+
return value.replace(/\/+$/, "");
|
|
873
|
+
}
|
|
874
|
+
function resolveChannel(input) {
|
|
875
|
+
const config = readConfig();
|
|
876
|
+
return input || process.env[product.env.channel] || config.runtimeChannel || "stable";
|
|
877
|
+
}
|
|
878
|
+
function resolvePin() {
|
|
879
|
+
const env = process.env[product.env.pin];
|
|
880
|
+
if (env && env.trim()) return env.trim();
|
|
881
|
+
const config = readConfig();
|
|
882
|
+
return typeof config.runtimeVersion === "string" && config.runtimeVersion.trim() ? config.runtimeVersion.trim() : null;
|
|
883
|
+
}
|
|
884
|
+
function manifestUrl(cdnOrigin) {
|
|
885
|
+
const url = new URL(`${resolveCdnOrigin(cdnOrigin)}${product.manifestPath}`);
|
|
886
|
+
url.searchParams.set("t", String(Date.now()));
|
|
887
|
+
return url.toString();
|
|
888
|
+
}
|
|
889
|
+
function tarballUrl(version, cdnOrigin) {
|
|
890
|
+
return `${resolveCdnOrigin(cdnOrigin)}${product.tarballPath(version)}`;
|
|
891
|
+
}
|
|
892
|
+
async function fetchManifest(cdnOrigin) {
|
|
893
|
+
const url = manifestUrl(cdnOrigin);
|
|
894
|
+
const res = await fetch(url, { headers: { Accept: "application/json" } });
|
|
895
|
+
if (!res.ok) {
|
|
896
|
+
throw new Error(`manifest fetch failed: ${res.status} ${res.statusText} (${url})`);
|
|
897
|
+
}
|
|
898
|
+
return await res.json();
|
|
899
|
+
}
|
|
900
|
+
function resolveVersion(manifest, opts = {}) {
|
|
901
|
+
const channel = resolveChannel(opts.channel);
|
|
902
|
+
const version = opts.version || resolvePin() || manifest.channels[channel]?.latest;
|
|
903
|
+
if (!version) {
|
|
904
|
+
throw new Error(
|
|
905
|
+
`no version specified and channel '${channel}' has no latest entry in the manifest`
|
|
906
|
+
);
|
|
907
|
+
}
|
|
908
|
+
const entry = manifest.versions[version];
|
|
909
|
+
if (!entry) {
|
|
910
|
+
throw new Error(
|
|
911
|
+
`version ${version} not found in manifest; available: ${Object.keys(manifest.versions).slice(-10).join(", ") || "(none)"}`
|
|
912
|
+
);
|
|
913
|
+
}
|
|
914
|
+
return { version, channel, entry };
|
|
915
|
+
}
|
|
916
|
+
async function install(opts = {}) {
|
|
917
|
+
product.ensureHome();
|
|
918
|
+
const cdnOrigin = resolveCdnOrigin(opts.cdnOrigin);
|
|
919
|
+
const manifest = await fetchManifest(cdnOrigin);
|
|
920
|
+
const { version, channel, entry } = resolveVersion(manifest, opts);
|
|
921
|
+
const destDir = product.runtimeDir(version);
|
|
922
|
+
const setActive = opts.setActive !== false;
|
|
923
|
+
if (!opts.force && import_node_fs4.default.existsSync(import_node_path3.default.join(destDir, "index.html"))) {
|
|
924
|
+
if (setActive) product.writeActiveRuntime(version);
|
|
925
|
+
return {
|
|
926
|
+
version,
|
|
927
|
+
channel,
|
|
928
|
+
cdnOrigin,
|
|
929
|
+
runtimeDir: destDir,
|
|
930
|
+
installed: false,
|
|
931
|
+
activated: setActive,
|
|
932
|
+
manifest
|
|
933
|
+
};
|
|
934
|
+
}
|
|
935
|
+
const tarUrl = entry.tarball || tarballUrl(version, cdnOrigin);
|
|
936
|
+
const tarCachePath = import_node_path3.default.join(
|
|
937
|
+
product.cacheDir(),
|
|
938
|
+
runtimeTarballCacheName(product, version)
|
|
898
939
|
);
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
940
|
+
process.stderr.write(`${product.id}: downloading runtime ${version}\u2026
|
|
941
|
+
`);
|
|
942
|
+
await downloadToFile(tarUrl, tarCachePath);
|
|
943
|
+
process.stderr.write(`${product.id}: extracting runtime ${version}\u2026
|
|
944
|
+
`);
|
|
945
|
+
const actualSha = await sha256File(tarCachePath);
|
|
946
|
+
if (actualSha !== entry.sha256) {
|
|
947
|
+
import_node_fs4.default.rmSync(tarCachePath, { force: true });
|
|
948
|
+
throw new Error(
|
|
949
|
+
`sha256 mismatch for runtime ${version}: expected ${entry.sha256}, actual ${actualSha}`
|
|
950
|
+
);
|
|
951
|
+
}
|
|
952
|
+
const tmpDir = import_node_path3.default.join(
|
|
953
|
+
import_node_path3.default.dirname(destDir),
|
|
954
|
+
`.installing-${version}-${process.pid}`
|
|
904
955
|
);
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
956
|
+
import_node_fs4.default.rmSync(tmpDir, { recursive: true, force: true });
|
|
957
|
+
import_node_fs4.default.mkdirSync(tmpDir, { recursive: true });
|
|
958
|
+
try {
|
|
959
|
+
await extractTarball(tarCachePath, tmpDir);
|
|
960
|
+
if (!import_node_fs4.default.existsSync(import_node_path3.default.join(tmpDir, "index.html"))) {
|
|
961
|
+
throw new Error(`extracted tarball for runtime ${version} is missing index.html`);
|
|
962
|
+
}
|
|
963
|
+
import_node_fs4.default.rmSync(destDir, { recursive: true, force: true });
|
|
964
|
+
import_node_fs4.default.renameSync(tmpDir, destDir);
|
|
965
|
+
} catch (err) {
|
|
966
|
+
import_node_fs4.default.rmSync(tmpDir, { recursive: true, force: true });
|
|
967
|
+
throw err;
|
|
968
|
+
}
|
|
969
|
+
if (setActive) product.writeActiveRuntime(version);
|
|
917
970
|
return {
|
|
918
971
|
version,
|
|
919
972
|
channel,
|
|
920
973
|
cdnOrigin,
|
|
921
974
|
runtimeDir: destDir,
|
|
922
|
-
installed:
|
|
975
|
+
installed: true,
|
|
923
976
|
activated: setActive,
|
|
924
977
|
manifest
|
|
925
978
|
};
|
|
926
979
|
}
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
980
|
+
async function updateToLatest(opts = {}) {
|
|
981
|
+
product.ensureHome();
|
|
982
|
+
const cdnOrigin = resolveCdnOrigin(opts.cdnOrigin);
|
|
983
|
+
const channel = resolveChannel(opts.channel);
|
|
984
|
+
const pin = resolvePin();
|
|
985
|
+
if (pin) {
|
|
986
|
+
const activeVersion2 = product.readActiveRuntime();
|
|
987
|
+
const pinInstalled = import_node_fs4.default.existsSync(import_node_path3.default.join(product.runtimeDir(pin), "index.html"));
|
|
988
|
+
if (activeVersion2 === pin && pinInstalled) {
|
|
989
|
+
return {
|
|
990
|
+
checked: true,
|
|
991
|
+
updated: false,
|
|
992
|
+
reason: `runtime is pinned to ${pin}`,
|
|
993
|
+
activeVersion: activeVersion2,
|
|
994
|
+
latestVersion: pin
|
|
995
|
+
};
|
|
996
|
+
}
|
|
997
|
+
const installed2 = await install({
|
|
998
|
+
version: pin,
|
|
999
|
+
channel,
|
|
1000
|
+
cdnOrigin,
|
|
1001
|
+
setActive: false
|
|
1002
|
+
});
|
|
1003
|
+
return {
|
|
1004
|
+
checked: true,
|
|
1005
|
+
updated: true,
|
|
1006
|
+
reason: `runtime is pinned to ${pin}`,
|
|
1007
|
+
activeVersion: pin,
|
|
1008
|
+
latestVersion: pin,
|
|
1009
|
+
install: installed2
|
|
1010
|
+
};
|
|
948
1011
|
}
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
import_fs2.default.rmSync(tmpDir, { recursive: true, force: true });
|
|
953
|
-
throw err;
|
|
954
|
-
}
|
|
955
|
-
if (setActive) writeActiveRuntime(version);
|
|
956
|
-
return {
|
|
957
|
-
version,
|
|
958
|
-
channel,
|
|
959
|
-
cdnOrigin,
|
|
960
|
-
runtimeDir: destDir,
|
|
961
|
-
installed: true,
|
|
962
|
-
activated: setActive,
|
|
963
|
-
manifest
|
|
964
|
-
};
|
|
965
|
-
}
|
|
966
|
-
async function updateRuntimeToLatest(opts = {}) {
|
|
967
|
-
ensureSootsimHome();
|
|
968
|
-
const cdnOrigin = resolveRuntimeCdnOrigin(opts.cdnOrigin);
|
|
969
|
-
const channel = resolveRuntimeChannel(opts.channel);
|
|
970
|
-
const pin = resolveRuntimePin();
|
|
971
|
-
if (pin) {
|
|
972
|
-
const activeVersion2 = readActiveRuntime();
|
|
973
|
-
const pinInstalled = import_fs2.default.existsSync(import_path2.default.join(runtimeDir(pin), "index.html"));
|
|
974
|
-
if (activeVersion2 === pin && pinInstalled) {
|
|
1012
|
+
const manifest = await fetchManifest(cdnOrigin);
|
|
1013
|
+
const latestVersion = manifest.channels[channel]?.latest;
|
|
1014
|
+
if (!latestVersion) {
|
|
975
1015
|
return {
|
|
976
1016
|
checked: true,
|
|
977
1017
|
updated: false,
|
|
978
|
-
reason: `
|
|
979
|
-
activeVersion:
|
|
980
|
-
|
|
1018
|
+
reason: `channel '${channel}' has no latest runtime`,
|
|
1019
|
+
activeVersion: product.readActiveRuntime()
|
|
1020
|
+
};
|
|
1021
|
+
}
|
|
1022
|
+
const entry = manifest.versions[latestVersion];
|
|
1023
|
+
if (!entry) {
|
|
1024
|
+
return {
|
|
1025
|
+
checked: true,
|
|
1026
|
+
updated: false,
|
|
1027
|
+
reason: `manifest is missing version ${latestVersion}`,
|
|
1028
|
+
activeVersion: product.readActiveRuntime(),
|
|
1029
|
+
latestVersion
|
|
1030
|
+
};
|
|
1031
|
+
}
|
|
1032
|
+
const activeVersion = product.readActiveRuntime();
|
|
1033
|
+
const activeDir = activeVersion ? product.runtimeDir(activeVersion) : null;
|
|
1034
|
+
const activeInstalled = activeDir ? import_node_fs4.default.existsSync(import_node_path3.default.join(activeDir, "index.html")) : false;
|
|
1035
|
+
const shouldInstall = !activeVersion || !activeInstalled || compareSemver(latestVersion, activeVersion) > 0;
|
|
1036
|
+
if (!shouldInstall) {
|
|
1037
|
+
return {
|
|
1038
|
+
checked: true,
|
|
1039
|
+
updated: false,
|
|
1040
|
+
reason: "active runtime is current",
|
|
1041
|
+
activeVersion,
|
|
1042
|
+
latestVersion
|
|
981
1043
|
};
|
|
982
1044
|
}
|
|
983
|
-
const
|
|
984
|
-
version:
|
|
1045
|
+
const installed = await install({
|
|
1046
|
+
version: latestVersion,
|
|
985
1047
|
channel,
|
|
986
1048
|
cdnOrigin,
|
|
987
1049
|
setActive: false
|
|
@@ -989,57 +1051,40 @@ async function updateRuntimeToLatest(opts = {}) {
|
|
|
989
1051
|
return {
|
|
990
1052
|
checked: true,
|
|
991
1053
|
updated: true,
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
install: install2
|
|
1054
|
+
activeVersion: latestVersion,
|
|
1055
|
+
latestVersion,
|
|
1056
|
+
install: installed
|
|
996
1057
|
};
|
|
997
1058
|
}
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
reason: `manifest is missing version ${latestVersion}`,
|
|
1014
|
-
activeVersion: readActiveRuntime(),
|
|
1015
|
-
latestVersion
|
|
1016
|
-
};
|
|
1017
|
-
}
|
|
1018
|
-
const activeVersion = readActiveRuntime();
|
|
1019
|
-
const activeDir = activeVersion ? runtimeDir(activeVersion) : null;
|
|
1020
|
-
const activeInstalled = activeDir ? import_fs2.default.existsSync(import_path2.default.join(activeDir, "index.html")) : false;
|
|
1021
|
-
const shouldInstall = !activeVersion || !activeInstalled || compareSemver(latestVersion, activeVersion) > 0;
|
|
1022
|
-
if (!shouldInstall) {
|
|
1023
|
-
return {
|
|
1024
|
-
checked: true,
|
|
1025
|
-
updated: false,
|
|
1026
|
-
reason: "active runtime is current",
|
|
1027
|
-
activeVersion,
|
|
1028
|
-
latestVersion
|
|
1029
|
-
};
|
|
1059
|
+
async function checkUpToDate(opts = {}) {
|
|
1060
|
+
const active = product.readActiveRuntime();
|
|
1061
|
+
const pinned = resolvePin();
|
|
1062
|
+
if (pinned) {
|
|
1063
|
+
return { active, latest: pinned, pinned, outdated: active !== pinned };
|
|
1064
|
+
}
|
|
1065
|
+
try {
|
|
1066
|
+
const manifest = await fetchManifest(resolveCdnOrigin(opts.cdnOrigin));
|
|
1067
|
+
const channel = resolveChannel(opts.channel);
|
|
1068
|
+
const latest = manifest.channels[channel]?.latest ?? null;
|
|
1069
|
+
const outdated = !!(latest && (!active || compareSemver(latest, active) > 0));
|
|
1070
|
+
return { active, latest, pinned: null, outdated };
|
|
1071
|
+
} catch {
|
|
1072
|
+
return { active, latest: null, pinned: null, outdated: false };
|
|
1073
|
+
}
|
|
1030
1074
|
}
|
|
1031
|
-
const install = await installRuntime({
|
|
1032
|
-
version: latestVersion,
|
|
1033
|
-
channel,
|
|
1034
|
-
cdnOrigin,
|
|
1035
|
-
setActive: false
|
|
1036
|
-
});
|
|
1037
1075
|
return {
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1076
|
+
product,
|
|
1077
|
+
resolveCdnOrigin,
|
|
1078
|
+
resolveChannel,
|
|
1079
|
+
resolvePin,
|
|
1080
|
+
manifestUrl,
|
|
1081
|
+
tarballUrl,
|
|
1082
|
+
fetchManifest,
|
|
1083
|
+
resolveVersion,
|
|
1084
|
+
install,
|
|
1085
|
+
updateToLatest,
|
|
1086
|
+
checkUpToDate,
|
|
1087
|
+
listInstalled: () => listInstalledRuntimes(product)
|
|
1043
1088
|
};
|
|
1044
1089
|
}
|
|
1045
1090
|
async function downloadToFile(url, destPath) {
|
|
@@ -1047,17 +1092,17 @@ async function downloadToFile(url, destPath) {
|
|
|
1047
1092
|
if (!res.ok || !res.body) {
|
|
1048
1093
|
throw new Error(`download failed: ${res.status} ${res.statusText} (${url})`);
|
|
1049
1094
|
}
|
|
1050
|
-
|
|
1095
|
+
import_node_fs4.default.mkdirSync(import_node_path3.default.dirname(destPath), { recursive: true });
|
|
1051
1096
|
const tmp = `${destPath}.partial`;
|
|
1052
1097
|
try {
|
|
1053
1098
|
await (0, import_promises.pipeline)(
|
|
1054
|
-
|
|
1055
|
-
|
|
1099
|
+
import_node_stream.Readable.fromWeb(res.body),
|
|
1100
|
+
import_node_fs4.default.createWriteStream(tmp)
|
|
1056
1101
|
);
|
|
1057
|
-
|
|
1102
|
+
import_node_fs4.default.renameSync(tmp, destPath);
|
|
1058
1103
|
} catch (err) {
|
|
1059
1104
|
try {
|
|
1060
|
-
|
|
1105
|
+
import_node_fs4.default.unlinkSync(tmp);
|
|
1061
1106
|
} catch {
|
|
1062
1107
|
}
|
|
1063
1108
|
throw err;
|
|
@@ -1065,8 +1110,8 @@ async function downloadToFile(url, destPath) {
|
|
|
1065
1110
|
}
|
|
1066
1111
|
function sha256File(filePath) {
|
|
1067
1112
|
return new Promise((resolve, reject) => {
|
|
1068
|
-
const hash =
|
|
1069
|
-
const stream =
|
|
1113
|
+
const hash = import_node_crypto.default.createHash("sha256");
|
|
1114
|
+
const stream = import_node_fs4.default.createReadStream(filePath);
|
|
1070
1115
|
stream.on("data", (chunk) => hash.update(chunk));
|
|
1071
1116
|
stream.on("error", reject);
|
|
1072
1117
|
stream.on("end", () => resolve(hash.digest("hex")));
|
|
@@ -1074,7 +1119,7 @@ function sha256File(filePath) {
|
|
|
1074
1119
|
}
|
|
1075
1120
|
function extractTarball(tarPath, destDir) {
|
|
1076
1121
|
return new Promise((resolve, reject) => {
|
|
1077
|
-
const child = (0,
|
|
1122
|
+
const child = (0, import_node_child_process.spawn)("tar", ["-xzf", tarPath, "-C", destDir], {
|
|
1078
1123
|
stdio: ["ignore", "inherit", "inherit"]
|
|
1079
1124
|
});
|
|
1080
1125
|
child.on("error", reject);
|
|
@@ -1085,15 +1130,37 @@ function extractTarball(tarPath, destDir) {
|
|
|
1085
1130
|
});
|
|
1086
1131
|
}
|
|
1087
1132
|
|
|
1133
|
+
// src/runtime-delivery.ts
|
|
1134
|
+
var DEFAULT_RUNTIME_CDN_ORIGIN = "https://contrast.dev";
|
|
1135
|
+
var SOOTSIM_RUNTIME_PRODUCT = {
|
|
1136
|
+
id: "sootsim",
|
|
1137
|
+
defaultCdnOrigin: DEFAULT_RUNTIME_CDN_ORIGIN,
|
|
1138
|
+
manifestPath: "/runtimes/manifest.json",
|
|
1139
|
+
tarballPath: (version) => `/runtimes/sootsim-runtime-${version}.tar.gz`,
|
|
1140
|
+
env: {
|
|
1141
|
+
cdnOrigin: "SOOTSIM_CDN_ORIGIN",
|
|
1142
|
+
channel: "SOOTSIM_RUNTIME_CHANNEL",
|
|
1143
|
+
pin: "SOOTSIM_RUNTIME_VERSION"
|
|
1144
|
+
},
|
|
1145
|
+
ensureHome: ensureSootsimHome,
|
|
1146
|
+
configFile: configFilePath,
|
|
1147
|
+
runtimesDir,
|
|
1148
|
+
runtimeDir,
|
|
1149
|
+
cacheDir,
|
|
1150
|
+
readActiveRuntime,
|
|
1151
|
+
writeActiveRuntime
|
|
1152
|
+
};
|
|
1153
|
+
var sootsimRuntime = createRuntimeDelivery(SOOTSIM_RUNTIME_PRODUCT);
|
|
1154
|
+
|
|
1088
1155
|
// src/host/agent-host.ts
|
|
1089
|
-
var
|
|
1090
|
-
var
|
|
1156
|
+
var import_node_fs8 = __toESM(require("node:fs"), 1);
|
|
1157
|
+
var import_node_path7 = __toESM(require("node:path"), 1);
|
|
1091
1158
|
|
|
1092
1159
|
// src/agent-sessions.ts
|
|
1093
|
-
var
|
|
1094
|
-
var
|
|
1095
|
-
var
|
|
1096
|
-
var
|
|
1160
|
+
var import_node_child_process2 = require("node:child_process");
|
|
1161
|
+
var import_node_crypto3 = require("node:crypto");
|
|
1162
|
+
var import_node_fs6 = __toESM(require("node:fs"), 1);
|
|
1163
|
+
var import_node_path5 = __toESM(require("node:path"), 1);
|
|
1097
1164
|
var import_node_readline = __toESM(require("node:readline"), 1);
|
|
1098
1165
|
|
|
1099
1166
|
// src/agent-events.ts
|
|
@@ -1136,9 +1203,9 @@ function encodeAgentPromptEnvelope(input) {
|
|
|
1136
1203
|
}
|
|
1137
1204
|
|
|
1138
1205
|
// src/attached-projects.ts
|
|
1139
|
-
var
|
|
1140
|
-
var
|
|
1141
|
-
var
|
|
1206
|
+
var import_node_crypto2 = require("node:crypto");
|
|
1207
|
+
var import_node_fs5 = __toESM(require("node:fs"), 1);
|
|
1208
|
+
var import_node_path4 = __toESM(require("node:path"), 1);
|
|
1142
1209
|
var overrideDir = null;
|
|
1143
1210
|
function userDataDir() {
|
|
1144
1211
|
if (overrideDir) return overrideDir;
|
|
@@ -1150,7 +1217,7 @@ function getUserDataDir() {
|
|
|
1150
1217
|
return userDataDir();
|
|
1151
1218
|
}
|
|
1152
1219
|
function storeFile() {
|
|
1153
|
-
return
|
|
1220
|
+
return import_node_path4.default.join(userDataDir(), "attached-projects.json");
|
|
1154
1221
|
}
|
|
1155
1222
|
function cloneEmpty() {
|
|
1156
1223
|
return {
|
|
@@ -1164,7 +1231,7 @@ function loadStore() {
|
|
|
1164
1231
|
const file = storeFile();
|
|
1165
1232
|
let raw;
|
|
1166
1233
|
try {
|
|
1167
|
-
raw =
|
|
1234
|
+
raw = import_node_fs5.default.readFileSync(file, "utf8");
|
|
1168
1235
|
} catch (err) {
|
|
1169
1236
|
if (err.code === "ENOENT") return cloneEmpty();
|
|
1170
1237
|
throw err;
|
|
@@ -1181,7 +1248,7 @@ function loadStore() {
|
|
|
1181
1248
|
} catch (err) {
|
|
1182
1249
|
const quarantine = `${file}.corrupt-${Date.now()}`;
|
|
1183
1250
|
try {
|
|
1184
|
-
|
|
1251
|
+
import_node_fs5.default.renameSync(file, quarantine);
|
|
1185
1252
|
console.warn(
|
|
1186
1253
|
`[sootsim] attached-projects.json was unparseable; quarantined to ${quarantine}. original error: ${err.message}`
|
|
1187
1254
|
);
|
|
@@ -1192,16 +1259,16 @@ function loadStore() {
|
|
|
1192
1259
|
}
|
|
1193
1260
|
function writeStore(store) {
|
|
1194
1261
|
const file = storeFile();
|
|
1195
|
-
|
|
1262
|
+
import_node_fs5.default.mkdirSync(import_node_path4.default.dirname(file), { recursive: true });
|
|
1196
1263
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
|
|
1197
|
-
const fd =
|
|
1264
|
+
const fd = import_node_fs5.default.openSync(tmp, "w", 384);
|
|
1198
1265
|
try {
|
|
1199
|
-
|
|
1200
|
-
|
|
1266
|
+
import_node_fs5.default.writeFileSync(fd, JSON.stringify(store, null, 2));
|
|
1267
|
+
import_node_fs5.default.fsyncSync(fd);
|
|
1201
1268
|
} finally {
|
|
1202
|
-
|
|
1269
|
+
import_node_fs5.default.closeSync(fd);
|
|
1203
1270
|
}
|
|
1204
|
-
|
|
1271
|
+
import_node_fs5.default.renameSync(tmp, file);
|
|
1205
1272
|
}
|
|
1206
1273
|
function mutateStore(fn) {
|
|
1207
1274
|
const store = loadStore();
|
|
@@ -1210,13 +1277,13 @@ function mutateStore(fn) {
|
|
|
1210
1277
|
return store;
|
|
1211
1278
|
}
|
|
1212
1279
|
function projectIdForCwd(cwd) {
|
|
1213
|
-
return (0,
|
|
1280
|
+
return (0, import_node_crypto2.createHash)("sha256").update(import_node_path4.default.resolve(cwd)).digest("hex").slice(0, 16);
|
|
1214
1281
|
}
|
|
1215
1282
|
function newSessionId() {
|
|
1216
|
-
return `s_${(0,
|
|
1283
|
+
return `s_${(0, import_node_crypto2.randomBytes)(10).toString("hex")}`;
|
|
1217
1284
|
}
|
|
1218
1285
|
function upsertProject(input) {
|
|
1219
|
-
const cwd =
|
|
1286
|
+
const cwd = import_node_path4.default.resolve(input.cwd);
|
|
1220
1287
|
const id = projectIdForCwd(cwd);
|
|
1221
1288
|
let result;
|
|
1222
1289
|
mutateStore((store) => {
|
|
@@ -1242,7 +1309,7 @@ function upsertProject(input) {
|
|
|
1242
1309
|
const now = Date.now();
|
|
1243
1310
|
const created = {
|
|
1244
1311
|
id,
|
|
1245
|
-
name: input.name ??
|
|
1312
|
+
name: input.name ?? import_node_path4.default.basename(cwd),
|
|
1246
1313
|
cwd,
|
|
1247
1314
|
repoRoot: input.repoRoot,
|
|
1248
1315
|
sourceRoots: input.sourceRoots ?? [cwd],
|
|
@@ -1372,8 +1439,8 @@ async function seedFromDemoAppRegistry() {
|
|
|
1372
1439
|
if (apps.length === 0) return;
|
|
1373
1440
|
mutateStore((store) => {
|
|
1374
1441
|
for (const app of apps) {
|
|
1375
|
-
if (!
|
|
1376
|
-
const cwd =
|
|
1442
|
+
if (!import_node_fs5.default.existsSync(app.dir)) continue;
|
|
1443
|
+
const cwd = import_node_path4.default.resolve(app.dir);
|
|
1377
1444
|
const id = projectIdForCwd(cwd);
|
|
1378
1445
|
if (store.attachedProjects.some((p) => p.id === id)) continue;
|
|
1379
1446
|
const now = Date.now();
|
|
@@ -1397,16 +1464,16 @@ async function seedFromDemoAppRegistry() {
|
|
|
1397
1464
|
|
|
1398
1465
|
// src/agent-sessions.ts
|
|
1399
1466
|
function sessionDir(sessionId) {
|
|
1400
|
-
return
|
|
1467
|
+
return import_node_path5.default.join(getUserDataDir(), "sessions", sessionId);
|
|
1401
1468
|
}
|
|
1402
1469
|
function promptFifoPath(sessionId) {
|
|
1403
|
-
return
|
|
1470
|
+
return import_node_path5.default.join(sessionDir(sessionId), "prompt.in");
|
|
1404
1471
|
}
|
|
1405
1472
|
function eventsFifoPath(sessionId) {
|
|
1406
|
-
return
|
|
1473
|
+
return import_node_path5.default.join(sessionDir(sessionId), "events.out");
|
|
1407
1474
|
}
|
|
1408
1475
|
function transcriptPath(sessionId) {
|
|
1409
|
-
return
|
|
1476
|
+
return import_node_path5.default.join(getUserDataDir(), "transcripts", `${sessionId}.log`);
|
|
1410
1477
|
}
|
|
1411
1478
|
function pidIsAlive(pid, sessionId) {
|
|
1412
1479
|
if (!pid) return false;
|
|
@@ -1416,7 +1483,7 @@ function pidIsAlive(pid, sessionId) {
|
|
|
1416
1483
|
return false;
|
|
1417
1484
|
}
|
|
1418
1485
|
if (sessionId) {
|
|
1419
|
-
if (!
|
|
1486
|
+
if (!import_node_fs6.default.existsSync(sessionDir(sessionId))) return false;
|
|
1420
1487
|
}
|
|
1421
1488
|
return true;
|
|
1422
1489
|
}
|
|
@@ -1428,11 +1495,11 @@ function resolveSootsimInvocation() {
|
|
|
1428
1495
|
const resourcesPath = process.resourcesPath;
|
|
1429
1496
|
if (resourcesPath) {
|
|
1430
1497
|
const candidates = [
|
|
1431
|
-
|
|
1432
|
-
|
|
1498
|
+
import_node_path5.default.join(resourcesPath, "bin", "sootsim"),
|
|
1499
|
+
import_node_path5.default.join(resourcesPath, "bin", `sootsim-${process.platform}-${process.arch}`)
|
|
1433
1500
|
];
|
|
1434
1501
|
for (const c of candidates) {
|
|
1435
|
-
if (
|
|
1502
|
+
if (import_node_fs6.default.existsSync(c)) return { cmd: c, prefixArgs: [] };
|
|
1436
1503
|
}
|
|
1437
1504
|
}
|
|
1438
1505
|
}
|
|
@@ -1455,15 +1522,15 @@ function tryWorkspaceSootsim() {
|
|
|
1455
1522
|
const sootsimDir = resolveSootsimPackageDir();
|
|
1456
1523
|
if (!sootsimDir) return null;
|
|
1457
1524
|
const binaryName = `sootsim-${process.platform}-${process.arch}`;
|
|
1458
|
-
const distBinary =
|
|
1459
|
-
if (
|
|
1460
|
-
const distBin =
|
|
1461
|
-
if (
|
|
1525
|
+
const distBinary = import_node_path5.default.join(sootsimDir, "dist-bin", binaryName);
|
|
1526
|
+
if (import_node_fs6.default.existsSync(distBinary)) return { cmd: distBinary, prefixArgs: [] };
|
|
1527
|
+
const distBin = import_node_path5.default.join(sootsimDir, "dist-cli", "bin.js");
|
|
1528
|
+
if (import_node_fs6.default.existsSync(distBin)) {
|
|
1462
1529
|
try {
|
|
1463
|
-
const src =
|
|
1464
|
-
if (
|
|
1465
|
-
const srcMtime =
|
|
1466
|
-
const buildMtime =
|
|
1530
|
+
const src = import_node_path5.default.join(sootsimDir, "cli", "commands", "agent-wrapper.ts");
|
|
1531
|
+
if (import_node_fs6.default.existsSync(src)) {
|
|
1532
|
+
const srcMtime = import_node_fs6.default.statSync(src).mtimeMs;
|
|
1533
|
+
const buildMtime = import_node_fs6.default.statSync(distBin).mtimeMs;
|
|
1467
1534
|
if (buildMtime < srcMtime) {
|
|
1468
1535
|
console.warn(
|
|
1469
1536
|
`[sootsim] dist-cli/bin.js is older than agent-wrapper.ts \u2014 rebuild with \`bun run --cwd packages/sootsim build:cli\`.`
|
|
@@ -1482,22 +1549,22 @@ function tryWorkspaceSootsim() {
|
|
|
1482
1549
|
function resolveSootsimPackageDir() {
|
|
1483
1550
|
try {
|
|
1484
1551
|
const resolved = require.resolve("sootsim/package.json");
|
|
1485
|
-
return
|
|
1552
|
+
return import_node_path5.default.dirname(resolved);
|
|
1486
1553
|
} catch {
|
|
1487
1554
|
}
|
|
1488
1555
|
const here = fileFromImportMeta();
|
|
1489
1556
|
if (!here) return null;
|
|
1490
|
-
let cur =
|
|
1557
|
+
let cur = import_node_path5.default.dirname(here);
|
|
1491
1558
|
for (let i = 0; i < 8; i++) {
|
|
1492
|
-
const pkg =
|
|
1559
|
+
const pkg = import_node_path5.default.join(cur, "package.json");
|
|
1493
1560
|
try {
|
|
1494
|
-
if (
|
|
1495
|
-
const parsed = JSON.parse(
|
|
1561
|
+
if (import_node_fs6.default.existsSync(pkg)) {
|
|
1562
|
+
const parsed = JSON.parse(import_node_fs6.default.readFileSync(pkg, "utf8"));
|
|
1496
1563
|
if (parsed.name === "sootsim") return cur;
|
|
1497
1564
|
}
|
|
1498
1565
|
} catch {
|
|
1499
1566
|
}
|
|
1500
|
-
const parent =
|
|
1567
|
+
const parent = import_node_path5.default.dirname(cur);
|
|
1501
1568
|
if (parent === cur) break;
|
|
1502
1569
|
cur = parent;
|
|
1503
1570
|
}
|
|
@@ -1513,28 +1580,28 @@ function fileFromImportMeta() {
|
|
|
1513
1580
|
}
|
|
1514
1581
|
}
|
|
1515
1582
|
async function withStartLock(projectId, provider, fn) {
|
|
1516
|
-
const lockDir =
|
|
1517
|
-
|
|
1583
|
+
const lockDir = import_node_path5.default.join(getUserDataDir(), "locks");
|
|
1584
|
+
import_node_fs6.default.mkdirSync(lockDir, { recursive: true });
|
|
1518
1585
|
try {
|
|
1519
|
-
|
|
1586
|
+
import_node_fs6.default.chmodSync(lockDir, 448);
|
|
1520
1587
|
} catch {
|
|
1521
1588
|
}
|
|
1522
|
-
const lockPath =
|
|
1589
|
+
const lockPath = import_node_path5.default.join(lockDir, `start-${projectId}-${provider}.lock`);
|
|
1523
1590
|
const deadline = Date.now() + 4e3;
|
|
1524
1591
|
let fd = null;
|
|
1525
1592
|
while (fd === null) {
|
|
1526
1593
|
try {
|
|
1527
|
-
fd =
|
|
1594
|
+
fd = import_node_fs6.default.openSync(
|
|
1528
1595
|
lockPath,
|
|
1529
|
-
|
|
1596
|
+
import_node_fs6.constants.O_WRONLY | import_node_fs6.constants.O_CREAT | import_node_fs6.constants.O_EXCL,
|
|
1530
1597
|
384
|
|
1531
1598
|
);
|
|
1532
1599
|
} catch (err) {
|
|
1533
1600
|
if (err.code !== "EEXIST") throw err;
|
|
1534
1601
|
try {
|
|
1535
|
-
const stale = Number(
|
|
1602
|
+
const stale = Number(import_node_fs6.default.readFileSync(lockPath, "utf8").trim());
|
|
1536
1603
|
if (stale && !isProcessAlive(stale)) {
|
|
1537
|
-
|
|
1604
|
+
import_node_fs6.default.unlinkSync(lockPath);
|
|
1538
1605
|
continue;
|
|
1539
1606
|
}
|
|
1540
1607
|
} catch {
|
|
@@ -1548,15 +1615,15 @@ async function withStartLock(projectId, provider, fn) {
|
|
|
1548
1615
|
}
|
|
1549
1616
|
}
|
|
1550
1617
|
try {
|
|
1551
|
-
|
|
1618
|
+
import_node_fs6.default.writeFileSync(fd, String(process.pid));
|
|
1552
1619
|
return await fn();
|
|
1553
1620
|
} finally {
|
|
1554
1621
|
try {
|
|
1555
|
-
|
|
1622
|
+
import_node_fs6.default.closeSync(fd);
|
|
1556
1623
|
} catch {
|
|
1557
1624
|
}
|
|
1558
1625
|
try {
|
|
1559
|
-
|
|
1626
|
+
import_node_fs6.default.unlinkSync(lockPath);
|
|
1560
1627
|
} catch {
|
|
1561
1628
|
}
|
|
1562
1629
|
}
|
|
@@ -1570,28 +1637,28 @@ function isProcessAlive(pid) {
|
|
|
1570
1637
|
}
|
|
1571
1638
|
}
|
|
1572
1639
|
function mkfifoSync(p) {
|
|
1573
|
-
const parent =
|
|
1574
|
-
|
|
1640
|
+
const parent = import_node_path5.default.dirname(p);
|
|
1641
|
+
import_node_fs6.default.mkdirSync(parent, { recursive: true });
|
|
1575
1642
|
try {
|
|
1576
|
-
|
|
1643
|
+
import_node_fs6.default.chmodSync(parent, 448);
|
|
1577
1644
|
} catch {
|
|
1578
1645
|
}
|
|
1579
|
-
if (
|
|
1646
|
+
if (import_node_fs6.default.existsSync(p)) {
|
|
1580
1647
|
try {
|
|
1581
|
-
const stat =
|
|
1648
|
+
const stat = import_node_fs6.default.statSync(p);
|
|
1582
1649
|
if (stat.isFIFO()) {
|
|
1583
1650
|
try {
|
|
1584
|
-
|
|
1651
|
+
import_node_fs6.default.chmodSync(p, 384);
|
|
1585
1652
|
} catch {
|
|
1586
1653
|
}
|
|
1587
1654
|
return;
|
|
1588
1655
|
}
|
|
1589
|
-
|
|
1656
|
+
import_node_fs6.default.unlinkSync(p);
|
|
1590
1657
|
} catch {
|
|
1591
|
-
|
|
1658
|
+
import_node_fs6.default.unlinkSync(p);
|
|
1592
1659
|
}
|
|
1593
1660
|
}
|
|
1594
|
-
const result = (0,
|
|
1661
|
+
const result = (0, import_node_child_process2.spawnSync)("mkfifo", ["-m", "600", p]);
|
|
1595
1662
|
if (result.status !== 0) {
|
|
1596
1663
|
throw new Error(
|
|
1597
1664
|
`mkfifo(${p}) failed: ${result.stderr?.toString().trim() || "unknown error"}`
|
|
@@ -1621,7 +1688,7 @@ async function startSession(opts) {
|
|
|
1621
1688
|
`session already running for project=${project.id} provider=${provider} (session ${existingLive.id}, pid ${existingLive.wrapperPid}). end it first with \`sootsim agent end <sessionId>\`.`
|
|
1622
1689
|
);
|
|
1623
1690
|
}
|
|
1624
|
-
const claudeSessionUuid = provider === "claude" ? (0,
|
|
1691
|
+
const claudeSessionUuid = provider === "claude" ? (0, import_node_crypto3.randomUUID)() : void 0;
|
|
1625
1692
|
const session = upsertSession({
|
|
1626
1693
|
projectId: project.id,
|
|
1627
1694
|
provider,
|
|
@@ -1635,10 +1702,10 @@ async function startSession(opts) {
|
|
|
1635
1702
|
const transcript = transcriptPath(session.id);
|
|
1636
1703
|
mkfifoSync(promptIn);
|
|
1637
1704
|
mkfifoSync(eventsOut);
|
|
1638
|
-
const transcriptDir =
|
|
1639
|
-
|
|
1705
|
+
const transcriptDir = import_node_path5.default.dirname(transcript);
|
|
1706
|
+
import_node_fs6.default.mkdirSync(transcriptDir, { recursive: true });
|
|
1640
1707
|
try {
|
|
1641
|
-
|
|
1708
|
+
import_node_fs6.default.chmodSync(transcriptDir, 448);
|
|
1642
1709
|
} catch {
|
|
1643
1710
|
}
|
|
1644
1711
|
const { cmd, prefixArgs } = resolveSootsimInvocation();
|
|
@@ -1666,7 +1733,7 @@ async function startSession(opts) {
|
|
|
1666
1733
|
if (claudeSessionUuid) {
|
|
1667
1734
|
wrapperArgs.push("--claude-session-uuid", claudeSessionUuid);
|
|
1668
1735
|
}
|
|
1669
|
-
const child = (0,
|
|
1736
|
+
const child = (0, import_node_child_process2.spawn)(cmd, wrapperArgs, {
|
|
1670
1737
|
detached: true,
|
|
1671
1738
|
stdio: "ignore",
|
|
1672
1739
|
env: {
|
|
@@ -1689,7 +1756,7 @@ async function startSession(opts) {
|
|
|
1689
1756
|
}
|
|
1690
1757
|
}
|
|
1691
1758
|
try {
|
|
1692
|
-
|
|
1759
|
+
import_node_fs6.default.rmSync(sessionDir(session.id), { recursive: true, force: true });
|
|
1693
1760
|
} catch {
|
|
1694
1761
|
}
|
|
1695
1762
|
updateSessionStatus(session.id, { status: "ended" });
|
|
@@ -1717,18 +1784,18 @@ async function sendPrompt(sessionId, prompt) {
|
|
|
1717
1784
|
);
|
|
1718
1785
|
}
|
|
1719
1786
|
const fifo = promptFifoPath(sessionId);
|
|
1720
|
-
if (!
|
|
1787
|
+
if (!import_node_fs6.default.existsSync(fifo)) {
|
|
1721
1788
|
throw new AgentSessionError("NO_FIFO", `prompt FIFO missing: ${fifo}`);
|
|
1722
1789
|
}
|
|
1723
|
-
const fd =
|
|
1790
|
+
const fd = import_node_fs6.default.openSync(fifo, import_node_fs6.constants.O_WRONLY);
|
|
1724
1791
|
try {
|
|
1725
1792
|
const wireText = encodeAgentPromptEnvelope(prompt);
|
|
1726
1793
|
if (!wireText) {
|
|
1727
1794
|
throw new AgentSessionError("EMPTY_PROMPT", "prompt text is empty");
|
|
1728
1795
|
}
|
|
1729
|
-
|
|
1796
|
+
import_node_fs6.default.writeSync(fd, wireText + "\n");
|
|
1730
1797
|
} finally {
|
|
1731
|
-
|
|
1798
|
+
import_node_fs6.default.closeSync(fd);
|
|
1732
1799
|
}
|
|
1733
1800
|
updateSessionStatus(sessionId, {
|
|
1734
1801
|
lastPrompt: prompt.displayText ?? prompt.text,
|
|
@@ -1750,7 +1817,7 @@ async function endSession(sessionId) {
|
|
|
1750
1817
|
const base = getUserDataDir();
|
|
1751
1818
|
if (dir.startsWith(base)) {
|
|
1752
1819
|
try {
|
|
1753
|
-
|
|
1820
|
+
import_node_fs6.default.rmSync(dir, { recursive: true, force: true });
|
|
1754
1821
|
} catch {
|
|
1755
1822
|
}
|
|
1756
1823
|
}
|
|
@@ -1758,11 +1825,11 @@ async function endSession(sessionId) {
|
|
|
1758
1825
|
}
|
|
1759
1826
|
function subscribeEvents(sessionId, onEvent) {
|
|
1760
1827
|
const fifo = eventsFifoPath(sessionId);
|
|
1761
|
-
if (!
|
|
1828
|
+
if (!import_node_fs6.default.existsSync(fifo)) {
|
|
1762
1829
|
throw new AgentSessionError("NO_FIFO", `events FIFO missing: ${fifo}`);
|
|
1763
1830
|
}
|
|
1764
|
-
const fd =
|
|
1765
|
-
const stream =
|
|
1831
|
+
const fd = import_node_fs6.default.openSync(fifo, import_node_fs6.constants.O_RDWR);
|
|
1832
|
+
const stream = import_node_fs6.default.createReadStream("", { fd, autoClose: true });
|
|
1766
1833
|
const rl = import_node_readline.default.createInterface({ input: stream, crlfDelay: Infinity });
|
|
1767
1834
|
rl.on("line", (line) => {
|
|
1768
1835
|
const event = parseAgentEventLine(line);
|
|
@@ -1783,7 +1850,7 @@ function subscribeEvents(sessionId, onEvent) {
|
|
|
1783
1850
|
};
|
|
1784
1851
|
}
|
|
1785
1852
|
async function waitForFirstEvent(fifo, predicate, timeoutMs) {
|
|
1786
|
-
const fd =
|
|
1853
|
+
const fd = import_node_fs6.default.openSync(fifo, import_node_fs6.constants.O_RDWR | import_node_fs6.constants.O_NONBLOCK);
|
|
1787
1854
|
const buf = Buffer.alloc(8192);
|
|
1788
1855
|
let leftover = "";
|
|
1789
1856
|
const deadline = Date.now() + timeoutMs;
|
|
@@ -1791,7 +1858,7 @@ async function waitForFirstEvent(fifo, predicate, timeoutMs) {
|
|
|
1791
1858
|
while (Date.now() < deadline) {
|
|
1792
1859
|
let n = 0;
|
|
1793
1860
|
try {
|
|
1794
|
-
n =
|
|
1861
|
+
n = import_node_fs6.default.readSync(fd, buf, 0, buf.length, null);
|
|
1795
1862
|
} catch (err) {
|
|
1796
1863
|
if (err.code !== "EAGAIN") throw err;
|
|
1797
1864
|
n = 0;
|
|
@@ -1811,15 +1878,15 @@ async function waitForFirstEvent(fifo, predicate, timeoutMs) {
|
|
|
1811
1878
|
}
|
|
1812
1879
|
return null;
|
|
1813
1880
|
} finally {
|
|
1814
|
-
|
|
1881
|
+
import_node_fs6.default.closeSync(fd);
|
|
1815
1882
|
}
|
|
1816
1883
|
}
|
|
1817
1884
|
|
|
1818
1885
|
// src/agentbus-prompt.ts
|
|
1819
|
-
var
|
|
1820
|
-
var
|
|
1886
|
+
var import_node_child_process3 = require("node:child_process");
|
|
1887
|
+
var import_node_fs7 = __toESM(require("node:fs"), 1);
|
|
1821
1888
|
var import_node_os2 = __toESM(require("node:os"), 1);
|
|
1822
|
-
var
|
|
1889
|
+
var import_node_path6 = __toESM(require("node:path"), 1);
|
|
1823
1890
|
|
|
1824
1891
|
// src/agent-identity.ts
|
|
1825
1892
|
var AGENTBUS_SESSION_RE = /^[A-Za-z0-9._:-]{1,160}$/;
|
|
@@ -1842,8 +1909,8 @@ function resolveAgentbusCommand(explicit) {
|
|
|
1842
1909
|
if (fromArg) return fromArg;
|
|
1843
1910
|
const fromEnv = process.env.AGENTBUS_COMMAND?.trim();
|
|
1844
1911
|
if (fromEnv) return fromEnv;
|
|
1845
|
-
const localBin =
|
|
1846
|
-
if (
|
|
1912
|
+
const localBin = import_node_path6.default.join(import_node_os2.default.homedir(), ".local", "bin", "agentbus");
|
|
1913
|
+
if (import_node_fs7.default.existsSync(localBin)) return localBin;
|
|
1847
1914
|
return "agentbus";
|
|
1848
1915
|
}
|
|
1849
1916
|
async function sendPromptToAgentbusSession(input) {
|
|
@@ -1858,7 +1925,7 @@ async function sendPromptToAgentbusSession(input) {
|
|
|
1858
1925
|
const command = resolveAgentbusCommand(input.command);
|
|
1859
1926
|
const timeoutMs = input.timeoutMs ?? 15e3;
|
|
1860
1927
|
await new Promise((resolve, reject) => {
|
|
1861
|
-
const child = (0,
|
|
1928
|
+
const child = (0, import_node_child_process3.spawn)(command, ["send", sessionId, text], {
|
|
1862
1929
|
stdio: ["ignore", "ignore", "pipe"],
|
|
1863
1930
|
env: process.env
|
|
1864
1931
|
});
|
|
@@ -2084,7 +2151,7 @@ var AgentHost = class {
|
|
|
2084
2151
|
);
|
|
2085
2152
|
const project = upsertProject({
|
|
2086
2153
|
cwd: match.cwd,
|
|
2087
|
-
name: match.projectName ??
|
|
2154
|
+
name: match.projectName ?? import_node_path7.default.basename(match.cwd),
|
|
2088
2155
|
preferredProvider: input.provider ?? existing?.preferredProvider,
|
|
2089
2156
|
sourceRoots: existing?.sourceRoots ?? [match.cwd],
|
|
2090
2157
|
knownBundleUrls,
|
|
@@ -2095,18 +2162,18 @@ var AgentHost = class {
|
|
|
2095
2162
|
}
|
|
2096
2163
|
getTranscript(sessionId) {
|
|
2097
2164
|
const p = transcriptPath(sessionId);
|
|
2098
|
-
if (!
|
|
2165
|
+
if (!import_node_fs8.default.existsSync(p)) {
|
|
2099
2166
|
return { error: "transcript not found", code: "NO_TRANSCRIPT" };
|
|
2100
2167
|
}
|
|
2101
|
-
return
|
|
2168
|
+
return import_node_fs8.default.readFileSync(p, "utf8");
|
|
2102
2169
|
}
|
|
2103
2170
|
getPaths() {
|
|
2104
2171
|
const dir = getUserDataDir();
|
|
2105
2172
|
return {
|
|
2106
2173
|
userDataDir: dir,
|
|
2107
|
-
storeFile:
|
|
2108
|
-
sessionsDir:
|
|
2109
|
-
transcriptsDir:
|
|
2174
|
+
storeFile: import_node_path7.default.join(dir, "attached-projects.json"),
|
|
2175
|
+
sessionsDir: import_node_path7.default.join(dir, "sessions"),
|
|
2176
|
+
transcriptsDir: import_node_path7.default.join(dir, "transcripts")
|
|
2110
2177
|
};
|
|
2111
2178
|
}
|
|
2112
2179
|
// --- subscription management ---
|
|
@@ -2691,10 +2758,10 @@ function handleAppApiRequest(req, res) {
|
|
|
2691
2758
|
}
|
|
2692
2759
|
|
|
2693
2760
|
// src/host/open-url.ts
|
|
2694
|
-
var
|
|
2695
|
-
var
|
|
2761
|
+
var import_child_process2 = require("child_process");
|
|
2762
|
+
var import_fs2 = require("fs");
|
|
2696
2763
|
var import_os = require("os");
|
|
2697
|
-
var
|
|
2764
|
+
var import_path2 = require("path");
|
|
2698
2765
|
var MAC_CHROMIUM_CANDIDATES = [
|
|
2699
2766
|
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome",
|
|
2700
2767
|
"~/Applications/Google Chrome.app/Contents/MacOS/Google Chrome",
|
|
@@ -2732,19 +2799,19 @@ var UNIX_CHROMIUM_COMMANDS = [
|
|
|
2732
2799
|
];
|
|
2733
2800
|
var WINDOWS_CHROMIUM_COMMANDS = ["chrome", "msedge", "brave"];
|
|
2734
2801
|
function expandHome(candidate) {
|
|
2735
|
-
return candidate.startsWith("~/") ? (0,
|
|
2802
|
+
return candidate.startsWith("~/") ? (0, import_path2.join)((0, import_os.homedir)(), candidate.slice(2)) : candidate;
|
|
2736
2803
|
}
|
|
2737
2804
|
function firstExisting(candidates) {
|
|
2738
2805
|
for (const candidate of candidates) {
|
|
2739
2806
|
const expanded = expandHome(candidate);
|
|
2740
|
-
if ((0,
|
|
2807
|
+
if ((0, import_fs2.existsSync)(expanded)) return expanded;
|
|
2741
2808
|
}
|
|
2742
2809
|
return null;
|
|
2743
2810
|
}
|
|
2744
2811
|
function lookupExecutable(command, platform) {
|
|
2745
2812
|
try {
|
|
2746
2813
|
const tool = platform === "win32" ? "where" : "which";
|
|
2747
|
-
const out = (0,
|
|
2814
|
+
const out = (0, import_child_process2.execFileSync)(tool, [command], {
|
|
2748
2815
|
encoding: "utf8",
|
|
2749
2816
|
timeout: 1500,
|
|
2750
2817
|
stdio: ["ignore", "pipe", "ignore"]
|
|
@@ -2756,7 +2823,7 @@ function lookupExecutable(command, platform) {
|
|
|
2756
2823
|
}
|
|
2757
2824
|
function resolveChromiumBinary(platform = process.platform) {
|
|
2758
2825
|
const envCandidate = process.env.CHROME_PATH || process.env.CHROMIUM_PATH;
|
|
2759
|
-
if (envCandidate && (0,
|
|
2826
|
+
if (envCandidate && (0, import_fs2.existsSync)(envCandidate)) return envCandidate;
|
|
2760
2827
|
const direct = platform === "darwin" ? firstExisting(MAC_CHROMIUM_CANDIDATES) : platform === "win32" ? firstExisting(WINDOWS_CHROMIUM_CANDIDATES) : firstExisting(LINUX_CHROMIUM_CANDIDATES);
|
|
2761
2828
|
if (direct) return direct;
|
|
2762
2829
|
const commands = platform === "win32" ? WINDOWS_CHROMIUM_COMMANDS : UNIX_CHROMIUM_COMMANDS;
|
|
@@ -2813,7 +2880,7 @@ function buildChromiumUrlCommand(url, options = {}) {
|
|
|
2813
2880
|
}
|
|
2814
2881
|
async function spawnLaunch(command, args, detached) {
|
|
2815
2882
|
return new Promise((resolve, reject) => {
|
|
2816
|
-
const child = (0,
|
|
2883
|
+
const child = (0, import_child_process2.spawn)(command, args, {
|
|
2817
2884
|
detached,
|
|
2818
2885
|
stdio: "ignore"
|
|
2819
2886
|
});
|
|
@@ -3328,7 +3395,7 @@ var SootSimBridgeHost = class _SootSimBridgeHost {
|
|
|
3328
3395
|
return;
|
|
3329
3396
|
}
|
|
3330
3397
|
if (msg.type === "runtime:list") {
|
|
3331
|
-
const versions =
|
|
3398
|
+
const versions = sootsimRuntime.listInstalled();
|
|
3332
3399
|
const active = this.getActiveRuntime();
|
|
3333
3400
|
const reply = {
|
|
3334
3401
|
type: "runtime:list:ok",
|
|
@@ -3345,7 +3412,7 @@ var SootSimBridgeHost = class _SootSimBridgeHost {
|
|
|
3345
3412
|
}
|
|
3346
3413
|
if (msg.type === "runtime:use") {
|
|
3347
3414
|
const version = typeof msg.version === "string" ? msg.version : "";
|
|
3348
|
-
const installed =
|
|
3415
|
+
const installed = sootsimRuntime.listInstalled();
|
|
3349
3416
|
if (!installed.includes(version)) {
|
|
3350
3417
|
try {
|
|
3351
3418
|
ws.send(
|
|
@@ -3874,7 +3941,7 @@ var SootSimBridgeHost = class _SootSimBridgeHost {
|
|
|
3874
3941
|
if (reason === "startup") {
|
|
3875
3942
|
process.stderr.write("sootsim: checking for runtime updates\u2026\n");
|
|
3876
3943
|
}
|
|
3877
|
-
const result = await
|
|
3944
|
+
const result = await sootsimRuntime.updateToLatest();
|
|
3878
3945
|
if (!result.updated || !result.latestVersion) {
|
|
3879
3946
|
if (reason === "startup") {
|
|
3880
3947
|
process.stderr.write(
|
|
@@ -4110,34 +4177,34 @@ var SootSimBridgeHost = class _SootSimBridgeHost {
|
|
|
4110
4177
|
return;
|
|
4111
4178
|
}
|
|
4112
4179
|
}
|
|
4113
|
-
const resolved =
|
|
4114
|
-
const baseWithSep = baseDir.endsWith(
|
|
4180
|
+
const resolved = import_path3.default.resolve(baseDir, "." + rel);
|
|
4181
|
+
const baseWithSep = baseDir.endsWith(import_path3.default.sep) ? baseDir : baseDir + import_path3.default.sep;
|
|
4115
4182
|
if (!resolved.startsWith(baseWithSep) && resolved !== baseDir) {
|
|
4116
4183
|
res.writeHead(403);
|
|
4117
4184
|
res.end("forbidden");
|
|
4118
4185
|
return;
|
|
4119
4186
|
}
|
|
4120
|
-
|
|
4187
|
+
import_fs3.default.realpath(resolved, (realErr, realResolved) => {
|
|
4121
4188
|
const servePath = realErr ? resolved : realResolved;
|
|
4122
|
-
const servePathWithSep = servePath.endsWith(
|
|
4189
|
+
const servePathWithSep = servePath.endsWith(import_path3.default.sep) ? servePath : servePath + import_path3.default.sep;
|
|
4123
4190
|
if (!realErr) {
|
|
4124
4191
|
const realBaseWithSep = (() => {
|
|
4125
4192
|
try {
|
|
4126
|
-
const rb =
|
|
4127
|
-
return rb.endsWith(
|
|
4193
|
+
const rb = import_fs3.default.realpathSync(baseDir);
|
|
4194
|
+
return rb.endsWith(import_path3.default.sep) ? rb : rb + import_path3.default.sep;
|
|
4128
4195
|
} catch {
|
|
4129
4196
|
return baseWithSep;
|
|
4130
4197
|
}
|
|
4131
4198
|
})();
|
|
4132
|
-
if (!servePathWithSep.startsWith(realBaseWithSep) && servePath +
|
|
4199
|
+
if (!servePathWithSep.startsWith(realBaseWithSep) && servePath + import_path3.default.sep !== realBaseWithSep) {
|
|
4133
4200
|
res.writeHead(403);
|
|
4134
4201
|
res.end("forbidden");
|
|
4135
4202
|
return;
|
|
4136
4203
|
}
|
|
4137
4204
|
}
|
|
4138
|
-
|
|
4205
|
+
import_fs3.default.stat(servePath, (err, stats) => {
|
|
4139
4206
|
if (err || !stats?.isFile()) {
|
|
4140
|
-
const ext2 =
|
|
4207
|
+
const ext2 = import_path3.default.extname(rel).toLowerCase();
|
|
4141
4208
|
if (ext2 && ext2 !== ".html") {
|
|
4142
4209
|
res.writeHead(404);
|
|
4143
4210
|
res.end("not found");
|
|
@@ -4148,8 +4215,8 @@ var SootSimBridgeHost = class _SootSimBridgeHost {
|
|
|
4148
4215
|
res.end("not found");
|
|
4149
4216
|
return;
|
|
4150
4217
|
}
|
|
4151
|
-
const indexPath =
|
|
4152
|
-
|
|
4218
|
+
const indexPath = import_path3.default.join(baseDir, "index.html");
|
|
4219
|
+
import_fs3.default.readFile(indexPath, (err2, data) => {
|
|
4153
4220
|
if (err2) {
|
|
4154
4221
|
res.writeHead(404);
|
|
4155
4222
|
res.end("not found");
|
|
@@ -4169,7 +4236,7 @@ var SootSimBridgeHost = class _SootSimBridgeHost {
|
|
|
4169
4236
|
});
|
|
4170
4237
|
return;
|
|
4171
4238
|
}
|
|
4172
|
-
const ext =
|
|
4239
|
+
const ext = import_path3.default.extname(servePath).toLowerCase();
|
|
4173
4240
|
const contentType = HTTP_MIME_TYPES[ext] || "application/octet-stream";
|
|
4174
4241
|
res.writeHead(200, {
|
|
4175
4242
|
"Content-Type": contentType,
|
|
@@ -4180,7 +4247,7 @@ var SootSimBridgeHost = class _SootSimBridgeHost {
|
|
|
4180
4247
|
return;
|
|
4181
4248
|
}
|
|
4182
4249
|
if (ext === ".html") {
|
|
4183
|
-
|
|
4250
|
+
import_fs3.default.readFile(servePath, (readErr, data) => {
|
|
4184
4251
|
if (readErr) {
|
|
4185
4252
|
try {
|
|
4186
4253
|
res.end();
|
|
@@ -4194,7 +4261,7 @@ var SootSimBridgeHost = class _SootSimBridgeHost {
|
|
|
4194
4261
|
});
|
|
4195
4262
|
return;
|
|
4196
4263
|
}
|
|
4197
|
-
const stream =
|
|
4264
|
+
const stream = import_fs3.default.createReadStream(servePath);
|
|
4198
4265
|
stream.pipe(res);
|
|
4199
4266
|
stream.on("error", () => {
|
|
4200
4267
|
try {
|
|
@@ -4400,7 +4467,7 @@ var SootSimBridgeHost = class _SootSimBridgeHost {
|
|
|
4400
4467
|
const target = `${filePath}${loc}`;
|
|
4401
4468
|
const trySpawn = (cmd, args) => new Promise((resolve) => {
|
|
4402
4469
|
try {
|
|
4403
|
-
const child = (0,
|
|
4470
|
+
const child = (0, import_child_process3.spawn)(cmd, args, { detached: true, stdio: "ignore" });
|
|
4404
4471
|
let settled = false;
|
|
4405
4472
|
child.on("error", () => {
|
|
4406
4473
|
if (settled) return;
|