sootsim 0.1.268 → 0.1.270

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.
Files changed (155) hide show
  1. package/README.md +7 -3
  2. package/detox/index.ts +5 -2
  3. package/dist-cli/bin.js +4 -4
  4. package/dist-cli/chunks/{agent-KQSZFG6R.js → agent-4YXUPSJ2.js} +2 -2
  5. package/dist-cli/chunks/{agent-wrapper-DLDQVS7O.js → agent-wrapper-BMJPWHWK.js} +2 -2
  6. package/dist-cli/chunks/{app-fonts-6XVNNHAB.js → app-fonts-EDRH6ETC.js} +2 -2
  7. package/dist-cli/chunks/{assert-DLGUW4JS.js → assert-CRDV324D.js} +2 -2
  8. package/dist-cli/chunks/{auth-MTSJWWMS.js → auth-WYRQIJEN.js} +2 -2
  9. package/dist-cli/chunks/beta-NBANSL2S.js +2 -0
  10. package/dist-cli/chunks/{camera-MGJUBHWZ.js → camera-5TO6IVBP.js} +3 -3
  11. package/dist-cli/chunks/{chunk-LJGOZ77E.js → chunk-2J3E5TPS.js} +1 -1
  12. package/dist-cli/chunks/{chunk-GUXMUE5A.js → chunk-3VIMSXQZ.js} +2 -2
  13. package/dist-cli/chunks/{chunk-YUDUKMJV.js → chunk-3ZOF2BTJ.js} +1 -1
  14. package/dist-cli/chunks/{chunk-RCU4A7LU.js → chunk-44ISBOEK.js} +3 -3
  15. package/dist-cli/chunks/{chunk-F7DMZRQX.js → chunk-4HPWZVBS.js} +1 -1
  16. package/dist-cli/chunks/{chunk-K5ZMEBMQ.js → chunk-557IYHPC.js} +1 -1
  17. package/dist-cli/chunks/{chunk-RG6QF6DY.js → chunk-5IHDZOMR.js} +1 -1
  18. package/dist-cli/chunks/{chunk-XIBSRCKK.js → chunk-6CI73D3X.js} +2 -2
  19. package/dist-cli/chunks/chunk-6JLIPPNB.js +2 -0
  20. package/dist-cli/chunks/{chunk-YMTVQA6W.js → chunk-74HIBIJQ.js} +4 -4
  21. package/dist-cli/chunks/{chunk-6TXGR4HK.js → chunk-ABSUFSOH.js} +2 -2
  22. package/dist-cli/chunks/{chunk-NPSDN7D7.js → chunk-AG563BSO.js} +2 -2
  23. package/dist-cli/chunks/{chunk-IWJTCFAE.js → chunk-AMA3YGJ5.js} +2 -2
  24. package/dist-cli/chunks/{chunk-EG3JCOGS.js → chunk-AMVYE3F4.js} +2 -2
  25. package/dist-cli/chunks/{chunk-LOOHTTDV.js → chunk-B5IBLYEO.js} +3 -3
  26. package/dist-cli/chunks/{chunk-M2LYCMW4.js → chunk-DCJXHSIA.js} +2 -2
  27. package/dist-cli/chunks/{chunk-ITQ7WKNC.js → chunk-ERXCR7NU.js} +2 -2
  28. package/dist-cli/chunks/{chunk-KR4LGQWN.js → chunk-FCMEOOQE.js} +2 -2
  29. package/dist-cli/chunks/{chunk-YNMYUJYR.js → chunk-FHPXOPMC.js} +2 -2
  30. package/dist-cli/chunks/{chunk-V27FSRID.js → chunk-FNBFRG64.js} +1 -1
  31. package/dist-cli/chunks/{chunk-5JH5F4TM.js → chunk-GAYG7AO4.js} +1 -1
  32. package/dist-cli/chunks/chunk-GQDQO3KU.js +5 -0
  33. package/dist-cli/chunks/{chunk-JERNRAFO.js → chunk-HWGKGIWE.js} +2 -2
  34. package/dist-cli/chunks/{chunk-YLMP3AEX.js → chunk-IIXRM6BB.js} +2 -2
  35. package/dist-cli/chunks/{chunk-EPKHW3XW.js → chunk-LHMVSKKD.js} +3 -3
  36. package/dist-cli/chunks/chunk-M32JVXHU.js +5 -0
  37. package/dist-cli/chunks/{chunk-FGKDYXO3.js → chunk-M5VURHXD.js} +1 -1
  38. package/dist-cli/chunks/{chunk-6YB3URLB.js → chunk-MD24VVKT.js} +2 -2
  39. package/dist-cli/chunks/{chunk-CWC7QMVM.js → chunk-MYBY7OHL.js} +1 -1
  40. package/dist-cli/chunks/{chunk-7XWLSCXZ.js → chunk-NTO6SKS5.js} +1 -1
  41. package/dist-cli/chunks/{chunk-H2WCONSC.js → chunk-OUKH6UGN.js} +1 -1
  42. package/dist-cli/chunks/{chunk-OOVGROTR.js → chunk-PDFKRVDC.js} +1 -1
  43. package/dist-cli/chunks/{chunk-74QJWGDX.js → chunk-SDKIUJUO.js} +2 -2
  44. package/dist-cli/chunks/chunk-SLR3HWMB.js +13 -0
  45. package/dist-cli/chunks/{chunk-WUOPQL2J.js → chunk-SW5HZ5LK.js} +1 -1
  46. package/dist-cli/chunks/{chunk-WT3OYHU7.js → chunk-TIONGRTA.js} +3 -3
  47. package/dist-cli/chunks/{chunk-EH3A54PO.js → chunk-TLNGREAA.js} +2 -2
  48. package/dist-cli/chunks/{chunk-5MIRQ65V.js → chunk-TMWNOQAA.js} +1 -1
  49. package/dist-cli/chunks/{chunk-3MZJ2KVR.js → chunk-TZH4VH32.js} +3 -3
  50. package/dist-cli/chunks/{chunk-FGY5ESGU.js → chunk-UPRCATUH.js} +2 -2
  51. package/dist-cli/chunks/chunk-XTTXSDDA.js +1 -0
  52. package/dist-cli/chunks/{chunk-ZTOWO5CK.js → chunk-YKK2QUGO.js} +1 -1
  53. package/dist-cli/chunks/{chunk-SV6D5FXN.js → chunk-ZTKDHPA6.js} +2 -2
  54. package/dist-cli/chunks/chunk-ZZH2AFPJ.js +1 -0
  55. package/dist-cli/chunks/cli-version-BLKUTVJ2.js +2 -0
  56. package/dist-cli/chunks/{compat-IVBKZVGH.js → compat-IZEDAAUW.js} +3 -3
  57. package/dist-cli/chunks/{config-PQ3KBTIM.js → config-I4CXZ6M7.js} +2 -2
  58. package/dist-cli/chunks/{control-BKTYM5XP.js → control-DVF7UL5D.js} +2 -2
  59. package/dist-cli/chunks/daemon-FPKQPSSY.js +2 -0
  60. package/dist-cli/chunks/{debug-HRR2LK2J.js → debug-5X2F2WRP.js} +3 -3
  61. package/dist-cli/chunks/{desktop-466O4AQA.js → desktop-JHEYQZGF.js} +3 -3
  62. package/dist-cli/chunks/{detox-UH44KHQJ.js → detox-W64UENQG.js} +2 -2
  63. package/dist-cli/chunks/{device-FZLXTC3W.js → device-ZBSW2EHS.js} +2 -2
  64. package/dist-cli/chunks/{diagnose-RJMRI27P.js → diagnose-WER4X3P5.js} +2 -2
  65. package/dist-cli/chunks/drivers-6P53DLMM.js +2 -0
  66. package/dist-cli/chunks/{film-VL66UAM3.js → film-TIXNUTR6.js} +3 -3
  67. package/dist-cli/chunks/flow-53XFDYLL.js +2 -0
  68. package/dist-cli/chunks/help-MPYJLD7I.js +2 -0
  69. package/dist-cli/chunks/{hidden-runtime-alias-3ZAR7GCH.js → hidden-runtime-alias-R3JH3INM.js} +2 -2
  70. package/dist-cli/chunks/{home-paths-S2GRJWV3.js → home-paths-CNNARPCT.js} +2 -2
  71. package/dist-cli/chunks/inspect-JBDDYUA5.js +2 -0
  72. package/dist-cli/chunks/install-desktop-BBP7AMK4.js +2 -0
  73. package/dist-cli/chunks/{login-TR3YAEA2.js → login-6NCCZ3CZ.js} +4 -4
  74. package/dist-cli/chunks/{logout-WPY2DOYZ.js → logout-C4VKXUH4.js} +2 -2
  75. package/dist-cli/chunks/{maestro-DSG7V2BA.js → maestro-ZRGFQ3MV.js} +3 -3
  76. package/dist-cli/chunks/{maestro-generate-6KA7PCN5.js → maestro-generate-A5XZS5GC.js} +3 -3
  77. package/dist-cli/chunks/{mode-QUYGPNBW.js → mode-IFFZ55HM.js} +2 -2
  78. package/dist-cli/chunks/optional-demo-registry-TQZA65K3.js +2 -0
  79. package/dist-cli/chunks/{perf-ELBRUVVU.js → perf-44KZNTIV.js} +2 -2
  80. package/dist-cli/chunks/{record-6PDTULUN.js → record-GZLZNXYZ.js} +3 -3
  81. package/dist-cli/chunks/runtime-F4FCEPPB.js +2 -0
  82. package/dist-cli/chunks/{screenshot-command-E2A4VY6D.js → screenshot-command-GL3STSWK.js} +3 -3
  83. package/dist-cli/chunks/{screenshots-capture-TRCRHK2E.js → screenshots-capture-QSSBWHN6.js} +2 -2
  84. package/dist-cli/chunks/serve-AFK6X2Q3.js +42 -0
  85. package/dist-cli/chunks/{setup-5BHQNK2L.js → setup-DYSDNEUE.js} +3 -3
  86. package/dist-cli/chunks/{skills-NQLI6WXW.js → skills-YXWQ43PZ.js} +2 -2
  87. package/dist-cli/chunks/{storage-SKARYTYK.js → storage-C7IS5GTM.js} +2 -2
  88. package/dist-cli/chunks/store-LVF2C2XZ.js +2 -0
  89. package/dist-cli/chunks/telemetry-5V3OXY6C.js +2 -0
  90. package/dist-cli/chunks/{timeline-DYJ4GKGE.js → timeline-FDTIHQ5V.js} +2 -2
  91. package/dist-cli/chunks/{upgrade-PHUUE5QV.js → upgrade-VRQCFJEI.js} +2 -2
  92. package/dist-cli/chunks/upload-CRCPDN6G.js +2 -0
  93. package/dist-cli/chunks/{version-XQQSXS3E.js → version-MP6NKJ27.js} +2 -2
  94. package/dist-cli/chunks/web-XYPFJHKW.js +2 -0
  95. package/dist-cli/chunks/{what-happened-I2N3FFIV.js → what-happened-IM6UH24Q.js} +2 -2
  96. package/dist-lib/agent-daemon-client.cjs +1 -1
  97. package/dist-lib/agent-events.cjs +1 -1
  98. package/dist-lib/agent-identity.cjs +10 -10
  99. package/dist-lib/agent-sessions.cjs +29 -13
  100. package/dist-lib/attached-projects.cjs +33 -13
  101. package/dist-lib/auth/shared-session.cjs +1 -1
  102. package/dist-lib/backend-origin.cjs +1 -1
  103. package/dist-lib/beta.cjs +1 -1
  104. package/dist-lib/beta.mjs +1 -1
  105. package/dist-lib/bridge-constants.cjs +23 -6
  106. package/dist-lib/cli-constants.cjs +1 -1
  107. package/dist-lib/config.cjs +1 -1
  108. package/dist-lib/detox/index.cjs +6 -4
  109. package/dist-lib/dev-bundle-resolution.cjs +1 -1
  110. package/dist-lib/home-paths.cjs +1 -1
  111. package/dist-lib/host/bridge-host.cjs +110 -54
  112. package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
  113. package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
  114. package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
  115. package/dist-lib/host/websocket-proxy.cjs +1 -1
  116. package/dist-lib/index.cjs +1 -1
  117. package/dist-lib/jump-to-source-babel.cjs +1 -1
  118. package/dist-lib/menu.cjs +1 -1
  119. package/dist-lib/menu.mjs +1 -1
  120. package/dist-lib/metro.cjs +1 -1
  121. package/dist-lib/profiles.cjs +1 -1
  122. package/dist-lib/render-mode.cjs +1 -1
  123. package/dist-lib/scripts/dev-server-scanner.cjs +1 -1
  124. package/dist-lib/sdk.cjs +1 -1
  125. package/dist-lib/sdk.mjs +1 -1
  126. package/dist-lib/skills.cjs +220 -148
  127. package/dist-lib/vite.cjs +1 -1
  128. package/package.json +1 -1
  129. package/src/agent-daemon-client.ts +2 -2
  130. package/src/agent-identity.ts +7 -5
  131. package/src/attached-projects.ts +35 -11
  132. package/src/bridge-constants.ts +23 -4
  133. package/src/host/agent-host.ts +63 -14
  134. package/src/{agentbus-prompt.ts → team-machine-prompt.ts} +13 -20
  135. package/dist-cli/chunks/beta-7R4DRB3R.js +0 -2
  136. package/dist-cli/chunks/chunk-2LWDKYJ3.js +0 -1
  137. package/dist-cli/chunks/chunk-346C7547.js +0 -2
  138. package/dist-cli/chunks/chunk-CD2GF6PV.js +0 -5
  139. package/dist-cli/chunks/chunk-PN2LR6T4.js +0 -5
  140. package/dist-cli/chunks/chunk-Y3IYHVEX.js +0 -13
  141. package/dist-cli/chunks/chunk-ZHSXFJ7W.js +0 -1
  142. package/dist-cli/chunks/cli-version-362THKXA.js +0 -2
  143. package/dist-cli/chunks/daemon-SCTA3HTZ.js +0 -2
  144. package/dist-cli/chunks/drivers-S7D5OZQN.js +0 -2
  145. package/dist-cli/chunks/flow-IM5OXO5S.js +0 -2
  146. package/dist-cli/chunks/help-G5CN3KXU.js +0 -2
  147. package/dist-cli/chunks/inspect-WI7GXOH5.js +0 -2
  148. package/dist-cli/chunks/install-desktop-PVBWQQHY.js +0 -2
  149. package/dist-cli/chunks/optional-demo-registry-CROVHXTW.js +0 -2
  150. package/dist-cli/chunks/runtime-ITR3EUXS.js +0 -2
  151. package/dist-cli/chunks/serve-JLLSEZDN.js +0 -41
  152. package/dist-cli/chunks/store-VR5QRAYX.js +0 -2
  153. package/dist-cli/chunks/telemetry-PMYZDJGO.js +0 -2
  154. package/dist-cli/chunks/upload-OUKKXVNC.js +0 -2
  155. package/dist-cli/chunks/web-AZI3JODI.js +0 -2
