sootsim 0.1.185 → 0.1.187
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist-cli/bin.js +3 -3
- package/dist-cli/chunks/{agent-VF756RZU.js → agent-LRKJIWBT.js} +2 -2
- package/dist-cli/chunks/{agent-wrapper-IAFL7ROV.js → agent-wrapper-7366QMW3.js} +2 -2
- package/dist-cli/chunks/{app-fonts-VWLEC7ZA.js → app-fonts-WIJGM2Q3.js} +2 -2
- package/dist-cli/chunks/{assert-I55QVGG7.js → assert-XH4UWOXZ.js} +2 -2
- package/dist-cli/chunks/beta-HKL7ZI2G.js +2 -0
- package/dist-cli/chunks/{camera-CYYBJH7W.js → camera-RKBTE4X7.js} +2 -2
- package/dist-cli/chunks/{chunk-4OUQAR34.js → chunk-2YX77KNA.js} +1 -1
- package/dist-cli/chunks/{chunk-TNHF6BON.js → chunk-4MSD5YEY.js} +1 -1
- package/dist-cli/chunks/{chunk-PKZNXDUJ.js → chunk-5MHGK7K5.js} +2 -2
- package/dist-cli/chunks/chunk-6DUOFTWZ.js +118 -0
- package/dist-cli/chunks/chunk-7OSC6Q5I.js +1 -0
- package/dist-cli/chunks/{chunk-TUF6EPCQ.js → chunk-7PXPUUCL.js} +2 -2
- package/dist-cli/chunks/{chunk-FY6DJGOS.js → chunk-7ZCLPWN7.js} +39 -15
- package/dist-cli/chunks/{chunk-LI4RLX6B.js → chunk-A6YGOAVQ.js} +1 -1
- package/dist-cli/chunks/{chunk-LJ3SOZBF.js → chunk-C3TVJ3MM.js} +2 -2
- package/dist-cli/chunks/{chunk-ARNLQPMQ.js → chunk-DVMV4JPO.js} +2 -2
- package/dist-cli/chunks/{chunk-M3P67TBN.js → chunk-ECNEUGXI.js} +1 -1
- package/dist-cli/chunks/{chunk-X4KS33ZC.js → chunk-ED7KWTZI.js} +2 -2
- package/dist-cli/chunks/{chunk-TFZO277G.js → chunk-EUJGZMDY.js} +1 -1
- package/dist-cli/chunks/{chunk-K2THZIVC.js → chunk-EXXEJKHE.js} +1 -1
- package/dist-cli/chunks/{chunk-HQG4DRQ3.js → chunk-FCEZIUSK.js} +1 -1
- package/dist-cli/chunks/{chunk-DZLBZGHN.js → chunk-FCYL4LNR.js} +2 -2
- package/dist-cli/chunks/chunk-FHK4ZNGV.js +5 -0
- package/dist-cli/chunks/{chunk-C3UEINOZ.js → chunk-FN7PINUE.js} +2 -2
- package/dist-cli/chunks/{chunk-NL5IFN4T.js → chunk-FTWRQ4GJ.js} +2 -2
- package/dist-cli/chunks/{chunk-BI56RR3G.js → chunk-FUA7CGJ3.js} +4 -4
- package/dist-cli/chunks/{chunk-EXFB33AZ.js → chunk-FUYTE2KH.js} +2 -2
- package/dist-cli/chunks/{chunk-R4KLD4P4.js → chunk-HCPE77ID.js} +2 -2
- package/dist-cli/chunks/{chunk-2T73IGB2.js → chunk-ILF5TI6Y.js} +2 -2
- package/dist-cli/chunks/{chunk-E5DE33BU.js → chunk-JCVOSH3U.js} +1 -1
- package/dist-cli/chunks/{chunk-WBY4JJ2K.js → chunk-JUAUV4UZ.js} +2 -2
- package/dist-cli/chunks/chunk-L4Z2UJX5.js +2 -0
- package/dist-cli/chunks/{chunk-FUHXL6BW.js → chunk-N64V23HY.js} +1 -1
- package/dist-cli/chunks/{chunk-QQ4NSPAD.js → chunk-NXBBBNH5.js} +2 -2
- package/dist-cli/chunks/{chunk-FHJTTB3W.js → chunk-O67BWHYY.js} +2 -2
- package/dist-cli/chunks/{chunk-C63EVPDN.js → chunk-OXS4KYCN.js} +2 -2
- package/dist-cli/chunks/{chunk-WEJKLJ4B.js → chunk-RFIK5SZF.js} +2 -2
- package/dist-cli/chunks/{chunk-GX6MKIFC.js → chunk-TF6TFVED.js} +1 -1
- package/dist-cli/chunks/chunk-TJMPYMXV.js +382 -0
- package/dist-cli/chunks/{chunk-QTFCJYBF.js → chunk-TXSPFIUO.js} +3 -3
- package/dist-cli/chunks/chunk-UBOHWJ5L.js +987 -0
- package/dist-cli/chunks/chunk-VZ4HTOAC.js +24 -0
- package/dist-cli/chunks/{chunk-BMCBPMTC.js → chunk-WDFDPB4M.js} +1 -1
- package/dist-cli/chunks/{chunk-MADEJDFD.js → chunk-WKGGTXDO.js} +1 -1
- package/dist-cli/chunks/chunk-XFDPG5AN.js +1 -0
- package/dist-cli/chunks/chunk-XJ3ANS4C.js +13 -0
- package/dist-cli/chunks/{chunk-4NUQVW5P.js → chunk-XLAWETKN.js} +17 -6
- package/dist-cli/chunks/{chunk-CYBRFHPU.js → chunk-XVI2A5KE.js} +2 -2
- package/dist-cli/chunks/{chunk-IJP257WP.js → chunk-Y77CNEAC.js} +1 -1
- package/dist-cli/chunks/{chunk-PIUKLO3W.js → chunk-ZR6PIQPZ.js} +1 -1
- package/dist-cli/chunks/cli-version-XGZD3TZF.js +2 -0
- package/dist-cli/chunks/{compat-ZJA3N4ZT.js → compat-XGX4RAXQ.js} +3 -3
- package/dist-cli/chunks/control-M76KO3SL.js +2 -0
- package/dist-cli/chunks/{cpu-profile-ACSQMVXY.js → cpu-profile-YJRYOP7N.js} +2 -2
- package/dist-cli/chunks/daemon-XRE3ZJ3A.js +2 -0
- package/dist-cli/chunks/{debug-W2ZOVTQO.js → debug-W4VWXPA4.js} +9 -6
- package/dist-cli/chunks/{detox-ANJO6T27.js → detox-EGVU4YL6.js} +2 -2
- package/dist-cli/chunks/{device-KPPN4KYD.js → device-XGK2VNF5.js} +2 -2
- package/dist-cli/chunks/{diagnose-5PEJYGES.js → diagnose-DI4BFQBP.js} +2 -2
- package/dist-cli/chunks/drivers-O6BFN76G.js +2 -0
- package/dist-cli/chunks/{electron-U456QLSQ.js → electron-3BE5EPSM.js} +3 -3
- package/dist-cli/chunks/flow-6WB3FX4N.js +2 -0
- package/dist-cli/chunks/help-BXNU6OAS.js +2 -0
- package/dist-cli/chunks/{hints-MBBQLMQU.js → hints-E7NSLFDT.js} +2 -2
- package/dist-cli/chunks/{home-paths-KQKYP2SE.js → home-paths-UASDA6NF.js} +2 -2
- package/dist-cli/chunks/inspect-Z33SVDQJ.js +2 -0
- package/dist-cli/chunks/{install-desktop-OR6ZJ43X.js → install-desktop-KFWZQGHM.js} +3 -3
- package/dist-cli/chunks/{keys-JSQMBUE7.js → keys-C5T4EK3E.js} +2 -2
- package/dist-cli/chunks/{login-DVMWAI3G.js → login-IB6EEROJ.js} +4 -4
- package/dist-cli/chunks/{logout-RIVPFE5N.js → logout-UPNDZL6K.js} +2 -2
- package/dist-cli/chunks/{maestro-TX6FPTVH.js → maestro-IU2V4VZI.js} +2 -2
- package/dist-cli/chunks/optional-demo-registry-P67F7BGJ.js +2 -0
- package/dist-cli/chunks/{preview-3AD7WNA6.js → preview-JBLUMPDD.js} +2 -2
- package/dist-cli/chunks/{profile-HY55VFNR.js → profile-SNBM3CDF.js} +2 -2
- package/dist-cli/chunks/{react-HDRCKCKV.js → react-SDFO4G5R.js} +2 -2
- package/dist-cli/chunks/{record-HW4C7QYN.js → record-ZWXDWCCP.js} +2 -2
- package/dist-cli/chunks/runtime-KQQS4SNR.js +2 -0
- package/dist-cli/chunks/{screenshot-XFR3QN5T.js → screenshot-CVHGCLGS.js} +2 -2
- package/dist-cli/chunks/{screenshot-mode-Y5CVO267.js → screenshot-mode-NDTW64AM.js} +2 -2
- package/dist-cli/chunks/{screenshots-RKUL2ZZT.js → screenshots-V6STBJXN.js} +2 -2
- package/dist-cli/chunks/{screenshots-capture-RVNF75ZD.js → screenshots-capture-6WYQMQ2U.js} +2 -2
- package/dist-cli/chunks/{serve-QMRYLWL5.js → serve-PW4LITPE.js} +16 -16
- package/dist-cli/chunks/{setup-ELNJS7AI.js → setup-CGNDZVXB.js} +3 -3
- package/dist-cli/chunks/{skills-GPSJYS4W.js → skills-KOK2FNL2.js} +2 -2
- package/dist-cli/chunks/{slides-OCFNPIFG.js → slides-3PLFSQMQ.js} +2 -2
- package/dist-cli/chunks/store-FSEOWL7R.js +2 -0
- package/dist-cli/chunks/{telemetry-KFZQUFG5.js → telemetry-B7LYDPT5.js} +2 -2
- package/dist-cli/chunks/telemetry-XACCAQXE.js +2 -0
- package/dist-cli/chunks/{test-Z2HZXCZM.js → test-RE7DJ2VV.js} +3 -3
- package/dist-cli/chunks/{three-mode-NKJFCDYS.js → three-mode-3IDJZUWE.js} +2 -2
- package/dist-cli/chunks/{timeline-PRGQMQRR.js → timeline-VSAVV7SE.js} +2 -2
- package/dist-cli/chunks/{upgrade-3NW7JRRX.js → upgrade-N7F4A22A.js} +2 -2
- package/dist-cli/chunks/upload-5YUE5AXH.js +2 -0
- package/dist-cli/chunks/{version-FDTZRIYT.js → version-NI3AUFKF.js} +2 -2
- package/dist-cli/chunks/{web-4N5QQEQJ.js → web-B4BOB3BY.js} +2 -2
- package/dist-cli/chunks/{what-happened-IX2RRCOS.js → what-happened-J6KHS3NN.js} +2 -2
- package/dist-cli/chunks/{whoami-QZ42FYYF.js → whoami-JX2QC2MC.js} +2 -2
- package/dist-lib/agent-daemon-client.cjs +1 -1
- package/dist-lib/agent-events.cjs +1 -1
- package/dist-lib/agent-sessions.cjs +1 -1
- package/dist-lib/attached-projects.cjs +1 -1
- package/dist-lib/auth/shared-session.cjs +1 -1
- package/dist-lib/backend-origin.cjs +1 -1
- package/dist-lib/beta.cjs +1 -1
- package/dist-lib/beta.mjs +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 +2 -2
- package/dist-lib/host/bridge-host.cjs +77 -44
- 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 +28 -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 +28 -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 +39 -12
- package/dist-lib/sdk.mjs +39 -12
- package/dist-lib/skills.cjs +283 -254
- package/dist-lib/vite.cjs +28 -1
- package/package.json +1 -1
- package/src/home-paths.ts +8 -1
- package/src/host/bridge-host.ts +15 -1
- package/src/runtime-assets.ts +70 -0
- package/src/vite-plugin.ts +9 -0
- package/dist-cli/chunks/beta-X6YPQVZH.js +0 -2
- package/dist-cli/chunks/chunk-7OAUPGLN.js +0 -23
- package/dist-cli/chunks/chunk-IGJHME3T.js +0 -1
- package/dist-cli/chunks/chunk-JRL7PFNZ.js +0 -463
- package/dist-cli/chunks/chunk-KOKIECMB.js +0 -118
- package/dist-cli/chunks/chunk-OAHGYDJR.js +0 -13
- package/dist-cli/chunks/chunk-PDLQWZN4.js +0 -2
- package/dist-cli/chunks/chunk-SL6565MR.js +0 -1
- package/dist-cli/chunks/chunk-V4M2R6FZ.js +0 -2
- package/dist-cli/chunks/chunk-V5JEPE3P.js +0 -5
- package/dist-cli/chunks/chunk-XU5EMZ4B.js +0 -264
- package/dist-cli/chunks/cli-version-ICHQMND6.js +0 -2
- package/dist-cli/chunks/control-CZFSYSYG.js +0 -2
- package/dist-cli/chunks/daemon-337B4P3B.js +0 -2
- package/dist-cli/chunks/drivers-MSDIFHBD.js +0 -2
- package/dist-cli/chunks/flow-JL3SC6HC.js +0 -2
- package/dist-cli/chunks/help-PA4RTR5X.js +0 -2
- package/dist-cli/chunks/inspect-ZP5SM4EW.js +0 -987
- package/dist-cli/chunks/optional-demo-registry-ONYG6DUI.js +0 -2
- package/dist-cli/chunks/runtime-RHHPW5WO.js +0 -2
- package/dist-cli/chunks/store-MBKDUQEQ.js +0 -2
- package/dist-cli/chunks/telemetry-46XXIUEE.js +0 -2
- package/dist-cli/chunks/upload-QVDVJ6ZK.js +0 -2
package/dist-lib/vite.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! sootsim v0.1.
|
|
1
|
+
/*! sootsim v0.1.187 | (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;
|
|
@@ -109,7 +109,32 @@ function isDaemonLockfileFresh(lock, now = Date.now()) {
|
|
|
109
109
|
// src/runtime-assets.ts
|
|
110
110
|
var import_fs = __toESM(require("fs"), 1);
|
|
111
111
|
var import_path = __toESM(require("path"), 1);
|
|
112
|
+
var import_url = require("url");
|
|
112
113
|
var SOOTSIM_RUNTIME_MISSING_MESSAGE = "[sootsim] no engine runtime installed \u2014 run `sootsim setup`, or `sootsim runtime install`";
|
|
114
|
+
var _monorepoRootCache;
|
|
115
|
+
function findMonorepoRoot() {
|
|
116
|
+
if (_monorepoRootCache !== void 0) return _monorepoRootCache;
|
|
117
|
+
let dir = import_path.default.dirname((0, import_url.fileURLToPath)(__sootsim_import_meta_url));
|
|
118
|
+
for (let i = 0; i < 12 && dir !== import_path.default.dirname(dir); i++) {
|
|
119
|
+
if (import_fs.default.existsSync(import_path.default.join(dir, "packages/sootsim-engine/package.json")) && import_fs.default.existsSync(import_path.default.join(dir, "public/sootsim"))) {
|
|
120
|
+
_monorepoRootCache = dir;
|
|
121
|
+
return dir;
|
|
122
|
+
}
|
|
123
|
+
dir = import_path.default.dirname(dir);
|
|
124
|
+
}
|
|
125
|
+
_monorepoRootCache = null;
|
|
126
|
+
return null;
|
|
127
|
+
}
|
|
128
|
+
function resolveDevCheckoutRuntimeRoot() {
|
|
129
|
+
if (process.env.SOOTSIM_HOME && readActiveRuntime()) return null;
|
|
130
|
+
const root = findMonorepoRoot();
|
|
131
|
+
if (!root) return null;
|
|
132
|
+
const devBuild = import_path.default.join(root, "public/sootsim");
|
|
133
|
+
if (import_fs.default.existsSync(import_path.default.join(devBuild, "index.html")) && import_fs.default.existsSync(import_path.default.join(devBuild, "engine/index.html")) && import_fs.default.existsSync(import_path.default.join(devBuild, "engine-tenant/worker.js"))) {
|
|
134
|
+
return devBuild;
|
|
135
|
+
}
|
|
136
|
+
return null;
|
|
137
|
+
}
|
|
113
138
|
var MIME_TYPES = {
|
|
114
139
|
".js": "application/javascript",
|
|
115
140
|
".mjs": "application/javascript",
|
|
@@ -145,6 +170,8 @@ var ROOT_RUNTIME_PATHS = [
|
|
|
145
170
|
"/preview-sw.js"
|
|
146
171
|
];
|
|
147
172
|
function resolveActiveRuntimeRoot() {
|
|
173
|
+
const devRoot = resolveDevCheckoutRuntimeRoot();
|
|
174
|
+
if (devRoot) return devRoot;
|
|
148
175
|
const active = readActiveRuntime();
|
|
149
176
|
if (!active) return null;
|
|
150
177
|
const dir = runtimeDir(active);
|
package/package.json
CHANGED
package/src/home-paths.ts
CHANGED
|
@@ -332,6 +332,12 @@ export interface DevBridgeLockfile {
|
|
|
332
332
|
platform: NodeJS.Platform
|
|
333
333
|
bridgePort: number
|
|
334
334
|
runtimePort: number
|
|
335
|
+
/** http port of the vite shell dev server that owns this bridge (e.g. 5173).
|
|
336
|
+
* optional: lockfiles written before this field existed still parse, and
|
|
337
|
+
* readers fall back to the default shell URL. this is what lets the CLI
|
|
338
|
+
* resolve the shell base URL and the bridge port from the SAME world
|
|
339
|
+
* instead of mixing dev bridge + daemon runtime (the split-brain bug). */
|
|
340
|
+
shellPort?: number
|
|
335
341
|
cwd: string
|
|
336
342
|
startedAt: number
|
|
337
343
|
heartbeatAt: number
|
|
@@ -387,7 +393,8 @@ export function readDevBridgeLockfile(): DevBridgeLockfile | null {
|
|
|
387
393
|
typeof parsed.runtimePort === 'number' &&
|
|
388
394
|
typeof parsed.cwd === 'string' &&
|
|
389
395
|
typeof parsed.startedAt === 'number' &&
|
|
390
|
-
typeof parsed.heartbeatAt === 'number'
|
|
396
|
+
typeof parsed.heartbeatAt === 'number' &&
|
|
397
|
+
(parsed.shellPort === undefined || typeof parsed.shellPort === 'number')
|
|
391
398
|
) {
|
|
392
399
|
return parsed as DevBridgeLockfile
|
|
393
400
|
}
|
package/src/host/bridge-host.ts
CHANGED
|
@@ -30,6 +30,7 @@ import {
|
|
|
30
30
|
type DevBridgeLockfile,
|
|
31
31
|
type SharedConfig,
|
|
32
32
|
} from '../home-paths.ts'
|
|
33
|
+
import { resolveDevCheckoutRuntimeRoot } from '../runtime-assets.ts'
|
|
33
34
|
import { updateRuntimeToLatest } from '../runtime-delivery.ts'
|
|
34
35
|
import { AgentHost, type AgentHostOptions } from './agent-host.ts'
|
|
35
36
|
import {
|
|
@@ -224,6 +225,11 @@ export interface BridgeHostOptions {
|
|
|
224
225
|
* this so local CLI commands prefer the live source bridge over a standalone
|
|
225
226
|
* daemon or stale default-port listener. */
|
|
226
227
|
writeDevLockfile?: boolean
|
|
228
|
+
/** resolve the http port of the vite shell dev server that hosts this
|
|
229
|
+
* bridge (e.g. 5173). called on every dev-lockfile write so the port
|
|
230
|
+
* fills in once the vite server is actually listening. only meaningful
|
|
231
|
+
* with writeDevLockfile. */
|
|
232
|
+
getShellPort?: () => number | null
|
|
227
233
|
/** the sootbean origin this daemon's runtimes should talk to for auth,
|
|
228
234
|
* billing, and preview uploads — inlined into served runtime html as
|
|
229
235
|
* `window.__sootsimSootbeanOrigin`. without it the engine's origin.ts
|
|
@@ -397,6 +403,7 @@ export class SootSimBridgeHost {
|
|
|
397
403
|
private automationSimActiveGraceMs: number
|
|
398
404
|
private shouldWriteLockfile: boolean
|
|
399
405
|
private shouldWriteDevLockfile: boolean
|
|
406
|
+
private getShellPort: (() => number | null) | null
|
|
400
407
|
private sootbeanOrigin: string | null = null
|
|
401
408
|
private effectivePort = 0
|
|
402
409
|
private startedAt = 0
|
|
@@ -431,6 +438,7 @@ export class SootSimBridgeHost {
|
|
|
431
438
|
// default off — callers that want the lockfile (sootsim serve) opt in.
|
|
432
439
|
this.shouldWriteLockfile = opts.writeLockfile === true
|
|
433
440
|
this.shouldWriteDevLockfile = opts.writeDevLockfile === true
|
|
441
|
+
this.getShellPort = opts.getShellPort ?? null
|
|
434
442
|
// fallback freely on port collision regardless of who owns the lockfile.
|
|
435
443
|
// serve.ts already refuses to start if a fresh daemon.json exists, so
|
|
436
444
|
// two daemons can't race the lockfile. without this, an unrelated process
|
|
@@ -1164,12 +1172,14 @@ export class SootSimBridgeHost {
|
|
|
1164
1172
|
}
|
|
1165
1173
|
|
|
1166
1174
|
private buildDevLockfileSnapshot(): DevBridgeLockfile {
|
|
1175
|
+
const shellPort = this.getShellPort?.() ?? null
|
|
1167
1176
|
return {
|
|
1168
1177
|
schema: 1,
|
|
1169
1178
|
pid: process.pid,
|
|
1170
1179
|
platform: process.platform,
|
|
1171
1180
|
bridgePort: this.effectivePort,
|
|
1172
1181
|
runtimePort: this.effectivePort,
|
|
1182
|
+
...(shellPort && shellPort > 0 ? { shellPort } : {}),
|
|
1173
1183
|
cwd: process.cwd(),
|
|
1174
1184
|
startedAt: this.startedAt,
|
|
1175
1185
|
heartbeatAt: Date.now(),
|
|
@@ -1187,7 +1197,11 @@ export class SootSimBridgeHost {
|
|
|
1187
1197
|
|
|
1188
1198
|
private refreshActiveRuntime() {
|
|
1189
1199
|
this.activeRuntimeVersion = readActiveRuntime()
|
|
1190
|
-
|
|
1200
|
+
// mode boundary (see runtime-assets resolveDevCheckoutRuntimeRoot): inside
|
|
1201
|
+
// the soot monorepo dev checkout serve the fresh dev-stack build so local
|
|
1202
|
+
// engine edits reach previews without a publish; otherwise the installed
|
|
1203
|
+
// runtime. the version above stays the installed version for display.
|
|
1204
|
+
this.activeRuntimeDirPath = resolveDevCheckoutRuntimeRoot() ?? getActiveRuntimeDir()
|
|
1191
1205
|
}
|
|
1192
1206
|
|
|
1193
1207
|
private runServerScan(): Promise<DiscoveredServer[]> {
|
package/src/runtime-assets.ts
CHANGED
|
@@ -4,11 +4,78 @@
|
|
|
4
4
|
|
|
5
5
|
import fs from 'fs'
|
|
6
6
|
import path from 'path'
|
|
7
|
+
import { fileURLToPath } from 'url'
|
|
7
8
|
import { readActiveRuntime, runtimeDir } from './home-paths'
|
|
8
9
|
|
|
9
10
|
export const SOOTSIM_RUNTIME_MISSING_MESSAGE =
|
|
10
11
|
'[sootsim] no engine runtime installed — run `sootsim setup`, or `sootsim runtime install`'
|
|
11
12
|
|
|
13
|
+
// --- dev-checkout mode boundary --------------------------------------------
|
|
14
|
+
//
|
|
15
|
+
// there is exactly one rule for which engine gets served: INSIDE the soot
|
|
16
|
+
// monorepo dev checkout the fresh dev-stack build (public/sootsim, kept current
|
|
17
|
+
// by `bun dev`'s watch:sootsim) IS the engine; OUTSIDE it (a published CLI in a
|
|
18
|
+
// user's project, or an isolated home) the installed runtime IS. this is a mode
|
|
19
|
+
// boundary, not a preference or a runtime fallback chain — the check is
|
|
20
|
+
// structural (the monorepo layout is present next to this module) and
|
|
21
|
+
// deterministic (the dev build's files exist). it exists because the daemon and
|
|
22
|
+
// the /__soot plugin otherwise serve ~/.sootsim/runtimes/<active>, a PUBLISHED
|
|
23
|
+
// runtime that `bun dev` never refreshes, so local engine edits are invisible
|
|
24
|
+
// until a manual publish — the silent trap that cost a full night of
|
|
25
|
+
// already-fixed bugs re-reproducing.
|
|
26
|
+
//
|
|
27
|
+
// the isolated CI headless path (scripts/local-publish-runtime.sh) sets
|
|
28
|
+
// SOOTSIM_HOME to a dedicated dir precisely to validate the published-runtime
|
|
29
|
+
// code path; keying off that EXISTING isolation env keeps it (and packaged
|
|
30
|
+
// electron with a custom home) on the installed runtime.
|
|
31
|
+
let _monorepoRootCache: string | null | undefined
|
|
32
|
+
|
|
33
|
+
function findMonorepoRoot(): string | null {
|
|
34
|
+
if (_monorepoRootCache !== undefined) return _monorepoRootCache
|
|
35
|
+
let dir = path.dirname(fileURLToPath(import.meta.url))
|
|
36
|
+
// walk up until we find the soot monorepo: it has packages/sootsim-engine and
|
|
37
|
+
// a public/sootsim dev-build output slot. bounded by the filesystem root.
|
|
38
|
+
for (let i = 0; i < 12 && dir !== path.dirname(dir); i++) {
|
|
39
|
+
if (
|
|
40
|
+
fs.existsSync(path.join(dir, 'packages/sootsim-engine/package.json')) &&
|
|
41
|
+
fs.existsSync(path.join(dir, 'public/sootsim'))
|
|
42
|
+
) {
|
|
43
|
+
_monorepoRootCache = dir
|
|
44
|
+
return dir
|
|
45
|
+
}
|
|
46
|
+
dir = path.dirname(dir)
|
|
47
|
+
}
|
|
48
|
+
_monorepoRootCache = null
|
|
49
|
+
return null
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** the fresh dev-stack engine build to serve when running inside the soot
|
|
53
|
+
* monorepo dev checkout, or null when the installed runtime should serve
|
|
54
|
+
* (published CLI, packaged electron, or an isolated SOOTSIM_HOME). */
|
|
55
|
+
export function resolveDevCheckoutRuntimeRoot(): string | null {
|
|
56
|
+
// an explicit home that has a STAGED/active runtime is the isolation the
|
|
57
|
+
// CI/local-publish path sets up to validate the installed-runtime code path —
|
|
58
|
+
// honor that staged runtime. an explicit home with NO active runtime is just
|
|
59
|
+
// an isolated dev daemon (own lockfile, doesn't clobber ~/.sootsim), which
|
|
60
|
+
// still wants the dev build; and the default home (SOOTSIM_HOME unset) always
|
|
61
|
+
// does. keying on "explicit home + a runtime deliberately staged there" keeps
|
|
62
|
+
// it structural, not a bespoke toggle.
|
|
63
|
+
if (process.env.SOOTSIM_HOME && readActiveRuntime()) return null
|
|
64
|
+
const root = findMonorepoRoot()
|
|
65
|
+
if (!root) return null
|
|
66
|
+
const devBuild = path.join(root, 'public/sootsim')
|
|
67
|
+
// require the runtime shape the installed runtime also has, so serving it is
|
|
68
|
+
// a drop-in (index.html shell + engine/ + engine-tenant/worker.js tenant).
|
|
69
|
+
if (
|
|
70
|
+
fs.existsSync(path.join(devBuild, 'index.html')) &&
|
|
71
|
+
fs.existsSync(path.join(devBuild, 'engine/index.html')) &&
|
|
72
|
+
fs.existsSync(path.join(devBuild, 'engine-tenant/worker.js'))
|
|
73
|
+
) {
|
|
74
|
+
return devBuild
|
|
75
|
+
}
|
|
76
|
+
return null
|
|
77
|
+
}
|
|
78
|
+
|
|
12
79
|
const MIME_TYPES: Record<string, string> = {
|
|
13
80
|
'.js': 'application/javascript',
|
|
14
81
|
'.mjs': 'application/javascript',
|
|
@@ -46,6 +113,9 @@ const ROOT_RUNTIME_PATHS = [
|
|
|
46
113
|
]
|
|
47
114
|
|
|
48
115
|
export function resolveActiveRuntimeRoot(): string | null {
|
|
116
|
+
// mode boundary: inside the dev checkout the dev-stack build is the engine.
|
|
117
|
+
const devRoot = resolveDevCheckoutRuntimeRoot()
|
|
118
|
+
if (devRoot) return devRoot
|
|
49
119
|
const active = readActiveRuntime()
|
|
50
120
|
if (!active) return null
|
|
51
121
|
const dir = runtimeDir(active)
|
package/src/vite-plugin.ts
CHANGED
|
@@ -598,6 +598,15 @@ export function wsBridgePlugin(): Plugin {
|
|
|
598
598
|
portOffset: process.env.PORT_OFFSET,
|
|
599
599
|
}),
|
|
600
600
|
writeDevLockfile: true,
|
|
601
|
+
// resolved on every lockfile heartbeat: the address is null until
|
|
602
|
+
// vite's http server is listening, then the real bound port. lets
|
|
603
|
+
// CLI commands resolve the shell base URL from the same lockfile
|
|
604
|
+
// that names the bridge port (one world, no split-brain).
|
|
605
|
+
getShellPort: () => {
|
|
606
|
+
const addr = server.httpServer?.address()
|
|
607
|
+
if (addr && typeof addr === 'object') return addr.port
|
|
608
|
+
return server.config.server.port || null
|
|
609
|
+
},
|
|
601
610
|
})
|
|
602
611
|
bridgeHost.start?.({ silent: true })
|
|
603
612
|
})
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
/*! sootsim v0.1.185 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
|
-
import{a as A,d as W,f as x}from"./chunk-E5DE33BU.js";import{I as v,J as P,K as T,L as C,j as k}from"./chunk-BI56RR3G.js";import{WebSocket as I}from"ws";function E(){if(k()){let n=P();if(n&&C(n))return n.bridgePort}let e=v();return e&&T(e)?e.bridgePort:7668}var w=class extends Error{lock;constructor(n,i){super(n),this.name="BridgeSimLockedError",this.lock=i}};function L(e){return e==="flag"?"via --sim":e==="saved"?"saved via `sootsim use`":"primary fallback \u2014 no sim pinned"}function V(e,n={}){let i=new Set,a=n.port??E(),l=n.commandTimeoutMs??15e3,r,m="none",h=new Set(n.stripBooleanFlags??[]),b=new Set(n.stripValueFlags??[]);for(let t=0;t<e.length;t++){let d=e[t];if(d==="--port"||d==="-p"){i.add(t),t+1<e.length&&(i.add(t+1),a=Number(e[t+1])),t++;continue}if(d.startsWith("--port=")){i.add(t),a=Number(d.slice(7));continue}if(d==="--timeout"){i.add(t),t+1<e.length&&(i.add(t+1),l=Number(e[t+1])),t++;continue}if(d==="--sim"||d==="--session"||d==="--tab"){i.add(t),t+1<e.length&&(i.add(t+1),r=e[t+1]?.trim()||void 0,m="flag"),t++;continue}let s=d.startsWith("--sim=")?d.slice(6):d.startsWith("--session=")?d.slice(10):d.startsWith("--tab=")?d.slice(6):void 0;if(s!==void 0){i.add(t),r=s.trim()||void 0,m="flag";continue}if(h.has(d)){i.add(t);continue}b.has(d)&&(i.add(t),t+1<e.length&&i.add(t+1),t++)}if(!r){let t=W();t&&(r=t.trim()||void 0,m="saved")}return{positional:e.filter((t,d)=>!i.has(d)),wsPort:a,simId:r,simIdSource:m,commandTimeoutMs:l}}function M(e,n={}){let i=1,a=n.commandTimeoutMs??15e3,l=new Map,r=new I(`ws://localhost:${e}`),m=A(),h=new Promise((s,o)=>{r.on("open",()=>{try{r.send(JSON.stringify({type:"bridge:hello",id:0,cliIdentityKey:m.key,cliIdentitySource:m.source,cliLabel:n.cliLabel}))}catch{}s()}),r.on("error",c=>{let g=c.message?`: ${c.message}`:"";o(new Error(`could not connect to ws://localhost:${e}${g}`))})}),b=!1,t=!1;function d(s,o){if(t||process.env.SOOTSIM_QUIET_TARGET_NOTICE==="1"||s.startsWith("bridge:")||s==="focus"||s==="close")return;t=!0;let c=o??"primary",g=L(o?n.simIdSource:"none");process.stderr.write(` \u2192 ${c} (${g})
|
|
3
|
-
`)}return r.on("message",s=>{let o;try{o=JSON.parse(s.toString())}catch{return}if(o.id===0)return;let c=l.get(o.id);c&&(l.delete(o.id),o._otherCliCount>0&&!b&&(b=!0,process.stderr.write(`
|
|
4
|
-
\u26A0 ${o._otherCliCount} other CLI identity/identities are driving this sim
|
|
5
|
-
taps, scrolls, and keyboard input from multiple agents will collide on
|
|
6
|
-
the same screen state (this is not a bridge throughput limit).
|
|
7
|
-
use \`sootsim open --new\` for an isolated sim per agent.
|
|
8
|
-
|
|
9
|
-
`)),o.error?o._locked?c.reject(new w(o.error,o._locked)):c.reject(new Error(o.error)):c.resolve(o.result))}),r.on("close",(s,o)=>{let c=o?.toString()||"connection closed";for(let[g,u]of l)l.delete(g),u.reject(new Error(`sim disconnected: ${c} (code ${s})`))}),{async send(s,o){let c=o?.timeoutMs??a,g=async u=>{await h;let f=i++;return new Promise((F,S)=>{let B=setTimeout(()=>{l.delete(f),S(new Error(`command timed out after ${Math.round(c/1e3)}s`))},c);l.set(f,{resolve:p=>{clearTimeout(B),F(p)},reject:p=>{clearTimeout(B),S(p)}});let y={...s,id:f};y.simId===void 0&&u&&(y.simId=u),d(s.type??"",y.simId),r.send(JSON.stringify(y))})};try{return await g(n.simId)}catch(u){let f=u instanceof Error?u.message:String(u);throw n.simIdSource==="saved"&&n.simId&&s.simId===void 0&&f===`no sim connected with id ${n.simId}`?(x(),new Error(`saved sim ${n.simId} is gone; run \`sootsim list\` and \`sootsim use <sim>\`, or open a fresh sim`)):u}},async listSims(){let s=await this.send({type:"bridge:list-sims"});return Array.isArray(s)?s:[]},async openUrl(s,o={}){return this.send({type:"bridge:open",url:s,newWindow:o.newWindow===!0})},async focusSim(s){return this.send({type:"focus",simId:s})},async closeSim(s){return this.send({type:"close",simId:s})},async claim(s,o={}){return await this.send({type:"bridge:claim",simId:s,force:o.force===!0})},close(){try{r.readyState===I.OPEN&&r.send(JSON.stringify({type:"bridge:bye",id:0}))}catch{}r.close();let s=setTimeout(()=>{r.readyState!==I.CLOSED&&r.terminate()},250)}}}function j(e){return M(e.wsPort,{commandTimeoutMs:e.commandTimeoutMs,simId:e.simId,simIdSource:e.simIdSource})}function O(e,n){let i=e.filter(r=>r.readyState==="open"&&r.id!==n),a=i.find(r=>r.userFocused)??i.find(r=>r.userVisible===!0&&r.isPrimary)??i.find(r=>r.userVisible===!0)??i.find(r=>r.isPrimary);if(!a)return null;let l=[a.isPrimary?"primary":null,a.userVisible===!1?"hidden":a.userVisible===!0?"visible":null,a.userFocused?"focused":null].filter(Boolean);return`${a.id}${l.length?` [${l.join(", ")}]`:""}`}async function q(e){try{let n=await e.send({type:"evaluate",code:`(() => ({
|
|
10
|
-
hidden: document.hidden,
|
|
11
|
-
visibilityState: document.visibilityState,
|
|
12
|
-
hasFocus: typeof document.hasFocus === 'function' ? document.hasFocus() : null,
|
|
13
|
-
simId: window.__sootsimBridge?.id ?? window.SootSim?.state?.simId ?? null,
|
|
14
|
-
url: location.href
|
|
15
|
-
}))()`}),i=typeof n=="object"&&n!==null?n:{hidden:n===!0};if(i.hidden===!0===!0){let l=null;try{l=O(await e.listSims(),i.simId)}catch{}return process.stderr.write(`
|
|
16
|
-
\u26A0 target sim${i.simId?` ${i.simId}`:""} is hidden (document.hidden = true)
|
|
17
|
-
`+(i.visibilityState?` visibility: ${i.visibilityState}
|
|
18
|
-
`:"")+` animations and rAF callbacks are throttled \u2014 coordinates may be wrong
|
|
19
|
-
and launch/transition animations will not complete.
|
|
20
|
-
`+(l?` another open sim looks usable: ${l}; target it with --sim.
|
|
21
|
-
`:" run `sootsim list` to find the visible sim and target it with --sim.\n")+` page-level window.focus() cannot unhide a browser tab.
|
|
22
|
-
|
|
23
|
-
`),{hidden:!0,warned:!0,simId:i.simId}}return{hidden:!1,warned:!1,simId:i.simId}}catch{return{hidden:!1,warned:!1}}}async function J(e,n,i={}){let a={type:"evaluate",code:n};return i.acquireLock&&(a.acquireLock=!0),e.send(a)}async function U(e,n,...i){return e.send({type:"call",path:n,args:i})}async function H(e,n,...i){return e.send({type:"call",path:n,args:i,acquireLock:!0})}export{E as a,w as b,V as c,M as d,j as e,q as f,J as g,U as h,H as i};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
/*! sootsim v0.1.185 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|