@mrpatronz/nexusflow 2.9.0 → 2.10.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 (732) hide show
  1. package/README.md +172 -113
  2. package/dist/agent/AcpCliAdapter.d.ts +2 -0
  3. package/dist/agent/AcpCliAdapter.d.ts.map +1 -1
  4. package/dist/agent/AcpCliAdapter.js +50 -4
  5. package/dist/agent/AcpCliAdapter.js.map +1 -1
  6. package/dist/agent/AntigravityCliAdapter.d.ts +44 -2
  7. package/dist/agent/AntigravityCliAdapter.d.ts.map +1 -1
  8. package/dist/agent/AntigravityCliAdapter.js +363 -16
  9. package/dist/agent/AntigravityCliAdapter.js.map +1 -1
  10. package/dist/agent/ClaudeCliAdapter.d.ts +3 -0
  11. package/dist/agent/ClaudeCliAdapter.d.ts.map +1 -1
  12. package/dist/agent/ClaudeCliAdapter.js +37 -10
  13. package/dist/agent/ClaudeCliAdapter.js.map +1 -1
  14. package/dist/agent/ClaudeSdkAdapter.d.ts +1 -0
  15. package/dist/agent/ClaudeSdkAdapter.d.ts.map +1 -1
  16. package/dist/agent/ClaudeSdkAdapter.js +38 -11
  17. package/dist/agent/ClaudeSdkAdapter.js.map +1 -1
  18. package/dist/agent/CliAdapterBase.d.ts +2 -0
  19. package/dist/agent/CliAdapterBase.d.ts.map +1 -1
  20. package/dist/agent/CliAdapterBase.js +5 -1
  21. package/dist/agent/CliAdapterBase.js.map +1 -1
  22. package/dist/agent/CodexCliAdapter.d.ts +1 -1
  23. package/dist/agent/CodexCliAdapter.d.ts.map +1 -1
  24. package/dist/agent/CodexCliAdapter.js +5 -4
  25. package/dist/agent/CodexCliAdapter.js.map +1 -1
  26. package/dist/agent/CodexSdkAdapter.d.ts.map +1 -1
  27. package/dist/agent/CodexSdkAdapter.js +4 -1
  28. package/dist/agent/CodexSdkAdapter.js.map +1 -1
  29. package/dist/agent/CopilotAcpAdapter.d.ts.map +1 -1
  30. package/dist/agent/CopilotAcpAdapter.js +2 -2
  31. package/dist/agent/CopilotAcpAdapter.js.map +1 -1
  32. package/dist/agent/ProviderRegistry.d.ts +8 -1
  33. package/dist/agent/ProviderRegistry.d.ts.map +1 -1
  34. package/dist/agent/ProviderRegistry.js.map +1 -1
  35. package/dist/agent/TurnSessionManager.d.ts +65 -0
  36. package/dist/agent/TurnSessionManager.d.ts.map +1 -0
  37. package/dist/agent/TurnSessionManager.js +330 -0
  38. package/dist/agent/TurnSessionManager.js.map +1 -0
  39. package/dist/agent/adapters.d.ts.map +1 -1
  40. package/dist/agent/adapters.js +23 -6
  41. package/dist/agent/adapters.js.map +1 -1
  42. package/dist/agent/cliAvailability.d.ts.map +1 -1
  43. package/dist/agent/cliAvailability.js +12 -0
  44. package/dist/agent/cliAvailability.js.map +1 -1
  45. package/dist/agent/mcp-config.d.ts +0 -5
  46. package/dist/agent/mcp-config.d.ts.map +1 -1
  47. package/dist/agent/mcp-config.js +2 -1
  48. package/dist/agent/mcp-config.js.map +1 -1
  49. package/dist/agent/models.d.ts +13 -0
  50. package/dist/agent/models.d.ts.map +1 -1
  51. package/dist/agent/models.js +262 -8
  52. package/dist/agent/models.js.map +1 -1
  53. package/dist/agent/nativeTools.d.ts.map +1 -1
  54. package/dist/agent/nativeTools.js +1 -0
  55. package/dist/agent/nativeTools.js.map +1 -1
  56. package/dist/agent/orchestrator.d.ts.map +1 -1
  57. package/dist/agent/orchestrator.js +3 -2
  58. package/dist/agent/orchestrator.js.map +1 -1
  59. package/dist/agent/session.d.ts +1 -0
  60. package/dist/agent/session.d.ts.map +1 -1
  61. package/dist/agent/session.js.map +1 -1
  62. package/dist/analyzers/detect-deps.js +16 -1
  63. package/dist/analyzers/detect-deps.js.map +1 -1
  64. package/dist/analyzers/run-analyzer.d.ts.map +1 -1
  65. package/dist/analyzers/run-analyzer.js.map +1 -1
  66. package/dist/commands/adapter.d.ts.map +1 -1
  67. package/dist/commands/adapter.js +15 -14
  68. package/dist/commands/adapter.js.map +1 -1
  69. package/dist/commands/add-repo.d.ts.map +1 -1
  70. package/dist/commands/add-repo.js +6 -5
  71. package/dist/commands/add-repo.js.map +1 -1
  72. package/dist/commands/commit.js +6 -8
  73. package/dist/commands/commit.js.map +1 -1
  74. package/dist/commands/config.d.ts.map +1 -1
  75. package/dist/commands/config.js +2 -1
  76. package/dist/commands/config.js.map +1 -1
  77. package/dist/commands/create.d.ts +4 -4
  78. package/dist/commands/create.d.ts.map +1 -1
  79. package/dist/commands/create.js +8 -7
  80. package/dist/commands/create.js.map +1 -1
  81. package/dist/commands/desktop.d.ts +44 -3
  82. package/dist/commands/desktop.d.ts.map +1 -1
  83. package/dist/commands/desktop.js +246 -7
  84. package/dist/commands/desktop.js.map +1 -1
  85. package/dist/commands/diff.d.ts.map +1 -1
  86. package/dist/commands/diff.js +3 -2
  87. package/dist/commands/diff.js.map +1 -1
  88. package/dist/commands/doctor.d.ts.map +1 -1
  89. package/dist/commands/doctor.js +3 -2
  90. package/dist/commands/doctor.js.map +1 -1
  91. package/dist/commands/finish.js +2 -1
  92. package/dist/commands/finish.js.map +1 -1
  93. package/dist/commands/handoff.d.ts.map +1 -1
  94. package/dist/commands/handoff.js +12 -12
  95. package/dist/commands/handoff.js.map +1 -1
  96. package/dist/commands/init.d.ts +2 -2
  97. package/dist/commands/init.d.ts.map +1 -1
  98. package/dist/commands/init.js +8 -7
  99. package/dist/commands/init.js.map +1 -1
  100. package/dist/commands/isolate.d.ts.map +1 -1
  101. package/dist/commands/isolate.js +2 -1
  102. package/dist/commands/isolate.js.map +1 -1
  103. package/dist/commands/knowledge.d.ts.map +1 -1
  104. package/dist/commands/knowledge.js +3 -2
  105. package/dist/commands/knowledge.js.map +1 -1
  106. package/dist/commands/list.d.ts.map +1 -1
  107. package/dist/commands/list.js +3 -2
  108. package/dist/commands/list.js.map +1 -1
  109. package/dist/commands/logs.js +3 -3
  110. package/dist/commands/logs.js.map +1 -1
  111. package/dist/commands/mcp.d.ts +1 -2
  112. package/dist/commands/mcp.d.ts.map +1 -1
  113. package/dist/commands/mcp.js +19 -12
  114. package/dist/commands/mcp.js.map +1 -1
  115. package/dist/commands/migrate.d.ts +12 -0
  116. package/dist/commands/migrate.d.ts.map +1 -0
  117. package/dist/commands/migrate.js +128 -0
  118. package/dist/commands/migrate.js.map +1 -0
  119. package/dist/commands/open.d.ts.map +1 -1
  120. package/dist/commands/open.js +2 -1
  121. package/dist/commands/open.js.map +1 -1
  122. package/dist/commands/progress.d.ts.map +1 -1
  123. package/dist/commands/progress.js +2 -1
  124. package/dist/commands/progress.js.map +1 -1
  125. package/dist/commands/project.d.ts.map +1 -1
  126. package/dist/commands/project.js +7 -6
  127. package/dist/commands/project.js.map +1 -1
  128. package/dist/commands/refresh.d.ts.map +1 -1
  129. package/dist/commands/refresh.js +8 -11
  130. package/dist/commands/refresh.js.map +1 -1
  131. package/dist/commands/remove.d.ts.map +1 -1
  132. package/dist/commands/remove.js +2 -1
  133. package/dist/commands/remove.js.map +1 -1
  134. package/dist/commands/schedule.js +16 -18
  135. package/dist/commands/schedule.js.map +1 -1
  136. package/dist/commands/start.d.ts.map +1 -1
  137. package/dist/commands/start.js +9 -8
  138. package/dist/commands/start.js.map +1 -1
  139. package/dist/commands/status.d.ts.map +1 -1
  140. package/dist/commands/status.js +2 -1
  141. package/dist/commands/status.js.map +1 -1
  142. package/dist/commands/stop.d.ts.map +1 -1
  143. package/dist/commands/stop.js +2 -1
  144. package/dist/commands/stop.js.map +1 -1
  145. package/dist/commands/strategy.d.ts.map +1 -1
  146. package/dist/commands/strategy.js +6 -5
  147. package/dist/commands/strategy.js.map +1 -1
  148. package/dist/commands/sync.js +8 -10
  149. package/dist/commands/sync.js.map +1 -1
  150. package/dist/commands/tui.d.ts.map +1 -1
  151. package/dist/commands/tui.js +11 -10
  152. package/dist/commands/tui.js.map +1 -1
  153. package/dist/commands/ui.d.ts.map +1 -1
  154. package/dist/commands/ui.js +4 -3
  155. package/dist/commands/ui.js.map +1 -1
  156. package/dist/core/adapters/local-storage.d.ts +3 -1
  157. package/dist/core/adapters/local-storage.d.ts.map +1 -1
  158. package/dist/core/adapters/local-storage.js +62 -4
  159. package/dist/core/adapters/local-storage.js.map +1 -1
  160. package/dist/core/analysis-cache.d.ts.map +1 -1
  161. package/dist/core/analysis-cache.js +8 -7
  162. package/dist/core/analysis-cache.js.map +1 -1
  163. package/dist/core/brand-config.d.ts +261 -0
  164. package/dist/core/brand-config.d.ts.map +1 -0
  165. package/dist/core/brand-config.js +514 -0
  166. package/dist/core/brand-config.js.map +1 -0
  167. package/dist/core/config.d.ts +1 -1
  168. package/dist/core/config.d.ts.map +1 -1
  169. package/dist/core/config.js +18 -8
  170. package/dist/core/config.js.map +1 -1
  171. package/dist/core/constants.d.ts +88 -0
  172. package/dist/core/constants.d.ts.map +1 -0
  173. package/dist/core/constants.js +103 -0
  174. package/dist/core/constants.js.map +1 -0
  175. package/dist/core/doctor.d.ts.map +1 -1
  176. package/dist/core/doctor.js +11 -3
  177. package/dist/core/doctor.js.map +1 -1
  178. package/dist/core/generation-lock.d.ts +2 -2
  179. package/dist/core/generation-lock.d.ts.map +1 -1
  180. package/dist/core/generation-lock.js +49 -22
  181. package/dist/core/generation-lock.js.map +1 -1
  182. package/dist/core/knowledge.d.ts +19 -0
  183. package/dist/core/knowledge.d.ts.map +1 -1
  184. package/dist/core/knowledge.js +150 -24
  185. package/dist/core/knowledge.js.map +1 -1
  186. package/dist/core/migrate.d.ts +53 -0
  187. package/dist/core/migrate.d.ts.map +1 -0
  188. package/dist/core/migrate.js +607 -0
  189. package/dist/core/migrate.js.map +1 -0
  190. package/dist/core/new-repo.js +1 -1
  191. package/dist/core/new-repo.js.map +1 -1
  192. package/dist/core/projects.d.ts.map +1 -1
  193. package/dist/core/projects.js +13 -4
  194. package/dist/core/projects.js.map +1 -1
  195. package/dist/core/refresh.d.ts.map +1 -1
  196. package/dist/core/refresh.js +6 -4
  197. package/dist/core/refresh.js.map +1 -1
  198. package/dist/core/scheduler.d.ts +1 -1
  199. package/dist/core/scheduler.d.ts.map +1 -1
  200. package/dist/core/scheduler.js +11 -9
  201. package/dist/core/scheduler.js.map +1 -1
  202. package/dist/core/sync.js +1 -1
  203. package/dist/core/sync.js.map +1 -1
  204. package/dist/core/workspace-git.d.ts.map +1 -1
  205. package/dist/core/workspace-git.js +34 -10
  206. package/dist/core/workspace-git.js.map +1 -1
  207. package/dist/core/workspace-state.d.ts +4 -0
  208. package/dist/core/workspace-state.d.ts.map +1 -1
  209. package/dist/core/workspace-state.js +8 -8
  210. package/dist/core/workspace-state.js.map +1 -1
  211. package/dist/core/workspace.d.ts +3 -4
  212. package/dist/core/workspace.d.ts.map +1 -1
  213. package/dist/core/workspace.js +62 -30
  214. package/dist/core/workspace.js.map +1 -1
  215. package/dist/desktop-server.js +6 -3
  216. package/dist/desktop-server.js.map +1 -1
  217. package/dist/generators/base.d.ts.map +1 -1
  218. package/dist/generators/base.js +7 -5
  219. package/dist/generators/base.js.map +1 -1
  220. package/dist/generators/claude.d.ts.map +1 -1
  221. package/dist/generators/claude.js +2 -1
  222. package/dist/generators/claude.js.map +1 -1
  223. package/dist/generators/cursor.d.ts +1 -1
  224. package/dist/generators/cursor.d.ts.map +1 -1
  225. package/dist/generators/cursor.js +9 -4
  226. package/dist/generators/cursor.js.map +1 -1
  227. package/dist/generators/index.d.ts +4 -8
  228. package/dist/generators/index.d.ts.map +1 -1
  229. package/dist/generators/index.js +34 -69
  230. package/dist/generators/index.js.map +1 -1
  231. package/dist/generators/plan-generator.d.ts.map +1 -1
  232. package/dist/generators/plan-generator.js +20 -11
  233. package/dist/generators/plan-generator.js.map +1 -1
  234. package/dist/generators/skills-generator.d.ts.map +1 -1
  235. package/dist/generators/skills-generator.js +26 -11
  236. package/dist/generators/skills-generator.js.map +1 -1
  237. package/dist/gui/app_logo.png +0 -0
  238. package/dist/gui/assets/AgentsPage-CnXzZFo1.js +3 -0
  239. package/dist/gui/assets/DashboardPage-rm3hKgsw.js +1 -0
  240. package/dist/gui/assets/GettingStartedPage-BKeuSHZQ.js +1 -0
  241. package/dist/gui/assets/NullStore-DuSDhGOe.js +1 -0
  242. package/dist/gui/assets/ProjectsPage-CioaA4uf.js +1 -0
  243. package/dist/gui/assets/ScaffoldRepoInline-DKZ1rPmE.js +1 -0
  244. package/dist/gui/assets/Separator-BgWyHDtg.js +1 -0
  245. package/dist/gui/assets/SettingsPage-BevO8oge.js +1 -0
  246. package/dist/gui/assets/SkillsPage-D2stJRWy.js +6 -0
  247. package/dist/gui/assets/StartWorkPage-C8a6eN90.js +1 -0
  248. package/dist/gui/assets/{StrategiesPage-C36TZgDX.js → StrategiesPage-BRQMly_d.js} +2 -2
  249. package/dist/gui/assets/WorkroomsPage-KqBkRD-x.js +4 -0
  250. package/dist/gui/assets/WorkspacesPage-DcA2i5HN.js +2 -0
  251. package/dist/gui/assets/alert-QnMXzwpU.js +1 -0
  252. package/dist/gui/assets/alert-dialog-BHEUQVyS.js +1 -0
  253. package/dist/gui/assets/badge-DTBzXOWn.js +1 -0
  254. package/dist/gui/assets/brand-hHByyyzq.js +1 -0
  255. package/dist/gui/assets/button-CREn1mup.js +1 -0
  256. package/dist/gui/assets/card-yrg6ov8B.js +1 -0
  257. package/dist/gui/assets/chevron-down-B_Mwbim8.js +1 -0
  258. package/dist/gui/assets/{circle-plus-lmU1yNJd.js → circle-plus--zM3-3r3.js} +1 -1
  259. package/dist/gui/assets/{code-xml-jFAa3-TT.js → code-xml-DH-38Tt7.js} +1 -1
  260. package/dist/gui/assets/{git-branch-Cfj9D8yW.js → git-branch-Ce0I2663.js} +1 -1
  261. package/dist/gui/assets/index-BB4BuHBQ.css +2 -0
  262. package/dist/gui/assets/index-BTe-_1Mu.js +57 -0
  263. package/dist/gui/assets/isElementDisabled-BrwmCB1d.js +1 -0
  264. package/dist/gui/assets/label-DC730X8s.js +1 -0
  265. package/dist/gui/assets/layers-j_brOuoa.js +1 -0
  266. package/dist/gui/assets/menu-d_G9km1-.js +1 -0
  267. package/dist/gui/assets/shield-check-Dd1Yv3l2.js +1 -0
  268. package/dist/gui/assets/square-check-big-BSIiYXPI.js +1 -0
  269. package/dist/gui/assets/tabs-BHwTt4t1.js +1 -0
  270. package/dist/gui/assets/{trash-2-CtR35_eF.js → trash-2-CMdv3eD3.js} +1 -1
  271. package/dist/gui/assets/useAriaLabelledBy-BmJErI5a.js +1 -0
  272. package/dist/gui/assets/useValueChanged-WS99hTmm.js +1 -0
  273. package/dist/gui/assets/{vsc-DFh0-53h.js → vsc-eMRaEwN3.js} +1 -1
  274. package/dist/gui/favicon-aurora.svg +8 -0
  275. package/dist/gui/favicon.ico +0 -0
  276. package/dist/gui/favicon.svg +8 -1
  277. package/dist/gui/index.html +21 -12
  278. package/dist/harness/claude.d.ts.map +1 -1
  279. package/dist/harness/claude.js +97 -7
  280. package/dist/harness/claude.js.map +1 -1
  281. package/dist/harness/codex.d.ts +1 -0
  282. package/dist/harness/codex.d.ts.map +1 -1
  283. package/dist/harness/codex.js +51 -34
  284. package/dist/harness/codex.js.map +1 -1
  285. package/dist/index.js +57 -27
  286. package/dist/index.js.map +1 -1
  287. package/dist/mcp/server.d.ts +12 -1
  288. package/dist/mcp/server.d.ts.map +1 -1
  289. package/dist/mcp/server.js +24 -6
  290. package/dist/mcp/server.js.map +1 -1
  291. package/dist/mcp/tools.d.ts +4 -2
  292. package/dist/mcp/tools.d.ts.map +1 -1
  293. package/dist/mcp/tools.js +372 -17
  294. package/dist/mcp/tools.js.map +1 -1
  295. package/dist/orchestration/detect.d.ts.map +1 -1
  296. package/dist/orchestration/detect.js +12 -5
  297. package/dist/orchestration/detect.js.map +1 -1
  298. package/dist/orchestration/log-tail.js +17 -17
  299. package/dist/orchestration/log-tail.js.map +1 -1
  300. package/dist/orchestration/runner.d.ts +1 -1
  301. package/dist/orchestration/runner.d.ts.map +1 -1
  302. package/dist/orchestration/runner.js +13 -8
  303. package/dist/orchestration/runner.js.map +1 -1
  304. package/dist/resources/agents-catalog.d.ts +3 -1
  305. package/dist/resources/agents-catalog.d.ts.map +1 -1
  306. package/dist/resources/agents-catalog.js +12 -6
  307. package/dist/resources/agents-catalog.js.map +1 -1
  308. package/dist/resources/contracts.d.ts +7 -0
  309. package/dist/resources/contracts.d.ts.map +1 -1
  310. package/dist/resources/contracts.js +8 -1
  311. package/dist/resources/contracts.js.map +1 -1
  312. package/dist/resources/fs-safety.d.ts +7 -1
  313. package/dist/resources/fs-safety.d.ts.map +1 -1
  314. package/dist/resources/fs-safety.js +44 -1
  315. package/dist/resources/fs-safety.js.map +1 -1
  316. package/dist/resources/materializer.d.ts +1 -0
  317. package/dist/resources/materializer.d.ts.map +1 -1
  318. package/dist/resources/materializer.js +48 -17
  319. package/dist/resources/materializer.js.map +1 -1
  320. package/dist/resources/service.d.ts.map +1 -1
  321. package/dist/resources/service.js +3 -2
  322. package/dist/resources/service.js.map +1 -1
  323. package/dist/server.d.ts +2 -19
  324. package/dist/server.d.ts.map +1 -1
  325. package/dist/server.js +1158 -318
  326. package/dist/server.js.map +1 -1
  327. package/dist/static-resources/workflows/cost-aware-sol-luna.md +95 -0
  328. package/dist/storage/db.d.ts +94 -0
  329. package/dist/storage/db.d.ts.map +1 -0
  330. package/dist/storage/db.js +609 -0
  331. package/dist/storage/db.js.map +1 -0
  332. package/dist/types.d.ts +19 -0
  333. package/dist/types.d.ts.map +1 -1
  334. package/dist/utils/detect-ai.d.ts.map +1 -1
  335. package/dist/utils/detect-ai.js +1 -3
  336. package/dist/utils/detect-ai.js.map +1 -1
  337. package/dist/utils/multi-git.d.ts +0 -8
  338. package/dist/utils/multi-git.d.ts.map +1 -1
  339. package/dist/utils/multi-git.js +12 -4
  340. package/dist/utils/multi-git.js.map +1 -1
  341. package/dist/utils/pr.d.ts.map +1 -1
  342. package/dist/utils/pr.js +10 -5
  343. package/dist/utils/pr.js.map +1 -1
  344. package/dist/utils/resolve-workspace.d.ts +1 -1
  345. package/dist/utils/resolve-workspace.d.ts.map +1 -1
  346. package/dist/utils/resolve-workspace.js +10 -3
  347. package/dist/utils/resolve-workspace.js.map +1 -1
  348. package/dist/utils/session-finder.d.ts +12 -1
  349. package/dist/utils/session-finder.d.ts.map +1 -1
  350. package/dist/utils/session-finder.js +183 -0
  351. package/dist/utils/session-finder.js.map +1 -1
  352. package/dist/utils/skills-catalog.d.ts +5 -1
  353. package/dist/utils/skills-catalog.d.ts.map +1 -1
  354. package/dist/utils/skills-catalog.js +131 -75
  355. package/dist/utils/skills-catalog.js.map +1 -1
  356. package/dist/utils/terminal-launch.d.ts +4 -0
  357. package/dist/utils/terminal-launch.d.ts.map +1 -1
  358. package/dist/utils/terminal-launch.js +71 -12
  359. package/dist/utils/terminal-launch.js.map +1 -1
  360. package/dist/utils/update-check.d.ts +4 -1
  361. package/dist/utils/update-check.d.ts.map +1 -1
  362. package/dist/utils/update-check.js +66 -19
  363. package/dist/utils/update-check.js.map +1 -1
  364. package/dist/utils/workflows.d.ts +4 -1
  365. package/dist/utils/workflows.d.ts.map +1 -1
  366. package/dist/utils/workflows.js +51 -21
  367. package/dist/utils/workflows.js.map +1 -1
  368. package/dist/workrooms/client.d.ts +54 -0
  369. package/dist/workrooms/client.d.ts.map +1 -0
  370. package/dist/workrooms/client.js +191 -0
  371. package/dist/workrooms/client.js.map +1 -0
  372. package/dist/workrooms/contracts.d.ts +579 -0
  373. package/dist/workrooms/contracts.d.ts.map +1 -0
  374. package/dist/workrooms/contracts.js +231 -0
  375. package/dist/workrooms/contracts.js.map +1 -0
  376. package/dist/workrooms/crypto.d.ts +30 -0
  377. package/dist/workrooms/crypto.d.ts.map +1 -0
  378. package/dist/workrooms/crypto.js +72 -0
  379. package/dist/workrooms/crypto.js.map +1 -0
  380. package/dist/workrooms/host.d.ts +61 -0
  381. package/dist/workrooms/host.d.ts.map +1 -0
  382. package/dist/workrooms/host.js +747 -0
  383. package/dist/workrooms/host.js.map +1 -0
  384. package/dist/workrooms/local-resources.d.ts +26 -0
  385. package/dist/workrooms/local-resources.d.ts.map +1 -0
  386. package/dist/workrooms/local-resources.js +367 -0
  387. package/dist/workrooms/local-resources.js.map +1 -0
  388. package/dist/workrooms/manager.d.ts +228 -0
  389. package/dist/workrooms/manager.d.ts.map +1 -0
  390. package/dist/workrooms/manager.js +768 -0
  391. package/dist/workrooms/manager.js.map +1 -0
  392. package/dist/workrooms/milestones.d.ts +42 -0
  393. package/dist/workrooms/milestones.d.ts.map +1 -0
  394. package/dist/workrooms/milestones.js +94 -0
  395. package/dist/workrooms/milestones.js.map +1 -0
  396. package/dist/workrooms/portable.d.ts +21 -0
  397. package/dist/workrooms/portable.d.ts.map +1 -0
  398. package/dist/workrooms/portable.js +201 -0
  399. package/dist/workrooms/portable.js.map +1 -0
  400. package/dist/workrooms/resource-package.d.ts +7 -0
  401. package/dist/workrooms/resource-package.d.ts.map +1 -0
  402. package/dist/workrooms/resource-package.js +260 -0
  403. package/dist/workrooms/resource-package.js.map +1 -0
  404. package/dist/workrooms/service.d.ts +92 -0
  405. package/dist/workrooms/service.d.ts.map +1 -0
  406. package/dist/workrooms/service.js +788 -0
  407. package/dist/workrooms/service.js.map +1 -0
  408. package/dist/workrooms/sqlite-store.d.ts +31 -0
  409. package/dist/workrooms/sqlite-store.d.ts.map +1 -0
  410. package/dist/workrooms/sqlite-store.js +511 -0
  411. package/dist/workrooms/sqlite-store.js.map +1 -0
  412. package/dist/workrooms/store.d.ts +542 -0
  413. package/dist/workrooms/store.d.ts.map +1 -0
  414. package/dist/workrooms/store.js +71 -0
  415. package/dist/workrooms/store.js.map +1 -0
  416. package/package.json +16 -10
  417. package/resources/workflows/cost-aware-sol-luna.md +95 -0
  418. package/dist/agent/AcpCliAdapter.test.d.ts +0 -2
  419. package/dist/agent/AcpCliAdapter.test.d.ts.map +0 -1
  420. package/dist/agent/AcpCliAdapter.test.js +0 -235
  421. package/dist/agent/AcpCliAdapter.test.js.map +0 -1
  422. package/dist/agent/AntigravityCliAdapter.test.d.ts +0 -2
  423. package/dist/agent/AntigravityCliAdapter.test.d.ts.map +0 -1
  424. package/dist/agent/AntigravityCliAdapter.test.js +0 -222
  425. package/dist/agent/AntigravityCliAdapter.test.js.map +0 -1
  426. package/dist/agent/ClaudeCliAdapter.test.d.ts +0 -2
  427. package/dist/agent/ClaudeCliAdapter.test.d.ts.map +0 -1
  428. package/dist/agent/ClaudeCliAdapter.test.js +0 -320
  429. package/dist/agent/ClaudeCliAdapter.test.js.map +0 -1
  430. package/dist/agent/ClaudeSdkAdapter.test.d.ts +0 -2
  431. package/dist/agent/ClaudeSdkAdapter.test.d.ts.map +0 -1
  432. package/dist/agent/ClaudeSdkAdapter.test.js +0 -155
  433. package/dist/agent/ClaudeSdkAdapter.test.js.map +0 -1
  434. package/dist/agent/CliAdapterBase.test.d.ts +0 -2
  435. package/dist/agent/CliAdapterBase.test.d.ts.map +0 -1
  436. package/dist/agent/CliAdapterBase.test.js +0 -240
  437. package/dist/agent/CliAdapterBase.test.js.map +0 -1
  438. package/dist/agent/CodexCliAdapter.test.d.ts +0 -2
  439. package/dist/agent/CodexCliAdapter.test.d.ts.map +0 -1
  440. package/dist/agent/CodexCliAdapter.test.js +0 -331
  441. package/dist/agent/CodexCliAdapter.test.js.map +0 -1
  442. package/dist/agent/CodexSdkAdapter.test.d.ts +0 -2
  443. package/dist/agent/CodexSdkAdapter.test.d.ts.map +0 -1
  444. package/dist/agent/CodexSdkAdapter.test.js +0 -76
  445. package/dist/agent/CodexSdkAdapter.test.js.map +0 -1
  446. package/dist/agent/ProviderRegistry.test.d.ts +0 -2
  447. package/dist/agent/ProviderRegistry.test.d.ts.map +0 -1
  448. package/dist/agent/ProviderRegistry.test.js +0 -129
  449. package/dist/agent/ProviderRegistry.test.js.map +0 -1
  450. package/dist/agent/adapters.test.d.ts +0 -2
  451. package/dist/agent/adapters.test.d.ts.map +0 -1
  452. package/dist/agent/adapters.test.js +0 -71
  453. package/dist/agent/adapters.test.js.map +0 -1
  454. package/dist/agent/cliAvailability.test.d.ts +0 -2
  455. package/dist/agent/cliAvailability.test.d.ts.map +0 -1
  456. package/dist/agent/cliAvailability.test.js +0 -217
  457. package/dist/agent/cliAvailability.test.js.map +0 -1
  458. package/dist/agent/mcp-config.test.d.ts +0 -2
  459. package/dist/agent/mcp-config.test.d.ts.map +0 -1
  460. package/dist/agent/mcp-config.test.js +0 -22
  461. package/dist/agent/mcp-config.test.js.map +0 -1
  462. package/dist/agent/models.test.d.ts +0 -2
  463. package/dist/agent/models.test.d.ts.map +0 -1
  464. package/dist/agent/models.test.js +0 -40
  465. package/dist/agent/models.test.js.map +0 -1
  466. package/dist/agent/nativeAgent.test.d.ts +0 -2
  467. package/dist/agent/nativeAgent.test.d.ts.map +0 -1
  468. package/dist/agent/nativeAgent.test.js +0 -35
  469. package/dist/agent/nativeAgent.test.js.map +0 -1
  470. package/dist/agent/nativeTools.test.d.ts +0 -2
  471. package/dist/agent/nativeTools.test.d.ts.map +0 -1
  472. package/dist/agent/nativeTools.test.js +0 -67
  473. package/dist/agent/nativeTools.test.js.map +0 -1
  474. package/dist/agent/orchestrator.test.d.ts +0 -2
  475. package/dist/agent/orchestrator.test.d.ts.map +0 -1
  476. package/dist/agent/orchestrator.test.js +0 -284
  477. package/dist/agent/orchestrator.test.js.map +0 -1
  478. package/dist/agent/session.test.d.ts +0 -2
  479. package/dist/agent/session.test.d.ts.map +0 -1
  480. package/dist/agent/session.test.js +0 -74
  481. package/dist/agent/session.test.js.map +0 -1
  482. package/dist/agent/smoke-chat.test.d.ts +0 -2
  483. package/dist/agent/smoke-chat.test.d.ts.map +0 -1
  484. package/dist/agent/smoke-chat.test.js +0 -166
  485. package/dist/agent/smoke-chat.test.js.map +0 -1
  486. package/dist/commands/add-repo.test.d.ts +0 -2
  487. package/dist/commands/add-repo.test.d.ts.map +0 -1
  488. package/dist/commands/add-repo.test.js +0 -30
  489. package/dist/commands/add-repo.test.js.map +0 -1
  490. package/dist/commands/commands.test.d.ts +0 -2
  491. package/dist/commands/commands.test.d.ts.map +0 -1
  492. package/dist/commands/commands.test.js +0 -156
  493. package/dist/commands/commands.test.js.map +0 -1
  494. package/dist/commands/commit.test.d.ts +0 -2
  495. package/dist/commands/commit.test.d.ts.map +0 -1
  496. package/dist/commands/commit.test.js +0 -54
  497. package/dist/commands/commit.test.js.map +0 -1
  498. package/dist/commands/isolate.test.d.ts +0 -2
  499. package/dist/commands/isolate.test.d.ts.map +0 -1
  500. package/dist/commands/isolate.test.js +0 -59
  501. package/dist/commands/isolate.test.js.map +0 -1
  502. package/dist/commands/knowledge.test.d.ts +0 -2
  503. package/dist/commands/knowledge.test.d.ts.map +0 -1
  504. package/dist/commands/knowledge.test.js +0 -90
  505. package/dist/commands/knowledge.test.js.map +0 -1
  506. package/dist/commands/status.test.d.ts +0 -2
  507. package/dist/commands/status.test.d.ts.map +0 -1
  508. package/dist/commands/status.test.js +0 -31
  509. package/dist/commands/status.test.js.map +0 -1
  510. package/dist/commands/ui.test.d.ts +0 -2
  511. package/dist/commands/ui.test.d.ts.map +0 -1
  512. package/dist/commands/ui.test.js +0 -58
  513. package/dist/commands/ui.test.js.map +0 -1
  514. package/dist/core/adapters/storage.test.d.ts +0 -2
  515. package/dist/core/adapters/storage.test.d.ts.map +0 -1
  516. package/dist/core/adapters/storage.test.js +0 -65
  517. package/dist/core/adapters/storage.test.js.map +0 -1
  518. package/dist/core/analysis-cache.test.d.ts +0 -2
  519. package/dist/core/analysis-cache.test.d.ts.map +0 -1
  520. package/dist/core/analysis-cache.test.js +0 -163
  521. package/dist/core/analysis-cache.test.js.map +0 -1
  522. package/dist/core/config.test.d.ts +0 -2
  523. package/dist/core/config.test.d.ts.map +0 -1
  524. package/dist/core/config.test.js +0 -90
  525. package/dist/core/config.test.js.map +0 -1
  526. package/dist/core/finish.test.d.ts +0 -2
  527. package/dist/core/finish.test.d.ts.map +0 -1
  528. package/dist/core/finish.test.js +0 -110
  529. package/dist/core/finish.test.js.map +0 -1
  530. package/dist/core/generation-lock.test.d.ts +0 -2
  531. package/dist/core/generation-lock.test.d.ts.map +0 -1
  532. package/dist/core/generation-lock.test.js +0 -134
  533. package/dist/core/generation-lock.test.js.map +0 -1
  534. package/dist/core/isolate.test.d.ts +0 -2
  535. package/dist/core/isolate.test.d.ts.map +0 -1
  536. package/dist/core/isolate.test.js +0 -320
  537. package/dist/core/isolate.test.js.map +0 -1
  538. package/dist/core/knowledge.test.d.ts +0 -2
  539. package/dist/core/knowledge.test.d.ts.map +0 -1
  540. package/dist/core/knowledge.test.js +0 -287
  541. package/dist/core/knowledge.test.js.map +0 -1
  542. package/dist/core/locks.test.d.ts +0 -2
  543. package/dist/core/locks.test.d.ts.map +0 -1
  544. package/dist/core/locks.test.js +0 -143
  545. package/dist/core/locks.test.js.map +0 -1
  546. package/dist/core/new-repo.test.d.ts +0 -2
  547. package/dist/core/new-repo.test.d.ts.map +0 -1
  548. package/dist/core/new-repo.test.js +0 -78
  549. package/dist/core/new-repo.test.js.map +0 -1
  550. package/dist/core/progress.test.d.ts +0 -2
  551. package/dist/core/progress.test.d.ts.map +0 -1
  552. package/dist/core/progress.test.js +0 -52
  553. package/dist/core/progress.test.js.map +0 -1
  554. package/dist/core/projects.test.d.ts +0 -2
  555. package/dist/core/projects.test.d.ts.map +0 -1
  556. package/dist/core/projects.test.js +0 -165
  557. package/dist/core/projects.test.js.map +0 -1
  558. package/dist/core/refresh.test.d.ts +0 -2
  559. package/dist/core/refresh.test.d.ts.map +0 -1
  560. package/dist/core/refresh.test.js +0 -93
  561. package/dist/core/refresh.test.js.map +0 -1
  562. package/dist/core/scanner.test.d.ts +0 -2
  563. package/dist/core/scanner.test.d.ts.map +0 -1
  564. package/dist/core/scanner.test.js +0 -53
  565. package/dist/core/scanner.test.js.map +0 -1
  566. package/dist/core/scheduler.test.d.ts +0 -2
  567. package/dist/core/scheduler.test.d.ts.map +0 -1
  568. package/dist/core/scheduler.test.js +0 -169
  569. package/dist/core/scheduler.test.js.map +0 -1
  570. package/dist/core/sync.test.d.ts +0 -2
  571. package/dist/core/sync.test.d.ts.map +0 -1
  572. package/dist/core/sync.test.js +0 -128
  573. package/dist/core/sync.test.js.map +0 -1
  574. package/dist/core/workspace-git.test.d.ts +0 -2
  575. package/dist/core/workspace-git.test.d.ts.map +0 -1
  576. package/dist/core/workspace-git.test.js +0 -52
  577. package/dist/core/workspace-git.test.js.map +0 -1
  578. package/dist/core/workspace-skills-workflow.integration.test.d.ts +0 -2
  579. package/dist/core/workspace-skills-workflow.integration.test.d.ts.map +0 -1
  580. package/dist/core/workspace-skills-workflow.integration.test.js +0 -177
  581. package/dist/core/workspace-skills-workflow.integration.test.js.map +0 -1
  582. package/dist/core/workspace-state.test.d.ts +0 -2
  583. package/dist/core/workspace-state.test.d.ts.map +0 -1
  584. package/dist/core/workspace-state.test.js +0 -84
  585. package/dist/core/workspace-state.test.js.map +0 -1
  586. package/dist/core/workspace.create.test.d.ts +0 -2
  587. package/dist/core/workspace.create.test.d.ts.map +0 -1
  588. package/dist/core/workspace.create.test.js +0 -224
  589. package/dist/core/workspace.create.test.js.map +0 -1
  590. package/dist/core/workspace.test.d.ts +0 -2
  591. package/dist/core/workspace.test.d.ts.map +0 -1
  592. package/dist/core/workspace.test.js +0 -53
  593. package/dist/core/workspace.test.js.map +0 -1
  594. package/dist/core/worktree.test.d.ts +0 -2
  595. package/dist/core/worktree.test.d.ts.map +0 -1
  596. package/dist/core/worktree.test.js +0 -153
  597. package/dist/core/worktree.test.js.map +0 -1
  598. package/dist/generators/base.test.d.ts +0 -2
  599. package/dist/generators/base.test.d.ts.map +0 -1
  600. package/dist/generators/base.test.js +0 -287
  601. package/dist/generators/base.test.js.map +0 -1
  602. package/dist/generators/knowledge-migration.test.d.ts +0 -2
  603. package/dist/generators/knowledge-migration.test.d.ts.map +0 -1
  604. package/dist/generators/knowledge-migration.test.js +0 -22
  605. package/dist/generators/knowledge-migration.test.js.map +0 -1
  606. package/dist/generators/plan-generator.test.d.ts +0 -2
  607. package/dist/generators/plan-generator.test.d.ts.map +0 -1
  608. package/dist/generators/plan-generator.test.js +0 -220
  609. package/dist/generators/plan-generator.test.js.map +0 -1
  610. package/dist/generators/skills-generator.test.d.ts +0 -2
  611. package/dist/generators/skills-generator.test.d.ts.map +0 -1
  612. package/dist/generators/skills-generator.test.js +0 -79
  613. package/dist/generators/skills-generator.test.js.map +0 -1
  614. package/dist/gui/assets/AgentsPage-B4fx43rd.js +0 -3
  615. package/dist/gui/assets/CSPContext-DBUu9tE0.js +0 -1
  616. package/dist/gui/assets/DashboardPage-DH52G8IG.js +0 -1
  617. package/dist/gui/assets/GettingStartedPage-BlTrQhvi.js +0 -1
  618. package/dist/gui/assets/ProjectsPage-BPVSLPXv.js +0 -1
  619. package/dist/gui/assets/ScaffoldRepoInline-ywcpq9PX.js +0 -1
  620. package/dist/gui/assets/SettingsPage-RQr8SalV.js +0 -1
  621. package/dist/gui/assets/SkillsPage-CYoSRrwx.js +0 -6
  622. package/dist/gui/assets/StartWorkPage-DBKK4lFi.js +0 -1
  623. package/dist/gui/assets/WorkspacesPage-DxEONvSq.js +0 -6
  624. package/dist/gui/assets/alert-dialog-CQAX2yRx.js +0 -1
  625. package/dist/gui/assets/badge-CAohJGj6.js +0 -1
  626. package/dist/gui/assets/bot-C2HWrAft.js +0 -1
  627. package/dist/gui/assets/button-BDDZnIHx.js +0 -1
  628. package/dist/gui/assets/card-BKXzd_5L.js +0 -1
  629. package/dist/gui/assets/chevron-down-qTL8HPug.js +0 -1
  630. package/dist/gui/assets/cpu-Cdwd84Jz.js +0 -1
  631. package/dist/gui/assets/empty-BdlgbifD.js +0 -1
  632. package/dist/gui/assets/index-BF6pre6G.css +0 -2
  633. package/dist/gui/assets/index-C_rwnBzF.js +0 -52
  634. package/dist/gui/assets/isElementDisabled-uy_EOitH.js +0 -1
  635. package/dist/gui/assets/label-CG5exjag.js +0 -1
  636. package/dist/gui/assets/square-DlIYnlSq.js +0 -1
  637. package/dist/gui/assets/textarea-ByfoCb54.js +0 -1
  638. package/dist/gui/assets/useAriaLabelledBy-ClesgjMe.js +0 -1
  639. package/dist/gui/assets/useValueChanged-DeYvGnKs.js +0 -1
  640. package/dist/gui/assets/zap-CWG_Lvki.js +0 -1
  641. package/dist/harness/contract.test.d.ts +0 -2
  642. package/dist/harness/contract.test.d.ts.map +0 -1
  643. package/dist/harness/contract.test.js +0 -426
  644. package/dist/harness/contract.test.js.map +0 -1
  645. package/dist/harness/harness.test.d.ts +0 -2
  646. package/dist/harness/harness.test.d.ts.map +0 -1
  647. package/dist/harness/harness.test.js +0 -215
  648. package/dist/harness/harness.test.js.map +0 -1
  649. package/dist/mcp/tools.test.d.ts +0 -2
  650. package/dist/mcp/tools.test.d.ts.map +0 -1
  651. package/dist/mcp/tools.test.js +0 -194
  652. package/dist/mcp/tools.test.js.map +0 -1
  653. package/dist/orchestration/log-tail.test.d.ts +0 -2
  654. package/dist/orchestration/log-tail.test.d.ts.map +0 -1
  655. package/dist/orchestration/log-tail.test.js +0 -72
  656. package/dist/orchestration/log-tail.test.js.map +0 -1
  657. package/dist/orchestration/orchestrator.test.d.ts +0 -2
  658. package/dist/orchestration/orchestrator.test.d.ts.map +0 -1
  659. package/dist/orchestration/orchestrator.test.js +0 -85
  660. package/dist/orchestration/orchestrator.test.js.map +0 -1
  661. package/dist/orchestration/runner.test.d.ts +0 -2
  662. package/dist/orchestration/runner.test.d.ts.map +0 -1
  663. package/dist/orchestration/runner.test.js +0 -233
  664. package/dist/orchestration/runner.test.js.map +0 -1
  665. package/dist/resources/agents-catalog.test.d.ts +0 -2
  666. package/dist/resources/agents-catalog.test.d.ts.map +0 -1
  667. package/dist/resources/agents-catalog.test.js +0 -50
  668. package/dist/resources/agents-catalog.test.js.map +0 -1
  669. package/dist/resources/codex-agent.test.d.ts +0 -2
  670. package/dist/resources/codex-agent.test.d.ts.map +0 -1
  671. package/dist/resources/codex-agent.test.js +0 -27
  672. package/dist/resources/codex-agent.test.js.map +0 -1
  673. package/dist/resources/materializer.test.d.ts +0 -2
  674. package/dist/resources/materializer.test.d.ts.map +0 -1
  675. package/dist/resources/materializer.test.js +0 -149
  676. package/dist/resources/materializer.test.js.map +0 -1
  677. package/dist/resources/service.test.d.ts +0 -2
  678. package/dist/resources/service.test.d.ts.map +0 -1
  679. package/dist/resources/service.test.js +0 -58
  680. package/dist/resources/service.test.js.map +0 -1
  681. package/dist/server.test.d.ts +0 -2
  682. package/dist/server.test.d.ts.map +0 -1
  683. package/dist/server.test.js +0 -1697
  684. package/dist/server.test.js.map +0 -1
  685. package/dist/utils/detect-ai.test.d.ts +0 -2
  686. package/dist/utils/detect-ai.test.d.ts.map +0 -1
  687. package/dist/utils/detect-ai.test.js +0 -70
  688. package/dist/utils/detect-ai.test.js.map +0 -1
  689. package/dist/utils/detect-editors.test.d.ts +0 -2
  690. package/dist/utils/detect-editors.test.d.ts.map +0 -1
  691. package/dist/utils/detect-editors.test.js +0 -85
  692. package/dist/utils/detect-editors.test.js.map +0 -1
  693. package/dist/utils/git.test.d.ts +0 -2
  694. package/dist/utils/git.test.d.ts.map +0 -1
  695. package/dist/utils/git.test.js +0 -125
  696. package/dist/utils/git.test.js.map +0 -1
  697. package/dist/utils/multi-git.test.d.ts +0 -2
  698. package/dist/utils/multi-git.test.d.ts.map +0 -1
  699. package/dist/utils/multi-git.test.js +0 -330
  700. package/dist/utils/multi-git.test.js.map +0 -1
  701. package/dist/utils/pr.test.d.ts +0 -2
  702. package/dist/utils/pr.test.d.ts.map +0 -1
  703. package/dist/utils/pr.test.js +0 -47
  704. package/dist/utils/pr.test.js.map +0 -1
  705. package/dist/utils/session-finder.test.d.ts +0 -2
  706. package/dist/utils/session-finder.test.d.ts.map +0 -1
  707. package/dist/utils/session-finder.test.js +0 -304
  708. package/dist/utils/session-finder.test.js.map +0 -1
  709. package/dist/utils/skills-catalog.test.d.ts +0 -2
  710. package/dist/utils/skills-catalog.test.d.ts.map +0 -1
  711. package/dist/utils/skills-catalog.test.js +0 -281
  712. package/dist/utils/skills-catalog.test.js.map +0 -1
  713. package/dist/utils/system-scanner.test.d.ts +0 -2
  714. package/dist/utils/system-scanner.test.d.ts.map +0 -1
  715. package/dist/utils/system-scanner.test.js +0 -73
  716. package/dist/utils/system-scanner.test.js.map +0 -1
  717. package/dist/utils/terminal-launch.test.d.ts +0 -2
  718. package/dist/utils/terminal-launch.test.d.ts.map +0 -1
  719. package/dist/utils/terminal-launch.test.js +0 -117
  720. package/dist/utils/terminal-launch.test.js.map +0 -1
  721. package/dist/utils/update-check.test.d.ts +0 -2
  722. package/dist/utils/update-check.test.d.ts.map +0 -1
  723. package/dist/utils/update-check.test.js +0 -30
  724. package/dist/utils/update-check.test.js.map +0 -1
  725. package/dist/utils/workflows.test.d.ts +0 -2
  726. package/dist/utils/workflows.test.d.ts.map +0 -1
  727. package/dist/utils/workflows.test.js +0 -86
  728. package/dist/utils/workflows.test.js.map +0 -1
  729. package/dist/utils/workspace-launch.test.d.ts +0 -2
  730. package/dist/utils/workspace-launch.test.d.ts.map +0 -1
  731. package/dist/utils/workspace-launch.test.js +0 -128
  732. package/dist/utils/workspace-launch.test.js.map +0 -1
