sootsim 0.1.251 → 0.1.253
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-VULBDRQX.js} +2 -2
- package/dist-cli/chunks/{agent-wrapper-JXCJFH4J.js → agent-wrapper-NIKM5YH7.js} +2 -2
- package/dist-cli/chunks/{app-fonts-KM5VGTPQ.js → app-fonts-H6Q7KUPX.js} +2 -2
- package/dist-cli/chunks/{assert-IWDBWZA3.js → assert-KG4DXXXU.js} +2 -2
- package/dist-cli/chunks/{auth-GGWN2KHL.js → auth-YFAM5XCG.js} +2 -2
- package/dist-cli/chunks/beta-X7YVGAZ7.js +2 -0
- package/dist-cli/chunks/{camera-W5JQ5P6L.js → camera-LDDRWGWU.js} +2 -2
- package/dist-cli/chunks/chunk-36BZF4FN.js +29 -0
- package/dist-cli/chunks/{chunk-CQKALFGJ.js → chunk-3UCSOXI3.js} +1 -1
- package/dist-cli/chunks/{chunk-XJYAJ5C3.js → chunk-45WNNP6S.js} +2 -2
- package/dist-cli/chunks/{chunk-UTNAJIRM.js → chunk-46TTKKZH.js} +2 -2
- package/dist-cli/chunks/chunk-57Y54BSR.js +1 -0
- package/dist-cli/chunks/{chunk-LJKL5JQ7.js → chunk-5FUEGJVZ.js} +2 -2
- package/dist-cli/chunks/{chunk-CDZTB6JX.js → chunk-5KIOJ7EY.js} +2 -2
- package/dist-cli/chunks/{chunk-IC4GREHT.js → chunk-5LRIUIDH.js} +1 -1
- package/dist-cli/chunks/{chunk-KEBLYJBJ.js → chunk-7X342NBJ.js} +2 -2
- package/dist-cli/chunks/chunk-AVDM5PJT.js +7 -0
- package/dist-cli/chunks/{chunk-7HCKUJ5R.js → chunk-BMDLK4TN.js} +1 -1
- package/dist-cli/chunks/{chunk-VO5UXLRE.js → chunk-C5WLLPSP.js} +2 -2
- package/dist-cli/chunks/chunk-DCSZ4W7L.js +4 -0
- package/dist-cli/chunks/{chunk-55GPRX3M.js → chunk-DEPT2HN2.js} +2 -2
- package/dist-cli/chunks/{chunk-KD347J3Y.js → chunk-DVL3QEUF.js} +2 -2
- package/dist-cli/chunks/{chunk-LETXRLKY.js → chunk-GQEV66R5.js} +1 -1
- package/dist-cli/chunks/{chunk-Z7IG2OVW.js → chunk-HWJY7OMU.js} +1 -1
- package/dist-cli/chunks/chunk-HWUTV647.js +1 -0
- package/dist-cli/chunks/{chunk-MK5FIMS5.js → chunk-I2SPWGIX.js} +2 -2
- package/dist-cli/chunks/{chunk-7MEV3VTL.js → chunk-IRKSPKGN.js} +1 -1
- package/dist-cli/chunks/{chunk-PM3MMXYH.js → chunk-L2MLV2CS.js} +2 -2
- package/dist-cli/chunks/{chunk-FBAFTRKJ.js → chunk-L6CZJTQL.js} +2 -2
- package/dist-cli/chunks/{chunk-KEJB5OS5.js → chunk-LQGKEJEY.js} +2 -2
- package/dist-cli/chunks/{chunk-WD4B3KV6.js → chunk-MJVYTFNP.js} +3 -3
- package/dist-cli/chunks/{chunk-YJEU2B3D.js → chunk-MWMCDY2F.js} +1 -1
- package/dist-cli/chunks/{chunk-RBHEKEEX.js → chunk-NGPLOHLX.js} +2 -2
- package/dist-cli/chunks/{chunk-63FDEQKS.js → chunk-NKBPE462.js} +1 -1
- package/dist-cli/chunks/{chunk-OOLWKYWS.js → chunk-NTITLMC6.js} +1 -1
- package/dist-cli/chunks/{chunk-TQJZ2AP4.js → chunk-NUEXSE26.js} +2 -2
- package/dist-cli/chunks/{chunk-DVLNBQO6.js → chunk-NUPOCIXQ.js} +2 -2
- package/dist-cli/chunks/{chunk-GMJ3ROI3.js → chunk-PDGZJCKZ.js} +2 -2
- package/dist-cli/chunks/{chunk-ULYIJUKO.js → chunk-PPEVHLXX.js} +2 -2
- package/dist-cli/chunks/{chunk-EY5V6OC5.js → chunk-Q5HUMK3X.js} +2 -2
- package/dist-cli/chunks/{chunk-NQCAEFUQ.js → chunk-QLD2JSAY.js} +1 -1
- package/dist-cli/chunks/{chunk-H3YZXLYR.js → chunk-RKLOJJIQ.js} +1 -1
- package/dist-cli/chunks/{chunk-IYPXOVE4.js → chunk-ROP4FQW2.js} +1 -1
- package/dist-cli/chunks/{chunk-ZL3QAP5O.js → chunk-SM36BLYO.js} +3 -3
- package/dist-cli/chunks/{chunk-37PWKV2H.js → chunk-UTHHCEOE.js} +1 -1
- package/dist-cli/chunks/{chunk-X4HNMVAY.js → chunk-VUUVN4CA.js} +2 -2
- package/dist-cli/chunks/{chunk-PZZPL7XB.js → chunk-WLTTYQFC.js} +1 -1
- package/dist-cli/chunks/{chunk-5T62AM5W.js → chunk-WXXCER5Y.js} +3 -3
- package/dist-cli/chunks/{chunk-7JTW5KO4.js → chunk-XRDM6KN6.js} +1 -1
- package/dist-cli/chunks/{chunk-HLD3JMUC.js → chunk-Y66ZEDLD.js} +2 -2
- package/dist-cli/chunks/{chunk-Z6ZYU2VN.js → chunk-YQDI7PAU.js} +1 -1
- package/dist-cli/chunks/cli-version-YK3KEAWE.js +2 -0
- package/dist-cli/chunks/{compat-Q7NF5FGR.js → compat-5MLHRLL7.js} +3 -3
- package/dist-cli/chunks/{config-CHFGC57H.js → config-XQU7NIBN.js} +2 -2
- package/dist-cli/chunks/{control-GMXYQHOC.js → control-CP27GWY2.js} +2 -2
- package/dist-cli/chunks/daemon-SZ5235QJ.js +2 -0
- package/dist-cli/chunks/{debug-JVFKA6ZJ.js → debug-XAS5RRTR.js} +3 -3
- package/dist-cli/chunks/{desktop-DT6WBVHN.js → desktop-DMRDH54D.js} +3 -3
- package/dist-cli/chunks/{detox-OQ3DVIZB.js → detox-5RWKQ4FY.js} +2 -2
- package/dist-cli/chunks/{device-XBBNWO67.js → device-K4QUDQJW.js} +2 -2
- package/dist-cli/chunks/{diagnose-JFWKSZI6.js → diagnose-XQ3UCGAC.js} +2 -2
- package/dist-cli/chunks/drivers-4XIRJTRV.js +2 -0
- package/dist-cli/chunks/{film-3BI63O2P.js → film-NBO7R7YE.js} +3 -3
- package/dist-cli/chunks/flow-IPFJBZ2T.js +2 -0
- package/dist-cli/chunks/help-OVFNRXKE.js +2 -0
- package/dist-cli/chunks/{hidden-runtime-alias-JGY2SN3U.js → hidden-runtime-alias-HMRDTRPL.js} +2 -2
- package/dist-cli/chunks/home-paths-IHLLHTH3.js +2 -0
- package/dist-cli/chunks/inspect-OLDRJZFR.js +2 -0
- package/dist-cli/chunks/install-desktop-4LN5U3GV.js +2 -0
- package/dist-cli/chunks/{login-QT6OUDLD.js → login-JJ26E3ZL.js} +4 -4
- package/dist-cli/chunks/{logout-QM7I6EYI.js → logout-Z4T2ZUMV.js} +2 -2
- package/dist-cli/chunks/{maestro-YU5YDZ44.js → maestro-27CX2MYE.js} +3 -3
- package/dist-cli/chunks/{maestro-generate-YQ5GE6LW.js → maestro-generate-S2HMOTKV.js} +3 -3
- package/dist-cli/chunks/{mode-MHOIKOWG.js → mode-MUI6VEX5.js} +2 -2
- package/dist-cli/chunks/optional-demo-registry-B5KGRDC7.js +2 -0
- package/dist-cli/chunks/{perf-UDWM5CLN.js → perf-XLL4NAW4.js} +2 -2
- package/dist-cli/chunks/{record-EEYIMPNW.js → record-CO6ZZXOF.js} +3 -3
- package/dist-cli/chunks/runtime-3BT5LEI2.js +2 -0
- package/dist-cli/chunks/{screenshot-command-MDOO4W2M.js → screenshot-command-7TLIPP6M.js} +3 -3
- package/dist-cli/chunks/{screenshots-capture-MYFBKRYI.js → screenshots-capture-W47CLDWK.js} +2 -2
- package/dist-cli/chunks/{serve-TFGKULND.js → serve-JFWQW3PY.js} +15 -15
- package/dist-cli/chunks/{setup-WOB5DERX.js → setup-64WP25N3.js} +3 -3
- package/dist-cli/chunks/{skills-MFFPTR5A.js → skills-FEOY5MFR.js} +2 -2
- package/dist-cli/chunks/{storage-6IZXGU2O.js → storage-DVJEOSE5.js} +2 -2
- package/dist-cli/chunks/store-VWZLLKMA.js +2 -0
- package/dist-cli/chunks/telemetry-RRR64APJ.js +2 -0
- package/dist-cli/chunks/{timeline-BRXK7M5J.js → timeline-BN4FOIE5.js} +2 -2
- package/dist-cli/chunks/{upgrade-K6A4PITT.js → upgrade-R6FMWF53.js} +4 -4
- package/dist-cli/chunks/upload-VV6ASI6M.js +2 -0
- package/dist-cli/chunks/version-5GYDQEIP.js +4 -0
- package/dist-cli/chunks/{web-P3ANEMOL.js → web-SZQMAIF5.js} +2 -2
- package/dist-cli/chunks/{what-happened-OFMSOZZB.js → what-happened-2KMAVPKZ.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 +404 -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 +523 -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 +36 -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
package/dist-lib/skills.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! sootsim v0.1.
|
|
1
|
+
/*! sootsim v0.1.253 | (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;
|
|
@@ -10528,10 +10528,10 @@ function tcpPing(port, timeout = TCP_GATE_MS) {
|
|
|
10528
10528
|
sock.connect(port, "localhost");
|
|
10529
10529
|
});
|
|
10530
10530
|
}
|
|
10531
|
-
function httpGet(port,
|
|
10531
|
+
function httpGet(port, path12, method = "GET", timeout = TIMEOUT_MS, headers = {}) {
|
|
10532
10532
|
return new Promise((resolve5) => {
|
|
10533
10533
|
const req = import_http.default.request(
|
|
10534
|
-
{ hostname: "localhost", port, path:
|
|
10534
|
+
{ hostname: "localhost", port, path: path12, method, timeout, headers },
|
|
10535
10535
|
(res) => {
|
|
10536
10536
|
let body = "";
|
|
10537
10537
|
res.on("data", (c) => body += c.toString());
|
|
@@ -11088,34 +11088,6 @@ function writeActiveRuntime(version) {
|
|
|
11088
11088
|
import_node_fs2.default.writeFileSync(activeRuntimeFile(), `${version}
|
|
11089
11089
|
`, "utf8");
|
|
11090
11090
|
}
|
|
11091
|
-
function listInstalledRuntimes() {
|
|
11092
|
-
try {
|
|
11093
|
-
return import_node_fs2.default.readdirSync(runtimesDir(), { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name).sort(compareSemver);
|
|
11094
|
-
} catch {
|
|
11095
|
-
return [];
|
|
11096
|
-
}
|
|
11097
|
-
}
|
|
11098
|
-
function compareSemver(a, b) {
|
|
11099
|
-
const parse = (v) => {
|
|
11100
|
-
const hyphen = v.indexOf("-");
|
|
11101
|
-
const core = hyphen >= 0 ? v.slice(0, hyphen) : v;
|
|
11102
|
-
const pre = hyphen >= 0 ? v.slice(hyphen + 1) : "";
|
|
11103
|
-
const parts = core.split(".").map((n) => Number.parseInt(n, 10));
|
|
11104
|
-
if (parts.some((n) => !Number.isFinite(n))) return [[Number.POSITIVE_INFINITY], v];
|
|
11105
|
-
return [parts, pre];
|
|
11106
|
-
};
|
|
11107
|
-
const [an, ap] = parse(a);
|
|
11108
|
-
const [bn, bp] = parse(b);
|
|
11109
|
-
for (let i = 0; i < Math.max(an.length, bn.length); i++) {
|
|
11110
|
-
const av = an[i] ?? 0;
|
|
11111
|
-
const bv = bn[i] ?? 0;
|
|
11112
|
-
if (av !== bv) return av - bv;
|
|
11113
|
-
}
|
|
11114
|
-
if (ap === bp) return 0;
|
|
11115
|
-
if (!ap) return 1;
|
|
11116
|
-
if (!bp) return -1;
|
|
11117
|
-
return ap < bp ? -1 : 1;
|
|
11118
|
-
}
|
|
11119
11091
|
function activeRuntimeDir() {
|
|
11120
11092
|
const version = readActiveRuntime();
|
|
11121
11093
|
if (!version) return null;
|
|
@@ -11271,139 +11243,241 @@ var init_runtime_assets = __esm({
|
|
|
11271
11243
|
}
|
|
11272
11244
|
});
|
|
11273
11245
|
|
|
11274
|
-
//
|
|
11275
|
-
function
|
|
11246
|
+
// ../contrast-runtime-delivery/src/product.ts
|
|
11247
|
+
function listInstalledRuntimes(product) {
|
|
11276
11248
|
try {
|
|
11277
|
-
|
|
11278
|
-
return parsed && typeof parsed === "object" ? parsed : {};
|
|
11249
|
+
return import_node_fs3.default.readdirSync(product.runtimesDir(), { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name).sort(compareSemver);
|
|
11279
11250
|
} catch {
|
|
11280
|
-
return
|
|
11251
|
+
return [];
|
|
11281
11252
|
}
|
|
11282
11253
|
}
|
|
11283
|
-
function
|
|
11284
|
-
|
|
11285
|
-
const value = input || process.env[RUNTIME_CDN_ORIGIN_ENV] || config.cdnOrigin || DEFAULT_RUNTIME_CDN_ORIGIN;
|
|
11286
|
-
return value.replace(/\/+$/, "");
|
|
11287
|
-
}
|
|
11288
|
-
function resolveRuntimeChannel(input) {
|
|
11289
|
-
const config = readConfig();
|
|
11290
|
-
return input || process.env[RUNTIME_CHANNEL_ENV] || config.runtimeChannel || "stable";
|
|
11291
|
-
}
|
|
11292
|
-
function resolveRuntimePin() {
|
|
11293
|
-
const env = process.env[RUNTIME_PIN_ENV];
|
|
11294
|
-
if (env && env.trim()) return env.trim();
|
|
11295
|
-
const config = readConfig();
|
|
11296
|
-
return typeof config.runtimeVersion === "string" && config.runtimeVersion.trim() ? config.runtimeVersion.trim() : null;
|
|
11297
|
-
}
|
|
11298
|
-
function runtimeManifestUrl(cdnOrigin) {
|
|
11299
|
-
const url = new URL(`${resolveRuntimeCdnOrigin(cdnOrigin)}/runtimes/manifest.json`);
|
|
11300
|
-
url.searchParams.set("t", String(Date.now()));
|
|
11301
|
-
return url.toString();
|
|
11302
|
-
}
|
|
11303
|
-
function runtimeTarballUrl(version, cdnOrigin) {
|
|
11304
|
-
return `${resolveRuntimeCdnOrigin(cdnOrigin)}/runtimes/sootsim-runtime-${version}.tar.gz`;
|
|
11254
|
+
function runtimeTarballCacheName(product, version) {
|
|
11255
|
+
return import_node_path2.default.posix.basename(product.tarballPath(version));
|
|
11305
11256
|
}
|
|
11306
|
-
|
|
11307
|
-
const
|
|
11308
|
-
|
|
11309
|
-
|
|
11310
|
-
|
|
11257
|
+
function compareSemver(a, b) {
|
|
11258
|
+
const parse = (v) => {
|
|
11259
|
+
const hyphen = v.indexOf("-");
|
|
11260
|
+
const core = hyphen >= 0 ? v.slice(0, hyphen) : v;
|
|
11261
|
+
const pre = hyphen >= 0 ? v.slice(hyphen + 1) : "";
|
|
11262
|
+
const parts = core.split(".").map((n) => Number.parseInt(n, 10));
|
|
11263
|
+
if (parts.some((n) => !Number.isFinite(n))) return [[Number.POSITIVE_INFINITY], v];
|
|
11264
|
+
return [parts, pre];
|
|
11265
|
+
};
|
|
11266
|
+
const [an, ap] = parse(a);
|
|
11267
|
+
const [bn, bp] = parse(b);
|
|
11268
|
+
for (let i = 0; i < Math.max(an.length, bn.length); i++) {
|
|
11269
|
+
const av = an[i] ?? 0;
|
|
11270
|
+
const bv = bn[i] ?? 0;
|
|
11271
|
+
if (av !== bv) return av - bv;
|
|
11311
11272
|
}
|
|
11312
|
-
|
|
11273
|
+
if (ap === bp) return 0;
|
|
11274
|
+
if (!ap) return 1;
|
|
11275
|
+
if (!bp) return -1;
|
|
11276
|
+
return ap < bp ? -1 : 1;
|
|
11313
11277
|
}
|
|
11314
|
-
|
|
11315
|
-
|
|
11316
|
-
|
|
11317
|
-
|
|
11318
|
-
|
|
11319
|
-
|
|
11320
|
-
);
|
|
11278
|
+
var import_node_fs3, import_node_path2;
|
|
11279
|
+
var init_product = __esm({
|
|
11280
|
+
"../contrast-runtime-delivery/src/product.ts"() {
|
|
11281
|
+
"use strict";
|
|
11282
|
+
import_node_fs3 = __toESM(require("node:fs"), 1);
|
|
11283
|
+
import_node_path2 = __toESM(require("node:path"), 1);
|
|
11321
11284
|
}
|
|
11322
|
-
|
|
11323
|
-
|
|
11324
|
-
|
|
11325
|
-
|
|
11326
|
-
|
|
11285
|
+
});
|
|
11286
|
+
|
|
11287
|
+
// ../contrast-runtime-delivery/src/index.ts
|
|
11288
|
+
function createRuntimeDelivery(product) {
|
|
11289
|
+
function readConfig() {
|
|
11290
|
+
try {
|
|
11291
|
+
const parsed = JSON.parse(
|
|
11292
|
+
import_node_fs4.default.readFileSync(product.configFile(), "utf8")
|
|
11293
|
+
);
|
|
11294
|
+
return parsed && typeof parsed === "object" ? parsed : {};
|
|
11295
|
+
} catch {
|
|
11296
|
+
return {};
|
|
11297
|
+
}
|
|
11327
11298
|
}
|
|
11328
|
-
|
|
11329
|
-
|
|
11330
|
-
|
|
11331
|
-
|
|
11332
|
-
|
|
11333
|
-
|
|
11334
|
-
|
|
11335
|
-
|
|
11336
|
-
|
|
11337
|
-
|
|
11338
|
-
|
|
11299
|
+
function resolveCdnOrigin(input) {
|
|
11300
|
+
const config = readConfig();
|
|
11301
|
+
const value = input || process.env[product.env.cdnOrigin] || config.cdnOrigin || product.defaultCdnOrigin;
|
|
11302
|
+
return value.replace(/\/+$/, "");
|
|
11303
|
+
}
|
|
11304
|
+
function resolveChannel(input) {
|
|
11305
|
+
const config = readConfig();
|
|
11306
|
+
return input || process.env[product.env.channel] || config.runtimeChannel || "stable";
|
|
11307
|
+
}
|
|
11308
|
+
function resolvePin() {
|
|
11309
|
+
const env = process.env[product.env.pin];
|
|
11310
|
+
if (env && env.trim()) return env.trim();
|
|
11311
|
+
const config = readConfig();
|
|
11312
|
+
return typeof config.runtimeVersion === "string" && config.runtimeVersion.trim() ? config.runtimeVersion.trim() : null;
|
|
11313
|
+
}
|
|
11314
|
+
function manifestUrl(cdnOrigin) {
|
|
11315
|
+
const url = new URL(`${resolveCdnOrigin(cdnOrigin)}${product.manifestPath}`);
|
|
11316
|
+
url.searchParams.set("t", String(Date.now()));
|
|
11317
|
+
return url.toString();
|
|
11318
|
+
}
|
|
11319
|
+
function tarballUrl(version, cdnOrigin) {
|
|
11320
|
+
return `${resolveCdnOrigin(cdnOrigin)}${product.tarballPath(version)}`;
|
|
11321
|
+
}
|
|
11322
|
+
async function fetchManifest(cdnOrigin) {
|
|
11323
|
+
const url = manifestUrl(cdnOrigin);
|
|
11324
|
+
const res = await fetch(url, { headers: { Accept: "application/json" } });
|
|
11325
|
+
if (!res.ok) {
|
|
11326
|
+
throw new Error(`manifest fetch failed: ${res.status} ${res.statusText} (${url})`);
|
|
11327
|
+
}
|
|
11328
|
+
return await res.json();
|
|
11329
|
+
}
|
|
11330
|
+
function resolveVersion(manifest, opts = {}) {
|
|
11331
|
+
const channel = resolveChannel(opts.channel);
|
|
11332
|
+
const version = opts.version || resolvePin() || manifest.channels[channel]?.latest;
|
|
11333
|
+
if (!version) {
|
|
11334
|
+
throw new Error(
|
|
11335
|
+
`no version specified and channel '${channel}' has no latest entry in the manifest`
|
|
11336
|
+
);
|
|
11337
|
+
}
|
|
11338
|
+
const entry = manifest.versions[version];
|
|
11339
|
+
if (!entry) {
|
|
11340
|
+
throw new Error(
|
|
11341
|
+
`version ${version} not found in manifest; available: ${Object.keys(manifest.versions).slice(-10).join(", ") || "(none)"}`
|
|
11342
|
+
);
|
|
11343
|
+
}
|
|
11344
|
+
return { version, channel, entry };
|
|
11345
|
+
}
|
|
11346
|
+
async function install(opts = {}) {
|
|
11347
|
+
product.ensureHome();
|
|
11348
|
+
const cdnOrigin = resolveCdnOrigin(opts.cdnOrigin);
|
|
11349
|
+
const manifest = await fetchManifest(cdnOrigin);
|
|
11350
|
+
const { version, channel, entry } = resolveVersion(manifest, opts);
|
|
11351
|
+
const destDir = product.runtimeDir(version);
|
|
11352
|
+
const setActive = opts.setActive !== false;
|
|
11353
|
+
if (!opts.force && import_node_fs4.default.existsSync(import_node_path3.default.join(destDir, product.installedMarker))) {
|
|
11354
|
+
if (setActive) product.writeActiveRuntime(version);
|
|
11355
|
+
return {
|
|
11356
|
+
version,
|
|
11357
|
+
channel,
|
|
11358
|
+
cdnOrigin,
|
|
11359
|
+
runtimeDir: destDir,
|
|
11360
|
+
installed: false,
|
|
11361
|
+
activated: setActive,
|
|
11362
|
+
manifest
|
|
11363
|
+
};
|
|
11364
|
+
}
|
|
11365
|
+
const tarUrl = entry.tarball || tarballUrl(version, cdnOrigin);
|
|
11366
|
+
const tarCachePath = import_node_path3.default.join(
|
|
11367
|
+
product.cacheDir(),
|
|
11368
|
+
runtimeTarballCacheName(product, version)
|
|
11369
|
+
);
|
|
11370
|
+
process.stderr.write(`${product.id}: downloading runtime ${version}\u2026
|
|
11371
|
+
`);
|
|
11372
|
+
await downloadToFile(tarUrl, tarCachePath);
|
|
11373
|
+
process.stderr.write(`${product.id}: extracting runtime ${version}\u2026
|
|
11374
|
+
`);
|
|
11375
|
+
const actualSha = await sha256File(tarCachePath);
|
|
11376
|
+
if (actualSha !== entry.sha256) {
|
|
11377
|
+
import_node_fs4.default.rmSync(tarCachePath, { force: true });
|
|
11378
|
+
throw new Error(
|
|
11379
|
+
`sha256 mismatch for runtime ${version}: expected ${entry.sha256}, actual ${actualSha}`
|
|
11380
|
+
);
|
|
11381
|
+
}
|
|
11382
|
+
const tmpDir = import_node_path3.default.join(
|
|
11383
|
+
import_node_path3.default.dirname(destDir),
|
|
11384
|
+
`.installing-${version}-${process.pid}`
|
|
11385
|
+
);
|
|
11386
|
+
import_node_fs4.default.rmSync(tmpDir, { recursive: true, force: true });
|
|
11387
|
+
import_node_fs4.default.mkdirSync(tmpDir, { recursive: true });
|
|
11388
|
+
try {
|
|
11389
|
+
await extractTarball(tarCachePath, tmpDir);
|
|
11390
|
+
if (!import_node_fs4.default.existsSync(import_node_path3.default.join(tmpDir, product.installedMarker))) {
|
|
11391
|
+
throw new Error(
|
|
11392
|
+
`extracted tarball for runtime ${version} is missing ${product.installedMarker}`
|
|
11393
|
+
);
|
|
11394
|
+
}
|
|
11395
|
+
import_node_fs4.default.rmSync(destDir, { recursive: true, force: true });
|
|
11396
|
+
import_node_fs4.default.renameSync(tmpDir, destDir);
|
|
11397
|
+
} catch (err) {
|
|
11398
|
+
import_node_fs4.default.rmSync(tmpDir, { recursive: true, force: true });
|
|
11399
|
+
throw err;
|
|
11400
|
+
}
|
|
11401
|
+
if (setActive) product.writeActiveRuntime(version);
|
|
11339
11402
|
return {
|
|
11340
11403
|
version,
|
|
11341
11404
|
channel,
|
|
11342
11405
|
cdnOrigin,
|
|
11343
11406
|
runtimeDir: destDir,
|
|
11344
|
-
installed:
|
|
11407
|
+
installed: true,
|
|
11345
11408
|
activated: setActive,
|
|
11346
11409
|
manifest
|
|
11347
11410
|
};
|
|
11348
11411
|
}
|
|
11349
|
-
|
|
11350
|
-
|
|
11351
|
-
|
|
11352
|
-
|
|
11353
|
-
|
|
11354
|
-
|
|
11355
|
-
|
|
11356
|
-
|
|
11357
|
-
|
|
11358
|
-
|
|
11359
|
-
|
|
11360
|
-
|
|
11361
|
-
|
|
11362
|
-
|
|
11363
|
-
|
|
11364
|
-
|
|
11365
|
-
|
|
11366
|
-
|
|
11367
|
-
|
|
11368
|
-
|
|
11369
|
-
|
|
11412
|
+
async function updateToLatest(opts = {}) {
|
|
11413
|
+
product.ensureHome();
|
|
11414
|
+
const cdnOrigin = resolveCdnOrigin(opts.cdnOrigin);
|
|
11415
|
+
const channel = resolveChannel(opts.channel);
|
|
11416
|
+
const pin = resolvePin();
|
|
11417
|
+
if (pin) {
|
|
11418
|
+
const activeVersion2 = product.readActiveRuntime();
|
|
11419
|
+
const pinInstalled = import_node_fs4.default.existsSync(
|
|
11420
|
+
import_node_path3.default.join(product.runtimeDir(pin), product.installedMarker)
|
|
11421
|
+
);
|
|
11422
|
+
if (activeVersion2 === pin && pinInstalled) {
|
|
11423
|
+
return {
|
|
11424
|
+
checked: true,
|
|
11425
|
+
updated: false,
|
|
11426
|
+
reason: `runtime is pinned to ${pin}`,
|
|
11427
|
+
activeVersion: activeVersion2,
|
|
11428
|
+
latestVersion: pin
|
|
11429
|
+
};
|
|
11430
|
+
}
|
|
11431
|
+
const installed3 = await install({
|
|
11432
|
+
version: pin,
|
|
11433
|
+
channel,
|
|
11434
|
+
cdnOrigin,
|
|
11435
|
+
setActive: false
|
|
11436
|
+
});
|
|
11437
|
+
return {
|
|
11438
|
+
checked: true,
|
|
11439
|
+
updated: true,
|
|
11440
|
+
reason: `runtime is pinned to ${pin}`,
|
|
11441
|
+
activeVersion: pin,
|
|
11442
|
+
latestVersion: pin,
|
|
11443
|
+
install: installed3
|
|
11444
|
+
};
|
|
11370
11445
|
}
|
|
11371
|
-
|
|
11372
|
-
|
|
11373
|
-
|
|
11374
|
-
import_fs2.default.rmSync(tmpDir, { recursive: true, force: true });
|
|
11375
|
-
throw err;
|
|
11376
|
-
}
|
|
11377
|
-
if (setActive) writeActiveRuntime(version);
|
|
11378
|
-
return {
|
|
11379
|
-
version,
|
|
11380
|
-
channel,
|
|
11381
|
-
cdnOrigin,
|
|
11382
|
-
runtimeDir: destDir,
|
|
11383
|
-
installed: true,
|
|
11384
|
-
activated: setActive,
|
|
11385
|
-
manifest
|
|
11386
|
-
};
|
|
11387
|
-
}
|
|
11388
|
-
async function updateRuntimeToLatest(opts = {}) {
|
|
11389
|
-
ensureSootsimHome();
|
|
11390
|
-
const cdnOrigin = resolveRuntimeCdnOrigin(opts.cdnOrigin);
|
|
11391
|
-
const channel = resolveRuntimeChannel(opts.channel);
|
|
11392
|
-
const pin = resolveRuntimePin();
|
|
11393
|
-
if (pin) {
|
|
11394
|
-
const activeVersion2 = readActiveRuntime();
|
|
11395
|
-
const pinInstalled = import_fs2.default.existsSync(import_path2.default.join(runtimeDir(pin), "index.html"));
|
|
11396
|
-
if (activeVersion2 === pin && pinInstalled) {
|
|
11446
|
+
const manifest = await fetchManifest(cdnOrigin);
|
|
11447
|
+
const latestVersion = manifest.channels[channel]?.latest;
|
|
11448
|
+
if (!latestVersion) {
|
|
11397
11449
|
return {
|
|
11398
11450
|
checked: true,
|
|
11399
11451
|
updated: false,
|
|
11400
|
-
reason: `
|
|
11401
|
-
activeVersion:
|
|
11402
|
-
|
|
11452
|
+
reason: `channel '${channel}' has no latest runtime`,
|
|
11453
|
+
activeVersion: product.readActiveRuntime()
|
|
11454
|
+
};
|
|
11455
|
+
}
|
|
11456
|
+
const entry = manifest.versions[latestVersion];
|
|
11457
|
+
if (!entry) {
|
|
11458
|
+
return {
|
|
11459
|
+
checked: true,
|
|
11460
|
+
updated: false,
|
|
11461
|
+
reason: `manifest is missing version ${latestVersion}`,
|
|
11462
|
+
activeVersion: product.readActiveRuntime(),
|
|
11463
|
+
latestVersion
|
|
11464
|
+
};
|
|
11465
|
+
}
|
|
11466
|
+
const activeVersion = product.readActiveRuntime();
|
|
11467
|
+
const activeDir = activeVersion ? product.runtimeDir(activeVersion) : null;
|
|
11468
|
+
const activeInstalled = activeDir ? import_node_fs4.default.existsSync(import_node_path3.default.join(activeDir, product.installedMarker)) : false;
|
|
11469
|
+
const shouldInstall = !activeVersion || !activeInstalled || compareSemver(latestVersion, activeVersion) > 0;
|
|
11470
|
+
if (!shouldInstall) {
|
|
11471
|
+
return {
|
|
11472
|
+
checked: true,
|
|
11473
|
+
updated: false,
|
|
11474
|
+
reason: "active runtime is current",
|
|
11475
|
+
activeVersion,
|
|
11476
|
+
latestVersion
|
|
11403
11477
|
};
|
|
11404
11478
|
}
|
|
11405
|
-
const
|
|
11406
|
-
version:
|
|
11479
|
+
const installed2 = await install({
|
|
11480
|
+
version: latestVersion,
|
|
11407
11481
|
channel,
|
|
11408
11482
|
cdnOrigin,
|
|
11409
11483
|
setActive: false
|
|
@@ -11411,57 +11485,40 @@ async function updateRuntimeToLatest(opts = {}) {
|
|
|
11411
11485
|
return {
|
|
11412
11486
|
checked: true,
|
|
11413
11487
|
updated: true,
|
|
11414
|
-
|
|
11415
|
-
|
|
11416
|
-
|
|
11417
|
-
install: install2
|
|
11418
|
-
};
|
|
11419
|
-
}
|
|
11420
|
-
const manifest = await fetchRuntimeManifest(cdnOrigin);
|
|
11421
|
-
const latestVersion = manifest.channels[channel]?.latest;
|
|
11422
|
-
if (!latestVersion) {
|
|
11423
|
-
return {
|
|
11424
|
-
checked: true,
|
|
11425
|
-
updated: false,
|
|
11426
|
-
reason: `channel '${channel}' has no latest runtime`,
|
|
11427
|
-
activeVersion: readActiveRuntime()
|
|
11488
|
+
activeVersion: latestVersion,
|
|
11489
|
+
latestVersion,
|
|
11490
|
+
install: installed2
|
|
11428
11491
|
};
|
|
11429
11492
|
}
|
|
11430
|
-
|
|
11431
|
-
|
|
11432
|
-
|
|
11433
|
-
|
|
11434
|
-
|
|
11435
|
-
|
|
11436
|
-
|
|
11437
|
-
|
|
11438
|
-
|
|
11439
|
-
|
|
11440
|
-
|
|
11441
|
-
|
|
11442
|
-
|
|
11443
|
-
|
|
11444
|
-
|
|
11445
|
-
return {
|
|
11446
|
-
checked: true,
|
|
11447
|
-
updated: false,
|
|
11448
|
-
reason: "active runtime is current",
|
|
11449
|
-
activeVersion,
|
|
11450
|
-
latestVersion
|
|
11451
|
-
};
|
|
11493
|
+
async function checkUpToDate(opts = {}) {
|
|
11494
|
+
const active = product.readActiveRuntime();
|
|
11495
|
+
const pinned = resolvePin();
|
|
11496
|
+
if (pinned) {
|
|
11497
|
+
return { active, latest: pinned, pinned, outdated: active !== pinned };
|
|
11498
|
+
}
|
|
11499
|
+
try {
|
|
11500
|
+
const manifest = await fetchManifest(resolveCdnOrigin(opts.cdnOrigin));
|
|
11501
|
+
const channel = resolveChannel(opts.channel);
|
|
11502
|
+
const latest = manifest.channels[channel]?.latest ?? null;
|
|
11503
|
+
const outdated = !!(latest && (!active || compareSemver(latest, active) > 0));
|
|
11504
|
+
return { active, latest, pinned: null, outdated };
|
|
11505
|
+
} catch {
|
|
11506
|
+
return { active, latest: null, pinned: null, outdated: false };
|
|
11507
|
+
}
|
|
11452
11508
|
}
|
|
11453
|
-
const install = await installRuntime({
|
|
11454
|
-
version: latestVersion,
|
|
11455
|
-
channel,
|
|
11456
|
-
cdnOrigin,
|
|
11457
|
-
setActive: false
|
|
11458
|
-
});
|
|
11459
11509
|
return {
|
|
11460
|
-
|
|
11461
|
-
|
|
11462
|
-
|
|
11463
|
-
|
|
11464
|
-
|
|
11510
|
+
product,
|
|
11511
|
+
resolveCdnOrigin,
|
|
11512
|
+
resolveChannel,
|
|
11513
|
+
resolvePin,
|
|
11514
|
+
manifestUrl,
|
|
11515
|
+
tarballUrl,
|
|
11516
|
+
fetchManifest,
|
|
11517
|
+
resolveVersion,
|
|
11518
|
+
install,
|
|
11519
|
+
updateToLatest,
|
|
11520
|
+
checkUpToDate,
|
|
11521
|
+
listInstalled: () => listInstalledRuntimes(product)
|
|
11465
11522
|
};
|
|
11466
11523
|
}
|
|
11467
11524
|
async function downloadToFile(url, destPath) {
|
|
@@ -11469,17 +11526,17 @@ async function downloadToFile(url, destPath) {
|
|
|
11469
11526
|
if (!res.ok || !res.body) {
|
|
11470
11527
|
throw new Error(`download failed: ${res.status} ${res.statusText} (${url})`);
|
|
11471
11528
|
}
|
|
11472
|
-
|
|
11529
|
+
import_node_fs4.default.mkdirSync(import_node_path3.default.dirname(destPath), { recursive: true });
|
|
11473
11530
|
const tmp = `${destPath}.partial`;
|
|
11474
11531
|
try {
|
|
11475
11532
|
await (0, import_promises.pipeline)(
|
|
11476
|
-
|
|
11477
|
-
|
|
11533
|
+
import_node_stream.Readable.fromWeb(res.body),
|
|
11534
|
+
import_node_fs4.default.createWriteStream(tmp)
|
|
11478
11535
|
);
|
|
11479
|
-
|
|
11536
|
+
import_node_fs4.default.renameSync(tmp, destPath);
|
|
11480
11537
|
} catch (err) {
|
|
11481
11538
|
try {
|
|
11482
|
-
|
|
11539
|
+
import_node_fs4.default.unlinkSync(tmp);
|
|
11483
11540
|
} catch {
|
|
11484
11541
|
}
|
|
11485
11542
|
throw err;
|
|
@@ -11487,8 +11544,8 @@ async function downloadToFile(url, destPath) {
|
|
|
11487
11544
|
}
|
|
11488
11545
|
function sha256File(filePath) {
|
|
11489
11546
|
return new Promise((resolve5, reject) => {
|
|
11490
|
-
const hash =
|
|
11491
|
-
const stream =
|
|
11547
|
+
const hash = import_node_crypto.default.createHash("sha256");
|
|
11548
|
+
const stream = import_node_fs4.default.createReadStream(filePath);
|
|
11492
11549
|
stream.on("data", (chunk) => hash.update(chunk));
|
|
11493
11550
|
stream.on("error", reject);
|
|
11494
11551
|
stream.on("end", () => resolve5(hash.digest("hex")));
|
|
@@ -11496,7 +11553,7 @@ function sha256File(filePath) {
|
|
|
11496
11553
|
}
|
|
11497
11554
|
function extractTarball(tarPath, destDir) {
|
|
11498
11555
|
return new Promise((resolve5, reject) => {
|
|
11499
|
-
const child = (0,
|
|
11556
|
+
const child = (0, import_node_child_process2.spawn)("tar", ["-xzf", tarPath, "-C", destDir], {
|
|
11500
11557
|
stdio: ["ignore", "inherit", "inherit"]
|
|
11501
11558
|
});
|
|
11502
11559
|
child.on("error", reject);
|
|
@@ -11506,21 +11563,52 @@ function extractTarball(tarPath, destDir) {
|
|
|
11506
11563
|
});
|
|
11507
11564
|
});
|
|
11508
11565
|
}
|
|
11509
|
-
var
|
|
11566
|
+
var import_node_child_process2, import_node_crypto, import_node_fs4, import_node_path3, import_node_stream, import_promises;
|
|
11567
|
+
var init_src = __esm({
|
|
11568
|
+
"../contrast-runtime-delivery/src/index.ts"() {
|
|
11569
|
+
"use strict";
|
|
11570
|
+
import_node_child_process2 = require("node:child_process");
|
|
11571
|
+
import_node_crypto = __toESM(require("node:crypto"), 1);
|
|
11572
|
+
import_node_fs4 = __toESM(require("node:fs"), 1);
|
|
11573
|
+
import_node_path3 = __toESM(require("node:path"), 1);
|
|
11574
|
+
import_node_stream = require("node:stream");
|
|
11575
|
+
import_promises = require("node:stream/promises");
|
|
11576
|
+
init_product();
|
|
11577
|
+
init_product();
|
|
11578
|
+
}
|
|
11579
|
+
});
|
|
11580
|
+
|
|
11581
|
+
// src/runtime-delivery.ts
|
|
11582
|
+
var DEFAULT_RUNTIME_CDN_ORIGIN, SOOTSIM_RUNTIME_PRODUCT, sootsimRuntime;
|
|
11510
11583
|
var init_runtime_delivery = __esm({
|
|
11511
11584
|
"src/runtime-delivery.ts"() {
|
|
11512
11585
|
"use strict";
|
|
11513
|
-
|
|
11514
|
-
import_crypto = __toESM(require("crypto"), 1);
|
|
11515
|
-
import_fs2 = __toESM(require("fs"), 1);
|
|
11516
|
-
import_path2 = __toESM(require("path"), 1);
|
|
11517
|
-
import_stream = require("stream");
|
|
11518
|
-
import_promises = require("stream/promises");
|
|
11586
|
+
init_src();
|
|
11519
11587
|
init_home_paths();
|
|
11520
11588
|
DEFAULT_RUNTIME_CDN_ORIGIN = "https://contrast.dev";
|
|
11521
|
-
|
|
11522
|
-
|
|
11523
|
-
|
|
11589
|
+
SOOTSIM_RUNTIME_PRODUCT = {
|
|
11590
|
+
id: "sootsim",
|
|
11591
|
+
defaultCdnOrigin: DEFAULT_RUNTIME_CDN_ORIGIN,
|
|
11592
|
+
manifestPath: "/runtimes/manifest.json",
|
|
11593
|
+
tarballPath: (version) => `/runtimes/sootsim-runtime-${version}.tar.gz`,
|
|
11594
|
+
// the engine runtime is a static SPA: shell at the root, engine/ and
|
|
11595
|
+
// engine-tenant/ beneath it. index.html is what the daemon and the
|
|
11596
|
+
// vite/metro plugins serve, so its absence means the tarball is not one.
|
|
11597
|
+
installedMarker: "index.html",
|
|
11598
|
+
env: {
|
|
11599
|
+
cdnOrigin: "SOOTSIM_CDN_ORIGIN",
|
|
11600
|
+
channel: "SOOTSIM_RUNTIME_CHANNEL",
|
|
11601
|
+
pin: "SOOTSIM_RUNTIME_VERSION"
|
|
11602
|
+
},
|
|
11603
|
+
ensureHome: ensureSootsimHome,
|
|
11604
|
+
configFile: configFilePath,
|
|
11605
|
+
runtimesDir,
|
|
11606
|
+
runtimeDir,
|
|
11607
|
+
cacheDir,
|
|
11608
|
+
readActiveRuntime,
|
|
11609
|
+
writeActiveRuntime
|
|
11610
|
+
};
|
|
11611
|
+
sootsimRuntime = createRuntimeDelivery(SOOTSIM_RUNTIME_PRODUCT);
|
|
11524
11612
|
}
|
|
11525
11613
|
});
|
|
11526
11614
|
|
|
@@ -11585,7 +11673,7 @@ function getUserDataDir() {
|
|
|
11585
11673
|
return userDataDir();
|
|
11586
11674
|
}
|
|
11587
11675
|
function storeFile() {
|
|
11588
|
-
return
|
|
11676
|
+
return import_node_path4.default.join(userDataDir(), "attached-projects.json");
|
|
11589
11677
|
}
|
|
11590
11678
|
function cloneEmpty() {
|
|
11591
11679
|
return {
|
|
@@ -11599,7 +11687,7 @@ function loadStore() {
|
|
|
11599
11687
|
const file = storeFile();
|
|
11600
11688
|
let raw;
|
|
11601
11689
|
try {
|
|
11602
|
-
raw =
|
|
11690
|
+
raw = import_node_fs5.default.readFileSync(file, "utf8");
|
|
11603
11691
|
} catch (err) {
|
|
11604
11692
|
if (err.code === "ENOENT") return cloneEmpty();
|
|
11605
11693
|
throw err;
|
|
@@ -11616,7 +11704,7 @@ function loadStore() {
|
|
|
11616
11704
|
} catch (err) {
|
|
11617
11705
|
const quarantine = `${file}.corrupt-${Date.now()}`;
|
|
11618
11706
|
try {
|
|
11619
|
-
|
|
11707
|
+
import_node_fs5.default.renameSync(file, quarantine);
|
|
11620
11708
|
console.warn(
|
|
11621
11709
|
`[sootsim] attached-projects.json was unparseable; quarantined to ${quarantine}. original error: ${err.message}`
|
|
11622
11710
|
);
|
|
@@ -11627,16 +11715,16 @@ function loadStore() {
|
|
|
11627
11715
|
}
|
|
11628
11716
|
function writeStore(store) {
|
|
11629
11717
|
const file = storeFile();
|
|
11630
|
-
|
|
11718
|
+
import_node_fs5.default.mkdirSync(import_node_path4.default.dirname(file), { recursive: true });
|
|
11631
11719
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
|
|
11632
|
-
const fd =
|
|
11720
|
+
const fd = import_node_fs5.default.openSync(tmp, "w", 384);
|
|
11633
11721
|
try {
|
|
11634
|
-
|
|
11635
|
-
|
|
11722
|
+
import_node_fs5.default.writeFileSync(fd, JSON.stringify(store, null, 2));
|
|
11723
|
+
import_node_fs5.default.fsyncSync(fd);
|
|
11636
11724
|
} finally {
|
|
11637
|
-
|
|
11725
|
+
import_node_fs5.default.closeSync(fd);
|
|
11638
11726
|
}
|
|
11639
|
-
|
|
11727
|
+
import_node_fs5.default.renameSync(tmp, file);
|
|
11640
11728
|
}
|
|
11641
11729
|
function mutateStore(fn) {
|
|
11642
11730
|
const store = loadStore();
|
|
@@ -11645,13 +11733,13 @@ function mutateStore(fn) {
|
|
|
11645
11733
|
return store;
|
|
11646
11734
|
}
|
|
11647
11735
|
function projectIdForCwd(cwd) {
|
|
11648
|
-
return (0,
|
|
11736
|
+
return (0, import_node_crypto2.createHash)("sha256").update(import_node_path4.default.resolve(cwd)).digest("hex").slice(0, 16);
|
|
11649
11737
|
}
|
|
11650
11738
|
function newSessionId() {
|
|
11651
|
-
return `s_${(0,
|
|
11739
|
+
return `s_${(0, import_node_crypto2.randomBytes)(10).toString("hex")}`;
|
|
11652
11740
|
}
|
|
11653
11741
|
function upsertProject(input) {
|
|
11654
|
-
const cwd =
|
|
11742
|
+
const cwd = import_node_path4.default.resolve(input.cwd);
|
|
11655
11743
|
const id = projectIdForCwd(cwd);
|
|
11656
11744
|
let result;
|
|
11657
11745
|
mutateStore((store) => {
|
|
@@ -11677,7 +11765,7 @@ function upsertProject(input) {
|
|
|
11677
11765
|
const now = Date.now();
|
|
11678
11766
|
const created = {
|
|
11679
11767
|
id,
|
|
11680
|
-
name: input.name ??
|
|
11768
|
+
name: input.name ?? import_node_path4.default.basename(cwd),
|
|
11681
11769
|
cwd,
|
|
11682
11770
|
repoRoot: input.repoRoot,
|
|
11683
11771
|
sourceRoots: input.sourceRoots ?? [cwd],
|
|
@@ -11806,8 +11894,8 @@ async function seedFromDemoAppRegistry() {
|
|
|
11806
11894
|
if (apps.length === 0) return;
|
|
11807
11895
|
mutateStore((store) => {
|
|
11808
11896
|
for (const app of apps) {
|
|
11809
|
-
if (!
|
|
11810
|
-
const cwd =
|
|
11897
|
+
if (!import_node_fs5.default.existsSync(app.dir)) continue;
|
|
11898
|
+
const cwd = import_node_path4.default.resolve(app.dir);
|
|
11811
11899
|
const id = projectIdForCwd(cwd);
|
|
11812
11900
|
if (store.attachedProjects.some((p) => p.id === id)) continue;
|
|
11813
11901
|
const now = Date.now();
|
|
@@ -11828,13 +11916,13 @@ async function seedFromDemoAppRegistry() {
|
|
|
11828
11916
|
}
|
|
11829
11917
|
});
|
|
11830
11918
|
}
|
|
11831
|
-
var
|
|
11919
|
+
var import_node_crypto2, import_node_fs5, import_node_path4, overrideDir, COST_HISTORY_MAX_AGE_MS;
|
|
11832
11920
|
var init_attached_projects = __esm({
|
|
11833
11921
|
"src/attached-projects.ts"() {
|
|
11834
11922
|
"use strict";
|
|
11835
|
-
|
|
11836
|
-
|
|
11837
|
-
|
|
11923
|
+
import_node_crypto2 = require("node:crypto");
|
|
11924
|
+
import_node_fs5 = __toESM(require("node:fs"), 1);
|
|
11925
|
+
import_node_path4 = __toESM(require("node:path"), 1);
|
|
11838
11926
|
init_home_paths();
|
|
11839
11927
|
overrideDir = null;
|
|
11840
11928
|
COST_HISTORY_MAX_AGE_MS = 14 * 24 * 60 * 60 * 1e3;
|
|
@@ -11843,16 +11931,16 @@ var init_attached_projects = __esm({
|
|
|
11843
11931
|
|
|
11844
11932
|
// src/agent-sessions.ts
|
|
11845
11933
|
function sessionDir(sessionId) {
|
|
11846
|
-
return
|
|
11934
|
+
return import_node_path5.default.join(getUserDataDir(), "sessions", sessionId);
|
|
11847
11935
|
}
|
|
11848
11936
|
function promptFifoPath(sessionId) {
|
|
11849
|
-
return
|
|
11937
|
+
return import_node_path5.default.join(sessionDir(sessionId), "prompt.in");
|
|
11850
11938
|
}
|
|
11851
11939
|
function eventsFifoPath(sessionId) {
|
|
11852
|
-
return
|
|
11940
|
+
return import_node_path5.default.join(sessionDir(sessionId), "events.out");
|
|
11853
11941
|
}
|
|
11854
11942
|
function transcriptPath(sessionId) {
|
|
11855
|
-
return
|
|
11943
|
+
return import_node_path5.default.join(getUserDataDir(), "transcripts", `${sessionId}.log`);
|
|
11856
11944
|
}
|
|
11857
11945
|
function pidIsAlive(pid, sessionId) {
|
|
11858
11946
|
if (!pid) return false;
|
|
@@ -11862,7 +11950,7 @@ function pidIsAlive(pid, sessionId) {
|
|
|
11862
11950
|
return false;
|
|
11863
11951
|
}
|
|
11864
11952
|
if (sessionId) {
|
|
11865
|
-
if (!
|
|
11953
|
+
if (!import_node_fs6.default.existsSync(sessionDir(sessionId))) return false;
|
|
11866
11954
|
}
|
|
11867
11955
|
return true;
|
|
11868
11956
|
}
|
|
@@ -11874,11 +11962,11 @@ function resolveSootsimInvocation() {
|
|
|
11874
11962
|
const resourcesPath = process.resourcesPath;
|
|
11875
11963
|
if (resourcesPath) {
|
|
11876
11964
|
const candidates = [
|
|
11877
|
-
|
|
11878
|
-
|
|
11965
|
+
import_node_path5.default.join(resourcesPath, "bin", "sootsim"),
|
|
11966
|
+
import_node_path5.default.join(resourcesPath, "bin", `sootsim-${process.platform}-${process.arch}`)
|
|
11879
11967
|
];
|
|
11880
11968
|
for (const c of candidates) {
|
|
11881
|
-
if (
|
|
11969
|
+
if (import_node_fs6.default.existsSync(c)) return { cmd: c, prefixArgs: [] };
|
|
11882
11970
|
}
|
|
11883
11971
|
}
|
|
11884
11972
|
}
|
|
@@ -11901,15 +11989,15 @@ function tryWorkspaceSootsim() {
|
|
|
11901
11989
|
const sootsimDir = resolveSootsimPackageDir();
|
|
11902
11990
|
if (!sootsimDir) return null;
|
|
11903
11991
|
const binaryName = `sootsim-${process.platform}-${process.arch}`;
|
|
11904
|
-
const distBinary =
|
|
11905
|
-
if (
|
|
11906
|
-
const distBin =
|
|
11907
|
-
if (
|
|
11992
|
+
const distBinary = import_node_path5.default.join(sootsimDir, "dist-bin", binaryName);
|
|
11993
|
+
if (import_node_fs6.default.existsSync(distBinary)) return { cmd: distBinary, prefixArgs: [] };
|
|
11994
|
+
const distBin = import_node_path5.default.join(sootsimDir, "dist-cli", "bin.js");
|
|
11995
|
+
if (import_node_fs6.default.existsSync(distBin)) {
|
|
11908
11996
|
try {
|
|
11909
|
-
const src =
|
|
11910
|
-
if (
|
|
11911
|
-
const srcMtime =
|
|
11912
|
-
const buildMtime =
|
|
11997
|
+
const src = import_node_path5.default.join(sootsimDir, "cli", "commands", "agent-wrapper.ts");
|
|
11998
|
+
if (import_node_fs6.default.existsSync(src)) {
|
|
11999
|
+
const srcMtime = import_node_fs6.default.statSync(src).mtimeMs;
|
|
12000
|
+
const buildMtime = import_node_fs6.default.statSync(distBin).mtimeMs;
|
|
11913
12001
|
if (buildMtime < srcMtime) {
|
|
11914
12002
|
console.warn(
|
|
11915
12003
|
`[sootsim] dist-cli/bin.js is older than agent-wrapper.ts \u2014 rebuild with \`bun run --cwd packages/sootsim build:cli\`.`
|
|
@@ -11928,22 +12016,22 @@ function tryWorkspaceSootsim() {
|
|
|
11928
12016
|
function resolveSootsimPackageDir() {
|
|
11929
12017
|
try {
|
|
11930
12018
|
const resolved = require.resolve("sootsim/package.json");
|
|
11931
|
-
return
|
|
12019
|
+
return import_node_path5.default.dirname(resolved);
|
|
11932
12020
|
} catch {
|
|
11933
12021
|
}
|
|
11934
12022
|
const here = fileFromImportMeta();
|
|
11935
12023
|
if (!here) return null;
|
|
11936
|
-
let cur =
|
|
12024
|
+
let cur = import_node_path5.default.dirname(here);
|
|
11937
12025
|
for (let i = 0; i < 8; i++) {
|
|
11938
|
-
const pkg =
|
|
12026
|
+
const pkg = import_node_path5.default.join(cur, "package.json");
|
|
11939
12027
|
try {
|
|
11940
|
-
if (
|
|
11941
|
-
const parsed = JSON.parse(
|
|
12028
|
+
if (import_node_fs6.default.existsSync(pkg)) {
|
|
12029
|
+
const parsed = JSON.parse(import_node_fs6.default.readFileSync(pkg, "utf8"));
|
|
11942
12030
|
if (parsed.name === "sootsim") return cur;
|
|
11943
12031
|
}
|
|
11944
12032
|
} catch {
|
|
11945
12033
|
}
|
|
11946
|
-
const parent =
|
|
12034
|
+
const parent = import_node_path5.default.dirname(cur);
|
|
11947
12035
|
if (parent === cur) break;
|
|
11948
12036
|
cur = parent;
|
|
11949
12037
|
}
|
|
@@ -11959,28 +12047,28 @@ function fileFromImportMeta() {
|
|
|
11959
12047
|
}
|
|
11960
12048
|
}
|
|
11961
12049
|
async function withStartLock(projectId, provider, fn) {
|
|
11962
|
-
const lockDir =
|
|
11963
|
-
|
|
12050
|
+
const lockDir = import_node_path5.default.join(getUserDataDir(), "locks");
|
|
12051
|
+
import_node_fs6.default.mkdirSync(lockDir, { recursive: true });
|
|
11964
12052
|
try {
|
|
11965
|
-
|
|
12053
|
+
import_node_fs6.default.chmodSync(lockDir, 448);
|
|
11966
12054
|
} catch {
|
|
11967
12055
|
}
|
|
11968
|
-
const lockPath =
|
|
12056
|
+
const lockPath = import_node_path5.default.join(lockDir, `start-${projectId}-${provider}.lock`);
|
|
11969
12057
|
const deadline = Date.now() + 4e3;
|
|
11970
12058
|
let fd = null;
|
|
11971
12059
|
while (fd === null) {
|
|
11972
12060
|
try {
|
|
11973
|
-
fd =
|
|
12061
|
+
fd = import_node_fs6.default.openSync(
|
|
11974
12062
|
lockPath,
|
|
11975
|
-
|
|
12063
|
+
import_node_fs6.constants.O_WRONLY | import_node_fs6.constants.O_CREAT | import_node_fs6.constants.O_EXCL,
|
|
11976
12064
|
384
|
|
11977
12065
|
);
|
|
11978
12066
|
} catch (err) {
|
|
11979
12067
|
if (err.code !== "EEXIST") throw err;
|
|
11980
12068
|
try {
|
|
11981
|
-
const stale = Number(
|
|
12069
|
+
const stale = Number(import_node_fs6.default.readFileSync(lockPath, "utf8").trim());
|
|
11982
12070
|
if (stale && !isProcessAlive(stale)) {
|
|
11983
|
-
|
|
12071
|
+
import_node_fs6.default.unlinkSync(lockPath);
|
|
11984
12072
|
continue;
|
|
11985
12073
|
}
|
|
11986
12074
|
} catch {
|
|
@@ -11994,15 +12082,15 @@ async function withStartLock(projectId, provider, fn) {
|
|
|
11994
12082
|
}
|
|
11995
12083
|
}
|
|
11996
12084
|
try {
|
|
11997
|
-
|
|
12085
|
+
import_node_fs6.default.writeFileSync(fd, String(process.pid));
|
|
11998
12086
|
return await fn();
|
|
11999
12087
|
} finally {
|
|
12000
12088
|
try {
|
|
12001
|
-
|
|
12089
|
+
import_node_fs6.default.closeSync(fd);
|
|
12002
12090
|
} catch {
|
|
12003
12091
|
}
|
|
12004
12092
|
try {
|
|
12005
|
-
|
|
12093
|
+
import_node_fs6.default.unlinkSync(lockPath);
|
|
12006
12094
|
} catch {
|
|
12007
12095
|
}
|
|
12008
12096
|
}
|
|
@@ -12016,28 +12104,28 @@ function isProcessAlive(pid) {
|
|
|
12016
12104
|
}
|
|
12017
12105
|
}
|
|
12018
12106
|
function mkfifoSync(p) {
|
|
12019
|
-
const parent =
|
|
12020
|
-
|
|
12107
|
+
const parent = import_node_path5.default.dirname(p);
|
|
12108
|
+
import_node_fs6.default.mkdirSync(parent, { recursive: true });
|
|
12021
12109
|
try {
|
|
12022
|
-
|
|
12110
|
+
import_node_fs6.default.chmodSync(parent, 448);
|
|
12023
12111
|
} catch {
|
|
12024
12112
|
}
|
|
12025
|
-
if (
|
|
12113
|
+
if (import_node_fs6.default.existsSync(p)) {
|
|
12026
12114
|
try {
|
|
12027
|
-
const stat =
|
|
12115
|
+
const stat = import_node_fs6.default.statSync(p);
|
|
12028
12116
|
if (stat.isFIFO()) {
|
|
12029
12117
|
try {
|
|
12030
|
-
|
|
12118
|
+
import_node_fs6.default.chmodSync(p, 384);
|
|
12031
12119
|
} catch {
|
|
12032
12120
|
}
|
|
12033
12121
|
return;
|
|
12034
12122
|
}
|
|
12035
|
-
|
|
12123
|
+
import_node_fs6.default.unlinkSync(p);
|
|
12036
12124
|
} catch {
|
|
12037
|
-
|
|
12125
|
+
import_node_fs6.default.unlinkSync(p);
|
|
12038
12126
|
}
|
|
12039
12127
|
}
|
|
12040
|
-
const result = (0,
|
|
12128
|
+
const result = (0, import_node_child_process3.spawnSync)("mkfifo", ["-m", "600", p]);
|
|
12041
12129
|
if (result.status !== 0) {
|
|
12042
12130
|
throw new Error(
|
|
12043
12131
|
`mkfifo(${p}) failed: ${result.stderr?.toString().trim() || "unknown error"}`
|
|
@@ -12060,7 +12148,7 @@ async function startSession(opts) {
|
|
|
12060
12148
|
`session already running for project=${project.id} provider=${provider} (session ${existingLive.id}, pid ${existingLive.wrapperPid}). end it first with \`sootsim agent end <sessionId>\`.`
|
|
12061
12149
|
);
|
|
12062
12150
|
}
|
|
12063
|
-
const claudeSessionUuid = provider === "claude" ? (0,
|
|
12151
|
+
const claudeSessionUuid = provider === "claude" ? (0, import_node_crypto3.randomUUID)() : void 0;
|
|
12064
12152
|
const session = upsertSession({
|
|
12065
12153
|
projectId: project.id,
|
|
12066
12154
|
provider,
|
|
@@ -12074,10 +12162,10 @@ async function startSession(opts) {
|
|
|
12074
12162
|
const transcript = transcriptPath(session.id);
|
|
12075
12163
|
mkfifoSync(promptIn);
|
|
12076
12164
|
mkfifoSync(eventsOut);
|
|
12077
|
-
const transcriptDir =
|
|
12078
|
-
|
|
12165
|
+
const transcriptDir = import_node_path5.default.dirname(transcript);
|
|
12166
|
+
import_node_fs6.default.mkdirSync(transcriptDir, { recursive: true });
|
|
12079
12167
|
try {
|
|
12080
|
-
|
|
12168
|
+
import_node_fs6.default.chmodSync(transcriptDir, 448);
|
|
12081
12169
|
} catch {
|
|
12082
12170
|
}
|
|
12083
12171
|
const { cmd, prefixArgs } = resolveSootsimInvocation();
|
|
@@ -12105,7 +12193,7 @@ async function startSession(opts) {
|
|
|
12105
12193
|
if (claudeSessionUuid) {
|
|
12106
12194
|
wrapperArgs.push("--claude-session-uuid", claudeSessionUuid);
|
|
12107
12195
|
}
|
|
12108
|
-
const child = (0,
|
|
12196
|
+
const child = (0, import_node_child_process3.spawn)(cmd, wrapperArgs, {
|
|
12109
12197
|
detached: true,
|
|
12110
12198
|
stdio: "ignore",
|
|
12111
12199
|
env: {
|
|
@@ -12128,7 +12216,7 @@ async function startSession(opts) {
|
|
|
12128
12216
|
}
|
|
12129
12217
|
}
|
|
12130
12218
|
try {
|
|
12131
|
-
|
|
12219
|
+
import_node_fs6.default.rmSync(sessionDir(session.id), { recursive: true, force: true });
|
|
12132
12220
|
} catch {
|
|
12133
12221
|
}
|
|
12134
12222
|
updateSessionStatus(session.id, { status: "ended" });
|
|
@@ -12156,18 +12244,18 @@ async function sendPrompt(sessionId, prompt) {
|
|
|
12156
12244
|
);
|
|
12157
12245
|
}
|
|
12158
12246
|
const fifo = promptFifoPath(sessionId);
|
|
12159
|
-
if (!
|
|
12247
|
+
if (!import_node_fs6.default.existsSync(fifo)) {
|
|
12160
12248
|
throw new AgentSessionError("NO_FIFO", `prompt FIFO missing: ${fifo}`);
|
|
12161
12249
|
}
|
|
12162
|
-
const fd =
|
|
12250
|
+
const fd = import_node_fs6.default.openSync(fifo, import_node_fs6.constants.O_WRONLY);
|
|
12163
12251
|
try {
|
|
12164
12252
|
const wireText = encodeAgentPromptEnvelope(prompt);
|
|
12165
12253
|
if (!wireText) {
|
|
12166
12254
|
throw new AgentSessionError("EMPTY_PROMPT", "prompt text is empty");
|
|
12167
12255
|
}
|
|
12168
|
-
|
|
12256
|
+
import_node_fs6.default.writeSync(fd, wireText + "\n");
|
|
12169
12257
|
} finally {
|
|
12170
|
-
|
|
12258
|
+
import_node_fs6.default.closeSync(fd);
|
|
12171
12259
|
}
|
|
12172
12260
|
updateSessionStatus(sessionId, {
|
|
12173
12261
|
lastPrompt: prompt.displayText ?? prompt.text,
|
|
@@ -12189,7 +12277,7 @@ async function endSession(sessionId) {
|
|
|
12189
12277
|
const base = getUserDataDir();
|
|
12190
12278
|
if (dir.startsWith(base)) {
|
|
12191
12279
|
try {
|
|
12192
|
-
|
|
12280
|
+
import_node_fs6.default.rmSync(dir, { recursive: true, force: true });
|
|
12193
12281
|
} catch {
|
|
12194
12282
|
}
|
|
12195
12283
|
}
|
|
@@ -12197,11 +12285,11 @@ async function endSession(sessionId) {
|
|
|
12197
12285
|
}
|
|
12198
12286
|
function subscribeEvents(sessionId, onEvent) {
|
|
12199
12287
|
const fifo = eventsFifoPath(sessionId);
|
|
12200
|
-
if (!
|
|
12288
|
+
if (!import_node_fs6.default.existsSync(fifo)) {
|
|
12201
12289
|
throw new AgentSessionError("NO_FIFO", `events FIFO missing: ${fifo}`);
|
|
12202
12290
|
}
|
|
12203
|
-
const fd =
|
|
12204
|
-
const stream =
|
|
12291
|
+
const fd = import_node_fs6.default.openSync(fifo, import_node_fs6.constants.O_RDWR);
|
|
12292
|
+
const stream = import_node_fs6.default.createReadStream("", { fd, autoClose: true });
|
|
12205
12293
|
const rl = import_node_readline.default.createInterface({ input: stream, crlfDelay: Infinity });
|
|
12206
12294
|
rl.on("line", (line) => {
|
|
12207
12295
|
const event = parseAgentEventLine(line);
|
|
@@ -12222,7 +12310,7 @@ function subscribeEvents(sessionId, onEvent) {
|
|
|
12222
12310
|
};
|
|
12223
12311
|
}
|
|
12224
12312
|
async function waitForFirstEvent(fifo, predicate, timeoutMs) {
|
|
12225
|
-
const fd =
|
|
12313
|
+
const fd = import_node_fs6.default.openSync(fifo, import_node_fs6.constants.O_RDWR | import_node_fs6.constants.O_NONBLOCK);
|
|
12226
12314
|
const buf = Buffer.alloc(8192);
|
|
12227
12315
|
let leftover = "";
|
|
12228
12316
|
const deadline = Date.now() + timeoutMs;
|
|
@@ -12230,7 +12318,7 @@ async function waitForFirstEvent(fifo, predicate, timeoutMs) {
|
|
|
12230
12318
|
while (Date.now() < deadline) {
|
|
12231
12319
|
let n = 0;
|
|
12232
12320
|
try {
|
|
12233
|
-
n =
|
|
12321
|
+
n = import_node_fs6.default.readSync(fd, buf, 0, buf.length, null);
|
|
12234
12322
|
} catch (err) {
|
|
12235
12323
|
if (err.code !== "EAGAIN") throw err;
|
|
12236
12324
|
n = 0;
|
|
@@ -12250,17 +12338,17 @@ async function waitForFirstEvent(fifo, predicate, timeoutMs) {
|
|
|
12250
12338
|
}
|
|
12251
12339
|
return null;
|
|
12252
12340
|
} finally {
|
|
12253
|
-
|
|
12341
|
+
import_node_fs6.default.closeSync(fd);
|
|
12254
12342
|
}
|
|
12255
12343
|
}
|
|
12256
|
-
var
|
|
12344
|
+
var import_node_child_process3, import_node_crypto3, import_node_fs6, import_node_path5, import_node_readline, AgentSessionError;
|
|
12257
12345
|
var init_agent_sessions = __esm({
|
|
12258
12346
|
"src/agent-sessions.ts"() {
|
|
12259
12347
|
"use strict";
|
|
12260
|
-
|
|
12261
|
-
|
|
12262
|
-
|
|
12263
|
-
|
|
12348
|
+
import_node_child_process3 = require("node:child_process");
|
|
12349
|
+
import_node_crypto3 = require("node:crypto");
|
|
12350
|
+
import_node_fs6 = __toESM(require("node:fs"), 1);
|
|
12351
|
+
import_node_path5 = __toESM(require("node:path"), 1);
|
|
12264
12352
|
import_node_readline = __toESM(require("node:readline"), 1);
|
|
12265
12353
|
init_agent_events();
|
|
12266
12354
|
init_agent_prompt();
|
|
@@ -12302,8 +12390,8 @@ function resolveAgentbusCommand(explicit) {
|
|
|
12302
12390
|
if (fromArg) return fromArg;
|
|
12303
12391
|
const fromEnv = process.env.AGENTBUS_COMMAND?.trim();
|
|
12304
12392
|
if (fromEnv) return fromEnv;
|
|
12305
|
-
const localBin =
|
|
12306
|
-
if (
|
|
12393
|
+
const localBin = import_node_path6.default.join(import_node_os2.default.homedir(), ".local", "bin", "agentbus");
|
|
12394
|
+
if (import_node_fs7.default.existsSync(localBin)) return localBin;
|
|
12307
12395
|
return "agentbus";
|
|
12308
12396
|
}
|
|
12309
12397
|
async function sendPromptToAgentbusSession(input) {
|
|
@@ -12318,7 +12406,7 @@ async function sendPromptToAgentbusSession(input) {
|
|
|
12318
12406
|
const command = resolveAgentbusCommand(input.command);
|
|
12319
12407
|
const timeoutMs = input.timeoutMs ?? 15e3;
|
|
12320
12408
|
await new Promise((resolve5, reject) => {
|
|
12321
|
-
const child = (0,
|
|
12409
|
+
const child = (0, import_node_child_process4.spawn)(command, ["send", sessionId, text], {
|
|
12322
12410
|
stdio: ["ignore", "ignore", "pipe"],
|
|
12323
12411
|
env: process.env
|
|
12324
12412
|
});
|
|
@@ -12353,14 +12441,14 @@ async function sendPromptToAgentbusSession(input) {
|
|
|
12353
12441
|
});
|
|
12354
12442
|
});
|
|
12355
12443
|
}
|
|
12356
|
-
var
|
|
12444
|
+
var import_node_child_process4, import_node_fs7, import_node_os2, import_node_path6;
|
|
12357
12445
|
var init_agentbus_prompt = __esm({
|
|
12358
12446
|
"src/agentbus-prompt.ts"() {
|
|
12359
12447
|
"use strict";
|
|
12360
|
-
|
|
12361
|
-
|
|
12448
|
+
import_node_child_process4 = require("node:child_process");
|
|
12449
|
+
import_node_fs7 = __toESM(require("node:fs"), 1);
|
|
12362
12450
|
import_node_os2 = __toESM(require("node:os"), 1);
|
|
12363
|
-
|
|
12451
|
+
import_node_path6 = __toESM(require("node:path"), 1);
|
|
12364
12452
|
init_agent_identity();
|
|
12365
12453
|
init_agent_identity();
|
|
12366
12454
|
}
|
|
@@ -12379,12 +12467,12 @@ function mapFrameworkToProjectFramework(fw) {
|
|
|
12379
12467
|
if (fw === "one" || fw === "vxrn") return "one";
|
|
12380
12468
|
return "unknown";
|
|
12381
12469
|
}
|
|
12382
|
-
var
|
|
12470
|
+
var import_node_fs8, import_node_path7, WS_OPEN, AgentHost;
|
|
12383
12471
|
var init_agent_host = __esm({
|
|
12384
12472
|
"src/host/agent-host.ts"() {
|
|
12385
12473
|
"use strict";
|
|
12386
|
-
|
|
12387
|
-
|
|
12474
|
+
import_node_fs8 = __toESM(require("node:fs"), 1);
|
|
12475
|
+
import_node_path7 = __toESM(require("node:path"), 1);
|
|
12388
12476
|
init_dev_server_scanner();
|
|
12389
12477
|
init_agent_sessions();
|
|
12390
12478
|
init_agentbus_prompt();
|
|
@@ -12571,7 +12659,7 @@ var init_agent_host = __esm({
|
|
|
12571
12659
|
);
|
|
12572
12660
|
const project = upsertProject({
|
|
12573
12661
|
cwd: match.cwd,
|
|
12574
|
-
name: match.projectName ??
|
|
12662
|
+
name: match.projectName ?? import_node_path7.default.basename(match.cwd),
|
|
12575
12663
|
preferredProvider: input.provider ?? existing?.preferredProvider,
|
|
12576
12664
|
sourceRoots: existing?.sourceRoots ?? [match.cwd],
|
|
12577
12665
|
knownBundleUrls,
|
|
@@ -12582,18 +12670,18 @@ var init_agent_host = __esm({
|
|
|
12582
12670
|
}
|
|
12583
12671
|
getTranscript(sessionId) {
|
|
12584
12672
|
const p = transcriptPath(sessionId);
|
|
12585
|
-
if (!
|
|
12673
|
+
if (!import_node_fs8.default.existsSync(p)) {
|
|
12586
12674
|
return { error: "transcript not found", code: "NO_TRANSCRIPT" };
|
|
12587
12675
|
}
|
|
12588
|
-
return
|
|
12676
|
+
return import_node_fs8.default.readFileSync(p, "utf8");
|
|
12589
12677
|
}
|
|
12590
12678
|
getPaths() {
|
|
12591
12679
|
const dir = getUserDataDir();
|
|
12592
12680
|
return {
|
|
12593
12681
|
userDataDir: dir,
|
|
12594
|
-
storeFile:
|
|
12595
|
-
sessionsDir:
|
|
12596
|
-
transcriptsDir:
|
|
12682
|
+
storeFile: import_node_path7.default.join(dir, "attached-projects.json"),
|
|
12683
|
+
sessionsDir: import_node_path7.default.join(dir, "sessions"),
|
|
12684
|
+
transcriptsDir: import_node_path7.default.join(dir, "transcripts")
|
|
12597
12685
|
};
|
|
12598
12686
|
}
|
|
12599
12687
|
// --- subscription management ---
|
|
@@ -13193,19 +13281,19 @@ var init_fetch_proxy_handler = __esm({
|
|
|
13193
13281
|
|
|
13194
13282
|
// src/host/open-url.ts
|
|
13195
13283
|
function expandHome(candidate) {
|
|
13196
|
-
return candidate.startsWith("~/") ? (0,
|
|
13284
|
+
return candidate.startsWith("~/") ? (0, import_path2.join)((0, import_os.homedir)(), candidate.slice(2)) : candidate;
|
|
13197
13285
|
}
|
|
13198
13286
|
function firstExisting(candidates) {
|
|
13199
13287
|
for (const candidate of candidates) {
|
|
13200
13288
|
const expanded = expandHome(candidate);
|
|
13201
|
-
if ((0,
|
|
13289
|
+
if ((0, import_fs2.existsSync)(expanded)) return expanded;
|
|
13202
13290
|
}
|
|
13203
13291
|
return null;
|
|
13204
13292
|
}
|
|
13205
13293
|
function lookupExecutable(command, platform) {
|
|
13206
13294
|
try {
|
|
13207
13295
|
const tool = platform === "win32" ? "where" : "which";
|
|
13208
|
-
const out = (0,
|
|
13296
|
+
const out = (0, import_child_process2.execFileSync)(tool, [command], {
|
|
13209
13297
|
encoding: "utf8",
|
|
13210
13298
|
timeout: 1500,
|
|
13211
13299
|
stdio: ["ignore", "pipe", "ignore"]
|
|
@@ -13217,7 +13305,7 @@ function lookupExecutable(command, platform) {
|
|
|
13217
13305
|
}
|
|
13218
13306
|
function resolveChromiumBinary(platform = process.platform) {
|
|
13219
13307
|
const envCandidate = process.env.CHROME_PATH || process.env.CHROMIUM_PATH;
|
|
13220
|
-
if (envCandidate && (0,
|
|
13308
|
+
if (envCandidate && (0, import_fs2.existsSync)(envCandidate)) return envCandidate;
|
|
13221
13309
|
const direct = platform === "darwin" ? firstExisting(MAC_CHROMIUM_CANDIDATES) : platform === "win32" ? firstExisting(WINDOWS_CHROMIUM_CANDIDATES) : firstExisting(LINUX_CHROMIUM_CANDIDATES);
|
|
13222
13310
|
if (direct) return direct;
|
|
13223
13311
|
const commands = platform === "win32" ? WINDOWS_CHROMIUM_COMMANDS : UNIX_CHROMIUM_COMMANDS;
|
|
@@ -13274,7 +13362,7 @@ function buildChromiumUrlCommand(url, options = {}) {
|
|
|
13274
13362
|
}
|
|
13275
13363
|
async function spawnLaunch(command, args, detached) {
|
|
13276
13364
|
return new Promise((resolve5, reject) => {
|
|
13277
|
-
const child = (0,
|
|
13365
|
+
const child = (0, import_child_process2.spawn)(command, args, {
|
|
13278
13366
|
detached,
|
|
13279
13367
|
stdio: "ignore"
|
|
13280
13368
|
});
|
|
@@ -13297,14 +13385,14 @@ async function launchUrl(url, options = {}) {
|
|
|
13297
13385
|
async function openUrl(url, options = {}) {
|
|
13298
13386
|
await launchUrl(url, options);
|
|
13299
13387
|
}
|
|
13300
|
-
var
|
|
13388
|
+
var import_child_process2, import_fs2, import_os, import_path2, MAC_CHROMIUM_CANDIDATES, LINUX_CHROMIUM_CANDIDATES, WINDOWS_CHROMIUM_CANDIDATES, UNIX_CHROMIUM_COMMANDS, WINDOWS_CHROMIUM_COMMANDS;
|
|
13301
13389
|
var init_open_url = __esm({
|
|
13302
13390
|
"src/host/open-url.ts"() {
|
|
13303
13391
|
"use strict";
|
|
13304
|
-
|
|
13305
|
-
|
|
13392
|
+
import_child_process2 = require("child_process");
|
|
13393
|
+
import_fs2 = require("fs");
|
|
13306
13394
|
import_os = require("os");
|
|
13307
|
-
|
|
13395
|
+
import_path2 = require("path");
|
|
13308
13396
|
MAC_CHROMIUM_CANDIDATES = [
|
|
13309
13397
|
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome",
|
|
13310
13398
|
"~/Applications/Google Chrome.app/Contents/MacOS/Google Chrome",
|
|
@@ -13566,14 +13654,14 @@ function unrefTimer(timer) {
|
|
|
13566
13654
|
timer.unref();
|
|
13567
13655
|
}
|
|
13568
13656
|
}
|
|
13569
|
-
var
|
|
13657
|
+
var import_child_process3, import_fs3, import_http3, import_path3, import_ws2, SOOTSIM_CROSS_ORIGIN_EMBEDDER_POLICY, 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;
|
|
13570
13658
|
var init_bridge_host = __esm({
|
|
13571
13659
|
"src/host/bridge-host.ts"() {
|
|
13572
13660
|
"use strict";
|
|
13573
|
-
|
|
13574
|
-
|
|
13661
|
+
import_child_process3 = require("child_process");
|
|
13662
|
+
import_fs3 = __toESM(require("fs"), 1);
|
|
13575
13663
|
import_http3 = require("http");
|
|
13576
|
-
|
|
13664
|
+
import_path3 = __toESM(require("path"), 1);
|
|
13577
13665
|
import_ws2 = require("ws");
|
|
13578
13666
|
init_dev_server_scanner();
|
|
13579
13667
|
init_bridge_constants();
|
|
@@ -13865,7 +13953,7 @@ var init_bridge_host = __esm({
|
|
|
13865
13953
|
return;
|
|
13866
13954
|
}
|
|
13867
13955
|
if (msg.type === "runtime:list") {
|
|
13868
|
-
const versions =
|
|
13956
|
+
const versions = sootsimRuntime.listInstalled();
|
|
13869
13957
|
const active = this.getActiveRuntime();
|
|
13870
13958
|
const reply = {
|
|
13871
13959
|
type: "runtime:list:ok",
|
|
@@ -13882,7 +13970,7 @@ var init_bridge_host = __esm({
|
|
|
13882
13970
|
}
|
|
13883
13971
|
if (msg.type === "runtime:use") {
|
|
13884
13972
|
const version = typeof msg.version === "string" ? msg.version : "";
|
|
13885
|
-
const installed2 =
|
|
13973
|
+
const installed2 = sootsimRuntime.listInstalled();
|
|
13886
13974
|
if (!installed2.includes(version)) {
|
|
13887
13975
|
try {
|
|
13888
13976
|
ws.send(
|
|
@@ -14411,7 +14499,7 @@ var init_bridge_host = __esm({
|
|
|
14411
14499
|
if (reason === "startup") {
|
|
14412
14500
|
process.stderr.write("sootsim: checking for runtime updates\u2026\n");
|
|
14413
14501
|
}
|
|
14414
|
-
const result = await
|
|
14502
|
+
const result = await sootsimRuntime.updateToLatest();
|
|
14415
14503
|
if (!result.updated || !result.latestVersion) {
|
|
14416
14504
|
if (reason === "startup") {
|
|
14417
14505
|
process.stderr.write(
|
|
@@ -14647,34 +14735,34 @@ var init_bridge_host = __esm({
|
|
|
14647
14735
|
return;
|
|
14648
14736
|
}
|
|
14649
14737
|
}
|
|
14650
|
-
const resolved =
|
|
14651
|
-
const baseWithSep = baseDir.endsWith(
|
|
14738
|
+
const resolved = import_path3.default.resolve(baseDir, "." + rel);
|
|
14739
|
+
const baseWithSep = baseDir.endsWith(import_path3.default.sep) ? baseDir : baseDir + import_path3.default.sep;
|
|
14652
14740
|
if (!resolved.startsWith(baseWithSep) && resolved !== baseDir) {
|
|
14653
14741
|
res.writeHead(403);
|
|
14654
14742
|
res.end("forbidden");
|
|
14655
14743
|
return;
|
|
14656
14744
|
}
|
|
14657
|
-
|
|
14745
|
+
import_fs3.default.realpath(resolved, (realErr, realResolved) => {
|
|
14658
14746
|
const servePath = realErr ? resolved : realResolved;
|
|
14659
|
-
const servePathWithSep = servePath.endsWith(
|
|
14747
|
+
const servePathWithSep = servePath.endsWith(import_path3.default.sep) ? servePath : servePath + import_path3.default.sep;
|
|
14660
14748
|
if (!realErr) {
|
|
14661
14749
|
const realBaseWithSep = (() => {
|
|
14662
14750
|
try {
|
|
14663
|
-
const rb =
|
|
14664
|
-
return rb.endsWith(
|
|
14751
|
+
const rb = import_fs3.default.realpathSync(baseDir);
|
|
14752
|
+
return rb.endsWith(import_path3.default.sep) ? rb : rb + import_path3.default.sep;
|
|
14665
14753
|
} catch {
|
|
14666
14754
|
return baseWithSep;
|
|
14667
14755
|
}
|
|
14668
14756
|
})();
|
|
14669
|
-
if (!servePathWithSep.startsWith(realBaseWithSep) && servePath +
|
|
14757
|
+
if (!servePathWithSep.startsWith(realBaseWithSep) && servePath + import_path3.default.sep !== realBaseWithSep) {
|
|
14670
14758
|
res.writeHead(403);
|
|
14671
14759
|
res.end("forbidden");
|
|
14672
14760
|
return;
|
|
14673
14761
|
}
|
|
14674
14762
|
}
|
|
14675
|
-
|
|
14763
|
+
import_fs3.default.stat(servePath, (err, stats) => {
|
|
14676
14764
|
if (err || !stats?.isFile()) {
|
|
14677
|
-
const ext2 =
|
|
14765
|
+
const ext2 = import_path3.default.extname(rel).toLowerCase();
|
|
14678
14766
|
if (ext2 && ext2 !== ".html") {
|
|
14679
14767
|
res.writeHead(404);
|
|
14680
14768
|
res.end("not found");
|
|
@@ -14685,8 +14773,8 @@ var init_bridge_host = __esm({
|
|
|
14685
14773
|
res.end("not found");
|
|
14686
14774
|
return;
|
|
14687
14775
|
}
|
|
14688
|
-
const indexPath =
|
|
14689
|
-
|
|
14776
|
+
const indexPath = import_path3.default.join(baseDir, "index.html");
|
|
14777
|
+
import_fs3.default.readFile(indexPath, (err2, data) => {
|
|
14690
14778
|
if (err2) {
|
|
14691
14779
|
res.writeHead(404);
|
|
14692
14780
|
res.end("not found");
|
|
@@ -14706,7 +14794,7 @@ var init_bridge_host = __esm({
|
|
|
14706
14794
|
});
|
|
14707
14795
|
return;
|
|
14708
14796
|
}
|
|
14709
|
-
const ext =
|
|
14797
|
+
const ext = import_path3.default.extname(servePath).toLowerCase();
|
|
14710
14798
|
const contentType = HTTP_MIME_TYPES[ext] || "application/octet-stream";
|
|
14711
14799
|
res.writeHead(200, {
|
|
14712
14800
|
"Content-Type": contentType,
|
|
@@ -14717,7 +14805,7 @@ var init_bridge_host = __esm({
|
|
|
14717
14805
|
return;
|
|
14718
14806
|
}
|
|
14719
14807
|
if (ext === ".html") {
|
|
14720
|
-
|
|
14808
|
+
import_fs3.default.readFile(servePath, (readErr, data) => {
|
|
14721
14809
|
if (readErr) {
|
|
14722
14810
|
try {
|
|
14723
14811
|
res.end();
|
|
@@ -14731,7 +14819,7 @@ var init_bridge_host = __esm({
|
|
|
14731
14819
|
});
|
|
14732
14820
|
return;
|
|
14733
14821
|
}
|
|
14734
|
-
const stream =
|
|
14822
|
+
const stream = import_fs3.default.createReadStream(servePath);
|
|
14735
14823
|
stream.pipe(res);
|
|
14736
14824
|
stream.on("error", () => {
|
|
14737
14825
|
try {
|
|
@@ -14937,7 +15025,7 @@ var init_bridge_host = __esm({
|
|
|
14937
15025
|
const target = `${filePath}${loc}`;
|
|
14938
15026
|
const trySpawn = (cmd, args) => new Promise((resolve5) => {
|
|
14939
15027
|
try {
|
|
14940
|
-
const child = (0,
|
|
15028
|
+
const child = (0, import_child_process3.spawn)(cmd, args, { detached: true, stdio: "ignore" });
|
|
14941
15029
|
let settled = false;
|
|
14942
15030
|
child.on("error", () => {
|
|
14943
15031
|
if (settled) return;
|
|
@@ -15439,7 +15527,7 @@ function buildComm() {
|
|
|
15439
15527
|
if (process.platform === "linux") {
|
|
15440
15528
|
return (pid) => {
|
|
15441
15529
|
try {
|
|
15442
|
-
return (0,
|
|
15530
|
+
return (0, import_fs4.readFileSync)(`/proc/${pid}/comm`, "utf8").trim() || null;
|
|
15443
15531
|
} catch {
|
|
15444
15532
|
return null;
|
|
15445
15533
|
}
|
|
@@ -15468,7 +15556,7 @@ function build() {
|
|
|
15468
15556
|
function buildLinux() {
|
|
15469
15557
|
return (pid) => {
|
|
15470
15558
|
try {
|
|
15471
|
-
const raw = (0,
|
|
15559
|
+
const raw = (0, import_fs4.readFileSync)(`/proc/${pid}/stat`, "utf8");
|
|
15472
15560
|
const end = raw.lastIndexOf(")");
|
|
15473
15561
|
if (end < 0) return null;
|
|
15474
15562
|
const rest = raw.slice(end + 1).trim().split(/\s+/);
|
|
@@ -15532,7 +15620,7 @@ function tryBuildDarwinCommFfi() {
|
|
|
15532
15620
|
function buildDarwinLsofComm() {
|
|
15533
15621
|
return (pid) => {
|
|
15534
15622
|
try {
|
|
15535
|
-
const out = (0,
|
|
15623
|
+
const out = (0, import_child_process4.execFileSync)("lsof", ["-R", "-p", String(pid), "-d", "cwd", "-a"], {
|
|
15536
15624
|
encoding: "utf8",
|
|
15537
15625
|
timeout: 2e3,
|
|
15538
15626
|
stdio: ["ignore", "pipe", "ignore"]
|
|
@@ -15549,7 +15637,7 @@ function buildDarwinLsofComm() {
|
|
|
15549
15637
|
function buildDarwinLsof() {
|
|
15550
15638
|
return (pid) => {
|
|
15551
15639
|
try {
|
|
15552
|
-
const out = (0,
|
|
15640
|
+
const out = (0, import_child_process4.execFileSync)("lsof", ["-R", "-p", String(pid), "-d", "cwd", "-a"], {
|
|
15553
15641
|
encoding: "utf8",
|
|
15554
15642
|
timeout: 2e3,
|
|
15555
15643
|
stdio: ["ignore", "pipe", "ignore"]
|
|
@@ -15564,12 +15652,12 @@ function buildDarwinLsof() {
|
|
|
15564
15652
|
}
|
|
15565
15653
|
};
|
|
15566
15654
|
}
|
|
15567
|
-
var
|
|
15655
|
+
var import_child_process4, import_fs4, import_module, cached3, cachedComm, PROC_PIDTBSDINFO, PROC_BSDINFO_SIZE, PBI_PPID_OFFSET, PBI_COMM_OFFSET, PBI_COMM_LEN;
|
|
15568
15656
|
var init_parent_pid = __esm({
|
|
15569
15657
|
"cli/parent-pid.ts"() {
|
|
15570
15658
|
"use strict";
|
|
15571
|
-
|
|
15572
|
-
|
|
15659
|
+
import_child_process4 = require("child_process");
|
|
15660
|
+
import_fs4 = require("fs");
|
|
15573
15661
|
import_module = require("module");
|
|
15574
15662
|
cached3 = null;
|
|
15575
15663
|
cachedComm = null;
|
|
@@ -15614,18 +15702,18 @@ function getCliIdentityKey() {
|
|
|
15614
15702
|
}
|
|
15615
15703
|
function getCurrentSimPath() {
|
|
15616
15704
|
if (process.env[CURRENT_SIM_PATH_ENV]) {
|
|
15617
|
-
return (0,
|
|
15705
|
+
return (0, import_path4.resolve)(process.env[CURRENT_SIM_PATH_ENV]);
|
|
15618
15706
|
}
|
|
15619
15707
|
const key = getCliIdentityKey();
|
|
15620
|
-
return (0,
|
|
15708
|
+
return (0, import_path4.join)((0, import_os2.tmpdir)(), `sootsim-current-sim-${key}.json`);
|
|
15621
15709
|
}
|
|
15622
15710
|
function readCurrentSim() {
|
|
15623
15711
|
const filepath = getCurrentSimPath();
|
|
15624
|
-
if (!(0,
|
|
15712
|
+
if (!(0, import_fs5.existsSync)(filepath)) return null;
|
|
15625
15713
|
try {
|
|
15626
|
-
const parsed = JSON.parse((0,
|
|
15714
|
+
const parsed = JSON.parse((0, import_fs5.readFileSync)(filepath, "utf8"));
|
|
15627
15715
|
if (parsed.version !== CURRENT_SIM_VERSION || typeof parsed.simId !== "string" || !parsed.simId.trim() || typeof parsed.updatedAt !== "string") {
|
|
15628
|
-
(0,
|
|
15716
|
+
(0, import_fs5.rmSync)(filepath, { force: true });
|
|
15629
15717
|
return null;
|
|
15630
15718
|
}
|
|
15631
15719
|
return {
|
|
@@ -15634,7 +15722,7 @@ function readCurrentSim() {
|
|
|
15634
15722
|
updatedAt: parsed.updatedAt
|
|
15635
15723
|
};
|
|
15636
15724
|
} catch {
|
|
15637
|
-
(0,
|
|
15725
|
+
(0, import_fs5.rmSync)(filepath, { force: true });
|
|
15638
15726
|
return null;
|
|
15639
15727
|
}
|
|
15640
15728
|
}
|
|
@@ -15642,15 +15730,15 @@ function readCurrentSimId() {
|
|
|
15642
15730
|
return readCurrentSim()?.simId || null;
|
|
15643
15731
|
}
|
|
15644
15732
|
function clearCurrentSimId() {
|
|
15645
|
-
(0,
|
|
15733
|
+
(0, import_fs5.rmSync)(getCurrentSimPath(), { force: true });
|
|
15646
15734
|
}
|
|
15647
|
-
var
|
|
15735
|
+
var import_fs5, import_os2, import_path4, CURRENT_SIM_VERSION, CURRENT_SIM_PATH_ENV, IDENTITY_ENV_VARS, IMMORTAL_HOST_COMM_RE;
|
|
15648
15736
|
var init_current_sim = __esm({
|
|
15649
15737
|
"cli/current-sim.ts"() {
|
|
15650
15738
|
"use strict";
|
|
15651
|
-
|
|
15739
|
+
import_fs5 = require("fs");
|
|
15652
15740
|
import_os2 = require("os");
|
|
15653
|
-
|
|
15741
|
+
import_path4 = require("path");
|
|
15654
15742
|
init_parent_pid();
|
|
15655
15743
|
CURRENT_SIM_VERSION = 1;
|
|
15656
15744
|
CURRENT_SIM_PATH_ENV = "SOOTSIM_CLI_CURRENT_SIM_PATH";
|
|
@@ -16091,11 +16179,11 @@ async function evalInBridge(bridge, code, opts = {}) {
|
|
|
16091
16179
|
if (opts.acquireLock) payload.acquireLock = true;
|
|
16092
16180
|
return bridge.send(payload);
|
|
16093
16181
|
}
|
|
16094
|
-
async function callInBridge(bridge,
|
|
16095
|
-
return bridge.send({ type: "call", path:
|
|
16182
|
+
async function callInBridge(bridge, path12, ...args) {
|
|
16183
|
+
return bridge.send({ type: "call", path: path12, args });
|
|
16096
16184
|
}
|
|
16097
|
-
async function callInBridgeWrite(bridge,
|
|
16098
|
-
return bridge.send({ type: "call", path:
|
|
16185
|
+
async function callInBridgeWrite(bridge, path12, ...args) {
|
|
16186
|
+
return bridge.send({ type: "call", path: path12, args, acquireLock: true });
|
|
16099
16187
|
}
|
|
16100
16188
|
var import_ws3, resolvedWorld, BridgeSimLockedError;
|
|
16101
16189
|
var init_ws_bridge = __esm({
|
|
@@ -17091,7 +17179,7 @@ function executeSyncHttp(url, method, params) {
|
|
|
17091
17179
|
delete childEnv[key];
|
|
17092
17180
|
}
|
|
17093
17181
|
}
|
|
17094
|
-
const child = (0,
|
|
17182
|
+
const child = (0, import_child_process5.spawnSync)(process.execPath, ["-e", HTTP_CHILD_SRC], {
|
|
17095
17183
|
input: JSON.stringify({ url, method, headers: params?.headers, body: params?.body }),
|
|
17096
17184
|
encoding: "utf8",
|
|
17097
17185
|
timeout: HTTP_TIMEOUT_MS,
|
|
@@ -17138,11 +17226,11 @@ function scriptConditionIsTruthy(value) {
|
|
|
17138
17226
|
if (!Number.isNaN(num) && num === 0) return false;
|
|
17139
17227
|
return true;
|
|
17140
17228
|
}
|
|
17141
|
-
var
|
|
17229
|
+
var import_child_process5, vm, HTTP_TIMEOUT_MS, HTTP_CHILD_SRC, TEMPLATE_RE, ESCAPED_TEMPLATE_RE, BARE_IDENTIFIER_RE, MaestroJsContext;
|
|
17142
17230
|
var init_maestro_js = __esm({
|
|
17143
17231
|
"cli/maestro-js.ts"() {
|
|
17144
17232
|
"use strict";
|
|
17145
|
-
|
|
17233
|
+
import_child_process5 = require("child_process");
|
|
17146
17234
|
vm = __toESM(require("vm"), 1);
|
|
17147
17235
|
HTTP_TIMEOUT_MS = 3e5;
|
|
17148
17236
|
HTTP_CHILD_SRC = `
|
|
@@ -17322,14 +17410,14 @@ process.stdin.on('end', async () => {
|
|
|
17322
17410
|
function getBaseDir() {
|
|
17323
17411
|
const explicit = process.env[SESSION_FILE_ENV];
|
|
17324
17412
|
if (explicit?.trim()) {
|
|
17325
|
-
return (0,
|
|
17413
|
+
return (0, import_node_path8.dirname)((0, import_node_path8.resolve)(explicit));
|
|
17326
17414
|
}
|
|
17327
17415
|
return electronUserDataDir();
|
|
17328
17416
|
}
|
|
17329
17417
|
function getSharedDesktopAuthFilePath() {
|
|
17330
17418
|
const explicit = process.env[SESSION_FILE_ENV];
|
|
17331
|
-
if (explicit?.trim()) return (0,
|
|
17332
|
-
return (0,
|
|
17419
|
+
if (explicit?.trim()) return (0, import_node_path8.resolve)(explicit);
|
|
17420
|
+
return (0, import_node_path8.join)(getBaseDir(), "desktop-auth.json");
|
|
17333
17421
|
}
|
|
17334
17422
|
function normalizeUser(input) {
|
|
17335
17423
|
if (!input || typeof input !== "object") return null;
|
|
@@ -17375,26 +17463,26 @@ function normalizeSession(input) {
|
|
|
17375
17463
|
}
|
|
17376
17464
|
function readSharedDesktopAuthSession() {
|
|
17377
17465
|
const filepath = getSharedDesktopAuthFilePath();
|
|
17378
|
-
if (!(0,
|
|
17466
|
+
if (!(0, import_node_fs9.existsSync)(filepath)) return null;
|
|
17379
17467
|
try {
|
|
17380
|
-
const parsed = JSON.parse((0,
|
|
17468
|
+
const parsed = JSON.parse((0, import_node_fs9.readFileSync)(filepath, "utf8"));
|
|
17381
17469
|
const normalized = normalizeSession(parsed);
|
|
17382
17470
|
if (!normalized) {
|
|
17383
|
-
(0,
|
|
17471
|
+
(0, import_node_fs9.rmSync)(filepath, { force: true });
|
|
17384
17472
|
return null;
|
|
17385
17473
|
}
|
|
17386
17474
|
return normalized;
|
|
17387
17475
|
} catch {
|
|
17388
|
-
(0,
|
|
17476
|
+
(0, import_node_fs9.rmSync)(filepath, { force: true });
|
|
17389
17477
|
return null;
|
|
17390
17478
|
}
|
|
17391
17479
|
}
|
|
17392
|
-
var
|
|
17480
|
+
var import_node_fs9, import_node_path8, SESSION_VERSION, SESSION_FILE_ENV, DEFAULT_ORIGIN;
|
|
17393
17481
|
var init_shared_session = __esm({
|
|
17394
17482
|
"src/auth/shared-session.ts"() {
|
|
17395
17483
|
"use strict";
|
|
17396
|
-
|
|
17397
|
-
|
|
17484
|
+
import_node_fs9 = require("node:fs");
|
|
17485
|
+
import_node_path8 = require("node:path");
|
|
17398
17486
|
init_home_paths();
|
|
17399
17487
|
SESSION_VERSION = 1;
|
|
17400
17488
|
SESSION_FILE_ENV = "SOOTSIM_SHARED_AUTH_FILE";
|
|
@@ -17670,16 +17758,16 @@ function resolveFlowScreenshotPath(screenshotDir, name) {
|
|
|
17670
17758
|
}
|
|
17671
17759
|
function resolveProjectRelativeFlowBase(flowDir) {
|
|
17672
17760
|
if (!flowDir) return process.cwd();
|
|
17673
|
-
return
|
|
17761
|
+
return path10.basename(flowDir) === ".maestro" ? path10.dirname(flowDir) : flowDir;
|
|
17674
17762
|
}
|
|
17675
17763
|
function resolveFlowScreenshotPathWithMode(screenshotDir, name, opts) {
|
|
17676
17764
|
const normalizedName = name.endsWith(".png") ? name : `${name}.png`;
|
|
17677
|
-
if (
|
|
17765
|
+
if (path10.isAbsolute(normalizedName)) return normalizedName;
|
|
17678
17766
|
if (opts.mode === "flow" && /[\\/]/.test(normalizedName)) {
|
|
17679
17767
|
const baseDir = normalizedName.startsWith("./") || normalizedName.startsWith("../") ? opts.flowDir ?? process.cwd() : resolveProjectRelativeFlowBase(opts.flowDir);
|
|
17680
|
-
return
|
|
17768
|
+
return path10.resolve(baseDir, normalizedName);
|
|
17681
17769
|
}
|
|
17682
|
-
return
|
|
17770
|
+
return path10.join(screenshotDir, normalizedName);
|
|
17683
17771
|
}
|
|
17684
17772
|
function normalizeFlowScreenshotSpec(step) {
|
|
17685
17773
|
if (typeof step === "string") {
|
|
@@ -17736,12 +17824,12 @@ function parseFlowSteps(content) {
|
|
|
17736
17824
|
const parsed = import_yaml.default.parse(candidate);
|
|
17737
17825
|
return Array.isArray(parsed) ? parsed : [];
|
|
17738
17826
|
}
|
|
17739
|
-
var
|
|
17827
|
+
var fs10, path10, import_settings2, import_yaml, DEFAULT_TIMEOUT, FLOW_TIMEOUT_SCALE, scaledTimeout, SCREEN_W, SCREEN_H, SootSimBridgeFlowRunner;
|
|
17740
17828
|
var init_bridge_flow_runner = __esm({
|
|
17741
17829
|
"cli/bridge-flow-runner.ts"() {
|
|
17742
17830
|
"use strict";
|
|
17743
|
-
|
|
17744
|
-
|
|
17831
|
+
fs10 = __toESM(require("fs"), 1);
|
|
17832
|
+
path10 = __toESM(require("path"), 1);
|
|
17745
17833
|
import_settings2 = require("sootsim-engine/settings");
|
|
17746
17834
|
import_yaml = __toESM(require("yaml"), 1);
|
|
17747
17835
|
init_frame_compose();
|
|
@@ -18029,14 +18117,14 @@ var init_bridge_flow_runner = __esm({
|
|
|
18029
18117
|
if (chunks.length === 0) {
|
|
18030
18118
|
throw new Error("recording requested but no video buffer was produced");
|
|
18031
18119
|
}
|
|
18032
|
-
|
|
18120
|
+
fs10.mkdirSync(this.opts.recordingOutputDir, { recursive: true });
|
|
18033
18121
|
const videoMime = stopped.mime || this.opts.recordingFormat || "video/webm";
|
|
18034
18122
|
const extension = videoMime.includes("mp4") ? "mp4" : "webm";
|
|
18035
|
-
const outputPath =
|
|
18123
|
+
const outputPath = path10.join(
|
|
18036
18124
|
this.opts.recordingOutputDir,
|
|
18037
18125
|
`sootsim-${Date.now()}.${extension}`
|
|
18038
18126
|
);
|
|
18039
|
-
|
|
18127
|
+
fs10.writeFileSync(outputPath, Buffer.concat(chunks));
|
|
18040
18128
|
return outputPath;
|
|
18041
18129
|
}
|
|
18042
18130
|
async waitForRecordingTail(opts) {
|
|
@@ -18545,7 +18633,7 @@ var init_bridge_flow_runner = __esm({
|
|
|
18545
18633
|
flowDir: this.opts.flowDir
|
|
18546
18634
|
}
|
|
18547
18635
|
);
|
|
18548
|
-
|
|
18636
|
+
fs10.mkdirSync(path10.dirname(outputPath), { recursive: true });
|
|
18549
18637
|
const layers = spec.layers ?? this.opts.screenshotLayers;
|
|
18550
18638
|
const screenshotRequest = {
|
|
18551
18639
|
type: "screenshot",
|
|
@@ -18561,11 +18649,11 @@ var init_bridge_flow_runner = __esm({
|
|
|
18561
18649
|
throw new Error("could not read current device model for framed screenshot");
|
|
18562
18650
|
}
|
|
18563
18651
|
const framed = await composeFramedScreenshot(rawBuffer, model);
|
|
18564
|
-
|
|
18652
|
+
fs10.writeFileSync(outputPath, framed);
|
|
18565
18653
|
console.log(`[flow] screenshot: ${outputPath} (frame: ${model})`);
|
|
18566
18654
|
return outputPath;
|
|
18567
18655
|
}
|
|
18568
|
-
|
|
18656
|
+
fs10.writeFileSync(outputPath, rawBuffer);
|
|
18569
18657
|
console.log(`[flow] screenshot: ${outputPath}`);
|
|
18570
18658
|
return outputPath;
|
|
18571
18659
|
}
|
|
@@ -18581,22 +18669,22 @@ var init_bridge_flow_runner = __esm({
|
|
|
18581
18669
|
return model;
|
|
18582
18670
|
}
|
|
18583
18671
|
async captureScreenshot(outputPath) {
|
|
18584
|
-
|
|
18672
|
+
fs10.mkdirSync(path10.dirname(outputPath), { recursive: true });
|
|
18585
18673
|
const dataUrl = await this.bridge.send({
|
|
18586
18674
|
type: "screenshot",
|
|
18587
18675
|
simId: this.opts.simId
|
|
18588
18676
|
});
|
|
18589
18677
|
const base64 = dataUrl.replace(/^data:image\/png;base64,/, "");
|
|
18590
|
-
|
|
18678
|
+
fs10.writeFileSync(outputPath, Buffer.from(base64, "base64"));
|
|
18591
18679
|
}
|
|
18592
18680
|
// writes a per-failure debug bundle: screenshot + structured describe
|
|
18593
18681
|
// + a11y tree + console errors/warnings + failed network requests +
|
|
18594
18682
|
// shell state, all under one directory so post-mortem is one grep away.
|
|
18595
18683
|
async captureFailureBundle(outputDir, context) {
|
|
18596
|
-
|
|
18684
|
+
fs10.mkdirSync(outputDir, { recursive: true });
|
|
18597
18685
|
const write = (name, content) => {
|
|
18598
18686
|
try {
|
|
18599
|
-
|
|
18687
|
+
fs10.writeFileSync(path10.join(outputDir, name), content);
|
|
18600
18688
|
} catch {
|
|
18601
18689
|
}
|
|
18602
18690
|
};
|
|
@@ -19138,8 +19226,8 @@ var init_bridge_flow_runner = __esm({
|
|
|
19138
19226
|
runScript(target) {
|
|
19139
19227
|
const spec = typeof target === "string" ? { file: target } : target;
|
|
19140
19228
|
if (!spec.file) throw new Error("runScript requires a file");
|
|
19141
|
-
const scriptPath =
|
|
19142
|
-
const source =
|
|
19229
|
+
const scriptPath = path10.resolve(this.opts.flowDir, spec.file);
|
|
19230
|
+
const source = fs10.readFileSync(scriptPath, "utf8");
|
|
19143
19231
|
this.js.evaluate(source, { env: spec.env });
|
|
19144
19232
|
console.log(`[flow] runScript: ${spec.file} done`);
|
|
19145
19233
|
}
|
|
@@ -19433,10 +19521,10 @@ var init_bridge_flow_runner = __esm({
|
|
|
19433
19521
|
for (const [k, v] of Object.entries(env)) this.js.putEnv(k, v);
|
|
19434
19522
|
}
|
|
19435
19523
|
if (file) {
|
|
19436
|
-
const flowPath =
|
|
19437
|
-
const flowContent =
|
|
19524
|
+
const flowPath = path10.resolve(this.opts.flowDir, file);
|
|
19525
|
+
const flowContent = fs10.readFileSync(flowPath, "utf8");
|
|
19438
19526
|
const previousDir = this.opts.flowDir;
|
|
19439
|
-
this.opts.flowDir =
|
|
19527
|
+
this.opts.flowDir = path10.dirname(flowPath);
|
|
19440
19528
|
try {
|
|
19441
19529
|
await this.runFlow(parseFlowSteps(flowContent));
|
|
19442
19530
|
} finally {
|
|
@@ -19591,8 +19679,8 @@ __export(registry_exports, {
|
|
|
19591
19679
|
skillRegistry: () => skillRegistry
|
|
19592
19680
|
});
|
|
19593
19681
|
module.exports = __toCommonJS(registry_exports);
|
|
19594
|
-
var
|
|
19595
|
-
var
|
|
19682
|
+
var fs11 = __toESM(require("fs"), 1);
|
|
19683
|
+
var path11 = __toESM(require("path"), 1);
|
|
19596
19684
|
|
|
19597
19685
|
// src/skills/builtin/a11y-review.ts
|
|
19598
19686
|
init_reap_browser();
|
|
@@ -19611,8 +19699,8 @@ var skill = {
|
|
|
19611
19699
|
},
|
|
19612
19700
|
async execute(params, context) {
|
|
19613
19701
|
const { chromium } = await import("playwright");
|
|
19614
|
-
const
|
|
19615
|
-
const
|
|
19702
|
+
const path12 = await import("path");
|
|
19703
|
+
const fs12 = await import("fs");
|
|
19616
19704
|
const browser = await launchReapedChrome((options) => chromium.launch(options), {
|
|
19617
19705
|
headless: true
|
|
19618
19706
|
});
|
|
@@ -19667,9 +19755,9 @@ var skill = {
|
|
|
19667
19755
|
warnings: issues.filter((i) => i.severity === "warning").length,
|
|
19668
19756
|
tree: typeof tree === "string" ? tree : JSON.stringify(tree)
|
|
19669
19757
|
};
|
|
19670
|
-
const reportPath =
|
|
19671
|
-
|
|
19672
|
-
|
|
19758
|
+
const reportPath = path12.join(context.outputDir, "a11y-report.json");
|
|
19759
|
+
fs12.mkdirSync(path12.dirname(reportPath), { recursive: true });
|
|
19760
|
+
fs12.writeFileSync(reportPath, JSON.stringify(report, null, 2));
|
|
19673
19761
|
return {
|
|
19674
19762
|
success: issues.filter((i) => i.severity === "error").length === 0,
|
|
19675
19763
|
message: `${report.errors} errors, ${report.warnings} warnings across ${report.nodeCount} nodes`,
|
|
@@ -19707,8 +19795,8 @@ var skill2 = {
|
|
|
19707
19795
|
}
|
|
19708
19796
|
},
|
|
19709
19797
|
async execute(params, context) {
|
|
19710
|
-
const
|
|
19711
|
-
const
|
|
19798
|
+
const fs12 = await import("fs");
|
|
19799
|
+
const path12 = await import("path");
|
|
19712
19800
|
const { POLYFILL_REGISTRY: POLYFILL_REGISTRY2 } = await Promise.resolve().then(() => (init_web(), web_exports));
|
|
19713
19801
|
if (params.packageName) {
|
|
19714
19802
|
const entry = POLYFILL_REGISTRY2[params.packageName];
|
|
@@ -19726,11 +19814,11 @@ var skill2 = {
|
|
|
19726
19814
|
data: { package: params.packageName, status, ...entry }
|
|
19727
19815
|
};
|
|
19728
19816
|
}
|
|
19729
|
-
const pkgPath =
|
|
19730
|
-
if (!
|
|
19817
|
+
const pkgPath = path12.join(context.projectDir, "package.json");
|
|
19818
|
+
if (!fs12.existsSync(pkgPath)) {
|
|
19731
19819
|
return { success: false, message: "No package.json found" };
|
|
19732
19820
|
}
|
|
19733
|
-
const pkg = JSON.parse(
|
|
19821
|
+
const pkg = JSON.parse(fs12.readFileSync(pkgPath, "utf8"));
|
|
19734
19822
|
const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
19735
19823
|
const results = {
|
|
19736
19824
|
full: [],
|
|
@@ -19748,9 +19836,9 @@ var skill2 = {
|
|
|
19748
19836
|
results.unknown.push(dep);
|
|
19749
19837
|
}
|
|
19750
19838
|
}
|
|
19751
|
-
const reportPath =
|
|
19752
|
-
|
|
19753
|
-
|
|
19839
|
+
const reportPath = path12.join(context.outputDir, "compat-report.json");
|
|
19840
|
+
fs12.mkdirSync(path12.dirname(reportPath), { recursive: true });
|
|
19841
|
+
fs12.writeFileSync(reportPath, JSON.stringify(results, null, 2));
|
|
19754
19842
|
return {
|
|
19755
19843
|
success: results.unsupported.length === 0,
|
|
19756
19844
|
message: `${results.full.length} full, ${results.partial.length} partial, ${results.unsupported.length} unsupported, ${results.unknown.length} unknown`,
|
|
@@ -19788,8 +19876,8 @@ var skill3 = {
|
|
|
19788
19876
|
record: { type: "boolean", description: "Record video of the flow" }
|
|
19789
19877
|
},
|
|
19790
19878
|
async execute(params, context) {
|
|
19791
|
-
const
|
|
19792
|
-
const
|
|
19879
|
+
const fs12 = await import("fs");
|
|
19880
|
+
const path12 = await import("path");
|
|
19793
19881
|
const yaml2 = await import("yaml");
|
|
19794
19882
|
const { DEFAULT_SOOTSIM_BRIDGE_PORT: DEFAULT_SOOTSIM_BRIDGE_PORT2 } = await Promise.resolve().then(() => (init_bridge_constants(), bridge_constants_exports));
|
|
19795
19883
|
const { SootSimBridgeHost: SootSimBridgeHost2 } = await Promise.resolve().then(() => (init_bridge_host(), bridge_host_exports));
|
|
@@ -19798,7 +19886,7 @@ var skill3 = {
|
|
|
19798
19886
|
const host = new SootSimBridgeHost2({ port: DEFAULT_SOOTSIM_BRIDGE_PORT2 });
|
|
19799
19887
|
host.start({ silent: true });
|
|
19800
19888
|
try {
|
|
19801
|
-
const flowContent =
|
|
19889
|
+
const flowContent = fs12.readFileSync(params.flowPath, "utf8");
|
|
19802
19890
|
const fmMatch = flowContent.match(/^---\n([\s\S]*?)\n---\n?/);
|
|
19803
19891
|
const stepsBody = fmMatch ? flowContent.slice(fmMatch[0].length) : flowContent;
|
|
19804
19892
|
const steps = yaml2.parse(stepsBody);
|
|
@@ -19823,7 +19911,7 @@ var skill3 = {
|
|
|
19823
19911
|
});
|
|
19824
19912
|
const driver = new SootSimBridgeFlowRunner2(bridge, {
|
|
19825
19913
|
screenshotDir: context.outputDir,
|
|
19826
|
-
flowDir:
|
|
19914
|
+
flowDir: path12.dirname(path12.resolve(params.flowPath)),
|
|
19827
19915
|
simId,
|
|
19828
19916
|
recordingOutputDir: params.record ? context.outputDir : void 0
|
|
19829
19917
|
});
|
|
@@ -19845,7 +19933,7 @@ var skill3 = {
|
|
|
19845
19933
|
simId,
|
|
19846
19934
|
videoPath: videoPath || void 0
|
|
19847
19935
|
},
|
|
19848
|
-
artifacts: videoPath ? [{ type: "video", name:
|
|
19936
|
+
artifacts: videoPath ? [{ type: "video", name: path12.basename(videoPath), path: videoPath }] : void 0
|
|
19849
19937
|
};
|
|
19850
19938
|
} finally {
|
|
19851
19939
|
try {
|
|
@@ -19892,8 +19980,8 @@ var skill4 = {
|
|
|
19892
19980
|
},
|
|
19893
19981
|
async execute(params, context) {
|
|
19894
19982
|
const { chromium } = await import("playwright");
|
|
19895
|
-
const
|
|
19896
|
-
const
|
|
19983
|
+
const path12 = await import("path");
|
|
19984
|
+
const fs12 = await import("fs");
|
|
19897
19985
|
const browser = await launchReapedChrome((options) => chromium.launch(options), {
|
|
19898
19986
|
headless: true
|
|
19899
19987
|
});
|
|
@@ -19919,9 +20007,9 @@ var skill4 = {
|
|
|
19919
20007
|
...profile,
|
|
19920
20008
|
fps: syncCount > 0 ? (syncCount / (duration / 1e3)).toFixed(1) : "0"
|
|
19921
20009
|
};
|
|
19922
|
-
const reportPath =
|
|
19923
|
-
|
|
19924
|
-
|
|
20010
|
+
const reportPath = path12.join(context.outputDir, "perf-report.json");
|
|
20011
|
+
fs12.mkdirSync(path12.dirname(reportPath), { recursive: true });
|
|
20012
|
+
fs12.writeFileSync(reportPath, JSON.stringify(report, null, 2));
|
|
19925
20013
|
return {
|
|
19926
20014
|
success: true,
|
|
19927
20015
|
message: `${report.fps} fps, ${profile.avgSyncMs?.toFixed(1)}ms avg sync, ${nodeCount} nodes`,
|
|
@@ -19954,8 +20042,8 @@ var skill5 = {
|
|
|
19954
20042
|
},
|
|
19955
20043
|
async execute(params, context) {
|
|
19956
20044
|
const { chromium } = await import("playwright");
|
|
19957
|
-
const
|
|
19958
|
-
const
|
|
20045
|
+
const path12 = await import("path");
|
|
20046
|
+
const fs12 = await import("fs");
|
|
19959
20047
|
const browser = await launchReapedChrome((options) => chromium.launch(options), {
|
|
19960
20048
|
headless: true
|
|
19961
20049
|
});
|
|
@@ -19963,8 +20051,8 @@ var skill5 = {
|
|
|
19963
20051
|
try {
|
|
19964
20052
|
await page.goto(context.url, { waitUntil: "networkidle" });
|
|
19965
20053
|
await page.waitForTimeout(2e3);
|
|
19966
|
-
const outputPath =
|
|
19967
|
-
|
|
20054
|
+
const outputPath = path12.join(context.outputDir, `${params.name}.png`);
|
|
20055
|
+
fs12.mkdirSync(path12.dirname(outputPath), { recursive: true });
|
|
19968
20056
|
await page.screenshot({ path: outputPath });
|
|
19969
20057
|
return {
|
|
19970
20058
|
success: true,
|
|
@@ -20005,8 +20093,8 @@ var skill6 = {
|
|
|
20005
20093
|
},
|
|
20006
20094
|
async execute(params, context) {
|
|
20007
20095
|
const { chromium } = await import("playwright");
|
|
20008
|
-
const
|
|
20009
|
-
const
|
|
20096
|
+
const path12 = await import("path");
|
|
20097
|
+
const fs12 = await import("fs");
|
|
20010
20098
|
const browser = await launchReapedChrome((options) => chromium.launch(options), {
|
|
20011
20099
|
headless: true
|
|
20012
20100
|
});
|
|
@@ -20014,14 +20102,14 @@ var skill6 = {
|
|
|
20014
20102
|
try {
|
|
20015
20103
|
await page.goto(context.url, { waitUntil: "networkidle" });
|
|
20016
20104
|
await page.waitForTimeout(2e3);
|
|
20017
|
-
const currentPath =
|
|
20018
|
-
|
|
20105
|
+
const currentPath = path12.join(context.outputDir, `${params.name}-current.png`);
|
|
20106
|
+
fs12.mkdirSync(path12.dirname(currentPath), { recursive: true });
|
|
20019
20107
|
await page.screenshot({ path: currentPath });
|
|
20020
20108
|
try {
|
|
20021
20109
|
const { PNG } = await import("pngjs");
|
|
20022
20110
|
const pixelmatch = (await import("pixelmatch")).default;
|
|
20023
|
-
const baseline = PNG.sync.read(
|
|
20024
|
-
const current = PNG.sync.read(
|
|
20111
|
+
const baseline = PNG.sync.read(fs12.readFileSync(params.baseline));
|
|
20112
|
+
const current = PNG.sync.read(fs12.readFileSync(currentPath));
|
|
20025
20113
|
const { width, height } = baseline;
|
|
20026
20114
|
const diff = new PNG({ width, height });
|
|
20027
20115
|
const numDiffPixels = pixelmatch(
|
|
@@ -20032,8 +20120,8 @@ var skill6 = {
|
|
|
20032
20120
|
height,
|
|
20033
20121
|
{ threshold: params.threshold || 0.1 }
|
|
20034
20122
|
);
|
|
20035
|
-
const diffPath =
|
|
20036
|
-
|
|
20123
|
+
const diffPath = path12.join(context.outputDir, `${params.name}-diff.png`);
|
|
20124
|
+
fs12.writeFileSync(diffPath, PNG.sync.write(diff));
|
|
20037
20125
|
const totalPixels = width * height;
|
|
20038
20126
|
const diffPercent = (numDiffPixels / totalPixels * 100).toFixed(2);
|
|
20039
20127
|
return {
|
|
@@ -20097,10 +20185,10 @@ var skillRegistry = {
|
|
|
20097
20185
|
},
|
|
20098
20186
|
// load skills from a project manifest (sootsim-skills.json)
|
|
20099
20187
|
async loadFromManifest(projectDir) {
|
|
20100
|
-
const manifestPath =
|
|
20101
|
-
if (!
|
|
20188
|
+
const manifestPath = path11.join(projectDir, "sootsim-skills.json");
|
|
20189
|
+
if (!fs11.existsSync(manifestPath)) return;
|
|
20102
20190
|
try {
|
|
20103
|
-
const manifest = JSON.parse(
|
|
20191
|
+
const manifest = JSON.parse(fs11.readFileSync(manifestPath, "utf8"));
|
|
20104
20192
|
if (Array.isArray(manifest.skills)) {
|
|
20105
20193
|
for (const entry of manifest.skills) {
|
|
20106
20194
|
if (typeof entry === "string") {
|
|
@@ -20111,7 +20199,7 @@ var skillRegistry = {
|
|
|
20111
20199
|
}
|
|
20112
20200
|
} else if (entry.file) {
|
|
20113
20201
|
try {
|
|
20114
|
-
const mod = await import(
|
|
20202
|
+
const mod = await import(path11.resolve(projectDir, entry.file));
|
|
20115
20203
|
if (mod.skill) this.register(mod.skill);
|
|
20116
20204
|
} catch {
|
|
20117
20205
|
}
|
|
@@ -20124,10 +20212,10 @@ var skillRegistry = {
|
|
|
20124
20212
|
// auto-discover skills based on project dependencies
|
|
20125
20213
|
suggestSkills(projectDir) {
|
|
20126
20214
|
const suggestions = [];
|
|
20127
|
-
const pkgPath =
|
|
20128
|
-
if (!
|
|
20215
|
+
const pkgPath = path11.join(projectDir, "package.json");
|
|
20216
|
+
if (!fs11.existsSync(pkgPath)) return suggestions;
|
|
20129
20217
|
try {
|
|
20130
|
-
const pkg = JSON.parse(
|
|
20218
|
+
const pkg = JSON.parse(fs11.readFileSync(pkgPath, "utf8"));
|
|
20131
20219
|
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
20132
20220
|
if (deps["detox"] || deps["maestro"]) {
|
|
20133
20221
|
suggestions.push("maestro-test");
|