atoo-studio 0.0.1 → 0.0.2

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 (408) hide show
  1. package/LICENSE +21 -0
  2. package/README.github.md +322 -0
  3. package/README.md +112 -0
  4. package/README.npm.md +112 -0
  5. package/bin/atoo-studio.js +90 -0
  6. package/dist/src/agents/claude-code-terminal/adapter.d.ts +42 -0
  7. package/dist/src/agents/claude-code-terminal/adapter.js +166 -0
  8. package/dist/src/agents/claude-code-terminal/index.d.ts +13 -0
  9. package/dist/src/agents/claude-code-terminal/index.js +45 -0
  10. package/dist/src/agents/claude-code-terminal/spawner.d.ts +9 -0
  11. package/dist/src/agents/claude-code-terminal/spawner.js +37 -0
  12. package/dist/src/agents/claude-code-terminal-chatro/adapter.d.ts +51 -0
  13. package/dist/src/agents/claude-code-terminal-chatro/adapter.js +301 -0
  14. package/dist/src/agents/claude-code-terminal-chatro/index.d.ts +13 -0
  15. package/dist/src/agents/claude-code-terminal-chatro/index.js +45 -0
  16. package/dist/src/agents/claude-code-terminal-chatro/jsonl-watcher.d.ts +67 -0
  17. package/dist/src/agents/claude-code-terminal-chatro/jsonl-watcher.js +431 -0
  18. package/dist/src/agents/claude-code-terminal-chatro/spawner.d.ts +9 -0
  19. package/dist/src/agents/claude-code-terminal-chatro/spawner.js +37 -0
  20. package/dist/src/agents/codex-terminal/adapter.d.ts +40 -0
  21. package/dist/src/agents/codex-terminal/adapter.js +160 -0
  22. package/dist/src/agents/codex-terminal/index.d.ts +13 -0
  23. package/dist/src/agents/codex-terminal/index.js +47 -0
  24. package/dist/src/agents/codex-terminal/spawner.d.ts +9 -0
  25. package/dist/src/agents/codex-terminal/spawner.js +56 -0
  26. package/dist/src/agents/codex-terminal-chatro/adapter.d.ts +58 -0
  27. package/dist/src/agents/codex-terminal-chatro/adapter.js +266 -0
  28. package/dist/src/agents/codex-terminal-chatro/index.d.ts +13 -0
  29. package/dist/src/agents/codex-terminal-chatro/index.js +50 -0
  30. package/dist/src/agents/codex-terminal-chatro/jsonl-watcher.d.ts +36 -0
  31. package/dist/src/agents/codex-terminal-chatro/jsonl-watcher.js +205 -0
  32. package/dist/src/agents/codex-terminal-chatro/spawner.d.ts +9 -0
  33. package/dist/src/agents/codex-terminal-chatro/spawner.js +57 -0
  34. package/dist/src/agents/lib/chain-builder.d.ts +21 -0
  35. package/dist/src/agents/lib/chain-builder.js +139 -0
  36. package/dist/src/agents/lib/claude/fs-sessions.d.ts +31 -0
  37. package/dist/src/agents/lib/claude/fs-sessions.js +329 -0
  38. package/dist/src/agents/lib/claude/jsonl-writer.d.ts +32 -0
  39. package/dist/src/agents/lib/claude/jsonl-writer.js +342 -0
  40. package/dist/src/agents/lib/claude/workspace-trust.d.ts +1 -0
  41. package/dist/src/agents/lib/claude/workspace-trust.js +29 -0
  42. package/dist/src/agents/lib/codex/fs-sessions.d.ts +34 -0
  43. package/dist/src/agents/lib/codex/fs-sessions.js +255 -0
  44. package/dist/src/agents/lib/codex/jsonl-mapper.d.ts +11 -0
  45. package/dist/src/agents/lib/codex/jsonl-mapper.js +154 -0
  46. package/dist/src/agents/lib/codex/jsonl-writer.d.ts +8 -0
  47. package/dist/src/agents/lib/codex/jsonl-writer.js +440 -0
  48. package/dist/src/agents/lib/fs-tracking.d.ts +36 -0
  49. package/dist/src/agents/lib/fs-tracking.js +109 -0
  50. package/dist/src/agents/lib/pty-activity-tracker.d.ts +37 -0
  51. package/dist/src/agents/lib/pty-activity-tracker.js +105 -0
  52. package/dist/src/agents/lib/session-id-utils.d.ts +46 -0
  53. package/dist/src/agents/lib/session-id-utils.js +147 -0
  54. package/dist/src/agents/lib/session-precreate.d.ts +17 -0
  55. package/dist/src/agents/lib/session-precreate.js +177 -0
  56. package/dist/src/agents/registry.d.ts +72 -0
  57. package/dist/src/agents/registry.js +337 -0
  58. package/dist/src/agents/types.d.ts +135 -0
  59. package/dist/src/agents/types.js +1 -0
  60. package/dist/src/auth/crypto-key.d.ts +6 -0
  61. package/dist/src/auth/crypto-key.js +45 -0
  62. package/dist/src/auth/middleware.d.ts +18 -0
  63. package/dist/src/auth/middleware.js +54 -0
  64. package/dist/src/auth/password.d.ts +2 -0
  65. package/dist/src/auth/password.js +12 -0
  66. package/dist/src/auth/session.d.ts +10 -0
  67. package/dist/src/auth/session.js +33 -0
  68. package/dist/src/auth/totp.d.ts +12 -0
  69. package/dist/src/auth/totp.js +61 -0
  70. package/dist/src/auth/webauthn.d.ts +6 -0
  71. package/dist/src/auth/webauthn.js +117 -0
  72. package/dist/src/config.d.ts +10 -0
  73. package/dist/src/config.js +16 -0
  74. package/dist/src/database/connection-manager.d.ts +25 -0
  75. package/dist/src/database/connection-manager.js +211 -0
  76. package/dist/src/database/discovery/container.d.ts +6 -0
  77. package/dist/src/database/discovery/container.js +226 -0
  78. package/dist/src/database/discovery/env-parser.d.ts +9 -0
  79. package/dist/src/database/discovery/env-parser.js +525 -0
  80. package/dist/src/database/discovery/local-files.d.ts +6 -0
  81. package/dist/src/database/discovery/local-files.js +58 -0
  82. package/dist/src/database/discovery/port-scan.d.ts +7 -0
  83. package/dist/src/database/discovery/port-scan.js +61 -0
  84. package/dist/src/database/drivers/cassandra.d.ts +12 -0
  85. package/dist/src/database/drivers/cassandra.js +91 -0
  86. package/dist/src/database/drivers/clickhouse.d.ts +11 -0
  87. package/dist/src/database/drivers/clickhouse.js +127 -0
  88. package/dist/src/database/drivers/elasticsearch.d.ts +12 -0
  89. package/dist/src/database/drivers/elasticsearch.js +169 -0
  90. package/dist/src/database/drivers/influxdb.d.ts +14 -0
  91. package/dist/src/database/drivers/influxdb.js +194 -0
  92. package/dist/src/database/drivers/memcached.d.ts +11 -0
  93. package/dist/src/database/drivers/memcached.js +117 -0
  94. package/dist/src/database/drivers/mongodb.d.ts +12 -0
  95. package/dist/src/database/drivers/mongodb.js +128 -0
  96. package/dist/src/database/drivers/mysql.d.ts +11 -0
  97. package/dist/src/database/drivers/mysql.js +112 -0
  98. package/dist/src/database/drivers/neo4j.d.ts +11 -0
  99. package/dist/src/database/drivers/neo4j.js +158 -0
  100. package/dist/src/database/drivers/postgresql.d.ts +11 -0
  101. package/dist/src/database/drivers/postgresql.js +133 -0
  102. package/dist/src/database/drivers/redis.d.ts +11 -0
  103. package/dist/src/database/drivers/redis.js +91 -0
  104. package/dist/src/database/drivers/sqlite.d.ts +10 -0
  105. package/dist/src/database/drivers/sqlite.js +100 -0
  106. package/dist/src/database/query-stream.d.ts +5 -0
  107. package/dist/src/database/query-stream.js +75 -0
  108. package/dist/src/database/types.d.ts +71 -0
  109. package/dist/src/database/types.js +1 -0
  110. package/dist/src/events/index.d.ts +3 -0
  111. package/dist/src/events/index.js +3 -0
  112. package/dist/src/events/types.d.ts +214 -0
  113. package/dist/src/events/types.js +22 -0
  114. package/dist/src/events/wire.d.ts +114 -0
  115. package/dist/src/events/wire.js +296 -0
  116. package/dist/src/fs-monitor-types.d.ts +24 -0
  117. package/dist/src/fs-monitor-types.js +1 -0
  118. package/dist/src/fs-monitor.d.ts +80 -0
  119. package/dist/src/fs-monitor.js +637 -0
  120. package/dist/src/handlers/auth.d.ts +1 -0
  121. package/dist/src/handlers/auth.js +170 -0
  122. package/dist/src/handlers/changes.d.ts +1 -0
  123. package/dist/src/handlers/changes.js +203 -0
  124. package/dist/src/handlers/containers.d.ts +12 -0
  125. package/dist/src/handlers/containers.js +379 -0
  126. package/dist/src/handlers/databases.d.ts +3 -0
  127. package/dist/src/handlers/databases.js +327 -0
  128. package/dist/src/handlers/environments.d.ts +3 -0
  129. package/dist/src/handlers/environments.js +286 -0
  130. package/dist/src/handlers/github.d.ts +1 -0
  131. package/dist/src/handlers/github.js +153 -0
  132. package/dist/src/handlers/projects.d.ts +1 -0
  133. package/dist/src/handlers/projects.js +895 -0
  134. package/dist/src/handlers/ssh.d.ts +1 -0
  135. package/dist/src/handlers/ssh.js +162 -0
  136. package/dist/src/handlers/users.d.ts +1 -0
  137. package/dist/src/handlers/users.js +195 -0
  138. package/dist/src/index.d.ts +1 -0
  139. package/dist/src/index.js +228 -0
  140. package/dist/src/mcp/config.d.ts +32 -0
  141. package/dist/src/mcp/config.js +227 -0
  142. package/dist/src/mcp/server.d.ts +1 -0
  143. package/dist/src/mcp/server.js +574 -0
  144. package/dist/src/serial/cuse-device.d.ts +19 -0
  145. package/dist/src/serial/cuse-device.js +260 -0
  146. package/dist/src/serial/manager.d.ts +63 -0
  147. package/dist/src/serial/manager.js +206 -0
  148. package/dist/src/serial/pty-pair.d.ts +16 -0
  149. package/dist/src/serial/pty-pair.js +68 -0
  150. package/dist/src/services/fs-browser.d.ts +14 -0
  151. package/dist/src/services/fs-browser.js +98 -0
  152. package/dist/src/services/git-ops.d.ts +78 -0
  153. package/dist/src/services/git-ops.js +288 -0
  154. package/dist/src/services/github-ops.d.ts +104 -0
  155. package/dist/src/services/github-ops.js +192 -0
  156. package/dist/src/services/obfuscation.d.ts +2 -0
  157. package/dist/src/services/obfuscation.js +16 -0
  158. package/dist/src/services/preview/headless-backend.d.ts +62 -0
  159. package/dist/src/services/preview/headless-backend.js +698 -0
  160. package/dist/src/services/preview/injected-scripts.d.ts +9 -0
  161. package/dist/src/services/preview/injected-scripts.js +232 -0
  162. package/dist/src/services/preview/preview-backend.d.ts +92 -0
  163. package/dist/src/services/preview/preview-backend.js +15 -0
  164. package/dist/src/services/preview/universal-setter.d.ts +7 -0
  165. package/dist/src/services/preview/universal-setter.js +46 -0
  166. package/dist/src/services/preview-manager.d.ts +50 -0
  167. package/dist/src/services/preview-manager.js +216 -0
  168. package/dist/src/services/project-watcher.d.ts +6 -0
  169. package/dist/src/services/project-watcher.js +307 -0
  170. package/dist/src/services/remote-fs-browser.d.ts +11 -0
  171. package/dist/src/services/remote-fs-browser.js +50 -0
  172. package/dist/src/services/remote-git-ops.d.ts +71 -0
  173. package/dist/src/services/remote-git-ops.js +215 -0
  174. package/dist/src/services/session-search.d.ts +56 -0
  175. package/dist/src/services/session-search.js +303 -0
  176. package/dist/src/services/ssh-manager.d.ts +44 -0
  177. package/dist/src/services/ssh-manager.js +359 -0
  178. package/dist/src/session-writer.d.ts +9 -0
  179. package/dist/src/session-writer.js +66 -0
  180. package/dist/src/spawner.d.ts +56 -0
  181. package/dist/src/spawner.js +135 -0
  182. package/dist/src/state/db.d.ts +214 -0
  183. package/dist/src/state/db.js +897 -0
  184. package/dist/src/state/store.d.ts +37 -0
  185. package/dist/src/state/store.js +108 -0
  186. package/dist/src/state/types.d.ts +13 -0
  187. package/dist/src/state/types.js +1 -0
  188. package/dist/src/web/devtools-proxy.d.ts +7 -0
  189. package/dist/src/web/devtools-proxy.js +176 -0
  190. package/dist/src/web/port-proxy.d.ts +15 -0
  191. package/dist/src/web/port-proxy.js +124 -0
  192. package/dist/src/web/preview-ws.d.ts +5 -0
  193. package/dist/src/web/preview-ws.js +207 -0
  194. package/dist/src/web/server.d.ts +6 -0
  195. package/dist/src/web/server.js +1694 -0
  196. package/dist/src/ws/agent-ws.d.ts +5 -0
  197. package/dist/src/ws/agent-ws.js +93 -0
  198. package/frontend/dist/assets/_basePickBy-B-LibQ4-.js +1 -0
  199. package/frontend/dist/assets/_baseUniq-CprifHap.js +1 -0
  200. package/frontend/dist/assets/_createAssigner-ByDUqGii.js +1 -0
  201. package/frontend/dist/assets/abap-DuT-3z4x.js +1 -0
  202. package/frontend/dist/assets/addon-fit-CxQet2ja.js +1 -0
  203. package/frontend/dist/assets/addon-web-links-D_jRkPIl.js +1 -0
  204. package/frontend/dist/assets/apex-B-em86xX.js +1 -0
  205. package/frontend/dist/assets/api-SUPuHhSY.js +2 -0
  206. package/frontend/dist/assets/arc-Z0_eVteO.js +1 -0
  207. package/frontend/dist/assets/architecture-PBZL5I3N-hvVXGhqd.js +1 -0
  208. package/frontend/dist/assets/architectureDiagram-2XIMDMQ5-DiHPxX4j.js +36 -0
  209. package/frontend/dist/assets/array-CwG8vNfn.js +1 -0
  210. package/frontend/dist/assets/auth-store-R7eW5SVu.js +1 -0
  211. package/frontend/dist/assets/azcli-Bg9wQloi.js +1 -0
  212. package/frontend/dist/assets/bat-BM46z99L.js +1 -0
  213. package/frontend/dist/assets/bicep-DcBsJUfh.js +2 -0
  214. package/frontend/dist/assets/blockDiagram-WCTKOSBZ-C40u_hLo.js +132 -0
  215. package/frontend/dist/assets/c4Diagram-IC4MRINW-Ct7LjWFQ.js +10 -0
  216. package/frontend/dist/assets/cameligo-zw7JTtim.js +1 -0
  217. package/frontend/dist/assets/channel-ClCsE6HN.js +1 -0
  218. package/frontend/dist/assets/chunk-4BX2VUAB-zZ6P90VO.js +1 -0
  219. package/frontend/dist/assets/chunk-55IACEB6-DXllTDQl.js +1 -0
  220. package/frontend/dist/assets/chunk-7E7YKBS2-7zRaOLjj.js +1 -0
  221. package/frontend/dist/assets/chunk-7R4GIKGN-Csst1274.js +80 -0
  222. package/frontend/dist/assets/chunk-C72U2L5F-_JbQPbLN.js +1 -0
  223. package/frontend/dist/assets/chunk-CFjPhJqf.js +1 -0
  224. package/frontend/dist/assets/chunk-EGIJ26TM-B--aFyPw.js +1 -0
  225. package/frontend/dist/assets/chunk-FMBD7UC4-DVR34RNb.js +15 -0
  226. package/frontend/dist/assets/chunk-GEFDOKGD-CnmN6cC8.js +2 -0
  227. package/frontend/dist/assets/chunk-JSJVCQXG-CWxHBzeJ.js +1 -0
  228. package/frontend/dist/assets/chunk-KX2RTZJC-DkRk56s7.js +1 -0
  229. package/frontend/dist/assets/chunk-KYZI473N-DCCsG2dK.js +53 -0
  230. package/frontend/dist/assets/chunk-L3YUKLVL-C-DkZTMr.js +1 -0
  231. package/frontend/dist/assets/chunk-MX3YWQON-OUdzv5sZ.js +1 -0
  232. package/frontend/dist/assets/chunk-NQ4KR5QH-Bpu9FsM7.js +220 -0
  233. package/frontend/dist/assets/chunk-O4XLMI2P-BMLK6_ib.js +7 -0
  234. package/frontend/dist/assets/chunk-OZEHJAEY-CNNiJtG0.js +1 -0
  235. package/frontend/dist/assets/chunk-PQ6SQG4A-evVHD3KM.js +1 -0
  236. package/frontend/dist/assets/chunk-PU5JKC2W-DPFTYuvl.js +70 -0
  237. package/frontend/dist/assets/chunk-QZHKN3VN-JRdddPvu.js +1 -0
  238. package/frontend/dist/assets/chunk-R5LLSJPH-CHQzVVOV.js +1 -0
  239. package/frontend/dist/assets/chunk-WL4C6EOR-BNFU6IIi.js +189 -0
  240. package/frontend/dist/assets/chunk-XIRO2GV7-98T93G85.js +1 -0
  241. package/frontend/dist/assets/chunk-XZSTWKYB-BcW3cyNp.js +94 -0
  242. package/frontend/dist/assets/chunk-YBOYWFTD-BgKO1qAJ.js +1 -0
  243. package/frontend/dist/assets/classDiagram-VBA2DB6C-DikXzgcD.js +1 -0
  244. package/frontend/dist/assets/classDiagram-v2-RAHNMMFH-D7E3tQUK.js +1 -0
  245. package/frontend/dist/assets/clojure-FspFoNNQ.js +1 -0
  246. package/frontend/dist/assets/clone-mOXuZa7C.js +1 -0
  247. package/frontend/dist/assets/codicon-ngg6Pgfi.ttf +0 -0
  248. package/frontend/dist/assets/coffee-13n8Bk2W.js +1 -0
  249. package/frontend/dist/assets/cose-bilkent-S5V4N54A-zUOWQqLe.js +1 -0
  250. package/frontend/dist/assets/cpp-BVm2xGEs.js +1 -0
  251. package/frontend/dist/assets/csharp-D2kAWmUm.js +1 -0
  252. package/frontend/dist/assets/csp-Ezvgpf0e.js +1 -0
  253. package/frontend/dist/assets/css-CYxRwcFy.js +3 -0
  254. package/frontend/dist/assets/css.worker-Cd5h-ZOL.js +89 -0
  255. package/frontend/dist/assets/cssMode-CrXej49V.js +1 -0
  256. package/frontend/dist/assets/cypher-jg3SGErc.js +1 -0
  257. package/frontend/dist/assets/cytoscape.esm-kyyvzxNV.js +321 -0
  258. package/frontend/dist/assets/dagre-DH4bgZO7.js +1 -0
  259. package/frontend/dist/assets/dagre-KLK3FWXG-DNSqDkwT.js +4 -0
  260. package/frontend/dist/assets/dart-179jqhK4.js +1 -0
  261. package/frontend/dist/assets/defaultLocale-Dda4OpKy.js +1 -0
  262. package/frontend/dist/assets/diagram-E7M64L7V-RqPNT5Vs.js +24 -0
  263. package/frontend/dist/assets/diagram-IFDJBPK2-B-5NRyaE.js +43 -0
  264. package/frontend/dist/assets/diagram-P4PSJMXO-BrP69Hk0.js +24 -0
  265. package/frontend/dist/assets/dist-CU_Nb1G5.js +1 -0
  266. package/frontend/dist/assets/dockerfile-CIAtSGxS.js +1 -0
  267. package/frontend/dist/assets/ecl-CGVKfDxD.js +1 -0
  268. package/frontend/dist/assets/editor-Br_kD0ds.css +1 -0
  269. package/frontend/dist/assets/editor.api2-YXkDn0Gm.js +872 -0
  270. package/frontend/dist/assets/editor.main-fBaXZjJ0.js +6 -0
  271. package/frontend/dist/assets/elixir-BZ-6w0y3.js +1 -0
  272. package/frontend/dist/assets/erDiagram-INFDFZHY-BYiB9NYg.js +70 -0
  273. package/frontend/dist/assets/flow9-CVuOjTMv.js +1 -0
  274. package/frontend/dist/assets/flowDiagram-PKNHOUZH-Cwq47rsR.js +162 -0
  275. package/frontend/dist/assets/freemarker2-DM-pztJU.js +3 -0
  276. package/frontend/dist/assets/fsharp-q0pGJYr6.js +1 -0
  277. package/frontend/dist/assets/ganttDiagram-A5KZAMGK-Dnx3szD9.js +292 -0
  278. package/frontend/dist/assets/gitGraph-HDMCJU4V-COlTQ7bA.js +1 -0
  279. package/frontend/dist/assets/gitGraphDiagram-K3NZZRJ6-BaUxboNc.js +65 -0
  280. package/frontend/dist/assets/go-dzSPfdEO.js +1 -0
  281. package/frontend/dist/assets/graphlib-kEFlkt3U.js +1 -0
  282. package/frontend/dist/assets/graphql-CG4OUoEV.js +1 -0
  283. package/frontend/dist/assets/handlebars-BbK53Vec.js +1 -0
  284. package/frontend/dist/assets/hcl-Cy14JPk3.js +1 -0
  285. package/frontend/dist/assets/html-DYtTQNOG.js +1 -0
  286. package/frontend/dist/assets/html.worker-BjVEKLoU.js +502 -0
  287. package/frontend/dist/assets/htmlMode-C6GTouth.js +1 -0
  288. package/frontend/dist/assets/index-DMLxes_u.js +157 -0
  289. package/frontend/dist/assets/index-DmzeqkB1.css +1 -0
  290. package/frontend/dist/assets/info-3K5VOQVL-DBtHyA4C.js +1 -0
  291. package/frontend/dist/assets/infoDiagram-LFFYTUFH-yBXLgMPI.js +2 -0
  292. package/frontend/dist/assets/ini-Pbg8HGVD.js +1 -0
  293. package/frontend/dist/assets/init-D6KNwrax.js +1 -0
  294. package/frontend/dist/assets/ishikawaDiagram-PHBUUO56-Bld4two_.js +70 -0
  295. package/frontend/dist/assets/java-BmVu6Qrl.js +1 -0
  296. package/frontend/dist/assets/javascript-PbfQEdcJ.js +1 -0
  297. package/frontend/dist/assets/journeyDiagram-4ABVD52K-4HyMd4R2.js +139 -0
  298. package/frontend/dist/assets/json.worker-DqU5Wxnl.js +58 -0
  299. package/frontend/dist/assets/jsonMode-CASsGppE.js +7 -0
  300. package/frontend/dist/assets/julia-3cGnieBq.js +1 -0
  301. package/frontend/dist/assets/kanban-definition-K7BYSVSG-DpgsZmpG.js +89 -0
  302. package/frontend/dist/assets/katex-CEw3x5bf.js +261 -0
  303. package/frontend/dist/assets/kotlin-BuWkVcfV.js +1 -0
  304. package/frontend/dist/assets/less-CJ_VPy2C.js +2 -0
  305. package/frontend/dist/assets/lexon-BygAuZPu.js +1 -0
  306. package/frontend/dist/assets/line-CA_wh_TY.js +1 -0
  307. package/frontend/dist/assets/linear-BAcLW45z.js +1 -0
  308. package/frontend/dist/assets/liquid-kz84dle6.js +1 -0
  309. package/frontend/dist/assets/lspLanguageFeatures-C7hAHFn1.js +4 -0
  310. package/frontend/dist/assets/lua-C8Xs3dCx.js +1 -0
  311. package/frontend/dist/assets/m3-DTJeKBk4.js +1 -0
  312. package/frontend/dist/assets/markdown-QCgx8JqZ.js +1 -0
  313. package/frontend/dist/assets/math-D0YcMJAn.js +1 -0
  314. package/frontend/dist/assets/mdx-yRw0ap-E.js +1 -0
  315. package/frontend/dist/assets/mermaid-parser.core-DAeTodBQ.js +4 -0
  316. package/frontend/dist/assets/mindmap-definition-YRQLILUH-CoNlFyVl.js +68 -0
  317. package/frontend/dist/assets/mips-DopWaYgE.js +1 -0
  318. package/frontend/dist/assets/monaco.contribution-DeY0Qei-.js +2 -0
  319. package/frontend/dist/assets/msdax-BDis4ARV.js +1 -0
  320. package/frontend/dist/assets/mysql-BV6MLsOI.js +1 -0
  321. package/frontend/dist/assets/objective-c-B1UuzKs6.js +1 -0
  322. package/frontend/dist/assets/ordinal-jM7S0YHN.js +1 -0
  323. package/frontend/dist/assets/packet-RMMSAZCW-FF6-Tmai.js +1 -0
  324. package/frontend/dist/assets/pascal-BkvESCrc.js +1 -0
  325. package/frontend/dist/assets/pascaligo-lTy0kZYr.js +1 -0
  326. package/frontend/dist/assets/path-DNPd7Py7.js +1 -0
  327. package/frontend/dist/assets/perl-CrtUPXLV.js +1 -0
  328. package/frontend/dist/assets/pgsql-B9IbNWx2.js +1 -0
  329. package/frontend/dist/assets/php-CXvQBY2p.js +1 -0
  330. package/frontend/dist/assets/pie-UPGHQEXC-CFvXY2o-.js +1 -0
  331. package/frontend/dist/assets/pieDiagram-SKSYHLDU-CM_hbCcn.js +30 -0
  332. package/frontend/dist/assets/pla-DxBxuqWu.js +1 -0
  333. package/frontend/dist/assets/postiats-OkEuT5YF.js +1 -0
  334. package/frontend/dist/assets/powerquery-CMx5Tq4K.js +1 -0
  335. package/frontend/dist/assets/powershell-CstRxrEc.js +1 -0
  336. package/frontend/dist/assets/preload-helper-D4M6sveU.js +1 -0
  337. package/frontend/dist/assets/protobuf-Bx0Z-uRj.js +2 -0
  338. package/frontend/dist/assets/pug--W8vanWl.js +1 -0
  339. package/frontend/dist/assets/python-DA0rnlw3.js +1 -0
  340. package/frontend/dist/assets/qsharp-CRtr0YbN.js +1 -0
  341. package/frontend/dist/assets/quadrantDiagram-337W2JSQ-B3n3IUhC.js +7 -0
  342. package/frontend/dist/assets/r-C6E1d6iv.js +1 -0
  343. package/frontend/dist/assets/radar-KQ55EAFF-MPZu7SdX.js +1 -0
  344. package/frontend/dist/assets/razor-yd73uata.js +1 -0
  345. package/frontend/dist/assets/redis-Dx13voP3.js +1 -0
  346. package/frontend/dist/assets/redshift-D66HwlyV.js +1 -0
  347. package/frontend/dist/assets/requirementDiagram-Z7DCOOCP-CorP7L7F.js +73 -0
  348. package/frontend/dist/assets/restructuredtext-DQT2NKJ2.js +1 -0
  349. package/frontend/dist/assets/rough.esm-DxAX5Vpo.js +1 -0
  350. package/frontend/dist/assets/ruby-iFXI8hwH.js +1 -0
  351. package/frontend/dist/assets/rust-CSKiei34.js +1 -0
  352. package/frontend/dist/assets/sankeyDiagram-WA2Y5GQK-RDx6Bd-B.js +10 -0
  353. package/frontend/dist/assets/sb-Bo3ttdP2.js +1 -0
  354. package/frontend/dist/assets/scala-BC1D-Nxp.js +1 -0
  355. package/frontend/dist/assets/scheme-Z4OAo4Lv.js +1 -0
  356. package/frontend/dist/assets/scss-BvrdPs6B.js +3 -0
  357. package/frontend/dist/assets/sequenceDiagram-2WXFIKYE-JMqJSFq6.js +145 -0
  358. package/frontend/dist/assets/shell-Bh_aCyF-.js +1 -0
  359. package/frontend/dist/assets/solidity-CWHj6tSe.js +1 -0
  360. package/frontend/dist/assets/sophia-raoNtKtm.js +1 -0
  361. package/frontend/dist/assets/sparql-XzmoGnue.js +1 -0
  362. package/frontend/dist/assets/sql-BD0i9Gvg.js +1 -0
  363. package/frontend/dist/assets/src-Bn-kKzs7.js +1 -0
  364. package/frontend/dist/assets/st-DtVKyms6.js +1 -0
  365. package/frontend/dist/assets/stateDiagram-RAJIS63D-CgFfENdy.js +1 -0
  366. package/frontend/dist/assets/stateDiagram-v2-FVOUBMTO-C4Hh2P-U.js +1 -0
  367. package/frontend/dist/assets/swift--UZs77wT.js +1 -0
  368. package/frontend/dist/assets/systemverilog-CDnBSWUd.js +1 -0
  369. package/frontend/dist/assets/tcl-DdCEuTHZ.js +1 -0
  370. package/frontend/dist/assets/timeline-definition-YZTLITO2-BnatPBR5.js +61 -0
  371. package/frontend/dist/assets/treemap-KZPCXAKY-qb1Pl9la.js +1 -0
  372. package/frontend/dist/assets/ts.worker-DyPAEIuH.js +67719 -0
  373. package/frontend/dist/assets/tsMode-iuvyEpyO.js +11 -0
  374. package/frontend/dist/assets/twig-SSL-Altf.js +1 -0
  375. package/frontend/dist/assets/typescript-17918Hud.js +1 -0
  376. package/frontend/dist/assets/typespec-BT7S0ETg.js +1 -0
  377. package/frontend/dist/assets/vb-CrIgucua.js +1 -0
  378. package/frontend/dist/assets/vennDiagram-LZ73GAT5-DygS4Zzd.js +34 -0
  379. package/frontend/dist/assets/wgsl-BeKc3oEp.js +298 -0
  380. package/frontend/dist/assets/workers-DTfwKVoM.js +1 -0
  381. package/frontend/dist/assets/xml-CBMr_Wbw.js +1 -0
  382. package/frontend/dist/assets/xterm-BrP-ENHg.css +1 -0
  383. package/frontend/dist/assets/xterm-CBX2m0YM.js +36 -0
  384. package/frontend/dist/assets/xychartDiagram-JWTSCODW-D6wY1Jwd.js +7 -0
  385. package/frontend/dist/assets/yaml-CTjCH7Bv.js +1 -0
  386. package/frontend/dist/fonts/inter-300.ttf +0 -0
  387. package/frontend/dist/fonts/inter-400.ttf +0 -0
  388. package/frontend/dist/fonts/inter-500.ttf +0 -0
  389. package/frontend/dist/fonts/inter-600.ttf +0 -0
  390. package/frontend/dist/fonts/inter-700.ttf +0 -0
  391. package/frontend/dist/index.html +49 -0
  392. package/frontend/dist/logo_192x192.png +0 -0
  393. package/frontend/dist/logo_32x32.png +0 -0
  394. package/frontend/dist/logo_512x512.png +0 -0
  395. package/frontend/dist/logo_64x64.png +0 -0
  396. package/frontend/dist/logobg_192x192.png +0 -0
  397. package/frontend/dist/logobg_512x512.png +0 -0
  398. package/frontend/dist/logobg_64x64.png +0 -0
  399. package/frontend/dist/manifest.json +25 -0
  400. package/frontend/dist/sw.js +22 -0
  401. package/package.json +74 -7
  402. package/preload/Makefile +12 -0
  403. package/preload/atoo-studio-preload.c +647 -0
  404. package/preload/atoo-studio-preload.so +0 -0
  405. package/setup-cuse.sh +260 -0
  406. package/setup.sh +81 -0
  407. package/src/serial/native/binding.gyp +10 -0
  408. package/src/serial/native/pty_pair.c +222 -0
