agim-cli 1.2.42 → 1.2.44

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (139) hide show
  1. package/dist/core/viewer-config.d.ts +35 -3
  2. package/dist/core/viewer-config.d.ts.map +1 -1
  3. package/dist/core/viewer-config.js +47 -3
  4. package/dist/core/viewer-config.js.map +1 -1
  5. package/dist/core/viewer-remote.d.ts.map +1 -1
  6. package/dist/core/viewer-remote.js +4 -3
  7. package/dist/core/viewer-remote.js.map +1 -1
  8. package/dist/web/public/assets/{a2a-Dvz7ig4m.js → a2a-Bg_mT0z1.js} +2 -2
  9. package/dist/web/public/assets/{a2a-Dvz7ig4m.js.map → a2a-Bg_mT0z1.js.map} +1 -1
  10. package/dist/web/public/assets/{activity-BJqk7b-v.js → activity-U9AaNlDt.js} +2 -2
  11. package/dist/web/public/assets/{activity-BJqk7b-v.js.map → activity-U9AaNlDt.js.map} +1 -1
  12. package/dist/web/public/assets/{admins-DeiNQcMh.js → admins-BTC_YEK9.js} +2 -2
  13. package/dist/web/public/assets/{admins-DeiNQcMh.js.map → admins-BTC_YEK9.js.map} +1 -1
  14. package/dist/web/public/assets/{agents-DJGdXKLv.js → agents-o9odac79.js} +2 -2
  15. package/dist/web/public/assets/{agents-DJGdXKLv.js.map → agents-o9odac79.js.map} +1 -1
  16. package/dist/web/public/assets/{approvals-BOJ9et5G.js → approvals-Boj7iXz4.js} +2 -2
  17. package/dist/web/public/assets/{approvals-BOJ9et5G.js.map → approvals-Boj7iXz4.js.map} +1 -1
  18. package/dist/web/public/assets/{audit-Dnnevx6v.js → audit-MprCFoy_.js} +2 -2
  19. package/dist/web/public/assets/{audit-Dnnevx6v.js.map → audit-MprCFoy_.js.map} +1 -1
  20. package/dist/web/public/assets/{bgjobs-BZAxNFpA.js → bgjobs-B6XvxURz.js} +2 -2
  21. package/dist/web/public/assets/{bgjobs-BZAxNFpA.js.map → bgjobs-B6XvxURz.js.map} +1 -1
  22. package/dist/web/public/assets/{brain-fC59o4ZL.js → brain-C5HejASN.js} +2 -2
  23. package/dist/web/public/assets/{brain-fC59o4ZL.js.map → brain-C5HejASN.js.map} +1 -1
  24. package/dist/web/public/assets/{briefcase-DJRv77W6.js → briefcase-DkCTxO1A.js} +2 -2
  25. package/dist/web/public/assets/{briefcase-DJRv77W6.js.map → briefcase-DkCTxO1A.js.map} +1 -1
  26. package/dist/web/public/assets/{chevron-right-DzyVDoQs.js → chevron-right-DEyrYFz4.js} +2 -2
  27. package/dist/web/public/assets/{chevron-right-DzyVDoQs.js.map → chevron-right-DEyrYFz4.js.map} +1 -1
  28. package/dist/web/public/assets/{circle-check-B7B_CkmJ.js → circle-check-bADFEXGw.js} +2 -2
  29. package/dist/web/public/assets/{circle-check-B7B_CkmJ.js.map → circle-check-bADFEXGw.js.map} +1 -1
  30. package/dist/web/public/assets/{circle-check-big-dmFsJv6U.js → circle-check-big-U4xrkHiS.js} +2 -2
  31. package/dist/web/public/assets/{circle-check-big-dmFsJv6U.js.map → circle-check-big-U4xrkHiS.js.map} +1 -1
  32. package/dist/web/public/assets/{circle-x-epC-av6L.js → circle-x-C6qY5UUl.js} +2 -2
  33. package/dist/web/public/assets/{circle-x-epC-av6L.js.map → circle-x-C6qY5UUl.js.map} +1 -1
  34. package/dist/web/public/assets/{confirm-dialog-BEzhDlk7.js → confirm-dialog-B53cbWzX.js} +2 -2
  35. package/dist/web/public/assets/{confirm-dialog-BEzhDlk7.js.map → confirm-dialog-B53cbWzX.js.map} +1 -1
  36. package/dist/web/public/assets/{data-table-B_BxQrSj.js → data-table-BKTemkw9.js} +2 -2
  37. package/dist/web/public/assets/{data-table-B_BxQrSj.js.map → data-table-BKTemkw9.js.map} +1 -1
  38. package/dist/web/public/assets/{dialog-BAZNQtMt.js → dialog-Cevi7KvQ.js} +2 -2
  39. package/dist/web/public/assets/{dialog-BAZNQtMt.js.map → dialog-Cevi7KvQ.js.map} +1 -1
  40. package/dist/web/public/assets/{download-C08F-eA4.js → download-DwJNwdwV.js} +2 -2
  41. package/dist/web/public/assets/{download-C08F-eA4.js.map → download-DwJNwdwV.js.map} +1 -1
  42. package/dist/web/public/assets/{email-qzOnhITw.js → email-CZVaRhG_.js} +2 -2
  43. package/dist/web/public/assets/{email-qzOnhITw.js.map → email-CZVaRhG_.js.map} +1 -1
  44. package/dist/web/public/assets/{empty-state-BKs1qKHx.js → empty-state-C87S9Wor.js} +2 -2
  45. package/dist/web/public/assets/{empty-state-BKs1qKHx.js.map → empty-state-C87S9Wor.js.map} +1 -1
  46. package/dist/web/public/assets/{external-link-HML--jya.js → external-link-CIM1wjHP.js} +2 -2
  47. package/dist/web/public/assets/{external-link-HML--jya.js.map → external-link-CIM1wjHP.js.map} +1 -1
  48. package/dist/web/public/assets/{eye-C20O3zvh.js → eye-TUAOhz72.js} +2 -2
  49. package/dist/web/public/assets/{eye-C20O3zvh.js.map → eye-TUAOhz72.js.map} +1 -1
  50. package/dist/web/public/assets/{facts-B7VlqoVs.js → facts-ByM1VHCp.js} +2 -2
  51. package/dist/web/public/assets/{facts-B7VlqoVs.js.map → facts-ByM1VHCp.js.map} +1 -1
  52. package/dist/web/public/assets/{health-IF_VcgWW.js → health-B4GF06J-.js} +2 -2
  53. package/dist/web/public/assets/{health-IF_VcgWW.js.map → health-B4GF06J-.js.map} +1 -1
  54. package/dist/web/public/assets/{hot-D-aKQ8y2.js → hot-O9Z19xXa.js} +2 -2
  55. package/dist/web/public/assets/{hot-D-aKQ8y2.js.map → hot-O9Z19xXa.js.map} +1 -1
  56. package/dist/web/public/assets/{index-B48azMO-.js → index-CITyis5g.js} +4 -4
  57. package/dist/web/public/assets/{index-B48azMO-.js.map → index-CITyis5g.js.map} +1 -1
  58. package/dist/web/public/assets/{installed-CkiQRc89.js → installed-CM34mlDU.js} +2 -2
  59. package/dist/web/public/assets/{installed-CkiQRc89.js.map → installed-CM34mlDU.js.map} +1 -1
  60. package/dist/web/public/assets/{jobs-g1Wl8_zd.js → jobs-DwA9Ip87.js} +2 -2
  61. package/dist/web/public/assets/{jobs-g1Wl8_zd.js.map → jobs-DwA9Ip87.js.map} +1 -1
  62. package/dist/web/public/assets/{layout-D_CUXsIR.js → layout-BxrFilDN.js} +2 -2
  63. package/dist/web/public/assets/{layout-D_CUXsIR.js.map → layout-BxrFilDN.js.map} +1 -1
  64. package/dist/web/public/assets/{layout-ChcpcCB8.js → layout-CR5gLapT.js} +2 -2
  65. package/dist/web/public/assets/{layout-ChcpcCB8.js.map → layout-CR5gLapT.js.map} +1 -1
  66. package/dist/web/public/assets/{layout-CjLzz--E.js → layout-CcJQxFci.js} +2 -2
  67. package/dist/web/public/assets/{layout-CjLzz--E.js.map → layout-CcJQxFci.js.map} +1 -1
  68. package/dist/web/public/assets/{layout-CS9s-Q0a.js → layout-DRRveTaR.js} +2 -2
  69. package/dist/web/public/assets/{layout-CS9s-Q0a.js.map → layout-DRRveTaR.js.map} +1 -1
  70. package/dist/web/public/assets/{layout-fTZD9lJN.js → layout-zotlJ5fW.js} +2 -2
  71. package/dist/web/public/assets/{layout-fTZD9lJN.js.map → layout-zotlJ5fW.js.map} +1 -1
  72. package/dist/web/public/assets/{loader-circle-DBf4xFjo.js → loader-circle-BFp6Oc8_.js} +2 -2
  73. package/dist/web/public/assets/{loader-circle-DBf4xFjo.js.map → loader-circle-BFp6Oc8_.js.map} +1 -1
  74. package/dist/web/public/assets/{map-pin-BYR0Sf5r.js → map-pin-DPqnsBIG.js} +2 -2
  75. package/dist/web/public/assets/{map-pin-BYR0Sf5r.js.map → map-pin-DPqnsBIG.js.map} +1 -1
  76. package/dist/web/public/assets/{memos-ChfapnyG.js → memos-DCACQN26.js} +2 -2
  77. package/dist/web/public/assets/{memos-ChfapnyG.js.map → memos-DCACQN26.js.map} +1 -1
  78. package/dist/web/public/assets/{messengers-zBIYakPW.js → messengers-CwWP1qI4.js} +2 -2
  79. package/dist/web/public/assets/{messengers-zBIYakPW.js.map → messengers-CwWP1qI4.js.map} +1 -1
  80. package/dist/web/public/assets/{network-CEqTiog6.js → network-CrMEVz4-.js} +2 -2
  81. package/dist/web/public/assets/{network-CEqTiog6.js.map → network-CrMEVz4-.js.map} +1 -1
  82. package/dist/web/public/assets/{outbox-D4IQcACJ.js → outbox-C7FpZzwS.js} +2 -2
  83. package/dist/web/public/assets/{outbox-D4IQcACJ.js.map → outbox-C7FpZzwS.js.map} +1 -1
  84. package/dist/web/public/assets/{pagination-R9mql8VB.js → pagination-Cgt8W6EX.js} +2 -2
  85. package/dist/web/public/assets/{pagination-R9mql8VB.js.map → pagination-Cgt8W6EX.js.map} +1 -1
  86. package/dist/web/public/assets/{persona-Cj_C5frK.js → persona-Bjty6uqM.js} +2 -2
  87. package/dist/web/public/assets/{persona-Cj_C5frK.js.map → persona-Bjty6uqM.js.map} +1 -1
  88. package/dist/web/public/assets/{play-CTWqoMcj.js → play-CEoS1N8t.js} +2 -2
  89. package/dist/web/public/assets/{play-CTWqoMcj.js.map → play-CEoS1N8t.js.map} +1 -1
  90. package/dist/web/public/assets/{policy-BKEZ2ziu.js → policy-DwI-ov9J.js} +2 -2
  91. package/dist/web/public/assets/{policy-BKEZ2ziu.js.map → policy-DwI-ov9J.js.map} +1 -1
  92. package/dist/web/public/assets/{refresh-ccw-Clj5sQNF.js → refresh-ccw-CPSYEbgh.js} +2 -2
  93. package/dist/web/public/assets/{refresh-ccw-Clj5sQNF.js.map → refresh-ccw-CPSYEbgh.js.map} +1 -1
  94. package/dist/web/public/assets/{reminders-C5bVkLgj.js → reminders-X-QFSWvZ.js} +2 -2
  95. package/dist/web/public/assets/{reminders-C5bVkLgj.js.map → reminders-X-QFSWvZ.js.map} +1 -1
  96. package/dist/web/public/assets/{save-CAFra1jb.js → save-tS3IBPf3.js} +2 -2
  97. package/dist/web/public/assets/{save-CAFra1jb.js.map → save-tS3IBPf3.js.map} +1 -1
  98. package/dist/web/public/assets/{schedules-KQCD7978.js → schedules-CfCNvhCV.js} +2 -2
  99. package/dist/web/public/assets/{schedules-KQCD7978.js.map → schedules-CfCNvhCV.js.map} +1 -1
  100. package/dist/web/public/assets/{search-bDqizeZv.js → search-BPvPCccn.js} +2 -2
  101. package/dist/web/public/assets/{search-bDqizeZv.js.map → search-BPvPCccn.js.map} +1 -1
  102. package/dist/web/public/assets/{service-DTeMmX2u.js → service-DSitDFzD.js} +2 -2
  103. package/dist/web/public/assets/{service-DTeMmX2u.js.map → service-DSitDFzD.js.map} +1 -1
  104. package/dist/web/public/assets/{status-badge-_3Ve0Jef.js → status-badge-HSHkhdur.js} +2 -2
  105. package/dist/web/public/assets/{status-badge-_3Ve0Jef.js.map → status-badge-HSHkhdur.js.map} +1 -1
  106. package/dist/web/public/assets/{subtasks-DROeZcfT.js → subtasks-eKq_P0v6.js} +2 -2
  107. package/dist/web/public/assets/{subtasks-DROeZcfT.js.map → subtasks-eKq_P0v6.js.map} +1 -1
  108. package/dist/web/public/assets/{table-CZwKizat.js → table-BBISYTH-.js} +2 -2
  109. package/dist/web/public/assets/{table-CZwKizat.js.map → table-BBISYTH-.js.map} +1 -1
  110. package/dist/web/public/assets/{topn-DpErN6N8.js → topn-JA8llaUI.js} +2 -2
  111. package/dist/web/public/assets/{topn-DpErN6N8.js.map → topn-JA8llaUI.js.map} +1 -1
  112. package/dist/web/public/assets/{trash-2-BkZrVFdH.js → trash-2-D8F96aYm.js} +2 -2
  113. package/dist/web/public/assets/{trash-2-BkZrVFdH.js.map → trash-2-D8F96aYm.js.map} +1 -1
  114. package/dist/web/public/assets/{use-memory-CElm89Hg.js → use-memory-BDa1R8Tf.js} +2 -2
  115. package/dist/web/public/assets/{use-memory-CElm89Hg.js.map → use-memory-BDa1R8Tf.js.map} +1 -1
  116. package/dist/web/public/assets/{use-observability-D8qHfj0S.js → use-observability-XgxLMQsY.js} +2 -2
  117. package/dist/web/public/assets/{use-observability-D8qHfj0S.js.map → use-observability-XgxLMQsY.js.map} +1 -1
  118. package/dist/web/public/assets/{use-settings-DgU8YmGj.js → use-settings-Bc4s-JUD.js} +2 -2
  119. package/dist/web/public/assets/{use-settings-DgU8YmGj.js.map → use-settings-Bc4s-JUD.js.map} +1 -1
  120. package/dist/web/public/assets/{use-skills-Cp_ok0Uq.js → use-skills-DCOYAQ8s.js} +2 -2
  121. package/dist/web/public/assets/{use-skills-Cp_ok0Uq.js.map → use-skills-DCOYAQ8s.js.map} +1 -1
  122. package/dist/web/public/assets/{use-workspace-Dc6rNi5d.js → use-workspace-JalfqH6H.js} +2 -2
  123. package/dist/web/public/assets/{use-workspace-Dc6rNi5d.js.map → use-workspace-JalfqH6H.js.map} +1 -1
  124. package/dist/web/public/assets/{useQuery-BjFqOBV3.js → useQuery-DFryK9Pn.js} +2 -2
  125. package/dist/web/public/assets/{useQuery-BjFqOBV3.js.map → useQuery-DFryK9Pn.js.map} +1 -1
  126. package/dist/web/public/assets/{vector-Bb3l7TOa.js → vector-G2dN_aut.js} +2 -2
  127. package/dist/web/public/assets/{vector-Bb3l7TOa.js.map → vector-G2dN_aut.js.map} +1 -1
  128. package/dist/web/public/assets/viewer-DliYQkQQ.js +12 -0
  129. package/dist/web/public/assets/viewer-DliYQkQQ.js.map +1 -0
  130. package/dist/web/public/assets/{workspace-Du8va-tD.js → workspace-BaLZIgGn.js} +2 -2
  131. package/dist/web/public/assets/{workspace-Du8va-tD.js.map → workspace-BaLZIgGn.js.map} +1 -1
  132. package/dist/web/public/assets/{workspaces-BjgDtEnF.js → workspaces-cX_rV523.js} +2 -2
  133. package/dist/web/public/assets/{workspaces-BjgDtEnF.js.map → workspaces-cX_rV523.js.map} +1 -1
  134. package/dist/web/public/assets/{x-CHe1y-sG.js → x-D5196-9X.js} +2 -2
  135. package/dist/web/public/assets/{x-CHe1y-sG.js.map → x-D5196-9X.js.map} +1 -1
  136. package/dist/web/public/index.html +1 -1
  137. package/package.json +1 -1
  138. package/dist/web/public/assets/viewer-BeyW50lw.js +0 -12
  139. package/dist/web/public/assets/viewer-BeyW50lw.js.map +0 -1
