@jlongo78/agent-spaces 0.9.8 → 0.9.10

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 (381) hide show
  1. package/.next/standalone/.next/BUILD_ID +1 -1
  2. package/.next/standalone/.next/app-path-routes-manifest.json +3 -0
  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/routes-manifest.json +23 -0
  6. package/.next/standalone/.next/server/app/(desktop)/admin/analytics/page.js.nft.json +1 -1
  7. package/.next/standalone/.next/server/app/(desktop)/admin/analytics/page_client-reference-manifest.js +1 -1
  8. package/.next/standalone/.next/server/app/(desktop)/admin/users/page_client-reference-manifest.js +1 -1
  9. package/.next/standalone/.next/server/app/(desktop)/analytics/page_client-reference-manifest.js +1 -1
  10. package/.next/standalone/.next/server/app/(desktop)/cortex/page_client-reference-manifest.js +1 -1
  11. package/.next/standalone/.next/server/app/(desktop)/network/page_client-reference-manifest.js +1 -1
  12. package/.next/standalone/.next/server/app/(desktop)/page_client-reference-manifest.js +1 -1
  13. package/.next/standalone/.next/server/app/(desktop)/projects/page_client-reference-manifest.js +1 -1
  14. package/.next/standalone/.next/server/app/(desktop)/sessions/[id]/page_client-reference-manifest.js +1 -1
  15. package/.next/standalone/.next/server/app/(desktop)/sessions/page_client-reference-manifest.js +1 -1
  16. package/.next/standalone/.next/server/app/(desktop)/settings/page_client-reference-manifest.js +1 -1
  17. package/.next/standalone/.next/server/app/(desktop)/terminal/page.js.nft.json +1 -1
  18. package/.next/standalone/.next/server/app/(desktop)/terminal/page_client-reference-manifest.js +1 -1
  19. package/.next/standalone/.next/server/app/(desktop)/terminal/pane/[id]/page_client-reference-manifest.js +1 -1
  20. package/.next/standalone/.next/server/app/(desktop)/terminal/remote/[nodeId]/[workspaceId]/page_client-reference-manifest.js +1 -1
  21. package/.next/standalone/.next/server/app/(desktop)/workspaces/page_client-reference-manifest.js +1 -1
  22. package/.next/standalone/.next/server/app/_global-error.html +2 -2
  23. package/.next/standalone/.next/server/app/_global-error.rsc +1 -1
  24. package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  25. package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  26. package/.next/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  27. package/.next/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  28. package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  29. package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  30. package/.next/standalone/.next/server/app/_not-found.html +1 -1
  31. package/.next/standalone/.next/server/app/_not-found.rsc +2 -2
  32. package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +2 -2
  33. package/.next/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  34. package/.next/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +2 -2
  35. package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  36. package/.next/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  37. package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  38. package/.next/standalone/.next/server/app/admin/analytics.html +1 -1
  39. package/.next/standalone/.next/server/app/admin/analytics.rsc +3 -3
  40. package/.next/standalone/.next/server/app/admin/analytics.segments/!KGRlc2t0b3Ap/admin/analytics/__PAGE__.segment.rsc +2 -2
  41. package/.next/standalone/.next/server/app/admin/analytics.segments/!KGRlc2t0b3Ap/admin/analytics.segment.rsc +1 -1
  42. package/.next/standalone/.next/server/app/admin/analytics.segments/!KGRlc2t0b3Ap/admin.segment.rsc +1 -1
  43. package/.next/standalone/.next/server/app/admin/analytics.segments/!KGRlc2t0b3Ap.segment.rsc +1 -1
  44. package/.next/standalone/.next/server/app/admin/analytics.segments/_full.segment.rsc +3 -3
  45. package/.next/standalone/.next/server/app/admin/analytics.segments/_head.segment.rsc +1 -1
  46. package/.next/standalone/.next/server/app/admin/analytics.segments/_index.segment.rsc +2 -2
  47. package/.next/standalone/.next/server/app/admin/analytics.segments/_tree.segment.rsc +2 -2
  48. package/.next/standalone/.next/server/app/admin/users.html +1 -1
  49. package/.next/standalone/.next/server/app/admin/users.rsc +2 -2
  50. package/.next/standalone/.next/server/app/admin/users.segments/!KGRlc2t0b3Ap/admin/users/__PAGE__.segment.rsc +1 -1
  51. package/.next/standalone/.next/server/app/admin/users.segments/!KGRlc2t0b3Ap/admin/users.segment.rsc +1 -1
  52. package/.next/standalone/.next/server/app/admin/users.segments/!KGRlc2t0b3Ap/admin.segment.rsc +1 -1
  53. package/.next/standalone/.next/server/app/admin/users.segments/!KGRlc2t0b3Ap.segment.rsc +1 -1
  54. package/.next/standalone/.next/server/app/admin/users.segments/_full.segment.rsc +2 -2
  55. package/.next/standalone/.next/server/app/admin/users.segments/_head.segment.rsc +1 -1
  56. package/.next/standalone/.next/server/app/admin/users.segments/_index.segment.rsc +2 -2
  57. package/.next/standalone/.next/server/app/admin/users.segments/_tree.segment.rsc +2 -2
  58. package/.next/standalone/.next/server/app/analytics.html +1 -1
  59. package/.next/standalone/.next/server/app/analytics.rsc +2 -2
  60. package/.next/standalone/.next/server/app/analytics.segments/!KGRlc2t0b3Ap/analytics/__PAGE__.segment.rsc +1 -1
  61. package/.next/standalone/.next/server/app/analytics.segments/!KGRlc2t0b3Ap/analytics.segment.rsc +1 -1
  62. package/.next/standalone/.next/server/app/analytics.segments/!KGRlc2t0b3Ap.segment.rsc +1 -1
  63. package/.next/standalone/.next/server/app/analytics.segments/_full.segment.rsc +2 -2
  64. package/.next/standalone/.next/server/app/analytics.segments/_head.segment.rsc +1 -1
  65. package/.next/standalone/.next/server/app/analytics.segments/_index.segment.rsc +2 -2
  66. package/.next/standalone/.next/server/app/analytics.segments/_tree.segment.rsc +2 -2
  67. package/.next/standalone/.next/server/app/api/chat/route.js +1 -1
  68. package/.next/standalone/.next/server/app/api/chat/route.js.nft.json +1 -1
  69. package/.next/standalone/.next/server/app/api/claude/usage/route/app-paths-manifest.json +3 -0
  70. package/.next/standalone/.next/server/app/api/claude/usage/route/build-manifest.json +11 -0
  71. package/.next/standalone/.next/server/app/api/claude/usage/route/server-reference-manifest.json +4 -0
  72. package/.next/standalone/.next/server/app/api/claude/usage/route.js +8 -0
  73. package/.next/standalone/.next/server/app/api/claude/usage/route.js.map +5 -0
  74. package/.next/standalone/.next/server/app/api/claude/usage/route.js.nft.json +1 -0
  75. package/.next/standalone/.next/server/app/api/claude/usage/route_client-reference-manifest.js +2 -0
  76. package/.next/standalone/.next/server/app/api/cortex/status/route.js.nft.json +1 -1
  77. package/.next/standalone/.next/server/app/api/sessions/[id]/chat/route.js +1 -1
  78. package/.next/standalone/.next/server/app/api/sessions/[id]/chat/route.js.nft.json +1 -1
  79. package/.next/standalone/.next/server/app/api/whisper/route.js.nft.json +1 -1
  80. package/.next/standalone/.next/server/app/api/workspaces/[id]/todos/[todoId]/route/app-paths-manifest.json +3 -0
  81. package/.next/standalone/.next/server/app/api/workspaces/[id]/todos/[todoId]/route/build-manifest.json +11 -0
  82. package/.next/standalone/.next/server/app/api/workspaces/[id]/todos/[todoId]/route/server-reference-manifest.json +4 -0
  83. package/.next/standalone/.next/server/app/api/workspaces/[id]/todos/[todoId]/route.js +8 -0
  84. package/.next/standalone/.next/server/app/api/workspaces/[id]/todos/[todoId]/route.js.map +5 -0
  85. package/.next/standalone/.next/server/app/api/workspaces/[id]/todos/[todoId]/route.js.nft.json +1 -0
  86. package/.next/standalone/.next/server/app/api/workspaces/[id]/todos/[todoId]/route_client-reference-manifest.js +2 -0
  87. package/.next/standalone/.next/server/app/api/workspaces/[id]/todos/route/app-paths-manifest.json +3 -0
  88. package/.next/standalone/.next/server/app/api/workspaces/[id]/todos/route/build-manifest.json +11 -0
  89. package/.next/standalone/.next/server/app/api/workspaces/[id]/todos/route/server-reference-manifest.json +4 -0
  90. package/.next/standalone/.next/server/app/api/workspaces/[id]/todos/route.js +8 -0
  91. package/.next/standalone/.next/server/app/api/workspaces/[id]/todos/route.js.map +5 -0
  92. package/.next/standalone/.next/server/app/api/workspaces/[id]/todos/route.js.nft.json +1 -0
  93. package/.next/standalone/.next/server/app/api/workspaces/[id]/todos/route_client-reference-manifest.js +2 -0
  94. package/.next/standalone/.next/server/app/cortex.html +1 -1
  95. package/.next/standalone/.next/server/app/cortex.rsc +2 -2
  96. package/.next/standalone/.next/server/app/cortex.segments/!KGRlc2t0b3Ap/cortex/__PAGE__.segment.rsc +1 -1
  97. package/.next/standalone/.next/server/app/cortex.segments/!KGRlc2t0b3Ap/cortex.segment.rsc +1 -1
  98. package/.next/standalone/.next/server/app/cortex.segments/!KGRlc2t0b3Ap.segment.rsc +1 -1
  99. package/.next/standalone/.next/server/app/cortex.segments/_full.segment.rsc +2 -2
  100. package/.next/standalone/.next/server/app/cortex.segments/_head.segment.rsc +1 -1
  101. package/.next/standalone/.next/server/app/cortex.segments/_index.segment.rsc +2 -2
  102. package/.next/standalone/.next/server/app/cortex.segments/_tree.segment.rsc +2 -2
  103. package/.next/standalone/.next/server/app/login/page_client-reference-manifest.js +1 -1
  104. package/.next/standalone/.next/server/app/login.html +1 -1
  105. package/.next/standalone/.next/server/app/login.rsc +2 -2
  106. package/.next/standalone/.next/server/app/login.segments/_full.segment.rsc +2 -2
  107. package/.next/standalone/.next/server/app/login.segments/_head.segment.rsc +1 -1
  108. package/.next/standalone/.next/server/app/login.segments/_index.segment.rsc +2 -2
  109. package/.next/standalone/.next/server/app/login.segments/_tree.segment.rsc +2 -2
  110. package/.next/standalone/.next/server/app/login.segments/login/__PAGE__.segment.rsc +1 -1
  111. package/.next/standalone/.next/server/app/login.segments/login.segment.rsc +1 -1
  112. package/.next/standalone/.next/server/app/m/page_client-reference-manifest.js +1 -1
  113. package/.next/standalone/.next/server/app/m/projects/page_client-reference-manifest.js +1 -1
  114. package/.next/standalone/.next/server/app/m/projects.html +1 -1
  115. package/.next/standalone/.next/server/app/m/projects.rsc +2 -2
  116. package/.next/standalone/.next/server/app/m/projects.segments/_full.segment.rsc +2 -2
  117. package/.next/standalone/.next/server/app/m/projects.segments/_head.segment.rsc +1 -1
  118. package/.next/standalone/.next/server/app/m/projects.segments/_index.segment.rsc +2 -2
  119. package/.next/standalone/.next/server/app/m/projects.segments/_tree.segment.rsc +2 -2
  120. package/.next/standalone/.next/server/app/m/projects.segments/m/projects/__PAGE__.segment.rsc +1 -1
  121. package/.next/standalone/.next/server/app/m/projects.segments/m/projects.segment.rsc +1 -1
  122. package/.next/standalone/.next/server/app/m/projects.segments/m.segment.rsc +1 -1
  123. package/.next/standalone/.next/server/app/m/sessions/[id]/page_client-reference-manifest.js +1 -1
  124. package/.next/standalone/.next/server/app/m/sessions/page_client-reference-manifest.js +1 -1
  125. package/.next/standalone/.next/server/app/m/sessions.html +1 -1
  126. package/.next/standalone/.next/server/app/m/sessions.rsc +2 -2
  127. package/.next/standalone/.next/server/app/m/sessions.segments/_full.segment.rsc +2 -2
  128. package/.next/standalone/.next/server/app/m/sessions.segments/_head.segment.rsc +1 -1
  129. package/.next/standalone/.next/server/app/m/sessions.segments/_index.segment.rsc +2 -2
  130. package/.next/standalone/.next/server/app/m/sessions.segments/_tree.segment.rsc +2 -2
  131. package/.next/standalone/.next/server/app/m/sessions.segments/m/sessions/__PAGE__.segment.rsc +1 -1
  132. package/.next/standalone/.next/server/app/m/sessions.segments/m/sessions.segment.rsc +1 -1
  133. package/.next/standalone/.next/server/app/m/sessions.segments/m.segment.rsc +1 -1
  134. package/.next/standalone/.next/server/app/m/settings/page_client-reference-manifest.js +1 -1
  135. package/.next/standalone/.next/server/app/m/settings.html +1 -1
  136. package/.next/standalone/.next/server/app/m/settings.rsc +2 -2
  137. package/.next/standalone/.next/server/app/m/settings.segments/_full.segment.rsc +2 -2
  138. package/.next/standalone/.next/server/app/m/settings.segments/_head.segment.rsc +1 -1
  139. package/.next/standalone/.next/server/app/m/settings.segments/_index.segment.rsc +2 -2
  140. package/.next/standalone/.next/server/app/m/settings.segments/_tree.segment.rsc +2 -2
  141. package/.next/standalone/.next/server/app/m/settings.segments/m/settings/__PAGE__.segment.rsc +1 -1
  142. package/.next/standalone/.next/server/app/m/settings.segments/m/settings.segment.rsc +1 -1
  143. package/.next/standalone/.next/server/app/m/settings.segments/m.segment.rsc +1 -1
  144. package/.next/standalone/.next/server/app/m/terminal/page_client-reference-manifest.js +1 -1
  145. package/.next/standalone/.next/server/app/m/terminal.html +1 -1
  146. package/.next/standalone/.next/server/app/m/terminal.rsc +2 -2
  147. package/.next/standalone/.next/server/app/m/terminal.segments/_full.segment.rsc +2 -2
  148. package/.next/standalone/.next/server/app/m/terminal.segments/_head.segment.rsc +1 -1
  149. package/.next/standalone/.next/server/app/m/terminal.segments/_index.segment.rsc +2 -2
  150. package/.next/standalone/.next/server/app/m/terminal.segments/_tree.segment.rsc +2 -2
  151. package/.next/standalone/.next/server/app/m/terminal.segments/m/terminal/__PAGE__.segment.rsc +1 -1
  152. package/.next/standalone/.next/server/app/m/terminal.segments/m/terminal.segment.rsc +1 -1
  153. package/.next/standalone/.next/server/app/m/terminal.segments/m.segment.rsc +1 -1
  154. package/.next/standalone/.next/server/app/m.html +1 -1
  155. package/.next/standalone/.next/server/app/m.rsc +2 -2
  156. package/.next/standalone/.next/server/app/m.segments/_full.segment.rsc +2 -2
  157. package/.next/standalone/.next/server/app/m.segments/_head.segment.rsc +1 -1
  158. package/.next/standalone/.next/server/app/m.segments/_index.segment.rsc +2 -2
  159. package/.next/standalone/.next/server/app/m.segments/_tree.segment.rsc +2 -2
  160. package/.next/standalone/.next/server/app/m.segments/m/__PAGE__.segment.rsc +1 -1
  161. package/.next/standalone/.next/server/app/m.segments/m.segment.rsc +1 -1
  162. package/.next/standalone/.next/server/app/network.html +1 -1
  163. package/.next/standalone/.next/server/app/network.rsc +2 -2
  164. package/.next/standalone/.next/server/app/network.segments/!KGRlc2t0b3Ap/network/__PAGE__.segment.rsc +1 -1
  165. package/.next/standalone/.next/server/app/network.segments/!KGRlc2t0b3Ap/network.segment.rsc +1 -1
  166. package/.next/standalone/.next/server/app/network.segments/!KGRlc2t0b3Ap.segment.rsc +1 -1
  167. package/.next/standalone/.next/server/app/network.segments/_full.segment.rsc +2 -2
  168. package/.next/standalone/.next/server/app/network.segments/_head.segment.rsc +1 -1
  169. package/.next/standalone/.next/server/app/network.segments/_index.segment.rsc +2 -2
  170. package/.next/standalone/.next/server/app/network.segments/_tree.segment.rsc +2 -2
  171. package/.next/standalone/.next/server/app/projects.html +1 -1
  172. package/.next/standalone/.next/server/app/projects.rsc +2 -2
  173. package/.next/standalone/.next/server/app/projects.segments/!KGRlc2t0b3Ap/projects/__PAGE__.segment.rsc +1 -1
  174. package/.next/standalone/.next/server/app/projects.segments/!KGRlc2t0b3Ap/projects.segment.rsc +1 -1
  175. package/.next/standalone/.next/server/app/projects.segments/!KGRlc2t0b3Ap.segment.rsc +1 -1
  176. package/.next/standalone/.next/server/app/projects.segments/_full.segment.rsc +2 -2
  177. package/.next/standalone/.next/server/app/projects.segments/_head.segment.rsc +1 -1
  178. package/.next/standalone/.next/server/app/projects.segments/_index.segment.rsc +2 -2
  179. package/.next/standalone/.next/server/app/projects.segments/_tree.segment.rsc +2 -2
  180. package/.next/standalone/.next/server/app/sessions.html +1 -1
  181. package/.next/standalone/.next/server/app/sessions.rsc +2 -2
  182. package/.next/standalone/.next/server/app/sessions.segments/!KGRlc2t0b3Ap/sessions/__PAGE__.segment.rsc +1 -1
  183. package/.next/standalone/.next/server/app/sessions.segments/!KGRlc2t0b3Ap/sessions.segment.rsc +1 -1
  184. package/.next/standalone/.next/server/app/sessions.segments/!KGRlc2t0b3Ap.segment.rsc +1 -1
  185. package/.next/standalone/.next/server/app/sessions.segments/_full.segment.rsc +2 -2
  186. package/.next/standalone/.next/server/app/sessions.segments/_head.segment.rsc +1 -1
  187. package/.next/standalone/.next/server/app/sessions.segments/_index.segment.rsc +2 -2
  188. package/.next/standalone/.next/server/app/sessions.segments/_tree.segment.rsc +2 -2
  189. package/.next/standalone/.next/server/app/settings.html +1 -1
  190. package/.next/standalone/.next/server/app/settings.rsc +3 -3
  191. package/.next/standalone/.next/server/app/settings.segments/!KGRlc2t0b3Ap/settings/__PAGE__.segment.rsc +2 -2
  192. package/.next/standalone/.next/server/app/settings.segments/!KGRlc2t0b3Ap/settings.segment.rsc +1 -1
  193. package/.next/standalone/.next/server/app/settings.segments/!KGRlc2t0b3Ap.segment.rsc +1 -1
  194. package/.next/standalone/.next/server/app/settings.segments/_full.segment.rsc +3 -3
  195. package/.next/standalone/.next/server/app/settings.segments/_head.segment.rsc +1 -1
  196. package/.next/standalone/.next/server/app/settings.segments/_index.segment.rsc +2 -2
  197. package/.next/standalone/.next/server/app/settings.segments/_tree.segment.rsc +2 -2
  198. package/.next/standalone/.next/server/app/terminal.html +1 -1
  199. package/.next/standalone/.next/server/app/terminal.rsc +3 -3
  200. package/.next/standalone/.next/server/app/terminal.segments/!KGRlc2t0b3Ap/terminal/__PAGE__.segment.rsc +2 -2
  201. package/.next/standalone/.next/server/app/terminal.segments/!KGRlc2t0b3Ap/terminal.segment.rsc +1 -1
  202. package/.next/standalone/.next/server/app/terminal.segments/!KGRlc2t0b3Ap.segment.rsc +1 -1
  203. package/.next/standalone/.next/server/app/terminal.segments/_full.segment.rsc +3 -3
  204. package/.next/standalone/.next/server/app/terminal.segments/_head.segment.rsc +1 -1
  205. package/.next/standalone/.next/server/app/terminal.segments/_index.segment.rsc +2 -2
  206. package/.next/standalone/.next/server/app/terminal.segments/_tree.segment.rsc +2 -2
  207. package/.next/standalone/.next/server/app/vr/page_client-reference-manifest.js +1 -1
  208. package/.next/standalone/.next/server/app/vr.html +1 -1
  209. package/.next/standalone/.next/server/app/vr.rsc +2 -2
  210. package/.next/standalone/.next/server/app/vr.segments/_full.segment.rsc +2 -2
  211. package/.next/standalone/.next/server/app/vr.segments/_head.segment.rsc +1 -1
  212. package/.next/standalone/.next/server/app/vr.segments/_index.segment.rsc +2 -2
  213. package/.next/standalone/.next/server/app/vr.segments/_tree.segment.rsc +2 -2
  214. package/.next/standalone/.next/server/app/vr.segments/vr/__PAGE__.segment.rsc +1 -1
  215. package/.next/standalone/.next/server/app/vr.segments/vr.segment.rsc +1 -1
  216. package/.next/standalone/.next/server/app/workspaces.html +1 -1
  217. package/.next/standalone/.next/server/app/workspaces.rsc +2 -2
  218. package/.next/standalone/.next/server/app/workspaces.segments/!KGRlc2t0b3Ap/workspaces/__PAGE__.segment.rsc +1 -1
  219. package/.next/standalone/.next/server/app/workspaces.segments/!KGRlc2t0b3Ap/workspaces.segment.rsc +1 -1
  220. package/.next/standalone/.next/server/app/workspaces.segments/!KGRlc2t0b3Ap.segment.rsc +1 -1
  221. package/.next/standalone/.next/server/app/workspaces.segments/_full.segment.rsc +2 -2
  222. package/.next/standalone/.next/server/app/workspaces.segments/_head.segment.rsc +1 -1
  223. package/.next/standalone/.next/server/app/workspaces.segments/_index.segment.rsc +2 -2
  224. package/.next/standalone/.next/server/app/workspaces.segments/_tree.segment.rsc +2 -2
  225. package/.next/standalone/.next/server/app-paths-manifest.json +3 -0
  226. package/.next/standalone/.next/server/chunks/[root-of-the-server]__00e90fc6._.js +15 -2
  227. package/.next/standalone/.next/server/chunks/[root-of-the-server]__01ab8675._.js +15 -2
  228. package/.next/standalone/.next/server/chunks/[root-of-the-server]__03974f05._.js +15 -2
  229. package/.next/standalone/.next/server/chunks/[root-of-the-server]__046c9b91._.js +16 -3
  230. package/.next/standalone/.next/server/chunks/[root-of-the-server]__04ae6bf0._.js +15 -2
  231. package/.next/standalone/.next/server/chunks/[root-of-the-server]__056fa416._.js +1 -1
  232. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0ac4ea3f._.js +1 -1
  233. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0b8e64cb._.js +15 -2
  234. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0facd39e._.js +15 -2
  235. package/.next/standalone/.next/server/chunks/[root-of-the-server]__10bc76a3._.js +1 -1
  236. package/.next/standalone/.next/server/chunks/[root-of-the-server]__115f3934._.js +15 -2
  237. package/.next/standalone/.next/server/chunks/[root-of-the-server]__11f155f1._.js +1 -1
  238. package/.next/standalone/.next/server/chunks/[root-of-the-server]__160e7c73._.js +52 -24
  239. package/.next/standalone/.next/server/chunks/[root-of-the-server]__17a3b966._.js +15 -2
  240. package/.next/standalone/.next/server/chunks/[root-of-the-server]__17d3a2b2._.js +15 -2
  241. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1a86c055._.js +15 -2
  242. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1fe0f452._.js +127 -0
  243. package/.next/standalone/.next/server/chunks/[root-of-the-server]__20b5e9c4._.js +1 -1
  244. package/.next/standalone/.next/server/chunks/[root-of-the-server]__28d6fbd8._.js +15 -2
  245. package/.next/standalone/.next/server/chunks/[root-of-the-server]__2a3f866b._.js +16 -3
  246. package/.next/standalone/.next/server/chunks/[root-of-the-server]__316617e7._.js +3 -3
  247. package/.next/standalone/.next/server/chunks/[root-of-the-server]__32ad8f71._.js +15 -2
  248. package/.next/standalone/.next/server/chunks/[root-of-the-server]__35457394._.js +15 -2
  249. package/.next/standalone/.next/server/chunks/[root-of-the-server]__35de78e6._.js +15 -2
  250. package/.next/standalone/.next/server/chunks/[root-of-the-server]__3685ffcb._.js +15 -2
  251. package/.next/standalone/.next/server/chunks/[root-of-the-server]__38954988._.js +15 -2
  252. package/.next/standalone/.next/server/chunks/[root-of-the-server]__3a32b624._.js +111 -0
  253. package/.next/standalone/.next/server/chunks/[root-of-the-server]__426ad936._.js +17 -4
  254. package/.next/standalone/.next/server/chunks/[root-of-the-server]__4985c034._.js +15 -2
  255. package/.next/standalone/.next/server/chunks/[root-of-the-server]__5c6ce9ed._.js +16 -3
  256. package/.next/standalone/.next/server/chunks/[root-of-the-server]__5cebe58a._.js +15 -2
  257. package/.next/standalone/.next/server/chunks/[root-of-the-server]__5d5e4789._.js +15 -2
  258. package/.next/standalone/.next/server/chunks/[root-of-the-server]__65676930._.js +1 -1
  259. package/.next/standalone/.next/server/chunks/[root-of-the-server]__67cab326._.js +2 -2
  260. package/.next/standalone/.next/server/chunks/[root-of-the-server]__698c6f01._.js +16 -3
  261. package/.next/standalone/.next/server/chunks/[root-of-the-server]__6c64af29._.js +22 -9
  262. package/.next/standalone/.next/server/chunks/[root-of-the-server]__73aed9f5._.js +15 -2
  263. package/.next/standalone/.next/server/chunks/[root-of-the-server]__79b6a9bb._.js +15 -2
  264. package/.next/standalone/.next/server/chunks/[root-of-the-server]__7db704c6._.js +17 -4
  265. package/.next/standalone/.next/server/chunks/[root-of-the-server]__812ca02b._.js +15 -2
  266. package/.next/standalone/.next/server/chunks/[root-of-the-server]__821f50fa._.js +15 -2
  267. package/.next/standalone/.next/server/chunks/[root-of-the-server]__8716b86e._.js +15 -2
  268. package/.next/standalone/.next/server/chunks/[root-of-the-server]__884ef754._.js +15 -2
  269. package/.next/standalone/.next/server/chunks/[root-of-the-server]__88cdbd68._.js +15 -2
  270. package/.next/standalone/.next/server/chunks/[root-of-the-server]__89d9aba9._.js +15 -2
  271. package/.next/standalone/.next/server/chunks/[root-of-the-server]__8c2e1260._.js +111 -0
  272. package/.next/standalone/.next/server/chunks/[root-of-the-server]__8d536cb5._.js +15 -2
  273. package/.next/standalone/.next/server/chunks/[root-of-the-server]__8df8c5d1._.js +15 -2
  274. package/.next/standalone/.next/server/chunks/[root-of-the-server]__8f2ccc41._.js +15 -2
  275. package/.next/standalone/.next/server/chunks/[root-of-the-server]__95c9d682._.js +15 -2
  276. package/.next/standalone/.next/server/chunks/[root-of-the-server]__9e5d7774._.js +15 -2
  277. package/.next/standalone/.next/server/chunks/[root-of-the-server]__9edcff87._.js +15 -2
  278. package/.next/standalone/.next/server/chunks/[root-of-the-server]__a049dfc2._.js +15 -2
  279. package/.next/standalone/.next/server/chunks/[root-of-the-server]__a5b4bb9a._.js +15 -2
  280. package/.next/standalone/.next/server/chunks/[root-of-the-server]__a83262a1._.js +15 -2
  281. package/.next/standalone/.next/server/chunks/[root-of-the-server]__a9cd1240._.js +15 -2
  282. package/.next/standalone/.next/server/chunks/[root-of-the-server]__a9d7f822._.js +15 -2
  283. package/.next/standalone/.next/server/chunks/[root-of-the-server]__ad08c221._.js +15 -2
  284. package/.next/standalone/.next/server/chunks/[root-of-the-server]__ad585f2f._.js +15 -2
  285. package/.next/standalone/.next/server/chunks/[root-of-the-server]__afcb8f7d._.js +15 -2
  286. package/.next/standalone/.next/server/chunks/[root-of-the-server]__bc250d43._.js +15 -2
  287. package/.next/standalone/.next/server/chunks/[root-of-the-server]__bce2a6e7._.js +15 -2
  288. package/.next/standalone/.next/server/chunks/[root-of-the-server]__bfcd7fd4._.js +13 -0
  289. package/.next/standalone/.next/server/chunks/[root-of-the-server]__c011bf91._.js +15 -2
  290. package/.next/standalone/.next/server/chunks/[root-of-the-server]__c37d6380._.js +1 -1
  291. package/.next/standalone/.next/server/chunks/[root-of-the-server]__cae392eb._.js +15 -2
  292. package/.next/standalone/.next/server/chunks/[root-of-the-server]__cc2616bb._.js +16 -3
  293. package/.next/standalone/.next/server/chunks/[root-of-the-server]__d501fa9b._.js +15 -2
  294. package/.next/standalone/.next/server/chunks/[root-of-the-server]__d59c6c15._.js +15 -2
  295. package/.next/standalone/.next/server/chunks/[root-of-the-server]__d5c1db32._.js +15 -2
  296. package/.next/standalone/.next/server/chunks/[root-of-the-server]__dba60c86._.js +15 -2
  297. package/.next/standalone/.next/server/chunks/[root-of-the-server]__de14b9ae._.js +15 -2
  298. package/.next/standalone/.next/server/chunks/[root-of-the-server]__e10643d1._.js +15 -2
  299. package/.next/standalone/.next/server/chunks/[root-of-the-server]__e3477417._.js +15 -2
  300. package/.next/standalone/.next/server/chunks/[root-of-the-server]__e4db362e._.js +1 -1
  301. package/.next/standalone/.next/server/chunks/[root-of-the-server]__e4e70b86._.js +15 -2
  302. package/.next/standalone/.next/server/chunks/[root-of-the-server]__e54925af._.js +15 -2
  303. package/.next/standalone/.next/server/chunks/[root-of-the-server]__e8cbeaca._.js +111 -0
  304. package/.next/standalone/.next/server/chunks/[root-of-the-server]__e8edc5b0._.js +15 -2
  305. package/.next/standalone/.next/server/chunks/[root-of-the-server]__eab4d83b._.js +15 -2
  306. package/.next/standalone/.next/server/chunks/[root-of-the-server]__f056fd83._.js +15 -2
  307. package/.next/standalone/.next/server/chunks/[root-of-the-server]__f0e99572._.js +15 -2
  308. package/.next/standalone/.next/server/chunks/[root-of-the-server]__fe1e16d0._.js +15 -2
  309. package/.next/standalone/.next/server/chunks/[root-of-the-server]__ff9cd277._.js +15 -2
  310. package/.next/standalone/.next/server/chunks/[root-of-the-server]__ffaea2ce._.js +15 -2
  311. package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_claude_usage_route_actions_fe002ec1.js +3 -0
  312. package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_workspaces_[id]_todos_route_actions_0d4ffac5.js +3 -0
  313. package/.next/standalone/.next/server/chunks/ce889_server_app_api_workspaces_[id]_todos_[todoId]_route_actions_754fe6b9.js +3 -0
  314. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__66aca5d4._.js +1 -1
  315. package/.next/standalone/.next/server/chunks/ssr/{_17b946fd._.js → _20c2cf3a._.js} +2 -2
  316. package/.next/standalone/.next/server/chunks/ssr/_5f55bf8f._.js +3 -0
  317. package/.next/standalone/.next/server/chunks/ssr/src_app_(desktop)_settings_page_tsx_f74824b3._.js +1 -1
  318. package/.next/standalone/.next/server/chunks/ssr/src_app_(desktop)_terminal_page_tsx_de5e8d85._.js +1 -1
  319. package/.next/standalone/.next/server/edge/chunks/[root-of-the-server]__90eeddae._.js +1 -1
  320. package/.next/standalone/.next/server/edge/chunks/[root-of-the-server]__ca3f649e._.js +2 -2
  321. package/.next/standalone/.next/server/middleware-manifest.json +5 -5
  322. package/.next/standalone/.next/server/pages/404.html +1 -1
  323. package/.next/standalone/.next/server/pages/500.html +2 -2
  324. package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
  325. package/.next/standalone/.next/server/server-reference-manifest.json +1 -1
  326. package/.next/standalone/.next/static/chunks/14216197f9dcbe5b.css +3 -0
  327. package/.next/standalone/.next/static/chunks/{0852575eb90c1e8d.js → 4c9fb0a38f041a3d.js} +2 -2
  328. package/.next/standalone/.next/static/chunks/8f6f93ab45a5ff5b.js +1 -0
  329. package/.next/standalone/.next/static/chunks/{e62bb488d02db247.js → d2566c2dcf53fef3.js} +1 -1
  330. package/.next/standalone/.next/static/chunks/{7f6a14f1849fa94d.js → ff7d85dade44d1f3.js} +1 -1
  331. package/.next/standalone/bin/cortex-hook.js +8 -3
  332. package/.next/standalone/bin/cortex-learn-hook.js +7 -2
  333. package/.next/standalone/bin/scrub-standalone.js +89 -0
  334. package/.next/standalone/bin/terminal-server.js +44 -16
  335. package/.next/standalone/docs/features/claude-usage.md +105 -0
  336. package/.next/standalone/docs/features/workspace-todos.md +127 -0
  337. package/.next/standalone/docs/superpowers/plans/2026-04-21-workspace-todos.md +1097 -0
  338. package/.next/standalone/docs/superpowers/plans/2026-04-22-claude-usage-display.md +749 -0
  339. package/.next/standalone/docs/superpowers/specs/2026-04-21-workspace-todos-design.md +180 -0
  340. package/.next/standalone/docs/superpowers/specs/2026-04-22-claude-usage-display-design.md +183 -0
  341. package/.next/standalone/package-lock.json +2 -2
  342. package/.next/standalone/package.json +2 -2
  343. package/.next/standalone/src/app/(desktop)/settings/page.tsx +40 -1
  344. package/.next/standalone/src/app/(desktop)/terminal/page.tsx +54 -2
  345. package/.next/standalone/src/app/api/chat/route.ts +56 -53
  346. package/.next/standalone/src/app/api/claude/usage/route.ts +33 -0
  347. package/.next/standalone/src/app/api/config/route.ts +3 -0
  348. package/.next/standalone/src/app/api/sessions/[id]/chat/route.ts +2 -1
  349. package/.next/standalone/src/app/api/workspaces/[id]/todos/[todoId]/route.ts +55 -0
  350. package/.next/standalone/src/app/api/workspaces/[id]/todos/route.ts +43 -0
  351. package/.next/standalone/src/components/claude/claude-usage-strip.tsx +175 -0
  352. package/.next/standalone/src/components/workspace/workspace-todos.tsx +265 -0
  353. package/.next/standalone/src/hooks/use-claude-usage.ts +66 -0
  354. package/.next/standalone/src/lib/claude/credentials.ts +36 -0
  355. package/.next/standalone/src/lib/claude/usage.ts +69 -0
  356. package/.next/standalone/src/lib/config.ts +3 -0
  357. package/.next/standalone/src/lib/db/queries.ts +103 -1
  358. package/.next/standalone/src/lib/db/schema.ts +18 -0
  359. package/.next/standalone/src/lib/spawn-env.ts +32 -0
  360. package/.next/standalone/src/lib/terminal/server.ts +3 -3
  361. package/.next/standalone/src/middleware.ts +23 -5
  362. package/.next/standalone/src/types/claude.ts +39 -0
  363. package/.next/standalone/tests/db/workspace-todos.test.ts +156 -0
  364. package/bin/cortex-hook.js +8 -3
  365. package/bin/cortex-learn-hook.js +7 -2
  366. package/bin/scrub-standalone.js +89 -0
  367. package/bin/terminal-server.js +44 -16
  368. package/package.json +2 -2
  369. package/.next/standalone/.claude/settings.local.json +0 -68
  370. package/.next/standalone/.claude/spaces-env.json +0 -1
  371. package/.next/standalone/.next/server/chunks/[root-of-the-server]__e2a996e5._.js +0 -114
  372. package/.next/standalone/.next/server/chunks/[root-of-the-server]__ead29015._.js +0 -13
  373. package/.next/standalone/.next/server/chunks/ssr/_3ba93bdd._.js +0 -3
  374. package/.next/standalone/.next/static/chunks/074df89a63b6a854.js +0 -1
  375. package/.next/standalone/.next/static/chunks/2b769d1597e4fc1c.css +0 -3
  376. package/.next/standalone/.spaces/cortex-context.md +0 -51
  377. package/.next/standalone/cortex-hook-debug.log +0 -57
  378. package/.next/standalone/docs/plans/2026-03-02-security-audit.md +0 -229
  379. /package/.next/standalone/.next/static/{u1pHON3drz1mBi7owkbBP → HNrWymrkgOP9Z4WIaYeOj}/_buildManifest.js +0 -0
  380. /package/.next/standalone/.next/static/{u1pHON3drz1mBi7owkbBP → HNrWymrkgOP9Z4WIaYeOj}/_clientMiddlewareManifest.json +0 -0
  381. /package/.next/standalone/.next/static/{u1pHON3drz1mBi7owkbBP → HNrWymrkgOP9Z4WIaYeOj}/_ssgManifest.js +0 -0
