sootsim 0.1.290 → 0.1.291
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 +5 -5
- package/dist-cli/chunks/{agent-SW4O4VFG.js → agent-EDS4HRKB.js} +2 -2
- package/dist-cli/chunks/{agent-wrapper-S7VI3ZCW.js → agent-wrapper-ZCSAPGFF.js} +2 -2
- package/dist-cli/chunks/{app-fonts-FFTAYNLC.js → app-fonts-4WW4EQEW.js} +2 -2
- package/dist-cli/chunks/{assert-YSAT2X4B.js → assert-XEWAR4HT.js} +2 -2
- package/dist-cli/chunks/{auth-BBXWHS3S.js → auth-SAYME64O.js} +2 -2
- package/dist-cli/chunks/beta-HKVUNMLY.js +2 -0
- package/dist-cli/chunks/{camera-LH2ZTROS.js → camera-2AHKTJ5I.js} +2 -2
- package/dist-cli/chunks/{chunk-WUYUHJOD.js → chunk-3FBFOGQJ.js} +1 -1
- package/dist-cli/chunks/{chunk-LJGC7CHF.js → chunk-462J7KLI.js} +18 -18
- package/dist-cli/chunks/{chunk-CBIBUDE4.js → chunk-5CJQNMXY.js} +2 -2
- package/dist-cli/chunks/{chunk-HHZMPBNU.js → chunk-5D5XSE5V.js} +2 -2
- package/dist-cli/chunks/{chunk-IIDQH75G.js → chunk-5IBT7JOS.js} +2 -2
- package/dist-cli/chunks/{chunk-ZJR7NF7O.js → chunk-5NGZRMTN.js} +1 -1
- package/dist-cli/chunks/{chunk-UWR4G5L5.js → chunk-5ZBUNUUE.js} +2 -2
- package/dist-cli/chunks/{chunk-IHORHFVB.js → chunk-653O3F3M.js} +2 -2
- package/dist-cli/chunks/{chunk-3ZLJ74Q2.js → chunk-76O3ZWTI.js} +1 -1
- package/dist-cli/chunks/{chunk-DURQWXCM.js → chunk-7CU7FXRN.js} +2 -2
- package/dist-cli/chunks/{chunk-7YYF4MBI.js → chunk-7GKJ3U2Z.js} +2 -2
- package/dist-cli/chunks/{chunk-IJXWIBTJ.js → chunk-7NW75BHD.js} +2 -2
- package/dist-cli/chunks/{chunk-NXGHLLUE.js → chunk-DLMAMKWL.js} +2 -2
- package/dist-cli/chunks/{chunk-VJP4E3Y7.js → chunk-EFTPP4W3.js} +3 -3
- package/dist-cli/chunks/{chunk-BBCCZ2JV.js → chunk-EPJO7YNS.js} +1 -1
- package/dist-cli/chunks/{chunk-UDUOJJ7M.js → chunk-FWC4J42U.js} +1 -1
- package/dist-cli/chunks/{chunk-BSJYTX7Z.js → chunk-GJDCBMAP.js} +1 -1
- package/dist-cli/chunks/{chunk-YZSZNAPH.js → chunk-GZON2OYB.js} +1 -1
- package/dist-cli/chunks/{chunk-VMU6I22G.js → chunk-H7F2BILD.js} +1 -1
- package/dist-cli/chunks/{chunk-O4YBOEQU.js → chunk-HFJEB4UJ.js} +2 -2
- package/dist-cli/chunks/{chunk-VECHY3XI.js → chunk-HQRKN435.js} +2 -2
- package/dist-cli/chunks/{chunk-PAOT7WT6.js → chunk-IDZP6WN5.js} +1 -1
- package/dist-cli/chunks/{chunk-24SJ7HEY.js → chunk-IGPDVTHJ.js} +1 -1
- package/dist-cli/chunks/{chunk-I5VNIQEQ.js → chunk-JTZNB4PB.js} +2 -2
- package/dist-cli/chunks/{chunk-OGZWLUGX.js → chunk-KBG6WN24.js} +2 -2
- package/dist-cli/chunks/{chunk-NIHPV2IG.js → chunk-KQKLLUX5.js} +2 -2
- package/dist-cli/chunks/{chunk-GMTRGHR3.js → chunk-KSN2WTV6.js} +1 -1
- package/dist-cli/chunks/{chunk-MIHJ4O2F.js → chunk-KTTLGU7Y.js} +2 -2
- package/dist-cli/chunks/chunk-KU3T3N2W.js +1 -0
- package/dist-cli/chunks/{chunk-AEXYSGDX.js → chunk-LD5ZN4ZU.js} +2 -2
- package/dist-cli/chunks/{chunk-W3ZBG5BY.js → chunk-LHBU5QMM.js} +1 -1
- package/dist-cli/chunks/{chunk-N3LAYW3R.js → chunk-LJU4JU3N.js} +2 -2
- package/dist-cli/chunks/{chunk-5EZS5AVW.js → chunk-NGPK2CLP.js} +3 -3
- package/dist-cli/chunks/{chunk-WZAIEVZO.js → chunk-NN4CZ2QW.js} +1 -1
- package/dist-cli/chunks/{chunk-6HJAZWM5.js → chunk-NPP6ZJLD.js} +2 -2
- package/dist-cli/chunks/{chunk-4WGKKFZK.js → chunk-NRXMKMIJ.js} +2 -2
- package/dist-cli/chunks/{chunk-SRDCVOCU.js → chunk-OC6PU44E.js} +1 -1
- package/dist-cli/chunks/{chunk-R7IIIW6G.js → chunk-QOIOK64H.js} +1 -1
- package/dist-cli/chunks/{chunk-ATN2ZQXJ.js → chunk-R36NUSCM.js} +2 -2
- package/dist-cli/chunks/{chunk-PRB5UOOW.js → chunk-U6GFEFUD.js} +3 -3
- package/dist-cli/chunks/{chunk-EPGSNTZA.js → chunk-UQLIMTO6.js} +1 -1
- package/dist-cli/chunks/{chunk-SWED2BLD.js → chunk-UZA3Q67P.js} +1 -1
- package/dist-cli/chunks/{chunk-V6BP2WIV.js → chunk-VK3IISND.js} +1 -1
- package/dist-cli/chunks/{chunk-V72JVGCL.js → chunk-Z6I5M7VJ.js} +2 -2
- package/dist-cli/chunks/{chunk-WQVV2NAR.js → chunk-ZEYCE3XJ.js} +1 -1
- package/dist-cli/chunks/{chunk-4KOOLTKV.js → chunk-ZYS5SEB2.js} +2 -2
- package/dist-cli/chunks/{cleanup-K7U6EVNB.js → cleanup-KXX5W42A.js} +2 -2
- package/dist-cli/chunks/cli-version-IQXVYN67.js +2 -0
- package/dist-cli/chunks/{compat-SZSCR6GH.js → compat-VDVJ2I74.js} +3 -3
- package/dist-cli/chunks/{config-S7NYZDBT.js → config-FIQQP5FR.js} +2 -2
- package/dist-cli/chunks/control-GDBZBVQC.js +2 -0
- package/dist-cli/chunks/daemon-Y76JSFGV.js +2 -0
- package/dist-cli/chunks/{debug-2BI2MQZF.js → debug-LPLH46JF.js} +3 -3
- package/dist-cli/chunks/{desktop-R26HXPGF.js → desktop-4HDRWKMN.js} +3 -3
- package/dist-cli/chunks/{detox-RQTJ4HYR.js → detox-U23WKW23.js} +2 -2
- package/dist-cli/chunks/{device-HUUMZTIL.js → device-HZKTA7ZV.js} +2 -2
- package/dist-cli/chunks/{diagnose-ARA5FXYD.js → diagnose-M64QUWBW.js} +2 -2
- package/dist-cli/chunks/disk-cleanup-P662TT6J.js +2 -0
- package/dist-cli/chunks/drivers-CKWEDYVG.js +2 -0
- package/dist-cli/chunks/{film-QLCYUCQ4.js → film-4IB44CT3.js} +3 -3
- package/dist-cli/chunks/flow-WDFYSQKC.js +2 -0
- package/dist-cli/chunks/help-2S3OHQLT.js +2 -0
- package/dist-cli/chunks/{hidden-runtime-alias-72NBAFKY.js → hidden-runtime-alias-UEU5POA4.js} +2 -2
- package/dist-cli/chunks/{home-paths-UIBXEFMN.js → home-paths-2C4YKPPX.js} +2 -2
- package/dist-cli/chunks/inspect-SKU24VE3.js +2 -0
- package/dist-cli/chunks/install-desktop-RKURHJ34.js +2 -0
- package/dist-cli/chunks/{login-YE2BK4QL.js → login-MY54AOXW.js} +4 -4
- package/dist-cli/chunks/{logout-WFW5QWT2.js → logout-LYR2RDJY.js} +2 -2
- package/dist-cli/chunks/{maestro-4BV3LFYD.js → maestro-4RAMCNZQ.js} +3 -3
- package/dist-cli/chunks/{maestro-generate-TIMKH72I.js → maestro-generate-CBSUR73A.js} +3 -3
- package/dist-cli/chunks/{mode-NYCOTNKV.js → mode-2KATMMXB.js} +2 -2
- package/dist-cli/chunks/optional-demo-registry-26Q7AW7X.js +2 -0
- package/dist-cli/chunks/{perf-ZH32XKVP.js → perf-FVL2ZRQW.js} +2 -2
- package/dist-cli/chunks/{record-PCUUDX52.js → record-TCD4VLNH.js} +3 -3
- package/dist-cli/chunks/runtime-Z3D53UGW.js +2 -0
- package/dist-cli/chunks/{screenshot-command-KV44OIET.js → screenshot-command-ENCJ4W2W.js} +3 -3
- package/dist-cli/chunks/{screenshots-capture-XUBNTFRQ.js → screenshots-capture-FVVMZPFO.js} +2 -2
- package/dist-cli/chunks/{serve-PWH4LRTV.js → serve-HNHS3QBP.js} +2 -2
- package/dist-cli/chunks/{setup-JLOEBJTV.js → setup-MRLIGVU4.js} +3 -3
- package/dist-cli/chunks/{skills-YECTLRSK.js → skills-2LW5BE7P.js} +2 -2
- package/dist-cli/chunks/{storage-QRIGOXVF.js → storage-KH5HQF3V.js} +2 -2
- package/dist-cli/chunks/store-IBEI6PK4.js +2 -0
- package/dist-cli/chunks/telemetry-3T56HLDZ.js +2 -0
- package/dist-cli/chunks/{timeline-UZZLCBZX.js → timeline-BWFBU4VM.js} +2 -2
- package/dist-cli/chunks/{upgrade-IHLQZEUO.js → upgrade-GZFX4JEO.js} +2 -2
- package/dist-cli/chunks/upload-PCXRS5D7.js +2 -0
- package/dist-cli/chunks/{version-CQDBVDLR.js → version-OKMVZCP5.js} +2 -2
- package/dist-cli/chunks/{web-QUPPSYGZ.js → web-ZHCP6WFY.js} +2 -2
- package/dist-cli/chunks/{what-happened-QFD2EAZH.js → what-happened-MC7JDW6C.js} +2 -2
- package/dist-lib/agent-daemon-client.cjs +1 -1
- package/dist-lib/agent-events.cjs +1 -1
- package/dist-lib/agent-identity.cjs +1 -1
- package/dist-lib/agent-sessions.cjs +1 -1
- package/dist-lib/attached-projects.cjs +1 -1
- package/dist-lib/auth/shared-session.cjs +1 -1
- package/dist-lib/backend-origin.cjs +1 -1
- package/dist-lib/beta.cjs +1 -1
- package/dist-lib/beta.mjs +1 -1
- package/dist-lib/bridge-constants.cjs +1 -1
- package/dist-lib/cli-constants.cjs +1 -1
- package/dist-lib/config.cjs +1 -1
- package/dist-lib/detox/index.cjs +2 -1
- package/dist-lib/dev-bundle-resolution.cjs +1 -1
- package/dist-lib/home-paths.cjs +1 -1
- package/dist-lib/host/bridge-host.cjs +1 -1
- package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
- package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
- package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
- package/dist-lib/host/websocket-proxy.cjs +1 -1
- package/dist-lib/index.cjs +1 -1
- package/dist-lib/jump-to-source-babel.cjs +1 -1
- package/dist-lib/menu.cjs +1 -1
- package/dist-lib/menu.mjs +1 -1
- package/dist-lib/metro.cjs +1 -1
- package/dist-lib/profiles.cjs +1 -1
- package/dist-lib/render-mode.cjs +1 -1
- package/dist-lib/scripts/dev-server-scanner.cjs +1 -1
- package/dist-lib/sdk.cjs +1 -1
- package/dist-lib/sdk.mjs +1 -1
- package/dist-lib/skills.cjs +2 -1
- package/dist-lib/vite.cjs +1 -1
- package/package.json +1 -1
- package/dist-cli/chunks/beta-JLPXVJ7I.js +0 -2
- package/dist-cli/chunks/chunk-NL2GIKEC.js +0 -1
- package/dist-cli/chunks/cli-version-JBK5UE3U.js +0 -2
- package/dist-cli/chunks/control-F5T7YG2J.js +0 -2
- package/dist-cli/chunks/daemon-IAAVBIHY.js +0 -2
- package/dist-cli/chunks/disk-cleanup-GBWPBY36.js +0 -2
- package/dist-cli/chunks/drivers-3PJWRMFP.js +0 -2
- package/dist-cli/chunks/flow-OH7WLXP3.js +0 -2
- package/dist-cli/chunks/help-IDHC44HQ.js +0 -2
- package/dist-cli/chunks/inspect-NU2X7MF7.js +0 -2
- package/dist-cli/chunks/install-desktop-ZKZOOLIS.js +0 -2
- package/dist-cli/chunks/optional-demo-registry-PKSJ7CKC.js +0 -2
- package/dist-cli/chunks/runtime-ZSB6FRNC.js +0 -2
- package/dist-cli/chunks/store-OC4DHBNY.js +0 -2
- package/dist-cli/chunks/telemetry-GMT2XQND.js +0 -2
- package/dist-cli/chunks/upload-VBJVH2S2.js +0 -2
package/dist-cli/bin.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
/*! sootsim v0.1.
|
|
3
|
-
import{a as w,b as g}from"./chunks/chunk-
|
|
2
|
+
/*! sootsim v0.1.291 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
3
|
+
import{a as w,b as g}from"./chunks/chunk-IGPDVTHJ.js";import"./chunks/chunk-ZEYCE3XJ.js";function b(t){let a=t instanceof Error?t.message:String(t);(/^command timed out after \d+s$/.test(a)||a.startsWith("sim disconnected:")||a.startsWith("bridge never reconnected")||a.startsWith("multiple sims are connected:")||a.startsWith("saved sim ")||a.startsWith("no sim connected with id ")||a.startsWith("could not connect to ws://")||a.startsWith("sootsim bridge daemon is not running")||a.startsWith("sootsim bridge lockfile is fresh")||a.startsWith("sootsim bridge exited before becoming ready")||a.startsWith("background daemon setup is unavailable")||a.startsWith("sootsim bridge did not start within"))&&!process.env.SOOTSIM_VERBOSE&&(process.stderr.write(` ${a}
|
|
4
4
|
`),process.exit(1)),t instanceof Error&&t.stack?process.stderr.write(`${t.stack}
|
|
5
5
|
`):process.stderr.write(`${a}
|
|
6
6
|
`),process.exit(1)}process.on("unhandledRejection",b);process.on("uncaughtException",b);var A=typeof __SOOTSIM_STANDALONE__<"u"&&__SOOTSIM_STANDALONE__,k=new Set(["desktop"]);function S(t){!A||!k.has(t)||(process.stderr.write(` sootsim ${t} isn't available in the standalone binary \u2014
|
|
7
7
|
it needs vite / electron / playwright from a project's node_modules.
|
|
8
8
|
run the npm package instead:
|
|
9
9
|
sootsim ${t}
|
|
10
|
-
`),process.exit(1))}var e=g(process.argv);if(!e.command&&e.commandArgs.length>0){let{resolveHiddenRuntimeAlias:t}=await import("./chunks/hidden-runtime-alias-
|
|
11
|
-
`)}var f=!1;async function v(){if(!f&&(f=!0,!(e.command==="cleanup"||e.command==="serve"||e.command==="agent-wrapper"||e.command==="daemon"&&e.commandArgs[0]==="uninstall")))try{let{isAutomaticSootsimCleanupComplete:t}=await import("./chunks/disk-cleanup-
|
|
10
|
+
`),process.exit(1))}var e=g(process.argv);if(!e.command&&e.commandArgs.length>0){let{resolveHiddenRuntimeAlias:t}=await import("./chunks/hidden-runtime-alias-UEU5POA4.js");e=t(e)}var _=e.command==="cleanup"&&e.commandArgs.length===1&&e.commandArgs[0]==="--automatic-worker";if(!_){let{trackCliEvent:t}=await import("./chunks/telemetry-3T56HLDZ.js");t({event:"cli_command_invoked",properties:{command:e.command||(e.version?"version":e.help?"help":"none"),arg_count:e.commandArgs.length,platform:process.platform,arch:process.arch,node_version:process.versions.node}})}if(e.command!=="serve"&&e.command!=="daemon"){let{consumeRuntimeUpgradeNotice:t}=await import("./chunks/home-paths-2C4YKPPX.js"),a=t();a&&process.stderr.write(` SootSim engine upgraded to v${a.to}`+(a.from?` (from v${a.from})`:"")+` \xB7 what's new: https://sootsim.com/changelog
|
|
11
|
+
`)}var f=!1;async function v(){if(!f&&(f=!0,!(e.command==="cleanup"||e.command==="serve"||e.command==="agent-wrapper"||e.command==="daemon"&&e.commandArgs[0]==="uninstall")))try{let{isAutomaticSootsimCleanupComplete:t}=await import("./chunks/disk-cleanup-P662TT6J.js");if(t())return;let{spawn:a}=await import("node:child_process"),n=["cleanup","--automatic-worker"],m=process.argv[1],d=A?a(process.execPath,n,{detached:!0,stdio:["ignore","ignore","inherit"],env:process.env}):m?a(process.execPath,[m,...n],{detached:!0,stdio:["ignore","ignore","inherit"],env:process.env}):a("sootsim",n,{detached:!0,stdio:["ignore","ignore","inherit"],env:process.env});d.once("error",p=>{process.stderr.write(` SootSim automatic cleanup will retry on the next run: ${p.message}
|
|
12
12
|
`)}),d.unref()}catch(t){process.stderr.write(` SootSim automatic cleanup will retry on the next run: ${t instanceof Error?t.message:String(t)}
|
|
13
|
-
`)}}async function r(t){let{flushCliTelemetry:a}=await import("./chunks/telemetry-
|
|
13
|
+
`)}}async function r(t){let{flushCliTelemetry:a}=await import("./chunks/telemetry-3T56HLDZ.js");await a(),await v(),process.exit(t)}if(e.version){let{getCliVersion:t}=await import("./chunks/cli-version-IQXVYN67.js"),{IS_BETA:a,BETA_LABEL:n}=await import("./chunks/beta-HKVUNMLY.js"),m=a?` \xB7 ${n}`:"";console.log(`sootsim v${t()}${m}`);let{readActiveRuntime:d}=await import("./chunks/home-paths-2C4YKPPX.js"),p=d();console.log(p?`runtime v${p}`:"runtime not installed"),await r(0)}if(e.help&&!e.command){let{printHelp:t}=await import("./chunks/help-2S3OHQLT.js");t(),await r(0)}var o=e.globalFlags.port,c=e.verbose,l=e.globalFlags.device,u=e.globalFlags.theme,C=e.globalFlags.driver,O=e.globalFlags.headless===!0,h=e.globalFlags.sim??e.globalFlags.session??e.globalFlags.tab,i=h?["--sim",h,...e.commandArgs]:e.commandArgs;if(l||u){let{settingsStore:t}=await import("./chunks/store-IBEI6PK4.js"),a={};l&&(a.deviceModel=l),u&&(a.colorScheme=u),t.apply(a)}if(!e.command&&e.commandArgs.length===0){let{runSetup:t,shouldRunSetupForBareCommand:a}=await import("./chunks/setup-MRLIGVU4.js");a()&&(await t(["--from-welcome"]),await r(0));let{printHelp:n}=await import("./chunks/help-2S3OHQLT.js");n(),await r(0)}var s=e.command??"";if(!s){if(e.commandArgs.length>0){let a=e.commandArgs.find(n=>!n.startsWith("-"))??e.commandArgs[0];console.error(` unknown command: ${a}`),console.error(" run `sootsim --help` to see the full surface."),await r(1)}let{printHelp:t}=await import("./chunks/help-2S3OHQLT.js");t(),await r(0)}if(e.help||e.commandArgs.includes("--help")||e.commandArgs.includes("-h")){if(s==="skill"){let{runSkill:n}=await import("./chunks/skills-2LW5BE7P.js");await n(e.commandArgs),await r(0)}let t=s==="do"||s==="get"||s==="debug"||s==="shell"||s==="perf"||s==="wait",a=e.commandArgs.find(n=>!n.startsWith("-"));if(!(s==="shell"||s==="perf"))if(t&&!a){let{printGroupHelp:n}=await import("./chunks/help-2S3OHQLT.js");n(s)&&await r(0)}else{let{printCommandHelp:n}=await import("./chunks/help-2S3OHQLT.js");n(t&&a?a:s,{prefer:t&&a?"verb":"command",group:t&&a?s:void 0}),await r(0)}}S(s);if(w.has(s)){let{runInspect:t}=await import("./chunks/inspect-SKU24VE3.js");await t([s,...i],{port:o,verbose:c})}else switch(s){case"assert":{let{runAssert:t}=await import("./chunks/assert-XEWAR4HT.js");await t(e.commandArgs);break}case"detox":{let{runDetox:t}=await import("./chunks/detox-U23WKW23.js");await t(e.commandArgs,{port:o,verbose:c});break}case"maestro":{let{runMaestro:t}=await import("./chunks/maestro-4RAMCNZQ.js"),a=await t(i,{port:o,verbose:c});await r(typeof a=="number"?a:0)}case"record":{let{runRecord:t}=await import("./chunks/record-TCD4VLNH.js");await t(i,{port:o,verbose:c});break}case"film":{let{runFilm:t}=await import("./chunks/film-4IB44CT3.js"),a=await t(i,{port:o,verbose:c});await r(typeof a=="number"?a:0)}case"storage":{let{runStorage:t}=await import("./chunks/storage-KH5HQF3V.js"),a=await t(i,{port:o,verbose:c});await r(typeof a=="number"?a:0)}case"perf":{let{runPerf:t}=await import("./chunks/perf-FVL2ZRQW.js"),a=await t(i,{port:o,verbose:c});await r(typeof a=="number"?a:0)}case"screenshot":{let{runScreenshotCommand:t}=await import("./chunks/screenshot-command-ENCJ4W2W.js"),a=await t(i,{port:o,verbose:c});await r(typeof a=="number"?a:0)}case"mode":{let{runMode:t}=await import("./chunks/mode-2KATMMXB.js");await t(i,{port:o,verbose:c});break}case"inspect":{let{runInspect:t}=await import("./chunks/inspect-SKU24VE3.js");await t(i,{port:o,verbose:c});break}case"debug":{let{runDebug:t}=await import("./chunks/debug-LPLH46JF.js");await t(i,{port:o,verbose:c});break}case"timeline":{let{runTimeline:t}=await import("./chunks/timeline-BWFBU4VM.js");await t(i,{port:o,verbose:c});break}case"what-happened":{let{runWhatHappened:t}=await import("./chunks/what-happened-MC7JDW6C.js");await t(i,{port:o,verbose:c});break}case"open":{let{runOpenCommand:t}=await import("./chunks/control-GDBZBVQC.js");await t(i,{port:o});break}case"use":{let{runUseCommand:t}=await import("./chunks/control-GDBZBVQC.js");await t(i,{port:o});break}case"claim":{let{runClaimCommand:t}=await import("./chunks/control-GDBZBVQC.js");await t(i,{port:o});break}case"close":{let{runCloseCommand:t}=await import("./chunks/control-GDBZBVQC.js");await t(i,{port:o});break}case"device":{let{runDeviceCommand:t}=await import("./chunks/device-HZKTA7ZV.js");await t(i,{port:o});break}case"compat":{let{runCompat:t}=await import("./chunks/compat-VDVJ2I74.js");await t(e.commandArgs);break}case"desktop":{let{runDesktop:t}=await import("./chunks/desktop-4HDRWKMN.js");await t(e.commandArgs,{port:o,device:l,driver:C});break}case"login":{let{runLogin:t}=await import("./chunks/login-MY54AOXW.js");await t(e.commandArgs);break}case"logout":{let{runLogout:t}=await import("./chunks/logout-LYR2RDJY.js");await t();break}case"auth":{let{runAuth:t}=await import("./chunks/auth-SAYME64O.js");await t(e.commandArgs);break}case"setup":{let{runSetup:t}=await import("./chunks/setup-MRLIGVU4.js");await t(e.commandArgs);break}case"serve":{let{runServe:t}=await import("./chunks/serve-HNHS3QBP.js");await t(e.commandArgs,{port:o});break}case"daemon":{let{runDaemon:t}=await import("./chunks/daemon-Y76JSFGV.js");await t(e.commandArgs,{port:o});break}case"runtime":{let{runRuntime:t}=await import("./chunks/runtime-Z3D53UGW.js");await t(e.commandArgs);break}case"upgrade":{let{runUpgrade:t}=await import("./chunks/upgrade-GZFX4JEO.js");await t(e.commandArgs);break}case"version":{let{runVersion:t}=await import("./chunks/version-OKMVZCP5.js");await t(e.commandArgs);break}case"agent":{let{runAgentCommand:t}=await import("./chunks/agent-EDS4HRKB.js"),a=await t(e.commandArgs);await r(a)}case"agent-wrapper":{let{runAgentWrapper:t}=await import("./chunks/agent-wrapper-ZCSAPGFF.js"),a=await t(e.commandArgs);await r(a)}case"skill":{let{runSkill:t}=await import("./chunks/skills-2LW5BE7P.js");await t(e.commandArgs);break}case"app-fonts":{let{runAppFonts:t}=await import("./chunks/app-fonts-4WW4EQEW.js");await t(e.commandArgs);break}case"config":{let{runConfig:t}=await import("./chunks/config-FIQQP5FR.js");await t(e.commandArgs);break}case"cleanup":{let{runCleanup:t}=await import("./chunks/cleanup-KXX5W42A.js"),a=await t(e.commandArgs);await r(a)}default:console.error(` unknown command: ${s}`),console.error(" run `sootsim --help` to see the full surface."),await r(1)}await v();
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
/*! sootsim v0.1.
|
|
2
|
-
import{a as b,b as E,c as A,d as l,e as S,g as j,h as T,j as I,n as k,o as D,p as x,q as g,r as O,s as C}from"./chunk-
|
|
1
|
+
/*! sootsim v0.1.291 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
|
+
import{a as b,b as E,c as A,d as l,e as S,g as j,h as T,j as I,n as k,o as D,p as x,q as g,r as O,s as C}from"./chunk-ZYS5SEB2.js";import"./chunk-76O3ZWTI.js";import{c as $}from"./chunk-NRXMKMIJ.js";import"./chunk-DLMAMKWL.js";import"./chunk-5D5XSE5V.js";import"./chunk-Z6I5M7VJ.js";import"./chunk-IDZP6WN5.js";import"./chunk-UQLIMTO6.js";import"./chunk-EPJO7YNS.js";import"./chunk-H7F2BILD.js";import{j as y}from"./chunk-5NGZRMTN.js";import"./chunk-LHBU5QMM.js";import"./chunk-GZON2OYB.js";import"./chunk-ZEYCE3XJ.js";import w from"node:fs";import d from"node:path";import{spawn as _}from"node:child_process";import F from"node:net";import{WebSocket as R}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 R(`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 sendClaimedPrompt(e,t){return this.send("agent:send-claimed-prompt",{simId: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!==R.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 M(n=7668,e=400){return new Promise(t=>{let r=new F.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 B(n={}){let e=n.port??7668;if(await M(e))return{alreadyRunning:!0};if(y())throw new c(`no sootsim bridge on port ${e}. run \`sootsim setup\` to install the background daemon, or \`sootsim serve\` in another shell.`,"DEV_HOST_REFUSED");let{cmd:t,prefixArgs:r}=C(),s=[...r,"serve","--quiet"];e!==7668&&s.push("--port",String(e));let o=_(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 M(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 serve\` manually to diagnose.`,"SPAWN_TIMEOUT")}async function h(n={}){await B({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 ge(n){let[e,...t]=n;try{switch(e){case void 0:case"--help":case"-h":case"help":return L(),0;case"attach":return await W(t);case"projects":return await J();case"project":return await V(t);case"sessions":return await H(t);case"start":return await G(t);case"prompt":return await q(t);case"watch":return await K(t);case"transcript":return await z(t);case"end":return await Q(t);case"paths":return await Y();default:return process.stderr.write(`unknown agent subcommand: ${e}
|
|
3
3
|
`),L(),2}}catch(r){if(r instanceof c)return process.stderr.write(`${r.message}
|
|
4
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 L(){$("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 W(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
5
|
`),2;let s=d.resolve(r);if(!w.existsSync(s))return process.stderr.write(`directory does not exist: ${s}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
/*! sootsim v0.1.
|
|
2
|
-
import{b as M}from"./chunk-
|
|
1
|
+
/*! sootsim v0.1.291 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
|
+
import{b as M}from"./chunk-76O3ZWTI.js";import"./chunk-ZEYCE3XJ.js";import{execFile as G,spawn as q}from"node:child_process";import{randomUUID as X}from"node:crypto";import{constants as R,createReadStream as Y,createWriteStream as j,existsSync as C,openSync as J}from"node:fs";import V from"node:fs/promises";import z from"node:path";import K from"node:readline";import{promisify as Q}from"node:util";import{spawn as H}from"node:child_process";import L from"node:readline";var b=class extends Error{code;data;constructor(t,r,m){super(t),this.name="CodexRpcError",this.code=r,this.data=m}};function W(d){let t=H(d.bin,["app-server"],{cwd:d.cwd,env:{...process.env,...d.env},stdio:["pipe","pipe","pipe"]}),r=new Map,m=new Map,u=1,f=!1,a=new Promise(s=>{t.on("exit",(o,e)=>{f=!0;let p=new Error(`codex app-server exited (code=${o}, signal=${e??""})`);for(let{reject:y}of r.values())y(p);r.clear(),s({code:o,signal:e})})});L.createInterface({input:t.stdout,crlfDelay:1/0}).on("line",s=>{let o=s.trim();if(!o)return;let e;try{e=JSON.parse(o)}catch{return}if(e.id!=null&&(e.result!==void 0||e.error!==void 0)){let p=typeof e.id=="string"?Number(e.id):e.id,y=p!=null?r.get(p):void 0;if(!y)return;r.delete(p),e.error?y.reject(new b(e.error.message,e.error.code,e.error.data)):y.resolve(e.result);return}if(e.method){let p=m.get(e.method);if(!p)return;for(let y of p)try{y(e.params)}catch(l){console.error(`[codex-client] handler for "${e.method}" threw:`,l instanceof Error?l.stack??l.message:l)}}}),t.stderr.setEncoding("utf8"),t.stderr.on("data",s=>{let o=m.get("__stderr__");if(o)for(let e of o)try{e({text:s})}catch{}});function n(s){if(!f)try{t.stdin.write(JSON.stringify(s)+`
|
|
3
3
|
`)}catch{}}return{exited:a,on(s,o){let e=m.get(s);return e||(e=new Set,m.set(s,e)),e.add(o),()=>{e?.delete(o)}},request(s,o){if(f)return Promise.reject(new Error(`codex app-server closed; cannot call ${s}`));let e=u++;return new Promise((p,y)=>{r.set(e,{resolve:l=>p(l),reject:y,method:s}),n({jsonrpc:"2.0",id:e,method:s,params:o})})},notify(s,o){n({jsonrpc:"2.0",method:s,params:o})},async shutdown(s=1500){if(f)return;try{t.stdin.end()}catch{}let o=setTimeout(()=>{if(!f)try{t.kill("SIGTERM")}catch{}},s);try{await a}finally{clearTimeout(o)}},kill(s="SIGTERM"){if(!f)try{t.kill(s)}catch{}}}}var O="never",F="danger-full-access",Z={type:"dangerFullAccess"},D="fast",ee="medium",te=Q(G);async function ne(d,t){let r=t||d;if(r.includes("/")||r.includes("\\"))return C(r)?{ok:!0,path:r}:{ok:!1,message:`agent binary not found at path: ${r}`};try{let{stdout:m}=await te("which",[r],{timeout:1500}),u=m.trim();return u?{ok:!0,path:u}:{ok:!1,message:`${r} not found on PATH`}}catch{return{ok:!1,message:`${r} not found on PATH. install the ${d} CLI and retry, or pass --${d}-bin /path/to/${d} to agent start.`}}}function re(d){let t={"--session-id":"sessionId","--project-id":"projectId","--provider":"provider","--cwd":"cwd","--prompt-in":"promptIn","--events-out":"eventsOut","--transcript":"transcript","--codex-bin":"codexBin","--claude-bin":"claudeBin","--claude-session-uuid":"claudeSessionUuid"},r={};for(let m=0;m<d.length;m++){let u=d[m];if(u==="--fresh-thread"){r.freshThread=!0;continue}let f=t[u];f&&(r[f]=d[m+1],m++)}return r}async function Ie(d){let t=re(d);if(!t.sessionId||!t.projectId||!t.provider||!t.cwd||!t.promptIn||!t.eventsOut)return process.stderr.write(`usage: sootsim agent-wrapper --session-id <id> --project-id <id>
|
|
4
4
|
--provider codex|claude --cwd <path>
|
|
5
5
|
--prompt-in <fifo> --events-out <fifo>
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
/*! sootsim v0.1.
|
|
2
|
-
import{d as p}from"./chunk-
|
|
1
|
+
/*! sootsim v0.1.291 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
|
+
import{d as p}from"./chunk-QOIOK64H.js";import"./chunk-ZEYCE3XJ.js";import{existsSync as h,mkdirSync as d,readFileSync as y,writeFileSync as g}from"node:fs";import{join as m}from"node:path";import{gzipSync as w}from"node:zlib";function f(t,e){let o=t.indexOf(`--${e}`);if(o!==-1&&o+1<t.length)return t[o+1];let i=t.find(r=>r.startsWith(`--${e}=`));return i?i.slice(e.length+3):void 0}async function S(t){let e=f(t,"wire")||"",o=f(t,"out-dir"),i=f(t,"manifest");if((!o||!i)&&(console.error(" usage: sootsim app-fonts stage --wire <wire> --out-dir <dir> --manifest <path>"),process.exit(1)),!e.trim()){console.log("no app fonts declared \u2014 nothing to stage");return}d(o,{recursive:!0});let r=await p(e,{onStaged:({url:n,byteLength:s})=>console.log(` staged app font: ${n} (${(s/1024).toFixed(1)} KiB)`),onError:(n,s)=>console.error(` warning: failed to fetch app font ${n}: ${s instanceof Error?s.message:s}`)}),a=[];for(let n of r){let s=w(n.bytes);g(m(o,n.urlhash),s),a.push({url:n.url,urlhash:n.urlhash,contentType:n.contentType,encoding:"gzip",sizeBytes:s.length,rawBytes:n.bytes.byteLength})}let c=[];if(h(i))try{let n=JSON.parse(y(i,"utf8"));Array.isArray(n)&&(c=n)}catch{}let u=new Set(c.map(n=>n.urlhash)),l=[...c,...a.filter(n=>!u.has(n.urlhash))];g(i,JSON.stringify(l)),console.log(`staged ${a.length} app font(s); manifest now has ${l.length} file(s)`)}async function E(t){let e=t[0];if(e==="stage"){await S(t.slice(1));return}console.error(` unknown app-fonts subcommand: ${e??"(none)"}`),console.error(" available: stage"),process.exit(1)}export{E as runAppFonts};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
/*! sootsim v0.1.
|
|
2
|
-
import"./chunk-
|
|
1
|
+
/*! sootsim v0.1.291 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
|
+
import"./chunk-ZEYCE3XJ.js";import{spawn as x}from"child_process";var w=new Set(["describe","find","list","network","logs","count","tree","url","a11y","node","layout","keyboard","errors","warnings","requests","animations","animation","state","sample-color"]),S=new Set(["--exists","--empty","--negate","--quiet","--allow-timeout","!"]),q=new Set(["--count","--count-at-least","--count-at-most","--contains","--not-contains","--matches","--not-matches","--equals","--jq","--has-path","--within"]),P=new Set(["--path-equals"]);function j(s){let r=[],u=[],n=0,e=!1,t=!1,i=!1;for(let o=0;o<s.length;o++){let a=s[o];if(a==="--within"){let c=Number(s[o+1]);if(!Number.isFinite(c)||c<0)return{error:`--within requires a non-negative number, got: ${s[o+1]}`};n=c,o++;continue}if(a==="--negate"||a==="!"){e=!0;continue}if(a==="--quiet"){t=!0;continue}if(a==="--allow-timeout"){i=!0;continue}if(S.has(a)){u.push({kind:a,args:[]});continue}if(q.has(a)){let c=s[o+1];if(c==null)return{error:`${a} requires a value`};u.push({kind:a,args:[c]}),o++;continue}if(P.has(a)){let c=s[o+1],f=s[o+2];if(c==null||f==null)return{error:`${a} requires <path> <value>`};u.push({kind:a,args:[c,f]}),o+=2;continue}r.push(a)}return r.length===0?{error:"assert requires a verb (e.g. find, describe, get errors)"}:{verbArgs:r,predicates:u,withinMs:n,negate:e,quiet:t,allowTimeout:i}}function N(s){return s[0]==="get"||s[0]==="debug"?w.has(s[1])?s[1]:null:s[0]==="do"||s[0]==="wait"?null:w.has(s[0])?s[0]:null}async function R(s){let u=[process.argv[1],...s,"--json"];return new Promise(n=>{let e=x(process.execPath,u,{stdio:["ignore","pipe","pipe"],env:process.env}),t="",i="";e.stdout.on("data",o=>t+=o.toString()),e.stderr.on("data",o=>i+=o.toString()),e.on("error",o=>{n({ok:!1,payload:null,reason:`spawn failed: ${o.message}`})}),e.on("close",o=>{if(o!==0){let a=i.trim().split(`
|
|
3
3
|
`).slice(-2).join(" | ").slice(0,200);n({ok:!1,payload:null,reason:`verb exited ${o}${a?`: ${a}`:""}`});return}if(!t.trim()){n({ok:!1,payload:null,reason:"verb produced no output"});return}try{let a=JSON.parse(t);n({ok:!0,payload:a})}catch{n({ok:!1,payload:null,reason:`verb output was not valid json: ${t.slice(0,120)}`})}})})}function y(s,r){let u=r.split(".").filter(e=>e.length>0),n=s;for(let e of u){if(n==null)return{found:!1};if(Array.isArray(n)){let t=Number(e);if(!Number.isInteger(t)||t<0||t>=n.length)return{found:!1};n=n[t];continue}if(typeof n=="object"){let t=n;if(!(e in t))return{found:!1};n=t[e];continue}return{found:!1}}return{found:!0,value:n}}function d(s){return Array.isArray(s)?s.length:s&&typeof s=="object"?Object.keys(s).length:null}async function A(s,r){let{kind:u,args:n}=s;switch(u){case"--exists":return r==null?{ok:!1,reason:"payload is null"}:d(r)===0?{ok:!1,reason:"payload is empty"}:{ok:!0,reason:"exists"};case"--empty":{if(r==null)return{ok:!0,reason:"payload is null"};let e=d(r);return e===0?{ok:!0,reason:"payload is empty"}:{ok:!1,reason:`payload has ${e} item(s)`}}case"--count":{let e=Number(n[0]),t=d(r);return t==null?{ok:!1,reason:`payload not countable (${typeof r})`}:{ok:t===e,reason:`count=${t}, want=${e}`}}case"--count-at-least":{let e=Number(n[0]),t=d(r);return t==null?{ok:!1,reason:"payload not countable"}:{ok:t>=e,reason:`count=${t}, want>=${e}`}}case"--count-at-most":{let e=Number(n[0]),t=d(r);return t==null?{ok:!1,reason:"payload not countable"}:{ok:t<=e,reason:`count=${t}, want<=${e}`}}case"--contains":{let e=n[0],t=JSON.stringify(r);return{ok:t.includes(e),reason:t.includes(e)?`contains "${e}"`:`missing "${e}"`}}case"--not-contains":{let e=n[0],t=JSON.stringify(r);return{ok:!t.includes(e),reason:t.includes(e)?`unexpected "${e}"`:`not contains "${e}"`}}case"--matches":{let e=new RegExp(n[0]),t=JSON.stringify(r),i=e.test(t);return{ok:i,reason:i?`matches /${n[0]}/`:`no match for /${n[0]}/`}}case"--not-matches":{let e=new RegExp(n[0]),t=JSON.stringify(r),i=!e.test(t);return{ok:i,reason:i?`not matches /${n[0]}/`:`unexpected /${n[0]}/`}}case"--equals":{let e=n[0],t=typeof r=="string"?r:typeof r=="number"||typeof r=="boolean"?String(r):JSON.stringify(r);return{ok:t===e,reason:`got=${JSON.stringify(t)}, want=${JSON.stringify(e)}`}}case"--has-path":{let e=y(r,n[0]);return{ok:e.found,reason:e.found?`path ${n[0]} present`:`path ${n[0]} missing`}}case"--path-equals":{let[e,t]=n,i=y(r,e);if(!i.found)return{ok:!1,reason:`path ${e} missing`};let o=typeof i.value=="string"||typeof i.value=="number"||typeof i.value=="boolean"?String(i.value):JSON.stringify(i.value);return{ok:o===t,reason:`${e}=${o}, want=${t}`}}case"--jq":{let e=n[0];try{let i=(await O(e,r)).trim();return{ok:i.length>0&&i!=="null"&&i!=="false"&&i!=='""',reason:`jq: ${i.slice(0,120)}`}}catch(t){throw new Error(`jq evaluation failed: ${t.message}`)}}default:return{ok:!1,reason:`unknown predicate ${u}`}}}function O(s,r){return new Promise((u,n)=>{let e=x("jq",[s],{stdio:["pipe","pipe","pipe"]}),t="",i="";e.stdout.on("data",o=>t+=o.toString()),e.stderr.on("data",o=>i+=o.toString()),e.on("error",n),e.on("close",o=>{if(o!==0){n(new Error(i.trim()||`jq exited ${o}`));return}u(t)}),e.stdin.end(JSON.stringify(r))})}async function T(s){(s[0]==="--help"||s[0]==="-h"||s.length===0)&&(J(),process.exit(s.length===0?2:0));let r=j(s);"error"in r&&(process.stderr.write(` assert: ${r.error}
|
|
4
4
|
`),process.exit(2));let{verbArgs:u,predicates:n,withinMs:e,negate:t,quiet:i,allowTimeout:o}=r;N(u)||(process.stderr.write(` assert: unknown or non-read verb: ${u.join(" ")}
|
|
5
5
|
supported: ${Array.from(w).sort().join(", ")}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
/*! sootsim v0.1.
|
|
2
|
-
import{a as t}from"./chunk-
|
|
1
|
+
/*! sootsim v0.1.291 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
|
+
import{a as t}from"./chunk-NPP6ZJLD.js";import{d as s}from"./chunk-KQKLLUX5.js";import"./chunk-5NGZRMTN.js";import"./chunk-ZEYCE3XJ.js";function i(){console.log(`
|
|
3
3
|
sootsim auth \u2014 inspect CLI auth
|
|
4
4
|
|
|
5
5
|
usage:
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
/*! sootsim v0.1.
|
|
2
|
-
import{m as d}from"./chunk-
|
|
1
|
+
/*! sootsim v0.1.291 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
|
+
import{m as d}from"./chunk-7GKJ3U2Z.js";import"./chunk-NN4CZ2QW.js";import{g as l,i as m,k as p}from"./chunk-5CJQNMXY.js";import"./chunk-UQLIMTO6.js";import"./chunk-EPJO7YNS.js";import"./chunk-5NGZRMTN.js";import"./chunk-ZEYCE3XJ.js";function f(){console.log(`
|
|
3
3
|
sootsim do scan \u2014 inject a barcode scan
|
|
4
4
|
|
|
5
5
|
usage:
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! sootsim v0.1.
|
|
1
|
+
/*! sootsim v0.1.291 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
import{createInterface as i}from"readline";var c=()=>i({input:process.stdin,output:process.stdout});function s(o){return new Promise(n=>{let r=c();r.question(o,t=>{r.close(),n(t.trim())})})}async function u(o,n=!0){let r=n?"[Y/n]":"[y/N]";if(!process.stdin.isTTY)return console.log(` ${o} ${r} ${n?"y":"n"} (non-interactive)`),n;let t=await s(` ${o} ${r} `);return t===""?n:t.toLowerCase().startsWith("y")}async function a(o,n){console.log(`
|
|
3
3
|
${o}
|
|
4
4
|
`);for(let e=0;e<n.length;e++)console.log(` ${e+1}. ${n[e]}`);if(console.log(),!process.stdin.isTTY)return console.log(` choose [1-${n.length}]: 1 (non-interactive)`),0;let r=await s(` choose [1-${n.length}]: `),t=parseInt(r,10);return t>=1&&t<=n.length?t-1:0}export{u as a,a as b};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
/*! sootsim v0.1.
|
|
2
|
-
import{a as st}from"./chunk-
|
|
1
|
+
/*! sootsim v0.1.291 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
|
+
import{a as st}from"./chunk-JTZNB4PB.js";import{a as it}from"./chunk-7CU7FXRN.js";import{a as ge,c as we,d as ye,e as tt,f as be,g as Se,h as rt,i as ve,j as nt}from"./chunk-NGPK2CLP.js";import{a as et}from"./chunk-KTTLGU7Y.js";import{e as ot}from"./chunk-KBG6WN24.js";import{h as Ye,p as Ze,r as Xe,v as Qe}from"./chunk-R36NUSCM.js";import{f as We}from"./chunk-7NW75BHD.js";import{h as me,m as qe}from"./chunk-7GKJ3U2Z.js";import{a as ze}from"./chunk-FWC4J42U.js";import{I as G,m as je,n as Ve,o as Je,p as Ge}from"./chunk-NN4CZ2QW.js";import{a as Ue}from"./chunk-VK3IISND.js";import{g as he,h as fe,i as Ke}from"./chunk-5CJQNMXY.js";import{c as Be,d as ue}from"./chunk-HQRKN435.js";import{a as Le,b as Ne,c as Ce}from"./chunk-IDZP6WN5.js";import{e as pe,f as He}from"./chunk-EPJO7YNS.js";import*as $ from"fs";import{createHash as Kt,randomUUID as qt}from"node:crypto";import{tmpdir as Y}from"os";import*as w from"path";import*as v from"fs";import*as S from"path";var Pt="inset 0 0 0 0.5px #000, inset 0 0 0 2px #757575, inset 0 0 0 5px #212121",lt=1;function kt(i){let e=Ce(i),t=e.scale,r=e.statusBarHeight>0&&!e.dynamicIsland&&e.homeIndicatorHeight===0&&e.cornerRadius===0,n=e.width,o=e.height,a=Le(e),s=r?e.width+58:a.frameWidth,l=r?e.height+111+111:a.frameHeight,p=9.5,u=lt,m=s+p*2,b=l+lt*2,g=p+(r?29:a.screenLeft),P=r?111:a.screenTop,k=r?52:a.frameRadius,H=[{side:e.hardwareButtons.lock.side,top:e.hardwareButtons.lock.top,height:e.hardwareButtons.lock.height,width:e.hardwareButtons.width},{side:e.hardwareButtons.ringToggle.side,top:e.hardwareButtons.ringToggle.top,height:e.hardwareButtons.ringToggle.height,width:e.hardwareButtons.width},{side:e.hardwareButtons.volumeUp.side,top:e.hardwareButtons.volumeUp.top,height:e.hardwareButtons.volumeUp.height,width:e.hardwareButtons.width},{side:e.hardwareButtons.volumeDown.side,top:e.hardwareButtons.volumeDown.top,height:e.hardwareButtons.volumeDown.height,width:e.hardwareButtons.width}];return{model:i,renderScale:t,outerWidth:Math.round(m*t),outerHeight:Math.round(b*t),logicalOuterWidth:m,logicalOuterHeight:b,logicalFrameWidth:s,logicalFrameHeight:l,logicalFrameLeft:p,logicalFrameTop:u,logicalScreenWidth:n,logicalScreenHeight:o,logicalScreenLeft:g,logicalScreenTop:P,logicalScreenRadius:r?0:a.screenRadius,logicalFrameRadius:k,frameBackground:r?"linear-gradient(180deg, #1b1c20 0%, #0f1012 42%, #050608 100%)":"#000000",frameOutline:r?"0 0 0 1px #1f2125":"0 0 0 1px #333",metallicRingShadow:r?null:Pt,buttons:H,legacyHomeButton:r?{top:111+e.height+47/2,left:e.width/2-64/2+29,size:64,ring:1.5}:null,showHomeIndicator:e.homeIndicatorHeight>0,logicalHomeIndicatorStripHeight:e.homeIndicatorHeight}}function At(i){let e=i.side==="right",t=e?"inset(-3px -3px -3px 0)":"inset(-3px 0 -3px -3px)";return`
|
|
3
3
|
<div
|
|
4
4
|
aria-hidden="true"
|
|
5
5
|
style="
|
|
@@ -177,7 +177,7 @@ import{a as st}from"./chunk-I5VNIQEQ.js";import{a as it}from"./chunk-DURQWXCM.js
|
|
|
177
177
|
</div>
|
|
178
178
|
</div>
|
|
179
179
|
</body>
|
|
180
|
-
</html>`}async function
|
|
180
|
+
</html>`}async function dt(i,e){let{chromium:t}=await import("playwright"),r=await it(n=>t.launch(n),{headless:!0});try{let n=await Rt(r);try{return await n.compose(i,e)}finally{await n.close()}}finally{await r.close()}}async function Rt(i){let e=new Map;async function t(r){let n=e.get(r);if(n)return n;let o=kt(r),a=await i.newContext({viewport:{width:o.outerWidth,height:o.outerHeight},deviceScaleFactor:1}),s=await a.newPage(),l={layout:o,context:a,page:s};return e.set(r,l),l}return{async compose(r,n){let o=await t(n),a=`data:image/png;base64,${r.toString("base64")}`;return await o.page.setContent(Mt(o.layout,a),{waitUntil:"load"}),await o.page.waitForTimeout(20),await o.page.screenshot({type:"png",clip:{x:0,y:0,width:o.layout.outerWidth,height:o.layout.outerHeight},omitBackground:!0})},async close(){for(let r of e.values())await r.context.close();e.clear()}}}import{spawnSync as _t}from"child_process";import*as N from"vm";var Ot=3e5,Dt=`
|
|
181
181
|
let input = '';
|
|
182
182
|
process.stdin.on('data', (c) => { input += c });
|
|
183
183
|
process.stdin.on('end', async () => {
|
|
@@ -199,7 +199,7 @@ process.stdin.on('end', async () => {
|
|
|
199
199
|
process.exitCode = 1;
|
|
200
200
|
}
|
|
201
201
|
});
|
|
202
|
-
`;function K(i,e,t){if(t?.multipartForm)throw new Error("http: multipartForm is not supported by sootsim yet");let r={...process.env};for(let s of Object.keys(r))(s.startsWith("BUN_INSPECT")||s==="NODE_OPTIONS")&&delete r[s];let n=_t(process.execPath,["-e",Dt],{input:JSON.stringify({url:i,method:e,headers:t?.headers,body:t?.body}),encoding:"utf8",timeout:Ot,maxBuffer:64*1024*1024,env:r});if(n.error)throw new Error(`http ${e} ${i} failed: ${n.error.message}`);let o;try{o=JSON.parse(n.stdout||"")}catch{throw new Error(`http ${e} ${i} failed: no response (${(n.stderr||"").trim().slice(0,200)})`)}let a=o;if(a.__error)throw new Error(`http ${e} ${i} failed: ${a.__error}`);return a}var Bt=/(?<!\\)\$\{([^$]*)\}/g,Lt=/\\(\$\{[^$]*\})/g,Nt=/^[A-Za-z_$][A-Za-z0-9_$]*$/,ee=class{context;envBinding=new Map;envScopeStack=[];syncedEnvKeys=new Set;output={};maestro;constructor(e={}){this.maestro={copiedText:null,platform:e.platform??"ios"};let t=e.onLog??(n=>console.log(`[flow] js: ${n}`)),r={output:this.output,maestro:this.maestro,http:{get:(n,o)=>K(n,"GET",o),post:(n,o)=>K(n,"POST",o),put:(n,o)=>K(n,"PUT",o),delete:(n,o)=>K(n,"DELETE",o),request:(n,o)=>K(n,(o?.method??"GET").toUpperCase(),o)},console:{log:(...n)=>t(n.map(o=>typeof o=="string"?o:
|
|
202
|
+
`;function K(i,e,t){if(t?.multipartForm)throw new Error("http: multipartForm is not supported by sootsim yet");let r={...process.env};for(let s of Object.keys(r))(s.startsWith("BUN_INSPECT")||s==="NODE_OPTIONS")&&delete r[s];let n=_t(process.execPath,["-e",Dt],{input:JSON.stringify({url:i,method:e,headers:t?.headers,body:t?.body}),encoding:"utf8",timeout:Ot,maxBuffer:64*1024*1024,env:r});if(n.error)throw new Error(`http ${e} ${i} failed: ${n.error.message}`);let o;try{o=JSON.parse(n.stdout||"")}catch{throw new Error(`http ${e} ${i} failed: no response (${(n.stderr||"").trim().slice(0,200)})`)}let a=o;if(a.__error)throw new Error(`http ${e} ${i} failed: ${a.__error}`);return a}var Bt=/(?<!\\)\$\{([^$]*)\}/g,Lt=/\\(\$\{[^$]*\})/g,Nt=/^[A-Za-z_$][A-Za-z0-9_$]*$/,ee=class{context;envBinding=new Map;envScopeStack=[];syncedEnvKeys=new Set;output={};maestro;constructor(e={}){this.maestro={copiedText:null,platform:e.platform??"ios"};let t=e.onLog??(n=>console.log(`[flow] js: ${n}`)),r={output:this.output,maestro:this.maestro,http:{get:(n,o)=>K(n,"GET",o),post:(n,o)=>K(n,"POST",o),put:(n,o)=>K(n,"PUT",o),delete:(n,o)=>K(n,"DELETE",o),request:(n,o)=>K(n,(o?.method??"GET").toUpperCase(),o)},console:{log:(...n)=>t(n.map(o=>typeof o=="string"?o:ct(o)).join(" "))}};this.context=N.createContext(r),N.runInContext(`
|
|
203
203
|
globalThis.__maestroScope = new Proxy(globalThis, {
|
|
204
204
|
has() { return true },
|
|
205
205
|
get(target, key) { return target[key] },
|
|
@@ -210,7 +210,7 @@ process.stdin.on('end', async () => {
|
|
|
210
210
|
var yPercent = Math.ceil(y * 100) + '%'
|
|
211
211
|
return xPercent + ',' + yPercent
|
|
212
212
|
}
|
|
213
|
-
`,this.context);for(let[n,o]of Object.entries(process.env))o!==void 0&&this.envBinding.set(n,o)}putEnv(e,t){this.envBinding.set(e,t)}setCopiedText(e){this.maestro.copiedText=e}enterEnvScope(){this.envScopeStack.push(new Map(this.envBinding))}leaveEnvScope(){let e=this.envScopeStack.pop();if(e){this.envBinding.clear();for(let[t,r]of e)this.envBinding.set(t,r)}}evaluate(e,t={}){let r=t.env;if(r&&Object.keys(r).length>0){this.enterEnvScope();try{for(let[n,o]of Object.entries(r))this.envBinding.set(n,o);return this.evalRaw(e)}finally{this.leaveEnvScope()}}return this.evalRaw(e)}evalRaw(e){this.syncEnvToContext();let t=e.replace(/\\/g,"\\\\").replace(/`/g,"\\`").replace(/\$\{/g,"\\${");return N.runInContext(`(function(){ with(__maestroScope){ return eval(\`${t}\`) } })()`,this.context)}syncEnvToContext(){let e=N.runInContext("globalThis",this.context);for(let t of this.syncedEnvKeys)this.envBinding.has(t)||delete e[t];this.syncedEnvKeys=new Set;for(let[t,r]of this.envBinding)try{e[t]=r,this.syncedEnvKeys.add(t)}catch{}}evaluateStringTemplate(e){return e.replace(Bt,(r,n)=>{if(n.trim().length===0)return"";let o=this.evaluate(n);if(o===void 0&&Nt.test(n.trim()))throw new Error(`missing variable for flow placeholder: ${n.trim()}`);return
|
|
213
|
+
`,this.context);for(let[n,o]of Object.entries(process.env))o!==void 0&&this.envBinding.set(n,o)}putEnv(e,t){this.envBinding.set(e,t)}setCopiedText(e){this.maestro.copiedText=e}enterEnvScope(){this.envScopeStack.push(new Map(this.envBinding))}leaveEnvScope(){let e=this.envScopeStack.pop();if(e){this.envBinding.clear();for(let[t,r]of e)this.envBinding.set(t,r)}}evaluate(e,t={}){let r=t.env;if(r&&Object.keys(r).length>0){this.enterEnvScope();try{for(let[n,o]of Object.entries(r))this.envBinding.set(n,o);return this.evalRaw(e)}finally{this.leaveEnvScope()}}return this.evalRaw(e)}evalRaw(e){this.syncEnvToContext();let t=e.replace(/\\/g,"\\\\").replace(/`/g,"\\`").replace(/\$\{/g,"\\${");return N.runInContext(`(function(){ with(__maestroScope){ return eval(\`${t}\`) } })()`,this.context)}syncEnvToContext(){let e=N.runInContext("globalThis",this.context);for(let t of this.syncedEnvKeys)this.envBinding.has(t)||delete e[t];this.syncedEnvKeys=new Set;for(let[t,r]of this.envBinding)try{e[t]=r,this.syncedEnvKeys.add(t)}catch{}}evaluateStringTemplate(e){return e.replace(Bt,(r,n)=>{if(n.trim().length===0)return"";let o=this.evaluate(n);if(o===void 0&&Nt.test(n.trim()))throw new Error(`missing variable for flow placeholder: ${n.trim()}`);return ct(o)}).replace(Lt,(r,n)=>n)}interpolateStep(e){return this.interpolateValue(e,null)}interpolateValue(e,t){return typeof e=="string"?t==="evalScript"?e:this.evaluateStringTemplate(e):Array.isArray(e)?t==="commands"||t==="onFlowStart"||t==="onFlowComplete"?e:e.map(r=>this.interpolateValue(r,t)):e&&typeof e=="object"?Object.fromEntries(Object.entries(e).map(([r,n])=>[r,this.interpolateValue(n,r)])):e}};function ct(i){if(i===void 0)return"undefined";if(i===null)return"null";if(typeof i=="object")try{return JSON.stringify(i)}catch{return String(i)}return String(i)}function ut(i){if(i==null)return!1;if(typeof i=="boolean")return i;let e=String(i);if(e.trim().length===0||e.toLowerCase()==="false"||e==="undefined"||e==="null")return!1;let t=Number(e);return!(!Number.isNaN(t)&&t===0)}var te=1e4,Ct=Math.min(10,Math.max(1,Number(process.env.SOOTSIM_FLOW_TIMEOUT_SCALE)||1)),q=i=>Math.round(i*Ct),ne=393,C=852;function f(i){return new Promise(e=>setTimeout(e,i))}function Ie(i){return!!(i&&typeof i=="object"&&!Array.isArray(i))}function z(i,e){if(!Ie(i))return null;let t=i[e];return typeof t=="string"&&t.length>0?t:null}function Ht(i,e){return Ie(i)?i[e]===!0:!1}function Ut(i){if(!i)return null;let e=i.recentApps;if(Array.isArray(e))for(let r of e){let n=z(r,"id");if(n)return n}let t=i.surfaceBindings;return z(t,"app:one")||z(t,"app:two")||null}function Wt(i){return i?S.basename(i)===".maestro"?S.dirname(i):i:process.cwd()}function jt(i,e,t){let r=e.endsWith(".png")?e:`${e}.png`;if(S.isAbsolute(r))return r;if(t.mode==="flow"&&/[\\/]/.test(r)){let n=r.startsWith("./")||r.startsWith("../")?t.flowDir??process.cwd():Wt(t.flowDir);return S.resolve(n,r)}return S.join(i,r)}function Vt(i){if(typeof i=="string")return{path:i,withFrame:!1};let e=i.path?.trim()||i.name?.trim();if(!e)throw new Error("takeScreenshot object form requires path or name");return{path:e,withFrame:i.withFrame===!0,layers:i.layers}}function re(i,e){let[t,r]=i.split(",").map(s=>s.trim()),n=(s,l)=>s.endsWith("%")?Number.parseFloat(s)/100*l:Number.parseFloat(s),o=e?.x??0,a=e?.y??0;return{x:o+n(t,e?.width??ne),y:a+n(r,e?.height??C)}}function pt(i){switch(i){case"back":return{back:!0};case"hideKeyboard":return{hideKeyboard:!0};case"waitForAnimationToEnd":return{waitForAnimationToEnd:!0};case"stopApp":return{stopApp:!0};case"clearState":return{clearState:!0};case"clearKeychain":return{clearKeychain:!0};case"eraseText":return{eraseText:50};case"scroll":case"scrollDown":return{scroll:{direction:"DOWN"}};case"scrollUp":return{scroll:{direction:"UP"}};default:return{[i]:!0}}}function Jt(i){let e=i.split(/^---$/m),t=e.length>1?e[e.length-1]:i,r=et.parse(t);return Array.isArray(r)?r:[]}var ie=class{constructor(e,t){this.bridge=e;this.opts=t}stepDelay=0;js=new ee({platform:"ios",onLog:e=>console.log(`[flow] js: ${e}`)});firstLaunchDone=!1;profilingEnabled=!1;recordingEnabled=!1;recordingAccessChecked=!1;recordingStartedAtMs=null;lastRecordingStartedAtMs=null;lastRecordingDurationMs=null;lastRecordingFrameStats=null;flowTraceSteps=[];lastVisualSettledAtMs=0;simRouteHint=null;lastFailedStep=null;get simId(){return this.opts.simId}setSimRouteHint(e){this.simRouteHint=this.normalizeSimRoute(e)}normalizeSimRoute(e){if(!e)return null;try{let t=new URL(e);t.searchParams.delete("inspectOpen");let r=t.searchParams.toString();return`${t.origin}${t.pathname}${r?`?${r}`:""}`}catch{return e}}async refreshSimId(){if(this.opts.simId)try{let e=await this.bridge.listSims(),t=e.find(l=>l.id===this.opts.simId);if(t&&(this.simRouteHint=this.normalizeSimRoute(t.url||t.origin)),e.find(l=>l.id===this.opts.simId&&l.readyState==="open")||!this.simRouteHint)return;let n=this.simRouteHint&&e.find(l=>l.readyState==="open"&&this.normalizeSimRoute(l.url||l.origin)===this.simRouteHint);if(!n)return;let o=e.find(l=>l.isPrimary&&l.readyState==="open"),a=e.find(l=>l.readyState==="open"),s=n??o??a;s&&(this.opts.simId=s.id,console.log(` [flow] sim rotated to ${s.id}`))}catch{}}async evaluate(e,t){return this.bridge.send({type:"evaluate",simId:this.opts.simId,code:e},t?{timeoutMs:t}:void 0)}async callTest(e,...t){return this.bridge.send({type:"call",simId:this.opts.simId,path:`__sootsimTest.${e}`,args:t})}async waitForTree(e=te){let t=Date.now()+q(e),r=Date.now(),n=null,o=0,a=0,s=-1,l=r;for(;Date.now()<t;){try{let u=await this.evaluate(je,8e3);if(o=0,u?.externalError)throw new Error(`app failed to load: ${u.externalError}`);if(u){let m=Date.now();u.nodes!==s&&(s=u.nodes,l=m);let b=u.flag===!0&&Je(u),g=u.flag!==!0&&Ge(u);if((b||g)&&u.externalReady!==!1&&!u.externalError&&!u.loadingText&&m-l>=Ve)return}}catch(u){if(n=u instanceof Error?u:new Error(String(u)),n.message.startsWith("app failed to load:"))throw n;if(o++,o>=4)throw new Error(`target sim is not responding to the bridge (${n.message}). it is likely a stale orphan \u2014 run \`sootsim list\`, then close it with \`sootsim close <id>\` or start a fresh one with \`sootsim open --new <port>\`.`);await this.refreshSimId()}let p=Date.now()-r;p-a>=5e3&&(a=p,console.log(` [flow] waiting for app to be ready\u2026 (${Math.round(p/1e3)}s)`)),await f(500)}throw n?.message.startsWith("app failed to load:")?n:new Error(`app not ready after ${e}ms`)}async ensureRecordingStarted(){if(!this.opts.recordingOutputDir)throw new Error("recording output directory not configured");this.recordingAccessChecked||(this.opts.requireRecordingEntitlement&&await st("flow --video",{originOverride:this.opts.billingOriginOverride,allowGitHubAuth:this.opts.allowGitHubRecording}),this.recordingAccessChecked=!0);let e=Date.now(),t=await this.evaluate(`(() => {
|
|
214
214
|
const rec = window.__sootsimRecorder
|
|
215
215
|
if (!rec) return { ok: false, error: 'recorder unavailable on this page' }
|
|
216
216
|
const format = ${JSON.stringify(this.opts.recordingFormat??"webm")}
|
|
@@ -386,7 +386,7 @@ process.stdin.on('end', async () => {
|
|
|
386
386
|
visible: !!keyboard?.isVisible?.(),
|
|
387
387
|
focused: !!test?.isTextInputFocused?.(),
|
|
388
388
|
}
|
|
389
|
-
})()`);if(!t?.visible&&!t?.focused){await f(80);return}await f(80)}}async eraseText(e){for(let t=0;t<e;t++)await this.bridge.send({type:"keyboard",simId:this.opts.simId,action:"dispatchKey",text:"Backspace"});await f(100)}async waitFor(e){let t=Date.now()+q(e.timeout||te);for(;Date.now()<t;){if(await this.findElement(e))return;await f(200)}let r=await this.findElement(e),n=r?` (matched node y=${Math.round(r.absolutePosition.y)} \u2014 still off-screen at deadline)`:"";throw new Error(`waitFor: ${JSON.stringify(e)} not found after ${e.timeout||te}ms${n}`)}async takeScreenshot(e){if(!this.hasFreshVisualSettle())try{await this.waitForVisualSettle(),await f(250)}catch{}let t=Vt(e),r=jt(this.opts.screenshotDir,t.path,{mode:this.opts.screenshotPathMode??"dir",flowDir:this.opts.flowDir});v.mkdirSync(S.dirname(r),{recursive:!0});let n=t.layers??this.opts.screenshotLayers,o={type:"screenshot",simId:this.opts.simId};n&&n!=="full"&&(o.layers=n);let s=(await this.bridge.send(o)).replace(/^data:image\/png;base64,/,""),l=Buffer.from(s,"base64");if(t.withFrame){let p=await this.readCurrentDeviceModel();if(!p)throw new Error("could not read current device model for framed screenshot");let u=await
|
|
389
|
+
})()`);if(!t?.visible&&!t?.focused){await f(80);return}await f(80)}}async eraseText(e){for(let t=0;t<e;t++)await this.bridge.send({type:"keyboard",simId:this.opts.simId,action:"dispatchKey",text:"Backspace"});await f(100)}async waitFor(e){let t=Date.now()+q(e.timeout||te);for(;Date.now()<t;){if(await this.findElement(e))return;await f(200)}let r=await this.findElement(e),n=r?` (matched node y=${Math.round(r.absolutePosition.y)} \u2014 still off-screen at deadline)`:"";throw new Error(`waitFor: ${JSON.stringify(e)} not found after ${e.timeout||te}ms${n}`)}async takeScreenshot(e){if(!this.hasFreshVisualSettle())try{await this.waitForVisualSettle(),await f(250)}catch{}let t=Vt(e),r=jt(this.opts.screenshotDir,t.path,{mode:this.opts.screenshotPathMode??"dir",flowDir:this.opts.flowDir});v.mkdirSync(S.dirname(r),{recursive:!0});let n=t.layers??this.opts.screenshotLayers,o={type:"screenshot",simId:this.opts.simId};n&&n!=="full"&&(o.layers=n);let s=(await this.bridge.send(o)).replace(/^data:image\/png;base64,/,""),l=Buffer.from(s,"base64");if(t.withFrame){let p=await this.readCurrentDeviceModel();if(!p)throw new Error("could not read current device model for framed screenshot");let u=await dt(l,p);return v.writeFileSync(r,u),console.log(`[flow] screenshot: ${r} (frame: ${p})`),r}return v.writeFileSync(r,l),console.log(`[flow] screenshot: ${r}`),r}async readCurrentDeviceModel(){let e=await this.bridge.send({type:"call",simId:this.opts.simId,path:"SootSim.bridges.settings.get",args:[]}),t=e&&typeof e.deviceModel=="string"?e.deviceModel:null;return!t||!(t in Ne)?null:t}async captureScreenshot(e){v.mkdirSync(S.dirname(e),{recursive:!0});let r=(await this.bridge.send({type:"screenshot",simId:this.opts.simId})).replace(/^data:image\/png;base64,/,"");v.writeFileSync(e,Buffer.from(r,"base64"))}async captureFailureBundle(e,t){v.mkdirSync(e,{recursive:!0});let r=(u,m)=>{try{v.writeFileSync(S.join(e,u),m)}catch{}},n=async u=>{try{return await this.bridge.send({type:"evaluate",simId:this.opts.simId,code:u})}catch{return null}},o=await n(`(async () => {
|
|
390
390
|
const out = {
|
|
391
391
|
simId: window.__sootsimBridge?.id ?? window.SootSim?.state?.simId ?? null,
|
|
392
392
|
url: location.href,
|
|
@@ -449,7 +449,7 @@ process.stdin.on('end', async () => {
|
|
|
449
449
|
})
|
|
450
450
|
})
|
|
451
451
|
})
|
|
452
|
-
})`),this.markVisualSettled()}catch{await f(180),this.markVisualSettled()}}markVisualSettled(){this.lastVisualSettledAtMs=Date.now()}hasFreshVisualSettle(){return Date.now()-this.lastVisualSettledAtMs<750}resolveShellLaunchAppId(e,t){if(typeof e=="string"&&e.length>0)return e;if(
|
|
452
|
+
})`),this.markVisualSettled()}catch{await f(180),this.markVisualSettled()}}markVisualSettled(){this.lastVisualSettledAtMs=Date.now()}hasFreshVisualSettle(){return Date.now()-this.lastVisualSettledAtMs<750}resolveShellLaunchAppId(e,t){if(typeof e=="string"&&e.length>0)return e;if(Ie(e)){let r=z(e,"appId")||z(e,"id");if(r)return r}return Ut(t)||"connect"}async waitForShellAppLaunched(e,t){let r=Date.now()+t,n=null;for(;Date.now()<r;){try{n=await G(this.bridge)}catch{n=null}if(n?.state==="app"&&n.activeApp===e&&n.showSwitcher===!1&&typeof n.launchProgress=="number"&&n.launchProgress>=.98)return;await f(16)}}async waitForShellHome(e){let t=Date.now()+e;for(;Date.now()<t;){let r=await G(this.bridge).catch(()=>null);if(r?.state==="home"&&r.activeApp==null&&r.showSwitcher===!1)return;await f(16)}}async launchShellAppFromHomeIfNeeded(e,t){let r=null;if(t)r=t;else try{r=await G(this.bridge)}catch{return!1}if(r?.state!=="home"||r.activeApp!=null)return!1;let n=this.resolveShellLaunchAppId(e,r);return this.recordingEnabled&&await this.ensureRecordingStarted(),await me(this.bridge,"launchApp",1e3,n),await this.waitForShellAppLaunched(n,1e3),!0}async startProfile(){let e=await this.evaluate(`(() => {
|
|
453
453
|
if (!window.__sootsimShellPerf) {
|
|
454
454
|
return { error: "shell frame profile unavailable (__sootsimShellPerf missing on the page)" }
|
|
455
455
|
}
|
|
@@ -460,7 +460,7 @@ process.stdin.on('end', async () => {
|
|
|
460
460
|
return { error: "shell frame profile unavailable (__sootsimShellPerf missing on the page)" }
|
|
461
461
|
}
|
|
462
462
|
return await window.__sootsimShellPerf.stop()
|
|
463
|
-
})()`);if(this.profilingEnabled=!1,e?.error)throw new Error(e.error);return e}async stopApp(){await this.reloadGuestApp(!1),await this.rearmCaptureAfterRuntimeReload()}async clearState(){await this.reloadGuestApp(!0),await this.rearmCaptureAfterRuntimeReload()}clearKeychain(){console.warn("[flow] clearKeychain: sootsim has no keychain surface \u2014 no-op (warning)")}async copyTextFrom(e){let t=typeof e=="string"?{id:e}:e,r=await this.findElement(t);if(!r)throw new Error(`copyTextFrom: element not found: ${JSON.stringify(t)}`);let n=r.text??r.testID??"";this.js.setCopiedText(n),this.js.putEnv("maestroCopiedText",n),console.log(`[flow] copied text: ${JSON.stringify(n)}`)}evalScript(e){let r=/(?<!\\)\$\{[^$]*\}/.test(e)?this.js.evaluateStringTemplate(e):this.js.evaluate(e);r!==void 0&&r!==""&&console.log("[flow] evalScript ->",r)}runScript(e){let t=typeof e=="string"?{file:e}:e;if(!t.file)throw new Error("runScript requires a file");let r=S.resolve(this.opts.flowDir,t.file),n=v.readFileSync(r,"utf8");this.js.evaluate(n,{env:t.env}),console.log(`[flow] runScript: ${t.file} done`)}async openLink(e){let t=typeof e=="string"?e:e.link;if(!t)throw new Error("openLink: missing link");let r=await this.callTest("openDeepLink",t);if(!r?.ok)throw new Error(`openLink failed: ${r?.error||"no test bridge"}`);await f(300)}async evaluateWhen(e){if(e.visible!==void 0){let t=typeof e.visible=="string"?{text:e.visible}:e.visible;return!!await this.findElement(t)}if(e.notVisible!==void 0){let t=typeof e.notVisible=="string"?{text:e.notVisible}:e.notVisible;return!await this.findElement(t)}return e.platform!==void 0?e.platform.toLowerCase()===this.js.maestro.platform.toLowerCase():e.true!==void 0?ut(e.true):!0}isOptional(e){if(e.optional===!0)return!0;let r=Object.entries(e).find(([o])=>o!=="when"&&o!=="optional"),n=r?r[1]:void 0;return!!(n&&typeof n=="object"&&"optional"in n&&n.optional)}async runStep(e,t){let r=typeof e=="string"?pt(e):e,n=Object.keys(r).find(l=>l!=="when")||Object.keys(r)[0];console.log(`[flow] step ${t+1}: ${n}`);let o=Date.now(),a=this.flowStepTargetLabel(r,n),s;try{s=this.js.interpolateStep(r),a=this.flowStepTargetLabel(s,n)??a}catch(l){if(this.isOptional(r)){console.log(`[flow] (optional, skipped: ${l.message.slice(0,80)})`),this.recordFlowTraceStep({stepIndex:t,stepName:n,targetLabel:a,startedAtMs:o,status:"skipped",error:l});return}throw this.lastFailedStep={index:t,kind:n,target:r[n]},this.recordFlowTraceStep({stepIndex:t,stepName:n,targetLabel:a,startedAtMs:o,status:"failure",error:l}),l}if(s.when&&!await this.evaluateWhen(s.when)){console.log("[flow] (when: predicate false, skipped)"),this.recordFlowTraceStep({stepIndex:t,stepName:n,targetLabel:a,startedAtMs:o,status:"skipped"});return}try{let l=!!(s.extendedWaitUntil||s.waitFor||s.scrollUntilVisible||s.launchApp||s.runFlow||s.runScript),p=1e4,u=this.runStepInner(s),m;if(l){let g=await u;typeof g=="string"&&(m=g)}else{let g=null,P=new Promise((k,H)=>{g=setTimeout(()=>{H(new Error(`step watchdog: ${n} made no progress in ${p}ms \u2014 bridge or bundle probably hung`))},p)});try{let k=await Promise.race([u,P]);typeof k=="string"&&(m=k)}finally{g&&clearTimeout(g)}}let y=!!(s.assertVisible||s.assertNotVisible||s.extendedWaitUntil||s.waitFor);this.stepDelay>0&&!y&&await f(this.stepDelay),this.recordFlowTraceStep({stepIndex:t,stepName:n,targetLabel:a,startedAtMs:o,status:"success",screenshotPath:m})}catch(l){if(this.isOptional(s)){console.log(`[flow] (optional, skipped: ${l.message.slice(0,80)})`),this.recordFlowTraceStep({stepIndex:t,stepName:n,targetLabel:a,startedAtMs:o,status:"skipped",error:l});return}throw this.lastFailedStep={index:t,kind:n,target:s[n]},this.recordFlowTraceStep({stepIndex:t,stepName:n,targetLabel:a,startedAtMs:o,status:"failure",error:l}),l}}async runStepInner(e){if(e.tapOn)await this.tapOn(e.tapOn);else if(e.longPressOn)await this.longPressOn(e.longPressOn);else if(e.scrollUntilVisible)await this.scrollUntilVisible(e.scrollUntilVisible);else if(e.extendedWaitUntil)await this.extendedWaitUntil(e.extendedWaitUntil);else if(e.assertVisible)await this.assertVisible(e.assertVisible);else if(e.assertNotVisible)await this.assertNotVisible(e.assertNotVisible);else if(e.inputText)await this.inputText(e.inputText);else if(e.pressKey)await this.pressKey(e.pressKey);else if(e.dispatchKey)await this.dispatchKey(e.dispatchKey);else if(e.waitFor)await this.waitFor(e.waitFor);else{if(e.takeScreenshot)return this.takeScreenshot(e.takeScreenshot);if(e.swipe)e.swipe.start&&e.swipe.end?await this.swipeCoords(e.swipe.start,e.swipe.end,e.swipe.duration):e.swipe.from?await this.swipeFrom(e.swipe.from,e.swipe.direction,e.swipe.duration):await this.swipe(e.swipe.direction,e.swipe.duration);else if(e.scroll)await this.swipe(e.scroll.direction==="DOWN"?"UP":"DOWN");else if(e.scrollTo){let t=typeof e.scrollTo.nodeId=="number"?{nodeId:e.scrollTo.nodeId}:e.scrollTo.id;if(!t)throw new Error("scrollTo requires id or nodeId");await this.scrollTo(t,e.scrollTo.x,e.scrollTo.y)}else if(e.pinch)await this.pinch(e.pinch);else if(e.waitForAnimationToEnd){let t=e.waitForAnimationToEnd;await this.waitForAnimationToEnd(typeof t=="number"?t:typeof t=="object"&&typeof t.timeout=="number"?t.timeout:2e3)}else if(e.back)await this.back();else if(e.hideKeyboard)await this.hideKeyboard();else if(e.launchApp)await this.launchApp(e.launchApp);else if(typeof e.wait=="number")await f(e.wait);else if(e.dumpTree)await this.dumpTree(e.dumpTree);else if(e.tapAtCoords)await this.tapAtCoords(e.tapAtCoords.x,e.tapAtCoords.y);else if(e.doubleTapAtCoords)await this.doubleTapAtCoords(e.doubleTapAtCoords.x,e.doubleTapAtCoords.y,e.doubleTapAtCoords.gapMs);else if(e.assertTreeContains)await this.assertTreeContains(e.assertTreeContains);else if(typeof e.eraseText=="number")await this.eraseText(e.eraseText);else if(e.repeat&&Array.isArray(e.repeat.commands)){let t=e.repeat.times,r=t==null||t===""?Number.MAX_SAFE_INTEGER:Number(t);if(!Number.isFinite(r))throw new Error(`repeat.times is not a number: ${t}`);let n=e.repeat.when??e.repeat.condition,o=async()=>n?this.evaluateWhen(n):!0,a=n?r:Math.min(r,1e3),s=0;for(;s<a&&await o();){for(let l=0;l<e.repeat.commands.length;l++)await this.runStep(e.repeat.commands[l],l);s++}}else if(e.stopApp!==void 0)await this.stopApp();else if(e.clearState!==void 0)await this.clearState();else if(e.clearKeychain!==void 0)this.clearKeychain();else if(e.copyTextFrom!==void 0)await this.copyTextFrom(e.copyTextFrom);else if(typeof e.evalScript=="string")this.evalScript(e.evalScript);else if(e.runScript){let t=e.runScript,r=typeof t=="string"?void 0:t.when;if(r&&!await this.evaluateWhen(r)){console.log("[flow] runScript skipped (when predicate false)");return}this.runScript(t)}else if(e.openLink!==void 0)await this.openLink(e.openLink);else if(e.runFlow){let t=e.runFlow,r=typeof t=="string"?t:t.file,n=typeof t=="string"?void 0:t.commands,o=typeof t=="string"?void 0:t.env,a=typeof t=="string"?void 0:t.when;if(a&&!await this.evaluateWhen(a)){console.log(`[flow] runFlow skipped (when predicate false): ${r??"inline commands"}`);return}if(!r&&!n)throw new Error("runFlow requires either file or commands");this.js.enterEnvScope();try{if(o)for(let[s,l]of Object.entries(o))this.js.putEnv(s,l);if(r){let s=S.resolve(this.opts.flowDir,r),l=v.readFileSync(s,"utf8"),p=this.opts.flowDir;this.opts.flowDir=S.dirname(s);try{await this.runFlow(Jt(l))}finally{this.opts.flowDir=p}}else if(n)for(let s=0;s<n.length;s++)await this.runStep(n[s],s)}finally{this.js.leaveEnvScope()}}else throw new Error(`unsupported flow step: ${JSON.stringify(e)}`)}}liveStatus=null;async runFlow(e){let t=[],r=[],n=[];for(let a of e){let s=Object.keys(a);if(s.length===1&&s[0]==="onFlowStart"&&Array.isArray(a.onFlowStart)){t.push(...a.onFlowStart);continue}if(s.length===1&&s[0]==="onFlowComplete"&&Array.isArray(a.onFlowComplete)){r.push(...a.onFlowComplete);continue}n.push(a)}if(this.liveStatus&&await this.liveStatus.plan(n.map((a,s)=>{let l=typeof a=="string"?pt(a):a,p=Object.keys(l).find(u=>u!=="when")??Object.keys(l)[0];return{index:s,name:p,target:this.flowStepTargetLabel(l,p)}})),t.length>0){console.log(`[flow] onFlowStart (${t.length} steps)`);for(let a=0;a<t.length;a++)await this.runStep(t[a],a)}let o=null;try{await this.runFlowBody(n)}catch(a){o=a instanceof Error?a:new Error(String(a))}if(r.length>0){console.log(`[flow] onFlowComplete (${r.length} steps)`);for(let a=0;a<r.length;a++)try{await this.runStep(r[a],a)}catch(s){console.warn(`[flow] onFlowComplete step ${a+1} failed: ${s instanceof Error?s.message:s}`)}}if(o)throw o}async runFlowBody(e){for(let t=0;t<e.length;t++){let r=e[t],n=typeof r.wait=="number"?r.wait:0,o=typeof r.waitFor?.timeout=="number"?r.waitFor.timeout:0,a=typeof r.extendedWaitUntil?.timeout=="number"?r.extendedWaitUntil.timeout:0,s=Math.max(6e4,n+15e3,q(o)+15e3,q(a)+15e3);this.liveStatus&&(await this.liveStatus.waitWhilePaused(),await this.liveStatus.step(t,"running"));let l=Date.now(),p=async(u,m)=>{if(!this.liveStatus)return;let y=this.flowTraceSteps[this.flowTraceSteps.length-1],g=y&&y.stepIndex===t&&y.startedAtMs>=l;await this.liveStatus.step(t,u?"failure":g&&y.status==="skipped"?"skipped":"success",{durationMs:Date.now()-l,error:u?m instanceof Error?m.message.slice(0,300):String(m).slice(0,300):g&&y.error||void 0})};try{r.runFlow||r.launchApp?await this.runStep(r,t):await Promise.race([this.runStep(r,t),new Promise((u,m)=>setTimeout(()=>m(new Error(`step ${t+1} (${Object.keys(r)[0]}) exceeded ${s}ms deadline`)),s))])}catch(u){let m=this.flowTraceSteps[this.flowTraceSteps.length-1];if(!(m&&m.stepIndex===t&&m.startedAtMs>=l)){let y=Object.keys(r)[0];this.lastFailedStep={index:t,kind:y,target:r[y]},this.recordFlowTraceStep({stepIndex:t,stepName:y,targetLabel:this.flowStepTargetLabel(r,y),startedAtMs:l,status:"failure",error:u})}throw await p(!0,u),u}await p(!1)}}};function Gt(i){if(typeof i!="object"||i==null||!("control"in i))return!1;let e=i.control;return typeof e=="object"&&e!=null&&"paused"in e&&e.paused===!0}var oe=class{constructor(e,t,r){this.bridge=e;this.flowName=t;this.getSimId=r}disabled=!1;paused=!1;lastSimId;plannedSteps=null;completedSteps=new Map;runId=`flr_${Date.now().toString(36)}_${Math.random().toString(36).slice(2,8)}`;async send(e,t){let r=await this.bridge.send({type:"flowStatus",simId:t,status:{runId:this.runId,flowName:this.flowName,...e}});this.paused=Gt(r)}async push(e){if(!this.disabled)try{let t=this.getSimId?.();if(t!==this.lastSimId&&this.lastSimId!=null&&this.plannedSteps&&e.phase!=="plan"){await this.send({phase:"plan",state:"running",steps:this.plannedSteps},t);for(let r of this.completedSteps.values())await this.send({phase:"step",state:"running",step:r},t)}this.lastSimId=t,await this.send(e,t)}catch(t){this.disabled=!0,console.log(`[flow] live status unavailable (${t instanceof Error?t.message.slice(0,120):t}) \u2014 continuing without the devtools rail`)}}async plan(e){this.plannedSteps=e.map(t=>({...t})),this.completedSteps.clear(),await this.push({phase:"plan",state:"running",steps:e})}async step(e,t,r){let n={index:e,status:t,...r};await this.push({phase:"step",state:"running",step:n}),this.completedSteps.set(e,n)}async end(e){await this.push({phase:"end",state:e})}async waitWhilePaused(){if(!this.disabled)for(;this.paused;){for(console.log("[flow] paused from devtools \u2014 waiting\u2026");this.paused&&!this.disabled;)await new Promise(e=>setTimeout(e,400)),await this.push({phase:"heartbeat",state:"paused"});this.disabled||console.log("[flow] resumed")}}};var Ie=null;function Hr(){return Ie}var $e=[];function Wr(){return $e}async function zt(i){if(!i)return"";let e=i.trim();if(!e)return"";if(/^\d+$/.test(e)||e.startsWith("http://")||e.startsWith("https://"))return e;let r=(await We()).find(n=>n.name.toLowerCase()===e.toLowerCase());return r?String(r.preferredPort):e}async function Yt(){let i=await Ue(),e=i.find(r=>r.patched);if(e)return`http://localhost:${e.port}/__soot/`;let t=i[0];return t?`http://localhost:${t.port}/__soot/`:null}async function ft(i){Ie=null,$e=[],(i.length===0||i.includes("--help")||i.includes("-h"))&&(console.log(`
|
|
463
|
+
})()`);if(this.profilingEnabled=!1,e?.error)throw new Error(e.error);return e}async stopApp(){await this.reloadGuestApp(!1),await this.rearmCaptureAfterRuntimeReload()}async clearState(){await this.reloadGuestApp(!0),await this.rearmCaptureAfterRuntimeReload()}clearKeychain(){console.warn("[flow] clearKeychain: sootsim has no keychain surface \u2014 no-op (warning)")}async copyTextFrom(e){let t=typeof e=="string"?{id:e}:e,r=await this.findElement(t);if(!r)throw new Error(`copyTextFrom: element not found: ${JSON.stringify(t)}`);let n=r.text??r.testID??"";this.js.setCopiedText(n),this.js.putEnv("maestroCopiedText",n),console.log(`[flow] copied text: ${JSON.stringify(n)}`)}evalScript(e){let r=/(?<!\\)\$\{[^$]*\}/.test(e)?this.js.evaluateStringTemplate(e):this.js.evaluate(e);r!==void 0&&r!==""&&console.log("[flow] evalScript ->",r)}runScript(e){let t=typeof e=="string"?{file:e}:e;if(!t.file)throw new Error("runScript requires a file");let r=S.resolve(this.opts.flowDir,t.file),n=v.readFileSync(r,"utf8");this.js.evaluate(n,{env:t.env}),console.log(`[flow] runScript: ${t.file} done`)}async openLink(e){let t=typeof e=="string"?e:e.link;if(!t)throw new Error("openLink: missing link");let r=await this.callTest("openDeepLink",t);if(!r?.ok)throw new Error(`openLink failed: ${r?.error||"no test bridge"}`);await f(300)}async evaluateWhen(e){if(e.visible!==void 0){let t=typeof e.visible=="string"?{text:e.visible}:e.visible;return!!await this.findElement(t)}if(e.notVisible!==void 0){let t=typeof e.notVisible=="string"?{text:e.notVisible}:e.notVisible;return!await this.findElement(t)}return e.platform!==void 0?e.platform.toLowerCase()===this.js.maestro.platform.toLowerCase():e.true!==void 0?ut(e.true):!0}isOptional(e){if(e.optional===!0)return!0;let r=Object.entries(e).find(([o])=>o!=="when"&&o!=="optional"),n=r?r[1]:void 0;return!!(n&&typeof n=="object"&&"optional"in n&&n.optional)}async runStep(e,t){let r=typeof e=="string"?pt(e):e,n=Object.keys(r).find(l=>l!=="when")||Object.keys(r)[0];console.log(`[flow] step ${t+1}: ${n}`);let o=Date.now(),a=this.flowStepTargetLabel(r,n),s;try{s=this.js.interpolateStep(r),a=this.flowStepTargetLabel(s,n)??a}catch(l){if(this.isOptional(r)){console.log(`[flow] (optional, skipped: ${l.message.slice(0,80)})`),this.recordFlowTraceStep({stepIndex:t,stepName:n,targetLabel:a,startedAtMs:o,status:"skipped",error:l});return}throw this.lastFailedStep={index:t,kind:n,target:r[n]},this.recordFlowTraceStep({stepIndex:t,stepName:n,targetLabel:a,startedAtMs:o,status:"failure",error:l}),l}if(s.when&&!await this.evaluateWhen(s.when)){console.log("[flow] (when: predicate false, skipped)"),this.recordFlowTraceStep({stepIndex:t,stepName:n,targetLabel:a,startedAtMs:o,status:"skipped"});return}try{let l=!!(s.extendedWaitUntil||s.waitFor||s.scrollUntilVisible||s.launchApp||s.runFlow||s.runScript),p=1e4,u=this.runStepInner(s),m;if(l){let g=await u;typeof g=="string"&&(m=g)}else{let g=null,P=new Promise((k,H)=>{g=setTimeout(()=>{H(new Error(`step watchdog: ${n} made no progress in ${p}ms \u2014 bridge or bundle probably hung`))},p)});try{let k=await Promise.race([u,P]);typeof k=="string"&&(m=k)}finally{g&&clearTimeout(g)}}let b=!!(s.assertVisible||s.assertNotVisible||s.extendedWaitUntil||s.waitFor);this.stepDelay>0&&!b&&await f(this.stepDelay),this.recordFlowTraceStep({stepIndex:t,stepName:n,targetLabel:a,startedAtMs:o,status:"success",screenshotPath:m})}catch(l){if(this.isOptional(s)){console.log(`[flow] (optional, skipped: ${l.message.slice(0,80)})`),this.recordFlowTraceStep({stepIndex:t,stepName:n,targetLabel:a,startedAtMs:o,status:"skipped",error:l});return}throw this.lastFailedStep={index:t,kind:n,target:s[n]},this.recordFlowTraceStep({stepIndex:t,stepName:n,targetLabel:a,startedAtMs:o,status:"failure",error:l}),l}}async runStepInner(e){if(e.tapOn)await this.tapOn(e.tapOn);else if(e.longPressOn)await this.longPressOn(e.longPressOn);else if(e.scrollUntilVisible)await this.scrollUntilVisible(e.scrollUntilVisible);else if(e.extendedWaitUntil)await this.extendedWaitUntil(e.extendedWaitUntil);else if(e.assertVisible)await this.assertVisible(e.assertVisible);else if(e.assertNotVisible)await this.assertNotVisible(e.assertNotVisible);else if(e.inputText)await this.inputText(e.inputText);else if(e.pressKey)await this.pressKey(e.pressKey);else if(e.dispatchKey)await this.dispatchKey(e.dispatchKey);else if(e.waitFor)await this.waitFor(e.waitFor);else{if(e.takeScreenshot)return this.takeScreenshot(e.takeScreenshot);if(e.swipe)e.swipe.start&&e.swipe.end?await this.swipeCoords(e.swipe.start,e.swipe.end,e.swipe.duration):e.swipe.from?await this.swipeFrom(e.swipe.from,e.swipe.direction,e.swipe.duration):await this.swipe(e.swipe.direction,e.swipe.duration);else if(e.scroll)await this.swipe(e.scroll.direction==="DOWN"?"UP":"DOWN");else if(e.scrollTo){let t=typeof e.scrollTo.nodeId=="number"?{nodeId:e.scrollTo.nodeId}:e.scrollTo.id;if(!t)throw new Error("scrollTo requires id or nodeId");await this.scrollTo(t,e.scrollTo.x,e.scrollTo.y)}else if(e.pinch)await this.pinch(e.pinch);else if(e.waitForAnimationToEnd){let t=e.waitForAnimationToEnd;await this.waitForAnimationToEnd(typeof t=="number"?t:typeof t=="object"&&typeof t.timeout=="number"?t.timeout:2e3)}else if(e.back)await this.back();else if(e.hideKeyboard)await this.hideKeyboard();else if(e.launchApp)await this.launchApp(e.launchApp);else if(typeof e.wait=="number")await f(e.wait);else if(e.dumpTree)await this.dumpTree(e.dumpTree);else if(e.tapAtCoords)await this.tapAtCoords(e.tapAtCoords.x,e.tapAtCoords.y);else if(e.doubleTapAtCoords)await this.doubleTapAtCoords(e.doubleTapAtCoords.x,e.doubleTapAtCoords.y,e.doubleTapAtCoords.gapMs);else if(e.assertTreeContains)await this.assertTreeContains(e.assertTreeContains);else if(typeof e.eraseText=="number")await this.eraseText(e.eraseText);else if(e.repeat&&Array.isArray(e.repeat.commands)){let t=e.repeat.times,r=t==null||t===""?Number.MAX_SAFE_INTEGER:Number(t);if(!Number.isFinite(r))throw new Error(`repeat.times is not a number: ${t}`);let n=e.repeat.when??e.repeat.condition,o=async()=>n?this.evaluateWhen(n):!0,a=n?r:Math.min(r,1e3),s=0;for(;s<a&&await o();){for(let l=0;l<e.repeat.commands.length;l++)await this.runStep(e.repeat.commands[l],l);s++}}else if(e.stopApp!==void 0)await this.stopApp();else if(e.clearState!==void 0)await this.clearState();else if(e.clearKeychain!==void 0)this.clearKeychain();else if(e.copyTextFrom!==void 0)await this.copyTextFrom(e.copyTextFrom);else if(typeof e.evalScript=="string")this.evalScript(e.evalScript);else if(e.runScript){let t=e.runScript,r=typeof t=="string"?void 0:t.when;if(r&&!await this.evaluateWhen(r)){console.log("[flow] runScript skipped (when predicate false)");return}this.runScript(t)}else if(e.openLink!==void 0)await this.openLink(e.openLink);else if(e.runFlow){let t=e.runFlow,r=typeof t=="string"?t:t.file,n=typeof t=="string"?void 0:t.commands,o=typeof t=="string"?void 0:t.env,a=typeof t=="string"?void 0:t.when;if(a&&!await this.evaluateWhen(a)){console.log(`[flow] runFlow skipped (when predicate false): ${r??"inline commands"}`);return}if(!r&&!n)throw new Error("runFlow requires either file or commands");this.js.enterEnvScope();try{if(o)for(let[s,l]of Object.entries(o))this.js.putEnv(s,l);if(r){let s=S.resolve(this.opts.flowDir,r),l=v.readFileSync(s,"utf8"),p=this.opts.flowDir;this.opts.flowDir=S.dirname(s);try{await this.runFlow(Jt(l))}finally{this.opts.flowDir=p}}else if(n)for(let s=0;s<n.length;s++)await this.runStep(n[s],s)}finally{this.js.leaveEnvScope()}}else throw new Error(`unsupported flow step: ${JSON.stringify(e)}`)}}liveStatus=null;async runFlow(e){let t=[],r=[],n=[];for(let a of e){let s=Object.keys(a);if(s.length===1&&s[0]==="onFlowStart"&&Array.isArray(a.onFlowStart)){t.push(...a.onFlowStart);continue}if(s.length===1&&s[0]==="onFlowComplete"&&Array.isArray(a.onFlowComplete)){r.push(...a.onFlowComplete);continue}n.push(a)}if(this.liveStatus&&await this.liveStatus.plan(n.map((a,s)=>{let l=typeof a=="string"?pt(a):a,p=Object.keys(l).find(u=>u!=="when")??Object.keys(l)[0];return{index:s,name:p,target:this.flowStepTargetLabel(l,p)}})),t.length>0){console.log(`[flow] onFlowStart (${t.length} steps)`);for(let a=0;a<t.length;a++)await this.runStep(t[a],a)}let o=null;try{await this.runFlowBody(n)}catch(a){o=a instanceof Error?a:new Error(String(a))}if(r.length>0){console.log(`[flow] onFlowComplete (${r.length} steps)`);for(let a=0;a<r.length;a++)try{await this.runStep(r[a],a)}catch(s){console.warn(`[flow] onFlowComplete step ${a+1} failed: ${s instanceof Error?s.message:s}`)}}if(o)throw o}async runFlowBody(e){for(let t=0;t<e.length;t++){let r=e[t],n=typeof r.wait=="number"?r.wait:0,o=typeof r.waitFor?.timeout=="number"?r.waitFor.timeout:0,a=typeof r.extendedWaitUntil?.timeout=="number"?r.extendedWaitUntil.timeout:0,s=Math.max(6e4,n+15e3,q(o)+15e3,q(a)+15e3);this.liveStatus&&(await this.liveStatus.waitWhilePaused(),await this.liveStatus.step(t,"running"));let l=Date.now(),p=async(u,m)=>{if(!this.liveStatus)return;let b=this.flowTraceSteps[this.flowTraceSteps.length-1],g=b&&b.stepIndex===t&&b.startedAtMs>=l;await this.liveStatus.step(t,u?"failure":g&&b.status==="skipped"?"skipped":"success",{durationMs:Date.now()-l,error:u?m instanceof Error?m.message.slice(0,300):String(m).slice(0,300):g&&b.error||void 0})};try{r.runFlow||r.launchApp?await this.runStep(r,t):await Promise.race([this.runStep(r,t),new Promise((u,m)=>setTimeout(()=>m(new Error(`step ${t+1} (${Object.keys(r)[0]}) exceeded ${s}ms deadline`)),s))])}catch(u){let m=this.flowTraceSteps[this.flowTraceSteps.length-1];if(!(m&&m.stepIndex===t&&m.startedAtMs>=l)){let b=Object.keys(r)[0];this.lastFailedStep={index:t,kind:b,target:r[b]},this.recordFlowTraceStep({stepIndex:t,stepName:b,targetLabel:this.flowStepTargetLabel(r,b),startedAtMs:l,status:"failure",error:u})}throw await p(!0,u),u}await p(!1)}}};function Gt(i){if(typeof i!="object"||i==null||!("control"in i))return!1;let e=i.control;return typeof e=="object"&&e!=null&&"paused"in e&&e.paused===!0}var oe=class{constructor(e,t,r){this.bridge=e;this.flowName=t;this.getSimId=r}disabled=!1;paused=!1;lastSimId;plannedSteps=null;completedSteps=new Map;runId=`flr_${Date.now().toString(36)}_${Math.random().toString(36).slice(2,8)}`;async send(e,t){let r=await this.bridge.send({type:"flowStatus",simId:t,status:{runId:this.runId,flowName:this.flowName,...e}});this.paused=Gt(r)}async push(e){if(!this.disabled)try{let t=this.getSimId?.();if(t!==this.lastSimId&&this.lastSimId!=null&&this.plannedSteps&&e.phase!=="plan"){await this.send({phase:"plan",state:"running",steps:this.plannedSteps},t);for(let r of this.completedSteps.values())await this.send({phase:"step",state:"running",step:r},t)}this.lastSimId=t,await this.send(e,t)}catch(t){this.disabled=!0,console.log(`[flow] live status unavailable (${t instanceof Error?t.message.slice(0,120):t}) \u2014 continuing without the devtools rail`)}}async plan(e){this.plannedSteps=e.map(t=>({...t})),this.completedSteps.clear(),await this.push({phase:"plan",state:"running",steps:e})}async step(e,t,r){let n={index:e,status:t,...r};await this.push({phase:"step",state:"running",step:n}),this.completedSteps.set(e,n)}async end(e){await this.push({phase:"end",state:e})}async waitWhilePaused(){if(!this.disabled)for(;this.paused;){for(console.log("[flow] paused from devtools \u2014 waiting\u2026");this.paused&&!this.disabled;)await new Promise(e=>setTimeout(e,400)),await this.push({phase:"heartbeat",state:"paused"});this.disabled||console.log("[flow] resumed")}}};var Fe=null;function Hr(){return Fe}var $e=[];function Ur(){return $e}async function zt(i){if(!i)return"";let e=i.trim();if(!e)return"";if(/^\d+$/.test(e)||e.startsWith("http://")||e.startsWith("https://"))return e;let r=(await Ue()).find(n=>n.name.toLowerCase()===e.toLowerCase());return r?String(r.preferredPort):e}async function Yt(){let i=await We(),e=i.find(r=>r.patched);if(e)return`http://localhost:${e.port}/__soot/`;let t=i[0];return t?`http://localhost:${t.port}/__soot/`:null}async function ft(i){Fe=null,$e=[],(i.length===0||i.includes("--help")||i.includes("-h"))&&(console.log(`
|
|
464
464
|
sootsim maestro \u2014 author and run Maestro YAML flows
|
|
465
465
|
|
|
466
466
|
usage:
|
|
@@ -540,28 +540,28 @@ flow extension:
|
|
|
540
540
|
takeScreenshot:
|
|
541
541
|
path: marketing/hero
|
|
542
542
|
withFrame: true
|
|
543
|
-
`),process.exit(0));let e=i[0];$.existsSync(e)||(console.error(` error: ${e} not found`),process.exit(1));let t=h=>i.find((
|
|
543
|
+
`),process.exit(0));let e=i[0];$.existsSync(e)||(console.error(` error: ${e} not found`),process.exit(1));let t=h=>i.find((d,y)=>i[y-1]===h),r=i.includes("--profile"),n=i.includes("--headed"),o=i.includes("--new")||n,a=t("--out")||"/tmp/sootsim-recordings",s=t("--screenshots")||(t("--out")?a:"/tmp/sootsim-flow"),l=t("--screenshot-paths")==="flow"?"flow":"dir",p=i.includes("--no-shell")?"tenant":i.includes("--shell-only")?"shell":void 0,u=t("--device")?.trim()||"",m=i.includes("--slow")?+(t("--slow")||"500"):0,b=i.includes("--electron"),g=i.includes("--preview"),P=await ot(t("--preview-origin")),k=t("--preview-public-origin"),H=i.includes("--preview-open"),Pe=t("--owner")?.trim()||"",ke=t("--repo")?.trim()||"",U=t("--billing-kind")?.trim()||"",mt=g?`maestro:${process.env.GITHUB_RUN_ID?`github:${process.env.GITHUB_RUN_ID}:attempt:${process.env.GITHUB_RUN_ATTEMPT||"1"}:job:${process.env.GITHUB_JOB||"preview"}`:`local:${qt()}`}:flow:${Kt("sha256").update(w.relative(process.cwd(),w.resolve(e))).digest("hex").slice(0,16)}`:"";U&&U!=="test_run"&&(console.error(` error: invalid --billing-kind: ${U}`),process.exit(1));let gt=i.flatMap((h,d)=>i[d-1]==="--replace"?["--replace",h]:[]),wt=i.flatMap((h,d)=>i[d-1]==="--remap"?["--remap",h]:[]),M=i.includes("--record")||g,yt=i.includes("--tail-wait")?Math.max(0,+(t("--tail-wait")||"2000")):M?g?6e3:2e3:0,bt=$.readFileSync(e,"utf8"),{frontmatter:T,steps:R}=we(bt);R.length===0&&(console.error(" error: flow file must contain a YAML array of steps"),process.exit(1));let W=u||T.device||"",Ae=T.theme||"",Z=b||T.electron===!0,St=T.app===void 0||T.app===null?"":typeof T.app=="number"?String(T.app):T.app,se=await zt(St),Me={stripBooleanFlags:["--record","--profile","--electron","--new","--preview","--preview-open","--headless","--headed"],stripValueFlags:["--out","--device","--slow","--tail-wait","--url","--replace","--remap","--screenshots","--screenshot-paths","--preview-origin","--preview-public-origin","--driver","--billing-kind","--owner","--repo"]},x=he(i,Me),vt=t("--url")||"";Z&&!ze()&&(console.error(" error: desktop companion not found. install or build it first with `bun run build:electron`"),process.exit(1));let Re=Z?"desktop companion":"bridge",xt=se?` | target: ${se}`:"";console.log(`
|
|
544
544
|
sootsim maestro \u2014 ${w.basename(e)}
|
|
545
545
|
${R.length} steps | ${Re}${xt}${M?" | recording":""}${r?" | profiling":""}${m?` | ${m}ms delay`:""}
|
|
546
|
-
`),g&&Be({event:"preview_flow_started",properties:{flowName:w.basename(e),stepCount:R.length,mode:Re,electron:Z,record:M,profile:r,previewOrigin:P}});let A=vt||se||"",ae=o||Z&&x.simIdSource!=="flag",_e=t("--driver")||"",le=!1,
|
|
546
|
+
`),g&&Be({event:"preview_flow_started",properties:{flowName:w.basename(e),stepCount:R.length,mode:Re,electron:Z,record:M,profile:r,previewOrigin:P}});let A=vt||se||"",ae=o||Z&&x.simIdSource!=="flag",_e=t("--driver")||"",le=!1,de=new Set,Oe=!1;if(!A&&!ae&&x.simIdSource==="none"){let h=Ke(x);try{let d=await h.listSims(),y=d.find(D=>D.isPrimary&&D.readyState==="open"),F=d.find(D=>D.readyState==="open"),J=y??F;J&&(Oe=!0,console.log(` reusing active sim: ${J.id}`))}catch{}finally{h.close()}}if(!A&&!Oe&&(ae||x.simIdSource==="none")){let h=await Yt();h||(console.error(" error: no current sim and no sootsim target found"),await ue(),process.exit(1)),A=h}if(A&&W){let h=new URL(await Ye(A));h.searchParams.set("device",W),A=h.toString()}if(A){let h=[A];if(h.push(...gt),h.push(...wt),ae&&h.push("--new"),h.push("--no-describe"),x.simIdSource==="flag"&&x.simId&&h.push("--sim",x.simId),_e&&(h.push("--driver",_e),le=!0),i.includes("--headless")&&!n&&h.push("--headless"),await Xe(h,{port:x.wsPort,timeoutMs:x.commandTimeoutMs}),le){let d=pe();d&&de.add(d)}}let B=he(i,Me),X=B.simIdSource==="flag"?B.simId:pe()||B.simId,Tt=B.simIdSource==="flag"?"flag":X?"saved":"none",E=fe(B.wsPort,{commandTimeoutMs:B.commandTimeoutMs,simId:X,simIdSource:Tt}),c,De=async()=>{let h=T.env?.SOOTSIM_STATUS_BAR_TIME;if(h){if(!/^(?:[1-9]|1[0-2]):[0-5][0-9]$/.test(h))throw new Error("SOOTSIM_STATUS_BAR_TIME must be a 12-hour time such as 9:41");await E.send({type:"evaluate",simId:c.simId,code:`window.dispatchEvent(new CustomEvent('sootsim:statusBarOverride', { detail: { time: ${JSON.stringify(h)} } }))`})}if(Ae&&await E.send({type:"call",simId:c.simId,path:"SootSim.bridges.settings.set",args:["colorScheme",Ae]}),!W)return!1;let d=await E.send({type:"evaluate",simId:c.simId,code:"window.location.href"});if(typeof d=="string"&&d.length>0){let y=new URL(d);y.searchParams.set("device",W),c.setSimRouteHint(y.toString())}return!!await E.send({type:"call",simId:c.simId,path:"SootSim.bridges.settings.set",args:["deviceModel",W]})};if(c=new ie(E,{screenshotDir:s,flowDir:w.dirname(w.resolve(e)),screenshotPathMode:l,screenshotLayers:p,simId:X,recordingOutputDir:M?a:void 0,recordingFormat:g?"mp4":"webm",billingOriginOverride:g?P:void 0,allowGitHubRecording:g,requireRecordingEntitlement:g,onAfterLaunch:async()=>{await De()&&await c.waitForTree(12e4),g&&await E.send({type:"evaluate",simId:c.simId,code:`(() => {
|
|
547
547
|
const r = window.SootSim?.bridges?.eventRecorder ?? window.__sootsimEventRecorder
|
|
548
548
|
return r?.start?.() ?? false
|
|
549
|
-
})()`})}}),m&&(
|
|
549
|
+
})()`})}}),m&&(c.stepDelay=m),c.liveStatus=new oe(E,w.basename(e),()=>c.simId),c.js.putEnv("MAESTRO_FILENAME",w.basename(e,w.extname(e))),T.env&&typeof T.env=="object")for(let[h,d]of Object.entries(T.env))c.js.putEnv(h,d);let _=null,I=null,L=null,O=null,j=null,ce=null,V=0,Q=!!R[0]?.launchApp;try{Q||await c.waitForTree(12e4),await De()&&!Q&&await c.waitForTree(12e4),g&&!Q&&!process.env.SOOTSIM_PREVIEW_RESET_DONE&&await c.launchApp({clearState:!0}),M&&(Q?c.prepareRecording():await c.startRecording()),r&&await c.startProfile(),g&&(await E.send({type:"evaluate",simId:c.simId,code:`(() => {
|
|
550
550
|
const r = window.SootSim?.bridges?.eventRecorder ?? window.__sootsimEventRecorder
|
|
551
551
|
return r?.start?.() ?? false
|
|
552
|
-
})()`})||console.warn(" warn: eventRecorder.start() returned false \u2014 preview will upload bundle without replay events")),await
|
|
552
|
+
})()`})||console.warn(" warn: eventRecorder.start() returned false \u2014 preview will upload bundle without replay events")),await c.runFlow(R),r&&(_=await c.stopProfile()),await c.waitForRecordingTail({maxMs:yt,smart:g}),M&&(I=await c.stopRecording(),L=c.getLastRecordingDurationMs()),g&&(O=await E.send({type:"evaluate",simId:c.simId,code:`(() => {
|
|
553
553
|
const r = window.SootSim?.bridges?.eventRecorder ?? window.__sootsimEventRecorder
|
|
554
554
|
return r?.stop?.() ?? []
|
|
555
|
-
})()`}),console.log(` captured ${O.length} replay events`),j=w.join(s,"preview-final.png"),await
|
|
556
|
-
+ completed (${R.length} steps)`),
|
|
555
|
+
})()`}),console.log(` captured ${O.length} replay events`),j=w.join(s,"preview-final.png"),await c.captureScreenshot(j),console.log(` final screenshot: ${j}`));let d=R.filter(y=>y&&typeof y=="object"&&"takeScreenshot"in y).length;console.log(`
|
|
556
|
+
+ completed (${R.length} steps)`),d>0&&console.log(` screenshots: ${d} \u2192 ${s}`),_&&ht(_),I&&console.log(` video: ${I}`),console.log()}catch(h){if(r&&!_)try{_=await c.stopProfile()}catch{}if(M&&!I)try{I=await c.stopRecording(),L=c.getLastRecordingDurationMs()}catch(d){console.warn(` recording stop failed: ${d?.message||String(d)}`)}if(g&&!O)try{O=await E.send({type:"evaluate",simId:c.simId,code:`(() => {
|
|
557
557
|
const r = window.SootSim?.bridges?.eventRecorder ?? window.__sootsimEventRecorder
|
|
558
558
|
return r?.stop?.() ?? []
|
|
559
|
-
})()`}),console.log(` captured ${O.length} partial replay events`)}catch(
|
|
559
|
+
})()`}),console.log(` captured ${O.length} partial replay events`)}catch(d){console.warn(` event recorder stop failed: ${d?.message||String(d)}`)}console.error(`
|
|
560
560
|
x failed: ${h.message}
|
|
561
|
-
`),_&&(console.log(" partial profile:"),ht(_)),
|
|
562
|
-
preparing preview upload\u2026`);let
|
|
561
|
+
`),_&&(console.log(" partial profile:"),ht(_)),I&&console.log(` partial video: ${I}`);try{let d=c.lastFailedStep,y=d?`step-${String(d.index+1).padStart(2,"0")}-${d.kind}`:"unstaged",F=w.join(s,y);await c.captureFailureBundle(F,{error:h,stepIndex:d?.index,stepKind:d?.kind,stepTarget:d?.target}),ce=F,console.log(` failure bundle: ${F}`),console.log(" (contents: screenshot.png, describe.json, a11y.txt, tree.txt, console.json, error.json)")}catch(d){try{let y=w.join(s,"error.png");await c.captureScreenshot(y),console.log(` error screenshot: ${y}`)}catch{}console.log(` (failure bundle capture failed: ${d instanceof Error?d.message:String(d)})`)}await qe(E,{errorsCommand:`sootsim get errors 5${c.simId?` --sim ${c.simId}`:""}`,warningsCommand:`sootsim get warnings 5${c.simId?` --sim ${c.simId}`:""}`,requestsCommand:`sootsim get requests 5${c.simId?` --sim ${c.simId}`:""}`}),V=1}if(await c.liveStatus?.end(V===0?"passed":"failed"),g&&(V===0||I||O))try{let h=await Xt(O??[]),d=["--origin",P,"--events",h];k&&d.push("--public-origin",k),I&&d.push("--video",I),j&&d.push("--screenshot",j),I&&L&&Number.isFinite(L)&&(d.push("--video-duration-ms",String(Math.round(L))),d.push("--recorded-duration-ms",String(Math.round(L))));let y=c.getLastRecordingStartedAtMs();y&&Number.isFinite(y)&&d.push("--recording-started-at-ms",String(Math.round(y))),x.wsPort&&d.push("--port",String(x.wsPort)),c.simId&&d.push("--sim",c.simId),H&&d.push("--open"),Pe&&d.push("--owner",Pe),ke&&d.push("--repo",ke),d.push("--run-scope",mt),U&&d.push("--billing-kind",U),console.log(`
|
|
562
|
+
preparing preview upload\u2026`);let F=c.getFlowTraceSteps();F.length>0&&d.push("--timeline-events",await Qt(F));let J=await er(F,y);J&&d.push("--snapshot-manifest",J),ce&&d.push("--failure-bundle",ce);let D=c.getLastRecordingFrameStats();D&&d.push("--trace-frame-stats",await tr(D));let{runUpload:Et}=await import("./upload-PCXRS5D7.js");Fe=await Et(d,{})}catch(h){console.error(` preview upload failed: ${h?.message||h}`),V=1}return $e=c.getFlowTraceSteps(),E.close(),le?(c.simId&&de.add(c.simId),await Zt(x.wsPort,x.commandTimeoutMs,[...de])):c.simId&&c.simId!==X&&He(c.simId),await ue(),V}async function Zt(i,e,t){let r=[...new Set(t.filter(Boolean))];if(r.length===0)return;let n=fe(i,{commandTimeoutMs:e});try{let o=await n.listSims(),a=r.filter(l=>o.some(p=>p.id===l&&p.readyState==="open"));if(a.length===0)return;let s=await Qe(n,i,e,a);await Ze(o,a),s.closed.length>0&&console.log(` closed flow sim(s): ${s.closed.join(", ")}`),s.remaining.length>0&&console.warn(` warn: flow sim(s) still connected after close: ${s.remaining.join(", ")}`)}catch(o){console.warn(` warn: failed to close flow sim(s): ${o instanceof Error?o.message:String(o)}`)}finally{n.close()}}async function Xt(i){let{gzipSync:e}=await import("zlib"),t=i.map(o=>JSON.stringify(o)).join(`
|
|
563
563
|
`)+(i.length?`
|
|
564
564
|
`:""),r=e(Buffer.from(t,"utf8")),n=w.join(Y(),`sootsim-events-${Date.now()}.jsonl.gz`);return $.writeFileSync(n,r),console.log(` events: ${i.length} written to ${n} (${r.length} bytes gz)`),n}async function Qt(i){let{gzipSync:e}=await import("zlib"),t=i.map((a,s)=>({schemaVersion:1,t:a.endedAtMs,seq:1e6+s,context:"host",kind:"flow-step",id:`flow-step-${a.stepIndex}`,data:{stepIndex:a.stepIndex,stepNumber:a.stepIndex+1,stepName:a.stepName,...a.targetLabel?{targetLabel:a.targetLabel}:{},status:a.status,durationMs:a.durationMs,startedAtMs:a.startedAtMs,endedAtMs:a.endedAtMs,...a.error?{error:a.error}:{}}})),r=t.map(a=>JSON.stringify(a)).join(`
|
|
565
565
|
`)+`
|
|
566
566
|
`,n=e(Buffer.from(r,"utf8")),o=w.join(Y(),`sootsim-flow-steps-${Date.now()}.jsonl.gz`);return $.writeFileSync(o,n),console.log(` flow trace: ${t.length} step events written to ${o} (${n.length} bytes gz)`),o}async function er(i,e){if(!e)return null;let t=i.flatMap(n=>n.screenshotPath?[{id:`flow-step-${n.stepIndex}`,label:n.targetLabel??`Step ${n.stepIndex+1}`,kind:"interaction",t:Math.max(0,n.endedAtMs-e),path:n.screenshotPath}]:[]);if(t.length===0)return null;let r=w.join(Y(),`sootsim-flow-snapshots-${Date.now()}.json`);return $.writeFileSync(r,JSON.stringify(t)),console.log(` flow snapshots: ${t.length} written to ${r}`),r}async function tr(i){let e=w.join(Y(),`sootsim-frame-stats-${Date.now()}.json`);return $.writeFileSync(e,JSON.stringify(i)),console.log(` frame stats: written to ${e}`),e}async function rr(i){let e=i[0],t=r=>i.find((n,o)=>i[o-1]===r);switch(e){case"start":{let{path:r,state:n}=tt();console.log(" flow draft started"),console.log(` session: ${r}`),console.log(` steps: ${n.steps.length}`);return}case"keep":case"good":{let r=Se();if(r.active||(console.error(" no active flow draft \u2014 run `sootsim maestro start` first"),process.exit(1)),!r.kept){console.log(" no pending action to keep");return}console.log(` kept: ${r.candidate.summary}`),console.log(` steps: ${r.stepCount}`);return}case"end":{let r=t("--output")||(i[1]&&!i[1].startsWith("-")?i[1]:void 0),n=i.includes("--validate")||i.includes("--video"),o=i.includes("--video"),a=Se();a.active&&a.kept&&console.log(` auto-kept trailing action: ${a.candidate.summary}`);let s=rt(r||(n?ir():void 0));if(s.active||(console.error(" no active flow draft \u2014 run `sootsim maestro start` first"),process.exit(1)),!s.valid){console.error(" flow draft is not valid:");for(let l of s.issues)console.error(` - ${l}`);console.error(" draft preserved \u2014 keep at least one real interaction or run `sootsim maestro start` to reset"),process.exit(1)}if(n){let l=or(i,s.outputPath),p=await ft(l);if(p!==0){console.error(`
|
|
567
|
-
validation failed \u2014 draft preserved so you can keep iterating`),process.exitCode=p;return}be(),console.log(` flow draft validated (${s.stepCount} step${s.stepCount===1?"":"s"})`),s.outputPath&&console.log(` saved: ${s.outputPath}`),o&&console.log(" video: recorded during validation run");return}if(be(),console.log(` flow draft ended (${s.stepCount} step${s.stepCount===1?"":"s"})`),s.outputPath){console.log(` saved: ${s.outputPath}`),console.log(` next: sootsim maestro test ${s.outputPath} --record`);return}console.log(""),process.stdout.write(s.yaml);return}case"validate":{let r=i[1];(!r||r.startsWith("-"))&&(console.error(" usage: sootsim maestro validate <path>"),process.exit(1));let n=ye(r);if(n.length>0){console.error(` x ${r} failed validation:`);for(let o of n)console.error(` - ${o}`);process.exit(1)}console.log(` + ${r} looks valid`);return}}}function nr(i){return i[0]==="--sim"&&i.length>=2?[...i.slice(2),"--sim",i[1]]:i}async function
|
|
567
|
+
validation failed \u2014 draft preserved so you can keep iterating`),process.exitCode=p;return}be(),console.log(` flow draft validated (${s.stepCount} step${s.stepCount===1?"":"s"})`),s.outputPath&&console.log(` saved: ${s.outputPath}`),o&&console.log(" video: recorded during validation run");return}if(be(),console.log(` flow draft ended (${s.stepCount} step${s.stepCount===1?"":"s"})`),s.outputPath){console.log(` saved: ${s.outputPath}`),console.log(` next: sootsim maestro test ${s.outputPath} --record`);return}console.log(""),process.stdout.write(s.yaml);return}case"validate":{let r=i[1];(!r||r.startsWith("-"))&&(console.error(" usage: sootsim maestro validate <path>"),process.exit(1));let n=ye(r);if(n.length>0){console.error(` x ${r} failed validation:`);for(let o of n)console.error(` - ${o}`);process.exit(1)}console.log(` + ${r} looks valid`);return}}}function nr(i){return i[0]==="--sim"&&i.length>=2?[...i.slice(2),"--sim",i[1]]:i}async function Wr(i){let e=nr(i),t=e[0];if(t==="start"||t==="keep"||t==="good"||t==="end"||t==="validate")return await rr(e),0;let r=await ft(e);return r!==0&&(process.exitCode=r),r}function ht(i){console.log(""),nt(i)}function ir(){return w.join(Y(),`sootsim-flow-draft-${Date.now()}.yaml`)}function or(i,e){if(!e)throw new Error("validated flow draft requires an output path");let t=[e];for(let r=1;r<i.length;r++){let n=i[r];if(!(n==="--validate"||n==="--video")){if(n==="--output"){r+=1;continue}r===1&&!n.startsWith("-")||t.push(n)}}return!t.includes("--record")&&i.includes("--video")&&t.push("--record"),t}export{dt as a,Rt as b,Hr as c,Ur as d,Yt as e,ft as f,nr as g,Wr as h};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
/*! sootsim v0.1.
|
|
2
|
-
import{c as b}from"./chunk-
|
|
1
|
+
/*! sootsim v0.1.291 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
|
+
import{c as b}from"./chunk-UQLIMTO6.js";import{b as L,e as T,g as E}from"./chunk-EPJO7YNS.js";import{K as S,L as I,M as B,N as P,g as A}from"./chunk-5NGZRMTN.js";import{WebSocket as $}from"ws";var W=null;function O(){let i=A();if(W?.homeDir===i)return W.world;let r=U();return W={homeDir:i,world:r},r}function U(){let i=I();if(i&&P(i))return{source:"dev-bridge",bridgePort:i.bridgePort,shellBaseUrl:i.shellPort?`http://localhost:${i.shellPort}/`:b};let r=S();return r&&B(r)?{source:"daemon",bridgePort:r.bridgePort,shellBaseUrl:r.runtimePort>0?`http://localhost:${r.runtimePort}/`:b}:{source:"default",bridgePort:7668,shellBaseUrl:b}}function _(i){let r=I();if(r&&P(r)&&r.bridgePort===i)return{source:"dev-bridge",shellBaseUrl:r.shellPort?`http://localhost:${r.shellPort}/`:b};let e=S();return e&&B(e)&&e.bridgePort===i?{source:"daemon",shellBaseUrl:e.runtimePort>0?`http://localhost:${e.runtimePort}/`:b}:null}function K(i){let r;try{let l=new URL(i);r=l.port?Number(l.port):l.protocol==="https:"?443:80}catch{return null}if(!Number.isFinite(r)||r<=0)return null;let e=I();if(e&&P(e)&&(e.shellPort===r||e.runtimePort===r||e.bridgePort===r))return e.bridgePort;let d=S();return d&&B(d)&&(d.runtimePort===r||d.bridgePort===r)?d.bridgePort:null}function D(){return O().bridgePort}function Q(i,r){let e=_(i),d=e?.source==="dev-bridge"?"dev bridge":e?.source==="daemon"?"daemon bridge":"bridge",l=e?`${e.source}.json`:"no lockfile",t=r??e?.shellBaseUrl;process.stderr.write(` \u2192 ${d} :${i} (${t?`shell ${t}, `:""}${l})
|
|
3
3
|
`)}var C=class extends Error{lock;constructor(r,e){super(r),this.name="BridgeSimLockedError",this.lock=e}};function N(i){return i==="flag"?"via --sim":i==="saved"?"saved via `sootsim use`":"primary fallback \u2014 no sim pinned"}function z(i,r={}){let e=new Set,d=r.port??D(),l=r.commandTimeoutMs??15e3,t,u="none",v=new Set(r.stripBooleanFlags??[]),y=new Set(r.stripValueFlags??[]);for(let n=0;n<i.length;n++){let a=i[n];if(a==="--port"||a==="-p"){e.add(n),n+1<i.length&&(e.add(n+1),d=Number(i[n+1])),n++;continue}if(a.startsWith("--port=")){e.add(n),d=Number(a.slice(7));continue}if(a==="--timeout"){e.add(n),n+1<i.length&&(e.add(n+1),l=Number(i[n+1])),n++;continue}if(a==="--sim"||a==="--session"||a==="--tab"){e.add(n),n+1<i.length&&(e.add(n+1),t=i[n+1]?.trim()||void 0,u="flag"),n++;continue}let s=a.startsWith("--sim=")?a.slice(6):a.startsWith("--session=")?a.slice(10):a.startsWith("--tab=")?a.slice(6):void 0;if(s!==void 0){e.add(n),t=s.trim()||void 0,u="flag";continue}if(v.has(a)){e.add(n);continue}y.has(a)&&(e.add(n),n+1<i.length&&e.add(n+1),n++)}if(!t){let n=T();n&&(t=n.trim()||void 0,u="saved")}return{positional:i.filter((n,a)=>!e.has(a)),wsPort:d,simId:t,simIdSource:u,commandTimeoutMs:l}}function R(i,r={}){let e=1,d=r.commandTimeoutMs??15e3,l=new Map,t=new $(`ws://localhost:${i}`),u=L(),v=new Promise((s,o)=>{t.on("open",()=>{try{t.send(JSON.stringify({type:"bridge:hello",id:0,cliIdentityKey:u.key,cliIdentitySource:u.source,cliLabel:r.cliLabel}))}catch{}s()}),t.on("error",c=>{let m=c.message?`: ${c.message}`:"";o(new Error(`could not connect to ws://localhost:${i}${m}`))})}),y=!1,n=!1;function a(s,o){if(n||process.env.SOOTSIM_QUIET_TARGET_NOTICE==="1"||s.startsWith("bridge:")||s==="focus"||s==="close")return;n=!0;let c=o??"primary",m=N(o?r.simIdSource:"none");process.stderr.write(` \u2192 ${c} (${m})
|
|
4
4
|
`)}return t.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&&!y&&(y=!0,process.stderr.write(`
|
|
5
5
|
\u26A0 ${o._otherCliCount} other CLI identity/identities are driving this sim
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
/*! sootsim v0.1.
|
|
2
|
-
import{c as f}from"./chunk-
|
|
1
|
+
/*! sootsim v0.1.291 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
|
+
import{c as f}from"./chunk-EPJO7YNS.js";import{existsSync as w,mkdirSync as g,readFileSync as h,writeFileSync as S,rmSync as q}from"fs";import{tmpdir as y}from"os";import{dirname as b,join as p}from"path";var m=new Map;function o(e,t){m.set(e,t)}var s=1;function a(){return p(y(),`sootsim-cli-hints-${f()}.json`)}function d(){return p(y(),"sootsim-cli-hints-global.json")}function u(e){if(!w(e))return{version:s,shown:{}};try{let t=JSON.parse(h(e,"utf8"));return t?.version!==s||!t?.shown?{version:s,shown:{}}:t}catch{return{version:s,shown:{}}}}function l(e,t){try{g(b(e),{recursive:!0}),S(e,JSON.stringify(t)+`
|
|
3
3
|
`)}catch{}}function v(){let e=(process.env.SOOTSIM_HINTS||"").toLowerCase();return e==="off"||e==="0"||e==="false"?"off":e==="always"||e==="verbose"?"always":"normal"}function H(e,t){let i=v();if(i==="off")return!1;if(i==="always"||t==="always")return!0;let r=Date.now();if(t==="once-per-identity"){let n=u(a());return n.shown[e]?!1:(n.shown[e]=r,l(a(),n),!0)}if(t==="once-ever"){let n=u(d());return n.shown[e]?!1:(n.shown[e]=r,l(d(),n),!0)}if(typeof t=="object"&&"cooldownMs"in t){let n=u(a()),c=n.shown[e]??0;return r-c<t.cooldownMs?!1:(n.shown[e]=r,l(a(),n),!0)}return!0}function A(e,...t){let i=m.get(e);if(!i)return process.env.SOOTSIM_HINTS_DEBUG&&console.error(` [hints] no hint registered for id "${e}"`),!1;if(!H(e,i.frequency))return!1;let r=i.render(...t);if(r==null)return!1;let n=Array.isArray(r)?r:[r];for(let c of n)console.error(` hint: ${c}`);return!0}o("app-still-loading",{frequency:{cooldownMs:6e4},render:e=>`app may still be loading (${e} nodes). run \`sootsim wait ready\` first.`});o("wait-selector-for-missing-testid",{frequency:"once-per-identity",render:e=>`sootsim wait selector ${e}`});o("prefer-cli-over-eval",{frequency:"once-per-identity",render:e=>e.length?["try the CLI shortcut instead:",...e.map(t=>` ${t}`)]:null});o("describe-use-filters",{frequency:"once-per-identity",render:()=>["describe output is long. narrow it with:"," sootsim describe --only '*Bottom Sheet*'"," sootsim describe --testid-like 'swap-*'"," sootsim describe --subtree <testID>"]});o("describe-filter-context",{frequency:"once-per-identity",render:()=>["filtered describe is search output, not current-route proof.","run `sootsim describe` without filters after navigation; clipped nodes are marked `(clipped:...)`."]});o("subtree-root-not-found",{frequency:"always",render:e=>`no node with testID/id "${e}" \u2014 try \`sootsim find --testid ${e}\` to discover available ids.`});o("clean-uninstall",{frequency:"once-ever",render:()=>["to remove the background daemon and all ~/.sootsim data, run `sootsim daemon uninstall`.","the optional desktop app and its macOS preference plist are separate from the daemon."]});export{A as a};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
/*! sootsim v0.1.
|
|
2
|
-
import{g as j,i as A,l as K,m as v}from"./chunk-
|
|
1
|
+
/*! sootsim v0.1.291 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
|
+
import{g as j,i as A,l as K,m as v}from"./chunk-5CJQNMXY.js";import{createHash as Y}from"node:crypto";import{mkdirSync as L,readFileSync as W,readdirSync as Q,unlinkSync as X,writeFileSync as D}from"node:fs";import{dirname as q,extname as Z,resolve as B}from"node:path";function H(t){let e=t[0]?.toLowerCase()??"toggle";return e!=="on"&&e!=="off"&&e!=="toggle"&&(console.error(` unknown argument: "${e}" (expected on | off | toggle)`),process.exit(1)),e}async function U(t,e,o){let n=j(t,{port:e.port}),i=H(n.positional),m=A({...n,commandTimeoutMs:5e3});try{let a=!!(await K(m,"SootSim.bridges.settings.get"))?.[o.modeKey],u=i==="on"?!0:i==="off"?!1:!a;if(a===u)return console.log(` ${o.displayName}: already ${u?"on":"off"}`),{current:a,target:u,changed:!1};if(!await m.send({type:"evaluate",acquireLock:!0,code:`(async () => {
|
|
3
3
|
const modeKey = ${JSON.stringify(o.modeKey)}
|
|
4
4
|
const target = ${JSON.stringify(u)}
|
|
5
5
|
window.dispatchEvent(new CustomEvent('sootsim:shell-command', {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! sootsim v0.1.
|
|
1
|
+
/*! sootsim v0.1.291 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
|
|
2
2
|
import{randomUUID as D}from"node:crypto";import r from"node:fs";import{homedir as x}from"node:os";import o from"node:path";var h="SOOTSIM_HOME",k="active",L="daemon.json",O="dev-bridge.json",A="config.json",S=3e4;function i(){let e=process.env[h];return e&&e.length>0?o.resolve(e):o.join(x(),".sootsim")}function E(){if(process.env.SOOTSIM_FORCE_DAEMON_INSTALL==="1")return!1;let e=process.env.SOOTSIM_DEV;if(e==="1"||e==="true")return!0;if(e==="0"||e==="false")return!1;let t=process.argv[1];if(!t)return!1;try{return r.realpathSync(t).includes(`${o.sep}packages${o.sep}sootsim${o.sep}`)}catch{return!1}}function N(){return process.env.SOOTSIM_FORCE_DAEMON_INSTALL==="1"?!1:process.env.IS_TAMAGUI_DEV==="1"}function J(){return E()||N()}function m(){return o.join(i(),"runtimes")}function _(e){return o.join(m(),e)}function b(){return o.join(m(),k)}function g(){return o.join(i(),"electron")}function V(){return o.join(g(),"userData")}function H(e){return o.join(g(),e)}function P(){return o.join(i(),"profiles")}function j(){return o.join(i(),"daemon-app")}function I(){return o.join(j(),"SootSim Daemon.app")}function G(){return o.join(I(),"Contents","MacOS","sootsim-daemon")}function w(){return o.join(i(),"cache")}function a(){return o.join(i(),L)}function f(){return o.join(i(),O)}function d(){return o.join(i(),A)}function y(){try{let e=r.readFileSync(d(),"utf8"),t=JSON.parse(e);return t&&typeof t=="object"?t:{}}catch{return{}}}function v(e){s();let t=y(),u={...t,...e};e.settings&&typeof e.settings=="object"&&(u.settings={...t.settings&&typeof t.settings=="object"?t.settings:{},...e.settings});let c=`${d()}.tmp`;return r.writeFileSync(c,`${JSON.stringify(u,null,2)}
|
|
3
3
|
`,"utf8"),r.renameSync(c,d()),u}function K(){return y().telemetry!==!1}function W(){let e=y().anonymousId;if(typeof e=="string"&&e.trim())return e;let t=`anon-cli-${D()}`;return v({anonymousId:t}),t}function X(e){v({telemetry:e})}function l(){return o.join(i(),"runtime-upgraded.json")}function Y(e){s();let t=`${l()}.tmp`;r.writeFileSync(t,`${JSON.stringify(e)}
|
|
4
4
|
`,"utf8"),r.renameSync(t,l())}function q(){try{let e=r.readFileSync(l(),"utf8");r.unlinkSync(l());let t=JSON.parse(e);return typeof t?.to!="string"||!t.to?null:{from:typeof t.from=="string"?t.from:null,to:t.to,at:typeof t.at=="number"?t.at:0}}catch{return null}}function s(){r.mkdirSync(i(),{recursive:!0}),r.mkdirSync(m(),{recursive:!0}),r.mkdirSync(g(),{recursive:!0}),r.mkdirSync(P(),{recursive:!0}),r.mkdirSync(w(),{recursive:!0})}function F(){try{let e=r.readFileSync(b(),"utf8").trim();return e.length>0?e:null}catch{return null}}function z(e){r.mkdirSync(m(),{recursive:!0}),r.writeFileSync(b(),`${e}
|