@openagt/dashboard 0.0.0-stage → 0.9.0

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 (610) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +125 -2
  3. package/dist/agent-id.d.ts +13 -0
  4. package/dist/agent-id.d.ts.map +1 -0
  5. package/dist/agent-id.js +20 -0
  6. package/dist/agent-id.js.map +1 -0
  7. package/dist/agent-locks.d.ts +3 -0
  8. package/dist/agent-locks.d.ts.map +1 -0
  9. package/dist/agent-locks.js +40 -0
  10. package/dist/agent-locks.js.map +1 -0
  11. package/dist/agent-view.d.ts +39 -0
  12. package/dist/agent-view.d.ts.map +1 -0
  13. package/dist/agent-view.js +45 -0
  14. package/dist/agent-view.js.map +1 -0
  15. package/dist/bin.d.ts +3 -0
  16. package/dist/bin.d.ts.map +1 -0
  17. package/dist/bin.js +11 -0
  18. package/dist/bin.js.map +1 -0
  19. package/dist/branch-name.d.ts +8 -0
  20. package/dist/branch-name.d.ts.map +1 -0
  21. package/dist/branch-name.js +20 -0
  22. package/dist/branch-name.js.map +1 -0
  23. package/dist/bridge-browser.d.ts +217 -0
  24. package/dist/bridge-browser.d.ts.map +1 -0
  25. package/dist/bridge-browser.js +520 -0
  26. package/dist/bridge-browser.js.map +1 -0
  27. package/dist/browser-stream.d.ts +20 -0
  28. package/dist/browser-stream.d.ts.map +1 -0
  29. package/dist/browser-stream.js +51 -0
  30. package/dist/browser-stream.js.map +1 -0
  31. package/dist/browser.d.ts +16 -0
  32. package/dist/browser.d.ts.map +1 -0
  33. package/dist/browser.js +38 -0
  34. package/dist/browser.js.map +1 -0
  35. package/dist/built-in.d.ts +38 -0
  36. package/dist/built-in.d.ts.map +1 -0
  37. package/dist/built-in.js +119 -0
  38. package/dist/built-in.js.map +1 -0
  39. package/dist/chrome-extension/background.js +532 -0
  40. package/dist/chrome-extension/content.js +1475 -0
  41. package/dist/chrome-extension/driver-plan.js +41 -0
  42. package/dist/chrome-extension/fingerprint.js +43 -0
  43. package/dist/chrome-extension/manifest.json +31 -0
  44. package/dist/chrome-extension/options.html +48 -0
  45. package/dist/chrome-extension/options.js +122 -0
  46. package/dist/cli.d.ts +43 -0
  47. package/dist/cli.d.ts.map +1 -0
  48. package/dist/cli.js +186 -0
  49. package/dist/cli.js.map +1 -0
  50. package/dist/client.d.ts +16 -0
  51. package/dist/client.d.ts.map +1 -0
  52. package/dist/client.js +30 -0
  53. package/dist/client.js.map +1 -0
  54. package/dist/cloud-run-state.d.ts +27 -0
  55. package/dist/cloud-run-state.d.ts.map +1 -0
  56. package/dist/cloud-run-state.js +36 -0
  57. package/dist/cloud-run-state.js.map +1 -0
  58. package/dist/cloud-scratch-refs.d.ts +85 -0
  59. package/dist/cloud-scratch-refs.d.ts.map +1 -0
  60. package/dist/cloud-scratch-refs.js +275 -0
  61. package/dist/cloud-scratch-refs.js.map +1 -0
  62. package/dist/cloud-work.d.ts +66 -0
  63. package/dist/cloud-work.d.ts.map +1 -0
  64. package/dist/cloud-work.js +204 -0
  65. package/dist/cloud-work.js.map +1 -0
  66. package/dist/daemon-runtime.d.ts +42 -0
  67. package/dist/daemon-runtime.d.ts.map +1 -0
  68. package/dist/daemon-runtime.js +183 -0
  69. package/dist/daemon-runtime.js.map +1 -0
  70. package/dist/daemon-services.d.ts +37 -0
  71. package/dist/daemon-services.d.ts.map +1 -0
  72. package/dist/daemon-services.js +126 -0
  73. package/dist/daemon-services.js.map +1 -0
  74. package/dist/daemon-tick.d.ts +68 -0
  75. package/dist/daemon-tick.d.ts.map +1 -0
  76. package/dist/daemon-tick.js +97 -0
  77. package/dist/daemon-tick.js.map +1 -0
  78. package/dist/daemon.d.ts +65 -0
  79. package/dist/daemon.d.ts.map +1 -0
  80. package/dist/daemon.js +202 -0
  81. package/dist/daemon.js.map +1 -0
  82. package/dist/dashboard/activity.d.ts +41 -0
  83. package/dist/dashboard/activity.d.ts.map +1 -0
  84. package/dist/dashboard/activity.js +56 -0
  85. package/dist/dashboard/activity.js.map +1 -0
  86. package/dist/dashboard/agent-handoff.d.ts +244 -0
  87. package/dist/dashboard/agent-handoff.d.ts.map +1 -0
  88. package/dist/dashboard/agent-handoff.js +310 -0
  89. package/dist/dashboard/agent-handoff.js.map +1 -0
  90. package/dist/dashboard/bridge-endpoints.d.ts +158 -0
  91. package/dist/dashboard/bridge-endpoints.d.ts.map +1 -0
  92. package/dist/dashboard/bridge-endpoints.js +382 -0
  93. package/dist/dashboard/bridge-endpoints.js.map +1 -0
  94. package/dist/dashboard/bridge-question.d.ts +33 -0
  95. package/dist/dashboard/bridge-question.d.ts.map +1 -0
  96. package/dist/dashboard/bridge-question.js +20 -0
  97. package/dist/dashboard/bridge-question.js.map +1 -0
  98. package/dist/dashboard/bridge-sessions.d.ts +25 -0
  99. package/dist/dashboard/bridge-sessions.d.ts.map +1 -0
  100. package/dist/dashboard/bridge-sessions.js +46 -0
  101. package/dist/dashboard/bridge-sessions.js.map +1 -0
  102. package/dist/dashboard/bridge-starts.d.ts +61 -0
  103. package/dist/dashboard/bridge-starts.d.ts.map +1 -0
  104. package/dist/dashboard/bridge-starts.js +94 -0
  105. package/dist/dashboard/bridge-starts.js.map +1 -0
  106. package/dist/dashboard/bridge-store.d.ts +179 -0
  107. package/dist/dashboard/bridge-store.d.ts.map +1 -0
  108. package/dist/dashboard/bridge-store.js +262 -0
  109. package/dist/dashboard/bridge-store.js.map +1 -0
  110. package/dist/dashboard/bundle.d.ts +12 -0
  111. package/dist/dashboard/bundle.d.ts.map +1 -0
  112. package/dist/dashboard/bundle.js +22 -0
  113. package/dist/dashboard/bundle.js.map +1 -0
  114. package/dist/dashboard/cache.d.ts +47 -0
  115. package/dist/dashboard/cache.d.ts.map +1 -0
  116. package/dist/dashboard/cache.js +87 -0
  117. package/dist/dashboard/cache.js.map +1 -0
  118. package/dist/dashboard/content-type.d.ts +3 -0
  119. package/dist/dashboard/content-type.d.ts.map +1 -0
  120. package/dist/dashboard/content-type.js +31 -0
  121. package/dist/dashboard/content-type.js.map +1 -0
  122. package/dist/dashboard/dashboard.d.ts +38 -0
  123. package/dist/dashboard/dashboard.d.ts.map +1 -0
  124. package/dist/dashboard/dashboard.js +42 -0
  125. package/dist/dashboard/dashboard.js.map +1 -0
  126. package/dist/dashboard/docs.d.ts +39 -0
  127. package/dist/dashboard/docs.d.ts.map +1 -0
  128. package/dist/dashboard/docs.js +59 -0
  129. package/dist/dashboard/docs.js.map +1 -0
  130. package/dist/dashboard/git-status.d.ts +44 -0
  131. package/dist/dashboard/git-status.d.ts.map +1 -0
  132. package/dist/dashboard/git-status.js +37 -0
  133. package/dist/dashboard/git-status.js.map +1 -0
  134. package/dist/dashboard/http.d.ts +29 -0
  135. package/dist/dashboard/http.d.ts.map +1 -0
  136. package/dist/dashboard/http.js +74 -0
  137. package/dist/dashboard/http.js.map +1 -0
  138. package/dist/dashboard/index.d.ts +24 -0
  139. package/dist/dashboard/index.d.ts.map +1 -0
  140. package/dist/dashboard/index.js +23 -0
  141. package/dist/dashboard/index.js.map +1 -0
  142. package/dist/dashboard/interventions.d.ts +67 -0
  143. package/dist/dashboard/interventions.d.ts.map +1 -0
  144. package/dist/dashboard/interventions.js +169 -0
  145. package/dist/dashboard/interventions.js.map +1 -0
  146. package/dist/dashboard/keyed-watcher.d.ts +29 -0
  147. package/dist/dashboard/keyed-watcher.d.ts.map +1 -0
  148. package/dist/dashboard/keyed-watcher.js +42 -0
  149. package/dist/dashboard/keyed-watcher.js.map +1 -0
  150. package/dist/dashboard/keys.d.ts +31 -0
  151. package/dist/dashboard/keys.d.ts.map +1 -0
  152. package/dist/dashboard/keys.js +37 -0
  153. package/dist/dashboard/keys.js.map +1 -0
  154. package/dist/dashboard/models.d.ts +25 -0
  155. package/dist/dashboard/models.d.ts.map +1 -0
  156. package/dist/dashboard/models.js +30 -0
  157. package/dist/dashboard/models.js.map +1 -0
  158. package/dist/dashboard/module-host.d.ts +44 -0
  159. package/dist/dashboard/module-host.d.ts.map +1 -0
  160. package/dist/dashboard/module-host.js +91 -0
  161. package/dist/dashboard/module-host.js.map +1 -0
  162. package/dist/dashboard/module-serve.d.ts +15 -0
  163. package/dist/dashboard/module-serve.d.ts.map +1 -0
  164. package/dist/dashboard/module-serve.js +45 -0
  165. package/dist/dashboard/module-serve.js.map +1 -0
  166. package/dist/dashboard/open-in-app.d.ts +43 -0
  167. package/dist/dashboard/open-in-app.d.ts.map +1 -0
  168. package/dist/dashboard/open-in-app.js +98 -0
  169. package/dist/dashboard/open-in-app.js.map +1 -0
  170. package/dist/dashboard/open-questions.d.ts +45 -0
  171. package/dist/dashboard/open-questions.d.ts.map +1 -0
  172. package/dist/dashboard/open-questions.js +62 -0
  173. package/dist/dashboard/open-questions.js.map +1 -0
  174. package/dist/dashboard/overview.d.ts +78 -0
  175. package/dist/dashboard/overview.d.ts.map +1 -0
  176. package/dist/dashboard/overview.js +87 -0
  177. package/dist/dashboard/overview.js.map +1 -0
  178. package/dist/dashboard/projects.d.ts +101 -0
  179. package/dist/dashboard/projects.d.ts.map +1 -0
  180. package/dist/dashboard/projects.js +63 -0
  181. package/dist/dashboard/projects.js.map +1 -0
  182. package/dist/dashboard/pull-requests.d.ts +127 -0
  183. package/dist/dashboard/pull-requests.d.ts.map +1 -0
  184. package/dist/dashboard/pull-requests.js +137 -0
  185. package/dist/dashboard/pull-requests.js.map +1 -0
  186. package/dist/dashboard/queue.d.ts +17 -0
  187. package/dist/dashboard/queue.d.ts.map +1 -0
  188. package/dist/dashboard/queue.js +19 -0
  189. package/dist/dashboard/queue.js.map +1 -0
  190. package/dist/dashboard/quota.d.ts +53 -0
  191. package/dist/dashboard/quota.d.ts.map +1 -0
  192. package/dist/dashboard/quota.js +42 -0
  193. package/dist/dashboard/quota.js.map +1 -0
  194. package/dist/dashboard/relay-endpoints.d.ts +32 -0
  195. package/dist/dashboard/relay-endpoints.d.ts.map +1 -0
  196. package/dist/dashboard/relay-endpoints.js +115 -0
  197. package/dist/dashboard/relay-endpoints.js.map +1 -0
  198. package/dist/dashboard/remote-run.d.ts +95 -0
  199. package/dist/dashboard/remote-run.d.ts.map +1 -0
  200. package/dist/dashboard/remote-run.js +235 -0
  201. package/dist/dashboard/remote-run.js.map +1 -0
  202. package/dist/dashboard/rpc-serve.d.ts +106 -0
  203. package/dist/dashboard/rpc-serve.d.ts.map +1 -0
  204. package/dist/dashboard/rpc-serve.js +180 -0
  205. package/dist/dashboard/rpc-serve.js.map +1 -0
  206. package/dist/dashboard/run-inbox.d.ts +31 -0
  207. package/dist/dashboard/run-inbox.d.ts.map +1 -0
  208. package/dist/dashboard/run-inbox.js +51 -0
  209. package/dist/dashboard/run-inbox.js.map +1 -0
  210. package/dist/dashboard/server.d.ts +105 -0
  211. package/dist/dashboard/server.d.ts.map +1 -0
  212. package/dist/dashboard/server.js +231 -0
  213. package/dist/dashboard/server.js.map +1 -0
  214. package/dist/dashboard/static.d.ts +9 -0
  215. package/dist/dashboard/static.d.ts.map +1 -0
  216. package/dist/dashboard/static.js +54 -0
  217. package/dist/dashboard/static.js.map +1 -0
  218. package/dist/dashboard/types.d.ts +135 -0
  219. package/dist/dashboard/types.d.ts.map +1 -0
  220. package/dist/dashboard/types.js +2 -0
  221. package/dist/dashboard/types.js.map +1 -0
  222. package/dist/dashboard/web-start-endpoints.d.ts +32 -0
  223. package/dist/dashboard/web-start-endpoints.d.ts.map +1 -0
  224. package/dist/dashboard/web-start-endpoints.js +75 -0
  225. package/dist/dashboard/web-start-endpoints.js.map +1 -0
  226. package/dist/dashboard-bundle/assets/client-CbBRB9m4.js +9 -0
  227. package/dist/dashboard-bundle/assets/jsx-runtime-By8HlURe.js +1 -0
  228. package/dist/dashboard-bundle/assets/main-B98UOA3_.js +140 -0
  229. package/dist/dashboard-bundle/assets/main-ByRjbCiA.css +2 -0
  230. package/dist/dashboard-bundle/assets/module-v213KWfH.js +21 -0
  231. package/dist/dashboard-bundle/assets/react-CZI7_Jkm.js +1 -0
  232. package/dist/dashboard-bundle/assets/react-dom-cJyBB_A4.js +1 -0
  233. package/dist/dashboard-bundle/assets/rolldown-runtime-QTnfLwEv.js +1 -0
  234. package/dist/dashboard-bundle/host/module.js +1 -0
  235. package/dist/dashboard-bundle/host/react-dom-client.js +1 -0
  236. package/dist/dashboard-bundle/host/react-dom.js +1 -0
  237. package/dist/dashboard-bundle/host/react-jsx-runtime.js +1 -0
  238. package/dist/dashboard-bundle/host/react.js +1 -0
  239. package/dist/dashboard-bundle/index.html +42 -0
  240. package/dist/dashboard-bundle/logo-animated.svg +34 -0
  241. package/dist/dashboard-bundle/logo.svg +16 -0
  242. package/dist/dashboard-rpc/context.d.ts +56 -0
  243. package/dist/dashboard-rpc/context.d.ts.map +1 -0
  244. package/dist/dashboard-rpc/context.js +106 -0
  245. package/dist/dashboard-rpc/context.js.map +1 -0
  246. package/dist/dashboard-rpc/control.d.ts +124 -0
  247. package/dist/dashboard-rpc/control.d.ts.map +1 -0
  248. package/dist/dashboard-rpc/control.js +284 -0
  249. package/dist/dashboard-rpc/control.js.map +1 -0
  250. package/dist/dashboard-rpc/devices.d.ts +9 -0
  251. package/dist/dashboard-rpc/devices.d.ts.map +1 -0
  252. package/dist/dashboard-rpc/devices.js +12 -0
  253. package/dist/dashboard-rpc/devices.js.map +1 -0
  254. package/dist/dashboard-rpc/events-tail.d.ts +68 -0
  255. package/dist/dashboard-rpc/events-tail.d.ts.map +1 -0
  256. package/dist/dashboard-rpc/events-tail.js +257 -0
  257. package/dist/dashboard-rpc/events-tail.js.map +1 -0
  258. package/dist/dashboard-rpc/events.d.ts +39 -0
  259. package/dist/dashboard-rpc/events.d.ts.map +1 -0
  260. package/dist/dashboard-rpc/events.js +47 -0
  261. package/dist/dashboard-rpc/events.js.map +1 -0
  262. package/dist/dashboard-rpc/index.d.ts +29 -0
  263. package/dist/dashboard-rpc/index.d.ts.map +1 -0
  264. package/dist/dashboard-rpc/index.js +40 -0
  265. package/dist/dashboard-rpc/index.js.map +1 -0
  266. package/dist/dashboard-rpc/models.d.ts +4 -0
  267. package/dist/dashboard-rpc/models.d.ts.map +1 -0
  268. package/dist/dashboard-rpc/models.js +8 -0
  269. package/dist/dashboard-rpc/models.js.map +1 -0
  270. package/dist/dashboard-rpc/modules.d.ts +45 -0
  271. package/dist/dashboard-rpc/modules.d.ts.map +1 -0
  272. package/dist/dashboard-rpc/modules.js +79 -0
  273. package/dist/dashboard-rpc/modules.js.map +1 -0
  274. package/dist/dashboard-rpc/preferences.d.ts +41 -0
  275. package/dist/dashboard-rpc/preferences.d.ts.map +1 -0
  276. package/dist/dashboard-rpc/preferences.js +65 -0
  277. package/dist/dashboard-rpc/preferences.js.map +1 -0
  278. package/dist/dashboard-rpc/projects.d.ts +85 -0
  279. package/dist/dashboard-rpc/projects.d.ts.map +1 -0
  280. package/dist/dashboard-rpc/projects.js +129 -0
  281. package/dist/dashboard-rpc/projects.js.map +1 -0
  282. package/dist/dashboard-rpc/quota.d.ts +4 -0
  283. package/dist/dashboard-rpc/quota.d.ts.map +1 -0
  284. package/dist/dashboard-rpc/quota.js +15 -0
  285. package/dist/dashboard-rpc/quota.js.map +1 -0
  286. package/dist/dashboard-rpc/reads.d.ts +185 -0
  287. package/dist/dashboard-rpc/reads.d.ts.map +1 -0
  288. package/dist/dashboard-rpc/reads.js +370 -0
  289. package/dist/dashboard-rpc/reads.js.map +1 -0
  290. package/dist/dashboard-rpc/relay-agent.d.ts +9 -0
  291. package/dist/dashboard-rpc/relay-agent.d.ts.map +1 -0
  292. package/dist/dashboard-rpc/relay-agent.js +21 -0
  293. package/dist/dashboard-rpc/relay-agent.js.map +1 -0
  294. package/dist/dashboard-rpc/relay-dispatch.d.ts +9 -0
  295. package/dist/dashboard-rpc/relay-dispatch.d.ts.map +1 -0
  296. package/dist/dashboard-rpc/relay-dispatch.js +24 -0
  297. package/dist/dashboard-rpc/relay-dispatch.js.map +1 -0
  298. package/dist/dashboard-rpc/stream-forward.d.ts +17 -0
  299. package/dist/dashboard-rpc/stream-forward.d.ts.map +1 -0
  300. package/dist/dashboard-rpc/stream-forward.js +38 -0
  301. package/dist/dashboard-rpc/stream-forward.js.map +1 -0
  302. package/dist/dashboard-rpc/test-context.d.ts +23 -0
  303. package/dist/dashboard-rpc/test-context.d.ts.map +1 -0
  304. package/dist/dashboard-rpc/test-context.js +43 -0
  305. package/dist/dashboard-rpc/test-context.js.map +1 -0
  306. package/dist/driver-names.d.ts +22 -0
  307. package/dist/driver-names.d.ts.map +1 -0
  308. package/dist/driver-names.js +29 -0
  309. package/dist/driver-names.js.map +1 -0
  310. package/dist/error-message.d.ts +8 -0
  311. package/dist/error-message.d.ts.map +1 -0
  312. package/dist/error-message.js +10 -0
  313. package/dist/error-message.js.map +1 -0
  314. package/dist/event-stream.d.ts +33 -0
  315. package/dist/event-stream.d.ts.map +1 -0
  316. package/dist/event-stream.js +104 -0
  317. package/dist/event-stream.js.map +1 -0
  318. package/dist/events.d.ts +236 -0
  319. package/dist/events.d.ts.map +1 -0
  320. package/dist/events.js +5 -0
  321. package/dist/events.js.map +1 -0
  322. package/dist/format-bytes.d.ts +3 -0
  323. package/dist/format-bytes.d.ts.map +1 -0
  324. package/dist/format-bytes.js +18 -0
  325. package/dist/format-bytes.js.map +1 -0
  326. package/dist/has-remote.d.ts +8 -0
  327. package/dist/has-remote.d.ts.map +1 -0
  328. package/dist/has-remote.js +10 -0
  329. package/dist/has-remote.js.map +1 -0
  330. package/dist/index.d.ts +42 -0
  331. package/dist/index.d.ts.map +1 -0
  332. package/dist/index.js +16 -0
  333. package/dist/index.js.map +1 -0
  334. package/dist/install.d.ts +31 -0
  335. package/dist/install.d.ts.map +1 -0
  336. package/dist/install.js +54 -0
  337. package/dist/install.js.map +1 -0
  338. package/dist/jsonl-tail.d.ts +59 -0
  339. package/dist/jsonl-tail.d.ts.map +1 -0
  340. package/dist/jsonl-tail.js +152 -0
  341. package/dist/jsonl-tail.js.map +1 -0
  342. package/dist/loopback-host.d.ts +20 -0
  343. package/dist/loopback-host.d.ts.map +1 -0
  344. package/dist/loopback-host.js +31 -0
  345. package/dist/loopback-host.js.map +1 -0
  346. package/dist/module-server.d.ts +56 -0
  347. package/dist/module-types/dashboard/components/DiffStat.d.ts +6 -0
  348. package/dist/module-types/dashboard/components/DriverModelMenu.d.ts +23 -0
  349. package/dist/module-types/dashboard/components/LinkActions.d.ts +26 -0
  350. package/dist/module-types/dashboard/components/Markdown.d.ts +4 -0
  351. package/dist/module-types/dashboard/components/SettingsRows.d.ts +37 -0
  352. package/dist/module-types/dashboard/components/StartAgentButton.d.ts +39 -0
  353. package/dist/module-types/dashboard/components/ui/badge.d.ts +2 -0
  354. package/dist/module-types/dashboard/components/ui/button.d.ts +10 -0
  355. package/dist/module-types/dashboard/components/ui/card.d.ts +5 -0
  356. package/dist/module-types/dashboard/components/ui/checkbox.d.ts +7 -0
  357. package/dist/module-types/dashboard/components/ui/dropdown-menu.d.ts +16 -0
  358. package/dist/module-types/dashboard/components/ui/input.d.ts +2 -0
  359. package/dist/module-types/dashboard/components/ui/option-label.d.ts +4 -0
  360. package/dist/module-types/dashboard/components/ui/popover.d.ts +8 -0
  361. package/dist/module-types/dashboard/components/ui/scroll-area.d.ts +10 -0
  362. package/dist/module-types/dashboard/components/ui/separator.d.ts +3 -0
  363. package/dist/module-types/dashboard/components/ui/skeleton.d.ts +2 -0
  364. package/dist/module-types/dashboard/components/ui/slider.d.ts +9 -0
  365. package/dist/module-types/dashboard/components/ui/tooltip.d.ts +11 -0
  366. package/dist/module-types/dashboard/lib/agent-settings.d.ts +2 -0
  367. package/dist/module-types/dashboard/lib/draft-handoff.d.ts +15 -0
  368. package/dist/module-types/dashboard/lib/format-date.d.ts +51 -0
  369. package/dist/module-types/dashboard/lib/host-services.d.ts +12 -0
  370. package/dist/module-types/dashboard/lib/models.d.ts +24 -0
  371. package/dist/module-types/dashboard/lib/route.d.ts +38 -0
  372. package/dist/module-types/dashboard/lib/rpc.d.ts +31 -0
  373. package/dist/module-types/dashboard/lib/use-action.d.ts +25 -0
  374. package/dist/module-types/dashboard/lib/use-async.d.ts +45 -0
  375. package/dist/module-types/dashboard/lib/use-modules.d.ts +79 -0
  376. package/dist/module-types/dashboard/lib/utils.d.ts +3 -0
  377. package/dist/module-types/dashboard/module/index.d.ts +335 -0
  378. package/dist/module-types/dashboard/rpc/models.d.ts +2 -0
  379. package/dist/module-types/dashboard/rpc/modules.d.ts +5 -0
  380. package/dist/module-types/src/agent-id.d.ts +12 -0
  381. package/dist/module-types/src/agent-locks.d.ts +2 -0
  382. package/dist/module-types/src/agent-view.d.ts +38 -0
  383. package/dist/module-types/src/bridge-browser.d.ts +216 -0
  384. package/dist/module-types/src/browser-stream.d.ts +19 -0
  385. package/dist/module-types/src/browser.d.ts +15 -0
  386. package/dist/module-types/src/built-in.d.ts +37 -0
  387. package/dist/module-types/src/client.d.ts +15 -0
  388. package/dist/module-types/src/cloud-run-state.d.ts +26 -0
  389. package/dist/module-types/src/dashboard/activity.d.ts +40 -0
  390. package/dist/module-types/src/dashboard/agent-handoff.d.ts +243 -0
  391. package/dist/module-types/src/dashboard/bridge-endpoints.d.ts +157 -0
  392. package/dist/module-types/src/dashboard/bridge-question.d.ts +32 -0
  393. package/dist/module-types/src/dashboard/bridge-store.d.ts +178 -0
  394. package/dist/module-types/src/dashboard/cache.d.ts +46 -0
  395. package/dist/module-types/src/dashboard/content-type.d.ts +2 -0
  396. package/dist/module-types/src/dashboard/dashboard.d.ts +37 -0
  397. package/dist/module-types/src/dashboard/docs.d.ts +38 -0
  398. package/dist/module-types/src/dashboard/git-status.d.ts +43 -0
  399. package/dist/module-types/src/dashboard/http.d.ts +28 -0
  400. package/dist/module-types/src/dashboard/interventions.d.ts +66 -0
  401. package/dist/module-types/src/dashboard/keyed-watcher.d.ts +28 -0
  402. package/dist/module-types/src/dashboard/keys.d.ts +30 -0
  403. package/dist/module-types/src/dashboard/models.d.ts +24 -0
  404. package/dist/module-types/src/dashboard/module-host.d.ts +43 -0
  405. package/dist/module-types/src/dashboard/module-serve.d.ts +14 -0
  406. package/dist/module-types/src/dashboard/open-in-app.d.ts +42 -0
  407. package/dist/module-types/src/dashboard/open-questions.d.ts +44 -0
  408. package/dist/module-types/src/dashboard/overview.d.ts +77 -0
  409. package/dist/module-types/src/dashboard/projects.d.ts +100 -0
  410. package/dist/module-types/src/dashboard/pull-requests.d.ts +126 -0
  411. package/dist/module-types/src/dashboard/queue.d.ts +16 -0
  412. package/dist/module-types/src/dashboard/quota.d.ts +52 -0
  413. package/dist/module-types/src/dashboard/remote-run.d.ts +94 -0
  414. package/dist/module-types/src/dashboard/rpc-serve.d.ts +105 -0
  415. package/dist/module-types/src/dashboard/run-inbox.d.ts +30 -0
  416. package/dist/module-types/src/dashboard/types.d.ts +134 -0
  417. package/dist/module-types/src/dashboard-rpc/context.d.ts +55 -0
  418. package/dist/module-types/src/dashboard-rpc/control.d.ts +123 -0
  419. package/dist/module-types/src/dashboard-rpc/devices.d.ts +8 -0
  420. package/dist/module-types/src/dashboard-rpc/events-tail.d.ts +67 -0
  421. package/dist/module-types/src/dashboard-rpc/events.d.ts +38 -0
  422. package/dist/module-types/src/dashboard-rpc/index.d.ts +28 -0
  423. package/dist/module-types/src/dashboard-rpc/models.d.ts +3 -0
  424. package/dist/module-types/src/dashboard-rpc/modules.d.ts +44 -0
  425. package/dist/module-types/src/dashboard-rpc/preferences.d.ts +40 -0
  426. package/dist/module-types/src/dashboard-rpc/projects.d.ts +84 -0
  427. package/dist/module-types/src/dashboard-rpc/quota.d.ts +3 -0
  428. package/dist/module-types/src/dashboard-rpc/reads.d.ts +184 -0
  429. package/dist/module-types/src/dashboard-rpc/relay-agent.d.ts +8 -0
  430. package/dist/module-types/src/dashboard-rpc/stream-forward.d.ts +16 -0
  431. package/dist/module-types/src/driver-names.d.ts +21 -0
  432. package/dist/module-types/src/error-message.d.ts +7 -0
  433. package/dist/module-types/src/event-stream.d.ts +32 -0
  434. package/dist/module-types/src/events.d.ts +235 -0
  435. package/dist/module-types/src/format-bytes.d.ts +2 -0
  436. package/dist/module-types/src/has-remote.d.ts +7 -0
  437. package/dist/module-types/src/index.d.ts +41 -0
  438. package/dist/module-types/src/jsonl-tail.d.ts +58 -0
  439. package/dist/module-types/src/loopback-host.d.ts +19 -0
  440. package/dist/module-types/src/node-fs.d.ts +32 -0
  441. package/dist/module-types/src/open-choices.d.ts +14 -0
  442. package/dist/module-types/src/openagent-dir.d.ts +10 -0
  443. package/dist/module-types/src/openagent-gitignore.d.ts +11 -0
  444. package/dist/module-types/src/pick-directory.d.ts +29 -0
  445. package/dist/module-types/src/preference-defaults.d.ts +42 -0
  446. package/dist/module-types/src/project-commands.d.ts +23 -0
  447. package/dist/module-types/src/project-errors.d.ts +59 -0
  448. package/dist/module-types/src/project-hooks.d.ts +129 -0
  449. package/dist/module-types/src/project-modules.d.ts +49 -0
  450. package/dist/module-types/src/project-presets.d.ts +29 -0
  451. package/dist/module-types/src/project.d.ts +28 -0
  452. package/dist/module-types/src/publish-levels.d.ts +32 -0
  453. package/dist/module-types/src/quota-boundary.d.ts +64 -0
  454. package/dist/module-types/src/quota-poller.d.ts +82 -0
  455. package/dist/module-types/src/registry.d.ts +226 -0
  456. package/dist/module-types/src/store/agent-checkout.d.ts +53 -0
  457. package/dist/module-types/src/store/agent-store.d.ts +266 -0
  458. package/dist/module-types/src/store/branches.d.ts +163 -0
  459. package/dist/module-types/src/store/git-host.d.ts +113 -0
  460. package/dist/module-types/src/store/index.d.ts +9 -0
  461. package/dist/module-types/src/store/provided.d.ts +16 -0
  462. package/dist/module-types/src/store/queue.d.ts +45 -0
  463. package/dist/module-types/src/store/repository.d.ts +32 -0
  464. package/dist/module-types/src/store/run-record.d.ts +21 -0
  465. package/dist/module-types/src/store/runs.d.ts +107 -0
  466. package/dist/module-types/src/store/tickets.d.ts +72 -0
  467. package/dist/module-types/src/terminal.d.ts +3 -0
  468. package/dist/module-types/src/worktrees.d.ts +89 -0
  469. package/dist/module.css +50 -0
  470. package/dist/node-fs.d.ts +33 -0
  471. package/dist/node-fs.d.ts.map +1 -0
  472. package/dist/node-fs.js +57 -0
  473. package/dist/node-fs.js.map +1 -0
  474. package/dist/open-choices.d.ts +15 -0
  475. package/dist/open-choices.d.ts.map +1 -0
  476. package/dist/open-choices.js +31 -0
  477. package/dist/open-choices.js.map +1 -0
  478. package/dist/openagent-dir.d.ts +11 -0
  479. package/dist/openagent-dir.d.ts.map +1 -0
  480. package/dist/openagent-dir.js +11 -0
  481. package/dist/openagent-dir.js.map +1 -0
  482. package/dist/openagent-gitignore.d.ts +12 -0
  483. package/dist/openagent-gitignore.d.ts.map +1 -0
  484. package/dist/openagent-gitignore.js +19 -0
  485. package/dist/openagent-gitignore.js.map +1 -0
  486. package/dist/pick-directory.d.ts +30 -0
  487. package/dist/pick-directory.d.ts.map +1 -0
  488. package/dist/pick-directory.js +102 -0
  489. package/dist/pick-directory.js.map +1 -0
  490. package/dist/preference-defaults.d.ts +43 -0
  491. package/dist/preference-defaults.d.ts.map +1 -0
  492. package/dist/preference-defaults.js +34 -0
  493. package/dist/preference-defaults.js.map +1 -0
  494. package/dist/project-commands.d.ts +24 -0
  495. package/dist/project-commands.d.ts.map +1 -0
  496. package/dist/project-commands.js +57 -0
  497. package/dist/project-commands.js.map +1 -0
  498. package/dist/project-errors.d.ts +60 -0
  499. package/dist/project-errors.d.ts.map +1 -0
  500. package/dist/project-errors.js +51 -0
  501. package/dist/project-errors.js.map +1 -0
  502. package/dist/project-hooks.d.ts +130 -0
  503. package/dist/project-hooks.d.ts.map +1 -0
  504. package/dist/project-hooks.js +232 -0
  505. package/dist/project-hooks.js.map +1 -0
  506. package/dist/project-modules.d.ts +50 -0
  507. package/dist/project-modules.d.ts.map +1 -0
  508. package/dist/project-modules.js +110 -0
  509. package/dist/project-modules.js.map +1 -0
  510. package/dist/project-pass.d.ts +32 -0
  511. package/dist/project-pass.d.ts.map +1 -0
  512. package/dist/project-pass.js +45 -0
  513. package/dist/project-pass.js.map +1 -0
  514. package/dist/project-presets.d.ts +30 -0
  515. package/dist/project-presets.d.ts.map +1 -0
  516. package/dist/project-presets.js +74 -0
  517. package/dist/project-presets.js.map +1 -0
  518. package/dist/project.d.ts +29 -0
  519. package/dist/project.d.ts.map +1 -0
  520. package/dist/project.js +41 -0
  521. package/dist/project.js.map +1 -0
  522. package/dist/publish-levels.d.ts +33 -0
  523. package/dist/publish-levels.d.ts.map +1 -0
  524. package/dist/publish-levels.js +53 -0
  525. package/dist/publish-levels.js.map +1 -0
  526. package/dist/quota-boundary.d.ts +65 -0
  527. package/dist/quota-boundary.d.ts.map +1 -0
  528. package/dist/quota-boundary.js +135 -0
  529. package/dist/quota-boundary.js.map +1 -0
  530. package/dist/quota-poller.d.ts +83 -0
  531. package/dist/quota-poller.d.ts.map +1 -0
  532. package/dist/quota-poller.js +118 -0
  533. package/dist/quota-poller.js.map +1 -0
  534. package/dist/registry.d.ts +227 -0
  535. package/dist/registry.d.ts.map +1 -0
  536. package/dist/registry.js +364 -0
  537. package/dist/registry.js.map +1 -0
  538. package/dist/remove-files.d.ts +24 -0
  539. package/dist/remove-files.d.ts.map +1 -0
  540. package/dist/remove-files.js +98 -0
  541. package/dist/remove-files.js.map +1 -0
  542. package/dist/request-path.d.ts +10 -0
  543. package/dist/request-path.d.ts.map +1 -0
  544. package/dist/request-path.js +16 -0
  545. package/dist/request-path.js.map +1 -0
  546. package/dist/store/agent-checkout.d.ts +54 -0
  547. package/dist/store/agent-checkout.d.ts.map +1 -0
  548. package/dist/store/agent-checkout.js +61 -0
  549. package/dist/store/agent-checkout.js.map +1 -0
  550. package/dist/store/agent-store.d.ts +267 -0
  551. package/dist/store/agent-store.d.ts.map +1 -0
  552. package/dist/store/agent-store.js +190 -0
  553. package/dist/store/agent-store.js.map +1 -0
  554. package/dist/store/branches.d.ts +164 -0
  555. package/dist/store/branches.d.ts.map +1 -0
  556. package/dist/store/branches.js +187 -0
  557. package/dist/store/branches.js.map +1 -0
  558. package/dist/store/git-host.d.ts +114 -0
  559. package/dist/store/git-host.d.ts.map +1 -0
  560. package/dist/store/git-host.js +103 -0
  561. package/dist/store/git-host.js.map +1 -0
  562. package/dist/store/index.d.ts +10 -0
  563. package/dist/store/index.d.ts.map +1 -0
  564. package/dist/store/index.js +10 -0
  565. package/dist/store/index.js.map +1 -0
  566. package/dist/store/provided.d.ts +17 -0
  567. package/dist/store/provided.d.ts.map +1 -0
  568. package/dist/store/provided.js +37 -0
  569. package/dist/store/provided.js.map +1 -0
  570. package/dist/store/queue.d.ts +46 -0
  571. package/dist/store/queue.d.ts.map +1 -0
  572. package/dist/store/queue.js +61 -0
  573. package/dist/store/queue.js.map +1 -0
  574. package/dist/store/repository.d.ts +33 -0
  575. package/dist/store/repository.d.ts.map +1 -0
  576. package/dist/store/repository.js +25 -0
  577. package/dist/store/repository.js.map +1 -0
  578. package/dist/store/run-record.d.ts +22 -0
  579. package/dist/store/run-record.d.ts.map +1 -0
  580. package/dist/store/run-record.js +108 -0
  581. package/dist/store/run-record.js.map +1 -0
  582. package/dist/store/runs.d.ts +108 -0
  583. package/dist/store/runs.d.ts.map +1 -0
  584. package/dist/store/runs.js +146 -0
  585. package/dist/store/runs.js.map +1 -0
  586. package/dist/store/test-branches.d.ts +18 -0
  587. package/dist/store/test-branches.d.ts.map +1 -0
  588. package/dist/store/test-branches.js +59 -0
  589. package/dist/store/test-branches.js.map +1 -0
  590. package/dist/store/test-runs.d.ts +15 -0
  591. package/dist/store/test-runs.d.ts.map +1 -0
  592. package/dist/store/test-runs.js +37 -0
  593. package/dist/store/test-runs.js.map +1 -0
  594. package/dist/store/tickets.d.ts +73 -0
  595. package/dist/store/tickets.d.ts.map +1 -0
  596. package/dist/store/tickets.js +67 -0
  597. package/dist/store/tickets.js.map +1 -0
  598. package/dist/terminal.d.ts +4 -0
  599. package/dist/terminal.d.ts.map +1 -0
  600. package/dist/terminal.js +97 -0
  601. package/dist/terminal.js.map +1 -0
  602. package/dist/update-check.d.ts +44 -0
  603. package/dist/update-check.d.ts.map +1 -0
  604. package/dist/update-check.js +71 -0
  605. package/dist/update-check.js.map +1 -0
  606. package/dist/worktrees.d.ts +90 -0
  607. package/dist/worktrees.d.ts.map +1 -0
  608. package/dist/worktrees.js +123 -0
  609. package/dist/worktrees.js.map +1 -0
  610. package/package.json +103 -3