@@ -0,0 +1,265 @@
1
+ 'use client';
2
+
3
+ import { useCallback, useEffect, useRef, useState } from 'react';
4
+ import { Check, Plus, X } from 'lucide-react';
5
+ import { api } from '@/lib/api';
6
+ import type { Workspace, WorkspaceTodo } from '@/types/claude';
7
+
8
+ export function WorkspaceTodos({ workspace }: { workspace: Workspace | null }) {
9
+ const workspaceId = workspace?.id ?? null;
10
+ const color = workspace?.color ?? '#6366f1';
11
+
12
+ const [todos, setTodos] = useState<WorkspaceTodo[]>([]);
13
+ const [adding, setAdding] = useState(false);
14
+ const [addInput, setAddInput] = useState('');
15
+ const [editingId, setEditingId] = useState<number | null>(null);
16
+ const [editText, setEditText] = useState('');
17
+ const addInputRef = useRef<HTMLInputElement>(null);
18
+
19
+ useEffect(() => {
20
+ if (workspaceId == null) { setTodos([]); return; }
21
+ let cancelled = false;
22
+ fetch(api(`/api/workspaces/${workspaceId}/todos`))
23
+ .then(r => r.json())
24
+ .then((data: WorkspaceTodo[]) => { if (!cancelled) setTodos(Array.isArray(data) ? data : []); })
25
+ .catch(() => { if (!cancelled) setTodos([]); });
26
+ return () => { cancelled = true; };
27
+ }, [workspaceId]);
28
+
29
+ const addTodo = useCallback(async () => {
30
+ const text = addInput.trim();
31
+ if (!text || workspaceId == null) { setAddInput(''); setAdding(false); return; }
32
+
33
+ const tempId = -Date.now();
34
+ const temp: WorkspaceTodo = {
35
+ id: tempId,
36
+ workspaceId,
37
+ text,
38
+ completed: false,
39
+ sortOrder: Number.MAX_SAFE_INTEGER,
40
+ created: new Date().toISOString(),
41
+ completedAt: null,
42
+ };
43
+ setTodos(prev => [...prev, temp]);
44
+ setAddInput('');
45
+ addInputRef.current?.focus();
46
+
47
+ try {
48
+ const res = await fetch(api(`/api/workspaces/${workspaceId}/todos`), {
49
+ method: 'POST',
50
+ headers: { 'Content-Type': 'application/json' },
51
+ body: JSON.stringify({ text }),
52
+ });
53
+ if (!res.ok) throw new Error(await res.text());
54
+ const real: WorkspaceTodo = await res.json();
55
+ setTodos(prev => prev.map(t => t.id === tempId ? real : t));
56
+ } catch (err) {
57
+ console.error('failed to add todo', err);
58
+ setTodos(prev => prev.filter(t => t.id !== tempId));
59
+ }
60
+ }, [addInput, workspaceId]);
61
+
62
+ const toggleTodo = useCallback(async (todo: WorkspaceTodo) => {
63
+ if (workspaceId == null) return;
64
+ const next = !todo.completed;
65
+ setTodos(prev => prev.map(t => t.id === todo.id
66
+ ? { ...t, completed: next, completedAt: next ? new Date().toISOString() : null }
67
+ : t
68
+ ));
69
+ try {
70
+ const res = await fetch(api(`/api/workspaces/${workspaceId}/todos/${todo.id}`), {
71
+ method: 'PATCH',
72
+ headers: { 'Content-Type': 'application/json' },
73
+ body: JSON.stringify({ completed: next }),
74
+ });
75
+ if (!res.ok) throw new Error();
76
+ const real: WorkspaceTodo = await res.json();
77
+ setTodos(prev => prev.map(t => t.id === todo.id ? real : t));
78
+ } catch {
79
+ setTodos(prev => prev.map(t => t.id === todo.id ? todo : t));
80
+ }
81
+ }, [workspaceId]);
82
+
83
+ const deleteTodo = useCallback(async (todo: WorkspaceTodo) => {
84
+ if (workspaceId == null) return;
85
+ // Snapshot the original index so we can restore in place on failure,
86
+ // rather than appending to the end.
87
+ let originalIndex = -1;
88
+ setTodos(prev => {
89
+ originalIndex = prev.findIndex(t => t.id === todo.id);
90
+ return prev.filter(t => t.id !== todo.id);
91
+ });
92
+ try {
93
+ const res = await fetch(api(`/api/workspaces/${workspaceId}/todos/${todo.id}`), { method: 'DELETE' });
94
+ if (!res.ok) throw new Error();
95
+ } catch {
96
+ setTodos(prev => {
97
+ if (originalIndex < 0 || prev.some(t => t.id === todo.id)) return prev;
98
+ const next = [...prev];
99
+ next.splice(Math.min(originalIndex, next.length), 0, todo);
100
+ return next;
101
+ });
102
+ }
103
+ }, [workspaceId]);
104
+
105
+ const saveEdit = useCallback(async (todo: WorkspaceTodo) => {
106
+ const text = editText.trim();
107
+ setEditingId(null);
108
+ if (!text || text === todo.text || workspaceId == null) return;
109
+ setTodos(prev => prev.map(t => t.id === todo.id ? { ...t, text } : t));
110
+ try {
111
+ const res = await fetch(api(`/api/workspaces/${workspaceId}/todos/${todo.id}`), {
112
+ method: 'PATCH',
113
+ headers: { 'Content-Type': 'application/json' },
114
+ body: JSON.stringify({ text }),
115
+ });
116
+ if (!res.ok) throw new Error();
117
+ } catch {
118
+ setTodos(prev => prev.map(t => t.id === todo.id ? { ...t, text: todo.text } : t));
119
+ }
120
+ }, [editText, workspaceId]);
121
+
122
+ const clearCompleted = useCallback(async () => {
123
+ if (workspaceId == null) return;
124
+ const done = todos.filter(t => t.completed);
125
+ if (done.length === 0) return;
126
+ setTodos(prev => prev.filter(t => !t.completed));
127
+ const results = await Promise.allSettled(
128
+ done.map(t => fetch(api(`/api/workspaces/${workspaceId}/todos/${t.id}`), { method: 'DELETE' }))
129
+ );
130
+ if (results.some(r => r.status === 'rejected' || (r.status === 'fulfilled' && !r.value.ok))) {
131
+ // Reconcile by refetching
132
+ fetch(api(`/api/workspaces/${workspaceId}/todos`))
133
+ .then(r => r.json())
134
+ .then((data: WorkspaceTodo[]) => setTodos(Array.isArray(data) ? data : []))
135
+ .catch(() => {});
136
+ }
137
+ }, [todos, workspaceId]);
138
+
139
+ const sorted = [...todos].sort((a, b) => {
140
+ if (a.completed !== b.completed) return a.completed ? 1 : -1;
141
+ if (!a.completed) return a.sortOrder - b.sortOrder;
142
+ const aT = a.completedAt ?? '';
143
+ const bT = b.completedAt ?? '';
144
+ return bT.localeCompare(aT);
145
+ });
146
+ const completedCount = sorted.filter(t => t.completed).length;
147
+
148
+ const chipHeight = 'h-7';
149
+ const chipShape = `${chipHeight} rounded-full inline-flex items-center gap-1.5 pl-2 pr-1 py-1 text-xs border whitespace-nowrap`;
150
+
151
+ return (
152
+ <div className="border-b border-zinc-800 bg-zinc-900/40 px-4 py-2 flex-shrink-0">
153
+ <div className="flex flex-wrap items-center gap-1.5 max-h-[30vh] overflow-y-auto">
154
+ {sorted.map(todo => {
155
+ const isEditing = editingId === todo.id;
156
+ const activeStyle = {
157
+ backgroundColor: `${color}22`,
158
+ borderColor: `${color}66`,
159
+ color: color,
160
+ };
161
+ const doneStyle = {
162
+ backgroundColor: 'rgba(39, 39, 42, 0.5)',
163
+ borderColor: 'rgba(63, 63, 70, 0.5)',
164
+ color: 'rgb(113, 113, 122)',
165
+ };
166
+ const style = todo.completed ? doneStyle : activeStyle;
167
+
168
+ return (
169
+ <div
170
+ key={todo.id}
171
+ className={`group ${chipShape}`}
172
+ style={style}
173
+ >
174
+ <button
175
+ onClick={() => toggleTodo(todo)}
176
+ className="w-3.5 h-3.5 rounded-full border-2 flex items-center justify-center flex-shrink-0 transition-colors"
177
+ style={{
178
+ borderColor: todo.completed ? color : `${color}aa`,
179
+ backgroundColor: todo.completed ? color : 'transparent',
180
+ }}
181
+ aria-label={todo.completed ? 'Mark incomplete' : 'Mark complete'}
182
+ >
183
+ {todo.completed && <Check className="w-2.5 h-2.5 text-white" />}
184
+ </button>
185
+
186
+ {isEditing ? (
187
+ <input
188
+ autoFocus
189
+ value={editText}
190
+ onChange={e => setEditText(e.target.value)}
191
+ onBlur={() => saveEdit(todo)}
192
+ onKeyDown={e => {
193
+ if (e.key === 'Enter') saveEdit(todo);
194
+ if (e.key === 'Escape') setEditingId(null);
195
+ }}
196
+ className="bg-transparent focus:outline-none max-w-[240px]"
197
+ style={{ color: 'inherit' }}
198
+ />
199
+ ) : (
200
+ <button
201
+ onClick={() => { setEditingId(todo.id); setEditText(todo.text); }}
202
+ className={`text-left truncate max-w-[200px] ${todo.completed ? 'line-through' : ''}`}
203
+ style={{ color: 'inherit' }}
204
+ >
205
+ {todo.text}
206
+ </button>
207
+ )}
208
+
209
+ <button
210
+ onClick={() => deleteTodo(todo)}
211
+ className="opacity-0 group-hover:opacity-100 transition-opacity rounded-full p-0.5 hover:bg-black/20 flex-shrink-0"
212
+ style={{ color: 'inherit' }}
213
+ aria-label="Delete todo"
214
+ >
215
+ <X className="w-3 h-3" />
216
+ </button>
217
+ </div>
218
+ );
219
+ })}
220
+
221
+ {/* Add chip */}
222
+ {adding ? (
223
+ <div className={`${chipShape} border-dashed border-zinc-600 text-zinc-300`}>
224
+ <Plus className="w-3 h-3 text-zinc-500 flex-shrink-0" />
225
+ <input
226
+ ref={addInputRef}
227
+ autoFocus
228
+ value={addInput}
229
+ onChange={e => setAddInput(e.target.value)}
230
+ onKeyDown={e => {
231
+ if (e.key === 'Enter') addTodo();
232
+ if (e.key === 'Escape') { setAddInput(''); setAdding(false); }
233
+ }}
234
+ onBlur={() => {
235
+ if (addInput.trim()) addTodo();
236
+ else setAdding(false);
237
+ }}
238
+ placeholder="todo…"
239
+ className="bg-transparent focus:outline-none text-xs placeholder:text-zinc-600 max-w-[200px]"
240
+ />
241
+ </div>
242
+ ) : (
243
+ <button
244
+ onClick={() => { if (workspaceId != null) setAdding(true); }}
245
+ disabled={workspaceId == null}
246
+ className={`${chipHeight} rounded-full inline-flex items-center gap-1 px-3 py-1 text-xs border border-dashed border-zinc-700 text-zinc-500 hover:text-zinc-300 hover:border-zinc-500 transition-colors disabled:opacity-50 disabled:cursor-not-allowed whitespace-nowrap`}
247
+ >
248
+ <Plus className="w-3 h-3" />
249
+ {workspaceId == null ? 'Select a workspace' : 'add todo'}
250
+ </button>
251
+ )}
252
+
253
+ {/* Clear completed */}
254
+ {completedCount > 0 && (
255
+ <button
256
+ onClick={clearCompleted}
257
+ className="ml-auto text-[10px] text-zinc-500 hover:text-zinc-300 px-2 py-1 transition-colors whitespace-nowrap"
258
+ >
259
+ clear {completedCount} done
260
+ </button>
261
+ )}
262
+ </div>
263
+ </div>
264
+ );
265
+ }
@@ -0,0 +1,66 @@
1
+ 'use client';
2
+
3
+ import { useEffect, useRef, useState } from 'react';
4
+ import { api } from '@/lib/api';
5
+ import type { UsageResponse } from '@/types/claude';
6
+
7
+ const POLL_INTERVAL_MS = 60_000;
8
+ const TRANSIENT_TOLERANCE = 2; // consecutive bad polls before we clobber good data
9
+
10
+ export function useClaudeUsage(enabled: boolean): UsageResponse | null {
11
+ const [response, setResponse] = useState<UsageResponse | null>(null);
12
+ const badPollsRef = useRef(0);
13
+
14
+ useEffect(() => {
15
+ if (!enabled) {
16
+ badPollsRef.current = 0;
17
+ return;
18
+ }
19
+
20
+ let cancelled = false;
21
+
22
+ async function load() {
23
+ try {
24
+ const res = await fetch(api('/api/claude/usage'));
25
+ if (!res.ok || cancelled) return;
26
+ const data: UsageResponse = await res.json();
27
+ if (cancelled) return;
28
+
29
+ const isTransient = data.status === 'upstream_error' || data.status === 'expired';
30
+ if (isTransient) {
31
+ badPollsRef.current += 1;
32
+ setResponse(prev => {
33
+ // If we already have a good response, keep it until the bad state persists.
34
+ if (prev?.status === 'ok' && badPollsRef.current < TRANSIENT_TOLERANCE) {
35
+ return prev;
36
+ }
37
+ return data;
38
+ });
39
+ } else {
40
+ badPollsRef.current = 0;
41
+ setResponse(data);
42
+ }
43
+ } catch {
44
+ // Network error — treat as transient.
45
+ if (cancelled) return;
46
+ badPollsRef.current += 1;
47
+ setResponse(prev => {
48
+ if (prev?.status === 'ok' && badPollsRef.current < TRANSIENT_TOLERANCE) {
49
+ return prev;
50
+ }
51
+ return { status: 'upstream_error' };
52
+ });
53
+ }
54
+ }
55
+
56
+ load();
57
+ const timer = setInterval(load, POLL_INTERVAL_MS);
58
+
59
+ return () => {
60
+ cancelled = true;
61
+ clearInterval(timer);
62
+ };
63
+ }, [enabled]);
64
+
65
+ return response;
66
+ }
@@ -0,0 +1,36 @@
1
+ import path from 'path';
2
+ import os from 'os';
3
+ import { readFile } from 'fs/promises';
4
+
5
+ export interface ClaudeAiOAuthTokens {
6
+ accessToken: string;
7
+ refreshToken: string | null;
8
+ expiresAt: number | null; // epoch ms
9
+ scopes?: string[];
10
+ }
11
+
12
+ function getCredentialsPath(): string {
13
+ const home = process.env.CLAUDE_CONFIG_DIR || path.join(os.homedir(), '.claude');
14
+ return path.join(home, '.credentials.json');
15
+ }
16
+
17
+ /**
18
+ * Reads ~/.claude/.credentials.json and returns the claudeAiOauth block.
19
+ * Returns null on any read/parse failure or if the block is absent.
20
+ */
21
+ export async function readClaudeAiOauthTokens(): Promise<ClaudeAiOAuthTokens | null> {
22
+ try {
23
+ const raw = await readFile(getCredentialsPath(), 'utf8');
24
+ const parsed = JSON.parse(raw) as { claudeAiOauth?: ClaudeAiOAuthTokens };
25
+ const tokens = parsed.claudeAiOauth;
26
+ if (!tokens?.accessToken) return null;
27
+ return tokens;
28
+ } catch {
29
+ return null;
30
+ }
31
+ }
32
+
33
+ export function isTokenExpired(tokens: ClaudeAiOAuthTokens, nowMs = Date.now()): boolean {
34
+ if (!tokens.expiresAt) return false; // no expiry set → treat as valid
35
+ return nowMs >= tokens.expiresAt;
36
+ }
@@ -0,0 +1,69 @@
1
+ import { createHash } from 'crypto';
2
+ import type { Utilization } from '@/types/claude';
3
+
4
+ const ANTHROPIC_USAGE_URL = 'https://api.anthropic.com/api/oauth/usage';
5
+ const REQUEST_TIMEOUT_MS = 5_000;
6
+ const CACHE_TTL_MS = 30_000;
7
+
8
+ // UA + anthropic-beta header match Claude Code's. The endpoint requires the
9
+ // beta header; see claude-code/src/utils/http.ts (getAuthHeaders) and
10
+ // claude-code/src/constants/oauth.ts (OAUTH_BETA_HEADER).
11
+ const USER_AGENT = 'claude-code/spaces';
12
+ const OAUTH_BETA_HEADER = 'oauth-2025-04-20';
13
+
14
+ interface CacheEntry {
15
+ fetchedAt: number;
16
+ data: Utilization;
17
+ }
18
+
19
+ const cache = new Map<string, CacheEntry>();
20
+
21
+ function cacheKey(accessToken: string): string {
22
+ // Full SHA-256 of the token so two tokens sharing a prefix cannot collide.
23
+ return createHash('sha256').update(accessToken).digest('hex');
24
+ }
25
+
26
+ export type FetchOutcome =
27
+ | { ok: true; data: Utilization }
28
+ | { ok: false; reason: 'upstream_error' };
29
+
30
+ export async function fetchUtilization(accessToken: string): Promise<FetchOutcome> {
31
+ const key = cacheKey(accessToken);
32
+ const cached = cache.get(key);
33
+ if (cached && Date.now() - cached.fetchedAt < CACHE_TTL_MS) {
34
+ return { ok: true, data: cached.data };
35
+ }
36
+
37
+ const controller = new AbortController();
38
+ const timer = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
39
+
40
+ try {
41
+ const res = await fetch(ANTHROPIC_USAGE_URL, {
42
+ method: 'GET',
43
+ headers: {
44
+ 'Authorization': `Bearer ${accessToken}`,
45
+ 'anthropic-beta': OAUTH_BETA_HEADER,
46
+ 'Content-Type': 'application/json',
47
+ 'User-Agent': USER_AGENT,
48
+ },
49
+ signal: controller.signal,
50
+ });
51
+
52
+ if (!res.ok) {
53
+ return { ok: false, reason: 'upstream_error' };
54
+ }
55
+
56
+ const data = (await res.json()) as Utilization;
57
+ cache.set(key, { fetchedAt: Date.now(), data });
58
+ return { ok: true, data };
59
+ } catch {
60
+ return { ok: false, reason: 'upstream_error' };
61
+ } finally {
62
+ clearTimeout(timer);
63
+ }
64
+ }
65
+
66
+ /** Testing/hot-reload helper. */
67
+ export function __clearUsageCache() {
68
+ cache.clear();
69
+ }
@@ -90,6 +90,7 @@ export interface SpacesConfig {
90
90
  installId: string;
91
91
  telemetryOptOut: boolean;
92
92
  devDirectories: string[];
93
+ todosEnabled: boolean;
93
94
  cortex?: CortexConfig;
94
95
  customModels?: CustomModelConfig[];
95
96
  }