@@ -0,0 +1,747 @@
1
+ import { X509Certificate, randomUUID } from 'node:crypto';
2
+ import * as fs from 'node:fs/promises';
3
+ import { createServer as createHttpsServer } from 'node:https';
4
+ import * as os from 'node:os';
5
+ import * as path from 'node:path';
6
+ import { getConnInfo } from '@hono/node-server/conninfo';
7
+ import { serve } from '@hono/node-server';
8
+ import { Hono } from 'hono';
9
+ import { bodyLimit } from 'hono/body-limit';
10
+ import { streamSSE } from 'hono/streaming';
11
+ import { generate } from 'selfsigned';
12
+ import { assertFileHandleMatchesPath, readFileHandleAtMost } from '../resources/fs-safety.js';
13
+ import { WorkroomAuthorizationError, WORKROOM_MAX_RESOURCE_UPLOAD_BYTES, WorkroomRevisionError, WorkroomValidationError, } from './contracts.js';
14
+ import { decryptExport, encryptExport, normalizeFingerprint, tokenDigest, verifyPassword } from './crypto.js';
15
+ import { createInitialWorkroomState, WorkroomService } from './service.js';
16
+ import { WorkroomSqliteStore } from './sqlite-store.js';
17
+ export function listWorkroomNetworkInterfaces() {
18
+ const result = [];
19
+ for (const [name, addresses] of Object.entries(os.networkInterfaces())) {
20
+ for (const address of addresses ?? []) {
21
+ if (address.family !== 'IPv4' && address.family !== 'IPv6')
22
+ continue;
23
+ result.push({ name, address: address.address, family: address.family, internal: address.internal });
24
+ }
25
+ }
26
+ return result.sort((left, right) => Number(left.internal) - Number(right.internal) || left.name.localeCompare(right.name));
27
+ }
28
+ export function assertLocalInterface(address) {
29
+ if (!listWorkroomNetworkInterfaces().some((candidate) => candidate.address === address)) {
30
+ throw new WorkroomValidationError('Select an address that belongs to this computer.');
31
+ }
32
+ }
33
+ function bearerToken(header) {
34
+ const match = header?.match(/^Bearer\s+(.+)$/i);
35
+ if (!match)
36
+ throw new WorkroomAuthorizationError('A Workroom device credential is required.');
37
+ return match[1];
38
+ }
39
+ function remoteSourceKey(c) {
40
+ try {
41
+ return getConnInfo(c).remote.address ?? 'unknown';
42
+ }
43
+ catch {
44
+ return 'unknown';
45
+ }
46
+ }
47
+ function workroomError(c, error) {
48
+ if (error instanceof WorkroomAuthorizationError)
49
+ return c.json({ error: error.message }, 401);
50
+ if (error instanceof WorkroomRevisionError) {
51
+ return c.json({ error: error.message, expectedRevision: error.expected, actualRevision: error.actual }, 409);
52
+ }
53
+ if (error instanceof WorkroomValidationError)
54
+ return c.json({ error: error.message }, 400);
55
+ const message = error instanceof Error ? error.message : String(error);
56
+ console.error('[workroom] request failed:', message);
57
+ return c.json({ error: 'The Workroom request failed.' }, 500);
58
+ }
59
+ export function createWorkroomApp(service) {
60
+ const app = new Hono();
61
+ let activeJoinRequests = 0;
62
+ const activeJoinRequestsBySource = new Map();
63
+ const joinRequestWindowsBySource = new Map();
64
+ let activeResourceUploads = 0;
65
+ let activeMutations = 0;
66
+ let activeReads = 0;
67
+ let activeEventStreams = 0;
68
+ let activeProtectedRequests = 0;
69
+ const activeProtectedRequestsBySource = new Map();
70
+ const protectedRequestWindowsBySource = new Map();
71
+ const readsByPrincipal = new Map();
72
+ const eventStreamsByPrincipal = new Map();
73
+ const publicRoomId = service.store.read().then((state) => state.roomId);
74
+ app.use('*', async (c, next) => {
75
+ c.header('Cache-Control', 'no-store');
76
+ c.header('X-Content-Type-Options', 'nosniff');
77
+ if (c.req.header('origin'))
78
+ return c.json({ error: 'Browser-originated remote requests are not allowed.' }, 403);
79
+ await next();
80
+ });
81
+ const admitProtectedRequest = (sourceKey) => {
82
+ const now = Date.now();
83
+ for (const [key, window] of protectedRequestWindowsBySource) {
84
+ if (now - window.startedAt >= 60_000)
85
+ protectedRequestWindowsBySource.delete(key);
86
+ }
87
+ const currentWindow = protectedRequestWindowsBySource.get(sourceKey);
88
+ const liveWindow = currentWindow && now - currentWindow.startedAt < 60_000
89
+ ? currentWindow
90
+ : { startedAt: now, count: 0 };
91
+ if (liveWindow.count >= 240) {
92
+ return { error: 'Too many protected Workroom requests from this source. Try again shortly.' };
93
+ }
94
+ if (!currentWindow && protectedRequestWindowsBySource.size >= 4_096) {
95
+ const oldest = protectedRequestWindowsBySource.keys().next().value;
96
+ if (oldest)
97
+ protectedRequestWindowsBySource.delete(oldest);
98
+ }
99
+ protectedRequestWindowsBySource.set(sourceKey, { startedAt: liveWindow.startedAt, count: liveWindow.count + 1 });
100
+ const activeForSource = activeProtectedRequestsBySource.get(sourceKey) ?? 0;
101
+ if (activeProtectedRequests >= 6 || activeForSource >= 2) {
102
+ return { error: 'The Workroom is busy authenticating requests. Try again shortly.' };
103
+ }
104
+ activeProtectedRequests += 1;
105
+ activeProtectedRequestsBySource.set(sourceKey, activeForSource + 1);
106
+ let released = false;
107
+ return { release: () => {
108
+ if (released)
109
+ return;
110
+ released = true;
111
+ activeProtectedRequests -= 1;
112
+ const remaining = (activeProtectedRequestsBySource.get(sourceKey) ?? 1) - 1;
113
+ if (remaining > 0)
114
+ activeProtectedRequestsBySource.set(sourceKey, remaining);
115
+ else
116
+ activeProtectedRequestsBySource.delete(sourceKey);
117
+ } };
118
+ };
119
+ app.use('/v1/*', async (c, next) => {
120
+ const pathname = new URL(c.req.url).pathname;
121
+ if (pathname === '/v1/health' || pathname === '/v1/events'
122
+ || (pathname === '/v1/join' && c.req.method === 'POST')) {
123
+ return next();
124
+ }
125
+ try {
126
+ bearerToken(c.req.header('authorization'));
127
+ }
128
+ catch (error) {
129
+ return workroomError(c, error);
130
+ }
131
+ const admission = admitProtectedRequest(remoteSourceKey(c));
132
+ if (admission.error)
133
+ return c.json({ error: admission.error }, 429);
134
+ try {
135
+ await next();
136
+ }
137
+ finally {
138
+ admission.release?.();
139
+ }
140
+ });
141
+ const mutationAdmission = (kind, roles) => async (c, next) => {
142
+ if (!['POST', 'PUT', 'PATCH', 'DELETE'].includes(c.req.method))
143
+ return next();
144
+ try {
145
+ const token = bearerToken(c.req.header('authorization'));
146
+ if (kind === 'human')
147
+ await service.authorizeHuman(token, roles);
148
+ else
149
+ await service.authorizeAgent(token);
150
+ if (activeMutations >= 16) {
151
+ return c.json({ error: 'The Workroom is busy processing changes. Try again shortly.' }, 429);
152
+ }
153
+ activeMutations += 1;
154
+ try {
155
+ await next();
156
+ }
157
+ finally {
158
+ activeMutations -= 1;
159
+ }
160
+ }
161
+ catch (error) {
162
+ return workroomError(c, error);
163
+ }
164
+ };
165
+ const readAdmission = (authorizeParticipant) => async (c, next) => {
166
+ if (c.req.method !== 'GET')
167
+ return next();
168
+ try {
169
+ const token = bearerToken(c.req.header('authorization'));
170
+ if (authorizeParticipant)
171
+ await service.authorizeRead(token);
172
+ const principalKey = tokenDigest(token);
173
+ const principalReads = readsByPrincipal.get(principalKey) ?? 0;
174
+ if (activeReads >= 4 || principalReads >= 2) {
175
+ return c.json({ error: 'The Workroom is busy processing reads. Try again shortly.' }, 429);
176
+ }
177
+ activeReads += 1;
178
+ readsByPrincipal.set(principalKey, principalReads + 1);
179
+ try {
180
+ await next();
181
+ }
182
+ finally {
183
+ activeReads -= 1;
184
+ const remaining = (readsByPrincipal.get(principalKey) ?? 1) - 1;
185
+ if (remaining > 0)
186
+ readsByPrincipal.set(principalKey, remaining);
187
+ else
188
+ readsByPrincipal.delete(principalKey);
189
+ }
190
+ }
191
+ catch (error) {
192
+ return workroomError(c, error);
193
+ }
194
+ };
195
+ app.use('/v1/documents/*', mutationAdmission('human'));
196
+ app.use('/v1/handoff', mutationAdmission('human'));
197
+ app.use('/v1/resources', mutationAdmission('human', ['host', 'publisher']));
198
+ app.use('/v1/workflow/select', mutationAdmission('human', ['host']));
199
+ app.use('/v1/workflow/steps/:stepId/transition', mutationAdmission('human'));
200
+ app.use('/v1/workflow/steps/:stepId/propose', mutationAdmission('agent'));
201
+ app.use('/v1/join/:requestId', readAdmission(false));
202
+ app.use('/v1/snapshot', readAdmission(true));
203
+ app.use('/v1/resources/*', readAdmission(true));
204
+ app.use('/v1/join', bodyLimit({ maxSize: 16 * 1024, onError: (c) => c.json({ error: 'Join request body is too large.' }, 413) }));
205
+ app.use('/v1/documents/*', bodyLimit({ maxSize: 512 * 1024, onError: (c) => c.json({ error: 'Document request body is too large.' }, 413) }));
206
+ app.use('/v1/handoff', bodyLimit({ maxSize: 1024 * 1024, onError: (c) => c.json({ error: 'Handoff request body is too large.' }, 413) }));
207
+ app.use('/v1/resources', bodyLimit({ maxSize: WORKROOM_MAX_RESOURCE_UPLOAD_BYTES, onError: (c) => c.json({ error: 'Resource request body is too large.' }, 413) }));
208
+ app.use('/v1/workflow/select', bodyLimit({ maxSize: 3 * 1024 * 1024, onError: (c) => c.json({ error: 'Workflow request body is too large.' }, 413) }));
209
+ app.use('/v1/workflow/steps/*', bodyLimit({ maxSize: 32 * 1024, onError: (c) => c.json({ error: 'Workflow transition body is too large.' }, 413) }));
210
+ app.use('/v1/*', bodyLimit({ maxSize: 16 * 1024 * 1024, onError: (c) => c.json({ error: 'Request body is too large.' }, 413) }));
211
+ app.get('/v1/health', async (c) => {
212
+ return c.json({ schemaVersion: 1, roomId: await publicRoomId });
213
+ });
214
+ app.post('/v1/join', async (c) => {
215
+ const sourceKey = remoteSourceKey(c);
216
+ const now = Date.now();
217
+ for (const [key, window] of joinRequestWindowsBySource) {
218
+ if (now - window.startedAt >= 60_000)
219
+ joinRequestWindowsBySource.delete(key);
220
+ }
221
+ const currentWindow = joinRequestWindowsBySource.get(sourceKey);
222
+ const liveWindow = currentWindow && now - currentWindow.startedAt < 60_000
223
+ ? currentWindow
224
+ : { startedAt: now, count: 0 };
225
+ if (liveWindow.count >= 30) {
226
+ return c.json({ error: 'Too many join requests from this source. Try again shortly.' }, 429);
227
+ }
228
+ if (!currentWindow && joinRequestWindowsBySource.size >= 4_096) {
229
+ const oldest = joinRequestWindowsBySource.keys().next().value;
230
+ if (oldest)
231
+ joinRequestWindowsBySource.delete(oldest);
232
+ }
233
+ joinRequestWindowsBySource.set(sourceKey, { startedAt: liveWindow.startedAt, count: liveWindow.count + 1 });
234
+ const sourceRequests = activeJoinRequestsBySource.get(sourceKey) ?? 0;
235
+ if (activeJoinRequests >= 4 || sourceRequests >= 1) {
236
+ return c.json({ error: 'The Workroom is busy processing join requests. Try again shortly.' }, 429);
237
+ }
238
+ activeJoinRequests += 1;
239
+ activeJoinRequestsBySource.set(sourceKey, sourceRequests + 1);
240
+ try {
241
+ const body = await c.req.json();
242
+ const result = await service.requestJoin({
243
+ roomId: String(body.roomId ?? ''),
244
+ inviteToken: String(body.inviteToken ?? ''),
245
+ password: String(body.password ?? ''),
246
+ displayName: String(body.displayName ?? ''),
247
+ deviceToken: String(body.deviceToken ?? ''),
248
+ agentToken: String(body.agentToken ?? ''),
249
+ sourceKey,
250
+ });
251
+ return c.json(result, 202);
252
+ }
253
+ catch (error) {
254
+ return workroomError(c, error);
255
+ }
256
+ finally {
257
+ activeJoinRequests -= 1;
258
+ const remaining = (activeJoinRequestsBySource.get(sourceKey) ?? 1) - 1;
259
+ if (remaining > 0)
260
+ activeJoinRequestsBySource.set(sourceKey, remaining);
261
+ else
262
+ activeJoinRequestsBySource.delete(sourceKey);
263
+ }
264
+ });
265
+ app.get('/v1/join/:requestId', async (c) => {
266
+ try {
267
+ return c.json(await service.getJoinStatus(c.req.param('requestId'), bearerToken(c.req.header('authorization'))));
268
+ }
269
+ catch (error) {
270
+ return workroomError(c, error);
271
+ }
272
+ });
273
+ app.get('/v1/snapshot', async (c) => {
274
+ try {
275
+ return c.json(await service.snapshot(bearerToken(c.req.header('authorization'))));
276
+ }
277
+ catch (error) {
278
+ return workroomError(c, error);
279
+ }
280
+ });
281
+ app.put('/v1/documents/:name', async (c) => {
282
+ try {
283
+ const token = bearerToken(c.req.header('authorization'));
284
+ await service.authorizeHuman(token);
285
+ const body = await c.req.json();
286
+ const document = await service.updateDocument(token, c.req.param('name'), String(body.content ?? ''), Number(body.expectedRevision));
287
+ return c.json({ document });
288
+ }
289
+ catch (error) {
290
+ return workroomError(c, error);
291
+ }
292
+ });
293
+ app.post('/v1/handoff', async (c) => {
294
+ try {
295
+ const token = bearerToken(c.req.header('authorization'));
296
+ await service.authorizeHuman(token);
297
+ const body = await c.req.json();
298
+ const document = await service.publishHandoff(token, String(body.content ?? ''), Array.isArray(body.repos) ? body.repos : [], Number(body.expectedRevision));
299
+ return c.json({ document });
300
+ }
301
+ catch (error) {
302
+ return workroomError(c, error);
303
+ }
304
+ });
305
+ app.post('/v1/resources', async (c) => {
306
+ let admitted = false;
307
+ try {
308
+ const token = bearerToken(c.req.header('authorization'));
309
+ await service.authorizeHuman(token, ['host', 'publisher']);
310
+ if (activeResourceUploads >= 2)
311
+ return c.json({ error: 'The Workroom is busy processing resource uploads. Try again shortly.' }, 429);
312
+ activeResourceUploads += 1;
313
+ admitted = true;
314
+ const pkg = await service.publishResource(token, await c.req.json());
315
+ return c.json({ package: pkg }, 201);
316
+ }
317
+ catch (error) {
318
+ return workroomError(c, error);
319
+ }
320
+ finally {
321
+ if (admitted)
322
+ activeResourceUploads -= 1;
323
+ }
324
+ });
325
+ app.get('/v1/resources/:digest', async (c) => {
326
+ try {
327
+ return c.json({ package: await service.getResource(bearerToken(c.req.header('authorization')), c.req.param('digest')) });
328
+ }
329
+ catch (error) {
330
+ return workroomError(c, error);
331
+ }
332
+ });
333
+ app.post('/v1/workflow/select', async (c) => {
334
+ try {
335
+ const token = bearerToken(c.req.header('authorization'));
336
+ await service.authorizeHuman(token, ['host']);
337
+ const body = await c.req.json();
338
+ await service.selectWorkflow(token, body.workflow, Number(body.expectedRevision));
339
+ return c.json({ success: true });
340
+ }
341
+ catch (error) {
342
+ return workroomError(c, error);
343
+ }
344
+ });
345
+ app.post('/v1/workflow/steps/:stepId/transition', async (c) => {
346
+ try {
347
+ const token = bearerToken(c.req.header('authorization'));
348
+ await service.authorizeHuman(token);
349
+ const body = await c.req.json();
350
+ const step = await service.transitionWorkflowStep(token, c.req.param('stepId'), body.status, Number(body.expectedRevision), typeof body.evidence === 'string' ? body.evidence : undefined);
351
+ return c.json({ step });
352
+ }
353
+ catch (error) {
354
+ return workroomError(c, error);
355
+ }
356
+ });
357
+ app.post('/v1/workflow/steps/:stepId/propose', async (c) => {
358
+ try {
359
+ const token = bearerToken(c.req.header('authorization'));
360
+ await service.authorizeAgent(token);
361
+ const body = await c.req.json();
362
+ const step = await service.proposeWorkflowStep(token, c.req.param('stepId'), Number(body.expectedRevision), typeof body.evidence === 'string' ? body.evidence : '');
363
+ return c.json({ step });
364
+ }
365
+ catch (error) {
366
+ return workroomError(c, error);
367
+ }
368
+ });
369
+ app.get('/v1/events', async (c) => {
370
+ let admitted = false;
371
+ let handedToStream = false;
372
+ let principalKey = '';
373
+ let authenticationRelease;
374
+ try {
375
+ let cursor = Number.parseInt(c.req.query('cursor') ?? '0', 10) || 0;
376
+ const token = bearerToken(c.req.header('authorization'));
377
+ const authenticationAdmission = admitProtectedRequest(remoteSourceKey(c));
378
+ if (authenticationAdmission.error)
379
+ return c.json({ error: authenticationAdmission.error }, 429);
380
+ authenticationRelease = authenticationAdmission.release;
381
+ try {
382
+ await service.snapshot(token);
383
+ }
384
+ finally {
385
+ authenticationRelease?.();
386
+ authenticationRelease = undefined;
387
+ }
388
+ principalKey = tokenDigest(token);
389
+ const principalStreams = eventStreamsByPrincipal.get(principalKey) ?? 0;
390
+ if (activeEventStreams >= 32 || principalStreams >= 2) {
391
+ return c.json({ error: 'Too many active Workroom event streams.' }, 429);
392
+ }
393
+ activeEventStreams += 1;
394
+ eventStreamsByPrincipal.set(principalKey, principalStreams + 1);
395
+ admitted = true;
396
+ const release = () => {
397
+ if (!admitted)
398
+ return;
399
+ admitted = false;
400
+ activeEventStreams -= 1;
401
+ const remaining = (eventStreamsByPrincipal.get(principalKey) ?? 1) - 1;
402
+ if (remaining > 0)
403
+ eventStreamsByPrincipal.set(principalKey, remaining);
404
+ else
405
+ eventStreamsByPrincipal.delete(principalKey);
406
+ };
407
+ const response = streamSSE(c, async (stream) => {
408
+ try {
409
+ while (!stream.aborted) {
410
+ const snapshot = await service.snapshot(token);
411
+ for (const event of snapshot.activity.filter((candidate) => candidate.sequence > cursor)) {
412
+ await stream.writeSSE({ id: String(event.sequence), event: event.type, data: JSON.stringify(event) });
413
+ cursor = event.sequence;
414
+ }
415
+ await stream.sleep(1_000);
416
+ }
417
+ }
418
+ finally {
419
+ release();
420
+ }
421
+ });
422
+ handedToStream = true;
423
+ return response;
424
+ }
425
+ catch (error) {
426
+ return workroomError(c, error);
427
+ }
428
+ finally {
429
+ authenticationRelease?.();
430
+ if (!handedToStream && admitted) {
431
+ admitted = false;
432
+ activeEventStreams -= 1;
433
+ const remaining = (eventStreamsByPrincipal.get(principalKey) ?? 1) - 1;
434
+ if (remaining > 0)
435
+ eventStreamsByPrincipal.set(principalKey, remaining);
436
+ else
437
+ eventStreamsByPrincipal.delete(principalKey);
438
+ }
439
+ }
440
+ });
441
+ return app;
442
+ }
443
+ async function listenWorkroom(service, address, port, key, cert) {
444
+ const app = createWorkroomApp(service);
445
+ return new Promise((resolve, reject) => {
446
+ const listener = serve({
447
+ fetch: app.fetch,
448
+ hostname: address,
449
+ port,
450
+ createServer: createHttpsServer,
451
+ serverOptions: { key, cert, handshakeTimeout: 10_000 },
452
+ });
453
+ listener.maxConnections = 64;
454
+ listener.requestTimeout = 30_000;
455
+ listener.headersTimeout = 10_000;
456
+ listener.keepAliveTimeout = 5_000;
457
+ const onError = (error) => reject(error);
458
+ listener.once('error', onError);
459
+ listener.once('listening', () => {
460
+ listener.off('error', onError);
461
+ listener.on('error', (error) => console.error('[workroom] listener error:', error.message));
462
+ resolve(listener);
463
+ });
464
+ });
465
+ }
466
+ function hostedResult(state, roomDir, service, server, hostToken, hostAgentToken) {
467
+ const formattedAddress = state.address.includes(':') ? `[${state.address}]` : state.address;
468
+ let stopPromise;
469
+ return {
470
+ roomId: state.roomId,
471
+ roomDir,
472
+ service,
473
+ server,
474
+ hostToken,
475
+ hostAgentToken,
476
+ certificateFingerprint: state.certificateFingerprint,
477
+ url: `https://${formattedAddress}:${state.port}`,
478
+ stop: () => {
479
+ if (stopPromise)
480
+ return stopPromise;
481
+ stopPromise = new Promise((resolve, reject) => {
482
+ const timer = setTimeout(resolve, 2_000);
483
+ timer.unref();
484
+ server.close((error) => {
485
+ clearTimeout(timer);
486
+ if (error)
487
+ reject(error);
488
+ else
489
+ resolve();
490
+ });
491
+ server.closeAllConnections();
492
+ });
493
+ return stopPromise;
494
+ },
495
+ };
496
+ }
497
+ const HOST_CREDENTIAL_FILE = 'host-credential.json';
498
+ const PENDING_HOST_CREDENTIAL_FILE = 'host-credential.pending.json';
499
+ async function writeHostedCredentialFile(destination, hostToken, hostAgentToken, password) {
500
+ const temp = `${destination}.tmp-${process.pid}`;
501
+ const credential = {
502
+ schemaVersion: 2,
503
+ hostAgentToken,
504
+ encryptedHostToken: await encryptExport({ hostToken }, password),
505
+ };
506
+ await fs.writeFile(temp, JSON.stringify(credential, null, 2), { encoding: 'utf8', mode: 0o600 });
507
+ await fs.rename(temp, destination);
508
+ await fs.chmod(destination, 0o600).catch(() => { });
509
+ }
510
+ export async function writeHostedWorkroomCredential(roomDir, hostToken, hostAgentToken, password) {
511
+ await writeHostedCredentialFile(path.join(roomDir, HOST_CREDENTIAL_FILE), hostToken, hostAgentToken, password);
512
+ }
513
+ export async function prepareHostedWorkroomCredentialRotation(roomDir, hostToken, hostAgentToken, password) {
514
+ await writeHostedCredentialFile(path.join(roomDir, PENDING_HOST_CREDENTIAL_FILE), hostToken, hostAgentToken, password);
515
+ }
516
+ export async function commitHostedWorkroomCredentialRotation(roomDir) {
517
+ const destination = path.join(roomDir, HOST_CREDENTIAL_FILE);
518
+ await fs.rename(path.join(roomDir, PENDING_HOST_CREDENTIAL_FILE), destination);
519
+ await fs.chmod(destination, 0o600).catch(() => { });
520
+ }
521
+ export async function discardHostedWorkroomCredentialRotation(roomDir) {
522
+ await fs.unlink(path.join(roomDir, PENDING_HOST_CREDENTIAL_FILE)).catch((error) => {
523
+ if (!(typeof error === 'object' && error !== null && 'code' in error && error.code === 'ENOENT'))
524
+ throw error;
525
+ });
526
+ }
527
+ export async function startHostedWorkroom(input) {
528
+ assertLocalInterface(input.address);
529
+ if (!Number.isInteger(input.port) || input.port < 1 || input.port > 65_535)
530
+ throw new WorkroomValidationError('Port must be between 1 and 65535.');
531
+ const roomId = input.roomId ?? `room-${randomUUID().replace(/-/g, '')}`;
532
+ if (!/^room-[a-f0-9]{32}$/.test(roomId))
533
+ throw new WorkroomValidationError('Invalid Workroom ID.');
534
+ const roomDir = path.join(input.homeDir, 'workrooms', roomId);
535
+ await fs.mkdir(roomDir, { recursive: true, mode: 0o700 });
536
+ const pems = await generate([{ name: 'commonName', value: 'NexusFlow Workroom' }], {
537
+ keyType: 'ec',
538
+ curve: 'P-256',
539
+ algorithm: 'sha256',
540
+ notAfterDate: new Date(Date.now() + 365 * 24 * 60 * 60 * 1000),
541
+ extensions: [
542
+ { name: 'basicConstraints', cA: false, critical: true },
543
+ { name: 'keyUsage', digitalSignature: true, keyAgreement: true, critical: true },
544
+ { name: 'extKeyUsage', serverAuth: true },
545
+ { name: 'subjectAltName', altNames: [{ type: 7, ip: input.address }] },
546
+ ],
547
+ });
548
+ const fingerprint = normalizeFingerprint(new X509Certificate(pems.cert).fingerprint256);
549
+ await Promise.all([
550
+ fs.writeFile(path.join(roomDir, 'certificate.pem'), pems.cert, { encoding: 'utf8', mode: 0o600 }),
551
+ fs.writeFile(path.join(roomDir, 'private-key.pem'), pems.private, { encoding: 'utf8', mode: 0o600 }),
552
+ ]);
553
+ const { state, hostToken, hostAgentToken } = await createInitialWorkroomState({
554
+ roomId,
555
+ name: input.name,
556
+ workspaceId: input.workspaceId,
557
+ address: input.address,
558
+ port: input.port,
559
+ certificateFingerprint: fingerprint,
560
+ password: input.password,
561
+ hostDisplayName: input.hostDisplayName,
562
+ bundle: input.bundle,
563
+ documents: input.documents,
564
+ });
565
+ const store = new WorkroomSqliteStore(roomDir);
566
+ await store.initialize(state);
567
+ await writeHostedWorkroomCredential(roomDir, hostToken, hostAgentToken, input.password);
568
+ const service = new WorkroomService(store);
569
+ const server = await listenWorkroom(service, input.address, input.port, pems.private, pems.cert);
570
+ return hostedResult(state, roomDir, service, server, hostToken, hostAgentToken);
571
+ }
572
+ async function readSmallImportMarker(markerPath) {
573
+ const maximumBytes = 16 * 1024;
574
+ const handle = await fs.open(markerPath, 'r');
575
+ try {
576
+ const stat = await assertFileHandleMatchesPath(handle, markerPath);
577
+ if (stat.size > BigInt(maximumBytes))
578
+ return {};
579
+ const bytes = await readFileHandleAtMost(handle, maximumBytes + 1);
580
+ if (bytes.length > maximumBytes)
581
+ return {};
582
+ const parsed = JSON.parse(bytes.toString('utf8'));
583
+ return typeof parsed === 'object' && parsed !== null ? parsed : {};
584
+ }
585
+ catch {
586
+ return {};
587
+ }
588
+ finally {
589
+ await handle.close().catch(() => { });
590
+ }
591
+ }
592
+ export async function listQuarantinedWorkrooms(homeDir) {
593
+ const root = path.join(homeDir, 'workrooms');
594
+ const result = [];
595
+ for (const entry of await fs.readdir(root, { withFileTypes: true }).catch(() => [])) {
596
+ if (!entry.isDirectory() || !/^room-[a-f0-9]{32}$/.test(entry.name))
597
+ continue;
598
+ const roomDir = path.join(root, entry.name);
599
+ let status;
600
+ let markerPath;
601
+ for (const [marker, markerStatus] of [
602
+ ['import-failed.json', 'failed'],
603
+ ['import-in-progress.json', 'in-progress'],
604
+ ]) {
605
+ try {
606
+ await fs.access(path.join(roomDir, marker));
607
+ status = markerStatus;
608
+ markerPath = path.join(roomDir, marker);
609
+ break;
610
+ }
611
+ catch { }
612
+ }
613
+ if (!status || !markerPath)
614
+ continue;
615
+ const marker = await readSmallImportMarker(markerPath).catch(() => ({}));
616
+ result.push({
617
+ roomId: entry.name,
618
+ status,
619
+ name: typeof marker.name === 'string' ? marker.name.slice(0, 160) : undefined,
620
+ workspaceId: typeof marker.workspaceId === 'string' ? marker.workspaceId.slice(0, 255) : undefined,
621
+ recordedAt: typeof marker.failedAt === 'string'
622
+ ? marker.failedAt
623
+ : typeof marker.startedAt === 'string' ? marker.startedAt : undefined,
624
+ });
625
+ }
626
+ return result.sort((left, right) => (right.recordedAt ?? '').localeCompare(left.recordedAt ?? ''));
627
+ }
628
+ export async function discardQuarantinedWorkroom(homeDir, roomId) {
629
+ if (!/^room-[a-f0-9]{32}$/.test(roomId))
630
+ throw new WorkroomValidationError('Invalid quarantined Workroom ID.');
631
+ const root = path.resolve(homeDir, 'workrooms');
632
+ const roomDir = path.resolve(root, roomId);
633
+ if (path.dirname(roomDir) !== root)
634
+ throw new WorkroomValidationError('Invalid quarantined Workroom ID.');
635
+ const stat = await fs.lstat(roomDir).catch(() => undefined);
636
+ if (!stat?.isDirectory() || stat.isSymbolicLink())
637
+ throw new WorkroomValidationError('Quarantined Workroom not found.');
638
+ let quarantined = false;
639
+ for (const marker of ['import-in-progress.json', 'import-failed.json']) {
640
+ try {
641
+ await fs.access(path.join(roomDir, marker));
642
+ quarantined = true;
643
+ }
644
+ catch { }
645
+ }
646
+ if (!quarantined)
647
+ throw new WorkroomValidationError('Only a quarantined failed import can be discarded.');
648
+ await fs.rm(roomDir, { recursive: true });
649
+ }
650
+ export async function listPausedWorkrooms(homeDir) {
651
+ const root = path.join(homeDir, 'workrooms');
652
+ const result = [];
653
+ for (const entry of await fs.readdir(root, { withFileTypes: true }).catch(() => [])) {
654
+ if (!entry.isDirectory() || !/^room-[a-f0-9]{32}$/.test(entry.name))
655
+ continue;
656
+ try {
657
+ let quarantined = false;
658
+ for (const marker of ['import-in-progress.json', 'import-failed.json']) {
659
+ try {
660
+ await fs.access(path.join(root, entry.name, marker));
661
+ quarantined = true;
662
+ }
663
+ catch { }
664
+ }
665
+ if (quarantined)
666
+ continue;
667
+ const state = await new WorkroomSqliteStore(path.join(root, entry.name)).read();
668
+ await Promise.all([
669
+ fs.access(path.join(root, entry.name, 'certificate.pem')),
670
+ fs.access(path.join(root, entry.name, 'private-key.pem')),
671
+ fs.access(path.join(root, entry.name, 'host-credential.json')),
672
+ ]);
673
+ result.push({
674
+ roomId: state.roomId,
675
+ name: state.name,
676
+ workspaceId: state.workspaceId,
677
+ address: state.address,
678
+ port: state.port,
679
+ createdAt: state.createdAt,
680
+ });
681
+ }
682
+ catch { }
683
+ }
684
+ return result.sort((left, right) => right.createdAt.localeCompare(left.createdAt));
685
+ }
686
+ export async function resumeHostedWorkroom(homeDir, roomId, password) {
687
+ if (!/^room-[a-f0-9]{32}$/.test(roomId))
688
+ throw new WorkroomValidationError('Invalid paused Workroom ID.');
689
+ const roomDir = path.join(homeDir, 'workrooms', roomId);
690
+ for (const marker of ['import-in-progress.json', 'import-failed.json']) {
691
+ try {
692
+ await fs.access(path.join(roomDir, marker));
693
+ throw new WorkroomValidationError('This Workroom is quarantined because its import did not complete.');
694
+ }
695
+ catch (error) {
696
+ if (error instanceof WorkroomValidationError)
697
+ throw error;
698
+ if (!(typeof error === 'object' && error !== null && 'code' in error && error.code === 'ENOENT'))
699
+ throw error;
700
+ }
701
+ }
702
+ const store = new WorkroomSqliteStore(roomDir);
703
+ const state = await store.read();
704
+ if (!(await verifyPassword(password, state.password))) {
705
+ throw new WorkroomAuthorizationError('The Workroom password is incorrect or its host credential is invalid.');
706
+ }
707
+ await store.migrateLegacy();
708
+ await store.pruneUnreferencedPackages();
709
+ assertLocalInterface(state.address);
710
+ const [cert, key, credentialRaw, pendingCredentialRaw] = await Promise.all([
711
+ fs.readFile(path.join(roomDir, 'certificate.pem'), 'utf8'),
712
+ fs.readFile(path.join(roomDir, 'private-key.pem'), 'utf8'),
713
+ fs.readFile(path.join(roomDir, HOST_CREDENTIAL_FILE), 'utf8').catch(() => undefined),
714
+ fs.readFile(path.join(roomDir, PENDING_HOST_CREDENTIAL_FILE), 'utf8').catch(() => undefined),
715
+ ]);
716
+ const service = new WorkroomService(store);
717
+ let selected;
718
+ for (const candidate of [
719
+ pendingCredentialRaw ? { raw: pendingCredentialRaw, pending: true } : undefined,
720
+ credentialRaw ? { raw: credentialRaw, pending: false } : undefined,
721
+ ]) {
722
+ if (!candidate)
723
+ continue;
724
+ try {
725
+ const credential = JSON.parse(candidate.raw);
726
+ if (credential.schemaVersion !== 2 || typeof credential.hostAgentToken !== 'string' || !credential.hostAgentToken || !credential.encryptedHostToken)
727
+ continue;
728
+ const decrypted = await decryptExport(credential.encryptedHostToken, password);
729
+ if (typeof decrypted.hostToken !== 'string')
730
+ continue;
731
+ await service.snapshot(decrypted.hostToken);
732
+ selected = { hostToken: decrypted.hostToken, hostAgentToken: credential.hostAgentToken, pending: candidate.pending };
733
+ break;
734
+ }
735
+ catch { }
736
+ }
737
+ if (!selected) {
738
+ throw new WorkroomAuthorizationError('The Workroom password is incorrect or its host credential is invalid.');
739
+ }
740
+ if (selected.pending)
741
+ await commitHostedWorkroomCredentialRotation(roomDir);
742
+ else if (pendingCredentialRaw)
743
+ await discardHostedWorkroomCredentialRotation(roomDir).catch(() => { });
744
+ const server = await listenWorkroom(service, state.address, state.port, key, cert);
745
+ return hostedResult(state, roomDir, service, server, selected.hostToken, selected.hostAgentToken);
746
+ }
747
+ //# sourceMappingURL=host.js.map