sootsim 0.1.176 → 0.1.178

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 (153) hide show
  1. package/dist-cli/bin.js +3 -3
  2. package/dist-cli/chunks/{agent-XZERN2SO.js → agent-FPRPN42P.js} +3 -3
  3. package/dist-cli/chunks/{agent-wrapper-SAIMSLSO.js → agent-wrapper-KABXHSDP.js} +2 -2
  4. package/dist-cli/chunks/{app-fonts-SQVNXLI5.js → app-fonts-GEL63MTY.js} +2 -2
  5. package/dist-cli/chunks/{assert-EWL6BYVH.js → assert-T55K3RFP.js} +2 -2
  6. package/dist-cli/chunks/beta-74JMB2XJ.js +2 -0
  7. package/dist-cli/chunks/{camera-FFYSKETF.js → camera-RPYSAI2K.js} +2 -2
  8. package/dist-cli/chunks/{chunk-VBUURELX.js → chunk-2IYQJHNS.js} +2 -2
  9. package/dist-cli/chunks/{chunk-6BU5E655.js → chunk-2SM7WWDI.js} +1 -1
  10. package/dist-cli/chunks/{chunk-MWTWVX32.js → chunk-3DSTCWVF.js} +2 -2
  11. package/dist-cli/chunks/{chunk-OAOQVBIR.js → chunk-42SYOZVV.js} +2 -2
  12. package/dist-cli/chunks/{chunk-Y2ZSLUGO.js → chunk-64VAJYXX.js} +2 -2
  13. package/dist-cli/chunks/{chunk-OORRMRMI.js → chunk-7BHPGH6Q.js} +1 -1
  14. package/dist-cli/chunks/{chunk-J2BOYJ2U.js → chunk-7KFBB76L.js} +2 -2
  15. package/dist-cli/chunks/{chunk-HAW6OMNW.js → chunk-B2Z36B4N.js} +2 -2
  16. package/dist-cli/chunks/{chunk-W5QHYSDJ.js → chunk-B5KTNMPL.js} +2 -2
  17. package/dist-cli/chunks/{chunk-JXZYXTBM.js → chunk-B77YOZBY.js} +2 -2
  18. package/dist-cli/chunks/{chunk-PA5EARX2.js → chunk-CJV7PX2Y.js} +2 -2
  19. package/dist-cli/chunks/{chunk-D6GUXY2L.js → chunk-CVBCNRKC.js} +2 -2
  20. package/dist-cli/chunks/chunk-DVBRRNWE.js +2 -0
  21. package/dist-cli/chunks/{chunk-2SUR2RR2.js → chunk-EHKLQO7I.js} +1 -1
  22. package/dist-cli/chunks/{chunk-XKVI3H2G.js → chunk-EUIPNUT4.js} +2 -2
  23. package/dist-cli/chunks/{chunk-CEMRS6UL.js → chunk-EY3XEEE4.js} +1 -1
  24. package/dist-cli/chunks/{chunk-W2AZ7ASM.js → chunk-H26BCZLV.js} +1 -1
  25. package/dist-cli/chunks/{chunk-BGP3OZID.js → chunk-IFJU3COY.js} +1 -1
  26. package/dist-cli/chunks/{chunk-STWES7DO.js → chunk-ITOXSEMN.js} +1 -1
  27. package/dist-cli/chunks/{chunk-Q4YNZFJF.js → chunk-JFQFJLTV.js} +4 -4
  28. package/dist-cli/chunks/{chunk-T3576IDX.js → chunk-K66BWMVS.js} +1 -1
  29. package/dist-cli/chunks/{chunk-PVIMLBMX.js → chunk-LJ2DIDX3.js} +3 -3
  30. package/dist-cli/chunks/{chunk-ZHFUIBAE.js → chunk-M7MO47BR.js} +1 -1
  31. package/dist-cli/chunks/{chunk-CFPELTGN.js → chunk-NE55HRAU.js} +2 -2
  32. package/dist-cli/chunks/{chunk-PPUEG6C4.js → chunk-O5SQ2RZE.js} +1 -1
  33. package/dist-cli/chunks/{chunk-N53VJ3FY.js → chunk-OK22FXGF.js} +2 -2
  34. package/dist-cli/chunks/{chunk-EU54PRND.js → chunk-PG42I7UQ.js} +2 -2
  35. package/dist-cli/chunks/{chunk-CF3NJNBJ.js → chunk-PHLMZYE4.js} +2 -2
  36. package/dist-cli/chunks/chunk-PNFYOQ4N.js +1 -0
  37. package/dist-cli/chunks/{chunk-SR7DWNZ3.js → chunk-PQLLJLSM.js} +1 -1
  38. package/dist-cli/chunks/{chunk-6S2MBFBN.js → chunk-PTBJZ3IO.js} +1 -1
  39. package/dist-cli/chunks/{chunk-ZAAITWNI.js → chunk-Q4PUVMFU.js} +1 -1
  40. package/dist-cli/chunks/{chunk-XKNXS6EC.js → chunk-RVVFK6CF.js} +1 -1
  41. package/dist-cli/chunks/{chunk-Y3NDHGEY.js → chunk-TBWJVJXW.js} +2 -2
  42. package/dist-cli/chunks/{chunk-HZSJ6FL3.js → chunk-UYKA44Y4.js} +2 -2
  43. package/dist-cli/chunks/chunk-V3N55LMK.js +4 -0
  44. package/dist-cli/chunks/{chunk-4WLI2STY.js → chunk-WY3B2Y5J.js} +2 -2
  45. package/dist-cli/chunks/{chunk-L2CTRBGR.js → chunk-XGU672KO.js} +1 -1
  46. package/dist-cli/chunks/{chunk-NMP6YTXS.js → chunk-YD3CNK36.js} +1 -1
  47. package/dist-cli/chunks/chunk-YFLYSJL6.js +1 -0
  48. package/dist-cli/chunks/{chunk-55LUU75I.js → chunk-YKV52CQX.js} +2 -2
  49. package/dist-cli/chunks/{chunk-OQ3N5IOK.js → chunk-YLQE2RO4.js} +3 -3
  50. package/dist-cli/chunks/{chunk-GBZNVWFP.js → chunk-YXBC4N6Z.js} +2 -2
  51. package/dist-cli/chunks/{chunk-63VEHUYI.js → chunk-ZKGEGXVG.js} +2 -2
  52. package/dist-cli/chunks/{chunk-NA2KJSP6.js → chunk-ZVZMM2RT.js} +1 -1
  53. package/dist-cli/chunks/cli-version-PVBTBN2X.js +2 -0
  54. package/dist-cli/chunks/{compat-ZFBUC4BH.js → compat-VDOLM4JY.js} +3 -3
  55. package/dist-cli/chunks/{control-3JJLR4W5.js → control-N6IWKWQ7.js} +2 -2
  56. package/dist-cli/chunks/{cpu-profile-FCEFZTYY.js → cpu-profile-CR4EKOPN.js} +2 -2
  57. package/dist-cli/chunks/daemon-HORAEEZR.js +2 -0
  58. package/dist-cli/chunks/{debug-CUBIZBSH.js → debug-4FCBFVDX.js} +3 -3
  59. package/dist-cli/chunks/{detox-4225EYR3.js → detox-TP77ADA2.js} +2 -2
  60. package/dist-cli/chunks/{device-S6BWDHPM.js → device-YRU6RDD2.js} +2 -2
  61. package/dist-cli/chunks/{diagnose-6CIKXRQI.js → diagnose-ZU4XLIKW.js} +2 -2
  62. package/dist-cli/chunks/drivers-BSP2USRT.js +2 -0
  63. package/dist-cli/chunks/{electron-37AEV4TD.js → electron-UWTORKRO.js} +3 -3
  64. package/dist-cli/chunks/flow-ZXUEU6WL.js +2 -0
  65. package/dist-cli/chunks/help-6OSM7CI4.js +2 -0
  66. package/dist-cli/chunks/{hints-NNX3XRHL.js → hints-X5YLALUQ.js} +2 -2
  67. package/dist-cli/chunks/{home-paths-GOXDTTLM.js → home-paths-LMEDDTAQ.js} +2 -2
  68. package/dist-cli/chunks/{inspect-YSYKYPAO.js → inspect-IFCVFMIW.js} +4 -4
  69. package/dist-cli/chunks/{install-desktop-OHGSHF3I.js → install-desktop-VVQIBZRU.js} +3 -3
  70. package/dist-cli/chunks/{keys-U7AANCE7.js → keys-GDX235ZQ.js} +2 -2
  71. package/dist-cli/chunks/{login-HQ7IGHOQ.js → login-MUIJHNM7.js} +4 -4
  72. package/dist-cli/chunks/{logout-CDVV56NI.js → logout-GV3H23TK.js} +2 -2
  73. package/dist-cli/chunks/{maestro-ZSO5MEL7.js → maestro-IFTHFVUR.js} +2 -2
  74. package/dist-cli/chunks/optional-demo-registry-26DVI7SE.js +2 -0
  75. package/dist-cli/chunks/{preview-QHRLVFZ3.js → preview-COYJHGIY.js} +2 -2
  76. package/dist-cli/chunks/{profile-JQ2VTWDK.js → profile-726ZBBXY.js} +2 -2
  77. package/dist-cli/chunks/{react-FZAOHKVR.js → react-LLN5L6NM.js} +2 -2
  78. package/dist-cli/chunks/{record-6SKJBVDV.js → record-TMJG2SMU.js} +2 -2
  79. package/dist-cli/chunks/runtime-3NQVPRES.js +2 -0
  80. package/dist-cli/chunks/{screenshot-ZWWD7RKD.js → screenshot-UFKR5MDO.js} +2 -2
  81. package/dist-cli/chunks/{screenshot-mode-AVGIIPOT.js → screenshot-mode-3ZGQR45L.js} +2 -2
  82. package/dist-cli/chunks/{screenshots-HNAQHHEZ.js → screenshots-JXS7HP2B.js} +2 -2
  83. package/dist-cli/chunks/{screenshots-capture-GR3JCQEV.js → screenshots-capture-ZBUHYPJJ.js} +2 -2
  84. package/dist-cli/chunks/{serve-E5JSN7LL.js → serve-ZG3KCDUO.js} +16 -16
  85. package/dist-cli/chunks/{setup-2M6ZQHFS.js → setup-2XT4LRR5.js} +2 -2
  86. package/dist-cli/chunks/{skills-EK6EIZKG.js → skills-3I7UWGIB.js} +2 -2
  87. package/dist-cli/chunks/{slides-7LMX75H7.js → slides-SCGGLDQQ.js} +2 -2
  88. package/dist-cli/chunks/store-7LKGHVAR.js +2 -0
  89. package/dist-cli/chunks/telemetry-SQRPQEGO.js +2 -0
  90. package/dist-cli/chunks/{test-GTYC4F55.js → test-ZRWZBUMK.js} +3 -3
  91. package/dist-cli/chunks/{three-mode-2PYZFZSU.js → three-mode-LJHDX4PK.js} +2 -2
  92. package/dist-cli/chunks/{timeline-MIFLVHUE.js → timeline-5OFJISEU.js} +2 -2
  93. package/dist-cli/chunks/{upgrade-ZVV5XJUB.js → upgrade-M7HFPN57.js} +2 -2
  94. package/dist-cli/chunks/upload-OOTFDONE.js +2 -0
  95. package/dist-cli/chunks/{version-IDZEL6JB.js → version-DHZQAZ66.js} +2 -2
  96. package/dist-cli/chunks/web-43QEU5SE.js +2 -0
  97. package/dist-cli/chunks/{what-happened-2YDLA4TU.js → what-happened-RNVAVGKL.js} +2 -2
  98. package/dist-cli/chunks/{whoami-MHMILIEP.js → whoami-F5EYWJCY.js} +2 -2
  99. package/dist-lib/agent-daemon-client.cjs +10 -1
  100. package/dist-lib/agent-events.cjs +1 -1
  101. package/dist-lib/agent-sessions.cjs +1 -1
  102. package/dist-lib/attached-projects.cjs +1 -1
  103. package/dist-lib/auth/shared-session.cjs +1 -1
  104. package/dist-lib/backend-origin.cjs +1 -1
  105. package/dist-lib/beta.cjs +1 -1
  106. package/dist-lib/beta.mjs +1 -1
  107. package/dist-lib/bridge-constants.cjs +1 -1
  108. package/dist-lib/cli-constants.cjs +1 -1
  109. package/dist-lib/config.cjs +1 -1
  110. package/dist-lib/detox/index.cjs +1 -1
  111. package/dist-lib/dev-bundle-resolution.cjs +1 -1
  112. package/dist-lib/home-paths.cjs +1 -1
  113. package/dist-lib/host/bridge-host.cjs +126 -12
  114. package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
  115. package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
  116. package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
  117. package/dist-lib/host/websocket-proxy.cjs +1 -1
  118. package/dist-lib/index.cjs +64 -21
  119. package/dist-lib/jump-to-source-babel.cjs +1 -1
  120. package/dist-lib/menu.cjs +1 -1
  121. package/dist-lib/menu.mjs +1 -1
  122. package/dist-lib/metro.cjs +1 -1
  123. package/dist-lib/profiles.cjs +1 -1
  124. package/dist-lib/render-mode.cjs +1 -1
  125. package/dist-lib/scripts/dev-server-scanner.cjs +1 -1
  126. package/dist-lib/sdk.cjs +1 -1
  127. package/dist-lib/sdk.mjs +1 -1
  128. package/dist-lib/skills.cjs +244 -102
  129. package/dist-lib/vite.cjs +64 -18
  130. package/package.json +7 -1
  131. package/src/agent-daemon-client.ts +13 -0
  132. package/src/agent-identity.ts +21 -0
  133. package/src/agentbus-prompt.ts +80 -0
  134. package/src/host/agent-host.ts +42 -0
  135. package/src/host/bridge-host.ts +14 -1
  136. package/src/native-seam-manifest.ts +11 -0
  137. package/src/vite-plugin-one.ts +63 -16
  138. package/dist-cli/chunks/beta-2CPZK3F2.js +0 -2
  139. package/dist-cli/chunks/chunk-3LI5PWSP.js +0 -2
  140. package/dist-cli/chunks/chunk-6WURQDZI.js +0 -1
  141. package/dist-cli/chunks/chunk-NPPSB4KE.js +0 -1
  142. package/dist-cli/chunks/chunk-XC3EDXUI.js +0 -4
  143. package/dist-cli/chunks/cli-version-ZQBDNAUR.js +0 -2
  144. package/dist-cli/chunks/daemon-3GBPTTR7.js +0 -2
  145. package/dist-cli/chunks/drivers-LI6YV5M7.js +0 -2
  146. package/dist-cli/chunks/flow-VBH4BQSB.js +0 -2
  147. package/dist-cli/chunks/help-23IS4JFP.js +0 -2
  148. package/dist-cli/chunks/optional-demo-registry-RG5TBVMN.js +0 -2
  149. package/dist-cli/chunks/runtime-KFHRVRZQ.js +0 -2
  150. package/dist-cli/chunks/store-VOGIKQFW.js +0 -2
  151. package/dist-cli/chunks/telemetry-7TUUNCCB.js +0 -2
  152. package/dist-cli/chunks/upload-AW66MDC5.js +0 -2
  153. package/dist-cli/chunks/web-IGOSYQWE.js +0 -2
