@jlongo78/agent-spaces 0.7.5 → 0.7.6

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 (630) hide show
  1. package/.next/standalone/.claude/settings.local.json +55 -0
  2. package/.next/standalone/.claude/spaces-env.json +1 -0
  3. package/.next/standalone/.next/BUILD_ID +1 -1
  4. package/.next/standalone/.next/app-path-routes-manifest.json +2 -1
  5. package/.next/standalone/.next/build-manifest.json +5 -5
  6. package/.next/standalone/.next/prerender-manifest.json +27 -3
  7. package/.next/standalone/.next/required-server-files.json +19 -19
  8. package/.next/standalone/.next/routes-manifest.json +6 -0
  9. package/.next/standalone/.next/server/app/(desktop)/admin/analytics/page/build-manifest.json +3 -3
  10. package/.next/standalone/.next/server/app/(desktop)/admin/analytics/page_client-reference-manifest.js +1 -1
  11. package/.next/standalone/.next/server/app/(desktop)/admin/users/page/build-manifest.json +3 -3
  12. package/.next/standalone/.next/server/app/(desktop)/admin/users/page_client-reference-manifest.js +1 -1
  13. package/.next/standalone/.next/server/app/(desktop)/analytics/page/build-manifest.json +3 -3
  14. package/.next/standalone/.next/server/app/(desktop)/analytics/page_client-reference-manifest.js +1 -1
  15. package/.next/standalone/.next/server/app/(desktop)/cortex/page/build-manifest.json +3 -3
  16. package/.next/standalone/.next/server/app/(desktop)/cortex/page/react-loadable-manifest.json +3 -3
  17. package/.next/standalone/.next/server/app/(desktop)/cortex/page.js.nft.json +1 -1
  18. package/.next/standalone/.next/server/app/(desktop)/cortex/page_client-reference-manifest.js +1 -1
  19. package/.next/standalone/.next/server/app/(desktop)/network/page/build-manifest.json +3 -3
  20. package/.next/standalone/.next/server/app/(desktop)/network/page_client-reference-manifest.js +1 -1
  21. package/.next/standalone/.next/server/app/(desktop)/page/build-manifest.json +3 -3
  22. package/.next/standalone/.next/server/app/(desktop)/page_client-reference-manifest.js +1 -1
  23. package/.next/standalone/.next/server/app/(desktop)/projects/page/build-manifest.json +3 -3
  24. package/.next/standalone/.next/server/app/(desktop)/projects/page_client-reference-manifest.js +1 -1
  25. package/.next/standalone/.next/server/app/(desktop)/sessions/[id]/page/build-manifest.json +3 -3
  26. package/.next/standalone/.next/server/app/(desktop)/sessions/[id]/page_client-reference-manifest.js +1 -1
  27. package/.next/standalone/.next/server/app/(desktop)/sessions/page/build-manifest.json +3 -3
  28. package/.next/standalone/.next/server/app/(desktop)/sessions/page_client-reference-manifest.js +1 -1
  29. package/.next/standalone/.next/server/app/(desktop)/settings/page/build-manifest.json +3 -3
  30. package/.next/standalone/.next/server/app/(desktop)/settings/page_client-reference-manifest.js +1 -1
  31. package/.next/standalone/.next/server/app/(desktop)/terminal/page/build-manifest.json +3 -3
  32. package/.next/standalone/.next/server/app/(desktop)/terminal/page.js.nft.json +1 -1
  33. package/.next/standalone/.next/server/app/(desktop)/terminal/page_client-reference-manifest.js +1 -1
  34. package/.next/standalone/.next/server/app/(desktop)/terminal/pane/[id]/page/build-manifest.json +3 -3
  35. package/.next/standalone/.next/server/app/(desktop)/terminal/pane/[id]/page.js.nft.json +1 -1
  36. package/.next/standalone/.next/server/app/(desktop)/terminal/pane/[id]/page_client-reference-manifest.js +1 -1
  37. package/.next/standalone/.next/server/app/(desktop)/terminal/remote/[nodeId]/[workspaceId]/page/build-manifest.json +3 -3
  38. package/.next/standalone/.next/server/app/(desktop)/terminal/remote/[nodeId]/[workspaceId]/page.js.nft.json +1 -1
  39. package/.next/standalone/.next/server/app/(desktop)/terminal/remote/[nodeId]/[workspaceId]/page_client-reference-manifest.js +1 -1
  40. package/.next/standalone/.next/server/app/(desktop)/workspaces/page/build-manifest.json +3 -3
  41. package/.next/standalone/.next/server/app/(desktop)/workspaces/page_client-reference-manifest.js +1 -1
  42. package/.next/standalone/.next/server/app/_global-error/page/build-manifest.json +3 -3
  43. package/.next/standalone/.next/server/app/_global-error.html +2 -2
  44. package/.next/standalone/.next/server/app/_global-error.rsc +1 -1
  45. package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  46. package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  47. package/.next/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  48. package/.next/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  49. package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  50. package/.next/standalone/.next/server/app/_not-found/page/build-manifest.json +3 -3
  51. package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  52. package/.next/standalone/.next/server/app/_not-found.html +1 -1
  53. package/.next/standalone/.next/server/app/_not-found.rsc +2 -2
  54. package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +2 -2
  55. package/.next/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  56. package/.next/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +2 -2
  57. package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  58. package/.next/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  59. package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  60. package/.next/standalone/.next/server/app/admin/analytics.html +1 -1
  61. package/.next/standalone/.next/server/app/admin/analytics.rsc +7 -6
  62. package/.next/standalone/.next/server/app/admin/analytics.segments/!KGRlc2t0b3Ap/admin/analytics/__PAGE__.segment.rsc +2 -2
  63. package/.next/standalone/.next/server/app/admin/analytics.segments/!KGRlc2t0b3Ap/admin/analytics.segment.rsc +1 -1
  64. package/.next/standalone/.next/server/app/admin/analytics.segments/!KGRlc2t0b3Ap/admin.segment.rsc +1 -1
  65. package/.next/standalone/.next/server/app/admin/analytics.segments/!KGRlc2t0b3Ap.segment.rsc +1 -1
  66. package/.next/standalone/.next/server/app/admin/analytics.segments/_full.segment.rsc +7 -6
  67. package/.next/standalone/.next/server/app/admin/analytics.segments/_head.segment.rsc +1 -1
  68. package/.next/standalone/.next/server/app/admin/analytics.segments/_index.segment.rsc +2 -2
  69. package/.next/standalone/.next/server/app/admin/analytics.segments/_tree.segment.rsc +2 -2
  70. package/.next/standalone/.next/server/app/admin/users.html +1 -1
  71. package/.next/standalone/.next/server/app/admin/users.rsc +2 -2
  72. package/.next/standalone/.next/server/app/admin/users.segments/!KGRlc2t0b3Ap/admin/users/__PAGE__.segment.rsc +1 -1
  73. package/.next/standalone/.next/server/app/admin/users.segments/!KGRlc2t0b3Ap/admin/users.segment.rsc +1 -1
  74. package/.next/standalone/.next/server/app/admin/users.segments/!KGRlc2t0b3Ap/admin.segment.rsc +1 -1
  75. package/.next/standalone/.next/server/app/admin/users.segments/!KGRlc2t0b3Ap.segment.rsc +1 -1
  76. package/.next/standalone/.next/server/app/admin/users.segments/_full.segment.rsc +2 -2
  77. package/.next/standalone/.next/server/app/admin/users.segments/_head.segment.rsc +1 -1
  78. package/.next/standalone/.next/server/app/admin/users.segments/_index.segment.rsc +2 -2
  79. package/.next/standalone/.next/server/app/admin/users.segments/_tree.segment.rsc +2 -2
  80. package/.next/standalone/.next/server/app/analytics.html +1 -1
  81. package/.next/standalone/.next/server/app/analytics.rsc +3 -3
  82. package/.next/standalone/.next/server/app/analytics.segments/!KGRlc2t0b3Ap/analytics/__PAGE__.segment.rsc +2 -2
  83. package/.next/standalone/.next/server/app/analytics.segments/!KGRlc2t0b3Ap/analytics.segment.rsc +1 -1
  84. package/.next/standalone/.next/server/app/analytics.segments/!KGRlc2t0b3Ap.segment.rsc +1 -1
  85. package/.next/standalone/.next/server/app/analytics.segments/_full.segment.rsc +3 -3
  86. package/.next/standalone/.next/server/app/analytics.segments/_head.segment.rsc +1 -1
  87. package/.next/standalone/.next/server/app/analytics.segments/_index.segment.rsc +2 -2
  88. package/.next/standalone/.next/server/app/analytics.segments/_tree.segment.rsc +2 -2
  89. package/.next/standalone/.next/server/app/api/analytics/overview/route.js.nft.json +1 -1
  90. package/.next/standalone/.next/server/app/api/bulk/route.js.nft.json +1 -1
  91. package/.next/standalone/.next/server/app/api/config/route.js.nft.json +1 -1
  92. package/.next/standalone/.next/server/app/api/cortex/context/route.js.nft.json +1 -1
  93. package/.next/standalone/.next/server/app/api/cortex/curation/assess/route.js.nft.json +1 -1
  94. package/.next/standalone/.next/server/app/api/cortex/curation/publish/route.js.nft.json +1 -1
  95. package/.next/standalone/.next/server/app/api/cortex/curation/refine/route.js.nft.json +1 -1
  96. package/.next/standalone/.next/server/app/api/cortex/curation/review/route.js.nft.json +1 -1
  97. package/.next/standalone/.next/server/app/api/cortex/curation/seed/route.js.nft.json +1 -1
  98. package/.next/standalone/.next/server/app/api/cortex/export/route.js.nft.json +1 -1
  99. package/.next/standalone/.next/server/app/api/cortex/federation/pending/route.js.nft.json +1 -1
  100. package/.next/standalone/.next/server/app/api/cortex/federation/resolve/route.js.nft.json +1 -1
  101. package/.next/standalone/.next/server/app/api/cortex/federation/search/route.js.nft.json +1 -1
  102. package/.next/standalone/.next/server/app/api/cortex/federation/teach/route.js.nft.json +1 -1
  103. package/.next/standalone/.next/server/app/api/cortex/graph/edges/route.js.nft.json +1 -1
  104. package/.next/standalone/.next/server/app/api/cortex/graph/entities/[id]/route.js.nft.json +1 -1
  105. package/.next/standalone/.next/server/app/api/cortex/graph/entities/route.js.nft.json +1 -1
  106. package/.next/standalone/.next/server/app/api/cortex/graph/populate/route.js.nft.json +1 -1
  107. package/.next/standalone/.next/server/app/api/cortex/import/route.js.nft.json +1 -1
  108. package/.next/standalone/.next/server/app/api/cortex/import/status/route.js.nft.json +1 -1
  109. package/.next/standalone/.next/server/app/api/cortex/ingest/bootstrap/route.js.nft.json +1 -1
  110. package/.next/standalone/.next/server/app/api/cortex/ingest/status/route.js.nft.json +1 -1
  111. package/.next/standalone/.next/server/app/api/cortex/knowledge/[id]/route.js.nft.json +1 -1
  112. package/.next/standalone/.next/server/app/api/cortex/knowledge/route.js.nft.json +1 -1
  113. package/.next/standalone/.next/server/app/api/cortex/lobes/[id]/route.js.nft.json +1 -1
  114. package/.next/standalone/.next/server/app/api/cortex/lobes/route.js.nft.json +1 -1
  115. package/.next/standalone/.next/server/app/api/cortex/lobes/share/route.js.nft.json +1 -1
  116. package/.next/standalone/.next/server/app/api/cortex/marketplace/browse/route.js.nft.json +1 -1
  117. package/.next/standalone/.next/server/app/api/cortex/marketplace/preview/route.js.nft.json +1 -1
  118. package/.next/standalone/.next/server/app/api/cortex/mcp/call/route.js.nft.json +1 -1
  119. package/.next/standalone/.next/server/app/api/cortex/mcp/tools/route.js.nft.json +1 -1
  120. package/.next/standalone/.next/server/app/api/cortex/search/route.js.nft.json +1 -1
  121. package/.next/standalone/.next/server/app/api/cortex/settings/route.js.nft.json +1 -1
  122. package/.next/standalone/.next/server/app/api/cortex/status/route.js.nft.json +1 -1
  123. package/.next/standalone/.next/server/app/api/cortex/timeline/route.js.nft.json +1 -1
  124. package/.next/standalone/.next/server/app/api/cortex/usage/route.js.nft.json +1 -1
  125. package/.next/standalone/.next/server/app/api/cortex/workspace/[id]/context/route.js.nft.json +1 -1
  126. package/.next/standalone/.next/server/app/api/events/route.js.nft.json +1 -1
  127. package/.next/standalone/.next/server/app/api/folders/route.js.nft.json +1 -1
  128. package/.next/standalone/.next/server/app/api/network/handshake/route.js.nft.json +1 -1
  129. package/.next/standalone/.next/server/app/api/network/projects/route.js.nft.json +1 -1
  130. package/.next/standalone/.next/server/app/api/network/search/route.js.nft.json +1 -1
  131. package/.next/standalone/.next/server/app/api/network/sessions/[id]/messages/route.js.nft.json +1 -1
  132. package/.next/standalone/.next/server/app/api/network/sessions/[id]/route.js.nft.json +1 -1
  133. package/.next/standalone/.next/server/app/api/network/sessions/route.js.nft.json +1 -1
  134. package/.next/standalone/.next/server/app/api/network/workspaces/[id]/route.js.nft.json +1 -1
  135. package/.next/standalone/.next/server/app/api/network/workspaces/route.js.nft.json +1 -1
  136. package/.next/standalone/.next/server/app/api/panes/[id]/route.js.nft.json +1 -1
  137. package/.next/standalone/.next/server/app/api/panes/route.js.nft.json +1 -1
  138. package/.next/standalone/.next/server/app/api/projects/route.js.nft.json +1 -1
  139. package/.next/standalone/.next/server/app/api/search/route.js.nft.json +1 -1
  140. package/.next/standalone/.next/server/app/api/sessions/[id]/chat/route.js.nft.json +1 -1
  141. package/.next/standalone/.next/server/app/api/sessions/[id]/messages/route.js.nft.json +1 -1
  142. package/.next/standalone/.next/server/app/api/sessions/[id]/route.js.nft.json +1 -1
  143. package/.next/standalone/.next/server/app/api/sessions/route.js.nft.json +1 -1
  144. package/.next/standalone/.next/server/app/api/sync/route.js.nft.json +1 -1
  145. package/.next/standalone/.next/server/app/api/tags/route.js.nft.json +1 -1
  146. package/.next/standalone/.next/server/app/api/tier/route.js.nft.json +1 -1
  147. package/.next/standalone/.next/server/app/api/workspaces/[id]/context/[key]/route.js.nft.json +1 -1
  148. package/.next/standalone/.next/server/app/api/workspaces/[id]/context/route.js.nft.json +1 -1
  149. package/.next/standalone/.next/server/app/api/workspaces/[id]/messages/[msgId]/route.js.nft.json +1 -1
  150. package/.next/standalone/.next/server/app/api/workspaces/[id]/messages/route.js.nft.json +1 -1
  151. package/.next/standalone/.next/server/app/api/workspaces/[id]/route.js.nft.json +1 -1
  152. package/.next/standalone/.next/server/app/api/workspaces/[id]/sessions/route.js.nft.json +1 -1
  153. package/.next/standalone/.next/server/app/api/workspaces/route.js.nft.json +1 -1
  154. package/.next/standalone/.next/server/app/cortex.html +1 -1
  155. package/.next/standalone/.next/server/app/cortex.rsc +3 -3
  156. package/.next/standalone/.next/server/app/cortex.segments/!KGRlc2t0b3Ap/cortex/__PAGE__.segment.rsc +2 -2
  157. package/.next/standalone/.next/server/app/cortex.segments/!KGRlc2t0b3Ap/cortex.segment.rsc +1 -1
  158. package/.next/standalone/.next/server/app/cortex.segments/!KGRlc2t0b3Ap.segment.rsc +1 -1
  159. package/.next/standalone/.next/server/app/cortex.segments/_full.segment.rsc +3 -3
  160. package/.next/standalone/.next/server/app/cortex.segments/_head.segment.rsc +1 -1
  161. package/.next/standalone/.next/server/app/cortex.segments/_index.segment.rsc +2 -2
  162. package/.next/standalone/.next/server/app/cortex.segments/_tree.segment.rsc +2 -2
  163. package/.next/standalone/.next/server/app/login/page/build-manifest.json +3 -3
  164. package/.next/standalone/.next/server/app/login/page_client-reference-manifest.js +1 -1
  165. package/.next/standalone/.next/server/app/login.html +1 -1
  166. package/.next/standalone/.next/server/app/login.rsc +2 -2
  167. package/.next/standalone/.next/server/app/login.segments/_full.segment.rsc +2 -2
  168. package/.next/standalone/.next/server/app/login.segments/_head.segment.rsc +1 -1
  169. package/.next/standalone/.next/server/app/login.segments/_index.segment.rsc +2 -2
  170. package/.next/standalone/.next/server/app/login.segments/_tree.segment.rsc +2 -2
  171. package/.next/standalone/.next/server/app/login.segments/login/__PAGE__.segment.rsc +1 -1
  172. package/.next/standalone/.next/server/app/login.segments/login.segment.rsc +1 -1
  173. package/.next/standalone/.next/server/app/m/page/build-manifest.json +3 -3
  174. package/.next/standalone/.next/server/app/m/page_client-reference-manifest.js +1 -1
  175. package/.next/standalone/.next/server/app/m/projects/page/build-manifest.json +3 -3
  176. package/.next/standalone/.next/server/app/m/projects/page_client-reference-manifest.js +1 -1
  177. package/.next/standalone/.next/server/app/m/projects.html +1 -1
  178. package/.next/standalone/.next/server/app/m/projects.rsc +2 -2
  179. package/.next/standalone/.next/server/app/m/projects.segments/_full.segment.rsc +2 -2
  180. package/.next/standalone/.next/server/app/m/projects.segments/_head.segment.rsc +1 -1
  181. package/.next/standalone/.next/server/app/m/projects.segments/_index.segment.rsc +2 -2
  182. package/.next/standalone/.next/server/app/m/projects.segments/_tree.segment.rsc +2 -2
  183. package/.next/standalone/.next/server/app/m/projects.segments/m/projects/__PAGE__.segment.rsc +1 -1
  184. package/.next/standalone/.next/server/app/m/projects.segments/m/projects.segment.rsc +1 -1
  185. package/.next/standalone/.next/server/app/m/projects.segments/m.segment.rsc +1 -1
  186. package/.next/standalone/.next/server/app/m/sessions/[id]/page/build-manifest.json +3 -3
  187. package/.next/standalone/.next/server/app/m/sessions/[id]/page_client-reference-manifest.js +1 -1
  188. package/.next/standalone/.next/server/app/m/sessions/page/build-manifest.json +3 -3
  189. package/.next/standalone/.next/server/app/m/sessions/page_client-reference-manifest.js +1 -1
  190. package/.next/standalone/.next/server/app/m/sessions.html +1 -1
  191. package/.next/standalone/.next/server/app/m/sessions.rsc +2 -2
  192. package/.next/standalone/.next/server/app/m/sessions.segments/_full.segment.rsc +2 -2
  193. package/.next/standalone/.next/server/app/m/sessions.segments/_head.segment.rsc +1 -1
  194. package/.next/standalone/.next/server/app/m/sessions.segments/_index.segment.rsc +2 -2
  195. package/.next/standalone/.next/server/app/m/sessions.segments/_tree.segment.rsc +2 -2
  196. package/.next/standalone/.next/server/app/m/sessions.segments/m/sessions/__PAGE__.segment.rsc +1 -1
  197. package/.next/standalone/.next/server/app/m/sessions.segments/m/sessions.segment.rsc +1 -1
  198. package/.next/standalone/.next/server/app/m/sessions.segments/m.segment.rsc +1 -1
  199. package/.next/standalone/.next/server/app/m/settings/page/build-manifest.json +3 -3
  200. package/.next/standalone/.next/server/app/m/settings/page_client-reference-manifest.js +1 -1
  201. package/.next/standalone/.next/server/app/m/settings.html +1 -1
  202. package/.next/standalone/.next/server/app/m/settings.rsc +2 -2
  203. package/.next/standalone/.next/server/app/m/settings.segments/_full.segment.rsc +2 -2
  204. package/.next/standalone/.next/server/app/m/settings.segments/_head.segment.rsc +1 -1
  205. package/.next/standalone/.next/server/app/m/settings.segments/_index.segment.rsc +2 -2
  206. package/.next/standalone/.next/server/app/m/settings.segments/_tree.segment.rsc +2 -2
  207. package/.next/standalone/.next/server/app/m/settings.segments/m/settings/__PAGE__.segment.rsc +1 -1
  208. package/.next/standalone/.next/server/app/m/settings.segments/m/settings.segment.rsc +1 -1
  209. package/.next/standalone/.next/server/app/m/settings.segments/m.segment.rsc +1 -1
  210. package/.next/standalone/.next/server/app/m/terminal/page/build-manifest.json +3 -3
  211. package/.next/standalone/.next/server/app/m/terminal/page_client-reference-manifest.js +1 -1
  212. package/.next/standalone/.next/server/app/m/terminal.html +1 -1
  213. package/.next/standalone/.next/server/app/m/terminal.rsc +2 -2
  214. package/.next/standalone/.next/server/app/m/terminal.segments/_full.segment.rsc +2 -2
  215. package/.next/standalone/.next/server/app/m/terminal.segments/_head.segment.rsc +1 -1
  216. package/.next/standalone/.next/server/app/m/terminal.segments/_index.segment.rsc +2 -2
  217. package/.next/standalone/.next/server/app/m/terminal.segments/_tree.segment.rsc +2 -2
  218. package/.next/standalone/.next/server/app/m/terminal.segments/m/terminal/__PAGE__.segment.rsc +1 -1
  219. package/.next/standalone/.next/server/app/m/terminal.segments/m/terminal.segment.rsc +1 -1
  220. package/.next/standalone/.next/server/app/m/terminal.segments/m.segment.rsc +1 -1
  221. package/.next/standalone/.next/server/app/m.html +1 -1
  222. package/.next/standalone/.next/server/app/m.rsc +2 -2
  223. package/.next/standalone/.next/server/app/m.segments/_full.segment.rsc +2 -2
  224. package/.next/standalone/.next/server/app/m.segments/_head.segment.rsc +1 -1
  225. package/.next/standalone/.next/server/app/m.segments/_index.segment.rsc +2 -2
  226. package/.next/standalone/.next/server/app/m.segments/_tree.segment.rsc +2 -2
  227. package/.next/standalone/.next/server/app/m.segments/m/__PAGE__.segment.rsc +1 -1
  228. package/.next/standalone/.next/server/app/m.segments/m.segment.rsc +1 -1
  229. package/.next/standalone/.next/server/app/network.html +1 -1
  230. package/.next/standalone/.next/server/app/network.rsc +2 -2
  231. package/.next/standalone/.next/server/app/network.segments/!KGRlc2t0b3Ap/network/__PAGE__.segment.rsc +1 -1
  232. package/.next/standalone/.next/server/app/network.segments/!KGRlc2t0b3Ap/network.segment.rsc +1 -1
  233. package/.next/standalone/.next/server/app/network.segments/!KGRlc2t0b3Ap.segment.rsc +1 -1
  234. package/.next/standalone/.next/server/app/network.segments/_full.segment.rsc +2 -2
  235. package/.next/standalone/.next/server/app/network.segments/_head.segment.rsc +1 -1
  236. package/.next/standalone/.next/server/app/network.segments/_index.segment.rsc +2 -2
  237. package/.next/standalone/.next/server/app/network.segments/_tree.segment.rsc +2 -2
  238. package/.next/standalone/.next/server/app/projects.html +1 -1
  239. package/.next/standalone/.next/server/app/projects.rsc +2 -2
  240. package/.next/standalone/.next/server/app/projects.segments/!KGRlc2t0b3Ap/projects/__PAGE__.segment.rsc +1 -1
  241. package/.next/standalone/.next/server/app/projects.segments/!KGRlc2t0b3Ap/projects.segment.rsc +1 -1
  242. package/.next/standalone/.next/server/app/projects.segments/!KGRlc2t0b3Ap.segment.rsc +1 -1
  243. package/.next/standalone/.next/server/app/projects.segments/_full.segment.rsc +2 -2
  244. package/.next/standalone/.next/server/app/projects.segments/_head.segment.rsc +1 -1
  245. package/.next/standalone/.next/server/app/projects.segments/_index.segment.rsc +2 -2
  246. package/.next/standalone/.next/server/app/projects.segments/_tree.segment.rsc +2 -2
  247. package/.next/standalone/.next/server/app/sessions.html +1 -1
  248. package/.next/standalone/.next/server/app/sessions.rsc +2 -2
  249. package/.next/standalone/.next/server/app/sessions.segments/!KGRlc2t0b3Ap/sessions/__PAGE__.segment.rsc +1 -1
  250. package/.next/standalone/.next/server/app/sessions.segments/!KGRlc2t0b3Ap/sessions.segment.rsc +1 -1
  251. package/.next/standalone/.next/server/app/sessions.segments/!KGRlc2t0b3Ap.segment.rsc +1 -1
  252. package/.next/standalone/.next/server/app/sessions.segments/_full.segment.rsc +2 -2
  253. package/.next/standalone/.next/server/app/sessions.segments/_head.segment.rsc +1 -1
  254. package/.next/standalone/.next/server/app/sessions.segments/_index.segment.rsc +2 -2
  255. package/.next/standalone/.next/server/app/sessions.segments/_tree.segment.rsc +2 -2
  256. package/.next/standalone/.next/server/app/settings.html +1 -1
  257. package/.next/standalone/.next/server/app/settings.rsc +2 -2
  258. package/.next/standalone/.next/server/app/settings.segments/!KGRlc2t0b3Ap/settings/__PAGE__.segment.rsc +1 -1
  259. package/.next/standalone/.next/server/app/settings.segments/!KGRlc2t0b3Ap/settings.segment.rsc +1 -1
  260. package/.next/standalone/.next/server/app/settings.segments/!KGRlc2t0b3Ap.segment.rsc +1 -1
  261. package/.next/standalone/.next/server/app/settings.segments/_full.segment.rsc +2 -2
  262. package/.next/standalone/.next/server/app/settings.segments/_head.segment.rsc +1 -1
  263. package/.next/standalone/.next/server/app/settings.segments/_index.segment.rsc +2 -2
  264. package/.next/standalone/.next/server/app/settings.segments/_tree.segment.rsc +2 -2
  265. package/.next/standalone/.next/server/app/terminal.html +1 -1
  266. package/.next/standalone/.next/server/app/terminal.rsc +3 -3
  267. package/.next/standalone/.next/server/app/terminal.segments/!KGRlc2t0b3Ap/terminal/__PAGE__.segment.rsc +2 -2
  268. package/.next/standalone/.next/server/app/terminal.segments/!KGRlc2t0b3Ap/terminal.segment.rsc +1 -1
  269. package/.next/standalone/.next/server/app/terminal.segments/!KGRlc2t0b3Ap.segment.rsc +1 -1
  270. package/.next/standalone/.next/server/app/terminal.segments/_full.segment.rsc +3 -3
  271. package/.next/standalone/.next/server/app/terminal.segments/_head.segment.rsc +1 -1
  272. package/.next/standalone/.next/server/app/terminal.segments/_index.segment.rsc +2 -2
  273. package/.next/standalone/.next/server/app/terminal.segments/_tree.segment.rsc +2 -2
  274. package/.next/standalone/.next/server/app/vr/page/app-paths-manifest.json +3 -0
  275. package/.next/standalone/.next/server/app/vr/page/build-manifest.json +18 -0
  276. package/.next/standalone/.next/server/app/vr/page/next-font-manifest.json +11 -0
  277. package/.next/standalone/.next/server/app/vr/page/react-loadable-manifest.json +11 -0
  278. package/.next/standalone/.next/server/app/vr/page/server-reference-manifest.json +4 -0
  279. package/.next/standalone/.next/server/app/vr/page.js +17 -0
  280. package/.next/standalone/.next/server/app/vr/page.js.map +5 -0
  281. package/.next/standalone/.next/server/app/vr/page.js.nft.json +1 -0
  282. package/.next/standalone/.next/server/app/vr/page_client-reference-manifest.js +2 -0
  283. package/.next/standalone/.next/server/app/vr.html +1 -0
  284. package/.next/standalone/.next/server/app/vr.meta +15 -0
  285. package/.next/standalone/.next/server/app/vr.rsc +21 -0
  286. package/.next/standalone/.next/server/app/vr.segments/_full.segment.rsc +21 -0
  287. package/.next/standalone/.next/server/app/vr.segments/_head.segment.rsc +6 -0
  288. package/.next/standalone/.next/server/app/vr.segments/_index.segment.rsc +6 -0
  289. package/.next/standalone/.next/server/app/vr.segments/_tree.segment.rsc +4 -0
  290. package/.next/standalone/.next/server/app/vr.segments/vr/__PAGE__.segment.rsc +9 -0
  291. package/.next/standalone/.next/server/app/vr.segments/vr.segment.rsc +4 -0
  292. package/.next/standalone/.next/server/app/workspaces.html +1 -1
  293. package/.next/standalone/.next/server/app/workspaces.rsc +2 -2
  294. package/.next/standalone/.next/server/app/workspaces.segments/!KGRlc2t0b3Ap/workspaces/__PAGE__.segment.rsc +1 -1
  295. package/.next/standalone/.next/server/app/workspaces.segments/!KGRlc2t0b3Ap/workspaces.segment.rsc +1 -1
  296. package/.next/standalone/.next/server/app/workspaces.segments/!KGRlc2t0b3Ap.segment.rsc +1 -1
  297. package/.next/standalone/.next/server/app/workspaces.segments/_full.segment.rsc +2 -2
  298. package/.next/standalone/.next/server/app/workspaces.segments/_head.segment.rsc +1 -1
  299. package/.next/standalone/.next/server/app/workspaces.segments/_index.segment.rsc +2 -2
  300. package/.next/standalone/.next/server/app/workspaces.segments/_tree.segment.rsc +2 -2
  301. package/.next/standalone/.next/server/app-paths-manifest.json +2 -1
  302. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0041efe4._.js +2 -2
  303. package/.next/standalone/.next/server/chunks/[root-of-the-server]__00bf0ace._.js +2 -2
  304. package/.next/standalone/.next/server/chunks/[root-of-the-server]__08a68343._.js +1 -1
  305. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0add852f._.js +1 -1
  306. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0c113ed0._.js +1 -1
  307. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0e1a27e0._.js +1 -1
  308. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0e71d908._.js +3 -3
  309. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0e9142f3._.js +2 -2
  310. package/.next/standalone/.next/server/chunks/[root-of-the-server]__10e47926._.js +2 -2
  311. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1194f2c1._.js +1 -1
  312. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1665dc78._.js +2 -2
  313. package/.next/standalone/.next/server/chunks/[root-of-the-server]__175cbabf._.js +2 -2
  314. package/.next/standalone/.next/server/chunks/[root-of-the-server]__19c2d094._.js +1 -1
  315. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1adae357._.js +2 -2
  316. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1d359752._.js +2 -2
  317. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1e8fabeb._.js +3 -3
  318. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1f8deca0._.js +8 -8
  319. package/.next/standalone/.next/server/chunks/[root-of-the-server]__253fdda1._.js +2 -2
  320. package/.next/standalone/.next/server/chunks/[root-of-the-server]__28e6434f._.js +2 -2
  321. package/.next/standalone/.next/server/chunks/[root-of-the-server]__2a386564._.js +3 -3
  322. package/.next/standalone/.next/server/chunks/[root-of-the-server]__2acbd703._.js +1 -1
  323. package/.next/standalone/.next/server/chunks/[root-of-the-server]__2acefabb._.js +1 -1
  324. package/.next/standalone/.next/server/chunks/[root-of-the-server]__2c20fb38._.js +2 -2
  325. package/.next/standalone/.next/server/chunks/[root-of-the-server]__309132cd._.js +1 -1
  326. package/.next/standalone/.next/server/chunks/[root-of-the-server]__33fec964._.js +3 -3
  327. package/.next/standalone/.next/server/chunks/[root-of-the-server]__3786d8ae._.js +2 -2
  328. package/.next/standalone/.next/server/chunks/[root-of-the-server]__3ae92407._.js +2 -2
  329. package/.next/standalone/.next/server/chunks/[root-of-the-server]__3beda9fe._.js +2 -2
  330. package/.next/standalone/.next/server/chunks/[root-of-the-server]__3e3f25a1._.js +1 -1
  331. package/.next/standalone/.next/server/chunks/[root-of-the-server]__4619e9bd._.js +1 -1
  332. package/.next/standalone/.next/server/chunks/[root-of-the-server]__4a051043._.js +2 -2
  333. package/.next/standalone/.next/server/chunks/[root-of-the-server]__50208a5f._.js +1 -1
  334. package/.next/standalone/.next/server/chunks/[root-of-the-server]__508002e4._.js +2 -2
  335. package/.next/standalone/.next/server/chunks/[root-of-the-server]__5086c373._.js +2 -2
  336. package/.next/standalone/.next/server/chunks/[root-of-the-server]__5913e097._.js +2 -2
  337. package/.next/standalone/.next/server/chunks/[root-of-the-server]__5b5f68d2._.js +2 -2
  338. package/.next/standalone/.next/server/chunks/[root-of-the-server]__5c1f2459._.js +2 -2
  339. package/.next/standalone/.next/server/chunks/[root-of-the-server]__5ec8c977._.js +2 -2
  340. package/.next/standalone/.next/server/chunks/[root-of-the-server]__5f8c694a._.js +1 -1
  341. package/.next/standalone/.next/server/chunks/[root-of-the-server]__63cebc6c._.js +2 -2
  342. package/.next/standalone/.next/server/chunks/[root-of-the-server]__64d30d4d._.js +2 -2
  343. package/.next/standalone/.next/server/chunks/[root-of-the-server]__6c54fc2e._.js +2 -2
  344. package/.next/standalone/.next/server/chunks/[root-of-the-server]__6dc1fb7e._.js +2 -2
  345. package/.next/standalone/.next/server/chunks/[root-of-the-server]__6e568102._.js +2 -2
  346. package/.next/standalone/.next/server/chunks/[root-of-the-server]__6faa04c0._.js +2 -2
  347. package/.next/standalone/.next/server/chunks/[root-of-the-server]__727d05f1._.js +1 -1
  348. package/.next/standalone/.next/server/chunks/[root-of-the-server]__74a34dc3._.js +2 -2
  349. package/.next/standalone/.next/server/chunks/[root-of-the-server]__75d12b32._.js +1 -1
  350. package/.next/standalone/.next/server/chunks/[root-of-the-server]__7e7250a4._.js +2 -2
  351. package/.next/standalone/.next/server/chunks/[root-of-the-server]__8309e0a4._.js +2 -2
  352. package/.next/standalone/.next/server/chunks/[root-of-the-server]__86cc0e2b._.js +6 -6
  353. package/.next/standalone/.next/server/chunks/[root-of-the-server]__8915603e._.js +1 -1
  354. package/.next/standalone/.next/server/chunks/[root-of-the-server]__89c2565a._.js +2 -2
  355. package/.next/standalone/.next/server/chunks/[root-of-the-server]__8d178ad9._.js +2 -2
  356. package/.next/standalone/.next/server/chunks/[root-of-the-server]__93ee06f3._.js +3 -3
  357. package/.next/standalone/.next/server/chunks/[root-of-the-server]__9e4c154a._.js +2 -2
  358. package/.next/standalone/.next/server/chunks/[root-of-the-server]__a1fbc199._.js +1 -1
  359. package/.next/standalone/.next/server/chunks/[root-of-the-server]__a9d2e1d3._.js +2 -2
  360. package/.next/standalone/.next/server/chunks/[root-of-the-server]__ae53d343._.js +2 -2
  361. package/.next/standalone/.next/server/chunks/[root-of-the-server]__b3a04cef._.js +2 -2
  362. package/.next/standalone/.next/server/chunks/[root-of-the-server]__b4270b77._.js +1 -1
  363. package/.next/standalone/.next/server/chunks/[root-of-the-server]__b6b6ce60._.js +1 -1
  364. package/.next/standalone/.next/server/chunks/[root-of-the-server]__b9545dd9._.js +1 -1
  365. package/.next/standalone/.next/server/chunks/[root-of-the-server]__c200e21a._.js +1 -1
  366. package/.next/standalone/.next/server/chunks/[root-of-the-server]__c3c74ca4._.js +1 -1
  367. package/.next/standalone/.next/server/chunks/[root-of-the-server]__c88b63f7._.js +2 -2
  368. package/.next/standalone/.next/server/chunks/[root-of-the-server]__cba5f007._.js +1 -1
  369. package/.next/standalone/.next/server/chunks/[root-of-the-server]__cbf4ceb0._.js +2 -2
  370. package/.next/standalone/.next/server/chunks/[root-of-the-server]__cefdba2f._.js +2 -2
  371. package/.next/standalone/.next/server/chunks/[root-of-the-server]__cf9e82bb._.js +2 -2
  372. package/.next/standalone/.next/server/chunks/[root-of-the-server]__d15515e3._.js +1 -1
  373. package/.next/standalone/.next/server/chunks/[root-of-the-server]__d2897392._.js +2 -2
  374. package/.next/standalone/.next/server/chunks/[root-of-the-server]__d3b2d856._.js +2 -2
  375. package/.next/standalone/.next/server/chunks/[root-of-the-server]__d73273ca._.js +2 -2
  376. package/.next/standalone/.next/server/chunks/[root-of-the-server]__d8417eb6._.js +2 -2
  377. package/.next/standalone/.next/server/chunks/[root-of-the-server]__db4726bc._.js +1 -1
  378. package/.next/standalone/.next/server/chunks/[root-of-the-server]__dc2a55de._.js +2 -2
  379. package/.next/standalone/.next/server/chunks/[root-of-the-server]__dc6e2e5f._.js +1 -1
  380. package/.next/standalone/.next/server/chunks/[root-of-the-server]__e0d4690b._.js +3 -3
  381. package/.next/standalone/.next/server/chunks/[root-of-the-server]__e3ecfd17._.js +3 -3
  382. package/.next/standalone/.next/server/chunks/[root-of-the-server]__e678dd53._.js +1 -1
  383. package/.next/standalone/.next/server/chunks/[root-of-the-server]__e9223f55._.js +2 -2
  384. package/.next/standalone/.next/server/chunks/[root-of-the-server]__ea630076._.js +3 -3
  385. package/.next/standalone/.next/server/chunks/[root-of-the-server]__eb8acb65._.js +1 -1
  386. package/.next/standalone/.next/server/chunks/[root-of-the-server]__f26ca49d._.js +1 -1
  387. package/.next/standalone/.next/server/chunks/[root-of-the-server]__f33e1101._.js +2 -2
  388. package/.next/standalone/.next/server/chunks/[root-of-the-server]__f3a4c668._.js +1 -1
  389. package/.next/standalone/.next/server/chunks/[root-of-the-server]__f515f865._.js +2 -2
  390. package/.next/standalone/.next/server/chunks/[root-of-the-server]__fceb5d60._.js +2 -2
  391. package/.next/standalone/.next/server/chunks/[root-of-the-server]__fed41403._.js +2 -2
  392. package/.next/standalone/.next/server/chunks/[root-of-the-server]__ff2e98c2._.js +2 -2
  393. package/.next/standalone/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_339169c8.js +1 -1
  394. package/.next/standalone/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_97dac613.js +1 -1
  395. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0d8d81ca._.js +1 -1
  396. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1425c64f._.js +1 -1
  397. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1d2ce8f1._.js +1 -1
  398. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__31137509._.js +1 -1
  399. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__3633a587._.js +1 -1
  400. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__3c79441b._.js +1 -1
  401. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__4ca0f26b._.js +1 -1
  402. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__5b90d3ad._.js +3 -0
  403. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__62a0b363._.js +1 -1
  404. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__66aca5d4._.js +1 -1
  405. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__68205a46._.js +1 -1
  406. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__69fd2efa._.js +1 -1
  407. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__85dcf0f7._.js +1 -1
  408. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__8c53a5da._.js +1 -1
  409. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__aecb1873._.js +1 -1
  410. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__b02cd143._.js +1 -1
  411. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__b9bcde11._.js +3 -0
  412. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__cac90169._.js +1 -1
  413. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__d25de2f0._.js +1 -1
  414. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__e2f86be8._.js +1 -1
  415. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__ee626b5b._.js +1 -1
  416. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__f39a9e98._.js +1 -1
  417. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__f3c566cd._.js +1 -1
  418. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__f76aa221._.js +1 -1
  419. package/.next/standalone/.next/server/chunks/ssr/_149d7fd4._.js +1 -1
  420. package/.next/standalone/.next/server/chunks/ssr/_2e0dd6a7._.js +1 -1
  421. package/.next/standalone/.next/server/chunks/ssr/_3cd2355c._.js +1 -1
  422. package/.next/standalone/.next/server/chunks/ssr/_3d206597._.js +4 -0
  423. package/.next/standalone/.next/server/chunks/ssr/_47cc9af0._.js +1 -1
  424. package/.next/standalone/.next/server/chunks/ssr/_5cf334fd._.js +3 -0
  425. package/.next/standalone/.next/server/chunks/ssr/_7082788b._.js +1 -1
  426. package/.next/standalone/.next/server/chunks/ssr/_7154d8ae._.js +1 -1
  427. package/.next/standalone/.next/server/chunks/ssr/_75bb1b9a._.js +1 -1
  428. package/.next/standalone/.next/server/chunks/ssr/{_aeeff784._.js → _81abf587._.js} +2 -2
  429. package/.next/standalone/.next/server/chunks/ssr/_8acf81e2._.js +1 -1
  430. package/.next/standalone/.next/server/chunks/ssr/_8c36feb8._.js +1 -1
  431. package/.next/standalone/.next/server/chunks/ssr/_91e9bb86._.js +1 -1
  432. package/.next/standalone/.next/server/chunks/ssr/_ac4c1838._.js +1 -1
  433. package/.next/standalone/.next/server/chunks/ssr/_ad8515fc._.js +1 -1
  434. package/.next/standalone/.next/server/chunks/ssr/_b1f49e81._.js +1 -1
  435. package/.next/standalone/.next/server/chunks/ssr/_c0fe7614._.js +1 -1
  436. package/.next/standalone/.next/server/chunks/ssr/_d4825f5a._.js +1 -1
  437. package/.next/standalone/.next/server/chunks/ssr/_da10a9f4._.js +1 -1
  438. package/.next/standalone/.next/server/chunks/ssr/_db0abd0a._.js +3 -0
  439. package/.next/standalone/.next/server/chunks/ssr/_dee5d4a1._.js +1 -1
  440. package/.next/standalone/.next/server/chunks/ssr/_ef482c0c._.js +1 -1
  441. package/.next/standalone/.next/server/chunks/ssr/_efe43d2f._.js +1 -1
  442. package/.next/standalone/.next/server/chunks/ssr/_f4a4e116._.js +1 -1
  443. package/.next/standalone/.next/server/chunks/ssr/_f4d525d2._.js +1 -1
  444. package/.next/standalone/.next/server/chunks/ssr/_f4e57187._.js +3 -0
  445. package/.next/standalone/.next/server/chunks/ssr/_next-internal_server_app_vr_page_actions_3fb70d92.js +3 -0
  446. package/.next/standalone/.next/server/chunks/ssr/node_modules_32f9d62f._.js +1 -1
  447. package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_02f39477.js +1 -1
  448. package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_eedfc1fd._.js +1 -1
  449. package/.next/standalone/.next/server/chunks/ssr/src_40fa36ce._.js +7 -0
  450. package/.next/standalone/.next/server/chunks/ssr/src_app_(desktop)_cortex_page_tsx_0f33d8b3._.js +3 -0
  451. package/.next/standalone/.next/server/edge/chunks/[root-of-the-server]__32a0045c._.js +1 -1
  452. package/.next/standalone/.next/server/edge/chunks/_d73df637._.js +1 -1
  453. package/.next/standalone/.next/server/middleware-build-manifest.js +3 -3
  454. package/.next/standalone/.next/server/middleware-manifest.json +5 -5
  455. package/.next/standalone/.next/server/next-font-manifest.js +1 -1
  456. package/.next/standalone/.next/server/next-font-manifest.json +4 -0
  457. package/.next/standalone/.next/server/pages/404.html +1 -1
  458. package/.next/standalone/.next/server/pages/500.html +2 -2
  459. package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
  460. package/.next/standalone/.next/server/server-reference-manifest.json +1 -1
  461. package/.next/standalone/.next/static/chunks/045c83caa4d15373.js +1 -0
  462. package/.next/standalone/.next/static/chunks/07ea09e6024a523b.js +1 -0
  463. package/.next/standalone/.next/static/chunks/232d8aae4fefab70.js +1 -0
  464. package/.next/standalone/.next/static/chunks/2ad22562bb37ecad.js +1011 -0
  465. package/.next/standalone/.next/static/chunks/396eac60f496f178.js +1 -0
  466. package/.next/standalone/.next/static/chunks/{a4e5c700421eaa46.js → 412140a02893327a.js} +1 -1
  467. package/.next/standalone/.next/static/chunks/481cc11ae80b08b1.js +1 -0
  468. package/.next/standalone/.next/static/chunks/5325351ef49cb65f.js +1 -0
  469. package/.next/standalone/.next/static/chunks/559735e598ca3cbb.js +1 -0
  470. package/.next/standalone/.next/static/chunks/59c63d5af5cf3daf.js +1 -0
  471. package/.next/standalone/.next/static/chunks/5d5d7b0095dd52ae.js +1 -0
  472. package/.next/standalone/.next/static/chunks/6ae575967d091df4.js +1 -0
  473. package/.next/standalone/.next/static/chunks/7a7c0d9d875332a3.js +1 -0
  474. package/.next/standalone/.next/static/chunks/7f8455bb855a6c84.js +1 -0
  475. package/.next/standalone/.next/static/chunks/898f380eba90427a.js +1 -0
  476. package/.next/standalone/.next/static/chunks/95339e55722bb4ca.js +5 -0
  477. package/.next/standalone/.next/static/chunks/9cd594813c539df9.js +1 -0
  478. package/.next/standalone/.next/static/chunks/ad1423eed05d129b.js +1 -0
  479. package/.next/standalone/.next/static/chunks/ae7b146884c67d2a.js +1 -0
  480. package/.next/standalone/.next/static/chunks/b84072d72aa86417.js +1 -0
  481. package/.next/standalone/.next/static/chunks/c1a95aebf6725f64.css +3 -0
  482. package/.next/standalone/.next/static/chunks/c515eb77d9410aa0.js +5 -0
  483. package/.next/standalone/.next/static/chunks/{9899cf4c2bdbe61d.js → d9ae203a7f123546.js} +2 -2
  484. package/.next/standalone/.next/static/chunks/e23f20b51a75a5bb.js +757 -0
  485. package/.next/standalone/.next/static/chunks/fdc09bd135846960.js +1 -0
  486. package/.next/standalone/.next/static/chunks/ff0196911449e745.js +1 -0
  487. package/.next/standalone/.next/static/chunks/{turbopack-4c21186b79fb4c10.js → turbopack-e1a0994ed4af988c.js} +1 -1
  488. package/.next/standalone/.spaces/cortex-context.md +70 -0
  489. package/.next/standalone/bin/cortex-hook.sh +62 -62
  490. package/.next/standalone/bin/cortex-mcp.js +60 -60
  491. package/.next/standalone/docs/superpowers/plans/2026-03-13-cortex-wiring.md +1387 -1387
  492. package/.next/standalone/docs/superpowers/plans/2026-03-14-cortex-v2-entity-graph.md +1923 -1923
  493. package/.next/standalone/docs/superpowers/plans/2026-03-14-cortex-v2-knowledge-evolution.md +1113 -1113
  494. package/.next/standalone/docs/superpowers/plans/2026-03-15-cortex-v2-boundary-engine.md +853 -853
  495. package/.next/standalone/docs/superpowers/plans/2026-03-15-cortex-v2-context-engine.md +1274 -1274
  496. package/.next/standalone/docs/superpowers/plans/2026-03-15-cortex-v2-signal-ingestion.md +933 -933
  497. package/.next/standalone/docs/superpowers/plans/2026-03-16-cortex-lobes.md +1080 -1080
  498. package/.next/standalone/docs/superpowers/plans/2026-03-16-cortex-v2-gravity-system.md +768 -768
  499. package/.next/standalone/docs/superpowers/plans/2026-03-16-cortex-v2-ui.md +1108 -1108
  500. package/.next/standalone/docs/superpowers/plans/2026-03-18-cortex-ui-integration.md +1846 -1846
  501. package/.next/standalone/docs/superpowers/specs/2026-03-13-cortex-wiring-design.md +268 -268
  502. package/.next/standalone/docs/superpowers/specs/2026-03-14-cortex-v2-design.md +623 -623
  503. package/.next/standalone/docs/superpowers/specs/2026-03-16-cortex-lobes-design.md +263 -263
  504. package/.next/standalone/docs/superpowers/specs/2026-03-16-cortex-v2-ui-design.md +240 -240
  505. package/.next/standalone/docs/superpowers/specs/2026-03-18-cortex-ui-integration-design.md +341 -341
  506. package/.next/standalone/node_modules/@img/sharp-win32-x64/lib/sharp-win32-x64.node +0 -0
  507. package/.next/standalone/node_modules/@img/{sharp-linux-x64 → sharp-win32-x64}/package.json +39 -46
  508. package/.next/standalone/package.json +103 -102
  509. package/.next/standalone/server.js +1 -1
  510. package/.next/standalone/src/app/(desktop)/cortex/page.tsx +78 -78
  511. package/.next/standalone/src/app/api/cortex/context/route.ts +78 -78
  512. package/.next/standalone/src/app/api/cortex/curation/assess/route.ts +27 -27
  513. package/.next/standalone/src/app/api/cortex/curation/publish/route.ts +23 -23
  514. package/.next/standalone/src/app/api/cortex/curation/refine/route.ts +23 -23
  515. package/.next/standalone/src/app/api/cortex/curation/review/route.ts +29 -29
  516. package/.next/standalone/src/app/api/cortex/curation/seed/route.ts +23 -23
  517. package/.next/standalone/src/app/api/cortex/export/route.ts +40 -40
  518. package/.next/standalone/src/app/api/cortex/federation/pending/route.ts +20 -20
  519. package/.next/standalone/src/app/api/cortex/federation/resolve/route.ts +43 -43
  520. package/.next/standalone/src/app/api/cortex/federation/search/route.ts +35 -35
  521. package/.next/standalone/src/app/api/cortex/federation/teach/route.ts +76 -76
  522. package/.next/standalone/src/app/api/cortex/graph/edges/route.ts +112 -112
  523. package/.next/standalone/src/app/api/cortex/graph/entities/[id]/route.ts +73 -73
  524. package/.next/standalone/src/app/api/cortex/graph/entities/route.ts +75 -75
  525. package/.next/standalone/src/app/api/cortex/graph/populate/route.ts +203 -203
  526. package/.next/standalone/src/app/api/cortex/import/route.ts +75 -75
  527. package/.next/standalone/src/app/api/cortex/import/status/route.ts +15 -15
  528. package/.next/standalone/src/app/api/cortex/ingest/bootstrap/route.ts +29 -29
  529. package/.next/standalone/src/app/api/cortex/ingest/status/route.ts +15 -15
  530. package/.next/standalone/src/app/api/cortex/knowledge/[id]/route.ts +91 -91
  531. package/.next/standalone/src/app/api/cortex/knowledge/route.ts +93 -93
  532. package/.next/standalone/src/app/api/cortex/lobes/[id]/route.ts +67 -67
  533. package/.next/standalone/src/app/api/cortex/lobes/route.ts +22 -22
  534. package/.next/standalone/src/app/api/cortex/lobes/share/route.ts +80 -80
  535. package/.next/standalone/src/app/api/cortex/marketplace/browse/route.ts +43 -43
  536. package/.next/standalone/src/app/api/cortex/marketplace/preview/route.ts +46 -46
  537. package/.next/standalone/src/app/api/cortex/mcp/call/route.ts +11 -11
  538. package/.next/standalone/src/app/api/cortex/mcp/tools/route.ts +6 -6
  539. package/.next/standalone/src/app/api/cortex/search/route.ts +43 -43
  540. package/.next/standalone/src/app/api/cortex/settings/route.ts +33 -33
  541. package/.next/standalone/src/app/api/cortex/status/route.ts +169 -169
  542. package/.next/standalone/src/app/api/cortex/timeline/route.ts +42 -42
  543. package/.next/standalone/src/app/api/cortex/usage/route.ts +31 -31
  544. package/.next/standalone/src/app/api/cortex/workspace/[id]/context/route.ts +41 -41
  545. package/.next/standalone/src/components/cortex/constants.ts +29 -29
  546. package/.next/standalone/src/components/cortex/cortex-dashboard.tsx +304 -304
  547. package/.next/standalone/src/components/cortex/cortex-indicator.tsx +44 -44
  548. package/.next/standalone/src/components/cortex/cortex-panel.tsx +140 -140
  549. package/.next/standalone/src/components/cortex/cortex-settings.tsx +221 -221
  550. package/.next/standalone/src/components/cortex/curation-tab.tsx +810 -810
  551. package/.next/standalone/src/components/cortex/entity-detail.tsx +101 -101
  552. package/.next/standalone/src/components/cortex/entity-graph.tsx +382 -382
  553. package/.next/standalone/src/components/cortex/import-dialog.tsx +212 -212
  554. package/.next/standalone/src/components/cortex/injection-badge.tsx +72 -72
  555. package/.next/standalone/src/components/cortex/knowledge-card.tsx +109 -109
  556. package/.next/standalone/src/components/cortex/knowledge-tab.tsx +158 -158
  557. package/.next/standalone/src/components/cortex/lobe-settings.tsx +215 -215
  558. package/.next/standalone/src/components/cortex/marketplace-card.tsx +126 -126
  559. package/.next/standalone/src/components/cortex/marketplace-tab.tsx +113 -113
  560. package/.next/standalone/src/lib/cortex/config.ts +40 -40
  561. package/.next/standalone/src/lib/cortex/debug.ts +10 -10
  562. package/.next/standalone/src/lib/cortex/distillation/usage-store.ts +18 -18
  563. package/.next/standalone/src/lib/cortex/graph/resolver.ts +10 -10
  564. package/.next/standalone/src/lib/cortex/graph/types.ts +22 -22
  565. package/.next/standalone/src/lib/cortex/index.ts +56 -56
  566. package/.next/standalone/src/lib/cortex/ingestion/bootstrap.ts +14 -14
  567. package/.next/standalone/src/lib/cortex/knowledge/compat.ts +14 -14
  568. package/.next/standalone/src/lib/cortex/knowledge/contradiction.ts +10 -10
  569. package/.next/standalone/src/lib/cortex/knowledge/types.ts +67 -67
  570. package/.next/standalone/src/lib/cortex/lobes/config.ts +16 -16
  571. package/.next/standalone/src/lib/cortex/lobes/resolver.ts +8 -8
  572. package/.next/standalone/src/lib/cortex/lobes/shares.ts +14 -14
  573. package/.next/standalone/src/lib/cortex/mcp/server.ts +8 -8
  574. package/.next/standalone/src/lib/cortex/portability/exporter.ts +6 -6
  575. package/.next/standalone/src/lib/cortex/portability/importer.ts +10 -10
  576. package/.next/standalone/src/lib/cortex/retrieval/context-engine.ts +10 -10
  577. package/.next/standalone/src/lib/cortex/types.ts +39 -39
  578. package/.next/standalone/tsconfig.json +34 -34
  579. package/LICENSE +661 -661
  580. package/README.md +131 -131
  581. package/bin/cortex-hook.sh +62 -62
  582. package/bin/cortex-mcp.js +60 -60
  583. package/bin/fix-standalone-externals.js +79 -79
  584. package/bin/lib/auto-setup.js +110 -110
  585. package/bin/mdns-service.js +171 -171
  586. package/bin/postinstall.js +35 -35
  587. package/bin/setup-admin.js +195 -195
  588. package/bin/spaces-dev.js +208 -208
  589. package/bin/spaces-install.js +599 -599
  590. package/bin/spaces-reset-totp.js +50 -50
  591. package/bin/spaces-service.js +1020 -1020
  592. package/bin/spaces-setup.js +253 -253
  593. package/bin/spaces.js +776 -776
  594. package/bin/ssh-auth-keys.sh +68 -68
  595. package/bin/terminal-server.js +1683 -1649
  596. package/package.json +103 -102
  597. package/.next/standalone/.next/server/chunks/ssr/_078dd64d._.js +0 -3
  598. package/.next/standalone/.next/server/chunks/ssr/_701606d5._.js +0 -3
  599. package/.next/standalone/.next/server/chunks/ssr/_72b1de37._.js +0 -3
  600. package/.next/standalone/.next/server/chunks/ssr/_950142a4._.js +0 -3
  601. package/.next/standalone/.next/server/chunks/ssr/src_components_terminal_terminal-pane_tsx_803c5e2c._.js +0 -7
  602. package/.next/standalone/.next/static/chunks/18f168665aef1aab.js +0 -1
  603. package/.next/standalone/.next/static/chunks/25b7a243a404a1a7.js +0 -1
  604. package/.next/standalone/.next/static/chunks/4a50d2a3e9bc9b41.js +0 -1
  605. package/.next/standalone/.next/static/chunks/6c78a1dfa7ec2959.css +0 -3
  606. package/.next/standalone/.next/static/chunks/7e0091ab6c5ee8bd.js +0 -1
  607. package/.next/standalone/.next/static/chunks/869f562dc32e55f4.js +0 -1
  608. package/.next/standalone/.next/static/chunks/8b3f4572fec83caa.js +0 -5
  609. package/.next/standalone/.next/static/chunks/8d5419afc4b9116b.js +0 -1
  610. package/.next/standalone/.next/static/chunks/9b2c5451f0b67975.js +0 -1
  611. package/.next/standalone/.next/static/chunks/ac339e970df82fa5.js +0 -5
  612. package/.next/standalone/.next/static/chunks/e7772d64463868eb.js +0 -1
  613. package/.next/standalone/node_modules/@img/sharp-libvips-linux-x64/README.md +0 -46
  614. package/.next/standalone/node_modules/@img/sharp-libvips-linux-x64/lib/glib-2.0/include/glibconfig.h +0 -221
  615. package/.next/standalone/node_modules/@img/sharp-libvips-linux-x64/lib/index.js +0 -1
  616. package/.next/standalone/node_modules/@img/sharp-libvips-linux-x64/lib/libvips-cpp.so.8.17.3 +0 -0
  617. package/.next/standalone/node_modules/@img/sharp-libvips-linux-x64/package.json +0 -42
  618. package/.next/standalone/node_modules/@img/sharp-libvips-linuxmusl-x64/README.md +0 -46
  619. package/.next/standalone/node_modules/@img/sharp-libvips-linuxmusl-x64/lib/glib-2.0/include/glibconfig.h +0 -221
  620. package/.next/standalone/node_modules/@img/sharp-libvips-linuxmusl-x64/lib/index.js +0 -1
  621. package/.next/standalone/node_modules/@img/sharp-libvips-linuxmusl-x64/lib/libvips-cpp.so.8.17.3 +0 -0
  622. package/.next/standalone/node_modules/@img/sharp-libvips-linuxmusl-x64/package.json +0 -42
  623. package/.next/standalone/node_modules/@img/sharp-libvips-linuxmusl-x64/versions.json +0 -30
  624. package/.next/standalone/node_modules/@img/sharp-linux-x64/lib/sharp-linux-x64.node +0 -0
  625. package/.next/standalone/node_modules/@img/sharp-linuxmusl-x64/lib/sharp-linuxmusl-x64.node +0 -0
  626. package/.next/standalone/node_modules/@img/sharp-linuxmusl-x64/package.json +0 -46
  627. /package/.next/standalone/.next/static/{77VYbwIoyxFNr5xevTrCu → ncDe4k4gvD0788HAnq_3G}/_buildManifest.js +0 -0
  628. /package/.next/standalone/.next/static/{77VYbwIoyxFNr5xevTrCu → ncDe4k4gvD0788HAnq_3G}/_clientMiddlewareManifest.json +0 -0
  629. /package/.next/standalone/.next/static/{77VYbwIoyxFNr5xevTrCu → ncDe4k4gvD0788HAnq_3G}/_ssgManifest.js +0 -0
  630. /package/.next/standalone/node_modules/@img/{sharp-libvips-linux-x64 → sharp-win32-x64}/versions.json +0 -0
