@jlongo78/agent-spaces 0.9.8 → 0.9.9

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 (356) 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/claude/usage/route/app-paths-manifest.json +3 -0
  68. package/.next/standalone/.next/server/app/api/claude/usage/route/build-manifest.json +11 -0
  69. package/.next/standalone/.next/server/app/api/claude/usage/route/server-reference-manifest.json +4 -0
  70. package/.next/standalone/.next/server/app/api/claude/usage/route.js +8 -0
  71. package/.next/standalone/.next/server/app/api/claude/usage/route.js.map +5 -0
  72. package/.next/standalone/.next/server/app/api/claude/usage/route.js.nft.json +1 -0
  73. package/.next/standalone/.next/server/app/api/claude/usage/route_client-reference-manifest.js +2 -0
  74. package/.next/standalone/.next/server/app/api/whisper/route.js.nft.json +1 -1
  75. package/.next/standalone/.next/server/app/api/workspaces/[id]/todos/[todoId]/route/app-paths-manifest.json +3 -0
  76. package/.next/standalone/.next/server/app/api/workspaces/[id]/todos/[todoId]/route/build-manifest.json +11 -0
  77. package/.next/standalone/.next/server/app/api/workspaces/[id]/todos/[todoId]/route/server-reference-manifest.json +4 -0
  78. package/.next/standalone/.next/server/app/api/workspaces/[id]/todos/[todoId]/route.js +8 -0
  79. package/.next/standalone/.next/server/app/api/workspaces/[id]/todos/[todoId]/route.js.map +5 -0
  80. package/.next/standalone/.next/server/app/api/workspaces/[id]/todos/[todoId]/route.js.nft.json +1 -0
  81. package/.next/standalone/.next/server/app/api/workspaces/[id]/todos/[todoId]/route_client-reference-manifest.js +2 -0
  82. package/.next/standalone/.next/server/app/api/workspaces/[id]/todos/route/app-paths-manifest.json +3 -0
  83. package/.next/standalone/.next/server/app/api/workspaces/[id]/todos/route/build-manifest.json +11 -0
  84. package/.next/standalone/.next/server/app/api/workspaces/[id]/todos/route/server-reference-manifest.json +4 -0
  85. package/.next/standalone/.next/server/app/api/workspaces/[id]/todos/route.js +8 -0
  86. package/.next/standalone/.next/server/app/api/workspaces/[id]/todos/route.js.map +5 -0
  87. package/.next/standalone/.next/server/app/api/workspaces/[id]/todos/route.js.nft.json +1 -0
  88. package/.next/standalone/.next/server/app/api/workspaces/[id]/todos/route_client-reference-manifest.js +2 -0
  89. package/.next/standalone/.next/server/app/cortex.html +1 -1
  90. package/.next/standalone/.next/server/app/cortex.rsc +2 -2
  91. package/.next/standalone/.next/server/app/cortex.segments/!KGRlc2t0b3Ap/cortex/__PAGE__.segment.rsc +1 -1
  92. package/.next/standalone/.next/server/app/cortex.segments/!KGRlc2t0b3Ap/cortex.segment.rsc +1 -1
  93. package/.next/standalone/.next/server/app/cortex.segments/!KGRlc2t0b3Ap.segment.rsc +1 -1
  94. package/.next/standalone/.next/server/app/cortex.segments/_full.segment.rsc +2 -2
  95. package/.next/standalone/.next/server/app/cortex.segments/_head.segment.rsc +1 -1
  96. package/.next/standalone/.next/server/app/cortex.segments/_index.segment.rsc +2 -2
  97. package/.next/standalone/.next/server/app/cortex.segments/_tree.segment.rsc +2 -2
  98. package/.next/standalone/.next/server/app/login/page_client-reference-manifest.js +1 -1
  99. package/.next/standalone/.next/server/app/login.html +1 -1
  100. package/.next/standalone/.next/server/app/login.rsc +2 -2
  101. package/.next/standalone/.next/server/app/login.segments/_full.segment.rsc +2 -2
  102. package/.next/standalone/.next/server/app/login.segments/_head.segment.rsc +1 -1
  103. package/.next/standalone/.next/server/app/login.segments/_index.segment.rsc +2 -2
  104. package/.next/standalone/.next/server/app/login.segments/_tree.segment.rsc +2 -2
  105. package/.next/standalone/.next/server/app/login.segments/login/__PAGE__.segment.rsc +1 -1
  106. package/.next/standalone/.next/server/app/login.segments/login.segment.rsc +1 -1
  107. package/.next/standalone/.next/server/app/m/page_client-reference-manifest.js +1 -1
  108. package/.next/standalone/.next/server/app/m/projects/page_client-reference-manifest.js +1 -1
  109. package/.next/standalone/.next/server/app/m/projects.html +1 -1
  110. package/.next/standalone/.next/server/app/m/projects.rsc +2 -2
  111. package/.next/standalone/.next/server/app/m/projects.segments/_full.segment.rsc +2 -2
  112. package/.next/standalone/.next/server/app/m/projects.segments/_head.segment.rsc +1 -1
  113. package/.next/standalone/.next/server/app/m/projects.segments/_index.segment.rsc +2 -2
  114. package/.next/standalone/.next/server/app/m/projects.segments/_tree.segment.rsc +2 -2
  115. package/.next/standalone/.next/server/app/m/projects.segments/m/projects/__PAGE__.segment.rsc +1 -1
  116. package/.next/standalone/.next/server/app/m/projects.segments/m/projects.segment.rsc +1 -1
  117. package/.next/standalone/.next/server/app/m/projects.segments/m.segment.rsc +1 -1
  118. package/.next/standalone/.next/server/app/m/sessions/[id]/page_client-reference-manifest.js +1 -1
  119. package/.next/standalone/.next/server/app/m/sessions/page_client-reference-manifest.js +1 -1
  120. package/.next/standalone/.next/server/app/m/sessions.html +1 -1
  121. package/.next/standalone/.next/server/app/m/sessions.rsc +2 -2
  122. package/.next/standalone/.next/server/app/m/sessions.segments/_full.segment.rsc +2 -2
  123. package/.next/standalone/.next/server/app/m/sessions.segments/_head.segment.rsc +1 -1
  124. package/.next/standalone/.next/server/app/m/sessions.segments/_index.segment.rsc +2 -2
  125. package/.next/standalone/.next/server/app/m/sessions.segments/_tree.segment.rsc +2 -2
  126. package/.next/standalone/.next/server/app/m/sessions.segments/m/sessions/__PAGE__.segment.rsc +1 -1
  127. package/.next/standalone/.next/server/app/m/sessions.segments/m/sessions.segment.rsc +1 -1
  128. package/.next/standalone/.next/server/app/m/sessions.segments/m.segment.rsc +1 -1
  129. package/.next/standalone/.next/server/app/m/settings/page_client-reference-manifest.js +1 -1
  130. package/.next/standalone/.next/server/app/m/settings.html +1 -1
  131. package/.next/standalone/.next/server/app/m/settings.rsc +2 -2
  132. package/.next/standalone/.next/server/app/m/settings.segments/_full.segment.rsc +2 -2
  133. package/.next/standalone/.next/server/app/m/settings.segments/_head.segment.rsc +1 -1
  134. package/.next/standalone/.next/server/app/m/settings.segments/_index.segment.rsc +2 -2
  135. package/.next/standalone/.next/server/app/m/settings.segments/_tree.segment.rsc +2 -2
  136. package/.next/standalone/.next/server/app/m/settings.segments/m/settings/__PAGE__.segment.rsc +1 -1
  137. package/.next/standalone/.next/server/app/m/settings.segments/m/settings.segment.rsc +1 -1
  138. package/.next/standalone/.next/server/app/m/settings.segments/m.segment.rsc +1 -1
  139. package/.next/standalone/.next/server/app/m/terminal/page_client-reference-manifest.js +1 -1
  140. package/.next/standalone/.next/server/app/m/terminal.html +1 -1
  141. package/.next/standalone/.next/server/app/m/terminal.rsc +2 -2
  142. package/.next/standalone/.next/server/app/m/terminal.segments/_full.segment.rsc +2 -2
  143. package/.next/standalone/.next/server/app/m/terminal.segments/_head.segment.rsc +1 -1
  144. package/.next/standalone/.next/server/app/m/terminal.segments/_index.segment.rsc +2 -2
  145. package/.next/standalone/.next/server/app/m/terminal.segments/_tree.segment.rsc +2 -2
  146. package/.next/standalone/.next/server/app/m/terminal.segments/m/terminal/__PAGE__.segment.rsc +1 -1
  147. package/.next/standalone/.next/server/app/m/terminal.segments/m/terminal.segment.rsc +1 -1
  148. package/.next/standalone/.next/server/app/m/terminal.segments/m.segment.rsc +1 -1
  149. package/.next/standalone/.next/server/app/m.html +1 -1
  150. package/.next/standalone/.next/server/app/m.rsc +2 -2
  151. package/.next/standalone/.next/server/app/m.segments/_full.segment.rsc +2 -2
  152. package/.next/standalone/.next/server/app/m.segments/_head.segment.rsc +1 -1
  153. package/.next/standalone/.next/server/app/m.segments/_index.segment.rsc +2 -2
  154. package/.next/standalone/.next/server/app/m.segments/_tree.segment.rsc +2 -2
  155. package/.next/standalone/.next/server/app/m.segments/m/__PAGE__.segment.rsc +1 -1
  156. package/.next/standalone/.next/server/app/m.segments/m.segment.rsc +1 -1
  157. package/.next/standalone/.next/server/app/network.html +1 -1
  158. package/.next/standalone/.next/server/app/network.rsc +2 -2
  159. package/.next/standalone/.next/server/app/network.segments/!KGRlc2t0b3Ap/network/__PAGE__.segment.rsc +1 -1
  160. package/.next/standalone/.next/server/app/network.segments/!KGRlc2t0b3Ap/network.segment.rsc +1 -1
  161. package/.next/standalone/.next/server/app/network.segments/!KGRlc2t0b3Ap.segment.rsc +1 -1
  162. package/.next/standalone/.next/server/app/network.segments/_full.segment.rsc +2 -2
  163. package/.next/standalone/.next/server/app/network.segments/_head.segment.rsc +1 -1
  164. package/.next/standalone/.next/server/app/network.segments/_index.segment.rsc +2 -2
  165. package/.next/standalone/.next/server/app/network.segments/_tree.segment.rsc +2 -2
  166. package/.next/standalone/.next/server/app/projects.html +1 -1
  167. package/.next/standalone/.next/server/app/projects.rsc +2 -2
  168. package/.next/standalone/.next/server/app/projects.segments/!KGRlc2t0b3Ap/projects/__PAGE__.segment.rsc +1 -1
  169. package/.next/standalone/.next/server/app/projects.segments/!KGRlc2t0b3Ap/projects.segment.rsc +1 -1
  170. package/.next/standalone/.next/server/app/projects.segments/!KGRlc2t0b3Ap.segment.rsc +1 -1
  171. package/.next/standalone/.next/server/app/projects.segments/_full.segment.rsc +2 -2
  172. package/.next/standalone/.next/server/app/projects.segments/_head.segment.rsc +1 -1
  173. package/.next/standalone/.next/server/app/projects.segments/_index.segment.rsc +2 -2
  174. package/.next/standalone/.next/server/app/projects.segments/_tree.segment.rsc +2 -2
  175. package/.next/standalone/.next/server/app/sessions.html +1 -1
  176. package/.next/standalone/.next/server/app/sessions.rsc +2 -2
  177. package/.next/standalone/.next/server/app/sessions.segments/!KGRlc2t0b3Ap/sessions/__PAGE__.segment.rsc +1 -1
  178. package/.next/standalone/.next/server/app/sessions.segments/!KGRlc2t0b3Ap/sessions.segment.rsc +1 -1
  179. package/.next/standalone/.next/server/app/sessions.segments/!KGRlc2t0b3Ap.segment.rsc +1 -1
  180. package/.next/standalone/.next/server/app/sessions.segments/_full.segment.rsc +2 -2
  181. package/.next/standalone/.next/server/app/sessions.segments/_head.segment.rsc +1 -1
  182. package/.next/standalone/.next/server/app/sessions.segments/_index.segment.rsc +2 -2
  183. package/.next/standalone/.next/server/app/sessions.segments/_tree.segment.rsc +2 -2
  184. package/.next/standalone/.next/server/app/settings.html +1 -1
  185. package/.next/standalone/.next/server/app/settings.rsc +3 -3
  186. package/.next/standalone/.next/server/app/settings.segments/!KGRlc2t0b3Ap/settings/__PAGE__.segment.rsc +2 -2
  187. package/.next/standalone/.next/server/app/settings.segments/!KGRlc2t0b3Ap/settings.segment.rsc +1 -1
  188. package/.next/standalone/.next/server/app/settings.segments/!KGRlc2t0b3Ap.segment.rsc +1 -1
  189. package/.next/standalone/.next/server/app/settings.segments/_full.segment.rsc +3 -3
  190. package/.next/standalone/.next/server/app/settings.segments/_head.segment.rsc +1 -1
  191. package/.next/standalone/.next/server/app/settings.segments/_index.segment.rsc +2 -2
  192. package/.next/standalone/.next/server/app/settings.segments/_tree.segment.rsc +2 -2
  193. package/.next/standalone/.next/server/app/terminal.html +1 -1
  194. package/.next/standalone/.next/server/app/terminal.rsc +3 -3
  195. package/.next/standalone/.next/server/app/terminal.segments/!KGRlc2t0b3Ap/terminal/__PAGE__.segment.rsc +2 -2
  196. package/.next/standalone/.next/server/app/terminal.segments/!KGRlc2t0b3Ap/terminal.segment.rsc +1 -1
  197. package/.next/standalone/.next/server/app/terminal.segments/!KGRlc2t0b3Ap.segment.rsc +1 -1
  198. package/.next/standalone/.next/server/app/terminal.segments/_full.segment.rsc +3 -3
  199. package/.next/standalone/.next/server/app/terminal.segments/_head.segment.rsc +1 -1
  200. package/.next/standalone/.next/server/app/terminal.segments/_index.segment.rsc +2 -2
  201. package/.next/standalone/.next/server/app/terminal.segments/_tree.segment.rsc +2 -2
  202. package/.next/standalone/.next/server/app/vr/page_client-reference-manifest.js +1 -1
  203. package/.next/standalone/.next/server/app/vr.html +1 -1
  204. package/.next/standalone/.next/server/app/vr.rsc +2 -2
  205. package/.next/standalone/.next/server/app/vr.segments/_full.segment.rsc +2 -2
  206. package/.next/standalone/.next/server/app/vr.segments/_head.segment.rsc +1 -1
  207. package/.next/standalone/.next/server/app/vr.segments/_index.segment.rsc +2 -2
  208. package/.next/standalone/.next/server/app/vr.segments/_tree.segment.rsc +2 -2
  209. package/.next/standalone/.next/server/app/vr.segments/vr/__PAGE__.segment.rsc +1 -1
  210. package/.next/standalone/.next/server/app/vr.segments/vr.segment.rsc +1 -1
  211. package/.next/standalone/.next/server/app/workspaces.html +1 -1
  212. package/.next/standalone/.next/server/app/workspaces.rsc +2 -2
  213. package/.next/standalone/.next/server/app/workspaces.segments/!KGRlc2t0b3Ap/workspaces/__PAGE__.segment.rsc +1 -1
  214. package/.next/standalone/.next/server/app/workspaces.segments/!KGRlc2t0b3Ap/workspaces.segment.rsc +1 -1
  215. package/.next/standalone/.next/server/app/workspaces.segments/!KGRlc2t0b3Ap.segment.rsc +1 -1
  216. package/.next/standalone/.next/server/app/workspaces.segments/_full.segment.rsc +2 -2
  217. package/.next/standalone/.next/server/app/workspaces.segments/_head.segment.rsc +1 -1
  218. package/.next/standalone/.next/server/app/workspaces.segments/_index.segment.rsc +2 -2
  219. package/.next/standalone/.next/server/app/workspaces.segments/_tree.segment.rsc +2 -2
  220. package/.next/standalone/.next/server/app-paths-manifest.json +3 -0
  221. package/.next/standalone/.next/server/chunks/[root-of-the-server]__00e90fc6._.js +15 -2
  222. package/.next/standalone/.next/server/chunks/[root-of-the-server]__01ab8675._.js +15 -2
  223. package/.next/standalone/.next/server/chunks/[root-of-the-server]__03974f05._.js +15 -2
  224. package/.next/standalone/.next/server/chunks/[root-of-the-server]__046c9b91._.js +15 -2
  225. package/.next/standalone/.next/server/chunks/[root-of-the-server]__04ae6bf0._.js +15 -2
  226. package/.next/standalone/.next/server/chunks/[root-of-the-server]__056fa416._.js +1 -1
  227. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0ac4ea3f._.js +1 -1
  228. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0b8e64cb._.js +15 -2
  229. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0facd39e._.js +15 -2
  230. package/.next/standalone/.next/server/chunks/[root-of-the-server]__10bc76a3._.js +1 -1
  231. package/.next/standalone/.next/server/chunks/[root-of-the-server]__115f3934._.js +15 -2
  232. package/.next/standalone/.next/server/chunks/[root-of-the-server]__11f155f1._.js +1 -1
  233. package/.next/standalone/.next/server/chunks/[root-of-the-server]__160e7c73._.js +52 -24
  234. package/.next/standalone/.next/server/chunks/[root-of-the-server]__17a3b966._.js +15 -2
  235. package/.next/standalone/.next/server/chunks/[root-of-the-server]__17d3a2b2._.js +15 -2
  236. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1a86c055._.js +15 -2
  237. package/.next/standalone/.next/server/chunks/[root-of-the-server]__20b5e9c4._.js +1 -1
  238. package/.next/standalone/.next/server/chunks/[root-of-the-server]__28d6fbd8._.js +15 -2
  239. package/.next/standalone/.next/server/chunks/[root-of-the-server]__2a3f866b._.js +16 -3
  240. package/.next/standalone/.next/server/chunks/[root-of-the-server]__316617e7._.js +2 -2
  241. package/.next/standalone/.next/server/chunks/[root-of-the-server]__32ad8f71._.js +15 -2
  242. package/.next/standalone/.next/server/chunks/[root-of-the-server]__35457394._.js +15 -2
  243. package/.next/standalone/.next/server/chunks/[root-of-the-server]__35de78e6._.js +15 -2
  244. package/.next/standalone/.next/server/chunks/[root-of-the-server]__3685ffcb._.js +15 -2
  245. package/.next/standalone/.next/server/chunks/[root-of-the-server]__38954988._.js +15 -2
  246. package/.next/standalone/.next/server/chunks/[root-of-the-server]__3a32b624._.js +111 -0
  247. package/.next/standalone/.next/server/chunks/[root-of-the-server]__426ad936._.js +17 -4
  248. package/.next/standalone/.next/server/chunks/[root-of-the-server]__4985c034._.js +15 -2
  249. package/.next/standalone/.next/server/chunks/[root-of-the-server]__5c6ce9ed._.js +16 -3
  250. package/.next/standalone/.next/server/chunks/[root-of-the-server]__5cebe58a._.js +15 -2
  251. package/.next/standalone/.next/server/chunks/[root-of-the-server]__5d5e4789._.js +15 -2
  252. package/.next/standalone/.next/server/chunks/[root-of-the-server]__65676930._.js +1 -1
  253. package/.next/standalone/.next/server/chunks/[root-of-the-server]__67cab326._.js +2 -2
  254. package/.next/standalone/.next/server/chunks/[root-of-the-server]__698c6f01._.js +16 -3
  255. package/.next/standalone/.next/server/chunks/[root-of-the-server]__6c64af29._.js +22 -9
  256. package/.next/standalone/.next/server/chunks/[root-of-the-server]__73aed9f5._.js +15 -2
  257. package/.next/standalone/.next/server/chunks/[root-of-the-server]__79b6a9bb._.js +15 -2
  258. package/.next/standalone/.next/server/chunks/[root-of-the-server]__7db704c6._.js +17 -4
  259. package/.next/standalone/.next/server/chunks/[root-of-the-server]__812ca02b._.js +15 -2
  260. package/.next/standalone/.next/server/chunks/[root-of-the-server]__821f50fa._.js +15 -2
  261. package/.next/standalone/.next/server/chunks/[root-of-the-server]__8716b86e._.js +15 -2
  262. package/.next/standalone/.next/server/chunks/[root-of-the-server]__884ef754._.js +15 -2
  263. package/.next/standalone/.next/server/chunks/[root-of-the-server]__88cdbd68._.js +15 -2
  264. package/.next/standalone/.next/server/chunks/[root-of-the-server]__89d9aba9._.js +15 -2
  265. package/.next/standalone/.next/server/chunks/[root-of-the-server]__8c2e1260._.js +111 -0
  266. package/.next/standalone/.next/server/chunks/[root-of-the-server]__8d536cb5._.js +15 -2
  267. package/.next/standalone/.next/server/chunks/[root-of-the-server]__8df8c5d1._.js +15 -2
  268. package/.next/standalone/.next/server/chunks/[root-of-the-server]__8f2ccc41._.js +15 -2
  269. package/.next/standalone/.next/server/chunks/[root-of-the-server]__95c9d682._.js +15 -2
  270. package/.next/standalone/.next/server/chunks/[root-of-the-server]__9e5d7774._.js +15 -2
  271. package/.next/standalone/.next/server/chunks/[root-of-the-server]__9edcff87._.js +15 -2
  272. package/.next/standalone/.next/server/chunks/[root-of-the-server]__a049dfc2._.js +15 -2
  273. package/.next/standalone/.next/server/chunks/[root-of-the-server]__a5b4bb9a._.js +16 -3
  274. package/.next/standalone/.next/server/chunks/[root-of-the-server]__a83262a1._.js +15 -2
  275. package/.next/standalone/.next/server/chunks/[root-of-the-server]__a9cd1240._.js +15 -2
  276. package/.next/standalone/.next/server/chunks/[root-of-the-server]__a9d7f822._.js +15 -2
  277. package/.next/standalone/.next/server/chunks/[root-of-the-server]__ad08c221._.js +15 -2
  278. package/.next/standalone/.next/server/chunks/[root-of-the-server]__ad585f2f._.js +15 -2
  279. package/.next/standalone/.next/server/chunks/[root-of-the-server]__afcb8f7d._.js +15 -2
  280. package/.next/standalone/.next/server/chunks/[root-of-the-server]__bc250d43._.js +15 -2
  281. package/.next/standalone/.next/server/chunks/[root-of-the-server]__bce2a6e7._.js +15 -2
  282. package/.next/standalone/.next/server/chunks/[root-of-the-server]__c011bf91._.js +15 -2
  283. package/.next/standalone/.next/server/chunks/[root-of-the-server]__c37d6380._.js +1 -1
  284. package/.next/standalone/.next/server/chunks/[root-of-the-server]__cae392eb._.js +15 -2
  285. package/.next/standalone/.next/server/chunks/[root-of-the-server]__cc2616bb._.js +16 -3
  286. package/.next/standalone/.next/server/chunks/[root-of-the-server]__d501fa9b._.js +15 -2
  287. package/.next/standalone/.next/server/chunks/[root-of-the-server]__d59c6c15._.js +16 -3
  288. package/.next/standalone/.next/server/chunks/[root-of-the-server]__d5c1db32._.js +15 -2
  289. package/.next/standalone/.next/server/chunks/[root-of-the-server]__dba60c86._.js +15 -2
  290. package/.next/standalone/.next/server/chunks/[root-of-the-server]__de14b9ae._.js +15 -2
  291. package/.next/standalone/.next/server/chunks/[root-of-the-server]__e10643d1._.js +15 -2
  292. package/.next/standalone/.next/server/chunks/[root-of-the-server]__e2a996e5._.js +23 -10
  293. package/.next/standalone/.next/server/chunks/[root-of-the-server]__e3477417._.js +15 -2
  294. package/.next/standalone/.next/server/chunks/[root-of-the-server]__e4db362e._.js +1 -1
  295. package/.next/standalone/.next/server/chunks/[root-of-the-server]__e4e70b86._.js +15 -2
  296. package/.next/standalone/.next/server/chunks/[root-of-the-server]__e54925af._.js +15 -2
  297. package/.next/standalone/.next/server/chunks/[root-of-the-server]__e8cbeaca._.js +111 -0
  298. package/.next/standalone/.next/server/chunks/[root-of-the-server]__e8edc5b0._.js +15 -2
  299. package/.next/standalone/.next/server/chunks/[root-of-the-server]__eab4d83b._.js +15 -2
  300. package/.next/standalone/.next/server/chunks/[root-of-the-server]__ead29015._.js +1 -1
  301. package/.next/standalone/.next/server/chunks/[root-of-the-server]__f056fd83._.js +15 -2
  302. package/.next/standalone/.next/server/chunks/[root-of-the-server]__f0e99572._.js +15 -2
  303. package/.next/standalone/.next/server/chunks/[root-of-the-server]__fe1e16d0._.js +15 -2
  304. package/.next/standalone/.next/server/chunks/[root-of-the-server]__ff9cd277._.js +15 -2
  305. package/.next/standalone/.next/server/chunks/[root-of-the-server]__ffaea2ce._.js +15 -2
  306. package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_claude_usage_route_actions_fe002ec1.js +3 -0
  307. package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_workspaces_[id]_todos_route_actions_0d4ffac5.js +3 -0
  308. package/.next/standalone/.next/server/chunks/ce889_server_app_api_workspaces_[id]_todos_[todoId]_route_actions_754fe6b9.js +3 -0
  309. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__66aca5d4._.js +1 -1
  310. package/.next/standalone/.next/server/chunks/ssr/{_17b946fd._.js → _20c2cf3a._.js} +2 -2
  311. package/.next/standalone/.next/server/chunks/ssr/_5f55bf8f._.js +3 -0
  312. package/.next/standalone/.next/server/chunks/ssr/src_app_(desktop)_settings_page_tsx_f74824b3._.js +1 -1
  313. package/.next/standalone/.next/server/chunks/ssr/src_app_(desktop)_terminal_page_tsx_de5e8d85._.js +1 -1
  314. package/.next/standalone/.next/server/edge/chunks/[root-of-the-server]__90eeddae._.js +1 -1
  315. package/.next/standalone/.next/server/middleware-manifest.json +5 -5
  316. package/.next/standalone/.next/server/pages/404.html +1 -1
  317. package/.next/standalone/.next/server/pages/500.html +2 -2
  318. package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
  319. package/.next/standalone/.next/server/server-reference-manifest.json +1 -1
  320. package/.next/standalone/.next/static/chunks/14216197f9dcbe5b.css +3 -0
  321. package/.next/standalone/.next/static/chunks/{0852575eb90c1e8d.js → 4c9fb0a38f041a3d.js} +2 -2
  322. package/.next/standalone/.next/static/chunks/8f6f93ab45a5ff5b.js +1 -0
  323. package/.next/standalone/.next/static/chunks/{e62bb488d02db247.js → d2566c2dcf53fef3.js} +1 -1
  324. package/.next/standalone/.next/static/chunks/{7f6a14f1849fa94d.js → ff7d85dade44d1f3.js} +1 -1
  325. package/.next/standalone/cortex-hook-debug.log +61 -0
  326. package/.next/standalone/docs/features/claude-usage.md +105 -0
  327. package/.next/standalone/docs/features/workspace-todos.md +127 -0
  328. package/.next/standalone/docs/superpowers/plans/2026-04-21-workspace-todos.md +1097 -0
  329. package/.next/standalone/docs/superpowers/plans/2026-04-22-claude-usage-display.md +749 -0
  330. package/.next/standalone/docs/superpowers/specs/2026-04-21-workspace-todos-design.md +180 -0
  331. package/.next/standalone/docs/superpowers/specs/2026-04-22-claude-usage-display-design.md +183 -0
  332. package/.next/standalone/package-lock.json +2 -2
  333. package/.next/standalone/package.json +1 -1
  334. package/.next/standalone/src/app/(desktop)/settings/page.tsx +40 -1
  335. package/.next/standalone/src/app/(desktop)/terminal/page.tsx +54 -2
  336. package/.next/standalone/src/app/api/claude/usage/route.ts +33 -0
  337. package/.next/standalone/src/app/api/config/route.ts +3 -0
  338. package/.next/standalone/src/app/api/workspaces/[id]/todos/[todoId]/route.ts +55 -0
  339. package/.next/standalone/src/app/api/workspaces/[id]/todos/route.ts +43 -0
  340. package/.next/standalone/src/components/claude/claude-usage-strip.tsx +175 -0
  341. package/.next/standalone/src/components/workspace/workspace-todos.tsx +265 -0
  342. package/.next/standalone/src/hooks/use-claude-usage.ts +66 -0
  343. package/.next/standalone/src/lib/claude/credentials.ts +36 -0
  344. package/.next/standalone/src/lib/claude/usage.ts +69 -0
  345. package/.next/standalone/src/lib/config.ts +3 -0
  346. package/.next/standalone/src/lib/db/queries.ts +103 -1
  347. package/.next/standalone/src/lib/db/schema.ts +18 -0
  348. package/.next/standalone/src/types/claude.ts +39 -0
  349. package/.next/standalone/tests/db/workspace-todos.test.ts +156 -0
  350. package/package.json +1 -1
  351. package/.next/standalone/.next/server/chunks/ssr/_3ba93bdd._.js +0 -3
  352. package/.next/standalone/.next/static/chunks/074df89a63b6a854.js +0 -1
  353. package/.next/standalone/.next/static/chunks/2b769d1597e4fc1c.css +0 -3
  354. /package/.next/standalone/.next/static/{u1pHON3drz1mBi7owkbBP → bAQs2gDlFrq3e8w9ni9tr}/_buildManifest.js +0 -0
  355. /package/.next/standalone/.next/static/{u1pHON3drz1mBi7owkbBP → bAQs2gDlFrq3e8w9ni9tr}/_clientMiddlewareManifest.json +0 -0
  356. /package/.next/standalone/.next/static/{u1pHON3drz1mBi7owkbBP → bAQs2gDlFrq3e8w9ni9tr}/_ssgManifest.js +0 -0
