agim-cli 1.2.139 → 1.2.141
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.
- package/CHANGELOG.md +122 -0
- package/dist/core/live-config.d.ts.map +1 -1
- package/dist/core/live-config.js +8 -0
- package/dist/core/live-config.js.map +1 -1
- package/dist/core/llm/registry.d.ts.map +1 -1
- package/dist/core/llm/registry.js +9 -1
- package/dist/core/llm/registry.js.map +1 -1
- package/dist/core/llm/secrets.d.ts +29 -3
- package/dist/core/llm/secrets.d.ts.map +1 -1
- package/dist/core/llm/secrets.js +114 -5
- package/dist/core/llm/secrets.js.map +1 -1
- package/dist/web/llm-api.js +12 -2
- package/dist/web/llm-api.js.map +1 -1
- package/dist/web/public/assets/{a2a-COCxV3Cc.js → a2a-DczMMkbl.js} +2 -2
- package/dist/web/public/assets/{a2a-COCxV3Cc.js.map → a2a-DczMMkbl.js.map} +1 -1
- package/dist/web/public/assets/{activity-lssr7XnJ.js → activity-cbLHkzca.js} +2 -2
- package/dist/web/public/assets/{activity-lssr7XnJ.js.map → activity-cbLHkzca.js.map} +1 -1
- package/dist/web/public/assets/{admins-DSW8IUl9.js → admins-C-YsGMj7.js} +2 -2
- package/dist/web/public/assets/{admins-DSW8IUl9.js.map → admins-C-YsGMj7.js.map} +1 -1
- package/dist/web/public/assets/agents-BWfov_1-.js +7 -0
- package/dist/web/public/assets/agents-BWfov_1-.js.map +1 -0
- package/dist/web/public/assets/{approvals-ClzA_Sl1.js → approvals-HSssmXKS.js} +2 -2
- package/dist/web/public/assets/{approvals-ClzA_Sl1.js.map → approvals-HSssmXKS.js.map} +1 -1
- package/dist/web/public/assets/{arrow-down-B6b32UC0.js → arrow-down-BXvC8Al2.js} +2 -2
- package/dist/web/public/assets/{arrow-down-B6b32UC0.js.map → arrow-down-BXvC8Al2.js.map} +1 -1
- package/dist/web/public/assets/{arrow-up-B-nP5kYY.js → arrow-up-63xELY5Q.js} +2 -2
- package/dist/web/public/assets/{arrow-up-B-nP5kYY.js.map → arrow-up-63xELY5Q.js.map} +1 -1
- package/dist/web/public/assets/{asks-DyXhQTTK.js → asks-COLEFOvK.js} +2 -2
- package/dist/web/public/assets/{asks-DyXhQTTK.js.map → asks-COLEFOvK.js.map} +1 -1
- package/dist/web/public/assets/{audit-BI7SCouF.js → audit-D4ZEiZub.js} +2 -2
- package/dist/web/public/assets/{audit-BI7SCouF.js.map → audit-D4ZEiZub.js.map} +1 -1
- package/dist/web/public/assets/{bell-B3N02OLo.js → bell-Cg2Bvv06.js} +2 -2
- package/dist/web/public/assets/{bell-B3N02OLo.js.map → bell-Cg2Bvv06.js.map} +1 -1
- package/dist/web/public/assets/{bgjobs-CicZiNip.js → bgjobs-CEjCzwtd.js} +2 -2
- package/dist/web/public/assets/{bgjobs-CicZiNip.js.map → bgjobs-CEjCzwtd.js.map} +1 -1
- package/dist/web/public/assets/{brain-C6ukvGuf.js → brain-euvl6F6C.js} +2 -2
- package/dist/web/public/assets/{brain-C6ukvGuf.js.map → brain-euvl6F6C.js.map} +1 -1
- package/dist/web/public/assets/{briefcase-hn1X3B5h.js → briefcase-DPWLbCnA.js} +2 -2
- package/dist/web/public/assets/{briefcase-hn1X3B5h.js.map → briefcase-DPWLbCnA.js.map} +1 -1
- package/dist/web/public/assets/{chat-BDQj16Vz.js → chat-Dz9kfaxH.js} +2 -2
- package/dist/web/public/assets/{chat-BDQj16Vz.js.map → chat-Dz9kfaxH.js.map} +1 -1
- package/dist/web/public/assets/{chevron-left-RxNVjq1Y.js → chevron-left-BeIh5thq.js} +2 -2
- package/dist/web/public/assets/{chevron-left-RxNVjq1Y.js.map → chevron-left-BeIh5thq.js.map} +1 -1
- package/dist/web/public/assets/{chevron-right-BUp0DVnl.js → chevron-right-uP_l9MMb.js} +2 -2
- package/dist/web/public/assets/{chevron-right-BUp0DVnl.js.map → chevron-right-uP_l9MMb.js.map} +1 -1
- package/dist/web/public/assets/{circle-check-Bm4WZ21u.js → circle-check-CewnjFgv.js} +2 -2
- package/dist/web/public/assets/{circle-check-Bm4WZ21u.js.map → circle-check-CewnjFgv.js.map} +1 -1
- package/dist/web/public/assets/{circle-check-big-BIrgy-jJ.js → circle-check-big-C2RTc48c.js} +2 -2
- package/dist/web/public/assets/{circle-check-big-BIrgy-jJ.js.map → circle-check-big-C2RTc48c.js.map} +1 -1
- package/dist/web/public/assets/{circle-x-D3x0-M6I.js → circle-x-Ccg1HyV-.js} +2 -2
- package/dist/web/public/assets/{circle-x-D3x0-M6I.js.map → circle-x-Ccg1HyV-.js.map} +1 -1
- package/dist/web/public/assets/{clock-DS7DQ1w2.js → clock-qxbYSynv.js} +2 -2
- package/dist/web/public/assets/{clock-DS7DQ1w2.js.map → clock-qxbYSynv.js.map} +1 -1
- package/dist/web/public/assets/{confirm-dialog-C68_XUSd.js → confirm-dialog-DmJq4Td9.js} +2 -2
- package/dist/web/public/assets/{confirm-dialog-C68_XUSd.js.map → confirm-dialog-DmJq4Td9.js.map} +1 -1
- package/dist/web/public/assets/{copy-Bzjhsg1p.js → copy-DxSHRdbc.js} +2 -2
- package/dist/web/public/assets/{copy-Bzjhsg1p.js.map → copy-DxSHRdbc.js.map} +1 -1
- package/dist/web/public/assets/{data-table-DEXi61Ud.js → data-table-S7rIjwdO.js} +2 -2
- package/dist/web/public/assets/{data-table-DEXi61Ud.js.map → data-table-S7rIjwdO.js.map} +1 -1
- package/dist/web/public/assets/{dialog-gd2B3olO.js → dialog-bAIDaO-6.js} +2 -2
- package/dist/web/public/assets/{dialog-gd2B3olO.js.map → dialog-bAIDaO-6.js.map} +1 -1
- package/dist/web/public/assets/{download-DCcaTdc6.js → download-OhsGtnO-.js} +2 -2
- package/dist/web/public/assets/{download-DCcaTdc6.js.map → download-OhsGtnO-.js.map} +1 -1
- package/dist/web/public/assets/{email-Bp4hAFCc.js → email-C1-HxWLF.js} +2 -2
- package/dist/web/public/assets/{email-Bp4hAFCc.js.map → email-C1-HxWLF.js.map} +1 -1
- package/dist/web/public/assets/{empty-state-Bzkp-ADK.js → empty-state-C-qjOHyu.js} +2 -2
- package/dist/web/public/assets/{empty-state-Bzkp-ADK.js.map → empty-state-C-qjOHyu.js.map} +1 -1
- package/dist/web/public/assets/{external-link-Deer-Lh8.js → external-link-DRVp9-lb.js} +2 -2
- package/dist/web/public/assets/{external-link-Deer-Lh8.js.map → external-link-DRVp9-lb.js.map} +1 -1
- package/dist/web/public/assets/{eye-aJAK4qYW.js → eye-CFhg5BTa.js} +2 -2
- package/dist/web/public/assets/{eye-aJAK4qYW.js.map → eye-CFhg5BTa.js.map} +1 -1
- package/dist/web/public/assets/{facts-CX8Slc_J.js → facts-CGaLWhzi.js} +2 -2
- package/dist/web/public/assets/{facts-CX8Slc_J.js.map → facts-CGaLWhzi.js.map} +1 -1
- package/dist/web/public/assets/{goals-CoO5qR3l.js → goals-C-dJANmn.js} +2 -2
- package/dist/web/public/assets/{goals-CoO5qR3l.js.map → goals-C-dJANmn.js.map} +1 -1
- package/dist/web/public/assets/{health-QRL6KLLZ.js → health-CWcti5h3.js} +2 -2
- package/dist/web/public/assets/{health-QRL6KLLZ.js.map → health-CWcti5h3.js.map} +1 -1
- package/dist/web/public/assets/{heart-pulse-DTuy4Tma.js → heart-pulse-DmGhKR2W.js} +2 -2
- package/dist/web/public/assets/{heart-pulse-DTuy4Tma.js.map → heart-pulse-DmGhKR2W.js.map} +1 -1
- package/dist/web/public/assets/{heartbeat-BLutWB3t.js → heartbeat-kLoGBNCo.js} +2 -2
- package/dist/web/public/assets/{heartbeat-BLutWB3t.js.map → heartbeat-kLoGBNCo.js.map} +1 -1
- package/dist/web/public/assets/{hot-B96_1Z-G.js → hot-BITDoax1.js} +2 -2
- package/dist/web/public/assets/{hot-B96_1Z-G.js.map → hot-BITDoax1.js.map} +1 -1
- package/dist/web/public/assets/{index-wVLKSZpI.js → index-O0BQoyzo.js} +22 -22
- package/dist/web/public/assets/{index-wVLKSZpI.js.map → index-O0BQoyzo.js.map} +1 -1
- package/dist/web/public/assets/{installed-5bpbtNzF.js → installed-Co9WrtQ7.js} +2 -2
- package/dist/web/public/assets/{installed-5bpbtNzF.js.map → installed-Co9WrtQ7.js.map} +1 -1
- package/dist/web/public/assets/{jobs-CPLjCaI5.js → jobs-hdHhBEvi.js} +2 -2
- package/dist/web/public/assets/{jobs-CPLjCaI5.js.map → jobs-hdHhBEvi.js.map} +1 -1
- package/dist/web/public/assets/{layout-Cdi09rZy.js → layout-BMXC1Uh1.js} +2 -2
- package/dist/web/public/assets/{layout-Cdi09rZy.js.map → layout-BMXC1Uh1.js.map} +1 -1
- package/dist/web/public/assets/{layout-CN-hNeUX.js → layout-CQtbOBag.js} +2 -2
- package/dist/web/public/assets/{layout-CN-hNeUX.js.map → layout-CQtbOBag.js.map} +1 -1
- package/dist/web/public/assets/{layout-nYKX1VY4.js → layout-CyBGneZ9.js} +2 -2
- package/dist/web/public/assets/{layout-nYKX1VY4.js.map → layout-CyBGneZ9.js.map} +1 -1
- package/dist/web/public/assets/{layout-DOvroJYL.js → layout-CysVsySh.js} +2 -2
- package/dist/web/public/assets/{layout-DOvroJYL.js.map → layout-CysVsySh.js.map} +1 -1
- package/dist/web/public/assets/{layout-K_oWND8q.js → layout-bDMXIKIR.js} +2 -2
- package/dist/web/public/assets/{layout-K_oWND8q.js.map → layout-bDMXIKIR.js.map} +1 -1
- package/dist/web/public/assets/{llm-BDW-Xpvk.js → llm-CPIRNQU2.js} +2 -2
- package/dist/web/public/assets/{llm-BDW-Xpvk.js.map → llm-CPIRNQU2.js.map} +1 -1
- package/dist/web/public/assets/{loader-circle-DPc6botW.js → loader-circle-9VUMGitw.js} +2 -2
- package/dist/web/public/assets/{loader-circle-DPc6botW.js.map → loader-circle-9VUMGitw.js.map} +1 -1
- package/dist/web/public/assets/{map-pin-ECh-25H3.js → map-pin-BXYvvHry.js} +2 -2
- package/dist/web/public/assets/{map-pin-ECh-25H3.js.map → map-pin-BXYvvHry.js.map} +1 -1
- package/dist/web/public/assets/{mcp-BV-k5VFD.js → mcp-BgLdlwSn.js} +2 -2
- package/dist/web/public/assets/{mcp-BV-k5VFD.js.map → mcp-BgLdlwSn.js.map} +1 -1
- package/dist/web/public/assets/{memos-BTsHVXah.js → memos-CfneX9DH.js} +2 -2
- package/dist/web/public/assets/{memos-BTsHVXah.js.map → memos-CfneX9DH.js.map} +1 -1
- package/dist/web/public/assets/{messengers-fyjNQwDX.js → messengers-7Phqea62.js} +2 -2
- package/dist/web/public/assets/{messengers-fyjNQwDX.js.map → messengers-7Phqea62.js.map} +1 -1
- package/dist/web/public/assets/{mobile-CeRuQZ-W.js → mobile-CV5b6D2W.js} +2 -2
- package/dist/web/public/assets/{mobile-CeRuQZ-W.js.map → mobile-CV5b6D2W.js.map} +1 -1
- package/dist/web/public/assets/{native-agent-Cg-Sab4t.js → native-agent-QvIa6LjE.js} +2 -2
- package/dist/web/public/assets/{native-agent-Cg-Sab4t.js.map → native-agent-QvIa6LjE.js.map} +1 -1
- package/dist/web/public/assets/{network-FK3KNI1a.js → network-BXhEjGhE.js} +2 -2
- package/dist/web/public/assets/{network-FK3KNI1a.js.map → network-BXhEjGhE.js.map} +1 -1
- package/dist/web/public/assets/{outbox-DhlxB8l0.js → outbox-DHQL7TQb.js} +2 -2
- package/dist/web/public/assets/{outbox-DhlxB8l0.js.map → outbox-DHQL7TQb.js.map} +1 -1
- package/dist/web/public/assets/{pagination-DzNnFLlI.js → pagination-VKuPb1Ot.js} +2 -2
- package/dist/web/public/assets/{pagination-DzNnFLlI.js.map → pagination-VKuPb1Ot.js.map} +1 -1
- package/dist/web/public/assets/{persona-B_EkauQB.js → persona-CWug2GLR.js} +2 -2
- package/dist/web/public/assets/{persona-B_EkauQB.js.map → persona-CWug2GLR.js.map} +1 -1
- package/dist/web/public/assets/{plans-D4aczyt4.js → plans-CZoEs5SY.js} +2 -2
- package/dist/web/public/assets/{plans-D4aczyt4.js.map → plans-CZoEs5SY.js.map} +1 -1
- package/dist/web/public/assets/{play-BdTIFReu.js → play-CfSn5Vdl.js} +2 -2
- package/dist/web/public/assets/{play-BdTIFReu.js.map → play-CfSn5Vdl.js.map} +1 -1
- package/dist/web/public/assets/{plus-CjK8x5Ta.js → plus-Z8l4CiqJ.js} +2 -2
- package/dist/web/public/assets/{plus-CjK8x5Ta.js.map → plus-Z8l4CiqJ.js.map} +1 -1
- package/dist/web/public/assets/{policy-D7vnZQeQ.js → policy-CutDSEPW.js} +2 -2
- package/dist/web/public/assets/{policy-D7vnZQeQ.js.map → policy-CutDSEPW.js.map} +1 -1
- package/dist/web/public/assets/{qr-code-CpmzdYE3.js → qr-code-DgU5aiM6.js} +2 -2
- package/dist/web/public/assets/{qr-code-CpmzdYE3.js.map → qr-code-DgU5aiM6.js.map} +1 -1
- package/dist/web/public/assets/{refresh-ccw-C2Q06LWj.js → refresh-ccw-D2CWiyU_.js} +2 -2
- package/dist/web/public/assets/{refresh-ccw-C2Q06LWj.js.map → refresh-ccw-D2CWiyU_.js.map} +1 -1
- package/dist/web/public/assets/{reminders-BW3VfYCD.js → reminders-Cb6Izedg.js} +2 -2
- package/dist/web/public/assets/{reminders-BW3VfYCD.js.map → reminders-Cb6Izedg.js.map} +1 -1
- package/dist/web/public/assets/{save-3XXDgdfD.js → save-DB0BDYTs.js} +2 -2
- package/dist/web/public/assets/{save-3XXDgdfD.js.map → save-DB0BDYTs.js.map} +1 -1
- package/dist/web/public/assets/{schedules-Bg5oBl6i.js → schedules-8mSjE14D.js} +2 -2
- package/dist/web/public/assets/{schedules-Bg5oBl6i.js.map → schedules-8mSjE14D.js.map} +1 -1
- package/dist/web/public/assets/{search-oQrctQNZ.js → search-B4fHilZ0.js} +2 -2
- package/dist/web/public/assets/{search-oQrctQNZ.js.map → search-B4fHilZ0.js.map} +1 -1
- package/dist/web/public/assets/{search-BjW_KGfJ.js → search-Con69NhG.js} +2 -2
- package/dist/web/public/assets/{search-BjW_KGfJ.js.map → search-Con69NhG.js.map} +1 -1
- package/dist/web/public/assets/{security-ongR2bsH.js → security-BTe3zUg8.js} +2 -2
- package/dist/web/public/assets/{security-ongR2bsH.js.map → security-BTe3zUg8.js.map} +1 -1
- package/dist/web/public/assets/{service-CNTTFkAV.js → service-C7SqcwfL.js} +2 -2
- package/dist/web/public/assets/{service-CNTTFkAV.js.map → service-C7SqcwfL.js.map} +1 -1
- package/dist/web/public/assets/{shield-alert-DW0flso9.js → shield-alert-CKFVsGgI.js} +2 -2
- package/dist/web/public/assets/{shield-alert-DW0flso9.js.map → shield-alert-CKFVsGgI.js.map} +1 -1
- package/dist/web/public/assets/{status-badge-CnqMu-7R.js → status-badge-BSkpyN4D.js} +2 -2
- package/dist/web/public/assets/{status-badge-CnqMu-7R.js.map → status-badge-BSkpyN4D.js.map} +1 -1
- package/dist/web/public/assets/{subtasks-ChtI7jpP.js → subtasks-Bel-I1Sk.js} +2 -2
- package/dist/web/public/assets/{subtasks-ChtI7jpP.js.map → subtasks-Bel-I1Sk.js.map} +1 -1
- package/dist/web/public/assets/{table-DVQPjWsi.js → table-CPn1MRcy.js} +2 -2
- package/dist/web/public/assets/{table-DVQPjWsi.js.map → table-CPn1MRcy.js.map} +1 -1
- package/dist/web/public/assets/{topn-Cs-wP6Tf.js → topn-Ba3RjcK1.js} +2 -2
- package/dist/web/public/assets/{topn-Cs-wP6Tf.js.map → topn-Ba3RjcK1.js.map} +1 -1
- package/dist/web/public/assets/{trash-2-BXhBc6TL.js → trash-2-Dfov8aHD.js} +2 -2
- package/dist/web/public/assets/{trash-2-BXhBc6TL.js.map → trash-2-Dfov8aHD.js.map} +1 -1
- package/dist/web/public/assets/{use-background-tasks-DWe_iYgk.js → use-background-tasks-BQrEeUwY.js} +2 -2
- package/dist/web/public/assets/{use-background-tasks-DWe_iYgk.js.map → use-background-tasks-BQrEeUwY.js.map} +1 -1
- package/dist/web/public/assets/{use-llm-admin-SE-2iSIe.js → use-llm-admin-DYekqogG.js} +2 -2
- package/dist/web/public/assets/{use-llm-admin-SE-2iSIe.js.map → use-llm-admin-DYekqogG.js.map} +1 -1
- package/dist/web/public/assets/{use-memory-tCgpqYla.js → use-memory-DbJ4pP2Z.js} +2 -2
- package/dist/web/public/assets/{use-memory-tCgpqYla.js.map → use-memory-DbJ4pP2Z.js.map} +1 -1
- package/dist/web/public/assets/{use-observability-CMUSiy5z.js → use-observability-C2M6WZ9W.js} +2 -2
- package/dist/web/public/assets/{use-observability-CMUSiy5z.js.map → use-observability-C2M6WZ9W.js.map} +1 -1
- package/dist/web/public/assets/{use-settings-BUM0BmtA.js → use-settings-DMdaoWsB.js} +2 -2
- package/dist/web/public/assets/{use-settings-BUM0BmtA.js.map → use-settings-DMdaoWsB.js.map} +1 -1
- package/dist/web/public/assets/{use-workspace-BOUxEbaB.js → use-workspace-BHG7h3jQ.js} +2 -2
- package/dist/web/public/assets/{use-workspace-BOUxEbaB.js.map → use-workspace-BHG7h3jQ.js.map} +1 -1
- package/dist/web/public/assets/{useQuery-II-YwTUw.js → useQuery-PdiC7-sY.js} +2 -2
- package/dist/web/public/assets/{useQuery-II-YwTUw.js.map → useQuery-PdiC7-sY.js.map} +1 -1
- package/dist/web/public/assets/{vector-C83bHtEW.js → vector-DnZM3OXU.js} +2 -2
- package/dist/web/public/assets/{vector-C83bHtEW.js.map → vector-DnZM3OXU.js.map} +1 -1
- package/dist/web/public/assets/{viewer-rMDo9pIb.js → viewer-Dz6k0YKp.js} +2 -2
- package/dist/web/public/assets/{viewer-rMDo9pIb.js.map → viewer-Dz6k0YKp.js.map} +1 -1
- package/dist/web/public/assets/{workspace-tVixiuWJ.js → workspace-BnXrWS3j.js} +2 -2
- package/dist/web/public/assets/{workspace-tVixiuWJ.js.map → workspace-BnXrWS3j.js.map} +1 -1
- package/dist/web/public/assets/{workspaces-CsLKDstm.js → workspaces-CSS_UBEi.js} +2 -2
- package/dist/web/public/assets/{workspaces-CsLKDstm.js.map → workspaces-CSS_UBEi.js.map} +1 -1
- package/dist/web/public/assets/{x-B0lqsHGi.js → x-DG-JKVw_.js} +2 -2
- package/dist/web/public/assets/{x-B0lqsHGi.js.map → x-DG-JKVw_.js.map} +1 -1
- package/dist/web/public/index.html +1 -1
- package/package.json +1 -1
- package/dist/web/public/assets/agents-0IMyFVui.js +0 -7
- package/dist/web/public/assets/agents-0IMyFVui.js.map +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{n as y,u as f,e as B,j as e,T as D,B as u,L as A,S as R,f as V,g as $,h as H,i as _,c as p,_ as N,k as h,l as C,m as U}from"./index-
|
|
1
|
+
import{n as y,u as f,e as B,j as e,T as D,B as u,L as A,S as R,f as V,g as $,h as H,i as _,c as p,_ as N,k as h,l as C,m as U}from"./index-O0BQoyzo.js";import{r as v}from"./react-Cb2sDjhD.js";import{E as z}from"./empty-state-C-qjOHyu.js";import{u as W,a as Z,b as I}from"./use-workspace-BHG7h3jQ.js";import{L as P}from"./loader-circle-9VUMGitw.js";import{R as O}from"./refresh-ccw-D2CWiyU_.js";import"./useQuery-PdiC7-sY.js";/**
|
|
2
2
|
* @license lucide-react v0.469.0 - ISC
|
|
3
3
|
*
|
|
4
4
|
* This source code is licensed under the ISC license.
|
|
@@ -14,4 +14,4 @@ import{n as y,u as f,e as B,j as e,T as D,B as u,L as A,S as R,f as V,g as $,h a
|
|
|
14
14
|
* This source code is licensed under the ISC license.
|
|
15
15
|
* See the LICENSE file in the root directory of this source tree.
|
|
16
16
|
*/const q=y("Folder",[["path",{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",key:"1kt360"}]]);function re(){const{t}=f(["workspace","common"]),[r,c]=B(),s=r.get("agent")??"",n=r.get("path")??"",i=W().data??{},o=v.useMemo(()=>Object.keys(i).sort(),[i]),d=Z(s,n,{enabled:!!s}),l=d.data,g=l?.type==="dir",T=l?.type==="file";function k(a){const m=new URLSearchParams(r);for(const[F,b]of Object.entries(a))b==null||b===""?m.delete(F):m.set(F,b);c(m,{replace:!1})}function E(a){k({agent:a||null,path:null})}function j(a){k({path:a||null})}function w(){if(!n)return;const a=n.lastIndexOf("/"),m=a>=0?n.slice(0,a):"";j(m)}return e.jsxs("div",{className:"flex min-h-dvh flex-col bg-bg",children:[e.jsx(D,{}),e.jsxs("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",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:t("pageTitle")}),e.jsxs(u,{variant:"ghost",size:"sm",className:"ml-auto",onClick:()=>d.refetch(),disabled:!s||d.isFetching,"aria-label":t("actions.refresh",{ns:"common"}),children:[d.isFetching?e.jsx(P,{className:"h-4 w-4 animate-spin"}):e.jsx(O,{className:"h-4 w-4"}),e.jsx("span",{className:"hidden sm:inline",children:t("actions.refresh",{ns:"common"})})]})]}),e.jsx("p",{className:"text-sm text-text-dim",children:t("subtitle")})]}),e.jsx("div",{className:"flex flex-wrap items-end gap-2",children:e.jsxs("div",{className:"flex flex-col gap-1",children:[e.jsx(A,{htmlFor:"agent",className:"text-xs text-text-dim",children:t("agentPicker.label")}),e.jsxs(R,{value:s||"__placeholder__",onValueChange:a=>E(a==="__placeholder__"?"":a),children:[e.jsx(V,{id:"agent",className:"w-64",children:e.jsx($,{placeholder:t("agentPicker.placeholder")})}),e.jsxs(H,{children:[e.jsx(_,{value:"__placeholder__",disabled:!0,children:t("agentPicker.placeholder")}),o.map(a=>e.jsx(_,{value:a,children:e.jsxs("span",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"font-mono text-xs",children:a}),e.jsx("span",{className:p("inline-block h-1.5 w-1.5 rounded-full",i[a]?"bg-success":"bg-text-muted")}),e.jsx("span",{className:"text-text-dim text-xs",children:i[a]?t("agentPicker.online"):t("agentPicker.offline")})]})},a))]})]})]})}),s?e.jsxs(e.Fragment,{children:[e.jsx(K,{path:n,onNavigate:j,onUp:w}),d.isLoading?e.jsx("div",{className:"h-32 rounded-md bg-surface-2 animate-pulse"}):g&&l?.type==="dir"?e.jsx(G,{entries:l.entries,onEnter:a=>j(n?`${n}/${a.name}`:a.name)}):T&&l?.type==="file"?e.jsx(J,{file:l,agent:s,onBack:w}):e.jsx(z,{icon:e.jsx(S,{}),title:t("editor.loadFailed"),description:d.error?.message??""})]}):e.jsx(z,{icon:e.jsx(S,{}),title:t("noAgent.title"),description:t("noAgent.description")})]})]})}function K({path:t,onNavigate:r,onUp:c}){const{t:s}=f("workspace"),n=t?t.split("/"):[];return e.jsxs("div",{className:"flex flex-wrap items-center gap-1 text-sm",children:[e.jsx(u,{type:"button",variant:"ghost",size:"sm",onClick:c,disabled:!t,"aria-label":s("tree.up"),children:e.jsx(N,{className:"h-4 w-4"})}),e.jsx("button",{type:"button",onClick:()=>r(""),className:"text-text-dim hover:text-text rounded px-1 py-0.5",children:s("tree.rootLabel")}),n.map((x,i)=>{const o=n.slice(0,i+1).join("/");return e.jsxs("span",{className:"flex items-center gap-1",children:[e.jsx("span",{className:"text-text-muted",children:"/"}),e.jsx("button",{type:"button",onClick:()=>r(o),className:"text-text-dim hover:text-text rounded px-1 py-0.5",children:x})]},o)})]})}function G({entries:t,onEnter:r}){const{t:c}=f("workspace");return t.length===0?e.jsx("div",{className:"rounded-md border border-border bg-surface p-3 text-sm text-text-dim",children:c("tree.empty")}):e.jsx("ul",{className:"divide-y divide-border rounded-md border border-border bg-surface",children:t.map(s=>e.jsx("li",{children:e.jsxs("button",{type:"button",onClick:()=>r(s),disabled:s.broken||s.symlink_escape,className:p("flex w-full items-center gap-2 px-3 py-2 text-sm text-left","transition-colors hover:bg-surface-hover disabled:opacity-50 disabled:cursor-not-allowed"),children:[s.isDir?e.jsx(q,{className:"h-4 w-4 text-accent"}):e.jsx(Q,{className:"h-4 w-4 text-text-dim"}),e.jsx("span",{className:s.isDir?"font-medium text-text":"text-text",children:s.name}),s.symlink_escape&&e.jsx(h,{variant:"warning",className:"ml-2",children:c("tree.symlinkEscape")}),s.broken&&!s.symlink_escape&&e.jsx(h,{variant:"danger",className:"ml-2",children:c("tree.broken")}),!s.isDir&&s.size!=null&&e.jsx("span",{className:"ml-auto text-xs text-text-muted tabular-nums",children:M(s.size)}),s.mtime&&e.jsx("span",{className:p("text-xs text-text-muted tabular-nums",!s.isDir&&s.size!=null?"ml-3":"ml-auto"),children:L(s.mtime)})]})},s.name))})}function J({file:t,agent:r,onBack:c}){const{t:s}=f(["workspace","common"]),[n,x]=v.useState(t.content);v.useEffect(()=>{x(t.content)},[t.content]);const i=n!==t.content,o=I();async function d(){try{await o.mutateAsync({agent:r,path:t.path,body:{content:n}}),C.success(s("toast.saved",{path:t.path}))}catch(l){const{message:g}=U(l,s);C.error(g)}}return t.encoding==="base64"?e.jsxs("div",{className:"rounded-md border border-border bg-surface p-4 text-sm",children:[e.jsxs(u,{variant:"ghost",size:"sm",onClick:c,className:"mb-3",children:[e.jsx(N,{className:"h-4 w-4"}),s("tree.up")]}),e.jsx("p",{className:"text-text-dim",children:s("editor.binary")}),e.jsxs("p",{className:"mt-2 text-xs text-text-muted tabular-nums",children:[t.path," · ",M(t.size)]})]}):e.jsxs("div",{className:"flex flex-col gap-2",children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsxs(u,{variant:"ghost",size:"sm",onClick:c,children:[e.jsx(N,{className:"h-4 w-4"}),s("tree.up")]}),e.jsx("code",{className:"rounded bg-surface-2 px-1.5 py-0.5 text-xs font-mono",children:t.path}),t.truncated&&e.jsx(h,{variant:"warning",children:"truncated"}),i&&e.jsx(h,{variant:"info",children:s("editor.dirtyHint")}),e.jsxs(u,{type:"button",size:"sm",className:"ml-auto",onClick:()=>void d(),disabled:!i||o.isPending||t.truncated,children:[o.isPending?e.jsx(P,{className:"h-4 w-4 animate-spin"}):null,o.isPending?s("editor.saving"):s("editor.save")]})]}),t.truncated&&e.jsx("p",{className:"text-xs text-warning",children:s("editor.truncated")}),e.jsx("textarea",{value:n,onChange:l=>x(l.target.value),rows:24,spellCheck:!1,className:p("w-full resize-y rounded-md border bg-bg px-3 py-2","font-mono text-xs leading-5","focus:outline-none focus:ring-2 focus:ring-accent focus:ring-offset-1 focus:ring-offset-bg",i?"border-accent":"border-border")}),!i&&e.jsx("p",{className:"text-xs text-text-muted",children:s("editor.savedMeta",{size:t.size,at:L(t.mtime)})})]})}function L(t){if(t==null)return"—";try{const r=new Date(t);return Number.isNaN(r.getTime())?t:r.toLocaleString(void 0,{month:"short",day:"numeric",hour:"2-digit",minute:"2-digit"})}catch{return t}}function M(t){return t<1024?`${t} B`:t<1024*1024?`${(t/1024).toFixed(1)} KiB`:`${(t/1024/1024).toFixed(1)} MiB`}export{re as default};
|
|
17
|
-
//# sourceMappingURL=workspace-
|
|
17
|
+
//# sourceMappingURL=workspace-BnXrWS3j.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workspace-tVixiuWJ.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 { ChevronUp, File, Folder, FolderTree, Loader2, RefreshCcw } 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 { describeError } from '@/lib/api/errors'\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 agents = agentsQuery.data ?? {}\n const agentNames = useMemo(() => Object.keys(agents).sort(), [agents])\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 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\">{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 {/* 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 ) : (\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 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\">truncated</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","useTranslation","params","setParams","useSearchParams","agent","path","agents","useAgentsStatus","agentNames","useMemo","filesQuery","useWorkspaceFiles","data","isDir","isFile","patchParams","patch","next","k","v","setAgent","navigateTo","nextPath","navigateUp","idx","parent","jsxs","jsx","Topbar","Button","Loader2","RefreshCcw","Label","Select","SelectTrigger","SelectValue","SelectContent","SelectItem","name","cn","Fragment","Breadcrumb","DirListing","entry","FileEditor","EmptyState","onNavigate","onUp","t","parts","ChevronUp","part","upto","entries","onEnter","e","Badge","formatSize","formatTime","file","onBack","draft","setDraft","useState","useEffect","dirty","write","useWriteWorkspaceFile","onSave","toast","err","message","describeError","iso","d","n"],"mappings":"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","x_google_ignoreList":[0,1,2]}
|
|
1
|
+
{"version":3,"file":"workspace-BnXrWS3j.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 { ChevronUp, File, Folder, FolderTree, Loader2, RefreshCcw } 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 { describeError } from '@/lib/api/errors'\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 agents = agentsQuery.data ?? {}\n const agentNames = useMemo(() => Object.keys(agents).sort(), [agents])\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 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\">{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 {/* 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 ) : (\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 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\">truncated</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","useTranslation","params","setParams","useSearchParams","agent","path","agents","useAgentsStatus","agentNames","useMemo","filesQuery","useWorkspaceFiles","data","isDir","isFile","patchParams","patch","next","k","v","setAgent","navigateTo","nextPath","navigateUp","idx","parent","jsxs","jsx","Topbar","Button","Loader2","RefreshCcw","Label","Select","SelectTrigger","SelectValue","SelectContent","SelectItem","name","cn","Fragment","Breadcrumb","DirListing","entry","FileEditor","EmptyState","onNavigate","onUp","t","parts","ChevronUp","part","upto","entries","onEnter","e","Badge","formatSize","formatTime","file","onBack","draft","setDraft","useState","useEffect","dirty","write","useWriteWorkspaceFile","onSave","toast","err","message","describeError","iso","d","n"],"mappings":"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","x_google_ignoreList":[0,1,2]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import{n as S,u as y,j as e,B as u,k as C,l as j,m as F,L as T,I as E}from"./index-
|
|
1
|
+
import{n as S,u as y,j as e,B as u,k as C,l as j,m as F,L as T,I as E}from"./index-O0BQoyzo.js";import{r as f}from"./react-Cb2sDjhD.js";import{E as B}from"./empty-state-C-qjOHyu.js";import{T as z,a as D,b as g,c as d,d as P,e as x}from"./table-CPn1MRcy.js";import{q as R,r as H}from"./use-settings-DMdaoWsB.js";import{L as k}from"./loader-circle-9VUMGitw.js";import{R as I}from"./refresh-ccw-D2CWiyU_.js";import{B as W}from"./briefcase-DPWLbCnA.js";import{S as A}from"./save-DB0BDYTs.js";import"./useQuery-PdiC7-sY.js";/**
|
|
2
2
|
* @license lucide-react v0.469.0 - ISC
|
|
3
3
|
*
|
|
4
4
|
* This source code is licensed under the ISC license.
|
|
5
5
|
* See the LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/const M=S("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"}]]),v={id:"",name:"",agents:"",members:"",rate:"",intervalSec:"",burst:""};function O(s){return{id:s.id,name:s.name,agents:s.agents.join(", "),members:(s.members??[]).join(", "),rate:s.rateLimit?String(s.rateLimit.rate):"",intervalSec:s.rateLimit?String(s.rateLimit.intervalSec):"",burst:s.rateLimit?String(s.rateLimit.burst):""}}function _(s){const n=o=>o.split(",").map(p=>p.trim()).filter(Boolean),m={id:s.id.trim(),name:s.name.trim()||s.id.trim(),agents:n(s.agents),members:n(s.members)},a=Number(s.rate),i=Number(s.intervalSec),l=Number(s.burst);return Number.isFinite(a)&&a>0&&Number.isFinite(i)&&i>0&&Number.isFinite(l)&&l>0&&(m.rateLimit={rate:a,intervalSec:i,burst:l}),m}function $(){const{t:s}=y(["settings","common"]),n=R(),m=H(),[a,i]=f.useState(v),[l,o]=f.useState(null);f.useEffect(()=>{a.id||a.name},[a.id,a.name]);function p(t){i(O(t)),o(t.id)}function b(){i(v),o(null)}async function N(t){t.preventDefault();const r=_(a);if(r.id)try{await m.mutateAsync(r),j.success(s("workspaces.toast.saved")),b()}catch(L){j.error(F(L,s).message)}}const h=n.data?.workspaces??[],w=h.length<=1&&h.every(t=>t.id==="default");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(u,{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(k,{className:"h-4 w-4 animate-spin"}):e.jsx(I,{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"}):w?e.jsx(B,{icon:e.jsx(W,{}),title:s("workspaces.empty.title"),description:s("workspaces.empty.description")}):e.jsxs(z,{children:[e.jsx(D,{children:e.jsxs(g,{children:[e.jsx(d,{className:"w-32",children:s("workspaces.col.id")}),e.jsx(d,{children:s("workspaces.col.name")}),e.jsx(d,{children:s("workspaces.col.agents")}),e.jsx(d,{children:s("workspaces.col.members")}),e.jsx(d,{children:s("workspaces.col.rateLimit")}),e.jsx(d,{className:"w-20"})]})}),e.jsx(P,{children:h.map(t=>e.jsxs(g,{children:[e.jsx(x,{className:"font-mono text-xs",children:t.id}),e.jsx(x,{className:"font-medium",children:t.name}),e.jsx(x,{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(r=>e.jsx(C,{variant:"secondary",children:r},r))})}),e.jsx(x,{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(x,{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(x,{children:e.jsxs(u,{type:"button",variant:"ghost",size:"sm",onClick:()=>p(t),children:[e.jsx(M,{className:"h-3 w-3"}),s("workspaces.edit")]})})]},t.id))})]}),e.jsxs("form",{onSubmit:t=>void N(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")}),l&&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(c,{id:"ws-id",label:s("workspaces.form.id"),hint:s("workspaces.form.idHint"),value:a.id,onChange:t=>i(r=>({...r,id:t})),placeholder:"team-foo",mono:!0}),e.jsx(c,{id:"ws-name",label:s("workspaces.form.name"),value:a.name,onChange:t=>i(r=>({...r,name:t})),placeholder:"Team Foo"}),e.jsx(c,{id:"ws-agents",label:s("workspaces.form.agents"),hint:s("workspaces.form.agentsHint"),value:a.agents,onChange:t=>i(r=>({...r,agents:t})),placeholder:"claude-code, codex",mono:!0}),e.jsx(c,{id:"ws-members",label:s("workspaces.form.members"),hint:s("workspaces.form.membersHint"),value:a.members,onChange:t=>i(r=>({...r,members:t})),placeholder:"wechat:wxid_abc, telegram:12345",mono:!0})]}),e.jsxs("div",{className:"mt-3",children:[e.jsx("div",{className:"text-xs font-medium text-text-dim",children:s("workspaces.form.rateLimit")}),e.jsxs("div",{className:"mt-1 grid grid-cols-3 gap-2",children:[e.jsx(c,{id:"ws-rate",label:s("workspaces.form.rate"),value:a.rate,onChange:t=>i(r=>({...r,rate:t})),placeholder:"10",mono:!0}),e.jsx(c,{id:"ws-ivl",label:s("workspaces.form.intervalSec"),value:a.intervalSec,onChange:t=>i(r=>({...r,intervalSec:t})),placeholder:"60",mono:!0}),e.jsx(c,{id:"ws-burst",label:s("workspaces.form.burst"),value:a.burst,onChange:t=>i(r=>({...r,burst:t})),placeholder:"15",mono:!0})]})]}),e.jsxs("div",{className:"mt-4 flex flex-wrap gap-2",children:[e.jsx(u,{type:"button",variant:"secondary",size:"sm",onClick:b,disabled:m.isPending,children:s("workspaces.form.reset")}),e.jsxs(u,{type:"submit",size:"sm",className:"ml-auto",disabled:m.isPending||!a.id.trim(),children:[m.isPending?e.jsx(k,{className:"h-4 w-4 animate-spin"}):e.jsx(A,{className:"h-4 w-4"}),s("workspaces.form.submit")]})]})]})]})}function c({id:s,label:n,hint:m,value:a,onChange:i,placeholder:l,mono:o}){return e.jsxs("div",{className:"flex flex-col gap-1",children:[e.jsx(T,{htmlFor:s,className:"text-xs text-text-dim",children:n}),e.jsx(E,{id:s,value:a,onChange:p=>i(p.target.value),placeholder:l,className:o?"font-mono text-xs":""}),m&&e.jsx("span",{className:"text-[10px] text-text-muted",children:m})]})}export{$ as default};
|
|
7
|
-
//# sourceMappingURL=workspaces-
|
|
7
|
+
//# sourceMappingURL=workspaces-CSS_UBEi.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workspaces-CsLKDstm.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, useState } from 'react'\nimport { useTranslation } from 'react-i18next'\nimport { toast } from 'sonner'\nimport { Briefcase, Loader2, Pencil, RefreshCcw, Save } from 'lucide-react'\n\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 { Input } from '@/components/ui/input'\nimport { Label } from '@/components/ui/label'\nimport { useUpsertWorkspace, useWorkspaces } from '@/hooks/use-settings'\nimport { describeError } from '@/lib/api/errors'\nimport type { WorkspaceConfig } from '@/types/api'\n\ninterface DraftFields {\n id: string\n name: string\n agents: string // comma-separated\n members: string // comma-separated\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\nfunction toDraft(ws: WorkspaceConfig): DraftFields {\n return {\n id: ws.id,\n name: ws.name,\n agents: ws.agents.join(', '),\n members: (ws.members ?? []).join(', '),\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 splitCsv = (s: string): string[] =>\n s.split(',').map((x) => x.trim()).filter(Boolean)\n const cfg: WorkspaceConfig = {\n id: d.id.trim(),\n name: d.name.trim() || d.id.trim(),\n agents: splitCsv(d.agents),\n members: splitCsv(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\nexport default function SettingsWorkspacesRoute(): JSX.Element {\n const { t } = useTranslation(['settings', 'common'])\n const list = useWorkspaces()\n const upsert = useUpsertWorkspace()\n\n const [draft, setDraft] = useState<DraftFields>(EMPTY_DRAFT)\n const [editing, setEditing] = useState<string | 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 const workspaces = list.data?.workspaces ?? []\n const hasOnlyDefault = workspaces.length <= 1\n && workspaces.every((w) => w.id === 'default')\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-20\" />\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 <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 </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 <FormField\n id=\"ws-agents\"\n label={t('workspaces.form.agents')}\n hint={t('workspaces.form.agentsHint')}\n value={draft.agents}\n onChange={(v) => setDraft((d) => ({ ...d, agents: v }))}\n placeholder=\"claude-code, codex\"\n mono\n />\n <FormField\n id=\"ws-members\"\n label={t('workspaces.form.members')}\n hint={t('workspaces.form.membersHint')}\n value={draft.members}\n onChange={(v) => setDraft((d) => ({ ...d, members: v }))}\n placeholder=\"wechat:wxid_abc, telegram:12345\"\n mono\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-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 </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"],"names":["Pencil","createLucideIcon","EMPTY_DRAFT","toDraft","ws","fromDraft","d","splitCsv","s","x","cfg","rate","ivl","burst","SettingsWorkspacesRoute","t","useTranslation","list","useWorkspaces","upsert","useUpsertWorkspace","draft","setDraft","useState","editing","setEditing","useEffect","startEdit","resetForm","onSubmit","e","toast","err","describeError","workspaces","hasOnlyDefault","w","jsxs","jsx","Button","Loader2","RefreshCcw","EmptyState","Briefcase","Table","TableHeader","TableRow","TableHead","TableBody","TableCell","a","Badge","FormField","v","Save","id","label","hint","value","onChange","placeholder","mono","Label","Input"],"mappings":"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","x_google_ignoreList":[0]}
|
|
1
|
+
{"version":3,"file":"workspaces-CSS_UBEi.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, useState } from 'react'\nimport { useTranslation } from 'react-i18next'\nimport { toast } from 'sonner'\nimport { Briefcase, Loader2, Pencil, RefreshCcw, Save } from 'lucide-react'\n\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 { Input } from '@/components/ui/input'\nimport { Label } from '@/components/ui/label'\nimport { useUpsertWorkspace, useWorkspaces } from '@/hooks/use-settings'\nimport { describeError } from '@/lib/api/errors'\nimport type { WorkspaceConfig } from '@/types/api'\n\ninterface DraftFields {\n id: string\n name: string\n agents: string // comma-separated\n members: string // comma-separated\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\nfunction toDraft(ws: WorkspaceConfig): DraftFields {\n return {\n id: ws.id,\n name: ws.name,\n agents: ws.agents.join(', '),\n members: (ws.members ?? []).join(', '),\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 splitCsv = (s: string): string[] =>\n s.split(',').map((x) => x.trim()).filter(Boolean)\n const cfg: WorkspaceConfig = {\n id: d.id.trim(),\n name: d.name.trim() || d.id.trim(),\n agents: splitCsv(d.agents),\n members: splitCsv(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\nexport default function SettingsWorkspacesRoute(): JSX.Element {\n const { t } = useTranslation(['settings', 'common'])\n const list = useWorkspaces()\n const upsert = useUpsertWorkspace()\n\n const [draft, setDraft] = useState<DraftFields>(EMPTY_DRAFT)\n const [editing, setEditing] = useState<string | 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 const workspaces = list.data?.workspaces ?? []\n const hasOnlyDefault = workspaces.length <= 1\n && workspaces.every((w) => w.id === 'default')\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-20\" />\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 <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 </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 <FormField\n id=\"ws-agents\"\n label={t('workspaces.form.agents')}\n hint={t('workspaces.form.agentsHint')}\n value={draft.agents}\n onChange={(v) => setDraft((d) => ({ ...d, agents: v }))}\n placeholder=\"claude-code, codex\"\n mono\n />\n <FormField\n id=\"ws-members\"\n label={t('workspaces.form.members')}\n hint={t('workspaces.form.membersHint')}\n value={draft.members}\n onChange={(v) => setDraft((d) => ({ ...d, members: v }))}\n placeholder=\"wechat:wxid_abc, telegram:12345\"\n mono\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-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 </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"],"names":["Pencil","createLucideIcon","EMPTY_DRAFT","toDraft","ws","fromDraft","d","splitCsv","s","x","cfg","rate","ivl","burst","SettingsWorkspacesRoute","t","useTranslation","list","useWorkspaces","upsert","useUpsertWorkspace","draft","setDraft","useState","editing","setEditing","useEffect","startEdit","resetForm","onSubmit","e","toast","err","describeError","workspaces","hasOnlyDefault","w","jsxs","jsx","Button","Loader2","RefreshCcw","EmptyState","Briefcase","Table","TableHeader","TableRow","TableHead","TableBody","TableCell","a","Badge","FormField","v","Save","id","label","hint","value","onChange","placeholder","mono","Label","Input"],"mappings":"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","x_google_ignoreList":[0]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import{n as e}from"./index-
|
|
1
|
+
import{n as e}from"./index-O0BQoyzo.js";/**
|
|
2
2
|
* @license lucide-react v0.469.0 - ISC
|
|
3
3
|
*
|
|
4
4
|
* This source code is licensed under the ISC license.
|
|
5
5
|
* See the LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/const o=e("X",[["path",{d:"M18 6 6 18",key:"1bl5f8"}],["path",{d:"m6 6 12 12",key:"d8bk6v"}]]);export{o as X};
|
|
7
|
-
//# sourceMappingURL=x-
|
|
7
|
+
//# sourceMappingURL=x-DG-JKVw_.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"x-
|
|
1
|
+
{"version":3,"file":"x-DG-JKVw_.js","sources":["../../node_modules/lucide-react/dist/esm/icons/x.js"],"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 X = createLucideIcon(\"X\", [\n [\"path\", { d: \"M18 6 6 18\", key: \"1bl5f8\" }],\n [\"path\", { d: \"m6 6 12 12\", key: \"d8bk6v\" }]\n]);\n\nexport { X as default };\n//# sourceMappingURL=x.js.map\n"],"names":["X","createLucideIcon"],"mappings":"wCAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GASK,MAACA,EAAIC,EAAiB,IAAK,CAC9B,CAAC,OAAQ,CAAE,EAAG,aAAc,IAAK,QAAQ,CAAE,EAC3C,CAAC,OAAQ,CAAE,EAAG,aAAc,IAAK,QAAQ,CAAE,CAC7C,CAAC","x_google_ignoreList":[0]}
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
} catch (e) { /* private-mode storage exceptions: noop */ }
|
|
36
36
|
})()
|
|
37
37
|
</script>
|
|
38
|
-
<script type="module" crossorigin src="/assets/index-
|
|
38
|
+
<script type="module" crossorigin src="/assets/index-O0BQoyzo.js"></script>
|
|
39
39
|
<link rel="modulepreload" crossorigin href="/assets/react-Cb2sDjhD.js">
|
|
40
40
|
<link rel="stylesheet" crossorigin href="/assets/index-f1K5Q2Yz.css">
|
|
41
41
|
</head>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agim-cli",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.141",
|
|
4
4
|
"description": "Agim (阿吉姆) — universal messenger-to-agent bridge. Connect WeChat / Feishu / DingTalk / Email to Claude Code / Codex / OpenCode, or any custom agent via ACP. Installs the `agim` command.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import{n as le,u as L,j as e,B as N,L as O,S as Q,f as Z,g as X,h as Y,i as I,k as U,l as f,m as F,c as J,I as R}from"./index-wVLKSZpI.js";import{r as u}from"./react-Cb2sDjhD.js";import{E as re}from"./empty-state-Bzkp-ADK.js";import{u as oe}from"./use-workspace-BOUxEbaB.js";import{b as de,c as me,h as xe,i as ue}from"./use-settings-BUM0BmtA.js";import{L as D}from"./loader-circle-DPc6botW.js";import{R as pe}from"./refresh-ccw-C2Q06LWj.js";import{X as he}from"./x-B0lqsHGi.js";import{S as ge}from"./save-3XXDgdfD.js";import{N as q}from"./network-FK3KNI1a.js";import{S as H}from"./search-oQrctQNZ.js";import{P as fe}from"./plus-CjK8x5Ta.js";import{T as je}from"./trash-2-BXhBc6TL.js";import"./useQuery-II-YwTUw.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 be=le("Bot",[["path",{d:"M12 8V4H8",key:"hb8ula"}],["rect",{width:"16",height:"12",x:"4",y:"8",rx:"2",key:"enze0r"}],["path",{d:"M2 14h2",key:"vft8re"}],["path",{d:"M20 14h2",key:"4cs60a"}],["path",{d:"M15 13v2",key:"1xurst"}],["path",{d:"M9 13v2",key:"rq6x2g"}]]),K={"claude-code":{aliases:["cc","claude"],pkg:"@anthropic-ai/claude-code"},codex:{aliases:["cx"],pkg:"@openai/codex"},opencode:{aliases:["oc"],pkg:"opencode-ai"},cursor:{aliases:["cs","cur"],pkg:"cursor-agent (curl https://cursor.com/install)"}},G=Object.keys(K);function $e(){const{t}=L(["settings","common"]),r=de(),s=oe(),i=me(),n=r.data,o=s.data??{},[d,m]=u.useState(null),[p,g]=u.useState(null),[S,j]=u.useState(null);u.useEffect(()=>{n&&d==null&&m(n.agents??[]),n&&p==null&&g(n.defaultAgent??""),n&&S==null&&j(n.acpAgents??[])},[n,d,p,S]);const h=d??n?.agents??[],b=p??n?.defaultAgent??"",k=S??n?.acpAgents??[],$=u.useMemo(()=>{if(!n)return!1;const c=h.length===(n.agents?.length??0)&&h.every(w=>n.agents?.includes(w)),v=b===(n.defaultAgent??""),y=we(k,n.acpAgents??[]);return!c||!v||!y},[n,h,b,k]),T=u.useMemo(()=>G.filter(c=>h.includes(c)&&o[c]),[h,o]);function _(c,v){const y=v?Array.from(new Set([...h,c])):h.filter(w=>w!==c);m(y),!v&&c===b&&g("")}async function M(){if(n)try{await i.mutateAsync({...n,agents:h,defaultAgent:b||n.defaultAgent,acpAgents:k}),f.success(t("agents.toast.saved")),m(null),g(null),j(null)}catch(c){f.error(F(c,t).message)}}function C(){m(null),g(null),j(null)}function P(c){j(c)}return e.jsxs("div",{className:"mx-auto flex max-w-4xl 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:t("agents.title")}),e.jsxs(N,{variant:"ghost",size:"sm",className:"ml-auto",onClick:()=>{r.refetch(),s.refetch()},disabled:r.isFetching||s.isFetching,"aria-label":t("actions.refresh",{ns:"common"}),children:[r.isFetching||s.isFetching?e.jsx(D,{className:"h-4 w-4 animate-spin"}):e.jsx(pe,{className:"h-4 w-4"}),e.jsx("span",{className:"hidden sm:inline",children:t("actions.refresh",{ns:"common"})})]})]}),e.jsx("p",{className:"text-sm text-text-dim",children:t("agents.subtitle")})]}),r.isLoading?e.jsx("div",{className:"h-64 rounded-md bg-surface-2 animate-pulse"}):e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"flex flex-col divide-y divide-border rounded-md border border-border bg-surface",children:G.map(c=>{const v=K[c],y=!!o[c],w=h.includes(c);return e.jsx(Ne,{name:c,aliases:v.aliases,pkg:v.pkg,installed:y,enabled:w,onToggle:z=>_(c,z)},c)})}),e.jsxs("section",{className:"rounded-md border border-border bg-surface p-4",children:[e.jsx(O,{htmlFor:"default-agent",className:"text-sm font-medium",children:t("agents.defaultAgent")}),e.jsx("p",{className:"mt-1 text-xs text-text-dim",children:t("agents.defaultAgentHint")}),e.jsxs(Q,{value:b||"__none__",onValueChange:c=>g(c==="__none__"?"":c),disabled:T.length===0,children:[e.jsx(Z,{id:"default-agent",className:"mt-2 w-64",children:e.jsx(X,{placeholder:t("agents.noEligible")})}),e.jsx(Y,{children:T.length===0?e.jsx(I,{value:"__none__",disabled:!0,children:t("agents.noEligible")}):T.map(c=>e.jsx(I,{value:c,children:c},c))})]})]}),n?.features?.remoteAgent?e.jsx(ke,{agents:k,onChange:P}):null,$&&e.jsxs("div",{className:"sticky bottom-0 flex items-center gap-2 rounded-md border border-border bg-surface px-4 py-2 shadow-md",children:[e.jsx(U,{variant:"info",children:t("agents.dirtyHint")}),e.jsxs(N,{variant:"secondary",size:"sm",onClick:C,disabled:i.isPending,children:[e.jsx(he,{className:"h-4 w-4"}),t("agents.discard")]}),e.jsxs(N,{size:"sm",onClick:()=>void M(),disabled:i.isPending,children:[i.isPending?e.jsx(D,{className:"h-4 w-4 animate-spin"}):e.jsx(ge,{className:"h-4 w-4"}),i.isPending?t("agents.saving"):t("agents.saveBtn")]})]})]})]})}function Ne({name:t,aliases:r,pkg:s,installed:i,enabled:n,onToggle:o}){const{t:d}=L("settings");return e.jsxs("div",{className:"flex items-start gap-3 px-3 py-3",children:[e.jsx("div",{className:"flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-surface-2 text-text-dim",children:e.jsx(be,{className:"h-4 w-4"})}),e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsx("span",{className:"font-medium text-text",children:t}),e.jsxs(U,{variant:i?"success":"outline",className:"text-[10px]",children:[e.jsx("span",{className:J("inline-block h-1.5 w-1.5 rounded-full",i?"bg-success":"bg-text-muted")}),d(i?"agents.online":"agents.offline")]})]}),e.jsxs("p",{className:"mt-0.5 text-xs text-text-dim",children:[e.jsxs("span",{className:"text-text-muted",children:[d("agents.aliasesLabel"),": "]}),e.jsx("span",{className:"font-mono",children:r.map(m=>`/${m}`).join(", ")})]}),!i&&e.jsx("p",{className:"mt-1 text-xs text-warning",children:d("agents.installHint",{pkg:s})})]}),e.jsx("input",{type:"checkbox",checked:n,onChange:m=>o(m.target.checked),className:"h-4 w-4 mt-2 accent-accent cursor-pointer"})]})}const ve=["none","apikey","bearer"],ye=/^[a-zA-Z0-9][a-zA-Z0-9._-]*$/;function we(t,r){if(t.length!==r.length)return!1;for(let s=0;s<t.length;s++){const i=t[s],n=r[s];if(i.name!==n.name||i.endpoint!==n.endpoint||(i.enabled??!0)!==(n.enabled??!0))return!1;const o=(i.aliases??[]).join(","),d=(n.aliases??[]).join(",");if(o!==d)return!1;const m=i.auth?.type??"none",p=n.auth?.type??"none";if(m!==p||(i.auth?.token??"")!==(n.auth?.token??""))return!1}return!0}function ke({agents:t,onChange:r}){const{t:s}=L(["settings","common"]),i=xe(),n=ue(),[o,d]=u.useState(""),[m,p]=u.useState(""),[g,S]=u.useState(""),[j,h]=u.useState("none"),[b,k]=u.useState(""),[$,T]=u.useState(!1),[_,M]=u.useState(""),C=o.trim(),P=C.length>0&&ye.test(C),c=t.some(a=>a.name===C),y=!(j!=="none")||b.trim().length>0,w=P&&g.trim().length>0&&y&&!c,z=g.trim().length>0&&y;function W(){d(""),p(""),S(""),h("none"),k("")}function ee(a){return a.split(",").map(l=>l.trim()).filter(Boolean)}function V(a,l){if(a==="none")return{type:"none"};const x=l.trim();return x?{type:a,token:x}:{type:a}}async function se(){if(!w)return;const a={name:C,endpoint:g.trim(),aliases:ee(m),auth:V(j,b),enabled:!0};r([...t,a]),W(),f.success(s("agents.acp.toast.staged"))}async function te(){if(z)try{const a=await i.mutateAsync({endpoint:g.trim(),auth:V(j,b)});f.success(s("agents.acp.toast.testOk",{name:a.name}))}catch(a){f.error(F(a,s).message)}}async function ae(a){const l=t[a];if(l){if(l.auth?.type!=="none"&&l.auth?.token&&Se(l.auth.token)){f.error(s("agents.acp.toast.testMasked"));return}try{const x=await i.mutateAsync({endpoint:l.endpoint,auth:l.auth});f.success(s("agents.acp.toast.testOk",{name:x.name}))}catch(x){f.error(F(x,s).message)}}}function ne(a,l){const x=t.map((E,A)=>A===a?{...E,enabled:l}:E);r(x)}function ce(a){r(t.filter((l,x)=>x!==a))}async function ie(){const a=_.trim();if(a)try{const l=await n.mutateAsync({baseUrl:a,register:!1}),x=new Set(t.map(A=>A.name)),E=l.agents.filter(A=>!x.has(A.name));if(E.length===0){f.info(s("agents.acp.toast.discoverEmpty"));return}r([...t,...E.map(A=>({...A,enabled:!0}))]),f.success(s("agents.acp.toast.discoverAdded",{count:E.length})),M(""),T(!1)}catch(l){f.error(F(l,s).message)}}return e.jsxs("section",{className:"rounded-md border border-border bg-surface",children:[e.jsxs("header",{className:"flex items-center gap-2 border-b border-border px-4 py-3",children:[e.jsx(q,{className:"h-4 w-4 text-text-dim"}),e.jsx("h2",{className:"text-sm font-semibold",children:s("agents.acp.title")}),e.jsx(U,{variant:"outline",className:"text-[10px]",children:t.length}),e.jsxs(N,{variant:"ghost",size:"sm",className:"ml-auto",onClick:()=>T(a=>!a),children:[e.jsx(H,{className:"h-4 w-4"}),e.jsx("span",{className:"hidden sm:inline",children:s("agents.acp.discoverBtn")})]})]}),e.jsx("p",{className:"px-4 pt-2 text-xs text-text-dim",children:s("agents.acp.subtitle")}),$&&e.jsxs("div",{className:"border-t border-border bg-surface-2 px-4 py-3",children:[e.jsx(O,{htmlFor:"acp-baseurl",className:"text-xs font-medium",children:s("agents.acp.baseUrl")}),e.jsx("p",{className:"mt-1 text-[11px] text-text-dim",children:s("agents.acp.baseUrlHint")}),e.jsxs("div",{className:"mt-2 flex flex-wrap gap-2",children:[e.jsx(R,{id:"acp-baseurl",value:_,onChange:a=>M(a.target.value),placeholder:"https://agents.example.com",className:"flex-1 min-w-[200px] font-mono text-xs"}),e.jsxs(N,{variant:"secondary",size:"sm",onClick:()=>void ie(),disabled:!_.trim()||n.isPending,children:[n.isPending?e.jsx(D,{className:"h-4 w-4 animate-spin"}):e.jsx(H,{className:"h-4 w-4"}),s("agents.acp.runDiscover")]})]})]}),t.length===0?e.jsx("div",{className:"px-4 py-6",children:e.jsx(re,{icon:e.jsx(q,{}),title:s("agents.acp.empty.title"),description:s("agents.acp.empty.description")})}):e.jsx("ul",{className:"divide-y divide-border",children:t.map((a,l)=>e.jsx(Ae,{agent:a,onToggle:x=>ne(l,x),onTest:()=>void ae(l),onRemove:()=>ce(l),testing:i.isPending},`${a.name}-${l}`))}),e.jsxs("div",{className:"border-t border-border px-4 py-3",children:[e.jsx("h3",{className:"text-xs font-semibold uppercase tracking-wide text-text-dim",children:s("agents.acp.addTitle")}),e.jsxs("div",{className:"mt-2 grid grid-cols-1 gap-2 sm:grid-cols-2",children:[e.jsx(B,{label:s("agents.acp.name"),hint:s("agents.acp.nameHint"),children:e.jsx(R,{value:o,onChange:a=>d(a.target.value),placeholder:"my-agent","aria-invalid":o.length>0&&!P})}),e.jsx(B,{label:s("agents.acp.aliases"),hint:s("agents.acp.aliasesHint"),children:e.jsx(R,{value:m,onChange:a=>p(a.target.value),placeholder:"ma, agent1"})}),e.jsx(B,{label:s("agents.acp.endpoint"),hint:s("agents.acp.endpointHint"),children:e.jsx(R,{value:g,onChange:a=>S(a.target.value),placeholder:"https://example.com/agents/weather",className:"font-mono text-xs"})}),e.jsx(B,{label:s("agents.acp.authType"),children:e.jsxs(Q,{value:j,onValueChange:a=>h(a),children:[e.jsx(Z,{children:e.jsx(X,{})}),e.jsx(Y,{children:ve.map(a=>e.jsx(I,{value:a,children:s(`agents.acp.auth.${a}`)},a))})]})}),j!=="none"&&e.jsx(B,{label:s("agents.acp.token"),className:"sm:col-span-2",children:e.jsx(R,{type:"password",value:b,onChange:a=>k(a.target.value),placeholder:s("agents.acp.tokenPlaceholder"),autoComplete:"new-password"})})]}),e.jsxs("div",{className:"mt-3 flex flex-wrap gap-2",children:[e.jsxs(N,{variant:"secondary",size:"sm",onClick:()=>void te(),disabled:!z||i.isPending,children:[i.isPending?e.jsx(D,{className:"h-4 w-4 animate-spin"}):e.jsx(H,{className:"h-4 w-4"}),s("agents.acp.testBtn")]}),e.jsxs(N,{size:"sm",onClick:()=>void se(),disabled:!w,children:[e.jsx(fe,{className:"h-4 w-4"}),s("agents.acp.addBtn")]}),c&&e.jsx("span",{className:"self-center text-xs text-warning",children:s("agents.acp.dupName")})]})]})]})}function Ae({agent:t,onToggle:r,onTest:s,onRemove:i,testing:n}){const{t:o}=L("settings"),d=t.enabled!==!1,m=t.auth?.type??"none";return e.jsxs("li",{className:"flex flex-wrap items-center gap-3 px-4 py-3",children:[e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsx("span",{className:"font-medium text-text",children:t.name}),e.jsx(U,{variant:"outline",className:"text-[10px] uppercase",children:o(`agents.acp.auth.${m}`)}),t.aliases&&t.aliases.length>0&&e.jsx("span",{className:"text-xs text-text-muted font-mono",children:t.aliases.map(p=>`/${p}`).join(", ")})]}),e.jsx("p",{className:"mt-0.5 truncate font-mono text-xs text-text-dim",title:t.endpoint,children:t.endpoint})]}),e.jsxs("label",{className:"flex items-center gap-1.5 text-xs text-text-dim",children:[e.jsx("input",{type:"checkbox",checked:d,onChange:p=>r(p.target.checked),className:"h-4 w-4 accent-accent cursor-pointer"}),o(d?"agents.acp.on":"agents.acp.off")]}),e.jsx(N,{variant:"ghost",size:"sm",onClick:s,disabled:n,"aria-label":o("agents.acp.testBtn"),children:n?e.jsx(D,{className:"h-4 w-4 animate-spin"}):e.jsx(H,{className:"h-4 w-4"})}),e.jsx(N,{variant:"ghost",size:"sm",onClick:i,"aria-label":o("agents.acp.removeBtn"),className:"text-danger hover:text-danger",children:e.jsx(je,{className:"h-4 w-4"})})]})}function B({label:t,hint:r,className:s,children:i}){return e.jsxs("div",{className:J("flex flex-col gap-1",s),children:[e.jsx(O,{className:"text-xs font-medium",children:t}),i,r&&e.jsx("p",{className:"text-[11px] text-text-dim",children:r})]})}function Se(t){return/\*{3,}/.test(t)}export{$e as default};
|
|
7
|
-
//# sourceMappingURL=agents-0IMyFVui.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"agents-0IMyFVui.js","sources":["../../node_modules/lucide-react/dist/esm/icons/bot.js","../../src/routes/settings/agents.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 Bot = createLucideIcon(\"Bot\", [\n [\"path\", { d: \"M12 8V4H8\", key: \"hb8ula\" }],\n [\"rect\", { width: \"16\", height: \"12\", x: \"4\", y: \"8\", rx: \"2\", key: \"enze0r\" }],\n [\"path\", { d: \"M2 14h2\", key: \"vft8re\" }],\n [\"path\", { d: \"M20 14h2\", key: \"4cs60a\" }],\n [\"path\", { d: \"M15 13v2\", key: \"1xurst\" }],\n [\"path\", { d: \"M9 13v2\", key: \"rq6x2g\" }]\n]);\n\nexport { Bot as default };\n//# sourceMappingURL=bot.js.map\n","/**\n * /settings/agents — built-in adapters + remote (ACP) agents.\n *\n * Two cards on one page:\n * 1. Built-in adapters (claude-code / codex / opencode):\n * enable/disable + default-agent picker. Mirrors v1's \"Agents\".\n * 2. Remote (ACP) agents: name/endpoint/auth-type table + manual\n * add form. Mirrors v1's \"Remote Agents (ACP)\" card. Discover\n * via `<baseUrl>/.well-known/acp` is available as a secondary\n * bulk-import form.\n *\n * Both cards share one save bar — PUT /api/config writes `agents[]`,\n * `defaultAgent`, and `acpAgents[]` atomically so the default never\n * goes out of sync with the enabled list, and partial ACP edits\n * don't ship without the user's intent.\n *\n * Masked tokens: GET returns `ab****yz` for ACP auth.token; PUT\n * detects this pattern and preserves the on-disk value so we never\n * overwrite a real token with its mask. New tokens (typed into the\n * add form or \"edit\" inline) flow through verbatim.\n */\n\nimport { useEffect, useMemo, useState } from 'react'\nimport { useTranslation } from 'react-i18next'\nimport { toast } from 'sonner'\nimport {\n Bot, Loader2, Network, Plus, RefreshCcw, Save, Search, Trash2, X,\n} from 'lucide-react'\n\nimport { Badge } from '@/components/ui/badge'\nimport { Button } from '@/components/ui/button'\nimport { Input } from '@/components/ui/input'\nimport { Label } from '@/components/ui/label'\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@/components/ui/select'\nimport { EmptyState } from '@/components/common/empty-state'\nimport { useAgentsStatus } from '@/hooks/use-workspace'\nimport {\n useConfig,\n useDiscoverAcp,\n useTestAcp,\n useUpdateConfig,\n} from '@/hooks/use-settings'\nimport { describeError } from '@/lib/api/errors'\nimport { cn } from '@/lib/utils'\nimport type { ACPAgentConfig, ACPAuthConfig, ACPAuthType } from '@/types/api'\n\n/** Mirror of v1 settings.html:BUILTIN_AGENTS. Hardcoded because\n * backend doesn't expose this metadata yet; the table changes\n * rarely enough that copying it here is fine. */\nconst BUILTIN_AGENTS: Record<string, { aliases: string[]; pkg: string }> = {\n 'claude-code': { aliases: ['cc', 'claude'], pkg: '@anthropic-ai/claude-code' },\n 'codex': { aliases: ['cx'], pkg: '@openai/codex' },\n 'opencode': { aliases: ['oc'], pkg: 'opencode-ai' },\n 'cursor': { aliases: ['cs', 'cur'], pkg: 'cursor-agent (curl https://cursor.com/install)' },\n}\n\nconst AGENT_NAMES = Object.keys(BUILTIN_AGENTS)\n\nexport default function SettingsAgentsRoute(): JSX.Element {\n const { t } = useTranslation(['settings', 'common'])\n const cfgQuery = useConfig()\n const statusQuery = useAgentsStatus()\n const updateCfg = useUpdateConfig()\n\n const cfg = cfgQuery.data\n const status = statusQuery.data ?? {}\n\n /** Local draft so toggles + default-picker + ACP edits can stage\n * changes before a single Save. `null` means \"sync from cfg on\n * next paint\". */\n const [draftEnabled, setDraftEnabled] = useState<string[] | null>(null)\n const [draftDefault, setDraftDefault] = useState<string | null>(null)\n const [draftAcp, setDraftAcp] = useState<ACPAgentConfig[] | null>(null)\n\n useEffect(() => {\n if (cfg && draftEnabled == null) setDraftEnabled(cfg.agents ?? [])\n if (cfg && draftDefault == null) setDraftDefault(cfg.defaultAgent ?? '')\n if (cfg && draftAcp == null) setDraftAcp(cfg.acpAgents ?? [])\n }, [cfg, draftEnabled, draftDefault, draftAcp])\n\n const enabled = draftEnabled ?? cfg?.agents ?? []\n const defaultAgent = draftDefault ?? cfg?.defaultAgent ?? ''\n const acpAgents = draftAcp ?? cfg?.acpAgents ?? []\n\n const isDirty = useMemo(() => {\n if (!cfg) return false\n const enabledSame =\n enabled.length === (cfg.agents?.length ?? 0)\n && enabled.every((a) => cfg.agents?.includes(a))\n const defaultSame = defaultAgent === (cfg.defaultAgent ?? '')\n const acpSame = acpEqual(acpAgents, cfg.acpAgents ?? [])\n return !enabledSame || !defaultSame || !acpSame\n }, [cfg, enabled, defaultAgent, acpAgents])\n\n /** Eligible defaults = installed + enabled. Picker disables when\n * empty (no agent is both). */\n const eligibleDefaults = useMemo(\n () => AGENT_NAMES.filter((a) => enabled.includes(a) && status[a]),\n [enabled, status],\n )\n\n function toggleAgent(name: string, on: boolean): void {\n const next = on\n ? Array.from(new Set([...enabled, name]))\n : enabled.filter((a) => a !== name)\n setDraftEnabled(next)\n // If the default just got disabled, clear it so save doesn't\n // ship an inconsistent pair.\n if (!on && name === defaultAgent) setDraftDefault('')\n }\n\n async function onSave(): Promise<void> {\n if (!cfg) return\n try {\n await updateCfg.mutateAsync({\n ...cfg,\n agents: enabled,\n defaultAgent: defaultAgent || cfg.defaultAgent,\n acpAgents,\n })\n toast.success(t('agents.toast.saved'))\n // Reset drafts so the next paint reads from refreshed cfg.\n setDraftEnabled(null)\n setDraftDefault(null)\n setDraftAcp(null)\n } catch (err) {\n toast.error(describeError(err, t).message)\n }\n }\n\n function onDiscard(): void {\n setDraftEnabled(null)\n setDraftDefault(null)\n setDraftAcp(null)\n }\n\n function updateAcp(next: ACPAgentConfig[]): void {\n setDraftAcp(next)\n }\n\n return (\n <div className=\"mx-auto flex max-w-4xl 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('agents.title')}</h1>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"ml-auto\"\n onClick={() => {\n void cfgQuery.refetch()\n void statusQuery.refetch()\n }}\n disabled={cfgQuery.isFetching || statusQuery.isFetching}\n aria-label={t('actions.refresh', { ns: 'common' })}\n >\n {(cfgQuery.isFetching || statusQuery.isFetching)\n ? <Loader2 className=\"h-4 w-4 animate-spin\" />\n : <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('agents.subtitle')}</p>\n </header>\n\n {cfgQuery.isLoading ? (\n <div className=\"h-64 rounded-md bg-surface-2 animate-pulse\" />\n ) : (\n <>\n {/* Agent rows */}\n <div className=\"flex flex-col divide-y divide-border rounded-md border border-border bg-surface\">\n {AGENT_NAMES.map((name) => {\n const info = BUILTIN_AGENTS[name]!\n const installed = !!status[name]\n const isEnabled = enabled.includes(name)\n return (\n <AgentRow\n key={name}\n name={name}\n aliases={info.aliases}\n pkg={info.pkg}\n installed={installed}\n enabled={isEnabled}\n onToggle={(on) => toggleAgent(name, on)}\n />\n )\n })}\n </div>\n\n {/* Default agent picker */}\n <section className=\"rounded-md border border-border bg-surface p-4\">\n <Label htmlFor=\"default-agent\" className=\"text-sm font-medium\">\n {t('agents.defaultAgent')}\n </Label>\n <p className=\"mt-1 text-xs text-text-dim\">{t('agents.defaultAgentHint')}</p>\n <Select\n value={defaultAgent || '__none__'}\n onValueChange={(v) => setDraftDefault(v === '__none__' ? '' : v)}\n disabled={eligibleDefaults.length === 0}\n >\n <SelectTrigger id=\"default-agent\" className=\"mt-2 w-64\">\n <SelectValue placeholder={t('agents.noEligible')} />\n </SelectTrigger>\n <SelectContent>\n {eligibleDefaults.length === 0 ? (\n <SelectItem value=\"__none__\" disabled>{t('agents.noEligible')}</SelectItem>\n ) : (\n eligibleDefaults.map((a) => (\n <SelectItem key={a} value={a}>{a}</SelectItem>\n ))\n )}\n </SelectContent>\n </Select>\n </section>\n\n {/* Remote (ACP) agents — gated by features.remoteAgent\n (IMHUB_ENABLE_REMOTE_AGENT on server). Card is omitted\n entirely; no breadcrumb hint shown. */}\n {cfg?.features?.remoteAgent ? (\n <AcpCard\n agents={acpAgents}\n onChange={updateAcp}\n />\n ) : null}\n\n {/* Save bar */}\n {isDirty && (\n <div className=\"sticky bottom-0 flex items-center gap-2 rounded-md border border-border bg-surface px-4 py-2 shadow-md\">\n <Badge variant=\"info\">{t('agents.dirtyHint')}</Badge>\n <Button\n variant=\"secondary\"\n size=\"sm\"\n onClick={onDiscard}\n disabled={updateCfg.isPending}\n >\n <X className=\"h-4 w-4\" />\n {t('agents.discard')}\n </Button>\n <Button\n size=\"sm\"\n onClick={() => void onSave()}\n disabled={updateCfg.isPending}\n >\n {updateCfg.isPending ? <Loader2 className=\"h-4 w-4 animate-spin\" /> : <Save className=\"h-4 w-4\" />}\n {updateCfg.isPending ? t('agents.saving') : t('agents.saveBtn')}\n </Button>\n </div>\n )}\n </>\n )}\n </div>\n )\n}\n\n/* ─────────────── Row ─────────────── */\n\ninterface AgentRowProps {\n name: string\n aliases: string[]\n pkg: string\n installed: boolean\n enabled: boolean\n onToggle: (on: boolean) => void\n}\n\nfunction AgentRow({\n name, aliases, pkg, installed, enabled, onToggle,\n}: AgentRowProps): JSX.Element {\n const { t } = useTranslation('settings')\n return (\n <div className=\"flex items-start gap-3 px-3 py-3\">\n <div className=\"flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-surface-2 text-text-dim\">\n <Bot className=\"h-4 w-4\" />\n </div>\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <span className=\"font-medium text-text\">{name}</span>\n <Badge variant={installed ? 'success' : 'outline'} className=\"text-[10px]\">\n <span className={cn(\n 'inline-block h-1.5 w-1.5 rounded-full',\n installed ? 'bg-success' : 'bg-text-muted',\n )} />\n {installed ? t('agents.online') : t('agents.offline')}\n </Badge>\n </div>\n <p className=\"mt-0.5 text-xs text-text-dim\">\n <span className=\"text-text-muted\">{t('agents.aliasesLabel')}: </span>\n <span className=\"font-mono\">{aliases.map((a) => `/${a}`).join(', ')}</span>\n </p>\n {!installed && (\n <p className=\"mt-1 text-xs text-warning\">\n {t('agents.installHint', { pkg })}\n </p>\n )}\n </div>\n <input\n type=\"checkbox\"\n checked={enabled}\n onChange={(e) => onToggle(e.target.checked)}\n className=\"h-4 w-4 mt-2 accent-accent cursor-pointer\"\n />\n </div>\n )\n}\n\n/* ─────────────── Remote (ACP) ─────────────── */\n\nconst AUTH_TYPES: ACPAuthType[] = ['none', 'apikey', 'bearer']\nconst NAME_RE = /^[a-zA-Z0-9][a-zA-Z0-9._-]*$/\n\n/** Compare two ACP lists by value. Order matters because the backend\n * preserves index identity (`existing.acpAgents[i]`) when merging\n * masked tokens — reordering = mask drift risk. */\nfunction acpEqual(a: ACPAgentConfig[], b: ACPAgentConfig[]): boolean {\n if (a.length !== b.length) return false\n for (let i = 0; i < a.length; i++) {\n const x = a[i]!\n const y = b[i]!\n if (x.name !== y.name) return false\n if (x.endpoint !== y.endpoint) return false\n if ((x.enabled ?? true) !== (y.enabled ?? true)) return false\n const xa = (x.aliases ?? []).join(',')\n const ya = (y.aliases ?? []).join(',')\n if (xa !== ya) return false\n const xat = x.auth?.type ?? 'none'\n const yat = y.auth?.type ?? 'none'\n if (xat !== yat) return false\n if ((x.auth?.token ?? '') !== (y.auth?.token ?? '')) return false\n }\n return true\n}\n\ninterface AcpCardProps {\n agents: ACPAgentConfig[]\n onChange: (next: ACPAgentConfig[]) => void\n}\n\nfunction AcpCard({ agents, onChange }: AcpCardProps): JSX.Element {\n const { t } = useTranslation(['settings', 'common'])\n const testMut = useTestAcp()\n const discoverMut = useDiscoverAcp()\n\n // Add-form state. We keep the typed token in plain state so the\n // user can paste before save; the masked round-trip from backend\n // only matters for existing rows.\n const [name, setName] = useState('')\n const [aliasesText, setAliasesText] = useState('')\n const [endpoint, setEndpoint] = useState('')\n const [authType, setAuthType] = useState<ACPAuthType>('none')\n const [token, setToken] = useState('')\n\n // Bulk-discover sub-form state. Hidden behind a toggle so the\n // primary path (manual add) stays uncluttered.\n const [showDiscover, setShowDiscover] = useState(false)\n const [baseUrl, setBaseUrl] = useState('')\n\n const trimmedName = name.trim()\n const nameValid = trimmedName.length > 0 && NAME_RE.test(trimmedName)\n const dup = agents.some((a) => a.name === trimmedName)\n const tokenRequired = authType !== 'none'\n const tokenOk = !tokenRequired || token.trim().length > 0\n const canAdd = nameValid && endpoint.trim().length > 0 && tokenOk && !dup\n const canTestNew = endpoint.trim().length > 0 && tokenOk\n\n function clearForm(): void {\n setName('')\n setAliasesText('')\n setEndpoint('')\n setAuthType('none')\n setToken('')\n }\n\n function parseAliases(text: string): string[] {\n return text.split(',').map((s) => s.trim()).filter(Boolean)\n }\n\n function buildAuth(type: ACPAuthType, tok: string): ACPAuthConfig | undefined {\n if (type === 'none') return { type: 'none' }\n const trimmed = tok.trim()\n if (!trimmed) return { type } // no token yet; save will reject\n return { type, token: trimmed }\n }\n\n async function onAdd(): Promise<void> {\n if (!canAdd) return\n const next: ACPAgentConfig = {\n name: trimmedName,\n endpoint: endpoint.trim(),\n aliases: parseAliases(aliasesText),\n auth: buildAuth(authType, token),\n enabled: true,\n }\n onChange([...agents, next])\n clearForm()\n toast.success(t('agents.acp.toast.staged'))\n }\n\n async function onTestNew(): Promise<void> {\n if (!canTestNew) return\n try {\n const res = await testMut.mutateAsync({\n endpoint: endpoint.trim(),\n auth: buildAuth(authType, token),\n })\n toast.success(t('agents.acp.toast.testOk', { name: res.name }))\n } catch (err) {\n toast.error(describeError(err, t).message)\n }\n }\n\n async function onTestRow(idx: number): Promise<void> {\n const a = agents[idx]\n if (!a) return\n // Masked tokens stay masked on the wire — backend's PUT mask-detect\n // is symmetric, but the test endpoint reads what we send. We can't\n // unmask client-side; warn the operator.\n if (a.auth?.type !== 'none' && a.auth?.token && isMaskedToken(a.auth.token)) {\n toast.error(t('agents.acp.toast.testMasked'))\n return\n }\n try {\n const res = await testMut.mutateAsync({\n endpoint: a.endpoint,\n auth: a.auth,\n })\n toast.success(t('agents.acp.toast.testOk', { name: res.name }))\n } catch (err) {\n toast.error(describeError(err, t).message)\n }\n }\n\n function onToggleRow(idx: number, on: boolean): void {\n const next = agents.map((a, i) => (i === idx ? { ...a, enabled: on } : a))\n onChange(next)\n }\n\n function onRemoveRow(idx: number): void {\n onChange(agents.filter((_, i) => i !== idx))\n }\n\n async function onDiscoverRun(): Promise<void> {\n const url = baseUrl.trim()\n if (!url) return\n try {\n const res = await discoverMut.mutateAsync({ baseUrl: url, register: false })\n // Stage new agents that aren't already in the list (by name).\n const existing = new Set(agents.map((a) => a.name))\n const incoming = res.agents.filter((a) => !existing.has(a.name))\n if (incoming.length === 0) {\n toast.info(t('agents.acp.toast.discoverEmpty'))\n return\n }\n onChange([...agents, ...incoming.map((a) => ({ ...a, enabled: true }))])\n toast.success(t('agents.acp.toast.discoverAdded', { count: incoming.length }))\n setBaseUrl('')\n setShowDiscover(false)\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\">\n <header className=\"flex items-center gap-2 border-b border-border px-4 py-3\">\n <Network className=\"h-4 w-4 text-text-dim\" />\n <h2 className=\"text-sm font-semibold\">{t('agents.acp.title')}</h2>\n <Badge variant=\"outline\" className=\"text-[10px]\">{agents.length}</Badge>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"ml-auto\"\n onClick={() => setShowDiscover((v) => !v)}\n >\n <Search className=\"h-4 w-4\" />\n <span className=\"hidden sm:inline\">{t('agents.acp.discoverBtn')}</span>\n </Button>\n </header>\n <p className=\"px-4 pt-2 text-xs text-text-dim\">{t('agents.acp.subtitle')}</p>\n\n {/* Discover form (collapsed by default) */}\n {showDiscover && (\n <div className=\"border-t border-border bg-surface-2 px-4 py-3\">\n <Label htmlFor=\"acp-baseurl\" className=\"text-xs font-medium\">\n {t('agents.acp.baseUrl')}\n </Label>\n <p className=\"mt-1 text-[11px] text-text-dim\">{t('agents.acp.baseUrlHint')}</p>\n <div className=\"mt-2 flex flex-wrap gap-2\">\n <Input\n id=\"acp-baseurl\"\n value={baseUrl}\n onChange={(e) => setBaseUrl(e.target.value)}\n placeholder=\"https://agents.example.com\"\n className=\"flex-1 min-w-[200px] font-mono text-xs\"\n />\n <Button\n variant=\"secondary\"\n size=\"sm\"\n onClick={() => void onDiscoverRun()}\n disabled={!baseUrl.trim() || discoverMut.isPending}\n >\n {discoverMut.isPending\n ? <Loader2 className=\"h-4 w-4 animate-spin\" />\n : <Search className=\"h-4 w-4\" />}\n {t('agents.acp.runDiscover')}\n </Button>\n </div>\n </div>\n )}\n\n {/* Registered ACP agents */}\n {agents.length === 0 ? (\n <div className=\"px-4 py-6\">\n <EmptyState\n icon={<Network />}\n title={t('agents.acp.empty.title')}\n description={t('agents.acp.empty.description')}\n />\n </div>\n ) : (\n <ul className=\"divide-y divide-border\">\n {agents.map((a, i) => (\n <AcpRow\n key={`${a.name}-${i}`}\n agent={a}\n onToggle={(on) => onToggleRow(i, on)}\n onTest={() => void onTestRow(i)}\n onRemove={() => onRemoveRow(i)}\n testing={testMut.isPending}\n />\n ))}\n </ul>\n )}\n\n {/* Add-agent form */}\n <div className=\"border-t border-border px-4 py-3\">\n <h3 className=\"text-xs font-semibold uppercase tracking-wide text-text-dim\">\n {t('agents.acp.addTitle')}\n </h3>\n <div className=\"mt-2 grid grid-cols-1 gap-2 sm:grid-cols-2\">\n <Field label={t('agents.acp.name')} hint={t('agents.acp.nameHint')}>\n <Input\n value={name}\n onChange={(e) => setName(e.target.value)}\n placeholder=\"my-agent\"\n aria-invalid={name.length > 0 && !nameValid}\n />\n </Field>\n <Field label={t('agents.acp.aliases')} hint={t('agents.acp.aliasesHint')}>\n <Input\n value={aliasesText}\n onChange={(e) => setAliasesText(e.target.value)}\n placeholder=\"ma, agent1\"\n />\n </Field>\n <Field label={t('agents.acp.endpoint')} hint={t('agents.acp.endpointHint')}>\n <Input\n value={endpoint}\n onChange={(e) => setEndpoint(e.target.value)}\n placeholder=\"https://example.com/agents/weather\"\n className=\"font-mono text-xs\"\n />\n </Field>\n <Field label={t('agents.acp.authType')}>\n <Select value={authType} onValueChange={(v) => setAuthType(v as ACPAuthType)}>\n <SelectTrigger><SelectValue /></SelectTrigger>\n <SelectContent>\n {AUTH_TYPES.map((a) => (\n <SelectItem key={a} value={a}>{t(`agents.acp.auth.${a}`)}</SelectItem>\n ))}\n </SelectContent>\n </Select>\n </Field>\n {authType !== 'none' && (\n <Field label={t('agents.acp.token')} className=\"sm:col-span-2\">\n <Input\n type=\"password\"\n value={token}\n onChange={(e) => setToken(e.target.value)}\n placeholder={t('agents.acp.tokenPlaceholder')}\n autoComplete=\"new-password\"\n />\n </Field>\n )}\n </div>\n <div className=\"mt-3 flex flex-wrap gap-2\">\n <Button\n variant=\"secondary\"\n size=\"sm\"\n onClick={() => void onTestNew()}\n disabled={!canTestNew || testMut.isPending}\n >\n {testMut.isPending\n ? <Loader2 className=\"h-4 w-4 animate-spin\" />\n : <Search className=\"h-4 w-4\" />}\n {t('agents.acp.testBtn')}\n </Button>\n <Button\n size=\"sm\"\n onClick={() => void onAdd()}\n disabled={!canAdd}\n >\n <Plus className=\"h-4 w-4\" />\n {t('agents.acp.addBtn')}\n </Button>\n {dup && (\n <span className=\"self-center text-xs text-warning\">\n {t('agents.acp.dupName')}\n </span>\n )}\n </div>\n </div>\n </section>\n )\n}\n\ninterface AcpRowProps {\n agent: ACPAgentConfig\n onToggle: (on: boolean) => void\n onTest: () => void\n onRemove: () => void\n testing: boolean\n}\n\nfunction AcpRow({ agent, onToggle, onTest, onRemove, testing }: AcpRowProps): JSX.Element {\n const { t } = useTranslation('settings')\n const isOn = agent.enabled !== false\n const authType = agent.auth?.type ?? 'none'\n return (\n <li className=\"flex flex-wrap items-center gap-3 px-4 py-3\">\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <span className=\"font-medium text-text\">{agent.name}</span>\n <Badge variant=\"outline\" className=\"text-[10px] uppercase\">\n {t(`agents.acp.auth.${authType}`)}\n </Badge>\n {agent.aliases && agent.aliases.length > 0 && (\n <span className=\"text-xs text-text-muted font-mono\">\n {agent.aliases.map((a) => `/${a}`).join(', ')}\n </span>\n )}\n </div>\n <p className=\"mt-0.5 truncate font-mono text-xs text-text-dim\" title={agent.endpoint}>\n {agent.endpoint}\n </p>\n </div>\n <label className=\"flex items-center gap-1.5 text-xs text-text-dim\">\n <input\n type=\"checkbox\"\n checked={isOn}\n onChange={(e) => onToggle(e.target.checked)}\n className=\"h-4 w-4 accent-accent cursor-pointer\"\n />\n {isOn ? t('agents.acp.on') : t('agents.acp.off')}\n </label>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={onTest}\n disabled={testing}\n aria-label={t('agents.acp.testBtn')}\n >\n {testing ? <Loader2 className=\"h-4 w-4 animate-spin\" /> : <Search className=\"h-4 w-4\" />}\n </Button>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={onRemove}\n aria-label={t('agents.acp.removeBtn')}\n className=\"text-danger hover:text-danger\"\n >\n <Trash2 className=\"h-4 w-4\" />\n </Button>\n </li>\n )\n}\n\ninterface FieldProps {\n label: string\n hint?: string\n className?: string\n children: React.ReactNode\n}\n\nfunction Field({ label, hint, className, children }: FieldProps): JSX.Element {\n return (\n <div className={cn('flex flex-col gap-1', className)}>\n <Label className=\"text-xs font-medium\">{label}</Label>\n {children}\n {hint && <p className=\"text-[11px] text-text-dim\">{hint}</p>}\n </div>\n )\n}\n\n/** Tokens look like `ab****yz` from the masked GET response. We\n * shouldn't send them back unchanged for test (the backend would\n * fail auth), and we shouldn't include them in the test mutation\n * body either. Treat any string with 3+ consecutive `*` as masked. */\nfunction isMaskedToken(s: string): boolean {\n return /\\*{3,}/.test(s)\n}\n"],"names":["Bot","createLucideIcon","BUILTIN_AGENTS","AGENT_NAMES","SettingsAgentsRoute","useTranslation","cfgQuery","useConfig","statusQuery","useAgentsStatus","updateCfg","useUpdateConfig","cfg","status","draftEnabled","setDraftEnabled","useState","draftDefault","setDraftDefault","draftAcp","setDraftAcp","useEffect","enabled","defaultAgent","acpAgents","isDirty","useMemo","enabledSame","a","defaultSame","acpSame","acpEqual","eligibleDefaults","toggleAgent","name","on","next","onSave","toast","err","describeError","onDiscard","updateAcp","jsxs","jsx","Button","Loader2","RefreshCcw","Fragment","info","installed","isEnabled","AgentRow","Label","Select","v","SelectTrigger","SelectValue","SelectContent","SelectItem","AcpCard","Badge","X","Save","aliases","pkg","onToggle","t","cn","e","AUTH_TYPES","NAME_RE","b","i","x","y","xa","ya","xat","yat","agents","onChange","testMut","useTestAcp","discoverMut","useDiscoverAcp","setName","aliasesText","setAliasesText","endpoint","setEndpoint","authType","setAuthType","token","setToken","showDiscover","setShowDiscover","baseUrl","setBaseUrl","trimmedName","nameValid","dup","tokenOk","canAdd","canTestNew","clearForm","parseAliases","text","s","buildAuth","type","tok","trimmed","onAdd","onTestNew","res","onTestRow","idx","isMaskedToken","onToggleRow","onRemoveRow","_","onDiscoverRun","url","existing","incoming","Network","Search","Input","EmptyState","AcpRow","Field","Plus","agent","onTest","onRemove","testing","isOn","Trash2","label","hint","className","children"],"mappings":"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","x_google_ignoreList":[0]}
|