agim-cli 1.2.48 → 1.2.49
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 +45 -0
- package/README.md +1 -1
- package/README.zh-CN.md +1 -1
- package/dist/cli-ui/config-wizard.js +1 -0
- package/dist/cli-ui/config-wizard.js.map +1 -1
- package/dist/cli-ui/i18n.d.ts +2 -0
- package/dist/cli-ui/i18n.d.ts.map +1 -1
- package/dist/cli-ui/i18n.js +4 -0
- package/dist/cli-ui/i18n.js.map +1 -1
- package/dist/cli.js +21 -0
- package/dist/cli.js.map +1 -1
- package/dist/core/agent-cwd.d.ts.map +1 -1
- package/dist/core/agent-cwd.js +28 -0
- package/dist/core/agent-cwd.js.map +1 -1
- package/dist/core/registry.d.ts.map +1 -1
- package/dist/core/registry.js +5 -0
- package/dist/core/registry.js.map +1 -1
- package/dist/plugins/agents/cursor/ensure-mcp-config.d.ts +43 -0
- package/dist/plugins/agents/cursor/ensure-mcp-config.d.ts.map +1 -0
- package/dist/plugins/agents/cursor/ensure-mcp-config.js +99 -0
- package/dist/plugins/agents/cursor/ensure-mcp-config.js.map +1 -0
- package/dist/plugins/agents/cursor/index.d.ts +28 -0
- package/dist/plugins/agents/cursor/index.d.ts.map +1 -0
- package/dist/plugins/agents/cursor/index.js +290 -0
- package/dist/plugins/agents/cursor/index.js.map +1 -0
- package/dist/web/public/assets/{a2a-Mke0F7ZM.js → a2a-06bnQicA.js} +2 -2
- package/dist/web/public/assets/{a2a-Mke0F7ZM.js.map → a2a-06bnQicA.js.map} +1 -1
- package/dist/web/public/assets/{activity-0zGnf1_m.js → activity-Bhc6Esfy.js} +2 -2
- package/dist/web/public/assets/{activity-0zGnf1_m.js.map → activity-Bhc6Esfy.js.map} +1 -1
- package/dist/web/public/assets/{admins-DSi3KRky.js → admins-BVpnOw3o.js} +2 -2
- package/dist/web/public/assets/{admins-DSi3KRky.js.map → admins-BVpnOw3o.js.map} +1 -1
- package/dist/web/public/assets/agents-Cn7D3UMz.js +7 -0
- package/dist/web/public/assets/agents-Cn7D3UMz.js.map +1 -0
- package/dist/web/public/assets/{approvals-Cu_JdM-8.js → approvals-BJiLyoLf.js} +2 -2
- package/dist/web/public/assets/{approvals-Cu_JdM-8.js.map → approvals-BJiLyoLf.js.map} +1 -1
- package/dist/web/public/assets/{asks-DfV8vxey.js → asks-C7gKbna1.js} +2 -2
- package/dist/web/public/assets/{asks-DfV8vxey.js.map → asks-C7gKbna1.js.map} +1 -1
- package/dist/web/public/assets/{audit-2EVhhvGV.js → audit-DgWZD8l5.js} +2 -2
- package/dist/web/public/assets/{audit-2EVhhvGV.js.map → audit-DgWZD8l5.js.map} +1 -1
- package/dist/web/public/assets/{bell-Wz_wuOa_.js → bell-pWZT2wlM.js} +2 -2
- package/dist/web/public/assets/{bell-Wz_wuOa_.js.map → bell-pWZT2wlM.js.map} +1 -1
- package/dist/web/public/assets/{bgjobs-DXROZFAW.js → bgjobs-DkAJdzHf.js} +2 -2
- package/dist/web/public/assets/{bgjobs-DXROZFAW.js.map → bgjobs-DkAJdzHf.js.map} +1 -1
- package/dist/web/public/assets/{brain-Dh5VOzRL.js → brain-B0mM-ro_.js} +2 -2
- package/dist/web/public/assets/{brain-Dh5VOzRL.js.map → brain-B0mM-ro_.js.map} +1 -1
- package/dist/web/public/assets/{briefcase-DfxbvM9i.js → briefcase-CUQlj33_.js} +2 -2
- package/dist/web/public/assets/{briefcase-DfxbvM9i.js.map → briefcase-CUQlj33_.js.map} +1 -1
- package/dist/web/public/assets/{chevron-right-DU8Xla1M.js → chevron-right-CJuDP_fx.js} +2 -2
- package/dist/web/public/assets/{chevron-right-DU8Xla1M.js.map → chevron-right-CJuDP_fx.js.map} +1 -1
- package/dist/web/public/assets/{circle-check-Be_S993G.js → circle-check-CYse8LRx.js} +2 -2
- package/dist/web/public/assets/{circle-check-Be_S993G.js.map → circle-check-CYse8LRx.js.map} +1 -1
- package/dist/web/public/assets/{circle-check-big-CsQkLR1u.js → circle-check-big-9NpJLA1Z.js} +2 -2
- package/dist/web/public/assets/{circle-check-big-CsQkLR1u.js.map → circle-check-big-9NpJLA1Z.js.map} +1 -1
- package/dist/web/public/assets/{circle-x-qkQu1Swu.js → circle-x-BxZ24SVG.js} +2 -2
- package/dist/web/public/assets/{circle-x-qkQu1Swu.js.map → circle-x-BxZ24SVG.js.map} +1 -1
- package/dist/web/public/assets/{confirm-dialog-Bm6MsLXZ.js → confirm-dialog-CmHeZ7ei.js} +2 -2
- package/dist/web/public/assets/{confirm-dialog-Bm6MsLXZ.js.map → confirm-dialog-CmHeZ7ei.js.map} +1 -1
- package/dist/web/public/assets/{data-table-Dw4Df09-.js → data-table-tu4BIahS.js} +2 -2
- package/dist/web/public/assets/{data-table-Dw4Df09-.js.map → data-table-tu4BIahS.js.map} +1 -1
- package/dist/web/public/assets/{dialog-CNsc4COh.js → dialog-D8QAkLhI.js} +2 -2
- package/dist/web/public/assets/{dialog-CNsc4COh.js.map → dialog-D8QAkLhI.js.map} +1 -1
- package/dist/web/public/assets/{download-Bnhk_vDY.js → download-DBS0ZPTh.js} +2 -2
- package/dist/web/public/assets/{download-Bnhk_vDY.js.map → download-DBS0ZPTh.js.map} +1 -1
- package/dist/web/public/assets/{email-jgAX8liM.js → email-DgbAEEvZ.js} +2 -2
- package/dist/web/public/assets/{email-jgAX8liM.js.map → email-DgbAEEvZ.js.map} +1 -1
- package/dist/web/public/assets/{empty-state-D8QXQ5y9.js → empty-state-B1S_EYNJ.js} +2 -2
- package/dist/web/public/assets/{empty-state-D8QXQ5y9.js.map → empty-state-B1S_EYNJ.js.map} +1 -1
- package/dist/web/public/assets/{external-link-C8AYvhBb.js → external-link-Dkmwlv6p.js} +2 -2
- package/dist/web/public/assets/{external-link-C8AYvhBb.js.map → external-link-Dkmwlv6p.js.map} +1 -1
- package/dist/web/public/assets/{eye-pmI_4E8x.js → eye-Ch0DLviZ.js} +2 -2
- package/dist/web/public/assets/{eye-pmI_4E8x.js.map → eye-Ch0DLviZ.js.map} +1 -1
- package/dist/web/public/assets/{facts-BRHLLX2u.js → facts-C3YV1Mkp.js} +2 -2
- package/dist/web/public/assets/{facts-BRHLLX2u.js.map → facts-C3YV1Mkp.js.map} +1 -1
- package/dist/web/public/assets/{goals-p7cNp01l.js → goals-DEt5gGry.js} +2 -2
- package/dist/web/public/assets/{goals-p7cNp01l.js.map → goals-DEt5gGry.js.map} +1 -1
- package/dist/web/public/assets/{health-CuGIXg8C.js → health-DuB9uNiZ.js} +2 -2
- package/dist/web/public/assets/{health-CuGIXg8C.js.map → health-DuB9uNiZ.js.map} +1 -1
- package/dist/web/public/assets/{heart-pulse-D0AHQl1d.js → heart-pulse-CD8xNAGs.js} +2 -2
- package/dist/web/public/assets/{heart-pulse-D0AHQl1d.js.map → heart-pulse-CD8xNAGs.js.map} +1 -1
- package/dist/web/public/assets/{heartbeat-DJRDS2GQ.js → heartbeat-DbR8VwmG.js} +2 -2
- package/dist/web/public/assets/{heartbeat-DJRDS2GQ.js.map → heartbeat-DbR8VwmG.js.map} +1 -1
- package/dist/web/public/assets/{hot-B1qKTiGD.js → hot-izk3vGQB.js} +2 -2
- package/dist/web/public/assets/{hot-B1qKTiGD.js.map → hot-izk3vGQB.js.map} +1 -1
- package/dist/web/public/assets/{index-XJngV1gH.js → index-BY1vfCja.js} +3 -3
- package/dist/web/public/assets/{index-XJngV1gH.js.map → index-BY1vfCja.js.map} +1 -1
- package/dist/web/public/assets/{installed-Dz4-KevJ.js → installed-BXB3-YIy.js} +2 -2
- package/dist/web/public/assets/{installed-Dz4-KevJ.js.map → installed-BXB3-YIy.js.map} +1 -1
- package/dist/web/public/assets/{jobs-kwOypiWd.js → jobs-DkbM4mIQ.js} +2 -2
- package/dist/web/public/assets/{jobs-kwOypiWd.js.map → jobs-DkbM4mIQ.js.map} +1 -1
- package/dist/web/public/assets/{layout-CbHxH58i.js → layout-5ePj6Bek.js} +2 -2
- package/dist/web/public/assets/{layout-CbHxH58i.js.map → layout-5ePj6Bek.js.map} +1 -1
- package/dist/web/public/assets/{layout-DD1Dei48.js → layout-B5Dzy_Zc.js} +2 -2
- package/dist/web/public/assets/{layout-DD1Dei48.js.map → layout-B5Dzy_Zc.js.map} +1 -1
- package/dist/web/public/assets/{layout-01n3Aibo.js → layout-BZpbNQFb.js} +2 -2
- package/dist/web/public/assets/{layout-01n3Aibo.js.map → layout-BZpbNQFb.js.map} +1 -1
- package/dist/web/public/assets/{layout-CVYe2vN8.js → layout-DY9Xq34u.js} +2 -2
- package/dist/web/public/assets/{layout-CVYe2vN8.js.map → layout-DY9Xq34u.js.map} +1 -1
- package/dist/web/public/assets/{layout-s11iwkL-.js → layout-DxzBaeTv.js} +2 -2
- package/dist/web/public/assets/{layout-s11iwkL-.js.map → layout-DxzBaeTv.js.map} +1 -1
- package/dist/web/public/assets/{llm-DPlK10Lg.js → llm-Dg4W7eRM.js} +2 -2
- package/dist/web/public/assets/{llm-DPlK10Lg.js.map → llm-Dg4W7eRM.js.map} +1 -1
- package/dist/web/public/assets/{loader-circle-DymEG5Cl.js → loader-circle-pGNYdPoE.js} +2 -2
- package/dist/web/public/assets/{loader-circle-DymEG5Cl.js.map → loader-circle-pGNYdPoE.js.map} +1 -1
- package/dist/web/public/assets/{map-pin-CyZg1-Jk.js → map-pin-D1UX9mg7.js} +2 -2
- package/dist/web/public/assets/{map-pin-CyZg1-Jk.js.map → map-pin-D1UX9mg7.js.map} +1 -1
- package/dist/web/public/assets/{mcp-CiifW_qp.js → mcp-uoOzu4_J.js} +2 -2
- package/dist/web/public/assets/{mcp-CiifW_qp.js.map → mcp-uoOzu4_J.js.map} +1 -1
- package/dist/web/public/assets/{memos-Bsiq64qW.js → memos-CAWASHg5.js} +2 -2
- package/dist/web/public/assets/{memos-Bsiq64qW.js.map → memos-CAWASHg5.js.map} +1 -1
- package/dist/web/public/assets/{messengers-alGJK9dO.js → messengers-B1-mZms8.js} +2 -2
- package/dist/web/public/assets/{messengers-alGJK9dO.js.map → messengers-B1-mZms8.js.map} +1 -1
- package/dist/web/public/assets/{native-agent-CgzcqRsU.js → native-agent-UuVvvzsW.js} +2 -2
- package/dist/web/public/assets/{native-agent-CgzcqRsU.js.map → native-agent-UuVvvzsW.js.map} +1 -1
- package/dist/web/public/assets/{network-BSRJfeGk.js → network-DpjSgAwW.js} +2 -2
- package/dist/web/public/assets/{network-BSRJfeGk.js.map → network-DpjSgAwW.js.map} +1 -1
- package/dist/web/public/assets/{outbox-DSDls9xU.js → outbox-DeAgiXkY.js} +2 -2
- package/dist/web/public/assets/{outbox-DSDls9xU.js.map → outbox-DeAgiXkY.js.map} +1 -1
- package/dist/web/public/assets/{pagination-DVXNZ2ti.js → pagination-5GD_he3L.js} +2 -2
- package/dist/web/public/assets/{pagination-DVXNZ2ti.js.map → pagination-5GD_he3L.js.map} +1 -1
- package/dist/web/public/assets/{persona-BB1gIwTX.js → persona-BhkDCmeB.js} +2 -2
- package/dist/web/public/assets/{persona-BB1gIwTX.js.map → persona-BhkDCmeB.js.map} +1 -1
- package/dist/web/public/assets/{play-CcECAHfL.js → play-B7o6cJ8W.js} +2 -2
- package/dist/web/public/assets/{play-CcECAHfL.js.map → play-B7o6cJ8W.js.map} +1 -1
- package/dist/web/public/assets/{plus-DrStBHss.js → plus-C5d4C6Zp.js} +2 -2
- package/dist/web/public/assets/{plus-DrStBHss.js.map → plus-C5d4C6Zp.js.map} +1 -1
- package/dist/web/public/assets/{policy-BgDYTxy7.js → policy-Ct_sKm3Y.js} +2 -2
- package/dist/web/public/assets/{policy-BgDYTxy7.js.map → policy-Ct_sKm3Y.js.map} +1 -1
- package/dist/web/public/assets/{refresh-ccw-BBRPVLH8.js → refresh-ccw-BlXMN3UX.js} +2 -2
- package/dist/web/public/assets/{refresh-ccw-BBRPVLH8.js.map → refresh-ccw-BlXMN3UX.js.map} +1 -1
- package/dist/web/public/assets/{reminders-jwy196Xw.js → reminders-gb1Y0S3t.js} +2 -2
- package/dist/web/public/assets/{reminders-jwy196Xw.js.map → reminders-gb1Y0S3t.js.map} +1 -1
- package/dist/web/public/assets/{save-iBtyruco.js → save-DAFuApnY.js} +2 -2
- package/dist/web/public/assets/{save-iBtyruco.js.map → save-DAFuApnY.js.map} +1 -1
- package/dist/web/public/assets/{schedules-DDl_Sr5r.js → schedules-CtFumT2B.js} +2 -2
- package/dist/web/public/assets/{schedules-DDl_Sr5r.js.map → schedules-CtFumT2B.js.map} +1 -1
- package/dist/web/public/assets/{search-Yb1S22sv.js → search-BWuZE0YD.js} +2 -2
- package/dist/web/public/assets/{search-Yb1S22sv.js.map → search-BWuZE0YD.js.map} +1 -1
- package/dist/web/public/assets/{service-jrg0kMtK.js → service-lah7RWEc.js} +2 -2
- package/dist/web/public/assets/{service-jrg0kMtK.js.map → service-lah7RWEc.js.map} +1 -1
- package/dist/web/public/assets/{status-badge-Arxyw3TL.js → status-badge-BgmFa_8z.js} +2 -2
- package/dist/web/public/assets/{status-badge-Arxyw3TL.js.map → status-badge-BgmFa_8z.js.map} +1 -1
- package/dist/web/public/assets/{subtasks-CkyuMv_X.js → subtasks-CgqrOGhl.js} +2 -2
- package/dist/web/public/assets/{subtasks-CkyuMv_X.js.map → subtasks-CgqrOGhl.js.map} +1 -1
- package/dist/web/public/assets/{table-BKdG9tsY.js → table-BhDzIBvB.js} +2 -2
- package/dist/web/public/assets/{table-BKdG9tsY.js.map → table-BhDzIBvB.js.map} +1 -1
- package/dist/web/public/assets/{topn-BpX8BKWS.js → topn-DXgTCdM_.js} +2 -2
- package/dist/web/public/assets/{topn-BpX8BKWS.js.map → topn-DXgTCdM_.js.map} +1 -1
- package/dist/web/public/assets/{trash-2-DxKJo_-6.js → trash-2-i4F_Rzh3.js} +2 -2
- package/dist/web/public/assets/{trash-2-DxKJo_-6.js.map → trash-2-i4F_Rzh3.js.map} +1 -1
- package/dist/web/public/assets/{use-background-tasks-vqoDXiAq.js → use-background-tasks-Cq2D7JQJ.js} +2 -2
- package/dist/web/public/assets/{use-background-tasks-vqoDXiAq.js.map → use-background-tasks-Cq2D7JQJ.js.map} +1 -1
- package/dist/web/public/assets/{use-llm-admin-D4snixaM.js → use-llm-admin-BzOVXSjz.js} +2 -2
- package/dist/web/public/assets/{use-llm-admin-D4snixaM.js.map → use-llm-admin-BzOVXSjz.js.map} +1 -1
- package/dist/web/public/assets/{use-memory-Cqf3xywK.js → use-memory-B_RQWQyG.js} +2 -2
- package/dist/web/public/assets/{use-memory-Cqf3xywK.js.map → use-memory-B_RQWQyG.js.map} +1 -1
- package/dist/web/public/assets/{use-observability-Thh7LWoE.js → use-observability-CCTN-a71.js} +2 -2
- package/dist/web/public/assets/{use-observability-Thh7LWoE.js.map → use-observability-CCTN-a71.js.map} +1 -1
- package/dist/web/public/assets/{use-settings-DRhH8owt.js → use-settings-D4EdDLiK.js} +2 -2
- package/dist/web/public/assets/{use-settings-DRhH8owt.js.map → use-settings-D4EdDLiK.js.map} +1 -1
- package/dist/web/public/assets/{use-workspace-iLKz-h_7.js → use-workspace-BhTEp_QH.js} +2 -2
- package/dist/web/public/assets/{use-workspace-iLKz-h_7.js.map → use-workspace-BhTEp_QH.js.map} +1 -1
- package/dist/web/public/assets/{useQuery-gnz30xMJ.js → useQuery-DmoWKLw3.js} +2 -2
- package/dist/web/public/assets/{useQuery-gnz30xMJ.js.map → useQuery-DmoWKLw3.js.map} +1 -1
- package/dist/web/public/assets/{vector-COjljy_4.js → vector-By-cheMu.js} +2 -2
- package/dist/web/public/assets/{vector-COjljy_4.js.map → vector-By-cheMu.js.map} +1 -1
- package/dist/web/public/assets/{viewer-AQHSc8hZ.js → viewer-CJNrz2iw.js} +2 -2
- package/dist/web/public/assets/{viewer-AQHSc8hZ.js.map → viewer-CJNrz2iw.js.map} +1 -1
- package/dist/web/public/assets/{workspace-DRtSCbx5.js → workspace-DvYlIAhu.js} +2 -2
- package/dist/web/public/assets/{workspace-DRtSCbx5.js.map → workspace-DvYlIAhu.js.map} +1 -1
- package/dist/web/public/assets/{workspaces-BLR5ZBu6.js → workspaces-2pn73O-K.js} +2 -2
- package/dist/web/public/assets/{workspaces-BLR5ZBu6.js.map → workspaces-2pn73O-K.js.map} +1 -1
- package/dist/web/public/assets/{x-DGQ0qjhc.js → x-5Z_de5zo.js} +2 -2
- package/dist/web/public/assets/{x-DGQ0qjhc.js.map → x-5Z_de5zo.js.map} +1 -1
- package/dist/web/public/index.html +1 -1
- package/package.json +1 -1
- package/dist/web/public/assets/agents-BLWe20EJ.js +0 -7
- package/dist/web/public/assets/agents-BLWe20EJ.js.map +0 -1
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { AgentBase, type SpawnPlan } from '../../../core/agent-base.js';
|
|
2
|
+
import type { AgentSendOpts } from '../../../core/types.js';
|
|
3
|
+
export declare class CursorAdapter extends AgentBase {
|
|
4
|
+
readonly name = "cursor";
|
|
5
|
+
readonly aliases: string[];
|
|
6
|
+
readonly kind: "cli";
|
|
7
|
+
/** Cached bin path resolution. null = "haven't probed";
|
|
8
|
+
* undefined = "probed, not found, fall back to bare name". */
|
|
9
|
+
private resolvedBin;
|
|
10
|
+
/** Have we written the imhub MCP entry to ~/.cursor/mcp.json yet this
|
|
11
|
+
* agim process lifetime? Saves the disk hit on every send. Reset on
|
|
12
|
+
* agim restart so the next run rewrites with the fresh socket path. */
|
|
13
|
+
private mcpReady;
|
|
14
|
+
protected get commandName(): string;
|
|
15
|
+
protected buildArgs(prompt: string, opts: AgentSendOpts): string[];
|
|
16
|
+
protected prepareCommand(prompt: string, opts: AgentSendOpts): Promise<SpawnPlan>;
|
|
17
|
+
/** Pull the assistant text from a single stream-json event. */
|
|
18
|
+
protected extractText(event: unknown): string;
|
|
19
|
+
/** Capture `session_id` from system.init AND token usage from result
|
|
20
|
+
* events so cli persists session resume + audit log records cost
|
|
21
|
+
* (well, tokens — cursor doesn't price client-side). */
|
|
22
|
+
protected inspectEvent(event: unknown, opts: AgentSendOpts): void;
|
|
23
|
+
protected handleError(_code: number, stderr: string, errorMessage: string): string | null;
|
|
24
|
+
protected notAvailableMessage(): string;
|
|
25
|
+
isAvailable(): Promise<boolean>;
|
|
26
|
+
}
|
|
27
|
+
export declare const cursorAdapter: CursorAdapter;
|
|
28
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/plugins/agents/cursor/index.ts"],"names":[],"mappings":"AA2DA,OAAO,EAAE,SAAS,EAAE,KAAK,SAAS,EAAE,MAAM,6BAA6B,CAAA;AACvE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAA;AAyC3D,qBAAa,aAAc,SAAQ,SAAS;IAC1C,QAAQ,CAAC,IAAI,YAAW;IACxB,QAAQ,CAAC,OAAO,WAAgB;IAChC,QAAQ,CAAC,IAAI,EAAG,KAAK,CAAS;IAE9B;mEAC+D;IAC/D,OAAO,CAAC,WAAW,CAAkC;IAErD;;4EAEwE;IACxE,OAAO,CAAC,QAAQ,CAAQ;IAExB,SAAS,KAAK,WAAW,IAAI,MAAM,CA0BlC;IAED,SAAS,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,GAAG,MAAM,EAAE;cAuBlD,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,SAAS,CAAC;IA0EvF,+DAA+D;IAC/D,SAAS,CAAC,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM;IAgB7C;;6DAEyD;IACzD,SAAS,CAAC,YAAY,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,aAAa,GAAG,IAAI;IAgCjE,SAAS,CAAC,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAYzF,SAAS,CAAC,mBAAmB,IAAI,MAAM;IAQjC,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;CAOtC;AAED,eAAO,MAAM,aAAa,eAAsB,CAAA"}
|
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
// Cursor (`cursor-agent`) agent adapter.
|
|
2
|
+
//
|
|
3
|
+
// CLI surface (observed from `cursor-agent --help` on v2026.05.20+):
|
|
4
|
+
// cursor-agent [flags] [prompt...] # interactive if TTY
|
|
5
|
+
// cursor-agent --print "<prompt>" # headless single-shot
|
|
6
|
+
// cursor-agent --print --output-format stream-json "<prompt>"
|
|
7
|
+
// ↓
|
|
8
|
+
// newline-delimited events: system.init, user, assistant, tool_call,
|
|
9
|
+
// result. Each event carries `session_id` (constant throughout a run).
|
|
10
|
+
// cursor-agent --print --resume <chatId> ... # resume an existing chat
|
|
11
|
+
// cursor-agent --print --continue ... # resume the most recent
|
|
12
|
+
// cursor-agent --print --plan ... # plan mode (read-only)
|
|
13
|
+
// cursor-agent --print --mode ask ... # Q&A mode (read-only)
|
|
14
|
+
// cursor-agent --print --model <id> ... # override model
|
|
15
|
+
// cursor-agent create-chat # pre-create a chat, get id
|
|
16
|
+
//
|
|
17
|
+
// Permissions model:
|
|
18
|
+
// - cursor reads MCP servers from `~/.cursor/mcp.json` (global) or
|
|
19
|
+
// `.cursor/mcp.json` (per-workspace). On adapter init we write the
|
|
20
|
+
// global file with an `imhub` entry pointing at the shared MCP sidecar
|
|
21
|
+
// (the same one claude-code uses). Subsequent tool calls hop through
|
|
22
|
+
// agim's approval-bus exactly like claude-code's.
|
|
23
|
+
// - `--approve-mcps` auto-approves MCP servers (no per-launch prompt;
|
|
24
|
+
// individual `mcp__imhub__*` calls still gate on agim's approval-bus).
|
|
25
|
+
// - `--force` (alias `--yolo`) bypasses cursor's own per-tool confirmation
|
|
26
|
+
// for shell / write / delete actions. Required for headless IM use —
|
|
27
|
+
// there's no interactive TTY to answer prompts. Operators can still
|
|
28
|
+
// deny via agim policy or by editing `~/.cursor/cli-config.json`'s
|
|
29
|
+
// `permissions.deny` array.
|
|
30
|
+
// - `--trust` marks the workspace as trusted; otherwise cursor refuses
|
|
31
|
+
// to start in `--print` mode against an unknown directory.
|
|
32
|
+
//
|
|
33
|
+
// Session lifecycle:
|
|
34
|
+
// - First call: spawn without `--resume`. The first event we see on
|
|
35
|
+
// stdout is `system.init` which carries `session_id`. inspectEvent
|
|
36
|
+
// calls `opts.onAgentSessionId(id)` so cli persists it on the agim
|
|
37
|
+
// Session row.
|
|
38
|
+
// - Subsequent calls: spawn with `--resume <session_id>`. cursor
|
|
39
|
+
// reopens the chat and appends the new turn.
|
|
40
|
+
// - `/new` clears the agim session row's cursor id; next run starts
|
|
41
|
+
// fresh.
|
|
42
|
+
//
|
|
43
|
+
// Authentication:
|
|
44
|
+
// - cursor stores credentials at `~/.cursor/cli-config.json` after
|
|
45
|
+
// `cursor-agent login`. agim runs as the same user, so the file is
|
|
46
|
+
// readable out of the box — no env-var dance needed. Set
|
|
47
|
+
// CURSOR_API_KEY env if the operator prefers a token over OAuth.
|
|
48
|
+
//
|
|
49
|
+
// Default model:
|
|
50
|
+
// - We respect whatever is set in `~/.cursor/cli-config.json`'s
|
|
51
|
+
// `model.modelId`. Operators override per-call via `opts.model` (e.g.
|
|
52
|
+
// `/cs model sonnet-4-thinking <prompt>`) or globally via cli-config.
|
|
53
|
+
import { randomUUID } from 'node:crypto';
|
|
54
|
+
import { existsSync, statSync } from 'node:fs';
|
|
55
|
+
import { mkdir } from 'node:fs/promises';
|
|
56
|
+
import { homedir } from 'node:os';
|
|
57
|
+
import { join } from 'node:path';
|
|
58
|
+
import { AgentBase } from '../../../core/agent-base.js';
|
|
59
|
+
import { approvalBus } from '../../../core/approval-bus.js';
|
|
60
|
+
import { resolveAgentCwd } from '../../../core/agent-cwd.js';
|
|
61
|
+
import { crossSpawn } from '../../../utils/cross-platform.js';
|
|
62
|
+
import { logger as rootLogger } from '../../../core/logger.js';
|
|
63
|
+
import { ensureImhubMcp } from './ensure-mcp-config.js';
|
|
64
|
+
const log = rootLogger.child({ component: 'agent.cursor' });
|
|
65
|
+
const DEFAULT_BIN = 'cursor-agent';
|
|
66
|
+
/** Path to the imhub MCP sidecar JS file. Shared with claude-code /
|
|
67
|
+
* antigravity — the protocol surface is host-agnostic. */
|
|
68
|
+
function sidecarPath() {
|
|
69
|
+
// From dist/plugins/agents/cursor/index.js the sidecar is at:
|
|
70
|
+
// ../claude-code/mcp-approval-server.js
|
|
71
|
+
return new URL('../claude-code/mcp-approval-server.js', import.meta.url).pathname;
|
|
72
|
+
}
|
|
73
|
+
export class CursorAdapter extends AgentBase {
|
|
74
|
+
name = 'cursor';
|
|
75
|
+
aliases = ['cs', 'cur'];
|
|
76
|
+
kind = 'cli';
|
|
77
|
+
/** Cached bin path resolution. null = "haven't probed";
|
|
78
|
+
* undefined = "probed, not found, fall back to bare name". */
|
|
79
|
+
resolvedBin = null;
|
|
80
|
+
/** Have we written the imhub MCP entry to ~/.cursor/mcp.json yet this
|
|
81
|
+
* agim process lifetime? Saves the disk hit on every send. Reset on
|
|
82
|
+
* agim restart so the next run rewrites with the fresh socket path. */
|
|
83
|
+
mcpReady = false;
|
|
84
|
+
get commandName() {
|
|
85
|
+
const override = process.env.IMHUB_CURSOR_BIN;
|
|
86
|
+
if (override)
|
|
87
|
+
return override;
|
|
88
|
+
if (this.resolvedBin !== null)
|
|
89
|
+
return this.resolvedBin ?? DEFAULT_BIN;
|
|
90
|
+
// The official installer puts the bin at `~/.local/bin/cursor-agent`
|
|
91
|
+
// (XDG user-local). systemd-launched agim doesn't source the user's
|
|
92
|
+
// shell rc, so PATH lookup of bare `cursor-agent` often fails even
|
|
93
|
+
// when the binary is right there. Probe the known locations.
|
|
94
|
+
const candidates = [
|
|
95
|
+
join(homedir(), '.local', 'bin', 'cursor-agent'),
|
|
96
|
+
'/usr/local/bin/cursor-agent',
|
|
97
|
+
'/opt/cursor/bin/cursor-agent',
|
|
98
|
+
];
|
|
99
|
+
for (const p of candidates) {
|
|
100
|
+
try {
|
|
101
|
+
const s = statSync(p);
|
|
102
|
+
if (s.isFile() && (s.mode & 0o111) !== 0) {
|
|
103
|
+
this.resolvedBin = p;
|
|
104
|
+
log.info({ event: 'cursor.bin.resolved', path: p }, 'resolved cursor-agent outside PATH');
|
|
105
|
+
return p;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
catch { /* not here */ }
|
|
109
|
+
}
|
|
110
|
+
this.resolvedBin = undefined;
|
|
111
|
+
return DEFAULT_BIN;
|
|
112
|
+
}
|
|
113
|
+
buildArgs(prompt, opts) {
|
|
114
|
+
const args = ['--print', '--output-format', 'stream-json'];
|
|
115
|
+
// Trust + force are mandatory for headless IM use — cursor refuses
|
|
116
|
+
// to write / shell otherwise and there's no TTY to answer prompts.
|
|
117
|
+
// Operators wanting tighter control can use IMHUB_NATIVE_AGENT_DENYLIST
|
|
118
|
+
// for agim tools and edit `~/.cursor/cli-config.json`'s `permissions.deny`
|
|
119
|
+
// for cursor-side tool gating.
|
|
120
|
+
args.push('--trust', '--force', '--approve-mcps');
|
|
121
|
+
if (opts.model)
|
|
122
|
+
args.push('--model', opts.model);
|
|
123
|
+
if (opts.planMode)
|
|
124
|
+
args.push('--plan');
|
|
125
|
+
if (opts.agentSessionId && !opts.agentSessionResume) {
|
|
126
|
+
// First call with this session id — cursor doesn't have a
|
|
127
|
+
// "--session-id <new>" form like claude-code; the session id is
|
|
128
|
+
// assigned by cursor and surfaced in system.init. Treat
|
|
129
|
+
// pre-supplied id as a resume hint.
|
|
130
|
+
args.push('--resume', opts.agentSessionId);
|
|
131
|
+
}
|
|
132
|
+
else if (opts.agentSessionId) {
|
|
133
|
+
args.push('--resume', opts.agentSessionId);
|
|
134
|
+
}
|
|
135
|
+
args.push(prompt);
|
|
136
|
+
return args;
|
|
137
|
+
}
|
|
138
|
+
async prepareCommand(prompt, opts) {
|
|
139
|
+
let cwd = resolveAgentCwd(this.name, opts);
|
|
140
|
+
if (cwd) {
|
|
141
|
+
try {
|
|
142
|
+
if (!existsSync(cwd))
|
|
143
|
+
await mkdir(cwd, { recursive: true });
|
|
144
|
+
}
|
|
145
|
+
catch (err) {
|
|
146
|
+
log.warn({ event: 'cursor.cwd.mkdir_failed', cwd, err: String(err) }, 'falling back to inherited cwd because workspace dir could not be created');
|
|
147
|
+
cwd = undefined;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
// Append cwd to --workspace so cursor scopes file ops to the per-agent
|
|
151
|
+
// workspace instead of the systemd cwd ("/").
|
|
152
|
+
const baseArgs = this.buildArgs(prompt, opts);
|
|
153
|
+
if (cwd) {
|
|
154
|
+
// Insert before the prompt (last arg). Order matters for cursor's
|
|
155
|
+
// commander parser — flags before positional.
|
|
156
|
+
const promptArg = baseArgs.pop();
|
|
157
|
+
baseArgs.push('--workspace', cwd, promptArg);
|
|
158
|
+
}
|
|
159
|
+
// MCP wiring (one-shot per agim process lifetime).
|
|
160
|
+
const sockPath = approvalBus.getSocketPath();
|
|
161
|
+
if (sockPath && !this.mcpReady) {
|
|
162
|
+
try {
|
|
163
|
+
await ensureImhubMcp({
|
|
164
|
+
command: process.execPath,
|
|
165
|
+
args: [sidecarPath()],
|
|
166
|
+
env: { IMHUB_APPROVAL_SOCK: sockPath },
|
|
167
|
+
});
|
|
168
|
+
this.mcpReady = true;
|
|
169
|
+
}
|
|
170
|
+
catch (err) {
|
|
171
|
+
log.warn({ event: 'cursor.mcp.disabled', err: String(err) }, 'imhub MCP not wired into cursor — agim tools will be invisible to cursor this run');
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
// approval-bus registration so mcp__imhub__* tool calls inside the
|
|
175
|
+
// cursor run resolve to this IM thread.
|
|
176
|
+
const { threadId, platform, channelId, userId } = opts;
|
|
177
|
+
const runId = randomUUID();
|
|
178
|
+
let registered = false;
|
|
179
|
+
if (sockPath && threadId && platform && channelId) {
|
|
180
|
+
approvalBus.registerRun(runId, {
|
|
181
|
+
threadId,
|
|
182
|
+
platform,
|
|
183
|
+
userId: userId ?? '',
|
|
184
|
+
channelId,
|
|
185
|
+
callerAgent: this.name,
|
|
186
|
+
...(typeof opts.parentJobId === 'number' ? { parentJobId: opts.parentJobId } : {}),
|
|
187
|
+
...(typeof opts.callDepth === 'number' ? { callDepth: opts.callDepth } : {}),
|
|
188
|
+
});
|
|
189
|
+
registered = true;
|
|
190
|
+
log.info({ event: 'cursor.approval.routed', runId, threadId, platform }, 'cursor run routed via approval-bus');
|
|
191
|
+
}
|
|
192
|
+
return {
|
|
193
|
+
args: baseArgs,
|
|
194
|
+
cwd,
|
|
195
|
+
extraEnv: {
|
|
196
|
+
IMHUB_RUN_ID: runId,
|
|
197
|
+
// cursor reads CURSOR_API_KEY if set; otherwise falls back to
|
|
198
|
+
// OAuth creds in ~/.cursor/cli-config.json. Pass HOME through
|
|
199
|
+
// so systemd-stripped env doesn't break the credential lookup.
|
|
200
|
+
HOME: process.env.HOME || homedir(),
|
|
201
|
+
},
|
|
202
|
+
cleanup: async () => {
|
|
203
|
+
if (registered)
|
|
204
|
+
approvalBus.unregisterRun(runId);
|
|
205
|
+
},
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
/** Pull the assistant text from a single stream-json event. */
|
|
209
|
+
extractText(event) {
|
|
210
|
+
const e = event;
|
|
211
|
+
if (e.type === 'assistant' && e.message?.content) {
|
|
212
|
+
const parts = [];
|
|
213
|
+
for (const item of e.message.content) {
|
|
214
|
+
if (item.type === 'text' && item.text)
|
|
215
|
+
parts.push(item.text);
|
|
216
|
+
}
|
|
217
|
+
return parts.join('');
|
|
218
|
+
}
|
|
219
|
+
// The terminal `result` event carries the aggregated final answer.
|
|
220
|
+
// We don't double-emit it (assistant events already covered the
|
|
221
|
+
// text); but if the stream skipped intermediate assistant events for
|
|
222
|
+
// some reason, result.result is the fallback.
|
|
223
|
+
return '';
|
|
224
|
+
}
|
|
225
|
+
/** Capture `session_id` from system.init AND token usage from result
|
|
226
|
+
* events so cli persists session resume + audit log records cost
|
|
227
|
+
* (well, tokens — cursor doesn't price client-side). */
|
|
228
|
+
inspectEvent(event, opts) {
|
|
229
|
+
const e = event;
|
|
230
|
+
if (e.type === 'system' && e.subtype === 'init' && typeof e.session_id === 'string') {
|
|
231
|
+
// Only surface if the caller didn't already pin one — saves a
|
|
232
|
+
// pointless SQLite write when resuming an existing session.
|
|
233
|
+
if (!opts.agentSessionId && opts.onAgentSessionId) {
|
|
234
|
+
try {
|
|
235
|
+
opts.onAgentSessionId(e.session_id);
|
|
236
|
+
log.info({ event: 'cursor.session.captured', id: e.session_id }, 'captured fresh cursor session id');
|
|
237
|
+
}
|
|
238
|
+
catch (err) {
|
|
239
|
+
log.debug({ event: 'cursor.session.callback_failed', err: String(err) });
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
if (e.type === 'result' && opts.onUsage && e.usage) {
|
|
244
|
+
const u = e.usage;
|
|
245
|
+
const cacheRead = typeof u.cacheReadTokens === 'number' ? u.cacheReadTokens : 0;
|
|
246
|
+
const cacheWrite = typeof u.cacheWriteTokens === 'number' ? u.cacheWriteTokens : 0;
|
|
247
|
+
const rawInput = typeof u.inputTokens === 'number' ? u.inputTokens : 0;
|
|
248
|
+
const tokensInput = rawInput + cacheRead + cacheWrite;
|
|
249
|
+
const tokensOutput = typeof u.outputTokens === 'number' ? u.outputTokens : 0;
|
|
250
|
+
const delta = {};
|
|
251
|
+
if (tokensInput > 0)
|
|
252
|
+
delta.tokensInput = tokensInput;
|
|
253
|
+
if (tokensOutput > 0)
|
|
254
|
+
delta.tokensOutput = tokensOutput;
|
|
255
|
+
if (delta.tokensInput !== undefined || delta.tokensOutput !== undefined) {
|
|
256
|
+
try {
|
|
257
|
+
opts.onUsage(delta);
|
|
258
|
+
}
|
|
259
|
+
catch { /* best-effort */ }
|
|
260
|
+
}
|
|
261
|
+
// cursor doesn't surface USD cost client-side; operators see it on
|
|
262
|
+
// cursor.com/dashboard. costUsd stays unset for cursor turns.
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
handleError(_code, stderr, errorMessage) {
|
|
266
|
+
const combined = `${stderr} ${errorMessage}`;
|
|
267
|
+
if (/unauthor|sign in|log in|CURSOR_API_KEY/i.test(combined)) {
|
|
268
|
+
return [
|
|
269
|
+
'🔐 Cursor 未登录 / 凭据过期。',
|
|
270
|
+
' 在装有 cursor-agent 的机器跑:`cursor-agent login`',
|
|
271
|
+
' 或设环境变量 CURSOR_API_KEY=<your-key>',
|
|
272
|
+
].join('\n');
|
|
273
|
+
}
|
|
274
|
+
return null;
|
|
275
|
+
}
|
|
276
|
+
notAvailableMessage() {
|
|
277
|
+
return ('Cursor CLI 未安装。安装:\n' +
|
|
278
|
+
' curl https://cursor.com/install -fsS | bash\n' +
|
|
279
|
+
'装完后跑一次 `cursor-agent login` 完成首次登录。');
|
|
280
|
+
}
|
|
281
|
+
async isAvailable() {
|
|
282
|
+
return new Promise((resolve) => {
|
|
283
|
+
const proc = crossSpawn(this.commandName, ['--version'], { stdio: 'ignore' });
|
|
284
|
+
proc.on('close', (code) => resolve(code === 0));
|
|
285
|
+
proc.on('error', () => resolve(false));
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
export const cursorAdapter = new CursorAdapter();
|
|
290
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/plugins/agents/cursor/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import{y as p,ab as f,q as o,ad as g,U as t,s as m,c as j}from"./index-
|
|
1
|
+
import{y as p,ab as f,q as o,ad as g,U as t,s as m,c as j}from"./index-BY1vfCja.js";import{e as N}from"./react-C9F3QeMB.js";import{D as y}from"./data-table-tu4BIahS.js";import{E as b}from"./empty-state-B1S_EYNJ.js";import{S as w}from"./status-badge-BgmFa_8z.js";import{u as x}from"./useQuery-DmoWKLw3.js";import{u as v}from"./use-event-stream-BGeFcayX.js";import{L as A}from"./loader-circle-pGNYdPoE.js";import{R as S}from"./refresh-ccw-BlXMN3UX.js";import"./table-BhDzIBvB.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 C=p("GitBranch",[["line",{x1:"6",x2:"6",y1:"3",y2:"15",key:"17qcm7"}],["circle",{cx:"18",cy:"6",r:"3",key:"1h7g24"}],["circle",{cx:"6",cy:"18",r:"3",key:"fqmcym"}],["path",{d:"M18 9a9 9 0 0 1-9 9",key:"n2h4wq"}]]),l={all:["a2a"],stats:["a2a","stats"],recent:e=>["a2a","recent",e]};function q(){return x({queryKey:l.stats,queryFn:()=>o.getA2AStats()})}function T(e){return x({queryKey:l.recent(e),queryFn:()=>o.getA2ARecent(e)})}function E(){const e=f();return()=>e.invalidateQueries({queryKey:l.all})}const L={connected:"text-success",connecting:"text-text-dim",reconnecting:"text-warning",closed:"text-text-muted"};function U(){const{t:e}=g(["tasks","common"]),s=E(),n=q(),r=T({limit:50}),u=r.data?.rows??[],i=n.data,d=v({job:()=>s()}),h=N.useMemo(()=>[{id:"id",header:e("a2a.col.id"),cell:a=>t.jsxs("span",{className:"tabular-nums text-text-dim",children:["#",a.id]}),headClassName:"w-16"},{id:"agent",header:e("a2a.col.agent"),cell:a=>t.jsx("span",{className:"font-medium",children:a.agent}),headClassName:"w-32"},{id:"parent",header:e("a2a.col.parent"),cell:a=>a.parent_id!=null?t.jsxs("span",{className:"tabular-nums text-text-dim",children:["#",a.parent_id]}):t.jsx("span",{className:"text-text-muted",children:"—"}),headClassName:"w-20"},{id:"depth",header:e("a2a.col.depth"),cell:a=>t.jsx("span",{className:"tabular-nums text-text-dim",children:a.call_depth}),headClassName:"w-16",hideOnMobile:!0},{id:"status",header:e("a2a.col.status"),cell:a=>t.jsx(w,{status:a.status,children:a.status}),headClassName:"w-28"},{id:"prompt",header:e("a2a.col.prompt"),cell:a=>t.jsx("span",{className:"line-clamp-2 text-text-dim",children:a.prompt??"—"}),asCardTitle:!0},{id:"createdAt",header:e("a2a.col.createdAt"),cell:a=>t.jsx("span",{className:"text-text-dim",children:R(a.created_at)}),headClassName:"w-40",hideOnMobile:!0}],[e]);return t.jsxs("div",{className:"mx-auto flex max-w-7xl flex-col gap-4",children:[t.jsxs("header",{className:"flex flex-col gap-1",children:[t.jsxs("div",{className:"flex flex-wrap items-center gap-3",children:[t.jsx("h1",{className:"text-xl font-semibold",children:e("a2a.title")}),t.jsx("span",{className:m("text-xs font-medium tabular-nums",L[d]),children:e(`jobs.live.${d}`)}),t.jsxs(j,{variant:"ghost",size:"sm",className:"ml-auto",onClick:()=>{r.refetch(),n.refetch()},disabled:r.isFetching||n.isFetching,"aria-label":e("actions.refresh",{ns:"common"}),children:[r.isFetching?t.jsx(A,{className:"h-4 w-4 animate-spin"}):t.jsx(S,{className:"h-4 w-4"}),t.jsx("span",{className:"hidden sm:inline",children:e("actions.refresh",{ns:"common"})})]})]}),t.jsx("p",{className:"text-sm text-text-dim",children:e("a2a.subtitle")})]}),i&&t.jsxs("div",{className:"grid grid-cols-3 gap-2",children:[t.jsx(c,{label:e("a2a.stats.total"),value:i.total,tone:"info"}),t.jsx(c,{label:e("a2a.stats.recent24h"),value:i.recent24h,tone:"success"}),t.jsx(c,{label:e("a2a.stats.maxDepth"),value:i.maxDepth,tone:"warning"})]}),t.jsx(y,{columns:h,rows:u,getRowId:a=>String(a.id),loading:r.isLoading,emptyState:t.jsx(b,{icon:t.jsx(C,{}),title:e("a2a.empty.title"),description:e("a2a.empty.description")})})]})}const k={info:"border-info/30 text-info",success:"border-success/30 text-success",warning:"border-warning/30 text-warning",danger:"border-danger/30 text-danger"};function c({label:e,value:s,tone:n}){return t.jsxs("div",{className:m("rounded-md border bg-surface px-3 py-2",k[n]),children:[t.jsx("div",{className:"text-xs uppercase tracking-wide text-text-dim",children:e}),t.jsx("div",{className:"text-2xl font-semibold tabular-nums",children:s})]})}function R(e){try{const s=new Date(e);return Number.isNaN(s.getTime())?e:s.toLocaleString(void 0,{month:"short",day:"numeric",hour:"2-digit",minute:"2-digit"})}catch{return e}}export{U as default};
|
|
7
|
-
//# sourceMappingURL=a2a-
|
|
7
|
+
//# sourceMappingURL=a2a-06bnQicA.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"a2a-Mke0F7ZM.js","sources":["../../node_modules/lucide-react/dist/esm/icons/git-branch.js","../../src/hooks/use-a2a.ts","../../src/routes/tasks/a2a.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 GitBranch = createLucideIcon(\"GitBranch\", [\n [\"line\", { x1: \"6\", x2: \"6\", y1: \"3\", y2: \"15\", key: \"17qcm7\" }],\n [\"circle\", { cx: \"18\", cy: \"6\", r: \"3\", key: \"1h7g24\" }],\n [\"circle\", { cx: \"6\", cy: \"18\", r: \"3\", key: \"fqmcym\" }],\n [\"path\", { d: \"M18 9a9 9 0 0 1-9 9\", key: \"n2h4wq\" }]\n]);\n\nexport { GitBranch as default };\n//# sourceMappingURL=git-branch.js.map\n","/**\n * useA2A* — react-query wrappers for the Agent-to-Agent inline-job\n * view. Read-only; data lives in jobs.db and is exposed via:\n *\n * GET /api/a2a/stats → totals, recent24h, maxDepth, byStatus/byAgent\n * GET /api/a2a/recent → recent rows (truncated prompt + result)\n *\n * SSE: subscribes to the `job` event so a freshly-completed inline\n * sub-invocation shows up without manual refresh.\n */\n\nimport { useQueryClient, useQuery } from '@tanstack/react-query'\nimport { api } from '@/lib/api/endpoints'\nimport type { A2AStats, ListA2ARecentQuery, ListA2ARecentResponse } from '@/types/api'\n\nexport const a2aKeys = {\n all: ['a2a'] as const,\n stats: ['a2a', 'stats'] as const,\n recent: (q: ListA2ARecentQuery) => ['a2a', 'recent', q] as const,\n}\n\nexport function useA2AStats() {\n return useQuery<A2AStats>({\n queryKey: a2aKeys.stats,\n queryFn: () => api.getA2AStats(),\n })\n}\n\nexport function useA2ARecent(query: ListA2ARecentQuery) {\n return useQuery<ListA2ARecentResponse>({\n queryKey: a2aKeys.recent(query),\n queryFn: () => api.getA2ARecent(query),\n })\n}\n\nexport function useInvalidateA2A() {\n const qc = useQueryClient()\n return () => qc.invalidateQueries({ queryKey: a2aKeys.all })\n}\n","/**\n * /tasks/a2a — Agent ↔ Agent inline-call history.\n *\n * Splits into stats KPI cards (total / recent24h / maxDepth) +\n * recent-rows table. Subscribes to the SSE `job` event so a fresh\n * agent-to-agent call appears live.\n */\n\nimport { useMemo } from 'react'\nimport { useTranslation } from 'react-i18next'\nimport { GitBranch, Loader2, RefreshCcw } from 'lucide-react'\n\nimport { DataTable, type DataTableColumn } from '@/components/common/data-table'\nimport { EmptyState } from '@/components/common/empty-state'\nimport { StatusBadge } from '@/components/common/status-badge'\nimport { Button } from '@/components/ui/button'\nimport { useA2ARecent, useA2AStats, useInvalidateA2A } from '@/hooks/use-a2a'\nimport { useEventStream, type SseStatus } from '@/hooks/use-event-stream'\nimport type { A2ARow } from '@/types/api'\nimport { cn } from '@/lib/utils'\n\nconst LIVE_STATUS_CLASS: Record<SseStatus, string> = {\n connected: 'text-success',\n connecting: 'text-text-dim',\n reconnecting: 'text-warning',\n closed: 'text-text-muted',\n}\n\nexport default function A2ARoute(): JSX.Element {\n const { t } = useTranslation(['tasks', 'common'])\n const invalidate = useInvalidateA2A()\n\n const statsQuery = useA2AStats()\n const recentQuery = useA2ARecent({ limit: 50 })\n const rows = recentQuery.data?.rows ?? []\n const stats = statsQuery.data\n\n const live = useEventStream({\n job: () => invalidate(),\n })\n\n const columns: DataTableColumn<A2ARow>[] = useMemo(\n () => [\n {\n id: 'id',\n header: t('a2a.col.id'),\n cell: (r) => <span className=\"tabular-nums text-text-dim\">#{r.id}</span>,\n headClassName: 'w-16',\n },\n {\n id: 'agent',\n header: t('a2a.col.agent'),\n cell: (r) => <span className=\"font-medium\">{r.agent}</span>,\n headClassName: 'w-32',\n },\n {\n id: 'parent',\n header: t('a2a.col.parent'),\n cell: (r) =>\n r.parent_id != null ? (\n <span className=\"tabular-nums text-text-dim\">#{r.parent_id}</span>\n ) : (\n <span className=\"text-text-muted\">—</span>\n ),\n headClassName: 'w-20',\n },\n {\n id: 'depth',\n header: t('a2a.col.depth'),\n cell: (r) => <span className=\"tabular-nums text-text-dim\">{r.call_depth}</span>,\n headClassName: 'w-16',\n hideOnMobile: true,\n },\n {\n id: 'status',\n header: t('a2a.col.status'),\n cell: (r) => <StatusBadge status={r.status}>{r.status}</StatusBadge>,\n headClassName: 'w-28',\n },\n {\n id: 'prompt',\n header: t('a2a.col.prompt'),\n cell: (r) => (\n <span className=\"line-clamp-2 text-text-dim\">{r.prompt ?? '—'}</span>\n ),\n asCardTitle: true,\n },\n {\n id: 'createdAt',\n header: t('a2a.col.createdAt'),\n cell: (r) => <span className=\"text-text-dim\">{formatTime(r.created_at)}</span>,\n headClassName: 'w-40',\n hideOnMobile: true,\n },\n ],\n [t],\n )\n\n return (\n <div className=\"mx-auto flex max-w-7xl 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('a2a.title')}</h1>\n <span className={cn('text-xs font-medium tabular-nums', LIVE_STATUS_CLASS[live])}>\n {t(`jobs.live.${live}`)}\n </span>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"ml-auto\"\n onClick={() => {\n void recentQuery.refetch()\n void statsQuery.refetch()\n }}\n disabled={recentQuery.isFetching || statsQuery.isFetching}\n aria-label={t('actions.refresh', { ns: 'common' })}\n >\n {recentQuery.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('a2a.subtitle')}</p>\n </header>\n\n {stats && (\n <div className=\"grid grid-cols-3 gap-2\">\n <StatCard label={t('a2a.stats.total')} value={stats.total} tone=\"info\" />\n <StatCard label={t('a2a.stats.recent24h')} value={stats.recent24h} tone=\"success\" />\n <StatCard label={t('a2a.stats.maxDepth')} value={stats.maxDepth} tone=\"warning\" />\n </div>\n )}\n\n <DataTable\n columns={columns}\n rows={rows}\n getRowId={(r) => String(r.id)}\n loading={recentQuery.isLoading}\n emptyState={\n <EmptyState\n icon={<GitBranch />}\n title={t('a2a.empty.title')}\n description={t('a2a.empty.description')}\n />\n }\n />\n </div>\n )\n}\n\ninterface StatCardProps {\n label: string\n value: number\n tone: 'info' | 'success' | 'warning' | 'danger'\n}\n\nconst TONE_STYLES: Record<StatCardProps['tone'], string> = {\n info: 'border-info/30 text-info',\n success: 'border-success/30 text-success',\n warning: 'border-warning/30 text-warning',\n danger: 'border-danger/30 text-danger',\n}\n\nfunction StatCard({ label, value, tone }: StatCardProps): JSX.Element {\n return (\n <div\n className={cn(\n 'rounded-md border bg-surface px-3 py-2',\n TONE_STYLES[tone],\n )}\n >\n <div className=\"text-xs uppercase tracking-wide text-text-dim\">{label}</div>\n <div className=\"text-2xl font-semibold tabular-nums\">{value}</div>\n </div>\n )\n}\n\nfunction formatTime(iso: string): string {\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"],"names":["GitBranch","createLucideIcon","a2aKeys","q","useA2AStats","useQuery","api","useA2ARecent","query","useInvalidateA2A","qc","useQueryClient","LIVE_STATUS_CLASS","A2ARoute","t","useTranslation","invalidate","statsQuery","recentQuery","rows","stats","live","useEventStream","columns","useMemo","r","jsxs","jsx","StatusBadge","formatTime","cn","Button","Loader2","RefreshCcw","StatCard","DataTable","EmptyState","TONE_STYLES","label","value","tone","iso","d"],"mappings":"8dAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GASA,MAAMA,EAAYC,EAAiB,YAAa,CAC9C,CAAC,OAAQ,CAAE,GAAI,IAAK,GAAI,IAAK,GAAI,IAAK,GAAI,KAAM,IAAK,QAAQ,CAAE,EAC/D,CAAC,SAAU,CAAE,GAAI,KAAM,GAAI,IAAK,EAAG,IAAK,IAAK,SAAU,EACvD,CAAC,SAAU,CAAE,GAAI,IAAK,GAAI,KAAM,EAAG,IAAK,IAAK,SAAU,EACvD,CAAC,OAAQ,CAAE,EAAG,sBAAuB,IAAK,QAAQ,CAAE,CACtD,CAAC,ECCYC,EAAU,CACrB,IAAQ,CAAC,KAAK,EACd,MAAQ,CAAC,MAAO,OAAO,EACvB,OAASC,GAA0B,CAAC,MAAO,SAAUA,CAAC,CACxD,EAEO,SAASC,GAAc,CAC5B,OAAOC,EAAmB,CACxB,SAAUH,EAAQ,MAClB,QAAS,IAAMI,EAAI,YAAA,CAAY,CAChC,CACH,CAEO,SAASC,EAAaC,EAA2B,CACtD,OAAOH,EAAgC,CACrC,SAAUH,EAAQ,OAAOM,CAAK,EAC9B,QAAS,IAAMF,EAAI,aAAaE,CAAK,CAAA,CACtC,CACH,CAEO,SAASC,GAAmB,CACjC,MAAMC,EAAKC,EAAA,EACX,MAAO,IAAMD,EAAG,kBAAkB,CAAE,SAAUR,EAAQ,IAAK,CAC7D,CCjBA,MAAMU,EAA+C,CACnD,UAAc,eACd,WAAc,gBACd,aAAc,eACd,OAAc,iBAChB,EAEA,SAAwBC,GAAwB,CAC9C,KAAM,CAAE,EAAAC,CAAA,EAAMC,EAAe,CAAC,QAAS,QAAQ,CAAC,EAC1CC,EAAaP,EAAA,EAEbQ,EAAab,EAAA,EACbc,EAAcX,EAAa,CAAE,MAAO,GAAI,EACxCY,EAAOD,EAAY,MAAM,MAAQ,CAAA,EACjCE,EAAQH,EAAW,KAEnBI,EAAOC,EAAe,CAC1B,IAAK,IAAMN,EAAA,CAAW,CACvB,EAEKO,EAAqCC,EAAAA,QACzC,IAAM,CACJ,CACE,GAAI,KACJ,OAAQV,EAAE,YAAY,EACtB,KAAOW,GAAMC,EAAAA,KAAC,OAAA,CAAK,UAAU,6BAA6B,SAAA,CAAA,IAAED,EAAE,EAAA,EAAG,EACjE,cAAe,MAAA,EAEjB,CACE,GAAI,QACJ,OAAQX,EAAE,eAAe,EACzB,KAAOW,GAAME,EAAAA,IAAC,QAAK,UAAU,cAAe,WAAE,MAAM,EACpD,cAAe,MAAA,EAEjB,CACE,GAAI,SACJ,OAAQb,EAAE,gBAAgB,EAC1B,KAAOW,GACLA,EAAE,WAAa,KACbC,EAAAA,KAAC,OAAA,CAAK,UAAU,6BAA6B,SAAA,CAAA,IAAED,EAAE,SAAA,EAAU,EAE3DE,EAAAA,IAAC,OAAA,CAAK,UAAU,kBAAkB,SAAA,IAAC,EAEvC,cAAe,MAAA,EAEjB,CACE,GAAI,QACJ,OAAQb,EAAE,eAAe,EACzB,KAAOW,GAAME,EAAAA,IAAC,QAAK,UAAU,6BAA8B,WAAE,WAAW,EACxE,cAAe,OACf,aAAc,EAAA,EAEhB,CACE,GAAI,SACJ,OAAQb,EAAE,gBAAgB,EAC1B,KAAOW,GAAME,EAAAA,IAACC,GAAY,OAAQH,EAAE,OAAS,SAAAA,EAAE,MAAA,CAAO,EACtD,cAAe,MAAA,EAEjB,CACE,GAAI,SACJ,OAAQX,EAAE,gBAAgB,EAC1B,KAAOW,GACLE,EAAAA,IAAC,QAAK,UAAU,6BAA8B,SAAAF,EAAE,QAAU,GAAA,CAAI,EAEhE,YAAa,EAAA,EAEf,CACE,GAAI,YACJ,OAAQX,EAAE,mBAAmB,EAC7B,KAAOW,GAAME,EAAAA,IAAC,OAAA,CAAK,UAAU,gBAAiB,SAAAE,EAAWJ,EAAE,UAAU,CAAA,CAAE,EACvE,cAAe,OACf,aAAc,EAAA,CAChB,EAEF,CAACX,CAAC,CAAA,EAGJ,OACEY,EAAAA,KAAC,MAAA,CAAI,UAAU,wCACb,SAAA,CAAAA,EAAAA,KAAC,SAAA,CAAO,UAAU,sBAChB,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,oCACb,SAAA,CAAAC,MAAC,KAAA,CAAG,UAAU,wBAAyB,SAAAb,EAAE,WAAW,EAAE,EACtDa,EAAAA,IAAC,OAAA,CAAK,UAAWG,EAAG,mCAAoClB,EAAkBS,CAAI,CAAC,EAC5E,SAAAP,EAAE,aAAaO,CAAI,EAAE,EACxB,EACAK,EAAAA,KAACK,EAAA,CACC,QAAQ,QACR,KAAK,KACL,UAAU,UACV,QAAS,IAAM,CACRb,EAAY,QAAA,EACZD,EAAW,QAAA,CAClB,EACA,SAAUC,EAAY,YAAcD,EAAW,WAC/C,aAAYH,EAAE,kBAAmB,CAAE,GAAI,SAAU,EAEhD,SAAA,CAAAI,EAAY,iBAAcc,EAAA,CAAQ,UAAU,uBAAuB,EAAKL,EAAAA,IAACM,EAAA,CAAW,UAAU,SAAA,CAAU,EACzGN,EAAAA,IAAC,OAAA,CAAK,UAAU,mBAAoB,SAAAb,EAAE,kBAAmB,CAAE,GAAI,QAAA,CAAU,CAAA,CAAE,CAAA,CAAA,CAAA,CAC7E,EACF,QACC,IAAA,CAAE,UAAU,wBAAyB,SAAAA,EAAE,cAAc,CAAA,CAAE,CAAA,EAC1D,EAECM,GACCM,EAAAA,KAAC,MAAA,CAAI,UAAU,yBACb,SAAA,CAAAC,EAAAA,IAACO,EAAA,CAAS,MAAOpB,EAAE,iBAAiB,EAAO,MAAOM,EAAM,MAAW,KAAK,MAAA,CAAO,EAC/EO,EAAAA,IAACO,EAAA,CAAS,MAAOpB,EAAE,qBAAqB,EAAG,MAAOM,EAAM,UAAW,KAAK,SAAA,CAAU,EAClFO,EAAAA,IAACO,EAAA,CAAS,MAAOpB,EAAE,oBAAoB,EAAI,MAAOM,EAAM,SAAW,KAAK,SAAA,CAAU,CAAA,EACpF,EAGFO,EAAAA,IAACQ,EAAA,CACC,QAAAZ,EACA,KAAAJ,EACA,SAAWM,GAAM,OAAOA,EAAE,EAAE,EAC5B,QAASP,EAAY,UACrB,WACES,EAAAA,IAACS,EAAA,CACC,WAAOpC,EAAA,EAAU,EACjB,MAAOc,EAAE,iBAAiB,EAC1B,YAAaA,EAAE,uBAAuB,CAAA,CAAA,CACxC,CAAA,CAEJ,EACF,CAEJ,CAQA,MAAMuB,EAAqD,CACzD,KAAS,8BACT,QAAS,iCACT,QAAS,iCACT,OAAS,+BACX,EAEA,SAASH,EAAS,CAAE,MAAAI,EAAO,MAAAC,EAAO,KAAAC,GAAoC,CACpE,OACEd,EAAAA,KAAC,MAAA,CACC,UAAWI,EACT,yCACAO,EAAYG,CAAI,CAAA,EAGlB,SAAA,CAAAb,EAAAA,IAAC,MAAA,CAAI,UAAU,gDAAiD,SAAAW,EAAM,EACtEX,EAAAA,IAAC,MAAA,CAAI,UAAU,sCAAuC,SAAAY,CAAA,CAAM,CAAA,CAAA,CAAA,CAGlE,CAEA,SAASV,EAAWY,EAAqB,CACvC,GAAI,CACF,MAAMC,EAAI,IAAI,KAAKD,CAAG,EACtB,OAAI,OAAO,MAAMC,EAAE,QAAA,CAAS,EAAUD,EAC/BC,EAAE,eAAe,OAAW,CAAE,MAAO,QAAS,IAAK,UAAW,KAAM,UAAW,OAAQ,SAAA,CAAW,CAC3G,MAAQ,CACN,OAAOD,CACT,CACF","x_google_ignoreList":[0]}
|
|
1
|
+
{"version":3,"file":"a2a-06bnQicA.js","sources":["../../node_modules/lucide-react/dist/esm/icons/git-branch.js","../../src/hooks/use-a2a.ts","../../src/routes/tasks/a2a.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 GitBranch = createLucideIcon(\"GitBranch\", [\n [\"line\", { x1: \"6\", x2: \"6\", y1: \"3\", y2: \"15\", key: \"17qcm7\" }],\n [\"circle\", { cx: \"18\", cy: \"6\", r: \"3\", key: \"1h7g24\" }],\n [\"circle\", { cx: \"6\", cy: \"18\", r: \"3\", key: \"fqmcym\" }],\n [\"path\", { d: \"M18 9a9 9 0 0 1-9 9\", key: \"n2h4wq\" }]\n]);\n\nexport { GitBranch as default };\n//# sourceMappingURL=git-branch.js.map\n","/**\n * useA2A* — react-query wrappers for the Agent-to-Agent inline-job\n * view. Read-only; data lives in jobs.db and is exposed via:\n *\n * GET /api/a2a/stats → totals, recent24h, maxDepth, byStatus/byAgent\n * GET /api/a2a/recent → recent rows (truncated prompt + result)\n *\n * SSE: subscribes to the `job` event so a freshly-completed inline\n * sub-invocation shows up without manual refresh.\n */\n\nimport { useQueryClient, useQuery } from '@tanstack/react-query'\nimport { api } from '@/lib/api/endpoints'\nimport type { A2AStats, ListA2ARecentQuery, ListA2ARecentResponse } from '@/types/api'\n\nexport const a2aKeys = {\n all: ['a2a'] as const,\n stats: ['a2a', 'stats'] as const,\n recent: (q: ListA2ARecentQuery) => ['a2a', 'recent', q] as const,\n}\n\nexport function useA2AStats() {\n return useQuery<A2AStats>({\n queryKey: a2aKeys.stats,\n queryFn: () => api.getA2AStats(),\n })\n}\n\nexport function useA2ARecent(query: ListA2ARecentQuery) {\n return useQuery<ListA2ARecentResponse>({\n queryKey: a2aKeys.recent(query),\n queryFn: () => api.getA2ARecent(query),\n })\n}\n\nexport function useInvalidateA2A() {\n const qc = useQueryClient()\n return () => qc.invalidateQueries({ queryKey: a2aKeys.all })\n}\n","/**\n * /tasks/a2a — Agent ↔ Agent inline-call history.\n *\n * Splits into stats KPI cards (total / recent24h / maxDepth) +\n * recent-rows table. Subscribes to the SSE `job` event so a fresh\n * agent-to-agent call appears live.\n */\n\nimport { useMemo } from 'react'\nimport { useTranslation } from 'react-i18next'\nimport { GitBranch, Loader2, RefreshCcw } from 'lucide-react'\n\nimport { DataTable, type DataTableColumn } from '@/components/common/data-table'\nimport { EmptyState } from '@/components/common/empty-state'\nimport { StatusBadge } from '@/components/common/status-badge'\nimport { Button } from '@/components/ui/button'\nimport { useA2ARecent, useA2AStats, useInvalidateA2A } from '@/hooks/use-a2a'\nimport { useEventStream, type SseStatus } from '@/hooks/use-event-stream'\nimport type { A2ARow } from '@/types/api'\nimport { cn } from '@/lib/utils'\n\nconst LIVE_STATUS_CLASS: Record<SseStatus, string> = {\n connected: 'text-success',\n connecting: 'text-text-dim',\n reconnecting: 'text-warning',\n closed: 'text-text-muted',\n}\n\nexport default function A2ARoute(): JSX.Element {\n const { t } = useTranslation(['tasks', 'common'])\n const invalidate = useInvalidateA2A()\n\n const statsQuery = useA2AStats()\n const recentQuery = useA2ARecent({ limit: 50 })\n const rows = recentQuery.data?.rows ?? []\n const stats = statsQuery.data\n\n const live = useEventStream({\n job: () => invalidate(),\n })\n\n const columns: DataTableColumn<A2ARow>[] = useMemo(\n () => [\n {\n id: 'id',\n header: t('a2a.col.id'),\n cell: (r) => <span className=\"tabular-nums text-text-dim\">#{r.id}</span>,\n headClassName: 'w-16',\n },\n {\n id: 'agent',\n header: t('a2a.col.agent'),\n cell: (r) => <span className=\"font-medium\">{r.agent}</span>,\n headClassName: 'w-32',\n },\n {\n id: 'parent',\n header: t('a2a.col.parent'),\n cell: (r) =>\n r.parent_id != null ? (\n <span className=\"tabular-nums text-text-dim\">#{r.parent_id}</span>\n ) : (\n <span className=\"text-text-muted\">—</span>\n ),\n headClassName: 'w-20',\n },\n {\n id: 'depth',\n header: t('a2a.col.depth'),\n cell: (r) => <span className=\"tabular-nums text-text-dim\">{r.call_depth}</span>,\n headClassName: 'w-16',\n hideOnMobile: true,\n },\n {\n id: 'status',\n header: t('a2a.col.status'),\n cell: (r) => <StatusBadge status={r.status}>{r.status}</StatusBadge>,\n headClassName: 'w-28',\n },\n {\n id: 'prompt',\n header: t('a2a.col.prompt'),\n cell: (r) => (\n <span className=\"line-clamp-2 text-text-dim\">{r.prompt ?? '—'}</span>\n ),\n asCardTitle: true,\n },\n {\n id: 'createdAt',\n header: t('a2a.col.createdAt'),\n cell: (r) => <span className=\"text-text-dim\">{formatTime(r.created_at)}</span>,\n headClassName: 'w-40',\n hideOnMobile: true,\n },\n ],\n [t],\n )\n\n return (\n <div className=\"mx-auto flex max-w-7xl 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('a2a.title')}</h1>\n <span className={cn('text-xs font-medium tabular-nums', LIVE_STATUS_CLASS[live])}>\n {t(`jobs.live.${live}`)}\n </span>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"ml-auto\"\n onClick={() => {\n void recentQuery.refetch()\n void statsQuery.refetch()\n }}\n disabled={recentQuery.isFetching || statsQuery.isFetching}\n aria-label={t('actions.refresh', { ns: 'common' })}\n >\n {recentQuery.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('a2a.subtitle')}</p>\n </header>\n\n {stats && (\n <div className=\"grid grid-cols-3 gap-2\">\n <StatCard label={t('a2a.stats.total')} value={stats.total} tone=\"info\" />\n <StatCard label={t('a2a.stats.recent24h')} value={stats.recent24h} tone=\"success\" />\n <StatCard label={t('a2a.stats.maxDepth')} value={stats.maxDepth} tone=\"warning\" />\n </div>\n )}\n\n <DataTable\n columns={columns}\n rows={rows}\n getRowId={(r) => String(r.id)}\n loading={recentQuery.isLoading}\n emptyState={\n <EmptyState\n icon={<GitBranch />}\n title={t('a2a.empty.title')}\n description={t('a2a.empty.description')}\n />\n }\n />\n </div>\n )\n}\n\ninterface StatCardProps {\n label: string\n value: number\n tone: 'info' | 'success' | 'warning' | 'danger'\n}\n\nconst TONE_STYLES: Record<StatCardProps['tone'], string> = {\n info: 'border-info/30 text-info',\n success: 'border-success/30 text-success',\n warning: 'border-warning/30 text-warning',\n danger: 'border-danger/30 text-danger',\n}\n\nfunction StatCard({ label, value, tone }: StatCardProps): JSX.Element {\n return (\n <div\n className={cn(\n 'rounded-md border bg-surface px-3 py-2',\n TONE_STYLES[tone],\n )}\n >\n <div className=\"text-xs uppercase tracking-wide text-text-dim\">{label}</div>\n <div className=\"text-2xl font-semibold tabular-nums\">{value}</div>\n </div>\n )\n}\n\nfunction formatTime(iso: string): string {\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"],"names":["GitBranch","createLucideIcon","a2aKeys","q","useA2AStats","useQuery","api","useA2ARecent","query","useInvalidateA2A","qc","useQueryClient","LIVE_STATUS_CLASS","A2ARoute","t","useTranslation","invalidate","statsQuery","recentQuery","rows","stats","live","useEventStream","columns","useMemo","r","jsxs","jsx","StatusBadge","formatTime","cn","Button","Loader2","RefreshCcw","StatCard","DataTable","EmptyState","TONE_STYLES","label","value","tone","iso","d"],"mappings":"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","x_google_ignoreList":[0]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import{y as t}from"./index-
|
|
1
|
+
import{y as t}from"./index-BY1vfCja.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 c=t("Activity",[["path",{d:"M22 12h-2.48a2 2 0 0 0-1.93 1.46l-2.35 8.36a.25.25 0 0 1-.48 0L9.24 2.18a.25.25 0 0 0-.48 0l-2.35 8.36A2 2 0 0 1 4.49 12H2",key:"169zse"}]]);export{c as A};
|
|
7
|
-
//# sourceMappingURL=activity-
|
|
7
|
+
//# sourceMappingURL=activity-Bhc6Esfy.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"activity-
|
|
1
|
+
{"version":3,"file":"activity-Bhc6Esfy.js","sources":["../../node_modules/lucide-react/dist/esm/icons/activity.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 Activity = createLucideIcon(\"Activity\", [\n [\n \"path\",\n {\n d: \"M22 12h-2.48a2 2 0 0 0-1.93 1.46l-2.35 8.36a.25.25 0 0 1-.48 0L9.24 2.18a.25.25 0 0 0-.48 0l-2.35 8.36A2 2 0 0 1 4.49 12H2\",\n key: \"169zse\"\n }\n ]\n]);\n\nexport { Activity as default };\n//# sourceMappingURL=activity.js.map\n"],"names":["Activity","createLucideIcon"],"mappings":"wCAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GASK,MAACA,EAAWC,EAAiB,WAAY,CAC5C,CACE,OACA,CACE,EAAG,6HACH,IAAK,QACX,CACA,CACA,CAAC","x_google_ignoreList":[0]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{y as A,ad as S,U as s,c as d,B as c,L as y,I as N,a3 as n,E as w}from"./index-
|
|
1
|
+
import{y as A,ad as S,U as s,c as d,B as c,L as y,I as N,a3 as n,E as w}from"./index-BY1vfCja.js";import{e as x}from"./react-C9F3QeMB.js";import{C as L}from"./confirm-dialog-CmHeZ7ei.js";import{E as P}from"./empty-state-B1S_EYNJ.js";import{T as E,d as z,e as C,c as h,a as B,b as u}from"./table-BhDzIBvB.js";import{a as F,u as U,e as D}from"./use-settings-D4EdDLiK.js";import{L as T}from"./loader-circle-pGNYdPoE.js";import{R as H}from"./refresh-ccw-BlXMN3UX.js";import{T as _}from"./trash-2-i4F_Rzh3.js";import"./dialog-D8QAkLhI.js";import"./x-5Z_de5zo.js";import"./useQuery-DmoWKLw3.js";/**
|
|
2
2
|
* @license lucide-react v0.469.0 - ISC
|
|
3
3
|
*
|
|
4
4
|
* This source code is licensed under the ISC license.
|
|
@@ -9,4 +9,4 @@ import{y as A,ad as S,U as s,c as d,B as c,L as y,I as N,a3 as n,E as w}from"./i
|
|
|
9
9
|
* This source code is licensed under the ISC license.
|
|
10
10
|
* See the LICENSE file in the root directory of this source tree.
|
|
11
11
|
*/const $=A("UserPlus",[["path",{d:"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2",key:"1yyitq"}],["circle",{cx:"9",cy:"7",r:"4",key:"nufk8"}],["line",{x1:"19",x2:"19",y1:"8",y2:"14",key:"1bvyxn"}],["line",{x1:"22",x2:"16",y1:"11",y2:"11",key:"1shjgl"}]]);function es(){const{t:e}=S(["settings","common"]),i=F(),t=i.data,r=U(),f=D(),[l,p]=x.useState(""),[m,j]=x.useState(""),[o,g]=x.useState(null);async function I(a){a.preventDefault();const b=l.trim(),v=m.trim();if(!(!b||!v))try{await r.mutateAsync({platform:b,userId:v}),n.success(e("admins.toast.added")),p(""),j("")}catch(R){n.error(w(R,e).message)}}async function k(){if(o)try{await f.mutateAsync(o),n.success(e("admins.toast.removed"))}catch(a){throw n.error(w(a,e).message),a}}return s.jsxs("div",{className:"mx-auto flex max-w-4xl flex-col gap-4",children:[s.jsxs("header",{className:"flex flex-col gap-1",children:[s.jsxs("div",{className:"flex flex-wrap items-center gap-3",children:[s.jsx("h1",{className:"text-xl font-semibold",children:e("admins.title")}),s.jsxs(d,{variant:"ghost",size:"sm",className:"ml-auto",onClick:()=>i.refetch(),disabled:i.isFetching,"aria-label":e("actions.refresh",{ns:"common"}),children:[i.isFetching?s.jsx(T,{className:"h-4 w-4 animate-spin"}):s.jsx(H,{className:"h-4 w-4"}),s.jsx("span",{className:"hidden sm:inline",children:e("actions.refresh",{ns:"common"})})]})]}),s.jsx("p",{className:"text-sm text-text-dim",children:e("admins.subtitle")})]}),t&&s.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[t.configured?s.jsx(c,{variant:"success",children:e("admins.configured")}):s.jsx(c,{variant:"warning",children:e("admins.notConfigured")}),t.bootstrapAvailable&&s.jsx(c,{variant:"info",title:t.bootstrapTokenPath,children:e("admins.bootstrapAvailable")})]}),i.isLoading?s.jsx("div",{className:"h-32 rounded-md bg-surface-2 animate-pulse"}):t&&t.admins.length===0?s.jsx(P,{icon:s.jsx(M,{}),title:e("admins.empty")}):t?s.jsxs(E,{children:[s.jsx(z,{children:s.jsxs(C,{children:[s.jsx(h,{className:"w-40",children:e("admins.col.platform")}),s.jsx(h,{children:e("admins.col.userId")}),s.jsx(h,{className:"w-24"})]})}),s.jsx(B,{children:t.admins.map(a=>s.jsxs(C,{children:[s.jsx(u,{className:"font-mono",children:a.platform}),s.jsx(u,{className:"font-mono text-xs",children:a.userId}),s.jsx(u,{children:s.jsxs(d,{variant:"ghost",size:"sm",onClick:()=>g(a),disabled:f.isPending,"aria-label":e("admins.remove.label"),children:[s.jsx(_,{className:"h-3 w-3"}),s.jsx("span",{className:"sr-only sm:not-sr-only sm:ml-1",children:e("admins.remove.label")})]})})]},`${a.platform}:${a.userId}`))})]}):null,s.jsxs("form",{onSubmit:a=>void I(a),className:"rounded-md border border-border bg-surface p-4",children:[s.jsx("div",{className:"mb-3 text-sm font-medium",children:e("admins.add.title")}),s.jsxs("div",{className:"grid grid-cols-1 gap-2 sm:grid-cols-[180px_1fr_auto] sm:items-end",children:[s.jsxs("div",{className:"flex flex-col gap-1",children:[s.jsx(y,{htmlFor:"admin-platform",className:"text-xs text-text-dim",children:e("admins.add.platform")}),s.jsx(N,{id:"admin-platform",value:l,onChange:a=>p(a.target.value),placeholder:"wechat",className:"font-mono text-xs"})]}),s.jsxs("div",{className:"flex flex-col gap-1",children:[s.jsx(y,{htmlFor:"admin-user",className:"text-xs text-text-dim",children:e("admins.add.userId")}),s.jsx(N,{id:"admin-user",value:m,onChange:a=>j(a.target.value),placeholder:"wxid_abc123",className:"font-mono text-xs"})]}),s.jsxs(d,{type:"submit",size:"sm",disabled:r.isPending||!l.trim()||!m.trim(),children:[r.isPending?s.jsx(T,{className:"h-4 w-4 animate-spin"}):s.jsx($,{className:"h-4 w-4"}),e("admins.add.submit")]})]})]}),s.jsx(L,{open:o!=null,onOpenChange:a=>{a||g(null)},title:e("admins.remove.confirmTitle"),description:e("admins.remove.confirmDescription"),intent:"danger",confirmLabel:e("admins.remove.label"),onConfirm:k})]})}export{es as default};
|
|
12
|
-
//# sourceMappingURL=admins-
|
|
12
|
+
//# sourceMappingURL=admins-BVpnOw3o.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"admins-DSi3KRky.js","sources":["../../node_modules/lucide-react/dist/esm/icons/shield.js","../../node_modules/lucide-react/dist/esm/icons/user-plus.js","../../src/routes/settings/admins.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 Shield = createLucideIcon(\"Shield\", [\n [\n \"path\",\n {\n d: \"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z\",\n key: \"oel41y\"\n }\n ]\n]);\n\nexport { Shield as default };\n//# sourceMappingURL=shield.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 UserPlus = createLucideIcon(\"UserPlus\", [\n [\"path\", { d: \"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2\", key: \"1yyitq\" }],\n [\"circle\", { cx: \"9\", cy: \"7\", r: \"4\", key: \"nufk8\" }],\n [\"line\", { x1: \"19\", x2: \"19\", y1: \"8\", y2: \"14\", key: \"1bvyxn\" }],\n [\"line\", { x1: \"22\", x2: \"16\", y1: \"11\", y2: \"11\", key: \"1shjgl\" }]\n]);\n\nexport { UserPlus as default };\n//# sourceMappingURL=user-plus.js.map\n","/**\n * /settings/admins — manage `IMHUB_ADMIN_USERS` entries.\n *\n * Each entry is a `(platform, userId)` pair (e.g. `wechat:wxid_abc`).\n * Add via the inline form at the bottom; remove via per-row trash\n * button → ConfirmDialog. The backend's POST/DELETE handlers gate\n * on isLocalBind — if the operator is hitting agim from another\n * host the mutations 403; we surface that toast verbatim.\n */\n\nimport { useState } from 'react'\nimport { useTranslation } from 'react-i18next'\nimport { toast } from 'sonner'\nimport { Loader2, RefreshCcw, Shield, Trash2, UserPlus } from 'lucide-react'\n\nimport { ConfirmDialog } from '@/components/common/confirm-dialog'\nimport { EmptyState } from '@/components/common/empty-state'\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 Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from '@/components/ui/table'\nimport {\n useAddAdmin,\n useAdminAllowlist,\n useRemoveAdmin,\n} from '@/hooks/use-settings'\nimport { describeError } from '@/lib/api/errors'\nimport type { AdminEntry } from '@/types/api'\n\nexport default function SettingsAdminsRoute(): JSX.Element {\n const { t } = useTranslation(['settings', 'common'])\n const listQuery = useAdminAllowlist()\n const data = listQuery.data\n\n const addAdmin = useAddAdmin()\n const removeAdmin = useRemoveAdmin()\n\n const [platform, setPlatform] = useState('')\n const [userId, setUserId] = useState('')\n const [removeTarget, setRemoveTarget] = useState<AdminEntry | null>(null)\n\n async function onAdd(e: React.FormEvent): Promise<void> {\n e.preventDefault()\n const p = platform.trim()\n const u = userId.trim()\n if (!p || !u) return\n try {\n await addAdmin.mutateAsync({ platform: p, userId: u })\n toast.success(t('admins.toast.added'))\n setPlatform('')\n setUserId('')\n } catch (err) {\n toast.error(describeError(err, t).message)\n }\n }\n\n async function onConfirmRemove(): Promise<void> {\n if (!removeTarget) return\n try {\n await removeAdmin.mutateAsync(removeTarget)\n toast.success(t('admins.toast.removed'))\n } catch (err) {\n toast.error(describeError(err, t).message)\n throw err\n }\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('admins.title')}</h1>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"ml-auto\"\n onClick={() => listQuery.refetch()}\n disabled={listQuery.isFetching}\n aria-label={t('actions.refresh', { ns: 'common' })}\n >\n {listQuery.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('admins.subtitle')}</p>\n </header>\n\n {data && (\n <div className=\"flex flex-wrap items-center gap-2\">\n {data.configured ? (\n <Badge variant=\"success\">{t('admins.configured')}</Badge>\n ) : (\n <Badge variant=\"warning\">{t('admins.notConfigured')}</Badge>\n )}\n {data.bootstrapAvailable && (\n <Badge variant=\"info\" title={data.bootstrapTokenPath}>\n {t('admins.bootstrapAvailable')}\n </Badge>\n )}\n </div>\n )}\n\n {listQuery.isLoading ? (\n <div className=\"h-32 rounded-md bg-surface-2 animate-pulse\" />\n ) : data && data.admins.length === 0 ? (\n <EmptyState icon={<Shield />} title={t('admins.empty')} />\n ) : data ? (\n <Table>\n <TableHeader>\n <TableRow>\n <TableHead className=\"w-40\">{t('admins.col.platform')}</TableHead>\n <TableHead>{t('admins.col.userId')}</TableHead>\n <TableHead className=\"w-24\" />\n </TableRow>\n </TableHeader>\n <TableBody>\n {data.admins.map((a) => (\n <TableRow key={`${a.platform}:${a.userId}`}>\n <TableCell className=\"font-mono\">{a.platform}</TableCell>\n <TableCell className=\"font-mono text-xs\">{a.userId}</TableCell>\n <TableCell>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => setRemoveTarget(a)}\n disabled={removeAdmin.isPending}\n aria-label={t('admins.remove.label')}\n >\n <Trash2 className=\"h-3 w-3\" />\n <span className=\"sr-only sm:not-sr-only sm:ml-1\">{t('admins.remove.label')}</span>\n </Button>\n </TableCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n ) : null}\n\n {/* Add form */}\n <form\n onSubmit={(e) => void onAdd(e)}\n className=\"rounded-md border border-border bg-surface p-4\"\n >\n <div className=\"mb-3 text-sm font-medium\">{t('admins.add.title')}</div>\n <div className=\"grid grid-cols-1 gap-2 sm:grid-cols-[180px_1fr_auto] sm:items-end\">\n <div className=\"flex flex-col gap-1\">\n <Label htmlFor=\"admin-platform\" className=\"text-xs text-text-dim\">\n {t('admins.add.platform')}\n </Label>\n <Input\n id=\"admin-platform\"\n value={platform}\n onChange={(e) => setPlatform(e.target.value)}\n placeholder=\"wechat\"\n className=\"font-mono text-xs\"\n />\n </div>\n <div className=\"flex flex-col gap-1\">\n <Label htmlFor=\"admin-user\" className=\"text-xs text-text-dim\">\n {t('admins.add.userId')}\n </Label>\n <Input\n id=\"admin-user\"\n value={userId}\n onChange={(e) => setUserId(e.target.value)}\n placeholder=\"wxid_abc123\"\n className=\"font-mono text-xs\"\n />\n </div>\n <Button\n type=\"submit\"\n size=\"sm\"\n disabled={addAdmin.isPending || !platform.trim() || !userId.trim()}\n >\n {addAdmin.isPending ? <Loader2 className=\"h-4 w-4 animate-spin\" /> : <UserPlus className=\"h-4 w-4\" />}\n {t('admins.add.submit')}\n </Button>\n </div>\n </form>\n\n <ConfirmDialog\n open={removeTarget != null}\n onOpenChange={(open) => { if (!open) setRemoveTarget(null) }}\n title={t('admins.remove.confirmTitle')}\n description={t('admins.remove.confirmDescription')}\n intent=\"danger\"\n confirmLabel={t('admins.remove.label')}\n onConfirm={onConfirmRemove}\n />\n </div>\n )\n}\n"],"names":["Shield","createLucideIcon","UserPlus","SettingsAdminsRoute","t","useTranslation","listQuery","useAdminAllowlist","data","addAdmin","useAddAdmin","removeAdmin","useRemoveAdmin","platform","setPlatform","useState","userId","setUserId","removeTarget","setRemoveTarget","onAdd","e","p","u","toast","err","describeError","onConfirmRemove","jsxs","jsx","Button","Loader2","RefreshCcw","Badge","EmptyState","Table","TableHeader","TableRow","TableHead","TableBody","TableCell","Trash2","Label","Input","ConfirmDialog","open"],"mappings":"6kBAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GASA,MAAMA,EAASC,EAAiB,SAAU,CACxC,CACE,OACA,CACE,EAAG,qKACH,IAAK,QACX,CACA,CACA,CAAC,ECjBD;AAAA;AAAA;AAAA;AAAA;AAAA,GASA,MAAMC,EAAWD,EAAiB,WAAY,CAC5C,CAAC,OAAQ,CAAE,EAAG,4CAA6C,IAAK,QAAQ,CAAE,EAC1E,CAAC,SAAU,CAAE,GAAI,IAAK,GAAI,IAAK,EAAG,IAAK,IAAK,QAAS,EACrD,CAAC,OAAQ,CAAE,GAAI,KAAM,GAAI,KAAM,GAAI,IAAK,GAAI,KAAM,IAAK,QAAQ,CAAE,EACjE,CAAC,OAAQ,CAAE,GAAI,KAAM,GAAI,KAAM,GAAI,KAAM,GAAI,KAAM,IAAK,QAAQ,CAAE,CACpE,CAAC,ECuBD,SAAwBE,IAAmC,CACzD,KAAM,CAAE,EAAAC,CAAA,EAAMC,EAAe,CAAC,WAAY,QAAQ,CAAC,EAC7CC,EAAYC,EAAA,EACZC,EAAOF,EAAU,KAEjBG,EAAWC,EAAA,EACXC,EAAcC,EAAA,EAEd,CAACC,EAAUC,CAAW,EAAIC,EAAAA,SAAS,EAAE,EACrC,CAACC,EAAQC,CAAS,EAAIF,EAAAA,SAAS,EAAE,EACjC,CAACG,EAAcC,CAAe,EAAIJ,EAAAA,SAA4B,IAAI,EAExE,eAAeK,EAAMC,EAAmC,CACtDA,EAAE,eAAA,EACF,MAAMC,EAAIT,EAAS,KAAA,EACbU,EAAIP,EAAO,KAAA,EACjB,GAAI,GAACM,GAAK,CAACC,GACX,GAAI,CACF,MAAMd,EAAS,YAAY,CAAE,SAAUa,EAAG,OAAQC,EAAG,EACrDC,EAAM,QAAQpB,EAAE,oBAAoB,CAAC,EACrCU,EAAY,EAAE,EACdG,EAAU,EAAE,CACd,OAASQ,EAAK,CACZD,EAAM,MAAME,EAAcD,EAAKrB,CAAC,EAAE,OAAO,CAC3C,CACF,CAEA,eAAeuB,GAAiC,CAC9C,GAAKT,EACL,GAAI,CACF,MAAMP,EAAY,YAAYO,CAAY,EAC1CM,EAAM,QAAQpB,EAAE,sBAAsB,CAAC,CACzC,OAASqB,EAAK,CACZD,MAAAA,EAAM,MAAME,EAAcD,EAAKrB,CAAC,EAAE,OAAO,EACnCqB,CACR,CACF,CAEA,OACEG,EAAAA,KAAC,MAAA,CAAI,UAAU,wCACb,SAAA,CAAAA,EAAAA,KAAC,SAAA,CAAO,UAAU,sBAChB,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,oCACb,SAAA,CAAAC,MAAC,KAAA,CAAG,UAAU,wBAAyB,SAAAzB,EAAE,cAAc,EAAE,EACzDwB,EAAAA,KAACE,EAAA,CACC,QAAQ,QACR,KAAK,KACL,UAAU,UACV,QAAS,IAAMxB,EAAU,QAAA,EACzB,SAAUA,EAAU,WACpB,aAAYF,EAAE,kBAAmB,CAAE,GAAI,SAAU,EAEhD,SAAA,CAAAE,EAAU,iBAAcyB,EAAA,CAAQ,UAAU,uBAAuB,EAAKF,EAAAA,IAACG,EAAA,CAAW,UAAU,SAAA,CAAU,EACvGH,EAAAA,IAAC,OAAA,CAAK,UAAU,mBAAoB,SAAAzB,EAAE,kBAAmB,CAAE,GAAI,QAAA,CAAU,CAAA,CAAE,CAAA,CAAA,CAAA,CAC7E,EACF,QACC,IAAA,CAAE,UAAU,wBAAyB,SAAAA,EAAE,iBAAiB,CAAA,CAAE,CAAA,EAC7D,EAECI,GACCoB,EAAAA,KAAC,MAAA,CAAI,UAAU,oCACZ,SAAA,CAAApB,EAAK,WACJqB,EAAAA,IAACI,EAAA,CAAM,QAAQ,UAAW,SAAA7B,EAAE,mBAAmB,CAAA,CAAE,QAEhD6B,EAAA,CAAM,QAAQ,UAAW,SAAA7B,EAAE,sBAAsB,EAAE,EAErDI,EAAK,oBACJqB,EAAAA,IAACI,EAAA,CAAM,QAAQ,OAAO,MAAOzB,EAAK,mBAC/B,SAAAJ,EAAE,2BAA2B,CAAA,CAChC,CAAA,EAEJ,EAGDE,EAAU,UACTuB,EAAAA,IAAC,MAAA,CAAI,UAAU,6CAA6C,EAC1DrB,GAAQA,EAAK,OAAO,SAAW,QAChC0B,EAAA,CAAW,KAAML,EAAAA,IAAC7B,EAAA,CAAA,CAAO,EAAI,MAAOI,EAAE,cAAc,CAAA,CAAG,EACtDI,EACFoB,EAAAA,KAACO,EAAA,CACC,SAAA,CAAAN,EAAAA,IAACO,EAAA,CACC,gBAACC,EAAA,CACC,SAAA,CAAAR,MAACS,EAAA,CAAU,UAAU,OAAQ,SAAAlC,EAAE,qBAAqB,EAAE,EACtDyB,EAAAA,IAACS,EAAA,CAAW,SAAAlC,EAAE,mBAAmB,CAAA,CAAE,EACnCyB,EAAAA,IAACS,EAAA,CAAU,UAAU,MAAA,CAAO,CAAA,CAAA,CAC9B,CAAA,CACF,EACAT,EAAAA,IAACU,GACE,SAAA/B,EAAK,OAAO,IAAK,UACf6B,EAAA,CACC,SAAA,CAAAR,EAAAA,IAACW,EAAA,CAAU,UAAU,YAAa,SAAA,EAAE,SAAS,EAC7CX,EAAAA,IAACW,EAAA,CAAU,UAAU,oBAAqB,WAAE,OAAO,QAClDA,EAAA,CACC,SAAAZ,EAAAA,KAACE,EAAA,CACC,QAAQ,QACR,KAAK,KACL,QAAS,IAAMX,EAAgB,CAAC,EAChC,SAAUR,EAAY,UACtB,aAAYP,EAAE,qBAAqB,EAEnC,SAAA,CAAAyB,EAAAA,IAACY,EAAA,CAAO,UAAU,SAAA,CAAU,QAC3B,OAAA,CAAK,UAAU,iCAAkC,SAAArC,EAAE,qBAAqB,CAAA,CAAE,CAAA,CAAA,CAAA,CAC7E,CACF,CAAA,GAda,GAAG,EAAE,QAAQ,IAAI,EAAE,MAAM,EAexC,CACD,CAAA,CACH,CAAA,CAAA,CACF,EACE,KAGJwB,EAAAA,KAAC,OAAA,CACC,SAAWP,GAAM,KAAKD,EAAMC,CAAC,EAC7B,UAAU,iDAEV,SAAA,CAAAQ,MAAC,MAAA,CAAI,UAAU,2BAA4B,SAAAzB,EAAE,kBAAkB,EAAE,EACjEwB,EAAAA,KAAC,MAAA,CAAI,UAAU,oEACb,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,sBACb,SAAA,CAAAC,EAAAA,IAACa,GAAM,QAAQ,iBAAiB,UAAU,wBACvC,SAAAtC,EAAE,qBAAqB,EAC1B,EACAyB,EAAAA,IAACc,EAAA,CACC,GAAG,iBACH,MAAO9B,EACP,SAAWQ,GAAMP,EAAYO,EAAE,OAAO,KAAK,EAC3C,YAAY,SACZ,UAAU,mBAAA,CAAA,CACZ,EACF,EACAO,EAAAA,KAAC,MAAA,CAAI,UAAU,sBACb,SAAA,CAAAC,EAAAA,IAACa,GAAM,QAAQ,aAAa,UAAU,wBACnC,SAAAtC,EAAE,mBAAmB,EACxB,EACAyB,EAAAA,IAACc,EAAA,CACC,GAAG,aACH,MAAO3B,EACP,SAAWK,GAAMJ,EAAUI,EAAE,OAAO,KAAK,EACzC,YAAY,cACZ,UAAU,mBAAA,CAAA,CACZ,EACF,EACAO,EAAAA,KAACE,EAAA,CACC,KAAK,SACL,KAAK,KACL,SAAUrB,EAAS,WAAa,CAACI,EAAS,QAAU,CAACG,EAAO,KAAA,EAE3D,SAAA,CAAAP,EAAS,gBAAasB,EAAA,CAAQ,UAAU,uBAAuB,EAAKF,EAAAA,IAAC3B,EAAA,CAAS,UAAU,SAAA,CAAU,EAClGE,EAAE,mBAAmB,CAAA,CAAA,CAAA,CACxB,CAAA,CACF,CAAA,CAAA,CAAA,EAGFyB,EAAAA,IAACe,EAAA,CACC,KAAM1B,GAAgB,KACtB,aAAe2B,GAAS,CAAOA,GAAM1B,EAAgB,IAAI,CAAE,EAC3D,MAAOf,EAAE,4BAA4B,EACrC,YAAaA,EAAE,kCAAkC,EACjD,OAAO,SACP,aAAcA,EAAE,qBAAqB,EACrC,UAAWuB,CAAA,CAAA,CACb,EACF,CAEJ","x_google_ignoreList":[0,1]}
|
|
1
|
+
{"version":3,"file":"admins-BVpnOw3o.js","sources":["../../node_modules/lucide-react/dist/esm/icons/shield.js","../../node_modules/lucide-react/dist/esm/icons/user-plus.js","../../src/routes/settings/admins.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 Shield = createLucideIcon(\"Shield\", [\n [\n \"path\",\n {\n d: \"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z\",\n key: \"oel41y\"\n }\n ]\n]);\n\nexport { Shield as default };\n//# sourceMappingURL=shield.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 UserPlus = createLucideIcon(\"UserPlus\", [\n [\"path\", { d: \"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2\", key: \"1yyitq\" }],\n [\"circle\", { cx: \"9\", cy: \"7\", r: \"4\", key: \"nufk8\" }],\n [\"line\", { x1: \"19\", x2: \"19\", y1: \"8\", y2: \"14\", key: \"1bvyxn\" }],\n [\"line\", { x1: \"22\", x2: \"16\", y1: \"11\", y2: \"11\", key: \"1shjgl\" }]\n]);\n\nexport { UserPlus as default };\n//# sourceMappingURL=user-plus.js.map\n","/**\n * /settings/admins — manage `IMHUB_ADMIN_USERS` entries.\n *\n * Each entry is a `(platform, userId)` pair (e.g. `wechat:wxid_abc`).\n * Add via the inline form at the bottom; remove via per-row trash\n * button → ConfirmDialog. The backend's POST/DELETE handlers gate\n * on isLocalBind — if the operator is hitting agim from another\n * host the mutations 403; we surface that toast verbatim.\n */\n\nimport { useState } from 'react'\nimport { useTranslation } from 'react-i18next'\nimport { toast } from 'sonner'\nimport { Loader2, RefreshCcw, Shield, Trash2, UserPlus } from 'lucide-react'\n\nimport { ConfirmDialog } from '@/components/common/confirm-dialog'\nimport { EmptyState } from '@/components/common/empty-state'\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 Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from '@/components/ui/table'\nimport {\n useAddAdmin,\n useAdminAllowlist,\n useRemoveAdmin,\n} from '@/hooks/use-settings'\nimport { describeError } from '@/lib/api/errors'\nimport type { AdminEntry } from '@/types/api'\n\nexport default function SettingsAdminsRoute(): JSX.Element {\n const { t } = useTranslation(['settings', 'common'])\n const listQuery = useAdminAllowlist()\n const data = listQuery.data\n\n const addAdmin = useAddAdmin()\n const removeAdmin = useRemoveAdmin()\n\n const [platform, setPlatform] = useState('')\n const [userId, setUserId] = useState('')\n const [removeTarget, setRemoveTarget] = useState<AdminEntry | null>(null)\n\n async function onAdd(e: React.FormEvent): Promise<void> {\n e.preventDefault()\n const p = platform.trim()\n const u = userId.trim()\n if (!p || !u) return\n try {\n await addAdmin.mutateAsync({ platform: p, userId: u })\n toast.success(t('admins.toast.added'))\n setPlatform('')\n setUserId('')\n } catch (err) {\n toast.error(describeError(err, t).message)\n }\n }\n\n async function onConfirmRemove(): Promise<void> {\n if (!removeTarget) return\n try {\n await removeAdmin.mutateAsync(removeTarget)\n toast.success(t('admins.toast.removed'))\n } catch (err) {\n toast.error(describeError(err, t).message)\n throw err\n }\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('admins.title')}</h1>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"ml-auto\"\n onClick={() => listQuery.refetch()}\n disabled={listQuery.isFetching}\n aria-label={t('actions.refresh', { ns: 'common' })}\n >\n {listQuery.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('admins.subtitle')}</p>\n </header>\n\n {data && (\n <div className=\"flex flex-wrap items-center gap-2\">\n {data.configured ? (\n <Badge variant=\"success\">{t('admins.configured')}</Badge>\n ) : (\n <Badge variant=\"warning\">{t('admins.notConfigured')}</Badge>\n )}\n {data.bootstrapAvailable && (\n <Badge variant=\"info\" title={data.bootstrapTokenPath}>\n {t('admins.bootstrapAvailable')}\n </Badge>\n )}\n </div>\n )}\n\n {listQuery.isLoading ? (\n <div className=\"h-32 rounded-md bg-surface-2 animate-pulse\" />\n ) : data && data.admins.length === 0 ? (\n <EmptyState icon={<Shield />} title={t('admins.empty')} />\n ) : data ? (\n <Table>\n <TableHeader>\n <TableRow>\n <TableHead className=\"w-40\">{t('admins.col.platform')}</TableHead>\n <TableHead>{t('admins.col.userId')}</TableHead>\n <TableHead className=\"w-24\" />\n </TableRow>\n </TableHeader>\n <TableBody>\n {data.admins.map((a) => (\n <TableRow key={`${a.platform}:${a.userId}`}>\n <TableCell className=\"font-mono\">{a.platform}</TableCell>\n <TableCell className=\"font-mono text-xs\">{a.userId}</TableCell>\n <TableCell>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => setRemoveTarget(a)}\n disabled={removeAdmin.isPending}\n aria-label={t('admins.remove.label')}\n >\n <Trash2 className=\"h-3 w-3\" />\n <span className=\"sr-only sm:not-sr-only sm:ml-1\">{t('admins.remove.label')}</span>\n </Button>\n </TableCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n ) : null}\n\n {/* Add form */}\n <form\n onSubmit={(e) => void onAdd(e)}\n className=\"rounded-md border border-border bg-surface p-4\"\n >\n <div className=\"mb-3 text-sm font-medium\">{t('admins.add.title')}</div>\n <div className=\"grid grid-cols-1 gap-2 sm:grid-cols-[180px_1fr_auto] sm:items-end\">\n <div className=\"flex flex-col gap-1\">\n <Label htmlFor=\"admin-platform\" className=\"text-xs text-text-dim\">\n {t('admins.add.platform')}\n </Label>\n <Input\n id=\"admin-platform\"\n value={platform}\n onChange={(e) => setPlatform(e.target.value)}\n placeholder=\"wechat\"\n className=\"font-mono text-xs\"\n />\n </div>\n <div className=\"flex flex-col gap-1\">\n <Label htmlFor=\"admin-user\" className=\"text-xs text-text-dim\">\n {t('admins.add.userId')}\n </Label>\n <Input\n id=\"admin-user\"\n value={userId}\n onChange={(e) => setUserId(e.target.value)}\n placeholder=\"wxid_abc123\"\n className=\"font-mono text-xs\"\n />\n </div>\n <Button\n type=\"submit\"\n size=\"sm\"\n disabled={addAdmin.isPending || !platform.trim() || !userId.trim()}\n >\n {addAdmin.isPending ? <Loader2 className=\"h-4 w-4 animate-spin\" /> : <UserPlus className=\"h-4 w-4\" />}\n {t('admins.add.submit')}\n </Button>\n </div>\n </form>\n\n <ConfirmDialog\n open={removeTarget != null}\n onOpenChange={(open) => { if (!open) setRemoveTarget(null) }}\n title={t('admins.remove.confirmTitle')}\n description={t('admins.remove.confirmDescription')}\n intent=\"danger\"\n confirmLabel={t('admins.remove.label')}\n onConfirm={onConfirmRemove}\n />\n </div>\n )\n}\n"],"names":["Shield","createLucideIcon","UserPlus","SettingsAdminsRoute","t","useTranslation","listQuery","useAdminAllowlist","data","addAdmin","useAddAdmin","removeAdmin","useRemoveAdmin","platform","setPlatform","useState","userId","setUserId","removeTarget","setRemoveTarget","onAdd","e","p","u","toast","err","describeError","onConfirmRemove","jsxs","jsx","Button","Loader2","RefreshCcw","Badge","EmptyState","Table","TableHeader","TableRow","TableHead","TableBody","TableCell","Trash2","Label","Input","ConfirmDialog","open"],"mappings":"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","x_google_ignoreList":[0,1]}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import{y as le,ad as U,U as e,c as N,L as O,S as Q,l as Z,m as X,j as Y,k as I,B as L,a3 as f,E as F,s as J,I as R}from"./index-BY1vfCja.js";import{e as u}from"./react-C9F3QeMB.js";import{E as re}from"./empty-state-B1S_EYNJ.js";import{u as oe}from"./use-workspace-BhTEp_QH.js";import{b as de,m as me,k as xe,c as ue}from"./use-settings-D4EdDLiK.js";import{L as D}from"./loader-circle-pGNYdPoE.js";import{R as pe}from"./refresh-ccw-BlXMN3UX.js";import{X as he}from"./x-5Z_de5zo.js";import{S as ge}from"./save-DAFuApnY.js";import{N as q}from"./network-DpjSgAwW.js";import{S as H}from"./search-BWuZE0YD.js";import{P as fe}from"./plus-C5d4C6Zp.js";import{T as je}from"./trash-2-i4F_Rzh3.js";import"./useQuery-DmoWKLw3.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}=U(["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(L,{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}=U("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(L,{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}=U(["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(L,{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}=U("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(L,{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-Cn7D3UMz.js.map
|