@@ -0,0 +1,55 @@
1
+ import { NextRequest, NextResponse } from 'next/server';
2
+ import { getAuthUser, withUser } from '@/lib/auth';
3
+ import { ensureInitialized } from '@/lib/db/init';
4
+ import { updateWorkspaceTodo, deleteWorkspaceTodo } from '@/lib/db/queries';
5
+
6
+ export async function PATCH(
7
+ request: NextRequest,
8
+ { params }: { params: Promise<{ id: string; todoId: string }> }
9
+ ) {
10
+ const user = getAuthUser(request);
11
+ return withUser(user, async () => {
12
+ await ensureInitialized();
13
+ const { id, todoId } = await params;
14
+ const wsId = parseInt(id, 10);
15
+ const tid = parseInt(todoId, 10);
16
+ if (!Number.isFinite(wsId) || !Number.isFinite(tid)) {
17
+ return NextResponse.json({ error: 'invalid workspace or todo id' }, { status: 400 });
18
+ }
19
+ const body = await request.json().catch(() => null);
20
+ if (!body || (body.text === undefined && body.completed === undefined)) {
21
+ return NextResponse.json({ error: 'text or completed required' }, { status: 400 });
22
+ }
23
+ try {
24
+ const updated = updateWorkspaceTodo(wsId, tid, {
25
+ text: typeof body.text === 'string' ? body.text : undefined,
26
+ completed: typeof body.completed === 'boolean' ? body.completed : undefined,
27
+ });
28
+ if (!updated) {
29
+ return NextResponse.json({ error: 'not found' }, { status: 404 });
30
+ }
31
+ return NextResponse.json(updated);
32
+ } catch (err) {
33
+ const message = err instanceof Error ? err.message : 'update failed';
34
+ return NextResponse.json({ error: message }, { status: 400 });
35
+ }
36
+ });
37
+ }
38
+
39
+ export async function DELETE(
40
+ request: NextRequest,
41
+ { params }: { params: Promise<{ id: string; todoId: string }> }
42
+ ) {
43
+ const user = getAuthUser(request);
44
+ return withUser(user, async () => {
45
+ await ensureInitialized();
46
+ const { id, todoId } = await params;
47
+ const wsId = parseInt(id, 10);
48
+ const tid = parseInt(todoId, 10);
49
+ if (!Number.isFinite(wsId) || !Number.isFinite(tid)) {
50
+ return NextResponse.json({ error: 'invalid workspace or todo id' }, { status: 400 });
51
+ }
52
+ deleteWorkspaceTodo(wsId, tid);
53
+ return NextResponse.json({ ok: true });
54
+ });
55
+ }
@@ -0,0 +1,43 @@
1
+ import { NextRequest, NextResponse } from 'next/server';
2
+ import { getAuthUser, withUser } from '@/lib/auth';
3
+ import { ensureInitialized } from '@/lib/db/init';
4
+ import { getWorkspaceTodos, addWorkspaceTodo } from '@/lib/db/queries';
5
+
6
+ export async function GET(
7
+ request: NextRequest,
8
+ { params }: { params: Promise<{ id: string }> }
9
+ ) {
10
+ const user = getAuthUser(request);
11
+ return withUser(user, async () => {
12
+ await ensureInitialized();
13
+ const { id } = await params;
14
+ const wsId = parseInt(id, 10);
15
+ if (!Number.isFinite(wsId)) {
16
+ return NextResponse.json({ error: 'invalid workspace id' }, { status: 400 });
17
+ }
18
+ const todos = getWorkspaceTodos(wsId);
19
+ return NextResponse.json(todos);
20
+ });
21
+ }
22
+
23
+ export async function POST(
24
+ request: NextRequest,
25
+ { params }: { params: Promise<{ id: string }> }
26
+ ) {
27
+ const user = getAuthUser(request);
28
+ return withUser(user, async () => {
29
+ await ensureInitialized();
30
+ const { id } = await params;
31
+ const wsId = parseInt(id, 10);
32
+ if (!Number.isFinite(wsId)) {
33
+ return NextResponse.json({ error: 'invalid workspace id' }, { status: 400 });
34
+ }
35
+ const body = await request.json().catch(() => null);
36
+ const text = typeof body?.text === 'string' ? body.text : '';
37
+ if (!text.trim()) {
38
+ return NextResponse.json({ error: 'text is required' }, { status: 400 });
39
+ }
40
+ const todo = addWorkspaceTodo(wsId, text);
41
+ return NextResponse.json(todo, { status: 201 });
42
+ });
43
+ }
@@ -0,0 +1,175 @@
1
+ 'use client';
2
+
3
+ import { useEffect, useRef, useState } from 'react';
4
+ import { Zap, LogIn } from 'lucide-react';
5
+ import { useClaudeUsage } from '@/hooks/use-claude-usage';
6
+ import type { RateLimit } from '@/types/claude';
7
+
8
+ interface Props {
9
+ enabled: boolean;
10
+ }
11
+
12
+ function utilizationColor(pct: number | null): string {
13
+ if (pct == null) return '#52525b'; // zinc-600 — unknown
14
+ if (pct <= 70) return '#22c55e'; // green-500
15
+ if (pct <= 90) return '#f59e0b'; // amber-500
16
+ return '#ef4444'; // red-500
17
+ }
18
+
19
+ function formatReset(resetsAt: string | null): string {
20
+ if (!resetsAt) return '';
21
+ const ms = new Date(resetsAt).getTime() - Date.now();
22
+ if (ms <= 0) return 'now';
23
+ const h = Math.floor(ms / 3_600_000);
24
+ const m = Math.floor((ms % 3_600_000) / 60_000);
25
+ if (h >= 24) {
26
+ const d = Math.floor(h / 24);
27
+ const rh = h - d * 24;
28
+ return `${d}d ${rh}h`;
29
+ }
30
+ if (h > 0) return `${h}h ${m}m`;
31
+ return `${m}m`;
32
+ }
33
+
34
+ function Bar({ label, limit }: { label: string; limit: RateLimit | null | undefined }) {
35
+ if (!limit || limit.utilization == null) return null;
36
+ const pct = Math.min(100, Math.max(0, limit.utilization));
37
+ const color = utilizationColor(pct);
38
+ const reset = formatReset(limit.resets_at);
39
+ return (
40
+ <div
41
+ className="flex items-center gap-1.5 text-[10px]"
42
+ title={reset ? `${label}: ${Math.floor(pct)}% used · resets in ${reset}` : `${label}: ${Math.floor(pct)}% used`}
43
+ >
44
+ <span className="text-zinc-400 font-medium">{label}</span>
45
+ <div className="w-12 h-1 bg-zinc-800 rounded-full overflow-hidden">
46
+ <div
47
+ className="h-full transition-all"
48
+ style={{ width: `${pct}%`, backgroundColor: color }}
49
+ />
50
+ </div>
51
+ <span className="text-zinc-500 tabular-nums w-7 text-right">{Math.floor(pct)}%</span>
52
+ </div>
53
+ );
54
+ }
55
+
56
+ export function ClaudeUsageStrip({ enabled }: Props) {
57
+ const response = useClaudeUsage(enabled);
58
+ const [expanded, setExpanded] = useState(false);
59
+ const popoverRef = useRef<HTMLDivElement>(null);
60
+
61
+ useEffect(() => {
62
+ if (!expanded) return;
63
+ function handleClick(e: MouseEvent) {
64
+ if (popoverRef.current && !popoverRef.current.contains(e.target as Node)) {
65
+ setExpanded(false);
66
+ }
67
+ }
68
+ document.addEventListener('mousedown', handleClick);
69
+ return () => document.removeEventListener('mousedown', handleClick);
70
+ }, [expanded]);
71
+
72
+ if (!enabled || !response) return null;
73
+
74
+ if (response.status === 'unauthenticated' || response.status === 'expired') {
75
+ return (
76
+ <div
77
+ className="flex items-center gap-1.5 px-2 py-1 text-[10px] text-zinc-500 border border-zinc-800 rounded-md"
78
+ title={response.status === 'expired' ? 'OAuth token expired — run any Claude Code command to refresh' : 'No Claude.ai credentials found'}
79
+ >
80
+ <LogIn className="w-3 h-3" />
81
+ sign in via Claude Code
82
+ </div>
83
+ );
84
+ }
85
+
86
+ if (response.status === 'upstream_error') {
87
+ return null; // Silent — per spec.
88
+ }
89
+
90
+ const { data } = response;
91
+ const extra = data.extra_usage;
92
+ const hasOverage = !!(extra?.is_enabled && extra?.used_credits && extra.used_credits > 0);
93
+
94
+ return (
95
+ <div className="relative">
96
+ <button
97
+ onClick={() => setExpanded(v => !v)}
98
+ className="flex items-center gap-2.5 px-2.5 py-1 border border-zinc-800 rounded-md hover:border-zinc-700 transition-colors"
99
+ title="Click for full usage detail"
100
+ >
101
+ <Zap className="w-3 h-3 text-amber-400" />
102
+ <Bar label="5h" limit={data.five_hour} />
103
+ <Bar label="7d" limit={data.seven_day} />
104
+ <Bar label="Opus" limit={data.seven_day_opus} />
105
+ <Bar label="Sonnet" limit={data.seven_day_sonnet} />
106
+ {hasOverage && extra?.used_credits != null && (
107
+ <span className="text-[10px] text-amber-400 border-l border-zinc-800 pl-2">
108
+ +${extra.used_credits.toFixed(2)} overage
109
+ </span>
110
+ )}
111
+ </button>
112
+
113
+ {expanded && (
114
+ <div
115
+ ref={popoverRef}
116
+ className="absolute top-full right-0 mt-1.5 z-50 w-80 p-3 bg-zinc-900 border border-zinc-700 rounded-md shadow-xl"
117
+ >
118
+ <div className="text-[10px] uppercase tracking-wider text-zinc-500 font-medium mb-2">
119
+ Plan Usage
120
+ </div>
121
+ <div className="space-y-2">
122
+ <ExpandedRow label="5-hour window" limit={data.five_hour} />
123
+ <ExpandedRow label="7-day (overall)" limit={data.seven_day} />
124
+ <ExpandedRow label="7-day · Opus" limit={data.seven_day_opus} />
125
+ <ExpandedRow label="7-day · Sonnet" limit={data.seven_day_sonnet} />
126
+ <ExpandedRow label="7-day · OAuth apps" limit={data.seven_day_oauth_apps} />
127
+ </div>
128
+ {extra?.is_enabled && (
129
+ <div className="mt-3 pt-3 border-t border-zinc-800">
130
+ <div className="text-[10px] uppercase tracking-wider text-zinc-500 font-medium mb-1.5">
131
+ Overage credits
132
+ </div>
133
+ <div className="text-xs text-zinc-300">
134
+ {extra.used_credits != null ? `$${extra.used_credits.toFixed(2)}` : '—'}
135
+ {extra.monthly_limit != null && (
136
+ <span className="text-zinc-500"> / ${extra.monthly_limit.toFixed(2)} monthly</span>
137
+ )}
138
+ </div>
139
+ </div>
140
+ )}
141
+ </div>
142
+ )}
143
+ </div>
144
+ );
145
+ }
146
+
147
+ function ExpandedRow({ label, limit }: { label: string; limit: RateLimit | null | undefined }) {
148
+ if (!limit || limit.utilization == null) {
149
+ return (
150
+ <div className="flex items-center justify-between text-xs">
151
+ <span className="text-zinc-400">{label}</span>
152
+ <span className="text-zinc-600">—</span>
153
+ </div>
154
+ );
155
+ }
156
+ const pct = Math.min(100, Math.max(0, limit.utilization));
157
+ const color = utilizationColor(pct);
158
+ const reset = formatReset(limit.resets_at);
159
+ return (
160
+ <div>
161
+ <div className="flex items-center justify-between text-xs mb-1">
162
+ <span className="text-zinc-300">{label}</span>
163
+ <span className="text-zinc-500 tabular-nums">
164
+ {Math.floor(pct)}%{reset && <span className="ml-1.5 text-zinc-600">· {reset}</span>}
165
+ </span>
166
+ </div>
167
+ <div className="h-1.5 bg-zinc-800 rounded-full overflow-hidden">
168
+ <div
169
+ className="h-full transition-all"
170
+ style={{ width: `${pct}%`, backgroundColor: color }}
171
+ />
172
+ </div>
173
+ </div>
174
+ );
175
+ }
@@ -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
+ }