@@ -103,6 +104,7 @@ export function readConfig(username: string): SpacesConfig {
103
104
  installId: raw.installId || crypto.randomUUID(),
104
105
  telemetryOptOut: !!raw.telemetryOptOut,
105
106
  devDirectories: Array.isArray(raw.devDirectories) ? raw.devDirectories.filter((d: unknown) => typeof d === 'string') : [],
107
+ todosEnabled: !!raw.todosEnabled,
106
108
  ...(raw.cortex && typeof raw.cortex === 'object' ? { cortex: raw.cortex } : {}),
107
109
  customModels: Array.isArray(raw.customModels) ? raw.customModels : [],
108
110
  };
@@ -117,6 +119,7 @@ export function readConfig(username: string): SpacesConfig {
117
119
  installId: crypto.randomUUID(),
118
120
  telemetryOptOut: false,
119
121
  devDirectories: [],
122
+ todosEnabled: false,
120
123
  customModels: [],
121
124
  };
122
125
  fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
@@ -1,6 +1,6 @@
1
1
  import crypto from 'crypto';
2
2
  import { getDb } from './schema';
3
- import type { SessionWithMeta, Project, Workspace, Tag, SearchResult } from '@/types/claude';
3
+ import type { SessionWithMeta, Project, Workspace, Tag, SearchResult, WorkspaceTodo } from '@/types/claude';
4
4
 
