@mrpatronz/nexusflow 2.9.0 → 2.10.1

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 (744) hide show
  1. package/README.md +177 -113
  2. package/desktop/assets/icon.png +0 -0
  3. package/dist/agent/AcpCliAdapter.d.ts +2 -0
  4. package/dist/agent/AcpCliAdapter.d.ts.map +1 -1
  5. package/dist/agent/AcpCliAdapter.js +50 -4
  6. package/dist/agent/AcpCliAdapter.js.map +1 -1
  7. package/dist/agent/AntigravityCliAdapter.d.ts +44 -2
  8. package/dist/agent/AntigravityCliAdapter.d.ts.map +1 -1
  9. package/dist/agent/AntigravityCliAdapter.js +363 -16
  10. package/dist/agent/AntigravityCliAdapter.js.map +1 -1
  11. package/dist/agent/ClaudeCliAdapter.d.ts +5 -2
  12. package/dist/agent/ClaudeCliAdapter.d.ts.map +1 -1
  13. package/dist/agent/ClaudeCliAdapter.js +43 -14
  14. package/dist/agent/ClaudeCliAdapter.js.map +1 -1
  15. package/dist/agent/ClaudeSdkAdapter.d.ts +1 -0
  16. package/dist/agent/ClaudeSdkAdapter.d.ts.map +1 -1
  17. package/dist/agent/ClaudeSdkAdapter.js +38 -11
  18. package/dist/agent/ClaudeSdkAdapter.js.map +1 -1
  19. package/dist/agent/CliAdapterBase.d.ts +2 -0
  20. package/dist/agent/CliAdapterBase.d.ts.map +1 -1
  21. package/dist/agent/CliAdapterBase.js +12 -1
  22. package/dist/agent/CliAdapterBase.js.map +1 -1
  23. package/dist/agent/CodexCliAdapter.d.ts +1 -1
  24. package/dist/agent/CodexCliAdapter.d.ts.map +1 -1
  25. package/dist/agent/CodexCliAdapter.js +5 -4
  26. package/dist/agent/CodexCliAdapter.js.map +1 -1
  27. package/dist/agent/CodexSdkAdapter.d.ts.map +1 -1
  28. package/dist/agent/CodexSdkAdapter.js +4 -1
  29. package/dist/agent/CodexSdkAdapter.js.map +1 -1
  30. package/dist/agent/CopilotAcpAdapter.d.ts.map +1 -1
  31. package/dist/agent/CopilotAcpAdapter.js +2 -2
  32. package/dist/agent/CopilotAcpAdapter.js.map +1 -1
  33. package/dist/agent/ProviderRegistry.d.ts +8 -1
  34. package/dist/agent/ProviderRegistry.d.ts.map +1 -1
  35. package/dist/agent/ProviderRegistry.js.map +1 -1
  36. package/dist/agent/TurnSessionManager.d.ts +65 -0
  37. package/dist/agent/TurnSessionManager.d.ts.map +1 -0
  38. package/dist/agent/TurnSessionManager.js +330 -0
  39. package/dist/agent/TurnSessionManager.js.map +1 -0
  40. package/dist/agent/adapters.d.ts.map +1 -1
  41. package/dist/agent/adapters.js +23 -6
  42. package/dist/agent/adapters.js.map +1 -1
  43. package/dist/agent/cliAvailability.d.ts +2 -5
  44. package/dist/agent/cliAvailability.d.ts.map +1 -1
  45. package/dist/agent/cliAvailability.js +18 -41
  46. package/dist/agent/cliAvailability.js.map +1 -1
  47. package/dist/agent/mcp-config.d.ts +0 -5
  48. package/dist/agent/mcp-config.d.ts.map +1 -1
  49. package/dist/agent/mcp-config.js +2 -1
  50. package/dist/agent/mcp-config.js.map +1 -1
  51. package/dist/agent/models.d.ts +13 -0
  52. package/dist/agent/models.d.ts.map +1 -1
  53. package/dist/agent/models.js +262 -8
  54. package/dist/agent/models.js.map +1 -1
  55. package/dist/agent/nativeTools.d.ts.map +1 -1
  56. package/dist/agent/nativeTools.js +1 -0
  57. package/dist/agent/nativeTools.js.map +1 -1
  58. package/dist/agent/orchestrator.d.ts.map +1 -1
  59. package/dist/agent/orchestrator.js +3 -2
  60. package/dist/agent/orchestrator.js.map +1 -1
  61. package/dist/agent/session.d.ts +6 -0
  62. package/dist/agent/session.d.ts.map +1 -1
  63. package/dist/agent/session.js +8 -0
  64. package/dist/agent/session.js.map +1 -1
  65. package/dist/analyzers/detect-deps.js +16 -1
  66. package/dist/analyzers/detect-deps.js.map +1 -1
  67. package/dist/analyzers/run-analyzer.d.ts.map +1 -1
  68. package/dist/analyzers/run-analyzer.js.map +1 -1
  69. package/dist/commands/adapter.d.ts.map +1 -1
  70. package/dist/commands/adapter.js +15 -14
  71. package/dist/commands/adapter.js.map +1 -1
  72. package/dist/commands/add-repo.d.ts.map +1 -1
  73. package/dist/commands/add-repo.js +6 -5
  74. package/dist/commands/add-repo.js.map +1 -1
  75. package/dist/commands/commit.js +6 -8
  76. package/dist/commands/commit.js.map +1 -1
  77. package/dist/commands/config.d.ts.map +1 -1
  78. package/dist/commands/config.js +2 -1
  79. package/dist/commands/config.js.map +1 -1
  80. package/dist/commands/create.d.ts +4 -4
  81. package/dist/commands/create.d.ts.map +1 -1
  82. package/dist/commands/create.js +48 -7
  83. package/dist/commands/create.js.map +1 -1
  84. package/dist/commands/desktop.d.ts +46 -3
  85. package/dist/commands/desktop.d.ts.map +1 -1
  86. package/dist/commands/desktop.js +343 -33
  87. package/dist/commands/desktop.js.map +1 -1
  88. package/dist/commands/diff.d.ts.map +1 -1
  89. package/dist/commands/diff.js +3 -2
  90. package/dist/commands/diff.js.map +1 -1
  91. package/dist/commands/doctor.d.ts.map +1 -1
  92. package/dist/commands/doctor.js +3 -2
  93. package/dist/commands/doctor.js.map +1 -1
  94. package/dist/commands/finish.js +2 -1
  95. package/dist/commands/finish.js.map +1 -1
  96. package/dist/commands/handoff.d.ts.map +1 -1
  97. package/dist/commands/handoff.js +12 -12
  98. package/dist/commands/handoff.js.map +1 -1
  99. package/dist/commands/init.d.ts +2 -2
  100. package/dist/commands/init.d.ts.map +1 -1
  101. package/dist/commands/init.js +8 -7
  102. package/dist/commands/init.js.map +1 -1
  103. package/dist/commands/isolate.d.ts.map +1 -1
  104. package/dist/commands/isolate.js +2 -1
  105. package/dist/commands/isolate.js.map +1 -1
  106. package/dist/commands/knowledge.d.ts.map +1 -1
  107. package/dist/commands/knowledge.js +3 -2
  108. package/dist/commands/knowledge.js.map +1 -1
  109. package/dist/commands/list.d.ts.map +1 -1
  110. package/dist/commands/list.js +3 -2
  111. package/dist/commands/list.js.map +1 -1
  112. package/dist/commands/logs.js +3 -3
  113. package/dist/commands/logs.js.map +1 -1
  114. package/dist/commands/mcp.d.ts +1 -2
  115. package/dist/commands/mcp.d.ts.map +1 -1
  116. package/dist/commands/mcp.js +19 -12
  117. package/dist/commands/mcp.js.map +1 -1
  118. package/dist/commands/migrate.d.ts +12 -0
  119. package/dist/commands/migrate.d.ts.map +1 -0
  120. package/dist/commands/migrate.js +128 -0
  121. package/dist/commands/migrate.js.map +1 -0
  122. package/dist/commands/open.d.ts.map +1 -1
  123. package/dist/commands/open.js +2 -1
  124. package/dist/commands/open.js.map +1 -1
  125. package/dist/commands/progress.d.ts.map +1 -1
  126. package/dist/commands/progress.js +2 -1
  127. package/dist/commands/progress.js.map +1 -1
  128. package/dist/commands/project.d.ts.map +1 -1
  129. package/dist/commands/project.js +7 -6
  130. package/dist/commands/project.js.map +1 -1
  131. package/dist/commands/refresh.d.ts.map +1 -1
  132. package/dist/commands/refresh.js +8 -11
  133. package/dist/commands/refresh.js.map +1 -1
  134. package/dist/commands/remove.d.ts.map +1 -1
  135. package/dist/commands/remove.js +2 -1
  136. package/dist/commands/remove.js.map +1 -1
  137. package/dist/commands/schedule.js +16 -18
  138. package/dist/commands/schedule.js.map +1 -1
  139. package/dist/commands/start.d.ts.map +1 -1
  140. package/dist/commands/start.js +9 -8
  141. package/dist/commands/start.js.map +1 -1
  142. package/dist/commands/status.d.ts.map +1 -1
  143. package/dist/commands/status.js +2 -1
  144. package/dist/commands/status.js.map +1 -1
  145. package/dist/commands/stop.d.ts.map +1 -1
  146. package/dist/commands/stop.js +2 -1
  147. package/dist/commands/stop.js.map +1 -1
  148. package/dist/commands/strategy.d.ts.map +1 -1
  149. package/dist/commands/strategy.js +6 -5
  150. package/dist/commands/strategy.js.map +1 -1
  151. package/dist/commands/sync.js +8 -10
  152. package/dist/commands/sync.js.map +1 -1
  153. package/dist/commands/tui.d.ts.map +1 -1
  154. package/dist/commands/tui.js +11 -10
  155. package/dist/commands/tui.js.map +1 -1
  156. package/dist/commands/ui.d.ts.map +1 -1
  157. package/dist/commands/ui.js +4 -3
  158. package/dist/commands/ui.js.map +1 -1
  159. package/dist/core/adapters/local-storage.d.ts +3 -1
  160. package/dist/core/adapters/local-storage.d.ts.map +1 -1
  161. package/dist/core/adapters/local-storage.js +62 -4
  162. package/dist/core/adapters/local-storage.js.map +1 -1
  163. package/dist/core/analysis-cache.d.ts.map +1 -1
  164. package/dist/core/analysis-cache.js +8 -7
  165. package/dist/core/analysis-cache.js.map +1 -1
  166. package/dist/core/brand-config.d.ts +261 -0
  167. package/dist/core/brand-config.d.ts.map +1 -0
  168. package/dist/core/brand-config.js +514 -0
  169. package/dist/core/brand-config.js.map +1 -0
  170. package/dist/core/config.d.ts +1 -1
  171. package/dist/core/config.d.ts.map +1 -1
  172. package/dist/core/config.js +18 -8
  173. package/dist/core/config.js.map +1 -1
  174. package/dist/core/constants.d.ts +88 -0
  175. package/dist/core/constants.d.ts.map +1 -0
  176. package/dist/core/constants.js +103 -0
  177. package/dist/core/constants.js.map +1 -0
  178. package/dist/core/doctor.d.ts.map +1 -1
  179. package/dist/core/doctor.js +11 -3
  180. package/dist/core/doctor.js.map +1 -1
  181. package/dist/core/generation-lock.d.ts +2 -2
  182. package/dist/core/generation-lock.d.ts.map +1 -1
  183. package/dist/core/generation-lock.js +49 -22
  184. package/dist/core/generation-lock.js.map +1 -1
  185. package/dist/core/knowledge.d.ts +19 -0
  186. package/dist/core/knowledge.d.ts.map +1 -1
  187. package/dist/core/knowledge.js +150 -24
  188. package/dist/core/knowledge.js.map +1 -1
  189. package/dist/core/migrate.d.ts +53 -0
  190. package/dist/core/migrate.d.ts.map +1 -0
  191. package/dist/core/migrate.js +607 -0
  192. package/dist/core/migrate.js.map +1 -0
  193. package/dist/core/new-repo.js +1 -1
  194. package/dist/core/new-repo.js.map +1 -1
  195. package/dist/core/projects.d.ts.map +1 -1
  196. package/dist/core/projects.js +13 -4
  197. package/dist/core/projects.js.map +1 -1
  198. package/dist/core/refresh.d.ts.map +1 -1
  199. package/dist/core/refresh.js +6 -4
  200. package/dist/core/refresh.js.map +1 -1
  201. package/dist/core/scheduler.d.ts +1 -1
  202. package/dist/core/scheduler.d.ts.map +1 -1
  203. package/dist/core/scheduler.js +11 -9
  204. package/dist/core/scheduler.js.map +1 -1
  205. package/dist/core/sync.js +1 -1
  206. package/dist/core/sync.js.map +1 -1
  207. package/dist/core/workspace-git.d.ts.map +1 -1
  208. package/dist/core/workspace-git.js +34 -10
  209. package/dist/core/workspace-git.js.map +1 -1
  210. package/dist/core/workspace-state.d.ts +4 -0
  211. package/dist/core/workspace-state.d.ts.map +1 -1
  212. package/dist/core/workspace-state.js +8 -8
  213. package/dist/core/workspace-state.js.map +1 -1
  214. package/dist/core/workspace.d.ts +13 -5
  215. package/dist/core/workspace.d.ts.map +1 -1
  216. package/dist/core/workspace.js +83 -34
  217. package/dist/core/workspace.js.map +1 -1
  218. package/dist/core/worktree.d.ts +10 -4
  219. package/dist/core/worktree.d.ts.map +1 -1
  220. package/dist/core/worktree.js +34 -47
  221. package/dist/core/worktree.js.map +1 -1
  222. package/dist/desktop-server.js +6 -3
  223. package/dist/desktop-server.js.map +1 -1
  224. package/dist/generators/base.d.ts.map +1 -1
  225. package/dist/generators/base.js +6 -5
  226. package/dist/generators/base.js.map +1 -1
  227. package/dist/generators/claude.d.ts.map +1 -1
  228. package/dist/generators/claude.js +2 -1
  229. package/dist/generators/claude.js.map +1 -1
  230. package/dist/generators/cursor.d.ts +1 -1
  231. package/dist/generators/cursor.d.ts.map +1 -1
  232. package/dist/generators/cursor.js +9 -4
  233. package/dist/generators/cursor.js.map +1 -1
  234. package/dist/generators/index.d.ts +4 -8
  235. package/dist/generators/index.d.ts.map +1 -1
  236. package/dist/generators/index.js +34 -69
  237. package/dist/generators/index.js.map +1 -1
  238. package/dist/generators/plan-generator.d.ts.map +1 -1
  239. package/dist/generators/plan-generator.js +20 -11
  240. package/dist/generators/plan-generator.js.map +1 -1
  241. package/dist/generators/skills-generator.d.ts.map +1 -1
  242. package/dist/generators/skills-generator.js +26 -11
  243. package/dist/generators/skills-generator.js.map +1 -1
  244. package/dist/gui/app_logo.png +0 -0
  245. package/dist/gui/assets/AgentsPage-DbivhmK0.js +3 -0
  246. package/dist/gui/assets/DashboardPage-D50Qrm3e.js +1 -0
  247. package/dist/gui/assets/GettingStartedPage-1MOTng3B.js +1 -0
  248. package/dist/gui/assets/NullStore-tdPen1kp.js +1 -0
  249. package/dist/gui/assets/ProjectsPage-srKgf7VN.js +1 -0
  250. package/dist/gui/assets/ScaffoldRepoInline-CP0yn5mw.js +1 -0
  251. package/dist/gui/assets/SettingsPage-DWmrLV8o.js +1 -0
  252. package/dist/gui/assets/SkillsPage-CKjTXdrd.js +6 -0
  253. package/dist/gui/assets/StartWorkPage-BCUnJ9k8.js +1 -0
  254. package/dist/gui/assets/{StrategiesPage-C36TZgDX.js → StrategiesPage-CdCbbIu-.js} +2 -2
  255. package/dist/gui/assets/WorkroomsPage-BcT-mGtT.js +4 -0
  256. package/dist/gui/assets/WorkspacesPage-CYFCm-7_.js +2 -0
  257. package/dist/gui/assets/alert-QnMXzwpU.js +1 -0
  258. package/dist/gui/assets/alert-dialog-u7qgb9Hq.js +1 -0
  259. package/dist/gui/assets/badge-DwXvB44H.js +1 -0
  260. package/dist/gui/assets/brand-hHByyyzq.js +1 -0
  261. package/dist/gui/assets/button-CREn1mup.js +1 -0
  262. package/dist/gui/assets/card-yrg6ov8B.js +1 -0
  263. package/dist/gui/assets/chevron-down-B_Mwbim8.js +1 -0
  264. package/dist/gui/assets/chunk-BV7QT456-DfUBKG-z.js +3 -0
  265. package/dist/gui/assets/{circle-plus-lmU1yNJd.js → circle-plus--zM3-3r3.js} +1 -1
  266. package/dist/gui/assets/{code-xml-jFAa3-TT.js → code-xml-DH-38Tt7.js} +1 -1
  267. package/dist/gui/assets/{git-branch-Cfj9D8yW.js → git-branch-Ce0I2663.js} +1 -1
  268. package/dist/gui/assets/index-3tD_IeyQ.js +55 -0
  269. package/dist/gui/assets/index-CK5YRfPV.css +2 -0
  270. package/dist/gui/assets/label-DC730X8s.js +1 -0
  271. package/dist/gui/assets/layers-j_brOuoa.js +1 -0
  272. package/dist/gui/assets/shield-check-Dd1Yv3l2.js +1 -0
  273. package/dist/gui/assets/square-check-big-BSIiYXPI.js +1 -0
  274. package/dist/gui/assets/tabs-BrHKp5bD.js +1 -0
  275. package/dist/gui/assets/{trash-2-CtR35_eF.js → trash-2-CMdv3eD3.js} +1 -1
  276. package/dist/gui/assets/useAriaLabelledBy-C4zV-1Ra.js +1 -0
  277. package/dist/gui/assets/{vsc-DFh0-53h.js → vsc-D80c4gBT.js} +1 -1
  278. package/dist/gui/favicon-aurora.svg +8 -0
  279. package/dist/gui/favicon.ico +0 -0
  280. package/dist/gui/favicon.svg +8 -1
  281. package/dist/gui/index.html +18 -12
  282. package/dist/harness/claude.d.ts.map +1 -1
  283. package/dist/harness/claude.js +97 -7
  284. package/dist/harness/claude.js.map +1 -1
  285. package/dist/harness/codex.d.ts +1 -0
  286. package/dist/harness/codex.d.ts.map +1 -1
  287. package/dist/harness/codex.js +51 -34
  288. package/dist/harness/codex.js.map +1 -1
  289. package/dist/index.js +57 -27
  290. package/dist/index.js.map +1 -1
  291. package/dist/mcp/server.d.ts +12 -1
  292. package/dist/mcp/server.d.ts.map +1 -1
  293. package/dist/mcp/server.js +24 -6
  294. package/dist/mcp/server.js.map +1 -1
  295. package/dist/mcp/tools.d.ts +4 -2
  296. package/dist/mcp/tools.d.ts.map +1 -1
  297. package/dist/mcp/tools.js +372 -17
  298. package/dist/mcp/tools.js.map +1 -1
  299. package/dist/orchestration/detect.d.ts.map +1 -1
  300. package/dist/orchestration/detect.js +12 -5
  301. package/dist/orchestration/detect.js.map +1 -1
  302. package/dist/orchestration/log-tail.js +17 -17
  303. package/dist/orchestration/log-tail.js.map +1 -1
  304. package/dist/orchestration/runner.d.ts +1 -1
  305. package/dist/orchestration/runner.d.ts.map +1 -1
  306. package/dist/orchestration/runner.js +41 -18
  307. package/dist/orchestration/runner.js.map +1 -1
  308. package/dist/resources/agents-catalog.d.ts +3 -1
  309. package/dist/resources/agents-catalog.d.ts.map +1 -1
  310. package/dist/resources/agents-catalog.js +12 -6
  311. package/dist/resources/agents-catalog.js.map +1 -1
  312. package/dist/resources/contracts.d.ts +7 -0
  313. package/dist/resources/contracts.d.ts.map +1 -1
  314. package/dist/resources/contracts.js +8 -1
  315. package/dist/resources/contracts.js.map +1 -1
  316. package/dist/resources/fs-safety.d.ts +7 -1
  317. package/dist/resources/fs-safety.d.ts.map +1 -1
  318. package/dist/resources/fs-safety.js +44 -1
  319. package/dist/resources/fs-safety.js.map +1 -1
  320. package/dist/resources/materializer.d.ts +1 -0
  321. package/dist/resources/materializer.d.ts.map +1 -1
  322. package/dist/resources/materializer.js +48 -17
  323. package/dist/resources/materializer.js.map +1 -1
  324. package/dist/resources/service.d.ts.map +1 -1
  325. package/dist/resources/service.js +3 -2
  326. package/dist/resources/service.js.map +1 -1
  327. package/dist/server.d.ts +2 -19
  328. package/dist/server.d.ts.map +1 -1
  329. package/dist/server.js +1294 -348
  330. package/dist/server.js.map +1 -1
  331. package/dist/static-resources/workflows/cost-aware-sol-luna.md +95 -0
  332. package/dist/storage/db.d.ts +94 -0
  333. package/dist/storage/db.d.ts.map +1 -0
  334. package/dist/storage/db.js +609 -0
  335. package/dist/storage/db.js.map +1 -0
  336. package/dist/types.d.ts +19 -0
  337. package/dist/types.d.ts.map +1 -1
  338. package/dist/utils/detect-ai.d.ts.map +1 -1
  339. package/dist/utils/detect-ai.js +1 -3
  340. package/dist/utils/detect-ai.js.map +1 -1
  341. package/dist/utils/multi-git.d.ts +0 -8
  342. package/dist/utils/multi-git.d.ts.map +1 -1
  343. package/dist/utils/multi-git.js +12 -4
  344. package/dist/utils/multi-git.js.map +1 -1
  345. package/dist/utils/pr.d.ts.map +1 -1
  346. package/dist/utils/pr.js +10 -5
  347. package/dist/utils/pr.js.map +1 -1
  348. package/dist/utils/repo-freshness.d.ts +106 -0
  349. package/dist/utils/repo-freshness.d.ts.map +1 -0
  350. package/dist/utils/repo-freshness.js +405 -0
  351. package/dist/utils/repo-freshness.js.map +1 -0
  352. package/dist/utils/resolve-workspace.d.ts +1 -1
  353. package/dist/utils/resolve-workspace.d.ts.map +1 -1
  354. package/dist/utils/resolve-workspace.js +10 -3
  355. package/dist/utils/resolve-workspace.js.map +1 -1
  356. package/dist/utils/session-finder.d.ts +12 -1
  357. package/dist/utils/session-finder.d.ts.map +1 -1
  358. package/dist/utils/session-finder.js +206 -8
  359. package/dist/utils/session-finder.js.map +1 -1
  360. package/dist/utils/skills-catalog.d.ts +5 -1
  361. package/dist/utils/skills-catalog.d.ts.map +1 -1
  362. package/dist/utils/skills-catalog.js +131 -75
  363. package/dist/utils/skills-catalog.js.map +1 -1
  364. package/dist/utils/terminal-launch.d.ts +8 -2
  365. package/dist/utils/terminal-launch.d.ts.map +1 -1
  366. package/dist/utils/terminal-launch.js +88 -19
  367. package/dist/utils/terminal-launch.js.map +1 -1
  368. package/dist/utils/update-check.d.ts +4 -1
  369. package/dist/utils/update-check.d.ts.map +1 -1
  370. package/dist/utils/update-check.js +66 -19
  371. package/dist/utils/update-check.js.map +1 -1
  372. package/dist/utils/user-paths.d.ts +23 -0
  373. package/dist/utils/user-paths.d.ts.map +1 -0
  374. package/dist/utils/user-paths.js +126 -0
  375. package/dist/utils/user-paths.js.map +1 -0
  376. package/dist/utils/workflows.d.ts +4 -1
  377. package/dist/utils/workflows.d.ts.map +1 -1
  378. package/dist/utils/workflows.js +51 -21
  379. package/dist/utils/workflows.js.map +1 -1
  380. package/dist/workrooms/client.d.ts +54 -0
  381. package/dist/workrooms/client.d.ts.map +1 -0
  382. package/dist/workrooms/client.js +191 -0
  383. package/dist/workrooms/client.js.map +1 -0
  384. package/dist/workrooms/contracts.d.ts +579 -0
  385. package/dist/workrooms/contracts.d.ts.map +1 -0
  386. package/dist/workrooms/contracts.js +231 -0
  387. package/dist/workrooms/contracts.js.map +1 -0
  388. package/dist/workrooms/crypto.d.ts +30 -0
  389. package/dist/workrooms/crypto.d.ts.map +1 -0
  390. package/dist/workrooms/crypto.js +72 -0
  391. package/dist/workrooms/crypto.js.map +1 -0
  392. package/dist/workrooms/host.d.ts +61 -0
  393. package/dist/workrooms/host.d.ts.map +1 -0
  394. package/dist/workrooms/host.js +747 -0
  395. package/dist/workrooms/host.js.map +1 -0
  396. package/dist/workrooms/local-resources.d.ts +26 -0
  397. package/dist/workrooms/local-resources.d.ts.map +1 -0
  398. package/dist/workrooms/local-resources.js +367 -0
  399. package/dist/workrooms/local-resources.js.map +1 -0
  400. package/dist/workrooms/manager.d.ts +228 -0
  401. package/dist/workrooms/manager.d.ts.map +1 -0
  402. package/dist/workrooms/manager.js +768 -0
  403. package/dist/workrooms/manager.js.map +1 -0
  404. package/dist/workrooms/milestones.d.ts +42 -0
  405. package/dist/workrooms/milestones.d.ts.map +1 -0
  406. package/dist/workrooms/milestones.js +94 -0
  407. package/dist/workrooms/milestones.js.map +1 -0
  408. package/dist/workrooms/portable.d.ts +21 -0
  409. package/dist/workrooms/portable.d.ts.map +1 -0
  410. package/dist/workrooms/portable.js +201 -0
  411. package/dist/workrooms/portable.js.map +1 -0
  412. package/dist/workrooms/resource-package.d.ts +7 -0
  413. package/dist/workrooms/resource-package.d.ts.map +1 -0
  414. package/dist/workrooms/resource-package.js +260 -0
  415. package/dist/workrooms/resource-package.js.map +1 -0
  416. package/dist/workrooms/service.d.ts +92 -0
  417. package/dist/workrooms/service.d.ts.map +1 -0
  418. package/dist/workrooms/service.js +788 -0
  419. package/dist/workrooms/service.js.map +1 -0
  420. package/dist/workrooms/sqlite-store.d.ts +31 -0
  421. package/dist/workrooms/sqlite-store.d.ts.map +1 -0
  422. package/dist/workrooms/sqlite-store.js +511 -0
  423. package/dist/workrooms/sqlite-store.js.map +1 -0
  424. package/dist/workrooms/store.d.ts +542 -0
  425. package/dist/workrooms/store.d.ts.map +1 -0
  426. package/dist/workrooms/store.js +71 -0
  427. package/dist/workrooms/store.js.map +1 -0
  428. package/package.json +21 -11
  429. package/resources/workflows/cost-aware-sol-luna.md +95 -0
  430. package/dist/agent/AcpCliAdapter.test.d.ts +0 -2
  431. package/dist/agent/AcpCliAdapter.test.d.ts.map +0 -1
  432. package/dist/agent/AcpCliAdapter.test.js +0 -235
  433. package/dist/agent/AcpCliAdapter.test.js.map +0 -1
  434. package/dist/agent/AntigravityCliAdapter.test.d.ts +0 -2
  435. package/dist/agent/AntigravityCliAdapter.test.d.ts.map +0 -1
  436. package/dist/agent/AntigravityCliAdapter.test.js +0 -222
  437. package/dist/agent/AntigravityCliAdapter.test.js.map +0 -1
  438. package/dist/agent/ClaudeCliAdapter.test.d.ts +0 -2
  439. package/dist/agent/ClaudeCliAdapter.test.d.ts.map +0 -1
  440. package/dist/agent/ClaudeCliAdapter.test.js +0 -320
  441. package/dist/agent/ClaudeCliAdapter.test.js.map +0 -1
  442. package/dist/agent/ClaudeSdkAdapter.test.d.ts +0 -2
  443. package/dist/agent/ClaudeSdkAdapter.test.d.ts.map +0 -1
  444. package/dist/agent/ClaudeSdkAdapter.test.js +0 -155
  445. package/dist/agent/ClaudeSdkAdapter.test.js.map +0 -1
  446. package/dist/agent/CliAdapterBase.test.d.ts +0 -2
  447. package/dist/agent/CliAdapterBase.test.d.ts.map +0 -1
  448. package/dist/agent/CliAdapterBase.test.js +0 -240
  449. package/dist/agent/CliAdapterBase.test.js.map +0 -1
  450. package/dist/agent/CodexCliAdapter.test.d.ts +0 -2
  451. package/dist/agent/CodexCliAdapter.test.d.ts.map +0 -1
  452. package/dist/agent/CodexCliAdapter.test.js +0 -331
  453. package/dist/agent/CodexCliAdapter.test.js.map +0 -1
  454. package/dist/agent/CodexSdkAdapter.test.d.ts +0 -2
  455. package/dist/agent/CodexSdkAdapter.test.d.ts.map +0 -1
  456. package/dist/agent/CodexSdkAdapter.test.js +0 -76
  457. package/dist/agent/CodexSdkAdapter.test.js.map +0 -1
  458. package/dist/agent/ProviderRegistry.test.d.ts +0 -2
  459. package/dist/agent/ProviderRegistry.test.d.ts.map +0 -1
  460. package/dist/agent/ProviderRegistry.test.js +0 -129
  461. package/dist/agent/ProviderRegistry.test.js.map +0 -1
  462. package/dist/agent/adapters.test.d.ts +0 -2
  463. package/dist/agent/adapters.test.d.ts.map +0 -1
  464. package/dist/agent/adapters.test.js +0 -71
  465. package/dist/agent/adapters.test.js.map +0 -1
  466. package/dist/agent/cliAvailability.test.d.ts +0 -2
  467. package/dist/agent/cliAvailability.test.d.ts.map +0 -1
  468. package/dist/agent/cliAvailability.test.js +0 -217
  469. package/dist/agent/cliAvailability.test.js.map +0 -1
  470. package/dist/agent/mcp-config.test.d.ts +0 -2
  471. package/dist/agent/mcp-config.test.d.ts.map +0 -1
  472. package/dist/agent/mcp-config.test.js +0 -22
  473. package/dist/agent/mcp-config.test.js.map +0 -1
  474. package/dist/agent/models.test.d.ts +0 -2
  475. package/dist/agent/models.test.d.ts.map +0 -1
  476. package/dist/agent/models.test.js +0 -40
  477. package/dist/agent/models.test.js.map +0 -1
  478. package/dist/agent/nativeAgent.test.d.ts +0 -2
  479. package/dist/agent/nativeAgent.test.d.ts.map +0 -1
  480. package/dist/agent/nativeAgent.test.js +0 -35
  481. package/dist/agent/nativeAgent.test.js.map +0 -1
  482. package/dist/agent/nativeTools.test.d.ts +0 -2
  483. package/dist/agent/nativeTools.test.d.ts.map +0 -1
  484. package/dist/agent/nativeTools.test.js +0 -67
  485. package/dist/agent/nativeTools.test.js.map +0 -1
  486. package/dist/agent/orchestrator.test.d.ts +0 -2
  487. package/dist/agent/orchestrator.test.d.ts.map +0 -1
  488. package/dist/agent/orchestrator.test.js +0 -284
  489. package/dist/agent/orchestrator.test.js.map +0 -1
  490. package/dist/agent/session.test.d.ts +0 -2
  491. package/dist/agent/session.test.d.ts.map +0 -1
  492. package/dist/agent/session.test.js +0 -74
  493. package/dist/agent/session.test.js.map +0 -1
  494. package/dist/agent/smoke-chat.test.d.ts +0 -2
  495. package/dist/agent/smoke-chat.test.d.ts.map +0 -1
  496. package/dist/agent/smoke-chat.test.js +0 -166
  497. package/dist/agent/smoke-chat.test.js.map +0 -1
  498. package/dist/commands/add-repo.test.d.ts +0 -2
  499. package/dist/commands/add-repo.test.d.ts.map +0 -1
  500. package/dist/commands/add-repo.test.js +0 -30
  501. package/dist/commands/add-repo.test.js.map +0 -1
  502. package/dist/commands/commands.test.d.ts +0 -2
  503. package/dist/commands/commands.test.d.ts.map +0 -1
  504. package/dist/commands/commands.test.js +0 -156
  505. package/dist/commands/commands.test.js.map +0 -1
  506. package/dist/commands/commit.test.d.ts +0 -2
  507. package/dist/commands/commit.test.d.ts.map +0 -1
  508. package/dist/commands/commit.test.js +0 -54
  509. package/dist/commands/commit.test.js.map +0 -1
  510. package/dist/commands/isolate.test.d.ts +0 -2
  511. package/dist/commands/isolate.test.d.ts.map +0 -1
  512. package/dist/commands/isolate.test.js +0 -59
  513. package/dist/commands/isolate.test.js.map +0 -1
  514. package/dist/commands/knowledge.test.d.ts +0 -2
  515. package/dist/commands/knowledge.test.d.ts.map +0 -1
  516. package/dist/commands/knowledge.test.js +0 -90
  517. package/dist/commands/knowledge.test.js.map +0 -1
  518. package/dist/commands/status.test.d.ts +0 -2
  519. package/dist/commands/status.test.d.ts.map +0 -1
  520. package/dist/commands/status.test.js +0 -31
  521. package/dist/commands/status.test.js.map +0 -1
  522. package/dist/commands/ui.test.d.ts +0 -2
  523. package/dist/commands/ui.test.d.ts.map +0 -1
  524. package/dist/commands/ui.test.js +0 -58
  525. package/dist/commands/ui.test.js.map +0 -1
  526. package/dist/core/adapters/storage.test.d.ts +0 -2
  527. package/dist/core/adapters/storage.test.d.ts.map +0 -1
  528. package/dist/core/adapters/storage.test.js +0 -65
  529. package/dist/core/adapters/storage.test.js.map +0 -1
  530. package/dist/core/analysis-cache.test.d.ts +0 -2
  531. package/dist/core/analysis-cache.test.d.ts.map +0 -1
  532. package/dist/core/analysis-cache.test.js +0 -163
  533. package/dist/core/analysis-cache.test.js.map +0 -1
  534. package/dist/core/config.test.d.ts +0 -2
  535. package/dist/core/config.test.d.ts.map +0 -1
  536. package/dist/core/config.test.js +0 -90
  537. package/dist/core/config.test.js.map +0 -1
  538. package/dist/core/finish.test.d.ts +0 -2
  539. package/dist/core/finish.test.d.ts.map +0 -1
  540. package/dist/core/finish.test.js +0 -110
  541. package/dist/core/finish.test.js.map +0 -1
  542. package/dist/core/generation-lock.test.d.ts +0 -2
  543. package/dist/core/generation-lock.test.d.ts.map +0 -1
  544. package/dist/core/generation-lock.test.js +0 -134
  545. package/dist/core/generation-lock.test.js.map +0 -1
  546. package/dist/core/isolate.test.d.ts +0 -2
  547. package/dist/core/isolate.test.d.ts.map +0 -1
  548. package/dist/core/isolate.test.js +0 -320
  549. package/dist/core/isolate.test.js.map +0 -1
  550. package/dist/core/knowledge.test.d.ts +0 -2
  551. package/dist/core/knowledge.test.d.ts.map +0 -1
  552. package/dist/core/knowledge.test.js +0 -287
  553. package/dist/core/knowledge.test.js.map +0 -1
  554. package/dist/core/locks.test.d.ts +0 -2
  555. package/dist/core/locks.test.d.ts.map +0 -1
  556. package/dist/core/locks.test.js +0 -143
  557. package/dist/core/locks.test.js.map +0 -1
  558. package/dist/core/new-repo.test.d.ts +0 -2
  559. package/dist/core/new-repo.test.d.ts.map +0 -1
  560. package/dist/core/new-repo.test.js +0 -78
  561. package/dist/core/new-repo.test.js.map +0 -1
  562. package/dist/core/progress.test.d.ts +0 -2
  563. package/dist/core/progress.test.d.ts.map +0 -1
  564. package/dist/core/progress.test.js +0 -52
  565. package/dist/core/progress.test.js.map +0 -1
  566. package/dist/core/projects.test.d.ts +0 -2
  567. package/dist/core/projects.test.d.ts.map +0 -1
  568. package/dist/core/projects.test.js +0 -165
  569. package/dist/core/projects.test.js.map +0 -1
  570. package/dist/core/refresh.test.d.ts +0 -2
  571. package/dist/core/refresh.test.d.ts.map +0 -1
  572. package/dist/core/refresh.test.js +0 -93
  573. package/dist/core/refresh.test.js.map +0 -1
  574. package/dist/core/scanner.test.d.ts +0 -2
  575. package/dist/core/scanner.test.d.ts.map +0 -1
  576. package/dist/core/scanner.test.js +0 -53
  577. package/dist/core/scanner.test.js.map +0 -1
  578. package/dist/core/scheduler.test.d.ts +0 -2
  579. package/dist/core/scheduler.test.d.ts.map +0 -1
  580. package/dist/core/scheduler.test.js +0 -169
  581. package/dist/core/scheduler.test.js.map +0 -1
  582. package/dist/core/sync.test.d.ts +0 -2
  583. package/dist/core/sync.test.d.ts.map +0 -1
  584. package/dist/core/sync.test.js +0 -128
  585. package/dist/core/sync.test.js.map +0 -1
  586. package/dist/core/workspace-git.test.d.ts +0 -2
  587. package/dist/core/workspace-git.test.d.ts.map +0 -1
  588. package/dist/core/workspace-git.test.js +0 -52
  589. package/dist/core/workspace-git.test.js.map +0 -1
  590. package/dist/core/workspace-skills-workflow.integration.test.d.ts +0 -2
  591. package/dist/core/workspace-skills-workflow.integration.test.d.ts.map +0 -1
  592. package/dist/core/workspace-skills-workflow.integration.test.js +0 -177
  593. package/dist/core/workspace-skills-workflow.integration.test.js.map +0 -1
  594. package/dist/core/workspace-state.test.d.ts +0 -2
  595. package/dist/core/workspace-state.test.d.ts.map +0 -1
  596. package/dist/core/workspace-state.test.js +0 -84
  597. package/dist/core/workspace-state.test.js.map +0 -1
  598. package/dist/core/workspace.create.test.d.ts +0 -2
  599. package/dist/core/workspace.create.test.d.ts.map +0 -1
  600. package/dist/core/workspace.create.test.js +0 -224
  601. package/dist/core/workspace.create.test.js.map +0 -1
  602. package/dist/core/workspace.test.d.ts +0 -2
  603. package/dist/core/workspace.test.d.ts.map +0 -1
  604. package/dist/core/workspace.test.js +0 -53
  605. package/dist/core/workspace.test.js.map +0 -1
  606. package/dist/core/worktree.test.d.ts +0 -2
  607. package/dist/core/worktree.test.d.ts.map +0 -1
  608. package/dist/core/worktree.test.js +0 -153
  609. package/dist/core/worktree.test.js.map +0 -1
  610. package/dist/generators/base.test.d.ts +0 -2
  611. package/dist/generators/base.test.d.ts.map +0 -1
  612. package/dist/generators/base.test.js +0 -287
  613. package/dist/generators/base.test.js.map +0 -1
  614. package/dist/generators/knowledge-migration.test.d.ts +0 -2
  615. package/dist/generators/knowledge-migration.test.d.ts.map +0 -1
  616. package/dist/generators/knowledge-migration.test.js +0 -22
  617. package/dist/generators/knowledge-migration.test.js.map +0 -1
  618. package/dist/generators/plan-generator.test.d.ts +0 -2
  619. package/dist/generators/plan-generator.test.d.ts.map +0 -1
  620. package/dist/generators/plan-generator.test.js +0 -220
  621. package/dist/generators/plan-generator.test.js.map +0 -1
  622. package/dist/generators/skills-generator.test.d.ts +0 -2
  623. package/dist/generators/skills-generator.test.d.ts.map +0 -1
  624. package/dist/generators/skills-generator.test.js +0 -79
  625. package/dist/generators/skills-generator.test.js.map +0 -1
  626. package/dist/gui/assets/AgentsPage-B4fx43rd.js +0 -3
  627. package/dist/gui/assets/CSPContext-DBUu9tE0.js +0 -1
  628. package/dist/gui/assets/DashboardPage-DH52G8IG.js +0 -1
  629. package/dist/gui/assets/GettingStartedPage-BlTrQhvi.js +0 -1
  630. package/dist/gui/assets/ProjectsPage-BPVSLPXv.js +0 -1
  631. package/dist/gui/assets/ScaffoldRepoInline-ywcpq9PX.js +0 -1
  632. package/dist/gui/assets/SettingsPage-RQr8SalV.js +0 -1
  633. package/dist/gui/assets/SkillsPage-CYoSRrwx.js +0 -6
  634. package/dist/gui/assets/StartWorkPage-DBKK4lFi.js +0 -1
  635. package/dist/gui/assets/WorkspacesPage-DxEONvSq.js +0 -6
  636. package/dist/gui/assets/alert-dialog-CQAX2yRx.js +0 -1
  637. package/dist/gui/assets/badge-CAohJGj6.js +0 -1
  638. package/dist/gui/assets/bot-C2HWrAft.js +0 -1
  639. package/dist/gui/assets/button-BDDZnIHx.js +0 -1
  640. package/dist/gui/assets/card-BKXzd_5L.js +0 -1
  641. package/dist/gui/assets/chevron-down-qTL8HPug.js +0 -1
  642. package/dist/gui/assets/cpu-Cdwd84Jz.js +0 -1
  643. package/dist/gui/assets/empty-BdlgbifD.js +0 -1
  644. package/dist/gui/assets/index-BF6pre6G.css +0 -2
  645. package/dist/gui/assets/index-C_rwnBzF.js +0 -52
  646. package/dist/gui/assets/isElementDisabled-uy_EOitH.js +0 -1
  647. package/dist/gui/assets/label-CG5exjag.js +0 -1
  648. package/dist/gui/assets/square-DlIYnlSq.js +0 -1
  649. package/dist/gui/assets/textarea-ByfoCb54.js +0 -1
  650. package/dist/gui/assets/useAriaLabelledBy-ClesgjMe.js +0 -1
  651. package/dist/gui/assets/useValueChanged-DeYvGnKs.js +0 -1
  652. package/dist/gui/assets/zap-CWG_Lvki.js +0 -1
  653. package/dist/harness/contract.test.d.ts +0 -2
  654. package/dist/harness/contract.test.d.ts.map +0 -1
  655. package/dist/harness/contract.test.js +0 -426
  656. package/dist/harness/contract.test.js.map +0 -1
  657. package/dist/harness/harness.test.d.ts +0 -2
  658. package/dist/harness/harness.test.d.ts.map +0 -1
  659. package/dist/harness/harness.test.js +0 -215
  660. package/dist/harness/harness.test.js.map +0 -1
  661. package/dist/mcp/tools.test.d.ts +0 -2
  662. package/dist/mcp/tools.test.d.ts.map +0 -1
  663. package/dist/mcp/tools.test.js +0 -194
  664. package/dist/mcp/tools.test.js.map +0 -1
  665. package/dist/orchestration/log-tail.test.d.ts +0 -2
  666. package/dist/orchestration/log-tail.test.d.ts.map +0 -1
  667. package/dist/orchestration/log-tail.test.js +0 -72
  668. package/dist/orchestration/log-tail.test.js.map +0 -1
  669. package/dist/orchestration/orchestrator.test.d.ts +0 -2
  670. package/dist/orchestration/orchestrator.test.d.ts.map +0 -1
  671. package/dist/orchestration/orchestrator.test.js +0 -85
  672. package/dist/orchestration/orchestrator.test.js.map +0 -1
  673. package/dist/orchestration/runner.test.d.ts +0 -2
  674. package/dist/orchestration/runner.test.d.ts.map +0 -1
  675. package/dist/orchestration/runner.test.js +0 -233
  676. package/dist/orchestration/runner.test.js.map +0 -1
  677. package/dist/resources/agents-catalog.test.d.ts +0 -2
  678. package/dist/resources/agents-catalog.test.d.ts.map +0 -1
  679. package/dist/resources/agents-catalog.test.js +0 -50
  680. package/dist/resources/agents-catalog.test.js.map +0 -1
  681. package/dist/resources/codex-agent.test.d.ts +0 -2
  682. package/dist/resources/codex-agent.test.d.ts.map +0 -1
  683. package/dist/resources/codex-agent.test.js +0 -27
  684. package/dist/resources/codex-agent.test.js.map +0 -1
  685. package/dist/resources/materializer.test.d.ts +0 -2
  686. package/dist/resources/materializer.test.d.ts.map +0 -1
  687. package/dist/resources/materializer.test.js +0 -149
  688. package/dist/resources/materializer.test.js.map +0 -1
  689. package/dist/resources/service.test.d.ts +0 -2
  690. package/dist/resources/service.test.d.ts.map +0 -1
  691. package/dist/resources/service.test.js +0 -58
  692. package/dist/resources/service.test.js.map +0 -1
  693. package/dist/server.test.d.ts +0 -2
  694. package/dist/server.test.d.ts.map +0 -1
  695. package/dist/server.test.js +0 -1697
  696. package/dist/server.test.js.map +0 -1
  697. package/dist/utils/detect-ai.test.d.ts +0 -2
  698. package/dist/utils/detect-ai.test.d.ts.map +0 -1
  699. package/dist/utils/detect-ai.test.js +0 -70
  700. package/dist/utils/detect-ai.test.js.map +0 -1
  701. package/dist/utils/detect-editors.test.d.ts +0 -2
  702. package/dist/utils/detect-editors.test.d.ts.map +0 -1
  703. package/dist/utils/detect-editors.test.js +0 -85
  704. package/dist/utils/detect-editors.test.js.map +0 -1
  705. package/dist/utils/git.test.d.ts +0 -2
  706. package/dist/utils/git.test.d.ts.map +0 -1
  707. package/dist/utils/git.test.js +0 -125
  708. package/dist/utils/git.test.js.map +0 -1
  709. package/dist/utils/multi-git.test.d.ts +0 -2
  710. package/dist/utils/multi-git.test.d.ts.map +0 -1
  711. package/dist/utils/multi-git.test.js +0 -330
  712. package/dist/utils/multi-git.test.js.map +0 -1
  713. package/dist/utils/pr.test.d.ts +0 -2
  714. package/dist/utils/pr.test.d.ts.map +0 -1
  715. package/dist/utils/pr.test.js +0 -47
  716. package/dist/utils/pr.test.js.map +0 -1
  717. package/dist/utils/session-finder.test.d.ts +0 -2
  718. package/dist/utils/session-finder.test.d.ts.map +0 -1
  719. package/dist/utils/session-finder.test.js +0 -304
  720. package/dist/utils/session-finder.test.js.map +0 -1
  721. package/dist/utils/skills-catalog.test.d.ts +0 -2
  722. package/dist/utils/skills-catalog.test.d.ts.map +0 -1
  723. package/dist/utils/skills-catalog.test.js +0 -281
  724. package/dist/utils/skills-catalog.test.js.map +0 -1
  725. package/dist/utils/system-scanner.test.d.ts +0 -2
  726. package/dist/utils/system-scanner.test.d.ts.map +0 -1
  727. package/dist/utils/system-scanner.test.js +0 -73
  728. package/dist/utils/system-scanner.test.js.map +0 -1
  729. package/dist/utils/terminal-launch.test.d.ts +0 -2
  730. package/dist/utils/terminal-launch.test.d.ts.map +0 -1
  731. package/dist/utils/terminal-launch.test.js +0 -117
  732. package/dist/utils/terminal-launch.test.js.map +0 -1
  733. package/dist/utils/update-check.test.d.ts +0 -2
  734. package/dist/utils/update-check.test.d.ts.map +0 -1
  735. package/dist/utils/update-check.test.js +0 -30
  736. package/dist/utils/update-check.test.js.map +0 -1
  737. package/dist/utils/workflows.test.d.ts +0 -2
  738. package/dist/utils/workflows.test.d.ts.map +0 -1
  739. package/dist/utils/workflows.test.js +0 -86
  740. package/dist/utils/workflows.test.js.map +0 -1
  741. package/dist/utils/workspace-launch.test.d.ts +0 -2
  742. package/dist/utils/workspace-launch.test.d.ts.map +0 -1
  743. package/dist/utils/workspace-launch.test.js +0 -128
  744. package/dist/utils/workspace-launch.test.js.map +0 -1
