@openscout/scout 0.2.76 → 0.2.78

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 (372) hide show
  1. package/README.md +41 -2
  2. package/bin/openscout-runtime.mjs +48 -30
  3. package/bin/scout.mjs +2 -2
  4. package/bin/scoutd +0 -0
  5. package/dist/build-manifest.json +3 -3
  6. package/dist/client/assets/ActivityScreen-Cu_1V4bq.js +1 -0
  7. package/dist/client/assets/AddProjectForm-DMnobKch.js +1 -0
  8. package/dist/client/assets/AgentAvatar-D90c1Rzk.js +1 -0
  9. package/dist/client/assets/AgentConfigurationScreen-BqfOz90D.js +1 -0
  10. package/dist/client/assets/AgentDefinitionsWorkspace-CUpUrY57.js +1 -0
  11. package/dist/client/assets/AgentDetailCard-BcRBRp88.js +1 -0
  12. package/dist/client/assets/AgentDetailCard-C4WVeJvJ.css +1 -0
  13. package/dist/client/assets/AgentFloorView-8LoAEBwS.js +1 -0
  14. package/dist/client/assets/AgentInfoScreen-DZs2_ibL.js +1 -0
  15. package/dist/client/assets/AgentLaneCard-RrNnDZu8.js +1 -0
  16. package/dist/client/assets/AgentLaneChrome-D9ZwUKrl.js +1 -0
  17. package/dist/client/assets/AgentLaneDetailSheet-BXbPls9N.js +5 -0
  18. package/dist/client/assets/AgentLaneSummaryResize-BhFmGNzT.js +1 -0
  19. package/dist/client/assets/AgentLanesEmbedScreen-W3qs022h.js +1 -0
  20. package/dist/client/assets/AgentLanesPreflight-eSAoDsPi.js +1 -0
  21. package/dist/client/assets/AgentLanesView-B9vuEEmZ.js +2 -0
  22. package/dist/client/assets/AgentLiveActions-CGS-Bxb7.css +1 -0
  23. package/dist/client/assets/AgentLiveActions-DBtnD0qE.js +1 -0
  24. package/dist/client/assets/AgentSessions-DyqOf4nG.js +6 -0
  25. package/dist/client/assets/AgentsConsole-BgiYP2wR.js +1 -0
  26. package/dist/client/assets/AgentsConsole-BjSTs-TV.css +1 -0
  27. package/dist/client/assets/AgentsScreen-DBi8x4MB.js +1 -0
  28. package/dist/client/assets/AgentsSubnav-DIEO4NPx.js +1 -0
  29. package/dist/client/assets/AtopView-BCkae3e1.js +1 -0
  30. package/dist/client/assets/BackToPicker-BRvfostO.js +1 -0
  31. package/dist/client/assets/BackToPicker-CdgVu-to.css +1 -0
  32. package/dist/client/assets/BriefingDetailScreen-BwFyysT8.js +6 -0
  33. package/dist/client/assets/BriefingsScreen-BQEevztH.js +1 -0
  34. package/dist/client/assets/BrokerMetadataPanel-7UjcuNjd.js +1 -0
  35. package/dist/client/assets/BrokerScreen-7ekklu88.js +5 -0
  36. package/dist/client/assets/ChatCollapsedStrip-CQSYSd8s.js +1 -0
  37. package/dist/client/assets/CodeDiffPane-DDPt6KPh.js +1 -0
  38. package/dist/client/assets/CodeProjectPicker-DqKFCpLU.js +2 -0
  39. package/dist/client/assets/CodeScreen-BxCrpRHd.js +1 -0
  40. package/dist/client/assets/ContextMenu-bARZqTzD.js +1 -0
  41. package/dist/client/assets/ConversationComposer-Bla3DDvM.js +1 -0
  42. package/dist/client/assets/ConversationFeedRows-B_gPxcqA.js +1 -0
  43. package/dist/client/assets/ConversationHeader-DE3FC0m-.js +1 -0
  44. package/dist/client/assets/ConversationPanels-DLek4H6A.js +2 -0
  45. package/dist/client/assets/ConversationScreen-BDRhx-RU.js +1 -0
  46. package/dist/client/assets/ConversationScreen-C9yMAMYF.css +1 -0
  47. package/dist/client/assets/ConversationStatus-BwVLiiO4.js +1 -0
  48. package/dist/client/assets/DataTable-E8s_MmoA.js +1 -0
  49. package/dist/client/assets/DispatchAftermath-Dpe88DFX.js +1 -0
  50. package/dist/client/assets/DocumentFocusViewer-BeVwwl26.js +1 -0
  51. package/dist/client/assets/EmbeddableSurfacesLab-BQqFQVnI.js +1 -0
  52. package/dist/client/assets/EmptyState-4F9XDFQm.js +1 -0
  53. package/dist/client/assets/FileViewerPane-CLgUhSm4.js +3 -0
  54. package/dist/client/assets/FleetSearch-Dz5euQJe.js +1 -0
  55. package/dist/client/assets/FleetSearch-EXOe8ulE.css +1 -0
  56. package/dist/client/assets/FlightObserveScreen-6RpZYwVz.js +1 -0
  57. package/dist/client/assets/FollowScreen-DZ4qfYOY.js +1 -0
  58. package/dist/client/assets/HarnessMark-Cbv3Ib0c.js +1 -0
  59. package/dist/client/assets/HarnessesScreen-CznAImej.js +1 -0
  60. package/dist/client/assets/HomeHero-B3uYd-pP.js +1 -0
  61. package/dist/client/assets/HomeHero-DEl-WBsT.css +1 -0
  62. package/dist/client/assets/KnowledgeSearchInspector-Dgdkfvvz.js +1 -0
  63. package/dist/client/assets/KnowledgeSearchScreen-DJDGGaqC.js +1 -0
  64. package/dist/client/assets/LaneToolHoverCard-Bla0gBdm.js +1 -0
  65. package/dist/client/assets/LaneTraceDetailSheet-D1CspRbl.js +1 -0
  66. package/dist/client/assets/LaneTraceEventFocus-BF9ERP5O.js +1 -0
  67. package/dist/client/assets/MeshCanvas-DFEPkpqY.js +3 -0
  68. package/dist/client/assets/MeshCanvasMinimap-CyVFYixr.js +1 -0
  69. package/dist/client/assets/MeshCanvasMinimap-Dv7nMbl5.css +1 -0
  70. package/dist/client/assets/MeshScreen-DFgevn8N.js +1 -0
  71. package/dist/client/assets/MeshTopologyView-CalkZghg.js +2 -0
  72. package/dist/client/assets/MessageComposerSuggestions-DpxN9WiB.js +1 -0
  73. package/dist/client/assets/MessagesScreen-C8YKW10Y.js +1 -0
  74. package/dist/client/assets/MissionControlView-lUeAiSVg.js +1 -0
  75. package/dist/client/assets/MissionFocusOverlay-wlCmWDCT.js +1 -0
  76. package/dist/client/assets/MissionLeftAgentRow-BpZWntfl.js +1 -0
  77. package/dist/client/assets/MissionLogPane-__MVtEl9.js +1 -0
  78. package/dist/client/assets/NewAgentModal-Bg-eWHpY.js +1 -0
  79. package/dist/client/assets/NewAgentModal-ru8u5YdJ.css +1 -0
  80. package/dist/client/assets/NewChatComposer-Cs6OsxK6.js +19 -0
  81. package/dist/client/assets/NewChatComposer-W-t-L4oV.css +1 -0
  82. package/dist/client/assets/NewChatOrigin-Bk2OyVjI.js +1 -0
  83. package/dist/client/assets/ObserveEmbedScreen-y2EpuqRZ.js +2 -0
  84. package/dist/client/assets/ObserveTextFlow-rsFj_rVo.js +2 -0
  85. package/dist/client/assets/ObservedTopologyPanel-BsBsvVPL.css +1 -0
  86. package/dist/client/assets/ObservedTopologyPanel-DyUeV98H.js +2 -0
  87. package/dist/client/assets/OpenScoutAppShell-Bh6FnEJO.css +1 -0
  88. package/dist/client/assets/OpenScoutAppShell-C_URc8sV.js +87 -0
  89. package/dist/client/assets/OpsAgentsView-UN7iOscs.js +1 -0
  90. package/dist/client/assets/OpsScreen-Buf3LKjb.js +1 -0
  91. package/dist/client/assets/OpsSubnav-DsuXzHah.js +1 -0
  92. package/dist/client/assets/PlanView-C1CjH3PG.js +1 -0
  93. package/dist/client/assets/ProjectAgentProfile-DJusrAV-.js +1 -0
  94. package/dist/client/assets/ProjectAgentProfileBar-CtTpj6fU.js +1 -0
  95. package/dist/client/assets/ProjectAgentProfileHero-BFwNJo_N.js +1 -0
  96. package/dist/client/assets/ProjectsInbox-GhVMxOhw.js +2 -0
  97. package/dist/client/assets/ProjectsRail-BgiuV4LR.js +1 -0
  98. package/dist/client/assets/ProjectsScreen-eNUBy4YU.js +1 -0
  99. package/dist/client/assets/ProjectsThreadAside-CoBgnHmr.js +1 -0
  100. package/dist/client/assets/Provider-C7UKGHQy.js +1 -0
  101. package/dist/client/assets/Provider-CCzjtkda.css +1 -0
  102. package/dist/client/assets/RailRow-BoGxAHNF.js +1 -0
  103. package/dist/client/assets/RailRow-Cf9LOiEj.css +1 -0
  104. package/dist/client/assets/RawSessionsTable-DL8y_eEy.js +1 -0
  105. package/dist/client/assets/RealtimeVoiceScreen-ffS-39zy.js +1 -0
  106. package/dist/client/assets/RepoDiffEmbedScreen-C0rumUME.js +1 -0
  107. package/dist/client/assets/RepoDiffPageScreen-DMv6DioL.js +1 -0
  108. package/dist/client/assets/RepoDiffViewer-D_exm6xK.js +7 -0
  109. package/dist/client/assets/RepoDiffViewerLazy-BPgF92Bg.js +2 -0
  110. package/dist/client/assets/ReposScreen-CB_YBWYf.js +6 -0
  111. package/dist/client/assets/ScoutDeckSurface-CxIYFyWx.js +1 -0
  112. package/dist/client/assets/ScoutDeckSurface-uhmuZRzC.css +1 -0
  113. package/dist/client/assets/ScoutSurface-CYz_TcWC.js +1 -0
  114. package/dist/client/assets/ScoutbotBroadcastChip-CxtYZWPZ.css +1 -0
  115. package/dist/client/assets/ScoutbotBroadcastChip-L_R9atj0.js +2 -0
  116. package/dist/client/assets/ScoutbotFxLab-CgiZMDMW.js +4 -0
  117. package/dist/client/assets/ScoutbotRealtimeVoiceCall-FMQOr1Np.js +1 -0
  118. package/dist/client/assets/SecondaryNav-B3-nh5dM.js +1 -0
  119. package/dist/client/assets/SessionEmbedScreen-BVC7yvWF.js +1 -0
  120. package/dist/client/assets/SessionObserve-BpggNO_M.css +1 -0
  121. package/dist/client/assets/SessionObserve-yfXFafp8.js +12 -0
  122. package/dist/client/assets/SessionRefScreen-DRgJu7Jo.js +1 -0
  123. package/dist/client/assets/SessionsScreen-D6XUsZfA.js +1 -0
  124. package/dist/client/assets/SettingsDrawer-CmJt72ww.css +1 -0
  125. package/dist/client/assets/SettingsDrawer-XfdAa_nD.js +3 -0
  126. package/dist/client/assets/SettingsScreen-Cy8z-EuR.js +1 -0
  127. package/dist/client/assets/ShikiPane-Ap1iPxYb.js +15 -0
  128. package/dist/client/assets/SlidePanel-Bg5dVaIa.css +1 -0
  129. package/dist/client/assets/SlidePanel-COwtoJqR.js +1 -0
  130. package/dist/client/assets/SpriteAvatar-DyaGuhik.js +1 -0
  131. package/dist/client/assets/StatusPill-DhBL__p8.js +1 -0
  132. package/dist/client/assets/TailView-DGj_5HA9.js +2 -0
  133. package/dist/client/assets/TailView-Mj3AU2u0.css +1 -0
  134. package/dist/client/assets/Terminal-CqvGbjXU.js +1 -0
  135. package/dist/client/assets/TerminalEmbedScreen-DuZZFFzW.js +1 -0
  136. package/dist/client/assets/TextDocumentSurface-BpAw4eQS.js +4 -0
  137. package/dist/client/assets/TmuxPeek-m1osv33Q.js +1 -0
  138. package/dist/client/assets/VoicePermissionsPanel-DsK53ar4.js +1 -0
  139. package/dist/client/assets/VoicePermissionsPanel-RijAZ1gP.css +1 -0
  140. package/dist/client/assets/WorkDetailScreen-Bx0JimPC.js +5 -0
  141. package/dist/client/assets/WorkFilesViewer-Btl6C2Q1.js +1 -0
  142. package/dist/client/assets/activity-CA8qS6PI.js +1 -0
  143. package/dist/client/assets/{addon-fit-BOSszMLK.js → addon-fit-BZ-kXjeN.js} +1 -1
  144. package/dist/client/assets/{addon-webgl-WE840gr0.js → addon-webgl-D9-EQVEK.js} +1 -1
  145. package/dist/client/assets/agent-chat-Bfjd9y6c.js +1 -0
  146. package/dist/client/assets/agent-definitions-CymTYqvo.css +1 -0
  147. package/dist/client/assets/agent-directory-studio-injection-Bc8590z5.css +1 -0
  148. package/dist/client/assets/agent-essentials-BSY1o46q.js +1 -0
  149. package/dist/client/assets/agent-floor-CuJr1iK1.css +1 -0
  150. package/dist/client/assets/agent-lane-card-Dm7YWoew.css +1 -0
  151. package/dist/client/assets/agent-lane-card-model-r2frk57c.js +1 -0
  152. package/dist/client/assets/agent-lane-detail-Djm3YJEa.js +1 -0
  153. package/dist/client/assets/agent-lane-preview-CmHVe3dU.js +4 -0
  154. package/dist/client/assets/agent-lanes-BDNktFBZ.css +1 -0
  155. package/dist/client/assets/agent-lanes-model-B4YTt4OF.js +2 -0
  156. package/dist/client/assets/agents-detail-redesign-h34ROjOW.css +1 -0
  157. package/dist/client/assets/agents-project-COzHxZAF.css +1 -0
  158. package/dist/client/assets/agents-project-model-UYiamtrU.js +1 -0
  159. package/dist/client/assets/agents-screen-BMu6PpRY.css +1 -0
  160. package/dist/client/assets/api-BkjHJfgJ.js +1 -0
  161. package/dist/client/assets/api-h5zurxmi.js +1 -0
  162. package/dist/client/assets/{arc.es-KGqGKGIy.js → arc.es-CQBb-dVu.js} +1 -1
  163. package/dist/client/assets/arrow-down-BPLe0am9.js +1 -0
  164. package/dist/client/assets/arrow-left-DEZzHiPS.js +1 -0
  165. package/dist/client/assets/arrow-up-right-ClxBnsi7.js +1 -0
  166. package/dist/client/assets/bash-format-BRV5C6Gv.js +1 -0
  167. package/dist/client/assets/bot-eu8pBNvI.js +1 -0
  168. package/dist/client/assets/briefings-BwuAFQK6.css +1 -0
  169. package/dist/client/assets/broker-display-pp33bLsu.js +2 -0
  170. package/dist/client/assets/cache-Dr0why2k.js +2 -0
  171. package/dist/client/assets/check-DjgFiBxb.js +1 -0
  172. package/dist/client/assets/chevron-down-BGk5qoEw.js +1 -0
  173. package/dist/client/assets/chevron-right-XiIHsk4m.js +1 -0
  174. package/dist/client/assets/chunk-T65CQEWV-CrzwSeEt.js +1 -0
  175. package/dist/client/assets/chunk-YOZR3KYS-Bet8khjg.js +47 -0
  176. package/dist/client/assets/clipboard-e3fSpeo7.js +1 -0
  177. package/dist/client/assets/code-screen-DrKinCyh.css +1 -0
  178. package/dist/client/assets/code-xml-B6jOCM4V.js +1 -0
  179. package/dist/client/assets/collapsed-strip-Dz-of2SM.css +1 -0
  180. package/dist/client/assets/colors-BtO5_zlx.js +1 -0
  181. package/dist/client/assets/console-B1IBqLI_.css +1 -0
  182. package/dist/client/assets/content-BDt9VBPk.js +1 -0
  183. package/dist/client/assets/content-BIXf4cKR.js +1 -0
  184. package/dist/client/assets/content-BLm0NBJM.js +1 -0
  185. package/dist/client/assets/content-C2EwTb2y.js +1 -0
  186. package/dist/client/assets/content-C5UbLsDF.js +1 -0
  187. package/dist/client/assets/content-CHU0wwA3.css +1 -0
  188. package/dist/client/assets/content-CR3vdrYY.js +1 -0
  189. package/dist/client/assets/content-CSPVmo2s.js +1 -0
  190. package/dist/client/assets/content-C_FGqx1X.js +1 -0
  191. package/dist/client/assets/content-CvlVUOG8.js +1 -0
  192. package/dist/client/assets/content-D5kJmfgl.js +1 -0
  193. package/dist/client/assets/content-DTpQsomG.js +1 -0
  194. package/dist/client/assets/content-DikVsqLf.js +1 -0
  195. package/dist/client/assets/content-DlUe5Ono.js +1 -0
  196. package/dist/client/assets/content-GIBv_55n.js +1 -0
  197. package/dist/client/assets/content-Q2oclDzi.js +1 -0
  198. package/dist/client/assets/context-budget-CbB4BDcO.js +1 -0
  199. package/dist/client/assets/conversation-icons-IIG5ha6D.js +1 -0
  200. package/dist/client/assets/conversation-model-B47vYmWN.js +1 -0
  201. package/dist/client/assets/conversation-motion-features-BdAONVls.js +1 -0
  202. package/dist/client/assets/conversation-prefs-DNre-Lcx.js +1 -0
  203. package/dist/client/assets/copy-CQGYbxdu.js +1 -0
  204. package/dist/client/assets/createLucideIcon-OpA4Amw5.js +1 -0
  205. package/dist/client/assets/ctx-panel-B4s49N9e.css +1 -0
  206. package/dist/client/assets/discover-C1YwpBDE.js +2 -0
  207. package/dist/client/assets/document-focus-viewer-BSC_JwVE.css +1 -0
  208. package/dist/client/assets/embed-entry-BAcGL3g9.js +2 -0
  209. package/dist/client/assets/external-link-CXBytO9o.js +1 -0
  210. package/dist/client/assets/eye-0PvebX_a.js +1 -0
  211. package/dist/client/assets/file-text-BODxCjcz.js +1 -0
  212. package/dist/client/assets/flight-observe-GFg9L8ft.css +1 -0
  213. package/dist/client/assets/follow-route-BvcGtBIL.js +1 -0
  214. package/dist/client/assets/fx-z37u1o2z.js +1 -0
  215. package/dist/client/assets/gestures-CcwOTu8C.js +1 -0
  216. package/dist/client/assets/harnesses-screen-DBZoTZz8.css +1 -0
  217. package/dist/client/assets/home-live-action-B22u89j7.js +1 -0
  218. package/dist/client/assets/home-moving-signal-CAa0V91u.css +1 -0
  219. package/dist/client/assets/home-moving-signal-CK147hxn.js +1 -0
  220. package/dist/client/assets/home-now-card-BgvNWuea.js +1 -0
  221. package/dist/client/assets/home-now-card-nano-BcjnOU9H.js +1 -0
  222. package/dist/client/assets/hooks-B6y_O2FB.js +2 -0
  223. package/dist/client/assets/hooks-D6NI15f6.css +1 -0
  224. package/dist/client/assets/inbox-thread-redesign-Bz4FjWzr.css +1 -0
  225. package/dist/client/assets/index-BWHgHrtv.js +1 -0
  226. package/dist/client/assets/index-BcuhqXLe.js +1 -0
  227. package/dist/client/assets/index-CJXzfjo9.js +1 -0
  228. package/dist/client/assets/index-CvF09yvf.css +1 -0
  229. package/dist/client/assets/index-DMiGbrBt.js +10 -0
  230. package/dist/client/assets/index-DQPvraRS.js +1 -0
  231. package/dist/client/assets/index-DxGoC5l5.css +1 -0
  232. package/dist/client/assets/inspector-panel-DPoCWxKs.js +2 -0
  233. package/dist/client/assets/keyboard-nav-2kv_tGUS.js +1 -0
  234. package/dist/client/assets/knowledge-search-CVxQwxPn.js +1 -0
  235. package/dist/client/assets/knowledge-search-DjrQdiiW.css +1 -0
  236. package/dist/client/assets/lane-ask-display-B6iCAVcd.js +18 -0
  237. package/dist/client/assets/lane-edit-display-C_Aujldz.js +9 -0
  238. package/dist/client/assets/lane-observe-D0rfKDnU.js +7 -0
  239. package/dist/client/assets/lane-roster-store-D8x1jac2.js +1 -0
  240. package/dist/client/assets/lane-tool-detail-0WhMf4Vj.js +9 -0
  241. package/dist/client/assets/left-Bk3XnxPD.css +1 -0
  242. package/dist/client/assets/left-C--GiIh8.js +2 -0
  243. package/dist/client/assets/left-CAaRBK9S.css +1 -0
  244. package/dist/client/assets/left-CCoobxPS.css +1 -0
  245. package/dist/client/assets/left-Cj7Rt89X.js +1 -0
  246. package/dist/client/assets/left-CpNEtFEg.js +1 -0
  247. package/dist/client/assets/left-CzXAuK_t.js +2 -0
  248. package/dist/client/assets/left-agents-Bo9sO1by.js +1 -0
  249. package/dist/client/assets/left-bN4PCAXa.js +1 -0
  250. package/dist/client/assets/left-default-DV9GdvYi.js +1 -0
  251. package/dist/client/assets/left-jYYGAOYD.js +1 -0
  252. package/dist/client/assets/left-lanes-D0l_Co7V.js +1 -0
  253. package/dist/client/assets/left-mission-Ci7zREkQ.js +1 -0
  254. package/dist/client/assets/left-mission-DSenPIyb.css +1 -0
  255. package/dist/client/assets/left-plan-D4U1uflW.js +2 -0
  256. package/dist/client/assets/library-D-RxGiCw.js +1 -0
  257. package/dist/client/assets/loader-circle-CbHjZsz1.js +1 -0
  258. package/dist/client/assets/local-agents--00gLMqr.js +1 -0
  259. package/dist/client/assets/mentions-jSuTGeet.js +1 -0
  260. package/dist/client/assets/mesh-buckets-CfAukILK.js +1 -0
  261. package/dist/client/assets/mesh-screen-BSDUjrnV.css +1 -0
  262. package/dist/client/assets/mesh-view-store-CWidRbTE.js +1 -0
  263. package/dist/client/assets/message-circle-CG-96zts.js +1 -0
  264. package/dist/client/assets/message-markup-3J9pi3nx.js +15 -0
  265. package/dist/client/assets/message-square-DSaGpjFU.js +1 -0
  266. package/dist/client/assets/message-visibility-kJM8XcSG.js +1 -0
  267. package/dist/client/assets/mission-control-D3ikEPND.css +1 -0
  268. package/dist/client/assets/mission-control-model-C0fByIjm.js +1 -0
  269. package/dist/client/assets/mission-control-store-BlnEhiCq.js +1 -0
  270. package/dist/client/assets/model-Co0zkMIc.js +1 -0
  271. package/dist/client/assets/model-CpAxGuis.js +1 -0
  272. package/dist/client/assets/observe-CuLGD9Zp.js +1 -0
  273. package/dist/client/assets/openAgent-Bjt57GdM.js +1 -0
  274. package/dist/client/assets/openContent-C6XO6kr5.js +1 -0
  275. package/dist/client/assets/operator-attention-BwSPeheT.js +1 -0
  276. package/dist/client/assets/ops-agents-BOYxzPTm.css +1 -0
  277. package/dist/client/assets/ops-atop-BB4B4JdE.css +1 -0
  278. package/dist/client/assets/ops-screen-giu3If_N.css +1 -0
  279. package/dist/client/assets/page-status-DpkedE1F.js +1 -0
  280. package/dist/client/assets/page-status-bar-ByUD7VPM.css +1 -0
  281. package/dist/client/assets/plan-view-D56fneVF.css +1 -0
  282. package/dist/client/assets/plus--b1raV_O.js +1 -0
  283. package/dist/client/assets/profile-CVRziEDA.js +1 -0
  284. package/dist/client/assets/project-overview-helpers-BQTc_Ous.js +1 -0
  285. package/dist/client/assets/projects-inbox-CHyUFQ6w.js +1 -0
  286. package/dist/client/assets/projects-inbox-COZ23dLR.css +1 -0
  287. package/dist/client/assets/radio-Bz8ZePxj.js +1 -0
  288. package/dist/client/assets/refresh-cw-BBmAnCB7.js +1 -0
  289. package/dist/client/assets/repo-diff-C9Qs-bEn.css +1 -0
  290. package/dist/client/assets/resizable-columns-C7ygvLt8.css +1 -0
  291. package/dist/client/assets/resolve-panes-r9B3mpW7.js +1 -0
  292. package/dist/client/assets/resolve-sidebar-context-DcG8xGaB.js +1 -0
  293. package/dist/client/assets/right-BHeiIaty.js +1 -0
  294. package/dist/client/assets/right-BkgKo9VT.js +1 -0
  295. package/dist/client/assets/right-BpEU5jWE.js +1 -0
  296. package/dist/client/assets/right-CRZXoy-X.js +1 -0
  297. package/dist/client/assets/right-ChF_pbPy.js +1 -0
  298. package/dist/client/assets/right-DMoUT3KN.js +1 -0
  299. package/dist/client/assets/right-DjRXbnRP.js +2 -0
  300. package/dist/client/assets/right-T4Ue6EqM.js +1 -0
  301. package/dist/client/assets/right-wzrLXKur.js +1 -0
  302. package/dist/client/assets/rocket-BSNS_rLs.js +1 -0
  303. package/dist/client/assets/router-Bq5dwf78.js +1 -0
  304. package/dist/client/assets/runtime-picker-Bcl5iIX5.js +1 -0
  305. package/dist/client/assets/runtime-picker-vhm0gtLs.css +1 -0
  306. package/dist/client/assets/scope-views-4khCg2_z.css +1 -0
  307. package/dist/client/assets/scope-views-U-ucT9m0.js +1 -0
  308. package/dist/client/assets/scout-voice-CU5c0LGi.js +1 -0
  309. package/dist/client/assets/scoutbot-BTIErYHo.js +3 -0
  310. package/dist/client/assets/scroll-text-D6Pdnar7.js +1 -0
  311. package/dist/client/assets/search-CWfZtOt2.js +1 -0
  312. package/dist/client/assets/secondaryNavConfig-DqUIp0Es.js +1 -0
  313. package/dist/client/assets/secondaryNavConfig-xssF_ubT.css +1 -0
  314. package/dist/client/assets/selection-bridge-16pk1qyG.js +1 -0
  315. package/dist/client/assets/send-horizontal-Bg5-QggH.js +1 -0
  316. package/dist/client/assets/server-CPp4ZJhZ.js +1 -0
  317. package/dist/client/assets/session-catalog-BmoyVTJ_.js +1 -0
  318. package/dist/client/assets/session-table-DZcrKoIH.js +1 -0
  319. package/dist/client/assets/sessionRead-CvFz2RHv.js +1 -0
  320. package/dist/client/assets/sliders-horizontal-1oW76Xc9.js +1 -0
  321. package/dist/client/assets/sparkles-ClfRJQ6w.js +1 -0
  322. package/dist/client/assets/sse-CjIkKo46.js +1 -0
  323. package/dist/client/assets/status-tone-BM_zuRy1.js +1 -0
  324. package/dist/client/assets/surface-activity-B1rgWB1i.js +1 -0
  325. package/dist/client/assets/system-surfaces-redesign-CD26LFc0.css +1 -0
  326. package/dist/client/assets/tail-display-BdyoLvzY.js +2 -0
  327. package/dist/client/assets/tail-events-D19uAGe3.js +1 -0
  328. package/dist/client/assets/terminal-B9AOZQKR.js +1 -0
  329. package/dist/client/assets/terminal-relay-CWbJ1RCW.js +1 -0
  330. package/dist/client/assets/terminal-screen-19jAI0Cw.css +1 -0
  331. package/dist/client/assets/terminal-sessions-D5CIR2OL.js +1 -0
  332. package/dist/client/assets/terminal-takeover-B8UeD9OX.js +1 -0
  333. package/dist/client/assets/text-DsBWV_4k.js +1 -0
  334. package/dist/client/assets/time-DltNTpLl.js +1 -0
  335. package/dist/client/assets/types-B0PlfpKc.js +1 -0
  336. package/dist/client/assets/ui-LM8pS8qE.js +1 -0
  337. package/dist/client/assets/use-conversation-list-Byab41G6.js +1 -0
  338. package/dist/client/assets/use-fleet-active-asks-BIbQx5AS.js +1 -0
  339. package/dist/client/assets/use-reduced-motion-RRBkmVkk.js +1 -0
  340. package/dist/client/assets/useAgentHoverCard-DMrbBif0.js +1 -0
  341. package/dist/client/assets/useContentSecondaryNav-DMl1WNm7.js +1 -0
  342. package/dist/client/assets/usePierreRuntime-wC-yMtBb.js +50 -0
  343. package/dist/client/assets/voice-levels-Dcr3jglk.js +1 -0
  344. package/dist/client/assets/wrench-Bkc_0lKF.js +1 -0
  345. package/dist/client/assets/x-D3GElQbe.js +1 -0
  346. package/dist/client/assets/{xterm-6eL7V7pF.js → xterm-BKR8oAkR.js} +1 -1
  347. package/dist/client/index.html +6 -3
  348. package/dist/drizzle/0003_harsh_meltdown.sql +45 -0
  349. package/dist/drizzle/0004_medical_aaron_stack.sql +40 -0
  350. package/dist/drizzle/0005_wet_shriek.sql +57 -0
  351. package/dist/drizzle/0006_woozy_dark_beast.sql +1 -0
  352. package/dist/drizzle/README.md +7 -0
  353. package/dist/drizzle/meta/0003_snapshot.json +4952 -0
  354. package/dist/drizzle/meta/0004_snapshot.json +5235 -0
  355. package/dist/drizzle/meta/0005_snapshot.json +5599 -0
  356. package/dist/drizzle/meta/0006_snapshot.json +5606 -0
  357. package/dist/drizzle/meta/_journal.json +28 -0
  358. package/dist/main.mjs +24907 -12910
  359. package/dist/node/main.mjs +10212 -195
  360. package/dist/openscout-terminal-relay.mjs +507 -64
  361. package/dist/pairing-runtime-controller.mjs +10793 -5165
  362. package/dist/runtime/base-daemon.mjs +627 -159
  363. package/dist/runtime/broker-daemon.mjs +65039 -30990
  364. package/dist/runtime/broker-process-manager.mjs +247 -54
  365. package/dist/runtime/mesh-discover.mjs +246 -54
  366. package/dist/scout-control-plane-web.mjs +56699 -47427
  367. package/dist/scout-web-server.mjs +56699 -47427
  368. package/package.json +1 -1
  369. package/dist/client/assets/RepoDiffViewer-DLVleMPW.js +0 -56
  370. package/dist/client/assets/embed-entry-BdmREZuc.js +0 -1
  371. package/dist/client/assets/index-DPFmfHm5.js +0 -271
  372. package/dist/client/assets/index-jpYnsyHM.css +0 -1