@@ -55,13 +55,45 @@ export interface ViewerConfig {
55
55
  /** Char / line / code-block thresholds for routing to web. */
56
56
  thresholds: ViewerThresholds;
57
57
  }
58
+ /**
59
+ * v1.2.43 — community-hosted default paste server.
60
+ *
61
+ * Operators who don't have a domain or working tunnel still get usable
62
+ * viewer links out of the box by routing through this public service.
63
+ * Users can:
64
+ * - Override by setting their own IMHUB_VIEWER_REMOTE_PASTE_URL
65
+ * - Opt back into a local-only path by setting IMHUB_VIEWER_PUBLIC_BASE_URL
66
+ * - Disable the default entirely with IMHUB_VIEWER_NO_DEFAULT_REMOTE=1
67
+ *
68
+ * IMPORTANT — privacy: with the default on, any markdown long enough
69
+ * to exit the inline path is uploaded to viewer.iclaw.host over HTTPS.
70
+ * agim's CLI wizard surfaces this trade-off on first run; deployment
71
+ * docs (`docs/viewer-modes.md`) cover it too.
72
+ */
73
+ export declare const DEFAULT_REMOTE_PASTE_URL = "https://viewer.iclaw.host/paste";
58
74
  export declare function getViewerConfig(): ViewerConfig;
