agim-cli 1.5.0 → 1.5.1

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 (344) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/README.md +39 -3
  3. package/README.zh-CN.md +42 -7
  4. package/dist/cli-ui/cmd-handlers.d.ts +22 -1
  5. package/dist/cli-ui/cmd-handlers.d.ts.map +1 -1
  6. package/dist/cli-ui/cmd-handlers.js +304 -40
  7. package/dist/cli-ui/cmd-handlers.js.map +1 -1
  8. package/dist/cli-ui/config-wizard.d.ts +13 -1
  9. package/dist/cli-ui/config-wizard.d.ts.map +1 -1
  10. package/dist/cli-ui/config-wizard.js +93 -21
  11. package/dist/cli-ui/config-wizard.js.map +1 -1
  12. package/dist/cli-ui/doctor.d.ts +15 -0
  13. package/dist/cli-ui/doctor.d.ts.map +1 -0
  14. package/dist/cli-ui/doctor.js +151 -0
  15. package/dist/cli-ui/doctor.js.map +1 -0
  16. package/dist/cli-ui/entry-menu.d.ts +6 -0
  17. package/dist/cli-ui/entry-menu.d.ts.map +1 -1
  18. package/dist/cli-ui/entry-menu.js +67 -30
  19. package/dist/cli-ui/entry-menu.js.map +1 -1
  20. package/dist/cli-ui/i18n.d.ts +15 -6
  21. package/dist/cli-ui/i18n.d.ts.map +1 -1
  22. package/dist/cli-ui/i18n.js +30 -12
  23. package/dist/cli-ui/i18n.js.map +1 -1
  24. package/dist/cli-ui/quickstart.d.ts +3 -0
  25. package/dist/cli-ui/quickstart.d.ts.map +1 -0
  26. package/dist/cli-ui/quickstart.js +108 -0
  27. package/dist/cli-ui/quickstart.js.map +1 -0
  28. package/dist/cli-ui/readiness.d.ts +10 -0
  29. package/dist/cli-ui/readiness.d.ts.map +1 -0
  30. package/dist/cli-ui/readiness.js +75 -0
  31. package/dist/cli-ui/readiness.js.map +1 -0
  32. package/dist/cli-ui/service.d.ts +23 -0
  33. package/dist/cli-ui/service.d.ts.map +1 -1
  34. package/dist/cli-ui/service.js +114 -5
  35. package/dist/cli-ui/service.js.map +1 -1
  36. package/dist/cli.js +99 -396
  37. package/dist/cli.js.map +1 -1
  38. package/dist/core/acp-server.d.ts.map +1 -1
  39. package/dist/core/acp-server.js +16 -2
  40. package/dist/core/acp-server.js.map +1 -1
  41. package/dist/core/agent-cwd.d.ts +8 -0
  42. package/dist/core/agent-cwd.d.ts.map +1 -1
  43. package/dist/core/agent-cwd.js +57 -7
  44. package/dist/core/agent-cwd.js.map +1 -1
  45. package/dist/core/commands/builtin.d.ts.map +1 -1
  46. package/dist/core/commands/builtin.js +12 -2
  47. package/dist/core/commands/builtin.js.map +1 -1
  48. package/dist/core/commands/model.d.ts.map +1 -1
  49. package/dist/core/commands/model.js +31 -2
  50. package/dist/core/commands/model.js.map +1 -1
  51. package/dist/core/llm/anthropic-provider.js +2 -1
  52. package/dist/core/llm/anthropic-provider.js.map +1 -1
  53. package/dist/core/llm/openai-compat-provider.js +3 -2
  54. package/dist/core/llm/openai-compat-provider.js.map +1 -1
  55. package/dist/core/llm/provider-base.d.ts +4 -4
  56. package/dist/core/llm/provider-base.d.ts.map +1 -1
  57. package/dist/core/llm/provider-base.js +1 -1
  58. package/dist/core/llm/provider-base.js.map +1 -1
  59. package/dist/plugins/agents/native/index.d.ts +1 -0
  60. package/dist/plugins/agents/native/index.d.ts.map +1 -1
  61. package/dist/plugins/agents/native/index.js +14 -0
  62. package/dist/plugins/agents/native/index.js.map +1 -1
  63. package/dist/plugins/agents/pi-native/factory.d.ts.map +1 -1
  64. package/dist/plugins/agents/pi-native/factory.js +19 -3
  65. package/dist/plugins/agents/pi-native/factory.js.map +1 -1
  66. package/dist/plugins/agents/pi-native/index.d.ts +11 -0
  67. package/dist/plugins/agents/pi-native/index.d.ts.map +1 -1
  68. package/dist/plugins/agents/pi-native/index.js +56 -2
  69. package/dist/plugins/agents/pi-native/index.js.map +1 -1
  70. package/dist/plugins/agents/pi-native/provider-resolver.d.ts +2 -0
  71. package/dist/plugins/agents/pi-native/provider-resolver.d.ts.map +1 -1
  72. package/dist/plugins/agents/pi-native/provider-resolver.js +9 -1
  73. package/dist/plugins/agents/pi-native/provider-resolver.js.map +1 -1
  74. package/dist/web/public/assets/a2a-CTsDMefo.js +7 -0
  75. package/dist/web/public/assets/a2a-CTsDMefo.js.map +1 -0
  76. package/dist/web/public/assets/{activity-BAgb2WZC.js → activity-ul8Os7Pz.js} +2 -2
  77. package/dist/web/public/assets/{activity-BAgb2WZC.js.map → activity-ul8Os7Pz.js.map} +1 -1
  78. package/dist/web/public/assets/{admins-CZYANmhn.js → admins-ByMAuquy.js} +3 -3
  79. package/dist/web/public/assets/{admins-CZYANmhn.js.map → admins-ByMAuquy.js.map} +1 -1
  80. package/dist/web/public/assets/agents-Ds1zyxBj.js +2 -0
  81. package/dist/web/public/assets/{agents-BXThDW6f.js.map → agents-Ds1zyxBj.js.map} +1 -1
  82. package/dist/web/public/assets/{approvals-ByPXIYVl.js → approvals-DOWlWI7Z.js} +3 -3
  83. package/dist/web/public/assets/{approvals-ByPXIYVl.js.map → approvals-DOWlWI7Z.js.map} +1 -1
  84. package/dist/web/public/assets/{arrow-down-B8DkdbEY.js → arrow-down-7i0xwCI2.js} +2 -2
  85. package/dist/web/public/assets/{arrow-down-B8DkdbEY.js.map → arrow-down-7i0xwCI2.js.map} +1 -1
  86. package/dist/web/public/assets/arrow-right-A889Wof8.js +7 -0
  87. package/dist/web/public/assets/arrow-right-A889Wof8.js.map +1 -0
  88. package/dist/web/public/assets/{arrow-up-i_dEdXkz.js → arrow-up-Dm0U4-6U.js} +2 -2
  89. package/dist/web/public/assets/{arrow-up-i_dEdXkz.js.map → arrow-up-Dm0U4-6U.js.map} +1 -1
  90. package/dist/web/public/assets/{asks-yD_inOnM.js → asks-DGuBsrJ7.js} +3 -3
  91. package/dist/web/public/assets/{asks-yD_inOnM.js.map → asks-DGuBsrJ7.js.map} +1 -1
  92. package/dist/web/public/assets/{audit-teCIRtgN.js → audit-BRXsplJ2.js} +2 -2
  93. package/dist/web/public/assets/{audit-teCIRtgN.js.map → audit-BRXsplJ2.js.map} +1 -1
  94. package/dist/web/public/assets/{bell-CeWDMs8_.js → bell-B-UdeJsp.js} +2 -2
  95. package/dist/web/public/assets/{bell-CeWDMs8_.js.map → bell-B-UdeJsp.js.map} +1 -1
  96. package/dist/web/public/assets/bgjobs-CcRiffyJ.js +2 -0
  97. package/dist/web/public/assets/bgjobs-CcRiffyJ.js.map +1 -0
  98. package/dist/web/public/assets/book-open-CSCq5cjL.js +7 -0
  99. package/dist/web/public/assets/book-open-CSCq5cjL.js.map +1 -0
  100. package/dist/web/public/assets/{brain-BQqv0Zhc.js → brain-Dl4DF5kX.js} +2 -2
  101. package/dist/web/public/assets/{brain-BQqv0Zhc.js.map → brain-Dl4DF5kX.js.map} +1 -1
  102. package/dist/web/public/assets/{briefcase-DUXbR4xs.js → briefcase-CeKUkFSq.js} +2 -2
  103. package/dist/web/public/assets/{briefcase-DUXbR4xs.js.map → briefcase-CeKUkFSq.js.map} +1 -1
  104. package/dist/web/public/assets/chat-rLJMdJBk.js +12 -0
  105. package/dist/web/public/assets/chat-rLJMdJBk.js.map +1 -0
  106. package/dist/web/public/assets/{chevron-left-RC6mMSiX.js → chevron-left-01fAFVpo.js} +2 -2
  107. package/dist/web/public/assets/{chevron-left-RC6mMSiX.js.map → chevron-left-01fAFVpo.js.map} +1 -1
  108. package/dist/web/public/assets/{chevron-right-DrkYVi19.js → chevron-right-CFRb-SM_.js} +3 -3
  109. package/dist/web/public/assets/{chevron-right-DrkYVi19.js.map → chevron-right-CFRb-SM_.js.map} +1 -1
  110. package/dist/web/public/assets/{circle-check-big-BC8ntMsz.js → circle-check-big-DBg2BD6o.js} +2 -2
  111. package/dist/web/public/assets/{circle-check-big-BC8ntMsz.js.map → circle-check-big-DBg2BD6o.js.map} +1 -1
  112. package/dist/web/public/assets/{circle-x-DHK7ypFY.js → circle-x-CqFMzO-x.js} +2 -2
  113. package/dist/web/public/assets/{circle-x-DHK7ypFY.js.map → circle-x-CqFMzO-x.js.map} +1 -1
  114. package/dist/web/public/assets/clipboard-list-lnqdk2_J.js +7 -0
  115. package/dist/web/public/assets/clipboard-list-lnqdk2_J.js.map +1 -0
  116. package/dist/web/public/assets/{clock-DXHhWqJH.js → clock-4hd1joQe.js} +3 -3
  117. package/dist/web/public/assets/{clock-DXHhWqJH.js.map → clock-4hd1joQe.js.map} +1 -1
  118. package/dist/web/public/assets/confirm-dialog-BDb0NLny.js +2 -0
  119. package/dist/web/public/assets/{confirm-dialog-gPKJnvEW.js.map → confirm-dialog-BDb0NLny.js.map} +1 -1
  120. package/dist/web/public/assets/{copy-DtQxgcR0.js → copy-CD4A7VD8.js} +3 -3
  121. package/dist/web/public/assets/{copy-DtQxgcR0.js.map → copy-CD4A7VD8.js.map} +1 -1
  122. package/dist/web/public/assets/dashboard-CG3WiG7h.js +2 -0
  123. package/dist/web/public/assets/dashboard-CG3WiG7h.js.map +1 -0
  124. package/dist/web/public/assets/{data-table-DOKUic1J.js → data-table-BkUshOZz.js} +2 -2
  125. package/dist/web/public/assets/{data-table-DOKUic1J.js.map → data-table-BkUshOZz.js.map} +1 -1
  126. package/dist/web/public/assets/database-lQzk64rV.js +7 -0
  127. package/dist/web/public/assets/database-lQzk64rV.js.map +1 -0
  128. package/dist/web/public/assets/{distill-p6P7-1UR.js → distill-CPurVW3v.js} +3 -3
  129. package/dist/web/public/assets/{distill-p6P7-1UR.js.map → distill-CPurVW3v.js.map} +1 -1
  130. package/dist/web/public/assets/{download-CqNiIHa8.js → download-CVZnHcwj.js} +2 -2
  131. package/dist/web/public/assets/{download-CqNiIHa8.js.map → download-CVZnHcwj.js.map} +1 -1
  132. package/dist/web/public/assets/dropdown-menu-BNH5SrVb.js +7 -0
  133. package/dist/web/public/assets/dropdown-menu-BNH5SrVb.js.map +1 -0
  134. package/dist/web/public/assets/{email-DwbfTUlV.js → email-YlI4MWLp.js} +3 -3
  135. package/dist/web/public/assets/{email-DwbfTUlV.js.map → email-YlI4MWLp.js.map} +1 -1
  136. package/dist/web/public/assets/{empty-state-CTwOQemt.js → empty-state-CuiqdZiB.js} +2 -2
  137. package/dist/web/public/assets/{empty-state-CTwOQemt.js.map → empty-state-CuiqdZiB.js.map} +1 -1
  138. package/dist/web/public/assets/{external-link-BY7Ye8yi.js → external-link-1WPpVvdu.js} +2 -2
  139. package/dist/web/public/assets/{external-link-BY7Ye8yi.js.map → external-link-1WPpVvdu.js.map} +1 -1
  140. package/dist/web/public/assets/{eye-6RUADoDS.js → eye-BfPyNFzk.js} +2 -2
  141. package/dist/web/public/assets/{eye-6RUADoDS.js.map → eye-BfPyNFzk.js.map} +1 -1
  142. package/dist/web/public/assets/{facts-DXE0aJmb.js → facts-xT_24pH8.js} +2 -2
  143. package/dist/web/public/assets/{facts-DXE0aJmb.js.map → facts-xT_24pH8.js.map} +1 -1
  144. package/dist/web/public/assets/file-text-BxfdLM0-.js +7 -0
  145. package/dist/web/public/assets/file-text-BxfdLM0-.js.map +1 -0
  146. package/dist/web/public/assets/{goals-C1LCm3qL.js → goals-C8ZQfbhj.js} +3 -3
  147. package/dist/web/public/assets/{goals-C1LCm3qL.js.map → goals-C8ZQfbhj.js.map} +1 -1
  148. package/dist/web/public/assets/health-A2StNEfn.js +2 -0
  149. package/dist/web/public/assets/{health-wqCp-K_o.js.map → health-A2StNEfn.js.map} +1 -1
  150. package/dist/web/public/assets/{heart-pulse-DfqI4GF7.js → heart-pulse-DXlE9oic.js} +2 -2
  151. package/dist/web/public/assets/{heart-pulse-DfqI4GF7.js.map → heart-pulse-DXlE9oic.js.map} +1 -1
  152. package/dist/web/public/assets/{heartbeat-Bumv4XtQ.js → heartbeat-ClO5gJrj.js} +3 -3
  153. package/dist/web/public/assets/{heartbeat-Bumv4XtQ.js.map → heartbeat-ClO5gJrj.js.map} +1 -1
  154. package/dist/web/public/assets/hot-bfTA-V_z.js +7 -0
  155. package/dist/web/public/assets/{hot-B-CMjQIr.js.map → hot-bfTA-V_z.js.map} +1 -1
  156. package/dist/web/public/assets/index-Bi2qWb-u.css +1 -0
  157. package/dist/web/public/assets/index-DCfdN5R7.js +244 -0
  158. package/dist/web/public/assets/index-DCfdN5R7.js.map +1 -0
  159. package/dist/web/public/assets/{injection-Dn_XqgLG.js → injection-omvCR6-p.js} +2 -2
  160. package/dist/web/public/assets/{injection-Dn_XqgLG.js.map → injection-omvCR6-p.js.map} +1 -1
  161. package/dist/web/public/assets/{installed-Cet-1M2Q.js → installed-DL6r3ktm.js} +4 -9
  162. package/dist/web/public/assets/installed-DL6r3ktm.js.map +1 -0
  163. package/dist/web/public/assets/jobs-Biy5lYd4.js +2 -0
  164. package/dist/web/public/assets/jobs-Biy5lYd4.js.map +1 -0
  165. package/dist/web/public/assets/layout-BLm6NJ3V.js +2 -0
  166. package/dist/web/public/assets/layout-BLm6NJ3V.js.map +1 -0
  167. package/dist/web/public/assets/layout-BTKafRVZ.js +2 -0
  168. package/dist/web/public/assets/layout-BTKafRVZ.js.map +1 -0
  169. package/dist/web/public/assets/layout-Bm-2s2fp.js +2 -0
  170. package/dist/web/public/assets/layout-Bm-2s2fp.js.map +1 -0
  171. package/dist/web/public/assets/layout-DsZ8eR4i.js +2 -0
  172. package/dist/web/public/assets/layout-DsZ8eR4i.js.map +1 -0
  173. package/dist/web/public/assets/{layout-D_3ZcVG7.js → layout-sxvovjEH.js} +2 -2
  174. package/dist/web/public/assets/{layout-D_3ZcVG7.js.map → layout-sxvovjEH.js.map} +1 -1
  175. package/dist/web/public/assets/llm-JjZDbBvJ.js +37 -0
  176. package/dist/web/public/assets/llm-JjZDbBvJ.js.map +1 -0
  177. package/dist/web/public/assets/loader-circle-DDdmcH0k.js +7 -0
  178. package/dist/web/public/assets/{loader-circle-DgdBWYl0.js.map → loader-circle-DDdmcH0k.js.map} +1 -1
  179. package/dist/web/public/assets/{map-pin-3QS1A0-I.js → map-pin-C_jAxukI.js} +2 -2
  180. package/dist/web/public/assets/{map-pin-3QS1A0-I.js.map → map-pin-C_jAxukI.js.map} +1 -1
  181. package/dist/web/public/assets/{mcp-DwKZULET.js → mcp-vKajK1F8.js} +3 -3
  182. package/dist/web/public/assets/{mcp-DwKZULET.js.map → mcp-vKajK1F8.js.map} +1 -1
  183. package/dist/web/public/assets/memos-DAt4k3DO.js +7 -0
  184. package/dist/web/public/assets/memos-DAt4k3DO.js.map +1 -0
  185. package/dist/web/public/assets/messengers-GYVTFlAj.js +2 -0
  186. package/dist/web/public/assets/messengers-GYVTFlAj.js.map +1 -0
  187. package/dist/web/public/assets/{mobile-Bq0FH9JV.js → mobile-VUyTo40E.js} +3 -3
  188. package/dist/web/public/assets/{mobile-Bq0FH9JV.js.map → mobile-VUyTo40E.js.map} +1 -1
  189. package/dist/web/public/assets/{network--s113Jkm.js → network-BUeWK3bs.js} +2 -2
  190. package/dist/web/public/assets/{network--s113Jkm.js.map → network-BUeWK3bs.js.map} +1 -1
  191. package/dist/web/public/assets/outbox-CEE0rwN3.js +2 -0
  192. package/dist/web/public/assets/outbox-CEE0rwN3.js.map +1 -0
  193. package/dist/web/public/assets/overview-BSOZ5gTD.js +12 -0
  194. package/dist/web/public/assets/overview-BSOZ5gTD.js.map +1 -0
  195. package/dist/web/public/assets/overview-COop5K2Y.js +12 -0
  196. package/dist/web/public/assets/overview-COop5K2Y.js.map +1 -0
  197. package/dist/web/public/assets/overview-DeH5ud6d.js +2 -0
  198. package/dist/web/public/assets/overview-DeH5ud6d.js.map +1 -0
  199. package/dist/web/public/assets/{pagination-DkdCTctJ.js → pagination-BBicLzXP.js} +3 -3
  200. package/dist/web/public/assets/{pagination-DkdCTctJ.js.map → pagination-BBicLzXP.js.map} +1 -1
  201. package/dist/web/public/assets/persona-CElXQZ4p.js +2 -0
  202. package/dist/web/public/assets/{persona-BvtcZh6G.js.map → persona-CElXQZ4p.js.map} +1 -1
  203. package/dist/web/public/assets/{plans-i3a6lrqF.js → plans-Bo5LlLeH.js} +3 -8
  204. package/dist/web/public/assets/plans-Bo5LlLeH.js.map +1 -0
  205. package/dist/web/public/assets/{play-CPoE_JnS.js → play-DX5wp4WH.js} +2 -2
  206. package/dist/web/public/assets/{play-CPoE_JnS.js.map → play-DX5wp4WH.js.map} +1 -1
  207. package/dist/web/public/assets/{plus-CfzKV_0u.js → plus-DH4J_YhN.js} +2 -2
  208. package/dist/web/public/assets/{plus-CfzKV_0u.js.map → plus-DH4J_YhN.js.map} +1 -1
  209. package/dist/web/public/assets/policy-BrgOuDt_.js +2 -0
  210. package/dist/web/public/assets/{policy-Cm88P8LO.js.map → policy-BrgOuDt_.js.map} +1 -1
  211. package/dist/web/public/assets/{qr-code-DMkV8nv2.js → qr-code-YrEuhMPC.js} +2 -2
  212. package/dist/web/public/assets/{qr-code-DMkV8nv2.js.map → qr-code-YrEuhMPC.js.map} +1 -1
  213. package/dist/web/public/assets/{refresh-ccw-nBMm5Xal.js → refresh-ccw-DlAd-eTQ.js} +2 -2
  214. package/dist/web/public/assets/{refresh-ccw-nBMm5Xal.js.map → refresh-ccw-DlAd-eTQ.js.map} +1 -1
  215. package/dist/web/public/assets/{reminders-DjEujanC.js → reminders-DBEE0zXG.js} +3 -3
  216. package/dist/web/public/assets/{reminders-DjEujanC.js.map → reminders-DBEE0zXG.js.map} +1 -1
  217. package/dist/web/public/assets/{save-DbrrCFDM.js → save-BDOtZrfp.js} +2 -2
  218. package/dist/web/public/assets/{save-DbrrCFDM.js.map → save-BDOtZrfp.js.map} +1 -1
  219. package/dist/web/public/assets/schedules-DAyhVI8-.js +2 -0
  220. package/dist/web/public/assets/schedules-DAyhVI8-.js.map +1 -0
  221. package/dist/web/public/assets/{search-5q3dkINm.js → search-55mtgHrB.js} +3 -3
  222. package/dist/web/public/assets/{search-5q3dkINm.js.map → search-55mtgHrB.js.map} +1 -1
  223. package/dist/web/public/assets/{search-DbE4VEm9.js → search-CAICU3aU.js} +2 -2
  224. package/dist/web/public/assets/{search-DbE4VEm9.js.map → search-CAICU3aU.js.map} +1 -1
  225. package/dist/web/public/assets/security-CbP4QgVp.js +2 -0
  226. package/dist/web/public/assets/security-CbP4QgVp.js.map +1 -0
  227. package/dist/web/public/assets/server-Dg4e8pvm.js +7 -0
  228. package/dist/web/public/assets/server-Dg4e8pvm.js.map +1 -0
  229. package/dist/web/public/assets/service-gWZa3sup.js +7 -0
  230. package/dist/web/public/assets/service-gWZa3sup.js.map +1 -0
  231. package/dist/web/public/assets/{shield-alert-WOa69jy3.js → shield-alert-DOKK9EnJ.js} +2 -2
  232. package/dist/web/public/assets/{shield-alert-WOa69jy3.js.map → shield-alert-DOKK9EnJ.js.map} +1 -1
  233. package/dist/web/public/assets/sparkles-G0QIs9nP.js +7 -0
  234. package/dist/web/public/assets/sparkles-G0QIs9nP.js.map +1 -0
  235. package/dist/web/public/assets/start-D-abhl3q.js +2 -0
  236. package/dist/web/public/assets/start-D-abhl3q.js.map +1 -0
  237. package/dist/web/public/assets/{status-badge-D5xhwquL.js → status-badge-CyLdpsXq.js} +2 -2
  238. package/dist/web/public/assets/{status-badge-D5xhwquL.js.map → status-badge-CyLdpsXq.js.map} +1 -1
  239. package/dist/web/public/assets/{subtasks-DMRyk6YS.js → subtasks-BnEjSGUR.js} +3 -3
  240. package/dist/web/public/assets/{subtasks-DMRyk6YS.js.map → subtasks-BnEjSGUR.js.map} +1 -1
  241. package/dist/web/public/assets/{table-Dx65w6V0.js → table-sCMZBe_Z.js} +2 -2
  242. package/dist/web/public/assets/{table-Dx65w6V0.js.map → table-sCMZBe_Z.js.map} +1 -1
  243. package/dist/web/public/assets/terminal-_pXeEjXG.js +7 -0
  244. package/dist/web/public/assets/terminal-_pXeEjXG.js.map +1 -0
  245. package/dist/web/public/assets/{topn-L7Juczp3.js → topn-D1B-gS1M.js} +3 -3
  246. package/dist/web/public/assets/{topn-L7Juczp3.js.map → topn-D1B-gS1M.js.map} +1 -1
  247. package/dist/web/public/assets/{trash-2-7xrfqd-v.js → trash-2-D2x2UPuZ.js} +2 -2
  248. package/dist/web/public/assets/{trash-2-7xrfqd-v.js.map → trash-2-D2x2UPuZ.js.map} +1 -1
  249. package/dist/web/public/assets/use-a2a-C98e2Via.js +2 -0
  250. package/dist/web/public/assets/use-a2a-C98e2Via.js.map +1 -0
  251. package/dist/web/public/assets/{use-agim-skills-pFjfgqMF.js → use-agim-skills-BbuJP3NT.js} +2 -2
  252. package/dist/web/public/assets/{use-agim-skills-pFjfgqMF.js.map → use-agim-skills-BbuJP3NT.js.map} +1 -1
  253. package/dist/web/public/assets/use-background-tasks-CwFmOokw.js +2 -0
  254. package/dist/web/public/assets/{use-background-tasks-D1--hHjp.js.map → use-background-tasks-CwFmOokw.js.map} +1 -1
  255. package/dist/web/public/assets/use-jobs-BJjeJ5lh.js +2 -0
  256. package/dist/web/public/assets/use-jobs-BJjeJ5lh.js.map +1 -0
  257. package/dist/web/public/assets/use-memory-CXDwKCco.js +2 -0
  258. package/dist/web/public/assets/{use-memory-Bz1Zao7g.js.map → use-memory-CXDwKCco.js.map} +1 -1
  259. package/dist/web/public/assets/use-observability-CY5ZUPrC.js +2 -0
  260. package/dist/web/public/assets/{use-observability-DtqSWVjM.js.map → use-observability-CY5ZUPrC.js.map} +1 -1
  261. package/dist/web/public/assets/use-outbox-DT_XWB_7.js +7 -0
  262. package/dist/web/public/assets/use-outbox-DT_XWB_7.js.map +1 -0
  263. package/dist/web/public/assets/use-schedules-D4W8fMwo.js +7 -0
  264. package/dist/web/public/assets/use-schedules-D4W8fMwo.js.map +1 -0
  265. package/dist/web/public/assets/use-settings-DGIjmUX0.js +2 -0
  266. package/dist/web/public/assets/use-settings-DGIjmUX0.js.map +1 -0
  267. package/dist/web/public/assets/use-skills-D2bMM580.js +7 -0
  268. package/dist/web/public/assets/use-skills-D2bMM580.js.map +1 -0
  269. package/dist/web/public/assets/use-vector-BYOFwjU0.js +2 -0
  270. package/dist/web/public/assets/use-vector-BYOFwjU0.js.map +1 -0
  271. package/dist/web/public/assets/use-workspace-CuytyHwb.js +2 -0
  272. package/dist/web/public/assets/{use-workspace-CConjEx0.js.map → use-workspace-CuytyHwb.js.map} +1 -1
  273. package/dist/web/public/assets/vector-CL8ezpSR.js +2 -0
  274. package/dist/web/public/assets/vector-CL8ezpSR.js.map +1 -0
  275. package/dist/web/public/assets/viewer-CD0iEfPU.js +7 -0
  276. package/dist/web/public/assets/viewer-CD0iEfPU.js.map +1 -0
  277. package/dist/web/public/assets/workspace-BA1_hso3.js +17 -0
  278. package/dist/web/public/assets/workspace-BA1_hso3.js.map +1 -0
  279. package/dist/web/public/assets/workspaces-DyGLJUgB.js +7 -0
  280. package/dist/web/public/assets/workspaces-DyGLJUgB.js.map +1 -0
  281. package/dist/web/public/index.html +2 -2
  282. package/dist/web/server.d.ts +0 -3
  283. package/dist/web/server.d.ts.map +1 -1
  284. package/dist/web/server.js +138 -3
  285. package/dist/web/server.js.map +1 -1
  286. package/package.json +1 -1
  287. package/dist/web/public/assets/a2a-D7MoJ1iT.js +0 -7
  288. package/dist/web/public/assets/a2a-D7MoJ1iT.js.map +0 -1
  289. package/dist/web/public/assets/agents-BXThDW6f.js +0 -7
  290. package/dist/web/public/assets/bgjobs-Rc05aEy9.js +0 -7
  291. package/dist/web/public/assets/bgjobs-Rc05aEy9.js.map +0 -1
  292. package/dist/web/public/assets/chat-DQpQLW9j.js +0 -17
  293. package/dist/web/public/assets/chat-DQpQLW9j.js.map +0 -1
  294. package/dist/web/public/assets/circle-check-DZnkaUdk.js +0 -7
  295. package/dist/web/public/assets/circle-check-DZnkaUdk.js.map +0 -1
  296. package/dist/web/public/assets/confirm-dialog-gPKJnvEW.js +0 -2
  297. package/dist/web/public/assets/health-wqCp-K_o.js +0 -2
  298. package/dist/web/public/assets/hot-B-CMjQIr.js +0 -12
  299. package/dist/web/public/assets/index-DHh1LYlA.js +0 -209
  300. package/dist/web/public/assets/index-DHh1LYlA.js.map +0 -1
  301. package/dist/web/public/assets/index-DknVjPYB.css +0 -1
  302. package/dist/web/public/assets/installed-Cet-1M2Q.js.map +0 -1
  303. package/dist/web/public/assets/jobs-CfEzOOAC.js +0 -2
  304. package/dist/web/public/assets/jobs-CfEzOOAC.js.map +0 -1
  305. package/dist/web/public/assets/layout-BX43KyXM.js +0 -2
  306. package/dist/web/public/assets/layout-BX43KyXM.js.map +0 -1
  307. package/dist/web/public/assets/layout-BcYZlaqf.js +0 -2
  308. package/dist/web/public/assets/layout-BcYZlaqf.js.map +0 -1
  309. package/dist/web/public/assets/layout-Cb7looUv.js +0 -2
  310. package/dist/web/public/assets/layout-Cb7looUv.js.map +0 -1
  311. package/dist/web/public/assets/layout-D7xH78OU.js +0 -2
  312. package/dist/web/public/assets/layout-D7xH78OU.js.map +0 -1
  313. package/dist/web/public/assets/llm-BZ9qqp-D.js +0 -27
  314. package/dist/web/public/assets/llm-BZ9qqp-D.js.map +0 -1
  315. package/dist/web/public/assets/loader-circle-DgdBWYl0.js +0 -7
  316. package/dist/web/public/assets/memos-BBtqFcoH.js +0 -12
  317. package/dist/web/public/assets/memos-BBtqFcoH.js.map +0 -1
  318. package/dist/web/public/assets/messengers-i7WvNT3o.js +0 -2
  319. package/dist/web/public/assets/messengers-i7WvNT3o.js.map +0 -1
  320. package/dist/web/public/assets/outbox-BbfC5kuG.js +0 -7
  321. package/dist/web/public/assets/outbox-BbfC5kuG.js.map +0 -1
  322. package/dist/web/public/assets/persona-BvtcZh6G.js +0 -2
  323. package/dist/web/public/assets/plans-i3a6lrqF.js.map +0 -1
  324. package/dist/web/public/assets/policy-Cm88P8LO.js +0 -2
  325. package/dist/web/public/assets/schedules-DzwDWykc.js +0 -7
  326. package/dist/web/public/assets/schedules-DzwDWykc.js.map +0 -1
  327. package/dist/web/public/assets/security-BIcnUrAs.js +0 -2
  328. package/dist/web/public/assets/security-BIcnUrAs.js.map +0 -1
  329. package/dist/web/public/assets/service-CnorFHzZ.js +0 -7
  330. package/dist/web/public/assets/service-CnorFHzZ.js.map +0 -1
  331. package/dist/web/public/assets/use-background-tasks-D1--hHjp.js +0 -2
  332. package/dist/web/public/assets/use-memory-Bz1Zao7g.js +0 -2
  333. package/dist/web/public/assets/use-observability-DtqSWVjM.js +0 -2
  334. package/dist/web/public/assets/use-settings-DKbDqCEJ.js +0 -2
  335. package/dist/web/public/assets/use-settings-DKbDqCEJ.js.map +0 -1
  336. package/dist/web/public/assets/use-workspace-CConjEx0.js +0 -2
  337. package/dist/web/public/assets/vector-D8sEa2W-.js +0 -2
  338. package/dist/web/public/assets/vector-D8sEa2W-.js.map +0 -1
  339. package/dist/web/public/assets/viewer-aSIjAKVA.js +0 -12
  340. package/dist/web/public/assets/viewer-aSIjAKVA.js.map +0 -1
  341. package/dist/web/public/assets/workspace-BqwWoinI.js +0 -17
  342. package/dist/web/public/assets/workspace-BqwWoinI.js.map +0 -1
  343. package/dist/web/public/assets/workspaces-ChsJcrav.js +0 -7
  344. package/dist/web/public/assets/workspaces-ChsJcrav.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspace-BA1_hso3.js","sources":["../../node_modules/lucide-react/dist/esm/icons/file.js","../../node_modules/lucide-react/dist/esm/icons/folder-tree.js","../../node_modules/lucide-react/dist/esm/icons/folder.js","../../src/routes/workspace.tsx"],"sourcesContent":["/**\n * @license lucide-react v0.469.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst File = createLucideIcon(\"File\", [\n [\"path\", { d: \"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z\", key: \"1rqfz7\" }],\n [\"path\", { d: \"M14 2v4a2 2 0 0 0 2 2h4\", key: \"tnqrlb\" }]\n]);\n\nexport { File as default };\n//# sourceMappingURL=file.js.map\n","/**\n * @license lucide-react v0.469.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst FolderTree = createLucideIcon(\"FolderTree\", [\n [\n \"path\",\n {\n d: \"M20 10a1 1 0 0 0 1-1V6a1 1 0 0 0-1-1h-2.5a1 1 0 0 1-.8-.4l-.9-1.2A1 1 0 0 0 15 3h-2a1 1 0 0 0-1 1v5a1 1 0 0 0 1 1Z\",\n key: \"hod4my\"\n }\n ],\n [\n \"path\",\n {\n d: \"M20 21a1 1 0 0 0 1-1v-3a1 1 0 0 0-1-1h-2.9a1 1 0 0 1-.88-.55l-.42-.85a1 1 0 0 0-.92-.6H13a1 1 0 0 0-1 1v5a1 1 0 0 0 1 1Z\",\n key: \"w4yl2u\"\n }\n ],\n [\"path\", { d: \"M3 5a2 2 0 0 0 2 2h3\", key: \"f2jnh7\" }],\n [\"path\", { d: \"M3 3v13a2 2 0 0 0 2 2h3\", key: \"k8epm1\" }]\n]);\n\nexport { FolderTree as default };\n//# sourceMappingURL=folder-tree.js.map\n","/**\n * @license lucide-react v0.469.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Folder = createLucideIcon(\"Folder\", [\n [\n \"path\",\n {\n d: \"M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z\",\n key: \"1kt360\"\n }\n ]\n]);\n\nexport { Folder as default };\n//# sourceMappingURL=folder.js.map\n","/**\n * /workspace — file browser + editor for the per-agent CWD.\n *\n * Single-column finder UI: pick an agent → drill into the workspace\n * via ?path=, click a file → opens the editor pane below the\n * listing. No recursive tree because the listing handler is cheap\n * and the typical workspace has ≤ 30 entries per dir.\n *\n * Editor is a plain `<textarea>` — Monaco / CodeMirror would balloon\n * the bundle for what is realistically operator-edits to\n * CLAUDE.md / AGENTS.md / config snippets. Binary files render a\n * read-only placeholder. Truncated files (> 1 MiB) block save to\n * prevent destructive overwrites.\n */\n\nimport { useEffect, useMemo, useState } from 'react'\nimport { useSearchParams } from 'react-router-dom'\nimport { useTranslation } from 'react-i18next'\nimport { toast } from 'sonner'\nimport {\n BookOpen,\n ChevronUp,\n File,\n FileText,\n Folder,\n FolderTree,\n Loader2,\n RefreshCcw,\n} from 'lucide-react'\n\nimport { Topbar } from '@/components/shell/topbar'\nimport { EmptyState } from '@/components/common/empty-state'\nimport { Badge } from '@/components/ui/badge'\nimport { Button } from '@/components/ui/button'\nimport { Label } from '@/components/ui/label'\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@/components/ui/select'\nimport {\n useAgentsStatus,\n useWorkspaceFiles,\n useWriteWorkspaceFile,\n} from '@/hooks/use-workspace'\nimport { useConfig } from '@/hooks/use-settings'\nimport { describeError } from '@/lib/api/errors'\nimport { agentDisplayName } from '@/lib/agent-label'\nimport type {\n WorkspaceFileContent,\n WorkspaceFileEntry,\n} from '@/types/api'\nimport { cn } from '@/lib/utils'\n\nexport default function WorkspaceRoute(): JSX.Element {\n const { t } = useTranslation(['workspace', 'common'])\n const [params, setParams] = useSearchParams()\n const agent = params.get('agent') ?? ''\n const path = params.get('path') ?? ''\n\n const agentsQuery = useAgentsStatus()\n const cfgQuery = useConfig()\n const agents = agentsQuery.data ?? {}\n const agentNames = useMemo(() => Object.keys(agents).sort(), [agents])\n const agentKey = agentNames.join('\\0')\n const defaultAgent = cfgQuery.data?.defaultAgent\n\n /** Query may resolve to either a dir listing or file content — we\n * branch on `data.type` in the render. */\n const filesQuery = useWorkspaceFiles(agent, path, { enabled: Boolean(agent) })\n const data = filesQuery.data\n const isDir = data?.type === 'dir'\n const isFile = data?.type === 'file'\n\n function patchParams(patch: Record<string, string | null>): void {\n const next = new URLSearchParams(params)\n for (const [k, v] of Object.entries(patch)) {\n if (v == null || v === '') next.delete(k)\n else next.set(k, v)\n }\n setParams(next, { replace: false })\n }\n\n useEffect(() => {\n if (agent || agentsQuery.isLoading) return\n const preferred = defaultAgent && agentNames.includes(defaultAgent)\n ? defaultAgent\n : agentNames.length === 1\n ? agentNames[0]\n : ''\n if (!preferred) return\n const next = new URLSearchParams(params)\n next.set('agent', preferred)\n next.delete('path')\n setParams(next, { replace: true })\n }, [agent, agentKey, agentNames, agentsQuery.isLoading, defaultAgent, params, setParams])\n\n function setAgent(next: string): void {\n // Switching agent always resets the path so we don't drag a\n // claude-specific path into codex's workspace.\n patchParams({ agent: next || null, path: null })\n }\n function navigateTo(nextPath: string): void {\n patchParams({ path: nextPath || null })\n }\n function navigateUp(): void {\n if (!path) return\n const idx = path.lastIndexOf('/')\n const parent = idx >= 0 ? path.slice(0, idx) : ''\n navigateTo(parent)\n }\n\n return (\n <div className=\"flex min-h-dvh flex-col bg-bg\">\n <Topbar />\n\n <main className=\"mx-auto flex w-full max-w-7xl flex-1 flex-col gap-4 px-3 py-4 sm:px-4 pb-safe\">\n <header className=\"flex flex-col gap-1\">\n <div className=\"flex flex-wrap items-center gap-3\">\n <h1 className=\"text-xl font-semibold\">{t('pageTitle')}</h1>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"ml-auto\"\n onClick={() => filesQuery.refetch()}\n disabled={!agent || filesQuery.isFetching}\n aria-label={t('actions.refresh', { ns: 'common' })}\n >\n {filesQuery.isFetching ? <Loader2 className=\"h-4 w-4 animate-spin\" /> : <RefreshCcw className=\"h-4 w-4\" />}\n <span className=\"hidden sm:inline\">{t('actions.refresh', { ns: 'common' })}</span>\n </Button>\n </div>\n <p className=\"text-sm text-text-dim\">{t('subtitle')}</p>\n </header>\n\n {/* Agent picker */}\n <div className=\"flex flex-wrap items-end gap-2\">\n <div className=\"flex flex-col gap-1\">\n <Label htmlFor=\"agent\" className=\"text-xs text-text-dim\">\n {t('agentPicker.label')}\n </Label>\n <Select value={agent || '__placeholder__'} onValueChange={(v) => setAgent(v === '__placeholder__' ? '' : v)}>\n <SelectTrigger id=\"agent\" className=\"w-64\">\n <SelectValue placeholder={t('agentPicker.placeholder')} />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"__placeholder__\" disabled>\n {t('agentPicker.placeholder')}\n </SelectItem>\n {agentNames.map((name) => (\n <SelectItem key={name} value={name}>\n <span className=\"flex items-center gap-2\">\n <span className=\"font-mono text-xs\">{agentDisplayName(name)}</span>\n <span className={cn(\n 'inline-block h-1.5 w-1.5 rounded-full',\n agents[name] ? 'bg-success' : 'bg-text-muted',\n )} />\n <span className=\"text-text-dim text-xs\">\n {agents[name] ? t('agentPicker.online') : t('agentPicker.offline')}\n </span>\n </span>\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n </div>\n\n {!agent ? (\n <EmptyState\n icon={<FolderTree />}\n title={t('noAgent.title')}\n description={t('noAgent.description')}\n />\n ) : (\n <>\n <WorkspaceStartCard\n agent={agent}\n onNavigate={navigateTo}\n />\n\n {/* Breadcrumb + Up */}\n <Breadcrumb\n path={path}\n onNavigate={navigateTo}\n onUp={navigateUp}\n />\n\n {filesQuery.isLoading ? (\n <div className=\"h-32 rounded-md bg-surface-2 animate-pulse\" />\n ) : isDir && data?.type === 'dir' ? (\n <DirListing\n entries={data.entries}\n onEnter={(entry) => navigateTo(\n path ? `${path}/${entry.name}` : entry.name,\n )}\n />\n ) : isFile && data?.type === 'file' ? (\n <FileEditor\n file={data}\n agent={agent}\n onBack={navigateUp}\n />\n ) : path && filesQuery.isError && canCreateMissingFile(path, filesQuery.error) ? (\n <MissingFilePanel\n agent={agent}\n path={path}\n onCreated={() => { void filesQuery.refetch() }}\n />\n ) : (\n <EmptyState\n icon={<FolderTree />}\n title={t('editor.loadFailed')}\n description={filesQuery.error?.message ?? ''}\n />\n )}\n </>\n )}\n </main>\n </div>\n )\n}\n\ninterface WorkspaceStartCardProps {\n agent: string\n onNavigate: (path: string) => void\n}\n\nfunction WorkspaceStartCard({ agent, onNavigate }: WorkspaceStartCardProps): JSX.Element {\n const { t } = useTranslation('workspace')\n const roleFile = roleFileForAgent(agent)\n return (\n <section className=\"rounded-md border border-border bg-surface p-4\">\n <div className=\"flex flex-col gap-3 sm:flex-row sm:items-center\">\n <span className=\"flex h-9 w-9 shrink-0 items-center justify-center rounded-full bg-accent-bg text-accent\">\n <BookOpen className=\"h-4 w-4\" />\n </span>\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <h2 className=\"text-sm font-semibold\">{t('quick.title')}</h2>\n <Badge variant=\"info\">{agentDisplayName(agent)}</Badge>\n </div>\n <p className=\"mt-1 text-sm text-text-dim\">{t('quick.detail')}</p>\n </div>\n <div className=\"flex flex-wrap gap-2\">\n <Button type=\"button\" size=\"sm\" onClick={() => onNavigate(roleFile)}>\n <FileText className=\"h-4 w-4\" />\n <span>{t('quick.openRoleFile')}</span>\n </Button>\n <Button type=\"button\" variant=\"secondary\" size=\"sm\" onClick={() => onNavigate('MEMORY.md')}>\n <FileText className=\"h-4 w-4\" />\n <span>{t('quick.openMemory')}</span>\n </Button>\n </div>\n </div>\n </section>\n )\n}\n\nfunction roleFileForAgent(agent: string): string {\n return agent === 'claude-code' ? 'CLAUDE.md' : 'AGENTS.md'\n}\n\ninterface MissingFilePanelProps {\n agent: string\n path: string\n onCreated: () => void\n}\n\nfunction MissingFilePanel({ agent, path, onCreated }: MissingFilePanelProps): JSX.Element {\n const { t } = useTranslation('workspace')\n const write = useWriteWorkspaceFile()\n const isMemory = path === 'MEMORY.md'\n\n async function onCreate(): Promise<void> {\n try {\n await write.mutateAsync({\n agent,\n path,\n body: { content: t(isMemory ? 'quick.memoryTemplate' : 'quick.fileTemplate') },\n })\n toast.success(t('toast.created', { path }))\n onCreated()\n } catch (err) {\n toast.error(describeError(err, t).message)\n }\n }\n\n return (\n <section className=\"rounded-md border border-border bg-surface p-4\">\n <div className=\"flex flex-col gap-3 sm:flex-row sm:items-center\">\n <span className=\"flex h-9 w-9 shrink-0 items-center justify-center rounded-full bg-surface-2 text-text-dim\">\n <FileText className=\"h-4 w-4\" />\n </span>\n <div className=\"min-w-0 flex-1\">\n <h2 className=\"text-sm font-semibold\">{t('quick.missingTitle')}</h2>\n <p className=\"mt-1 text-sm text-text-dim\">{t('quick.missingDetail', { path })}</p>\n </div>\n <Button\n type=\"button\"\n size=\"sm\"\n onClick={() => void onCreate()}\n disabled={write.isPending}\n >\n {write.isPending ? <Loader2 className=\"h-4 w-4 animate-spin\" /> : <FileText className=\"h-4 w-4\" />}\n <span>{t(isMemory ? 'quick.createMemory' : 'quick.createFile')}</span>\n </Button>\n </div>\n </section>\n )\n}\n\nfunction canCreateMissingFile(path: string, error: unknown): boolean {\n if (path.includes('/')) return false\n if (!path.endsWith('.md')) return false\n const message = error instanceof Error ? error.message.toLowerCase() : String(error).toLowerCase()\n return message.includes('not found')\n || message.includes('enoent')\n || message.includes('no such file')\n}\n\ninterface BreadcrumbProps {\n path: string\n onNavigate: (path: string) => void\n onUp: () => void\n}\n\nfunction Breadcrumb({ path, onNavigate, onUp }: BreadcrumbProps): JSX.Element {\n const { t } = useTranslation('workspace')\n const parts = path ? path.split('/') : []\n return (\n <div className=\"flex flex-wrap items-center gap-1 text-sm\">\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n onClick={onUp}\n disabled={!path}\n aria-label={t('tree.up')}\n >\n <ChevronUp className=\"h-4 w-4\" />\n </Button>\n <button\n type=\"button\"\n onClick={() => onNavigate('')}\n className=\"text-text-dim hover:text-text rounded px-1 py-0.5\"\n >\n {t('tree.rootLabel')}\n </button>\n {parts.map((part, i) => {\n const upto = parts.slice(0, i + 1).join('/')\n return (\n <span key={upto} className=\"flex items-center gap-1\">\n <span className=\"text-text-muted\">/</span>\n <button\n type=\"button\"\n onClick={() => onNavigate(upto)}\n className=\"text-text-dim hover:text-text rounded px-1 py-0.5\"\n >\n {part}\n </button>\n </span>\n )\n })}\n </div>\n )\n}\n\ninterface DirListingProps {\n entries: WorkspaceFileEntry[]\n onEnter: (entry: WorkspaceFileEntry) => void\n}\n\nfunction DirListing({ entries, onEnter }: DirListingProps): JSX.Element {\n const { t } = useTranslation('workspace')\n if (entries.length === 0) {\n return <div className=\"rounded-md border border-border bg-surface p-3 text-sm text-text-dim\">{t('tree.empty')}</div>\n }\n return (\n <ul className=\"divide-y divide-border rounded-md border border-border bg-surface\">\n {entries.map((e) => (\n <li key={e.name}>\n <button\n type=\"button\"\n onClick={() => onEnter(e)}\n disabled={e.broken || e.symlink_escape}\n className={cn(\n 'flex w-full items-center gap-2 px-3 py-2 text-sm text-left',\n 'transition-colors hover:bg-surface-hover disabled:opacity-50 disabled:cursor-not-allowed',\n )}\n >\n {e.isDir ? <Folder className=\"h-4 w-4 text-accent\" /> : <File className=\"h-4 w-4 text-text-dim\" />}\n <span className={e.isDir ? 'font-medium text-text' : 'text-text'}>{e.name}</span>\n {e.symlink_escape && (\n <Badge variant=\"warning\" className=\"ml-2\">{t('tree.symlinkEscape')}</Badge>\n )}\n {e.broken && !e.symlink_escape && (\n <Badge variant=\"danger\" className=\"ml-2\">{t('tree.broken')}</Badge>\n )}\n {!e.isDir && e.size != null && (\n <span className=\"ml-auto text-xs text-text-muted tabular-nums\">{formatSize(e.size)}</span>\n )}\n {e.mtime && (\n <span className={cn('text-xs text-text-muted tabular-nums', !e.isDir && e.size != null ? 'ml-3' : 'ml-auto')}>\n {formatTime(e.mtime)}\n </span>\n )}\n </button>\n </li>\n ))}\n </ul>\n )\n}\n\ninterface FileEditorProps {\n file: WorkspaceFileContent\n agent: string\n onBack: () => void\n}\n\nfunction FileEditor({ file, agent, onBack }: FileEditorProps): JSX.Element {\n const { t } = useTranslation(['workspace', 'common'])\n const [draft, setDraft] = useState(file.content)\n useEffect(() => { setDraft(file.content) }, [file.content])\n const dirty = draft !== file.content\n\n const write = useWriteWorkspaceFile()\n\n async function onSave(): Promise<void> {\n try {\n await write.mutateAsync({ agent, path: file.path, body: { content: draft } })\n toast.success(t('toast.saved', { path: file.path }))\n } catch (err) {\n const { message } = describeError(err, t)\n toast.error(message)\n }\n }\n\n if (file.encoding === 'base64') {\n return (\n <div className=\"rounded-md border border-border bg-surface p-4 text-sm\">\n <Button variant=\"ghost\" size=\"sm\" onClick={onBack} className=\"mb-3\">\n <ChevronUp className=\"h-4 w-4\" />\n {t('tree.up')}\n </Button>\n <p className=\"text-text-dim\">{t('editor.binary')}</p>\n <p className=\"mt-2 text-xs text-text-muted tabular-nums\">\n {file.path} · {formatSize(file.size)}\n </p>\n </div>\n )\n }\n\n return (\n <div className=\"flex flex-col gap-2\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <Button variant=\"ghost\" size=\"sm\" onClick={onBack}>\n <ChevronUp className=\"h-4 w-4\" />\n {t('tree.up')}\n </Button>\n <code className=\"rounded bg-surface-2 px-1.5 py-0.5 text-xs font-mono\">{file.path}</code>\n {file.truncated && <Badge variant=\"warning\">{t('editor.truncatedBadge')}</Badge>}\n {dirty && <Badge variant=\"info\">{t('editor.dirtyHint')}</Badge>}\n <Button\n type=\"button\"\n size=\"sm\"\n className=\"ml-auto\"\n onClick={() => void onSave()}\n disabled={!dirty || write.isPending || file.truncated}\n >\n {write.isPending ? <Loader2 className=\"h-4 w-4 animate-spin\" /> : null}\n {write.isPending ? t('editor.saving') : t('editor.save')}\n </Button>\n </div>\n {file.truncated && (\n <p className=\"text-xs text-warning\">{t('editor.truncated')}</p>\n )}\n <textarea\n value={draft}\n onChange={(e) => setDraft(e.target.value)}\n rows={24}\n spellCheck={false}\n className={cn(\n 'w-full resize-y rounded-md border bg-bg px-3 py-2',\n 'font-mono text-xs leading-5',\n 'focus:outline-none focus:ring-2 focus:ring-accent focus:ring-offset-1 focus:ring-offset-bg',\n dirty ? 'border-accent' : 'border-border',\n )}\n />\n {!dirty && (\n <p className=\"text-xs text-text-muted\">\n {t('editor.savedMeta', { size: file.size, at: formatTime(file.mtime) })}\n </p>\n )}\n </div>\n )\n}\n\nfunction formatTime(iso: string | null): string {\n if (iso == null) return '—'\n try {\n const d = new Date(iso)\n if (Number.isNaN(d.getTime())) return iso\n return d.toLocaleString(undefined, { month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' })\n } catch {\n return iso\n }\n}\n\nfunction formatSize(n: number): string {\n if (n < 1024) return `${n} B`\n if (n < 1024 * 1024) return `${(n / 1024).toFixed(1)} KiB`\n return `${(n / 1024 / 1024).toFixed(1)} MiB`\n}\n"],"names":["File","createLucideIcon","FolderTree","Folder","WorkspaceRoute","t","useTranslation","params","setParams","useSearchParams","agent","path","agentsQuery","useAgentsStatus","cfgQuery","useConfig","agents","agentNames","useMemo","agentKey","defaultAgent","filesQuery","useWorkspaceFiles","data","isDir","isFile","patchParams","patch","next","k","v","useEffect","preferred","setAgent","navigateTo","nextPath","navigateUp","idx","parent","jsxs","jsx","Topbar","Button","Loader2","RefreshCcw","Label","Select","SelectTrigger","SelectValue","SelectContent","SelectItem","name","agentDisplayName","cn","Fragment","WorkspaceStartCard","Breadcrumb","DirListing","entry","FileEditor","canCreateMissingFile","MissingFilePanel","EmptyState","onNavigate","roleFile","roleFileForAgent","BookOpen","Badge","FileText","onCreated","write","useWriteWorkspaceFile","isMemory","onCreate","toast","err","describeError","error","message","onUp","parts","ChevronUp","part","i","upto","entries","onEnter","e","formatSize","formatTime","file","onBack","draft","setDraft","useState","dirty","onSave","iso","d","n"],"mappings":"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","x_google_ignoreList":[0,1,2]}
