sootsim 0.1.176 → 0.1.177

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 (151) hide show
  1. package/dist-cli/bin.js +3 -3
  2. package/dist-cli/chunks/{agent-XZERN2SO.js → agent-3BCITLIZ.js} +3 -3
  3. package/dist-cli/chunks/{agent-wrapper-SAIMSLSO.js → agent-wrapper-26RIZVGD.js} +2 -2
  4. package/dist-cli/chunks/{app-fonts-SQVNXLI5.js → app-fonts-JVDHATQE.js} +2 -2
  5. package/dist-cli/chunks/{assert-EWL6BYVH.js → assert-IT2OXM4Y.js} +2 -2
  6. package/dist-cli/chunks/beta-SPH73CAA.js +2 -0
  7. package/dist-cli/chunks/{camera-FFYSKETF.js → camera-ZYVEUCIO.js} +2 -2
  8. package/dist-cli/chunks/{chunk-OQ3N5IOK.js → chunk-3L6I2M2Z.js} +3 -3
  9. package/dist-cli/chunks/chunk-4INGTBO7.js +4 -0
  10. package/dist-cli/chunks/{chunk-Q4YNZFJF.js → chunk-4JESO36F.js} +4 -4
  11. package/dist-cli/chunks/{chunk-GBZNVWFP.js → chunk-4YNKFN2A.js} +2 -2
  12. package/dist-cli/chunks/{chunk-4WLI2STY.js → chunk-52O56BTW.js} +2 -2
  13. package/dist-cli/chunks/{chunk-ZHFUIBAE.js → chunk-64QAFSY7.js} +1 -1
  14. package/dist-cli/chunks/{chunk-HAW6OMNW.js → chunk-65ZBQDQM.js} +2 -2
  15. package/dist-cli/chunks/{chunk-NA2KJSP6.js → chunk-A2WASN2L.js} +1 -1
  16. package/dist-cli/chunks/{chunk-MWTWVX32.js → chunk-A3VHHWLU.js} +2 -2
  17. package/dist-cli/chunks/{chunk-HZSJ6FL3.js → chunk-AN4DM7IB.js} +2 -2
  18. package/dist-cli/chunks/{chunk-J2BOYJ2U.js → chunk-ATVKVVHZ.js} +2 -2
  19. package/dist-cli/chunks/chunk-B6GISAUX.js +1 -0
  20. package/dist-cli/chunks/{chunk-Y3NDHGEY.js → chunk-BTTZN2SN.js} +2 -2
  21. package/dist-cli/chunks/{chunk-VBUURELX.js → chunk-C5QOGCVN.js} +2 -2
  22. package/dist-cli/chunks/{chunk-SR7DWNZ3.js → chunk-CH3MWM5W.js} +1 -1
  23. package/dist-cli/chunks/{chunk-63VEHUYI.js → chunk-CHTYIQLE.js} +2 -2
  24. package/dist-cli/chunks/{chunk-L2CTRBGR.js → chunk-CUO7F2JE.js} +1 -1
  25. package/dist-cli/chunks/{chunk-6BU5E655.js → chunk-D2BBJUEY.js} +1 -1
  26. package/dist-cli/chunks/chunk-DGDBEXXQ.js +1 -0
  27. package/dist-cli/chunks/{chunk-OORRMRMI.js → chunk-IBSEFPPL.js} +1 -1
  28. package/dist-cli/chunks/{chunk-Y2ZSLUGO.js → chunk-JFLNZGDS.js} +2 -2
  29. package/dist-cli/chunks/{chunk-XKVI3H2G.js → chunk-JHYLPDCC.js} +2 -2
  30. package/dist-cli/chunks/{chunk-NMP6YTXS.js → chunk-JS3NH2SJ.js} +1 -1
  31. package/dist-cli/chunks/{chunk-W5QHYSDJ.js → chunk-JS7SSYDG.js} +2 -2
  32. package/dist-cli/chunks/{chunk-PPUEG6C4.js → chunk-JXO6UPGI.js} +1 -1
  33. package/dist-cli/chunks/{chunk-T3576IDX.js → chunk-LTZPVG65.js} +1 -1
  34. package/dist-cli/chunks/{chunk-XKNXS6EC.js → chunk-NOLQYF76.js} +1 -1
  35. package/dist-cli/chunks/{chunk-W2AZ7ASM.js → chunk-NYGESF6F.js} +1 -1
  36. package/dist-cli/chunks/{chunk-6S2MBFBN.js → chunk-NZWTC6K6.js} +1 -1
  37. package/dist-cli/chunks/{chunk-ZAAITWNI.js → chunk-PAU64XFG.js} +1 -1
  38. package/dist-cli/chunks/{chunk-N53VJ3FY.js → chunk-PL3ALTWB.js} +2 -2
  39. package/dist-cli/chunks/{chunk-JXZYXTBM.js → chunk-QWZFOMCI.js} +2 -2
  40. package/dist-cli/chunks/{chunk-55LUU75I.js → chunk-SNLUVL3H.js} +2 -2
  41. package/dist-cli/chunks/{chunk-CFPELTGN.js → chunk-SU3JJ7ER.js} +2 -2
  42. package/dist-cli/chunks/{chunk-CF3NJNBJ.js → chunk-TVFHGWTW.js} +2 -2
  43. package/dist-cli/chunks/{chunk-OAOQVBIR.js → chunk-UBJQDMDG.js} +2 -2
  44. package/dist-cli/chunks/{chunk-D6GUXY2L.js → chunk-UJN3FMEX.js} +2 -2
  45. package/dist-cli/chunks/{chunk-STWES7DO.js → chunk-WKG5J4RD.js} +1 -1
  46. package/dist-cli/chunks/{chunk-CEMRS6UL.js → chunk-WRHJEI7Y.js} +1 -1
  47. package/dist-cli/chunks/{chunk-EU54PRND.js → chunk-WUEKKZ7Z.js} +2 -2
  48. package/dist-cli/chunks/{chunk-2SUR2RR2.js → chunk-Y2637KG7.js} +1 -1
  49. package/dist-cli/chunks/chunk-YU6CNUJD.js +2 -0
  50. package/dist-cli/chunks/{chunk-BGP3OZID.js → chunk-YVDSGGOT.js} +1 -1
  51. package/dist-cli/chunks/{chunk-PA5EARX2.js → chunk-Z4IMGLHM.js} +2 -2
  52. package/dist-cli/chunks/{chunk-PVIMLBMX.js → chunk-ZUTVEJVA.js} +3 -3
  53. package/dist-cli/chunks/cli-version-HENS6BZI.js +2 -0
  54. package/dist-cli/chunks/{compat-ZFBUC4BH.js → compat-MNTQH57R.js} +3 -3
  55. package/dist-cli/chunks/{control-3JJLR4W5.js → control-WQ7XEPCI.js} +2 -2
  56. package/dist-cli/chunks/{cpu-profile-FCEFZTYY.js → cpu-profile-P27HBXOI.js} +2 -2
  57. package/dist-cli/chunks/daemon-WUAZELEI.js +2 -0
  58. package/dist-cli/chunks/{debug-CUBIZBSH.js → debug-ES4A3SZQ.js} +3 -3
  59. package/dist-cli/chunks/{detox-4225EYR3.js → detox-Q36B2553.js} +2 -2
  60. package/dist-cli/chunks/{device-S6BWDHPM.js → device-NA7TB4E6.js} +2 -2
  61. package/dist-cli/chunks/{diagnose-6CIKXRQI.js → diagnose-DKW5WI3X.js} +2 -2
  62. package/dist-cli/chunks/drivers-RFOOGIRC.js +2 -0
  63. package/dist-cli/chunks/{electron-37AEV4TD.js → electron-6C2VDAZW.js} +3 -3
  64. package/dist-cli/chunks/flow-GSHP52QS.js +2 -0
  65. package/dist-cli/chunks/help-J6PF4PZX.js +2 -0
  66. package/dist-cli/chunks/{hints-NNX3XRHL.js → hints-W7ZZ6KZE.js} +2 -2
  67. package/dist-cli/chunks/{home-paths-GOXDTTLM.js → home-paths-K4347S7C.js} +2 -2
  68. package/dist-cli/chunks/{inspect-YSYKYPAO.js → inspect-ZPHNFMEX.js} +4 -4
  69. package/dist-cli/chunks/{install-desktop-OHGSHF3I.js → install-desktop-ZCCPJMOF.js} +3 -3
  70. package/dist-cli/chunks/{keys-U7AANCE7.js → keys-XM67H4SM.js} +2 -2
  71. package/dist-cli/chunks/{login-HQ7IGHOQ.js → login-O4OGJKYL.js} +4 -4
  72. package/dist-cli/chunks/{logout-CDVV56NI.js → logout-DWCBRMLM.js} +2 -2
  73. package/dist-cli/chunks/{maestro-ZSO5MEL7.js → maestro-MEWENIGQ.js} +2 -2
  74. package/dist-cli/chunks/optional-demo-registry-O3XS3WXJ.js +2 -0
  75. package/dist-cli/chunks/{preview-QHRLVFZ3.js → preview-VPWG4462.js} +2 -2
  76. package/dist-cli/chunks/{profile-JQ2VTWDK.js → profile-R4CSGXYJ.js} +2 -2
  77. package/dist-cli/chunks/{react-FZAOHKVR.js → react-5LFUOYV5.js} +2 -2
  78. package/dist-cli/chunks/{record-6SKJBVDV.js → record-MHAAYOWF.js} +2 -2
  79. package/dist-cli/chunks/runtime-R2PRKIZM.js +2 -0
  80. package/dist-cli/chunks/{screenshot-ZWWD7RKD.js → screenshot-XAEO7EBF.js} +2 -2
  81. package/dist-cli/chunks/{screenshot-mode-AVGIIPOT.js → screenshot-mode-QNR5ESKN.js} +2 -2
  82. package/dist-cli/chunks/{screenshots-HNAQHHEZ.js → screenshots-Z6OSENKY.js} +2 -2
  83. package/dist-cli/chunks/{screenshots-capture-GR3JCQEV.js → screenshots-capture-3DJPYJUD.js} +2 -2
  84. package/dist-cli/chunks/{serve-E5JSN7LL.js → serve-IVTQFOFI.js} +16 -16
  85. package/dist-cli/chunks/{setup-2M6ZQHFS.js → setup-AMRSL4IK.js} +2 -2
  86. package/dist-cli/chunks/{skills-EK6EIZKG.js → skills-K4DG2CIH.js} +2 -2
  87. package/dist-cli/chunks/{slides-7LMX75H7.js → slides-UIH7KXFR.js} +2 -2
  88. package/dist-cli/chunks/store-2JY2VLVA.js +2 -0
  89. package/dist-cli/chunks/telemetry-KNKROOT5.js +2 -0
  90. package/dist-cli/chunks/{test-GTYC4F55.js → test-XUJ2V5ZX.js} +3 -3
  91. package/dist-cli/chunks/{three-mode-2PYZFZSU.js → three-mode-P6HSLJMD.js} +2 -2
  92. package/dist-cli/chunks/{timeline-MIFLVHUE.js → timeline-YSUY4PHV.js} +2 -2
  93. package/dist-cli/chunks/{upgrade-ZVV5XJUB.js → upgrade-YZMDFQIH.js} +2 -2
  94. package/dist-cli/chunks/upload-TIH2LID6.js +2 -0
  95. package/dist-cli/chunks/{version-IDZEL6JB.js → version-5QAMZ5CK.js} +2 -2
  96. package/dist-cli/chunks/{web-IGOSYQWE.js → web-LM3JSBQF.js} +2 -2
  97. package/dist-cli/chunks/{what-happened-2YDLA4TU.js → what-happened-NYVQ7KER.js} +2 -2
  98. package/dist-cli/chunks/{whoami-MHMILIEP.js → whoami-AAHH72FM.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 +1 -1
  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 +231 -102
  129. package/dist-lib/vite.cjs +1 -1
  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/dist-cli/chunks/beta-2CPZK3F2.js +0 -2
  138. package/dist-cli/chunks/chunk-3LI5PWSP.js +0 -2
  139. package/dist-cli/chunks/chunk-6WURQDZI.js +0 -1
  140. package/dist-cli/chunks/chunk-NPPSB4KE.js +0 -1
  141. package/dist-cli/chunks/chunk-XC3EDXUI.js +0 -4
  142. package/dist-cli/chunks/cli-version-ZQBDNAUR.js +0 -2
  143. package/dist-cli/chunks/daemon-3GBPTTR7.js +0 -2
  144. package/dist-cli/chunks/drivers-LI6YV5M7.js +0 -2
  145. package/dist-cli/chunks/flow-VBH4BQSB.js +0 -2
  146. package/dist-cli/chunks/help-23IS4JFP.js +0 -2
  147. package/dist-cli/chunks/optional-demo-registry-RG5TBVMN.js +0 -2
  148. package/dist-cli/chunks/runtime-KFHRVRZQ.js +0 -2
  149. package/dist-cli/chunks/store-VOGIKQFW.js +0 -2
  150. package/dist-cli/chunks/telemetry-7TUUNCCB.js +0 -2
  151. package/dist-cli/chunks/upload-AW66MDC5.js +0 -2
@@ -1,4 +1,4 @@
1
- /*! sootsim v0.1.176 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! sootsim v0.1.177 | (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;
@@ -5530,9 +5530,9 @@ var init_registry = __esm({
5530
5530
  versions: [
5531
5531
  {
5532
5532
  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"
5533
+ coverage: 0.65,
5534
+ note: "native seam for EnrichedMarkdownText/EnrichedMarkdown/EnrichedMarkdownTextInput generated host components; upstream JS wrapper and Streamdown integration run unchanged",
5535
+ missing: "native MD4C fidelity, selection menus, spoilers, math, images, and editable rich-markdown commands are simplified"
5536
5536
  }
5537
5537
  ]
5538
5538
  },
@@ -10106,10 +10106,10 @@ function tcpPing(port, timeout = TCP_GATE_MS) {
10106
10106
  sock.connect(port, "localhost");
10107
10107
  });
10108
10108
  }
10109
- function httpGet(port, path9, method = "GET", timeout = TIMEOUT_MS, headers = {}) {
10109
+ function httpGet(port, path10, method = "GET", timeout = TIMEOUT_MS, headers = {}) {
10110
10110
  return new Promise((resolve6) => {
10111
10111
  const req = import_http.default.request(
10112
- { hostname: "localhost", port, path: path9, method, timeout, headers },
10112
+ { hostname: "localhost", port, path: path10, method, timeout, headers },
10113
10113
  (res) => {
10114
10114
  let body = "";
10115
10115
  res.on("data", (c) => body += c.toString());
@@ -11724,6 +11724,97 @@ var init_agent_sessions = __esm({
11724
11724
  }
11725
11725
  });
11726
11726
 
11727
+ // src/agent-identity.ts
11728
+ function agentbusSessionIdFromCliIdentity(identity) {
11729
+ if (!identity?.startsWith("AGENTBUS_SESSION:")) return null;
11730
+ const sessionId = identity.slice("AGENTBUS_SESSION:".length).trim();
11731
+ if (!AGENTBUS_SESSION_RE.test(sessionId)) return null;
11732
+ return sessionId;
11733
+ }
11734
+ function isValidAgentbusSessionId(sessionId) {
11735
+ return AGENTBUS_SESSION_RE.test(sessionId);
11736
+ }
11737
+ var AGENTBUS_SESSION_RE;
11738
+ var init_agent_identity = __esm({
11739
+ "src/agent-identity.ts"() {
11740
+ "use strict";
11741
+ AGENTBUS_SESSION_RE = /^[A-Za-z0-9._:-]{1,160}$/;
11742
+ }
11743
+ });
11744
+
11745
+ // src/agentbus-prompt.ts
11746
+ function formatAgentbusPromptText(prompt) {
11747
+ return typeof prompt.text === "string" ? prompt.text.trim() : "";
11748
+ }
11749
+ function resolveAgentbusCommand(explicit) {
11750
+ const fromArg = explicit?.trim();
11751
+ if (fromArg) return fromArg;
11752
+ const fromEnv = process.env.AGENTBUS_COMMAND?.trim();
11753
+ if (fromEnv) return fromEnv;
11754
+ const localBin = import_node_path4.default.join(import_node_os2.default.homedir(), ".local", "bin", "agentbus");
11755
+ if (import_node_fs5.default.existsSync(localBin)) return localBin;
11756
+ return "agentbus";
11757
+ }
11758
+ async function sendPromptToAgentbusSession(input) {
11759
+ const sessionId = input.sessionId.trim();
11760
+ if (!isValidAgentbusSessionId(sessionId)) {
11761
+ throw new Error(`invalid agentbus session id: ${sessionId || "<empty>"}`);
11762
+ }
11763
+ const text = formatAgentbusPromptText(input.prompt);
11764
+ if (!text) {
11765
+ throw new Error("prompt text is empty");
11766
+ }
11767
+ const command = resolveAgentbusCommand(input.command);
11768
+ const timeoutMs = input.timeoutMs ?? 15e3;
11769
+ await new Promise((resolve6, reject) => {
11770
+ const child = (0, import_node_child_process2.spawn)(command, ["send", sessionId, text], {
11771
+ stdio: ["ignore", "ignore", "pipe"],
11772
+ env: process.env
11773
+ });
11774
+ let stderr = "";
11775
+ const timer = setTimeout(() => {
11776
+ try {
11777
+ child.kill("SIGTERM");
11778
+ } catch {
11779
+ }
11780
+ reject(new Error(`agentbus send timed out after ${Math.round(timeoutMs / 1e3)}s`));
11781
+ }, timeoutMs);
11782
+ child.stderr?.setEncoding("utf8");
11783
+ child.stderr?.on("data", (chunk) => {
11784
+ if (stderr.length < 4e3) stderr += String(chunk);
11785
+ });
11786
+ child.on("error", (err) => {
11787
+ clearTimeout(timer);
11788
+ reject(err);
11789
+ });
11790
+ child.on("exit", (code, signal) => {
11791
+ clearTimeout(timer);
11792
+ if (code === 0) {
11793
+ resolve6();
11794
+ return;
11795
+ }
11796
+ const detail = stderr.trim();
11797
+ reject(
11798
+ new Error(
11799
+ detail || `agentbus send exited with ${signal ? `signal ${signal}` : `code ${code ?? "unknown"}`}`
11800
+ )
11801
+ );
11802
+ });
11803
+ });
11804
+ }
11805
+ var import_node_child_process2, import_node_fs5, import_node_os2, import_node_path4;
11806
+ var init_agentbus_prompt = __esm({
11807
+ "src/agentbus-prompt.ts"() {
11808
+ "use strict";
11809
+ import_node_child_process2 = require("node:child_process");
11810
+ import_node_fs5 = __toESM(require("node:fs"), 1);
11811
+ import_node_os2 = __toESM(require("node:os"), 1);
11812
+ import_node_path4 = __toESM(require("node:path"), 1);
11813
+ init_agent_identity();
11814
+ init_agent_identity();
11815
+ }
11816
+ });
11817
+
11727
11818
  // src/host/agent-host.ts
11728
11819
  function defaultExcludePorts() {
11729
11820
  return [
@@ -11738,14 +11829,15 @@ function mapFrameworkToProjectFramework(fw) {
11738
11829
  if (fw === "one" || fw === "vxrn") return "one";
11739
11830
  return "unknown";
11740
11831
  }
11741
- var import_node_fs5, import_node_path4, WS_OPEN, AgentHost;
11832
+ var import_node_fs6, import_node_path5, WS_OPEN, AgentHost;
11742
11833
  var init_agent_host = __esm({
11743
11834
  "src/host/agent-host.ts"() {
11744
11835
  "use strict";
11745
- import_node_fs5 = __toESM(require("node:fs"), 1);
11746
- import_node_path4 = __toESM(require("node:path"), 1);
11836
+ import_node_fs6 = __toESM(require("node:fs"), 1);
11837
+ import_node_path5 = __toESM(require("node:path"), 1);
11747
11838
  init_dev_server_scanner();
11748
11839
  init_agent_sessions();
11840
+ init_agentbus_prompt();
11749
11841
  init_attached_projects();
11750
11842
  WS_OPEN = 1;
11751
11843
  AgentHost = class {
@@ -11845,6 +11937,8 @@ var init_agent_host = __esm({
11845
11937
  return listSessions(msg.projectId ? String(msg.projectId) : void 0);
11846
11938
  case "agent:start-session":
11847
11939
  return this.doStartSession(msg.input ?? {});
11940
+ case "agent:send-claimed-prompt":
11941
+ return this.sendClaimedPrompt(msg);
11848
11942
  case "agent:send-prompt": {
11849
11943
  const sessionId = String(msg.sessionId);
11850
11944
  const session = findSessionById(sessionId);
@@ -11876,6 +11970,28 @@ var init_agent_host = __esm({
11876
11970
  }
11877
11971
  }
11878
11972
  // --- operation impls ---
11973
+ async sendClaimedPrompt(msg) {
11974
+ const simId = typeof msg.simId === "string" ? msg.simId.trim() : "";
11975
+ if (!simId) {
11976
+ throw new AgentSessionError("NO_SIM", "agent:send-claimed-prompt requires simId");
11977
+ }
11978
+ const lease = this.opts.resolveCliLease?.(simId) ?? null;
11979
+ if (!lease || lease.kind !== "cli" || lease.expiresAt <= Date.now()) {
11980
+ throw new AgentSessionError("NO_CLAIM", `sim ${simId} has no active CLI claim`);
11981
+ }
11982
+ const sessionId = agentbusSessionIdFromCliIdentity(lease.cliIdentityKey);
11983
+ if (!sessionId) {
11984
+ throw new AgentSessionError(
11985
+ "UNSUPPORTED_CLAIM",
11986
+ `sim ${simId} is claimed by a CLI identity that is not promptable`
11987
+ );
11988
+ }
11989
+ await sendPromptToAgentbusSession({
11990
+ sessionId,
11991
+ prompt: this.normalizePromptEnvelope(msg)
11992
+ });
11993
+ return { ok: true, routed: "agentbus", sessionId };
11994
+ }
11879
11995
  async doStartSession(input) {
11880
11996
  const project = findProjectById(input.projectId);
11881
11997
  if (!project) {
@@ -11905,7 +12021,7 @@ var init_agent_host = __esm({
11905
12021
  );
11906
12022
  const project = upsertProject({
11907
12023
  cwd: match.cwd,
11908
- name: match.projectName ?? import_node_path4.default.basename(match.cwd),
12024
+ name: match.projectName ?? import_node_path5.default.basename(match.cwd),
11909
12025
  preferredProvider: input.provider ?? existing?.preferredProvider,
11910
12026
  sourceRoots: existing?.sourceRoots ?? [match.cwd],
11911
12027
  knownBundleUrls,
@@ -11916,18 +12032,18 @@ var init_agent_host = __esm({
11916
12032
  }
11917
12033
  getTranscript(sessionId) {
11918
12034
  const p = transcriptPath(sessionId);
11919
- if (!import_node_fs5.default.existsSync(p)) {
12035
+ if (!import_node_fs6.default.existsSync(p)) {
11920
12036
  return { error: "transcript not found", code: "NO_TRANSCRIPT" };
11921
12037
  }
11922
- return import_node_fs5.default.readFileSync(p, "utf8");
12038
+ return import_node_fs6.default.readFileSync(p, "utf8");
11923
12039
  }
11924
12040
  getPaths() {
11925
12041
  const dir = getUserDataDir();
11926
12042
  return {
11927
12043
  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")
12044
+ storeFile: import_node_path5.default.join(dir, "attached-projects.json"),
12045
+ sessionsDir: import_node_path5.default.join(dir, "sessions"),
12046
+ transcriptsDir: import_node_path5.default.join(dir, "transcripts")
11931
12047
  };
11932
12048
  }
11933
12049
  // --- subscription management ---
@@ -12967,7 +13083,18 @@ var init_bridge_host = __esm({
12967
13083
  this.shouldWriteDevLockfile = opts.writeDevLockfile === true;
12968
13084
  this.portFallbackCount = Math.max(1, opts.portFallbackCount ?? 10);
12969
13085
  this.openUrlHandler = opts.openUrl;
12970
- this.agentHost = new AgentHost({ getExcludePorts: opts.agentScanExcludes });
13086
+ this.agentHost = new AgentHost({
13087
+ getExcludePorts: opts.agentScanExcludes,
13088
+ resolveCliLease: (simId) => {
13089
+ const sim = this.sims.get(simId);
13090
+ const lease = sim ? this.getActiveLease(sim) : null;
13091
+ return lease ? {
13092
+ kind: lease.kind,
13093
+ cliIdentityKey: lease.cliIdentityKey,
13094
+ expiresAt: lease.expiresAt
13095
+ } : null;
13096
+ }
13097
+ });
12971
13098
  this.sootbeanOrigin = opts.sootbeanOrigin?.replace(/\/$/, "") || null;
12972
13099
  this.simIdleReapTtlMs = opts.simIdleReapTtlMs ?? _SootSimBridgeHost.SIM_IDLE_REAP_TTL_MS;
12973
13100
  this.automationSimIdleReapTtlMs = opts.automationSimIdleReapTtlMs ?? _SootSimBridgeHost.AUTOMATION_SIM_IDLE_REAP_TTL_MS;
@@ -14787,6 +14914,8 @@ var init_current_sim = __esm({
14787
14914
  IDENTITY_ENV_VARS = [
14788
14915
  "SOOTSIM_CLI_IDENTITY",
14789
14916
  // explicit override — fastest path, skips all pid lookups
14917
+ "AGENTBUS_SESSION",
14918
+ // agentbus session id; lets sootsim route prompt-bar followups back to this agent
14790
14919
  "CLAUDE_CODE_SESSION_ID",
14791
14920
  // claude code, if ever set
14792
14921
  "CODEX_THREAD_ID",
@@ -15141,11 +15270,11 @@ async function evalInBridge(bridge, code, opts = {}) {
15141
15270
  if (opts.acquireLock) payload.acquireLock = true;
15142
15271
  return bridge.send(payload);
15143
15272
  }
15144
- async function callInBridge(bridge, path9, ...args) {
15145
- return bridge.send({ type: "call", path: path9, args });
15273
+ async function callInBridge(bridge, path10, ...args) {
15274
+ return bridge.send({ type: "call", path: path10, args });
15146
15275
  }
15147
- async function callInBridgeWrite(bridge, path9, ...args) {
15148
- return bridge.send({ type: "call", path: path9, args, acquireLock: true });
15276
+ async function callInBridgeWrite(bridge, path10, ...args) {
15277
+ return bridge.send({ type: "call", path: path10, args, acquireLock: true });
15149
15278
  }
15150
15279
  var import_ws3, BridgeSimLockedError;
15151
15280
  var init_ws_bridge = __esm({
@@ -16148,14 +16277,14 @@ process.stdin.on('end', async () => {
16148
16277
  function getBaseDir() {
16149
16278
  const explicit = process.env[SESSION_FILE_ENV];
16150
16279
  if (explicit?.trim()) {
16151
- return (0, import_node_path5.dirname)((0, import_node_path5.resolve)(explicit));
16280
+ return (0, import_node_path6.dirname)((0, import_node_path6.resolve)(explicit));
16152
16281
  }
16153
16282
  return electronUserDataDir();
16154
16283
  }
16155
16284
  function getSharedDesktopAuthFilePath() {
16156
16285
  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");
16286
+ if (explicit?.trim()) return (0, import_node_path6.resolve)(explicit);
16287
+ return (0, import_node_path6.join)(getBaseDir(), "desktop-auth.json");
16159
16288
  }
16160
16289
  function normalizeUser(input) {
16161
16290
  if (!input || typeof input !== "object") return null;
@@ -16201,26 +16330,26 @@ function normalizeSession(input) {
16201
16330
  }
16202
16331
  function readSharedDesktopAuthSession() {
16203
16332
  const filepath = getSharedDesktopAuthFilePath();
16204
- if (!(0, import_node_fs6.existsSync)(filepath)) return null;
16333
+ if (!(0, import_node_fs7.existsSync)(filepath)) return null;
16205
16334
  try {
16206
- const parsed = JSON.parse((0, import_node_fs6.readFileSync)(filepath, "utf8"));
16335
+ const parsed = JSON.parse((0, import_node_fs7.readFileSync)(filepath, "utf8"));
16207
16336
  const normalized = normalizeSession(parsed);
16208
16337
  if (!normalized) {
16209
- (0, import_node_fs6.rmSync)(filepath, { force: true });
16338
+ (0, import_node_fs7.rmSync)(filepath, { force: true });
16210
16339
  return null;
16211
16340
  }
16212
16341
  return normalized;
16213
16342
  } catch {
16214
- (0, import_node_fs6.rmSync)(filepath, { force: true });
16343
+ (0, import_node_fs7.rmSync)(filepath, { force: true });
16215
16344
  return null;
16216
16345
  }
16217
16346
  }
16218
- var import_node_fs6, import_node_path5, SESSION_VERSION, SESSION_FILE_ENV, DEFAULT_ORIGIN;
16347
+ var import_node_fs7, import_node_path6, SESSION_VERSION, SESSION_FILE_ENV, DEFAULT_ORIGIN;
16219
16348
  var init_shared_session = __esm({
16220
16349
  "src/auth/shared-session.ts"() {
16221
16350
  "use strict";
16222
- import_node_fs6 = require("node:fs");
16223
- import_node_path5 = require("node:path");
16351
+ import_node_fs7 = require("node:fs");
16352
+ import_node_path6 = require("node:path");
16224
16353
  init_home_paths();
16225
16354
  SESSION_VERSION = 1;
16226
16355
  SESSION_FILE_ENV = "SOOTSIM_SHARED_AUTH_FILE";
@@ -16230,13 +16359,13 @@ var init_shared_session = __esm({
16230
16359
 
16231
16360
  // cli/auth.ts
16232
16361
  function credentialsPath() {
16233
- return (0, import_node_path6.join)(electronUserDataDir(), "credentials.json");
16362
+ return (0, import_node_path7.join)(electronUserDataDir(), "credentials.json");
16234
16363
  }
16235
16364
  function readStoredApiKey() {
16236
16365
  const file = credentialsPath();
16237
- if (!(0, import_node_fs7.existsSync)(file)) return null;
16366
+ if (!(0, import_node_fs8.existsSync)(file)) return null;
16238
16367
  try {
16239
- const parsed = JSON.parse((0, import_node_fs7.readFileSync)(file, "utf8"));
16368
+ const parsed = JSON.parse((0, import_node_fs8.readFileSync)(file, "utf8"));
16240
16369
  if (parsed.version !== 1) return null;
16241
16370
  if (typeof parsed.apiKey !== "string" || !parsed.apiKey.startsWith("sk_sootsim_")) {
16242
16371
  return null;
@@ -16292,12 +16421,12 @@ function resolveCliAuth() {
16292
16421
  function authHeaderValue(auth) {
16293
16422
  return auth.kind === "api-key" ? `Bearer ${auth.secret}` : `Bearer ${auth.token}`;
16294
16423
  }
16295
- var import_node_fs7, import_node_path6, GITHUB_TOKEN_PREFIXES;
16424
+ var import_node_fs8, import_node_path7, GITHUB_TOKEN_PREFIXES;
16296
16425
  var init_auth = __esm({
16297
16426
  "cli/auth.ts"() {
16298
16427
  "use strict";
16299
- import_node_fs7 = require("node:fs");
16300
- import_node_path6 = require("node:path");
16428
+ import_node_fs8 = require("node:fs");
16429
+ import_node_path7 = require("node:path");
16301
16430
  init_shared_session();
16302
16431
  init_home_paths();
16303
16432
  GITHUB_TOKEN_PREFIXES = ["ghs_", "ghp_", "gho_", "ghu_", "github_pat_"];
@@ -16487,16 +16616,16 @@ function resolveFlowScreenshotPath(screenshotDir, name) {
16487
16616
  }
16488
16617
  function resolveProjectRelativeFlowBase(flowDir) {
16489
16618
  if (!flowDir) return process.cwd();
16490
- return path7.basename(flowDir) === ".maestro" ? path7.dirname(flowDir) : flowDir;
16619
+ return path8.basename(flowDir) === ".maestro" ? path8.dirname(flowDir) : flowDir;
16491
16620
  }
16492
16621
  function resolveFlowScreenshotPathWithMode(screenshotDir, name, opts) {
16493
16622
  const normalizedName = name.endsWith(".png") ? name : `${name}.png`;
16494
- if (path7.isAbsolute(normalizedName)) return normalizedName;
16623
+ if (path8.isAbsolute(normalizedName)) return normalizedName;
16495
16624
  if (opts.mode === "flow" && /[\\/]/.test(normalizedName)) {
16496
16625
  const baseDir = normalizedName.startsWith("./") || normalizedName.startsWith("../") ? opts.flowDir ?? process.cwd() : resolveProjectRelativeFlowBase(opts.flowDir);
16497
- return path7.resolve(baseDir, normalizedName);
16626
+ return path8.resolve(baseDir, normalizedName);
16498
16627
  }
16499
- return path7.join(screenshotDir, normalizedName);
16628
+ return path8.join(screenshotDir, normalizedName);
16500
16629
  }
16501
16630
  function normalizeFlowScreenshotSpec(step) {
16502
16631
  if (typeof step === "string") {
@@ -16551,12 +16680,12 @@ function parseFlowSteps(content) {
16551
16680
  const parsed = import_yaml.default.parse(candidate);
16552
16681
  return Array.isArray(parsed) ? parsed : [];
16553
16682
  }
16554
- var fs7, path7, import_settings2, import_yaml, DEFAULT_TIMEOUT, SCREEN_W, SCREEN_H, CLI_PERF_SESSION_GLOBAL, SootSimBridgeFlowRunner;
16683
+ var fs8, path8, import_settings2, import_yaml, DEFAULT_TIMEOUT, SCREEN_W, SCREEN_H, CLI_PERF_SESSION_GLOBAL, SootSimBridgeFlowRunner;
16555
16684
  var init_bridge_flow_runner = __esm({
16556
16685
  "cli/bridge-flow-runner.ts"() {
16557
16686
  "use strict";
16558
- fs7 = __toESM(require("fs"), 1);
16559
- path7 = __toESM(require("path"), 1);
16687
+ fs8 = __toESM(require("fs"), 1);
16688
+ path8 = __toESM(require("path"), 1);
16560
16689
  import_settings2 = require("sootsim-engine/settings");
16561
16690
  import_yaml = __toESM(require("yaml"), 1);
16562
16691
  init_frame_compose();
@@ -16778,14 +16907,14 @@ var init_bridge_flow_runner = __esm({
16778
16907
  if (chunks.length === 0) {
16779
16908
  throw new Error("recording requested but no video buffer was produced");
16780
16909
  }
16781
- fs7.mkdirSync(this.opts.recordingOutputDir, { recursive: true });
16910
+ fs8.mkdirSync(this.opts.recordingOutputDir, { recursive: true });
16782
16911
  const videoMime = stopped.mime || this.opts.recordingFormat || "video/webm";
16783
16912
  const extension = videoMime.includes("mp4") ? "mp4" : "webm";
16784
- const outputPath = path7.join(
16913
+ const outputPath = path8.join(
16785
16914
  this.opts.recordingOutputDir,
16786
16915
  `sootsim-${Date.now()}.${extension}`
16787
16916
  );
16788
- fs7.writeFileSync(outputPath, Buffer.concat(chunks));
16917
+ fs8.writeFileSync(outputPath, Buffer.concat(chunks));
16789
16918
  return outputPath;
16790
16919
  }
16791
16920
  async waitForRecordingTail(opts) {
@@ -17198,7 +17327,7 @@ var init_bridge_flow_runner = __esm({
17198
17327
  flowDir: this.opts.flowDir
17199
17328
  }
17200
17329
  );
17201
- fs7.mkdirSync(path7.dirname(outputPath), { recursive: true });
17330
+ fs8.mkdirSync(path8.dirname(outputPath), { recursive: true });
17202
17331
  const layers = spec.layers ?? this.opts.screenshotLayers;
17203
17332
  const screenshotRequest = {
17204
17333
  type: "screenshot",
@@ -17214,11 +17343,11 @@ var init_bridge_flow_runner = __esm({
17214
17343
  throw new Error("could not read current device model for framed screenshot");
17215
17344
  }
17216
17345
  const framed = await composeFramedScreenshot(rawBuffer, model);
17217
- fs7.writeFileSync(outputPath, framed);
17346
+ fs8.writeFileSync(outputPath, framed);
17218
17347
  console.log(`[flow] screenshot: ${outputPath} (frame: ${model})`);
17219
17348
  return;
17220
17349
  }
17221
- fs7.writeFileSync(outputPath, rawBuffer);
17350
+ fs8.writeFileSync(outputPath, rawBuffer);
17222
17351
  console.log(`[flow] screenshot: ${outputPath}`);
17223
17352
  }
17224
17353
  async readCurrentDeviceModel() {
@@ -17233,22 +17362,22 @@ var init_bridge_flow_runner = __esm({
17233
17362
  return model;
17234
17363
  }
17235
17364
  async captureFailureScreenshot(outputPath) {
17236
- fs7.mkdirSync(path7.dirname(outputPath), { recursive: true });
17365
+ fs8.mkdirSync(path8.dirname(outputPath), { recursive: true });
17237
17366
  const dataUrl = await this.bridge.send({
17238
17367
  type: "screenshot",
17239
17368
  simId: this.opts.simId
17240
17369
  });
17241
17370
  const base64 = dataUrl.replace(/^data:image\/png;base64,/, "");
17242
- fs7.writeFileSync(outputPath, Buffer.from(base64, "base64"));
17371
+ fs8.writeFileSync(outputPath, Buffer.from(base64, "base64"));
17243
17372
  }
17244
17373
  // writes a per-failure debug bundle: screenshot + structured describe
17245
17374
  // + a11y tree + console errors/warnings + failed network requests +
17246
17375
  // shell state, all under one directory so post-mortem is one grep away.
17247
17376
  async captureFailureBundle(outputDir, context) {
17248
- fs7.mkdirSync(outputDir, { recursive: true });
17377
+ fs8.mkdirSync(outputDir, { recursive: true });
17249
17378
  const write = (name, content) => {
17250
17379
  try {
17251
- fs7.writeFileSync(path7.join(outputDir, name), content);
17380
+ fs8.writeFileSync(path8.join(outputDir, name), content);
17252
17381
  } catch {
17253
17382
  }
17254
17383
  };
@@ -17749,8 +17878,8 @@ var init_bridge_flow_runner = __esm({
17749
17878
  runScript(target) {
17750
17879
  const spec = typeof target === "string" ? { file: target } : target;
17751
17880
  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");
17881
+ const scriptPath = path8.resolve(this.opts.flowDir, spec.file);
17882
+ const source = fs8.readFileSync(scriptPath, "utf8");
17754
17883
  this.js.evaluate(source, { env: spec.env });
17755
17884
  console.log(`[flow] runScript: ${spec.file} done`);
17756
17885
  }
@@ -17989,10 +18118,10 @@ var init_bridge_flow_runner = __esm({
17989
18118
  for (const [k, v] of Object.entries(env)) this.js.putEnv(k, v);
17990
18119
  }
17991
18120
  if (file) {
17992
- const flowPath = path7.resolve(this.opts.flowDir, file);
17993
- const flowContent = fs7.readFileSync(flowPath, "utf8");
18121
+ const flowPath = path8.resolve(this.opts.flowDir, file);
18122
+ const flowContent = fs8.readFileSync(flowPath, "utf8");
17994
18123
  const previousDir = this.opts.flowDir;
17995
- this.opts.flowDir = path7.dirname(flowPath);
18124
+ this.opts.flowDir = path8.dirname(flowPath);
17996
18125
  try {
17997
18126
  await this.runFlow(parseFlowSteps(flowContent));
17998
18127
  } finally {
@@ -18088,8 +18217,8 @@ __export(registry_exports, {
18088
18217
  skillRegistry: () => skillRegistry
18089
18218
  });
18090
18219
  module.exports = __toCommonJS(registry_exports);
18091
- var fs8 = __toESM(require("fs"), 1);
18092
- var path8 = __toESM(require("path"), 1);
18220
+ var fs9 = __toESM(require("fs"), 1);
18221
+ var path9 = __toESM(require("path"), 1);
18093
18222
 
18094
18223
  // src/skills/builtin/a11y-review.ts
18095
18224
  var skill = {
@@ -18107,8 +18236,8 @@ var skill = {
18107
18236
  },
18108
18237
  async execute(params, context) {
18109
18238
  const { chromium } = await import("playwright");
18110
- const path9 = await import("path");
18111
- const fs9 = await import("fs");
18239
+ const path10 = await import("path");
18240
+ const fs10 = await import("fs");
18112
18241
  const browser = await chromium.launch({ channel: "chrome", headless: true });
18113
18242
  const page = await browser.newPage({ viewport: { width: 500, height: 900 } });
18114
18243
  try {
@@ -18161,9 +18290,9 @@ var skill = {
18161
18290
  warnings: issues.filter((i) => i.severity === "warning").length,
18162
18291
  tree: typeof tree === "string" ? tree : JSON.stringify(tree)
18163
18292
  };
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));
18293
+ const reportPath = path10.join(context.outputDir, "a11y-report.json");
18294
+ fs10.mkdirSync(path10.dirname(reportPath), { recursive: true });
18295
+ fs10.writeFileSync(reportPath, JSON.stringify(report, null, 2));
18167
18296
  return {
18168
18297
  success: issues.filter((i) => i.severity === "error").length === 0,
18169
18298
  message: `${report.errors} errors, ${report.warnings} warnings across ${report.nodeCount} nodes`,
@@ -18201,8 +18330,8 @@ var skill2 = {
18201
18330
  }
18202
18331
  },
18203
18332
  async execute(params, context) {
18204
- const fs9 = await import("fs");
18205
- const path9 = await import("path");
18333
+ const fs10 = await import("fs");
18334
+ const path10 = await import("path");
18206
18335
  const { POLYFILL_REGISTRY: POLYFILL_REGISTRY2 } = await Promise.resolve().then(() => (init_web(), web_exports));
18207
18336
  if (params.packageName) {
18208
18337
  const entry = POLYFILL_REGISTRY2[params.packageName];
@@ -18220,11 +18349,11 @@ var skill2 = {
18220
18349
  data: { package: params.packageName, status, ...entry }
18221
18350
  };
18222
18351
  }
18223
- const pkgPath = path9.join(context.projectDir, "package.json");
18224
- if (!fs9.existsSync(pkgPath)) {
18352
+ const pkgPath = path10.join(context.projectDir, "package.json");
18353
+ if (!fs10.existsSync(pkgPath)) {
18225
18354
  return { success: false, message: "No package.json found" };
18226
18355
  }
18227
- const pkg = JSON.parse(fs9.readFileSync(pkgPath, "utf8"));
18356
+ const pkg = JSON.parse(fs10.readFileSync(pkgPath, "utf8"));
18228
18357
  const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
18229
18358
  const results = {
18230
18359
  full: [],
@@ -18242,9 +18371,9 @@ var skill2 = {
18242
18371
  results.unknown.push(dep);
18243
18372
  }
18244
18373
  }
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));
18374
+ const reportPath = path10.join(context.outputDir, "compat-report.json");
18375
+ fs10.mkdirSync(path10.dirname(reportPath), { recursive: true });
18376
+ fs10.writeFileSync(reportPath, JSON.stringify(results, null, 2));
18248
18377
  return {
18249
18378
  success: results.unsupported.length === 0,
18250
18379
  message: `${results.full.length} full, ${results.partial.length} partial, ${results.unsupported.length} unsupported, ${results.unknown.length} unknown`,
@@ -18282,8 +18411,8 @@ var skill3 = {
18282
18411
  },
18283
18412
  async execute(params, context) {
18284
18413
  const { chromium } = await import("playwright");
18285
- const path9 = await import("path");
18286
- const fs9 = await import("fs");
18414
+ const path10 = await import("path");
18415
+ const fs10 = await import("fs");
18287
18416
  const browser = await chromium.launch({ channel: "chrome", headless: true });
18288
18417
  const page = await browser.newPage({ viewport: { width: 500, height: 900 } });
18289
18418
  try {
@@ -18307,9 +18436,9 @@ var skill3 = {
18307
18436
  ...profile,
18308
18437
  fps: syncCount > 0 ? (syncCount / (duration / 1e3)).toFixed(1) : "0"
18309
18438
  };
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));
18439
+ const reportPath = path10.join(context.outputDir, "perf-report.json");
18440
+ fs10.mkdirSync(path10.dirname(reportPath), { recursive: true });
18441
+ fs10.writeFileSync(reportPath, JSON.stringify(report, null, 2));
18313
18442
  return {
18314
18443
  success: true,
18315
18444
  message: `${report.fps} fps, ${profile.avgSyncMs?.toFixed(1)}ms avg sync, ${nodeCount} nodes`,
@@ -18341,15 +18470,15 @@ var skill4 = {
18341
18470
  },
18342
18471
  async execute(params, context) {
18343
18472
  const { chromium } = await import("playwright");
18344
- const path9 = await import("path");
18345
- const fs9 = await import("fs");
18473
+ const path10 = await import("path");
18474
+ const fs10 = await import("fs");
18346
18475
  const browser = await chromium.launch({ channel: "chrome", headless: true });
18347
18476
  const page = await browser.newPage({ viewport: { width: 500, height: 900 } });
18348
18477
  try {
18349
18478
  await page.goto(context.url, { waitUntil: "networkidle" });
18350
18479
  await page.waitForTimeout(2e3);
18351
- const outputPath = path9.join(context.outputDir, `${params.name}.png`);
18352
- fs9.mkdirSync(path9.dirname(outputPath), { recursive: true });
18480
+ const outputPath = path10.join(context.outputDir, `${params.name}.png`);
18481
+ fs10.mkdirSync(path10.dirname(outputPath), { recursive: true });
18353
18482
  await page.screenshot({ path: outputPath });
18354
18483
  return {
18355
18484
  success: true,
@@ -18387,8 +18516,8 @@ var skill5 = {
18387
18516
  record: { type: "boolean", description: "Record video of the flow" }
18388
18517
  },
18389
18518
  async execute(params, context) {
18390
- const fs9 = await import("fs");
18391
- const path9 = await import("path");
18519
+ const fs10 = await import("fs");
18520
+ const path10 = await import("path");
18392
18521
  const yaml2 = await import("yaml");
18393
18522
  const { DEFAULT_SOOTSIM_BRIDGE_PORT: DEFAULT_SOOTSIM_BRIDGE_PORT2 } = await Promise.resolve().then(() => (init_bridge_constants(), bridge_constants_exports));
18394
18523
  const { SootSimBridgeHost: SootSimBridgeHost2 } = await Promise.resolve().then(() => (init_bridge_host(), bridge_host_exports));
@@ -18397,7 +18526,7 @@ var skill5 = {
18397
18526
  const host = new SootSimBridgeHost2({ port: DEFAULT_SOOTSIM_BRIDGE_PORT2 });
18398
18527
  host.start({ silent: true });
18399
18528
  try {
18400
- const flowContent = fs9.readFileSync(params.flowPath, "utf8");
18529
+ const flowContent = fs10.readFileSync(params.flowPath, "utf8");
18401
18530
  const fmMatch = flowContent.match(/^---\n([\s\S]*?)\n---\n?/);
18402
18531
  const stepsBody = fmMatch ? flowContent.slice(fmMatch[0].length) : flowContent;
18403
18532
  const steps = yaml2.parse(stepsBody);
@@ -18422,7 +18551,7 @@ var skill5 = {
18422
18551
  });
18423
18552
  const driver = new SootSimBridgeFlowRunner2(bridge, {
18424
18553
  screenshotDir: context.outputDir,
18425
- flowDir: path9.dirname(path9.resolve(params.flowPath)),
18554
+ flowDir: path10.dirname(path10.resolve(params.flowPath)),
18426
18555
  simId,
18427
18556
  recordingOutputDir: params.record ? context.outputDir : void 0
18428
18557
  });
@@ -18444,7 +18573,7 @@ var skill5 = {
18444
18573
  simId,
18445
18574
  videoPath: videoPath || void 0
18446
18575
  },
18447
- artifacts: videoPath ? [{ type: "video", name: path9.basename(videoPath), path: videoPath }] : void 0
18576
+ artifacts: videoPath ? [{ type: "video", name: path10.basename(videoPath), path: videoPath }] : void 0
18448
18577
  };
18449
18578
  } finally {
18450
18579
  try {
@@ -18492,21 +18621,21 @@ var skill6 = {
18492
18621
  },
18493
18622
  async execute(params, context) {
18494
18623
  const { chromium } = await import("playwright");
18495
- const path9 = await import("path");
18496
- const fs9 = await import("fs");
18624
+ const path10 = await import("path");
18625
+ const fs10 = await import("fs");
18497
18626
  const browser = await chromium.launch({ channel: "chrome", headless: true });
18498
18627
  const page = await browser.newPage({ viewport: { width: 500, height: 900 } });
18499
18628
  try {
18500
18629
  await page.goto(context.url, { waitUntil: "networkidle" });
18501
18630
  await page.waitForTimeout(2e3);
18502
- const currentPath = path9.join(context.outputDir, `${params.name}-current.png`);
18503
- fs9.mkdirSync(path9.dirname(currentPath), { recursive: true });
18631
+ const currentPath = path10.join(context.outputDir, `${params.name}-current.png`);
18632
+ fs10.mkdirSync(path10.dirname(currentPath), { recursive: true });
18504
18633
  await page.screenshot({ path: currentPath });
18505
18634
  try {
18506
18635
  const { PNG } = await import("pngjs");
18507
18636
  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));
18637
+ const baseline = PNG.sync.read(fs10.readFileSync(params.baseline));
18638
+ const current = PNG.sync.read(fs10.readFileSync(currentPath));
18510
18639
  const { width, height } = baseline;
18511
18640
  const diff = new PNG({ width, height });
18512
18641
  const numDiffPixels = pixelmatch(
@@ -18517,8 +18646,8 @@ var skill6 = {
18517
18646
  height,
18518
18647
  { threshold: params.threshold || 0.1 }
18519
18648
  );
18520
- const diffPath = path9.join(context.outputDir, `${params.name}-diff.png`);
18521
- fs9.writeFileSync(diffPath, PNG.sync.write(diff));
18649
+ const diffPath = path10.join(context.outputDir, `${params.name}-diff.png`);
18650
+ fs10.writeFileSync(diffPath, PNG.sync.write(diff));
18522
18651
  const totalPixels = width * height;
18523
18652
  const diffPercent = (numDiffPixels / totalPixels * 100).toFixed(2);
18524
18653
  return {
@@ -18582,10 +18711,10 @@ var skillRegistry = {
18582
18711
  },
18583
18712
  // load skills from a project manifest (sootsim-skills.json)
18584
18713
  async loadFromManifest(projectDir) {
18585
- const manifestPath = path8.join(projectDir, "sootsim-skills.json");
18586
- if (!fs8.existsSync(manifestPath)) return;
18714
+ const manifestPath = path9.join(projectDir, "sootsim-skills.json");
18715
+ if (!fs9.existsSync(manifestPath)) return;
18587
18716
  try {
18588
- const manifest = JSON.parse(fs8.readFileSync(manifestPath, "utf8"));
18717
+ const manifest = JSON.parse(fs9.readFileSync(manifestPath, "utf8"));
18589
18718
  if (Array.isArray(manifest.skills)) {
18590
18719
  for (const entry of manifest.skills) {
18591
18720
  if (typeof entry === "string") {
@@ -18596,7 +18725,7 @@ var skillRegistry = {
18596
18725
  }
18597
18726
  } else if (entry.file) {
18598
18727
  try {
18599
- const mod = await import(path8.resolve(projectDir, entry.file));
18728
+ const mod = await import(path9.resolve(projectDir, entry.file));
18600
18729
  if (mod.skill) this.register(mod.skill);
18601
18730
  } catch {
18602
18731
  }
@@ -18609,10 +18738,10 @@ var skillRegistry = {
18609
18738
  // auto-discover skills based on project dependencies
18610
18739
  suggestSkills(projectDir) {
18611
18740
  const suggestions = [];
18612
- const pkgPath = path8.join(projectDir, "package.json");
18613
- if (!fs8.existsSync(pkgPath)) return suggestions;
18741
+ const pkgPath = path9.join(projectDir, "package.json");
18742
+ if (!fs9.existsSync(pkgPath)) return suggestions;
18614
18743
  try {
18615
- const pkg = JSON.parse(fs8.readFileSync(pkgPath, "utf8"));
18744
+ const pkg = JSON.parse(fs9.readFileSync(pkgPath, "utf8"));
18616
18745
  const deps = { ...pkg.dependencies, ...pkg.devDependencies };
18617
18746
  if (deps["detox"] || deps["maestro"]) {
18618
18747
  suggestions.push("test-flow");