59
75
  /**
60
- * v1.2.42 — pick the active viewer mode. First non-empty source wins.
61
- * Exported (and pure) so tests + the wizard show the same answer the
62
- * sink uses at runtime.
76
+ * v1.2.42 / v1.2.43 — pick the active viewer mode. First non-empty
77
+ * configured source wins; the community default remote is the final
78
+ * fallback so an out-of-the-box install still produces working links.
79
+ *
80
+ * Order:
81
+ * 1. user-set IMHUB_VIEWER_REMOTE_PASTE_URL → remote (operator-managed)
82
+ * 2. user-set IMHUB_VIEWER_PUBLIC_BASE_URL → local (own domain)
83
+ * 3. IMHUB_VIEWER_TUNNEL_MODE=quick → tunnel
84
+ * 4. community default viewer.iclaw.host → remote (default-on)
85
+ * 5. nothing → none (inline degrade)
86
+ *
87
+ * Set IMHUB_VIEWER_NO_DEFAULT_REMOTE=1 to skip step 4 (privacy opt-out).
63
88
  */
64
89
  export declare function resolveViewerMode(cfg?: ViewerConfig): ViewerMode;
90
+ /**
91
+ * Resolve the effective remote paste URL the sink should POST to.
92
+ * Honours user-set value first, then the community default unless
93
+ * the operator opted out via IMHUB_VIEWER_NO_DEFAULT_REMOTE=1.
94
+ * Returns null when no usable URL is available.
95
+ */
96
+ export declare function getEffectiveRemotePasteUrl(cfg?: ViewerConfig): string | null;
65
97
  /**
66
98
  * Resolve the effective public base URL. Order of preference:
67
99
  * 1. Explicit IMHUB_VIEWER_PUBLIC_BASE_URL (operator-managed reverse proxy)
@@ -1 +1 @@
1
- {"version":3,"file":"viewer-config.d.ts","sourceRoot":"","sources":["../../src/core/viewer-config.ts"],"names":[],"mappings":"AAMA,OAAO,EAAsB,KAAK,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AAG9E,MAAM,MAAM,gBAAgB,GAAG,KAAK,GAAG,OAAO,CAAA;AAE9C;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAA;AAE/D,MAAM,WAAW,YAAY;IAC3B,mFAAmF;IACnF,OAAO,EAAE,OAAO,CAAA;IAChB;;;;;OAKG;IACH,aAAa,EAAE,MAAM,CAAA;IACrB;;;;;OAKG;IACH,UAAU,EAAE,gBAAgB,CAAA;IAC5B;;;;;;;;;;;;OAYG;IACH,cAAc,EAAE,MAAM,CAAA;IACtB,kEAAkE;IAClE,gBAAgB,EAAE,MAAM,CAAA;IACxB,8DAA8D;IAC9D,UAAU,EAAE,gBAAgB,CAAA;CAC7B;AAQD,wBAAgB,eAAe,IAAI,YAAY,CAoB9C;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,GAAE,YAAgC,GAAG,UAAU,CAMnF;AAED;;;;;;;GAOG;AACH,wBAAgB,yBAAyB,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAQnE;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,EAAE,EAAE,MAAM,EAAE,eAAe,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAIjF"}
1
+ {"version":3,"file":"viewer-config.d.ts","sourceRoot":"","sources":["../../src/core/viewer-config.ts"],"names":[],"mappings":"AAMA,OAAO,EAAsB,KAAK,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AAG9E,MAAM,MAAM,gBAAgB,GAAG,KAAK,GAAG,OAAO,CAAA;AAE9C;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAA;AAE/D,MAAM,WAAW,YAAY;IAC3B,mFAAmF;IACnF,OAAO,EAAE,OAAO,CAAA;IAChB;;;;;OAKG;IACH,aAAa,EAAE,MAAM,CAAA;IACrB;;;;;OAKG;IACH,UAAU,EAAE,gBAAgB,CAAA;IAC5B;;;;;;;;;;;;OAYG;IACH,cAAc,EAAE,MAAM,CAAA;IACtB,kEAAkE;IAClE,gBAAgB,EAAE,MAAM,CAAA;IACxB,8DAA8D;IAC9D,UAAU,EAAE,gBAAgB,CAAA;CAC7B;AAQD;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,wBAAwB,oCAAoC,CAAA;AAEzE,wBAAgB,eAAe,IAAI,YAAY,CAoB9C;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,GAAE,YAAgC,GAAG,UAAU,CAOnF;AAED;;;;;GAKG;AACH,wBAAgB,0BAA0B,CAAC,GAAG,GAAE,YAAgC,GAAG,MAAM,GAAG,IAAI,CAI/F;AAOD;;;;;;;GAOG;AACH,wBAAgB,yBAAyB,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAQnE;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,EAAE,EAAE,MAAM,EAAE,eAAe,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAIjF"}
@@ -11,6 +11,22 @@ function parsePositiveInt(raw, fallback) {
11
11
  const n = parseInt(raw, 10);
12
12
  return Number.isFinite(n) && n > 0 ? n : fallback;
13
13
  }
14
+ /**
15
+ * v1.2.43 — community-hosted default paste server.
16
+ *
17
+ * Operators who don't have a domain or working tunnel still get usable
18
+ * viewer links out of the box by routing through this public service.
19
+ * Users can:
20
+ * - Override by setting their own IMHUB_VIEWER_REMOTE_PASTE_URL
21
+ * - Opt back into a local-only path by setting IMHUB_VIEWER_PUBLIC_BASE_URL
22
+ * - Disable the default entirely with IMHUB_VIEWER_NO_DEFAULT_REMOTE=1
23
+ *
24
+ * IMPORTANT — privacy: with the default on, any markdown long enough
25
+ * to exit the inline path is uploaded to viewer.iclaw.host over HTTPS.
26
+ * agim's CLI wizard surfaces this trade-off on first run; deployment
27
+ * docs (`docs/viewer-modes.md`) cover it too.
28
+ */
29
+ export const DEFAULT_REMOTE_PASTE_URL = 'https://viewer.iclaw.host/paste';
14
30
  export function getViewerConfig() {
15
31
  const enabledRaw = (process.env.IMHUB_VIEWER_ENABLED || '').toLowerCase();
16
32
  const enabled = enabledRaw === '1' || enabledRaw === 'true' || enabledRaw === 'yes';
@@ -33,9 +49,18 @@ export function getViewerConfig() {
33
49
  };
34
50
  }
