sootsim 0.1.169 → 0.1.171
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 +66 -63
- package/detox/index.ts +3 -3
- package/dist-cli/bin.js +3 -3
- package/dist-cli/chunks/agent-J4NTKR6V.js +46 -0
- package/dist-cli/chunks/{agent-wrapper-Y5FQA3RL.js → agent-wrapper-V2TD3UZR.js} +2 -2
- package/dist-cli/chunks/{app-fonts-FYVA4XV6.js → app-fonts-ROVXMKLG.js} +2 -2
- package/dist-cli/chunks/{assert-U64QBDM2.js → assert-CXQAEBLS.js} +2 -2
- package/dist-cli/chunks/beta-BLY4YCCD.js +2 -0
- package/dist-cli/chunks/{camera-3GXBVIAM.js → camera-XPZFAU3B.js} +2 -2
- package/dist-cli/chunks/chunk-2UEHUM6Q.js +13 -0
- package/dist-cli/chunks/chunk-3OFDUWRM.js +2 -0
- package/dist-cli/chunks/chunk-547XSOJL.js +62 -0
- package/dist-cli/chunks/{chunk-3L4NRJ6C.js → chunk-AHOHHXWK.js} +1 -1
- package/dist-cli/chunks/{chunk-JDGLBW64.js → chunk-AOPGVSJW.js} +1 -1
- package/dist-cli/chunks/chunk-B77QXVTZ.js +118 -0
- package/dist-cli/chunks/chunk-CJTJX3H7.js +23 -0
- package/dist-cli/chunks/{chunk-2TYEWVS4.js → chunk-CVLJ4RMA.js} +1 -1
- package/dist-cli/chunks/chunk-DGVQPBNL.js +1 -0
- package/dist-cli/chunks/{chunk-MVOHANJG.js → chunk-DR3E2NVD.js} +4 -4
- package/dist-cli/chunks/{chunk-FIDPRJYH.js → chunk-E7P6ILZK.js} +2 -2
- package/dist-cli/chunks/{chunk-CR6DOLUD.js → chunk-EXN7SSF3.js} +1 -1
- package/dist-cli/chunks/{chunk-IODOTOOP.js → chunk-FJ2WDOTA.js} +2 -2
- package/dist-cli/chunks/{chunk-LZEL2RU3.js → chunk-HBR56XPR.js} +1 -1
- package/dist-cli/chunks/chunk-HQ3WABUY.js +1 -0
- package/dist-cli/chunks/{chunk-5Q7IHJ7K.js → chunk-I5OLONCL.js} +2 -2
- package/dist-cli/chunks/{chunk-XEH4QGWB.js → chunk-I5XY2BFR.js} +2 -2
- package/dist-cli/chunks/{chunk-GC4THE6K.js → chunk-ICA7K635.js} +2 -2
- package/dist-cli/chunks/{chunk-WZG3YVJR.js → chunk-J7DI5B4Y.js} +1 -1
- package/dist-cli/chunks/{chunk-YADWU7OZ.js → chunk-JQSGI66Q.js} +2 -2
- package/dist-cli/chunks/chunk-JQW2OOL5.js +2 -0
- package/dist-cli/chunks/{chunk-B7BMSU7H.js → chunk-KT55MHRH.js} +1 -1
- package/dist-cli/chunks/{chunk-PV6MBKKE.js → chunk-LSZRVSXO.js} +2 -2
- package/dist-cli/chunks/{chunk-IACEJQIO.js → chunk-MBVNBHRK.js} +2 -2
- package/dist-cli/chunks/{chunk-VMYMPL6H.js → chunk-N64WUTJB.js} +5 -5
- package/dist-cli/chunks/{chunk-KUUFY6FC.js → chunk-O54LARIO.js} +1 -1
- package/dist-cli/chunks/{chunk-Y6IDAARY.js → chunk-OIIPFIZL.js} +1 -1
- package/dist-cli/chunks/chunk-OSS2T3WP.js +2 -0
- package/dist-cli/chunks/{chunk-KZIXAYN5.js → chunk-OTN33CWO.js} +4 -4
- package/dist-cli/chunks/{chunk-4F3BBP7B.js → chunk-OYQVSV4I.js} +2 -2
- package/dist-cli/chunks/{chunk-G2ZFDIPK.js → chunk-QBCJDPG3.js} +4 -4
- package/dist-cli/chunks/chunk-QIMO6SQX.js +2 -0
- package/dist-cli/chunks/{chunk-SNX3M4XD.js → chunk-RISDCDO2.js} +3 -3
- package/dist-cli/chunks/chunk-RJZRI3P3.js +2 -0
- package/dist-cli/chunks/{chunk-OGLWXPVG.js → chunk-RNWTVHIS.js} +3 -3
- package/dist-cli/chunks/chunk-RULKWLIO.js +6 -0
- package/dist-cli/chunks/{chunk-IBEMMV5E.js → chunk-RXBB4S3Q.js} +8 -8
- package/dist-cli/chunks/{chunk-SIB6I72P.js → chunk-U7NWELJ3.js} +2 -2
- package/dist-cli/chunks/{chunk-HC72ILJK.js → chunk-WPEXAZSS.js} +2 -2
- package/dist-cli/chunks/{chunk-DQZEN256.js → chunk-WXPG6OS6.js} +1 -1
- package/dist-cli/chunks/{chunk-DNA6VS6M.js → chunk-X4VXITOI.js} +1 -1
- package/dist-cli/chunks/{chunk-BIWJE7CB.js → chunk-XD66TGXU.js} +1 -1
- package/dist-cli/chunks/{chunk-X2HNVXNM.js → chunk-XFSQORQ5.js} +2 -2
- package/dist-cli/chunks/{chunk-5C6BR24W.js → chunk-YBPF6OGE.js} +6 -6
- package/dist-cli/chunks/{chunk-GLRFKYDV.js → chunk-YPHT4BSL.js} +2 -2
- package/dist-cli/chunks/cli-version-EQIZQ5NI.js +2 -0
- package/dist-cli/chunks/{compat-ORRWNXVT.js → compat-32AVWHB7.js} +3 -3
- package/dist-cli/chunks/control-LF34QRMZ.js +2 -0
- package/dist-cli/chunks/{cpu-profile-6PRSBZ2F.js → cpu-profile-EEAXEDDO.js} +2 -2
- package/dist-cli/chunks/daemon-MUQQZ64R.js +2 -0
- package/dist-cli/chunks/{debug-Q3J2X4WW.js → debug-MW62345L.js} +5 -5
- package/dist-cli/chunks/{detox-DN57GMMJ.js → detox-UAPUROWZ.js} +2 -2
- package/dist-cli/chunks/{device-IL5TPYGU.js → device-IWWFCELP.js} +2 -2
- package/dist-cli/chunks/{diagnose-BW6QWP4F.js → diagnose-DL22YIRH.js} +2 -2
- package/dist-cli/chunks/drivers-3LBGADWJ.js +2 -0
- package/dist-cli/chunks/{electron-DGMSXQWG.js → electron-KDVB42AG.js} +3 -3
- package/dist-cli/chunks/flow-OE7GVTNZ.js +2 -0
- package/dist-cli/chunks/help-G7XRDP3G.js +2 -0
- package/dist-cli/chunks/{hints-TK3EHB4U.js → hints-GNVLVDPN.js} +2 -2
- package/dist-cli/chunks/home-paths-4JHJTIX5.js +2 -0
- package/dist-cli/chunks/{inspect-NFWFGU4B.js → inspect-RT36PPFH.js} +24 -24
- package/dist-cli/chunks/{install-desktop-GB3JKSNX.js → install-desktop-MXUBQ6NJ.js} +3 -3
- package/dist-cli/chunks/{keys-RAAHRIFH.js → keys-PS5IUZ2M.js} +2 -2
- package/dist-cli/chunks/{login-KQ37GHDE.js → login-PLPGPVOR.js} +4 -4
- package/dist-cli/chunks/{logout-63SH2Y25.js → logout-3NCVFTBB.js} +2 -2
- package/dist-cli/chunks/{maestro-24BT3MML.js → maestro-OTPRMCZ3.js} +2 -2
- package/dist-cli/chunks/optional-demo-registry-RMRKVBDN.js +2 -0
- package/dist-cli/chunks/{preview-KQAOVN6R.js → preview-JM3GALNL.js} +2 -2
- package/dist-cli/chunks/{profile-AN2B4NJT.js → profile-T2BO5XLW.js} +2 -2
- package/dist-cli/chunks/{react-ATGV35B4.js → react-U3FQRLFA.js} +2 -2
- package/dist-cli/chunks/{record-36662T3R.js → record-C6FA3WXN.js} +4 -4
- package/dist-cli/chunks/runtime-IGGC2EEX.js +2 -0
- package/dist-cli/chunks/{screenshot-K4N5MPAT.js → screenshot-XPDBDFIK.js} +4 -4
- package/dist-cli/chunks/{screenshot-mode-4QOJDLSH.js → screenshot-mode-4FED7FGF.js} +2 -2
- package/dist-cli/chunks/{screenshots-TB35YMSR.js → screenshots-GVEUZFXL.js} +2 -2
- package/dist-cli/chunks/{screenshots-capture-W6X33BZ4.js → screenshots-capture-TPGPJZ3J.js} +2 -2
- package/dist-cli/chunks/{server-L2PKDJZ2.js → serve-5G4JU44V.js} +18 -17
- package/dist-cli/chunks/setup-BGRJTFGF.js +77 -0
- package/dist-cli/chunks/skills-AGVA7E6K.js +40 -0
- package/dist-cli/chunks/{slides-TORKO36P.js → slides-Z7LW64IW.js} +2 -2
- package/dist-cli/chunks/store-KKALNEVX.js +2 -0
- package/dist-cli/chunks/telemetry-WHOFSYSH.js +2 -0
- package/dist-cli/chunks/{test-5VCENVW3.js → test-PFT2C45X.js} +3 -3
- package/dist-cli/chunks/{three-mode-ZVS2DSX6.js → three-mode-HOCUD4BU.js} +2 -2
- package/dist-cli/chunks/{timeline-TNC5OWLF.js → timeline-STMBOMTT.js} +2 -2
- package/dist-cli/chunks/{upgrade-E7IO6A7Z.js → upgrade-UXMJ73RU.js} +2 -2
- package/dist-cli/chunks/upload-NJTGOKHA.js +2 -0
- package/dist-cli/chunks/version-FNSM3CIG.js +4 -0
- package/dist-cli/chunks/web-TMIGK6QS.js +2 -0
- package/dist-cli/chunks/{what-happened-RMHZ7DGX.js → what-happened-R5KC4F7B.js} +3 -3
- package/dist-cli/chunks/{whoami-D53ANHR5.js → whoami-DWRGFQKR.js} +2 -2
- package/dist-lib/agent-daemon-client.cjs +4 -5
- 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 +3 -6
- package/dist-lib/beta.mjs +3 -5
- 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 +4 -4
- package/dist-lib/dev-bundle-resolution.cjs +2 -9
- package/dist-lib/home-paths.cjs +59 -1
- package/dist-lib/host/bridge-host.cjs +67 -5
- 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/menu.cjs +1 -1
- package/dist-lib/menu.mjs +1 -1
- package/dist-lib/metro.cjs +2 -2
- package/dist-lib/profiles.cjs +1 -1
- package/dist-lib/render-mode.cjs +1 -1
- package/dist-lib/scripts/dev-server-scanner.cjs +5 -4
- package/dist-lib/sdk.cjs +1 -1
- package/dist-lib/sdk.mjs +1 -1
- package/dist-lib/skills.cjs +127 -11
- package/dist-lib/vite.cjs +2 -2
- package/package.json +2 -1
- package/scripts/dev-server-scanner.ts +3 -4
- package/scripts/postinstall.cjs +2 -2
- package/scripts/preuninstall.cjs +5 -7
- package/skills/soot.md +178 -0
- package/skills/sootsim-debug.md +384 -0
- package/skills/sootsim-setup.md +96 -0
- package/skills/sootsim-test.md +292 -0
- package/skills/sootsim-visual.md +122 -0
- package/src/agent-daemon-client.ts +4 -14
- package/src/beta.ts +3 -5
- package/src/dev-bundle-resolution.ts +1 -14
- package/src/home-paths.ts +77 -2
- package/src/host/agent-host.ts +1 -1
- package/src/host/bridge-host.ts +65 -6
- package/src/metro-plugin.ts +1 -1
- package/src/runtime-assets.ts +1 -1
- package/src/vite-plugin.ts +1 -0
- package/dist-cli/chunks/agent-V3GVCRPL.js +0 -46
- package/dist-cli/chunks/auto-bootstrap-YXDP3WKH.js +0 -2
- package/dist-cli/chunks/beta-FGSMZWLP.js +0 -2
- package/dist-cli/chunks/chunk-2IFWVIKM.js +0 -2
- package/dist-cli/chunks/chunk-3T36XLP3.js +0 -119
- package/dist-cli/chunks/chunk-5KY7TQ42.js +0 -5
- package/dist-cli/chunks/chunk-BQOMDL4K.js +0 -1
- package/dist-cli/chunks/chunk-FHMPJZKM.js +0 -7
- package/dist-cli/chunks/chunk-GQAWFQNN.js +0 -23
- package/dist-cli/chunks/chunk-HJTKKF7M.js +0 -13
- package/dist-cli/chunks/chunk-K4JAWKOY.js +0 -1
- package/dist-cli/chunks/chunk-M2TMFGZH.js +0 -2
- package/dist-cli/chunks/chunk-NXGQS7IR.js +0 -2
- package/dist-cli/chunks/chunk-R2INPDGW.js +0 -1
- package/dist-cli/chunks/chunk-SLL5SZN4.js +0 -2
- package/dist-cli/chunks/chunk-XM66K64H.js +0 -79
- package/dist-cli/chunks/cli-version-3L6FFDIX.js +0 -2
- package/dist-cli/chunks/config-5IB6ONJ2.js +0 -45
- package/dist-cli/chunks/control-BM4V27OB.js +0 -2
- package/dist-cli/chunks/daemon-62MZT4G4.js +0 -67
- package/dist-cli/chunks/drivers-V6QDFZQD.js +0 -2
- package/dist-cli/chunks/flow-VBM6TU32.js +0 -2
- package/dist-cli/chunks/help-XWKNL743.js +0 -2
- package/dist-cli/chunks/home-paths-G23H3RO6.js +0 -2
- package/dist-cli/chunks/install-5YL7FITA.js +0 -2
- package/dist-cli/chunks/launch-DYFE4CAD.js +0 -16
- package/dist-cli/chunks/optional-demo-registry-JJXPB3UD.js +0 -2
- package/dist-cli/chunks/runtime-NRMC3U3D.js +0 -2
- package/dist-cli/chunks/runtime-delivery-RO6CTYPQ.js +0 -2
- package/dist-cli/chunks/setup-repo-AK6QOUE7.js +0 -2
- package/dist-cli/chunks/skills-KDSOWUOE.js +0 -10
- package/dist-cli/chunks/start-GH2AOUX6.js +0 -23
- package/dist-cli/chunks/store-JHW65VGQ.js +0 -2
- package/dist-cli/chunks/telemetry-SZLRXJXW.js +0 -2
- package/dist-cli/chunks/upload-KKEWETA5.js +0 -2
- package/dist-cli/chunks/version-37OD33SE.js +0 -4
- package/dist-cli/chunks/web-4JVMIBTB.js +0 -2
package/src/host/bridge-host.ts
CHANGED
|
@@ -21,10 +21,13 @@ import {
|
|
|
21
21
|
readActiveRuntime,
|
|
22
22
|
readSharedConfig,
|
|
23
23
|
removeDaemonLockfile,
|
|
24
|
+
removeDevBridgeLockfile,
|
|
24
25
|
writeActiveRuntime,
|
|
25
26
|
writeDaemonLockfile,
|
|
27
|
+
writeDevBridgeLockfile,
|
|
26
28
|
writeSharedConfig,
|
|
27
29
|
type DaemonLockfile,
|
|
30
|
+
type DevBridgeLockfile,
|
|
28
31
|
type SharedConfig,
|
|
29
32
|
} from '../home-paths.ts'
|
|
30
33
|
import { updateRuntimeToLatest } from '../runtime-delivery.ts'
|
|
@@ -210,17 +213,22 @@ export interface BridgeHostOptions {
|
|
|
210
213
|
portFallbackCount?: number
|
|
211
214
|
/** when true, write ~/.sootsim/daemon.json on successful bind + update
|
|
212
215
|
* it on a heartbeat interval + remove it on close. only the standalone
|
|
213
|
-
* `sootsim
|
|
216
|
+
* `sootsim serve` process should set this — tests, vite plugin, and
|
|
214
217
|
* anything embedded should leave it off to avoid clobbering a real
|
|
215
218
|
* daemon's lockfile. defaults to false. */
|
|
216
219
|
writeLockfile?: boolean
|
|
220
|
+
/** when true, write ~/.sootsim/dev-bridge.json on successful bind + update
|
|
221
|
+
* it on a heartbeat interval + remove it on close. the Vite dev shell sets
|
|
222
|
+
* this so local CLI commands prefer the live source bridge over a standalone
|
|
223
|
+
* daemon or stale default-port listener. */
|
|
224
|
+
writeDevLockfile?: boolean
|
|
217
225
|
/** the sootbean origin this daemon's runtimes should talk to for auth,
|
|
218
226
|
* billing, and preview uploads — inlined into served runtime html as
|
|
219
227
|
* `window.__sootsimSootbeanOrigin`. without it the engine's origin.ts
|
|
220
228
|
* resolves the daemon's own loopback host (localhost:<runtimePort>) to
|
|
221
229
|
* the dev `localhost:3000` stack, so a *prod* CLI user's preview
|
|
222
230
|
* recording would upload to a localhost stack that doesn't exist. the
|
|
223
|
-
* `sootsim
|
|
231
|
+
* `sootsim serve` command resolves this with the same probe the
|
|
224
232
|
* upload itself uses (`resolveDefaultUploadOrigin`). */
|
|
225
233
|
sootbeanOrigin?: string
|
|
226
234
|
/** override the abandoned-sim GC TTL (ms). defaults to
|
|
@@ -386,10 +394,12 @@ export class SootSimBridgeHost {
|
|
|
386
394
|
private maxConcurrentAutomationSims: number
|
|
387
395
|
private automationSimActiveGraceMs: number
|
|
388
396
|
private shouldWriteLockfile: boolean
|
|
397
|
+
private shouldWriteDevLockfile: boolean
|
|
389
398
|
private sootbeanOrigin: string | null = null
|
|
390
399
|
private effectivePort = 0
|
|
391
400
|
private startedAt = 0
|
|
392
401
|
private heartbeatTimer: NodeJS.Timeout | null = null
|
|
402
|
+
private devHeartbeatTimer: NodeJS.Timeout | null = null
|
|
393
403
|
// ws-level heartbeat: sims that hang up uncleanly (page navigated, network
|
|
394
404
|
// dropped, sim crashed) leave their server-side WebSocket sitting "open"
|
|
395
405
|
// forever. ping every WS_HEARTBEAT_INTERVAL_MS; if the previous round's
|
|
@@ -416,10 +426,11 @@ export class SootSimBridgeHost {
|
|
|
416
426
|
constructor(opts: BridgeHostOptions = {}) {
|
|
417
427
|
this.preferredPort = opts.port || DEFAULT_SOOTSIM_BRIDGE_PORT
|
|
418
428
|
this.port = this.preferredPort
|
|
419
|
-
// default off — callers that want the lockfile (sootsim
|
|
429
|
+
// default off — callers that want the lockfile (sootsim serve) opt in.
|
|
420
430
|
this.shouldWriteLockfile = opts.writeLockfile === true
|
|
431
|
+
this.shouldWriteDevLockfile = opts.writeDevLockfile === true
|
|
421
432
|
// fallback freely on port collision regardless of who owns the lockfile.
|
|
422
|
-
//
|
|
433
|
+
// serve.ts already refuses to start if a fresh daemon.json exists, so
|
|
423
434
|
// two daemons can't race the lockfile. without this, an unrelated process
|
|
424
435
|
// on 7668 (another worktree's vite dev fallback bridge, etc.) was enough
|
|
425
436
|
// to keep the daemon from binding at all — and launchd's KeepAlive then
|
|
@@ -1052,7 +1063,7 @@ export class SootSimBridgeHost {
|
|
|
1052
1063
|
})
|
|
1053
1064
|
}
|
|
1054
1065
|
|
|
1055
|
-
/** after a successful bind: start the cli idle sweep, write the daemon
|
|
1066
|
+
/** after a successful bind: start the cli idle sweep, write the daemon/dev
|
|
1056
1067
|
* lockfile (if this host owns it), seed the agent host, kick off the
|
|
1057
1068
|
* heartbeat loop. idempotent across rebinds because close() tears down
|
|
1058
1069
|
* every timer and the lockfile. */
|
|
@@ -1077,7 +1088,7 @@ export class SootSimBridgeHost {
|
|
|
1077
1088
|
// atomic claim: bail if another fresh daemon's lockfile already
|
|
1078
1089
|
// exists (stale ones are overwritten). last line of defense
|
|
1079
1090
|
// against two daemons clobbering the same file between the
|
|
1080
|
-
// freshness check in
|
|
1091
|
+
// freshness check in serve.ts and here.
|
|
1081
1092
|
const claimed = claimDaemonLockfile(this.buildLockfileSnapshot())
|
|
1082
1093
|
if (!claimed) {
|
|
1083
1094
|
throw new Error(
|
|
@@ -1099,6 +1110,22 @@ export class SootSimBridgeHost {
|
|
|
1099
1110
|
this.startRuntimeUpdater()
|
|
1100
1111
|
}
|
|
1101
1112
|
|
|
1113
|
+
if (this.shouldWriteDevLockfile) {
|
|
1114
|
+
try {
|
|
1115
|
+
this.writeDevLockfileSnapshot()
|
|
1116
|
+
} catch (err) {
|
|
1117
|
+
process.stderr.write(
|
|
1118
|
+
`ws bridge failed to write dev bridge lockfile: ${String(err)}\n`,
|
|
1119
|
+
)
|
|
1120
|
+
}
|
|
1121
|
+
this.devHeartbeatTimer = setInterval(() => {
|
|
1122
|
+
try {
|
|
1123
|
+
this.writeDevLockfileSnapshot()
|
|
1124
|
+
} catch {}
|
|
1125
|
+
}, DAEMON_HEARTBEAT_INTERVAL_MS) as unknown as NodeJS.Timeout
|
|
1126
|
+
this.devHeartbeatTimer.unref()
|
|
1127
|
+
}
|
|
1128
|
+
|
|
1102
1129
|
// seed the attached-projects store from the demo registry on first
|
|
1103
1130
|
// daemon boot. idempotent; no-ops once the store has anything in it.
|
|
1104
1131
|
void this.agentHost.seedOnBoot()
|
|
@@ -1121,10 +1148,28 @@ export class SootSimBridgeHost {
|
|
|
1121
1148
|
}
|
|
1122
1149
|
}
|
|
1123
1150
|
|
|
1151
|
+
private buildDevLockfileSnapshot(): DevBridgeLockfile {
|
|
1152
|
+
return {
|
|
1153
|
+
schema: 1,
|
|
1154
|
+
pid: process.pid,
|
|
1155
|
+
platform: process.platform,
|
|
1156
|
+
bridgePort: this.effectivePort,
|
|
1157
|
+
runtimePort: this.effectivePort,
|
|
1158
|
+
cwd: process.cwd(),
|
|
1159
|
+
startedAt: this.startedAt,
|
|
1160
|
+
heartbeatAt: Date.now(),
|
|
1161
|
+
source: 'vite-dev',
|
|
1162
|
+
}
|
|
1163
|
+
}
|
|
1164
|
+
|
|
1124
1165
|
private writeLockfileSnapshot() {
|
|
1125
1166
|
writeDaemonLockfile(this.buildLockfileSnapshot())
|
|
1126
1167
|
}
|
|
1127
1168
|
|
|
1169
|
+
private writeDevLockfileSnapshot() {
|
|
1170
|
+
writeDevBridgeLockfile(this.buildDevLockfileSnapshot())
|
|
1171
|
+
}
|
|
1172
|
+
|
|
1128
1173
|
private refreshActiveRuntime() {
|
|
1129
1174
|
this.activeRuntimeVersion = readActiveRuntime()
|
|
1130
1175
|
this.activeRuntimeDirPath = getActiveRuntimeDir()
|
|
@@ -1416,6 +1461,11 @@ export class SootSimBridgeHost {
|
|
|
1416
1461
|
bridgePort: this.effectivePort,
|
|
1417
1462
|
runtimePort: this.effectivePort,
|
|
1418
1463
|
activeRuntime: this.activeRuntimeVersion,
|
|
1464
|
+
bridgeSource: this.shouldWriteDevLockfile
|
|
1465
|
+
? 'vite-dev'
|
|
1466
|
+
: this.shouldWriteLockfile
|
|
1467
|
+
? 'daemon'
|
|
1468
|
+
: 'embedded',
|
|
1419
1469
|
startedAt: this.startedAt,
|
|
1420
1470
|
uptimeMs: this.startedAt > 0 ? Date.now() - this.startedAt : 0,
|
|
1421
1471
|
}),
|
|
@@ -1885,6 +1935,10 @@ export class SootSimBridgeHost {
|
|
|
1885
1935
|
clearInterval(this.heartbeatTimer)
|
|
1886
1936
|
this.heartbeatTimer = null
|
|
1887
1937
|
}
|
|
1938
|
+
if (this.devHeartbeatTimer) {
|
|
1939
|
+
clearInterval(this.devHeartbeatTimer)
|
|
1940
|
+
this.devHeartbeatTimer = null
|
|
1941
|
+
}
|
|
1888
1942
|
if (this.wsHeartbeatTimer) {
|
|
1889
1943
|
clearInterval(this.wsHeartbeatTimer)
|
|
1890
1944
|
this.wsHeartbeatTimer = null
|
|
@@ -1898,6 +1952,11 @@ export class SootSimBridgeHost {
|
|
|
1898
1952
|
removeDaemonLockfile()
|
|
1899
1953
|
} catch {}
|
|
1900
1954
|
}
|
|
1955
|
+
if (this.shouldWriteDevLockfile) {
|
|
1956
|
+
try {
|
|
1957
|
+
removeDevBridgeLockfile()
|
|
1958
|
+
} catch {}
|
|
1959
|
+
}
|
|
1901
1960
|
this.effectivePort = 0
|
|
1902
1961
|
this.startedAt = 0
|
|
1903
1962
|
this.agentHost.close()
|
package/src/metro-plugin.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// sootsim metro plugin — serves the sootsim shell at /__soot/ on metro's server.
|
|
2
2
|
// shell assets come from the active engine runtime under ~/.sootsim/runtimes/,
|
|
3
|
-
// which is fetched by `sootsim runtime install` / `sootsim setup
|
|
3
|
+
// which is fetched by `sootsim runtime install` / `sootsim setup`. resolved
|
|
4
4
|
// per-request so swapping runtimes (`sootsim runtime use <v>`) takes effect
|
|
5
5
|
// without restarting metro.
|
|
6
6
|
//
|
package/src/runtime-assets.ts
CHANGED
|
@@ -7,7 +7,7 @@ import path from 'path'
|
|
|
7
7
|
import { readActiveRuntime, runtimeDir } from './home-paths'
|
|
8
8
|
|
|
9
9
|
export const SOOTSIM_RUNTIME_MISSING_MESSAGE =
|
|
10
|
-
'[sootsim] no engine runtime installed — run `sootsim setup
|
|
10
|
+
'[sootsim] no engine runtime installed — run `sootsim setup`, or `sootsim runtime install`'
|
|
11
11
|
|
|
12
12
|
const MIME_TYPES: Record<string, string> = {
|
|
13
13
|
'.js': 'application/javascript',
|
package/src/vite-plugin.ts
CHANGED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
/*! sootsim v0.1.169 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
|
-
import{a as E,b as A,c as S,d as l,e as j,g as T,h as I,j as D,m as k,n as x,o as O,p as g,q as R,r as C}from"./chunk-HC72ILJK.js";import"./chunk-LZEL2RU3.js";import{c as b}from"./chunk-IBEMMV5E.js";import"./chunk-IACEJQIO.js";import"./chunk-3T36XLP3.js";import"./chunk-GLRFKYDV.js";import"./chunk-2IFWVIKM.js";import"./chunk-DQZEN256.js";import"./chunk-KUUFY6FC.js";import"./chunk-3L4NRJ6C.js";import"./chunk-NXGQS7IR.js";import"./chunk-2TYEWVS4.js";import{h as y,i as $}from"./chunk-5KY7TQ42.js";import"./chunk-JDGLBW64.js";import w from"node:fs";import d from"node:path";import{spawn as F}from"node:child_process";import B from"node:net";import{WebSocket as M}from"ws";var c=class extends Error{code;constructor(e,t){super(e),this.name="AgentDaemonError",this.code=t}},f=class{ws;port;commandTimeoutMs;ready;closed=!1;nextId=1;pending=new Map;eventListeners=new Set;statusListeners=new Set;disconnectListeners=new Set;constructor(e={}){this.port=e.port??7668,this.commandTimeoutMs=e.commandTimeoutMs??15e3,this.ws=new M(`ws://localhost:${this.port}`),this.ready=new Promise((t,r)=>{let s=()=>{this.ws.off("error",o),t()},o=i=>{this.ws.off("open",s),r(new c(`could not connect to sootsim daemon on port ${this.port}: ${i.message}`,"NO_DAEMON"))};this.ws.once("open",s),this.ws.once("error",o)}),this.ws.on("message",t=>this.handleMessage(t)),this.ws.on("close",()=>this.handleClose()),this.ws.on("error",()=>{})}async waitReady(){return this.ready}async listProjects(){return this.send("agent:list-projects")}async upsertProject(e){return this.send("agent:upsert-project",{input:e})}async deleteProject(e){return this.send("agent:delete-project",{projectId:e})}async autoAttachForUrl(e){return this.send("agent:auto-attach-for-url",{input:e})}async listSessions(e){return this.send("agent:list-sessions",{projectId:e})}async startSession(e){return this.send("agent:start-session",{input:e})}async sendPrompt(e,t){return this.send("agent:send-prompt",{sessionId:e,prompt:t})}async endSession(e){return this.send("agent:end-session",{sessionId:e})}async getTranscript(e){return this.send("agent:get-transcript",{sessionId:e})}async getPaths(){return this.send("agent:get-paths")}async subscribeEvents(e){return this.send("agent:subscribe-events",{sessionId:e})}async unsubscribeEvents(e){return this.send("agent:unsubscribe-events",{sessionId:e})}onAgentEvent(e){return this.eventListeners.add(e),()=>this.eventListeners.delete(e)}onSessionStatusChange(e){return this.statusListeners.add(e),()=>this.statusListeners.delete(e)}onDisconnect(e){return this.disconnectListeners.add(e),()=>this.disconnectListeners.delete(e)}close(){if(!this.closed){this.closed=!0;try{this.ws.close()}catch{}}}async send(e,t={}){if(await this.ready,this.closed||this.ws.readyState!==M.OPEN)throw new c("daemon connection is closed","NO_DAEMON");let r=this.nextId++;return new Promise((s,o)=>{let i=setTimeout(()=>{this.pending.delete(r),o(new c(`${e} timed out after ${Math.round(this.commandTimeoutMs/1e3)}s`,"TIMEOUT"))},this.commandTimeoutMs);this.pending.set(r,{resolve:s,reject:o,timer:i});try{this.ws.send(JSON.stringify({id:r,type:e,...t}))}catch(a){clearTimeout(i),this.pending.delete(r),o(a instanceof Error?a:new Error(String(a)))}})}handleMessage(e){let t;try{t=JSON.parse(String(e))}catch{return}if(!t||typeof t!="object")return;if(t.type==="agent:event"){for(let s of this.eventListeners)try{s({sessionId:t.sessionId,event:t.event})}catch{}return}if(t.type==="agent:session-status"){for(let s of this.statusListeners)try{s(t.session)}catch{}return}if(typeof t.id!="number")return;let r=this.pending.get(t.id);r&&(this.pending.delete(t.id),clearTimeout(r.timer),t.error?r.reject(new c(t.error,t.code)):r.resolve(t.result))}handleClose(){if(!this.closed){this.closed=!0;for(let[,e]of this.pending)clearTimeout(e.timer),e.reject(new c("daemon disconnected","DISCONNECT"));this.pending.clear();for(let e of this.disconnectListeners)try{e()}catch{}}}};function L(n=7668,e=400){return new Promise(t=>{let r=new B.Socket,s=!1,o=i=>{s||(s=!0,r.destroy(),t(i))};r.setTimeout(e),r.once("connect",()=>o(!0)),r.once("timeout",()=>o(!1)),r.once("error",()=>o(!1)),r.connect(n,"127.0.0.1")})}async function W(n={}){let e=n.port??7668;if(await L(e))return{alreadyRunning:!0};if($()){let a=y()?"this is a dev workstation (IS_TAMAGUI_DEV=1)":"this is a dev checkout";throw new c(`no sootsim bridge on port ${e} and refusing to spawn a standalone daemon \u2014 ${a}. start the live \`bun dev\` stack so the bridge is up, or set SOOTSIM_FORCE_DAEMON_INSTALL=1 to spawn one here on purpose.`,"DEV_HOST_REFUSED")}let{cmd:t,prefixArgs:r}=C(),s=[...r,"server","--quiet"];e!==7668&&s.push("--port",String(e));let o=F(t,s,{detached:!0,stdio:"ignore",env:process.env,cwd:process.cwd()});o.unref();let i=Date.now()+(n.startupTimeoutMs??5e3);for(;Date.now()<i;){if(await L(e))return{alreadyRunning:!1,pid:o.pid};await new Promise(a=>setTimeout(a,100))}throw new c(`spawned sootsim daemon on port ${e} but it did not come up in time. run \`sootsim server\` manually to diagnose.`,"SPAWN_TIMEOUT")}async function h(n={}){await W({port:n.port,startupTimeoutMs:n.startupTimeoutMs});let e=new f(n);try{await e.waitReady()}catch(t){throw e.close(),t}return e}async function fe(n){let[e,...t]=n;try{switch(e){case void 0:case"--help":case"-h":case"help":return _(),0;case"attach":return await V(t);case"projects":return await J();case"project":return await G(t);case"sessions":return await H(t);case"start":return await q(t);case"prompt":return await K(t);case"watch":return await X(t);case"transcript":return await Q(t);case"end":return await Y(t);case"paths":return await Z();default:return process.stderr.write(`unknown agent subcommand: ${e}
|
|
3
|
-
`),_(),2}}catch(r){if(r instanceof c)return process.stderr.write(`${r.message}
|
|
4
|
-
`),1;throw r}}async function v(n){let e=await h({clientLabel:"sootsim-agent-cli"});try{return await n(e)}finally{e.close()}}function _(){b("agent")}function P(n,e){let t={},r=[];for(let s=0;s<n.length;s++){let o=n[s],i=e[o];i==="value"?(t[o]=n[s+1]??"",s++):i==="bool"?t[o]=!0:r.push(o)}return{flags:t,positional:r}}function U(n,e="codex"){return n==="codex"||n==="claude"?n:e}async function V(n){let{flags:e,positional:t}=P(n,{"--name":"value","--provider":"value"}),r=t[0];if(!r)return process.stderr.write(`usage: sootsim agent attach <dir> [--name X] [--provider codex|claude]
|
|
5
|
-
`),2;let s=d.resolve(r);if(!w.existsSync(s))return process.stderr.write(`directory does not exist: ${s}
|
|
6
|
-
`),1;let o=S({cwd:s,name:e["--name"]||d.basename(s),preferredProvider:U(e["--provider"]),sourceRoots:[s]});return process.stdout.write(`\u2713 attached "${o.name}" (id: ${o.id})
|
|
7
|
-
cwd: ${o.cwd}
|
|
8
|
-
framework: ${o.framework}
|
|
9
|
-
preferred provider: ${o.preferredProvider}
|
|
10
|
-
`),0}async function J(){let n=[...j()].sort((t,r)=>r.updatedAt-t.updatedAt);if(n.length===0)return process.stdout.write("no attached projects yet. try `sootsim agent attach <dir>`.\n"),0;let e=`${"ID".padEnd(18)} ${"NAME".padEnd(20)} ${"FRAMEWORK".padEnd(10)} ${"PROVIDER".padEnd(8)} ${"7D COST".padEnd(10)} CWD
|
|
11
|
-
`;process.stdout.write(e);for(let t of n){let r=T(t),s=r>0?`$${r.toFixed(2)}`:"\u2014";process.stdout.write(`${t.id.padEnd(18)} ${p(t.name,20).padEnd(20)} ${t.framework.padEnd(10)} ${t.preferredProvider.padEnd(8)} ${s.padEnd(10)} ${t.cwd}
|
|
12
|
-
`)}return 0}async function G(n){let[e,t]=n;if(e==="show"){if(!t)return process.stderr.write(`usage: sootsim agent project show <id>
|
|
13
|
-
`),2;let r=l(t);return r?(process.stdout.write(JSON.stringify(r,null,2)+`
|
|
14
|
-
`),0):(process.stderr.write(`no project with id=${t}
|
|
15
|
-
`),1)}return e==="remove"?t?(I(t),process.stdout.write(`\u2713 removed project ${t}
|
|
16
|
-
`),0):(process.stderr.write(`usage: sootsim agent project remove <id>
|
|
17
|
-
`),2):(process.stderr.write(`usage: sootsim agent project [show|remove] <id>
|
|
18
|
-
`),2)}async function H(n){let{flags:e}=P(n,{"--project":"value","--all":"bool"}),t=e["--project"]||void 0,r=e["--all"]===!0,s=D(t);if(r||(s=s.filter(i=>i.status!=="ended")),s=s.sort((i,a)=>a.lastSeenAt-i.lastSeenAt),s.length===0)return process.stdout.write(r?`no sessions.
|
|
19
|
-
`:`no active sessions. pass --all to include ended.
|
|
20
|
-
`),0;let o=`${"SESSION".padEnd(26)} ${"PROJECT".padEnd(18)} ${"PROVIDER".padEnd(8)} ${"STATUS".padEnd(16)} ${"ALIVE".padEnd(5)} LAST PROMPT
|
|
21
|
-
`;process.stdout.write(o);for(let i of s){let a=R(i.wrapperPid,i.id)?"yes":"no",m=i.lastPrompt?p(i.lastPrompt,40):"";process.stdout.write(`${N(i.id).padEnd(26)} ${N(i.projectId).padEnd(18)} ${i.provider.padEnd(8)} ${i.status.padEnd(16)} ${a.padEnd(5)} ${m}
|
|
22
|
-
`)}return 0}async function q(n){let{flags:e,positional:t}=P(n,{"--provider":"value","--codex-bin":"value","--claude-bin":"value","--fresh-thread":"bool"}),r=t[0];if(!r)return process.stderr.write(`usage: sootsim agent start <projectId> [--provider codex|claude] [--fresh-thread]
|
|
23
|
-
`),2;let s=await v(i=>i.startSession({projectId:r,provider:U(e["--provider"],void 0)||void 0,codexBin:e["--codex-bin"]||void 0,claudeBin:e["--claude-bin"]||void 0,freshThread:e["--fresh-thread"]===!0})),o=l(s.session.projectId);return process.stdout.write(`\u2713 session ${s.session.id} started
|
|
24
|
-
project: ${o.name} (${o.id})
|
|
25
|
-
provider: ${s.session.provider}
|
|
26
|
-
pid: ${s.wrapperPid}
|
|
27
|
-
prompt with: sootsim agent prompt ${s.session.id} "<text>"
|
|
28
|
-
watch events: sootsim agent watch ${s.session.id}
|
|
29
|
-
`),0}async function K(n){let[e,...t]=n,r=t.join(" ");return!e||!r?(process.stderr.write(`usage: sootsim agent prompt <sessionId> "<text>"
|
|
30
|
-
`),2):(await v(s=>s.sendPrompt(e,{text:r})),process.stdout.write(`\u2713 prompt sent to ${e}
|
|
31
|
-
`),0)}async function X(n){let e=n[0];if(!e)return process.stderr.write(`usage: sootsim agent watch <sessionId>
|
|
32
|
-
`),2;process.stdout.write(`watching ${e}
|
|
33
|
-
---
|
|
34
|
-
`);let t=await h({clientLabel:"sootsim-agent-watch"}),r,s=new Promise(a=>{r=a}),o=t.onAgentEvent(({sessionId:a,event:m})=>{a===e&&process.stdout.write(z(m)+`
|
|
35
|
-
`)}),i=t.onDisconnect(()=>{process.stderr.write(`
|
|
36
|
-
[sootsim] daemon disconnected; exiting watch.
|
|
37
|
-
`),r(1)});try{await t.subscribeEvents(e)}catch(a){throw o(),i(),t.close(),a}return process.on("SIGINT",()=>{o(),i(),t.unsubscribeEvents(e).catch(()=>{}),t.close(),r(130)}),s}function z(n){let e=ee(n.ts);switch(n.type){case"ready":return`[${e}] ready ${n.provider} @ ${n.cwd}`;case"prompt-received":return`[${e}] prompt "${p(n.text,120)}"`;case"turn-started":return`[${e}] turn-started ${n.turnId??""}`;case"turn-message":return`[${e}] turn-message ${n.delta.replace(/\s+$/,"")}`;case"turn-reasoning":return`[${e}] turn-reasoning ${p(n.delta,200)}`;case"tool-call":return`[${e}] tool-call ${n.name}`;case"file-edited":return`[${e}] file-edited ${n.kind.padEnd(6)} ${n.path}`;case"turn-completed":return`[${e}] turn-completed ${n.durationMs}ms files=${n.filesTouched.length}`;case"approval-needed":return`[${e}] approval ${n.kind}`;case"error":return`[${e}] error ${n.message}`;case"exited":return`[${e}] exited code=${n.code}`;case"file-diff-delta":return`[${e}] file-diff-delta ${n.path}`;case"turn-plan":return`[${e}] turn-plan steps=${n.steps.length}`;default:return`[${e}] ${n.type}`}}async function Q(n){let e=n[0];if(!e)return process.stderr.write(`usage: sootsim agent transcript <sessionId>
|
|
38
|
-
`),2;let t=g(e);return w.existsSync(t)?(process.stdout.write(w.readFileSync(t,"utf8")),0):(process.stderr.write(`transcript not found: ${t}
|
|
39
|
-
`),1)}async function Y(n){let e=n[0];return e?(await v(t=>t.endSession(e)),process.stdout.write(`\u2713 ended session ${e}
|
|
40
|
-
`),0):(process.stderr.write(`usage: sootsim agent end <sessionId>
|
|
41
|
-
`),2)}async function Z(){let n=A();return process.stdout.write(`userData: ${n}
|
|
42
|
-
state: ${d.join(n,"attached-projects.json")}
|
|
43
|
-
sessions: ${d.join(n,"sessions")}
|
|
44
|
-
transcripts: ${d.join(n,"transcripts")}
|
|
45
|
-
locks: ${d.join(n,"locks")}
|
|
46
|
-
`),0}function p(n,e){return n.length<=e?n:n.slice(0,e-1)+"\u2026"}function N(n){return n.length>14?`${n.slice(0,14)}\u2026`:n}function ee(n){return new Date(n).toISOString().replace("T"," ").slice(0,19)}var he={sessionDir:k,promptFifoPath:x,eventsFifoPath:O,transcriptPath:g,parseAgentEventLine:E};export{he as __internals,fe as runAgentCommand};
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
/*! sootsim v0.1.169 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
|
-
import{a,b,c,d}from"./chunk-FHMPJZKM.js";import"./chunk-GQAWFQNN.js";import"./chunk-DQZEN256.js";import"./chunk-KUUFY6FC.js";import"./chunk-5KY7TQ42.js";import"./chunk-JDGLBW64.js";export{c as ensureDaemonRunning,a as ensureRuntimeInstalled,d as ensureSootsimReady,b as resolveBootstrapPort};
|