@jlongo78/agent-spaces 0.5.3 → 0.5.4

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 (320) hide show
  1. package/.next/standalone/.claude/settings.local.json +16 -0
  2. package/.next/standalone/.next/BUILD_ID +1 -1
  3. package/.next/standalone/.next/build-manifest.json +2 -2
  4. package/.next/standalone/.next/prerender-manifest.json +3 -3
  5. package/.next/standalone/.next/required-server-files.json +19 -19
  6. package/.next/standalone/.next/server/app/(desktop)/admin/analytics/page_client-reference-manifest.js +1 -1
  7. package/.next/standalone/.next/server/app/(desktop)/admin/users/page_client-reference-manifest.js +1 -1
  8. package/.next/standalone/.next/server/app/(desktop)/analytics/page_client-reference-manifest.js +1 -1
  9. package/.next/standalone/.next/server/app/(desktop)/network/page_client-reference-manifest.js +1 -1
  10. package/.next/standalone/.next/server/app/(desktop)/page_client-reference-manifest.js +1 -1
  11. package/.next/standalone/.next/server/app/(desktop)/projects/page_client-reference-manifest.js +1 -1
  12. package/.next/standalone/.next/server/app/(desktop)/sessions/[id]/page_client-reference-manifest.js +1 -1
  13. package/.next/standalone/.next/server/app/(desktop)/sessions/page_client-reference-manifest.js +1 -1
  14. package/.next/standalone/.next/server/app/(desktop)/settings/page_client-reference-manifest.js +1 -1
  15. package/.next/standalone/.next/server/app/(desktop)/terminal/page_client-reference-manifest.js +1 -1
  16. package/.next/standalone/.next/server/app/(desktop)/terminal/pane/[id]/page_client-reference-manifest.js +1 -1
  17. package/.next/standalone/.next/server/app/(desktop)/terminal/remote/[nodeId]/[workspaceId]/page_client-reference-manifest.js +1 -1
  18. package/.next/standalone/.next/server/app/(desktop)/workspaces/page_client-reference-manifest.js +1 -1
  19. package/.next/standalone/.next/server/app/_global-error.html +2 -2
  20. package/.next/standalone/.next/server/app/_global-error.rsc +1 -1
  21. package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  22. package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  23. package/.next/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  24. package/.next/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  25. package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  26. package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  27. package/.next/standalone/.next/server/app/_not-found.html +1 -1
  28. package/.next/standalone/.next/server/app/_not-found.rsc +3 -3
  29. package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
  30. package/.next/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  31. package/.next/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
  32. package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  33. package/.next/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  34. package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  35. package/.next/standalone/.next/server/app/admin/analytics.html +1 -1
  36. package/.next/standalone/.next/server/app/admin/analytics.rsc +5 -5
  37. package/.next/standalone/.next/server/app/admin/analytics.segments/!KGRlc2t0b3Ap/admin/analytics/__PAGE__.segment.rsc +2 -2
  38. package/.next/standalone/.next/server/app/admin/analytics.segments/!KGRlc2t0b3Ap/admin/analytics.segment.rsc +1 -1
  39. package/.next/standalone/.next/server/app/admin/analytics.segments/!KGRlc2t0b3Ap/admin.segment.rsc +1 -1
  40. package/.next/standalone/.next/server/app/admin/analytics.segments/!KGRlc2t0b3Ap.segment.rsc +2 -2
  41. package/.next/standalone/.next/server/app/admin/analytics.segments/_full.segment.rsc +5 -5
  42. package/.next/standalone/.next/server/app/admin/analytics.segments/_head.segment.rsc +1 -1
  43. package/.next/standalone/.next/server/app/admin/analytics.segments/_index.segment.rsc +3 -3
  44. package/.next/standalone/.next/server/app/admin/analytics.segments/_tree.segment.rsc +2 -2
  45. package/.next/standalone/.next/server/app/admin/users.html +1 -1
  46. package/.next/standalone/.next/server/app/admin/users.rsc +5 -5
  47. package/.next/standalone/.next/server/app/admin/users.segments/!KGRlc2t0b3Ap/admin/users/__PAGE__.segment.rsc +2 -2
  48. package/.next/standalone/.next/server/app/admin/users.segments/!KGRlc2t0b3Ap/admin/users.segment.rsc +1 -1
  49. package/.next/standalone/.next/server/app/admin/users.segments/!KGRlc2t0b3Ap/admin.segment.rsc +1 -1
  50. package/.next/standalone/.next/server/app/admin/users.segments/!KGRlc2t0b3Ap.segment.rsc +2 -2
  51. package/.next/standalone/.next/server/app/admin/users.segments/_full.segment.rsc +5 -5
  52. package/.next/standalone/.next/server/app/admin/users.segments/_head.segment.rsc +1 -1
  53. package/.next/standalone/.next/server/app/admin/users.segments/_index.segment.rsc +3 -3
  54. package/.next/standalone/.next/server/app/admin/users.segments/_tree.segment.rsc +2 -2
  55. package/.next/standalone/.next/server/app/analytics.html +1 -1
  56. package/.next/standalone/.next/server/app/analytics.rsc +5 -5
  57. package/.next/standalone/.next/server/app/analytics.segments/!KGRlc2t0b3Ap/analytics/__PAGE__.segment.rsc +2 -2
  58. package/.next/standalone/.next/server/app/analytics.segments/!KGRlc2t0b3Ap/analytics.segment.rsc +1 -1
  59. package/.next/standalone/.next/server/app/analytics.segments/!KGRlc2t0b3Ap.segment.rsc +2 -2
  60. package/.next/standalone/.next/server/app/analytics.segments/_full.segment.rsc +5 -5
  61. package/.next/standalone/.next/server/app/analytics.segments/_head.segment.rsc +1 -1
  62. package/.next/standalone/.next/server/app/analytics.segments/_index.segment.rsc +3 -3
  63. package/.next/standalone/.next/server/app/analytics.segments/_tree.segment.rsc +2 -2
  64. package/.next/standalone/.next/server/app/api/analytics/overview/route.js.nft.json +1 -1
  65. package/.next/standalone/.next/server/app/api/bulk/route.js.nft.json +1 -1
  66. package/.next/standalone/.next/server/app/api/chat/route.js +1 -1
  67. package/.next/standalone/.next/server/app/api/chat/route.js.nft.json +1 -1
  68. package/.next/standalone/.next/server/app/api/config/route.js.nft.json +1 -1
  69. package/.next/standalone/.next/server/app/api/events/route.js.nft.json +1 -1
  70. package/.next/standalone/.next/server/app/api/folders/route.js.nft.json +1 -1
  71. package/.next/standalone/.next/server/app/api/network/handshake/route.js +1 -1
  72. package/.next/standalone/.next/server/app/api/network/handshake/route.js.nft.json +1 -1
  73. package/.next/standalone/.next/server/app/api/network/projects/route.js +2 -1
  74. package/.next/standalone/.next/server/app/api/network/projects/route.js.nft.json +1 -1
  75. package/.next/standalone/.next/server/app/api/network/search/route.js +2 -1
  76. package/.next/standalone/.next/server/app/api/network/search/route.js.nft.json +1 -1
  77. package/.next/standalone/.next/server/app/api/network/sessions/[id]/messages/route.js +2 -1
  78. package/.next/standalone/.next/server/app/api/network/sessions/[id]/messages/route.js.nft.json +1 -1
  79. package/.next/standalone/.next/server/app/api/network/sessions/[id]/route.js +2 -1
  80. package/.next/standalone/.next/server/app/api/network/sessions/[id]/route.js.nft.json +1 -1
  81. package/.next/standalone/.next/server/app/api/network/sessions/route.js +2 -1
  82. package/.next/standalone/.next/server/app/api/network/sessions/route.js.nft.json +1 -1
  83. package/.next/standalone/.next/server/app/api/network/workspaces/[id]/route.js +2 -1
  84. package/.next/standalone/.next/server/app/api/network/workspaces/[id]/route.js.nft.json +1 -1
  85. package/.next/standalone/.next/server/app/api/network/workspaces/route.js +2 -1
  86. package/.next/standalone/.next/server/app/api/network/workspaces/route.js.nft.json +1 -1
  87. package/.next/standalone/.next/server/app/api/panes/[id]/route.js.nft.json +1 -1
  88. package/.next/standalone/.next/server/app/api/panes/route.js.nft.json +1 -1
  89. package/.next/standalone/.next/server/app/api/projects/route.js.nft.json +1 -1
  90. package/.next/standalone/.next/server/app/api/search/route.js +1 -1
  91. package/.next/standalone/.next/server/app/api/search/route.js.nft.json +1 -1
  92. package/.next/standalone/.next/server/app/api/sessions/[id]/chat/route.js.nft.json +1 -1
  93. package/.next/standalone/.next/server/app/api/sessions/[id]/messages/route.js.nft.json +1 -1
  94. package/.next/standalone/.next/server/app/api/sessions/[id]/route.js.nft.json +1 -1
  95. package/.next/standalone/.next/server/app/api/sessions/route.js +1 -1
  96. package/.next/standalone/.next/server/app/api/sessions/route.js.nft.json +1 -1
  97. package/.next/standalone/.next/server/app/api/sync/route.js.nft.json +1 -1
  98. package/.next/standalone/.next/server/app/api/tags/route.js.nft.json +1 -1
  99. package/.next/standalone/.next/server/app/api/tier/route.js +1 -1
  100. package/.next/standalone/.next/server/app/api/tier/route.js.nft.json +1 -1
  101. package/.next/standalone/.next/server/app/api/workspaces/[id]/context/[key]/route.js.nft.json +1 -1
  102. package/.next/standalone/.next/server/app/api/workspaces/[id]/context/route.js.nft.json +1 -1
  103. package/.next/standalone/.next/server/app/api/workspaces/[id]/messages/[msgId]/route.js.nft.json +1 -1
  104. package/.next/standalone/.next/server/app/api/workspaces/[id]/messages/route.js.nft.json +1 -1
  105. package/.next/standalone/.next/server/app/api/workspaces/[id]/route.js.nft.json +1 -1
  106. package/.next/standalone/.next/server/app/api/workspaces/[id]/sessions/route.js.nft.json +1 -1
  107. package/.next/standalone/.next/server/app/api/workspaces/route.js +1 -1
  108. package/.next/standalone/.next/server/app/api/workspaces/route.js.nft.json +1 -1
  109. package/.next/standalone/.next/server/app/login/page_client-reference-manifest.js +1 -1
  110. package/.next/standalone/.next/server/app/login.html +1 -1
  111. package/.next/standalone/.next/server/app/login.rsc +4 -4
  112. package/.next/standalone/.next/server/app/login.segments/_full.segment.rsc +4 -4
  113. package/.next/standalone/.next/server/app/login.segments/_head.segment.rsc +1 -1
  114. package/.next/standalone/.next/server/app/login.segments/_index.segment.rsc +3 -3
  115. package/.next/standalone/.next/server/app/login.segments/_tree.segment.rsc +2 -2
  116. package/.next/standalone/.next/server/app/login.segments/login/__PAGE__.segment.rsc +2 -2
  117. package/.next/standalone/.next/server/app/login.segments/login.segment.rsc +1 -1
  118. package/.next/standalone/.next/server/app/m/page_client-reference-manifest.js +1 -1
  119. package/.next/standalone/.next/server/app/m/projects/page_client-reference-manifest.js +1 -1
  120. package/.next/standalone/.next/server/app/m/projects.html +1 -1
  121. package/.next/standalone/.next/server/app/m/projects.rsc +5 -5
  122. package/.next/standalone/.next/server/app/m/projects.segments/_full.segment.rsc +5 -5
  123. package/.next/standalone/.next/server/app/m/projects.segments/_head.segment.rsc +1 -1
  124. package/.next/standalone/.next/server/app/m/projects.segments/_index.segment.rsc +3 -3
  125. package/.next/standalone/.next/server/app/m/projects.segments/_tree.segment.rsc +2 -2
  126. package/.next/standalone/.next/server/app/m/projects.segments/m/projects/__PAGE__.segment.rsc +2 -2
  127. package/.next/standalone/.next/server/app/m/projects.segments/m/projects.segment.rsc +1 -1
  128. package/.next/standalone/.next/server/app/m/projects.segments/m.segment.rsc +2 -2
  129. package/.next/standalone/.next/server/app/m/sessions/[id]/page_client-reference-manifest.js +1 -1
  130. package/.next/standalone/.next/server/app/m/sessions/page_client-reference-manifest.js +1 -1
  131. package/.next/standalone/.next/server/app/m/sessions.html +1 -1
  132. package/.next/standalone/.next/server/app/m/sessions.rsc +5 -5
  133. package/.next/standalone/.next/server/app/m/sessions.segments/_full.segment.rsc +5 -5
  134. package/.next/standalone/.next/server/app/m/sessions.segments/_head.segment.rsc +1 -1
  135. package/.next/standalone/.next/server/app/m/sessions.segments/_index.segment.rsc +3 -3
  136. package/.next/standalone/.next/server/app/m/sessions.segments/_tree.segment.rsc +2 -2
  137. package/.next/standalone/.next/server/app/m/sessions.segments/m/sessions/__PAGE__.segment.rsc +2 -2
  138. package/.next/standalone/.next/server/app/m/sessions.segments/m/sessions.segment.rsc +1 -1
  139. package/.next/standalone/.next/server/app/m/sessions.segments/m.segment.rsc +2 -2
  140. package/.next/standalone/.next/server/app/m/settings/page_client-reference-manifest.js +1 -1
  141. package/.next/standalone/.next/server/app/m/settings.html +1 -1
  142. package/.next/standalone/.next/server/app/m/settings.rsc +5 -5
  143. package/.next/standalone/.next/server/app/m/settings.segments/_full.segment.rsc +5 -5
  144. package/.next/standalone/.next/server/app/m/settings.segments/_head.segment.rsc +1 -1
  145. package/.next/standalone/.next/server/app/m/settings.segments/_index.segment.rsc +3 -3
  146. package/.next/standalone/.next/server/app/m/settings.segments/_tree.segment.rsc +2 -2
  147. package/.next/standalone/.next/server/app/m/settings.segments/m/settings/__PAGE__.segment.rsc +2 -2
  148. package/.next/standalone/.next/server/app/m/settings.segments/m/settings.segment.rsc +1 -1
  149. package/.next/standalone/.next/server/app/m/settings.segments/m.segment.rsc +2 -2
  150. package/.next/standalone/.next/server/app/m/terminal/page_client-reference-manifest.js +1 -1
  151. package/.next/standalone/.next/server/app/m/terminal.html +1 -1
  152. package/.next/standalone/.next/server/app/m/terminal.rsc +5 -5
  153. package/.next/standalone/.next/server/app/m/terminal.segments/_full.segment.rsc +5 -5
  154. package/.next/standalone/.next/server/app/m/terminal.segments/_head.segment.rsc +1 -1
  155. package/.next/standalone/.next/server/app/m/terminal.segments/_index.segment.rsc +3 -3
  156. package/.next/standalone/.next/server/app/m/terminal.segments/_tree.segment.rsc +2 -2
  157. package/.next/standalone/.next/server/app/m/terminal.segments/m/terminal/__PAGE__.segment.rsc +2 -2
  158. package/.next/standalone/.next/server/app/m/terminal.segments/m/terminal.segment.rsc +1 -1
  159. package/.next/standalone/.next/server/app/m/terminal.segments/m.segment.rsc +2 -2
  160. package/.next/standalone/.next/server/app/m.html +1 -1
  161. package/.next/standalone/.next/server/app/m.rsc +5 -5
  162. package/.next/standalone/.next/server/app/m.segments/_full.segment.rsc +5 -5
  163. package/.next/standalone/.next/server/app/m.segments/_head.segment.rsc +1 -1
  164. package/.next/standalone/.next/server/app/m.segments/_index.segment.rsc +3 -3
  165. package/.next/standalone/.next/server/app/m.segments/_tree.segment.rsc +2 -2
  166. package/.next/standalone/.next/server/app/m.segments/m/__PAGE__.segment.rsc +2 -2
  167. package/.next/standalone/.next/server/app/m.segments/m.segment.rsc +2 -2
  168. package/.next/standalone/.next/server/app/network.html +1 -1
  169. package/.next/standalone/.next/server/app/network.rsc +5 -5
  170. package/.next/standalone/.next/server/app/network.segments/!KGRlc2t0b3Ap/network/__PAGE__.segment.rsc +2 -2
  171. package/.next/standalone/.next/server/app/network.segments/!KGRlc2t0b3Ap/network.segment.rsc +1 -1
  172. package/.next/standalone/.next/server/app/network.segments/!KGRlc2t0b3Ap.segment.rsc +2 -2
  173. package/.next/standalone/.next/server/app/network.segments/_full.segment.rsc +5 -5
  174. package/.next/standalone/.next/server/app/network.segments/_head.segment.rsc +1 -1
  175. package/.next/standalone/.next/server/app/network.segments/_index.segment.rsc +3 -3
  176. package/.next/standalone/.next/server/app/network.segments/_tree.segment.rsc +2 -2
  177. package/.next/standalone/.next/server/app/projects.html +1 -1
  178. package/.next/standalone/.next/server/app/projects.rsc +5 -5
  179. package/.next/standalone/.next/server/app/projects.segments/!KGRlc2t0b3Ap/projects/__PAGE__.segment.rsc +2 -2
  180. package/.next/standalone/.next/server/app/projects.segments/!KGRlc2t0b3Ap/projects.segment.rsc +1 -1
  181. package/.next/standalone/.next/server/app/projects.segments/!KGRlc2t0b3Ap.segment.rsc +2 -2
  182. package/.next/standalone/.next/server/app/projects.segments/_full.segment.rsc +5 -5
  183. package/.next/standalone/.next/server/app/projects.segments/_head.segment.rsc +1 -1
  184. package/.next/standalone/.next/server/app/projects.segments/_index.segment.rsc +3 -3
  185. package/.next/standalone/.next/server/app/projects.segments/_tree.segment.rsc +2 -2
  186. package/.next/standalone/.next/server/app/sessions.html +1 -1
  187. package/.next/standalone/.next/server/app/sessions.rsc +5 -5
  188. package/.next/standalone/.next/server/app/sessions.segments/!KGRlc2t0b3Ap/sessions/__PAGE__.segment.rsc +2 -2
  189. package/.next/standalone/.next/server/app/sessions.segments/!KGRlc2t0b3Ap/sessions.segment.rsc +1 -1
  190. package/.next/standalone/.next/server/app/sessions.segments/!KGRlc2t0b3Ap.segment.rsc +2 -2
  191. package/.next/standalone/.next/server/app/sessions.segments/_full.segment.rsc +5 -5
  192. package/.next/standalone/.next/server/app/sessions.segments/_head.segment.rsc +1 -1
  193. package/.next/standalone/.next/server/app/sessions.segments/_index.segment.rsc +3 -3
  194. package/.next/standalone/.next/server/app/sessions.segments/_tree.segment.rsc +2 -2
  195. package/.next/standalone/.next/server/app/settings.html +1 -1
  196. package/.next/standalone/.next/server/app/settings.rsc +5 -5
  197. package/.next/standalone/.next/server/app/settings.segments/!KGRlc2t0b3Ap/settings/__PAGE__.segment.rsc +2 -2
  198. package/.next/standalone/.next/server/app/settings.segments/!KGRlc2t0b3Ap/settings.segment.rsc +1 -1
  199. package/.next/standalone/.next/server/app/settings.segments/!KGRlc2t0b3Ap.segment.rsc +2 -2
  200. package/.next/standalone/.next/server/app/settings.segments/_full.segment.rsc +5 -5
  201. package/.next/standalone/.next/server/app/settings.segments/_head.segment.rsc +1 -1
  202. package/.next/standalone/.next/server/app/settings.segments/_index.segment.rsc +3 -3
  203. package/.next/standalone/.next/server/app/settings.segments/_tree.segment.rsc +2 -2
  204. package/.next/standalone/.next/server/app/terminal.html +1 -1
  205. package/.next/standalone/.next/server/app/terminal.rsc +5 -5
  206. package/.next/standalone/.next/server/app/terminal.segments/!KGRlc2t0b3Ap/terminal/__PAGE__.segment.rsc +2 -2
  207. package/.next/standalone/.next/server/app/terminal.segments/!KGRlc2t0b3Ap/terminal.segment.rsc +1 -1
  208. package/.next/standalone/.next/server/app/terminal.segments/!KGRlc2t0b3Ap.segment.rsc +2 -2
  209. package/.next/standalone/.next/server/app/terminal.segments/_full.segment.rsc +5 -5
  210. package/.next/standalone/.next/server/app/terminal.segments/_head.segment.rsc +1 -1
  211. package/.next/standalone/.next/server/app/terminal.segments/_index.segment.rsc +3 -3
  212. package/.next/standalone/.next/server/app/terminal.segments/_tree.segment.rsc +2 -2
  213. package/.next/standalone/.next/server/app/workspaces.html +1 -1
  214. package/.next/standalone/.next/server/app/workspaces.rsc +5 -5
  215. package/.next/standalone/.next/server/app/workspaces.segments/!KGRlc2t0b3Ap/workspaces/__PAGE__.segment.rsc +2 -2
  216. package/.next/standalone/.next/server/app/workspaces.segments/!KGRlc2t0b3Ap/workspaces.segment.rsc +1 -1
  217. package/.next/standalone/.next/server/app/workspaces.segments/!KGRlc2t0b3Ap.segment.rsc +2 -2
  218. package/.next/standalone/.next/server/app/workspaces.segments/_full.segment.rsc +5 -5
  219. package/.next/standalone/.next/server/app/workspaces.segments/_head.segment.rsc +1 -1
  220. package/.next/standalone/.next/server/app/workspaces.segments/_index.segment.rsc +3 -3
  221. package/.next/standalone/.next/server/app/workspaces.segments/_tree.segment.rsc +2 -2
  222. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0d038fdf._.js +106 -0
  223. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0e4c2d35._.js → [root-of-the-server]__12673e47._.js} +2 -2
  224. package/.next/standalone/.next/server/chunks/[root-of-the-server]__130dee4b._.js +2 -2
  225. package/.next/standalone/.next/server/chunks/[root-of-the-server]__142c2f41._.js +2 -2
  226. package/.next/standalone/.next/server/chunks/[root-of-the-server]__2861e096._.js +1 -1
  227. package/.next/standalone/.next/server/chunks/[root-of-the-server]__2d3d8d52._.js +2 -2
  228. package/.next/standalone/.next/server/chunks/[root-of-the-server]__45205e47._.js +98 -0
  229. package/.next/standalone/.next/server/chunks/[root-of-the-server]__46b7da42._.js +98 -0
  230. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__8765f2fc._.js → [root-of-the-server]__4cf845f6._.js} +3 -3
  231. package/.next/standalone/.next/server/chunks/[root-of-the-server]__57b966d5._.js +2 -2
  232. package/.next/standalone/.next/server/chunks/[root-of-the-server]__5a0020ba._.js +3 -3
  233. package/.next/standalone/.next/server/chunks/[root-of-the-server]__5bd0f118._.js +2 -2
  234. package/.next/standalone/.next/server/chunks/[root-of-the-server]__5bf8f2c0._.js +98 -0
  235. package/.next/standalone/.next/server/chunks/[root-of-the-server]__69eb20b1._.js +98 -0
  236. package/.next/standalone/.next/server/chunks/[root-of-the-server]__74c48d65._.js +2 -2
  237. package/.next/standalone/.next/server/chunks/[root-of-the-server]__7d6610c4._.js +2 -2
  238. package/.next/standalone/.next/server/chunks/[root-of-the-server]__84f3af14._.js +2 -2
  239. package/.next/standalone/.next/server/chunks/[root-of-the-server]__a38f7af1._.js +98 -0
  240. package/.next/standalone/.next/server/chunks/[root-of-the-server]__a6eb742d._.js +3 -3
  241. package/.next/standalone/.next/server/chunks/[root-of-the-server]__b4c83e91._.js +3 -3
  242. package/.next/standalone/.next/server/chunks/[root-of-the-server]__b7c8a7dd._.js +98 -0
  243. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__cae0486f._.js → [root-of-the-server]__c1d7faa6._.js} +4 -4
  244. package/.next/standalone/.next/server/chunks/[root-of-the-server]__c546cf71._.js +1 -1
  245. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__a2ee9884._.js → [root-of-the-server]__c977bf2f._.js} +2 -2
  246. package/.next/standalone/.next/server/chunks/[root-of-the-server]__d2f9be33._.js +98 -0
  247. package/.next/standalone/.next/server/chunks/[root-of-the-server]__d5615808._.js +2 -2
  248. package/.next/standalone/.next/server/chunks/[root-of-the-server]__d877df12._.js +1 -1
  249. package/.next/standalone/.next/server/chunks/[root-of-the-server]__e9d6e526._.js +98 -0
  250. package/.next/standalone/.next/server/chunks/[root-of-the-server]__f66ceeb8._.js +2 -2
  251. package/.next/standalone/.next/server/chunks/[root-of-the-server]__f893957c._.js +3 -3
  252. package/.next/standalone/.next/server/chunks/[root-of-the-server]__fcd26315._.js +2 -2
  253. package/.next/standalone/.next/server/chunks/[root-of-the-server]__fd505913._.js +2 -2
  254. package/.next/standalone/.next/server/chunks/[root-of-the-server]__feff7b91._.js +3 -3
  255. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__66aca5d4._.js +1 -1
  256. package/.next/standalone/.next/server/chunks/ssr/_1f12caba._.js +1 -1
  257. package/.next/standalone/.next/server/chunks/ssr/_43e7e611._.js +1 -1
  258. package/.next/standalone/.next/server/chunks/ssr/src_app_(desktop)_network_page_tsx_27f035db._.js +1 -1
  259. package/.next/standalone/.next/server/chunks/ssr/src_lib_telemetry_ts_d7f80cd0._.js +1 -1
  260. package/.next/standalone/.next/server/edge/chunks/_d73df637._.js +1 -1
  261. package/.next/standalone/.next/server/middleware-manifest.json +5 -5
  262. package/.next/standalone/.next/server/pages/404.html +1 -1
  263. package/.next/standalone/.next/server/pages/500.html +2 -2
  264. package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
  265. package/.next/standalone/.next/server/server-reference-manifest.json +1 -1
  266. package/.next/standalone/.next/static/chunks/{10c6424526b53431.js → 483bf086feba6531.js} +1 -1
  267. package/.next/standalone/.next/static/chunks/{f8d7a4a58f712ecd.js → 56ddb2d75f5beb1a.js} +1 -1
  268. package/.next/standalone/.next/static/chunks/7c4cfb3160fa8dd4.js +5 -0
  269. package/.next/standalone/.next/static/chunks/{3434c5b2c9958276.js → ae3a695e671c8d31.js} +1 -1
  270. package/.next/standalone/.next/static/chunks/e972ec0d23b19896.js +5 -0
  271. package/.next/standalone/.next/static/chunks/ff5fac1bd7b518dd.css +3 -0
  272. package/.next/standalone/node_modules/@img/sharp-win32-x64/lib/sharp-win32-x64.node +0 -0
  273. package/.next/standalone/node_modules/@img/{sharp-linux-x64 → sharp-win32-x64}/package.json +39 -46
  274. package/.next/standalone/package.json +89 -89
  275. package/.next/standalone/server.js +1 -1
  276. package/.next/standalone/tsconfig.json +34 -34
  277. package/LICENSE +661 -661
  278. package/README.md +131 -131
  279. package/bin/fix-standalone-externals.js +79 -79
  280. package/bin/lib/auto-setup.js +110 -101
  281. package/bin/mdns-service.js +171 -171
  282. package/bin/postinstall.js +35 -35
  283. package/bin/setup-admin.js +195 -189
  284. package/bin/spaces-dev.js +208 -208
  285. package/bin/spaces-install.js +572 -483
  286. package/bin/spaces-service.js +881 -0
  287. package/bin/spaces-setup.js +253 -247
  288. package/bin/spaces.js +500 -466
  289. package/bin/terminal-server.js +1252 -1117
  290. package/package.json +89 -89
  291. package/.next/standalone/.next/server/chunks/[root-of-the-server]__18a58c5f._.js +0 -3
  292. package/.next/standalone/.next/server/chunks/[root-of-the-server]__41e589ee._.js +0 -3
  293. package/.next/standalone/.next/server/chunks/[root-of-the-server]__464db440._.js +0 -3
  294. package/.next/standalone/.next/server/chunks/[root-of-the-server]__4ad64489._.js +0 -3
  295. package/.next/standalone/.next/server/chunks/[root-of-the-server]__64f5810e._.js +0 -98
  296. package/.next/standalone/.next/server/chunks/[root-of-the-server]__95b7f18e._.js +0 -3
  297. package/.next/standalone/.next/server/chunks/[root-of-the-server]__a6ce192e._.js +0 -3
  298. package/.next/standalone/.next/server/chunks/[root-of-the-server]__e2b78951._.js +0 -3
  299. package/.next/standalone/.next/server/chunks/[root-of-the-server]__f84e3cf3._.js +0 -98
  300. package/.next/standalone/.next/static/chunks/302ce212c690bec4.js +0 -5
  301. package/.next/standalone/.next/static/chunks/67c7bf5024309fca.css +0 -3
  302. package/.next/standalone/.next/static/chunks/cb442c50eecb758d.js +0 -5
  303. package/.next/standalone/node_modules/@img/sharp-libvips-linux-x64/README.md +0 -46
  304. package/.next/standalone/node_modules/@img/sharp-libvips-linux-x64/lib/glib-2.0/include/glibconfig.h +0 -221
  305. package/.next/standalone/node_modules/@img/sharp-libvips-linux-x64/lib/index.js +0 -1
  306. package/.next/standalone/node_modules/@img/sharp-libvips-linux-x64/lib/libvips-cpp.so.8.17.3 +0 -0
  307. package/.next/standalone/node_modules/@img/sharp-libvips-linux-x64/package.json +0 -42
  308. package/.next/standalone/node_modules/@img/sharp-libvips-linuxmusl-x64/README.md +0 -46
  309. package/.next/standalone/node_modules/@img/sharp-libvips-linuxmusl-x64/lib/glib-2.0/include/glibconfig.h +0 -221
  310. package/.next/standalone/node_modules/@img/sharp-libvips-linuxmusl-x64/lib/index.js +0 -1
  311. package/.next/standalone/node_modules/@img/sharp-libvips-linuxmusl-x64/lib/libvips-cpp.so.8.17.3 +0 -0
  312. package/.next/standalone/node_modules/@img/sharp-libvips-linuxmusl-x64/package.json +0 -42
  313. package/.next/standalone/node_modules/@img/sharp-libvips-linuxmusl-x64/versions.json +0 -30
  314. package/.next/standalone/node_modules/@img/sharp-linux-x64/lib/sharp-linux-x64.node +0 -0
  315. package/.next/standalone/node_modules/@img/sharp-linuxmusl-x64/lib/sharp-linuxmusl-x64.node +0 -0
  316. package/.next/standalone/node_modules/@img/sharp-linuxmusl-x64/package.json +0 -46
  317. /package/.next/standalone/.next/static/{nbYSIjUtkSwSvTgyR5p00 → 5J530rtIR_FsG4E9MLLpB}/_buildManifest.js +0 -0
  318. /package/.next/standalone/.next/static/{nbYSIjUtkSwSvTgyR5p00 → 5J530rtIR_FsG4E9MLLpB}/_clientMiddlewareManifest.json +0 -0
  319. /package/.next/standalone/.next/static/{nbYSIjUtkSwSvTgyR5p00 → 5J530rtIR_FsG4E9MLLpB}/_ssgManifest.js +0 -0
  320. /package/.next/standalone/node_modules/@img/{sharp-libvips-linux-x64 → sharp-win32-x64}/versions.json +0 -0