5
5
  // ─── Projects ───────────────────────────────────────────────
6
6
 
@@ -738,3 +738,105 @@ export function getDailyActivity(days = 30): { date: string; sessionCount: numbe
738
738
  `).all(`-${days} days`) as any[];
739
739
  }
740
740
 
741
+ // ─── Workspace Todos ───────────────────────────────────────
742
+
743
+ interface TodoRow {
744
+ id: number;
745
+ workspace_id: number;
746
+ text: string;
747
+ completed: number;
748
+ sort_order: number;
749
+ created: string;
750
+ completed_at: string | null;
751
+ }
752
+
753
+ function rowToTodo(r: TodoRow): WorkspaceTodo {
754
+ return {
755
+ id: r.id,
756
+ workspaceId: r.workspace_id,
757
+ text: r.text,
758
+ completed: !!r.completed,
759
+ sortOrder: r.sort_order,
760
+ created: r.created,
761
+ completedAt: r.completed_at,
762
+ };
763
+ }
764
+
765
+ export function getWorkspaceTodos(workspaceId: number): WorkspaceTodo[] {
766
+ const db = getDb();
767
+ const rows = db.prepare(`
768
+ SELECT id, workspace_id, text, completed, sort_order, created, completed_at
769
+ FROM workspace_todos
770
+ WHERE workspace_id = ?
771
+ ORDER BY completed ASC,
772
+ CASE WHEN completed = 0 THEN sort_order END ASC,
773
+ completed_at DESC
774
+ `).all(workspaceId) as TodoRow[];
775
+ return rows.map(rowToTodo);
776
+ }
777
+
778
+ export function addWorkspaceTodo(workspaceId: number, text: string): WorkspaceTodo {
779
+ const db = getDb();
780
+ const trimmed = text.trim();
781
+ if (!trimmed) throw new Error('todo text is required');
782
+
783
+ const maxRow = db.prepare(`
784
+ SELECT COALESCE(MAX(sort_order), -1) AS max_order
785
+ FROM workspace_todos
786
+ WHERE workspace_id = ? AND completed = 0
787
+ `).get(workspaceId) as { max_order: number };
788
+ const nextOrder = (maxRow?.max_order ?? -1) + 1;
789
+
790
+ const info = db.prepare(`
791
+ INSERT INTO workspace_todos (workspace_id, text, sort_order)
792
+ VALUES (?, ?, ?)
793
+ `).run(workspaceId, trimmed, nextOrder);
794
+
795
+ const row = db.prepare(`
796
+ SELECT id, workspace_id, text, completed, sort_order, created, completed_at
797
+ FROM workspace_todos WHERE id = ?
798
+ `).get(Number(info.lastInsertRowid)) as TodoRow;
799
+ return rowToTodo(row);
800
+ }
801
+
802
+ export function updateWorkspaceTodo(
803
+ workspaceId: number,
804
+ todoId: number,
805
+ data: { text?: string; completed?: boolean }
806
+ ): WorkspaceTodo | null {
807
+ const db = getDb();
808
+
809
+ if (data.text !== undefined) {
810
+ const trimmed = data.text.trim();
811
+ if (!trimmed) throw new Error('todo text cannot be empty');
812
+ db.prepare('UPDATE workspace_todos SET text = ? WHERE id = ? AND workspace_id = ?').run(trimmed, todoId, workspaceId);
813
+ }
814
+
815
+ if (data.completed !== undefined) {
816
+ if (data.completed) {
817
+ db.prepare(`
818
+ UPDATE workspace_todos
819
+ SET completed = 1, completed_at = datetime('now')
820
+ WHERE id = ? AND workspace_id = ?
821
+ `).run(todoId, workspaceId);
822
+ } else {
823
+ db.prepare(`
824
+ UPDATE workspace_todos
825
+ SET completed = 0, completed_at = NULL
826
+ WHERE id = ? AND workspace_id = ?
827
+ `).run(todoId, workspaceId);
828
+ }
829
+ }
830
+
831
+ const row = db.prepare(`
832
+ SELECT id, workspace_id, text, completed, sort_order, created, completed_at
833
+ FROM workspace_todos WHERE id = ? AND workspace_id = ?
834
+ `).get(todoId, workspaceId) as TodoRow | undefined;
835
+ return row ? rowToTodo(row) : null;
836
+ }
837
+
838
+ export function deleteWorkspaceTodo(workspaceId: number, todoId: number): void {
839
+ const db = getDb();
840
+ db.prepare('DELETE FROM workspace_todos WHERE id = ? AND workspace_id = ?').run(todoId, workspaceId);
841
+ }
842
+
@@ -113,6 +113,19 @@ function initSchema(db: Database.Database) {
113
113
  enabled INTEGER DEFAULT 0,
114
114
  created TEXT DEFAULT (datetime('now'))
115
115
  );
116
+
117
+ CREATE TABLE IF NOT EXISTS workspace_todos (
118
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
119
+ workspace_id INTEGER NOT NULL REFERENCES workspaces(id) ON DELETE CASCADE,
120
+ text TEXT NOT NULL,
121
+ completed INTEGER NOT NULL DEFAULT 0,
122
+ sort_order INTEGER NOT NULL DEFAULT 0,
123
+ created TEXT NOT NULL DEFAULT (datetime('now')),
124
+ completed_at TEXT
125
+ );
126
+
127
+ CREATE INDEX IF NOT EXISTS idx_workspace_todos_workspace
128
+ ON workspace_todos(workspace_id);
116
129
  `);
