sootsim 0.1.295 → 0.1.296
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 +13 -4
- package/dist-cli/bin.js +5 -5
- package/dist-cli/chunks/{agent-ASAYE5YY.js → agent-3F4K6MQK.js} +2 -2
- package/dist-cli/chunks/{agent-wrapper-K2D4Q5AA.js → agent-wrapper-5LLVCQRZ.js} +2 -2
- package/dist-cli/chunks/app-fonts-LPTY7A5G.js +4 -0
- package/dist-cli/chunks/{assert-4FKHHDY7.js → assert-R2ZUXEMS.js} +2 -2
- package/dist-cli/chunks/{auth-BQPOPEFK.js → auth-CA62Q6IS.js} +2 -2
- package/dist-cli/chunks/{beta-3LNYONDF.js → beta-4AXSOQLU.js} +2 -2
- package/dist-cli/chunks/{camera-Y5MZ5V4L.js → camera-Y4RBIONE.js} +2 -2
- package/dist-cli/chunks/{chunk-L7V46673.js → chunk-222Y7NQA.js} +1 -1
- package/dist-cli/chunks/{chunk-6VF477QO.js → chunk-2LQOLMRK.js} +1 -1
- package/dist-cli/chunks/{chunk-S6BEA6OC.js → chunk-2XUKWIAL.js} +1 -1
- package/dist-cli/chunks/{chunk-XQRUWC3F.js → chunk-3PAZJSIG.js} +2 -2
- package/dist-cli/chunks/{chunk-UAZ3NVKO.js → chunk-4MDLYOEI.js} +2 -2
- package/dist-cli/chunks/{chunk-MEYVMDZR.js → chunk-4NFGOGB7.js} +2 -2
- package/dist-cli/chunks/chunk-54TQ3ZGI.js +30 -0
- package/dist-cli/chunks/chunk-5FNPAMP4.js +125 -0
- package/dist-cli/chunks/{chunk-FH7DQ2HB.js → chunk-6C24WCDK.js} +2 -2
- package/dist-cli/chunks/{chunk-T2DHHOWE.js → chunk-74FOMZP7.js} +2 -2
- package/dist-cli/chunks/{chunk-K7LQB4IF.js → chunk-7GQWF7HE.js} +1 -1
- package/dist-cli/chunks/{chunk-RNW36VM5.js → chunk-7V3JNANH.js} +4 -4
- package/dist-cli/chunks/{chunk-SU5WQ4SQ.js → chunk-7YQXQSG7.js} +1 -1
- package/dist-cli/chunks/{chunk-DKS75M2I.js → chunk-AUBP44CY.js} +2 -2
- package/dist-cli/chunks/chunk-B2FB6IYX.js +4 -0
- package/dist-cli/chunks/{chunk-E6DZD6JD.js → chunk-B2LDO55K.js} +1 -1
- package/dist-cli/chunks/{chunk-XCCDO6I2.js → chunk-BVWIR4CD.js} +1 -1
- package/dist-cli/chunks/{chunk-UBIGBHUM.js → chunk-C462URRQ.js} +2 -2
- package/dist-cli/chunks/{chunk-CVDC2ER2.js → chunk-CAAADPRH.js} +2 -2
- package/dist-cli/chunks/{chunk-ETDZQUGI.js → chunk-CDCVWGNU.js} +3 -3
- package/dist-cli/chunks/{chunk-JPPGM6RZ.js → chunk-CS23DQB2.js} +2 -2
- package/dist-cli/chunks/chunk-DUYKBCM7.js +4 -0
- package/dist-cli/chunks/chunk-EISE56VD.js +6 -0
- package/dist-cli/chunks/{chunk-TNKZWHD2.js → chunk-EJ6BAJKX.js} +1 -1
- package/dist-cli/chunks/chunk-F2MS365Z.js +4 -0
- package/dist-cli/chunks/{chunk-I4QJVACX.js → chunk-FROCFR77.js} +1 -1
- package/dist-cli/chunks/{chunk-RV67EC7L.js → chunk-FUPQIX4U.js} +2 -2
- package/dist-cli/chunks/{chunk-U2QPKFOY.js → chunk-G2SO5FPN.js} +2 -2
- package/dist-cli/chunks/chunk-GG5PWLGC.js +4 -0
- package/dist-cli/chunks/chunk-GG6XOQ5P.js +15 -0
- package/dist-cli/chunks/chunk-HSGS2U7P.js +6 -0
- package/dist-cli/chunks/{chunk-7GZ6XF2B.js → chunk-IR3DUBRF.js} +2 -2
- package/dist-cli/chunks/chunk-LHUY46GE.js +4 -0
- package/dist-cli/chunks/{chunk-WFYQNZTT.js → chunk-MDBR4XTV.js} +3 -3
- package/dist-cli/chunks/{chunk-UWFAWMPE.js → chunk-MQ6QX46T.js} +2 -2
- package/dist-cli/chunks/chunk-N3FZRJT7.js +4 -0
- package/dist-cli/chunks/{chunk-QPA44BZC.js → chunk-NEARYPSC.js} +11 -11
- package/dist-cli/chunks/chunk-P7HBJBHH.js +4 -0
- package/dist-cli/chunks/{chunk-7FYIMLU4.js → chunk-PEUWZRXA.js} +17 -17
- package/dist-cli/chunks/{chunk-X5FTDIHQ.js → chunk-QIDFGREY.js} +1 -1
- package/dist-cli/chunks/{chunk-4NJIXTVJ.js → chunk-R65XMN4D.js} +1 -1
- package/dist-cli/chunks/{chunk-Y6FJ5FCY.js → chunk-S5Z4HKWX.js} +1 -1
- package/dist-cli/chunks/chunk-SUJSGGSS.js +23 -0
- package/dist-cli/chunks/{chunk-BX2NUJGR.js → chunk-TIOPG6QZ.js} +1 -1
- package/dist-cli/chunks/chunk-WJVBD2UL.js +9 -0
- package/dist-cli/chunks/{chunk-3WQISFAK.js → chunk-X7B5KJ6N.js} +1 -1
- package/dist-cli/chunks/{chunk-2RI6RC6I.js → chunk-XMVVZCIM.js} +2 -2
- package/dist-cli/chunks/chunk-ZIBKGZJD.js +4 -0
- package/dist-cli/chunks/chunk-ZPBIHFQW.js +12 -0
- package/dist-cli/chunks/cleanup-4RSKYPQ7.js +25 -0
- package/dist-cli/chunks/{cli-version-I6BOBK57.js → cli-version-VZFF7GGM.js} +2 -2
- package/dist-cli/chunks/compat-FABLN4UI.js +20 -0
- package/dist-cli/chunks/config-74J37LKC.js +13 -0
- package/dist-cli/chunks/control-VBK32Y7F.js +4 -0
- package/dist-cli/chunks/daemon-VFO7LRR4.js +4 -0
- package/dist-cli/chunks/{debug-VG2JOF6H.js → debug-AOYA2CLR.js} +3 -3
- package/dist-cli/chunks/{desktop-GH2POW6X.js → desktop-G7XWDCTM.js} +3 -3
- package/dist-cli/chunks/{detox-X6T265L5.js → detox-QXJ3L2ZI.js} +2 -2
- package/dist-cli/chunks/{device-VDOOSAXO.js → device-NZZ5ZT3Q.js} +2 -2
- package/dist-cli/chunks/{diagnose-6D6WNAGL.js → diagnose-5CAEJ42M.js} +2 -2
- package/dist-cli/chunks/disk-cleanup-GZSUZJ6Y.js +4 -0
- package/dist-cli/chunks/drivers-OLJCUSPO.js +4 -0
- package/dist-cli/chunks/{film-UZWYISAB.js → film-C25VRUNC.js} +3 -3
- package/dist-cli/chunks/flow-IW3WUF5D.js +4 -0
- package/dist-cli/chunks/help-GEVJF2DA.js +4 -0
- package/dist-cli/chunks/{hidden-runtime-alias-UGMJ4LJX.js → hidden-runtime-alias-NSLIK6XT.js} +2 -2
- package/dist-cli/chunks/home-paths-OC6JZXIM.js +4 -0
- package/dist-cli/chunks/inspect-KXJNI7CU.js +4 -0
- package/dist-cli/chunks/install-desktop-IYWPRFPB.js +4 -0
- package/dist-cli/chunks/{login-K43TRKUC.js → login-LB4TMM4T.js} +4 -4
- package/dist-cli/chunks/{logout-L43CR6M2.js → logout-33IOBD4X.js} +2 -2
- package/dist-cli/chunks/{maestro-7VZFYLNS.js → maestro-EEVXX536.js} +3 -3
- package/dist-cli/chunks/{maestro-generate-PMYHUVH4.js → maestro-generate-ICPWVXGA.js} +3 -3
- package/dist-cli/chunks/{mode-QQS5XFFX.js → mode-6IXOZDK3.js} +2 -2
- package/dist-cli/chunks/{optional-demo-registry-2V327HDG.js → optional-demo-registry-KBMC7SNI.js} +2 -2
- package/dist-cli/chunks/{perf-CL5P3JVP.js → perf-CTTJSAIJ.js} +2 -2
- package/dist-cli/chunks/{permissions-RGVCEC2B.js → permissions-BFQS4DIY.js} +2 -2
- package/dist-cli/chunks/{record-ASW6UFQT.js → record-MJR5ELHE.js} +3 -3
- package/dist-cli/chunks/report-issue-FMJRNDKH.js +29 -0
- package/dist-cli/chunks/runtime-PV4HH2OB.js +4 -0
- package/dist-cli/chunks/{screenshot-command-FEJGQMQF.js → screenshot-command-MGNASAXR.js} +3 -3
- package/dist-cli/chunks/{screenshots-capture-3JPZ5WMX.js → screenshots-capture-N6PANAVT.js} +2 -2
- package/dist-cli/chunks/serve-RS6TIO7U.js +44 -0
- package/dist-cli/chunks/setup-MFYGYR2F.js +32 -0
- package/dist-cli/chunks/{skills-T6EEX5P6.js → skills-TD35LDKK.js} +2 -2
- package/dist-cli/chunks/{storage-ZFUK4EQA.js → storage-VCFXDJNO.js} +2 -2
- package/dist-cli/chunks/store-VNSTKYBQ.js +4 -0
- package/dist-cli/chunks/telemetry-GPNHSYFF.js +4 -0
- package/dist-cli/chunks/{timeline-EIURYQVC.js → timeline-UJCZAWJV.js} +2 -2
- package/dist-cli/chunks/upgrade-S24NH4YG.js +7 -0
- package/dist-cli/chunks/upload-CCKAO2M5.js +4 -0
- package/dist-cli/chunks/version-IVPWT2ZQ.js +6 -0
- package/dist-cli/chunks/web-6BMWAWJL.js +4 -0
- package/dist-cli/chunks/{what-happened-L5ZN7S5G.js → what-happened-HRHB6ETL.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 +3 -2
- package/dist-lib/detox/index.cjs +1 -1
- package/dist-lib/dev-bundle-resolution.cjs +1 -1
- package/dist-lib/home-paths.cjs +41 -14
- package/dist-lib/host/bridge-host.cjs +215 -84
- 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 +2 -2
- package/dist-lib/jump-to-source-babel.cjs +1 -1
- package/dist-lib/menu.cjs +2 -3
- package/dist-lib/menu.mjs +2 -3
- 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 +2 -2
- package/dist-lib/sdk.cjs +1 -1
- package/dist-lib/sdk.mjs +1 -1
- package/dist-lib/skills.cjs +366 -154
- package/dist-lib/vite.cjs +2 -2
- package/package.json +2 -1
- package/scripts/postinstall.cjs +2 -78
- package/skills/contrast/SKILL.md +1 -0
- package/skills/sootsim-setup/SKILL.md +25 -0
- package/src/config.ts +4 -0
- package/src/disk-cleanup.ts +5 -26
- package/src/home-paths.ts +58 -23
- package/src/host/bridge-host.ts +152 -57
- package/src/menu.ts +0 -1
- package/src/runtime-assets.ts +35 -0
- package/src/runtime-delivery.ts +5 -8
- package/src/skills/builtin/compat-check.ts +32 -65
- package/dist-cli/chunks/app-fonts-36N7AVQ3.js +0 -4
- package/dist-cli/chunks/chunk-4ODQVUBH.js +0 -6
- package/dist-cli/chunks/chunk-4V2KYK5T.js +0 -4
- package/dist-cli/chunks/chunk-7GVBNEQ3.js +0 -9
- package/dist-cli/chunks/chunk-COEKUTWV.js +0 -4
- package/dist-cli/chunks/chunk-D2DU3ROC.js +0 -6
- package/dist-cli/chunks/chunk-DXCQP3VE.js +0 -12
- package/dist-cli/chunks/chunk-HT6WYHQL.js +0 -6
- package/dist-cli/chunks/chunk-I7AWRAXM.js +0 -125
- package/dist-cli/chunks/chunk-OQ7SSRYK.js +0 -4
- package/dist-cli/chunks/chunk-QKZVANQG.js +0 -31
- package/dist-cli/chunks/chunk-TGYZYSDB.js +0 -15
- package/dist-cli/chunks/chunk-TXURXDZN.js +0 -4
- package/dist-cli/chunks/chunk-ZJZYGLJ2.js +0 -4
- package/dist-cli/chunks/cleanup-SMCA44QC.js +0 -25
- package/dist-cli/chunks/compat-FCM2ZQLV.js +0 -35
- package/dist-cli/chunks/config-PZSANSAI.js +0 -13
- package/dist-cli/chunks/control-PM554MHE.js +0 -4
- package/dist-cli/chunks/daemon-5KXEZZLJ.js +0 -4
- package/dist-cli/chunks/disk-cleanup-HTOIDDKK.js +0 -4
- package/dist-cli/chunks/drivers-CKLBQDXG.js +0 -4
- package/dist-cli/chunks/flow-VOS3RKB3.js +0 -4
- package/dist-cli/chunks/help-LVMDERFQ.js +0 -4
- package/dist-cli/chunks/home-paths-3LYT47SY.js +0 -4
- package/dist-cli/chunks/inspect-FHCSOWGQ.js +0 -4
- package/dist-cli/chunks/install-desktop-KLMCVDGZ.js +0 -4
- package/dist-cli/chunks/runtime-GB3ZE27C.js +0 -4
- package/dist-cli/chunks/serve-SYXRHRQO.js +0 -44
- package/dist-cli/chunks/setup-QLGL6MC6.js +0 -99
- package/dist-cli/chunks/store-WCDTSWJC.js +0 -4
- package/dist-cli/chunks/telemetry-D7SL4WW7.js +0 -4
- package/dist-cli/chunks/upgrade-Q7ZGWMCJ.js +0 -6
- package/dist-cli/chunks/upload-7XEICYJX.js +0 -4
- package/dist-cli/chunks/version-PDG4V26R.js +0 -6
- package/dist-cli/chunks/web-AMW2TRWB.js +0 -4
package/dist-lib/vite.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! sootsim v0.1.
|
|
1
|
+
/*! sootsim v0.1.296 | (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;
|
|
@@ -85,7 +85,7 @@ function readDaemonLockfile() {
|
|
|
85
85
|
const bytesRead = import_node_fs.default.readSync(fd, buf, 0, DAEMON_LOCKFILE_MAX_BYTES, 0);
|
|
86
86
|
const raw = buf.subarray(0, bytesRead).toString("utf8");
|
|
87
87
|
const parsed = JSON.parse(raw);
|
|
88
|
-
if (parsed && parsed.schema === 1 && typeof parsed.pid === "number" && typeof parsed.bridgePort === "number" && typeof parsed.runtimePort === "number" && typeof parsed.startedAt === "number" && typeof parsed.heartbeatAt === "number") {
|
|
88
|
+
if (parsed && parsed.schema === 1 && typeof parsed.pid === "number" && typeof parsed.bridgePort === "number" && typeof parsed.runtimePort === "number" && typeof parsed.startedAt === "number" && typeof parsed.heartbeatAt === "number" && (parsed.servedRuntimes === void 0 || Array.isArray(parsed.servedRuntimes) && parsed.servedRuntimes.every((version) => typeof version === "string"))) {
|
|
89
89
|
return parsed;
|
|
90
90
|
}
|
|
91
91
|
return null;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sootsim",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.296",
|
|
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",
|
|
@@ -169,6 +169,7 @@
|
|
|
169
169
|
},
|
|
170
170
|
"dependencies": {
|
|
171
171
|
"@expo/plist": "^0.5.4",
|
|
172
|
+
"jiti": "2.7.0",
|
|
172
173
|
"ws": "^8.18.0"
|
|
173
174
|
},
|
|
174
175
|
"peerDependencies": {
|
package/scripts/postinstall.cjs
CHANGED
|
@@ -1,79 +1,3 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
// runs as a child of npm. failures here are non-fatal; setup/open/runtime
|
|
5
|
-
// commands can install the runtime later.
|
|
6
|
-
//
|
|
7
|
-
// skipped when running as root via sudo: $HOME would be /root, but the user
|
|
8
|
-
// who actually wants the runtime probably isn't root. their first sootsim
|
|
9
|
-
// invocation will install into their own ~/.sootsim instead.
|
|
10
|
-
|
|
11
|
-
const { spawnSync } = require('child_process')
|
|
12
|
-
const fs = require('fs')
|
|
13
|
-
const os = require('os')
|
|
14
|
-
const path = require('path')
|
|
15
|
-
|
|
16
|
-
if (process.env.SOOTSIM_SKIP_POSTINSTALL === '1') {
|
|
17
|
-
process.exit(0)
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
// in dev / workspace installs (i.e. running inside the Contrast monorepo, not
|
|
21
|
-
// installed as a dep), the package dir is `<repo>/packages/sootsim/` rather
|
|
22
|
-
// than `.../node_modules/sootsim/`. skip the runtime fetch in that case —
|
|
23
|
-
// the workspace already has the engine source.
|
|
24
|
-
const pkgDir = path.resolve(__dirname, '..')
|
|
25
|
-
if (!pkgDir.includes(`${path.sep}node_modules${path.sep}`)) {
|
|
26
|
-
process.exit(0)
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
const isRoot = typeof process.getuid === 'function' && process.getuid() === 0
|
|
30
|
-
if (isRoot && process.env.SUDO_USER) {
|
|
31
|
-
console.log(
|
|
32
|
-
'sootsim: postinstall skipped under sudo — runtime will install on first run',
|
|
33
|
-
)
|
|
34
|
-
process.exit(0)
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
const existingActiveRuntime = readExistingActiveRuntime()
|
|
38
|
-
if (existingActiveRuntime) {
|
|
39
|
-
console.log(
|
|
40
|
-
`sootsim: postinstall skipped — active runtime ${existingActiveRuntime} already installed`,
|
|
41
|
-
)
|
|
42
|
-
process.exit(0)
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
const RUNTIME_INSTALL_TIMEOUT_MS = 60_000
|
|
46
|
-
|
|
47
|
-
const bin = path.join(__dirname, '..', 'dist-cli', 'bin.js')
|
|
48
|
-
const res = spawnSync(process.execPath, [bin, 'runtime', 'install'], {
|
|
49
|
-
stdio: 'inherit',
|
|
50
|
-
timeout: RUNTIME_INSTALL_TIMEOUT_MS,
|
|
51
|
-
})
|
|
52
|
-
|
|
53
|
-
if (res.error && res.error.code === 'ETIMEDOUT') {
|
|
54
|
-
// the runtime tarball is ~48MB; on a slow link it does not finish inside the
|
|
55
|
-
// npm-install budget above. say that plainly instead of implying we chose to
|
|
56
|
-
// defer — the user has to run the install themselves for it to complete.
|
|
57
|
-
console.log(
|
|
58
|
-
`sootsim: runtime download did not finish within ${RUNTIME_INSTALL_TIMEOUT_MS / 1000}s, so npm install could return — run \`sootsim upgrade\` to finish it`,
|
|
59
|
-
)
|
|
60
|
-
} else if (res.status !== 0) {
|
|
61
|
-
console.log('sootsim: runtime install deferred to first run')
|
|
62
|
-
}
|
|
63
|
-
process.exit(0)
|
|
64
|
-
|
|
65
|
-
function readExistingActiveRuntime() {
|
|
66
|
-
const home =
|
|
67
|
-
process.env.SOOTSIM_HOME && process.env.SOOTSIM_HOME.length > 0
|
|
68
|
-
? path.resolve(process.env.SOOTSIM_HOME)
|
|
69
|
-
: path.join(os.homedir(), '.sootsim')
|
|
70
|
-
const runtimesDir = path.join(home, 'runtimes')
|
|
71
|
-
try {
|
|
72
|
-
const active = fs.readFileSync(path.join(runtimesDir, 'active'), 'utf8').trim()
|
|
73
|
-
if (!active) return null
|
|
74
|
-
const indexPath = path.join(runtimesDir, active, 'index.html')
|
|
75
|
-
return fs.existsSync(indexPath) ? active : null
|
|
76
|
-
} catch {
|
|
77
|
-
return null
|
|
78
|
-
}
|
|
79
|
-
}
|
|
2
|
+
// npm installs package code only. `sootsim setup` owns runtime and machine
|
|
3
|
+
// changes so installs never download a runtime or register a service implicitly.
|
package/skills/contrast/SKILL.md
CHANGED
|
@@ -52,6 +52,7 @@ automation, inspecting the render tree, and managing sims.
|
|
|
52
52
|
| `sootsim close` | close a connected sim |
|
|
53
53
|
| `sootsim setup` | check local setup and install the recommended bridge daemon |
|
|
54
54
|
| `sootsim compat` | check package compatibility |
|
|
55
|
+
| `sootsim report-issue` | send an explicitly approved compatibility report |
|
|
55
56
|
| `sootsim desktop` | launch or install the desktop companion |
|
|
56
57
|
| `sootsim daemon` | manage the optional background bridge service |
|
|
57
58
|
| `sootsim version` | show the CLI + engine runtime versions you are running |
|
|
@@ -36,6 +36,7 @@ debugging or `/sootsim-test` for writing tests.
|
|
|
36
36
|
|
|
37
37
|
```sh
|
|
38
38
|
sootsim setup # one-time guided setup; installs daemon
|
|
39
|
+
sootsim compat --json # scan the app's native package compatibility
|
|
39
40
|
sootsim open 8081 # load a metro/expo dev server
|
|
40
41
|
sootsim list # confirm exactly one sim is reachable
|
|
41
42
|
sootsim use <id> # pin it for the rest of the workflow
|
|
@@ -59,6 +60,30 @@ sootsim open https://my-app.local # load a hosted bundle
|
|
|
59
60
|
every subsequent command
|
|
60
61
|
- `sootsim get errors 5` and `sootsim get requests 5` are quiet (or the
|
|
61
62
|
warnings are ones you understand)
|
|
63
|
+
- the compatibility scan's partial, unsupported, unknown, and version-mismatched
|
|
64
|
+
packages have been summarized without treating its aggregate score as a pass/fail gate
|
|
65
|
+
|
|
66
|
+
## compatibility feedback requires approval
|
|
67
|
+
|
|
68
|
+
run `sootsim compat --json` from the app project root during setup. if the scan
|
|
69
|
+
identifies a plausible missing SootSim seam, or the running app gives concrete
|
|
70
|
+
evidence that behavior is missing or broken specifically in SootSim, summarize
|
|
71
|
+
the package, expected behavior, actual behavior, and runtime evidence for the
|
|
72
|
+
user. then offer to send that finding with `sootsim report-issue`.
|
|
73
|
+
|
|
74
|
+
**never submit a report automatically or behind the user's back.** wait for an
|
|
75
|
+
explicit yes. only then run this from the app project root:
|
|
76
|
+
|
|
77
|
+
```sh
|
|
78
|
+
sootsim report-issue --yes "<package; expected behavior; actual behavior; runtime evidence>"
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
the command automatically attaches the local compatibility scan plus bounded
|
|
82
|
+
CLI, runtime, operating-system, and architecture metadata. it does not attach
|
|
83
|
+
source files, environment variables, terminal output, logs, screenshots, git
|
|
84
|
+
data, or app data. `--dry-run` previews the attachment summary without sending.
|
|
85
|
+
do not use `--yes` merely because the agent believes a report would be useful;
|
|
86
|
+
it records the user's approval after the offer.
|
|
62
87
|
|
|
63
88
|
## recovery — common failure modes
|
|
64
89
|
|
package/src/config.ts
CHANGED
|
@@ -18,6 +18,8 @@ export type NativeModuleResolution = ModuleResolution | Record<string, any> // d
|
|
|
18
18
|
export interface SootSimConfig<
|
|
19
19
|
Settings extends Record<string, any> = Record<string, any>,
|
|
20
20
|
> {
|
|
21
|
+
// host-only engine selection. omitted means the current stable runtime.
|
|
22
|
+
runtimeVersion?: string
|
|
21
23
|
modules?: Record<string, ModuleResolution>
|
|
22
24
|
turboModules?: Record<string, NativeModuleResolution>
|
|
23
25
|
nativeModules?: Record<string, NativeModuleResolution>
|
|
@@ -61,6 +63,7 @@ export function hasSootSimConfig<
|
|
|
61
63
|
>(config?: SootSimConfig<Settings> | null): config is SootSimConfig<Settings> {
|
|
62
64
|
if (!config) return false
|
|
63
65
|
return (
|
|
66
|
+
(typeof config.runtimeVersion === 'string' && config.runtimeVersion.length > 0) ||
|
|
64
67
|
hasOwnKeys(config.modules as Record<string, unknown> | undefined) ||
|
|
65
68
|
hasOwnKeys(config.turboModules as Record<string, unknown> | undefined) ||
|
|
66
69
|
hasOwnKeys(config.nativeModules as Record<string, unknown> | undefined) ||
|
|
@@ -82,6 +85,7 @@ export function mergeSootSimConfig<
|
|
|
82
85
|
if (!hasSootSimConfig(override)) return base ? { ...base } : undefined
|
|
83
86
|
|
|
84
87
|
return {
|
|
88
|
+
runtimeVersion: override.runtimeVersion ?? base.runtimeVersion,
|
|
85
89
|
modules: { ...(base.modules || {}), ...(override.modules || {}) },
|
|
86
90
|
turboModules: { ...(base.turboModules || {}), ...(override.turboModules || {}) },
|
|
87
91
|
nativeModules: {
|
package/src/disk-cleanup.ts
CHANGED
|
@@ -1,12 +1,7 @@
|
|
|
1
1
|
import fs from 'node:fs'
|
|
2
2
|
import path from 'node:path'
|
|
3
3
|
import { isDisposableBrowserCacheDir } from './browser-cache'
|
|
4
|
-
import {
|
|
5
|
-
ensureSootsimHome,
|
|
6
|
-
isDaemonLockfileFresh,
|
|
7
|
-
readDaemonLockfile,
|
|
8
|
-
sootsimHomeDir,
|
|
9
|
-
} from './home-paths'
|
|
4
|
+
import { ensureSootsimHome, readLiveRuntimeVersions, sootsimHomeDir } from './home-paths'
|
|
10
5
|
import { sootsimRuntime } from './runtime-delivery'
|
|
11
6
|
|
|
12
7
|
const AUTOMATIC_CLEANUP_GENERATION = 1
|
|
@@ -38,7 +33,6 @@ export interface SootsimCleanupOptions {
|
|
|
38
33
|
export interface SootsimCleanupPlan {
|
|
39
34
|
home: string
|
|
40
35
|
activeRuntime: string | null
|
|
41
|
-
pinnedRuntime: string | null
|
|
42
36
|
entries: SootsimCleanupEntry[]
|
|
43
37
|
reclaimableBytes: number
|
|
44
38
|
protectedBytes: number
|
|
@@ -183,18 +177,11 @@ function collectRecordingEntries(
|
|
|
183
177
|
})
|
|
184
178
|
}
|
|
185
179
|
|
|
186
|
-
function inUseRuntimeVersions(): string[] {
|
|
187
|
-
const lock = readDaemonLockfile()
|
|
188
|
-
if (!isDaemonLockfileFresh(lock) || !lock.activeRuntime) return []
|
|
189
|
-
return [lock.activeRuntime]
|
|
190
|
-
}
|
|
191
|
-
|
|
192
180
|
function runtimeEntries(aggressive: boolean): {
|
|
193
181
|
activeRuntime: string | null
|
|
194
|
-
pinnedRuntime: string | null
|
|
195
182
|
entries: SootsimCleanupEntry[]
|
|
196
183
|
} {
|
|
197
|
-
const inUseVersions = new Set(
|
|
184
|
+
const inUseVersions = new Set(readLiveRuntimeVersions())
|
|
198
185
|
const protectVersions = [...inUseVersions]
|
|
199
186
|
const normal = sootsimRuntime.planLocalRetention({
|
|
200
187
|
retainVersions: 2,
|
|
@@ -218,13 +205,9 @@ function runtimeEntries(aggressive: boolean): {
|
|
|
218
205
|
const runtimePath = sootsimRuntime.product.runtimeDir(version)
|
|
219
206
|
let state: SootsimCleanupState = 'retained'
|
|
220
207
|
let detail = 'retained runtime'
|
|
221
|
-
if (
|
|
222
|
-
inUseVersions.has(version) &&
|
|
223
|
-
version !== normal.activeVersion &&
|
|
224
|
-
version !== normal.pinnedVersion
|
|
225
|
-
) {
|
|
208
|
+
if (inUseVersions.has(version) && version !== normal.activeVersion) {
|
|
226
209
|
state = 'in-use'
|
|
227
|
-
detail = 'runtime is
|
|
210
|
+
detail = 'runtime is serving a connected simulator'
|
|
228
211
|
} else if (normallyRemoved.has(version)) {
|
|
229
212
|
state = 'safe'
|
|
230
213
|
detail = 'inactive runtime outside the two-version rollback window'
|
|
@@ -233,8 +216,6 @@ function runtimeEntries(aggressive: boolean): {
|
|
|
233
216
|
detail = 'most recent rollback runtime'
|
|
234
217
|
} else if (version === normal.activeVersion) {
|
|
235
218
|
detail = 'active runtime; always protected'
|
|
236
|
-
} else if (version === normal.pinnedVersion) {
|
|
237
|
-
detail = 'pinned runtime; always protected'
|
|
238
219
|
}
|
|
239
220
|
entries.push({
|
|
240
221
|
path: runtimePath,
|
|
@@ -259,7 +240,6 @@ function runtimeEntries(aggressive: boolean): {
|
|
|
259
240
|
|
|
260
241
|
return {
|
|
261
242
|
activeRuntime: normal.activeVersion,
|
|
262
|
-
pinnedRuntime: normal.pinnedVersion,
|
|
263
243
|
entries,
|
|
264
244
|
}
|
|
265
245
|
}
|
|
@@ -279,7 +259,6 @@ export function planSootsimCleanup(
|
|
|
279
259
|
return {
|
|
280
260
|
home,
|
|
281
261
|
activeRuntime: runtimes.activeRuntime,
|
|
282
|
-
pinnedRuntime: runtimes.pinnedRuntime,
|
|
283
262
|
entries,
|
|
284
263
|
reclaimableBytes: entries.reduce(
|
|
285
264
|
(total, entry) => total + (entry.selected ? entry.bytes : 0),
|
|
@@ -307,7 +286,7 @@ export function applySootsimCleanup(
|
|
|
307
286
|
const retainVersions = options.aggressive === true ? 1 : 2
|
|
308
287
|
sootsimRuntime.pruneLocalRetention({
|
|
309
288
|
retainVersions,
|
|
310
|
-
protectVersions:
|
|
289
|
+
protectVersions: readLiveRuntimeVersions(),
|
|
311
290
|
})
|
|
312
291
|
|
|
313
292
|
for (const entry of plan.entries) {
|
package/src/home-paths.ts
CHANGED
|
@@ -20,8 +20,8 @@
|
|
|
20
20
|
// │ by the next interactive CLI run
|
|
21
21
|
// ├── automatic-cleanup-v1.json completion marker for the one-time safe
|
|
22
22
|
// │ cleanup introduced for legacy unbounded data
|
|
23
|
-
// └── config.json user prefs:
|
|
24
|
-
//
|
|
23
|
+
// └── config.json user prefs: update channel, cdn origin override,
|
|
24
|
+
// telemetry, engine settings
|
|
25
25
|
|
|
26
26
|
import { randomUUID } from 'node:crypto'
|
|
27
27
|
import fs from 'node:fs'
|
|
@@ -167,19 +167,9 @@ export function configFilePath(): string {
|
|
|
167
167
|
// ~/.sootsim/config.json is the single user-level config file every sootsim
|
|
168
168
|
// surface (cli, electron renderer, dev browser via electron ipc) agrees on.
|
|
169
169
|
//
|
|
170
|
-
//
|
|
171
|
-
//
|
|
172
|
-
//
|
|
173
|
-
// "onboardingComplete": true, // sessions. shape mirrors the
|
|
174
|
-
// "betaConsentVersion": 1, // PERSISTED_KEYS slice of
|
|
175
|
-
// "detailedTelemetry": false, // SettingsValues — see
|
|
176
|
-
// ... // sootsim-engine/settings/schema.ts
|
|
177
|
-
// }
|
|
178
|
-
// }
|
|
179
|
-
//
|
|
180
|
-
// telemetry default is opt-in (missing/corrupt config means "enabled") so a
|
|
181
|
-
// fresh install never silently drops error reports. settings default is empty
|
|
182
|
-
// (the engine's getDefaults() fills the rest).
|
|
170
|
+
// privacy preferences live in the nested settings object so the cli, desktop
|
|
171
|
+
// main process, renderer, daemon-served browser, and settings UI all read and
|
|
172
|
+
// write one persisted value per choice.
|
|
183
173
|
|
|
184
174
|
export interface SharedConfig {
|
|
185
175
|
telemetry?: boolean
|
|
@@ -218,8 +208,33 @@ export function writeSharedConfig(patch: Partial<SharedConfig>): SharedConfig {
|
|
|
218
208
|
return next
|
|
219
209
|
}
|
|
220
210
|
|
|
221
|
-
export
|
|
222
|
-
|
|
211
|
+
export interface PrivacyPreferences {
|
|
212
|
+
productAnalytics: boolean
|
|
213
|
+
crashReports: boolean
|
|
214
|
+
configured: boolean
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
export function readPrivacyPreferences(): PrivacyPreferences {
|
|
218
|
+
const settings = readSharedConfig().settings
|
|
219
|
+
const productAnalytics = settings?.productAnalytics
|
|
220
|
+
const crashReports = settings?.crashReports
|
|
221
|
+
return {
|
|
222
|
+
productAnalytics: typeof productAnalytics === 'boolean' ? productAnalytics : true,
|
|
223
|
+
crashReports: typeof crashReports === 'boolean' ? crashReports : true,
|
|
224
|
+
configured:
|
|
225
|
+
typeof productAnalytics === 'boolean' && typeof crashReports === 'boolean',
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
export function writePrivacyPreferences(
|
|
230
|
+
preferences: Pick<PrivacyPreferences, 'productAnalytics' | 'crashReports'>,
|
|
231
|
+
): void {
|
|
232
|
+
writeSharedConfig({
|
|
233
|
+
settings: {
|
|
234
|
+
productAnalytics: preferences.productAnalytics,
|
|
235
|
+
crashReports: preferences.crashReports,
|
|
236
|
+
},
|
|
237
|
+
})
|
|
223
238
|
}
|
|
224
239
|
|
|
225
240
|
// stable per-machine anonymous telemetry id. every signed-out cli used to
|
|
@@ -234,10 +249,6 @@ export function readOrCreateAnonymousId(): string {
|
|
|
234
249
|
return created
|
|
235
250
|
}
|
|
236
251
|
|
|
237
|
-
export function writeTelemetryEnabled(enabled: boolean): void {
|
|
238
|
-
writeSharedConfig({ telemetry: enabled })
|
|
239
|
-
}
|
|
240
|
-
|
|
241
252
|
// --- background-upgrade notice --------------------------------------------
|
|
242
253
|
//
|
|
243
254
|
// the daemon auto-updates the engine runtime in the background (hourly), so
|
|
@@ -342,6 +353,8 @@ export interface DaemonLockfile {
|
|
|
342
353
|
activeRuntime: string | null
|
|
343
354
|
/** absolute path to the active runtime's dist directory, or null. */
|
|
344
355
|
activeRuntimeDir: string | null
|
|
356
|
+
/** repo-selected runtime versions currently served to connected sims. */
|
|
357
|
+
servedRuntimes?: string[]
|
|
345
358
|
/** epoch-ms of daemon start. */
|
|
346
359
|
startedAt: number
|
|
347
360
|
/** epoch-ms of last heartbeat. daemons update this every ~5s; readers
|
|
@@ -369,6 +382,8 @@ export interface DevBridgeLockfile {
|
|
|
369
382
|
startedAt: number
|
|
370
383
|
heartbeatAt: number
|
|
371
384
|
source: 'vite-dev'
|
|
385
|
+
/** repo-selected runtime versions currently served to connected sims. */
|
|
386
|
+
servedRuntimes?: string[]
|
|
372
387
|
}
|
|
373
388
|
|
|
374
389
|
const DAEMON_LOCKFILE_MAX_BYTES = 16 * 1024
|
|
@@ -390,7 +405,10 @@ export function readDaemonLockfile(): DaemonLockfile | null {
|
|
|
390
405
|
typeof parsed.bridgePort === 'number' &&
|
|
391
406
|
typeof parsed.runtimePort === 'number' &&
|
|
392
407
|
typeof parsed.startedAt === 'number' &&
|
|
393
|
-
typeof parsed.heartbeatAt === 'number'
|
|
408
|
+
typeof parsed.heartbeatAt === 'number' &&
|
|
409
|
+
(parsed.servedRuntimes === undefined ||
|
|
410
|
+
(Array.isArray(parsed.servedRuntimes) &&
|
|
411
|
+
parsed.servedRuntimes.every((version) => typeof version === 'string')))
|
|
394
412
|
) {
|
|
395
413
|
return parsed as DaemonLockfile
|
|
396
414
|
}
|
|
@@ -421,7 +439,10 @@ export function readDevBridgeLockfile(): DevBridgeLockfile | null {
|
|
|
421
439
|
typeof parsed.cwd === 'string' &&
|
|
422
440
|
typeof parsed.startedAt === 'number' &&
|
|
423
441
|
typeof parsed.heartbeatAt === 'number' &&
|
|
424
|
-
(parsed.shellPort === undefined || typeof parsed.shellPort === 'number')
|
|
442
|
+
(parsed.shellPort === undefined || typeof parsed.shellPort === 'number') &&
|
|
443
|
+
(parsed.servedRuntimes === undefined ||
|
|
444
|
+
(Array.isArray(parsed.servedRuntimes) &&
|
|
445
|
+
parsed.servedRuntimes.every((version) => typeof version === 'string')))
|
|
425
446
|
) {
|
|
426
447
|
return parsed as DevBridgeLockfile
|
|
427
448
|
}
|
|
@@ -475,6 +496,20 @@ export function isDevBridgeLockfileFresh(
|
|
|
475
496
|
}
|
|
476
497
|
}
|
|
477
498
|
|
|
499
|
+
export function readLiveRuntimeVersions(): string[] {
|
|
500
|
+
const versions = new Set<string>()
|
|
501
|
+
const daemon = readDaemonLockfile()
|
|
502
|
+
if (isDaemonLockfileFresh(daemon)) {
|
|
503
|
+
if (daemon.activeRuntime) versions.add(daemon.activeRuntime)
|
|
504
|
+
for (const version of daemon.servedRuntimes ?? []) versions.add(version)
|
|
505
|
+
}
|
|
506
|
+
const devBridge = readDevBridgeLockfile()
|
|
507
|
+
if (isDevBridgeLockfileFresh(devBridge)) {
|
|
508
|
+
for (const version of devBridge.servedRuntimes ?? []) versions.add(version)
|
|
509
|
+
}
|
|
510
|
+
return [...versions].sort()
|
|
511
|
+
}
|
|
512
|
+
|
|
478
513
|
export function writeDaemonLockfile(data: DaemonLockfile): void {
|
|
479
514
|
ensureSootsimHome()
|
|
480
515
|
const tmp = `${daemonLockfilePath()}.tmp`
|