package/bin/spaces.js CHANGED
@@ -1,466 +1,500 @@
1
- #!/usr/bin/env node
2
-
3
- const http = require('http');
4
- const { execFileSync, spawn } = require('child_process');
5
- const path = require('path');
6
- const os = require('os');
7
- const fs = require('fs');
8
- // terminal-server is loaded lazily (after SPACES_TIER is set in process.env)
9
-
10
- const SPACES_DIR = path.join(os.homedir(), '.spaces');
11
- const CONFIG_PATH = path.join(SPACES_DIR, 'server.json');
12
- const SESSION_SECRET_PATH = path.join(SPACES_DIR, 'session_secret');
13
- const NEXT_INTERNAL_PORT = 3400;
14
- const projectDir = path.join(__dirname, '..');
15
- const MANAGED_PACKAGES = path.join(SPACES_DIR, 'packages');
16
- const MANAGED_NODE_MODULES = path.join(MANAGED_PACKAGES, 'node_modules');
17
-
18
- // ─── CLI arg parsing ──────────────────────────────────────
19
- const args = process.argv.slice(2);
20
- const cliFlags = {};
21
- for (let i = 0; i < args.length; i++) {
22
- if (args[i] === '--setup') { cliFlags.setup = true; }
23
- else if (args[i] === '--port' && args[i + 1]) { cliFlags.port = parseInt(args[++i], 10); }
24
- else if (args[i] === '--tier' && args[i + 1]) { cliFlags.tier = args[++i]; }
25
- else if (args[i] === '--base-path' && args[i + 1]) { cliFlags.basePath = args[++i]; }
26
- else if (args[i] === '--help' || args[i] === '-h') { cliFlags.help = true; }
27
- }
28
-
29
- if (cliFlags.help) {
30
- console.log(`
31
- Spaces - Agent Workspace Manager
32
-
33
- Usage:
34
- spaces Start the server (auto-detects tier)
35
- spaces stop Stop running server
36
- spaces install <teams|pro> Install a tier package
37
- spaces uninstall [teams|pro] Uninstall packages (all if none specified)
38
- spaces verify Verify installed packages
39
- spaces upgrade [teams|pro] Upgrade installed packages
40
- spaces --setup Interactive first-time setup wizard
41
- spaces --port 3457 Override port
42
- spaces --tier team Override tier (community|team|federation)
43
- spaces --base-path /spaces Set base path for reverse proxy
44
- spaces --help Show this help
45
- `);
46
- process.exit(0);
47
- }
48
-
49
- // ─── Stop command ─────────────────────────────────────────
50
- const subcommand = args[0];
51
- if (subcommand === 'stop') {
52
- stopServer();
53
- process.exit(0);
54
- }
55
-
56
- // ─── Route install/verify/upgrade to spaces-install.js ────
57
- if (subcommand === 'install' || subcommand === 'uninstall' || subcommand === 'verify' || subcommand === 'upgrade') {
58
- // Re-exec with spaces-install.js, passing through all args
59
- const installScript = path.join(__dirname, 'spaces-install.js');
60
- const { status } = require('child_process').spawnSync(
61
- process.execPath, [installScript, ...args],
62
- { stdio: 'inherit', env: process.env }
63
- );
64
- process.exit(status || 0);
65
- }
66
-
67
- // ─── Setup wizard ─────────────────────────────────────────
68
- if (cliFlags.setup) {
69
- require('./spaces-setup');
70
- // spaces-setup handles its own process.exit
71
- } else {
72
- startServer();
73
- }
74
-
75
- function startServer() {
76
- // ─── Load saved config ────────────────────────────────────
77
- let savedConfig = {};
78
- if (fs.existsSync(CONFIG_PATH)) {
79
- try { savedConfig = JSON.parse(fs.readFileSync(CONFIG_PATH, 'utf-8')); } catch {}
80
- }
81
-
82
- // ─── Resolve settings (CLI > env > config > defaults) ─────
83
- const PORT = cliFlags.port
84
- || parseInt(process.env.SPACES_PORT || '', 10)
85
- || savedConfig.port
86
- || 3457;
87
-
88
- const basePath = cliFlags.basePath
89
- || process.env.SPACES_BASE_PATH
90
- || savedConfig.basePath
91
- || '';
92
-
93
- const allowedOrigins = process.env.SPACES_ALLOWED_ORIGINS
94
- || savedConfig.allowedOrigins
95
- || '';
96
-
97
- // ─── Kill any existing server on this port ───────────────────
98
- stopServer();
99
-
100
- // ─── Resolve optional packages once ─────────────────────────
101
- const proPath = resolveSpacesPro();
102
- const teamsPath = resolveSpacesTeams();
103
-
104
- // Tier resolution: CLI > env > config > auto-detect
105
- let tier = cliFlags.tier
106
- || process.env.SPACES_TIER
107
- || savedConfig.tier
108
- || '';
109
-
110
- // Auto-detect tier from package presence
111
- if (!tier) {
112
- if (proPath) tier = 'federation';
113
- else if (teamsPath) tier = 'team';
114
- else tier = 'community';
115
- }
116
-
117
- console.log('');
118
- console.log(' Spaces - Agent Workspace Manager');
119
- console.log(' =================================');
120
- console.log('');
121
- console.log(` Tier: ${tier}`);
122
-
123
- // ─── Server tier prerequisites ────────────────────────────
124
- const childEnv = { ...process.env };
125
-
126
- if (tier !== 'community') {
127
- // team/federation tiers require @spaces/teams (auth + collaboration)
128
- if ((tier === 'team' || tier === 'federation') && !teamsPath) {
129
- console.error(' Error: @spaces/teams is required for team/federation tiers.');
130
- console.error(' Install it: spaces install teams');
131
- process.exit(1);
132
- }
133
- // federation tier requires @spaces/pro (network)
134
- if (tier === 'federation' && !proPath) {
135
- console.error(' Error: @spaces/pro is required for the federation tier.');
136
- console.error(' Install it: spaces install pro');
137
- process.exit(1);
138
- }
139
-
140
- // Check for session secret
141
- let sessionSecret = process.env.SPACES_SESSION_SECRET || '';
142
- if (!sessionSecret && fs.existsSync(SESSION_SECRET_PATH)) {
143
- sessionSecret = fs.readFileSync(SESSION_SECRET_PATH, 'utf-8').trim();
144
- }
145
-
146
- // Check for admin DB — auto-setup if missing
147
- const adminDbPath = path.join(SPACES_DIR, 'admin.db');
148
- if (!fs.existsSync(adminDbPath) || !sessionSecret) {
149
- const { autoSetup } = require('./lib/auto-setup');
150
- const result = autoSetup({ SPACES_DIR, SESSION_SECRET_PATH, ADMIN_DB_PATH: adminDbPath, CONFIG_PATH, tier, port: PORT, basePath });
151
- sessionSecret = result.sessionSecret;
152
- }
153
-
154
- childEnv.SPACES_SESSION_SECRET = sessionSecret;
155
- process.env.SPACES_SESSION_SECRET = sessionSecret;
156
- console.log(` Admin DB: ${adminDbPath}`);
157
- }
158
-
159
- // Set tier in both child env and own process env (terminal-server reads it)
160
- childEnv.SPACES_TIER = tier;
161
- process.env.SPACES_TIER = tier;
162
- if (basePath) {
163
- childEnv.SPACES_BASE_PATH = basePath;
164
- console.log(` Base path: ${basePath}`);
165
- }
166
- if (allowedOrigins) {
167
- childEnv.SPACES_ALLOWED_ORIGINS = allowedOrigins;
168
- process.env.SPACES_ALLOWED_ORIGINS = allowedOrigins;
169
- console.log(` Allowed origins: ${allowedOrigins}`);
170
- }
171
-
172
- // ─── Resolve NODE_PATH for @spaces/pro and @spaces/teams ──
173
- // Update both childEnv (for the Next.js child process) and process.env
174
- // (for terminal-server.js which runs in this same parent process).
175
- // Include:
176
- // - Managed packages node_modules (~/.spaces/packages/node_modules)
177
- // - Each managed package's own node_modules (for its bundled deps)
178
- // - The host app's own node_modules (fallback for peer deps)
179
- const appNodeModules = path.join(projectDir, 'node_modules');
180
- const nodePaths = [MANAGED_NODE_MODULES, appNodeModules];
181
- // Add each resolved package's own node_modules so its bundled deps are found
182
- for (const pkgPath of [proPath, teamsPath]) {
183
- if (pkgPath) {
184
- // pkgPath is the package root (symlink target or direct path)
185
- const realPath = fs.realpathSync(pkgPath);
186
- const pkgNodeModules = path.join(realPath, 'node_modules');
187
- if (fs.existsSync(pkgNodeModules) && !nodePaths.includes(pkgNodeModules)) {
188
- nodePaths.push(pkgNodeModules);
189
- }
190
- // Also add the parent scope for @spaces/* resolution
191
- const parentModules = path.dirname(path.dirname(pkgPath));
192
- if (!nodePaths.includes(parentModules)) {
193
- nodePaths.push(parentModules);
194
- }
195
- }
196
- }
197
- for (const dir of nodePaths) {
198
- for (const target of [childEnv, process.env]) {
199
- const existing = target.NODE_PATH || '';
200
- if (!existing.includes(dir)) {
201
- target.NODE_PATH = existing
202
- ? `${dir}${path.delimiter}${existing}`
203
- : dir;
204
- }
205
- }
206
- }
207
- // Re-init module paths so require() in this process picks up the new NODE_PATH
208
- require('module').Module._initPaths();
209
-
210
- // Verify collaboration pipeline works end-to-end at startup
211
- if (tier === 'team' || tier === 'federation') {
212
- try {
213
- const teams = require('@spaces/teams');
214
- console.log(' Collaboration: @spaces/teams loaded OK');
215
- // Smoke-test that peer deps resolve from this process
216
- require('better-sqlite3');
217
- } catch (e) {
218
- console.error(` Warning: Collaboration may not work — ${e.message}`);
219
- console.error(' Check that NODE_PATH includes the host app node_modules.');
220
- }
221
- }
222
-
223
- console.log('');
224
-
225
- // Check for ~/.claude/ directory
226
- const claudeDir = path.join(os.homedir(), '.claude');
227
- if (!fs.existsSync(claudeDir)) {
228
- console.log(' Warning: ~/.claude/ not found. Have you used Claude Code yet?');
229
- console.log('');
230
- }
231
-
232
- // ─── Detect build type ────────────────────────────────────
233
- const standaloneServer = path.join(projectDir, '.next', 'standalone', 'server.js');
234
- const fullBuildDir = path.join(projectDir, '.next', 'BUILD_ID');
235
- const isStandalone = fs.existsSync(standaloneServer);
236
- const isFullBuild = fs.existsSync(fullBuildDir);
237
-
238
- if (!isStandalone && !isFullBuild) {
239
- console.error(' Error: No build found.');
240
- console.error(' Run "npm run build" first, or install via "npm install -g @jlongo78/agent-spaces".');
241
- process.exit(1);
242
- }
243
-
244
- // ─── Spawn Next.js ────────────────────────────────────────
245
- let next;
246
- if (isStandalone) {
247
- const parentNodeModules = path.join(projectDir, 'node_modules');
248
- const existingNodePath = childEnv.NODE_PATH || '';
249
- childEnv.NODE_PATH = existingNodePath
250
- ? `${parentNodeModules}${path.delimiter}${existingNodePath}`
251
- : parentNodeModules;
252
-
253
- next = spawn(process.execPath, [standaloneServer], {
254
- cwd: path.dirname(standaloneServer),
255
- stdio: ['ignore', 'pipe', 'pipe'],
256
- env: {
257
- ...childEnv,
258
- PORT: String(NEXT_INTERNAL_PORT),
259
- HOSTNAME: '0.0.0.0',
260
- NODE_ENV: 'production',
261
- },
262
- });
263
- } else {
264
- next = spawn('npx', ['next', 'start', '--port', String(NEXT_INTERNAL_PORT)], {
265
- cwd: projectDir,
266
- stdio: ['ignore', 'pipe', 'pipe'],
267
- env: {
268
- ...childEnv,
269
- PORT: String(NEXT_INTERNAL_PORT),
270
- HOSTNAME: '0.0.0.0',
271
- NODE_ENV: 'production',
272
- },
273
- shell: true,
274
- });
275
- }
276
-
277
- let nextReady = false;
278
-
279
- next.stdout.on('data', (data) => {
280
- const msg = data.toString();
281
- process.stdout.write(msg);
282
- if (!nextReady && (msg.includes('Ready') || msg.includes('started server') || msg.includes('Listening') || msg.includes('localhost'))) {
283
- nextReady = true;
284
- console.log(`\n Ready at http://localhost:${PORT}\n`);
285
-
286
- const url = `http://localhost:${PORT}`;
287
- try {
288
- if (process.platform === 'win32') {
289
- execFileSync('cmd', ['/c', 'start', url], { stdio: 'ignore' });
290
- } else if (process.platform === 'darwin') {
291
- execFileSync('open', [url], { stdio: 'ignore' });
292
- } else {
293
- execFileSync('xdg-open', [url], { stdio: 'ignore' });
294
- }
295
- } catch {
296
- console.log(` Open ${url} in your browser`);
297
- }
298
- }
299
- });
300
-
301
- next.stderr.on('data', (data) => {
302
- const msg = data.toString();
303
- if (!msg.includes('Warning')) {
304
- process.stderr.write(data);
305
- }
306
- });
307
-
308
- next.on('exit', (code) => {
309
- if (code !== 0 && code !== null) {
310
- console.error(` [spaces] Next.js exited with code ${code}`);
311
- }
312
- cleanup();
313
- });
314
-
315
- // ─── HTTP proxy server ────────────────────────────────────
316
- const server = http.createServer((req, res) => {
317
- // WebSocket paths are handled by the 'upgrade' event, but a plain
318
- // HTTP request to /ws (e.g. health check) should not be proxied to
319
- // Next.js which would 308-redirect it due to trailingSlash.
320
- const urlPath = (req.url || '').split('?')[0];
321
- if (urlPath === '/ws' || urlPath.endsWith('/ws') || urlPath.endsWith('/ws/')) {
322
- res.writeHead(200, { 'Content-Type': 'text/plain' });
323
- res.end('WebSocket endpoint');
324
- return;
325
- }
326
-
327
- const proxyReq = http.request(
328
- {
329
- hostname: '127.0.0.1',
330
- port: NEXT_INTERNAL_PORT,
331
- path: req.url,
332
- method: req.method,
333
- headers: req.headers,
334
- },
335
- (proxyRes) => {
336
- res.writeHead(proxyRes.statusCode, proxyRes.headers);
337
- proxyRes.pipe(res);
338
- }
339
- );
340
- proxyReq.on('error', () => {
341
- if (!res.headersSent) {
342
- res.writeHead(502);
343
- res.end('Server not ready yet. Refresh in a moment.');
344
- }
345
- });
346
- req.pipe(proxyReq);
347
- });
348
-
349
- const { createTerminalServer } = require('./terminal-server');
350
- createTerminalServer(server);
351
-
352
- server.listen(PORT, () => {
353
- console.log(` Starting server on http://localhost:${PORT}`);
354
- console.log('');
355
- });
356
-
357
- function cleanup() {
358
- next.kill();
359
- server.close();
360
- process.exit(0);
361
- }
362
-
363
- process.on('SIGINT', cleanup);
364
- process.on('SIGTERM', cleanup);
365
- }
366
-
367
- // ─── Stop running server ─────────────────────────────────────
368
- function findPidsOnPort(port) {
369
- const pids = new Set();
370
- // Try lsof first
371
- try {
372
- const output = execFileSync('lsof', ['-ti', `tcp:${port}`], { encoding: 'utf-8' }).trim();
373
- for (const p of output.split('\n')) { if (p.trim()) pids.add(parseInt(p.trim(), 10)); }
374
- } catch {}
375
- // Fallback to fuser (catches processes lsof misses)
376
- try {
377
- const output = execFileSync('fuser', [`${port}/tcp`], { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] }).trim();
378
- for (const p of output.split(/\s+/)) { if (p.trim()) pids.add(parseInt(p.trim(), 10)); }
379
- } catch {}
380
- return [...pids].filter(p => !isNaN(p) && p > 0);
381
- }
382
-
383
- function stopServer() {
384
- let savedConfig = {};
385
- if (fs.existsSync(CONFIG_PATH)) {
386
- try { savedConfig = JSON.parse(fs.readFileSync(CONFIG_PATH, 'utf-8')); } catch {}
387
- }
388
- const port = parseInt(process.env.SPACES_PORT || '', 10) || savedConfig.port || 3457;
389
- const ports = [port, NEXT_INTERNAL_PORT];
390
- let killed = 0;
391
-
392
- for (const p of ports) {
393
- for (const pid of findPidsOnPort(p)) {
394
- try {
395
- process.kill(pid, 'SIGTERM');
396
- killed++;
397
- } catch {}
398
- }
399
- }
400
-
401
- if (killed > 0) {
402
- console.log(` Stopped ${killed} process(es) on port ${port}`);
403
- // Wait for ports to be released, escalate to SIGKILL if needed
404
- const deadline = Date.now() + 2000;
405
- let escalated = false;
406
- while (Date.now() < deadline) {
407
- const remaining = ports.flatMap(p => findPidsOnPort(p));
408
- if (remaining.length === 0) break;
409
- if (!escalated && Date.now() > deadline - 1000) {
410
- for (const pid of remaining) {
411
- try { process.kill(pid, 'SIGKILL'); } catch {}
412
- }
413
- escalated = true;
414
- }
415
- require('child_process').spawnSync('sleep', ['0.2']);
416
- }
417
- } else {
418
- console.log(` No running server found on port ${port}`);
419
- }
420
- }
421
-
422
- // ─── @spaces/pro resolution ──────────────────────────────────
423
- function resolveSpacesPro() {
424
- // 1. Managed install (~/.spaces/packages/)
425
- const managed = path.join(MANAGED_NODE_MODULES, '@spaces', 'pro');
426
- if (fs.existsSync(path.join(managed, 'dist', 'index.js'))) return managed;
427
-
428
- // 2. Local node_modules (npm link / optionalDep)
429
- try {
430
- return require.resolve('@spaces/pro');
431
- } catch {}
432
-
433
- // 3. Global npm prefix (legacy)
434
- try {
435
- const globalPrefix = execFileSync('npm', ['prefix', '-g'], { encoding: 'utf-8' }).trim();
436
- const globalProPath = path.join(globalPrefix, 'lib', 'node_modules', '@spaces', 'pro');
437
- if (fs.existsSync(globalProPath)) return globalProPath;
438
- const altPath = path.join(globalPrefix, 'node_modules', '@spaces', 'pro');
439
- if (fs.existsSync(altPath)) return altPath;
440
- } catch {}
441
-
442
- return null;
443
- }
444
-
445
- // ─── @spaces/teams resolution ────────────────────────────────
446
- function resolveSpacesTeams() {
447
- // 1. Managed install (~/.spaces/packages/)
448
- const managed = path.join(MANAGED_NODE_MODULES, '@spaces', 'teams');
449
- if (fs.existsSync(path.join(managed, 'dist', 'index.js'))) return managed;
450
-
451
- // 2. Local node_modules (npm link / optionalDep)
452
- try {
453
- return require.resolve('@spaces/teams');
454
- } catch {}
455
-
456
- // 3. Global npm prefix (legacy)
457
- try {
458
- const globalPrefix = execFileSync('npm', ['prefix', '-g'], { encoding: 'utf-8' }).trim();
459
- const globalTeamsPath = path.join(globalPrefix, 'lib', 'node_modules', '@spaces', 'teams');
460
- if (fs.existsSync(globalTeamsPath)) return globalTeamsPath;
461
- const altPath = path.join(globalPrefix, 'node_modules', '@spaces', 'teams');
462
- if (fs.existsSync(altPath)) return altPath;
463
- } catch {}
464
-
465
- return null;
466
- }
1
+ #!/usr/bin/env node
2
+
3
+ const http = require('http');
4
+ const { execFileSync, spawn } = require('child_process');
5
+ const path = require('path');
6
+ const os = require('os');
7
+ const fs = require('fs');
8
+ // terminal-server is loaded lazily (after SPACES_TIER is set in process.env)
9
+
10
+ const SPACES_DIR = path.join(os.homedir(), '.spaces');
11
+ const CONFIG_PATH = path.join(SPACES_DIR, 'server.json');
12
+ const SESSION_SECRET_PATH = path.join(SPACES_DIR, 'session_secret');
13
+ const NEXT_INTERNAL_PORT = 3400;
14
+ const projectDir = path.join(__dirname, '..');
15
+ const MANAGED_PACKAGES = path.join(SPACES_DIR, 'packages');
16
+ const MANAGED_NODE_MODULES = path.join(MANAGED_PACKAGES, 'node_modules');
17
+
18
+ // ─── CLI arg parsing ──────────────────────────────────────
19
+ const args = process.argv.slice(2);
20
+ const cliFlags = {};
21
+ for (let i = 0; i < args.length; i++) {
22
+ if (args[i] === '--setup') { cliFlags.setup = true; }
23
+ else if (args[i] === '--port' && args[i + 1]) { cliFlags.port = parseInt(args[++i], 10); }
24
+ else if (args[i] === '--tier' && args[i + 1]) { cliFlags.tier = args[++i]; }
25
+ else if (args[i] === '--base-path' && args[i + 1]) { cliFlags.basePath = args[++i]; }
26
+ else if (args[i] === '--help' || args[i] === '-h') { cliFlags.help = true; }
27
+ }
28
+
29
+ if (cliFlags.help) {
30
+ console.log(`
31
+ Spaces - Agent Workspace Manager
32
+
33
+ Usage:
34
+ spaces Start the server (auto-detects tier)
35
+ spaces stop Stop running server
36
+ spaces install <teams|pro> Install a tier package
37
+ spaces uninstall [teams|pro] Uninstall packages (all if none specified)
38
+ spaces verify Verify installed packages
39
+ spaces upgrade [teams|pro] Upgrade installed packages
40
+ spaces --setup Interactive first-time setup wizard
41
+ spaces --port 3457 Override port
42
+ spaces --tier team Override tier (community|team|federation)
43
+ spaces --base-path /spaces Set base path for reverse proxy
44
+ spaces service install Install as OS service (systemd/launchd/Task Scheduler)
45
+ spaces service uninstall Remove OS service
46
+ spaces service start Start the service
47
+ spaces service stop Stop the service
48
+ spaces service status Show service status
49
+ spaces service logs Tail service logs
50
+ spaces --help Show this help
51
+ `);
52
+ process.exit(0);
53
+ }
54
+
55
+ // ─── Stop command ─────────────────────────────────────────
56
+ const subcommand = args[0];
57
+ if (subcommand === 'stop') {
58
+ stopServer();
59
+ process.exit(0);
60
+ }
61
+
62
+ // ─── Route install/verify/upgrade to spaces-install.js ────
63
+ if (subcommand === 'install' || subcommand === 'uninstall' || subcommand === 'verify' || subcommand === 'upgrade') {
64
+ // Re-exec with spaces-install.js, passing through all args
65
+ const installScript = path.join(__dirname, 'spaces-install.js');
66
+ const { status } = require('child_process').spawnSync(
67
+ process.execPath, [installScript, ...args],
68
+ { stdio: 'inherit', env: process.env }
69
+ );
70
+ process.exit(status || 0);
71
+ }
72
+
73
+ // ─── Route service commands to spaces-service.js ─────
74
+ if (subcommand === 'service') {
75
+ const serviceScript = path.join(__dirname, 'spaces-service.js');
76
+ const { status } = require('child_process').spawnSync(
77
+ process.execPath, [serviceScript, ...args.slice(1)],
78
+ { stdio: 'inherit', env: process.env }
79
+ );
80
+ process.exit(status || 0);
81
+ }
82
+
83
+ // ─── Setup wizard ─────────────────────────────────────────
84
+ if (cliFlags.setup) {
85
+ require('./spaces-setup');
86
+ // spaces-setup handles its own process.exit
87
+ } else if (subcommand && !subcommand.startsWith('-')) {
88
+ console.error(` Unknown command: ${subcommand}`);
89
+ console.error(` Run "spaces --help" for usage`);
90
+ process.exit(1);
91
+ } else {
92
+ startServer();
93
+ }
94
+
95
+ function startServer() {
96
+ // ─── Load saved config ────────────────────────────────────
97
+ let savedConfig = {};
98
+ if (fs.existsSync(CONFIG_PATH)) {
99
+ try { savedConfig = JSON.parse(fs.readFileSync(CONFIG_PATH, 'utf-8')); } catch {}
100
+ }
101
+
102
+ // ─── Resolve settings (CLI > env > config > defaults) ─────
103
+ const PORT = cliFlags.port
104
+ || parseInt(process.env.SPACES_PORT || '', 10)
105
+ || savedConfig.port
106
+ || 3457;
107
+
108
+ const basePath = cliFlags.basePath
109
+ || process.env.SPACES_BASE_PATH
110
+ || savedConfig.basePath
111
+ || '';
112
+
113
+ const allowedOrigins = process.env.SPACES_ALLOWED_ORIGINS
114
+ || savedConfig.allowedOrigins
115
+ || '';
116
+
117
+ // ─── Kill any existing server on this port ───────────────────
118
+ stopServer();
119
+
120
+ // ─── Resolve optional packages once ─────────────────────────
121
+ const proPath = resolveSpacesPro();
122
+ const teamsPath = resolveSpacesTeams();
123
+
124
+ // Tier resolution: CLI > env > config > auto-detect
125
+ let tier = cliFlags.tier
126
+ || process.env.SPACES_TIER
127
+ || savedConfig.tier
128
+ || '';
129
+
130
+ // Auto-detect tier from package presence
131
+ if (!tier) {
132
+ if (proPath) tier = 'federation';
133
+ else if (teamsPath) tier = 'team';
134
+ else tier = 'community';
135
+ }
136
+
137
+ console.log('');
138
+ console.log(' Spaces - Agent Workspace Manager');
139
+ console.log(' =================================');
140
+ console.log('');
141
+ console.log(` Tier: ${tier}`);
142
+
143
+ // ─── Server tier prerequisites ────────────────────────────
144
+ const childEnv = { ...process.env };
145
+
146
+ if (tier !== 'community') {
147
+ // team/federation tiers require @spaces/teams (auth + collaboration)
148
+ if ((tier === 'team' || tier === 'federation') && !teamsPath) {
149
+ console.error(' Error: @spaces/teams is required for team/federation tiers.');
150
+ console.error(' Install it: spaces install teams');
151
+ process.exit(1);
152
+ }
153
+ // federation tier requires @spaces/pro (network)
154
+ if (tier === 'federation' && !proPath) {
155
+ console.error(' Error: @spaces/pro is required for the federation tier.');
156
+ console.error(' Install it: spaces install pro');
157
+ process.exit(1);
158
+ }
159
+
160
+ // Check for session secret
161
+ let sessionSecret = process.env.SPACES_SESSION_SECRET || '';
162
+ if (!sessionSecret && fs.existsSync(SESSION_SECRET_PATH)) {
163
+ sessionSecret = fs.readFileSync(SESSION_SECRET_PATH, 'utf-8').trim();
164
+ }
165
+
166
+ // Check for admin DB — auto-setup if missing
167
+ const adminDbPath = path.join(SPACES_DIR, 'admin.db');
168
+ if (!fs.existsSync(adminDbPath) || !sessionSecret) {
169
+ const { autoSetup } = require('./lib/auto-setup');
170
+ const result = autoSetup({ SPACES_DIR, SESSION_SECRET_PATH, ADMIN_DB_PATH: adminDbPath, CONFIG_PATH, tier, port: PORT, basePath });
171
+ sessionSecret = result.sessionSecret;
172
+ }
173
+
174
+ childEnv.SPACES_SESSION_SECRET = sessionSecret;
175
+ process.env.SPACES_SESSION_SECRET = sessionSecret;
176
+ console.log(` Admin DB: ${adminDbPath}`);
177
+ }
178
+
179
+ // Set tier in both child env and own process env (terminal-server reads it)
180
+ childEnv.SPACES_TIER = tier;
181
+ process.env.SPACES_TIER = tier;
182
+ if (basePath) {
183
+ childEnv.SPACES_BASE_PATH = basePath;
184
+ console.log(` Base path: ${basePath}`);
185
+ }
186
+ if (allowedOrigins) {
187
+ childEnv.SPACES_ALLOWED_ORIGINS = allowedOrigins;
188
+ process.env.SPACES_ALLOWED_ORIGINS = allowedOrigins;
189
+ console.log(` Allowed origins: ${allowedOrigins}`);
190
+ }
191
+
192
+ // ─── Resolve NODE_PATH for @spaces/pro and @spaces/teams ──
193
+ // Update both childEnv (for the Next.js child process) and process.env
194
+ // (for terminal-server.js which runs in this same parent process).
195
+ // Include:
196
+ // - Managed packages node_modules (~/.spaces/packages/node_modules)
197
+ // - Each managed package's own node_modules (for its bundled deps)
198
+ // - The host app's own node_modules (fallback for peer deps)
199
+ const appNodeModules = path.join(projectDir, 'node_modules');
200
+ const nodePaths = [MANAGED_NODE_MODULES, appNodeModules];
201
+ // Add each resolved package's own node_modules so its bundled deps are found
202
+ for (const pkgPath of [proPath, teamsPath]) {
203
+ if (pkgPath) {
204
+ // pkgPath is the package root (symlink target or direct path)
205
+ const realPath = fs.realpathSync(pkgPath);
206
+ const pkgNodeModules = path.join(realPath, 'node_modules');
207
+ if (fs.existsSync(pkgNodeModules) && !nodePaths.includes(pkgNodeModules)) {
208
+ nodePaths.push(pkgNodeModules);
209
+ }
210
+ // Also add the parent scope for @spaces/* resolution
211
+ const parentModules = path.dirname(path.dirname(pkgPath));
212
+ if (!nodePaths.includes(parentModules)) {
213
+ nodePaths.push(parentModules);
214
+ }
215
+ }
216
+ }
217
+ for (const dir of nodePaths) {
218
+ for (const target of [childEnv, process.env]) {
219
+ const existing = target.NODE_PATH || '';
220
+ if (!existing.includes(dir)) {
221
+ target.NODE_PATH = existing
222
+ ? `${dir}${path.delimiter}${existing}`
223
+ : dir;
224
+ }
225
+ }
226
+ }
227
+ // Re-init module paths so require() in this process picks up the new NODE_PATH
228
+ require('module').Module._initPaths();
229
+
230
+ // Verify collaboration pipeline works end-to-end at startup
231
+ if (tier === 'team' || tier === 'federation') {
232
+ try {
233
+ const teams = require('@spaces/teams');
234
+ console.log(' Collaboration: @spaces/teams loaded OK');
235
+ // Smoke-test that peer deps resolve from this process
236
+ require('better-sqlite3');
237
+ } catch (e) {
238
+ console.error(` Warning: Collaboration may not work — ${e.message}`);
239
+ console.error(' Check that NODE_PATH includes the host app node_modules.');
240
+ }
241
+ }
242
+
243
+ console.log('');
244
+
245
+ // Check for ~/.claude/ directory
246
+ const claudeDir = path.join(os.homedir(), '.claude');
247
+ if (!fs.existsSync(claudeDir)) {
248
+ console.log(' Warning: ~/.claude/ not found. Have you used Claude Code yet?');
249
+ console.log('');
250
+ }
251
+
252
+ // ─── Detect build type ────────────────────────────────────
253
+ const standaloneServer = path.join(projectDir, '.next', 'standalone', 'server.js');
254
+ const fullBuildDir = path.join(projectDir, '.next', 'BUILD_ID');
255
+ const isStandalone = fs.existsSync(standaloneServer);
256
+ const isFullBuild = fs.existsSync(fullBuildDir);
257
+
258
+ if (!isStandalone && !isFullBuild) {
259
+ console.error(' Error: No build found.');
260
+ console.error(' Run "npm run build" first, or install via "npm install -g @jlongo78/agent-spaces".');
261
+ process.exit(1);
262
+ }
263
+
264
+ // ─── Spawn Next.js ────────────────────────────────────────
265
+ let next;
266
+ if (isStandalone) {
267
+ const parentNodeModules = path.join(projectDir, 'node_modules');
268
+ const existingNodePath = childEnv.NODE_PATH || '';
269
+ childEnv.NODE_PATH = existingNodePath
270
+ ? `${parentNodeModules}${path.delimiter}${existingNodePath}`
271
+ : parentNodeModules;
272
+
273
+ next = spawn(process.execPath, [standaloneServer], {
274
+ cwd: path.dirname(standaloneServer),
275
+ stdio: ['ignore', 'pipe', 'pipe'],
276
+ env: {
277
+ ...childEnv,
278
+ PORT: String(NEXT_INTERNAL_PORT),
279
+ HOSTNAME: '0.0.0.0',
280
+ NODE_ENV: 'production',
281
+ },
282
+ });
283
+ } else {
284
+ next = spawn('npx', ['next', 'start', '--port', String(NEXT_INTERNAL_PORT)], {
285
+ cwd: projectDir,
286
+ stdio: ['ignore', 'pipe', 'pipe'],
287
+ env: {
288
+ ...childEnv,
289
+ PORT: String(NEXT_INTERNAL_PORT),
290
+ HOSTNAME: '0.0.0.0',
291
+ NODE_ENV: 'production',
292
+ },
293
+ shell: true,
294
+ });
295
+ }
296
+
297
+ let nextReady = false;
298
+
299
+ next.stdout.on('data', (data) => {
300
+ const msg = data.toString();
301
+ process.stdout.write(msg);
302
+ if (!nextReady && (msg.includes('Ready') || msg.includes('started server') || msg.includes('Listening') || msg.includes('localhost'))) {
303
+ nextReady = true;
304
+ console.log(`\n Ready at http://localhost:${PORT}\n`);
305
+
306
+ const url = `http://localhost:${PORT}`;
307
+ const isService = process.env.SPACES_SERVICE === '1';
308
+ if (!isService) {
309
+ try {
310
+ if (process.platform === 'win32') {
311
+ execFileSync('cmd', ['/c', 'start', url], { stdio: 'ignore' });
312
+ } else if (process.platform === 'darwin') {
313
+ execFileSync('open', [url], { stdio: 'ignore' });
314
+ } else {
315
+ execFileSync('xdg-open', [url], { stdio: 'ignore' });
316
+ }
317
+ } catch {
318
+ console.log(` Open ${url} in your browser`);
319
+ }
320
+ }
321
+ }
322
+ });
323
+
324
+ next.stderr.on('data', (data) => {
325
+ const msg = data.toString();
326
+ if (!msg.includes('Warning')) {
327
+ process.stderr.write(data);
328
+ }
329
+ });
330
+
331
+ next.on('exit', (code) => {
332
+ if (code !== 0 && code !== null) {
333
+ console.error(` [spaces] Next.js exited with code ${code}`);
334
+ }
335
+ cleanup();
336
+ });
337
+
338
+ // ─── HTTP proxy server ────────────────────────────────────
339
+ const server = http.createServer((req, res) => {
340
+ // WebSocket paths are handled by the 'upgrade' event, but a plain
341
+ // HTTP request to /ws (e.g. health check) should not be proxied to
342
+ // Next.js which would 308-redirect it due to trailingSlash.
343
+ const urlPath = (req.url || '').split('?')[0];
344
+ if (urlPath === '/ws' || urlPath.endsWith('/ws') || urlPath.endsWith('/ws/')) {
345
+ res.writeHead(200, { 'Content-Type': 'text/plain' });
346
+ res.end('WebSocket endpoint');
347
+ return;
348
+ }
349
+
350
+ const proxyReq = http.request(
351
+ {
352
+ hostname: '127.0.0.1',
353
+ port: NEXT_INTERNAL_PORT,
354
+ path: req.url,
355
+ method: req.method,
356
+ headers: req.headers,
357
+ },
358
+ (proxyRes) => {
359
+ res.writeHead(proxyRes.statusCode, proxyRes.headers);
360
+ proxyRes.pipe(res);
361
+ }
362
+ );
363
+ proxyReq.on('error', () => {
364
+ if (!res.headersSent) {
365
+ res.writeHead(502);
366
+ res.end('Server not ready yet. Refresh in a moment.');
367
+ }
368
+ });
369
+ req.pipe(proxyReq);
370
+ });
371
+
372
+ const { createTerminalServer } = require('./terminal-server');
373
+ createTerminalServer(server);
374
+
375
+ server.listen(PORT, () => {
376
+ console.log(` Starting server on http://localhost:${PORT}`);
377
+ console.log('');
378
+ });
379
+
380
+ function cleanup() {
381
+ next.kill();
382
+ server.close();
383
+ process.exit(0);
384
+ }
385
+
386
+ process.on('SIGINT', cleanup);
387
+ process.on('SIGTERM', cleanup);
388
+ }
389
+
390
+ // ─── Stop running server ─────────────────────────────────────
391
+ function findPidsOnPort(port) {
392
+ const pids = new Set();
393
+ if (process.platform === 'win32') {
394
+ try {
395
+ const output = execFileSync('netstat', ['-ano'], { encoding: 'utf-8' });
396
+ for (const line of output.split(String.fromCharCode(10))) {
397
+ if (line.includes(':' + port + ' ') && line.includes('LISTENING')) {
398
+ const parts = line.trim().split(/\s+/);
399
+ const pid = parseInt(parts[parts.length - 1], 10);
400
+ if (pid > 0) pids.add(pid);
401
+ }
402
+ }
403
+ } catch {}
404
+ } else {
405
+ try {
406
+ const output = execFileSync('lsof', ['-ti', `tcp:${port}`], { encoding: 'utf-8' }).trim();
407
+ for (const p of output.split('\n')) { if (p.trim()) pids.add(parseInt(p.trim(), 10)); }
408
+ } catch {}
409
+ try {
410
+ const output = execFileSync('fuser', [`${port}/tcp`], { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] }).trim();
411
+ for (const p of output.split(/\s+/)) { if (p.trim()) pids.add(parseInt(p.trim(), 10)); }
412
+ } catch {}
413
+ }
414
+ return [...pids].filter(p => !isNaN(p) && p > 0);
415
+ }
416
+
417
+ function stopServer() {
418
+ let savedConfig = {};
419
+ if (fs.existsSync(CONFIG_PATH)) {
420
+ try { savedConfig = JSON.parse(fs.readFileSync(CONFIG_PATH, 'utf-8')); } catch {}
421
+ }
422
+ const port = parseInt(process.env.SPACES_PORT || '', 10) || savedConfig.port || 3457;
423
+ const ports = [port, NEXT_INTERNAL_PORT];
424
+ let killed = 0;
425
+
426
+ for (const p of ports) {
427
+ for (const pid of findPidsOnPort(p)) {
428
+ try {
429
+ process.kill(pid, 'SIGTERM');
430
+ killed++;
431
+ } catch {}
432
+ }
433
+ }
434
+
435
+ if (killed > 0) {
436
+ console.log(` Stopped ${killed} process(es) on port ${port}`);
437
+ // Wait for ports to be released, escalate to SIGKILL if needed
438
+ const deadline = Date.now() + 2000;
439
+ let escalated = false;
440
+ while (Date.now() < deadline) {
441
+ const remaining = ports.flatMap(p => findPidsOnPort(p));
442
+ if (remaining.length === 0) break;
443
+ if (!escalated && Date.now() > deadline - 1000) {
444
+ for (const pid of remaining) {
445
+ try { process.kill(pid, 'SIGKILL'); } catch {}
446
+ }
447
+ escalated = true;
448
+ }
449
+ if (process.platform === 'win32') { require('child_process').spawnSync('powershell', ['-Command', 'Start-Sleep -Milliseconds 200']); } else { require('child_process').spawnSync('sleep', ['0.2']); }
450
+ }
451
+ } else {
452
+ console.log(` No running server found on port ${port}`);
453
+ }
454
+ }
455
+
456
+ // ─── @spaces/pro resolution ──────────────────────────────────
457
+ function resolveSpacesPro() {
458
+ // 1. Managed install (~/.spaces/packages/)
459
+ const managed = path.join(MANAGED_NODE_MODULES, '@spaces', 'pro');
460
+ if (fs.existsSync(path.join(managed, 'dist', 'index.js'))) return managed;
461
+
462
+ // 2. Local node_modules (npm link / optionalDep)
463
+ try {
464
+ return require.resolve('@spaces/pro');
465
+ } catch {}
466
+
467
+ // 3. Global npm prefix (legacy)
468
+ try {
469
+ const globalPrefix = execFileSync('npm', ['prefix', '-g'], { encoding: 'utf-8' }).trim();
470
+ const globalProPath = path.join(globalPrefix, 'lib', 'node_modules', '@spaces', 'pro');
471
+ if (fs.existsSync(globalProPath)) return globalProPath;
472
+ const altPath = path.join(globalPrefix, 'node_modules', '@spaces', 'pro');
473
+ if (fs.existsSync(altPath)) return altPath;
474
+ } catch {}
475
+
476
+ return null;
477
+ }
478
+
479
+ // ─── @spaces/teams resolution ────────────────────────────────
480
+ function resolveSpacesTeams() {
481
+ // 1. Managed install (~/.spaces/packages/)
482
+ const managed = path.join(MANAGED_NODE_MODULES, '@spaces', 'teams');
483
+ if (fs.existsSync(path.join(managed, 'dist', 'index.js'))) return managed;
484
+
485
+ // 2. Local node_modules (npm link / optionalDep)
486
+ try {
487
+ return require.resolve('@spaces/teams');
488
+ } catch {}
489
+
490
+ // 3. Global npm prefix (legacy)
491
+ try {
492
+ const globalPrefix = execFileSync('npm', ['prefix', '-g'], { encoding: 'utf-8' }).trim();
493
+ const globalTeamsPath = path.join(globalPrefix, 'lib', 'node_modules', '@spaces', 'teams');
494
+ if (fs.existsSync(globalTeamsPath)) return globalTeamsPath;
495
+ const altPath = path.join(globalPrefix, 'node_modules', '@spaces', 'teams');
496
+ if (fs.existsSync(altPath)) return altPath;
497
+ } catch {}
498
+
499
+ return null;
500
+ }