@@ -1,4 +1,4 @@
1
- /*! sootsim v0.1.268 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.270 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -1038,7 +1038,7 @@ var init_registry = __esm({
1038
1038
  {
1039
1039
  range: ">=55.0.0",
1040
1040
  coverage: 0.9,
1041
- note: "SymbolView renders the symbol name as text when SF Symbols / Material Symbols fonts are not loaded \u2014 visible glyph requires the real Apple font (license-restricted, can't bundle) or Google Material Symbols font registered via FontFace API. unstable_getMaterialSymbolSourceAsync returns a stable URI/size shape so apps that gate on the source resolve correctly.",
1041
+ note: "SymbolView renders the shared SootSim SF Symbol vector and preserves the requested system name for frozen Design replay. Unknown names use the supplied fallback. unstable_getMaterialSymbolSourceAsync returns a stable URI/size shape so apps that gate on the source resolve correctly.",
1042
1042
  working: "SymbolView, name object/string selection (string | { ios, android, web }), size/tintColor styling, fallback rendering, unstable_getMaterialSymbolSourceAsync",
1043
1043
  missing: "bundled SF Symbols font (Apple license), bundled Material Symbols font (size budget), animation/effect modifiers (.bounce, .scale)"
1044
1044
  }
@@ -1233,7 +1233,7 @@ var init_registry = __esm({
1233
1233
  {
1234
1234
  range: ">=13.0.0",
1235
1235
  coverage: 0.94,
1236
- note: "real SQLite via lazy-loaded bedrock-sqlite (~1MB WASM) \u2014 full SQL support including joins, transactions, prepared statements, RETURNING. WASM ships in the runtime tarball, fetched on first openDatabase call. memfs persists to IDB via Module._memfs (requires the bedrock-sqlite build with the memfs-on-module export from orez/sqlite-wasm); reloads restore the prior state \u2014 verified end-to-end via the orbstack/published-runtime probe across 3 page reloads. sync-only methods (execSync/runSync) throw until backend finishes loading; await openDatabaseAsync or whenSqliteReady() first.",
1236
+ note: "real SQLite via lazy-loaded bedrock-sqlite (~1MB WASM) \u2014 full SQL support including joins, transactions, prepared statements, RETURNING. WASM ships in the runtime tarball and loads with the expo-sqlite compatibility chunk, so synchronous APIs are ready as soon as the module import resolves. memfs persists to IDB via Module._memfs (requires the bedrock-sqlite build with the memfs-on-module export from orez/sqlite-wasm); reloads restore the prior state \u2014 verified end-to-end via the orbstack/published-runtime probe across 3 page reloads.",
1237
1237
  working: "openDatabaseAsync / openDatabaseSync (real bedrock instance), execAsync / execSync, prepareAsync / prepareSync, runAsync / runSync, getFirstAsync / getFirstSync, getAllAsync / getAllSync, getEachAsync / getEachSync, withTransactionAsync / withTransactionSync, withExclusiveTransactionAsync, isInTransactionAsync / isInTransactionSync, closeAsync / closeSync, deleteDatabaseAsync / deleteDatabaseSync, SQLiteStatement.executeAsync / executeSync / executeForRawResultAsync / executeForRawResultSync / getColumnNames* / finalize*, SQLiteProvider, useSQLiteContext, defaultDatabaseDirectory, async iteration via for-await-of, RETURNING clauses",
1238
1238
  missing: "serializeAsync (bedrock does not expose sqlite3_serialize through its module surface), backupDatabaseAsync, addDatabaseChangeListener (no sqlite3_update_hook bindings), createSessionAsync, loadExtensionAsync, SQLiteTaggedQuery (Bun-style template literal API)"
1239
1239
  }
@@ -3854,7 +3854,7 @@ var init_registry = __esm({
3854
3854
  {
3855
3855
  range: ">=1.21.0",
3856
3856
  coverage: 0.72,
3857
- note: "native-seam only for toolbar/menu host views. the real @vxrn/native StackToolbar and MenuAction React code runs from the bundle and converts its public composition API into native host props and native-stack header items.",
3857
+ note: "native-seam only for toolbar/menu host views. One's public Stack.Toolbar components use the real @vxrn/native implementation, whose React code runs from the bundle and converts the composition API into native host props and native-stack header items.",
3858
3858
  working: "StackToolbar header and bottom placements, Button, Label, Icon with SF Symbols/image sources, Badge, fixed/fluid Spacer, View children, nested Menu/MenuAction trees, disabled/selected/destructive actions, visible action callbacks, and native-stack header bar item integration",
3859
3859
  missing: "Color and zoom-transition native hosts, SplitView gamma host, bottom SearchBarSlot integration with a configured native search controller, exact UIKit shared-background grouping"
3860
3860
  }
@@ -10326,7 +10326,8 @@ __export(bridge_constants_exports, {
10326
10326
  resolveSootsimBridgePort: () => resolveSootsimBridgePort,
10327
10327
  resolveSootsimBridgePortForHttpPort: () => resolveSootsimBridgePortForHttpPort,
10328
10328
  resolveSootsimBridgePortForRuntimeLocation: () => resolveSootsimBridgePortForRuntimeLocation,
10329
- resolveSootsimBridgeWebSocketUrl: () => resolveSootsimBridgeWebSocketUrl
10329
+ resolveSootsimBridgeWebSocketUrl: () => resolveSootsimBridgeWebSocketUrl,
10330
+ resolveSootsimWebSocketProxyUrl: () => resolveSootsimWebSocketProxyUrl
10330
10331
  });
10331
10332
  function parsePort(value) {
10332
10333
  if (typeof value === "number") {
@@ -10393,16 +10394,31 @@ function resolveSootsimBridgePortForRuntimeLocation(input = {}) {
10393
10394
  if (baseHttpPort === null) return DEFAULT_SOOTSIM_BRIDGE_PORT;
10394
10395
  return resolveSootsimBridgePortForHttpPort({ httpPort, baseHttpPort });
10395
10396
  }
10396
- function resolveSootsimBridgeWebSocketUrl(input) {
10397
+ function resolveSootsimWebSocketProxyUrl(input) {
10397
10398
  const pageUrl = parseHrefUrl(input.href);
10398
10399
  if (!pageUrl || pageUrl.protocol !== "http:" && pageUrl.protocol !== "https:") {
10399
- throw new Error(`invalid SootSim browser bridge page URL: ${input.href}`);
10400
+ throw new Error(`invalid SootSim websocket proxy page URL: ${input.href}`);
10401
+ }
10402
+ let targetUrl;
10403
+ try {
10404
+ targetUrl = new URL(input.targetUrl);
10405
+ } catch {
10406
+ throw new Error(`invalid SootSim websocket proxy target URL: ${input.targetUrl}`);
10407
+ }
10408
+ if (targetUrl.protocol !== "ws:" && targetUrl.protocol !== "wss:") {
10409
+ throw new Error(`invalid SootSim websocket proxy target URL: ${input.targetUrl}`);
10400
10410
  }
10401
10411
  const proxyUrl = new URL("/__websocket-proxy", pageUrl);
10402
10412
  proxyUrl.protocol = pageUrl.protocol === "https:" ? "wss:" : "ws:";
10403
- proxyUrl.searchParams.set("url", `ws://localhost:${input.bridgePort}`);
10413
+ proxyUrl.searchParams.set("url", input.targetUrl);
10404
10414
  return proxyUrl.href;
10405
10415
  }
10416
+ function resolveSootsimBridgeWebSocketUrl(input) {
10417
+ return resolveSootsimWebSocketProxyUrl({
10418
+ targetUrl: `ws://localhost:${input.bridgePort}`,
10419
+ href: input.href
10420
+ });
10421
+ }
10406
10422
  var DEFAULT_SOOTSIM_BRIDGE_PORT, CONTRAST_DEV_HTTP_BASE_PORT, SOOTSIM_SITE_DEV_HTTP_BASE_PORT, SOOTSIM_SHELL_DEV_HTTP_BASE_PORT, LOCAL_DEV_HTTP_BASE_PORTS, MAX_LOCAL_DEV_PORT_OFFSET, SOOTSIM_BRIDGE_SIM_CLOSE_CODE, SOOTSIM_BRIDGE_SIM_CLOSE_REASON;
10407
10423
  var init_bridge_constants = __esm({
10408
10424
  "src/bridge-constants.ts"() {
@@ -10541,10 +10557,10 @@ function tcpPing(port, timeout = TCP_GATE_MS) {
10541
10557
  sock.connect(port, "localhost");
10542
10558
  });
10543
10559
  }
10544
- function httpGet(port, path12, method = "GET", timeout = TIMEOUT_MS, headers = {}) {
10560
+ function httpGet(port, path11, method = "GET", timeout = TIMEOUT_MS, headers = {}) {
10545
10561
  return new Promise((resolve5) => {
10546
10562
  const req = import_http.default.request(
10547
- { hostname: "localhost", port, path: path12, method, timeout, headers },
10563
+ { hostname: "localhost", port, path: path11, method, timeout, headers },
10548
10564
  (res) => {
10549
10565
  let body = "";
10550
10566
  res.on("data", (c) => body += c.toString());
@@ -11885,21 +11901,37 @@ function listSessions(projectId) {
11885
11901
  const all = loadStore().agentSessions;
11886
11902
  return projectId ? all.filter((s) => s.projectId === projectId) : all;
11887
11903
  }
11888
- function updateSessionStatus(id, patch) {
11904
+ function applySessionStatusPatch(existing, patch, now = Date.now()) {
11905
+ return {
11906
+ ...existing,
11907
+ ...patch,
11908
+ id: existing.id,
11909
+ projectId: existing.projectId,
11910
+ createdAt: existing.createdAt,
11911
+ lastSeenAt: now
11912
+ };
11913
+ }
11914
+ function updateSessionStatuses(updates) {
11915
+ if (updates.length === 0) return;
11889
11916
  mutateStore((store) => {
11890
- const existing = store.agentSessions.find((s) => s.id === id);
11891
- if (!existing) return;
11892
- const idx = store.agentSessions.indexOf(existing);
11893
- store.agentSessions[idx] = {
11894
- ...existing,
11895
- ...patch,
11896
- id: existing.id,
11897
- projectId: existing.projectId,
11898
- createdAt: existing.createdAt,
11899
- lastSeenAt: Date.now()
11900
- };
11917
+ const now = Date.now();
11918
+ const indexById = new Map(
11919
+ store.agentSessions.map((session, index) => [session.id, index])
11920
+ );
11921
+ for (const { id, patch } of updates) {
11922
+ const idx = indexById.get(id);
11923
+ if (idx === void 0) continue;
11924
+ store.agentSessions[idx] = applySessionStatusPatch(
11925
+ store.agentSessions[idx],
11926
+ patch,
11927
+ now
11928
+ );
11929
+ }
11901
11930
  });
11902
11931
  }
11932
+ function updateSessionStatus(id, patch) {
11933
+ updateSessionStatuses([{ id, patch }]);
11934
+ }
11903
11935
  async function seedFromDemoAppRegistry() {
11904
11936
  const existing = loadStore().attachedProjects;
11905
11937
  if (existing.length > 0) return;
@@ -12382,46 +12414,42 @@ var init_agent_sessions = __esm({
12382
12414
  });
12383
12415
 
12384
12416
  // src/agent-identity.ts
12385
- function agentbusSessionIdFromCliIdentity(identity) {
12417
+ function teamMachineSessionIdFromCliIdentity(identity) {
12386
12418
  if (!identity?.startsWith("AGENTBUS_SESSION:")) return null;
12387
12419
  const sessionId = identity.slice("AGENTBUS_SESSION:".length).trim();
12388
- if (!AGENTBUS_SESSION_RE.test(sessionId)) return null;
12420
+ if (!TEAM_MACHINE_SESSION_RE.test(sessionId)) return null;
12389
12421
  return sessionId;
12390
12422
  }
12391
- function isValidAgentbusSessionId(sessionId) {
12392
- return AGENTBUS_SESSION_RE.test(sessionId);
12423
+ function isValidTeamMachineSessionId(sessionId) {
12424
+ return TEAM_MACHINE_SESSION_RE.test(sessionId);
12393
12425
  }
12394
- var AGENTBUS_SESSION_RE;
12426
+ var TEAM_MACHINE_SESSION_RE;
12395
12427
  var init_agent_identity = __esm({
12396
12428
  "src/agent-identity.ts"() {
12397
12429
  "use strict";
12398
- AGENTBUS_SESSION_RE = /^[A-Za-z0-9._:-]{1,160}$/;
12430
+ TEAM_MACHINE_SESSION_RE = /^[A-Za-z0-9._:-]{1,160}$/;
12399
12431
  }
12400
12432
  });
12401
12433
 
12402
- // src/agentbus-prompt.ts
12403
- function formatAgentbusPromptText(prompt) {
12434
+ // src/team-machine-prompt.ts
12435
+ function formatTeamMachinePromptText(prompt) {
12404
12436
  return typeof prompt.text === "string" ? prompt.text.trim() : "";
12405
12437
  }
12406
- function resolveAgentbusCommand(explicit) {
12438
+ function resolveTeamMachineCommand(explicit) {
12407
12439
  const fromArg = explicit?.trim();
12408
12440
  if (fromArg) return fromArg;
12409
- const fromEnv = process.env.AGENTBUS_COMMAND?.trim();
12410
- if (fromEnv) return fromEnv;
12411
- const localBin = import_node_path6.default.join(import_node_os2.default.homedir(), ".local", "bin", "agentbus");
12412
- if (import_node_fs7.default.existsSync(localBin)) return localBin;
12413
- return "agentbus";
12441
+ return "tm";
12414
12442
  }
12415
- async function sendPromptToAgentbusSession(input) {
12443
+ async function sendPromptToTeamMachineSession(input) {
12416
12444
  const sessionId = input.sessionId.trim();
12417
- if (!isValidAgentbusSessionId(sessionId)) {
12418
- throw new Error(`invalid agentbus session id: ${sessionId || "<empty>"}`);
12445
+ if (!isValidTeamMachineSessionId(sessionId)) {
12446
+ throw new Error(`invalid Team Machine session id: ${sessionId || "<empty>"}`);
12419
12447
  }
12420
- const text = formatAgentbusPromptText(input.prompt);
12448
+ const text = formatTeamMachinePromptText(input.prompt);
12421
12449
  if (!text) {
12422
12450
  throw new Error("prompt text is empty");
12423
12451
  }
12424
- const command = resolveAgentbusCommand(input.command);
12452
+ const command = resolveTeamMachineCommand(input.command);
12425
12453
  const timeoutMs = input.timeoutMs ?? 15e3;
12426
12454
  await new Promise((resolve5, reject) => {
12427
12455
  const child = (0, import_node_child_process4.spawn)(command, ["send", sessionId, text], {
@@ -12434,7 +12462,7 @@ async function sendPromptToAgentbusSession(input) {
12434
12462
  child.kill("SIGTERM");
12435
12463
  } catch {
12436
12464
  }
12437
- reject(new Error(`agentbus send timed out after ${Math.round(timeoutMs / 1e3)}s`));
12465
+ reject(new Error(`tm send timed out after ${Math.round(timeoutMs / 1e3)}s`));
12438
12466
  }, timeoutMs);
12439
12467
  child.stderr?.setEncoding("utf8");
12440
12468
  child.stderr?.on("data", (chunk) => {
@@ -12453,20 +12481,17 @@ async function sendPromptToAgentbusSession(input) {
12453
12481
  const detail = stderr.trim();
12454
12482
  reject(
12455
12483
  new Error(
12456
- detail || `agentbus send exited with ${signal ? `signal ${signal}` : `code ${code ?? "unknown"}`}`
12484
+ detail || `tm send exited with ${signal ? `signal ${signal}` : `code ${code ?? "unknown"}`}`
12457
12485
  )
12458
12486
  );
12459
12487
  });
12460
12488
  });
12461
12489
  }
12462
- var import_node_child_process4, import_node_fs7, import_node_os2, import_node_path6;
12463
- var init_agentbus_prompt = __esm({
12464
- "src/agentbus-prompt.ts"() {
12490
+ var import_node_child_process4;
12491
+ var init_team_machine_prompt = __esm({
12492
+ "src/team-machine-prompt.ts"() {
12465
12493
  "use strict";
12466
12494
  import_node_child_process4 = require("node:child_process");
12467
- import_node_fs7 = __toESM(require("node:fs"), 1);
12468
- import_node_os2 = __toESM(require("node:os"), 1);
12469
- import_node_path6 = __toESM(require("node:path"), 1);
12470
12495
  init_agent_identity();
12471
12496
  init_agent_identity();
12472
12497
  }
@@ -12485,17 +12510,18 @@ function mapFrameworkToProjectFramework(fw) {
12485
12510
  if (fw === "one" || fw === "vxrn") return "one";
12486
12511
  return "unknown";
12487
12512
  }
12488
- var import_node_fs8, import_node_path7, WS_OPEN, AgentHost;
12513
+ var import_node_fs7, import_node_path6, WS_OPEN, SESSION_STATUS_PERSIST_DELAY_MS, AgentHost;
12489
12514
  var init_agent_host = __esm({
12490
12515
  "src/host/agent-host.ts"() {
12491
12516
  "use strict";
12492
- import_node_fs8 = __toESM(require("node:fs"), 1);
12493
- import_node_path7 = __toESM(require("node:path"), 1);
12517
+ import_node_fs7 = __toESM(require("node:fs"), 1);
12518
+ import_node_path6 = __toESM(require("node:path"), 1);
12494
12519
  init_dev_server_scanner();
12495
12520
  init_agent_sessions();
12496
- init_agentbus_prompt();
12497
12521
  init_attached_projects();
12522
+ init_team_machine_prompt();
12498
12523
  WS_OPEN = 1;
12524
+ SESSION_STATUS_PERSIST_DELAY_MS = 25;
12499
12525
  AgentHost = class {
12500
12526
  // live fan-out, keyed by sessionId. refcount tracks how many sockets have
12501
12527
  // subscribed; the FIFO reader stays open as long as refcount > 0.
@@ -12517,6 +12543,12 @@ var init_agent_host = __esm({
12517
12543
  // in-memory count so session status stays `working` until that backlog
12518
12544
  // truly drains.
12519
12545
  pendingTurns = /* @__PURE__ */ new Map();