@@ -0,0 +1,235 @@
1
+ import { EventStream } from '../event-stream.js';
2
+ import { errorMessage } from '../error-message.js';
3
+ const START_TIMEOUT_MS = 15_000;
4
+ /** How long a status ping waits before calling a device offline (#1072): short, since it polls. */
5
+ const PING_TIMEOUT_MS = 3_000;
6
+ /**
7
+ * Health-check a saved device (#1072): a cookie'd `GET /_relay/ping`, true on any 2xx, false on a
8
+ * non-2xx, an unreachable host, or the timeout. The token stays in memory for the check only, never
9
+ * persisted, same as {@link startRemoteAgent}. This is how the browser's status dots learn reachable
10
+ * from not: it has the tokens, the daemon does the cross-origin request.
11
+ */
12
+ export async function pingRemote(target) {
13
+ try {
14
+ const res = await fetch(`${trimSlashes(target.url)}/_relay/ping`, {
15
+ headers: { cookie: `oa_daemon=${target.token}` },
16
+ signal: AbortSignal.timeout(PING_TIMEOUT_MS),
17
+ });
18
+ return res.ok;
19
+ }
20
+ catch {
21
+ return false;
22
+ }
23
+ }
24
+ /** The two headers every relay request carries: JSON, and the shared-token cookie (#1051). No Origin on purpose. */
25
+ function relayHeaders(token) {
26
+ return { 'content-type': 'application/json', cookie: `oa_daemon=${token}` };
27
+ }
28
+ /**
29
+ * Start an agent on the remote daemon and return its {@link StartAgentResult} (with the remote's own run
30
+ * id). A non-2xx or a transport failure surfaces as an `ok: false` result the dashboard shows, the
31
+ * same shape a local refusal has, so the caller does not special-case remote errors.
32
+ */
33
+ export async function startRemoteAgent(target, body) {
34
+ try {
35
+ const res = await fetch(`${trimSlashes(target.url)}/_relay/start`, {
36
+ method: 'POST',
37
+ headers: relayHeaders(target.token),
38
+ body: JSON.stringify(body),
39
+ signal: AbortSignal.timeout(START_TIMEOUT_MS),
40
+ });
41
+ if (!res.ok)
42
+ return { ok: false, error: `the device refused the run (${res.status})` };
43
+ return (await res.json());
44
+ }
45
+ catch (err) {
46
+ return { ok: false, error: `could not reach the device: ${errorMessage(err)}` };
47
+ }
48
+ }
49
+ const RPC_TIMEOUT_MS = 60_000; // a relayed git push/PR runs over the network on the device
50
+ /**
51
+ * Relay one run-scoped RPC to the device that owns a remote agent (#1067 slice 2). The local daemon
52
+ * holds the device token, so a read/diff/handoff/push/PR for a relayed agent runs ON the device: POST
53
+ * {fn, args} to the remote's /_relay/rpc over the shared-token cookie (#1051) (no Origin), returning the device's
54
+ * result. Throws on an unreachable device or a non-2xx so the caller falls back to its own empty/error
55
+ * shape, the same way a failed local read does.
56
+ */
57
+ export async function relayRpc(target, fn, args) {
58
+ const res = await fetch(`${trimSlashes(target.url)}/_relay/rpc`, {
59
+ method: 'POST',
60
+ headers: relayHeaders(target.token),
61
+ body: JSON.stringify({ fn, args }),
62
+ signal: AbortSignal.timeout(RPC_TIMEOUT_MS),
63
+ });
64
+ if (!res.ok)
65
+ throw new Error(`the device refused the request (${res.status})`);
66
+ const body = (await res.json());
67
+ return body.result;
68
+ }
69
+ /**
70
+ * Fetch-stream a remote agent's newline-delimited events into `onEvent` until the remote closes the
71
+ * body, the agent ends, or `cancel()` is called. A 401 (the token was rotated) ends the stream
72
+ * cleanly rather than as an error, so the dashboard sees a normal `done`, not a lost connection.
73
+ * Returns a cancel function; calling it aborts the fetch and releases the reader.
74
+ */
75
+ export function streamRemoteEvents(target, agentId, onEvent, onEnd) {
76
+ const controller = new AbortController();
77
+ let ended = false;
78
+ const end = () => {
79
+ if (ended)
80
+ return;
81
+ ended = true;
82
+ onEnd?.();
83
+ };
84
+ void (async () => {
85
+ try {
86
+ const url = `${trimSlashes(target.url)}/_relay/events?run=${encodeURIComponent(agentId)}`;
87
+ const res = await fetch(url, { headers: relayHeaders(target.token), signal: controller.signal });
88
+ // 401 = the device rotated its token. Nothing more will stream; end cleanly (a done, not a loss).
89
+ if (!res.ok || !res.body)
90
+ return end();
91
+ const reader = res.body.getReader();
92
+ const decoder = new TextDecoder();
93
+ let buffer = '';
94
+ for (;;) {
95
+ const { value, done } = await reader.read();
96
+ if (done)
97
+ break;
98
+ buffer += decoder.decode(value, { stream: true });
99
+ // Emit every complete line, keeping the trailing partial for the next chunk.
100
+ let newline = buffer.indexOf('\n');
101
+ while (newline !== -1) {
102
+ emitLine(buffer.slice(0, newline), onEvent);
103
+ buffer = buffer.slice(newline + 1);
104
+ newline = buffer.indexOf('\n');
105
+ }
106
+ }
107
+ emitLine(buffer, onEvent); // a final line with no trailing newline
108
+ }
109
+ catch {
110
+ // Aborted by cancel(), or the transport dropped: either way the stream is over.
111
+ }
112
+ finally {
113
+ end();
114
+ }
115
+ })();
116
+ return () => {
117
+ controller.abort();
118
+ end();
119
+ };
120
+ }
121
+ /** Parse one NDJSON line as a {@link OpenAgentEvent} and forward it; a blank or malformed line is skipped. */
122
+ function emitLine(line, onEvent) {
123
+ const trimmed = line.trim();
124
+ if (!trimmed)
125
+ return;
126
+ try {
127
+ onEvent(JSON.parse(trimmed));
128
+ }
129
+ catch {
130
+ // A partial or malformed line is dropped rather than crashing the pump.
131
+ }
132
+ }
133
+ /**
134
+ * The local daemon's live relayed runs (#1067), keyed by the remote agent id. Registering an agent opens
135
+ * an {@link EventStream} the dashboard reads through `onEvents`, fed by {@link streamRemoteEvents}
136
+ * from the remote. This map is where a saved device's token lives daemon-side: in memory, for the
137
+ * run's lifetime.
138
+ *
139
+ * The `targets` map outlives the event pump (#1067 slice 2): a finished remote agent's post-run reads,
140
+ * open-PR and merge still have to reach the device after its event stream has ended, so the device
141
+ * target is kept until {@link dispose} clears it, not dropped when the stream closes.
142
+ *
143
+ * The `metas` map (#1077) holds a local {@link AgentMeta} stub per relayed agent so `onAgents` can show a
144
+ * remote run in the session list and re-open it after a dashboard reload; {@link list} projects it
145
+ * per project. Same lifetime as `targets`: it outlives the event stream and is cleared on dispose.
146
+ */
147
+ export class RelayedAgents {
148
+ agents = new Map();
149
+ targets = new Map();
150
+ // The local AgentMeta stub for each relayed agent, so onAgents can show a remote agent in the session list
151
+ // and re-open it after a reload; outlives the event stream, cleared on dispose (same lifetime as targets).
152
+ metas = new Map();
153
+ /** Open a local stream for a remote agent and start pumping the remote's events into it. */
154
+ register(agentId, target, meta, projectId) {
155
+ this.targets.set(agentId, target); // kept past the stream, for post-run reads/push/PR (slice 2)
156
+ this.metas.set(agentId, { meta, projectId }); // the local list row, so a reload re-opens the run (#1077)
157
+ this.agents.get(agentId)?.cancel(); // a re-register (same id) replaces the old pump
158
+ const stream = new EventStream();
159
+ const cancel = streamRemoteEvents(target, agentId, event => {
160
+ stream.push(event);
161
+ this.apply(agentId, event); // fold the event into the run's list row, mirroring the device
162
+ }, () => this.endStream(agentId));
163
+ this.agents.set(agentId, { target, stream, cancel });
164
+ }
165
+ /** The live event stream for a relayed agent, or undefined when this daemon is not relaying it. */
166
+ get(agentId) {
167
+ return agentId ? this.agents.get(agentId)?.stream : undefined;
168
+ }
169
+ /** The device a relayed agent runs on, kept past the event stream so post-run push/PR still reach it. */
170
+ target(agentId) {
171
+ return agentId ? this.targets.get(agentId) : undefined;
172
+ }
173
+ /** A project's relayed run stubs (#1077), newest-first, so `onAgents` can surface them in the list. */
174
+ list(projectId) {
175
+ const rows = [];
176
+ for (const entry of this.metas.values())
177
+ if (entry.projectId === projectId)
178
+ rows.push(entry.meta);
179
+ // Newest first: startedAt is ISO, so a string compare is the time order (no parse).
180
+ return rows.sort((a, b) => (a.startedAt < b.startedAt ? 1 : a.startedAt > b.startedAt ? -1 : 0));
181
+ }
182
+ /** Fold each relayed event into the agent's list row via the store's own reducer (#1077), so the
183
+ * local stub mirrors the device: the terminal status on `end`, the waiting flag while it is parked
184
+ * (#785), the driver once its session starts. Events carry no write time, so this stamps its own. */
185
+ apply(agentId, event) {
186
+ const entry = this.metas.get(agentId);
187
+ if (!entry)
188
+ return;
189
+ entry.meta = foldRelayedEvent(entry.meta, event, new Date().toISOString());
190
+ }
191
+ /** Close a relayed agent's event stream (not its target). Idempotent. */
192
+ endStream(agentId) {
193
+ const agent = this.agents.get(agentId);
194
+ if (!agent)
195
+ return;
196
+ this.agents.delete(agentId);
197
+ agent.stream.close(); // a clean close surfaces as `done` in the browser, not a lost stream
198
+ // The stream dropped with no terminal event: the agent is no longer live, so stop showing it as such.
199
+ const entry = this.metas.get(agentId);
200
+ if (entry && entry.meta.status === 'running')
201
+ entry.meta.status = 'stopped';
202
+ }
203
+ /** Stop every pump, close every stream, and forget every device target + list stub, on daemon shutdown. */
204
+ dispose() {
205
+ for (const [agentId, agent] of this.agents) {
206
+ agent.cancel();
207
+ agent.stream.close();
208
+ this.agents.delete(agentId);
209
+ }
210
+ this.targets.clear();
211
+ this.metas.clear();
212
+ }
213
+ }
214
+ /** Trim trailing slashes off a base URL so `${base}/_relay/...` never doubles them. */
215
+ function trimSlashes(url) {
216
+ return url.replace(/\/+$/, '');
217
+ }
218
+ /**
219
+ * Fold one relayed event into the memory-only row of a run on a device: what the device's own
220
+ * card would say, kept here because that card is on the device. The events are the ones a run's
221
+ * diary yields: the agent's session id, its cost, its end.
222
+ */
223
+ export function foldRelayedEvent(meta, event, at) {
224
+ const next = { ...meta, updatedAt: at };
225
+ if (event.kind === 'session-update')
226
+ next.sessionId = event.sessionId;
227
+ else if (event.kind === 'usage')
228
+ next.cost = (next.cost ?? 0) + event.costUsd;
229
+ else if (event.kind === 'end') {
230
+ next.status = event.ok ? 'done' : event.stopped ? 'stopped' : event.waiting ? 'waiting' : 'failed';
231
+ next.endedAt = at;
232
+ }
233
+ return next;
234
+ }
235
+ //# sourceMappingURL=remote-run.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remote-run.js","sourceRoot":"","sources":["../../src/dashboard/remote-run.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,106 @@
1
+ import type { IncomingMessage, ServerResponse } from 'node:http';
2
+ import type { OpenAgentEvent } from '../events.js';
3
+ import type { PreferencesStore } from '../registry.js';
4
+ import type { QuotaSource } from './quota.js';
5
+ import type { ModelsSource } from './models.js';
6
+ import type { BridgeBrowserOwner } from '../bridge-browser.js';
7
+ import type { ProjectErrorsReader } from '../project-errors.js';
8
+ import type { AddProjectResult, RemoveProjectResult, StartAgentOptions, StartAgentResult } from './types.js';
9
+ import type { AgentMeta } from '../store/index.js';
10
+ /** Wired by the daemon so `sendStart` can reach the daemon's own `startAgent` closure. */
11
+ export type StartAgentHandler = (prompt: string, options: StartAgentOptions, projectId?: string) => StartAgentResult | Promise<StartAgentResult>;
12
+ /** Wired by the daemon so `sendAddProject` can install + register a repo (#433). */
13
+ export type AddProjectHandler = (path: string, share: boolean) => AddProjectResult | Promise<AddProjectResult>;
14
+ /** Wired by the daemon so `sendRemoveProject` can take a project off the list, by its id, and with `files` remove what OpenAgent left in its folder. */
15
+ export type RemoveProjectHandler = (projectId: string, files: boolean) => RemoveProjectResult | Promise<RemoveProjectResult>;
16
+ /** Resolve an agent to its live event stream: the relay feeds `onEvents` from its own in-memory stream
17
+ * rather than a file on disk (#426), and the daemon feeds an agent it is relaying from a device (#1067).
18
+ * Returns undefined when there is no in-memory stream, so `onEvents` falls back to tailing the log. */
19
+ export type EventsSource = (projectId: string, agentId?: string) => AsyncIterable<OpenAgentEvent> | undefined;
20
+ /** Look up the device a relayed agent (#1067) executes on, or undefined for an ordinary local agent. The
21
+ * daemon wires this from its live relayed-agent map; a run-scoped RPC uses it to forward a remote agent's
22
+ * read/steer/handoff to that device instead of resolving a (nonexistent) local checkout. */
23
+ export interface RemoteAgents {
24
+ target(agentId: string | undefined): {
25
+ url: string;
26
+ token: string;
27
+ } | undefined;
28
+ /** A project's relayed run stubs (#1077), so `onAgents` can show a remote agent in the list and re-open it after a reload. */
29
+ list(projectId: string): AgentMeta[];
30
+ }
31
+ /**
32
+ * What every RPC acts through.
33
+ *
34
+ * Every field is required (D3). These used to be optional because three hosts served this same
35
+ * surface — the daemon, a per-session foreground dashboard, and a public relay — each wiring a
36
+ * different subset, so every RPC carried an "absent capability" branch and the client rendered a
37
+ * degradation matrix. There is one host now, and it wires all of it.
38
+ */
39
+ export interface DashboardContext {
40
+ startAgent: StartAgentHandler;
41
+ addProject: AddProjectHandler;
42
+ removeProject: RemoveProjectHandler;
43
+ /** The in-memory event stream for an agent relayed from a connected device (#1067), else undefined. */
44
+ eventsSource: EventsSource;
45
+ /** The relayed-agent lookup (#1067 slice 2), so a run-scoped RPC can tell a local agent from one
46
+ * running on a connected device and forward the call there. */
47
+ remote: RemoteAgents;
48
+ /** The user-preferences store (#410), over the registry file. */
49
+ preferences: PreferencesStore;
50
+ /** The quota source behind the usage panel (#533). */
51
+ quota: QuotaSource;
52
+ /** Which models each coding agent offers, for the agent and model menu. */
53
+ models: ModelsSource;
54
+ /** What a project currently suffers from (#1500): the daemon's error state, read per project. */
55
+ projectErrors: ProjectErrorsReader;
56
+ /** The daemon's own bridge browser (#1332): status, and show/hide/restart on request. */
57
+ bridgeBrowser: BridgeBrowserOwner;
58
+ }
59
+ /**
60
+ * CSRF guard for the state-changing RPCs. A browser attaches an `Origin`
61
+ * header to every cross-site request, so we reject any POST whose Origin is not this
62
+ * same server (or a loopback host) — otherwise a page on `evil.com` could `fetch()` the
63
+ * localhost dashboard and start or steer a run. An absent Origin means a non-browser caller
64
+ * (curl, the test suite) with no ambient session to abuse, so it passes. Lives here beside
65
+ * the mount, its only caller.
66
+ */
67
+ export declare function isSameOriginRequest(req: IncomingMessage): boolean;
68
+ /**
69
+ * DNS-rebinding guard, the other half of the CSRF check above. A page on `evil.com` whose DNS
70
+ * re-answers as `127.0.0.1` is *same-origin* with this server as far as the browser is concerned,
71
+ * so its `fetch()` takes the passing branch of {@link isSameOriginRequest} — and every RPC behind
72
+ * the mount, `sendStart` included, is reachable from a page the user merely visited.
73
+ *
74
+ * The `Host` header is what still gives the attacker away: it carries the name the browser was
75
+ * asked for (`evil.com`), not the address it resolved to. So when we are bound to loopback, the
76
+ * only `Host` a real user's browser can send is a loopback one (or the bound address itself) —
77
+ * anything else is a rebound name and is rejected. An absent `Host` is rejected too when we are
78
+ * enforcing: HTTP/1.1 requires it, and every browser sends it.
79
+ *
80
+ * A non-loopback bind (`--host`, #1051) is reached by a hostname we cannot predict, so there is
81
+ * no allowlist to check against; that case gates behind the shared daemon token instead. Hosts
82
+ * that never pass a bind host at all (the relay, which serves a public domain) are unaffected.
83
+ */
84
+ export declare function isExpectedHost(req: IncomingMessage, boundHost: string | undefined): boolean;
85
+ /** Where the dashboard's RPCs live. One prefix, so the static handler can decline it by path. */
86
+ export declare const RPC_PREFIX = "/_rpc";
87
+ /**
88
+ * Mount the dashboard's RPC surface (#405) on the daemon's `node:http` server: `POST /_rpc/<name>`
89
+ * for the calls, `GET /_rpc/events` for the live stream. It runs in the daemon process, so
90
+ * `sendStart` reaches the daemon's own `startAgent` through the wired {@link DashboardContext}.
91
+ *
92
+ * Cross-origin POSTs are rejected (CSRF: a page on evil.com must not steer or start a session), as
93
+ * are requests carrying someone else's `Host` when we are bound to loopback (DNS rebinding: the
94
+ * same page must not reach us by pointing its own name at `127.0.0.1`). Pass `opts.host` — the
95
+ * address the server is bound to — to enable that second check. Returns whether the request was
96
+ * the RPC surface's.
97
+ *
98
+ * This replaced Telefunc (F3), which required a build-time transform over every `.telefunc.ts`
99
+ * file, a registration table pinning each RPC to the client-baked key of the *dashboard* source
100
+ * path it was re-exported from, and a request-context indirection for wiring that never varied
101
+ * per request. What it bought over this was type-safety across a package boundary that A7 removed.
102
+ */
103
+ export declare function makeRpcMount(context: DashboardContext, opts?: {
104
+ host?: string;
105
+ }): (req: IncomingMessage, res: ServerResponse) => Promise<boolean>;
106
+ //# sourceMappingURL=rpc-serve.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rpc-serve.d.ts","sourceRoot":"","sources":["../../src/dashboard/rpc-serve.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,180 @@
1
+ import { hostnameFromHostHeader, isLoopbackHost } from '../loopback-host.js';
2
+ import { setDashboardContext } from '../dashboard-rpc/context.js';
3
+ import { RPC_HANDLERS, RPC_EVENT_STREAM } from '../dashboard-rpc/index.js';
4
+ import { errorMessage } from '../error-message.js';
5
+ /**
6
+ * CSRF guard for the state-changing RPCs. A browser attaches an `Origin`
7
+ * header to every cross-site request, so we reject any POST whose Origin is not this
8
+ * same server (or a loopback host) — otherwise a page on `evil.com` could `fetch()` the
9
+ * localhost dashboard and start or steer a run. An absent Origin means a non-browser caller
10
+ * (curl, the test suite) with no ambient session to abuse, so it passes. Lives here beside
11
+ * the mount, its only caller.
12
+ */
13
+ export function isSameOriginRequest(req) {
14
+ const origin = req.headers.origin;
15
+ if (!origin)
16
+ return true;
17
+ const host = req.headers.host;
18
+ if (host && (origin === `http://${host}` || origin === `https://${host}`))
19
+ return true;
20
+ let hostname;
21
+ try {
22
+ hostname = new URL(origin).hostname;
23
+ }
24
+ catch {
25
+ return false; // malformed Origin: treat as cross-origin
26
+ }
27
+ return isLoopbackHost(hostname);
28
+ }
29
+ /**
30
+ * DNS-rebinding guard, the other half of the CSRF check above. A page on `evil.com` whose DNS
31
+ * re-answers as `127.0.0.1` is *same-origin* with this server as far as the browser is concerned,
32
+ * so its `fetch()` takes the passing branch of {@link isSameOriginRequest} — and every RPC behind
33
+ * the mount, `sendStart` included, is reachable from a page the user merely visited.
34
+ *
35
+ * The `Host` header is what still gives the attacker away: it carries the name the browser was
36
+ * asked for (`evil.com`), not the address it resolved to. So when we are bound to loopback, the
37
+ * only `Host` a real user's browser can send is a loopback one (or the bound address itself) —
38
+ * anything else is a rebound name and is rejected. An absent `Host` is rejected too when we are
39
+ * enforcing: HTTP/1.1 requires it, and every browser sends it.
40
+ *
41
+ * A non-loopback bind (`--host`, #1051) is reached by a hostname we cannot predict, so there is
42
+ * no allowlist to check against; that case gates behind the shared daemon token instead. Hosts
43
+ * that never pass a bind host at all (the relay, which serves a public domain) are unaffected.
44
+ */
45
+ export function isExpectedHost(req, boundHost) {
46
+ if (boundHost === undefined || !isLoopbackHost(boundHost))
47
+ return true;
48
+ const header = req.headers.host;
49
+ if (!header)
50
+ return false;
51
+ const hostname = hostnameFromHostHeader(header);
52
+ return isLoopbackHost(hostname) || hostname === boundHost;
53
+ }
54
+ /** Where the dashboard's RPCs live. One prefix, so the static handler can decline it by path. */
55
+ export const RPC_PREFIX = '/_rpc';
56
+ /** Read a request body, bounded so a bad caller cannot make the daemon buffer without limit. */
57
+ async function readBody(req, limit = 4 * 1024 * 1024) {
58
+ let size = 0;
59
+ const chunks = [];
60
+ for await (const chunk of req) {
61
+ const buf = chunk;
62
+ size += buf.length;
63
+ if (size > limit)
64
+ throw new Error('request body too large');
65
+ chunks.push(buf);
66
+ }
67
+ return Buffer.concat(chunks).toString('utf8');
68
+ }
69
+ function sendJson(res, status, body) {
70
+ const text = JSON.stringify(body);
71
+ res.writeHead(status, { 'content-type': 'application/json', 'cache-control': 'no-store' });
72
+ res.end(text);
73
+ }
74
+ /**
75
+ * Stream an agent's events as Server-Sent Events (#405). One JSON value per `data:` line; the
76
+ * response ending IS the clean close the client distinguishes from a dropped connection.
77
+ *
78
+ * This was a Telefunc Channel. The Channel gave serialization, reconnect and typing over a
79
+ * WebSocket-shaped abstraction; what the dashboard actually uses is "push me lines until I go
80
+ * away", and it brought its own reconnect-with-backoff on top (#948/#1383) because the Channel's
81
+ * did not distinguish a dead daemon from a finished stream.
82
+ */
83
+ async function serveEventStream(req, res, url) {
84
+ const projectId = url.searchParams.get('projectId') ?? '';
85
+ const agentId = url.searchParams.get('agentId') ?? undefined;
86
+ res.writeHead(200, {
87
+ 'content-type': 'text/event-stream',
88
+ 'cache-control': 'no-store',
89
+ connection: 'keep-alive',
90
+ // The daemon is behind nothing, but a proxy in front of a `--host` bind would otherwise buffer.
91
+ 'x-accel-buffering': 'no',
92
+ });
93
+ let finished = false;
94
+ const stop = await RPC_EVENT_STREAM(projectId, agentId, value => {
95
+ res.write(`data: ${JSON.stringify(value)}\n\n`);
96
+ }, () => {
97
+ finished = true;
98
+ res.end();
99
+ });
100
+ if (!stop) {
101
+ // Nothing to stream (unknown project): end cleanly, which the client reads as "done", not
102
+ // "lost" — the same distinction the Channel's clean-vs-errored close carried.
103
+ res.end();
104
+ return;
105
+ }
106
+ if (finished)
107
+ return; // the source was exhausted before it was even wired
108
+ const finish = () => {
109
+ stop();
110
+ res.end();
111
+ };
112
+ req.on('close', finish);
113
+ req.on('error', finish);
114
+ }
115
+ /**
116
+ * Mount the dashboard's RPC surface (#405) on the daemon's `node:http` server: `POST /_rpc/<name>`
117
+ * for the calls, `GET /_rpc/events` for the live stream. It runs in the daemon process, so
118
+ * `sendStart` reaches the daemon's own `startAgent` through the wired {@link DashboardContext}.
119
+ *
120
+ * Cross-origin POSTs are rejected (CSRF: a page on evil.com must not steer or start a session), as
121
+ * are requests carrying someone else's `Host` when we are bound to loopback (DNS rebinding: the
122
+ * same page must not reach us by pointing its own name at `127.0.0.1`). Pass `opts.host` — the
123
+ * address the server is bound to — to enable that second check. Returns whether the request was
124
+ * the RPC surface's.
125
+ *
126
+ * This replaced Telefunc (F3), which required a build-time transform over every `.telefunc.ts`
127
+ * file, a registration table pinning each RPC to the client-baked key of the *dashboard* source
128
+ * path it was re-exported from, and a request-context indirection for wiring that never varied
129
+ * per request. What it bought over this was type-safety across a package boundary that A7 removed.
130
+ */
131
+ export function makeRpcMount(context, opts = {}) {
132
+ setDashboardContext(context);
133
+ return async (req, res) => {
134
+ // A fixed base, like every other request parse here: only the path and the query are read,
135
+ // and a request carrying an empty or malformed `Host` made this throw — outside the handler's
136
+ // own try, so the daemon died of the unhandled rejection rather than answering the request.
137
+ const url = new URL(req.url ?? '/', 'http://localhost');
138
+ if (url.pathname !== RPC_PREFIX && !url.pathname.startsWith(`${RPC_PREFIX}/`))
139
+ return false;
140
+ if (!isSameOriginRequest(req)) {
141
+ res.writeHead(403, { 'content-type': 'text/plain' });
142
+ res.end('cross-origin request forbidden');
143
+ return true;
144
+ }
145
+ if (!isExpectedHost(req, opts.host)) {
146
+ res.writeHead(403, { 'content-type': 'text/plain' });
147
+ res.end('unexpected Host header');
148
+ return true;
149
+ }
150
+ const name = url.pathname.slice(RPC_PREFIX.length + 1);
151
+ try {
152
+ if (req.method === 'GET' && name === 'events') {
153
+ await serveEventStream(req, res, url);
154
+ return true;
155
+ }
156
+ const handler = RPC_HANDLERS[name];
157
+ if (req.method !== 'POST' || !handler) {
158
+ sendJson(res, 404, { error: `no such RPC: ${name}` });
159
+ return true;
160
+ }
161
+ const raw = await readBody(req);
162
+ const args = raw ? JSON.parse(raw) : [];
163
+ if (!Array.isArray(args)) {
164
+ sendJson(res, 400, { error: 'the request body must be a JSON array of arguments' });
165
+ return true;
166
+ }
167
+ sendJson(res, 200, { ret: await handler(...args) });
168
+ }
169
+ catch (err) {
170
+ // An RPC that throws is a failed call, not a dead daemon: answer it and stay up. Without
171
+ // this a rejected promise inside the mount became an unhandled rejection.
172
+ if (!res.headersSent)
173
+ sendJson(res, 500, { error: errorMessage(err) });
174
+ else
175
+ res.end();
176
+ }
177
+ return true;
178
+ };
179
+ }
180
+ //# sourceMappingURL=rpc-serve.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rpc-serve.js","sourceRoot":"","sources":["../../src/dashboard/rpc-serve.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ import { type InboxLine } from '@openagt/agent-driver';
2
+ /**
3
+ * What a person says to a run (#1774): their own words, or their answer to the question the run
4
+ * stopped on. The daemon runs no agent, so the line reaches the run through what the run's tool
5
+ * reads: the inbox file in the run's checkout while the run works, the project's `resume` hook
6
+ * line once it has ended. OpenAgent names no tool in either.
7
+ */
8
+ /**
9
+ * The inbox of a run, in its checkout's `.openagent/`: the file agent-driver's session reads
10
+ * when a turn ends, one JSON line per message or answer. The run's tool hands the session the
11
+ * same path.
12
+ */
13
+ export declare const RUN_INBOX_FILE = "inbox.jsonl";
14
+ /** What a write to a run came to: done, or why not, in words the surface shows. */
15
+ export type SteerResult = {
16
+ ok: true;
17
+ } | {
18
+ ok: false;
19
+ error: string;
20
+ };
21
+ /**
22
+ * Hand one line to a run of the project at `cwd`. A run that is working takes it from its inbox
23
+ * when its turn ends. A run that has ended (done, stopped, failed, or waiting on its question) is
24
+ * continued through the project's `resume` hook. A run that ends while the line is on its way
25
+ * would leave it in an inbox nobody reads, so the run is looked at again after the write, and
26
+ * what is still in the inbox then is taken back and resumes the run instead.
27
+ */
28
+ export declare function sayToRun(cwd: string, agentId: string, line: InboxLine, deps?: {
29
+ isWorking?: (cwd: string, agentId: string) => Promise<boolean>;
30
+ }): Promise<SteerResult>;
31
+ //# sourceMappingURL=run-inbox.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-inbox.d.ts","sourceRoot":"","sources":["../../src/dashboard/run-inbox.ts"],"names":[],"mappings":"AAEA,OAAO,EAA0B,KAAK,SAAS,EAAE,MAAM,uBAAuB,CAAA;AAK9E;;;;;GAKG;AAEH;;;;GAIG;AACH,eAAO,MAAM,cAAc,gBAAgB,CAAA;AAE3C,mFAAmF;AACnF,MAAM,MAAM,WAAW,GAAG;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAA;AAQrE;;;;;;GAMG;AACH,wBAAsB,QAAQ,CAC5B,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,SAAS,EACf,IAAI,GAAE;IAAE,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;CAAO,GAC5E,OAAO,CAAC,WAAW,CAAC,CAiBtB"}
@@ -0,0 +1,51 @@
1
+ import { hostname } from 'node:os';
2
+ import { join } from 'node:path';
3
+ import { appendInbox, takeInbox } from '@openagt/agent-driver';
4
+ import { OPENAGENT_DIR } from '../openagent-dir.js';
5
+ import { runResumeHook } from '../project-hooks.js';
6
+ import { findAgent, isPidAlive, resolveAgentCheckout } from '../store/index.js';
7
+ /**
8
+ * What a person says to a run (#1774): their own words, or their answer to the question the run
9
+ * stopped on. The daemon runs no agent, so the line reaches the run through what the run's tool
10
+ * reads: the inbox file in the run's checkout while the run works, the project's `resume` hook
11
+ * line once it has ended. OpenAgent names no tool in either.
12
+ */
13
+ /**
14
+ * The inbox of a run, in its checkout's `.openagent/`: the file agent-driver's session reads
15
+ * when a turn ends, one JSON line per message or answer. The run's tool hands the session the
16
+ * same path.
17
+ */
18
+ export const RUN_INBOX_FILE = 'inbox.jsonl';
19
+ /** Whether the run's card says it is working, on this machine, under a process that is alive. */
20
+ async function isRunWorking(cwd, agentId) {
21
+ const agent = await findAgent(cwd, agentId).catch(() => undefined);
22
+ return agent?.status === 'running' && agent.pid !== undefined && agent.host === hostname() && isPidAlive(agent.pid);
23
+ }
24
+ /**
25
+ * Hand one line to a run of the project at `cwd`. A run that is working takes it from its inbox
26
+ * when its turn ends. A run that has ended (done, stopped, failed, or waiting on its question) is
27
+ * continued through the project's `resume` hook. A run that ends while the line is on its way
28
+ * would leave it in an inbox nobody reads, so the run is looked at again after the write, and
29
+ * what is still in the inbox then is taken back and resumes the run instead.
30
+ */
31
+ export async function sayToRun(cwd, agentId, line, deps = {}) {
32
+ const isWorking = deps.isWorking ?? isRunWorking;
33
+ const lines = [line];
34
+ if (await isWorking(cwd, agentId)) {
35
+ const inbox = join(await resolveAgentCheckout(cwd, agentId), OPENAGENT_DIR, RUN_INBOX_FILE);
36
+ await appendInbox(inbox, line);
37
+ if (await isWorking(cwd, agentId))
38
+ return { ok: true };
39
+ lines.splice(0, 1, ...(await takeInbox(inbox)));
40
+ }
41
+ for (const stranded of lines) {
42
+ const resumed = await runResumeHook(cwd, {
43
+ runId: agentId,
44
+ ...(stranded.kind === 'message' ? { text: stranded.text } : { answer: stranded.answer }),
45
+ });
46
+ if (!resumed.ok)
47
+ return resumed;
48
+ }
49
+ return { ok: true };
50
+ }
51
+ //# sourceMappingURL=run-inbox.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-inbox.js","sourceRoot":"","sources":["../../src/dashboard/run-inbox.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,OAAO,EAAE,WAAW,EAAE,SAAS,EAAkB,MAAM,uBAAuB,CAAA;AAC9E,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AACnD,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAA;AAE/E;;;;;GAKG;AAEH;;;;GAIG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,aAAa,CAAA;AAK3C,iGAAiG;AACjG,KAAK,UAAU,YAAY,CAAC,GAAW,EAAE,OAAe;IACtD,MAAM,KAAK,GAAG,MAAM,SAAS,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAA;IAClE,OAAO,KAAK,EAAE,MAAM,KAAK,SAAS,IAAI,KAAK,CAAC,GAAG,KAAK,SAAS,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,EAAE,IAAI,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;AACrH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAC5B,GAAW,EACX,OAAe,EACf,IAAe,EACf,IAAI,GAAuE,EAAE;IAE7E,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,IAAI,YAAY,CAAA;IAChD,MAAM,KAAK,GAAG,CAAC,IAAI,CAAC,CAAA;IACpB,IAAI,MAAM,SAAS,CAAC,GAAG,EAAE,OAAO,CAAC,EAAE,CAAC;QAClC,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,oBAAoB,CAAC,GAAG,EAAE,OAAO,CAAC,EAAE,aAAa,EAAE,cAAc,CAAC,CAAA;QAC3F,MAAM,WAAW,CAAC,KAAK,EAAE,IAAI,CAAC,CAAA;QAC9B,IAAI,MAAM,SAAS,CAAC,GAAG,EAAE,OAAO,CAAC;YAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAA;QACtD,KAAK,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,MAAM,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;IACjD,CAAC;IACD,KAAK,MAAM,QAAQ,IAAI,KAAK,EAAE,CAAC;QAC7B,MAAM,OAAO,GAAG,MAAM,aAAa,CAAC,GAAG,EAAE;YACvC,KAAK,EAAE,OAAO;YACd,GAAG,CAAC,QAAQ,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC;SACzF,CAAC,CAAA;QACF,IAAI,CAAC,OAAO,CAAC,EAAE;YAAE,OAAO,OAAO,CAAA;IACjC,CAAC;IACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAA;AACrB,CAAC"}