35
51
  /**
36
- * v1.2.42 — pick the active viewer mode. First non-empty source wins.
37
- * Exported (and pure) so tests + the wizard show the same answer the
38
- * sink uses at runtime.
52
+ * v1.2.42 / v1.2.43 — pick the active viewer mode. First non-empty
53
+ * configured source wins; the community default remote is the final
54
+ * fallback so an out-of-the-box install still produces working links.
55
+ *
56
+ * Order:
57
+ * 1. user-set IMHUB_VIEWER_REMOTE_PASTE_URL → remote (operator-managed)
58
+ * 2. user-set IMHUB_VIEWER_PUBLIC_BASE_URL → local (own domain)
59
+ * 3. IMHUB_VIEWER_TUNNEL_MODE=quick → tunnel
60
+ * 4. community default viewer.iclaw.host → remote (default-on)
61
+ * 5. nothing → none (inline degrade)
62
+ *
63
+ * Set IMHUB_VIEWER_NO_DEFAULT_REMOTE=1 to skip step 4 (privacy opt-out).
39
64
  */
40
65
  export function resolveViewerMode(cfg = getViewerConfig()) {
41
66
  if (!cfg.enabled)
@@ -46,8 +71,27 @@ export function resolveViewerMode(cfg = getViewerConfig()) {
46
71
  return 'local';
47
72
  if (cfg.tunnelMode === 'quick')
48
73
  return 'tunnel';
74
+ if (!isDefaultRemoteDisabled())
75
+ return 'remote'; // community default
49
76
  return 'none';
50
77
  }
78
+ /**
79
+ * Resolve the effective remote paste URL the sink should POST to.
80
+ * Honours user-set value first, then the community default unless
81
+ * the operator opted out via IMHUB_VIEWER_NO_DEFAULT_REMOTE=1.
82
+ * Returns null when no usable URL is available.
83
+ */
84
+ export function getEffectiveRemotePasteUrl(cfg = getViewerConfig()) {
85
+ if (cfg.remotePasteUrl)
86
+ return cfg.remotePasteUrl;
87
+ if (!isDefaultRemoteDisabled())
88
+ return DEFAULT_REMOTE_PASTE_URL;
89
+ return null;
90
+ }
91
+ function isDefaultRemoteDisabled() {
92
+ const v = (process.env.IMHUB_VIEWER_NO_DEFAULT_REMOTE || '').toLowerCase();
93
+ return v === '1' || v === 'true' || v === 'yes';
94
+ }
51
95
  /**
52
96
  * Resolve the effective public base URL. Order of preference:
53
97
  * 1. Explicit IMHUB_VIEWER_PUBLIC_BASE_URL (operator-managed reverse proxy)
@@ -1 +1 @@
1
- {"version":3,"file":"viewer-config.js","sourceRoot":"","sources":["../../src/core/viewer-config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"viewer-config.js","sourceRoot":"","sources":["../../src/core/viewer-config.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"viewer-remote.d.ts","sourceRoot":"","sources":["../../src/core/viewer-remote.ts"],"names":[],"mappings":"AA6CA,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,yEAAyE;IACzE,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,eAAe,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAoElF"}
1
+ {"version":3,"file":"viewer-remote.d.ts","sourceRoot":"","sources":["../../src/core/viewer-remote.ts"],"names":[],"mappings":"AA6CA,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,yEAAyE;IACzE,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,eAAe,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAqElF"}
@@ -35,7 +35,7 @@
35
35
  //
36
36
  // Anything else → return null; the sink degrades to inline summary.
37
37
  import { logger as rootLogger } from './logger.js';
38
- import { getViewerConfig } from './viewer-config.js';
38
+ import { getViewerConfig, getEffectiveRemotePasteUrl } from './viewer-config.js';
39
39
  const log = rootLogger.child({ component: 'viewer-remote' });
40
40
  const POST_TIMEOUT_MS = 10_000;
41
41
  const MAX_UPLOAD_BYTES = 1_000_000; // 1 MB. Bigger than this, degrade.
@@ -54,7 +54,8 @@ const MAX_UPLOAD_BYTES = 1_000_000; // 1 MB. Bigger than this, degrade.
54
54
  */
55
55
  export async function postPasteRemote(opts) {
56
56
  const cfg = getViewerConfig();
57
- if (!cfg.remotePasteUrl)
57
+ const endpoint = getEffectiveRemotePasteUrl(cfg);
58
+ if (!endpoint)
58
59
  return null;
59
60
  const bytes = Buffer.byteLength(opts.content, 'utf-8');
60
61
  if (bytes > MAX_UPLOAD_BYTES) {
@@ -69,7 +70,7 @@ export async function postPasteRemote(opts) {
69
70
  const timer = setTimeout(() => ac.abort(), POST_TIMEOUT_MS);
70
71
  let res;
71
72
  try {
72
- res = await fetch(cfg.remotePasteUrl, {
73
+ res = await fetch(endpoint, {
73
74
  method: 'POST',
74
75
  headers: {
75
76
  'Content-Type': 'application/json',
@@ -1 +1 @@
1
- {"version":3,"file":"viewer-remote.js","sourceRoot":"","sources":["../../src/core/viewer-remote.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"viewer-remote.js","sourceRoot":"","sources":["../../src/core/viewer-remote.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,7 @@
1
- import{x as p,aa as f,q as o,ac as g,Q as t,r as m,c as j}from"./index-B48azMO-.js";import{e as N}from"./react-C9F3QeMB.js";import{D as y}from"./data-table-B_BxQrSj.js";import{E as b}from"./empty-state-BKs1qKHx.js";import{S as w}from"./status-badge-_3Ve0Jef.js";import{u as x}from"./useQuery-BjFqOBV3.js";import{u as v}from"./use-event-stream-BGeFcayX.js";import{L as A}from"./loader-circle-DBf4xFjo.js";import{R as S}from"./refresh-ccw-Clj5sQNF.js";import"./table-CZwKizat.js";/**
1
+ import{x as p,aa as f,q as o,ac as g,Q as t,r as m,c as j}from"./index-CITyis5g.js";import{e as N}from"./react-C9F3QeMB.js";import{D as y}from"./data-table-BKTemkw9.js";import{E as b}from"./empty-state-C87S9Wor.js";import{S as w}from"./status-badge-HSHkhdur.js";import{u as x}from"./useQuery-DFryK9Pn.js";import{u as v}from"./use-event-stream-BGeFcayX.js";import{L as A}from"./loader-circle-BFp6Oc8_.js";import{R as S}from"./refresh-ccw-CPSYEbgh.js";import"./table-BBISYTH-.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 z(){const{t:e}=g(["tasks","common"]),s=E(),n=q(),r=T({limit:50}),u=r.data?.rows??[],c=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")})]}),c&&t.jsxs("div",{className:"grid grid-cols-3 gap-2",children:[t.jsx(i,{label:e("a2a.stats.total"),value:c.total,tone:"info"}),t.jsx(i,{label:e("a2a.stats.recent24h"),value:c.recent24h,tone:"success"}),t.jsx(i,{label:e("a2a.stats.maxDepth"),value:c.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 i({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{z as default};
7
- //# sourceMappingURL=a2a-Dvz7ig4m.js.map
7
+ //# sourceMappingURL=a2a-Bg_mT0z1.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"a2a-Dvz7ig4m.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
+ {"version":3,"file":"a2a-Bg_mT0z1.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{x as t}from"./index-B48azMO-.js";/**
1
+ import{x as t}from"./index-CITyis5g.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-BJqk7b-v.js.map
7
+ //# sourceMappingURL=activity-U9AaNlDt.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"activity-BJqk7b-v.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
+ {"version":3,"file":"activity-U9AaNlDt.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{x as A,ac as S,Q as s,c as d,B as c,L as N,I as y,a2 as n,z as w}from"./index-B48azMO-.js";import{e as x}from"./react-C9F3QeMB.js";import{C as L}from"./confirm-dialog-BEzhDlk7.js";import{E as P}from"./empty-state-BKs1qKHx.js";import{T as z,d as E,e as C,c as h,a as B,b as u}from"./table-CZwKizat.js";import{a as F,u as D,e as H}from"./use-settings-DgU8YmGj.js";import{L as T}from"./loader-circle-DBf4xFjo.js";import{R as U}from"./refresh-ccw-Clj5sQNF.js";import{T as _}from"./trash-2-BkZrVFdH.js";import"./dialog-BAZNQtMt.js";import"./x-CHe1y-sG.js";import"./useQuery-BjFqOBV3.js";/**
1
+ import{x as A,ac as S,Q as s,c as d,B as c,L as N,I as y,a2 as n,z as w}from"./index-CITyis5g.js";import{e as x}from"./react-C9F3QeMB.js";import{C as L}from"./confirm-dialog-B53cbWzX.js";import{E as P}from"./empty-state-C87S9Wor.js";import{T as z,d as E,e as C,c as h,a as B,b as u}from"./table-BBISYTH-.js";import{a as F,u as D,e as H}from"./use-settings-Bc4s-JUD.js";import{L as T}from"./loader-circle-BFp6Oc8_.js";import{R as U}from"./refresh-ccw-CPSYEbgh.js";import{T as _}from"./trash-2-D8F96aYm.js";import"./dialog-Cevi7KvQ.js";import"./x-D5196-9X.js";import"./useQuery-DFryK9Pn.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{x as A,ac as S,Q as s,c as d,B as c,L as N,I as y,a2 as n,z 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 Q=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=D(),f=H(),[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(U,{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(z,{children:[s.jsx(E,{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(N,{htmlFor:"admin-platform",className:"text-xs text-text-dim",children:e("admins.add.platform")}),s.jsx(y,{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(N,{htmlFor:"admin-user",className:"text-xs text-text-dim",children:e("admins.add.userId")}),s.jsx(y,{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(Q,{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-DeiNQcMh.js.map
12
+ //# sourceMappingURL=admins-BTC_YEK9.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"admins-DeiNQcMh.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]}
1
+ {"version":3,"file":"admins-BTC_YEK9.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]}
@@ -1,4 +1,4 @@
1
- import{x as G,ac as L,Q as e,c as N,L as O,S as Z,l as X,m as Y,j as J,k as I,B as U,a2 as f,z as F,r as K,I as M}from"./index-B48azMO-.js";import{e as u}from"./react-C9F3QeMB.js";import{E as re}from"./empty-state-BKs1qKHx.js";import{u as oe}from"./use-workspace-Dc6rNi5d.js";import{b as de,m as me,k as xe,c as ue}from"./use-settings-DgU8YmGj.js";import{L as B}from"./loader-circle-DBf4xFjo.js";import{R as pe}from"./refresh-ccw-Clj5sQNF.js";import{X as he}from"./x-CHe1y-sG.js";import{S as ge}from"./save-CAFra1jb.js";import{N as q}from"./network-CEqTiog6.js";import{S as H}from"./search-bDqizeZv.js";import{T as fe}from"./trash-2-BkZrVFdH.js";import"./useQuery-BjFqOBV3.js";/**
1
+ import{x as G,ac as L,Q as e,c as N,L as O,S as Z,l as X,m as Y,j as J,k as I,B as U,a2 as f,z as F,r as K,I as M}from"./index-CITyis5g.js";import{e as u}from"./react-C9F3QeMB.js";import{E as re}from"./empty-state-C87S9Wor.js";import{u as oe}from"./use-workspace-JalfqH6H.js";import{b as de,m as me,k as xe,c as ue}from"./use-settings-Bc4s-JUD.js";import{L as B}from"./loader-circle-BFp6Oc8_.js";import{R as pe}from"./refresh-ccw-CPSYEbgh.js";import{X as he}from"./x-D5196-9X.js";import{S as ge}from"./save-tS3IBPf3.js";import{N as q}from"./network-CrMEVz4-.js";import{S as H}from"./search-BPvPCccn.js";import{T as fe}from"./trash-2-D8F96aYm.js";import"./useQuery-DFryK9Pn.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{x as G,ac as L,Q as e,c as N,L as O,S as Z,l as X,m as Y,j as J,k as I,B
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 be=G("Plus",[["path",{d:"M5 12h14",key:"1ays0h"}],["path",{d:"M12 5v14",key:"s699le"}]]),W={"claude-code":{aliases:["cc","claude"],pkg:"@anthropic-ai/claude-code"},codex:{aliases:["cx"],pkg:"@openai/codex"},opencode:{aliases:["oc"],pkg:"opencode-ai"}},Q=Object.keys(W);function Ue(){const{t}=L(["settings","common"]),r=de(),s=oe(),i=me(),n=r.data,o=s.data??{},[d,m]=u.useState(null),[p,g]=u.useState(null),[S,j]=u.useState(null);u.useEffect(()=>{n&&d==null&&m(n.agents??[]),n&&p==null&&g(n.defaultAgent??""),n&&S==null&&j(n.acpAgents??[])},[n,d,p,S]);const h=d??n?.agents??[],b=p??n?.defaultAgent??"",k=S??n?.acpAgents??[],$=u.useMemo(()=>{if(!n)return!1;const c=h.length===(n.agents?.length??0)&&h.every(w=>n.agents?.includes(w)),v=b===(n.defaultAgent??""),y=we(k,n.acpAgents??[]);return!c||!v||!y},[n,h,b,k]),T=u.useMemo(()=>Q.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 z(){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 D(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(B,{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:Q.map(c=>{const v=W[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:P=>_(c,P)},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(Z,{value:b||"__none__",onValueChange:c=>g(c==="__none__"?"":c),disabled:T.length===0,children:[e.jsx(X,{id:"default-agent",className:"mt-2 w-64",children:e.jsx(Y,{placeholder:t("agents.noEligible")})}),e.jsx(J,{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:D}):null,$&&e.jsxs("div",{className:"sticky bottom-0 flex items-center gap-2 rounded-md border border-border bg-surface px-4 py-2 shadow-md",children:[e.jsx(U,{variant:"info",children:t("agents.dirtyHint")}),e.jsxs(N,{variant:"secondary",size:"sm",onClick:C,disabled:i.isPending,children:[e.jsx(he,{className:"h-4 w-4"}),t("agents.discard")]}),e.jsxs(N,{size:"sm",onClick:()=>void z(),disabled:i.isPending,children:[i.isPending?e.jsx(B,{className:"h-4 w-4 animate-spin"}):e.jsx(ge,{className:"h-4 w-4"}),i.isPending?t("agents.saving"):t("agents.saveBtn")]})]})]})]})}function Ne({name:t,aliases:r,pkg:s,installed:i,enabled:n,onToggle:o}){const{t:d}=L("settings");return e.jsxs("div",{className:"flex items-start gap-3 px-3 py-3",children:[e.jsx("div",{className:"flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-surface-2 text-text-dim",children:e.jsx(je,{className:"h-4 w-4"})}),e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsx("span",{className:"font-medium text-text",children:t}),e.jsxs(U,{variant:i?"success":"outline",className:"text-[10px]",children:[e.jsx("span",{className:K("inline-block h-1.5 w-1.5 rounded-full",i?"bg-success":"bg-text-muted")}),d(i?"agents.online":"agents.offline")]})]}),e.jsxs("p",{className:"mt-0.5 text-xs text-text-dim",children:[e.jsxs("span",{className:"text-text-muted",children:[d("agents.aliasesLabel"),": "]}),e.jsx("span",{className:"font-mono",children:r.map(m=>`/${m}`).join(", ")})]}),!i&&e.jsx("p",{className:"mt-1 text-xs text-warning",children:d("agents.installHint",{pkg:s})})]}),e.jsx("input",{type:"checkbox",checked:n,onChange:m=>o(m.target.checked),className:"h-4 w-4 mt-2 accent-accent cursor-pointer"})]})}const ve=["none","apikey","bearer"],ye=/^[a-zA-Z0-9][a-zA-Z0-9._-]*$/;function we(t,r){if(t.length!==r.length)return!1;for(let s=0;s<t.length;s++){const i=t[s],n=r[s];if(i.name!==n.name||i.endpoint!==n.endpoint||(i.enabled??!0)!==(n.enabled??!0))return!1;const o=(i.aliases??[]).join(","),d=(n.aliases??[]).join(",");if(o!==d)return!1;const m=i.auth?.type??"none",p=n.auth?.type??"none";if(m!==p||(i.auth?.token??"")!==(n.auth?.token??""))return!1}return!0}function ke({agents:t,onChange:r}){const{t:s}=L(["settings","common"]),i=xe(),n=ue(),[o,d]=u.useState(""),[m,p]=u.useState(""),[g,S]=u.useState(""),[j,h]=u.useState("none"),[b,k]=u.useState(""),[$,T]=u.useState(!1),[_,z]=u.useState(""),C=o.trim(),D=C.length>0&&ye.test(C),c=t.some(a=>a.name===C),y=!(j!=="none")||b.trim().length>0,w=D&&g.trim().length>0&&y&&!c,P=g.trim().length>0&&y;function ee(){d(""),p(""),S(""),h("none"),k("")}function se(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 te(){if(!w)return;const a={name:C,endpoint:g.trim(),aliases:se(m),auth:V(j,b),enabled:!0};r([...t,a]),ee(),f.success(s("agents.acp.toast.staged"))}async function ae(){if(P)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 ne(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 ce(a,l){const x=t.map((E,A)=>A===a?{...E,enabled:l}:E);r(x)}function ie(a){r(t.filter((l,x)=>x!==a))}async function le(){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})),z(""),T(!1)}catch(l){f.error(F(l,s).message)}}return e.jsxs("section",{className:"rounded-md border border-border bg-surface",children:[e.jsxs("header",{className:"flex items-center gap-2 border-b border-border px-4 py-3",children:[e.jsx(q,{className:"h-4 w-4 text-text-dim"}),e.jsx("h2",{className:"text-sm font-semibold",children:s("agents.acp.title")}),e.jsx(U,{variant:"outline",className:"text-[10px]",children:t.length}),e.jsxs(N,{variant:"ghost",size:"sm",className:"ml-auto",onClick:()=>T(a=>!a),children:[e.jsx(H,{className:"h-4 w-4"}),e.jsx("span",{className:"hidden sm:inline",children:s("agents.acp.discoverBtn")})]})]}),e.jsx("p",{className:"px-4 pt-2 text-xs text-text-dim",children:s("agents.acp.subtitle")}),$&&e.jsxs("div",{className:"border-t border-border bg-surface-2 px-4 py-3",children:[e.jsx(O,{htmlFor:"acp-baseurl",className:"text-xs font-medium",children:s("agents.acp.baseUrl")}),e.jsx("p",{className:"mt-1 text-[11px] text-text-dim",children:s("agents.acp.baseUrlHint")}),e.jsxs("div",{className:"mt-2 flex flex-wrap gap-2",children:[e.jsx(M,{id:"acp-baseurl",value:_,onChange:a=>z(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 le(),disabled:!_.trim()||n.isPending,children:[n.isPending?e.jsx(B,{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=>ce(l,x),onTest:()=>void ne(l),onRemove:()=>ie(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(R,{label:s("agents.acp.name"),hint:s("agents.acp.nameHint"),children:e.jsx(M,{value:o,onChange:a=>d(a.target.value),placeholder:"my-agent","aria-invalid":o.length>0&&!D})}),e.jsx(R,{label:s("agents.acp.aliases"),hint:s("agents.acp.aliasesHint"),children:e.jsx(M,{value:m,onChange:a=>p(a.target.value),placeholder:"ma, agent1"})}),e.jsx(R,{label:s("agents.acp.endpoint"),hint:s("agents.acp.endpointHint"),children:e.jsx(M,{value:g,onChange:a=>S(a.target.value),placeholder:"https://example.com/agents/weather",className:"font-mono text-xs"})}),e.jsx(R,{label:s("agents.acp.authType"),children:e.jsxs(Z,{value:j,onValueChange:a=>h(a),children:[e.jsx(X,{children:e.jsx(Y,{})}),e.jsx(J,{children:ve.map(a=>e.jsx(I,{value:a,children:s(`agents.acp.auth.${a}`)},a))})]})}),j!=="none"&&e.jsx(R,{label:s("agents.acp.token"),className:"sm:col-span-2",children:e.jsx(M,{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 ae(),disabled:!P||i.isPending,children:[i.isPending?e.jsx(B,{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 te(),disabled:!w,children:[e.jsx(be,{className:"h-4 w-4"}),s("agents.acp.addBtn")]}),c&&e.jsx("span",{className:"self-center text-xs text-warning",children:s("agents.acp.dupName")})]})]})]})}function Ae({agent:t,onToggle:r,onTest:s,onRemove:i,testing:n}){const{t:o}=L("settings"),d=t.enabled!==!1,m=t.auth?.type??"none";return e.jsxs("li",{className:"flex flex-wrap items-center gap-3 px-4 py-3",children:[e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsx("span",{className:"font-medium text-text",children:t.name}),e.jsx(U,{variant:"outline",className:"text-[10px] uppercase",children:o(`agents.acp.auth.${m}`)}),t.aliases&&t.aliases.length>0&&e.jsx("span",{className:"text-xs text-text-muted font-mono",children:t.aliases.map(p=>`/${p}`).join(", ")})]}),e.jsx("p",{className:"mt-0.5 truncate font-mono text-xs text-text-dim",title:t.endpoint,children:t.endpoint})]}),e.jsxs("label",{className:"flex items-center gap-1.5 text-xs text-text-dim",children:[e.jsx("input",{type:"checkbox",checked:d,onChange:p=>r(p.target.checked),className:"h-4 w-4 accent-accent cursor-pointer"}),o(d?"agents.acp.on":"agents.acp.off")]}),e.jsx(N,{variant:"ghost",size:"sm",onClick:s,disabled:n,"aria-label":o("agents.acp.testBtn"),children:n?e.jsx(B,{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(fe,{className:"h-4 w-4"})})]})}function R({label:t,hint:r,className:s,children:i}){return e.jsxs("div",{className:K("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{Ue as default};
12
- //# sourceMappingURL=agents-DJGdXKLv.js.map
12
+ //# sourceMappingURL=agents-o9odac79.js.map