@@ -0,0 +1,768 @@
1
+ import { createHash, randomUUID } from 'node:crypto';
2
+ import * as fs from 'node:fs/promises';
3
+ import * as path from 'node:path';
4
+ import { getConfigDir } from '../core/config.js';
5
+ import { acquireLock } from '../core/locks.js';
6
+ import { loadFeatureConfig } from '../core/workspace.js';
7
+ import { WORKROOM_MAX_DOCUMENT_BYTES, WORKROOM_MAX_RESOURCE_CATALOG_JSON_BYTES, WORKROOM_MAX_WORKFLOW_EVIDENCE_BYTES, WorkroomAuthorizationError, WorkroomValidationError, } from './contracts.js';
8
+ import { PinnedWorkroomClient, formatWorkroomInvite, parseWorkroomInvite } from './client.js';
9
+ import { decryptExport, encryptExport, randomToken, tokenDigest } from './crypto.js';
10
+ import { commitHostedWorkroomCredentialRotation, discardQuarantinedWorkroom, discardHostedWorkroomCredentialRotation, listQuarantinedWorkrooms, listPausedWorkrooms, prepareHostedWorkroomCredentialRotation, resumeHostedWorkroom, startHostedWorkroom, } from './host.js';
11
+ import { applyCachedResource, cacheResourcePackage, digestLocalResourceDefinition, getLocalResourceDefinition, listLocalShareableResources, packageLocalResource, } from './local-resources.js';
12
+ import { buildPublishedHandoff } from './portable.js';
13
+ import { parseResourceDefinition, validateResourcePackage } from './resource-package.js';
14
+ import { workroomExportPayloadSchema } from './store.js';
15
+ export function validateWorkroomExportPayload(input) {
16
+ const parsed = workroomExportPayloadSchema.safeParse(input);
17
+ if (!parsed.success)
18
+ throw new WorkroomValidationError('The Workroom export payload does not match schema version 1.');
19
+ const payload = parsed.data;
20
+ for (const name of ['plan', 'decisions', 'handoff']) {
21
+ const document = payload.room.documents[name];
22
+ if (document.name !== name || Buffer.byteLength(document.content, 'utf8') > WORKROOM_MAX_DOCUMENT_BYTES) {
23
+ throw new WorkroomValidationError(`The exported ${name} document is invalid or too large.`);
24
+ }
25
+ if (document.history.some((revision) => revision.revision >= document.revision || Buffer.byteLength(revision.content, 'utf8') > WORKROOM_MAX_DOCUMENT_BYTES)) {
26
+ throw new WorkroomValidationError(`The exported ${name} document history is invalid.`);
27
+ }
28
+ }
29
+ for (let index = 1; index < payload.room.activity.length; index += 1) {
30
+ if (payload.room.activity[index].sequence <= payload.room.activity[index - 1].sequence) {
31
+ throw new WorkroomValidationError('The Workroom export activity sequence is invalid.');
32
+ }
33
+ }
34
+ const workflowEvidenceBytes = payload.room.workflowProgress?.steps.reduce((total, step) => total + Buffer.byteLength(step.evidence ?? '', 'utf8'), 0) ?? 0;
35
+ if (workflowEvidenceBytes > WORKROOM_MAX_WORKFLOW_EVIDENCE_BYTES) {
36
+ throw new WorkroomValidationError('The Workroom export workflow evidence exceeds the 512 KiB room limit.');
37
+ }
38
+ const packages = payload.packages.map((pkg) => validateResourcePackage(pkg));
39
+ const packageStorageBytes = packages.reduce((total, pkg) => total + Buffer.byteLength(`${JSON.stringify(pkg, null, 2)}\n`, 'utf8'), 0);
40
+ if (packageStorageBytes > WORKROOM_MAX_RESOURCE_CATALOG_JSON_BYTES) {
41
+ throw new WorkroomValidationError('The Workroom export exceeds the 40 MiB shared resource storage limit.');
42
+ }
43
+ const keys = new Set();
44
+ for (const pkg of packages) {
45
+ const key = `${pkg.manifest.kind}:${pkg.manifest.id}:${pkg.manifest.version}`;
46
+ if (keys.has(key))
47
+ throw new WorkroomValidationError('The Workroom export contains duplicate immutable resource versions.');
48
+ keys.add(key);
49
+ }
50
+ const catalog = new Map(payload.room.resources.map((resource) => [resource.digest, resource]));
51
+ if (catalog.size !== packages.length || payload.room.resources.some((resource) => resource.quarantinedAt)) {
52
+ throw new WorkroomValidationError('The Workroom export resource catalog does not match its packages.');
53
+ }
54
+ for (const pkg of packages) {
55
+ const resource = catalog.get(pkg.manifest.digest);
56
+ if (!resource || resource.kind !== pkg.manifest.kind || resource.id !== pkg.manifest.id || resource.version !== pkg.manifest.version) {
57
+ throw new WorkroomValidationError('The Workroom export resource catalog does not match its packages.');
58
+ }
59
+ }
60
+ return { payload, packages };
61
+ }
62
+ function activeCredentialPath(workspaceId, homeDir = getConfigDir()) {
63
+ const safePrefix = workspaceId.replace(/[^a-zA-Z0-9._-]/g, '-').slice(0, 64) || 'workspace';
64
+ const identity = createHash('sha256').update(workspaceId, 'utf8').digest('hex').slice(0, 16);
65
+ return path.join(homeDir, 'workrooms', 'active', `${safePrefix}-${identity}.json`);
66
+ }
67
+ function processIsAlive(pid) {
68
+ try {
69
+ process.kill(pid, 0);
70
+ return true;
71
+ }
72
+ catch (error) {
73
+ return typeof error === 'object' && error !== null && 'code' in error && error.code === 'EPERM';
74
+ }
75
+ }
76
+ async function writeActiveCredential(credential, homeDir = getConfigDir()) {
77
+ const destination = activeCredentialPath(credential.workspaceId, homeDir);
78
+ await fs.mkdir(path.dirname(destination), { recursive: true, mode: 0o700 });
79
+ const release = await acquireLock(`${destination}.lock`, {
80
+ staleMs: 60_000,
81
+ timeoutMs: 10_000,
82
+ timeoutMessage: 'Timed out waiting for the active Workroom credential lock.',
83
+ });
84
+ const ownershipId = randomUUID();
85
+ const temp = `${destination}.tmp-${process.pid}-${ownershipId}`;
86
+ try {
87
+ const existing = await fs.readFile(destination, 'utf8')
88
+ .then((raw) => JSON.parse(raw), () => undefined);
89
+ if (existing?.ownerPid && existing.ownershipId && processIsAlive(existing.ownerPid)) {
90
+ throw new WorkroomValidationError('Another running NexusFlow dashboard already owns the Workroom connection for this workspace.');
91
+ }
92
+ await fs.writeFile(temp, JSON.stringify({ ...credential, ownerPid: process.pid, ownershipId }, null, 2), { encoding: 'utf8', mode: 0o600 });
93
+ await fs.rename(temp, destination);
94
+ await fs.chmod(destination, 0o600).catch(() => { });
95
+ return ownershipId;
96
+ }
97
+ catch (error) {
98
+ await fs.unlink(temp).catch(() => { });
99
+ throw error;
100
+ }
101
+ finally {
102
+ await release();
103
+ }
104
+ }
105
+ async function removeOwnedActiveCredential(workspaceId, roomId, ownershipId, homeDir = getConfigDir()) {
106
+ const destination = activeCredentialPath(workspaceId, homeDir);
107
+ const release = await acquireLock(`${destination}.lock`, {
108
+ staleMs: 60_000,
109
+ timeoutMs: 10_000,
110
+ timeoutMessage: 'Timed out waiting for the active Workroom credential lock.',
111
+ });
112
+ try {
113
+ const existing = await fs.readFile(destination, 'utf8')
114
+ .then((raw) => JSON.parse(raw), () => undefined);
115
+ if (existing?.roomId === roomId && existing.ownershipId === ownershipId && existing.ownerPid === process.pid) {
116
+ await fs.unlink(destination).catch(() => { });
117
+ }
118
+ }
119
+ finally {
120
+ await release();
121
+ }
122
+ }
123
+ export async function loadPinnedWorkroomClientForWorkspace(workspaceId) {
124
+ let credential;
125
+ try {
126
+ credential = JSON.parse(await fs.readFile(activeCredentialPath(workspaceId), 'utf8'));
127
+ }
128
+ catch {
129
+ throw new WorkroomValidationError('No active Workroom connection is registered for this workspace.');
130
+ }
131
+ if (credential.schemaVersion !== 1 || credential.workspaceId !== workspaceId || !credential.agentToken) {
132
+ throw new WorkroomValidationError('The active Workroom connection record is invalid.');
133
+ }
134
+ return new PinnedWorkroomClient(credential.url, credential.fingerprint, credential.agentToken);
135
+ }
136
+ export class WorkroomManager {
137
+ homeDir;
138
+ host;
139
+ guest;
140
+ humanSession;
141
+ activeGeneration = 0;
142
+ activeHumanOperations = 0;
143
+ lifecycleState = 'idle';
144
+ passwordRotationInProgress = false;
145
+ shutdownRequested = false;
146
+ stopPromise;
147
+ lifecycleWaiters = new Set();
148
+ credentialOwnership = new Map();
149
+ recoveryFailures = [];
150
+ constructor(homeDir = getConfigDir()) {
151
+ this.homeDir = homeDir;
152
+ }
153
+ hasActiveRoom() {
154
+ return Boolean(this.host || this.guest);
155
+ }
156
+ activeRoomType() {
157
+ if (this.host)
158
+ return 'host';
159
+ if (this.guest)
160
+ return 'guest';
161
+ return undefined;
162
+ }
163
+ activeRoomChanged() {
164
+ this.activeGeneration += 1;
165
+ this.humanSession = undefined;
166
+ }
167
+ signalLifecycleChange() {
168
+ const waiters = [...this.lifecycleWaiters];
169
+ this.lifecycleWaiters.clear();
170
+ for (const resolve of waiters)
171
+ resolve();
172
+ }
173
+ async waitForLifecycleIdle() {
174
+ while (this.lifecycleState !== 'idle' || this.passwordRotationInProgress || this.activeHumanOperations > 0) {
175
+ await new Promise((resolve) => this.lifecycleWaiters.add(resolve));
176
+ }
177
+ }
178
+ beginLifecycle(next) {
179
+ if (this.shutdownRequested && next !== 'stopping') {
180
+ throw new WorkroomValidationError('The Workroom is shutting down.');
181
+ }
182
+ if (this.passwordRotationInProgress) {
183
+ throw new WorkroomValidationError('A Workroom password rotation is already in progress.');
184
+ }
185
+ if (this.lifecycleState !== 'idle') {
186
+ throw new WorkroomValidationError(`A Workroom lifecycle change is already ${this.lifecycleState}.`);
187
+ }
188
+ if (next !== 'stopping' && next !== 'polling' && (this.host || this.guest)) {
189
+ throw new WorkroomValidationError('Stop or leave the active Workroom first.');
190
+ }
191
+ if (next === 'polling' && !this.guest)
192
+ throw new WorkroomValidationError('No pending Workroom join exists.');
193
+ this.lifecycleState = next;
194
+ }
195
+ endLifecycle(expected) {
196
+ if (this.lifecycleState === expected)
197
+ this.lifecycleState = 'idle';
198
+ this.signalLifecycleChange();
199
+ }
200
+ beginHumanSession() {
201
+ if (!this.host && !this.guest)
202
+ throw new WorkroomValidationError('Join or start a Workroom first.');
203
+ if (this.shutdownRequested || this.lifecycleState === 'stopping') {
204
+ throw new WorkroomValidationError('The Workroom is shutting down.');
205
+ }
206
+ const token = randomToken();
207
+ this.humanSession = { digest: tokenDigest(token), generation: this.activeGeneration };
208
+ return token;
209
+ }
210
+ async reclaimHostHumanSession(password) {
211
+ if (!this.host)
212
+ throw new WorkroomValidationError('Guest connections must leave and rejoin after losing local human authority.');
213
+ const cutoff = Date.now() - 60_000;
214
+ this.recoveryFailures = this.recoveryFailures.filter((attempt) => attempt >= cutoff);
215
+ if (this.recoveryFailures.length >= 5) {
216
+ throw new WorkroomValidationError('Too many failed local recovery attempts. Try again in one minute.');
217
+ }
218
+ if (!(await this.host.service.verifyHostRecoveryPassword(password))) {
219
+ this.recoveryFailures.push(Date.now());
220
+ throw new WorkroomAuthorizationError('The Workroom password is incorrect.');
221
+ }
222
+ this.recoveryFailures = [];
223
+ return this.beginHumanSession();
224
+ }
225
+ abandonLockedGuest() {
226
+ if (!this.guest || this.host)
227
+ throw new WorkroomValidationError('Only a locked guest connection can be abandoned without a human session.');
228
+ return this.stopOrLeave();
229
+ }
230
+ assertHumanSession(token) {
231
+ if (!token || !this.humanSession || tokenDigest(token) !== this.humanSession.digest
232
+ || this.humanSession.generation !== this.activeGeneration) {
233
+ throw new WorkroomAuthorizationError('A browser-established Workroom human session is required.');
234
+ }
235
+ return this.humanSession;
236
+ }
237
+ assertHumanAuthority(authority) {
238
+ if (!this.humanSession || authority.digest !== this.humanSession.digest
239
+ || authority.generation !== this.humanSession.generation
240
+ || authority.generation !== this.activeGeneration) {
241
+ throw new WorkroomAuthorizationError('The Workroom changed after this browser operation was authorized.');
242
+ }
243
+ }
244
+ async runWithHumanAuthority(authority, operation) {
245
+ this.assertHumanAuthority(authority);
246
+ if (this.shutdownRequested || this.lifecycleState === 'stopping') {
247
+ throw new WorkroomValidationError('The Workroom is shutting down.');
248
+ }
249
+ this.activeHumanOperations += 1;
250
+ try {
251
+ this.assertHumanAuthority(authority);
252
+ return await operation();
253
+ }
254
+ finally {
255
+ this.activeHumanOperations -= 1;
256
+ this.signalLifecycleChange();
257
+ }
258
+ }
259
+ async startHost(input) {
260
+ this.beginLifecycle('starting');
261
+ try {
262
+ return await this.startHostUnlocked(input);
263
+ }
264
+ finally {
265
+ this.endLifecycle('starting');
266
+ }
267
+ }
268
+ async startHostUnlocked(input) {
269
+ const hosted = await startHostedWorkroom({
270
+ homeDir: this.homeDir,
271
+ name: input.name,
272
+ workspaceId: input.workspaceId,
273
+ address: input.address,
274
+ port: input.port,
275
+ password: input.password,
276
+ hostDisplayName: input.hostDisplayName,
277
+ bundle: input.bundle,
278
+ documents: input.documents,
279
+ });
280
+ this.host = hosted;
281
+ this.activeRoomChanged();
282
+ try {
283
+ const ownershipId = await writeActiveCredential({
284
+ schemaVersion: 1,
285
+ workspaceId: input.workspaceId,
286
+ roomId: hosted.roomId,
287
+ url: hosted.url,
288
+ fingerprint: hosted.certificateFingerprint,
289
+ agentToken: hosted.hostAgentToken,
290
+ }, this.homeDir);
291
+ this.credentialOwnership.set(input.workspaceId, { roomId: hosted.roomId, ownershipId });
292
+ }
293
+ catch (error) {
294
+ this.host = undefined;
295
+ this.activeRoomChanged();
296
+ this.recoveryFailures = [];
297
+ await hosted.stop().catch(() => { });
298
+ throw error;
299
+ }
300
+ return this.status();
301
+ }
302
+ listPaused() {
303
+ return listPausedWorkrooms(this.homeDir);
304
+ }
305
+ listQuarantined() {
306
+ return listQuarantinedWorkrooms(this.homeDir);
307
+ }
308
+ discardQuarantined(roomId) {
309
+ if (this.host || this.guest)
310
+ throw new WorkroomValidationError('Stop or leave the active Workroom before discarding a failed import.');
311
+ return discardQuarantinedWorkroom(this.homeDir, roomId);
312
+ }
313
+ async resumeHost(roomId, password) {
314
+ this.beginLifecycle('resuming');
315
+ try {
316
+ const hosted = await resumeHostedWorkroom(this.homeDir, roomId, password);
317
+ this.host = hosted;
318
+ this.activeRoomChanged();
319
+ const state = await hosted.service.store.read();
320
+ try {
321
+ const ownershipId = await writeActiveCredential({
322
+ schemaVersion: 1,
323
+ workspaceId: state.workspaceId,
324
+ roomId: state.roomId,
325
+ url: hosted.url,
326
+ fingerprint: state.certificateFingerprint,
327
+ agentToken: hosted.hostAgentToken,
328
+ }, this.homeDir);
329
+ this.credentialOwnership.set(state.workspaceId, { roomId: state.roomId, ownershipId });
330
+ }
331
+ catch (error) {
332
+ this.host = undefined;
333
+ this.activeRoomChanged();
334
+ await hosted.stop().catch(() => { });
335
+ throw error;
336
+ }
337
+ return this.status();
338
+ }
339
+ finally {
340
+ this.endLifecycle('resuming');
341
+ }
342
+ }
343
+ stopOrLeave(authority) {
344
+ if (this.stopPromise)
345
+ return this.stopPromise;
346
+ if (authority)
347
+ this.assertHumanAuthority(authority);
348
+ this.shutdownRequested = true;
349
+ const stopPromise = this.stopOrLeaveOnce();
350
+ this.stopPromise = stopPromise;
351
+ return stopPromise;
352
+ }
353
+ async stopOrLeaveOnce() {
354
+ try {
355
+ await this.waitForLifecycleIdle();
356
+ this.beginLifecycle('stopping');
357
+ const host = this.host;
358
+ const workspaceIds = [
359
+ host ? (await host.service.store.read()).workspaceId : undefined,
360
+ this.guest?.effectiveWorkspaceId ?? this.guest?.localWorkspaceId,
361
+ ].filter((value) => Boolean(value));
362
+ const ownedCredentials = workspaceIds.flatMap((workspaceId) => {
363
+ const owned = this.credentialOwnership.get(workspaceId);
364
+ return owned ? [{ workspaceId, ...owned }] : [];
365
+ });
366
+ this.host = undefined;
367
+ this.guest = undefined;
368
+ this.activeRoomChanged();
369
+ if (host)
370
+ await host.stop();
371
+ await Promise.all(ownedCredentials.map((owned) => removeOwnedActiveCredential(owned.workspaceId, owned.roomId, owned.ownershipId, this.homeDir).catch(() => { })));
372
+ for (const workspaceId of workspaceIds)
373
+ this.credentialOwnership.delete(workspaceId);
374
+ }
375
+ finally {
376
+ this.endLifecycle('stopping');
377
+ this.shutdownRequested = false;
378
+ this.stopPromise = undefined;
379
+ this.signalLifecycleChange();
380
+ }
381
+ }
382
+ async status() {
383
+ if (this.host) {
384
+ const snapshot = await this.host.service.snapshot(this.host.hostAgentToken);
385
+ return {
386
+ mode: 'host',
387
+ roomId: this.host.roomId,
388
+ name: snapshot.name,
389
+ url: this.host.url,
390
+ localWorkspaceId: (await this.host.service.store.read()).workspaceId,
391
+ certificateFingerprint: this.host.certificateFingerprint,
392
+ snapshot,
393
+ };
394
+ }
395
+ if (this.guest) {
396
+ let snapshot;
397
+ let connection;
398
+ if (this.guest.status === 'accepted') {
399
+ try {
400
+ snapshot = await this.guest.agentClient.snapshot();
401
+ connection = 'connected';
402
+ }
403
+ catch (error) {
404
+ connection = error instanceof WorkroomAuthorizationError ? 'revoked' : 'disconnected';
405
+ }
406
+ }
407
+ return {
408
+ mode: 'guest',
409
+ roomId: this.guest.invite.roomId,
410
+ name: snapshot?.name,
411
+ url: this.guest.invite.url,
412
+ status: this.guest.status,
413
+ connection,
414
+ memberId: this.guest.memberId,
415
+ localWorkspaceId: this.guest.effectiveWorkspaceId ?? this.guest.localWorkspaceId,
416
+ snapshot,
417
+ };
418
+ }
419
+ return { mode: 'idle' };
420
+ }
421
+ async createInvite() {
422
+ if (!this.host)
423
+ throw new WorkroomValidationError('Only the active host can create invitations.');
424
+ const created = await this.host.service.createInvite(this.host.hostToken);
425
+ return {
426
+ invite: formatWorkroomInvite({
427
+ schemaVersion: 1,
428
+ url: this.host.url,
429
+ roomId: this.host.roomId,
430
+ token: created.token,
431
+ fingerprint: this.host.certificateFingerprint,
432
+ }),
433
+ expiresAt: created.expiresAt,
434
+ };
435
+ }
436
+ async join(inviteText, password, displayName, localWorkspaceId) {
437
+ this.beginLifecycle('joining');
438
+ try {
439
+ const invite = parseWorkroomInvite(inviteText);
440
+ const deviceToken = randomToken();
441
+ const agentToken = randomToken();
442
+ const publicClient = new PinnedWorkroomClient(invite.url, invite.fingerprint);
443
+ const health = await publicClient.health();
444
+ if (health.roomId !== invite.roomId)
445
+ throw new WorkroomAuthorizationError('The invitation does not match this Workroom.');
446
+ const response = await publicClient.requestJoin({
447
+ roomId: invite.roomId,
448
+ inviteToken: invite.token,
449
+ password,
450
+ displayName,
451
+ deviceToken,
452
+ agentToken,
453
+ });
454
+ this.guest = {
455
+ invite,
456
+ displayName: displayName.trim(),
457
+ deviceToken,
458
+ agentToken,
459
+ requestId: response.requestId,
460
+ client: new PinnedWorkroomClient(invite.url, invite.fingerprint, deviceToken),
461
+ agentClient: new PinnedWorkroomClient(invite.url, invite.fingerprint, agentToken),
462
+ localWorkspaceId,
463
+ status: 'pending',
464
+ };
465
+ this.activeRoomChanged();
466
+ return this.status();
467
+ }
468
+ finally {
469
+ this.endLifecycle('joining');
470
+ }
471
+ }
472
+ async pollJoin() {
473
+ this.beginLifecycle('polling');
474
+ try {
475
+ const guest = this.guest;
476
+ const result = await guest.client.joinStatus(guest.requestId, guest.deviceToken);
477
+ guest.status = result.status;
478
+ guest.memberId = result.memberId;
479
+ if (result.status === 'accepted') {
480
+ const snapshot = await guest.agentClient.snapshot();
481
+ guest.effectiveWorkspaceId = guest.localWorkspaceId;
482
+ if (guest.effectiveWorkspaceId) {
483
+ const ownershipId = await writeActiveCredential({
484
+ schemaVersion: 1,
485
+ workspaceId: guest.effectiveWorkspaceId,
486
+ roomId: snapshot.roomId,
487
+ url: guest.invite.url,
488
+ fingerprint: guest.invite.fingerprint,
489
+ agentToken: guest.agentToken,
490
+ memberId: result.memberId,
491
+ }, this.homeDir);
492
+ this.credentialOwnership.set(guest.effectiveWorkspaceId, { roomId: snapshot.roomId, ownershipId });
493
+ }
494
+ }
495
+ return this.status();
496
+ }
497
+ finally {
498
+ this.endLifecycle('polling');
499
+ }
500
+ }
501
+ async decideJoin(requestId, accept) {
502
+ if (!this.host)
503
+ throw new WorkroomValidationError('Only the active host can decide join requests.');
504
+ await this.host.service.decideJoin(this.host.hostToken, requestId, accept);
505
+ }
506
+ async setRole(memberId, role) {
507
+ if (!this.host)
508
+ throw new WorkroomValidationError('Only the active host can change member roles.');
509
+ await this.host.service.setParticipantRole(this.host.hostToken, memberId, role);
510
+ }
511
+ async revokeMember(memberId) {
512
+ if (!this.host)
513
+ throw new WorkroomValidationError('Only the active host can revoke members.');
514
+ await this.host.service.revokeParticipant(this.host.hostToken, memberId);
515
+ }
516
+ async rotatePassword(password, revokeDevices = true) {
517
+ const host = this.host;
518
+ if (!host)
519
+ throw new WorkroomValidationError('Only the active host can rotate the password.');
520
+ if (this.shutdownRequested)
521
+ throw new WorkroomValidationError('The Workroom is shutting down.');
522
+ if (this.lifecycleState !== 'idle')
523
+ throw new WorkroomValidationError(`A Workroom lifecycle change is already ${this.lifecycleState}.`);
524
+ if (this.passwordRotationInProgress)
525
+ throw new WorkroomValidationError('A Workroom password rotation is already in progress.');
526
+ this.passwordRotationInProgress = true;
527
+ let stateRotated = false;
528
+ try {
529
+ await prepareHostedWorkroomCredentialRotation(host.roomDir, host.hostToken, host.hostAgentToken, password);
530
+ await host.service.rotatePassword(host.hostToken, password, revokeDevices);
531
+ stateRotated = true;
532
+ await commitHostedWorkroomCredentialRotation(host.roomDir);
533
+ }
534
+ catch (error) {
535
+ if (!stateRotated)
536
+ await discardHostedWorkroomCredentialRotation(host.roomDir).catch(() => { });
537
+ throw error;
538
+ }
539
+ finally {
540
+ this.passwordRotationInProgress = false;
541
+ this.signalLifecycleChange();
542
+ }
543
+ }
544
+ activeRoom() {
545
+ if (this.host)
546
+ return { roomId: this.host.roomId, service: this.host.service, token: this.host.hostToken };
547
+ if (this.guest?.status === 'accepted')
548
+ return { roomId: this.guest.invite.roomId, token: this.guest.deviceToken, client: this.guest.client };
549
+ throw new WorkroomValidationError('Join or start a Workroom first.');
550
+ }
551
+ async snapshot() {
552
+ if (this.host)
553
+ return this.host.service.snapshot(this.host.hostAgentToken);
554
+ if (this.guest?.status === 'accepted')
555
+ return this.guest.agentClient.snapshot();
556
+ throw new WorkroomValidationError('Join or start a Workroom first.');
557
+ }
558
+ async updateDocument(name, content, expectedRevision) {
559
+ const active = this.activeRoom();
560
+ return active.service
561
+ ? active.service.updateDocument(active.token, name, content, expectedRevision)
562
+ : (await active.client.updateDocument(name, content, expectedRevision)).document;
563
+ }
564
+ async publishHandoff(workspacePath) {
565
+ const feature = await loadFeatureConfig(workspacePath);
566
+ if (!feature)
567
+ throw new WorkroomValidationError('Local workspace not found.');
568
+ const active = this.activeRoom();
569
+ const snapshot = active.service ? await active.service.snapshot(active.token) : await active.client.snapshot();
570
+ const actor = this.host
571
+ ? snapshot.participants.find((participant) => participant.role === 'host')
572
+ : snapshot.participants.find((participant) => participant.id === this.guest?.memberId);
573
+ if (!actor)
574
+ throw new WorkroomAuthorizationError('The active Workroom member could not be identified.');
575
+ const handoff = await buildPublishedHandoff(feature, workspacePath, actor.id);
576
+ return active.service
577
+ ? active.service.publishHandoff(active.token, handoff.markdown, handoff.repos, snapshot.documents.handoff.revision)
578
+ : (await active.client.publishHandoff(handoff.markdown, handoff.repos, snapshot.documents.handoff.revision)).document;
579
+ }
580
+ listLocalResources() {
581
+ return listLocalShareableResources();
582
+ }
583
+ async publishLocalResource(kind, id, version) {
584
+ const active = this.activeRoom();
585
+ const pkg = await packageLocalResource(kind, id, version);
586
+ return active.service
587
+ ? active.service.publishResource(active.token, pkg)
588
+ : (await active.client.publishResource(pkg)).package;
589
+ }
590
+ async downloadResource(digest) {
591
+ const active = this.activeRoom();
592
+ const pkg = active.service
593
+ ? await active.service.getResource(active.token, digest)
594
+ : (await active.client.getResource(digest)).package;
595
+ const existingDefinition = await getLocalResourceDefinition(pkg.manifest.kind, pkg.manifest.id);
596
+ return {
597
+ cachePath: await cacheResourcePackage(active.roomId, pkg),
598
+ preview: {
599
+ manifest: pkg.manifest,
600
+ action: existingDefinition ? 'update' : 'create',
601
+ localDigest: digestLocalResourceDefinition(existingDefinition),
602
+ incomingDefinition: JSON.stringify(parseResourceDefinition(pkg), null, 2),
603
+ existingDefinition: existingDefinition ? JSON.stringify(existingDefinition, null, 2) : undefined,
604
+ files: pkg.files.map((file) => {
605
+ const bytes = Buffer.from(file.contentBase64, 'base64');
606
+ let content;
607
+ let encoding;
608
+ try {
609
+ const decoded = new TextDecoder('utf-8', { fatal: true }).decode(bytes);
610
+ if (/[^\t\n\r\x20-\x7e\u00a0-\uffff]/u.test(decoded))
611
+ throw new Error('binary');
612
+ content = decoded;
613
+ encoding = 'utf8';
614
+ }
615
+ catch {
616
+ content = bytes.toString('base64');
617
+ encoding = 'base64';
618
+ }
619
+ return {
620
+ path: file.path,
621
+ bytes: bytes.length,
622
+ executable: Boolean((file.mode ?? 0) & 0o111),
623
+ encoding,
624
+ content,
625
+ };
626
+ }),
627
+ },
628
+ };
629
+ }
630
+ async applyResource(digest, approvedDigest, approvedLocalDigest) {
631
+ const active = this.activeRoom();
632
+ return applyCachedResource(active.roomId, digest, approvedDigest, approvedLocalDigest);
633
+ }
634
+ async quarantineResource(digest) {
635
+ if (!this.host)
636
+ throw new WorkroomValidationError('Only the active host can quarantine a shared resource version.');
637
+ await this.host.service.quarantineResource(this.host.hostToken, digest);
638
+ }
639
+ async purgeResource(digest) {
640
+ if (!this.host)
641
+ throw new WorkroomValidationError('Only the active host can purge a quarantined shared resource version.');
642
+ await this.host.service.purgeResource(this.host.hostToken, digest);
643
+ }
644
+ async selectWorkflow(workflow, expectedRevision) {
645
+ const active = this.activeRoom();
646
+ if (active.service)
647
+ await active.service.selectWorkflow(active.token, workflow, expectedRevision);
648
+ else
649
+ await active.client.selectWorkflow(workflow, expectedRevision);
650
+ }
651
+ async selectLocalWorkflow(workflowId, version, steps, expectedRevision) {
652
+ if (!this.host)
653
+ throw new WorkroomValidationError('Only the active host can select a shared workflow.');
654
+ const definition = await getLocalResourceDefinition('workflow', workflowId);
655
+ if (!definition || typeof definition.name !== 'string' || typeof definition.description !== 'string' || typeof definition.content !== 'string') {
656
+ throw new WorkroomValidationError('Select an available local workflow.');
657
+ }
658
+ await this.selectWorkflow({
659
+ schemaVersion: 1,
660
+ id: workflowId,
661
+ version,
662
+ name: definition.name,
663
+ description: definition.description,
664
+ markdown: definition.content,
665
+ steps: [...steps],
666
+ dependencies: [],
667
+ }, expectedRevision);
668
+ }
669
+ async transitionWorkflowStep(stepId, status, expectedRevision, evidence) {
670
+ const active = this.activeRoom();
671
+ return active.service
672
+ ? active.service.transitionWorkflowStep(active.token, stepId, status, expectedRevision, evidence)
673
+ : (await active.client.transitionWorkflowStep(stepId, status, expectedRevision, evidence)).step;
674
+ }
675
+ async exportRoom(passphrase) {
676
+ if (!this.host)
677
+ throw new WorkroomValidationError('Only the active host can export the room.');
678
+ if (passphrase.length < 12)
679
+ throw new WorkroomValidationError('Export passphrases must contain at least 12 characters.');
680
+ return encryptExport(await this.host.service.store.createExportPayload(), passphrase);
681
+ }
682
+ async importRoom(envelope, exportPassphrase, host) {
683
+ this.beginLifecycle('importing');
684
+ try {
685
+ return await this.importRoomUnlocked(envelope, exportPassphrase, host);
686
+ }
687
+ finally {
688
+ this.endLifecycle('importing');
689
+ }
690
+ }
691
+ async importRoomUnlocked(envelope, exportPassphrase, host) {
692
+ let decrypted;
693
+ try {
694
+ decrypted = await decryptExport(envelope, exportPassphrase);
695
+ }
696
+ catch {
697
+ throw new WorkroomValidationError('The encrypted Workroom export is invalid or the passphrase is incorrect.');
698
+ }
699
+ const { payload, packages } = validateWorkroomExportPayload(decrypted);
700
+ const roomId = `room-${randomUUID().replace(/-/g, '')}`;
701
+ const roomDir = path.join(this.homeDir, 'workrooms', roomId);
702
+ const importMarker = {
703
+ schemaVersion: 1,
704
+ name: host.name || payload.room.name,
705
+ workspaceId: payload.room.workspaceId,
706
+ };
707
+ await fs.mkdir(roomDir, { recursive: true, mode: 0o700 });
708
+ await fs.writeFile(path.join(roomDir, 'import-in-progress.json'), JSON.stringify({ ...importMarker, startedAt: new Date().toISOString() }), { encoding: 'utf8', mode: 0o600 });
709
+ let importedHost;
710
+ try {
711
+ await this.startHostUnlocked({
712
+ ...host,
713
+ roomId,
714
+ name: host.name || payload.room.name,
715
+ workspaceId: payload.room.workspaceId,
716
+ bundle: payload.room.bundle,
717
+ documents: {
718
+ plan: payload.room.documents.plan.content,
719
+ decisions: payload.room.documents.decisions.content,
720
+ handoff: payload.room.documents.handoff.content,
721
+ },
722
+ });
723
+ importedHost = this.host;
724
+ for (const pkg of packages)
725
+ await importedHost.service.publishResource(importedHost.hostToken, pkg);
726
+ await importedHost.service.store.mutate((state) => {
727
+ const importedActivity = payload.room.activity.slice(-999);
728
+ const sequence = (importedActivity.at(-1)?.sequence ?? 0) + 1;
729
+ const roomCreated = state.activity[0];
730
+ return {
731
+ state: {
732
+ ...state,
733
+ revision: state.revision + 1,
734
+ documents: payload.room.documents,
735
+ workflowProgress: payload.room.workflowProgress,
736
+ activity: roomCreated ? [...importedActivity, {
737
+ ...roomCreated,
738
+ sequence,
739
+ summary: 'Imported encrypted Workroom backup with new room credentials.',
740
+ }] : importedActivity,
741
+ },
742
+ result: undefined,
743
+ };
744
+ });
745
+ await fs.unlink(path.join(roomDir, 'import-in-progress.json'));
746
+ return this.status();
747
+ }
748
+ catch (error) {
749
+ if (this.host) {
750
+ this.host = undefined;
751
+ this.activeRoomChanged();
752
+ }
753
+ await importedHost?.stop().catch(() => { });
754
+ const failureMarkerWritten = await fs.writeFile(path.join(roomDir, 'import-failed.json'), JSON.stringify({ ...importMarker, failedAt: new Date().toISOString() }), { encoding: 'utf8', mode: 0o600 }).then(() => true, () => false);
755
+ if (failureMarkerWritten) {
756
+ await fs.unlink(path.join(roomDir, 'import-in-progress.json')).catch(() => { });
757
+ }
758
+ const owned = this.credentialOwnership.get(payload.room.workspaceId);
759
+ if (owned) {
760
+ await removeOwnedActiveCredential(payload.room.workspaceId, owned.roomId, owned.ownershipId, this.homeDir).catch(() => { });
761
+ this.credentialOwnership.delete(payload.room.workspaceId);
762
+ }
763
+ throw error;
764
+ }
765
+ }
766
+ }
767
+ export const workroomManager = new WorkroomManager();
768
+ //# sourceMappingURL=manager.js.map