@@ -0,0 +1,7 @@
1
+ import{h as $,u as R,j as e,e as f,d as P,f as H,p as D,q as F,w as B,I,X as q}from"./index-DCfdN5R7.js";import{r as h}from"./react-DlP5eolq.js";import{C as Q}from"./confirm-dialog-BDb0NLny.js";import{E as _}from"./empty-state-CuiqdZiB.js";import{T as X,a as Y,b as A,c as k,d as G,e as N}from"./table-sCMZBe_Z.js";import{D as J,a as Z,b as V,d as ee,e as se,f as te}from"./dropdown-menu-BNH5SrVb.js";import{u as ae}from"./use-workspace-CuytyHwb.js";import{r as re,m as ne,s as ie,t as oe}from"./use-settings-DGIjmUX0.js";import{L as E}from"./loader-circle-DDdmcH0k.js";import{R as le}from"./refresh-ccw-DlAd-eTQ.js";import{B as ce}from"./briefcase-CeKUkFSq.js";import{T as me}from"./trash-2-D2x2UPuZ.js";import{S as de}from"./save-BDOtZrfp.js";import{P as xe}from"./plus-DH4J_YhN.js";import"./chevron-right-CFRb-SM_.js";/**
2
+ * @license lucide-react v0.469.0 - ISC
3
+ *
4
+ * This source code is licensed under the ISC license.
5
+ * See the LICENSE file in the root directory of this source tree.
6
+ */const ue=$("Pencil",[["path",{d:"M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z",key:"1a8usu"}],["path",{d:"m15 5 4 4",key:"1mk7zo"}]]),z={id:"",name:"",agents:[],members:[],rate:"",intervalSec:"",burst:""},pe=[{id:"default",labelKey:"workspaces.form.ratePresets.default",descriptionKey:"workspaces.form.ratePresetDescriptions.default",rate:"",intervalSec:"",burst:""},{id:"strict",labelKey:"workspaces.form.ratePresets.strict",descriptionKey:"workspaces.form.ratePresetDescriptions.strict",rate:"3",intervalSec:"60",burst:"5"},{id:"busy",labelKey:"workspaces.form.ratePresets.busy",descriptionKey:"workspaces.form.ratePresetDescriptions.busy",rate:"30",intervalSec:"60",burst:"45"}];function fe(s){return{id:s.id,name:s.name,agents:v(s.agents),members:v(s.members??[]),rate:s.rateLimit?String(s.rateLimit.rate):"",intervalSec:s.rateLimit?String(s.rateLimit.intervalSec):"",burst:s.rateLimit?String(s.rateLimit.burst):""}}function he(s){const n={id:s.id.trim(),name:s.name.trim()||s.id.trim(),agents:v(s.agents),members:v(s.members)},c=Number(s.rate),d=Number(s.intervalSec),l=Number(s.burst);return Number.isFinite(c)&&c>0&&Number.isFinite(d)&&d>0&&Number.isFinite(l)&&l>0&&(n.rateLimit={rate:c,intervalSec:d,burst:l}),n}function be(s,n){return s.rate===n.rate&&s.intervalSec===n.intervalSec&&s.burst===n.burst}function ze(){const{t:s}=R(["settings","common"]),n=re(),c=ae(),d=ne(),l=ie(),w=oe(),[i,m]=h.useState(z),[y,b]=h.useState(null),[u,g]=h.useState(null);h.useEffect(()=>{i.id||i.name},[i.id,i.name]);function C(t){m(fe(t)),b(t.id)}function x(){m(z),b(null)}async function L(t){t.preventDefault();const a=he(i);if(a.id)try{await l.mutateAsync(a),D.success(s("workspaces.toast.saved")),x()}catch(o){D.error(F(o,s).message)}}async function T(){if(u)try{await w.mutateAsync(u.id),D.success(s("workspaces.toast.deleted")),y===u.id&&x(),g(null)}catch(t){throw D.error(F(t,s).message),t}}function M(t){m(a=>({...a,rate:t.rate,intervalSec:t.intervalSec,burst:t.burst}))}const p=n.data?.workspaces??[],r=p.length<=1&&p.every(t=>t.id==="default"),j=h.useMemo(()=>{const t=c.data??{};return Object.entries(t).sort(([a,o],[W,U])=>o!==U?o?-1:1:a.localeCompare(W)).map(([a,o])=>({value:a,label:a,badge:s(o?"workspaces.form.agentOnline":"workspaces.form.agentOffline"),muted:!o}))},[c.data,s]),O=h.useMemo(()=>{const t=new Map;for(const a of d.data?.knownUsers??[]){const o=ge(a);t.set(o,{value:o,label:o,detail:s("workspaces.form.memberLastSeen",{time:je(a.lastSeenAt)})})}for(const a of p)for(const o of a.members??[])o&&(t.has(o)||t.set(o,{value:o,label:o,detail:s("workspaces.form.memberFromScope",{scope:a.id})}));return[...t.values()].sort((a,o)=>a.label.localeCompare(o.label))},[d.data?.knownUsers,s,p]);return e.jsxs("div",{className:"mx-auto flex max-w-5xl flex-col gap-4",children:[e.jsxs("header",{className:"flex flex-col gap-1",children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-3",children:[e.jsx("h1",{className:"text-xl font-semibold",children:s("workspaces.title")}),e.jsxs(f,{variant:"ghost",size:"sm",className:"ml-auto",onClick:()=>n.refetch(),disabled:n.isFetching,"aria-label":s("actions.refresh",{ns:"common"}),children:[n.isFetching?e.jsx(E,{className:"h-4 w-4 animate-spin"}):e.jsx(le,{className:"h-4 w-4"}),e.jsx("span",{className:"hidden sm:inline",children:s("actions.refresh",{ns:"common"})})]})]}),e.jsx("p",{className:"text-sm text-text-dim",children:s("workspaces.subtitle")})]}),n.isLoading?e.jsx("div",{className:"h-32 rounded-md bg-surface-2 animate-pulse"}):r?e.jsx(_,{icon:e.jsx(ce,{}),title:s("workspaces.empty.title"),description:s("workspaces.empty.description")}):e.jsxs(X,{children:[e.jsx(Y,{children:e.jsxs(A,{children:[e.jsx(k,{className:"w-32",children:s("workspaces.col.id")}),e.jsx(k,{children:s("workspaces.col.name")}),e.jsx(k,{children:s("workspaces.col.agents")}),e.jsx(k,{children:s("workspaces.col.members")}),e.jsx(k,{children:s("workspaces.col.rateLimit")}),e.jsx(k,{className:"w-36"})]})}),e.jsx(G,{children:p.map(t=>e.jsxs(A,{children:[e.jsx(N,{className:"font-mono text-xs",children:t.id}),e.jsx(N,{className:"font-medium",children:t.name}),e.jsx(N,{children:t.agents.length===0?e.jsx("span",{className:"text-text-muted text-xs",children:"—"}):e.jsx("div",{className:"flex flex-wrap gap-1",children:t.agents.map(a=>e.jsx(P,{variant:"secondary",children:a},a))})}),e.jsx(N,{children:(t.members??[]).length===0?e.jsx("span",{className:"text-text-muted text-xs",children:s("workspaces.membersOpen")}):e.jsx("span",{className:"text-text-dim text-xs",children:s("workspaces.membersCount",{count:t.members.length})})}),e.jsx(N,{className:"text-xs text-text-dim",children:t.rateLimit?s("workspaces.rateLimitFormat",{rate:t.rateLimit.rate,intervalSec:t.rateLimit.intervalSec,burst:t.rateLimit.burst}):"—"}),e.jsx(N,{children:e.jsxs("div",{className:"flex flex-wrap justify-end gap-1",children:[e.jsxs(f,{type:"button",variant:"ghost",size:"sm",onClick:()=>C(t),children:[e.jsx(ue,{className:"h-3 w-3"}),s("workspaces.edit")]}),t.id!=="default"&&e.jsxs(f,{type:"button",variant:"ghost",size:"sm",onClick:()=>g(t),disabled:w.isPending,"aria-label":s("workspaces.remove.ariaLabel",{id:t.id}),children:[e.jsx(me,{className:"h-3 w-3"}),s("workspaces.remove.label")]})]})})]},t.id))})]}),e.jsxs("form",{onSubmit:t=>void L(t),className:"rounded-md border border-border bg-surface p-4",children:[e.jsx("div",{className:"mb-1 text-sm font-medium",children:s("workspaces.form.title")}),y&&e.jsx("p",{className:"mb-3 text-xs text-text-dim",children:s("workspaces.form.subtitleEdit")}),e.jsxs("div",{className:"grid grid-cols-1 gap-3 sm:grid-cols-2",children:[e.jsx(S,{id:"ws-id",label:s("workspaces.form.id"),hint:s("workspaces.form.idHint"),value:i.id,onChange:t=>m(a=>({...a,id:t})),placeholder:"team-foo",mono:!0}),e.jsx(S,{id:"ws-name",label:s("workspaces.form.name"),value:i.name,onChange:t=>m(a=>({...a,name:t})),placeholder:"Team Foo"}),e.jsx(K,{id:"ws-agents",label:s("workspaces.form.agents"),hint:s("workspaces.form.agentsHint"),emptyText:s("workspaces.form.emptyAgents"),chooseLabel:s("workspaces.form.selectAgents"),customPlaceholder:s("workspaces.form.customAgentPlaceholder"),choices:j,value:i.agents,loading:c.isLoading,onChange:t=>m(a=>({...a,agents:t}))}),e.jsx(K,{id:"ws-members",label:s("workspaces.form.members"),hint:s("workspaces.form.membersHint"),emptyText:s("workspaces.form.emptyMembers"),chooseLabel:s("workspaces.form.selectMembers"),customPlaceholder:s("workspaces.form.customMemberPlaceholder"),choices:O,value:i.members,loading:d.isLoading||n.isLoading,onChange:t=>m(a=>({...a,members:t}))})]}),e.jsxs("div",{className:"mt-3",children:[e.jsx("div",{className:"text-xs font-medium text-text-dim",children:s("workspaces.form.rateLimit")}),e.jsx("div",{className:"mt-2 grid grid-cols-1 gap-2 sm:grid-cols-3",children:pe.map(t=>{const a=be(i,t);return e.jsxs(f,{type:"button",variant:a?"default":"secondary",size:"sm",className:"h-auto flex-col items-start gap-0.5 whitespace-normal px-3 py-2 text-left",onClick:()=>M(t),"aria-pressed":a,children:[e.jsx("span",{children:s(t.labelKey)}),e.jsx("span",{className:H("text-[10px] font-normal",a?"text-accent-fg/80":"text-text-muted"),children:s(t.descriptionKey)})]},t.id)})}),e.jsx("p",{className:"mt-2 text-[10px] text-text-muted",children:s("workspaces.form.ratePresetHint")}),e.jsxs("div",{className:"mt-1 grid grid-cols-3 gap-2",children:[e.jsx(S,{id:"ws-rate",label:s("workspaces.form.rate"),value:i.rate,onChange:t=>m(a=>({...a,rate:t})),placeholder:"10",mono:!0}),e.jsx(S,{id:"ws-ivl",label:s("workspaces.form.intervalSec"),value:i.intervalSec,onChange:t=>m(a=>({...a,intervalSec:t})),placeholder:"60",mono:!0}),e.jsx(S,{id:"ws-burst",label:s("workspaces.form.burst"),value:i.burst,onChange:t=>m(a=>({...a,burst:t})),placeholder:"15",mono:!0})]})]}),e.jsxs("div",{className:"mt-4 flex flex-wrap gap-2",children:[e.jsx(f,{type:"button",variant:"secondary",size:"sm",onClick:x,disabled:l.isPending,children:s("workspaces.form.reset")}),e.jsxs(f,{type:"submit",size:"sm",className:"ml-auto",disabled:l.isPending||!i.id.trim(),children:[l.isPending?e.jsx(E,{className:"h-4 w-4 animate-spin"}):e.jsx(de,{className:"h-4 w-4"}),s("workspaces.form.submit")]})]})]}),e.jsx(Q,{open:u!=null,onOpenChange:t=>{t||g(null)},title:s("workspaces.remove.confirmTitle",{id:u?.id??""}),description:s("workspaces.remove.confirmDescription",{name:u?.name??""}),intent:"danger",confirmLabel:s("workspaces.remove.confirm"),onConfirm:T})]})}function K({id:s,label:n,hint:c,emptyText:d,chooseLabel:l,customPlaceholder:w,choices:i,value:m,loading:y,onChange:b}){const{t:u}=R("settings"),[g,C]=h.useState(""),x=v(m),L=h.useMemo(()=>new Set(x),[x]);function T(r){L.has(r)?b(x.filter(j=>j!==r)):b([...x,r])}function M(r){b(x.filter(j=>j!==r))}function p(){const r=v(g.split(","));r.length!==0&&(b(v([...x,...r])),C(""))}return e.jsxs("div",{className:"flex flex-col gap-1 sm:col-span-2",children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsx(B,{id:`${s}-label`,className:"text-xs text-text-dim",children:n}),e.jsx(P,{variant:"secondary",children:u("workspaces.form.selectedCount",{count:x.length})})]}),e.jsxs("div",{className:"rounded-md border border-border bg-surface-2 p-2",children:[e.jsx("div",{className:"flex min-h-8 flex-wrap items-center gap-1.5",children:x.length===0?e.jsx("span",{className:"px-1 text-xs text-text-muted",children:d}):x.map(r=>e.jsxs(P,{variant:"secondary",className:"normal-case tracking-normal",children:[e.jsx("span",{className:"font-mono",children:r}),e.jsx("button",{type:"button",className:"ml-1 rounded-full text-text-dim hover:text-text",onClick:()=>M(r),"aria-label":u("workspaces.form.removeSelected",{value:r}),children:e.jsx(q,{className:"h-3 w-3"})})]},r))}),e.jsxs("div",{className:"mt-2 flex flex-wrap gap-2",children:[e.jsxs(J,{children:[e.jsx(Z,{asChild:!0,children:e.jsxs(f,{type:"button",variant:"outline",size:"sm",disabled:y,children:[y?e.jsx(E,{className:"h-4 w-4 animate-spin"}):e.jsx(xe,{className:"h-4 w-4"}),l]})}),e.jsxs(V,{align:"start",className:"max-h-80 w-80 overflow-y-auto",children:[e.jsx(ee,{children:l}),e.jsx(se,{}),i.length===0?e.jsx("div",{className:"px-2 py-2 text-sm text-text-muted",children:u("workspaces.form.noChoices")}):i.map(r=>e.jsxs(te,{checked:L.has(r.value),onCheckedChange:()=>T(r.value),onSelect:j=>j.preventDefault(),className:H("items-start gap-2",r.muted&&"text-text-muted"),children:[e.jsxs("span",{className:"min-w-0 flex-1",children:[e.jsx("span",{className:"block truncate font-mono text-xs",children:r.label}),r.detail&&e.jsx("span",{className:"mt-0.5 block truncate text-xs text-text-muted",children:r.detail})]}),r.badge&&e.jsx(P,{variant:r.muted?"outline":"success",children:r.badge})]},r.value))]})]}),e.jsxs("div",{className:"flex min-w-[220px] flex-1 gap-2",children:[e.jsx(I,{id:s,value:g,onChange:r=>C(r.target.value),onKeyDown:r=>{r.key==="Enter"&&(r.preventDefault(),p())},placeholder:w,className:"h-7 font-mono text-xs","aria-labelledby":`${s}-label`}),e.jsx(f,{type:"button",variant:"secondary",size:"sm",onClick:p,disabled:!g.trim(),children:u("workspaces.form.addCustom")})]})]})]}),c&&e.jsx("span",{className:"text-[10px] text-text-muted",children:c})]})}function S({id:s,label:n,hint:c,value:d,onChange:l,placeholder:w,mono:i}){return e.jsxs("div",{className:"flex flex-col gap-1",children:[e.jsx(B,{htmlFor:s,className:"text-xs text-text-dim",children:n}),e.jsx(I,{id:s,value:d,onChange:m=>l(m.target.value),placeholder:w,className:i?"font-mono text-xs":""}),c&&e.jsx("span",{className:"text-[10px] text-text-muted",children:c})]})}function v(s){const n=[],c=new Set;for(const d of s){const l=d.trim();!l||c.has(l)||(c.add(l),n.push(l))}return n}function ge(s){return`${s.platform}:${s.userId}`}function je(s){const n=new Date(s);return Number.isNaN(n.getTime())?s:n.toLocaleString()}export{ze as default};
7
+ //# sourceMappingURL=workspaces-DyGLJUgB.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspaces-DyGLJUgB.js","sources":["../../node_modules/lucide-react/dist/esm/icons/pencil.js","../../src/routes/settings/workspaces.tsx"],"sourcesContent":["/**\n * @license lucide-react v0.469.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Pencil = createLucideIcon(\"Pencil\", [\n [\n \"path\",\n {\n d: \"M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z\",\n key: \"1a8usu\"\n }\n ],\n [\"path\", { d: \"m15 5 4 4\", key: \"1mk7zo\" }]\n]);\n\nexport { Pencil as default };\n//# sourceMappingURL=pencil.js.map\n","/**\n * /settings/workspaces — multi-tenant workspace registry editor.\n *\n * Lists every workspace (id / name / agent whitelist count / member\n * count / rate-limit) and provides an inline form to add new ones\n * or upsert existing. The backend's POST handler is upsert-by-id, so\n * editing means \"click Edit on a row → form pre-fills → tweak → Save\"\n * — same endpoint, same semantics as Add.\n *\n * Open vs gated workspaces:\n * * `members: []` (empty array) means the workspace is open to any\n * user. The backend treats `undefined` and `[]` identically; we\n * normalise to `[]` for the round-trip.\n * * `agents: []` means \"allow every registered agent\".\n *\n * Rate-limit fields are optional triple (rate / intervalSec / burst).\n * Leaving them blank submits `rateLimit: undefined` and the backend\n * falls back to defaults.\n */\n\nimport { useEffect, useMemo, useState } from 'react'\nimport { useTranslation } from 'react-i18next'\nimport { toast } from 'sonner'\nimport { Briefcase, Loader2, Pencil, Plus, RefreshCcw, Save, Trash2, X } from 'lucide-react'\n\nimport { ConfirmDialog } from '@/components/common/confirm-dialog'\nimport { EmptyState } from '@/components/common/empty-state'\nimport {\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from '@/components/ui/table'\nimport { Badge } from '@/components/ui/badge'\nimport { Button } from '@/components/ui/button'\nimport {\n DropdownMenu,\n DropdownMenuCheckboxItem,\n DropdownMenuContent,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from '@/components/ui/dropdown-menu'\nimport { Input } from '@/components/ui/input'\nimport { Label } from '@/components/ui/label'\nimport { useAgentsStatus } from '@/hooks/use-workspace'\nimport { useAdminAllowlist, useDeleteWorkspace, useUpsertWorkspace, useWorkspaces } from '@/hooks/use-settings'\nimport { describeError } from '@/lib/api/errors'\nimport { cn } from '@/lib/utils'\nimport type { KnownImUser, WorkspaceConfig } from '@/types/api'\n\ninterface DraftFields {\n id: string\n name: string\n agents: string[]\n members: string[]\n rate: string\n intervalSec: string\n burst: string\n}\n\ninterface Choice {\n value: string\n label: string\n detail?: string\n badge?: string\n muted?: boolean\n}\n\ninterface RatePreset {\n id: 'default' | 'strict' | 'busy'\n labelKey: string\n descriptionKey: string\n rate: string\n intervalSec: string\n burst: string\n}\n\nconst EMPTY_DRAFT: DraftFields = {\n id: '', name: '',\n agents: [], members: [],\n rate: '', intervalSec: '', burst: '',\n}\n\nconst RATE_PRESETS: RatePreset[] = [\n {\n id: 'default',\n labelKey: 'workspaces.form.ratePresets.default',\n descriptionKey: 'workspaces.form.ratePresetDescriptions.default',\n rate: '',\n intervalSec: '',\n burst: '',\n },\n {\n id: 'strict',\n labelKey: 'workspaces.form.ratePresets.strict',\n descriptionKey: 'workspaces.form.ratePresetDescriptions.strict',\n rate: '3',\n intervalSec: '60',\n burst: '5',\n },\n {\n id: 'busy',\n labelKey: 'workspaces.form.ratePresets.busy',\n descriptionKey: 'workspaces.form.ratePresetDescriptions.busy',\n rate: '30',\n intervalSec: '60',\n burst: '45',\n },\n]\n\nfunction toDraft(ws: WorkspaceConfig): DraftFields {\n return {\n id: ws.id,\n name: ws.name,\n agents: uniqueStrings(ws.agents),\n members: uniqueStrings(ws.members ?? []),\n rate: ws.rateLimit ? String(ws.rateLimit.rate) : '',\n intervalSec: ws.rateLimit ? String(ws.rateLimit.intervalSec) : '',\n burst: ws.rateLimit ? String(ws.rateLimit.burst) : '',\n }\n}\n\nfunction fromDraft(d: DraftFields): WorkspaceConfig {\n const cfg: WorkspaceConfig = {\n id: d.id.trim(),\n name: d.name.trim() || d.id.trim(),\n agents: uniqueStrings(d.agents),\n members: uniqueStrings(d.members),\n }\n // Rate limit only when all three fields parse as positive numbers.\n const rate = Number(d.rate)\n const ivl = Number(d.intervalSec)\n const burst = Number(d.burst)\n if (Number.isFinite(rate) && rate > 0\n && Number.isFinite(ivl) && ivl > 0\n && Number.isFinite(burst) && burst > 0) {\n cfg.rateLimit = { rate, intervalSec: ivl, burst }\n }\n return cfg\n}\n\nfunction isRatePresetActive(draft: DraftFields, preset: RatePreset): boolean {\n return draft.rate === preset.rate\n && draft.intervalSec === preset.intervalSec\n && draft.burst === preset.burst\n}\n\nexport default function SettingsWorkspacesRoute(): JSX.Element {\n const { t } = useTranslation(['settings', 'common'])\n const list = useWorkspaces()\n const agentsQuery = useAgentsStatus()\n const adminsQuery = useAdminAllowlist()\n const upsert = useUpsertWorkspace()\n const removeWorkspace = useDeleteWorkspace()\n\n const [draft, setDraft] = useState<DraftFields>(EMPTY_DRAFT)\n const [editing, setEditing] = useState<string | null>(null)\n const [deleteTarget, setDeleteTarget] = useState<WorkspaceConfig | null>(null)\n\n useEffect(() => {\n if (draft.id || draft.name) return\n // Keep the form blank on first paint; pre-fill happens via Edit.\n }, [draft.id, draft.name])\n\n function startEdit(ws: WorkspaceConfig): void {\n setDraft(toDraft(ws))\n setEditing(ws.id)\n }\n\n function resetForm(): void {\n setDraft(EMPTY_DRAFT)\n setEditing(null)\n }\n\n async function onSubmit(e: React.FormEvent): Promise<void> {\n e.preventDefault()\n const cfg = fromDraft(draft)\n if (!cfg.id) return\n try {\n await upsert.mutateAsync(cfg)\n toast.success(t('workspaces.toast.saved'))\n resetForm()\n } catch (err) {\n toast.error(describeError(err, t).message)\n }\n }\n\n async function onConfirmDelete(): Promise<void> {\n if (!deleteTarget) return\n try {\n await removeWorkspace.mutateAsync(deleteTarget.id)\n toast.success(t('workspaces.toast.deleted'))\n if (editing === deleteTarget.id) resetForm()\n setDeleteTarget(null)\n } catch (err) {\n toast.error(describeError(err, t).message)\n throw err\n }\n }\n\n function applyRatePreset(preset: RatePreset): void {\n setDraft((d) => ({\n ...d,\n rate: preset.rate,\n intervalSec: preset.intervalSec,\n burst: preset.burst,\n }))\n }\n\n const workspaces = list.data?.workspaces ?? []\n const hasOnlyDefault = workspaces.length <= 1\n && workspaces.every((w) => w.id === 'default')\n const agentChoices = useMemo<Choice[]>(() => {\n const status = agentsQuery.data ?? {}\n return Object.entries(status)\n .sort(([aName, aOnline], [bName, bOnline]) => {\n if (aOnline !== bOnline) return aOnline ? -1 : 1\n return aName.localeCompare(bName)\n })\n .map(([name, online]) => ({\n value: name,\n label: name,\n badge: online ? t('workspaces.form.agentOnline') : t('workspaces.form.agentOffline'),\n muted: !online,\n }))\n }, [agentsQuery.data, t])\n const memberChoices = useMemo<Choice[]>(() => {\n const m = new Map<string, Choice>()\n for (const u of adminsQuery.data?.knownUsers ?? []) {\n const key = imUserKey(u)\n m.set(key, {\n value: key,\n label: key,\n detail: t('workspaces.form.memberLastSeen', { time: formatSeenAt(u.lastSeenAt) }),\n })\n }\n for (const ws of workspaces) {\n for (const member of ws.members ?? []) {\n if (!member) continue\n if (!m.has(member)) {\n m.set(member, {\n value: member,\n label: member,\n detail: t('workspaces.form.memberFromScope', { scope: ws.id }),\n })\n }\n }\n }\n return [...m.values()].sort((a, b) => a.label.localeCompare(b.label))\n }, [adminsQuery.data?.knownUsers, t, workspaces])\n\n return (\n <div className=\"mx-auto flex max-w-5xl flex-col gap-4\">\n <header className=\"flex flex-col gap-1\">\n <div className=\"flex flex-wrap items-center gap-3\">\n <h1 className=\"text-xl font-semibold\">{t('workspaces.title')}</h1>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"ml-auto\"\n onClick={() => list.refetch()}\n disabled={list.isFetching}\n aria-label={t('actions.refresh', { ns: 'common' })}\n >\n {list.isFetching ? <Loader2 className=\"h-4 w-4 animate-spin\" /> : <RefreshCcw className=\"h-4 w-4\" />}\n <span className=\"hidden sm:inline\">{t('actions.refresh', { ns: 'common' })}</span>\n </Button>\n </div>\n <p className=\"text-sm text-text-dim\">{t('workspaces.subtitle')}</p>\n </header>\n\n {list.isLoading ? (\n <div className=\"h-32 rounded-md bg-surface-2 animate-pulse\" />\n ) : hasOnlyDefault ? (\n <EmptyState\n icon={<Briefcase />}\n title={t('workspaces.empty.title')}\n description={t('workspaces.empty.description')}\n />\n ) : (\n <Table>\n <TableHeader>\n <TableRow>\n <TableHead className=\"w-32\">{t('workspaces.col.id')}</TableHead>\n <TableHead>{t('workspaces.col.name')}</TableHead>\n <TableHead>{t('workspaces.col.agents')}</TableHead>\n <TableHead>{t('workspaces.col.members')}</TableHead>\n <TableHead>{t('workspaces.col.rateLimit')}</TableHead>\n <TableHead className=\"w-36\" />\n </TableRow>\n </TableHeader>\n <TableBody>\n {workspaces.map((ws) => (\n <TableRow key={ws.id}>\n <TableCell className=\"font-mono text-xs\">{ws.id}</TableCell>\n <TableCell className=\"font-medium\">{ws.name}</TableCell>\n <TableCell>\n {ws.agents.length === 0 ? (\n <span className=\"text-text-muted text-xs\">—</span>\n ) : (\n <div className=\"flex flex-wrap gap-1\">\n {ws.agents.map((a) => (\n <Badge key={a} variant=\"secondary\">{a}</Badge>\n ))}\n </div>\n )}\n </TableCell>\n <TableCell>\n {(ws.members ?? []).length === 0 ? (\n <span className=\"text-text-muted text-xs\">{t('workspaces.membersOpen')}</span>\n ) : (\n <span className=\"text-text-dim text-xs\">\n {t('workspaces.membersCount', { count: ws.members!.length })}\n </span>\n )}\n </TableCell>\n <TableCell className=\"text-xs text-text-dim\">\n {ws.rateLimit\n ? t('workspaces.rateLimitFormat', {\n rate: ws.rateLimit.rate,\n intervalSec: ws.rateLimit.intervalSec,\n burst: ws.rateLimit.burst,\n })\n : '—'}\n </TableCell>\n <TableCell>\n <div className=\"flex flex-wrap justify-end gap-1\">\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => startEdit(ws)}\n >\n <Pencil className=\"h-3 w-3\" />\n {t('workspaces.edit')}\n </Button>\n {ws.id !== 'default' && (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => setDeleteTarget(ws)}\n disabled={removeWorkspace.isPending}\n aria-label={t('workspaces.remove.ariaLabel', { id: ws.id })}\n >\n <Trash2 className=\"h-3 w-3\" />\n {t('workspaces.remove.label')}\n </Button>\n )}\n </div>\n </TableCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n )}\n\n {/* Form */}\n <form\n onSubmit={(e) => void onSubmit(e)}\n className=\"rounded-md border border-border bg-surface p-4\"\n >\n <div className=\"mb-1 text-sm font-medium\">{t('workspaces.form.title')}</div>\n {editing && (\n <p className=\"mb-3 text-xs text-text-dim\">{t('workspaces.form.subtitleEdit')}</p>\n )}\n <div className=\"grid grid-cols-1 gap-3 sm:grid-cols-2\">\n <FormField\n id=\"ws-id\"\n label={t('workspaces.form.id')}\n hint={t('workspaces.form.idHint')}\n value={draft.id}\n onChange={(v) => setDraft((d) => ({ ...d, id: v }))}\n placeholder=\"team-foo\"\n mono\n />\n <FormField\n id=\"ws-name\"\n label={t('workspaces.form.name')}\n value={draft.name}\n onChange={(v) => setDraft((d) => ({ ...d, name: v }))}\n placeholder=\"Team Foo\"\n />\n <MultiSelectField\n id=\"ws-agents\"\n label={t('workspaces.form.agents')}\n hint={t('workspaces.form.agentsHint')}\n emptyText={t('workspaces.form.emptyAgents')}\n chooseLabel={t('workspaces.form.selectAgents')}\n customPlaceholder={t('workspaces.form.customAgentPlaceholder')}\n choices={agentChoices}\n value={draft.agents}\n loading={agentsQuery.isLoading}\n onChange={(agents) => setDraft((d) => ({ ...d, agents }))}\n />\n <MultiSelectField\n id=\"ws-members\"\n label={t('workspaces.form.members')}\n hint={t('workspaces.form.membersHint')}\n emptyText={t('workspaces.form.emptyMembers')}\n chooseLabel={t('workspaces.form.selectMembers')}\n customPlaceholder={t('workspaces.form.customMemberPlaceholder')}\n choices={memberChoices}\n value={draft.members}\n loading={adminsQuery.isLoading || list.isLoading}\n onChange={(members) => setDraft((d) => ({ ...d, members }))}\n />\n </div>\n <div className=\"mt-3\">\n <div className=\"text-xs font-medium text-text-dim\">{t('workspaces.form.rateLimit')}</div>\n <div className=\"mt-2 grid grid-cols-1 gap-2 sm:grid-cols-3\">\n {RATE_PRESETS.map((preset) => {\n const active = isRatePresetActive(draft, preset)\n return (\n <Button\n key={preset.id}\n type=\"button\"\n variant={active ? 'default' : 'secondary'}\n size=\"sm\"\n className=\"h-auto flex-col items-start gap-0.5 whitespace-normal px-3 py-2 text-left\"\n onClick={() => applyRatePreset(preset)}\n aria-pressed={active}\n >\n <span>{t(preset.labelKey)}</span>\n <span className={cn('text-[10px] font-normal', active ? 'text-accent-fg/80' : 'text-text-muted')}>\n {t(preset.descriptionKey)}\n </span>\n </Button>\n )\n })}\n </div>\n <p className=\"mt-2 text-[10px] text-text-muted\">{t('workspaces.form.ratePresetHint')}</p>\n <div className=\"mt-1 grid grid-cols-3 gap-2\">\n <FormField\n id=\"ws-rate\"\n label={t('workspaces.form.rate')}\n value={draft.rate}\n onChange={(v) => setDraft((d) => ({ ...d, rate: v }))}\n placeholder=\"10\"\n mono\n />\n <FormField\n id=\"ws-ivl\"\n label={t('workspaces.form.intervalSec')}\n value={draft.intervalSec}\n onChange={(v) => setDraft((d) => ({ ...d, intervalSec: v }))}\n placeholder=\"60\"\n mono\n />\n <FormField\n id=\"ws-burst\"\n label={t('workspaces.form.burst')}\n value={draft.burst}\n onChange={(v) => setDraft((d) => ({ ...d, burst: v }))}\n placeholder=\"15\"\n mono\n />\n </div>\n </div>\n <div className=\"mt-4 flex flex-wrap gap-2\">\n <Button\n type=\"button\"\n variant=\"secondary\"\n size=\"sm\"\n onClick={resetForm}\n disabled={upsert.isPending}\n >\n {t('workspaces.form.reset')}\n </Button>\n <Button\n type=\"submit\"\n size=\"sm\"\n className=\"ml-auto\"\n disabled={upsert.isPending || !draft.id.trim()}\n >\n {upsert.isPending ? <Loader2 className=\"h-4 w-4 animate-spin\" /> : <Save className=\"h-4 w-4\" />}\n {t('workspaces.form.submit')}\n </Button>\n </div>\n </form>\n\n <ConfirmDialog\n open={deleteTarget != null}\n onOpenChange={(open) => { if (!open) setDeleteTarget(null) }}\n title={t('workspaces.remove.confirmTitle', { id: deleteTarget?.id ?? '' })}\n description={t('workspaces.remove.confirmDescription', { name: deleteTarget?.name ?? '' })}\n intent=\"danger\"\n confirmLabel={t('workspaces.remove.confirm')}\n onConfirm={onConfirmDelete}\n />\n </div>\n )\n}\n\nfunction MultiSelectField({\n id,\n label,\n hint,\n emptyText,\n chooseLabel,\n customPlaceholder,\n choices,\n value,\n loading,\n onChange,\n}: {\n id: string\n label: string\n hint?: string\n emptyText: string\n chooseLabel: string\n customPlaceholder: string\n choices: Choice[]\n value: string[]\n loading?: boolean\n onChange: (next: string[]) => void\n}): JSX.Element {\n const { t } = useTranslation('settings')\n const [custom, setCustom] = useState('')\n const selected = uniqueStrings(value)\n const selectedSet = useMemo(() => new Set(selected), [selected])\n\n function toggle(nextValue: string): void {\n if (selectedSet.has(nextValue)) {\n onChange(selected.filter((v) => v !== nextValue))\n } else {\n onChange([...selected, nextValue])\n }\n }\n\n function remove(nextValue: string): void {\n onChange(selected.filter((v) => v !== nextValue))\n }\n\n function addCustom(): void {\n const parsed = uniqueStrings(custom.split(','))\n if (parsed.length === 0) return\n onChange(uniqueStrings([...selected, ...parsed]))\n setCustom('')\n }\n\n return (\n <div className=\"flex flex-col gap-1 sm:col-span-2\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <Label id={`${id}-label`} className=\"text-xs text-text-dim\">\n {label}\n </Label>\n <Badge variant=\"secondary\">{t('workspaces.form.selectedCount', { count: selected.length })}</Badge>\n </div>\n\n <div className=\"rounded-md border border-border bg-surface-2 p-2\">\n <div className=\"flex min-h-8 flex-wrap items-center gap-1.5\">\n {selected.length === 0 ? (\n <span className=\"px-1 text-xs text-text-muted\">{emptyText}</span>\n ) : selected.map((item) => (\n <Badge key={item} variant=\"secondary\" className=\"normal-case tracking-normal\">\n <span className=\"font-mono\">{item}</span>\n <button\n type=\"button\"\n className=\"ml-1 rounded-full text-text-dim hover:text-text\"\n onClick={() => remove(item)}\n aria-label={t('workspaces.form.removeSelected', { value: item })}\n >\n <X className=\"h-3 w-3\" />\n </button>\n </Badge>\n ))}\n </div>\n\n <div className=\"mt-2 flex flex-wrap gap-2\">\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button type=\"button\" variant=\"outline\" size=\"sm\" disabled={loading}>\n {loading ? <Loader2 className=\"h-4 w-4 animate-spin\" /> : <Plus className=\"h-4 w-4\" />}\n {chooseLabel}\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"start\" className=\"max-h-80 w-80 overflow-y-auto\">\n <DropdownMenuLabel>{chooseLabel}</DropdownMenuLabel>\n <DropdownMenuSeparator />\n {choices.length === 0 ? (\n <div className=\"px-2 py-2 text-sm text-text-muted\">{t('workspaces.form.noChoices')}</div>\n ) : choices.map((choice) => (\n <DropdownMenuCheckboxItem\n key={choice.value}\n checked={selectedSet.has(choice.value)}\n onCheckedChange={() => toggle(choice.value)}\n onSelect={(event) => event.preventDefault()}\n className={cn('items-start gap-2', choice.muted && 'text-text-muted')}\n >\n <span className=\"min-w-0 flex-1\">\n <span className=\"block truncate font-mono text-xs\">{choice.label}</span>\n {choice.detail && (\n <span className=\"mt-0.5 block truncate text-xs text-text-muted\">{choice.detail}</span>\n )}\n </span>\n {choice.badge && (\n <Badge variant={choice.muted ? 'outline' : 'success'}>{choice.badge}</Badge>\n )}\n </DropdownMenuCheckboxItem>\n ))}\n </DropdownMenuContent>\n </DropdownMenu>\n\n <div className=\"flex min-w-[220px] flex-1 gap-2\">\n <Input\n id={id}\n value={custom}\n onChange={(e) => setCustom(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === 'Enter') {\n e.preventDefault()\n addCustom()\n }\n }}\n placeholder={customPlaceholder}\n className=\"h-7 font-mono text-xs\"\n aria-labelledby={`${id}-label`}\n />\n <Button type=\"button\" variant=\"secondary\" size=\"sm\" onClick={addCustom} disabled={!custom.trim()}>\n {t('workspaces.form.addCustom')}\n </Button>\n </div>\n </div>\n </div>\n {hint && <span className=\"text-[10px] text-text-muted\">{hint}</span>}\n </div>\n )\n}\n\ninterface FormFieldProps {\n id: string\n label: string\n hint?: string\n value: string\n onChange: (v: string) => void\n placeholder?: string\n mono?: boolean\n}\n\nfunction FormField({ id, label, hint, value, onChange, placeholder, mono }: FormFieldProps): JSX.Element {\n return (\n <div className=\"flex flex-col gap-1\">\n <Label htmlFor={id} className=\"text-xs text-text-dim\">{label}</Label>\n <Input\n id={id}\n value={value}\n onChange={(e) => onChange(e.target.value)}\n placeholder={placeholder}\n className={mono ? 'font-mono text-xs' : ''}\n />\n {hint && <span className=\"text-[10px] text-text-muted\">{hint}</span>}\n </div>\n )\n}\n\nfunction uniqueStrings(values: string[]): string[] {\n const out: string[] = []\n const seen = new Set<string>()\n for (const raw of values) {\n const value = raw.trim()\n if (!value || seen.has(value)) continue\n seen.add(value)\n out.push(value)\n }\n return out\n}\n\nfunction imUserKey(user: KnownImUser): string {\n return `${user.platform}:${user.userId}`\n}\n\nfunction formatSeenAt(value: string): string {\n const dt = new Date(value)\n if (Number.isNaN(dt.getTime())) return value\n return dt.toLocaleString()\n}\n"],"names":["Pencil","createLucideIcon","EMPTY_DRAFT","RATE_PRESETS","toDraft","ws","uniqueStrings","fromDraft","d","cfg","rate","ivl","burst","isRatePresetActive","draft","preset","SettingsWorkspacesRoute","t","useTranslation","list","useWorkspaces","agentsQuery","useAgentsStatus","adminsQuery","useAdminAllowlist","upsert","useUpsertWorkspace","removeWorkspace","useDeleteWorkspace","setDraft","useState","editing","setEditing","deleteTarget","setDeleteTarget","useEffect","startEdit","resetForm","onSubmit","e","toast","err","describeError","onConfirmDelete","applyRatePreset","workspaces","hasOnlyDefault","w","agentChoices","useMemo","status","aName","aOnline","bName","bOnline","name","online","memberChoices","m","u","key","imUserKey","formatSeenAt","member","b","jsxs","jsx","Button","Loader2","RefreshCcw","EmptyState","Briefcase","Table","TableHeader","TableRow","TableHead","TableBody","TableCell","Badge","Trash2","FormField","v","MultiSelectField","agents","members","active","cn","Save","ConfirmDialog","open","id","label","hint","emptyText","chooseLabel","customPlaceholder","choices","value","loading","onChange","custom","setCustom","selected","selectedSet","toggle","nextValue","remove","addCustom","parsed","Label","item","X","DropdownMenu","DropdownMenuTrigger","Plus","DropdownMenuContent","DropdownMenuLabel","DropdownMenuSeparator","choice","DropdownMenuCheckboxItem","event","Input","placeholder","mono","values","out","seen","raw","user","dt"],"mappings":"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","x_google_ignoreList":[0]}
@@ -35,9 +35,9 @@
35
35
  } catch (e) { /* private-mode storage exceptions: noop */ }
36
36
  })()
37
37
  </script>
38
- <script type="module" crossorigin src="/assets/index-DHh1LYlA.js"></script>
38
+ <script type="module" crossorigin src="/assets/index-DCfdN5R7.js"></script>
39
39
  <link rel="modulepreload" crossorigin href="/assets/react-DlP5eolq.js">
40
- <link rel="stylesheet" crossorigin href="/assets/index-DknVjPYB.css">
40
+ <link rel="stylesheet" crossorigin href="/assets/index-Bi2qWb-u.css">
41
41
  </head>
42
42
  <body>
43
43
  <div id="root"></div>
@@ -23,9 +23,6 @@ export declare const __webAuthForTesting: {
23
23
  setTokenModule(mod: typeof import("../core/access-token.js") | null): void;
24
24
  };
25
25
  export declare function createSerialQueue(): (fn: () => Promise<void>) => void;
26
- /**
27
- * Start the web chat server
28
- */
29
26
  export declare function startWebServer(options: {
30
27
  port?: number;
31
28
  defaultAgent: string;
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/web/server.ts"],"names":[],"mappings":"AAEA,OAAO,EAAgB,KAAK,eAAe,EAAuB,MAAM,WAAW,CAAA;AAmGnF,iBAAS,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAO/D;AAwBD,iBAAS,qBAAqB,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAQ5D;AAyID;;;;;;;;;;;;;0EAa0E;AAC1E,iBAAS,cAAc,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAcrD;AAaD,eAAO,MAAM,mBAAmB;;;;wBAIV,cAAc,yBAAyB,CAAC,GAAG,IAAI,GAAG,IAAI;CAG3E,CAAA;AAED,wBAAgB,iBAAiB,IAAI,CAAC,EAAE,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,KAAK,IAAI,CAOrE;AAED;;GAEG;AACH,wBAAsB,cAAc,CAAC,OAAO,EAAE;IAC5C,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,YAAY,EAAE,MAAM,CAAA;CACrB,GAAG,OAAO,CAAC;IAAE,KAAK,EAAE,MAAM,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAkxC/C"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/web/server.ts"],"names":[],"mappings":"AAEA,OAAO,EAAgB,KAAK,eAAe,EAAuB,MAAM,WAAW,CAAA;AAoGnF,iBAAS,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAO/D;AAwBD,iBAAS,qBAAqB,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAQ5D;AAyID;;;;;;;;;;;;;0EAa0E;AAC1E,iBAAS,cAAc,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAcrD;AAaD,eAAO,MAAM,mBAAmB;;;;wBAIV,cAAc,yBAAyB,CAAC,GAAG,IAAI,GAAG,IAAI;CAG3E,CAAA;AAED,wBAAgB,iBAAiB,IAAI,CAAC,EAAE,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,KAAK,IAAI,CAOrE;AAiCD,wBAAsB,cAAc,CAAC,OAAO,EAAE;IAC5C,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,YAAY,EAAE,MAAM,CAAA;CACrB,GAAG,OAAO,CAAC;IAAE,KAAK,EAAE,MAAM,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAwyC/C"}
@@ -1,5 +1,6 @@
1
1
  // Web chat server — HTTP + WebSocket for browser-based agent interaction
2
2
  import { createServer } from 'node:http';
3
+ import { createServer as createNetServer } from 'node:net';
3
4
  import { readFileSync, existsSync, readdirSync } from 'node:fs';
4
5
  import { readdir, stat, readFile, writeFile, rename, unlink, realpath, open } from 'node:fs/promises';
5
6
  import { join, dirname, resolve as resolvePath, sep as pathSep, relative as relativePath } from 'node:path';
@@ -330,9 +331,44 @@ export function createSerialQueue() {
330
331
  /**
331
332
  * Start the web chat server
332
333
  */
334
+ async function assertPortCanListen(port, bindHost) {
335
+ await new Promise((resolve, reject) => {
336
+ const probe = createNetServer();
337
+ const cleanup = () => {
338
+ probe.off('error', onError);
339
+ probe.off('listening', onListening);
340
+ };
341
+ const onError = (err) => {
342
+ cleanup();
343
+ try {
344
+ probe.close();
345
+ }
346
+ catch { /* not listening */ }
347
+ reject(err);
348
+ };
349
+ const onListening = () => {
350
+ cleanup();
351
+ probe.close(() => resolve());
352
+ };
353
+ probe.once('error', onError);
354
+ probe.once('listening', onListening);
355
+ try {
356
+ probe.listen(port, bindHost);
357
+ }
358
+ catch (err) {
359
+ cleanup();
360
+ try {
361
+ probe.close();
362
+ }
363
+ catch { /* not listening */ }
364
+ reject(err);
365
+ }
366
+ });
367
+ }
333
368
  export async function startWebServer(options) {
334
369
  const port = options.port || DEFAULT_PORT;
335
370
  const bindHost = process.env.AGIM_WEB_BIND || '127.0.0.1';
371
+ await assertPortCanListen(port, bindHost);
336
372
  const clients = new Map();
337
373
  // R9: threadId → tokenId ownership. A WS peer claims a threadId on
338
374
  // first connection (verifyClient already verified the token); later
@@ -1174,6 +1210,11 @@ export async function startWebServer(options) {
1174
1210
  if (url.pathname === '/api/service/status' && req.method === 'GET') {
1175
1211
  return handleServiceStatus(res);
1176
1212
  }
1213
+ if (url.pathname === '/api/service/log-tail' && req.method === 'GET') {
1214
+ if (!requireAdmin(req, res))
1215
+ return;
1216
+ return handleServiceLogTail(res, url);
1217
+ }
1177
1218
  if (url.pathname === '/api/service/start' && req.method === 'POST') {
1178
1219
  if (!requireAdmin(req, res))
1179
1220
  return;
@@ -1548,8 +1589,32 @@ export async function startWebServer(options) {
1548
1589
  // Default to loopback; operators can opt into LAN/public exposure with
1549
1590
  // AGIM_WEB_BIND=0.0.0.0 behind their firewall/reverse proxy.
1550
1591
  await new Promise((resolve, reject) => {
1551
- httpServer.on('error', reject);
1552
- httpServer.listen(port, bindHost, () => resolve());
1592
+ const onError = (err) => {
1593
+ httpServer.off('listening', onListening);
1594
+ try {
1595
+ httpServer.close();
1596
+ }
1597
+ catch { /* not listening yet */ }
1598
+ reject(err);
1599
+ };
1600
+ const onListening = () => {
1601
+ httpServer.off('error', onError);
1602
+ resolve();
1603
+ };
1604
+ httpServer.once('error', onError);
1605
+ httpServer.once('listening', onListening);
1606
+ try {
1607
+ httpServer.listen(port, bindHost);
1608
+ }
1609
+ catch (err) {
1610
+ httpServer.off('error', onError);
1611
+ httpServer.off('listening', onListening);
1612
+ try {
1613
+ httpServer.close();
1614
+ }
1615
+ catch { /* not listening yet */ }
1616
+ reject(err);
1617
+ }
1553
1618
  });
1554
1619
  webLog.info({ port, bindHost }, `Chat UI available at http://${bindHost === '0.0.0.0' ? 'localhost' : bindHost}:${port}`);
1555
1620
  // ============================================================
@@ -2190,6 +2255,68 @@ async function handleServiceStatus(res) {
2190
2255
  sendJson(res, 500, { error: err instanceof Error ? err.message : String(err) });
2191
2256
  }
2192
2257
  }
2258
+ async function handleServiceLogTail(res, url) {
2259
+ try {
2260
+ const { LOG_FILE } = await import('../cli-ui/service.js');
2261
+ const requestedLines = parseInt(url.searchParams.get('lines') || '120', 10);
2262
+ const lines = Math.min(Math.max(Number.isFinite(requestedLines) ? requestedLines : 120, 20), 500);
2263
+ const maxBytes = 256 * 1024;
2264
+ let st;
2265
+ try {
2266
+ st = await stat(LOG_FILE);
2267
+ }
2268
+ catch (err) {
2269
+ const e = err;
2270
+ if (e.code === 'ENOENT') {
2271
+ sendJson(res, 200, {
2272
+ path: LOG_FILE,
2273
+ exists: false,
2274
+ content: '',
2275
+ lines: 0,
2276
+ truncated: false,
2277
+ size: 0,
2278
+ mtime: null,
2279
+ });
2280
+ return;
2281
+ }
2282
+ throw err;
2283
+ }
2284
+ if (!st.isFile()) {
2285
+ sendJson(res, 400, { error: 'Service log path is not a regular file' });
2286
+ return;
2287
+ }
2288
+ const start = Math.max(0, st.size - maxBytes);
2289
+ const len = st.size - start;
2290
+ let buf;
2291
+ const fd = await open(LOG_FILE, 'r');
2292
+ try {
2293
+ buf = Buffer.alloc(len);
2294
+ const { bytesRead } = await fd.read(buf, 0, len, start);
2295
+ buf = buf.subarray(0, bytesRead);
2296
+ }
2297
+ finally {
2298
+ await fd.close();
2299
+ }
2300
+ let text = buf.toString('utf8');
2301
+ if (start > 0)
2302
+ text = text.replace(/^[^\n]*(\n|$)/, '');
2303
+ const allLines = text.split(/\r?\n/);
2304
+ const selected = allLines.slice(-lines);
2305
+ const content = selected.join('\n');
2306
+ sendJson(res, 200, {
2307
+ path: LOG_FILE,
2308
+ exists: true,
2309
+ content,
2310
+ lines: content ? selected.length : 0,
2311
+ truncated: start > 0 || allLines.length > lines,
2312
+ size: st.size,
2313
+ mtime: st.mtime.toISOString(),
2314
+ });
2315
+ }
2316
+ catch (err) {
2317
+ sendJson(res, 500, { error: err instanceof Error ? err.message : String(err) });
2318
+ }
2319
+ }
2193
2320
  async function handleServiceStart(res) {
2194
2321
  try {
2195
2322
  const { detectService, spawnBackground, reapStrayAgimProcesses } = await import('../cli-ui/service.js');
@@ -4483,10 +4610,18 @@ async function handleWorkspaceFileWrite(req, res, url) {
4483
4610
  throw err;
4484
4611
  }
4485
4612
  const finalSt = await stat(target);
4613
+ const savedPath = relativePath(base, target);
4614
+ if (savedPath === 'MEMORY.md') {
4615
+ try {
4616
+ const { ensureAgentMemoryLink } = await import('../core/agent-cwd.js');
4617
+ await ensureAgentMemoryLink(agent);
4618
+ }
4619
+ catch { /* best-effort: memory file itself was saved successfully */ }
4620
+ }
4486
4621
  sendJson(res, 200, {
4487
4622
  ok: true,
4488
4623
  agent,
4489
- path: relativePath(base, target),
4624
+ path: savedPath,
4490
4625
  size: finalSt.size,
4491
4626
  mtime: finalSt.mtime.toISOString(),
4492
4627
  });