117
130
 
118
131
  // Migrate: add workspace and popout columns to existing tables
@@ -204,3 +217,8 @@ export function closeDb() {
204
217
  }
205
218
  _dbs.clear();
206
219
  }
220
+
221
+ // Test-only export. Do not use outside of tests.
222
+ export const __testing = {
223
+ dbs: _dbs,
224
+ };
@@ -0,0 +1,32 @@
1
+ // Build a minimal, safe environment for child processes that execute user-controlled
2
+ // code (PTY shells, `claude` CLI, etc). The server's own env contains secrets —
3
+ // SPACES_SESSION_SECRET, GH_PAT, NPM_TOKEN, ANTHROPIC_API_KEY — and any of those
4
+ // leaking into a user PTY would let the user forge sessions or impersonate the
5
+ // server against upstream services.
6
+
7
+ const ALLOWED_ENV_VARS = new Set([
8
+ // Identity / shell basics
9
+ 'HOME', 'USER', 'LOGNAME', 'SHELL', 'PATH', 'PWD', 'OLDPWD', 'HOSTNAME',
10
+ // Locale / time
11
+ 'LANG', 'LC_ALL', 'LC_CTYPE', 'LC_MESSAGES', 'LC_COLLATE', 'LC_TIME',
12
+ 'LC_NUMERIC', 'LC_MONETARY', 'TZ',
13
+ // XDG base dirs
14
+ 'XDG_CONFIG_HOME', 'XDG_DATA_HOME', 'XDG_CACHE_HOME', 'XDG_RUNTIME_DIR',
15
+ 'XDG_STATE_HOME',
16
+ // Terminal / display
17
+ 'TERM', 'TERM_PROGRAM', 'TERM_PROGRAM_VERSION', 'COLORTERM', 'COLUMNS', 'LINES',
18
+ // Node / package manager tooling child tools may need
19
+ 'NODE_ENV', 'NVM_DIR', 'NVM_BIN',
20
+ ]);
21
+
22
+ export function buildSpawnEnv(extras: Record<string, string | undefined> = {}): NodeJS.ProcessEnv {
23
+ const env: Record<string, string> = {};
24
+ for (const key of ALLOWED_ENV_VARS) {
25
+ const v = process.env[key];
26
+ if (v !== undefined) env[key] = v;
27
+ }
28
+ for (const [k, v] of Object.entries(extras)) {
29
+ if (v !== undefined) env[k] = v;
30
+ }
31
+ return env as unknown as NodeJS.ProcessEnv;
32
+ }
@@ -3,6 +3,7 @@ import * as pty from 'node-pty';
3
3
  import { IncomingMessage } from 'http';
4
4
  import crypto from 'crypto';
5
5
  import { AGENT_TYPES } from '../agents';
6
+ import { buildSpawnEnv } from '../spawn-env';
6
7
 
7
8
  interface TermSession {
8
9
  pty: pty.IPty;
@@ -83,9 +84,8 @@ export function startTerminalServer(port = 3458) {
83
84
  const shell = isWindows ? 'cmd.exe' : (process.env.SHELL || '/bin/bash');
84
85
  const agent = AGENT_TYPES[agentType];
85
86
 
86
- // Strip CLAUDECODE to avoid nesting detection
87
- const env = { ...process.env } as Record<string, string>;
88
- delete env.CLAUDECODE;
87
+ // Build a minimal, non-secret-bearing env for the user-facing PTY.
88
+ const env = buildSpawnEnv() as Record<string, string>;
89
89
 
90
90
  if (customModelId) {
91
91
  const port = process.env.SPACES_PORT || '3457';