sootsim 0.1.250 → 0.1.252
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -5
- package/dist-cli/bin.js +4 -4
- package/dist-cli/chunks/{agent-JPKDUK4P.js → agent-JRN5KS75.js} +2 -2
- package/dist-cli/chunks/{agent-wrapper-Z64YICSQ.js → agent-wrapper-2ZH2WQ2L.js} +2 -2
- package/dist-cli/chunks/{app-fonts-524IXHZF.js → app-fonts-LBQ7A7LL.js} +2 -2
- package/dist-cli/chunks/{assert-WZRU7L2S.js → assert-XFQCRREO.js} +2 -2
- package/dist-cli/chunks/{auth-3ZPMASCJ.js → auth-DAMRQQ53.js} +2 -2
- package/dist-cli/chunks/beta-JJ4YSCOE.js +2 -0
- package/dist-cli/chunks/{camera-FPGFHVAE.js → camera-NQWFOHXI.js} +2 -2
- package/dist-cli/chunks/chunk-25FMG2DR.js +1 -0
- package/dist-cli/chunks/{chunk-ZFJZLRAG.js → chunk-4P7EXY3Q.js} +2 -2
- package/dist-cli/chunks/{chunk-JMJJJQ3N.js → chunk-54RVP6DQ.js} +1 -1
- package/dist-cli/chunks/{chunk-ODXX3PDC.js → chunk-56CSO42W.js} +2 -2
- package/dist-cli/chunks/{chunk-7SDQP3K6.js → chunk-5PVVFMLA.js} +2 -2
- package/dist-cli/chunks/{chunk-LFRFK56L.js → chunk-677KF26C.js} +1 -1
- package/dist-cli/chunks/{chunk-ZBAOOQ7L.js → chunk-AJVA4XFD.js} +2 -2
- package/dist-cli/chunks/{chunk-OOYVCERU.js → chunk-BU4QJGYM.js} +2 -2
- package/dist-cli/chunks/{chunk-LCEWHXGT.js → chunk-F2DZ3EHN.js} +2 -2
- package/dist-cli/chunks/chunk-F7NVK7U5.js +29 -0
- package/dist-cli/chunks/{chunk-GVEBFN3A.js → chunk-FCNI6ZWQ.js} +2 -2
- package/dist-cli/chunks/{chunk-7CESRUUF.js → chunk-GBJS3QVL.js} +2 -2
- package/dist-cli/chunks/{chunk-RDQ4RP2I.js → chunk-GPECMCCD.js} +2 -2
- package/dist-cli/chunks/{chunk-HQVZVJWB.js → chunk-GRPNPAFQ.js} +1 -1
- package/dist-cli/chunks/{chunk-EJQGI6U6.js → chunk-HERRSHL3.js} +2 -2
- package/dist-cli/chunks/{chunk-QQDVBF5C.js → chunk-HNYCB3ZY.js} +1 -1
- package/dist-cli/chunks/chunk-HV773SED.js +4 -0
- package/dist-cli/chunks/{chunk-DOOM7A5G.js → chunk-J4XJHPJV.js} +2 -2
- package/dist-cli/chunks/{chunk-TIWQBBA6.js → chunk-JYJ37QKN.js} +2 -2
- package/dist-cli/chunks/chunk-K5UURTEB.js +1 -0
- package/dist-cli/chunks/{chunk-AV734IPM.js → chunk-LHAUZJH5.js} +1 -1
- package/dist-cli/chunks/{chunk-XBWJ7DPK.js → chunk-LL7KIGNG.js} +2 -2
- package/dist-cli/chunks/{chunk-HTGCR74O.js → chunk-LXRPMNYD.js} +2 -2
- package/dist-cli/chunks/{chunk-2FGQSNTC.js → chunk-LYIN47A5.js} +2 -2
- package/dist-cli/chunks/{chunk-Q72PZST6.js → chunk-MJU6KNLI.js} +3 -3
- package/dist-cli/chunks/{chunk-23DV2XSE.js → chunk-MMCNYDBD.js} +1 -1
- package/dist-cli/chunks/{chunk-G2QKQWCY.js → chunk-NADQK2CU.js} +1 -1
- package/dist-cli/chunks/{chunk-N52AECUU.js → chunk-NB6RTLLI.js} +3 -3
- package/dist-cli/chunks/{chunk-S5ILN4OM.js → chunk-NNEUAQME.js} +3 -3
- package/dist-cli/chunks/{chunk-RMP6YTMJ.js → chunk-NTZYSZ3Q.js} +2 -2
- package/dist-cli/chunks/{chunk-AWT2ISDX.js → chunk-NYKHYDBN.js} +1 -1
- package/dist-cli/chunks/{chunk-7WCUYHR3.js → chunk-OSPFE643.js} +1 -1
- package/dist-cli/chunks/{chunk-DX6CUGUF.js → chunk-PLK4SCBY.js} +2 -2
- package/dist-cli/chunks/{chunk-HLDQHWK5.js → chunk-PVDPE5BH.js} +1 -1
- package/dist-cli/chunks/{chunk-L5VG4RQT.js → chunk-QHNYUT7D.js} +1 -1
- package/dist-cli/chunks/{chunk-ZA4K47LA.js → chunk-S6DIPG7L.js} +2 -2
- package/dist-cli/chunks/{chunk-YACJ3KQ4.js → chunk-T2BJFGBC.js} +1 -1
- package/dist-cli/chunks/{chunk-CJMASJXU.js → chunk-TDWFR6H5.js} +2 -2
- package/dist-cli/chunks/{chunk-COON6LFC.js → chunk-U5JMZPBD.js} +1 -1
- package/dist-cli/chunks/{chunk-N6WXF6OS.js → chunk-UA5FVOEO.js} +1 -1
- package/dist-cli/chunks/chunk-UVE2LY6V.js +7 -0
- package/dist-cli/chunks/{chunk-GHJRRNR3.js → chunk-WS3DDBN3.js} +1 -1
- package/dist-cli/chunks/{chunk-KZZFQRPX.js → chunk-X2IKDV5A.js} +1 -1
- package/dist-cli/chunks/{chunk-GXNJSLZM.js → chunk-ZKN7GCX4.js} +2 -2
- package/dist-cli/chunks/cli-version-OZF5OMW4.js +2 -0
- package/dist-cli/chunks/{compat-C3N6PFK5.js → compat-ME4QWRZ6.js} +3 -3
- package/dist-cli/chunks/{config-UVEGEV7N.js → config-TMMSBXDV.js} +2 -2
- package/dist-cli/chunks/{control-ROSEFQH3.js → control-QGYYWKJP.js} +2 -2
- package/dist-cli/chunks/daemon-6NBHEVXS.js +2 -0
- package/dist-cli/chunks/{debug-VLB6FCUL.js → debug-LFJ46Q45.js} +3 -3
- package/dist-cli/chunks/{desktop-LAPJ2XXG.js → desktop-W5GPU7JA.js} +3 -3
- package/dist-cli/chunks/{detox-UKRIYJBM.js → detox-U3B3N3K7.js} +2 -2
- package/dist-cli/chunks/{device-HABOB4FC.js → device-I2WVQFXL.js} +2 -2
- package/dist-cli/chunks/{diagnose-TPTVALBD.js → diagnose-6TQOA4QJ.js} +2 -2
- package/dist-cli/chunks/drivers-5J25VDIG.js +2 -0
- package/dist-cli/chunks/{film-RZABTGXV.js → film-P5E64XQH.js} +3 -3
- package/dist-cli/chunks/flow-LD6MOZQC.js +2 -0
- package/dist-cli/chunks/help-VCWJZBQU.js +2 -0
- package/dist-cli/chunks/{hidden-runtime-alias-AITHRBI5.js → hidden-runtime-alias-ICP5W4W5.js} +2 -2
- package/dist-cli/chunks/home-paths-MCD3DISJ.js +2 -0
- package/dist-cli/chunks/inspect-VF575AD3.js +2 -0
- package/dist-cli/chunks/install-desktop-Q4Y6FTSA.js +2 -0
- package/dist-cli/chunks/{login-LIPDXOLT.js → login-A5LRYTNO.js} +4 -4
- package/dist-cli/chunks/{logout-7TCXGQM4.js → logout-M3HFZGFU.js} +2 -2
- package/dist-cli/chunks/{maestro-CQRCUEZJ.js → maestro-HNREOYXF.js} +3 -3
- package/dist-cli/chunks/{maestro-generate-TBBDRYEU.js → maestro-generate-BEEDUOOJ.js} +3 -3
- package/dist-cli/chunks/{mode-Z7E6YZTJ.js → mode-IBFHS3G2.js} +2 -2
- package/dist-cli/chunks/optional-demo-registry-6XYQJXI5.js +2 -0
- package/dist-cli/chunks/{perf-OS7TTPQ2.js → perf-62BD5VIU.js} +2 -2
- package/dist-cli/chunks/{record-YH22UVU2.js → record-2ILPO4XB.js} +3 -3
- package/dist-cli/chunks/runtime-WCDQFR7G.js +2 -0
- package/dist-cli/chunks/{screenshot-command-DV35HE24.js → screenshot-command-YZR5KVV2.js} +3 -3
- package/dist-cli/chunks/{screenshots-capture-OV6RMSA2.js → screenshots-capture-QHQ43OBD.js} +2 -2
- package/dist-cli/chunks/{serve-WTZRYS6X.js → serve-GQ4PUD5P.js} +15 -15
- package/dist-cli/chunks/{setup-AQ46RLHL.js → setup-C74I2RO3.js} +3 -3
- package/dist-cli/chunks/{skills-P6P5L7CV.js → skills-I7EVR3MU.js} +2 -2
- package/dist-cli/chunks/{storage-PIHIVEBL.js → storage-CH6BAYB4.js} +2 -2
- package/dist-cli/chunks/store-PTQ4QMFA.js +2 -0
- package/dist-cli/chunks/telemetry-AJDAGOFX.js +2 -0
- package/dist-cli/chunks/{timeline-334MEYTC.js → timeline-FUS7F5LI.js} +2 -2
- package/dist-cli/chunks/{upgrade-UVEGTAME.js → upgrade-DHMZFD5R.js} +4 -4
- package/dist-cli/chunks/upload-XJXPQMKX.js +2 -0
- package/dist-cli/chunks/version-M2GSAVKM.js +4 -0
- package/dist-cli/chunks/web-NV7UM2T7.js +2 -0
- package/dist-cli/chunks/{what-happened-3UH7ZQW6.js → what-happened-VRDDXQWR.js} +2 -2
- package/dist-lib/agent-daemon-client.cjs +1 -1
- package/dist-lib/agent-events.cjs +1 -1
- package/dist-lib/agent-identity.cjs +1 -1
- package/dist-lib/agent-sessions.cjs +1 -1
- package/dist-lib/attached-projects.cjs +1 -1
- package/dist-lib/auth/shared-session.cjs +1 -1
- package/dist-lib/backend-origin.cjs +1 -1
- package/dist-lib/beta.cjs +1 -1
- package/dist-lib/beta.mjs +1 -1
- package/dist-lib/bridge-constants.cjs +1 -1
- package/dist-lib/cli-constants.cjs +1 -1
- package/dist-lib/config.cjs +1 -1
- package/dist-lib/detox/index.cjs +1 -1
- package/dist-lib/dev-bundle-resolution.cjs +1 -1
- package/dist-lib/home-paths.cjs +1 -33
- package/dist-lib/host/bridge-host.cjs +396 -329
- package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
- package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
- package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
- package/dist-lib/host/websocket-proxy.cjs +1 -1
- package/dist-lib/index.cjs +1 -1
- package/dist-lib/jump-to-source-babel.cjs +1 -1
- package/dist-lib/menu.cjs +1 -1
- package/dist-lib/menu.mjs +1 -1
- package/dist-lib/metro.cjs +1 -1
- package/dist-lib/profiles.cjs +1 -1
- package/dist-lib/render-mode.cjs +1 -1
- package/dist-lib/scripts/dev-server-scanner.cjs +1 -1
- package/dist-lib/sdk.cjs +1 -1
- package/dist-lib/sdk.mjs +1 -1
- package/dist-lib/skills.cjs +517 -437
- package/dist-lib/vite.cjs +1 -1
- package/package.json +2 -1
- package/src/home-paths.ts +5 -40
- package/src/host/bridge-host.ts +4 -5
- package/src/runtime-delivery.ts +32 -377
- package/dist-cli/chunks/beta-BBI3GYZ6.js +0 -2
- package/dist-cli/chunks/chunk-2UGQF7XX.js +0 -4
- package/dist-cli/chunks/chunk-J3XNJTO5.js +0 -1
- package/dist-cli/chunks/chunk-M7NRJV7O.js +0 -1
- package/dist-cli/chunks/chunk-PZR5U4RD.js +0 -29
- package/dist-cli/chunks/chunk-TJBXFUCI.js +0 -7
- package/dist-cli/chunks/cli-version-GWSUBSWJ.js +0 -2
- package/dist-cli/chunks/daemon-NVFYFCWX.js +0 -2
- package/dist-cli/chunks/drivers-ZUD4PX2W.js +0 -2
- package/dist-cli/chunks/flow-NHVT35XI.js +0 -2
- package/dist-cli/chunks/help-CM77GYXU.js +0 -2
- package/dist-cli/chunks/home-paths-XIHGBDLL.js +0 -2
- package/dist-cli/chunks/inspect-2WK43KRH.js +0 -2
- package/dist-cli/chunks/install-desktop-TS2RBWU5.js +0 -2
- package/dist-cli/chunks/optional-demo-registry-ANMKFJWS.js +0 -2
- package/dist-cli/chunks/runtime-WYDPR5RI.js +0 -2
- package/dist-cli/chunks/store-SVTB7QDS.js +0 -2
- package/dist-cli/chunks/telemetry-HM3ULN5U.js +0 -2
- package/dist-cli/chunks/upload-BIEPTIMK.js +0 -2
- package/dist-cli/chunks/version-VITMYQHS.js +0 -4
- package/dist-cli/chunks/web-G5IDDAAI.js +0 -2
package/dist-lib/vite.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! sootsim v0.1.
|
|
1
|
+
/*! sootsim v0.1.252 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
|
|
3
3
|
"use strict";
|
|
4
4
|
var __create = Object.create;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sootsim",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.252",
|
|
4
4
|
"description": "sootsim CLI + vite/metro plugins + skills registry. bridge client for driving the proprietary sootsim-engine over WebSocket.",
|
|
5
5
|
"author": "Tamagui LLC",
|
|
6
6
|
"license": "MIT",
|
|
@@ -171,6 +171,7 @@
|
|
|
171
171
|
}
|
|
172
172
|
},
|
|
173
173
|
"devDependencies": {
|
|
174
|
+
"@contrast/runtime-delivery": "workspace:*",
|
|
174
175
|
"@sootsim/compat": "workspace:*",
|
|
175
176
|
"@sootsim/globals": "workspace:*",
|
|
176
177
|
"@sootsim/skills": "workspace:*",
|
package/src/home-paths.ts
CHANGED
|
@@ -304,46 +304,11 @@ export function writeActiveRuntime(version: string): void {
|
|
|
304
304
|
fs.writeFileSync(activeRuntimeFile(), `${version}\n`, 'utf8')
|
|
305
305
|
}
|
|
306
306
|
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
return fs
|
|
313
|
-
.readdirSync(runtimesDir(), { withFileTypes: true })
|
|
314
|
-
.filter((d) => d.isDirectory())
|
|
315
|
-
.map((d) => d.name)
|
|
316
|
-
.sort(compareSemver)
|
|
317
|
-
} catch {
|
|
318
|
-
return []
|
|
319
|
-
}
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
/** compare two version strings as coarse semver. treats pre-release
|
|
323
|
-
* tags as lower than release of the same major.minor.patch. callers
|
|
324
|
-
* that need strict semver compliance should use a dedicated library. */
|
|
325
|
-
export function compareSemver(a: string, b: string): number {
|
|
326
|
-
const parse = (v: string): [number[], string] => {
|
|
327
|
-
const hyphen = v.indexOf('-')
|
|
328
|
-
const core = hyphen >= 0 ? v.slice(0, hyphen) : v
|
|
329
|
-
const pre = hyphen >= 0 ? v.slice(hyphen + 1) : ''
|
|
330
|
-
const parts = core.split('.').map((n) => Number.parseInt(n, 10))
|
|
331
|
-
if (parts.some((n) => !Number.isFinite(n))) return [[Number.POSITIVE_INFINITY], v]
|
|
332
|
-
return [parts, pre]
|
|
333
|
-
}
|
|
334
|
-
const [an, ap] = parse(a)
|
|
335
|
-
const [bn, bp] = parse(b)
|
|
336
|
-
for (let i = 0; i < Math.max(an.length, bn.length); i++) {
|
|
337
|
-
const av = an[i] ?? 0
|
|
338
|
-
const bv = bn[i] ?? 0
|
|
339
|
-
if (av !== bv) return av - bv
|
|
340
|
-
}
|
|
341
|
-
// pre-release of same core sorts lower than release (empty pre).
|
|
342
|
-
if (ap === bp) return 0
|
|
343
|
-
if (!ap) return 1
|
|
344
|
-
if (!bp) return -1
|
|
345
|
-
return ap < bp ? -1 : 1
|
|
346
|
-
}
|
|
307
|
+
// listInstalledRuntimes + compareSemver live in @contrast/runtime-delivery:
|
|
308
|
+
// they are delivery machinery (sorting the hosted catalog, deciding whether
|
|
309
|
+
// channel latest is newer than active), shared with contrast, and this module
|
|
310
|
+
// stays free of that dependency so every published `sootsim/*` export that
|
|
311
|
+
// resolves through it keeps working with no bundling requirement.
|
|
347
312
|
|
|
348
313
|
/** absolute path to the active runtime's directory, or null if none active
|
|
349
314
|
* or the active version is no longer installed. */
|
package/src/host/bridge-host.ts
CHANGED
|
@@ -18,7 +18,6 @@ import {
|
|
|
18
18
|
claimDaemonLockfile,
|
|
19
19
|
ensureSootsimHome,
|
|
20
20
|
isSootsimDevCheckout,
|
|
21
|
-
listInstalledRuntimes,
|
|
22
21
|
readActiveRuntime,
|
|
23
22
|
readSharedConfig,
|
|
24
23
|
removeDaemonLockfile,
|
|
@@ -33,7 +32,7 @@ import {
|
|
|
33
32
|
type SharedConfig,
|
|
34
33
|
} from '../home-paths.ts'
|
|
35
34
|
import { resolveDevCheckoutRuntimeRoot } from '../runtime-assets.ts'
|
|
36
|
-
import {
|
|
35
|
+
import { sootsimRuntime } from '../runtime-delivery.ts'
|
|
37
36
|
import { AgentHost, type AgentHostOptions } from './agent-host.ts'
|
|
38
37
|
import {
|
|
39
38
|
handleAppApiRequest,
|
|
@@ -650,7 +649,7 @@ export class SootSimBridgeHost {
|
|
|
650
649
|
// are handled in-daemon; install runs entirely inside the CLI so
|
|
651
650
|
// we don't need a daemon-side handler for it.
|
|
652
651
|
if (msg.type === 'runtime:list') {
|
|
653
|
-
const versions =
|
|
652
|
+
const versions = sootsimRuntime.listInstalled()
|
|
654
653
|
const active = this.getActiveRuntime()
|
|
655
654
|
const reply = {
|
|
656
655
|
type: 'runtime:list:ok',
|
|
@@ -666,7 +665,7 @@ export class SootSimBridgeHost {
|
|
|
666
665
|
}
|
|
667
666
|
if (msg.type === 'runtime:use') {
|
|
668
667
|
const version = typeof msg.version === 'string' ? msg.version : ''
|
|
669
|
-
const installed =
|
|
668
|
+
const installed = sootsimRuntime.listInstalled()
|
|
670
669
|
if (!installed.includes(version)) {
|
|
671
670
|
try {
|
|
672
671
|
ws.send(
|
|
@@ -1305,7 +1304,7 @@ export class SootSimBridgeHost {
|
|
|
1305
1304
|
if (reason === 'startup') {
|
|
1306
1305
|
process.stderr.write('sootsim: checking for runtime updates…\n')
|
|
1307
1306
|
}
|
|
1308
|
-
const result = await
|
|
1307
|
+
const result = await sootsimRuntime.updateToLatest()
|
|
1309
1308
|
if (!result.updated || !result.latestVersion) {
|
|
1310
1309
|
if (reason === 'startup') {
|
|
1311
1310
|
process.stderr.write(
|
package/src/runtime-delivery.ts
CHANGED
|
@@ -1,39 +1,27 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
// sootsim's binding of the shared runtime-delivery machinery.
|
|
2
|
+
//
|
|
3
|
+
// the machinery itself (hosted manifest, sha256-verified tarballs, channels,
|
|
4
|
+
// pinning, auto-update) lives in @contrast/runtime-delivery and knows nothing
|
|
5
|
+
// about sootsim. this file supplies sootsim's identity: ~/.sootsim, the
|
|
6
|
+
// SOOTSIM_* env overrides, and the contrast.dev/runtimes hosting layout.
|
|
7
|
+
//
|
|
8
|
+
// @contrast/runtime-delivery is an internal workspace package that is never
|
|
9
|
+
// published, so both the CLI bundle and dist-lib inline it (see the `alias`
|
|
10
|
+
// entry in scripts/build-cli.ts). pack-smoke fails the build if it ever leaks
|
|
11
|
+
// out as a bare require.
|
|
12
|
+
|
|
13
|
+
import { createRuntimeDelivery, type RuntimeProduct } from '@contrast/runtime-delivery'
|
|
7
14
|
import {
|
|
8
15
|
cacheDir,
|
|
9
|
-
compareSemver,
|
|
10
16
|
configFilePath,
|
|
11
17
|
ensureSootsimHome,
|
|
12
18
|
readActiveRuntime,
|
|
13
19
|
runtimeDir,
|
|
20
|
+
runtimesDir,
|
|
14
21
|
writeActiveRuntime,
|
|
15
22
|
} from './home-paths'
|
|
16
23
|
|
|
17
24
|
export const DEFAULT_RUNTIME_CDN_ORIGIN = 'https://contrast.dev'
|
|
18
|
-
export const RUNTIME_CDN_ORIGIN_ENV = 'SOOTSIM_CDN_ORIGIN'
|
|
19
|
-
export const RUNTIME_CHANNEL_ENV = 'SOOTSIM_RUNTIME_CHANNEL'
|
|
20
|
-
export const RUNTIME_PIN_ENV = 'SOOTSIM_RUNTIME_VERSION'
|
|
21
|
-
|
|
22
|
-
export interface RuntimeManifestChannel {
|
|
23
|
-
latest: string
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export interface RuntimeManifestVersion {
|
|
27
|
-
tarball?: string
|
|
28
|
-
sha256: string
|
|
29
|
-
size?: number
|
|
30
|
-
published?: string
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export interface RuntimeManifest {
|
|
34
|
-
channels: Record<string, RuntimeManifestChannel>
|
|
35
|
-
versions: Record<string, RuntimeManifestVersion>
|
|
36
|
-
}
|
|
37
25
|
|
|
38
26
|
/** website URL where the sootsim changelog is rendered. the CLI used to drain
|
|
39
27
|
* a paginated /api/changelog/sootsim endpoint here; the changelog is now a
|
|
@@ -42,356 +30,23 @@ export interface RuntimeManifest {
|
|
|
42
30
|
* notes` points users at the page. */
|
|
43
31
|
export const SOOTSIM_CHANGELOG_URL = 'https://sootsim.com/changelog'
|
|
44
32
|
|
|
45
|
-
export
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
export interface RuntimeUpdateResult {
|
|
64
|
-
checked: boolean
|
|
65
|
-
updated: boolean
|
|
66
|
-
reason?: string
|
|
67
|
-
activeVersion: string | null
|
|
68
|
-
latestVersion?: string
|
|
69
|
-
install?: RuntimeInstallResult
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
interface SootsimConfig {
|
|
73
|
-
runtimeChannel?: string
|
|
74
|
-
runtimeVersion?: string
|
|
75
|
-
cdnOrigin?: string
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
function readConfig(): SootsimConfig {
|
|
79
|
-
try {
|
|
80
|
-
const parsed = JSON.parse(fs.readFileSync(configFilePath(), 'utf8')) as SootsimConfig
|
|
81
|
-
return parsed && typeof parsed === 'object' ? parsed : {}
|
|
82
|
-
} catch {
|
|
83
|
-
return {}
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
export function resolveRuntimeCdnOrigin(input?: string): string {
|
|
88
|
-
const config = readConfig()
|
|
89
|
-
const value =
|
|
90
|
-
input ||
|
|
91
|
-
process.env[RUNTIME_CDN_ORIGIN_ENV] ||
|
|
92
|
-
config.cdnOrigin ||
|
|
93
|
-
DEFAULT_RUNTIME_CDN_ORIGIN
|
|
94
|
-
return value.replace(/\/+$/, '')
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
export function resolveRuntimeChannel(input?: string): string {
|
|
98
|
-
const config = readConfig()
|
|
99
|
-
return input || process.env[RUNTIME_CHANNEL_ENV] || config.runtimeChannel || 'stable'
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
/** pinned runtime version, or null when following the channel's latest.
|
|
103
|
-
* env wins over config so CI can pin per-invocation; the persistent pin
|
|
104
|
-
* lives in ~/.sootsim/config.json (`sootsim runtime pin <version>`). */
|
|
105
|
-
export function resolveRuntimePin(): string | null {
|
|
106
|
-
const env = process.env[RUNTIME_PIN_ENV]
|
|
107
|
-
if (env && env.trim()) return env.trim()
|
|
108
|
-
const config = readConfig()
|
|
109
|
-
return typeof config.runtimeVersion === 'string' && config.runtimeVersion.trim()
|
|
110
|
-
? config.runtimeVersion.trim()
|
|
111
|
-
: null
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
export function runtimeManifestUrl(cdnOrigin?: string): string {
|
|
115
|
-
const url = new URL(`${resolveRuntimeCdnOrigin(cdnOrigin)}/runtimes/manifest.json`)
|
|
116
|
-
// cdn edges can keep the no-query manifest around longer than its
|
|
117
|
-
// max-age. runtime checks need the latest manifest every time.
|
|
118
|
-
url.searchParams.set('t', String(Date.now()))
|
|
119
|
-
return url.toString()
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
export function runtimeTarballUrl(version: string, cdnOrigin?: string): string {
|
|
123
|
-
return `${resolveRuntimeCdnOrigin(cdnOrigin)}/runtimes/sootsim-runtime-${version}.tar.gz`
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
export async function fetchRuntimeManifest(cdnOrigin?: string): Promise<RuntimeManifest> {
|
|
127
|
-
const url = runtimeManifestUrl(cdnOrigin)
|
|
128
|
-
const res = await fetch(url, { headers: { Accept: 'application/json' } })
|
|
129
|
-
if (!res.ok) {
|
|
130
|
-
throw new Error(`manifest fetch failed: ${res.status} ${res.statusText} (${url})`)
|
|
131
|
-
}
|
|
132
|
-
return (await res.json()) as RuntimeManifest
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
export function resolveRuntimeVersion(
|
|
136
|
-
manifest: RuntimeManifest,
|
|
137
|
-
opts: Pick<RuntimeInstallOptions, 'version' | 'channel'> = {},
|
|
138
|
-
): { version: string; channel: string; entry: RuntimeManifestVersion } {
|
|
139
|
-
const channel = resolveRuntimeChannel(opts.channel)
|
|
140
|
-
const version =
|
|
141
|
-
opts.version || resolveRuntimePin() || manifest.channels[channel]?.latest
|
|
142
|
-
if (!version) {
|
|
143
|
-
throw new Error(
|
|
144
|
-
`no version specified and channel '${channel}' has no latest entry in the manifest`,
|
|
145
|
-
)
|
|
146
|
-
}
|
|
147
|
-
const entry = manifest.versions[version]
|
|
148
|
-
if (!entry) {
|
|
149
|
-
throw new Error(
|
|
150
|
-
`version ${version} not found in manifest; available: ${
|
|
151
|
-
Object.keys(manifest.versions).slice(-10).join(', ') || '(none)'
|
|
152
|
-
}`,
|
|
153
|
-
)
|
|
154
|
-
}
|
|
155
|
-
return { version, channel, entry }
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
export async function installRuntime(
|
|
159
|
-
opts: RuntimeInstallOptions = {},
|
|
160
|
-
): Promise<RuntimeInstallResult> {
|
|
161
|
-
ensureSootsimHome()
|
|
162
|
-
|
|
163
|
-
const cdnOrigin = resolveRuntimeCdnOrigin(opts.cdnOrigin)
|
|
164
|
-
const manifest = await fetchRuntimeManifest(cdnOrigin)
|
|
165
|
-
const { version, channel, entry } = resolveRuntimeVersion(manifest, opts)
|
|
166
|
-
const destDir = runtimeDir(version)
|
|
167
|
-
const setActive = opts.setActive !== false
|
|
168
|
-
|
|
169
|
-
if (!opts.force && fs.existsSync(path.join(destDir, 'index.html'))) {
|
|
170
|
-
if (setActive) writeActiveRuntime(version)
|
|
171
|
-
return {
|
|
172
|
-
version,
|
|
173
|
-
channel,
|
|
174
|
-
cdnOrigin,
|
|
175
|
-
runtimeDir: destDir,
|
|
176
|
-
installed: false,
|
|
177
|
-
activated: setActive,
|
|
178
|
-
manifest,
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
const tarUrl = entry.tarball || runtimeTarballUrl(version, cdnOrigin)
|
|
183
|
-
const tarCachePath = path.join(cacheDir(), `sootsim-runtime-${version}.tar.gz`)
|
|
184
|
-
process.stderr.write(`sootsim: downloading runtime ${version}…\n`)
|
|
185
|
-
await downloadToFile(tarUrl, tarCachePath)
|
|
186
|
-
process.stderr.write(`sootsim: extracting runtime ${version}…\n`)
|
|
187
|
-
|
|
188
|
-
const actualSha = await sha256File(tarCachePath)
|
|
189
|
-
if (actualSha !== entry.sha256) {
|
|
190
|
-
fs.rmSync(tarCachePath, { force: true })
|
|
191
|
-
throw new Error(
|
|
192
|
-
`sha256 mismatch for runtime ${version}: expected ${entry.sha256}, actual ${actualSha}`,
|
|
193
|
-
)
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
const tmpDir = path.join(path.dirname(destDir), `.installing-${version}-${process.pid}`)
|
|
197
|
-
fs.rmSync(tmpDir, { recursive: true, force: true })
|
|
198
|
-
fs.mkdirSync(tmpDir, { recursive: true })
|
|
199
|
-
try {
|
|
200
|
-
await extractTarball(tarCachePath, tmpDir)
|
|
201
|
-
if (!fs.existsSync(path.join(tmpDir, 'index.html'))) {
|
|
202
|
-
throw new Error(`extracted tarball for runtime ${version} is missing index.html`)
|
|
203
|
-
}
|
|
204
|
-
fs.rmSync(destDir, { recursive: true, force: true })
|
|
205
|
-
fs.renameSync(tmpDir, destDir)
|
|
206
|
-
} catch (err) {
|
|
207
|
-
fs.rmSync(tmpDir, { recursive: true, force: true })
|
|
208
|
-
throw err
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
if (setActive) writeActiveRuntime(version)
|
|
212
|
-
return {
|
|
213
|
-
version,
|
|
214
|
-
channel,
|
|
215
|
-
cdnOrigin,
|
|
216
|
-
runtimeDir: destDir,
|
|
217
|
-
installed: true,
|
|
218
|
-
activated: setActive,
|
|
219
|
-
manifest,
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
export async function updateRuntimeToLatest(
|
|
224
|
-
opts: Pick<RuntimeInstallOptions, 'channel' | 'cdnOrigin'> = {},
|
|
225
|
-
): Promise<RuntimeUpdateResult> {
|
|
226
|
-
ensureSootsimHome()
|
|
227
|
-
const cdnOrigin = resolveRuntimeCdnOrigin(opts.cdnOrigin)
|
|
228
|
-
const channel = resolveRuntimeChannel(opts.channel)
|
|
229
|
-
|
|
230
|
-
// a pinned runtime never follows the channel. when the pin is already
|
|
231
|
-
// active + on disk this is a no-network no-op; otherwise install exactly
|
|
232
|
-
// the pinned version (it must still exist in the hosted manifest).
|
|
233
|
-
const pin = resolveRuntimePin()
|
|
234
|
-
if (pin) {
|
|
235
|
-
const activeVersion = readActiveRuntime()
|
|
236
|
-
const pinInstalled = fs.existsSync(path.join(runtimeDir(pin), 'index.html'))
|
|
237
|
-
if (activeVersion === pin && pinInstalled) {
|
|
238
|
-
return {
|
|
239
|
-
checked: true,
|
|
240
|
-
updated: false,
|
|
241
|
-
reason: `runtime is pinned to ${pin}`,
|
|
242
|
-
activeVersion,
|
|
243
|
-
latestVersion: pin,
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
const install = await installRuntime({
|
|
247
|
-
version: pin,
|
|
248
|
-
channel,
|
|
249
|
-
cdnOrigin,
|
|
250
|
-
setActive: false,
|
|
251
|
-
})
|
|
252
|
-
return {
|
|
253
|
-
checked: true,
|
|
254
|
-
updated: true,
|
|
255
|
-
reason: `runtime is pinned to ${pin}`,
|
|
256
|
-
activeVersion: pin,
|
|
257
|
-
latestVersion: pin,
|
|
258
|
-
install,
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
const manifest = await fetchRuntimeManifest(cdnOrigin)
|
|
263
|
-
const latestVersion = manifest.channels[channel]?.latest
|
|
264
|
-
if (!latestVersion) {
|
|
265
|
-
return {
|
|
266
|
-
checked: true,
|
|
267
|
-
updated: false,
|
|
268
|
-
reason: `channel '${channel}' has no latest runtime`,
|
|
269
|
-
activeVersion: readActiveRuntime(),
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
const entry = manifest.versions[latestVersion]
|
|
273
|
-
if (!entry) {
|
|
274
|
-
return {
|
|
275
|
-
checked: true,
|
|
276
|
-
updated: false,
|
|
277
|
-
reason: `manifest is missing version ${latestVersion}`,
|
|
278
|
-
activeVersion: readActiveRuntime(),
|
|
279
|
-
latestVersion,
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
const activeVersion = readActiveRuntime()
|
|
284
|
-
const activeDir = activeVersion ? runtimeDir(activeVersion) : null
|
|
285
|
-
const activeInstalled = activeDir
|
|
286
|
-
? fs.existsSync(path.join(activeDir, 'index.html'))
|
|
287
|
-
: false
|
|
288
|
-
const shouldInstall =
|
|
289
|
-
!activeVersion || !activeInstalled || compareSemver(latestVersion, activeVersion) > 0
|
|
290
|
-
|
|
291
|
-
if (!shouldInstall) {
|
|
292
|
-
return {
|
|
293
|
-
checked: true,
|
|
294
|
-
updated: false,
|
|
295
|
-
reason: 'active runtime is current',
|
|
296
|
-
activeVersion,
|
|
297
|
-
latestVersion,
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
// setActive=false: callers like the daemon flip the active runtime
|
|
302
|
-
// themselves so they can broadcast runtime:changed to connected
|
|
303
|
-
// browsers. CLI install uses installRuntime() directly with
|
|
304
|
-
// setActive=true and is unaffected.
|
|
305
|
-
const install = await installRuntime({
|
|
306
|
-
version: latestVersion,
|
|
307
|
-
channel,
|
|
308
|
-
cdnOrigin,
|
|
309
|
-
setActive: false,
|
|
310
|
-
})
|
|
311
|
-
return {
|
|
312
|
-
checked: true,
|
|
313
|
-
updated: true,
|
|
314
|
-
activeVersion: latestVersion,
|
|
315
|
-
latestVersion,
|
|
316
|
-
install,
|
|
317
|
-
}
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
export interface RuntimeUpToDateCheck {
|
|
321
|
-
active: string | null
|
|
322
|
-
latest: string | null
|
|
323
|
-
// pinned version when one is set — a pinned runtime is only "outdated"
|
|
324
|
-
// when the pin itself isn't active yet, never against channel latest.
|
|
325
|
-
pinned: string | null
|
|
326
|
-
// true only when a target version is known and it is newer than / not
|
|
327
|
-
// the active one (or nothing is active yet). network failures resolve
|
|
328
|
-
// to false so callers can treat this as a best-effort hint.
|
|
329
|
-
outdated: boolean
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
/** read-only check: is the active runtime the latest on its channel (or,
|
|
333
|
-
* when pinned, the pin)? unlike updateRuntimeToLatest this never downloads
|
|
334
|
-
* or activates — it's for surfacing a "newer runtime available" hint at
|
|
335
|
-
* startup / in help. */
|
|
336
|
-
export async function checkRuntimeUpToDate(
|
|
337
|
-
opts: Pick<RuntimeInstallOptions, 'channel' | 'cdnOrigin'> = {},
|
|
338
|
-
): Promise<RuntimeUpToDateCheck> {
|
|
339
|
-
const active = readActiveRuntime()
|
|
340
|
-
const pinned = resolveRuntimePin()
|
|
341
|
-
if (pinned) {
|
|
342
|
-
return { active, latest: pinned, pinned, outdated: active !== pinned }
|
|
343
|
-
}
|
|
344
|
-
try {
|
|
345
|
-
const manifest = await fetchRuntimeManifest(resolveRuntimeCdnOrigin(opts.cdnOrigin))
|
|
346
|
-
const channel = resolveRuntimeChannel(opts.channel)
|
|
347
|
-
const latest = manifest.channels[channel]?.latest ?? null
|
|
348
|
-
const outdated = !!(latest && (!active || compareSemver(latest, active) > 0))
|
|
349
|
-
return { active, latest, pinned: null, outdated }
|
|
350
|
-
} catch {
|
|
351
|
-
return { active, latest: null, pinned: null, outdated: false }
|
|
352
|
-
}
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
async function downloadToFile(url: string, destPath: string): Promise<void> {
|
|
356
|
-
const res = await fetch(url)
|
|
357
|
-
if (!res.ok || !res.body) {
|
|
358
|
-
throw new Error(`download failed: ${res.status} ${res.statusText} (${url})`)
|
|
359
|
-
}
|
|
360
|
-
fs.mkdirSync(path.dirname(destPath), { recursive: true })
|
|
361
|
-
const tmp = `${destPath}.partial`
|
|
362
|
-
try {
|
|
363
|
-
await pipeline(
|
|
364
|
-
Readable.fromWeb(res.body as unknown as Parameters<typeof Readable.fromWeb>[0]),
|
|
365
|
-
fs.createWriteStream(tmp),
|
|
366
|
-
)
|
|
367
|
-
fs.renameSync(tmp, destPath)
|
|
368
|
-
} catch (err) {
|
|
369
|
-
try {
|
|
370
|
-
fs.unlinkSync(tmp)
|
|
371
|
-
} catch {}
|
|
372
|
-
throw err
|
|
373
|
-
}
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
function sha256File(filePath: string): Promise<string> {
|
|
377
|
-
return new Promise((resolve, reject) => {
|
|
378
|
-
const hash = crypto.createHash('sha256')
|
|
379
|
-
const stream = fs.createReadStream(filePath)
|
|
380
|
-
stream.on('data', (chunk) => hash.update(chunk))
|
|
381
|
-
stream.on('error', reject)
|
|
382
|
-
stream.on('end', () => resolve(hash.digest('hex')))
|
|
383
|
-
})
|
|
33
|
+
export const SOOTSIM_RUNTIME_PRODUCT: RuntimeProduct = {
|
|
34
|
+
id: 'sootsim',
|
|
35
|
+
defaultCdnOrigin: DEFAULT_RUNTIME_CDN_ORIGIN,
|
|
36
|
+
manifestPath: '/runtimes/manifest.json',
|
|
37
|
+
tarballPath: (version) => `/runtimes/sootsim-runtime-${version}.tar.gz`,
|
|
38
|
+
env: {
|
|
39
|
+
cdnOrigin: 'SOOTSIM_CDN_ORIGIN',
|
|
40
|
+
channel: 'SOOTSIM_RUNTIME_CHANNEL',
|
|
41
|
+
pin: 'SOOTSIM_RUNTIME_VERSION',
|
|
42
|
+
},
|
|
43
|
+
ensureHome: ensureSootsimHome,
|
|
44
|
+
configFile: configFilePath,
|
|
45
|
+
runtimesDir,
|
|
46
|
+
runtimeDir,
|
|
47
|
+
cacheDir,
|
|
48
|
+
readActiveRuntime,
|
|
49
|
+
writeActiveRuntime,
|
|
384
50
|
}
|
|
385
51
|
|
|
386
|
-
|
|
387
|
-
return new Promise((resolve, reject) => {
|
|
388
|
-
const child = spawn('tar', ['-xzf', tarPath, '-C', destDir], {
|
|
389
|
-
stdio: ['ignore', 'inherit', 'inherit'],
|
|
390
|
-
})
|
|
391
|
-
child.on('error', reject)
|
|
392
|
-
child.on('exit', (code) => {
|
|
393
|
-
if (code === 0) resolve()
|
|
394
|
-
else reject(new Error(`tar exited with code ${code}`))
|
|
395
|
-
})
|
|
396
|
-
})
|
|
397
|
-
}
|
|
52
|
+
export const sootsimRuntime = createRuntimeDelivery(SOOTSIM_RUNTIME_PRODUCT)
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
/*! sootsim v0.1.250 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
|
-
import{G as R,H as d,I as x,K as w,l as g,u as $,x as b}from"./chunk-TJBXFUCI.js";import{spawn as E}from"child_process";import k from"crypto";import o from"fs";import u from"path";import{Readable as C}from"stream";import{pipeline as T}from"stream/promises";var _="https://contrast.dev",U="SOOTSIM_CDN_ORIGIN",D="SOOTSIM_RUNTIME_CHANNEL",P="SOOTSIM_RUNTIME_VERSION",X="https://sootsim.com/changelog";function y(){try{let t=JSON.parse(o.readFileSync(b(),"utf8"));return t&&typeof t=="object"?t:{}}catch{return{}}}function f(t){let n=y();return(t||process.env[U]||n.cdnOrigin||_).replace(/\/+$/,"")}function S(t){let n=y();return t||process.env[D]||n.runtimeChannel||"stable"}function O(){let t=process.env[P];if(t&&t.trim())return t.trim();let n=y();return typeof n.runtimeVersion=="string"&&n.runtimeVersion.trim()?n.runtimeVersion.trim():null}function A(t){let n=new URL(`${f(t)}/runtimes/manifest.json`);return n.searchParams.set("t",String(Date.now())),n.toString()}function j(t,n){return`${f(n)}/runtimes/sootsim-runtime-${t}.tar.gz`}async function I(t){let n=A(t),r=await fetch(n,{headers:{Accept:"application/json"}});if(!r.ok)throw new Error(`manifest fetch failed: ${r.status} ${r.statusText} (${n})`);return await r.json()}function L(t,n={}){let r=S(n.channel),e=n.version||O()||t.channels[r]?.latest;if(!e)throw new Error(`no version specified and channel '${r}' has no latest entry in the manifest`);let s=t.versions[e];if(!s)throw new Error(`version ${e} not found in manifest; available: ${Object.keys(t.versions).slice(-10).join(", ")||"(none)"}`);return{version:e,channel:r,entry:s}}async function N(t={}){R();let n=f(t.cdnOrigin),r=await I(n),{version:e,channel:s,entry:i}=L(r,t),c=g(e),a=t.setActive!==!1;if(!t.force&&o.existsSync(u.join(c,"index.html")))return a&&x(e),{version:e,channel:s,cdnOrigin:n,runtimeDir:c,installed:!1,activated:a,manifest:r};let h=i.tarball||j(e,n),m=u.join($(),`sootsim-runtime-${e}.tar.gz`);process.stderr.write(`sootsim: downloading runtime ${e}\u2026
|
|
3
|
-
`),await F(h,m),process.stderr.write(`sootsim: extracting runtime ${e}\u2026
|
|
4
|
-
`);let v=await G(m);if(v!==i.sha256)throw o.rmSync(m,{force:!0}),new Error(`sha256 mismatch for runtime ${e}: expected ${i.sha256}, actual ${v}`);let l=u.join(u.dirname(c),`.installing-${e}-${process.pid}`);o.rmSync(l,{recursive:!0,force:!0}),o.mkdirSync(l,{recursive:!0});try{if(await H(m,l),!o.existsSync(u.join(l,"index.html")))throw new Error(`extracted tarball for runtime ${e} is missing index.html`);o.rmSync(c,{recursive:!0,force:!0}),o.renameSync(l,c)}catch(p){throw o.rmSync(l,{recursive:!0,force:!0}),p}return a&&x(e),{version:e,channel:s,cdnOrigin:n,runtimeDir:c,installed:!0,activated:a,manifest:r}}async function Y(t={}){R();let n=f(t.cdnOrigin),r=S(t.channel),e=O();if(e){let p=d(),V=o.existsSync(u.join(g(e),"index.html"));if(p===e&&V)return{checked:!0,updated:!1,reason:`runtime is pinned to ${e}`,activeVersion:p,latestVersion:e};let M=await N({version:e,channel:r,cdnOrigin:n,setActive:!1});return{checked:!0,updated:!0,reason:`runtime is pinned to ${e}`,activeVersion:e,latestVersion:e,install:M}}let s=await I(n),i=s.channels[r]?.latest;if(!i)return{checked:!0,updated:!1,reason:`channel '${r}' has no latest runtime`,activeVersion:d()};if(!s.versions[i])return{checked:!0,updated:!1,reason:`manifest is missing version ${i}`,activeVersion:d(),latestVersion:i};let a=d(),h=a?g(a):null,m=h?o.existsSync(u.join(h,"index.html")):!1;if(!(!a||!m||w(i,a)>0))return{checked:!0,updated:!1,reason:"active runtime is current",activeVersion:a,latestVersion:i};let l=await N({version:i,channel:r,cdnOrigin:n,setActive:!1});return{checked:!0,updated:!0,activeVersion:i,latestVersion:i,install:l}}async function Z(t={}){let n=d(),r=O();if(r)return{active:n,latest:r,pinned:r,outdated:n!==r};try{let e=await I(f(t.cdnOrigin)),s=S(t.channel),i=e.channels[s]?.latest??null,c=!!(i&&(!n||w(i,n)>0));return{active:n,latest:i,pinned:null,outdated:c}}catch{return{active:n,latest:null,pinned:null,outdated:!1}}}async function F(t,n){let r=await fetch(t);if(!r.ok||!r.body)throw new Error(`download failed: ${r.status} ${r.statusText} (${t})`);o.mkdirSync(u.dirname(n),{recursive:!0});let e=`${n}.partial`;try{await T(C.fromWeb(r.body),o.createWriteStream(e)),o.renameSync(e,n)}catch(s){try{o.unlinkSync(e)}catch{}throw s}}function G(t){return new Promise((n,r)=>{let e=k.createHash("sha256"),s=o.createReadStream(t);s.on("data",i=>e.update(i)),s.on("error",r),s.on("end",()=>n(e.digest("hex")))})}function H(t,n){return new Promise((r,e)=>{let s=E("tar",["-xzf",t,"-C",n],{stdio:["ignore","inherit","inherit"]});s.on("error",e),s.on("exit",i=>{i===0?r():e(new Error(`tar exited with code ${i}`))})})}export{_ as a,X as b,f as c,S as d,O as e,I as f,N as g,Y as h,Z as i};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
/*! sootsim v0.1.250 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
/*! sootsim v0.1.250 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
/*! sootsim v0.1.250 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
|
-
import{a as k,b as O,c as x,e as m,f as I,g as h}from"./chunk-2UGQF7XX.js";import{d as R}from"./chunk-ZA4K47LA.js";import{G as v,H as a,I as y,J as u,K as b,l as w,z as d}from"./chunk-TJBXFUCI.js";import S from"fs";import{WebSocket as N}from"ws";async function J(t,e={}){let[s,...n]=t;if(!s||s==="--help"||s==="-h"){A();return}switch(s){case"install":return T(n,e);case"list":case"ls":return _(n);case"use":return C(n);case"remove":case"rm":return U(n);case"which":case"active":return E();case"pin":return F(n);case"unpin":return P();case"notes":case"changelog":return G(n);default:console.error(` unknown runtime subcommand: ${s}`),A(),process.exit(1)}}function A(){console.log(`
|
|
3
|
-
sootsim runtime \u2014 manage engine runtimes under ~/.sootsim/runtimes/
|
|
4
|
-
|
|
5
|
-
usage:
|
|
6
|
-
sootsim runtime install [version] install a version (default: pin or channel latest)
|
|
7
|
-
sootsim runtime list show installed + available versions
|
|
8
|
-
sootsim runtime use <version> switch active runtime
|
|
9
|
-
sootsim runtime pin [version] pin the runtime (stops background updates moving it)
|
|
10
|
-
sootsim runtime unpin clear the pin and follow channel latest again
|
|
11
|
-
sootsim runtime remove <version> delete an installed runtime
|
|
12
|
-
sootsim runtime which print active runtime version
|
|
13
|
-
sootsim runtime notes print hosted release notes URL
|
|
14
|
-
|
|
15
|
-
flags:
|
|
16
|
-
--channel <name> channel to resolve 'latest' from (default: stable)
|
|
17
|
-
--force reinstall even if the version is already on disk
|
|
18
|
-
--set-active=false do not switch active runtime after install
|
|
19
|
-
|
|
20
|
-
environment:
|
|
21
|
-
SOOTSIM_CDN_ORIGIN override the CDN base URL (default: ${k})
|
|
22
|
-
|
|
23
|
-
examples:
|
|
24
|
-
sootsim runtime install
|
|
25
|
-
sootsim runtime install 1.2.3
|
|
26
|
-
sootsim runtime install --channel beta
|
|
27
|
-
sootsim runtime use 1.2.3
|
|
28
|
-
sootsim runtime notes
|
|
29
|
-
`)}async function T(t,e){let{version:s,flags:n}=M(t),o=n.channel??e.channel??"stable",l=n.force===!0,r=n.setActive!==!1;v(),console.log("sootsim runtime install"),console.log(` cdn: ${x()}`);try{let i=await h({version:s,channel:o,force:l,setActive:r});console.log(` version: ${i.version} (channel: ${i.channel})`),i.installed?console.log(` installed ${i.version}`):console.log(` already installed at ${i.runtimeDir}`),r&&await f(i.version)}catch(i){console.error(` ${p(i)}`),process.exit(1)}}async function f(t){y(t),console.log(` active: ${t}`),await L(t)||console.log(` (no daemon running \u2014 next sootsim/electron launch will pick up ${t})`)}async function L(t){let{isDaemonLockfileFresh:e,readDaemonLockfile:s}=await import("./home-paths-XIHGBDLL.js"),n=s();if(!e(n))return!1;let o=R();return new Promise(l=>{let r=!1,i=!1,g=D=>{r||(r=!0,l(D))},c=new N(`ws://127.0.0.1:${o}`,{handshakeTimeout:800}),$=setTimeout(()=>{try{c.close()}catch{}g(i)},1500);c.on("open",()=>{try{c.send(JSON.stringify({type:"runtime:use",version:t,id:0})),i=!0}catch{}setTimeout(()=>{try{c.close()}catch{}},100)}),c.on("close",()=>{clearTimeout($),g(i)}),c.on("error",()=>{clearTimeout($),g(!1)})})}async function _(t){v();let e=u(),s=a(),n=m();if(console.log("installed:"),e.length===0)console.log(" (none)");else for(let o of e)console.log(` ${o===s?"*":" "} ${o}${o===n?" (pinned)":""}`);n&&!e.includes(n)&&console.log(`pinned: ${n} (not installed \u2014 run \`sootsim runtime install\`)`);try{let o=await I();console.log("available (latest per channel):");for(let[r,i]of Object.entries(o.channels))console.log(` ${r.padEnd(8)} ${i.latest}`);let l=Object.keys(o.versions).sort(b).reverse();if(l.length>1){console.log("hosted versions:");for(let r of l)console.log(` ${r}`)}}catch(o){console.log(`available: (could not fetch manifest: ${p(o)})`)}}async function C(t){let e=t[0];e||(console.error(" usage: sootsim runtime use <version>"),process.exit(1));let s=u();s.includes(e)||(console.error(` version ${e} is not installed`),console.error(` installed: ${s.join(", ")||"(none)"}`),console.error(` run \`sootsim runtime install ${e}\` first`),process.exit(1)),await f(e)}async function U(t){let e=t[0];e||(console.error(" usage: sootsim runtime remove <version>"),process.exit(1)),a()===e&&(console.error(` cannot remove active runtime ${e}`),console.error(" switch with `sootsim runtime use <other>` first, or install another version"),process.exit(1));let n=w(e);if(!S.existsSync(n)){console.error(` ${e} is not installed`);return}S.rmSync(n,{recursive:!0,force:!0}),console.log(` removed ${e}`)}async function E(){let t=a();if(!t){console.log(" no active runtime");return}console.log(t)}async function F(t){let e=t[0];if(!e){let n=m();n?console.log(` runtime pinned to ${n}`):(console.log(" no pin \u2014 runtime follows channel latest"),console.log(" usage: sootsim runtime pin <version>"));return}if(d({runtimeVersion:e}),console.log(` pinned runtime to ${e}`),u().includes(e)){a()!==e&&await f(e);return}try{let n=await h({version:e,setActive:!1});console.log(n.installed?` installed ${n.version}`:` already installed at ${n.runtimeDir}`),await f(e)}catch(n){console.error(` ${p(n)}`),console.error(` pin saved, but ${e} could not be installed \u2014 check \`sootsim runtime list\` for hosted versions`),process.exit(1)}}async function P(){let t=m();if(!t){console.log(" no pin set");return}d({runtimeVersion:void 0}),console.log(` unpinned (was ${t}) \u2014 runtime follows channel latest again`),console.log(" run `sootsim upgrade` to move to the latest now")}async function G(t){t.length>0&&(console.error(" usage: sootsim runtime notes"),process.exit(1));let e=a();e&&console.log(` active runtime: v${e}`),console.log(` release notes: ${O}`)}function M(t){let e={},s=[];for(let n=0;n<t.length;n++){let o=t[n];if(o==="--channel"&&n+1<t.length){e.channel=t[n+1],n++;continue}if(o.startsWith("--channel=")){e.channel=o.slice(10);continue}if(o==="--force"){e.force=!0;continue}if(o==="--set-active=false"||o==="--no-set-active"){e.setActive=!1;continue}s.push(o)}return{version:s[0]??null,flags:e}}function p(t){return t instanceof Error?t.message:String(t)}export{J as a};
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
/*! sootsim v0.1.250 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
|
-
import{randomUUID as I}from"node:crypto";import r from"node:fs";import{homedir as E}from"node:os";import o from"node:path";var _="SOOTSIM_HOME",P="active",j="daemon.json",F="dev-bridge.json",w="config.json",L=3e4;function u(){let e=process.env[_];return e&&e.length>0?o.resolve(e):o.join(E(),".sootsim")}function R(){if(process.env.SOOTSIM_FORCE_DAEMON_INSTALL==="1")return!1;let e=process.env.SOOTSIM_DEV;if(e==="1"||e==="true")return!0;if(e==="0"||e==="false")return!1;let t=process.argv[1];if(!t)return!1;try{return r.realpathSync(t).includes(`${o.sep}packages${o.sep}sootsim${o.sep}`)}catch{return!1}}function T(){return process.env.SOOTSIM_FORCE_DAEMON_INSTALL==="1"?!1:process.env.IS_TAMAGUI_DEV==="1"}function z(){return R()||T()}function f(){return o.join(u(),"runtimes")}function B(e){return o.join(f(),e)}function O(){return o.join(f(),P)}function D(){return o.join(u(),"electron")}function Q(){return o.join(D(),"userData")}function Z(e){return o.join(D(),e)}function C(){return o.join(u(),"profiles")}function M(){return o.join(u(),"daemon-app")}function $(){return o.join(M(),"SootSim Daemon.app")}function ee(){return o.join($(),"Contents","MacOS","sootsim-daemon")}function U(){return o.join(u(),"cache")}function m(){return o.join(u(),j)}function d(){return o.join(u(),F)}function x(){return o.join(u(),w)}function h(){try{let e=r.readFileSync(x(),"utf8"),t=JSON.parse(e);return t&&typeof t=="object"?t:{}}catch{return{}}}function N(e){l();let t=h(),i={...t,...e};e.settings&&typeof e.settings=="object"&&(i.settings={...t.settings&&typeof t.settings=="object"?t.settings:{},...e.settings});let c=`${x()}.tmp`;return r.writeFileSync(c,`${JSON.stringify(i,null,2)}
|
|
3
|
-
`,"utf8"),r.renameSync(c,x()),i}function te(){return h().telemetry!==!1}function re(){let e=h().anonymousId;if(typeof e=="string"&&e.trim())return e;let t=`anon-cli-${I()}`;return N({anonymousId:t}),t}function ne(e){N({telemetry:e})}function g(){return o.join(u(),"runtime-upgraded.json")}function oe(e){l();let t=`${g()}.tmp`;r.writeFileSync(t,`${JSON.stringify(e)}
|
|
4
|
-
`,"utf8"),r.renameSync(t,g())}function ie(){try{let e=r.readFileSync(g(),"utf8");r.unlinkSync(g());let t=JSON.parse(e);return typeof t?.to!="string"||!t.to?null:{from:typeof t.from=="string"?t.from:null,to:t.to,at:typeof t.at=="number"?t.at:0}}catch{return null}}function l(){r.mkdirSync(u(),{recursive:!0}),r.mkdirSync(f(),{recursive:!0}),r.mkdirSync(D(),{recursive:!0}),r.mkdirSync(C(),{recursive:!0}),r.mkdirSync(U(),{recursive:!0})}function J(){try{let e=r.readFileSync(O(),"utf8").trim();return e.length>0?e:null}catch{return null}}function se(e){r.mkdirSync(f(),{recursive:!0}),r.writeFileSync(O(),`${e}
|
|
5
|
-
`,"utf8")}function ue(){try{return r.readdirSync(f(),{withFileTypes:!0}).filter(e=>e.isDirectory()).map(e=>e.name).sort(V)}catch{return[]}}function V(e,t){let i=s=>{let a=s.indexOf("-"),p=a>=0?s.slice(0,a):s,A=a>=0?s.slice(a+1):"",k=p.split(".").map(b=>Number.parseInt(b,10));return k.some(b=>!Number.isFinite(b))?[[Number.POSITIVE_INFINITY],s]:[k,A]},[c,n]=i(e),[v,S]=i(t);for(let s=0;s<Math.max(c.length,v.length);s++){let a=c[s]??0,p=v[s]??0;if(a!==p)return a-p}return n===S?0:n?S?n<S?-1:1:-1:1}function ce(){let e=J();if(!e)return null;let t=B(e);try{if(r.statSync(t).isDirectory())return t}catch{}return null}var y=16*1024;function H(){try{let e=r.openSync(m(),"r");try{let t=Buffer.alloc(y),i=r.readSync(e,t,0,y,0),c=t.subarray(0,i).toString("utf8"),n=JSON.parse(c);return n&&n.schema===1&&typeof n.pid=="number"&&typeof n.bridgePort=="number"&&typeof n.runtimePort=="number"&&typeof n.startedAt=="number"&&typeof n.heartbeatAt=="number"?n:null}finally{r.closeSync(e)}}catch{return null}}function ae(){try{let e=r.openSync(d(),"r");try{let t=Buffer.alloc(y),i=r.readSync(e,t,0,y,0),c=t.subarray(0,i).toString("utf8"),n=JSON.parse(c);return n&&n.schema===1&&n.source==="vite-dev"&&typeof n.pid=="number"&&typeof n.bridgePort=="number"&&typeof n.runtimePort=="number"&&typeof n.cwd=="string"&&typeof n.startedAt=="number"&&typeof n.heartbeatAt=="number"&&(n.shellPort===void 0||typeof n.shellPort=="number")?n:null}finally{r.closeSync(e)}}catch{return null}}function G(e,t=Date.now()){if(!e||t-e.heartbeatAt>L)return!1;try{return process.kill(e.pid,0),!0}catch{return!1}}function fe(e,t=Date.now()){if(!e||t-e.heartbeatAt>L)return!1;try{return process.kill(e.pid,0),!0}catch{return!1}}function K(e){l();let t=`${m()}.tmp`;r.writeFileSync(t,`${JSON.stringify(e,null,2)}
|
|
6
|
-
`,"utf8"),r.renameSync(t,m())}function le(e){l();let t=`${d()}.tmp`;r.writeFileSync(t,`${JSON.stringify(e,null,2)}
|
|
7
|
-
`,"utf8"),r.renameSync(t,d())}function pe(e){l();let t=H();return t&&G(t)&&t.pid!==e.pid?!1:(K(e),!0)}function me(){try{r.unlinkSync(m())}catch{}}function de(){try{r.unlinkSync(d())}catch{}}export{_ as a,P as b,j as c,F as d,w as e,L as f,u as g,R as h,T as i,z as j,f as k,B as l,O as m,D as n,Q as o,Z as p,C as q,M as r,$ as s,ee as t,U as u,m as v,d as w,x,h as y,N as z,te as A,re as B,ne as C,g as D,oe as E,ie as F,l as G,J as H,se as I,ue as J,V as K,ce as L,H as M,ae as N,G as O,fe as P,K as Q,le as R,pe as S,me as T,de as U};
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
/*! sootsim v0.1.250 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
|
-
import{a,b,c,d,e}from"./chunk-ZBAOOQ7L.js";import"./chunk-RDQ4RP2I.js";import"./chunk-DOOM7A5G.js";import"./chunk-2FGQSNTC.js";import"./chunk-CJMASJXU.js";import"./chunk-RMP6YTMJ.js";import"./chunk-ODXX3PDC.js";import"./chunk-QQDVBF5C.js";import"./chunk-N6WXF6OS.js";import"./chunk-HLDQHWK5.js";import"./chunk-TJBXFUCI.js";import"./chunk-LFRFK56L.js";import"./chunk-L5VG4RQT.js";import"./chunk-OOYVCERU.js";import"./chunk-23DV2XSE.js";export{c as daemonInstall,b as getDaemonServiceStatus,a as runDaemon,d as teardownDaemonService,e as teardownSootsimHome};
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
/*! sootsim v0.1.250 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
|
-
import"./chunk-M7NRJV7O.js";import{f as a,g as b,h as c,i as d,j as e,k as f,l as g,m as h,n as i}from"./chunk-DX6CUGUF.js";import"./chunk-GHJRRNR3.js";import"./chunk-JMJJJQ3N.js";import"./chunk-N6WXF6OS.js";import"./chunk-TJBXFUCI.js";import"./chunk-23DV2XSE.js";export{e as ALL_DRIVERS,i as buildDriverListRows,a as chromiumDriver,b as electronDriver,f as getAllDrivers,g as getDriver,c as playwrightDriver,h as resolveDriver,d as systemDriver};
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
/*! sootsim v0.1.250 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
|
-
import{c,d,e,f,g,h}from"./chunk-S5ILN4OM.js";import"./chunk-ZFJZLRAG.js";import"./chunk-HQVZVJWB.js";import{c as a,d as b}from"./chunk-N52AECUU.js";import"./chunk-TIWQBBA6.js";import"./chunk-7SDQP3K6.js";import"./chunk-HTGCR74O.js";import"./chunk-EJQGI6U6.js";import"./chunk-XBWJ7DPK.js";import"./chunk-J3XNJTO5.js";import"./chunk-DX6CUGUF.js";import"./chunk-GHJRRNR3.js";import"./chunk-KZZFQRPX.js";import"./chunk-YACJ3KQ4.js";import"./chunk-JMJJJQ3N.js";import"./chunk-AWT2ISDX.js";import"./chunk-GXNJSLZM.js";import"./chunk-COON6LFC.js";import"./chunk-ZA4K47LA.js";import"./chunk-G2QKQWCY.js";import"./chunk-RDQ4RP2I.js";import"./chunk-DOOM7A5G.js";import"./chunk-RMP6YTMJ.js";import"./chunk-ODXX3PDC.js";import"./chunk-QQDVBF5C.js";import"./chunk-N6WXF6OS.js";import"./chunk-HLDQHWK5.js";import"./chunk-TJBXFUCI.js";import"./chunk-7CESRUUF.js";import"./chunk-OOYVCERU.js";import"./chunk-23DV2XSE.js";export{e as discoverSootsimUrl,c as getLastFlowPreviewUploadResult,d as getLastFlowTraceSteps,g as hoistLeadingSimFlag,a as parseFlowFile,f as runFlowPlayback,h as runMaestroAuthoring,b as validateFlowFile};
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
/*! sootsim v0.1.250 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
|
-
import{a,b,c}from"./chunk-2FGQSNTC.js";import"./chunk-CJMASJXU.js";import"./chunk-RMP6YTMJ.js";import"./chunk-ODXX3PDC.js";import"./chunk-QQDVBF5C.js";import"./chunk-N6WXF6OS.js";import"./chunk-HLDQHWK5.js";import"./chunk-TJBXFUCI.js";import"./chunk-LFRFK56L.js";import"./chunk-L5VG4RQT.js";import"./chunk-OOYVCERU.js";import"./chunk-23DV2XSE.js";export{c as printCommandHelp,b as printGroupHelp,a as printHelp};
|