package/bin/spaces.js CHANGED
@@ -1,776 +1,776 @@
1
- #!/usr/bin/env node
2
-
3
- // Re-exec with higher heap if needed (embedding models + LanceDB leak memory over time)
4
- if (!process.execArgv.some(a => a.includes('max-old-space-size')) && !process.env.__SPACES_HEAP) {
5
- process.env.__SPACES_HEAP = '1';
6
- require('child_process').spawn(
7
- process.execPath,
8
- ['--max-old-space-size=8192', ...process.argv.slice(1)],
9
- { stdio: 'inherit', env: process.env }
10
- ).on('exit', (code) => process.exit(code ?? 1));
11
- // Stop the outer process from continuing
12
- return;
13
- }
14
-
15
- const net = require('net');
16
- const http = require('http');
17
- const https = require('https');
18
- const { execFileSync, spawn } = require('child_process');
19
- const path = require('path');
20
- const os = require('os');
21
- const fs = require('fs');
22
- // terminal-server is loaded lazily (after SPACES_TIER is set in process.env)
23
-
24
- // ─── Memory monitoring (only when SPACES_DEBUG or cortex.debug) ──
25
- let _lastHeapMB = 0;
26
- function logMemory(label) {
27
- if (!process.env.SPACES_DEBUG && !_spacesDebug) return;
28
- const mem = process.memoryUsage();
29
- const heapMB = Math.round(mem.heapUsed / 1048576);
30
- const rssMB = Math.round(mem.rss / 1048576);
31
- const extMB = Math.round((mem.external || 0) / 1048576);
32
- const abMB = Math.round((mem.arrayBuffers || 0) / 1048576);
33
- const delta = heapMB - _lastHeapMB;
34
- if (label || Math.abs(delta) > 20) {
35
- console.log(`[Memory] ${label || 'periodic'}: heap=${heapMB}MB rss=${rssMB}MB external=${extMB}MB arrayBuffers=${abMB}MB ${delta > 0 ? '+' : ''}${delta}MB`);
36
- }
37
- _lastHeapMB = heapMB;
38
- }
39
- let _spacesDebug = false;
40
- try {
41
- const cfgPath = path.join(os.homedir(), '.spaces', 'config.json');
42
- if (fs.existsSync(cfgPath)) _spacesDebug = !!JSON.parse(fs.readFileSync(cfgPath, 'utf-8')).cortex?.debug;
43
- } catch { /* ignore */ }
44
- setInterval(() => logMemory(), 60000);
45
-
46
- const SPACES_DIR = path.join(os.homedir(), '.spaces');
47
- const CONFIG_PATH = path.join(SPACES_DIR, 'server.json');
48
- const SESSION_SECRET_PATH = path.join(SPACES_DIR, 'session_secret');
49
- const NEXT_INTERNAL_PORT = 3400;
50
- const projectDir = path.join(__dirname, '..');
51
- const MANAGED_PACKAGES = path.join(SPACES_DIR, 'packages');
52
- const MANAGED_NODE_MODULES = path.join(MANAGED_PACKAGES, 'node_modules');
53
-
54
- // ─── CLI arg parsing ──────────────────────────────────────
55
- const args = process.argv.slice(2);
56
- const cliFlags = {};
57
- for (let i = 0; i < args.length; i++) {
58
- if (args[i] === '--setup') { cliFlags.setup = true; }
59
- else if (args[i] === '--port' && args[i + 1]) { cliFlags.port = parseInt(args[++i], 10); }
60
- else if (args[i] === '--tier' && args[i + 1]) { cliFlags.tier = args[++i]; }
61
- else if (args[i] === '--base-path' && args[i + 1]) { cliFlags.basePath = args[++i]; }
62
- else if (args[i] === '--help' || args[i] === '-h') { cliFlags.help = true; }
63
- }
64
-
65
- if (cliFlags.help) {
66
- console.log(`
67
- Spaces - Agent Workspace Manager
68
-
69
- Usage:
70
- spaces Start the server (auto-detects tier)
71
- spaces stop Stop running server
72
- spaces install <teams|pro> Install a tier package
73
- spaces uninstall [teams|pro] Uninstall packages (all if none specified)
74
- spaces verify Verify installed packages
75
- spaces upgrade [teams|pro] Upgrade installed packages
76
- spaces --setup Interactive first-time setup wizard
77
- spaces --port 3457 Override port
78
- spaces --tier team Override tier (community|team|federation)
79
- spaces --base-path /spaces Set base path for reverse proxy
80
- spaces service install Install as OS service (systemd/launchd/Task Scheduler)
81
- spaces service uninstall Remove OS service
82
- spaces service start Start the service
83
- spaces service stop Stop the service
84
- spaces service status Show service status
85
- spaces service logs Tail service logs
86
- spaces reset-totp <user> Reset TOTP/2FA for a user
87
- spaces --help Show this help
88
- `);
89
- process.exit(0);
90
- }
91
-
92
- // ─── Stop command ─────────────────────────────────────────
93
- const subcommand = args[0];
94
- if (subcommand === 'stop') {
95
- stopServer();
96
- process.exit(0);
97
- }
98
-
99
- // ─── Route install/verify/upgrade to spaces-install.js ────
100
- if (subcommand === 'install' || subcommand === 'uninstall' || subcommand === 'verify' || subcommand === 'upgrade') {
101
- // Re-exec with spaces-install.js, passing through all args
102
- const installScript = path.join(__dirname, 'spaces-install.js');
103
- const { status } = require('child_process').spawnSync(
104
- process.execPath, [installScript, ...args],
105
- { stdio: 'inherit', env: process.env }
106
- );
107
- process.exit(status || 0);
108
- }
109
-
110
- // ─── Route reset-totp to spaces-reset-totp.js ───────
111
- if (subcommand === 'reset-totp') {
112
- const resetScript = path.join(__dirname, 'spaces-reset-totp.js');
113
- const { status } = require('child_process').spawnSync(
114
- process.execPath, [resetScript, ...args.slice(1)],
115
- { stdio: 'inherit', env: process.env }
116
- );
117
- process.exit(status || 0);
118
- }
119
-
120
- // ─── Route service commands to spaces-service.js ─────
121
- if (subcommand === 'service') {
122
- const serviceScript = path.join(__dirname, 'spaces-service.js');
123
- const { status } = require('child_process').spawnSync(
124
- process.execPath, [serviceScript, ...args.slice(1)],
125
- { stdio: 'inherit', env: process.env }
126
- );
127
- process.exit(status || 0);
128
- }
129
-
130
- // ─── Setup wizard ─────────────────────────────────────────
131
- if (cliFlags.setup) {
132
- require('./spaces-setup');
133
- // spaces-setup handles its own process.exit
134
- } else if (subcommand && !subcommand.startsWith('-')) {
135
- console.error(` Unknown command: ${subcommand}`);
136
- console.error(` Run "spaces --help" for usage`);
137
- process.exit(1);
138
- } else {
139
- startServer();
140
- }
141
-
142
- // ─── TLS certificate ────────────────────────────────────────
143
- // Uses a real cert if configured in server.json (tlsCert, tlsKey, optional
144
- // tlsCa for the full chain), otherwise generates a self-signed cert so
145
- // mobile browsers that force HTTPS-first can still connect.
146
- function ensureTlsCert() {
147
- // Check for configured real cert in server.json
148
- try {
149
- const config = JSON.parse(fs.readFileSync(CONFIG_PATH, 'utf-8'));
150
- if (config.tlsCert && config.tlsKey) {
151
- if (fs.existsSync(config.tlsCert) && fs.existsSync(config.tlsKey)) {
152
- // Read cert + key, and optionally the CA bundle for full chain
153
- const certPem = fs.readFileSync(config.tlsCert, 'utf-8').trim();
154
- const caPem = (config.tlsCa && fs.existsSync(config.tlsCa))
155
- ? fs.readFileSync(config.tlsCa, 'utf-8').trim()
156
- : null;
157
- const creds = {
158
- cert: caPem ? certPem + '\n' + caPem : certPem,
159
- key: fs.readFileSync(config.tlsKey, 'utf-8'),
160
- };
161
- console.log(' Using TLS certificate: ' + config.tlsCert);
162
- return creds;
163
- }
164
- console.log(' Warning: tlsCert/tlsKey configured but files not found, falling back to self-signed');
165
- }
166
- } catch {}
167
-
168
- // Fall back to self-signed
169
- const certPath = path.join(SPACES_DIR, 'tls-cert.pem');
170
- const keyPath = path.join(SPACES_DIR, 'tls-key.pem');
171
-
172
- if (fs.existsSync(certPath) && fs.existsSync(keyPath)) {
173
- try {
174
- return { cert: fs.readFileSync(certPath), key: fs.readFileSync(keyPath) };
175
- } catch {}
176
- }
177
-
178
- try {
179
- fs.mkdirSync(SPACES_DIR, { recursive: true });
180
- execFileSync('openssl', [
181
- 'req', '-x509', '-newkey', 'rsa:2048',
182
- '-keyout', keyPath, '-out', certPath,
183
- '-sha256', '-days', '365', '-nodes',
184
- '-subj', '/CN=spaces-local',
185
- '-addext', 'subjectAltName=DNS:localhost,DNS:*.local,DNS:*.robindale.com,IP:127.0.0.1',
186
- ], { stdio: 'pipe', timeout: 15000 });
187
- console.log(' Generated self-signed TLS certificate');
188
- return { cert: fs.readFileSync(certPath), key: fs.readFileSync(keyPath) };
189
- } catch (e) {
190
- console.log(` Warning: Could not generate TLS cert (${e.message})`);
191
- console.log(' HTTPS will not be available. Install OpenSSL to enable it.');
192
- return null;
193
- }
194
- }
195
-
196
- function startServer() {
197
- // ─── Load saved config ────────────────────────────────────
198
- let savedConfig = {};
199
- if (fs.existsSync(CONFIG_PATH)) {
200
- try { savedConfig = JSON.parse(fs.readFileSync(CONFIG_PATH, 'utf-8')); } catch {}
201
- }
202
-
203
- // ─── Resolve settings (CLI > env > config > defaults) ─────
204
- const PORT = cliFlags.port
205
- || parseInt(process.env.SPACES_PORT || '', 10)
206
- || savedConfig.port
207
- || 3457;
208
-
209
- const basePath = cliFlags.basePath
210
- || process.env.SPACES_BASE_PATH
211
- || savedConfig.basePath
212
- || '';
213
-
214
- const allowedOrigins = process.env.SPACES_ALLOWED_ORIGINS
215
- || savedConfig.allowedOrigins
216
- || '';
217
-
218
- // ─── Kill any existing server on this port ───────────────────
219
- stopServer();
220
-
221
- // ─── Resolve optional packages once ─────────────────────────
222
- const proPath = resolveSpacesPro();
223
- const teamsPath = resolveSpacesTeams();
224
- const cortexPath = resolveSpacesCortex();
225
-
226
- // Tier resolution: CLI > env > config > auto-detect
227
- let tier = cliFlags.tier
228
- || process.env.SPACES_TIER
229
- || savedConfig.tier
230
- || '';
231
-
232
- // Auto-detect tier from package presence
233
- if (!tier) {
234
- if (proPath) tier = 'federation';
235
- else if (teamsPath) tier = 'team';
236
- else tier = 'community';
237
- }
238
-
239
- console.log('');
240
- console.log(' Spaces - Agent Workspace Manager');
241
- console.log(' =================================');
242
- console.log('');
243
- console.log(` Tier: ${tier}`);
244
-
245
- // ─── Server tier prerequisites ────────────────────────────
246
- const childEnv = { ...process.env };
247
-
248
- if (tier !== 'community') {
249
- // team/federation tiers require @spaces/teams (auth + collaboration)
250
- if ((tier === 'team' || tier === 'federation') && !teamsPath) {
251
- console.error(' Error: @spaces/teams is required for team/federation tiers.');
252
- console.error(' Install it: spaces install teams');
253
- process.exit(1);
254
- }
255
- // federation tier requires @spaces/pro (network)
256
- if (tier === 'federation' && !proPath) {
257
- console.error(' Error: @spaces/pro is required for the federation tier.');
258
- console.error(' Install it: spaces install pro');
259
- process.exit(1);
260
- }
261
-
262
- // Check for session secret
263
- let sessionSecret = process.env.SPACES_SESSION_SECRET || '';
264
- if (!sessionSecret && fs.existsSync(SESSION_SECRET_PATH)) {
265
- sessionSecret = fs.readFileSync(SESSION_SECRET_PATH, 'utf-8').trim();
266
- }
267
-
268
- // Check for admin DB — auto-setup if missing
269
- const adminDbPath = path.join(SPACES_DIR, 'admin.db');
270
- if (!fs.existsSync(adminDbPath) || !sessionSecret) {
271
- const { autoSetup } = require('./lib/auto-setup');
272
- const result = autoSetup({ SPACES_DIR, SESSION_SECRET_PATH, ADMIN_DB_PATH: adminDbPath, CONFIG_PATH, tier, port: PORT, basePath });
273
- sessionSecret = result.sessionSecret;
274
- }
275
-
276
- childEnv.SPACES_SESSION_SECRET = sessionSecret;
277
- process.env.SPACES_SESSION_SECRET = sessionSecret;
278
- console.log(` Admin DB: ${adminDbPath}`);
279
- }
280
-
281
- // Set tier in both child env and own process env (terminal-server reads it)
282
- childEnv.SPACES_TIER = tier;
283
- process.env.SPACES_TIER = tier;
284
- if (basePath) {
285
- childEnv.SPACES_BASE_PATH = basePath;
286
- console.log(` Base path: ${basePath}`);
287
- }
288
- if (allowedOrigins) {
289
- childEnv.SPACES_ALLOWED_ORIGINS = allowedOrigins;
290
- process.env.SPACES_ALLOWED_ORIGINS = allowedOrigins;
291
- console.log(` Allowed origins: ${allowedOrigins}`);
292
- }
293
-
294
- // ─── Resolve NODE_PATH for @spaces/pro and @spaces/teams ──
295
- // Update both childEnv (for the Next.js child process) and process.env
296
- // (for terminal-server.js which runs in this same parent process).
297
- // Include:
298
- // - Managed packages node_modules (~/.spaces/packages/node_modules)
299
- // - Each managed package's own node_modules (for its bundled deps)
300
- // - The host app's own node_modules (fallback for peer deps)
301
- const appNodeModules = path.join(projectDir, 'node_modules');
302
- const nodePaths = [MANAGED_NODE_MODULES, appNodeModules];
303
- // Add each resolved package's own node_modules so its bundled deps are found
304
- for (const pkgPath of [proPath, teamsPath, cortexPath]) {
305
- if (pkgPath) {
306
- // pkgPath is the package root (symlink target or direct path)
307
- const realPath = fs.realpathSync(pkgPath);
308
- const pkgNodeModules = path.join(realPath, 'node_modules');
309
- if (fs.existsSync(pkgNodeModules) && !nodePaths.includes(pkgNodeModules)) {
310
- nodePaths.push(pkgNodeModules);
311
- }
312
- // Also add the parent scope for @spaces/* resolution
313
- const parentModules = path.dirname(path.dirname(pkgPath));
314
- if (!nodePaths.includes(parentModules)) {
315
- nodePaths.push(parentModules);
316
- }
317
- }
318
- }
319
- for (const dir of nodePaths) {
320
- for (const target of [childEnv, process.env]) {
321
- const existing = target.NODE_PATH || '';
322
- if (!existing.includes(dir)) {
323
- target.NODE_PATH = existing
324
- ? `${dir}${path.delimiter}${existing}`
325
- : dir;
326
- }
327
- }
328
- }
329
- // Re-init module paths so require() in this process picks up the new NODE_PATH
330
- require('module').Module._initPaths();
331
-
332
- // Verify collaboration pipeline works end-to-end at startup
333
- if (tier === 'team' || tier === 'federation') {
334
- try {
335
- const teams = require('@spaces/teams');
336
- console.log(' Collaboration: @spaces/teams loaded OK');
337
- // Smoke-test that peer deps resolve from this process
338
- require('better-sqlite3');
339
- } catch (e) {
340
- console.error(` Warning: Collaboration may not work — ${e.message}`);
341
- console.error(' Check that NODE_PATH includes the host app node_modules.');
342
- }
343
- }
344
-
345
- // ─── Detect @spaces/cortex ──────────────────────────────────
346
- if (cortexPath) {
347
- childEnv.SPACES_HAS_CORTEX = '1';
348
- process.env.SPACES_HAS_CORTEX = '1';
349
- console.log(' Cortex: @spaces/cortex detected');
350
- }
351
-
352
- console.log('');
353
-
354
- // ─── Background update check (non-blocking, repeats every 4h) ──
355
- // Checks npm registry, GitHub releases, and addon git repos.
356
- // Writes results to ~/.spaces/update-check.json for the UI banner.
357
- const updateCheckPath = path.join(SPACES_DIR, 'update-check.json');
358
- const checkForUpdates = async (logIfAvailable = true) => {
359
- try {
360
- const pkg = require(path.join(projectDir, 'package.json'));
361
- const currentVersion = pkg.version;
362
- const npmName = pkg.name || '@jlongo78/agent-spaces';
363
- const githubRepo = 'jlongo78/spaces';
364
-
365
- // Check npm registry
366
- let npmLatest = null;
367
- try {
368
- const res = await fetch(`https://registry.npmjs.org/${encodeURIComponent(npmName)}/latest`, {
369
- signal: AbortSignal.timeout(5000),
370
- });
371
- if (res.ok) {
372
- const data = await res.json();
373
- npmLatest = data.version;
374
- }
375
- } catch { /* */ }
376
-
377
- // Check GitHub for latest release or tag (may be ahead of npm)
378
- let githubLatest = null;
379
- let githubPrerelease = false;
380
- let githubUrl = null;
381
- try {
382
- // Check releases first (includes pre-releases)
383
- const res = await fetch(`https://api.github.com/repos/${githubRepo}/releases?per_page=5`, {
384
- signal: AbortSignal.timeout(5000),
385
- headers: { 'Accept': 'application/vnd.github.v3+json', 'User-Agent': 'agent-spaces' },
386
- });
387
- if (res.ok) {
388
- const releases = await res.json();
389
- if (releases.length > 0) {
390
- // Find latest stable and latest pre-release
391
- const stable = releases.find(r => !r.prerelease && !r.draft);
392
- const pre = releases.find(r => r.prerelease && !r.draft);
393
- if (stable) {
394
- githubLatest = stable.tag_name.replace(/^v/, '');
395
- githubUrl = stable.html_url;
396
- }
397
- if (pre) {
398
- const preVersion = pre.tag_name.replace(/^v/, '');
399
- // If pre-release is newer than stable, surface it
400
- if (!githubLatest || preVersion > githubLatest) {
401
- githubLatest = preVersion;
402
- githubPrerelease = true;
403
- githubUrl = pre.html_url;
404
- }
405
- }
406
- }
407
- }
408
- } catch { /* */ }
409
-
410
- // Check addon git repos
411
- const gitSafe = ['-c', 'safe.directory=*'];
412
- const addonPaths = { teams: teamsPath, pro: proPath, cortex: cortexPath };
413
- const addons = {};
414
- for (const [key, addonDir] of Object.entries(addonPaths)) {
415
- if (!addonDir || !fs.existsSync(path.join(addonDir, '.git'))) continue;
416
- const realDir = fs.realpathSync(addonDir);
417
- try {
418
- execFileSync('git', [...gitSafe, 'fetch', '--quiet'], { cwd: realDir, stdio: 'ignore', timeout: 5000 });
419
- const local = execFileSync('git', [...gitSafe, 'rev-parse', 'HEAD'], { cwd: realDir, encoding: 'utf-8' }).trim();
420
- const remote = execFileSync('git', [...gitSafe, 'rev-parse', '@{u}'], { cwd: realDir, encoding: 'utf-8' }).trim();
421
- const behind = local !== remote;
422
- let commitsBehind = 0;
423
- if (behind) {
424
- try {
425
- const count = execFileSync('git', [...gitSafe, 'rev-list', '--count', `HEAD..@{u}`], { cwd: realDir, encoding: 'utf-8' }).trim();
426
- commitsBehind = parseInt(count, 10) || 0;
427
- } catch { /* */ }
428
- }
429
- addons[key] = { installed: true, behind, commitsBehind, localHead: local.slice(0, 7) };
430
- if (behind && logIfAvailable) {
431
- console.log(` Update available for @spaces/${key}: ${commitsBehind} commit(s) behind (run: spaces upgrade ${key})`);
432
- }
433
- } catch {
434
- addons[key] = { installed: true, behind: false, commitsBehind: 0 };
435
- }
436
- }
437
-
438
- const npmAvailable = npmLatest && npmLatest !== currentVersion && npmLatest > currentVersion;
439
- const githubAvailable = githubLatest && githubLatest !== currentVersion && githubLatest > currentVersion;
440
-
441
- const result = {
442
- current: currentVersion,
443
- npm: npmLatest ? { latest: npmLatest, available: !!npmAvailable } : null,
444
- github: githubLatest ? { latest: githubLatest, prerelease: githubPrerelease, url: githubUrl, available: !!githubAvailable } : null,
445
- // Backward compat: 'available' and 'latest' still work for the existing banner
446
- latest: npmLatest || githubLatest || currentVersion,
447
- available: !!(npmAvailable || githubAvailable),
448
- addons,
449
- checkedAt: Date.now(),
450
- name: npmName,
451
- };
452
-
453
- fs.writeFileSync(updateCheckPath, JSON.stringify(result, null, 2));
454
-
455
- if (npmAvailable && logIfAvailable) {
456
- console.log(` Update available: ${currentVersion} → ${npmLatest} (run: npm i -g ${npmName})`);
457
- }
458
- if (githubAvailable && (!npmAvailable || githubLatest > npmLatest) && logIfAvailable) {
459
- console.log(` GitHub ${githubPrerelease ? 'pre-release' : 'release'}: ${githubLatest} (${githubUrl || `https://github.com/${githubRepo}/releases`})`);
460
- }
461
- } catch { /* network error — skip silently */ }
462
- };
463
- checkForUpdates(true);
464
- setInterval(() => checkForUpdates(false), 4 * 3600_000);
465
-
466
- // Check for ~/.claude/ directory
467
- const claudeDir = path.join(os.homedir(), '.claude');
468
- if (!fs.existsSync(claudeDir)) {
469
- console.log(' Warning: ~/.claude/ not found. Have you used Claude Code yet?');
470
- console.log('');
471
- }
472
-
473
- // ─── Detect build type ────────────────────────────────────
474
- const standaloneServer = path.join(projectDir, '.next', 'standalone', 'server.js');
475
- const fullBuildDir = path.join(projectDir, '.next', 'BUILD_ID');
476
- const isStandalone = fs.existsSync(standaloneServer);
477
- const isFullBuild = fs.existsSync(fullBuildDir);
478
-
479
- if (!isStandalone && !isFullBuild) {
480
- console.error(' Error: No build found.');
481
- console.error(' Run "npm run build" first, or install via "npm install -g @jlongo78/agent-spaces".');
482
- process.exit(1);
483
- }
484
-
485
- // ─── Spawn Next.js ────────────────────────────────────────
486
- let next;
487
- if (isStandalone) {
488
- const parentNodeModules = path.join(projectDir, 'node_modules');
489
- const existingNodePath = childEnv.NODE_PATH || '';
490
- childEnv.NODE_PATH = existingNodePath
491
- ? `${parentNodeModules}${path.delimiter}${existingNodePath}`
492
- : parentNodeModules;
493
-
494
- next = spawn(process.execPath, [standaloneServer], {
495
- cwd: path.dirname(standaloneServer),
496
- stdio: ['ignore', 'pipe', 'pipe'],
497
- env: {
498
- ...childEnv,
499
- PORT: String(NEXT_INTERNAL_PORT),
500
- HOSTNAME: '0.0.0.0',
501
- NODE_ENV: 'production',
502
- },
503
- });
504
- } else {
505
- next = spawn('npx', ['next', 'start', '--port', String(NEXT_INTERNAL_PORT)], {
506
- cwd: projectDir,
507
- stdio: ['ignore', 'pipe', 'pipe'],
508
- env: {
509
- ...childEnv,
510
- PORT: String(NEXT_INTERNAL_PORT),
511
- HOSTNAME: '0.0.0.0',
512
- NODE_ENV: 'production',
513
- },
514
- shell: true,
515
- });
516
- }
517
-
518
- let nextReady = false;
519
-
520
- next.stdout.on('data', (data) => {
521
- const msg = data.toString();
522
- process.stdout.write(msg);
523
- if (!nextReady && (msg.includes('Ready') || msg.includes('started server') || msg.includes('Listening') || msg.includes('localhost'))) {
524
- nextReady = true;
525
- console.log(`\n Ready at http://localhost:${PORT}`);
526
- if (tlsCreds) console.log(` Also at https://localhost:${PORT} (self-signed)`);
527
- console.log('');
528
-
529
- const url = `http://localhost:${PORT}`;
530
- const isService = process.env.SPACES_SERVICE === '1';
531
- if (!isService) {
532
- try {
533
- if (process.platform === 'win32') {
534
- execFileSync('cmd', ['/c', 'start', url], { stdio: 'ignore' });
535
- } else if (process.platform === 'darwin') {
536
- execFileSync('open', [url], { stdio: 'ignore' });
537
- } else {
538
- execFileSync('xdg-open', [url], { stdio: 'ignore' });
539
- }
540
- } catch {
541
- console.log(` Open ${url} in your browser`);
542
- }
543
- }
544
- }
545
- });
546
-
547
- next.stderr.on('data', (data) => {
548
- const msg = data.toString();
549
- if (!msg.includes('Warning')) {
550
- process.stderr.write(data);
551
- }
552
- });
553
-
554
- next.on('exit', (code) => {
555
- if (code !== 0 && code !== null) {
556
- console.error(` [spaces] Next.js exited with code ${code}`);
557
- }
558
- cleanup();
559
- });
560
-
561
- // ─── Proxy request handler (shared by HTTP and HTTPS) ────
562
- function proxyHandler(req, res) {
563
- // WebSocket paths are handled by the 'upgrade' event, but a plain
564
- // HTTP request to /ws (e.g. health check) should not be proxied to
565
- // Next.js which would 308-redirect it due to trailingSlash.
566
- const urlPath = (req.url || '').split('?')[0];
567
- if (urlPath === '/ws' || urlPath.endsWith('/ws') || urlPath.endsWith('/ws/')) {
568
- res.writeHead(200, { 'Content-Type': 'text/plain' });
569
- res.end('WebSocket endpoint');
570
- return;
571
- }
572
-
573
- const proxyReq = http.request(
574
- {
575
- hostname: '127.0.0.1',
576
- port: NEXT_INTERNAL_PORT,
577
- path: req.url,
578
- method: req.method,
579
- headers: req.headers,
580
- },
581
- (proxyRes) => {
582
- res.writeHead(proxyRes.statusCode, proxyRes.headers);
583
- proxyRes.pipe(res);
584
- }
585
- );
586
- proxyReq.on('error', () => {
587
- if (!res.headersSent) {
588
- res.writeHead(502);
589
- res.end('Server not ready yet. Refresh in a moment.');
590
- }
591
- });
592
- req.pipe(proxyReq);
593
- }
594
-
595
- // ─── HTTP + HTTPS on a single port ─────────────────────────
596
- // Peek at the first byte of each connection: 0x16 = TLS ClientHello,
597
- // anything else = plain HTTP. This lets mobile browsers that force
598
- // HTTPS-first connect to the same port without a separate listener.
599
- const httpServer = http.createServer(proxyHandler);
600
- const tlsCreds = ensureTlsCert();
601
- const httpsServer = tlsCreds ? https.createServer(tlsCreds, proxyHandler) : null;
602
-
603
- const { createTerminalServer } = require('./terminal-server');
604
- createTerminalServer(httpServer);
605
- if (httpsServer) createTerminalServer(httpsServer);
606
-
607
- // Wire up 'address()' on the inner servers so terminal-server can
608
- // discover the port, then emit 'listening' so its event handler fires.
609
- const patchAddress = (srv) => { srv.address = () => ({ port: PORT }); };
610
- patchAddress(httpServer);
611
- if (httpsServer) patchAddress(httpsServer);
612
-
613
- const dualServer = net.createServer((socket) => {
614
- // If client connects but sends nothing for 5s, destroy.
615
- // Once routed, clear the timeout so long-lived connections (WebSocket) aren't killed.
616
- socket.setTimeout(5000, () => socket.destroy());
617
- socket.once('data', (buf) => {
618
- socket.setTimeout(0);
619
- socket.pause();
620
- const target = (buf[0] === 0x16 && httpsServer) ? httpsServer : httpServer;
621
- target.emit('connection', socket);
622
- socket.unshift(buf);
623
- socket.resume();
624
- });
625
- });
626
-
627
- dualServer.listen(PORT, () => {
628
- // Now that the port is bound, tell the inner servers they're "listening"
629
- // so terminal-server's mDNS and message watcher start up.
630
- httpServer.emit('listening');
631
- if (httpsServer) httpsServer.emit('listening');
632
-
633
- if (httpsServer) {
634
- console.log(` Starting server on port ${PORT} (HTTP + HTTPS)`);
635
- } else {
636
- console.log(` Starting server on http://localhost:${PORT}`);
637
- }
638
- console.log('');
639
- });
640
-
641
- function cleanup() {
642
- next.kill();
643
- dualServer.close();
644
- process.exit(0);
645
- }
646
-
647
- process.on('SIGINT', cleanup);
648
- process.on('SIGTERM', cleanup);
649
- }
650
-
651
- // ─── Stop running server ─────────────────────────────────────
652
- function findPidsOnPort(port) {
653
- const pids = new Set();
654
- if (process.platform === 'win32') {
655
- try {
656
- const output = execFileSync('netstat', ['-ano'], { encoding: 'utf-8' });
657
- for (const line of output.split(String.fromCharCode(10))) {
658
- if (line.includes(':' + port + ' ') && line.includes('LISTENING')) {
659
- const parts = line.trim().split(/\s+/);
660
- const pid = parseInt(parts[parts.length - 1], 10);
661
- if (pid > 0) pids.add(pid);
662
- }
663
- }
664
- } catch {}
665
- } else {
666
- try {
667
- const output = execFileSync('lsof', ['-ti', `tcp:${port}`], { encoding: 'utf-8' }).trim();
668
- for (const p of output.split('\n')) { if (p.trim()) pids.add(parseInt(p.trim(), 10)); }
669
- } catch {}
670
- try {
671
- const output = execFileSync('fuser', [`${port}/tcp`], { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] }).trim();
672
- for (const p of output.split(/\s+/)) { if (p.trim()) pids.add(parseInt(p.trim(), 10)); }
673
- } catch {}
674
- }
675
- return [...pids].filter(p => !isNaN(p) && p > 0);
676
- }
677
-
678
- function stopServer() {
679
- let savedConfig = {};
680
- if (fs.existsSync(CONFIG_PATH)) {
681
- try { savedConfig = JSON.parse(fs.readFileSync(CONFIG_PATH, 'utf-8')); } catch {}
682
- }
683
- const port = parseInt(process.env.SPACES_PORT || '', 10) || savedConfig.port || 3457;
684
- const ports = [port, NEXT_INTERNAL_PORT];
685
- let killed = 0;
686
-
687
- for (const p of ports) {
688
- for (const pid of findPidsOnPort(p)) {
689
- try {
690
- process.kill(pid, 'SIGTERM');
691
- killed++;
692
- } catch {}
693
- }
694
- }
695
-
696
- if (killed > 0) {
697
- console.log(` Stopped ${killed} process(es) on port ${port}`);
698
- // Wait for ports to be released, escalate to SIGKILL if needed
699
- const deadline = Date.now() + 2000;
700
- let escalated = false;
701
- while (Date.now() < deadline) {
702
- const remaining = ports.flatMap(p => findPidsOnPort(p));
703
- if (remaining.length === 0) break;
704
- if (!escalated && Date.now() > deadline - 1000) {
705
- for (const pid of remaining) {
706
- try { process.kill(pid, 'SIGKILL'); } catch {}
707
- }
708
- escalated = true;
709
- }
710
- if (process.platform === 'win32') { require('child_process').spawnSync('powershell', ['-Command', 'Start-Sleep -Milliseconds 200']); } else { require('child_process').spawnSync('sleep', ['0.2']); }
711
- }
712
- } else {
713
- console.log(` No running server found on port ${port}`);
714
- }
715
- }
716
-
717
- // ─── @spaces/pro resolution ──────────────────────────────────
718
- function resolveSpacesPro() {
719
- // 1. Managed install (~/.spaces/packages/)
720
- const managed = path.join(MANAGED_NODE_MODULES, '@spaces', 'pro');
721
- if (fs.existsSync(path.join(managed, 'dist', 'index.js'))) return managed;
722
-
723
- // 2. Local node_modules (npm link / optionalDep)
724
- try {
725
- return require.resolve('@spaces/pro');
726
- } catch {}
727
-
728
- // 3. Global npm prefix (legacy)
729
- try {
730
- const globalPrefix = execFileSync('npm', ['prefix', '-g'], { encoding: 'utf-8' }).trim();
731
- const globalProPath = path.join(globalPrefix, 'lib', 'node_modules', '@spaces', 'pro');
732
- if (fs.existsSync(globalProPath)) return globalProPath;
733
- const altPath = path.join(globalPrefix, 'node_modules', '@spaces', 'pro');
734
- if (fs.existsSync(altPath)) return altPath;
735
- } catch {}
736
-
737
- return null;
738
- }
739
-
740
- // ─── @spaces/teams resolution ────────────────────────────────
741
- function resolveSpacesTeams() {
742
- // 1. Managed install (~/.spaces/packages/)
743
- const managed = path.join(MANAGED_NODE_MODULES, '@spaces', 'teams');
744
- if (fs.existsSync(path.join(managed, 'dist', 'index.js'))) return managed;
745
-
746
- // 2. Local node_modules (npm link / optionalDep)
747
- try {
748
- return require.resolve('@spaces/teams');
749
- } catch {}
750
-
751
- // 3. Global npm prefix (legacy)
752
- try {
753
- const globalPrefix = execFileSync('npm', ['prefix', '-g'], { encoding: 'utf-8' }).trim();
754
- const globalTeamsPath = path.join(globalPrefix, 'lib', 'node_modules', '@spaces', 'teams');
755
- if (fs.existsSync(globalTeamsPath)) return globalTeamsPath;
756
- const altPath = path.join(globalPrefix, 'node_modules', '@spaces', 'teams');
757
- if (fs.existsSync(altPath)) return altPath;
758
- } catch {}
759
-
760
- return null;
761
- }
762
-
763
- // ─── @spaces/cortex resolution ───────────────────────────────
764
- function resolveSpacesCortex() {
765
- const managed = path.join(MANAGED_NODE_MODULES, '@spaces', 'cortex');
766
- if (fs.existsSync(path.join(managed, 'dist', 'index.js'))) return managed;
767
- try { return require.resolve('@spaces/cortex'); } catch {}
768
- try {
769
- const globalPrefix = execFileSync('npm', ['prefix', '-g'], { encoding: 'utf-8' }).trim();
770
- const globalPath = path.join(globalPrefix, 'lib', 'node_modules', '@spaces', 'cortex');
771
- if (fs.existsSync(globalPath)) return globalPath;
772
- const altPath = path.join(globalPrefix, 'node_modules', '@spaces', 'cortex');
773
- if (fs.existsSync(altPath)) return altPath;
774
- } catch {}
775
- return null;
776
- }
1
+ #!/usr/bin/env node
2
+
3
+ // Re-exec with higher heap if needed (embedding models + LanceDB leak memory over time)
4
+ if (!process.execArgv.some(a => a.includes('max-old-space-size')) && !process.env.__SPACES_HEAP) {
5
+ process.env.__SPACES_HEAP = '1';
6
+ require('child_process').spawn(
7
+ process.execPath,
8
+ ['--max-old-space-size=8192', ...process.argv.slice(1)],
9
+ { stdio: 'inherit', env: process.env }
10
+ ).on('exit', (code) => process.exit(code ?? 1));
11
+ // Stop the outer process from continuing
12
+ return;
13
+ }
14
+
15
+ const net = require('net');
16
+ const http = require('http');
17
+ const https = require('https');
18
+ const { execFileSync, spawn } = require('child_process');
19
+ const path = require('path');
20
+ const os = require('os');
21
+ const fs = require('fs');
22
+ // terminal-server is loaded lazily (after SPACES_TIER is set in process.env)
23
+
24
+ // ─── Memory monitoring (only when SPACES_DEBUG or cortex.debug) ──
25
+ let _lastHeapMB = 0;
26
+ function logMemory(label) {
27
+ if (!process.env.SPACES_DEBUG && !_spacesDebug) return;
28
+ const mem = process.memoryUsage();
29
+ const heapMB = Math.round(mem.heapUsed / 1048576);
30
+ const rssMB = Math.round(mem.rss / 1048576);
31
+ const extMB = Math.round((mem.external || 0) / 1048576);
32
+ const abMB = Math.round((mem.arrayBuffers || 0) / 1048576);
33
+ const delta = heapMB - _lastHeapMB;
34
+ if (label || Math.abs(delta) > 20) {
35
+ console.log(`[Memory] ${label || 'periodic'}: heap=${heapMB}MB rss=${rssMB}MB external=${extMB}MB arrayBuffers=${abMB}MB ${delta > 0 ? '+' : ''}${delta}MB`);
36
+ }
37
+ _lastHeapMB = heapMB;
38
+ }
39
+ let _spacesDebug = false;
40
+ try {
41
+ const cfgPath = path.join(os.homedir(), '.spaces', 'config.json');
42
+ if (fs.existsSync(cfgPath)) _spacesDebug = !!JSON.parse(fs.readFileSync(cfgPath, 'utf-8')).cortex?.debug;
43
+ } catch { /* ignore */ }
44
+ setInterval(() => logMemory(), 60000);
45
+
46
+ const SPACES_DIR = path.join(os.homedir(), '.spaces');
47
+ const CONFIG_PATH = path.join(SPACES_DIR, 'server.json');
48
+ const SESSION_SECRET_PATH = path.join(SPACES_DIR, 'session_secret');
49
+ const NEXT_INTERNAL_PORT = 3400;
50
+ const projectDir = path.join(__dirname, '..');
51
+ const MANAGED_PACKAGES = path.join(SPACES_DIR, 'packages');
52
+ const MANAGED_NODE_MODULES = path.join(MANAGED_PACKAGES, 'node_modules');
53
+
54
+ // ─── CLI arg parsing ──────────────────────────────────────
55
+ const args = process.argv.slice(2);
56
+ const cliFlags = {};
57
+ for (let i = 0; i < args.length; i++) {
58
+ if (args[i] === '--setup') { cliFlags.setup = true; }
59
+ else if (args[i] === '--port' && args[i + 1]) { cliFlags.port = parseInt(args[++i], 10); }
60
+ else if (args[i] === '--tier' && args[i + 1]) { cliFlags.tier = args[++i]; }
61
+ else if (args[i] === '--base-path' && args[i + 1]) { cliFlags.basePath = args[++i]; }
62
+ else if (args[i] === '--help' || args[i] === '-h') { cliFlags.help = true; }
63
+ }
64
+
65
+ if (cliFlags.help) {
66
+ console.log(`
67
+ Spaces - Agent Workspace Manager
68
+
69
+ Usage:
70
+ spaces Start the server (auto-detects tier)
71
+ spaces stop Stop running server
72
+ spaces install <teams|pro> Install a tier package
73
+ spaces uninstall [teams|pro] Uninstall packages (all if none specified)
74
+ spaces verify Verify installed packages
75
+ spaces upgrade [teams|pro] Upgrade installed packages
76
+ spaces --setup Interactive first-time setup wizard
77
+ spaces --port 3457 Override port
78
+ spaces --tier team Override tier (community|team|federation)
79
+ spaces --base-path /spaces Set base path for reverse proxy
80
+ spaces service install Install as OS service (systemd/launchd/Task Scheduler)
81
+ spaces service uninstall Remove OS service
82
+ spaces service start Start the service
83
+ spaces service stop Stop the service
84
+ spaces service status Show service status
85
+ spaces service logs Tail service logs
86
+ spaces reset-totp <user> Reset TOTP/2FA for a user
87
+ spaces --help Show this help
88
+ `);
89
+ process.exit(0);
90
+ }
91
+
92
+ // ─── Stop command ─────────────────────────────────────────
93
+ const subcommand = args[0];
94
+ if (subcommand === 'stop') {
95
+ stopServer();
96
+ process.exit(0);
97
+ }
98
+
99
+ // ─── Route install/verify/upgrade to spaces-install.js ────
100
+ if (subcommand === 'install' || subcommand === 'uninstall' || subcommand === 'verify' || subcommand === 'upgrade') {
101
+ // Re-exec with spaces-install.js, passing through all args
102
+ const installScript = path.join(__dirname, 'spaces-install.js');
103
+ const { status } = require('child_process').spawnSync(
104
+ process.execPath, [installScript, ...args],
105
+ { stdio: 'inherit', env: process.env }
106
+ );
107
+ process.exit(status || 0);
108
+ }
109
+
110
+ // ─── Route reset-totp to spaces-reset-totp.js ───────
111
+ if (subcommand === 'reset-totp') {
112
+ const resetScript = path.join(__dirname, 'spaces-reset-totp.js');
113
+ const { status } = require('child_process').spawnSync(
114
+ process.execPath, [resetScript, ...args.slice(1)],
115
+ { stdio: 'inherit', env: process.env }
116
+ );
117
+ process.exit(status || 0);
118
+ }
119
+
120
+ // ─── Route service commands to spaces-service.js ─────
121
+ if (subcommand === 'service') {
122
+ const serviceScript = path.join(__dirname, 'spaces-service.js');
123
+ const { status } = require('child_process').spawnSync(
124
+ process.execPath, [serviceScript, ...args.slice(1)],
125
+ { stdio: 'inherit', env: process.env }
126
+ );
127
+ process.exit(status || 0);
128
+ }
129
+
130
+ // ─── Setup wizard ─────────────────────────────────────────
131
+ if (cliFlags.setup) {
132
+ require('./spaces-setup');
133
+ // spaces-setup handles its own process.exit
134
+ } else if (subcommand && !subcommand.startsWith('-')) {
135
+ console.error(` Unknown command: ${subcommand}`);
136
+ console.error(` Run "spaces --help" for usage`);
137
+ process.exit(1);
138
+ } else {
139
+ startServer();
140
+ }
141
+
142
+ // ─── TLS certificate ────────────────────────────────────────
143
+ // Uses a real cert if configured in server.json (tlsCert, tlsKey, optional
144
+ // tlsCa for the full chain), otherwise generates a self-signed cert so
145
+ // mobile browsers that force HTTPS-first can still connect.
146
+ function ensureTlsCert() {
147
+ // Check for configured real cert in server.json
148
+ try {
149
+ const config = JSON.parse(fs.readFileSync(CONFIG_PATH, 'utf-8'));
150
+ if (config.tlsCert && config.tlsKey) {
151
+ if (fs.existsSync(config.tlsCert) && fs.existsSync(config.tlsKey)) {
152
+ // Read cert + key, and optionally the CA bundle for full chain
153
+ const certPem = fs.readFileSync(config.tlsCert, 'utf-8').trim();
154
+ const caPem = (config.tlsCa && fs.existsSync(config.tlsCa))
155
+ ? fs.readFileSync(config.tlsCa, 'utf-8').trim()
156
+ : null;
157
+ const creds = {
158
+ cert: caPem ? certPem + '\n' + caPem : certPem,
159
+ key: fs.readFileSync(config.tlsKey, 'utf-8'),
160
+ };
161
+ console.log(' Using TLS certificate: ' + config.tlsCert);
162
+ return creds;
163
+ }
164
+ console.log(' Warning: tlsCert/tlsKey configured but files not found, falling back to self-signed');
165
+ }
166
+ } catch {}
167
+
168
+ // Fall back to self-signed
169
+ const certPath = path.join(SPACES_DIR, 'tls-cert.pem');
170
+ const keyPath = path.join(SPACES_DIR, 'tls-key.pem');
171
+
172
+ if (fs.existsSync(certPath) && fs.existsSync(keyPath)) {
173
+ try {
174
+ return { cert: fs.readFileSync(certPath), key: fs.readFileSync(keyPath) };
175
+ } catch {}
176
+ }
177
+
178
+ try {
179
+ fs.mkdirSync(SPACES_DIR, { recursive: true });
180
+ execFileSync('openssl', [
181
+ 'req', '-x509', '-newkey', 'rsa:2048',
182
+ '-keyout', keyPath, '-out', certPath,
183
+ '-sha256', '-days', '365', '-nodes',
184
+ '-subj', '/CN=spaces-local',
185
+ '-addext', 'subjectAltName=DNS:localhost,DNS:*.local,DNS:*.robindale.com,IP:127.0.0.1',
186
+ ], { stdio: 'pipe', timeout: 15000 });
187
+ console.log(' Generated self-signed TLS certificate');
188
+ return { cert: fs.readFileSync(certPath), key: fs.readFileSync(keyPath) };
189
+ } catch (e) {
190
+ console.log(` Warning: Could not generate TLS cert (${e.message})`);
191
+ console.log(' HTTPS will not be available. Install OpenSSL to enable it.');
192
+ return null;
193
+ }
194
+ }
195
+
196
+ function startServer() {
197
+ // ─── Load saved config ────────────────────────────────────
198
+ let savedConfig = {};
199
+ if (fs.existsSync(CONFIG_PATH)) {
200
+ try { savedConfig = JSON.parse(fs.readFileSync(CONFIG_PATH, 'utf-8')); } catch {}
201
+ }
202
+
203
+ // ─── Resolve settings (CLI > env > config > defaults) ─────
204
+ const PORT = cliFlags.port
205
+ || parseInt(process.env.SPACES_PORT || '', 10)
206
+ || savedConfig.port
207
+ || 3457;
208
+
209
+ const basePath = cliFlags.basePath
210
+ || process.env.SPACES_BASE_PATH
211
+ || savedConfig.basePath
212
+ || '';
213
+
214
+ const allowedOrigins = process.env.SPACES_ALLOWED_ORIGINS
215
+ || savedConfig.allowedOrigins
216
+ || '';
217
+
218
+ // ─── Kill any existing server on this port ───────────────────
219
+ stopServer();
220
+
221
+ // ─── Resolve optional packages once ─────────────────────────
222
+ const proPath = resolveSpacesPro();
223
+ const teamsPath = resolveSpacesTeams();
224
+ const cortexPath = resolveSpacesCortex();
225
+
226
+ // Tier resolution: CLI > env > config > auto-detect
227
+ let tier = cliFlags.tier
228
+ || process.env.SPACES_TIER
229
+ || savedConfig.tier
230
+ || '';
231
+
232
+ // Auto-detect tier from package presence
233
+ if (!tier) {
234
+ if (proPath) tier = 'federation';
235
+ else if (teamsPath) tier = 'team';
236
+ else tier = 'community';
237
+ }
238
+
239
+ console.log('');
240
+ console.log(' Spaces - Agent Workspace Manager');
241
+ console.log(' =================================');
242
+ console.log('');
243
+ console.log(` Tier: ${tier}`);
244
+
245
+ // ─── Server tier prerequisites ────────────────────────────
246
+ const childEnv = { ...process.env };
247
+
248
+ if (tier !== 'community') {
249
+ // team/federation tiers require @spaces/teams (auth + collaboration)
250
+ if ((tier === 'team' || tier === 'federation') && !teamsPath) {
251
+ console.error(' Error: @spaces/teams is required for team/federation tiers.');
252
+ console.error(' Install it: spaces install teams');
253
+ process.exit(1);
254
+ }
255
+ // federation tier requires @spaces/pro (network)
256
+ if (tier === 'federation' && !proPath) {
257
+ console.error(' Error: @spaces/pro is required for the federation tier.');
258
+ console.error(' Install it: spaces install pro');
259
+ process.exit(1);
260
+ }
261
+
262
+ // Check for session secret
263
+ let sessionSecret = process.env.SPACES_SESSION_SECRET || '';
264
+ if (!sessionSecret && fs.existsSync(SESSION_SECRET_PATH)) {
265
+ sessionSecret = fs.readFileSync(SESSION_SECRET_PATH, 'utf-8').trim();
266
+ }
267
+
268
+ // Check for admin DB — auto-setup if missing
269
+ const adminDbPath = path.join(SPACES_DIR, 'admin.db');
270
+ if (!fs.existsSync(adminDbPath) || !sessionSecret) {
271
+ const { autoSetup } = require('./lib/auto-setup');
272
+ const result = autoSetup({ SPACES_DIR, SESSION_SECRET_PATH, ADMIN_DB_PATH: adminDbPath, CONFIG_PATH, tier, port: PORT, basePath });
273
+ sessionSecret = result.sessionSecret;
274
+ }
275
+
276
+ childEnv.SPACES_SESSION_SECRET = sessionSecret;
277
+ process.env.SPACES_SESSION_SECRET = sessionSecret;
278
+ console.log(` Admin DB: ${adminDbPath}`);
279
+ }
280
+
281
+ // Set tier in both child env and own process env (terminal-server reads it)
282
+ childEnv.SPACES_TIER = tier;
283
+ process.env.SPACES_TIER = tier;
284
+ if (basePath) {
285
+ childEnv.SPACES_BASE_PATH = basePath;
286
+ console.log(` Base path: ${basePath}`);
287
+ }
288
+ if (allowedOrigins) {
289
+ childEnv.SPACES_ALLOWED_ORIGINS = allowedOrigins;
290
+ process.env.SPACES_ALLOWED_ORIGINS = allowedOrigins;
291
+ console.log(` Allowed origins: ${allowedOrigins}`);
292
+ }
293
+
294
+ // ─── Resolve NODE_PATH for @spaces/pro and @spaces/teams ──
295
+ // Update both childEnv (for the Next.js child process) and process.env
296
+ // (for terminal-server.js which runs in this same parent process).
297
+ // Include:
298
+ // - Managed packages node_modules (~/.spaces/packages/node_modules)
299
+ // - Each managed package's own node_modules (for its bundled deps)
300
+ // - The host app's own node_modules (fallback for peer deps)
301
+ const appNodeModules = path.join(projectDir, 'node_modules');
302
+ const nodePaths = [MANAGED_NODE_MODULES, appNodeModules];
303
+ // Add each resolved package's own node_modules so its bundled deps are found
304
+ for (const pkgPath of [proPath, teamsPath, cortexPath]) {
305
+ if (pkgPath) {
306
+ // pkgPath is the package root (symlink target or direct path)
307
+ const realPath = fs.realpathSync(pkgPath);
308
+ const pkgNodeModules = path.join(realPath, 'node_modules');
309
+ if (fs.existsSync(pkgNodeModules) && !nodePaths.includes(pkgNodeModules)) {
310
+ nodePaths.push(pkgNodeModules);
311
+ }
312
+ // Also add the parent scope for @spaces/* resolution
313
+ const parentModules = path.dirname(path.dirname(pkgPath));
314
+ if (!nodePaths.includes(parentModules)) {
315
+ nodePaths.push(parentModules);
316
+ }
317
+ }
318
+ }
319
+ for (const dir of nodePaths) {
320
+ for (const target of [childEnv, process.env]) {
321
+ const existing = target.NODE_PATH || '';
322
+ if (!existing.includes(dir)) {
323
+ target.NODE_PATH = existing
324
+ ? `${dir}${path.delimiter}${existing}`
325
+ : dir;
326
+ }
327
+ }
328
+ }
329
+ // Re-init module paths so require() in this process picks up the new NODE_PATH
330
+ require('module').Module._initPaths();
331
+
332
+ // Verify collaboration pipeline works end-to-end at startup
333
+ if (tier === 'team' || tier === 'federation') {
334
+ try {
335
+ const teams = require('@spaces/teams');
336
+ console.log(' Collaboration: @spaces/teams loaded OK');
337
+ // Smoke-test that peer deps resolve from this process
338
+ require('better-sqlite3');
339
+ } catch (e) {
340
+ console.error(` Warning: Collaboration may not work — ${e.message}`);
341
+ console.error(' Check that NODE_PATH includes the host app node_modules.');
342
+ }
343
+ }
344
+
345
+ // ─── Detect @spaces/cortex ──────────────────────────────────
346
+ if (cortexPath) {
347
+ childEnv.SPACES_HAS_CORTEX = '1';
348
+ process.env.SPACES_HAS_CORTEX = '1';
349
+ console.log(' Cortex: @spaces/cortex detected');
350
+ }
351
+
352
+ console.log('');
353
+
354
+ // ─── Background update check (non-blocking, repeats every 4h) ──
355
+ // Checks npm registry, GitHub releases, and addon git repos.
356
+ // Writes results to ~/.spaces/update-check.json for the UI banner.
357
+ const updateCheckPath = path.join(SPACES_DIR, 'update-check.json');
358
+ const checkForUpdates = async (logIfAvailable = true) => {
359
+ try {
360
+ const pkg = require(path.join(projectDir, 'package.json'));
361
+ const currentVersion = pkg.version;
362
+ const npmName = pkg.name || '@jlongo78/agent-spaces';
363
+ const githubRepo = 'jlongo78/spaces';
364
+
365
+ // Check npm registry
366
+ let npmLatest = null;
367
+ try {
368
+ const res = await fetch(`https://registry.npmjs.org/${encodeURIComponent(npmName)}/latest`, {
369
+ signal: AbortSignal.timeout(5000),
370
+ });
371
+ if (res.ok) {
372
+ const data = await res.json();
373
+ npmLatest = data.version;
374
+ }
375
+ } catch { /* */ }
376
+
377
+ // Check GitHub for latest release or tag (may be ahead of npm)
378
+ let githubLatest = null;
379
+ let githubPrerelease = false;
380
+ let githubUrl = null;
381
+ try {
382
+ // Check releases first (includes pre-releases)
383
+ const res = await fetch(`https://api.github.com/repos/${githubRepo}/releases?per_page=5`, {
384
+ signal: AbortSignal.timeout(5000),
385
+ headers: { 'Accept': 'application/vnd.github.v3+json', 'User-Agent': 'agent-spaces' },
386
+ });
387
+ if (res.ok) {
388
+ const releases = await res.json();
389
+ if (releases.length > 0) {
390
+ // Find latest stable and latest pre-release
391
+ const stable = releases.find(r => !r.prerelease && !r.draft);
392
+ const pre = releases.find(r => r.prerelease && !r.draft);
393
+ if (stable) {
394
+ githubLatest = stable.tag_name.replace(/^v/, '');
395
+ githubUrl = stable.html_url;
396
+ }
397
+ if (pre) {
398
+ const preVersion = pre.tag_name.replace(/^v/, '');
399
+ // If pre-release is newer than stable, surface it
400
+ if (!githubLatest || preVersion > githubLatest) {
401
+ githubLatest = preVersion;
402
+ githubPrerelease = true;
403
+ githubUrl = pre.html_url;
404
+ }
405
+ }
406
+ }
407
+ }
408
+ } catch { /* */ }
409
+
410
+ // Check addon git repos
411
+ const gitSafe = ['-c', 'safe.directory=*'];
412
+ const addonPaths = { teams: teamsPath, pro: proPath, cortex: cortexPath };
413
+ const addons = {};
414
+ for (const [key, addonDir] of Object.entries(addonPaths)) {
415
+ if (!addonDir || !fs.existsSync(path.join(addonDir, '.git'))) continue;
416
+ const realDir = fs.realpathSync(addonDir);
417
+ try {
418
+ execFileSync('git', [...gitSafe, 'fetch', '--quiet'], { cwd: realDir, stdio: 'ignore', timeout: 5000 });
419
+ const local = execFileSync('git', [...gitSafe, 'rev-parse', 'HEAD'], { cwd: realDir, encoding: 'utf-8' }).trim();
420
+ const remote = execFileSync('git', [...gitSafe, 'rev-parse', '@{u}'], { cwd: realDir, encoding: 'utf-8' }).trim();
421
+ let commitsBehind = 0;
422
+ if (local !== remote) {
423
+ try {
424
+ const count = execFileSync('git', [...gitSafe, 'rev-list', '--count', `HEAD..@{u}`], { cwd: realDir, encoding: 'utf-8' }).trim();
425
+ commitsBehind = parseInt(count, 10) || 0;
426
+ } catch { /* */ }
427
+ }
428
+ const behind = commitsBehind > 0;
429
+ addons[key] = { installed: true, behind, commitsBehind, localHead: local.slice(0, 7) };
430
+ if (behind && logIfAvailable) {
431
+ console.log(` Update available for @spaces/${key}: ${commitsBehind} commit(s) behind (run: spaces upgrade ${key})`);
432
+ }
433
+ } catch {
434
+ addons[key] = { installed: true, behind: false, commitsBehind: 0 };
435
+ }
436
+ }
437
+
438
+ const npmAvailable = npmLatest && npmLatest !== currentVersion && npmLatest > currentVersion;
439
+ const githubAvailable = githubLatest && githubLatest !== currentVersion && githubLatest > currentVersion;
440
+
441
+ const result = {
442
+ current: currentVersion,
443
+ npm: npmLatest ? { latest: npmLatest, available: !!npmAvailable } : null,
444
+ github: githubLatest ? { latest: githubLatest, prerelease: githubPrerelease, url: githubUrl, available: !!githubAvailable } : null,
445
+ // Backward compat: 'available' and 'latest' still work for the existing banner
446
+ latest: npmLatest || githubLatest || currentVersion,
447
+ available: !!(npmAvailable || githubAvailable),
448
+ addons,
449
+ checkedAt: Date.now(),
450
+ name: npmName,
451
+ };
452
+
453
+ fs.writeFileSync(updateCheckPath, JSON.stringify(result, null, 2));
454
+
455
+ if (npmAvailable && logIfAvailable) {
456
+ console.log(` Update available: ${currentVersion} → ${npmLatest} (run: npm i -g ${npmName})`);
457
+ }
458
+ if (githubAvailable && (!npmAvailable || githubLatest > npmLatest) && logIfAvailable) {
459
+ console.log(` GitHub ${githubPrerelease ? 'pre-release' : 'release'}: ${githubLatest} (${githubUrl || `https://github.com/${githubRepo}/releases`})`);
460
+ }
461
+ } catch { /* network error — skip silently */ }
462
+ };
463
+ checkForUpdates(true);
464
+ setInterval(() => checkForUpdates(false), 4 * 3600_000);
465
+
466
+ // Check for ~/.claude/ directory
467
+ const claudeDir = path.join(os.homedir(), '.claude');
468
+ if (!fs.existsSync(claudeDir)) {
469
+ console.log(' Warning: ~/.claude/ not found. Have you used Claude Code yet?');
470
+ console.log('');
471
+ }
472
+
473
+ // ─── Detect build type ────────────────────────────────────
474
+ const standaloneServer = path.join(projectDir, '.next', 'standalone', 'server.js');
475
+ const fullBuildDir = path.join(projectDir, '.next', 'BUILD_ID');
476
+ const isStandalone = fs.existsSync(standaloneServer);
477
+ const isFullBuild = fs.existsSync(fullBuildDir);
478
+
479
+ if (!isStandalone && !isFullBuild) {
480
+ console.error(' Error: No build found.');
481
+ console.error(' Run "npm run build" first, or install via "npm install -g @jlongo78/agent-spaces".');
482
+ process.exit(1);
483
+ }
484
+
485
+ // ─── Spawn Next.js ────────────────────────────────────────
486
+ let next;
487
+ if (isStandalone) {
488
+ const parentNodeModules = path.join(projectDir, 'node_modules');
489
+ const existingNodePath = childEnv.NODE_PATH || '';
490
+ childEnv.NODE_PATH = existingNodePath
491
+ ? `${parentNodeModules}${path.delimiter}${existingNodePath}`
492
+ : parentNodeModules;
493
+
494
+ next = spawn(process.execPath, [standaloneServer], {
495
+ cwd: path.dirname(standaloneServer),
496
+ stdio: ['ignore', 'pipe', 'pipe'],
497
+ env: {
498
+ ...childEnv,
499
+ PORT: String(NEXT_INTERNAL_PORT),
500
+ HOSTNAME: '0.0.0.0',
501
+ NODE_ENV: 'production',
502
+ },
503
+ });
504
+ } else {
505
+ next = spawn('npx', ['next', 'start', '--port', String(NEXT_INTERNAL_PORT)], {
506
+ cwd: projectDir,
507
+ stdio: ['ignore', 'pipe', 'pipe'],
508
+ env: {
509
+ ...childEnv,
510
+ PORT: String(NEXT_INTERNAL_PORT),
511
+ HOSTNAME: '0.0.0.0',
512
+ NODE_ENV: 'production',
513
+ },
514
+ shell: true,
515
+ });
516
+ }
517
+
518
+ let nextReady = false;
519
+
520
+ next.stdout.on('data', (data) => {
521
+ const msg = data.toString();
522
+ process.stdout.write(msg);
523
+ if (!nextReady && (msg.includes('Ready') || msg.includes('started server') || msg.includes('Listening') || msg.includes('localhost'))) {
524
+ nextReady = true;
525
+ console.log(`\n Ready at http://localhost:${PORT}`);
526
+ if (tlsCreds) console.log(` Also at https://localhost:${PORT} (self-signed)`);
527
+ console.log('');
528
+
529
+ const url = `http://localhost:${PORT}`;
530
+ const isService = process.env.SPACES_SERVICE === '1';
531
+ if (!isService) {
532
+ try {
533
+ if (process.platform === 'win32') {
534
+ execFileSync('cmd', ['/c', 'start', url], { stdio: 'ignore' });
535
+ } else if (process.platform === 'darwin') {
536
+ execFileSync('open', [url], { stdio: 'ignore' });
537
+ } else {
538
+ execFileSync('xdg-open', [url], { stdio: 'ignore' });
539
+ }
540
+ } catch {
541
+ console.log(` Open ${url} in your browser`);
542
+ }
543
+ }
544
+ }
545
+ });
546
+
547
+ next.stderr.on('data', (data) => {
548
+ const msg = data.toString();
549
+ if (!msg.includes('Warning')) {
550
+ process.stderr.write(data);
551
+ }
552
+ });
553
+
554
+ next.on('exit', (code) => {
555
+ if (code !== 0 && code !== null) {
556
+ console.error(` [spaces] Next.js exited with code ${code}`);
557
+ }
558
+ cleanup();
559
+ });
560
+
561
+ // ─── Proxy request handler (shared by HTTP and HTTPS) ────
562
+ function proxyHandler(req, res) {
563
+ // WebSocket paths are handled by the 'upgrade' event, but a plain
564
+ // HTTP request to /ws (e.g. health check) should not be proxied to
565
+ // Next.js which would 308-redirect it due to trailingSlash.
566
+ const urlPath = (req.url || '').split('?')[0];
567
+ if (urlPath === '/ws' || urlPath.endsWith('/ws') || urlPath.endsWith('/ws/')) {
568
+ res.writeHead(200, { 'Content-Type': 'text/plain' });
569
+ res.end('WebSocket endpoint');
570
+ return;
571
+ }
572
+
573
+ const proxyReq = http.request(
574
+ {
575
+ hostname: '127.0.0.1',
576
+ port: NEXT_INTERNAL_PORT,
577
+ path: req.url,
578
+ method: req.method,
579
+ headers: req.headers,
580
+ },
581
+ (proxyRes) => {
582
+ res.writeHead(proxyRes.statusCode, proxyRes.headers);
583
+ proxyRes.pipe(res);
584
+ }
585
+ );
586
+ proxyReq.on('error', () => {
587
+ if (!res.headersSent) {
588
+ res.writeHead(502);
589
+ res.end('Server not ready yet. Refresh in a moment.');
590
+ }
591
+ });
592
+ req.pipe(proxyReq);
593
+ }
594
+
595
+ // ─── HTTP + HTTPS on a single port ─────────────────────────
596
+ // Peek at the first byte of each connection: 0x16 = TLS ClientHello,
597
+ // anything else = plain HTTP. This lets mobile browsers that force
598
+ // HTTPS-first connect to the same port without a separate listener.
599
+ const httpServer = http.createServer(proxyHandler);
600
+ const tlsCreds = ensureTlsCert();
601
+ const httpsServer = tlsCreds ? https.createServer(tlsCreds, proxyHandler) : null;
602
+
603
+ const { createTerminalServer } = require('./terminal-server');
604
+ createTerminalServer(httpServer);
605
+ if (httpsServer) createTerminalServer(httpsServer);
606
+
607
+ // Wire up 'address()' on the inner servers so terminal-server can
608
+ // discover the port, then emit 'listening' so its event handler fires.
609
+ const patchAddress = (srv) => { srv.address = () => ({ port: PORT }); };
610
+ patchAddress(httpServer);
611
+ if (httpsServer) patchAddress(httpsServer);
612
+
613
+ const dualServer = net.createServer((socket) => {
614
+ // If client connects but sends nothing for 5s, destroy.
615
+ // Once routed, clear the timeout so long-lived connections (WebSocket) aren't killed.
616
+ socket.setTimeout(5000, () => socket.destroy());
617
+ socket.once('data', (buf) => {
618
+ socket.setTimeout(0);
619
+ socket.pause();
620
+ const target = (buf[0] === 0x16 && httpsServer) ? httpsServer : httpServer;
621
+ target.emit('connection', socket);
622
+ socket.unshift(buf);
623
+ socket.resume();
624
+ });
625
+ });
626
+
627
+ dualServer.listen(PORT, () => {
628
+ // Now that the port is bound, tell the inner servers they're "listening"
629
+ // so terminal-server's mDNS and message watcher start up.
630
+ httpServer.emit('listening');
631
+ if (httpsServer) httpsServer.emit('listening');
632
+
633
+ if (httpsServer) {
634
+ console.log(` Starting server on port ${PORT} (HTTP + HTTPS)`);
635
+ } else {
636
+ console.log(` Starting server on http://localhost:${PORT}`);
637
+ }
638
+ console.log('');
639
+ });
640
+
641
+ function cleanup() {
642
+ next.kill();
643
+ dualServer.close();
644
+ process.exit(0);
645
+ }
646
+
647
+ process.on('SIGINT', cleanup);
648
+ process.on('SIGTERM', cleanup);
649
+ }
650
+
651
+ // ─── Stop running server ─────────────────────────────────────
652
+ function findPidsOnPort(port) {
653
+ const pids = new Set();
654
+ if (process.platform === 'win32') {
655
+ try {
656
+ const output = execFileSync('netstat', ['-ano'], { encoding: 'utf-8' });
657
+ for (const line of output.split(String.fromCharCode(10))) {
658
+ if (line.includes(':' + port + ' ') && line.includes('LISTENING')) {
659
+ const parts = line.trim().split(/\s+/);
660
+ const pid = parseInt(parts[parts.length - 1], 10);
661
+ if (pid > 0) pids.add(pid);
662
+ }
663
+ }
664
+ } catch {}
665
+ } else {
666
+ try {
667
+ const output = execFileSync('lsof', ['-ti', `tcp:${port}`], { encoding: 'utf-8' }).trim();
668
+ for (const p of output.split('\n')) { if (p.trim()) pids.add(parseInt(p.trim(), 10)); }
669
+ } catch {}
670
+ try {
671
+ const output = execFileSync('fuser', [`${port}/tcp`], { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] }).trim();
672
+ for (const p of output.split(/\s+/)) { if (p.trim()) pids.add(parseInt(p.trim(), 10)); }
673
+ } catch {}
674
+ }
675
+ return [...pids].filter(p => !isNaN(p) && p > 0);
676
+ }
677
+
678
+ function stopServer() {
679
+ let savedConfig = {};
680
+ if (fs.existsSync(CONFIG_PATH)) {
681
+ try { savedConfig = JSON.parse(fs.readFileSync(CONFIG_PATH, 'utf-8')); } catch {}
682
+ }
683
+ const port = parseInt(process.env.SPACES_PORT || '', 10) || savedConfig.port || 3457;
684
+ const ports = [port, NEXT_INTERNAL_PORT];
685
+ let killed = 0;
686
+
687
+ for (const p of ports) {
688
+ for (const pid of findPidsOnPort(p)) {
689
+ try {
690
+ process.kill(pid, 'SIGTERM');
691
+ killed++;
692
+ } catch {}
693
+ }
694
+ }
695
+
696
+ if (killed > 0) {
697
+ console.log(` Stopped ${killed} process(es) on port ${port}`);
698
+ // Wait for ports to be released, escalate to SIGKILL if needed
699
+ const deadline = Date.now() + 2000;
700
+ let escalated = false;
701
+ while (Date.now() < deadline) {
702
+ const remaining = ports.flatMap(p => findPidsOnPort(p));
703
+ if (remaining.length === 0) break;
704
+ if (!escalated && Date.now() > deadline - 1000) {
705
+ for (const pid of remaining) {
706
+ try { process.kill(pid, 'SIGKILL'); } catch {}
707
+ }
708
+ escalated = true;
709
+ }
710
+ if (process.platform === 'win32') { require('child_process').spawnSync('powershell', ['-Command', 'Start-Sleep -Milliseconds 200']); } else { require('child_process').spawnSync('sleep', ['0.2']); }
711
+ }
712
+ } else {
713
+ console.log(` No running server found on port ${port}`);
714
+ }
715
+ }
716
+
717
+ // ─── @spaces/pro resolution ──────────────────────────────────
718
+ function resolveSpacesPro() {
719
+ // 1. Managed install (~/.spaces/packages/)
720
+ const managed = path.join(MANAGED_NODE_MODULES, '@spaces', 'pro');
721
+ if (fs.existsSync(path.join(managed, 'dist', 'index.js'))) return managed;
722
+
723
+ // 2. Local node_modules (npm link / optionalDep)
724
+ try {
725
+ return require.resolve('@spaces/pro');
726
+ } catch {}
727
+
728
+ // 3. Global npm prefix (legacy)
729
+ try {
730
+ const globalPrefix = execFileSync('npm', ['prefix', '-g'], { encoding: 'utf-8' }).trim();
731
+ const globalProPath = path.join(globalPrefix, 'lib', 'node_modules', '@spaces', 'pro');
732
+ if (fs.existsSync(globalProPath)) return globalProPath;
733
+ const altPath = path.join(globalPrefix, 'node_modules', '@spaces', 'pro');
734
+ if (fs.existsSync(altPath)) return altPath;
735
+ } catch {}
736
+
737
+ return null;
738
+ }
739
+
740
+ // ─── @spaces/teams resolution ────────────────────────────────
741
+ function resolveSpacesTeams() {
742
+ // 1. Managed install (~/.spaces/packages/)
743
+ const managed = path.join(MANAGED_NODE_MODULES, '@spaces', 'teams');
744
+ if (fs.existsSync(path.join(managed, 'dist', 'index.js'))) return managed;
745
+
746
+ // 2. Local node_modules (npm link / optionalDep)
747
+ try {
748
+ return require.resolve('@spaces/teams');
749
+ } catch {}
750
+
751
+ // 3. Global npm prefix (legacy)
752
+ try {
753
+ const globalPrefix = execFileSync('npm', ['prefix', '-g'], { encoding: 'utf-8' }).trim();
754
+ const globalTeamsPath = path.join(globalPrefix, 'lib', 'node_modules', '@spaces', 'teams');
755
+ if (fs.existsSync(globalTeamsPath)) return globalTeamsPath;
756
+ const altPath = path.join(globalPrefix, 'node_modules', '@spaces', 'teams');
757
+ if (fs.existsSync(altPath)) return altPath;
758
+ } catch {}
759
+
760
+ return null;
761
+ }
762
+
763
+ // ─── @spaces/cortex resolution ───────────────────────────────
764
+ function resolveSpacesCortex() {
765
+ const managed = path.join(MANAGED_NODE_MODULES, '@spaces', 'cortex');
766
+ if (fs.existsSync(path.join(managed, 'dist', 'index.js'))) return managed;
767
+ try { return require.resolve('@spaces/cortex'); } catch {}
768
+ try {
769
+ const globalPrefix = execFileSync('npm', ['prefix', '-g'], { encoding: 'utf-8' }).trim();
770
+ const globalPath = path.join(globalPrefix, 'lib', 'node_modules', '@spaces', 'cortex');
771
+ if (fs.existsSync(globalPath)) return globalPath;
772
+ const altPath = path.join(globalPrefix, 'node_modules', '@spaces', 'cortex');
773
+ if (fs.existsSync(altPath)) return altPath;
774
+ } catch {}
775
+ return null;
776
+ }