@@ -1,6 +1,6 @@
1
1
  // @bun
2
2
  // packages/runtime/src/base-daemon.ts
3
- import { spawn as spawn3, spawnSync as spawnSync2 } from "child_process";
3
+ import { spawn as spawn3 } from "child_process";
4
4
  import { existsSync as existsSync6, mkdirSync as mkdirSync2, openSync, writeFileSync as writeFileSync2 } from "fs";
5
5
  import { homedir as homedir6 } from "os";
6
6
  import { dirname as dirname4, join as join6, resolve as resolve3 } from "path";
@@ -81,33 +81,49 @@ function requestBrokerOverUnixSocket(socketPath, baseUrl, path, options) {
81
81
  if (body !== undefined) {
82
82
  headers["content-length"] = Buffer.byteLength(body).toString();
83
83
  }
84
+ let settled = false;
85
+ const cleanupAbortListener = () => {
86
+ options.signal?.removeEventListener("abort", handleAbort);
87
+ };
88
+ const rejectOnce = (error) => {
89
+ if (settled)
90
+ return;
91
+ settled = true;
92
+ cleanupAbortListener();
93
+ reject(error);
94
+ };
84
95
  const request = httpRequest({
85
96
  socketPath,
86
97
  path: `${url.pathname}${url.search}`,
87
98
  method: options.method ?? (body === undefined ? "GET" : "POST"),
88
99
  headers
89
100
  }, (response) => {
90
- let text = "";
91
- response.setEncoding("utf8");
101
+ const chunks = [];
92
102
  response.on("data", (chunk) => {
93
- text += String(chunk);
103
+ chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
104
+ });
105
+ response.on("aborted", () => {
106
+ rejectOnce(new Error("Scout broker response aborted"));
94
107
  });
108
+ response.on("error", rejectOnce);
95
109
  response.on("end", () => {
96
- options.signal?.removeEventListener("abort", handleAbort);
110
+ if (settled)
111
+ return;
112
+ settled = true;
113
+ cleanupAbortListener();
97
114
  resolve({
98
115
  ok: Boolean(response.statusCode && response.statusCode >= 200 && response.statusCode < 300),
99
116
  status: response.statusCode ?? 0,
100
- text
117
+ text: Buffer.concat(chunks).toString("utf8")
101
118
  });
102
119
  });
103
120
  });
104
121
  const handleAbort = () => {
105
- request.destroy(options.signal?.reason instanceof Error ? options.signal.reason : new Error("Scout broker request aborted"));
122
+ const error = options.signal?.reason instanceof Error ? options.signal.reason : new Error("Scout broker request aborted");
123
+ rejectOnce(error);
124
+ request.destroy(error);
106
125
  };
107
- request.on("error", (error) => {
108
- options.signal?.removeEventListener("abort", handleAbort);
109
- reject(error);
110
- });
126
+ request.on("error", rejectOnce);
111
127
  if (options.signal) {
112
128
  if (options.signal.aborted) {
113
129
  handleAbort();
@@ -184,6 +200,175 @@ async function requestScoutBrokerJsonWithTrace(baseUrl, path, options = {}) {
184
200
  return { value: undefined, trace };
185
201
  }
186
202
 
203
+ // packages/runtime/src/schema-version.ts
204
+ var CONTROL_PLANE_SCHEMA_VERSION = 17;
205
+
206
+ // packages/runtime/src/sqlite-adapter.ts
207
+ import { createRequire } from "module";
208
+
209
+ // packages/runtime/src/runtime-adapters.ts
210
+ function detectRuntimeHost(globalScope = globalThis) {
211
+ return typeof globalScope.Bun === "undefined" ? "node" : "bun";
212
+ }
213
+ function normalizeRuntimeHost(value) {
214
+ const normalized = value?.trim().toLowerCase();
215
+ if (normalized === "bun")
216
+ return "bun";
217
+ if (normalized === "node")
218
+ return "node";
219
+ return null;
220
+ }
221
+ function normalizeRuntimeServiceAdapter(value) {
222
+ const normalized = value?.trim().toLowerCase().replaceAll("_", "-");
223
+ if (normalized === "macos-scoutd" || normalized === "macos-launchd")
224
+ return "macos-scoutd";
225
+ if (normalized === "linux-systemd-user" || normalized === "systemd-user")
226
+ return "linux-systemd-user";
227
+ if (normalized === "headless-foreground" || normalized === "foreground" || normalized === "headless") {
228
+ return "headless-foreground";
229
+ }
230
+ if (normalized === "windows-service")
231
+ return "windows-service";
232
+ return null;
233
+ }
234
+ function defaultServiceAdapterForPlatform(platform = process.platform, env = process.env) {
235
+ const explicit = normalizeRuntimeServiceAdapter(env.OPENSCOUT_SERVICE_ADAPTER);
236
+ if (explicit)
237
+ return explicit;
238
+ if (normalizeRuntimeHost(env.OPENSCOUT_RUNTIME_HOST) === "node") {
239
+ return "headless-foreground";
240
+ }
241
+ if (platform === "darwin")
242
+ return "macos-scoutd";
243
+ if (platform === "linux")
244
+ return "headless-foreground";
245
+ if (platform === "win32")
246
+ return "windows-service";
247
+ return "headless-foreground";
248
+ }
249
+ function planRuntimeAdapters(options = {}) {
250
+ const env = options.env ?? process.env;
251
+ const host = options.host ?? normalizeRuntimeHost(env.OPENSCOUT_RUNTIME_HOST) ?? detectRuntimeHost();
252
+ return {
253
+ host,
254
+ database: host === "bun" ? "bun-sqlite" : "node-sqlite",
255
+ httpServer: host === "bun" ? "bun-serve" : "node-http-ws",
256
+ files: host === "bun" ? "bun-file" : "node-fs",
257
+ process: host === "bun" ? "bun-spawn" : "node-child-process",
258
+ service: defaultServiceAdapterForPlatform(options.platform, env)
259
+ };
260
+ }
261
+
262
+ // packages/runtime/src/sqlite-adapter.ts
263
+ var require2 = createRequire(import.meta.url);
264
+ function controlPlaneSqliteAdapterKind() {
265
+ return planRuntimeAdapters().database;
266
+ }
267
+ function openControlPlaneSqliteDatabase(path, options) {
268
+ return openRuntimeSqliteDatabase(path, options);
269
+ }
270
+ function openRuntimeSqliteDatabase(path, options) {
271
+ const adapter = controlPlaneSqliteAdapterKind();
272
+ if (adapter === "bun-sqlite") {
273
+ const { Database } = require2("bun:sqlite");
274
+ return new Database(path, options);
275
+ }
276
+ const { DatabaseSync } = require2("node:sqlite");
277
+ return new NodeSqliteDatabaseAdapter(new DatabaseSync(path, {
278
+ open: true,
279
+ readOnly: options?.readonly === true
280
+ }));
281
+ }
282
+ function prepareNodeSqliteSql(sql) {
283
+ const numberedParamIndexes = [];
284
+ const normalizedSql = sql.replace(/\?(\d+)/g, (_match, rawIndex) => {
285
+ numberedParamIndexes.push(Number.parseInt(rawIndex, 10) - 1);
286
+ return "?";
287
+ });
288
+ return {
289
+ sql: normalizedSql,
290
+ numberedParamIndexes: numberedParamIndexes.length > 0 ? numberedParamIndexes : null
291
+ };
292
+ }
293
+ function bindNodeSqliteParams(numberedParamIndexes, params) {
294
+ if (!numberedParamIndexes) {
295
+ return params;
296
+ }
297
+ return numberedParamIndexes.map((index) => params[index]);
298
+ }
299
+
300
+ class NodeSqliteStatementAdapter {
301
+ statement;
302
+ numberedParamIndexes;
303
+ constructor(statement, numberedParamIndexes) {
304
+ this.statement = statement;
305
+ this.numberedParamIndexes = numberedParamIndexes;
306
+ }
307
+ all(...params) {
308
+ return this.statement.all(...bindNodeSqliteParams(this.numberedParamIndexes, params));
309
+ }
310
+ get(...params) {
311
+ return this.statement.get(...bindNodeSqliteParams(this.numberedParamIndexes, params)) ?? null;
312
+ }
313
+ run(...params) {
314
+ return this.statement.run(...bindNodeSqliteParams(this.numberedParamIndexes, params));
315
+ }
316
+ }
317
+
318
+ class NodeSqliteDatabaseAdapter {
319
+ database;
320
+ transactionDepth = 0;
321
+ savepointId = 0;
322
+ constructor(database) {
323
+ this.database = database;
324
+ }
325
+ exec(sql) {
326
+ return this.database.exec(sql);
327
+ }
328
+ query(sql) {
329
+ const prepared = prepareNodeSqliteSql(sql);
330
+ return new NodeSqliteStatementAdapter(this.database.prepare(prepared.sql), prepared.numberedParamIndexes);
331
+ }
332
+ close() {
333
+ this.database.close();
334
+ }
335
+ transaction(callback) {
336
+ return (...args) => {
337
+ if (this.transactionDepth > 0) {
338
+ return this.runSavepoint(callback, args);
339
+ }
340
+ this.database.exec("BEGIN IMMEDIATE;");
341
+ this.transactionDepth += 1;
342
+ try {
343
+ const result = callback(...args);
344
+ this.database.exec("COMMIT;");
345
+ return result;
346
+ } catch (error) {
347
+ this.database.exec("ROLLBACK;");
348
+ throw error;
349
+ } finally {
350
+ this.transactionDepth -= 1;
351
+ }
352
+ };
353
+ }
354
+ runSavepoint(callback, args) {
355
+ const savepointName = `openscout_nested_${this.savepointId++}`;
356
+ this.database.exec(`SAVEPOINT ${savepointName};`);
357
+ this.transactionDepth += 1;
358
+ try {
359
+ const result = callback(...args);
360
+ this.database.exec(`RELEASE SAVEPOINT ${savepointName};`);
361
+ return result;
362
+ } catch (error) {
363
+ this.database.exec(`ROLLBACK TO SAVEPOINT ${savepointName};`);
364
+ this.database.exec(`RELEASE SAVEPOINT ${savepointName};`);
365
+ throw error;
366
+ } finally {
367
+ this.transactionDepth -= 1;
368
+ }
369
+ }
370
+ }
371
+
187
372
  // packages/runtime/src/support-paths.ts
188
373
  import { homedir } from "os";
189
374
  import { join } from "path";
@@ -811,7 +996,7 @@ var SCOUT_HOST_PROBE_SCHEMA_VERSIONS = {
811
996
  "git.mergeBase": 1,
812
997
  "git.logLastCommitUnix": 1,
813
998
  "git.worktreeListPorcelain": 1,
814
- "tmux.sessions": 1,
999
+ "tmux.sessions": 2,
815
1000
  "tmux.panes": 1,
816
1001
  "zellij.sessions": 1,
817
1002
  "ps.runtime": 1,
@@ -1570,6 +1755,8 @@ var tailscaleStatusProbe = defineProbe({
1570
1755
 
1571
1756
  // packages/runtime/src/tailscale.ts
1572
1757
  var DEFAULT_TAILSCALE_STATUS_TIMEOUT_MS2 = 1500;
1758
+ var SYNC_TAILSCALE_STATUS_CACHE_MS = 30000;
1759
+ var syncStatusCache = null;
1573
1760
  function readStatusJsonFromFileSync(filePath) {
1574
1761
  const raw = readFileSync2(filePath, "utf8");
1575
1762
  return parseTailscaleStatusJson(raw);
@@ -1594,6 +1781,15 @@ function readStatusJsonSync(env = process.env) {
1594
1781
  if (!tailscaleBin) {
1595
1782
  return null;
1596
1783
  }
1784
+ const cacheKey = [
1785
+ tailscaleBin,
1786
+ env.OPENSCOUT_TAILSCALE_AUTO_HOSTS ?? "",
1787
+ env.OPENSCOUT_TAILSCALE_STATUS_TIMEOUT_MS ?? ""
1788
+ ].join("\x00");
1789
+ const cached = syncStatusCache;
1790
+ if (env === process.env && cached?.key === cacheKey && Date.now() - cached.at < SYNC_TAILSCALE_STATUS_CACHE_MS) {
1791
+ return cached.value;
1792
+ }
1597
1793
  try {
1598
1794
  const stdout = execFileSync(tailscaleBin, ["status", "--json"], {
1599
1795
  encoding: "utf8",
@@ -1601,8 +1797,13 @@ function readStatusJsonSync(env = process.env) {
1601
1797
  timeout: statusTimeoutMs2(env),
1602
1798
  windowsHide: true
1603
1799
  });
1604
- return parseTailscaleStatusJson(stdout);
1800
+ const value = parseTailscaleStatusJson(stdout);
1801
+ if (env === process.env)
1802
+ syncStatusCache = { key: cacheKey, at: Date.now(), value };
1803
+ return value;
1605
1804
  } catch {
1805
+ if (env === process.env)
1806
+ syncStatusCache = { key: cacheKey, at: Date.now(), value: null };
1606
1807
  return null;
1607
1808
  }
1608
1809
  }
@@ -1853,44 +2054,6 @@ function findExecutableOnSearchPath(name, env) {
1853
2054
  return null;
1854
2055
  }
1855
2056
 
1856
- // packages/runtime/src/runtime-adapters.ts
1857
- function normalizeRuntimeHost(value) {
1858
- const normalized = value?.trim().toLowerCase();
1859
- if (normalized === "bun")
1860
- return "bun";
1861
- if (normalized === "node")
1862
- return "node";
1863
- return null;
1864
- }
1865
- function normalizeRuntimeServiceAdapter(value) {
1866
- const normalized = value?.trim().toLowerCase().replaceAll("_", "-");
1867
- if (normalized === "macos-scoutd" || normalized === "macos-launchd")
1868
- return "macos-scoutd";
1869
- if (normalized === "linux-systemd-user" || normalized === "systemd-user")
1870
- return "linux-systemd-user";
1871
- if (normalized === "headless-foreground" || normalized === "foreground" || normalized === "headless") {
1872
- return "headless-foreground";
1873
- }
1874
- if (normalized === "windows-service")
1875
- return "windows-service";
1876
- return null;
1877
- }
1878
- function defaultServiceAdapterForPlatform(platform = process.platform, env = process.env) {
1879
- const explicit = normalizeRuntimeServiceAdapter(env.OPENSCOUT_SERVICE_ADAPTER);
1880
- if (explicit)
1881
- return explicit;
1882
- if (normalizeRuntimeHost(env.OPENSCOUT_RUNTIME_HOST) === "node") {
1883
- return "headless-foreground";
1884
- }
1885
- if (platform === "darwin")
1886
- return "macos-scoutd";
1887
- if (platform === "linux")
1888
- return "headless-foreground";
1889
- if (platform === "win32")
1890
- return "windows-service";
1891
- return "headless-foreground";
1892
- }
1893
-
1894
2057
  // packages/runtime/src/broker-process-manager.ts
1895
2058
  function isTmpPath(p) {
1896
2059
  return /^\/(?:private\/)?tmp\//.test(p);
@@ -2066,12 +2229,12 @@ function resolveBrokerServiceLabel(mode) {
2066
2229
  }
2067
2230
  switch (mode) {
2068
2231
  case "prod":
2069
- return "com.openscout";
2232
+ return "app.openscout";
2070
2233
  case "custom":
2071
- return "com.openscout.custom";
2234
+ return "app.openscout.custom";
2072
2235
  case "dev":
2073
2236
  default:
2074
- return "dev.openscout";
2237
+ return "app.openscout";
2075
2238
  }
2076
2239
  }
2077
2240
  function resolveBrokerServiceConfig() {
@@ -2238,13 +2401,16 @@ function readRuntimeFreshness(value) {
2238
2401
  state,
2239
2402
  intentional: readBoolean(value.intentional) ?? false,
2240
2403
  basis,
2404
+ reasonCode: readString2(value.reasonCode) ?? null,
2241
2405
  artifactCommit: readString2(value.artifactCommit) ?? null,
2242
2406
  expectedCommit: readString2(value.expectedCommit) ?? null,
2243
2407
  pin: readString2(value.pin) ?? null,
2244
2408
  pinReason: readString2(value.pinReason) ?? null,
2245
2409
  manifestPath: readString2(value.manifestPath) ?? null,
2246
2410
  version: readString2(value.version) ?? null,
2247
- builtAt: readString2(value.builtAt) ?? null,
2411
+ actualBuiltAt: readString2(value.actualBuiltAt) ?? readString2(value.builtAt) ?? null,
2412
+ expectedBuiltAt: readString2(value.expectedBuiltAt) ?? null,
2413
+ builtAt: readString2(value.builtAt) ?? readString2(value.actualBuiltAt) ?? null,
2248
2414
  sourceDirty: readBoolean(value.sourceDirty) ?? null,
2249
2415
  detail
2250
2416
  };
@@ -2374,7 +2540,30 @@ function spawnScoutdJson(scoutdPath, command, env, timeoutMs) {
2374
2540
  });
2375
2541
  });
2376
2542
  }
2543
+ var SCHEMA_GUARDED_SERVICE_COMMANDS = new Set([
2544
+ "install",
2545
+ "start",
2546
+ "restart"
2547
+ ]);
2548
+ function assertBrokerServiceSchemaCompatible(config) {
2549
+ const databasePath = join5(config.controlHome, "control-plane.sqlite");
2550
+ if (!existsSync5(databasePath))
2551
+ return;
2552
+ const database = openControlPlaneSqliteDatabase(databasePath, { readonly: true });
2553
+ try {
2554
+ const row = database.query("PRAGMA user_version").get();
2555
+ const databaseVersion = row?.user_version ?? 0;
2556
+ if (databaseVersion > CONTROL_PLANE_SCHEMA_VERSION) {
2557
+ throw new Error(`Refusing to change the Scout service: candidate runtime schema v${CONTROL_PLANE_SCHEMA_VERSION} ` + `is older than control-plane database schema v${databaseVersion}. ` + "The existing service was left untouched. Update or rebase this checkout before restarting Scout.");
2558
+ }
2559
+ } finally {
2560
+ database.close?.();
2561
+ }
2562
+ }
2377
2563
  async function runScoutdServiceCommand(command, config, timeoutMs = SCOUTD_DEFAULT_TIMEOUT_MS, runScoutdJson = spawnScoutdJson) {
2564
+ if (SCHEMA_GUARDED_SERVICE_COMMANDS.has(command)) {
2565
+ assertBrokerServiceSchemaCompatible(config);
2566
+ }
2378
2567
  const scoutd = resolveScoutdCommand(config);
2379
2568
  if (!scoutd) {
2380
2569
  throw new Error("Unable to locate scoutd for broker service management. Build scoutd with `npm run scoutd:build`, install a package that includes scoutd, or set OPENSCOUT_SCOUTD_BIN.");
@@ -2609,6 +2798,9 @@ function formatBrokerServiceStatus(status) {
2609
2798
  ];
2610
2799
  if (status.runtimeFreshness) {
2611
2800
  lines.push(`runtime freshness detail: ${status.runtimeFreshness.detail}`);
2801
+ if (status.runtimeFreshness.reasonCode) {
2802
+ lines.push(`runtime freshness reason: ${status.runtimeFreshness.reasonCode}`);
2803
+ }
2612
2804
  }
2613
2805
  if (status.health.socketFallbackError) {
2614
2806
  lines.push(`socket fallback: ${status.health.socketFallbackError}`);
@@ -2626,6 +2818,141 @@ if (process.argv[1] && fileURLToPath(import.meta.url) === process.argv[1] && !pr
2626
2818
  });
2627
2819
  }
2628
2820
 
2821
+ // packages/runtime/src/scout-ascii-mark.ts
2822
+ var ORB_COLS = 60;
2823
+ var ORB_ROWS = 47;
2824
+ var ORB_FIELD = "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";
2825
+ var ORB_CEIL = 0.83;
2826
+ var ORB_GAMMA = 0.72;
2827
+ var ORB_GAIN = 1.55;
2828
+ var ORB_TONES = 4;
2829
+ var ORB_GLYPH = "\u2591";
2830
+ var ORB_BAYER = [
2831
+ [0.125, 0.625],
2832
+ [0.875, 0.375]
2833
+ ];
2834
+ var ORB_SHIMMER_AMP = 0.34;
2835
+ var ORB_STILL = 0.42;
2836
+ var ORB_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
2837
+ function clamp01(v) {
2838
+ return Math.max(0, Math.min(1, v));
2839
+ }
2840
+ function fieldRaw(x, y) {
2841
+ return ORB_ALPHABET.indexOf(ORB_FIELD[y * ORB_COLS + x]) / 63;
2842
+ }
2843
+ function isOccupied(raw, x, y) {
2844
+ let base = clamp01(raw) / ORB_CEIL;
2845
+ base = Math.pow(clamp01(base), ORB_GAMMA);
2846
+ return base * ORB_GAIN > ORB_BAYER[y % 2][x % 2];
2847
+ }
2848
+ function orbShimmer(x, y, t) {
2849
+ const nx = x / (ORB_COLS - 1) * 2 - 1;
2850
+ const ny = y / (ORB_ROWS - 1) * 2 - 1;
2851
+ const a = 120 * Math.PI / 180;
2852
+ const u = nx * Math.cos(a) + ny * Math.sin(a) - t;
2853
+ const c = Math.pow(Math.cos(u * Math.PI * 2) * 0.5 + 0.5, 2.8);
2854
+ return 1 - ORB_SHIMMER_AMP + ORB_SHIMMER_AMP * c * 2;
2855
+ }
2856
+ function toneFor(raw, x, y, t) {
2857
+ let v = clamp01(raw * orbShimmer(x, y, t)) / ORB_CEIL;
2858
+ v = Math.pow(clamp01(v), ORB_GAMMA);
2859
+ const step = Math.min(ORB_TONES - 1, Math.max(0, Math.floor(v * ORB_TONES)));
2860
+ return Math.round(step * 4 / (ORB_TONES - 1));
2861
+ }
2862
+ function renderScoutAsciiMarkFrame(t) {
2863
+ const layers = [[], [], [], [], []];
2864
+ for (let y = 0;y < ORB_ROWS; y += 1) {
2865
+ const rows = ["", "", "", "", ""];
2866
+ for (let x = 0;x < ORB_COLS; x += 1) {
2867
+ const raw = fieldRaw(x, y);
2868
+ if (!isOccupied(raw, x, y)) {
2869
+ for (let i = 0;i < 5; i += 1)
2870
+ rows[i] += " ";
2871
+ continue;
2872
+ }
2873
+ const tone = toneFor(raw, x, y, t);
2874
+ for (let i = 0;i < 5; i += 1) {
2875
+ rows[i] += i === tone ? ORB_GLYPH : " ";
2876
+ }
2877
+ }
2878
+ for (let i = 0;i < 5; i += 1)
2879
+ layers[i].push(rows[i]);
2880
+ }
2881
+ return layers.map((rows) => rows.join(`
2882
+ `));
2883
+ }
2884
+ function renderScoutAsciiMarkHtml() {
2885
+ return renderScoutAsciiMarkFrame(ORB_STILL).map((text, i) => `<pre class="orb-l" data-t="${i}">${text}</pre>`).join("");
2886
+ }
2887
+ function renderScoutAsciiMarkScript() {
2888
+ return `<script>
2889
+ (function () {
2890
+ var els = document.querySelectorAll(".orb-l");
2891
+ if (els.length !== 5 || !window.requestAnimationFrame) return;
2892
+ var mq = window.matchMedia("(prefers-reduced-motion: reduce)");
2893
+ var F = "${ORB_FIELD}";
2894
+ var A = "${ORB_ALPHABET}";
2895
+ var COLS = ${ORB_COLS}, ROWS = ${ORB_ROWS};
2896
+ var BAYER = [[0.125, 0.625], [0.875, 0.375]];
2897
+ var CEIL = ${ORB_CEIL}, GAMMA = ${ORB_GAMMA}, GAIN = ${ORB_GAIN};
2898
+ var TONES = ${ORB_TONES}, AMP = ${ORB_SHIMMER_AMP};
2899
+ var STILL = ${ORB_STILL};
2900
+ var raf = 0, last = 0;
2901
+
2902
+ function clamp01(v) { return v < 0 ? 0 : v > 1 ? 1 : v; }
2903
+
2904
+ function occupied(raw, x, y) {
2905
+ var base = Math.pow(clamp01(clamp01(raw) / CEIL), GAMMA);
2906
+ return base * GAIN > BAYER[y % 2][x % 2];
2907
+ }
2908
+
2909
+ function toneOf(raw, x, y, t) {
2910
+ var nx = (x / (COLS - 1)) * 2 - 1;
2911
+ var ny = (y / (ROWS - 1)) * 2 - 1;
2912
+ var u = nx * Math.cos(2.0943951) + ny * Math.sin(2.0943951) - t;
2913
+ var c = Math.pow(Math.cos(u * Math.PI * 2) * 0.5 + 0.5, 2.8);
2914
+ var shimmer = 1 - AMP + AMP * c * 2;
2915
+ var v = Math.pow(clamp01(clamp01(raw * shimmer) / CEIL), GAMMA);
2916
+ var step = Math.min(TONES - 1, Math.max(0, Math.floor(v * TONES)));
2917
+ return Math.round(step * 4 / (TONES - 1));
2918
+ }
2919
+
2920
+ function frame(t) {
2921
+ var out = ["", "", "", "", ""];
2922
+ for (var y = 0; y < ROWS; y++) {
2923
+ for (var x = 0; x < COLS; x++) {
2924
+ var raw = A.indexOf(F.charAt(y * COLS + x)) / 63;
2925
+ if (!occupied(raw, x, y)) {
2926
+ for (var i = 0; i < 5; i++) out[i] += " ";
2927
+ } else {
2928
+ var tone = toneOf(raw, x, y, t);
2929
+ for (var j = 0; j < 5; j++) out[j] += j === tone ? "\\u2591" : " ";
2930
+ }
2931
+ }
2932
+ if (y < ROWS - 1) for (var k = 0; k < 5; k++) out[k] += "\\n";
2933
+ }
2934
+ for (var m = 0; m < 5; m++) els[m].textContent = out[m];
2935
+ }
2936
+
2937
+ function loop(ts) {
2938
+ raf = requestAnimationFrame(loop);
2939
+ if (ts - last < 48) return;
2940
+ last = ts;
2941
+ frame(STILL + (ts / 1000) * 0.38);
2942
+ }
2943
+ function sync() {
2944
+ cancelAnimationFrame(raf);
2945
+ raf = 0;
2946
+ if (mq.matches || document.hidden) frame(STILL);
2947
+ else raf = requestAnimationFrame(loop);
2948
+ }
2949
+ if (mq.addEventListener) mq.addEventListener("change", sync);
2950
+ document.addEventListener("visibilitychange", sync);
2951
+ sync();
2952
+ })();
2953
+ </script>`;
2954
+ }
2955
+
2629
2956
  // packages/runtime/src/local-edge.ts
2630
2957
  function normalizeViteHmrPath(value) {
2631
2958
  const trimmed = value?.trim();
@@ -2719,91 +3046,180 @@ function renderOpenScoutStartPage(config) {
2719
3046
  <meta charset="utf-8">
2720
3047
  <meta name="viewport" content="width=device-width, initial-scale=1">
2721
3048
  <title>Start Scout</title>
3049
+ <script>
3050
+ (function () {
3051
+ var theme = "dark";
3052
+ try {
3053
+ var query = new URLSearchParams(window.location.search).get("theme");
3054
+ var stored = JSON.parse(window.localStorage.getItem("openscout.theme") || "{}").theme;
3055
+ var preference = query || stored;
3056
+ if (preference === "light") theme = "light";
3057
+ if (preference === "system") {
3058
+ theme = window.matchMedia("(prefers-color-scheme: light)").matches ? "light" : "dark";
3059
+ }
3060
+ } catch {}
3061
+ document.documentElement.dataset.scoutTheme = theme;
3062
+ })();
3063
+ </script>
2722
3064
  <style>
2723
3065
  :root {
2724
3066
  color-scheme: light dark;
2725
- font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
2726
- background: #0f1720;
2727
- color: #f5f7fb;
3067
+ --bg: #080a07;
3068
+ --surface: #10130e;
3069
+ --ink: #f5f1e8;
3070
+ --muted: #aaa69b;
3071
+ --edge: #303729;
3072
+ --accent: #a6e15e;
3073
+ --orb-0: #2a2723;
3074
+ --orb-1: #444038;
3075
+ --orb-2: #6d675a;
3076
+ --orb-3: #9a9181;
3077
+ --orb-4: #d8d0c0;
3078
+ font-family: "Inter Tight", Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
3079
+ background: var(--bg);
3080
+ color: var(--ink);
2728
3081
  }
2729
3082
  * { box-sizing: border-box; margin: 0; padding: 0; }
2730
3083
  body {
2731
3084
  min-height: 100vh;
2732
3085
  display: grid;
2733
3086
  place-items: center;
2734
- padding: 32px;
2735
- background:
2736
- radial-gradient(ellipse at 15% 30%, rgba(91, 141, 239, 0.16) 0%, transparent 50%),
2737
- radial-gradient(ellipse at 85% 70%, rgba(74, 222, 128, 0.06) 0%, transparent 40%),
2738
- #111827;
3087
+ padding: 32px 28px;
3088
+ background: var(--bg);
2739
3089
  }
2740
3090
  main {
2741
- width: min(400px, 100%);
2742
- padding: 28px 30px 26px;
2743
- border: 1px solid rgba(255, 255, 255, 0.09);
2744
- border-radius: 10px;
2745
- background: rgba(15, 23, 32, 0.9);
2746
- box-shadow: 0 1px 0 rgba(255, 255, 255, 0.04) inset, 0 20px 60px rgba(0, 0, 0, 0.45);
2747
- }
2748
- .badge {
2749
- display: inline-flex;
3091
+ width: min(640px, 100%);
3092
+ }
3093
+ .brand {
3094
+ display: flex;
2750
3095
  align-items: center;
2751
- gap: 6px;
2752
- margin-bottom: 18px;
2753
- font-size: 11px;
2754
- font-weight: 600;
2755
- letter-spacing: 0.07em;
3096
+ justify-content: space-between;
3097
+ gap: 16px;
3098
+ padding-bottom: 14px;
3099
+ margin-bottom: 36px;
3100
+ border-bottom: 1px solid color-mix(in srgb, var(--edge) 80%, transparent);
3101
+ }
3102
+ .host {
3103
+ overflow: hidden;
3104
+ color: var(--muted);
3105
+ font: 500 11px/1.2 ui-monospace, "SF Mono", Menlo, monospace;
3106
+ letter-spacing: 0.08em;
3107
+ text-overflow: ellipsis;
2756
3108
  text-transform: uppercase;
2757
- color: rgba(74, 222, 128, 0.8);
3109
+ white-space: nowrap;
2758
3110
  }
2759
- @keyframes blink {
2760
- 0%, 100% { opacity: 1; }
2761
- 50% { opacity: 0.2; }
3111
+ .service {
3112
+ color: var(--muted);
3113
+ font-size: 12px;
3114
+ letter-spacing: 0.01em;
3115
+ white-space: nowrap;
2762
3116
  }
2763
- .badge-dot {
2764
- width: 6px;
2765
- height: 6px;
2766
- border-radius: 50%;
2767
- background: #4ade80;
2768
- flex-shrink: 0;
2769
- animation: blink 2.4s ease-in-out infinite;
3117
+ .hero {
3118
+ display: grid;
3119
+ grid-template-columns: minmax(0, 1fr) auto;
3120
+ gap: 24px 36px;
3121
+ align-items: center;
2770
3122
  }
3123
+ /* The mark is a second way into the app, not just decoration \u2014 it is the
3124
+ largest, most inviting thing on the page, so clicking it should do what
3125
+ clicking it looks like it should do. It stays aria-hidden and outside the
3126
+ tab order on purpose: 2820 glyph cells are noise to a screen reader, and
3127
+ the real #start button sits beside it as the accessible, keyboard-
3128
+ reachable path. This is a redundant mouse affordance, never the only one. */
3129
+ .orb {
3130
+ position: relative;
3131
+ justify-self: end;
3132
+ user-select: none;
3133
+ cursor: pointer;
3134
+ transition: transform 160ms ease, filter 160ms ease;
3135
+ }
3136
+ .orb:hover { transform: translateY(-1px); filter: brightness(1.18); }
3137
+ .orb:active { transform: translateY(0); filter: brightness(1.05); }
3138
+ .orb[data-busy="true"] { cursor: progress; }
3139
+ .orb[data-busy="true"]:hover { transform: none; filter: none; }
3140
+ @media (prefers-reduced-motion: reduce) {
3141
+ .orb { transition: none; }
3142
+ .orb:hover, .orb:active { transform: none; }
3143
+ }
3144
+ .orb-l {
3145
+ margin: 0;
3146
+ color: var(--orb-0);
3147
+ font: 400 5px/1 ui-monospace, "SF Mono", Menlo, Consolas, monospace;
3148
+ letter-spacing: 0;
3149
+ white-space: pre;
3150
+ -webkit-font-smoothing: none;
3151
+ -moz-osx-font-smoothing: unset;
3152
+ font-smooth: never;
3153
+ text-rendering: geometricPrecision;
3154
+ font-variant-ligatures: none;
3155
+ font-kerning: none;
3156
+ }
3157
+ .orb-l + .orb-l { position: absolute; inset: 0; }
3158
+ .orb-l[data-t="1"] { color: var(--orb-1); }
3159
+ .orb-l[data-t="2"] { color: var(--orb-2); }
3160
+ .orb-l[data-t="3"] { color: var(--orb-3); }
3161
+ .orb-l[data-t="4"] { color: var(--orb-4); }
2771
3162
  h1 {
2772
- font-size: 22px;
2773
- font-weight: 700;
2774
- line-height: 1.2;
2775
- margin-bottom: 8px;
2776
- color: #f5f7fb;
3163
+ margin-bottom: 10px;
3164
+ color: var(--ink);
3165
+ font-size: clamp(24px, 3.6vw, 28px);
3166
+ font-weight: 560;
3167
+ letter-spacing: -0.04em;
3168
+ line-height: 1.12;
2777
3169
  }
2778
3170
  p {
3171
+ max-width: 34ch;
3172
+ color: var(--muted);
2779
3173
  font-size: 14px;
2780
- color: rgba(245, 247, 251, 0.5);
2781
3174
  line-height: 1.55;
2782
3175
  margin-bottom: 22px;
2783
3176
  }
2784
3177
  button {
2785
- width: 100%;
2786
3178
  min-height: 44px;
2787
- border: 0;
2788
- border-radius: 7px;
2789
- background: #f4d35e;
2790
- color: #17202a;
3179
+ display: inline-flex;
3180
+ align-items: center;
3181
+ justify-content: center;
3182
+ gap: 8px;
3183
+ border: 1px solid var(--edge);
3184
+ border-radius: 8px;
3185
+ padding: 0 14px;
3186
+ background: var(--surface);
3187
+ color: var(--ink);
2791
3188
  font: inherit;
2792
- font-size: 14px;
2793
- font-weight: 700;
3189
+ font-size: 13px;
3190
+ font-weight: 550;
3191
+ letter-spacing: -0.015em;
2794
3192
  cursor: pointer;
2795
- transition: background 0.1s, opacity 0.1s;
3193
+ transition: background 120ms ease, border-color 120ms ease, color 120ms ease, opacity 120ms ease;
3194
+ }
3195
+ button:hover:not(:disabled) {
3196
+ border-color: color-mix(in srgb, var(--accent) 42%, var(--edge));
3197
+ background: color-mix(in srgb, var(--surface) 88%, var(--accent));
3198
+ }
3199
+ button:active:not(:disabled) {
3200
+ background: color-mix(in srgb, var(--surface) 78%, var(--accent));
2796
3201
  }
2797
- button:hover:not(:disabled) { background: #f7dc74; }
2798
- button:active:not(:disabled) { background: #e8c44a; }
2799
- button:disabled { cursor: progress; opacity: 0.6; }
3202
+ button:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
3203
+ button:disabled { cursor: progress; opacity: 0.55; }
3204
+ .button-arrow {
3205
+ color: var(--accent);
3206
+ font-size: 14px;
3207
+ font-weight: 500;
3208
+ line-height: 1;
3209
+ transition: transform 120ms ease;
3210
+ }
3211
+ button:hover:not(:disabled) .button-arrow { transform: translateX(1px); }
2800
3212
  .progress {
2801
- height: 2px;
2802
- margin-top: 14px;
2803
- border-radius: 2px;
2804
- background: rgba(255, 255, 255, 0.06);
3213
+ width: min(220px, 100%);
3214
+ height: 1px;
3215
+ margin-top: 18px;
3216
+ border-radius: 1px;
3217
+ background: color-mix(in srgb, var(--edge) 70%, transparent);
2805
3218
  overflow: hidden;
3219
+ opacity: 0;
3220
+ transition: opacity 120ms ease;
2806
3221
  }
3222
+ main.is-waiting .progress { opacity: 1; }
2807
3223
  @keyframes sweep {
2808
3224
  0% { transform: translateX(-100%); }
2809
3225
  100% { transform: translateX(500%); }
@@ -2811,8 +3227,8 @@ function renderOpenScoutStartPage(config) {
2811
3227
  .progress-bar {
2812
3228
  height: 100%;
2813
3229
  width: 20%;
2814
- border-radius: 2px;
2815
- background: rgba(244, 211, 94, 0.7);
3230
+ border-radius: 1px;
3231
+ background: var(--accent);
2816
3232
  transform: translateX(-100%);
2817
3233
  }
2818
3234
  .progress-bar.running {
@@ -2822,36 +3238,82 @@ function renderOpenScoutStartPage(config) {
2822
3238
  display: block;
2823
3239
  min-height: 16px;
2824
3240
  margin-top: 10px;
2825
- color: rgba(245, 247, 251, 0.38);
3241
+ color: var(--muted);
2826
3242
  font-family: ui-monospace, "SF Mono", Menlo, "Cascadia Code", monospace;
2827
- font-size: 12px;
3243
+ font-size: 11px;
2828
3244
  line-height: 1.4;
2829
3245
  }
3246
+ :root[data-scout-theme="dark"] { color-scheme: dark; }
3247
+ :root[data-scout-theme="light"] {
3248
+ color-scheme: light;
3249
+ --bg: #f3f1ea;
3250
+ --surface: #fbfaf5;
3251
+ --ink: #171914;
3252
+ --muted: #65655d;
3253
+ --edge: #c6c8ba;
3254
+ --accent: #3a6807;
3255
+ --orb-0: #d2cec4;
3256
+ --orb-1: #a19d94;
3257
+ --orb-2: #717068;
3258
+ --orb-3: #484b44;
3259
+ --orb-4: #1c2019;
3260
+ }
3261
+ @media (max-width: 520px) {
3262
+ body { place-items: start center; padding: 24px 20px; }
3263
+ main { padding-top: 10vh; }
3264
+ .brand { margin-bottom: 28px; }
3265
+ .service { display: none; }
3266
+ .hero { grid-template-columns: 1fr; gap: 28px; }
3267
+ .orb { order: -1; justify-self: start; }
3268
+ .orb-l { font-size: 4.5px; }
3269
+ h1 { font-size: clamp(22px, 6.5vw, 26px); }
3270
+ p { max-width: none; }
3271
+ button { width: 100%; }
3272
+ .progress { width: 100%; }
3273
+ }
3274
+ @media (prefers-reduced-motion: reduce) {
3275
+ button, .button-arrow, .progress { transition: none; }
3276
+ button:hover:not(:disabled) .button-arrow { transform: none; }
3277
+ .progress-bar.running { animation: none; transform: none; width: 100%; }
3278
+ }
2830
3279
  </style>
2831
3280
  </head>
2832
3281
  <body>
2833
- <main>
2834
- <div class="badge"><span class="badge-dot"></span>Broker online</div>
2835
- <h1>Start Scout</h1>
2836
- <p>The web app is not running yet. Click to start it on this machine.</p>
2837
- <button id="start" type="button">Start Scout</button>
2838
- <div class="progress"><div class="progress-bar" id="bar"></div></div>
2839
- <output id="status" role="status"></output>
3282
+ <main id="shell">
3283
+ <div class="brand">
3284
+ <span class="host" id="host">Scout local</span>
3285
+ <span class="service">Local web service</span>
3286
+ </div>
3287
+ <div class="hero">
3288
+ <section>
3289
+ <h1>Bring Scout online.</h1>
3290
+ <p>The web interface is not running yet. Start it to return to your agents, messages, and activity.</p>
3291
+ <button id="start" type="button"><span>Start Scout</span><span class="button-arrow" aria-hidden="true">\u2192</span></button>
3292
+ <div class="progress"><div class="progress-bar" id="bar"></div></div>
3293
+ <output id="status" role="status"></output>
3294
+ </section>
3295
+ <div class="orb" aria-hidden="true">${renderScoutAsciiMarkHtml()}</div>
3296
+ </div>
2840
3297
  </main>
3298
+ ${renderScoutAsciiMarkScript()}
2841
3299
  <script>
2842
3300
  const config = ${pageConfig};
3301
+ const shell = document.getElementById('shell');
3302
+ const host = document.getElementById('host');
2843
3303
  const button = document.getElementById('start');
2844
3304
  const bar = document.getElementById('bar');
2845
3305
  const status = document.getElementById('status');
2846
3306
  const targetPath = window.location.pathname + window.location.search + window.location.hash;
2847
3307
  const healthUrl = new URL('/api/health', window.location.origin);
2848
3308
  const startUrl = new URL(config.startPath, window.location.origin);
3309
+ host.textContent = window.location.host;
2849
3310
 
2850
3311
  function setStatus(message) {
2851
3312
  status.textContent = message;
2852
3313
  }
2853
3314
 
2854
3315
  function setWaiting(on) {
3316
+ shell.classList.toggle('is-waiting', on);
2855
3317
  bar.classList.toggle('running', on);
2856
3318
  }
2857
3319
 
@@ -2873,8 +3335,14 @@ function renderOpenScoutStartPage(config) {
2873
3335
  return false;
2874
3336
  }
2875
3337
 
2876
- button.addEventListener('click', async () => {
3338
+ const orb = document.querySelector('.orb');
3339
+
3340
+ async function startScout() {
3341
+ // Both entry points share one guard: the mark can be clicked while the
3342
+ // button is mid-flight, and a second POST would race the first.
3343
+ if (button.disabled) return;
2877
3344
  button.disabled = true;
3345
+ if (orb) orb.dataset.busy = 'true';
2878
3346
  setWaiting(true);
2879
3347
  setStatus('Starting Scout web...');
2880
3348
  try {
@@ -2896,13 +3364,18 @@ function renderOpenScoutStartPage(config) {
2896
3364
  setWaiting(false);
2897
3365
  setStatus('Scout web did not become ready. Try again in a moment.');
2898
3366
  button.disabled = false;
3367
+ if (orb) orb.dataset.busy = 'false';
2899
3368
  }
2900
3369
  } catch (error) {
2901
3370
  setWaiting(false);
2902
3371
  setStatus(error instanceof Error ? error.message : String(error));
2903
3372
  button.disabled = false;
3373
+ if (orb) orb.dataset.busy = 'false';
2904
3374
  }
2905
- });
3375
+ }
3376
+
3377
+ button.addEventListener('click', startScout);
3378
+ if (orb) orb.addEventListener('click', startScout);
2906
3379
  </script>
2907
3380
  </body>
2908
3381
  </html>`;
@@ -2962,12 +3435,11 @@ var RESTART_MIN_DELAY_MS = 1000;
2962
3435
  var RESTART_MAX_DELAY_MS = 30000;
2963
3436
  var BROKER_HEALTH_TIMEOUT_MS = 30000;
2964
3437
  var BROKER_HEALTH_POLL_MS = 250;
2965
- var CHILD_SHUTDOWN_TIMEOUT_MS = 12000;
3438
+ var CHILD_SHUTDOWN_TIMEOUT_MS = 15000;
2966
3439
  var WEB_START_RETRY_MS = 5000;
2967
3440
  var MENU_BUNDLE_ID = "app.openscout.scout.menu";
2968
- var MENU_PROCESS_NAME = "ScoutMenu";
2969
3441
  var PROCESS_NAME = "scout-base";
2970
- var BROKER_LAUNCHER_PROCESS_NAME = "scout-broker-run";
3442
+ var BROKER_PROCESS_NAME = "scout-broker";
2971
3443
  var EDGE_PROCESS_NAME = "scout-edge";
2972
3444
  var MDNS_PROCESS_NAME = "scout-mdns";
2973
3445
  process.title = PROCESS_NAME;
@@ -2977,10 +3449,11 @@ var caddyProcess = null;
2977
3449
  var mdnsProcesses = [];
2978
3450
  var brokerRestartDelayMs = RESTART_MIN_DELAY_MS;
2979
3451
  var edgeRestartDelayMs = RESTART_MIN_DELAY_MS;
2980
- var supervisedWebPid = null;
2981
3452
  var baseKeepAlive = null;
2982
3453
  var webStartRetryTimer = null;
2983
3454
  var webStartInFlight = false;
3455
+ var parentWatcher = null;
3456
+ var parentPid = Number.parseInt(process.env.OPENSCOUT_PARENT_PID ?? "0", 10);
2984
3457
  var config = resolveBrokerServiceConfig();
2985
3458
  var brokerControlUrl = buildLocalBrokerControlUrl(config.brokerHost, config.brokerPort);
2986
3459
  function log(message, details) {
@@ -3049,7 +3522,7 @@ function spawnBroker() {
3049
3522
  runtimeEntrypoint(config),
3050
3523
  "broker"
3051
3524
  ], {
3052
- argv0: BROKER_LAUNCHER_PROCESS_NAME,
3525
+ argv0: BROKER_PROCESS_NAME,
3053
3526
  cwd: config.runtimePackageDir,
3054
3527
  env: {
3055
3528
  ...process.env,
@@ -3069,7 +3542,6 @@ function spawnBroker() {
3069
3542
  brokerProcess.once("exit", (code, signal) => {
3070
3543
  log("broker exited", { code, signal });
3071
3544
  brokerProcess = null;
3072
- supervisedWebPid = null;
3073
3545
  if (!shuttingDown) {
3074
3546
  scheduleBrokerRestart();
3075
3547
  }
@@ -3262,13 +3734,12 @@ async function startWebWhenBrokerIsReady() {
3262
3734
  signal: AbortSignal.timeout(15000)
3263
3735
  });
3264
3736
  const body = await response.json();
3265
- supervisedWebPid = typeof body.pid === "number" ? body.pid : resolvePortListenerPid(Number.parseInt(process.env.OPENSCOUT_WEB_PORT ?? "", 10) || resolveWebPort());
3266
3737
  if (!response.ok || body.ok !== true) {
3267
3738
  warn("web server did not report healthy", body.error ?? response.statusText);
3268
3739
  scheduleWebStartRetry();
3269
3740
  return;
3270
3741
  }
3271
- log("web server ready", { pid: supervisedWebPid });
3742
+ log("web server ready", { pid: body.pid ?? null });
3272
3743
  } catch (error) {
3273
3744
  warn("web server startup failed", error instanceof Error ? error.message : String(error));
3274
3745
  scheduleWebStartRetry();
@@ -3287,22 +3758,17 @@ function scheduleWebStartRetry() {
3287
3758
  }, WEB_START_RETRY_MS);
3288
3759
  webStartRetryTimer.unref();
3289
3760
  }
3290
- function resolvePortListenerPid(port) {
3291
- const result = spawnSync2("lsof", ["-nP", `-iTCP:${port}`, "-sTCP:LISTEN", "-t"], {
3292
- encoding: "utf8"
3293
- });
3294
- if ((result.status ?? 1) !== 0) {
3295
- return null;
3296
- }
3297
- const pid = Number.parseInt(result.stdout.trim().split(/\s+/)[0] ?? "", 10);
3298
- return Number.isFinite(pid) && pid > 0 ? pid : null;
3299
- }
3300
3761
  function findRepoMenuBundle() {
3301
3762
  let current = dirname4(fileURLToPath2(import.meta.url));
3302
3763
  while (true) {
3303
- const candidate = resolve3(current, "apps", "macos", "dist", "ScoutMenu.app");
3304
- if (existsSync6(candidate)) {
3305
- return candidate;
3764
+ const distRoot = resolve3(current, "apps", "macos", "dist");
3765
+ const candidates = [
3766
+ resolve3(distRoot, "Scout.app", "Contents", "Library", "LoginItems", "ScoutMenu.app"),
3767
+ resolve3(distRoot, "ScoutMenu.app")
3768
+ ];
3769
+ for (const candidate of candidates) {
3770
+ if (existsSync6(candidate))
3771
+ return candidate;
3306
3772
  }
3307
3773
  const parent = dirname4(current);
3308
3774
  if (parent === current) {
@@ -3329,12 +3795,6 @@ function startMenuBarApp() {
3329
3795
  warn("menu bar app launch failed", { target: repoBundle ?? MENU_BUNDLE_ID, code });
3330
3796
  });
3331
3797
  }
3332
- function stopMenuBarApp() {
3333
- if (process.platform !== "darwin" || process.env.OPENSCOUT_BASE_MENU_ENABLED === "0") {
3334
- return;
3335
- }
3336
- spawn3("pkill", ["-x", MENU_PROCESS_NAME], { stdio: "ignore" }).unref();
3337
- }
3338
3798
  function isChildExited(child) {
3339
3799
  return child.exitCode !== null || child.signalCode !== null;
3340
3800
  }
@@ -3373,14 +3833,6 @@ async function terminateChildProcess(child, label, timeoutMs = CHILD_SHUTDOWN_TI
3373
3833
  }
3374
3834
  await waitForChildExit(child, 2000);
3375
3835
  }
3376
- function stopSupervisedWeb() {
3377
- if (supervisedWebPid && supervisedWebPid > 0) {
3378
- try {
3379
- process.kill(supervisedWebPid, "SIGTERM");
3380
- } catch {}
3381
- }
3382
- supervisedWebPid = null;
3383
- }
3384
3836
  async function shutdown(exitCode = 0) {
3385
3837
  if (shuttingDown) {
3386
3838
  return;
@@ -3390,12 +3842,14 @@ async function shutdown(exitCode = 0) {
3390
3842
  clearInterval(baseKeepAlive);
3391
3843
  baseKeepAlive = null;
3392
3844
  }
3845
+ if (parentWatcher) {
3846
+ clearInterval(parentWatcher);
3847
+ parentWatcher = null;
3848
+ }
3393
3849
  if (webStartRetryTimer) {
3394
3850
  clearTimeout(webStartRetryTimer);
3395
3851
  webStartRetryTimer = null;
3396
3852
  }
3397
- stopSupervisedWeb();
3398
- stopMenuBarApp();
3399
3853
  const activeCaddyProcess = caddyProcess;
3400
3854
  stopEdgeProcesses();
3401
3855
  await terminateChildProcess(brokerProcess, "broker");
@@ -3421,6 +3875,20 @@ for (const signal of ["SIGINT", "SIGTERM"]) {
3421
3875
  });
3422
3876
  });
3423
3877
  }
3878
+ if (Number.isFinite(parentPid) && parentPid > 0 && parentPid !== process.pid) {
3879
+ parentWatcher = setInterval(() => {
3880
+ try {
3881
+ process.kill(parentPid, 0);
3882
+ } catch {
3883
+ log(`parent ${parentPid} is gone, shutting down base`);
3884
+ shutdown(0).catch((error) => {
3885
+ warn("shutdown failed", error instanceof Error ? error.message : String(error));
3886
+ process.exit(1);
3887
+ });
3888
+ }
3889
+ }, 2000);
3890
+ parentWatcher.unref();
3891
+ }
3424
3892
  log("starting Scout base service", {
3425
3893
  label: config.label,
3426
3894
  brokerUrl: config.brokerUrl,