@@ -0,0 +1,72 @@
1
+ import type WebSocket from 'ws';
2
+ import type { Agent, AgentFactory, AgentSessionInfo, AgentInitOptions, AgentDescriptor, HistoricalSession, LinkedIssueInfo } from './types.js';
3
+ import type { SessionEvent } from '../events/types.js';
4
+ interface BrowserState {
5
+ linkedIssue?: LinkedIssueInfo;
6
+ viewMode?: string;
7
+ showVerbose?: boolean;
8
+ title?: string;
9
+ metaName?: string;
10
+ metaDescription?: string;
11
+ tags?: string[];
12
+ }
13
+ declare class AgentRegistry {
14
+ private factories;
15
+ private agents;
16
+ registerFactory(factory: AgentFactory): void;
17
+ createAgent(agentType: string, sessionId: string, options: AgentInitOptions): Promise<Agent>;
18
+ getAgent(sessionId: string): Agent | undefined;
19
+ destroyAgent(sessionId: string): Promise<void>;
20
+ setSessionFocused(sessionId: string): void;
21
+ setSessionBlurred(sessionId: string): void;
22
+ setBrowserState(sessionId: string, state: Partial<BrowserState>): void;
23
+ getBrowserState(sessionId: string): BrowserState | undefined;
24
+ listAgents(): (AgentSessionInfo & {
25
+ browserState?: BrowserState;
26
+ })[];
27
+ addBrowserClient(sessionId: string, ws: WebSocket): void;
28
+ removeBrowserClient(sessionId: string, ws: WebSocket): void;
29
+ getAvailableAgents(): AgentDescriptor[];
30
+ getHistoricalSessions(cwd?: string): Promise<HistoricalSession[]>;
31
+ /**
32
+ * Collect all session JSONL file paths for a project directory,
33
+ * deduplicated across all registered agent factories.
34
+ * Resolves related paths (main project + all worktrees, current and historical)
35
+ * so that searching from any worktree or the main project returns the full history.
36
+ */
37
+ getSessionFilesForProject(cwd: string): Promise<string[]>;
38
+ resumeAgent(sessionUuid: string, options?: {
39
+ cwd?: string;
40
+ skipPermissions?: boolean;
41
+ agentType?: string;
42
+ }): Promise<Agent>;
43
+ /**
44
+ * Create a new chain link from an existing session.
45
+ * Carries forward user messages + last N events, generates a chain-linked UUID.
46
+ * The new session can search previous chain links via CurrentSessionChain.
47
+ */
48
+ chainAgent(sessionUuid: string, options?: {
49
+ cwd?: string;
50
+ skipPermissions?: boolean;
51
+ agentType?: string;
52
+ }): Promise<Agent>;
53
+ /**
54
+ * Create a chain link from in-memory events (for active agents).
55
+ * Bypasses the FS scanner — events come directly from the live agent.
56
+ */
57
+ chainFromEvents(events: SessionEvent[], parentSessionId: string, options?: {
58
+ cwd?: string;
59
+ skipPermissions?: boolean;
60
+ agentType?: string;
61
+ }): Promise<Agent>;
62
+ /**
63
+ * Convert a fork JSONL (always written in Claude format by forkToResumable)
64
+ * to the target agent's native format if cross-family.
65
+ * Returns the UUID to use for resume (same UUID, but file now in target format).
66
+ */
67
+ convertForkForAgent(forkUuid: string, sourceAgentType: string, targetAgentType: string, cwd: string): Promise<string>;
68
+ private broadcastToClients;
69
+ private broadcastRawToClients;
70
+ }
71
+ export declare const agentRegistry: AgentRegistry;
72
+ export {};
@@ -0,0 +1,337 @@
1
+ import { v4 as uuidv4 } from 'uuid';
2
+ import { store } from '../state/store.js';
3
+ import { db } from '../state/db.js';
4
+ import { buildChainSession } from './lib/chain-builder.js';
5
+ import { fsSessionScanner } from './lib/claude/fs-sessions.js';
6
+ class AgentRegistry {
7
+ factories = new Map();
8
+ agents = new Map();
9
+ registerFactory(factory) {
10
+ this.factories.set(factory.agentType, factory);
11
+ console.log(`[agent-registry] Registered factory: ${factory.agentType}`);
12
+ }
13
+ async createAgent(agentType, sessionId, options) {
14
+ const factory = this.factories.get(agentType);
15
+ if (!factory) {
16
+ throw new Error(`Unknown agent type: ${agentType}`);
17
+ }
18
+ const agent = factory.create(sessionId);
19
+ const entry = {
20
+ agent,
21
+ agentType,
22
+ browserClients: new Set(),
23
+ contextInProgress: false,
24
+ browserState: {},
25
+ };
26
+ this.agents.set(sessionId, entry);
27
+ // Wire up event forwarding
28
+ agent.on('message', (msg) => {
29
+ this.broadcastToClients(sessionId, msg);
30
+ });
31
+ // Forward agent status to the global store for WebSocket broadcasting.
32
+ // Each agent adapter owns its activity status (open/active/attention).
33
+ agent.on('status', (status) => {
34
+ if (status === 'exited')
35
+ return; // handled by destroyAgent
36
+ store.setAgentStatus(sessionId, status);
37
+ });
38
+ agent.on('context_in_progress', (inProgress) => {
39
+ const e = this.agents.get(sessionId);
40
+ if (e)
41
+ e.contextInProgress = inProgress;
42
+ this.broadcastRawToClients(sessionId, { type: 'context_in_progress', inProgress });
43
+ });
44
+ agent.on('exit', () => {
45
+ console.log(`[agent-registry] Agent exited: ${sessionId}`);
46
+ });
47
+ agent.on('error', (err) => {
48
+ console.error(`[agent-registry] Agent error for ${sessionId}:`, err.message);
49
+ });
50
+ // Initialize the agent
51
+ await agent.initialize(options);
52
+ console.log(`[agent-registry] Agent created: ${sessionId} (type: ${agentType})`);
53
+ return agent;
54
+ }
55
+ getAgent(sessionId) {
56
+ return this.agents.get(sessionId)?.agent;
57
+ }
58
+ async destroyAgent(sessionId) {
59
+ const entry = this.agents.get(sessionId);
60
+ if (!entry)
61
+ return;
62
+ // Remove all event listeners BEFORE destroying to prevent
63
+ // late status broadcasts from reviving the session in the UI
64
+ entry.agent.removeAllListeners();
65
+ // Close all browser WS connections
66
+ for (const ws of entry.browserClients) {
67
+ try {
68
+ ws.close();
69
+ }
70
+ catch { }
71
+ }
72
+ entry.browserClients.clear();
73
+ await entry.agent.destroy();
74
+ this.agents.delete(sessionId);
75
+ // Clean up status from the global store and broadcast removal
76
+ store.removeAgentStatus(sessionId);
77
+ console.log(`[agent-registry] Agent destroyed: ${sessionId}`);
78
+ }
79
+ setSessionFocused(sessionId) {
80
+ this.agents.get(sessionId)?.agent.onFocused();
81
+ }
82
+ setSessionBlurred(sessionId) {
83
+ this.agents.get(sessionId)?.agent.onBlurred();
84
+ }
85
+ setBrowserState(sessionId, state) {
86
+ const entry = this.agents.get(sessionId);
87
+ if (entry)
88
+ Object.assign(entry.browserState, state);
89
+ }
90
+ getBrowserState(sessionId) {
91
+ return this.agents.get(sessionId)?.browserState;
92
+ }
93
+ listAgents() {
94
+ const infos = [];
95
+ for (const entry of this.agents.values()) {
96
+ const info = entry.agent.getInfo();
97
+ if (entry.browserState.linkedIssue)
98
+ info.linkedIssue = entry.browserState.linkedIssue;
99
+ infos.push({ ...info, browserState: entry.browserState });
100
+ }
101
+ return infos;
102
+ }
103
+ addBrowserClient(sessionId, ws) {
104
+ const entry = this.agents.get(sessionId);
105
+ if (!entry)
106
+ return;
107
+ entry.browserClients.add(ws);
108
+ // Send current context_in_progress state so late-joining browsers get it
109
+ if (entry.contextInProgress) {
110
+ ws.send(JSON.stringify({ type: 'context_in_progress', inProgress: true }));
111
+ }
112
+ }
113
+ removeBrowserClient(sessionId, ws) {
114
+ const entry = this.agents.get(sessionId);
115
+ if (!entry)
116
+ return;
117
+ entry.browserClients.delete(ws);
118
+ }
119
+ getAvailableAgents() {
120
+ const descriptors = [];
121
+ for (const factory of this.factories.values()) {
122
+ descriptors.push(factory.getDescriptor());
123
+ }
124
+ return descriptors;
125
+ }
126
+ async getHistoricalSessions(cwd) {
127
+ const allSessions = [];
128
+ for (const factory of this.factories.values()) {
129
+ const sessions = await factory.getHistoricalSessions();
130
+ allSessions.push(...sessions);
131
+ }
132
+ // Deduplicate by session ID — when same UUID exists across factories, keep the most recent
133
+ const bestById = new Map();
134
+ for (const s of allSessions) {
135
+ const existing = bestById.get(s.id);
136
+ if (!existing || new Date(s.lastModified).getTime() > new Date(existing.lastModified).getTime()) {
137
+ bestById.set(s.id, s);
138
+ }
139
+ }
140
+ let unique = Array.from(bestById.values());
141
+ // Filter by project path (includes main project + all worktree paths)
142
+ if (cwd) {
143
+ const relatedPaths = new Set(db.getAllRelatedProjectPaths(cwd));
144
+ unique = unique.filter(s => relatedPaths.has(s.directory));
145
+ }
146
+ // Sort by date descending (most recent first)
147
+ unique.sort((a, b) => new Date(b.lastModified).getTime() - new Date(a.lastModified).getTime());
148
+ return unique;
149
+ }
150
+ /**
151
+ * Collect all session JSONL file paths for a project directory,
152
+ * deduplicated across all registered agent factories.
153
+ * Resolves related paths (main project + all worktrees, current and historical)
154
+ * so that searching from any worktree or the main project returns the full history.
155
+ */
156
+ async getSessionFilesForProject(cwd) {
157
+ // Resolve all related project paths (main + worktrees, current and historical)
158
+ const relatedPaths = db.getAllRelatedProjectPaths(cwd);
159
+ const seen = new Set();
160
+ const allFiles = [];
161
+ for (const factory of this.factories.values()) {
162
+ const files = await factory.getSessionFilesForProject(relatedPaths);
163
+ for (const f of files) {
164
+ if (!seen.has(f)) {
165
+ seen.add(f);
166
+ allFiles.push(f);
167
+ }
168
+ }
169
+ }
170
+ return allFiles;
171
+ }
172
+ async resumeAgent(sessionUuid, options = {}) {
173
+ // Find the factory that owns this session
174
+ let sourceFactory = null;
175
+ for (const factory of this.factories.values()) {
176
+ if (await factory.ownsSession(sessionUuid)) {
177
+ sourceFactory = factory;
178
+ break;
179
+ }
180
+ }
181
+ if (!sourceFactory) {
182
+ throw new Error(`No agent implementation recognizes session ${sessionUuid}`);
183
+ }
184
+ // Determine target factory (requested agentType or same as source)
185
+ const targetAgentType = options.agentType || sourceFactory.agentType;
186
+ const targetFactory = this.factories.get(targetAgentType);
187
+ if (!targetFactory) {
188
+ throw new Error(`Unknown agent type: ${targetAgentType}`);
189
+ }
190
+ let resumeUuid = sessionUuid;
191
+ let isChainContinuation = false;
192
+ // Cross-family resume: create a chain link instead of reusing the same UUID.
193
+ // This keeps each session file unambiguously one agent family and preserves
194
+ // the parent→child link via the session ID schema.
195
+ if (sourceFactory.agentFamily !== targetFactory.agentFamily) {
196
+ const events = await sourceFactory.readSessionEvents(sessionUuid);
197
+ if (!events.length) {
198
+ throw new Error(`No events found in session ${sessionUuid} for cross-family conversion`);
199
+ }
200
+ const cwd = options.cwd || '.';
201
+ const { buildLinkedUuid } = await import('./lib/session-id-utils.js');
202
+ const chainUuid = buildLinkedUuid(sessionUuid, 'chain');
203
+ targetFactory.writeSessionForResume(events, chainUuid, cwd);
204
+ resumeUuid = chainUuid;
205
+ isChainContinuation = true;
206
+ }
207
+ const sessionId = `agent_${uuidv4()}`;
208
+ return this.createAgent(targetFactory.agentType, sessionId, {
209
+ cwd: options.cwd,
210
+ skipPermissions: options.skipPermissions,
211
+ resumeSessionUuid: resumeUuid,
212
+ isChainContinuation,
213
+ });
214
+ }
215
+ /**
216
+ * Create a new chain link from an existing session.
217
+ * Carries forward user messages + last N events, generates a chain-linked UUID.
218
+ * The new session can search previous chain links via CurrentSessionChain.
219
+ */
220
+ async chainAgent(sessionUuid, options = {}) {
221
+ // Find the factory that owns the source session.
222
+ // Invalidate caches first since we may be chaining from a still-running session
223
+ // whose JSONL has grown since the last scan.
224
+ fsSessionScanner.invalidate();
225
+ let sourceFactory = null;
226
+ for (const factory of this.factories.values()) {
227
+ if (await factory.ownsSession(sessionUuid)) {
228
+ sourceFactory = factory;
229
+ break;
230
+ }
231
+ }
232
+ if (!sourceFactory) {
233
+ throw new Error(`No agent implementation recognizes session ${sessionUuid}`);
234
+ }
235
+ // Read events from the source session (file is up-to-date since CLIs write incrementally)
236
+ const events = await sourceFactory.readSessionEvents(sessionUuid);
237
+ if (!events.length) {
238
+ throw new Error(`No events found in session ${sessionUuid} for chain creation`);
239
+ }
240
+ // Determine target factory
241
+ const targetAgentType = options.agentType || sourceFactory.agentType;
242
+ const targetFactory = this.factories.get(targetAgentType);
243
+ if (!targetFactory) {
244
+ throw new Error(`Unknown agent type: ${targetAgentType}`);
245
+ }
246
+ const cwd = options.cwd || '.';
247
+ // Build chain events + UUID (does not write to disk)
248
+ const chain = buildChainSession(events, sessionUuid);
249
+ if (!chain) {
250
+ throw new Error(`Session has no conversation content to chain — try sending a message first`);
251
+ }
252
+ // Write in the target agent's native format
253
+ targetFactory.writeSessionForResume(chain.events, chain.uuid, cwd);
254
+ const sessionId = `agent_${uuidv4()}`;
255
+ return this.createAgent(targetFactory.agentType, sessionId, {
256
+ cwd: options.cwd,
257
+ skipPermissions: options.skipPermissions,
258
+ resumeSessionUuid: chain.uuid,
259
+ isChainContinuation: true,
260
+ });
261
+ }
262
+ /**
263
+ * Create a chain link from in-memory events (for active agents).
264
+ * Bypasses the FS scanner — events come directly from the live agent.
265
+ */
266
+ async chainFromEvents(events, parentSessionId, options = {}) {
267
+ if (!events.length) {
268
+ throw new Error('No events provided for chain creation');
269
+ }
270
+ // Determine target factory
271
+ const targetAgentType = options.agentType || 'claude-code-terminal-chatro';
272
+ const targetFactory = this.factories.get(targetAgentType);
273
+ if (!targetFactory) {
274
+ throw new Error(`Unknown agent type: ${targetAgentType}`);
275
+ }
276
+ const cwd = options.cwd || '.';
277
+ // Build chain events + UUID (does not write to disk)
278
+ const chain = buildChainSession(events, parentSessionId);
279
+ if (!chain) {
280
+ throw new Error('Session has no conversation content to chain — try sending a message first');
281
+ }
282
+ // Write in the target agent's native format
283
+ targetFactory.writeSessionForResume(chain.events, chain.uuid, cwd);
284
+ const sessionId = `agent_${uuidv4()}`;
285
+ return this.createAgent(targetFactory.agentType, sessionId, {
286
+ cwd: options.cwd,
287
+ skipPermissions: options.skipPermissions,
288
+ resumeSessionUuid: chain.uuid,
289
+ isChainContinuation: true,
290
+ });
291
+ }
292
+ /**
293
+ * Convert a fork JSONL (always written in Claude format by forkToResumable)
294
+ * to the target agent's native format if cross-family.
295
+ * Returns the UUID to use for resume (same UUID, but file now in target format).
296
+ */
297
+ async convertForkForAgent(forkUuid, sourceAgentType, targetAgentType, cwd) {
298
+ const sourceFactory = this.factories.get(sourceAgentType);
299
+ const targetFactory = this.factories.get(targetAgentType);
300
+ if (!sourceFactory || !targetFactory)
301
+ return forkUuid;
302
+ if (sourceFactory.agentFamily === targetFactory.agentFamily)
303
+ return forkUuid;
304
+ // Fork was written as Claude JSONL — read via a Claude factory
305
+ const claudeFactory = [...this.factories.values()].find(f => f.agentFamily === 'claude');
306
+ if (!claudeFactory)
307
+ return forkUuid;
308
+ const events = await claudeFactory.readSessionEvents(forkUuid);
309
+ if (!events.length)
310
+ return forkUuid;
311
+ targetFactory.writeSessionForResume(events, forkUuid, cwd);
312
+ return forkUuid;
313
+ }
314
+ broadcastToClients(sessionId, message) {
315
+ const entry = this.agents.get(sessionId);
316
+ if (!entry)
317
+ return;
318
+ const data = JSON.stringify(message);
319
+ for (const ws of entry.browserClients) {
320
+ if (ws.readyState === 1) {
321
+ ws.send(data);
322
+ }
323
+ }
324
+ }
325
+ broadcastRawToClients(sessionId, message) {
326
+ const entry = this.agents.get(sessionId);
327
+ if (!entry)
328
+ return;
329
+ const data = JSON.stringify(message);
330
+ for (const ws of entry.browserClients) {
331
+ if (ws.readyState === 1) {
332
+ ws.send(data);
333
+ }
334
+ }
335
+ }
336
+ }
337
+ export const agentRegistry = new AgentRegistry();
@@ -0,0 +1,135 @@
1
+ import { EventEmitter } from 'events';
2
+ import type { SessionEvent } from '../events/types.js';
3
+ import type { WireMessage } from '../events/wire.js';
4
+ export type AgentStatus = 'open' | 'active' | 'attention' | 'exited';
5
+ export type AgentMode = 'terminal' | 'chat' | 'terminal+chat' | 'terminal+chatRO';
6
+ export interface AgentDescriptor {
7
+ agentType: string;
8
+ agentFamily: string;
9
+ name: string;
10
+ mode: AgentMode;
11
+ iconUrl: string;
12
+ }
13
+ export interface AgentCapabilities {
14
+ canChangeMode: boolean;
15
+ canChangeModel: boolean;
16
+ hasContextUsage: boolean;
17
+ canFork: boolean;
18
+ canResume: boolean;
19
+ hasTerminal: boolean;
20
+ hasFileTracking: boolean;
21
+ availableModes: string[];
22
+ availableModels: string[];
23
+ }
24
+ export interface LinkedIssueInfo {
25
+ type: 'issue' | 'pr';
26
+ number: number;
27
+ title: string;
28
+ url: string;
29
+ }
30
+ export interface AgentSessionInfo {
31
+ sessionId: string;
32
+ agentType: string;
33
+ agentMode: AgentMode;
34
+ status: AgentStatus;
35
+ mode?: string;
36
+ model?: string;
37
+ cwd?: string;
38
+ capabilities: AgentCapabilities;
39
+ createdAt: number;
40
+ /** The CLI's own session UUID (for chain link detection in the sidebar) */
41
+ cliSessionId?: string;
42
+ /** Linked GitHub issue or PR */
43
+ linkedIssue?: LinkedIssueInfo;
44
+ }
45
+ export interface AgentInitOptions {
46
+ cwd?: string;
47
+ skipPermissions?: boolean;
48
+ resumeSessionUuid?: string;
49
+ /** When true, this is a chain continuation session — append chain system prompt */
50
+ isChainContinuation?: boolean;
51
+ /** Optional message to append to the initial greeting in the pre-created session */
52
+ initialMessage?: string;
53
+ }
54
+ export interface Agent extends EventEmitter {
55
+ initialize(options: AgentInitOptions): Promise<void>;
56
+ destroy(): Promise<void>;
57
+ sendMessage(text: string, attachments?: Attachment[]): void;
58
+ approve(requestId: string, updatedInput?: any): void;
59
+ deny(requestId: string): void;
60
+ answerQuestion(requestId: string, answers: Record<string, string>): void;
61
+ setMode(mode: string): void;
62
+ setModel(model: string): void;
63
+ refreshContext(): void;
64
+ sendKey(key: string): void;
65
+ onFocused(): void;
66
+ onBlurred(): void;
67
+ /**
68
+ * Fork this agent's events into a resumable session file.
69
+ * Returns the resume UUID, or null if forking isn't supported.
70
+ */
71
+ forkToResumable(afterEventUuid: string, fromEventUuid?: string, targetDir?: string): string | null;
72
+ getInfo(): AgentSessionInfo;
73
+ getMessages(): WireMessage[];
74
+ getEvents(): SessionEvent[];
75
+ getWireMessages(): WireMessage[];
76
+ getCliSessionId?(): string | null;
77
+ }
78
+ export interface HistoricalSession {
79
+ id: string;
80
+ agentType: string;
81
+ title: string;
82
+ directory: string;
83
+ lastModified: string;
84
+ eventCount: number;
85
+ metaName?: string;
86
+ tags?: string[];
87
+ }
88
+ export interface AgentFactory {
89
+ agentType: string;
90
+ /** Agent family identifier — factories in the same family can resume each other's sessions directly */
91
+ agentFamily: string;
92
+ create(sessionId: string): Agent;
93
+ getDescriptor(): AgentDescriptor;
94
+ getHistoricalSessions(): Promise<HistoricalSession[]>;
95
+ ownsSession(uuid: string): Promise<boolean>;
96
+ /** Return all session JSONL file paths (including subagent files) for the given project directories */
97
+ getSessionFilesForProject(cwds: string[]): Promise<string[]>;
98
+ /** Read a session's events (for cross-family conversion) */
99
+ readSessionEvents(uuid: string): Promise<SessionEvent[]>;
100
+ /** Write events in this family's native format for resuming. Returns the JSONL path. */
101
+ writeSessionForResume(events: SessionEvent[], targetUuid: string, directory: string): string;
102
+ }
103
+ export interface Attachment {
104
+ media_type: string;
105
+ data: string;
106
+ name?: string;
107
+ text?: string;
108
+ }
109
+ export type AgentCommand = {
110
+ action: 'send_message';
111
+ text: string;
112
+ attachments?: Attachment[];
113
+ } | {
114
+ action: 'approve';
115
+ requestId: string;
116
+ updatedInput?: any;
117
+ } | {
118
+ action: 'deny';
119
+ requestId: string;
120
+ } | {
121
+ action: 'answer_question';
122
+ requestId: string;
123
+ answers: Record<string, string>;
124
+ } | {
125
+ action: 'set_mode';
126
+ mode: string;
127
+ } | {
128
+ action: 'set_model';
129
+ model: string;
130
+ } | {
131
+ action: 'refresh_context';
132
+ } | {
133
+ action: 'send_key';
134
+ key: string;
135
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,6 @@
1
+ /** Get or generate the server-side encryption key for TOTP secrets. */
2
+ export declare function getAuthKey(): Buffer;
3
+ /** Encrypt plaintext using AES-256-GCM with the server auth key. */
4
+ export declare function encrypt(plaintext: string): string;
5
+ /** Decrypt ciphertext encrypted with encrypt(). */
6
+ export declare function decrypt(ciphertext: string): string;
@@ -0,0 +1,45 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ import os from 'os';
4
+ import crypto from 'crypto';
5
+ const STORE_DIR = path.join(os.homedir(), '.atoo-studio');
6
+ const AUTH_KEY_PATH = path.join(STORE_DIR, 'auth.key');
7
+ let cachedKey = null;
8
+ /** Get or generate the server-side encryption key for TOTP secrets. */
9
+ export function getAuthKey() {
10
+ if (cachedKey)
11
+ return cachedKey;
12
+ if (!fs.existsSync(STORE_DIR)) {
13
+ fs.mkdirSync(STORE_DIR, { recursive: true });
14
+ }
15
+ if (fs.existsSync(AUTH_KEY_PATH)) {
16
+ cachedKey = Buffer.from(fs.readFileSync(AUTH_KEY_PATH, 'utf-8').trim(), 'hex');
17
+ }
18
+ else {
19
+ cachedKey = crypto.randomBytes(32);
20
+ fs.writeFileSync(AUTH_KEY_PATH, cachedKey.toString('hex'), { mode: 0o600 });
21
+ console.log('[auth] Generated new auth encryption key');
22
+ }
23
+ return cachedKey;
24
+ }
25
+ /** Encrypt plaintext using AES-256-GCM with the server auth key. */
26
+ export function encrypt(plaintext) {
27
+ const key = getAuthKey();
28
+ const iv = crypto.randomBytes(12);
29
+ const cipher = crypto.createCipheriv('aes-256-gcm', key, iv);
30
+ const encrypted = Buffer.concat([cipher.update(plaintext, 'utf8'), cipher.final()]);
31
+ const tag = cipher.getAuthTag();
32
+ // Format: iv:tag:ciphertext (all hex)
33
+ return `${iv.toString('hex')}:${tag.toString('hex')}:${encrypted.toString('hex')}`;
34
+ }
35
+ /** Decrypt ciphertext encrypted with encrypt(). */
36
+ export function decrypt(ciphertext) {
37
+ const key = getAuthKey();
38
+ const [ivHex, tagHex, dataHex] = ciphertext.split(':');
39
+ const iv = Buffer.from(ivHex, 'hex');
40
+ const tag = Buffer.from(tagHex, 'hex');
41
+ const data = Buffer.from(dataHex, 'hex');
42
+ const decipher = crypto.createDecipheriv('aes-256-gcm', key, iv);
43
+ decipher.setAuthTag(tag);
44
+ return Buffer.concat([decipher.update(data), decipher.final()]).toString('utf8');
45
+ }
@@ -0,0 +1,18 @@
1
+ import type { Request, Response, NextFunction } from 'express';
2
+ import type { IncomingMessage } from 'http';
3
+ import { type User } from '../state/db.js';
4
+ declare global {
5
+ namespace Express {
6
+ interface Request {
7
+ user?: User;
8
+ }
9
+ }
10
+ }
11
+ /** Middleware: require a valid auth session. Attaches req.user. */
12
+ export declare function requireAuth(req: Request, res: Response, next: NextFunction): void;
13
+ /** Middleware: require admin role. Must be used after requireAuth. */
14
+ export declare function requireAdmin(req: Request, res: Response, next: NextFunction): void;
15
+ /** Parse session from WebSocket upgrade request headers. Returns user or null. */
16
+ export declare function authenticateWsUpgrade(req: IncomingMessage): User | null;
17
+ /** Check if auth is required (users exist). */
18
+ export declare function isAuthEnabled(): boolean;
@@ -0,0 +1,54 @@
1
+ import { SESSION_COOKIE_NAME } from './session.js';
2
+ import { getSessionUser } from './session.js';
3
+ import { db } from '../state/db.js';
4
+ /** Middleware: require a valid auth session. Attaches req.user. */
5
+ export function requireAuth(req, res, next) {
6
+ // Setup mode: if no users exist, return 503
7
+ if (db.getUserCount() === 0) {
8
+ res.status(503).json({ error: 'Setup required', setupRequired: true });
9
+ return;
10
+ }
11
+ const sessionId = req.cookies?.[SESSION_COOKIE_NAME];
12
+ if (!sessionId) {
13
+ res.status(401).json({ error: 'Authentication required' });
14
+ return;
15
+ }
16
+ const user = getSessionUser(sessionId);
17
+ if (!user) {
18
+ res.status(401).json({ error: 'Invalid or expired session' });
19
+ return;
20
+ }
21
+ req.user = user;
22
+ next();
23
+ }
24
+ /** Middleware: require admin role. Must be used after requireAuth. */
25
+ export function requireAdmin(req, res, next) {
26
+ requireAuth(req, res, () => {
27
+ if (req.user?.role !== 'admin') {
28
+ res.status(403).json({ error: 'Admin access required' });
29
+ return;
30
+ }
31
+ next();
32
+ });
33
+ }
34
+ /** Parse session from WebSocket upgrade request headers. Returns user or null. */
35
+ export function authenticateWsUpgrade(req) {
36
+ // If no users exist (setup mode), allow all WebSocket connections
37
+ if (db.getUserCount() === 0)
38
+ return null;
39
+ const cookieHeader = req.headers.cookie;
40
+ if (!cookieHeader)
41
+ return null;
42
+ const sessionId = parseCookieValue(cookieHeader, SESSION_COOKIE_NAME);
43
+ if (!sessionId)
44
+ return null;
45
+ return getSessionUser(sessionId);
46
+ }
47
+ /** Check if auth is required (users exist). */
48
+ export function isAuthEnabled() {
49
+ return db.getUserCount() > 0;
50
+ }
51
+ function parseCookieValue(cookieHeader, name) {
52
+ const match = cookieHeader.match(new RegExp(`(?:^|;\\s*)${name}=([^;]*)`));
53
+ return match ? decodeURIComponent(match[1]) : null;
54
+ }
@@ -0,0 +1,2 @@
1
+ export declare function hashPassword(plain: string): Promise<string>;
2
+ export declare function verifyPassword(plain: string, hash: string): Promise<boolean>;