12546
+ // status fan-out is realtime state. keep the current value in memory and
12547
+ // batch its durable store write so an fsync cannot delay the websocket event
12548
+ // it describes. close() flushes the final batch synchronously.
12549
+ pendingSessionStates = /* @__PURE__ */ new Map();
12550
+ pendingSessionPatches = /* @__PURE__ */ new Map();
12551
+ sessionStatusPersistTimer = null;
12520
12552
  opts;
12521
12553
  constructor(opts = {}) {
12522
12554
  this.opts = opts;
@@ -12567,6 +12599,11 @@ var init_agent_host = __esm({
12567
12599
  /** terminate every subscription and drop every socket reference. called
12568
12600
  * by the bridge host during shutdown. */
12569
12601
  close() {
12602
+ if (this.sessionStatusPersistTimer) {
12603
+ clearTimeout(this.sessionStatusPersistTimer);
12604
+ this.sessionStatusPersistTimer = null;
12605
+ }
12606
+ this.flushSessionStatuses();
12570
12607
  for (const sub of this.subscriptions.values()) {
12571
12608
  try {
12572
12609
  sub.unsubscribe();
@@ -12635,18 +12672,18 @@ var init_agent_host = __esm({
12635
12672
  if (!lease || lease.kind !== "cli" || lease.expiresAt <= Date.now()) {
12636
12673
  throw new AgentSessionError("NO_CLAIM", `sim ${simId} has no active CLI claim`);
12637
12674
  }
12638
- const sessionId = agentbusSessionIdFromCliIdentity(lease.cliIdentityKey);
12675
+ const sessionId = teamMachineSessionIdFromCliIdentity(lease.cliIdentityKey);
12639
12676
  if (!sessionId) {
12640
12677
  throw new AgentSessionError(
12641
12678
  "UNSUPPORTED_CLAIM",
12642
12679
  `sim ${simId} is claimed by a CLI identity that is not promptable`
12643
12680
  );
12644
12681
  }
12645
- await sendPromptToAgentbusSession({
12682
+ await sendPromptToTeamMachineSession({
12646
12683
  sessionId,
12647
12684
  prompt: this.normalizePromptEnvelope(msg)
12648
12685
  });
12649
- return { ok: true, routed: "agentbus", sessionId };
12686
+ return { ok: true, routed: "team-machine", sessionId };
12650
12687
  }
12651
12688
  async doStartSession(input) {
12652
12689
  const project = findProjectById(input.projectId);
@@ -12677,7 +12714,7 @@ var init_agent_host = __esm({
12677
12714
  );
12678
12715
  const project = upsertProject({
12679
12716
  cwd: match.cwd,
12680
- name: match.projectName ?? import_node_path7.default.basename(match.cwd),
12717
+ name: match.projectName ?? import_node_path6.default.basename(match.cwd),
12681
12718
  preferredProvider: input.provider ?? existing?.preferredProvider,
12682
12719
  sourceRoots: existing?.sourceRoots ?? [match.cwd],
12683
12720
  knownBundleUrls,
@@ -12688,18 +12725,18 @@ var init_agent_host = __esm({
12688
12725
  }
12689
12726
  getTranscript(sessionId) {
12690
12727
  const p = transcriptPath(sessionId);
12691
- if (!import_node_fs8.default.existsSync(p)) {
12728
+ if (!import_node_fs7.default.existsSync(p)) {
12692
12729
  return { error: "transcript not found", code: "NO_TRANSCRIPT" };
12693
12730
  }
12694
- return import_node_fs8.default.readFileSync(p, "utf8");
12731
+ return import_node_fs7.default.readFileSync(p, "utf8");
12695
12732
  }
12696
12733
  getPaths() {
12697
12734
  const dir = getUserDataDir();
12698
12735
  return {
12699
12736
  userDataDir: dir,
12700
- storeFile: import_node_path7.default.join(dir, "attached-projects.json"),
12701
- sessionsDir: import_node_path7.default.join(dir, "sessions"),
12702
- transcriptsDir: import_node_path7.default.join(dir, "transcripts")
12737
+ storeFile: import_node_path6.default.join(dir, "attached-projects.json"),
12738
+ sessionsDir: import_node_path6.default.join(dir, "sessions"),
12739
+ transcriptsDir: import_node_path6.default.join(dir, "transcripts")
12703
12740
  };
12704
12741
  }
12705
12742
  // --- subscription management ---
@@ -12879,10 +12916,45 @@ var init_agent_host = __esm({
12879
12916
  }
12880
12917
  }
12881
12918
  patchSession(sessionId, patch) {
12882
- updateSessionStatus(sessionId, patch);
12883
- const updated = findSessionById(sessionId);
12884
- if (updated) {
12885
- this.broadcastSessionStatus(updated);
12919
+ const existing = this.pendingSessionStates.get(sessionId) ?? findSessionById(sessionId);
12920
+ if (!existing) return;
12921
+ const updated = applySessionStatusPatch(existing, patch);
12922
+ this.pendingSessionStates.set(sessionId, updated);
12923
+ this.pendingSessionPatches.set(sessionId, {
12924
+ ...this.pendingSessionPatches.get(sessionId),
12925
+ ...patch
12926
+ });
12927
+ this.broadcastSessionStatus(updated);
12928
+ if (this.sessionStatusPersistTimer) return;
12929
+ this.sessionStatusPersistTimer = setTimeout(() => {
12930
+ this.sessionStatusPersistTimer = null;
12931
+ this.flushSessionStatuses();
12932
+ }, SESSION_STATUS_PERSIST_DELAY_MS);
12933
+ }
12934
+ flushSessionStatuses() {
12935
+ if (this.pendingSessionPatches.size === 0) return;
12936
+ const pendingStates = this.pendingSessionStates;
12937
+ const pendingPatches = this.pendingSessionPatches;
12938
+ this.pendingSessionStates = /* @__PURE__ */ new Map();
12939
+ this.pendingSessionPatches = /* @__PURE__ */ new Map();
12940
+ try {
12941
+ updateSessionStatuses([...pendingPatches].map(([id, patch]) => ({ id, patch })));
12942
+ } catch (error) {
12943
+ for (const [id, session] of pendingStates) {
12944
+ if (!this.pendingSessionStates.has(id)) {
12945
+ this.pendingSessionStates.set(id, session);
12946
+ }
12947
+ }
12948
+ for (const [id, patch] of pendingPatches) {
12949
+ this.pendingSessionPatches.set(id, {
12950
+ ...patch,
12951
+ ...this.pendingSessionPatches.get(id)
12952
+ });
12953
+ }
12954
+ process.stderr.write(
12955
+ `[sootsim-agent] session status persistence failed: ${error instanceof Error ? error.message : String(error)}
12956
+ `
12957
+ );
12886
12958
  }
12887
12959
  }
12888
12960
  coalescePromptEcho(sessionId, event) {
@@ -15766,7 +15838,7 @@ var init_current_sim = __esm({
15766
15838
  "SOOTSIM_CLI_IDENTITY",
15767
15839
  // explicit override — fastest path, skips all pid lookups
15768
15840
  "AGENTBUS_SESSION",
15769
- // agentbus session id; lets sootsim route prompt-bar followups back to this agent
15841
+ // Team Machine session id; routes prompt-bar followups back to this agent
15770
15842
  "CLAUDE_CODE_SESSION_ID",
15771
15843
  // claude code, if ever set
15772
15844
  "CODEX_THREAD_ID",
@@ -15790,7 +15862,7 @@ var init_current_sim = __esm({
15790
15862
  "VSCODE_INJECTION"
15791
15863
  // vscode integrated terminal
15792
15864
  ];
15793
- IMMORTAL_HOST_COMM_RE = /^(?:tmux|screen)|^(?:agentbus|tm)$/i;
15865
+ IMMORTAL_HOST_COMM_RE = /^(?:tmux|screen)|^tm$/i;
15794
15866
  }
15795
15867
  });
15796
15868
 
@@ -16199,11 +16271,11 @@ async function evalInBridge(bridge, code, opts = {}) {
16199
16271
  if (opts.acquireLock) payload.acquireLock = true;
16200
16272
  return bridge.send(payload);
16201
16273
  }
16202
- async function callInBridge(bridge, path12, ...args) {
16203
- return bridge.send({ type: "call", path: path12, args });
16274
+ async function callInBridge(bridge, path11, ...args) {
16275
+ return bridge.send({ type: "call", path: path11, args });
16204
16276
  }
16205
- async function callInBridgeWrite(bridge, path12, ...args) {
16206
- return bridge.send({ type: "call", path: path12, args, acquireLock: true });
16277
+ async function callInBridgeWrite(bridge, path11, ...args) {
16278
+ return bridge.send({ type: "call", path: path11, args, acquireLock: true });
16207
16279
  }
16208
16280
  var import_ws3, resolvedWorld, BridgeSimLockedError;
16209
16281
  var init_ws_bridge = __esm({
@@ -17431,14 +17503,14 @@ process.stdin.on('end', async () => {
17431
17503
  function getBaseDir() {
17432
17504
  const explicit = process.env[SESSION_FILE_ENV];
17433
17505
  if (explicit?.trim()) {
17434
- return (0, import_node_path8.dirname)((0, import_node_path8.resolve)(explicit));
17506
+ return (0, import_node_path7.dirname)((0, import_node_path7.resolve)(explicit));
17435
17507
  }
17436
17508
  return electronUserDataDir();
17437
17509
  }
17438
17510
  function getSharedDesktopAuthFilePath() {
17439
17511
  const explicit = process.env[SESSION_FILE_ENV];
17440
- if (explicit?.trim()) return (0, import_node_path8.resolve)(explicit);
17441
- return (0, import_node_path8.join)(getBaseDir(), "desktop-auth.json");
17512
+ if (explicit?.trim()) return (0, import_node_path7.resolve)(explicit);
17513
+ return (0, import_node_path7.join)(getBaseDir(), "desktop-auth.json");
17442
17514
  }
17443
17515
  function normalizeUser(input) {
17444
17516
  if (!input || typeof input !== "object") return null;
@@ -17484,26 +17556,26 @@ function normalizeSession(input) {
17484
17556
  }
17485
17557
  function readSharedDesktopAuthSession() {
17486
17558
  const filepath = getSharedDesktopAuthFilePath();
17487
- if (!(0, import_node_fs9.existsSync)(filepath)) return null;
17559
+ if (!(0, import_node_fs8.existsSync)(filepath)) return null;
17488
17560
  try {
17489
- const parsed = JSON.parse((0, import_node_fs9.readFileSync)(filepath, "utf8"));
17561
+ const parsed = JSON.parse((0, import_node_fs8.readFileSync)(filepath, "utf8"));
17490
17562
  const normalized = normalizeSession(parsed);
17491
17563
  if (!normalized) {
17492
- (0, import_node_fs9.rmSync)(filepath, { force: true });
17564
+ (0, import_node_fs8.rmSync)(filepath, { force: true });
17493
17565
  return null;
17494
17566
  }
17495
17567
  return normalized;
17496
17568
  } catch {
17497
- (0, import_node_fs9.rmSync)(filepath, { force: true });
17569
+ (0, import_node_fs8.rmSync)(filepath, { force: true });
17498
17570
  return null;
17499
17571
  }
17500
17572
  }
17501
- var import_node_fs9, import_node_path8, SESSION_VERSION, SESSION_FILE_ENV, DEFAULT_ORIGIN;
17573
+ var import_node_fs8, import_node_path7, SESSION_VERSION, SESSION_FILE_ENV, DEFAULT_ORIGIN;
17502
17574
  var init_shared_session = __esm({
17503
17575
  "src/auth/shared-session.ts"() {
17504
17576
  "use strict";
17505
- import_node_fs9 = require("node:fs");
17506
- import_node_path8 = require("node:path");
17577
+ import_node_fs8 = require("node:fs");
17578
+ import_node_path7 = require("node:path");
17507
17579
  init_home_paths();
17508
17580
  SESSION_VERSION = 1;
17509
17581
  SESSION_FILE_ENV = "SOOTSIM_SHARED_AUTH_FILE";
@@ -17779,16 +17851,16 @@ function resolveFlowScreenshotPath(screenshotDir, name) {
17779
17851
  }
17780
17852
  function resolveProjectRelativeFlowBase(flowDir) {
17781
17853
  if (!flowDir) return process.cwd();
17782
- return path10.basename(flowDir) === ".maestro" ? path10.dirname(flowDir) : flowDir;
17854
+ return path9.basename(flowDir) === ".maestro" ? path9.dirname(flowDir) : flowDir;
17783
17855
  }
17784
17856
  function resolveFlowScreenshotPathWithMode(screenshotDir, name, opts) {
17785
17857
  const normalizedName = name.endsWith(".png") ? name : `${name}.png`;
17786
- if (path10.isAbsolute(normalizedName)) return normalizedName;
17858
+ if (path9.isAbsolute(normalizedName)) return normalizedName;
17787
17859
  if (opts.mode === "flow" && /[\\/]/.test(normalizedName)) {
17788
17860
  const baseDir = normalizedName.startsWith("./") || normalizedName.startsWith("../") ? opts.flowDir ?? process.cwd() : resolveProjectRelativeFlowBase(opts.flowDir);
17789
- return path10.resolve(baseDir, normalizedName);
17861
+ return path9.resolve(baseDir, normalizedName);
17790
17862
  }
17791
- return path10.join(screenshotDir, normalizedName);
17863
+ return path9.join(screenshotDir, normalizedName);
17792
17864
  }
17793
17865
  function normalizeFlowScreenshotSpec(step) {
17794
17866
  if (typeof step === "string") {
@@ -17845,12 +17917,12 @@ function parseFlowSteps(content) {
17845
17917
  const parsed = import_yaml.default.parse(candidate);
17846
17918
  return Array.isArray(parsed) ? parsed : [];
17847
17919
  }
17848
- var fs10, path10, import_settings2, import_yaml, DEFAULT_TIMEOUT, FLOW_TIMEOUT_SCALE, scaledTimeout, SCREEN_W, SCREEN_H, SootSimBridgeFlowRunner;
17920
+ var fs9, path9, import_settings2, import_yaml, DEFAULT_TIMEOUT, FLOW_TIMEOUT_SCALE, scaledTimeout, SCREEN_W, SCREEN_H, SootSimBridgeFlowRunner;
17849
17921
  var init_bridge_flow_runner = __esm({
17850
17922
  "cli/bridge-flow-runner.ts"() {
17851
17923
  "use strict";
17852
- fs10 = __toESM(require("fs"), 1);
17853
- path10 = __toESM(require("path"), 1);
17924
+ fs9 = __toESM(require("fs"), 1);
17925
+ path9 = __toESM(require("path"), 1);
17854
17926
  import_settings2 = require("sootsim-engine/settings");
17855
17927
  import_yaml = __toESM(require("yaml"), 1);
17856
17928
  init_frame_compose();
@@ -18138,14 +18210,14 @@ var init_bridge_flow_runner = __esm({
18138
18210
  if (chunks.length === 0) {
18139
18211
  throw new Error("recording requested but no video buffer was produced");
18140
18212
  }
18141
- fs10.mkdirSync(this.opts.recordingOutputDir, { recursive: true });
18213
+ fs9.mkdirSync(this.opts.recordingOutputDir, { recursive: true });
18142
18214
  const videoMime = stopped.mime || this.opts.recordingFormat || "video/webm";
18143
18215
  const extension = videoMime.includes("mp4") ? "mp4" : "webm";
18144
- const outputPath = path10.join(
18216
+ const outputPath = path9.join(
18145
18217
  this.opts.recordingOutputDir,
18146
18218
  `sootsim-${Date.now()}.${extension}`
18147
18219
  );
18148
- fs10.writeFileSync(outputPath, Buffer.concat(chunks));
18220
+ fs9.writeFileSync(outputPath, Buffer.concat(chunks));
18149
18221
  return outputPath;
18150
18222
  }
18151
18223
  async waitForRecordingTail(opts) {
@@ -18654,7 +18726,7 @@ var init_bridge_flow_runner = __esm({
18654
18726
  flowDir: this.opts.flowDir
18655
18727
  }
18656
18728
  );
18657
- fs10.mkdirSync(path10.dirname(outputPath), { recursive: true });
18729
+ fs9.mkdirSync(path9.dirname(outputPath), { recursive: true });
18658
18730
  const layers = spec.layers ?? this.opts.screenshotLayers;
18659
18731
  const screenshotRequest = {
18660
18732
  type: "screenshot",
@@ -18670,11 +18742,11 @@ var init_bridge_flow_runner = __esm({
18670
18742
  throw new Error("could not read current device model for framed screenshot");
18671
18743
  }
18672
18744
  const framed = await composeFramedScreenshot(rawBuffer, model);
18673
- fs10.writeFileSync(outputPath, framed);
18745
+ fs9.writeFileSync(outputPath, framed);
18674
18746
  console.log(`[flow] screenshot: ${outputPath} (frame: ${model})`);
18675
18747
  return outputPath;
18676
18748
  }
18677
- fs10.writeFileSync(outputPath, rawBuffer);
18749
+ fs9.writeFileSync(outputPath, rawBuffer);
18678
18750
  console.log(`[flow] screenshot: ${outputPath}`);
18679
18751
  return outputPath;
18680
18752
  }
@@ -18690,22 +18762,22 @@ var init_bridge_flow_runner = __esm({
18690
18762
  return model;
18691
18763
  }
18692
18764
  async captureScreenshot(outputPath) {
18693
- fs10.mkdirSync(path10.dirname(outputPath), { recursive: true });
18765
+ fs9.mkdirSync(path9.dirname(outputPath), { recursive: true });
18694
18766
  const dataUrl = await this.bridge.send({
18695
18767
  type: "screenshot",
18696
18768
  simId: this.opts.simId
18697
18769
  });
18698
18770
  const base64 = dataUrl.replace(/^data:image\/png;base64,/, "");
18699
- fs10.writeFileSync(outputPath, Buffer.from(base64, "base64"));
18771
+ fs9.writeFileSync(outputPath, Buffer.from(base64, "base64"));
18700
18772
  }
18701
18773
  // writes a per-failure debug bundle: screenshot + structured describe
18702
18774
  // + a11y tree + console errors/warnings + failed network requests +
18703
18775
  // shell state, all under one directory so post-mortem is one grep away.
18704
18776
  async captureFailureBundle(outputDir, context) {
18705
- fs10.mkdirSync(outputDir, { recursive: true });
18777
+ fs9.mkdirSync(outputDir, { recursive: true });
18706
18778
  const write = (name, content) => {
18707
18779
  try {
18708
- fs10.writeFileSync(path10.join(outputDir, name), content);
18780
+ fs9.writeFileSync(path9.join(outputDir, name), content);
18709
18781
  } catch {
18710
18782
  }
18711
18783
  };
@@ -19247,8 +19319,8 @@ var init_bridge_flow_runner = __esm({
19247
19319
  runScript(target) {
19248
19320
  const spec = typeof target === "string" ? { file: target } : target;
19249
19321
  if (!spec.file) throw new Error("runScript requires a file");
19250
- const scriptPath = path10.resolve(this.opts.flowDir, spec.file);
19251
- const source = fs10.readFileSync(scriptPath, "utf8");
19322
+ const scriptPath = path9.resolve(this.opts.flowDir, spec.file);
19323
+ const source = fs9.readFileSync(scriptPath, "utf8");
19252
19324
  this.js.evaluate(source, { env: spec.env });
19253
19325
  console.log(`[flow] runScript: ${spec.file} done`);
19254
19326
  }
@@ -19542,10 +19614,10 @@ var init_bridge_flow_runner = __esm({
19542
19614
  for (const [k, v] of Object.entries(env)) this.js.putEnv(k, v);
19543
19615
  }
19544
19616
  if (file) {
19545
- const flowPath = path10.resolve(this.opts.flowDir, file);
19546
- const flowContent = fs10.readFileSync(flowPath, "utf8");
19617
+ const flowPath = path9.resolve(this.opts.flowDir, file);
19618
+ const flowContent = fs9.readFileSync(flowPath, "utf8");
19547
19619
  const previousDir = this.opts.flowDir;
19548
- this.opts.flowDir = path10.dirname(flowPath);
19620
+ this.opts.flowDir = path9.dirname(flowPath);
19549
19621
  try {
19550
19622
  await this.runFlow(parseFlowSteps(flowContent));
19551
19623
  } finally {
@@ -19700,8 +19772,8 @@ __export(registry_exports, {
19700
19772
  skillRegistry: () => skillRegistry
19701
19773
  });
19702
19774
  module.exports = __toCommonJS(registry_exports);
19703
- var fs11 = __toESM(require("fs"), 1);
19704
- var path11 = __toESM(require("path"), 1);
19775
+ var fs10 = __toESM(require("fs"), 1);
19776
+ var path10 = __toESM(require("path"), 1);
19705
19777
 
19706
19778
  // src/skills/builtin/a11y-review.ts
19707
19779
  init_reap_browser();
@@ -19720,8 +19792,8 @@ var skill = {
19720
19792
  },
19721
19793
  async execute(params, context) {
19722
19794
  const { chromium } = await import("playwright");
19723
- const path12 = await import("path");
19724
- const fs12 = await import("fs");
19795
+ const path11 = await import("path");
19796
+ const fs11 = await import("fs");
19725
19797
  const browser = await launchReapedChrome((options) => chromium.launch(options), {
19726
19798
  headless: true
19727
19799
  });
@@ -19776,9 +19848,9 @@ var skill = {
19776
19848
  warnings: issues.filter((i) => i.severity === "warning").length,
19777
19849
  tree: typeof tree === "string" ? tree : JSON.stringify(tree)
19778
19850
  };
19779
- const reportPath = path12.join(context.outputDir, "a11y-report.json");
19780
- fs12.mkdirSync(path12.dirname(reportPath), { recursive: true });
19781
- fs12.writeFileSync(reportPath, JSON.stringify(report, null, 2));
19851
+ const reportPath = path11.join(context.outputDir, "a11y-report.json");
19852
+ fs11.mkdirSync(path11.dirname(reportPath), { recursive: true });
19853
+ fs11.writeFileSync(reportPath, JSON.stringify(report, null, 2));
19782
19854
  return {
19783
19855
  success: issues.filter((i) => i.severity === "error").length === 0,
19784
19856
  message: `${report.errors} errors, ${report.warnings} warnings across ${report.nodeCount} nodes`,
@@ -19816,8 +19888,8 @@ var skill2 = {
19816
19888
  }
19817
19889
  },
19818
19890
  async execute(params, context) {
19819
- const fs12 = await import("fs");
19820
- const path12 = await import("path");
19891
+ const fs11 = await import("fs");
19892
+ const path11 = await import("path");
19821
19893
  const { POLYFILL_REGISTRY: POLYFILL_REGISTRY2 } = await Promise.resolve().then(() => (init_web(), web_exports));
19822
19894
  if (params.packageName) {
19823
19895
  const entry = POLYFILL_REGISTRY2[params.packageName];
@@ -19835,11 +19907,11 @@ var skill2 = {
19835
19907
  data: { package: params.packageName, status, ...entry }
19836
19908
  };
19837
19909
  }
19838
- const pkgPath = path12.join(context.projectDir, "package.json");
19839
- if (!fs12.existsSync(pkgPath)) {
19910
+ const pkgPath = path11.join(context.projectDir, "package.json");
19911
+ if (!fs11.existsSync(pkgPath)) {
19840
19912
  return { success: false, message: "No package.json found" };
19841
19913
  }
19842
- const pkg = JSON.parse(fs12.readFileSync(pkgPath, "utf8"));
19914
+ const pkg = JSON.parse(fs11.readFileSync(pkgPath, "utf8"));
19843
19915
  const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
19844
19916
  const results = {
19845
19917
  full: [],
@@ -19857,9 +19929,9 @@ var skill2 = {
19857
19929
  results.unknown.push(dep);
19858
19930
  }
19859
19931
  }
19860
- const reportPath = path12.join(context.outputDir, "compat-report.json");
19861
- fs12.mkdirSync(path12.dirname(reportPath), { recursive: true });
19862
- fs12.writeFileSync(reportPath, JSON.stringify(results, null, 2));
19932
+ const reportPath = path11.join(context.outputDir, "compat-report.json");
19933
+ fs11.mkdirSync(path11.dirname(reportPath), { recursive: true });
19934
+ fs11.writeFileSync(reportPath, JSON.stringify(results, null, 2));
19863
19935
  return {
19864
19936
  success: results.unsupported.length === 0,
19865
19937
  message: `${results.full.length} full, ${results.partial.length} partial, ${results.unsupported.length} unsupported, ${results.unknown.length} unknown`,
@@ -19897,8 +19969,8 @@ var skill3 = {
19897
19969
  record: { type: "boolean", description: "Record video of the flow" }
19898
19970
  },
19899
19971
  async execute(params, context) {
19900
- const fs12 = await import("fs");
19901
- const path12 = await import("path");
19972
+ const fs11 = await import("fs");
19973
+ const path11 = await import("path");
19902
19974
  const yaml2 = await import("yaml");
19903
19975
  const { DEFAULT_SOOTSIM_BRIDGE_PORT: DEFAULT_SOOTSIM_BRIDGE_PORT2 } = await Promise.resolve().then(() => (init_bridge_constants(), bridge_constants_exports));
19904
19976
  const { SootSimBridgeHost: SootSimBridgeHost2 } = await Promise.resolve().then(() => (init_bridge_host(), bridge_host_exports));
@@ -19907,7 +19979,7 @@ var skill3 = {
19907
19979
  const host = new SootSimBridgeHost2({ port: DEFAULT_SOOTSIM_BRIDGE_PORT2 });
19908
19980
  host.start({ silent: true });
19909
19981
  try {
19910
- const flowContent = fs12.readFileSync(params.flowPath, "utf8");
19982
+ const flowContent = fs11.readFileSync(params.flowPath, "utf8");
19911
19983
  const fmMatch = flowContent.match(/^---\n([\s\S]*?)\n---\n?/);
19912
19984
  const stepsBody = fmMatch ? flowContent.slice(fmMatch[0].length) : flowContent;
19913
19985
  const steps = yaml2.parse(stepsBody);
@@ -19932,7 +20004,7 @@ var skill3 = {
19932
20004
  });
19933
20005
  const driver = new SootSimBridgeFlowRunner2(bridge, {
19934
20006
  screenshotDir: context.outputDir,
19935
- flowDir: path12.dirname(path12.resolve(params.flowPath)),
20007
+ flowDir: path11.dirname(path11.resolve(params.flowPath)),
19936
20008
  simId,
19937
20009
  recordingOutputDir: params.record ? context.outputDir : void 0
19938
20010
  });
@@ -19954,7 +20026,7 @@ var skill3 = {
19954
20026
  simId,
19955
20027
  videoPath: videoPath || void 0
19956
20028
  },
19957
- artifacts: videoPath ? [{ type: "video", name: path12.basename(videoPath), path: videoPath }] : void 0
20029
+ artifacts: videoPath ? [{ type: "video", name: path11.basename(videoPath), path: videoPath }] : void 0
19958
20030
  };
19959
20031
  } finally {
19960
20032
  try {
@@ -20001,8 +20073,8 @@ var skill4 = {
20001
20073
  },
20002
20074
  async execute(params, context) {
20003
20075
  const { chromium } = await import("playwright");
20004
- const path12 = await import("path");
20005
- const fs12 = await import("fs");
20076
+ const path11 = await import("path");
20077
+ const fs11 = await import("fs");
20006
20078
  const browser = await launchReapedChrome((options) => chromium.launch(options), {
20007
20079
  headless: true
20008
20080
  });
@@ -20028,9 +20100,9 @@ var skill4 = {
20028
20100
  ...profile,
20029
20101
  fps: syncCount > 0 ? (syncCount / (duration / 1e3)).toFixed(1) : "0"
20030
20102
  };
20031
- const reportPath = path12.join(context.outputDir, "perf-report.json");
20032
- fs12.mkdirSync(path12.dirname(reportPath), { recursive: true });
20033
- fs12.writeFileSync(reportPath, JSON.stringify(report, null, 2));
20103
+ const reportPath = path11.join(context.outputDir, "perf-report.json");
20104
+ fs11.mkdirSync(path11.dirname(reportPath), { recursive: true });
20105
+ fs11.writeFileSync(reportPath, JSON.stringify(report, null, 2));
20034
20106
  return {
20035
20107
  success: true,
20036
20108
  message: `${report.fps} fps, ${profile.avgSyncMs?.toFixed(1)}ms avg sync, ${nodeCount} nodes`,
@@ -20063,8 +20135,8 @@ var skill5 = {
20063
20135
  },
20064
20136
  async execute(params, context) {
20065
20137
  const { chromium } = await import("playwright");
20066
- const path12 = await import("path");
20067
- const fs12 = await import("fs");
20138
+ const path11 = await import("path");
20139
+ const fs11 = await import("fs");
20068
20140
  const browser = await launchReapedChrome((options) => chromium.launch(options), {
20069
20141
  headless: true
20070
20142
  });
@@ -20072,8 +20144,8 @@ var skill5 = {
20072
20144
  try {
20073
20145
  await page.goto(context.url, { waitUntil: "networkidle" });
20074
20146
  await page.waitForTimeout(2e3);
20075
- const outputPath = path12.join(context.outputDir, `${params.name}.png`);
20076
- fs12.mkdirSync(path12.dirname(outputPath), { recursive: true });
20147
+ const outputPath = path11.join(context.outputDir, `${params.name}.png`);
20148
+ fs11.mkdirSync(path11.dirname(outputPath), { recursive: true });
20077
20149
  await page.screenshot({ path: outputPath });
20078
20150
  return {
20079
20151
  success: true,
@@ -20114,8 +20186,8 @@ var skill6 = {
20114
20186
  },
20115
20187
  async execute(params, context) {
20116
20188
  const { chromium } = await import("playwright");
20117
- const path12 = await import("path");
20118
- const fs12 = await import("fs");
20189
+ const path11 = await import("path");
20190
+ const fs11 = await import("fs");
20119
20191
  const browser = await launchReapedChrome((options) => chromium.launch(options), {
20120
20192
  headless: true
20121
20193
  });
@@ -20123,14 +20195,14 @@ var skill6 = {
20123
20195
  try {
20124
20196
  await page.goto(context.url, { waitUntil: "networkidle" });
20125
20197
  await page.waitForTimeout(2e3);
20126
- const currentPath = path12.join(context.outputDir, `${params.name}-current.png`);
20127
- fs12.mkdirSync(path12.dirname(currentPath), { recursive: true });
20198
+ const currentPath = path11.join(context.outputDir, `${params.name}-current.png`);
20199
+ fs11.mkdirSync(path11.dirname(currentPath), { recursive: true });
20128
20200
  await page.screenshot({ path: currentPath });
20129
20201
  try {
20130
20202
  const { PNG } = await import("pngjs");
20131
20203
  const pixelmatch = (await import("pixelmatch")).default;
20132
- const baseline = PNG.sync.read(fs12.readFileSync(params.baseline));
20133
- const current = PNG.sync.read(fs12.readFileSync(currentPath));
20204
+ const baseline = PNG.sync.read(fs11.readFileSync(params.baseline));
20205
+ const current = PNG.sync.read(fs11.readFileSync(currentPath));
20134
20206
  const { width, height } = baseline;
20135
20207
  const diff = new PNG({ width, height });
20136
20208
  const numDiffPixels = pixelmatch(
@@ -20141,8 +20213,8 @@ var skill6 = {
20141
20213
  height,
20142
20214
  { threshold: params.threshold || 0.1 }
20143
20215
  );
20144
- const diffPath = path12.join(context.outputDir, `${params.name}-diff.png`);
20145
- fs12.writeFileSync(diffPath, PNG.sync.write(diff));
20216
+ const diffPath = path11.join(context.outputDir, `${params.name}-diff.png`);
20217
+ fs11.writeFileSync(diffPath, PNG.sync.write(diff));
20146
20218
  const totalPixels = width * height;
20147
20219
  const diffPercent = (numDiffPixels / totalPixels * 100).toFixed(2);
20148
20220
  return {
@@ -20206,10 +20278,10 @@ var skillRegistry = {
20206
20278
  },
20207
20279
  // load skills from a project manifest (sootsim-skills.json)
20208
20280
  async loadFromManifest(projectDir) {
20209
- const manifestPath = path11.join(projectDir, "sootsim-skills.json");
20210
- if (!fs11.existsSync(manifestPath)) return;
20281
+ const manifestPath = path10.join(projectDir, "sootsim-skills.json");
20282
+ if (!fs10.existsSync(manifestPath)) return;
20211
20283
  try {
20212
- const manifest = JSON.parse(fs11.readFileSync(manifestPath, "utf8"));
20284
+ const manifest = JSON.parse(fs10.readFileSync(manifestPath, "utf8"));
20213
20285
  if (Array.isArray(manifest.skills)) {
20214
20286
  for (const entry of manifest.skills) {
20215
20287
  if (typeof entry === "string") {
@@ -20220,7 +20292,7 @@ var skillRegistry = {
20220
20292
  }
20221
20293
  } else if (entry.file) {
20222
20294
  try {
20223
- const mod = await import(path11.resolve(projectDir, entry.file));
20295
+ const mod = await import(path10.resolve(projectDir, entry.file));
20224
20296
  if (mod.skill) this.register(mod.skill);
20225
20297
  } catch {
20226
20298
  }
@@ -20233,10 +20305,10 @@ var skillRegistry = {
20233
20305
  // auto-discover skills based on project dependencies
20234
20306
  suggestSkills(projectDir) {
20235
20307
  const suggestions = [];
20236
- const pkgPath = path11.join(projectDir, "package.json");
20237
- if (!fs11.existsSync(pkgPath)) return suggestions;
20308
+ const pkgPath = path10.join(projectDir, "package.json");
20309
+ if (!fs10.existsSync(pkgPath)) return suggestions;
20238
20310
  try {
20239
- const pkg = JSON.parse(fs11.readFileSync(pkgPath, "utf8"));
20311
+ const pkg = JSON.parse(fs10.readFileSync(pkgPath, "utf8"));
20240
20312
  const deps = { ...pkg.dependencies, ...pkg.devDependencies };
20241
20313
  if (deps["detox"] || deps["maestro"]) {
20242
20314
  suggestions.push("maestro-test");