@@ -1,4 +1,4 @@
1
- /*! sootsim v0.1.176 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.178 | (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;
@@ -3497,6 +3497,19 @@ var init_registry = __esm({
3497
3497
  }
3498
3498
  ]
3499
3499
  },
3500
+ "@bottom-tabs/react-navigation": {
3501
+ category: "Navigation",
3502
+ stubType: "works",
3503
+ versions: [
3504
+ {
3505
+ range: ">=1.0.0",
3506
+ coverage: 0.95,
3507
+ note: "pure JS React Navigation adapter over react-native-bottom-tabs; native tab rendering flows through the bottom-tabs seam",
3508
+ working: "createNativeBottomTabNavigator, Navigator, Screen options for title/label/icon/badge/lazy/freeze/testID/role, and TabView-level translucent/labeled/haptic/scroll-edge props via react-native-bottom-tabs",
3509
+ missing: "fidelity is bounded by the react-native-bottom-tabs native seam; no separate web tab implementation is provided by this adapter"
3510
+ }
3511
+ ]
3512
+ },
3500
3513
  "@react-navigation/stack": {
3501
3514
  category: "Navigation",
3502
3515
  stubType: "works",
@@ -5530,9 +5543,9 @@ var init_registry = __esm({
5530
5543
  versions: [
5531
5544
  {
5532
5545
  range: ">=1.0.0",
5533
- coverage: 0.85,
5534
- note: "load-safe noop \u2014 Editor passes children through",
5535
- missing: "no native markdown editing \u2014 recommended swap: marked/markdown-it + textarea on web"
5546
+ coverage: 0.65,
5547
+ note: "native seam for EnrichedMarkdownText/EnrichedMarkdown/EnrichedMarkdownTextInput generated host components; upstream JS wrapper and Streamdown integration run unchanged",
5548
+ missing: "native MD4C fidelity, selection menus, spoilers, math, images, and editable rich-markdown commands are simplified"
5536
5549
  }
5537
5550
  ]
5538
5551
  },
@@ -10106,10 +10119,10 @@ function tcpPing(port, timeout = TCP_GATE_MS) {
10106
10119
  sock.connect(port, "localhost");
10107
10120
  });
10108
10121
  }
10109
- function httpGet(port, path9, method = "GET", timeout = TIMEOUT_MS, headers = {}) {
10122
+ function httpGet(port, path10, method = "GET", timeout = TIMEOUT_MS, headers = {}) {
10110
10123
  return new Promise((resolve6) => {
10111
10124
  const req = import_http.default.request(
10112
- { hostname: "localhost", port, path: path9, method, timeout, headers },
10125
+ { hostname: "localhost", port, path: path10, method, timeout, headers },
10113
10126
  (res) => {
10114
10127
  let body = "";
10115
10128
  res.on("data", (c) => body += c.toString());
@@ -11724,6 +11737,97 @@ var init_agent_sessions = __esm({
11724
11737
  }
11725
11738
  });
11726
11739
 
11740
+ // src/agent-identity.ts
11741
+ function agentbusSessionIdFromCliIdentity(identity) {
11742
+ if (!identity?.startsWith("AGENTBUS_SESSION:")) return null;
11743
+ const sessionId = identity.slice("AGENTBUS_SESSION:".length).trim();
11744
+ if (!AGENTBUS_SESSION_RE.test(sessionId)) return null;
11745
+ return sessionId;
11746
+ }
11747
+ function isValidAgentbusSessionId(sessionId) {
11748
+ return AGENTBUS_SESSION_RE.test(sessionId);
11749
+ }
11750
+ var AGENTBUS_SESSION_RE;
11751
+ var init_agent_identity = __esm({
11752
+ "src/agent-identity.ts"() {
11753
+ "use strict";
11754
+ AGENTBUS_SESSION_RE = /^[A-Za-z0-9._:-]{1,160}$/;
11755
+ }
11756
+ });
11757
+
11758
+ // src/agentbus-prompt.ts
11759
+ function formatAgentbusPromptText(prompt) {
11760
+ return typeof prompt.text === "string" ? prompt.text.trim() : "";
11761
+ }
11762
+ function resolveAgentbusCommand(explicit) {
11763
+ const fromArg = explicit?.trim();
11764
+ if (fromArg) return fromArg;
11765
+ const fromEnv = process.env.AGENTBUS_COMMAND?.trim();
11766
+ if (fromEnv) return fromEnv;
11767
+ const localBin = import_node_path4.default.join(import_node_os2.default.homedir(), ".local", "bin", "agentbus");
11768
+ if (import_node_fs5.default.existsSync(localBin)) return localBin;
11769
+ return "agentbus";
11770
+ }
11771
+ async function sendPromptToAgentbusSession(input) {
11772
+ const sessionId = input.sessionId.trim();
11773
+ if (!isValidAgentbusSessionId(sessionId)) {
11774
+ throw new Error(`invalid agentbus session id: ${sessionId || "<empty>"}`);
11775
+ }
11776
+ const text = formatAgentbusPromptText(input.prompt);
11777
+ if (!text) {
11778
+ throw new Error("prompt text is empty");
11779
+ }
11780
+ const command = resolveAgentbusCommand(input.command);
11781
+ const timeoutMs = input.timeoutMs ?? 15e3;
11782
+ await new Promise((resolve6, reject) => {
11783
+ const child = (0, import_node_child_process2.spawn)(command, ["send", sessionId, text], {
11784
+ stdio: ["ignore", "ignore", "pipe"],
11785
+ env: process.env
11786
+ });
11787
+ let stderr = "";
11788
+ const timer = setTimeout(() => {
11789
+ try {
11790
+ child.kill("SIGTERM");
11791
+ } catch {
11792
+ }
11793
+ reject(new Error(`agentbus send timed out after ${Math.round(timeoutMs / 1e3)}s`));
11794
+ }, timeoutMs);
11795
+ child.stderr?.setEncoding("utf8");
11796
+ child.stderr?.on("data", (chunk) => {
11797
+ if (stderr.length < 4e3) stderr += String(chunk);
11798
+ });
11799
+ child.on("error", (err) => {
11800
+ clearTimeout(timer);
11801
+ reject(err);
11802
+ });
11803
+ child.on("exit", (code, signal) => {
11804
+ clearTimeout(timer);
11805
+ if (code === 0) {
11806
+ resolve6();
11807
+ return;
11808
+ }
11809
+ const detail = stderr.trim();
11810
+ reject(
11811
+ new Error(
11812
+ detail || `agentbus send exited with ${signal ? `signal ${signal}` : `code ${code ?? "unknown"}`}`
11813
+ )
11814
+ );
11815
+ });
11816
+ });
11817
+ }
11818
+ var import_node_child_process2, import_node_fs5, import_node_os2, import_node_path4;
11819
+ var init_agentbus_prompt = __esm({
11820
+ "src/agentbus-prompt.ts"() {
11821
+ "use strict";
11822
+ import_node_child_process2 = require("node:child_process");
11823
+ import_node_fs5 = __toESM(require("node:fs"), 1);
11824
+ import_node_os2 = __toESM(require("node:os"), 1);
11825
+ import_node_path4 = __toESM(require("node:path"), 1);
11826
+ init_agent_identity();
11827
+ init_agent_identity();
11828
+ }
11829
+ });
11830
+
11727
11831
  // src/host/agent-host.ts
11728
11832
  function defaultExcludePorts() {
11729
11833
  return [
@@ -11738,14 +11842,15 @@ function mapFrameworkToProjectFramework(fw) {
11738
11842
  if (fw === "one" || fw === "vxrn") return "one";
11739
11843
  return "unknown";
11740
11844
  }
11741
- var import_node_fs5, import_node_path4, WS_OPEN, AgentHost;
11845
+ var import_node_fs6, import_node_path5, WS_OPEN, AgentHost;
11742
11846
  var init_agent_host = __esm({
11743
11847
  "src/host/agent-host.ts"() {
11744
11848
  "use strict";
11745
- import_node_fs5 = __toESM(require("node:fs"), 1);
11746
- import_node_path4 = __toESM(require("node:path"), 1);
11849
+ import_node_fs6 = __toESM(require("node:fs"), 1);
11850
+ import_node_path5 = __toESM(require("node:path"), 1);
11747
11851
  init_dev_server_scanner();
11748
11852
  init_agent_sessions();
11853
+ init_agentbus_prompt();
11749
11854
  init_attached_projects();
11750
11855
  WS_OPEN = 1;
11751
11856
  AgentHost = class {
@@ -11845,6 +11950,8 @@ var init_agent_host = __esm({
11845
11950
  return listSessions(msg.projectId ? String(msg.projectId) : void 0);
11846
11951
  case "agent:start-session":
11847
11952
  return this.doStartSession(msg.input ?? {});
11953
+ case "agent:send-claimed-prompt":
11954
+ return this.sendClaimedPrompt(msg);
11848
11955
  case "agent:send-prompt": {
11849
11956
  const sessionId = String(msg.sessionId);
11850
11957
  const session = findSessionById(sessionId);
@@ -11876,6 +11983,28 @@ var init_agent_host = __esm({
11876
11983
  }
11877
11984
  }
11878
11985
  // --- operation impls ---
11986
+ async sendClaimedPrompt(msg) {
11987
+ const simId = typeof msg.simId === "string" ? msg.simId.trim() : "";
11988
+ if (!simId) {
11989
+ throw new AgentSessionError("NO_SIM", "agent:send-claimed-prompt requires simId");
11990
+ }
11991
+ const lease = this.opts.resolveCliLease?.(simId) ?? null;
11992
+ if (!lease || lease.kind !== "cli" || lease.expiresAt <= Date.now()) {
11993
+ throw new AgentSessionError("NO_CLAIM", `sim ${simId} has no active CLI claim`);
11994
+ }
11995
+ const sessionId = agentbusSessionIdFromCliIdentity(lease.cliIdentityKey);
11996
+ if (!sessionId) {
11997
+ throw new AgentSessionError(
11998
+ "UNSUPPORTED_CLAIM",
11999
+ `sim ${simId} is claimed by a CLI identity that is not promptable`
12000
+ );
12001
+ }
12002
+ await sendPromptToAgentbusSession({
12003
+ sessionId,
12004
+ prompt: this.normalizePromptEnvelope(msg)
12005
+ });
12006
+ return { ok: true, routed: "agentbus", sessionId };
12007
+ }
11879
12008
  async doStartSession(input) {
11880
12009
  const project = findProjectById(input.projectId);
11881
12010
  if (!project) {
@@ -11905,7 +12034,7 @@ var init_agent_host = __esm({
11905
12034
  );
11906
12035
  const project = upsertProject({
11907
12036
  cwd: match.cwd,
11908
- name: match.projectName ?? import_node_path4.default.basename(match.cwd),
12037
+ name: match.projectName ?? import_node_path5.default.basename(match.cwd),
11909
12038
  preferredProvider: input.provider ?? existing?.preferredProvider,
11910
12039
  sourceRoots: existing?.sourceRoots ?? [match.cwd],
11911
12040
  knownBundleUrls,
@@ -11916,18 +12045,18 @@ var init_agent_host = __esm({
11916
12045
  }
11917
12046
  getTranscript(sessionId) {
11918
12047
  const p = transcriptPath(sessionId);
11919
- if (!import_node_fs5.default.existsSync(p)) {
12048
+ if (!import_node_fs6.default.existsSync(p)) {
11920
12049
  return { error: "transcript not found", code: "NO_TRANSCRIPT" };
11921
12050
  }
11922
- return import_node_fs5.default.readFileSync(p, "utf8");
12051
+ return import_node_fs6.default.readFileSync(p, "utf8");
11923
12052
  }
11924
12053
  getPaths() {
11925
12054
  const dir = getUserDataDir();
11926
12055
  return {
11927
12056
  userDataDir: dir,
11928
- storeFile: import_node_path4.default.join(dir, "attached-projects.json"),
11929
- sessionsDir: import_node_path4.default.join(dir, "sessions"),
11930
- transcriptsDir: import_node_path4.default.join(dir, "transcripts")
12057
+ storeFile: import_node_path5.default.join(dir, "attached-projects.json"),
12058
+ sessionsDir: import_node_path5.default.join(dir, "sessions"),
12059
+ transcriptsDir: import_node_path5.default.join(dir, "transcripts")
11931
12060
  };
11932
12061
  }
11933
12062
  // --- subscription management ---
@@ -12967,7 +13096,18 @@ var init_bridge_host = __esm({
12967
13096
  this.shouldWriteDevLockfile = opts.writeDevLockfile === true;
12968
13097
  this.portFallbackCount = Math.max(1, opts.portFallbackCount ?? 10);
12969
13098
  this.openUrlHandler = opts.openUrl;
12970
- this.agentHost = new AgentHost({ getExcludePorts: opts.agentScanExcludes });
13099
+ this.agentHost = new AgentHost({
13100
+ getExcludePorts: opts.agentScanExcludes,
13101
+ resolveCliLease: (simId) => {
13102
+ const sim = this.sims.get(simId);
13103
+ const lease = sim ? this.getActiveLease(sim) : null;
13104
+ return lease ? {
13105
+ kind: lease.kind,
13106
+ cliIdentityKey: lease.cliIdentityKey,
13107
+ expiresAt: lease.expiresAt
13108
+ } : null;
13109
+ }
13110
+ });
12971
13111
  this.sootbeanOrigin = opts.sootbeanOrigin?.replace(/\/$/, "") || null;
12972
13112
  this.simIdleReapTtlMs = opts.simIdleReapTtlMs ?? _SootSimBridgeHost.SIM_IDLE_REAP_TTL_MS;
12973
13113
  this.automationSimIdleReapTtlMs = opts.automationSimIdleReapTtlMs ?? _SootSimBridgeHost.AUTOMATION_SIM_IDLE_REAP_TTL_MS;
@@ -14787,6 +14927,8 @@ var init_current_sim = __esm({
14787
14927
  IDENTITY_ENV_VARS = [
14788
14928
  "SOOTSIM_CLI_IDENTITY",
14789
14929
  // explicit override — fastest path, skips all pid lookups
14930
+ "AGENTBUS_SESSION",
14931
+ // agentbus session id; lets sootsim route prompt-bar followups back to this agent
14790
14932
  "CLAUDE_CODE_SESSION_ID",
14791
14933
  // claude code, if ever set
14792
14934
  "CODEX_THREAD_ID",
@@ -15141,11 +15283,11 @@ async function evalInBridge(bridge, code, opts = {}) {
15141
15283
  if (opts.acquireLock) payload.acquireLock = true;
15142
15284
  return bridge.send(payload);
15143
15285
  }
15144
- async function callInBridge(bridge, path9, ...args) {
15145
- return bridge.send({ type: "call", path: path9, args });
15286
+ async function callInBridge(bridge, path10, ...args) {
15287
+ return bridge.send({ type: "call", path: path10, args });
15146
15288
  }
15147
- async function callInBridgeWrite(bridge, path9, ...args) {
15148
- return bridge.send({ type: "call", path: path9, args, acquireLock: true });
15289
+ async function callInBridgeWrite(bridge, path10, ...args) {
15290
+ return bridge.send({ type: "call", path: path10, args, acquireLock: true });
15149
15291
  }
15150
15292
  var import_ws3, BridgeSimLockedError;
15151
15293
  var init_ws_bridge = __esm({
@@ -16148,14 +16290,14 @@ process.stdin.on('end', async () => {
16148
16290
  function getBaseDir() {
16149
16291
  const explicit = process.env[SESSION_FILE_ENV];
16150
16292
  if (explicit?.trim()) {
16151
- return (0, import_node_path5.dirname)((0, import_node_path5.resolve)(explicit));
16293
+ return (0, import_node_path6.dirname)((0, import_node_path6.resolve)(explicit));
16152
16294
  }
16153
16295
  return electronUserDataDir();
16154
16296
  }
16155
16297
  function getSharedDesktopAuthFilePath() {
16156
16298
  const explicit = process.env[SESSION_FILE_ENV];
16157
- if (explicit?.trim()) return (0, import_node_path5.resolve)(explicit);
16158
- return (0, import_node_path5.join)(getBaseDir(), "desktop-auth.json");
16299
+ if (explicit?.trim()) return (0, import_node_path6.resolve)(explicit);
16300
+ return (0, import_node_path6.join)(getBaseDir(), "desktop-auth.json");
16159
16301
  }
16160
16302
  function normalizeUser(input) {
16161
16303
  if (!input || typeof input !== "object") return null;
@@ -16201,26 +16343,26 @@ function normalizeSession(input) {
16201
16343
  }
16202
16344
  function readSharedDesktopAuthSession() {
16203
16345
  const filepath = getSharedDesktopAuthFilePath();
16204
- if (!(0, import_node_fs6.existsSync)(filepath)) return null;
16346
+ if (!(0, import_node_fs7.existsSync)(filepath)) return null;
16205
16347
  try {
16206
- const parsed = JSON.parse((0, import_node_fs6.readFileSync)(filepath, "utf8"));
16348
+ const parsed = JSON.parse((0, import_node_fs7.readFileSync)(filepath, "utf8"));
16207
16349
  const normalized = normalizeSession(parsed);
16208
16350
  if (!normalized) {
16209
- (0, import_node_fs6.rmSync)(filepath, { force: true });
16351
+ (0, import_node_fs7.rmSync)(filepath, { force: true });
16210
16352
  return null;
16211
16353
  }
16212
16354
  return normalized;
16213
16355
  } catch {
16214
- (0, import_node_fs6.rmSync)(filepath, { force: true });
16356
+ (0, import_node_fs7.rmSync)(filepath, { force: true });
16215
16357
  return null;
16216
16358
  }
16217
16359
  }
16218
- var import_node_fs6, import_node_path5, SESSION_VERSION, SESSION_FILE_ENV, DEFAULT_ORIGIN;
16360
+ var import_node_fs7, import_node_path6, SESSION_VERSION, SESSION_FILE_ENV, DEFAULT_ORIGIN;
16219
16361
  var init_shared_session = __esm({
16220
16362
  "src/auth/shared-session.ts"() {
16221
16363
  "use strict";
16222
- import_node_fs6 = require("node:fs");
16223
- import_node_path5 = require("node:path");
16364
+ import_node_fs7 = require("node:fs");
16365
+ import_node_path6 = require("node:path");
16224
16366
  init_home_paths();
16225
16367
  SESSION_VERSION = 1;
16226
16368
  SESSION_FILE_ENV = "SOOTSIM_SHARED_AUTH_FILE";
@@ -16230,13 +16372,13 @@ var init_shared_session = __esm({
16230
16372
 
16231
16373
  // cli/auth.ts
16232
16374
  function credentialsPath() {
16233
- return (0, import_node_path6.join)(electronUserDataDir(), "credentials.json");
16375
+ return (0, import_node_path7.join)(electronUserDataDir(), "credentials.json");
16234
16376
  }
16235
16377
  function readStoredApiKey() {
16236
16378
  const file = credentialsPath();
16237
- if (!(0, import_node_fs7.existsSync)(file)) return null;
16379
+ if (!(0, import_node_fs8.existsSync)(file)) return null;
16238
16380
  try {
16239
- const parsed = JSON.parse((0, import_node_fs7.readFileSync)(file, "utf8"));
16381
+ const parsed = JSON.parse((0, import_node_fs8.readFileSync)(file, "utf8"));
16240
16382
  if (parsed.version !== 1) return null;
16241
16383
  if (typeof parsed.apiKey !== "string" || !parsed.apiKey.startsWith("sk_sootsim_")) {
16242
16384
  return null;
@@ -16292,12 +16434,12 @@ function resolveCliAuth() {
16292
16434
  function authHeaderValue(auth) {
16293
16435
  return auth.kind === "api-key" ? `Bearer ${auth.secret}` : `Bearer ${auth.token}`;
16294
16436
  }
16295
- var import_node_fs7, import_node_path6, GITHUB_TOKEN_PREFIXES;
16437
+ var import_node_fs8, import_node_path7, GITHUB_TOKEN_PREFIXES;
16296
16438
  var init_auth = __esm({
16297
16439
  "cli/auth.ts"() {
16298
16440
  "use strict";
16299
- import_node_fs7 = require("node:fs");
16300
- import_node_path6 = require("node:path");
16441
+ import_node_fs8 = require("node:fs");
16442
+ import_node_path7 = require("node:path");
16301
16443
  init_shared_session();
16302
16444
  init_home_paths();
16303
16445
  GITHUB_TOKEN_PREFIXES = ["ghs_", "ghp_", "gho_", "ghu_", "github_pat_"];
@@ -16487,16 +16629,16 @@ function resolveFlowScreenshotPath(screenshotDir, name) {
16487
16629
  }
16488
16630
  function resolveProjectRelativeFlowBase(flowDir) {
16489
16631
  if (!flowDir) return process.cwd();
16490
- return path7.basename(flowDir) === ".maestro" ? path7.dirname(flowDir) : flowDir;
16632
+ return path8.basename(flowDir) === ".maestro" ? path8.dirname(flowDir) : flowDir;
16491
16633
  }
16492
16634
  function resolveFlowScreenshotPathWithMode(screenshotDir, name, opts) {
16493
16635
  const normalizedName = name.endsWith(".png") ? name : `${name}.png`;
16494
- if (path7.isAbsolute(normalizedName)) return normalizedName;
16636
+ if (path8.isAbsolute(normalizedName)) return normalizedName;
16495
16637
  if (opts.mode === "flow" && /[\\/]/.test(normalizedName)) {
16496
16638
  const baseDir = normalizedName.startsWith("./") || normalizedName.startsWith("../") ? opts.flowDir ?? process.cwd() : resolveProjectRelativeFlowBase(opts.flowDir);
16497
- return path7.resolve(baseDir, normalizedName);
16639
+ return path8.resolve(baseDir, normalizedName);
16498
16640
  }
16499
- return path7.join(screenshotDir, normalizedName);
16641
+ return path8.join(screenshotDir, normalizedName);
16500
16642
  }
16501
16643
  function normalizeFlowScreenshotSpec(step) {
16502
16644
  if (typeof step === "string") {
@@ -16551,12 +16693,12 @@ function parseFlowSteps(content) {
16551
16693
  const parsed = import_yaml.default.parse(candidate);
16552
16694
  return Array.isArray(parsed) ? parsed : [];
16553
16695
  }
16554
- var fs7, path7, import_settings2, import_yaml, DEFAULT_TIMEOUT, SCREEN_W, SCREEN_H, CLI_PERF_SESSION_GLOBAL, SootSimBridgeFlowRunner;
16696
+ var fs8, path8, import_settings2, import_yaml, DEFAULT_TIMEOUT, SCREEN_W, SCREEN_H, CLI_PERF_SESSION_GLOBAL, SootSimBridgeFlowRunner;
16555
16697
  var init_bridge_flow_runner = __esm({
16556
16698
  "cli/bridge-flow-runner.ts"() {
16557
16699
  "use strict";
16558
- fs7 = __toESM(require("fs"), 1);
16559
- path7 = __toESM(require("path"), 1);
16700
+ fs8 = __toESM(require("fs"), 1);
16701
+ path8 = __toESM(require("path"), 1);
16560
16702
  import_settings2 = require("sootsim-engine/settings");
16561
16703
  import_yaml = __toESM(require("yaml"), 1);
16562
16704
  init_frame_compose();
@@ -16778,14 +16920,14 @@ var init_bridge_flow_runner = __esm({
16778
16920
  if (chunks.length === 0) {
16779
16921
  throw new Error("recording requested but no video buffer was produced");
16780
16922
  }
16781
- fs7.mkdirSync(this.opts.recordingOutputDir, { recursive: true });
16923
+ fs8.mkdirSync(this.opts.recordingOutputDir, { recursive: true });
16782
16924
  const videoMime = stopped.mime || this.opts.recordingFormat || "video/webm";
16783
16925
  const extension = videoMime.includes("mp4") ? "mp4" : "webm";
16784
- const outputPath = path7.join(
16926
+ const outputPath = path8.join(
16785
16927
  this.opts.recordingOutputDir,
16786
16928
  `sootsim-${Date.now()}.${extension}`
16787
16929
  );
16788
- fs7.writeFileSync(outputPath, Buffer.concat(chunks));
16930
+ fs8.writeFileSync(outputPath, Buffer.concat(chunks));
16789
16931
  return outputPath;
16790
16932
  }
16791
16933
  async waitForRecordingTail(opts) {
@@ -17198,7 +17340,7 @@ var init_bridge_flow_runner = __esm({
17198
17340
  flowDir: this.opts.flowDir
17199
17341
  }
17200
17342
  );
17201
- fs7.mkdirSync(path7.dirname(outputPath), { recursive: true });
17343
+ fs8.mkdirSync(path8.dirname(outputPath), { recursive: true });
17202
17344
  const layers = spec.layers ?? this.opts.screenshotLayers;
17203
17345
  const screenshotRequest = {
17204
17346
  type: "screenshot",
@@ -17214,11 +17356,11 @@ var init_bridge_flow_runner = __esm({
17214
17356
  throw new Error("could not read current device model for framed screenshot");
17215
17357
  }
17216
17358
  const framed = await composeFramedScreenshot(rawBuffer, model);
17217
- fs7.writeFileSync(outputPath, framed);
17359
+ fs8.writeFileSync(outputPath, framed);
17218
17360
  console.log(`[flow] screenshot: ${outputPath} (frame: ${model})`);
17219
17361
  return;
17220
17362
  }
17221
- fs7.writeFileSync(outputPath, rawBuffer);
17363
+ fs8.writeFileSync(outputPath, rawBuffer);
17222
17364
  console.log(`[flow] screenshot: ${outputPath}`);
17223
17365
  }
17224
17366
  async readCurrentDeviceModel() {
@@ -17233,22 +17375,22 @@ var init_bridge_flow_runner = __esm({
17233
17375
  return model;
17234
17376
  }
17235
17377
  async captureFailureScreenshot(outputPath) {
17236
- fs7.mkdirSync(path7.dirname(outputPath), { recursive: true });
17378
+ fs8.mkdirSync(path8.dirname(outputPath), { recursive: true });
17237
17379
  const dataUrl = await this.bridge.send({
17238
17380
  type: "screenshot",
17239
17381
  simId: this.opts.simId
17240
17382
  });
17241
17383
  const base64 = dataUrl.replace(/^data:image\/png;base64,/, "");
17242
- fs7.writeFileSync(outputPath, Buffer.from(base64, "base64"));
17384
+ fs8.writeFileSync(outputPath, Buffer.from(base64, "base64"));
17243
17385
  }
17244
17386
  // writes a per-failure debug bundle: screenshot + structured describe
17245
17387
  // + a11y tree + console errors/warnings + failed network requests +
17246
17388
  // shell state, all under one directory so post-mortem is one grep away.
17247
17389
  async captureFailureBundle(outputDir, context) {
17248
- fs7.mkdirSync(outputDir, { recursive: true });
17390
+ fs8.mkdirSync(outputDir, { recursive: true });
17249
17391
  const write = (name, content) => {
17250
17392
  try {
17251
- fs7.writeFileSync(path7.join(outputDir, name), content);
17393
+ fs8.writeFileSync(path8.join(outputDir, name), content);
17252
17394
  } catch {
17253
17395
  }
17254
17396
  };
@@ -17749,8 +17891,8 @@ var init_bridge_flow_runner = __esm({
17749
17891
  runScript(target) {
17750
17892
  const spec = typeof target === "string" ? { file: target } : target;
17751
17893
  if (!spec.file) throw new Error("runScript requires a file");
17752
- const scriptPath = path7.resolve(this.opts.flowDir, spec.file);
17753
- const source = fs7.readFileSync(scriptPath, "utf8");
17894
+ const scriptPath = path8.resolve(this.opts.flowDir, spec.file);
17895
+ const source = fs8.readFileSync(scriptPath, "utf8");
17754
17896
  this.js.evaluate(source, { env: spec.env });
17755
17897
  console.log(`[flow] runScript: ${spec.file} done`);
17756
17898
  }
@@ -17989,10 +18131,10 @@ var init_bridge_flow_runner = __esm({
17989
18131
  for (const [k, v] of Object.entries(env)) this.js.putEnv(k, v);
17990
18132
  }
17991
18133
  if (file) {
17992
- const flowPath = path7.resolve(this.opts.flowDir, file);
17993
- const flowContent = fs7.readFileSync(flowPath, "utf8");
18134
+ const flowPath = path8.resolve(this.opts.flowDir, file);
18135
+ const flowContent = fs8.readFileSync(flowPath, "utf8");
17994
18136
  const previousDir = this.opts.flowDir;
17995
- this.opts.flowDir = path7.dirname(flowPath);
18137
+ this.opts.flowDir = path8.dirname(flowPath);
17996
18138
  try {
17997
18139
  await this.runFlow(parseFlowSteps(flowContent));
17998
18140
  } finally {
@@ -18088,8 +18230,8 @@ __export(registry_exports, {
18088
18230
  skillRegistry: () => skillRegistry
18089
18231
  });
18090
18232
  module.exports = __toCommonJS(registry_exports);
18091
- var fs8 = __toESM(require("fs"), 1);
18092
- var path8 = __toESM(require("path"), 1);
18233
+ var fs9 = __toESM(require("fs"), 1);
18234
+ var path9 = __toESM(require("path"), 1);
18093
18235
 
18094
18236
  // src/skills/builtin/a11y-review.ts
18095
18237
  var skill = {
@@ -18107,8 +18249,8 @@ var skill = {
18107
18249
  },
18108
18250
  async execute(params, context) {
18109
18251
  const { chromium } = await import("playwright");
18110
- const path9 = await import("path");
18111
- const fs9 = await import("fs");
18252
+ const path10 = await import("path");
18253
+ const fs10 = await import("fs");
18112
18254
  const browser = await chromium.launch({ channel: "chrome", headless: true });
18113
18255
  const page = await browser.newPage({ viewport: { width: 500, height: 900 } });
18114
18256
  try {
@@ -18161,9 +18303,9 @@ var skill = {
18161
18303
  warnings: issues.filter((i) => i.severity === "warning").length,
18162
18304
  tree: typeof tree === "string" ? tree : JSON.stringify(tree)
18163
18305
  };
18164
- const reportPath = path9.join(context.outputDir, "a11y-report.json");
18165
- fs9.mkdirSync(path9.dirname(reportPath), { recursive: true });
18166
- fs9.writeFileSync(reportPath, JSON.stringify(report, null, 2));
18306
+ const reportPath = path10.join(context.outputDir, "a11y-report.json");
18307
+ fs10.mkdirSync(path10.dirname(reportPath), { recursive: true });
18308
+ fs10.writeFileSync(reportPath, JSON.stringify(report, null, 2));
18167
18309
  return {
18168
18310
  success: issues.filter((i) => i.severity === "error").length === 0,
18169
18311
  message: `${report.errors} errors, ${report.warnings} warnings across ${report.nodeCount} nodes`,
@@ -18201,8 +18343,8 @@ var skill2 = {
18201
18343
  }
18202
18344
  },
18203
18345
  async execute(params, context) {
18204
- const fs9 = await import("fs");
18205
- const path9 = await import("path");
18346
+ const fs10 = await import("fs");
18347
+ const path10 = await import("path");
18206
18348
  const { POLYFILL_REGISTRY: POLYFILL_REGISTRY2 } = await Promise.resolve().then(() => (init_web(), web_exports));
18207
18349
  if (params.packageName) {
18208
18350
  const entry = POLYFILL_REGISTRY2[params.packageName];
@@ -18220,11 +18362,11 @@ var skill2 = {
18220
18362
  data: { package: params.packageName, status, ...entry }
18221
18363
  };
18222
18364
  }
18223
- const pkgPath = path9.join(context.projectDir, "package.json");
18224
- if (!fs9.existsSync(pkgPath)) {
18365
+ const pkgPath = path10.join(context.projectDir, "package.json");
18366
+ if (!fs10.existsSync(pkgPath)) {
18225
18367
  return { success: false, message: "No package.json found" };
18226
18368
  }
18227
- const pkg = JSON.parse(fs9.readFileSync(pkgPath, "utf8"));
18369
+ const pkg = JSON.parse(fs10.readFileSync(pkgPath, "utf8"));
18228
18370
  const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
18229
18371
  const results = {
18230
18372
  full: [],
@@ -18242,9 +18384,9 @@ var skill2 = {
18242
18384
  results.unknown.push(dep);
18243
18385
  }
18244
18386
  }
18245
- const reportPath = path9.join(context.outputDir, "compat-report.json");
18246
- fs9.mkdirSync(path9.dirname(reportPath), { recursive: true });
18247
- fs9.writeFileSync(reportPath, JSON.stringify(results, null, 2));
18387
+ const reportPath = path10.join(context.outputDir, "compat-report.json");
18388
+ fs10.mkdirSync(path10.dirname(reportPath), { recursive: true });
18389
+ fs10.writeFileSync(reportPath, JSON.stringify(results, null, 2));
18248
18390
  return {
18249
18391
  success: results.unsupported.length === 0,
18250
18392
  message: `${results.full.length} full, ${results.partial.length} partial, ${results.unsupported.length} unsupported, ${results.unknown.length} unknown`,
@@ -18282,8 +18424,8 @@ var skill3 = {
18282
18424
  },
18283
18425
  async execute(params, context) {
18284
18426
  const { chromium } = await import("playwright");
18285
- const path9 = await import("path");
18286
- const fs9 = await import("fs");
18427
+ const path10 = await import("path");
18428
+ const fs10 = await import("fs");
18287
18429
  const browser = await chromium.launch({ channel: "chrome", headless: true });
18288
18430
  const page = await browser.newPage({ viewport: { width: 500, height: 900 } });
18289
18431
  try {
@@ -18307,9 +18449,9 @@ var skill3 = {
18307
18449
  ...profile,
18308
18450
  fps: syncCount > 0 ? (syncCount / (duration / 1e3)).toFixed(1) : "0"
18309
18451
  };
18310
- const reportPath = path9.join(context.outputDir, "perf-report.json");
18311
- fs9.mkdirSync(path9.dirname(reportPath), { recursive: true });
18312
- fs9.writeFileSync(reportPath, JSON.stringify(report, null, 2));
18452
+ const reportPath = path10.join(context.outputDir, "perf-report.json");
18453
+ fs10.mkdirSync(path10.dirname(reportPath), { recursive: true });
18454
+ fs10.writeFileSync(reportPath, JSON.stringify(report, null, 2));
18313
18455
  return {
18314
18456
  success: true,
18315
18457
  message: `${report.fps} fps, ${profile.avgSyncMs?.toFixed(1)}ms avg sync, ${nodeCount} nodes`,
@@ -18341,15 +18483,15 @@ var skill4 = {
18341
18483
  },
18342
18484
  async execute(params, context) {
18343
18485
  const { chromium } = await import("playwright");
18344
- const path9 = await import("path");
18345
- const fs9 = await import("fs");
18486
+ const path10 = await import("path");
18487
+ const fs10 = await import("fs");
18346
18488
  const browser = await chromium.launch({ channel: "chrome", headless: true });
18347
18489
  const page = await browser.newPage({ viewport: { width: 500, height: 900 } });
18348
18490
  try {
18349
18491
  await page.goto(context.url, { waitUntil: "networkidle" });
18350
18492
  await page.waitForTimeout(2e3);
18351
- const outputPath = path9.join(context.outputDir, `${params.name}.png`);
18352
- fs9.mkdirSync(path9.dirname(outputPath), { recursive: true });
18493
+ const outputPath = path10.join(context.outputDir, `${params.name}.png`);
18494
+ fs10.mkdirSync(path10.dirname(outputPath), { recursive: true });
18353
18495
  await page.screenshot({ path: outputPath });
18354
18496
  return {
18355
18497
  success: true,
@@ -18387,8 +18529,8 @@ var skill5 = {
18387
18529
  record: { type: "boolean", description: "Record video of the flow" }
18388
18530
  },
18389
18531
  async execute(params, context) {
18390
- const fs9 = await import("fs");
18391
- const path9 = await import("path");
18532
+ const fs10 = await import("fs");
18533
+ const path10 = await import("path");
18392
18534
  const yaml2 = await import("yaml");
18393
18535
  const { DEFAULT_SOOTSIM_BRIDGE_PORT: DEFAULT_SOOTSIM_BRIDGE_PORT2 } = await Promise.resolve().then(() => (init_bridge_constants(), bridge_constants_exports));
18394
18536
  const { SootSimBridgeHost: SootSimBridgeHost2 } = await Promise.resolve().then(() => (init_bridge_host(), bridge_host_exports));
@@ -18397,7 +18539,7 @@ var skill5 = {
18397
18539
  const host = new SootSimBridgeHost2({ port: DEFAULT_SOOTSIM_BRIDGE_PORT2 });
18398
18540
  host.start({ silent: true });
18399
18541
  try {
18400
- const flowContent = fs9.readFileSync(params.flowPath, "utf8");
18542
+ const flowContent = fs10.readFileSync(params.flowPath, "utf8");
18401
18543
  const fmMatch = flowContent.match(/^---\n([\s\S]*?)\n---\n?/);
18402
18544
  const stepsBody = fmMatch ? flowContent.slice(fmMatch[0].length) : flowContent;
18403
18545
  const steps = yaml2.parse(stepsBody);
@@ -18422,7 +18564,7 @@ var skill5 = {
18422
18564
  });
18423
18565
  const driver = new SootSimBridgeFlowRunner2(bridge, {
18424
18566
  screenshotDir: context.outputDir,
18425
- flowDir: path9.dirname(path9.resolve(params.flowPath)),
18567
+ flowDir: path10.dirname(path10.resolve(params.flowPath)),
18426
18568
  simId,
18427
18569
  recordingOutputDir: params.record ? context.outputDir : void 0
18428
18570
  });
@@ -18444,7 +18586,7 @@ var skill5 = {
18444
18586
  simId,
18445
18587
  videoPath: videoPath || void 0
18446
18588
  },
18447
- artifacts: videoPath ? [{ type: "video", name: path9.basename(videoPath), path: videoPath }] : void 0
18589
+ artifacts: videoPath ? [{ type: "video", name: path10.basename(videoPath), path: videoPath }] : void 0
18448
18590
  };
18449
18591
  } finally {
18450
18592
  try {
@@ -18492,21 +18634,21 @@ var skill6 = {
18492
18634
  },
18493
18635
  async execute(params, context) {
18494
18636
  const { chromium } = await import("playwright");
18495
- const path9 = await import("path");
18496
- const fs9 = await import("fs");
18637
+ const path10 = await import("path");
18638
+ const fs10 = await import("fs");
18497
18639
  const browser = await chromium.launch({ channel: "chrome", headless: true });
18498
18640
  const page = await browser.newPage({ viewport: { width: 500, height: 900 } });
18499
18641
  try {
18500
18642
  await page.goto(context.url, { waitUntil: "networkidle" });
18501
18643
  await page.waitForTimeout(2e3);
18502
- const currentPath = path9.join(context.outputDir, `${params.name}-current.png`);
18503
- fs9.mkdirSync(path9.dirname(currentPath), { recursive: true });
18644
+ const currentPath = path10.join(context.outputDir, `${params.name}-current.png`);
18645
+ fs10.mkdirSync(path10.dirname(currentPath), { recursive: true });
18504
18646
  await page.screenshot({ path: currentPath });
18505
18647
  try {
18506
18648
  const { PNG } = await import("pngjs");
18507
18649
  const pixelmatch = (await import("pixelmatch")).default;
18508
- const baseline = PNG.sync.read(fs9.readFileSync(params.baseline));
18509
- const current = PNG.sync.read(fs9.readFileSync(currentPath));
18650
+ const baseline = PNG.sync.read(fs10.readFileSync(params.baseline));
18651
+ const current = PNG.sync.read(fs10.readFileSync(currentPath));
18510
18652
  const { width, height } = baseline;
18511
18653
  const diff = new PNG({ width, height });
18512
18654
  const numDiffPixels = pixelmatch(
@@ -18517,8 +18659,8 @@ var skill6 = {
18517
18659
  height,
18518
18660
  { threshold: params.threshold || 0.1 }
18519
18661
  );
18520
- const diffPath = path9.join(context.outputDir, `${params.name}-diff.png`);
18521
- fs9.writeFileSync(diffPath, PNG.sync.write(diff));
18662
+ const diffPath = path10.join(context.outputDir, `${params.name}-diff.png`);
18663
+ fs10.writeFileSync(diffPath, PNG.sync.write(diff));
18522
18664
  const totalPixels = width * height;
18523
18665
  const diffPercent = (numDiffPixels / totalPixels * 100).toFixed(2);
18524
18666
  return {
@@ -18582,10 +18724,10 @@ var skillRegistry = {
18582
18724
  },
18583
18725
  // load skills from a project manifest (sootsim-skills.json)
18584
18726
  async loadFromManifest(projectDir) {
18585
- const manifestPath = path8.join(projectDir, "sootsim-skills.json");
18586
- if (!fs8.existsSync(manifestPath)) return;
18727
+ const manifestPath = path9.join(projectDir, "sootsim-skills.json");
18728
+ if (!fs9.existsSync(manifestPath)) return;
18587
18729
  try {
18588
- const manifest = JSON.parse(fs8.readFileSync(manifestPath, "utf8"));
18730
+ const manifest = JSON.parse(fs9.readFileSync(manifestPath, "utf8"));
18589
18731
  if (Array.isArray(manifest.skills)) {
18590
18732
  for (const entry of manifest.skills) {
18591
18733
  if (typeof entry === "string") {
@@ -18596,7 +18738,7 @@ var skillRegistry = {
18596
18738
  }
18597
18739
  } else if (entry.file) {
18598
18740
  try {
18599
- const mod = await import(path8.resolve(projectDir, entry.file));
18741
+ const mod = await import(path9.resolve(projectDir, entry.file));
18600
18742
  if (mod.skill) this.register(mod.skill);
18601
18743
  } catch {
18602
18744
  }
@@ -18609,10 +18751,10 @@ var skillRegistry = {
18609
18751
  // auto-discover skills based on project dependencies
18610
18752
  suggestSkills(projectDir) {
18611
18753
  const suggestions = [];
18612
- const pkgPath = path8.join(projectDir, "package.json");
18613
- if (!fs8.existsSync(pkgPath)) return suggestions;
18754
+ const pkgPath = path9.join(projectDir, "package.json");
18755
+ if (!fs9.existsSync(pkgPath)) return suggestions;
18614
18756
  try {
18615
- const pkg = JSON.parse(fs8.readFileSync(pkgPath, "utf8"));
18757
+ const pkg = JSON.parse(fs9.readFileSync(pkgPath, "utf8"));
18616
18758
  const deps = { ...pkg.dependencies, ...pkg.devDependencies };
18617
18759
  if (deps["detox"] || deps["maestro"]) {
18618
18760
  suggestions.push("test-flow");