@auto-ai/agent 2.1.170 → 2.1.174

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 (498) hide show
  1. package/dist/safe-a/404/index.html +1 -1
  2. package/dist/safe-a/404.html +1 -1
  3. package/dist/safe-a/_next/static/chunks/{ab522ef4566e28db.js → 01766c1e2fdff227.js} +1 -1
  4. package/dist/safe-a/_next/static/chunks/{aa34ec2d74f7775c.js → 04c9439163b67552.js} +1 -1
  5. package/dist/safe-a/_next/static/chunks/05e1926dc5c477b7.js +1 -0
  6. package/dist/safe-a/_next/static/chunks/{e7d6284971d07422.js → 06b923aa1177f43f.js} +1 -1
  7. package/dist/safe-a/_next/static/chunks/08ce2af10358a8ab.js +1 -0
  8. package/dist/safe-a/_next/static/chunks/{9924bd3807982f9c.js → 092c97532613af2a.js} +1 -1
  9. package/dist/safe-a/_next/static/chunks/0b639ff4f1971d14.js +1 -0
  10. package/dist/safe-a/_next/static/chunks/{7cd0d9159e722599.js → 0b69dba7f1e63f30.js} +1 -1
  11. package/dist/safe-a/_next/static/chunks/0ce6504fc10ce408.js +1 -0
  12. package/dist/safe-a/_next/static/chunks/{e07906d264057e7b.js → 0e1e7d5f7a375308.js} +1 -1
  13. package/dist/safe-a/_next/static/chunks/{00b0744649a5e608.js → 0e8139882ad093d2.js} +1 -1
  14. package/dist/safe-a/_next/static/chunks/0ea5a62c3f30dc56.js +1 -0
  15. package/dist/safe-a/_next/static/chunks/0f1810e4c6b0dd0c.js +1 -0
  16. package/dist/safe-a/_next/static/chunks/{70b95d96e33a5d63.js → 0fa097a572705cfa.js} +1 -1
  17. package/dist/safe-a/_next/static/chunks/{faf267ae8eaabb78.js → 0fb0d030e8dee231.js} +1 -1
  18. package/dist/safe-a/_next/static/chunks/{ed4322c3137a7cbf.js → 0fd3876e0d9e8acc.js} +1 -1
  19. package/dist/safe-a/_next/static/chunks/{4d30478be74fb192.js → 106955e3cc6a6843.js} +1 -1
  20. package/dist/safe-a/_next/static/chunks/{3f18c3fa64301e74.js → 1078bc1642db53ad.js} +1 -1
  21. package/dist/safe-a/_next/static/chunks/{a0256e00bbdc334c.js → 108a0b77418f1d31.js} +1 -1
  22. package/dist/safe-a/_next/static/chunks/10f9223e5a712af5.css +1 -0
  23. package/dist/safe-a/_next/static/chunks/{967dfe61a543e533.js → 13b54d70a1ee1de7.js} +1 -1
  24. package/dist/safe-a/_next/static/chunks/{54a2df4508a1c311.js → 13f94fc3dda88c90.js} +1 -1
  25. package/dist/safe-a/_next/static/chunks/155374df9f6b4b9a.js +1 -0
  26. package/dist/safe-a/_next/static/chunks/{12932eb7d288b09b.js → 16ea1d3cf6db8a53.js} +1 -1
  27. package/dist/safe-a/_next/static/chunks/{23f50ba74d421ab3.js → 170f7361bd4d33e2.js} +1 -1
  28. package/dist/safe-a/_next/static/chunks/17722e3ac4e00587.js +1 -0
  29. package/dist/safe-a/_next/static/chunks/{c0960892f67b4256.js → 179a5dac78ab2cb9.js} +1 -1
  30. package/dist/safe-a/_next/static/chunks/{966730983f55a7c6.js → 1818d7a661948f6b.js} +1 -1
  31. package/dist/safe-a/_next/static/chunks/18977fe8f51209aa.js +1 -0
  32. package/dist/safe-a/_next/static/chunks/{57e13ec897ff78d6.js → 19584f955475ce91.js} +1 -1
  33. package/dist/safe-a/_next/static/chunks/1974f51c298bce94.js +1 -0
  34. package/dist/safe-a/_next/static/chunks/{948dc342d4746ffc.js → 19c1491e85e22b3b.js} +1 -1
  35. package/dist/safe-a/_next/static/chunks/{a8696c4a576878ae.js → 19ca17e5015c42a3.js} +1 -1
  36. package/dist/safe-a/_next/static/chunks/{03039556684e9812.js → 1a4b553856a8ffdf.js} +1 -1
  37. package/dist/safe-a/_next/static/chunks/1acf2d9664500f51.js +1 -0
  38. package/dist/safe-a/_next/static/chunks/{93588b2335ca95de.js → 1b55c29b8cad4a50.js} +1 -1
  39. package/dist/safe-a/_next/static/chunks/{878dd96f8fcd6bd4.js → 1bb28f71c19fa824.js} +1 -1
  40. package/dist/safe-a/_next/static/chunks/1bfa645704d9149a.js +1 -0
  41. package/dist/safe-a/_next/static/chunks/1c9321874fea5f0d.js +1 -0
  42. package/dist/safe-a/_next/static/chunks/{8b1990cf2eb41663.js → 1d3e7886be9f671c.js} +1 -1
  43. package/dist/safe-a/_next/static/chunks/{d2bba4dbd6e24f7e.js → 1e17456ccebc9cd2.js} +1 -1
  44. package/dist/safe-a/_next/static/chunks/{2bd512c6acf9ee9b.js → 1e43922998a0ed2f.js} +1 -1
  45. package/dist/safe-a/_next/static/chunks/1f3da8a76b11d2aa.js +1 -0
  46. package/dist/safe-a/_next/static/chunks/{d653880800910810.js → 1fec17d16aff9eed.js} +1 -1
  47. package/dist/safe-a/_next/static/chunks/{a39dba23f5098cde.js → 2046937bffedf074.js} +1 -1
  48. package/dist/safe-a/_next/static/chunks/219a3413675ba6f1.js +1 -0
  49. package/dist/safe-a/_next/static/chunks/{8cee526b3846c40b.js → 2326118ef1328bc5.js} +1 -1
  50. package/dist/safe-a/_next/static/chunks/236775e4ec4f8a94.js +1 -0
  51. package/dist/safe-a/_next/static/chunks/{afab34a5bb437673.js → 242529c986baeb00.js} +1 -1
  52. package/dist/safe-a/_next/static/chunks/26aeb1c7cdca0bc7.js +1 -0
  53. package/dist/safe-a/_next/static/chunks/{0835edf516aebfa0.js → 270d7571d2eea071.js} +1 -1
  54. package/dist/safe-a/_next/static/chunks/{591fe54d06e0a33e.js → 27c407347ce26b78.js} +1 -1
  55. package/dist/safe-a/_next/static/chunks/{03af20498d43b518.js → 27ff2e69b2fd19e5.js} +1 -1
  56. package/dist/safe-a/_next/static/chunks/29676075a0390867.js +1 -0
  57. package/dist/safe-a/_next/static/chunks/{2be2d49054d4606c.js → 2c6d585a97629311.js} +1 -1
  58. package/dist/safe-a/_next/static/chunks/2df3e464b6247e75.js +1 -0
  59. package/dist/safe-a/_next/static/chunks/2e574acbf68e77ff.js +1 -0
  60. package/dist/safe-a/_next/static/chunks/{c537d051140acc61.js → 2ec6d7ddb4c04987.js} +1 -1
  61. package/dist/safe-a/_next/static/chunks/{dee1daaeed29e5a2.js → 2f7d30e66e995b02.js} +1 -1
  62. package/dist/safe-a/_next/static/chunks/{66247e9b3cf471f5.js → 2fab2306850ac97b.js} +1 -1
  63. package/dist/safe-a/_next/static/chunks/{9721e6d173bcda17.js → 2fcc6298b6dd7a82.js} +1 -1
  64. package/dist/safe-a/_next/static/chunks/{ccbe0fe39b523768.js → 303d9c2a2c956f25.js} +1 -1
  65. package/dist/safe-a/_next/static/chunks/3051ec76bf1f7867.js +1 -0
  66. package/dist/safe-a/_next/static/chunks/32a7ca0a75a897da.js +1 -0
  67. package/dist/safe-a/_next/static/chunks/{06e2cd3fae94aae8.js → 32b4d63e10d31351.js} +1 -1
  68. package/dist/safe-a/_next/static/chunks/32b9bdd82a961878.js +1 -0
  69. package/dist/safe-a/_next/static/chunks/3509a66e019ceae3.js +1 -0
  70. package/dist/safe-a/_next/static/chunks/{ae7e9c73a1d653fd.js → 3520f1af0a1b7f66.js} +1 -1
  71. package/dist/safe-a/_next/static/chunks/{7b6898a7f9df6495.js → 354aaa2e36b75b81.js} +1 -1
  72. package/dist/safe-a/_next/static/chunks/{e4776ea06fa1720a.js → 3590c4a4f40cdb5d.js} +1 -1
  73. package/dist/safe-a/_next/static/chunks/{2ccdfcf9ecfa2ea8.js → 35f1637c2feb232d.js} +1 -1
  74. package/dist/safe-a/_next/static/chunks/{94d40dcd515ca4ad.js → 37bbbf907196a5bf.js} +1 -1
  75. package/dist/safe-a/_next/static/chunks/{7ed753f2db91bc38.js → 37cfaa4963ac51f3.js} +1 -1
  76. package/dist/safe-a/_next/static/chunks/{29a317486c4ab7d7.js → 3934bd57f459566e.js} +1 -1
  77. package/dist/safe-a/_next/static/chunks/{a3af4dcdb725b47f.js → 3a947667fddbdd53.js} +1 -1
  78. package/dist/safe-a/_next/static/chunks/3aac5736e5781b46.js +1 -0
  79. package/dist/safe-a/_next/static/chunks/{f7d33f46dfbddf65.js → 3ae23df392f9bed8.js} +1 -1
  80. package/dist/safe-a/_next/static/chunks/{65ee07c4b6209141.js → 3ae4e2529aa621fb.js} +1 -1
  81. package/dist/safe-a/_next/static/chunks/{30f37e8e02339538.js → 3b2bb9f17546ee3e.js} +1 -1
  82. package/dist/safe-a/_next/static/chunks/{02339beb679bec8d.js → 3bcd531d40d6c019.js} +1 -1
  83. package/dist/safe-a/_next/static/chunks/3c695d1c2efbc749.js +1 -0
  84. package/dist/safe-a/_next/static/chunks/3d8e9a96a69193d4.js +1 -0
  85. package/dist/safe-a/_next/static/chunks/3dcb1dcf23e7ab9c.js +1 -0
  86. package/dist/safe-a/_next/static/chunks/3e2ea3a7fe64826d.js +1 -0
  87. package/dist/safe-a/_next/static/chunks/{472047ea96adfca5.js → 3e9c98df7d56e9b2.js} +1 -1
  88. package/dist/safe-a/_next/static/chunks/{3da255bcf22e013d.js → 3ec05a61e93547d3.js} +1 -1
  89. package/dist/safe-a/_next/static/chunks/{d0d8ac4e89477172.js → 3f6fe8a1903009ea.js} +1 -1
  90. package/dist/safe-a/_next/static/chunks/3fb4674edcb2d726.js +1 -0
  91. package/dist/safe-a/_next/static/chunks/{c013a3a3b1574b7d.js → 3fd03b9ed21b30fc.js} +1 -1
  92. package/dist/safe-a/_next/static/chunks/40268f8e3ff0314e.js +1 -0
  93. package/dist/safe-a/_next/static/chunks/{dabd2cc5e900d556.js → 40cc0252b2f1d855.js} +1 -1
  94. package/dist/safe-a/_next/static/chunks/{19a47cfc8ca4c0a7.js → 413a7be096275d7f.js} +1 -1
  95. package/dist/safe-a/_next/static/chunks/{435e18828af1d066.js → 459d401d9f9e5b9f.js} +1 -1
  96. package/dist/safe-a/_next/static/chunks/45ab9a1f693d609c.js +1 -0
  97. package/dist/safe-a/_next/static/chunks/{9db0d8129d6b7b5e.js → 481a2858f7df907d.js} +1 -1
  98. package/dist/safe-a/_next/static/chunks/{de208f3610c12b2c.js → 49df9708d6328c4a.js} +1 -1
  99. package/dist/safe-a/_next/static/chunks/4a33b6b9bc52fb1a.js +1 -0
  100. package/dist/safe-a/_next/static/chunks/{ad22e1613386ba8d.js → 4a340ea4ac145216.js} +1 -1
  101. package/dist/safe-a/_next/static/chunks/4be779bcbd94352d.js +1 -0
  102. package/dist/safe-a/_next/static/chunks/4c33a1cc6db74105.js +1 -0
  103. package/dist/safe-a/_next/static/chunks/4d129d4e15c8c424.js +1 -0
  104. package/dist/safe-a/_next/static/chunks/{c84ea2dc8d3281e6.js → 4df298f5b420f474.js} +1 -1
  105. package/dist/safe-a/_next/static/chunks/{dfe4d8ffc37b96da.js → 4dfbfdff43b8479b.js} +1 -1
  106. package/dist/safe-a/_next/static/chunks/5069ee4aa806b0ea.js +1 -0
  107. package/dist/safe-a/_next/static/chunks/519049cd74a40910.js +1 -0
  108. package/dist/safe-a/_next/static/chunks/522518d740397639.js +1 -0
  109. package/dist/safe-a/_next/static/chunks/52e2164e45febae6.js +1 -0
  110. package/dist/safe-a/_next/static/chunks/{f8757d2c1a969081.js → 534b5acf573aa491.js} +1 -1
  111. package/dist/safe-a/_next/static/chunks/538cc02e54714b23.js +1 -0
  112. package/dist/safe-a/_next/static/chunks/53a59aecd3e0dfb5.js +1 -0
  113. package/dist/safe-a/_next/static/chunks/{97d506a00590396c.js → 53be52c43a14557c.js} +1 -1
  114. package/dist/safe-a/_next/static/chunks/54c43751bf4c4da2.js +1 -0
  115. package/dist/safe-a/_next/static/chunks/{0c19efa935cdd816.js → 55087cc98e6237f1.js} +1 -1
  116. package/dist/safe-a/_next/static/chunks/{5c2a7e118fa66960.js → 55f8de91b4803778.js} +1 -1
  117. package/dist/safe-a/_next/static/chunks/{569dda34679bca70.js → 560ca23f77c0e819.js} +1 -1
  118. package/dist/safe-a/_next/static/chunks/{6e145bea7acc82b4.js → 57bb853857f3de83.js} +1 -1
  119. package/dist/safe-a/_next/static/chunks/{65963496d7fa49bc.js → 588e6975a7bd6671.js} +1 -1
  120. package/dist/safe-a/_next/static/chunks/{648649ebbc7565b9.js → 5a0b630678282d4f.js} +1 -1
  121. package/dist/safe-a/_next/static/chunks/{1f90e84b5a4dad81.js → 5a3e355216280144.js} +1 -1
  122. package/dist/safe-a/_next/static/chunks/{63f33483697b26ca.js → 5a4c198fd41e8ec4.js} +1 -1
  123. package/dist/safe-a/_next/static/chunks/5b916c9dc09e323c.js +1 -0
  124. package/dist/safe-a/_next/static/chunks/5bad5163b6e015f5.js +1 -0
  125. package/dist/safe-a/_next/static/chunks/5ccd5a6ac9c2f980.js +1 -0
  126. package/dist/safe-a/_next/static/chunks/{eb248f97f593a288.js → 5d5333084191fb10.js} +1 -1
  127. package/dist/safe-a/_next/static/chunks/5d79b7f202080232.js +1 -0
  128. package/dist/safe-a/_next/static/chunks/{a367a4ab4b91ce6b.js → 5ea79c109cbe8a86.js} +1 -1
  129. package/dist/safe-a/_next/static/chunks/{daaffc256846db90.js → 5ee72092303043ef.js} +1 -1
  130. package/dist/safe-a/_next/static/chunks/5ef8399eb6496949.js +1 -0
  131. package/dist/safe-a/_next/static/chunks/{9583c5cc3861200c.js → 5fc8a5235ddfa787.js} +1 -1
  132. package/dist/safe-a/_next/static/chunks/61b3d4c00499dd14.js +1 -0
  133. package/dist/safe-a/_next/static/chunks/{8c97e3b556b32001.js → 61ce261738313b8a.js} +1 -1
  134. package/dist/safe-a/_next/static/chunks/{503bbec2e3179a3c.js → 62d925bcc8518b6f.js} +1 -1
  135. package/dist/safe-a/_next/static/chunks/63ec034afca4b5d6.js +1 -0
  136. package/dist/safe-a/_next/static/chunks/{547eb82208058c71.js → 644aa76620718c98.js} +1 -1
  137. package/dist/safe-a/_next/static/chunks/{6d0bf0ac1fdb7eab.js → 648b653b36802fdc.js} +1 -1
  138. package/dist/safe-a/_next/static/chunks/{1d737ed6e08d2466.js → 6522643341a0921c.js} +1 -1
  139. package/dist/safe-a/_next/static/chunks/{829196dbf7eddb51.js → 65fb49c8a7f59842.js} +1 -1
  140. package/dist/safe-a/_next/static/chunks/{e878ffaf394e2c30.js → 65fe0975412ff703.js} +1 -1
  141. package/dist/safe-a/_next/static/chunks/{03c48f22d87b83a9.js → 66b30159915524db.js} +1 -1
  142. package/dist/safe-a/_next/static/chunks/{cf99b249b986e2bd.js → 66ed07a735eac6e3.js} +1 -1
  143. package/dist/safe-a/_next/static/chunks/6785757cc05fec19.js +1 -0
  144. package/dist/safe-a/_next/static/chunks/{8aafb8ec5208a445.js → 67c9db5577080125.js} +1 -1
  145. package/dist/safe-a/_next/static/chunks/{ada2807c297fe674.js → 68bd2bd64624e20d.js} +1 -1
  146. package/dist/safe-a/_next/static/chunks/{774e554c11c8759a.js → 692e7ee14236fefb.js} +1 -1
  147. package/dist/safe-a/_next/static/chunks/{dcdc329f64f1a7a8.js → 69cfdbc51cf2d3c3.js} +1 -1
  148. package/dist/safe-a/_next/static/chunks/{1aaf9fb00fb53ef9.js → 6ae709c575c74979.js} +1 -1
  149. package/dist/safe-a/_next/static/chunks/{dfbd9d8a4137edd6.js → 6b652524b5ffdd9e.js} +1 -1
  150. package/dist/safe-a/_next/static/chunks/{645741ee91707763.js → 6b7c3c962a14dc29.js} +1 -1
  151. package/dist/safe-a/_next/static/chunks/{ec24f7a0593636d9.js → 6bc7c57f119ad4f6.js} +1 -1
  152. package/dist/safe-a/_next/static/chunks/{2c0b2fd9fb2fea66.js → 6c3b2d0be1c633b6.js} +1 -1
  153. package/dist/safe-a/_next/static/chunks/{29cf9e89be8a7f75.js → 6cc2f7f962cdd082.js} +1 -1
  154. package/dist/safe-a/_next/static/chunks/{3e45de4a81d1f7a6.js → 6d4209e94b1aafe6.js} +1 -1
  155. package/dist/safe-a/_next/static/chunks/6ddf95b168bfbc36.js +1 -0
  156. package/dist/safe-a/_next/static/chunks/6e61f670898cb297.css +1 -0
  157. package/dist/safe-a/_next/static/chunks/{c43f94053172eb84.js → 6f3afa83656eab67.js} +1 -1
  158. package/dist/safe-a/_next/static/chunks/6f4460bd0b8a57af.js +1 -0
  159. package/dist/safe-a/_next/static/chunks/{ec048ffab26ebcd6.js → 6fe835d41fdbd638.js} +1 -1
  160. package/dist/safe-a/_next/static/chunks/{6349c7cf3b394b81.js → 70459a2a4c45653e.js} +1 -1
  161. package/dist/safe-a/_next/static/chunks/{c5fd875d1d9fd6c4.js → 7137c7537c459c31.js} +1 -1
  162. package/dist/safe-a/_next/static/chunks/{740732a162598c49.js → 715c085d7c10eeda.js} +1 -1
  163. package/dist/safe-a/_next/static/chunks/71d3a80bc9d53b07.js +1 -0
  164. package/dist/safe-a/_next/static/chunks/{5c076874caf0532e.js → 71e3a90489469c28.js} +1 -1
  165. package/dist/safe-a/_next/static/chunks/{d0d06ea64246c2e0.js → 72a56bd75075fd83.js} +1 -1
  166. package/dist/safe-a/_next/static/chunks/{957b35b92a00be9d.js → 72ef1696f44fcf61.js} +1 -1
  167. package/dist/safe-a/_next/static/chunks/{5076e29ddf662e81.js → 736441266ceb14e2.js} +1 -1
  168. package/dist/safe-a/_next/static/chunks/{0f93a62e5e2db48b.js → 73cbf0064096e28c.js} +1 -1
  169. package/dist/safe-a/_next/static/chunks/{ae1404fdd6ec935a.js → 751de74a23cc9036.js} +1 -1
  170. package/dist/safe-a/_next/static/chunks/{e632e1b120215697.js → 756b6c2e620386ff.js} +1 -1
  171. package/dist/safe-a/_next/static/chunks/{5ca0c9bb26daf732.js → 75a396e1752cd59d.js} +1 -1
  172. package/dist/safe-a/_next/static/chunks/764c541428e1c6eb.js +1 -0
  173. package/dist/safe-a/_next/static/chunks/{e7f1683dcd85bf06.js → 79128afded6e01d9.js} +1 -1
  174. package/dist/safe-a/_next/static/chunks/7988d5ea63356e10.js +1 -0
  175. package/dist/safe-a/_next/static/chunks/{cd733da27bed8af2.js → 7aa69fd5d97b7146.js} +1 -1
  176. package/dist/safe-a/_next/static/chunks/7b9c09d0ce43f1c2.js +1 -0
  177. package/dist/safe-a/_next/static/chunks/{fa361913d47fdc14.css → 7bdf0e5b41aeb209.css} +0 -3
  178. package/dist/safe-a/_next/static/chunks/{9ae8f05f80dedfa4.js → 7d3bf918bccde738.js} +1 -1
  179. package/dist/safe-a/_next/static/chunks/7dbb8abebf50d816.js +1 -0
  180. package/dist/safe-a/_next/static/chunks/7ef348801eff6590.js +1 -0
  181. package/dist/safe-a/_next/static/chunks/{2f35f32799fb08ac.js → 7f6e82ac63db5eff.js} +1 -1
  182. package/dist/safe-a/_next/static/chunks/{738c808ddc82ea44.js → 7fd45fb9cf0995f3.js} +1 -1
  183. package/dist/safe-a/_next/static/chunks/8085c74f26fa2c4e.js +1 -0
  184. package/dist/safe-a/_next/static/chunks/{a12eeb7c77a7506f.js → 84185f4bb07ccbd7.js} +1 -1
  185. package/dist/safe-a/_next/static/chunks/85fc05549f7f100c.js +1 -0
  186. package/dist/safe-a/_next/static/chunks/{35db6eb7eec8b825.js → 87e12ecbe9521f9b.js} +1 -1
  187. package/dist/safe-a/_next/static/chunks/{86c0a63bf95598a3.js → 88a999988f915988.js} +1 -1
  188. package/dist/safe-a/_next/static/chunks/88bc97899d2ce4e5.js +1 -0
  189. package/dist/safe-a/_next/static/chunks/{8e33e395e6224908.js → 8bdc142fad5847ed.js} +1 -1
  190. package/dist/safe-a/_next/static/chunks/8cccc3fe71fa849b.js +1 -0
  191. package/dist/safe-a/_next/static/chunks/{6818b9385873d081.js → 8deb0392842e5a01.js} +1 -1
  192. package/dist/safe-a/_next/static/chunks/{99ce8e2a747001a9.js → 8f038ff914c4b0df.js} +1 -1
  193. package/dist/safe-a/_next/static/chunks/{a78da44a16cc3db3.js → 8f5be275907dd98c.js} +1 -1
  194. package/dist/safe-a/_next/static/chunks/{0518cc63903bebac.js → 9037530b0f1d5783.js} +1 -1
  195. package/dist/safe-a/_next/static/chunks/{b4db35dceb9577e1.js → 9078ad91aa20dca0.js} +1 -1
  196. package/dist/safe-a/_next/static/chunks/92c3617a4e22a464.js +1 -0
  197. package/dist/safe-a/_next/static/chunks/{eb34cdf40f4c4d62.js → 932d3fcc2596e8d5.js} +1 -1
  198. package/dist/safe-a/_next/static/chunks/937e26e6e01d9ec9.js +1 -0
  199. package/dist/safe-a/_next/static/chunks/93bfaf233e66b48c.js +1 -0
  200. package/dist/safe-a/_next/static/chunks/{3422b2c2f9bdf0e0.js → 94029062f236cadc.js} +1 -1
  201. package/dist/safe-a/_next/static/chunks/94e88cfda11697d2.js +1 -0
  202. package/dist/safe-a/_next/static/chunks/{55e32e78e4db3889.js → 95c4d26e469d1d8f.js} +1 -1
  203. package/dist/safe-a/_next/static/chunks/{b717d3610f87602f.js → 96026b5eb5d2566b.js} +1 -1
  204. package/dist/safe-a/_next/static/chunks/{ede1765e6899133a.js → 962a27e9c634b823.js} +1 -1
  205. package/dist/safe-a/_next/static/chunks/{093669121f3b7aa1.js → 966fb5830ce1029c.js} +1 -1
  206. package/dist/safe-a/_next/static/chunks/{aa8c7d3d99a14fdb.js → 9724567275720686.js} +1 -1
  207. package/dist/safe-a/_next/static/chunks/{aff6654f4fbc26b0.js → 98e243fb5992a71c.js} +1 -1
  208. package/dist/safe-a/_next/static/chunks/98fff38c6425a797.css +7 -0
  209. package/dist/safe-a/_next/static/chunks/{fddfcced721d9669.js → 9a7b2a483b109c0a.js} +1 -1
  210. package/dist/safe-a/_next/static/chunks/9b3df6b20a9625d5.js +1 -0
  211. package/dist/safe-a/_next/static/chunks/9c6c00fa68012026.js +1 -0
  212. package/dist/safe-a/_next/static/chunks/{46568a8bad984d09.js → 9cb28a1dacb7ea6d.js} +1 -1
  213. package/dist/safe-a/_next/static/chunks/9ccf7a8bca1730bf.js +1 -0
  214. package/dist/safe-a/_next/static/chunks/{c2e5be103cef6113.js → 9e96c84b86d1bbf3.js} +1 -1
  215. package/dist/safe-a/_next/static/chunks/{38dcdbfb8c6966a9.js → 9f0ee4783140adf1.js} +1 -1
  216. package/dist/safe-a/_next/static/chunks/9fefea69ec034a63.js +1 -0
  217. package/dist/safe-a/_next/static/chunks/{d9bf3f0f6088ac8c.js → a1b9abf15c0f7655.js} +1 -1
  218. package/dist/safe-a/_next/static/chunks/{65159d9aa3ecc0c9.js → a37aa474433d29e3.js} +1 -1
  219. package/dist/safe-a/_next/static/chunks/a4776dc3e00e5ab0.js +1 -0
  220. package/dist/safe-a/_next/static/chunks/{2331e2a388a9bd50.js → a5df6158856685f1.js} +1 -1
  221. package/dist/safe-a/_next/static/chunks/a6737fc58619eae5.js +1 -0
  222. package/dist/safe-a/_next/static/chunks/{217c50478c5ea4d7.js → a6a98f9278704b6a.js} +1 -1
  223. package/dist/safe-a/_next/static/chunks/{6ecccb36549d3028.js → a7277c96f3669bea.js} +1 -1
  224. package/dist/safe-a/_next/static/chunks/{9b0ac8da8e1c0d7e.js → a9fed5c43d754a96.js} +1 -1
  225. package/dist/safe-a/_next/static/chunks/{6e663a2e3562125c.js → aa0a4c596151b22b.js} +1 -1
  226. package/dist/safe-a/_next/static/chunks/{f7ad257814e6e947.js → aa867a1fa8b105e1.js} +1 -1
  227. package/dist/safe-a/_next/static/chunks/ad4ba491cf12423f.js +5 -0
  228. package/dist/safe-a/_next/static/chunks/{f40b91cb7cc58cf2.js → ad50a7d15cd9d9d8.js} +1 -1
  229. package/dist/safe-a/_next/static/chunks/{0708a65cc3ecf56b.js → af7b0bd1b40ad066.js} +1 -1
  230. package/dist/safe-a/_next/static/chunks/{9e9339584dbc8172.js → b24e3802454a5567.js} +1 -1
  231. package/dist/safe-a/_next/static/chunks/{e1416a0b2152bdbf.js → b29a85c3dae2bb9c.js} +1 -1
  232. package/dist/safe-a/_next/static/chunks/b30f1da4e57f459a.js +1 -0
  233. package/dist/safe-a/_next/static/chunks/{129875fd1b096964.js → b360c9fc22dbf831.js} +1 -1
  234. package/dist/safe-a/_next/static/chunks/{ddc8a591c8943264.js → b3e79c76be269ccc.js} +1 -1
  235. package/dist/safe-a/_next/static/chunks/{82aea21a16d00076.js → b429be4e16fa1e00.js} +1 -1
  236. package/dist/safe-a/_next/static/chunks/{e66819cb4afcfe87.js → b61ec36c9bbca3e0.js} +1 -1
  237. package/dist/safe-a/_next/static/chunks/{405cd8dd7faa6eaf.js → b65565677c3e8c0a.js} +1 -1
  238. package/dist/safe-a/_next/static/chunks/{37f3ea0b3cf40bca.js → b66afb4b0be97af8.js} +1 -1
  239. package/dist/safe-a/_next/static/chunks/{d53ff6336a32e4c5.js → b69f987a60b05db3.js} +1 -1
  240. package/dist/safe-a/_next/static/chunks/{9d65a2db77bf6c63.js → b78822282754a47c.js} +1 -1
  241. package/dist/safe-a/_next/static/chunks/b7f72bcb870dda3b.js +1 -0
  242. package/dist/safe-a/_next/static/chunks/b92c67520afabac2.js +1 -0
  243. package/dist/safe-a/_next/static/chunks/bbcf9daa108b22fb.js +1 -0
  244. package/dist/safe-a/_next/static/chunks/bbf364bb7f0ab6f7.js +1 -0
  245. package/dist/safe-a/_next/static/chunks/{f05af2c706c87fb5.js → bc7bda699a7ccda1.js} +1 -1
  246. package/dist/safe-a/_next/static/chunks/{f0a3b313fc0fcace.js → bd1f33816fa01c16.js} +1 -1
  247. package/dist/safe-a/_next/static/chunks/bd2dcf98c9b362f6.js +1 -0
  248. package/dist/safe-a/_next/static/chunks/{cb8a82631d87b798.js → bd984c5404403e7d.js} +1 -1
  249. package/dist/safe-a/_next/static/chunks/bdd88bcfd223f52a.js +1 -0
  250. package/dist/safe-a/_next/static/chunks/{6fc97877fbcf3403.js → bf2262100cea8c64.js} +1 -1
  251. package/dist/safe-a/_next/static/chunks/bf2c1c402dbcccdf.js +1 -0
  252. package/dist/safe-a/_next/static/chunks/bfc6ee42cec583d5.js +1 -0
  253. package/dist/safe-a/_next/static/chunks/{c5932397b84e3c27.js → c15069059c9d1f53.js} +1 -1
  254. package/dist/safe-a/_next/static/chunks/{9de7a5feb6be8bc3.js → c1615032cbbf5b56.js} +1 -1
  255. package/dist/safe-a/_next/static/chunks/{4c87634b39751c56.js → c2546d2b493dd907.js} +1 -1
  256. package/dist/safe-a/_next/static/chunks/{82cdf7e6dbe7070d.js → c3669d468d3f2b3a.js} +1 -1
  257. package/dist/safe-a/_next/static/chunks/c3b49937059d3d70.js +1 -0
  258. package/dist/safe-a/_next/static/chunks/{5a43f7cd89a42167.js → c5b5aba98d38ef23.js} +1 -1
  259. package/dist/safe-a/_next/static/chunks/c5be27a596acfa18.js +1 -0
  260. package/dist/safe-a/_next/static/chunks/{6e4e92cbcf961542.js → c6cc32860b96278f.js} +1 -1
  261. package/dist/safe-a/_next/static/chunks/{997894582876b3bb.js → c725524ea13a50ab.js} +1 -1
  262. package/dist/safe-a/_next/static/chunks/c8942bee3aebddae.js +1 -0
  263. package/dist/safe-a/_next/static/chunks/{fc3c1b765cc5906d.js → c8e45be36912e439.js} +1 -1
  264. package/dist/safe-a/_next/static/chunks/c933951b3113492f.js +1 -0
  265. package/dist/safe-a/_next/static/chunks/c9813626ba898586.js +1 -0
  266. package/dist/safe-a/_next/static/chunks/ca2725c2b45709c1.js +1 -0
  267. package/dist/safe-a/_next/static/chunks/{47098fcba8e98974.js → caf4049dc563940e.js} +1 -1
  268. package/dist/safe-a/_next/static/chunks/cafadd69e03e6c4b.js +1 -0
  269. package/dist/safe-a/_next/static/chunks/{57bc9169370081d7.js → cba2741f84ef36ed.js} +1 -1
  270. package/dist/safe-a/_next/static/chunks/{47d485f30e419da8.js → cccecf726769787f.js} +1 -1
  271. package/dist/safe-a/_next/static/chunks/{261bf96e2331ea0a.js → cd0e7e3cc303b4e4.js} +1 -1
  272. package/dist/safe-a/_next/static/chunks/cd4556cbed1f8957.js +1 -0
  273. package/dist/safe-a/_next/static/chunks/{da11b1522a2497e3.js → cd5eec7d305aa041.js} +1 -1
  274. package/dist/safe-a/_next/static/chunks/{564507763428bfb0.js → d09636e7bcf60ad1.js} +1 -1
  275. package/dist/safe-a/_next/static/chunks/d2d432a9facf4278.js +1 -0
  276. package/dist/safe-a/_next/static/chunks/{fdf535baa39c0e26.js → d2e37b6d5ff62bcb.js} +1 -1
  277. package/dist/safe-a/_next/static/chunks/{fe840e6cda1c115e.js → d33a24782888b869.js} +1 -1
  278. package/dist/safe-a/_next/static/chunks/{7f611b9b215dfcef.js → d33e49aabd798892.js} +1 -1
  279. package/dist/safe-a/_next/static/chunks/{7d7ef3758ed7347b.js → d3990c1e87ef3e23.js} +1 -1
  280. package/dist/safe-a/_next/static/chunks/d433c87b0bc69cda.js +1 -0
  281. package/dist/safe-a/_next/static/chunks/{9a63abc493c1c840.js → d47cd27ac08f5429.js} +1 -1
  282. package/dist/safe-a/_next/static/chunks/{0e68cace7cf0464c.js → d599ef4d0f84a93d.js} +1 -1
  283. package/dist/safe-a/_next/static/chunks/d5e3d29f769997cc.js +1 -0
  284. package/dist/safe-a/_next/static/chunks/{7e5b28d162f1ea9d.js → d69b21102305d19e.js} +1 -1
  285. package/dist/safe-a/_next/static/chunks/d704441569a382a1.js +1 -0
  286. package/dist/safe-a/_next/static/chunks/{b92da682bccc569b.js → d715e874b8ee8540.js} +1 -1
  287. package/dist/safe-a/_next/static/chunks/{1a91a01fbaf01e7e.js → d729414ff836cd53.js} +1 -1
  288. package/dist/safe-a/_next/static/chunks/{333630802bd6f1a6.js → d82740475fc07e98.js} +1 -1
  289. package/dist/safe-a/_next/static/chunks/{9bedfcbe8f9ff43f.js → d842d30dcb0f50a9.js} +1 -1
  290. package/dist/safe-a/_next/static/chunks/{502779251884e330.js → d8af8dadd0889c71.js} +1 -1
  291. package/dist/safe-a/_next/static/chunks/{50c602f1b79d61a7.js → d9b92ed2d544fca5.js} +1 -1
  292. package/dist/safe-a/_next/static/chunks/{d147ab3cf51edc42.js → da346aeed70dd39a.js} +1 -1
  293. package/dist/safe-a/_next/static/chunks/dbbd673619a7f82f.js +1 -0
  294. package/dist/safe-a/_next/static/chunks/dc0bc471de951daf.js +1 -0
  295. package/dist/safe-a/_next/static/chunks/{9d8fff267f5576eb.js → dc2186b66132ca97.js} +1 -1
  296. package/dist/safe-a/_next/static/chunks/{d3fc1847f85d724b.js → de0ee516f6a1aa07.js} +1 -1
  297. package/dist/safe-a/_next/static/chunks/{473249ae7830085a.js → e04bace22e04d63c.js} +1 -1
  298. package/dist/safe-a/_next/static/chunks/{9b94620a86d2a1c2.js → e0c76ff7114dc8dc.js} +1 -1
  299. package/dist/safe-a/_next/static/chunks/{dc7f280eee64d574.js → e11d4fd8de65621d.js} +1 -1
  300. package/dist/safe-a/_next/static/chunks/{ec7ee73b22712e55.js → e1999bcadd3448e5.js} +1 -1
  301. package/dist/safe-a/_next/static/chunks/{232cc01daaf29e5d.js → e3fe320ec1b8f889.js} +1 -1
  302. package/dist/safe-a/_next/static/chunks/{98eb20270ccd4b41.js → e42498eec0c8d570.js} +1 -1
  303. package/dist/safe-a/_next/static/chunks/{50cbc92b0512838a.js → e4973ad5c183f17a.js} +1 -1
  304. package/dist/safe-a/_next/static/chunks/{c8b301b059ee1946.js → e5275dcacbabc3e3.js} +1 -1
  305. package/dist/safe-a/_next/static/chunks/e60ef129113f6e24.js +1 -0
  306. package/dist/safe-a/_next/static/chunks/{8ebfebffa66b3ca7.js → e61019aedfdf554e.js} +1 -1
  307. package/dist/safe-a/_next/static/chunks/e6324292aef80338.js +1 -0
  308. package/dist/safe-a/_next/static/chunks/{e89655c05e6b5b1f.js → e7003dbd5d8cb2d1.js} +1 -1
  309. package/dist/safe-a/_next/static/chunks/e7bcbeb465fa49cf.js +1 -0
  310. package/dist/safe-a/_next/static/chunks/e7f1a043618e43cf.js +1 -0
  311. package/dist/safe-a/_next/static/chunks/e8105dbb23b8e514.js +1 -0
  312. package/dist/safe-a/_next/static/chunks/{e7731336476789d7.js → ea12d36cdfbaafa9.js} +1 -1
  313. package/dist/safe-a/_next/static/chunks/{05ac495e860ba7c2.js → ea2a84258a02d5c5.js} +1 -1
  314. package/dist/safe-a/_next/static/chunks/{b9b23fa418eacd67.js → ea36a5ae7c6ce34f.js} +1 -1
  315. package/dist/safe-a/_next/static/chunks/eac98d693efb6a1f.js +1 -0
  316. package/dist/safe-a/_next/static/chunks/{fbb5b0d1f5b25465.js → eb2d81df9fe374a8.js} +1 -1
  317. package/dist/safe-a/_next/static/chunks/{30c0274cb379ab0d.js → eb9ae8e95cac1197.js} +1 -1
  318. package/dist/safe-a/_next/static/chunks/{abf043c7dd51a07b.js → ebb0ee69f6a7883e.js} +1 -1
  319. package/dist/safe-a/_next/static/chunks/{d84ed83f568f41c6.js → ebcbb5070eb8e29f.js} +1 -1
  320. package/dist/safe-a/_next/static/chunks/ebcd85ff4a1db0dc.js +5 -0
  321. package/dist/safe-a/_next/static/chunks/ec7537a65499e7a4.js +1 -0
  322. package/dist/safe-a/_next/static/chunks/{5ad5a5ee1cc648ae.js → ee79511740d19885.js} +1 -1
  323. package/dist/safe-a/_next/static/chunks/eed0c3ef6a5c3706.js +1 -0
  324. package/dist/safe-a/_next/static/chunks/{404f44571be80b78.js → ef51763a796dde8b.js} +1 -1
  325. package/dist/safe-a/_next/static/chunks/{025f9752d60b79ce.js → f0cb9b2226c53ef9.js} +1 -1
  326. package/dist/safe-a/_next/static/chunks/{c5b0f8f27c2db9f1.js → f0d9f0621f8ec46d.js} +1 -1
  327. package/dist/safe-a/_next/static/chunks/{5474db37e4b450e8.js → f12f45a558c3fed2.js} +1 -1
  328. package/dist/safe-a/_next/static/chunks/{868f60fa1a2ff26b.js → f1e5e295d4db5c0f.js} +1 -1
  329. package/dist/safe-a/_next/static/chunks/{3b0acee8a8035ee7.js → f1f911d553a62027.js} +1 -1
  330. package/dist/safe-a/_next/static/chunks/{36897fabf62bf445.js → f235a8df2f905e6a.js} +1 -1
  331. package/dist/safe-a/_next/static/chunks/{27b3d30516d46fc8.js → f36595b9995a49a9.js} +1 -1
  332. package/dist/safe-a/_next/static/chunks/f42a71992d139302.js +1 -0
  333. package/dist/safe-a/_next/static/chunks/{dd03bb14e8e590f0.js → f42d74f288f2229c.js} +1 -1
  334. package/dist/safe-a/_next/static/chunks/{f39ec71d70b31fe1.js → f461a75ec3b0e4e9.js} +1 -1
  335. package/dist/safe-a/_next/static/chunks/{9f7b593a28b4dbe4.js → f50fd84e477dbaeb.js} +1 -1
  336. package/dist/safe-a/_next/static/chunks/{4c19e1ee54dac526.js → f659a364f48244ea.js} +1 -1
  337. package/dist/safe-a/_next/static/chunks/{7c4b1ab5c0f1b167.js → f813c3d77459119f.js} +1 -1
  338. package/dist/safe-a/_next/static/chunks/f874690806ec289e.js +1 -0
  339. package/dist/safe-a/_next/static/chunks/{cac08e0e891f58d2.js → f9cb4b70f67c86d8.js} +1 -1
  340. package/dist/safe-a/_next/static/chunks/{2854919e0953bd0d.js → fa39b9f8bced4bcd.js} +1 -1
  341. package/dist/safe-a/_next/static/chunks/{4df5dd4e3c591164.js → fa5b61b8e7219fe6.js} +1 -1
  342. package/dist/safe-a/_next/static/chunks/{1386362cdfd92116.js → facb82117d49a6e1.js} +1 -1
  343. package/dist/safe-a/_next/static/chunks/{e1626e173f56ae31.js → fb05f79f5e4b514e.js} +1 -1
  344. package/dist/safe-a/_next/static/chunks/{18e062f9f23f27c0.js → fb0f4d868b87961b.js} +1 -1
  345. package/dist/safe-a/_next/static/chunks/{3d9ee9c4bc8e29b2.js → fb2f1266493dd820.js} +1 -1
  346. package/dist/safe-a/_next/static/chunks/fc2efa33a196ee45.js +1 -0
  347. package/dist/safe-a/_next/static/chunks/{a4ab363af889263f.js → fd3d43eb8557ee49.js} +1 -1
  348. package/dist/safe-a/_next/static/chunks/{8ead3da37182ce4c.js → fdfce6fa0b958336.js} +1 -1
  349. package/dist/safe-a/_next/static/chunks/{04ed04c00511a337.js → ff12eca45020947a.js} +1 -1
  350. package/dist/safe-a/_next/static/chunks/ff6860dcd793aa23.js +1 -0
  351. package/dist/safe-a/_next/static/chunks/{turbopack-36509d12126a5bb6.js → turbopack-3d84668fefd38b4b.js} +1 -1
  352. package/dist/safe-a/_next/static/chunks/{turbopack-6a1d2af530d97cf8.js → turbopack-63952675b1d69124.js} +1 -1
  353. package/dist/safe-a/_next/static/chunks/turbopack-8b41433c9a94981f.js +3 -0
  354. package/dist/safe-a/_next/static/{GEpoLDHgyzXdgHMKRqrNr → dqDFW64gE_H1NTMvUHYb-}/_buildManifest.js +1 -1
  355. package/dist/safe-a/_next/static/media/data-loading.be8d921a.png +0 -0
  356. package/dist/safe-a/_next/static/media/no-data.48c973b9.png +0 -0
  357. package/dist/safe-a/index.html +2 -2
  358. package/dist/safe-a/index.txt +22 -22
  359. package/dist/safe-a/manage/about/index.html +2 -2
  360. package/dist/safe-a/manage/about/index.txt +24 -23
  361. package/dist/safe-a/manage/env/index.html +2 -2
  362. package/dist/safe-a/manage/env/index.txt +27 -26
  363. package/dist/safe-a/manage/general/index.html +2 -2
  364. package/dist/safe-a/manage/general/index.txt +24 -23
  365. package/dist/safe-a/manage/index.html +2 -2
  366. package/dist/safe-a/manage/index.txt +21 -20
  367. package/dist/safe-a/manage/mcp/index.html +2 -2
  368. package/dist/safe-a/manage/mcp/index.txt +25 -24
  369. package/dist/safe-a/manage/permissions/index.html +2 -2
  370. package/dist/safe-a/manage/permissions/index.txt +24 -23
  371. package/dist/safe-a/manage/skills/index.html +2 -2
  372. package/dist/safe-a/manage/skills/index.txt +25 -24
  373. package/dist/safe-a/manage/task/index.html +2 -2
  374. package/dist/safe-a/manage/task/index.txt +25 -24
  375. package/dist/safe-a/manage/teams/index.html +2 -2
  376. package/dist/safe-a/manage/teams/index.txt +25 -24
  377. package/dist/safe-a/manage/tools/index.html +2 -2
  378. package/dist/safe-a/manage/tools/index.txt +25 -24
  379. package/dist/ws-test/ws-test.css +360 -79
  380. package/dist/ws-test/ws-test.html +94 -138
  381. package/dist/ws-test/ws-test.js +879 -554
  382. package/package.json +6 -6
  383. package/.env.example +0 -7
  384. package/dist/safe-a/_next/static/chunks/00f91b7d88f62204.js +0 -1
  385. package/dist/safe-a/_next/static/chunks/078aea2e54474461.js +0 -5
  386. package/dist/safe-a/_next/static/chunks/08ecdb579e7fd3de.js +0 -1
  387. package/dist/safe-a/_next/static/chunks/10924447cee18191.js +0 -1
  388. package/dist/safe-a/_next/static/chunks/1116b1064a071974.js +0 -1
  389. package/dist/safe-a/_next/static/chunks/125b77ecc6b4189f.js +0 -1
  390. package/dist/safe-a/_next/static/chunks/1b739dfdbcce05bd.js +0 -1
  391. package/dist/safe-a/_next/static/chunks/1c1f2b4adafc2442.js +0 -1
  392. package/dist/safe-a/_next/static/chunks/1d0273aae0bc102c.js +0 -1
  393. package/dist/safe-a/_next/static/chunks/1df41f8d439107ef.js +0 -1
  394. package/dist/safe-a/_next/static/chunks/1faaa282be969b14.js +0 -1
  395. package/dist/safe-a/_next/static/chunks/29105a13d179d5b2.js +0 -1
  396. package/dist/safe-a/_next/static/chunks/29403b19d94e37bb.js +0 -1
  397. package/dist/safe-a/_next/static/chunks/29f39316c32518a2.js +0 -1
  398. package/dist/safe-a/_next/static/chunks/2a07e0d1ef712b41.js +0 -1
  399. package/dist/safe-a/_next/static/chunks/2b38c2b26760e4cb.js +0 -1
  400. package/dist/safe-a/_next/static/chunks/2bb180b50bafe979.js +0 -1
  401. package/dist/safe-a/_next/static/chunks/2ce249001ad95013.js +0 -1
  402. package/dist/safe-a/_next/static/chunks/2ddf153879790e6a.js +0 -1
  403. package/dist/safe-a/_next/static/chunks/2fcbd3cabd5261f8.js +0 -1
  404. package/dist/safe-a/_next/static/chunks/314748f34f8e81bb.js +0 -1
  405. package/dist/safe-a/_next/static/chunks/33e878df066811db.js +0 -1
  406. package/dist/safe-a/_next/static/chunks/37615c61dd14fc8d.js +0 -1
  407. package/dist/safe-a/_next/static/chunks/38decd5cd3fe2525.js +0 -1
  408. package/dist/safe-a/_next/static/chunks/3ecc6705303560ea.js +0 -1
  409. package/dist/safe-a/_next/static/chunks/3fe95be4b92470e2.js +0 -1
  410. package/dist/safe-a/_next/static/chunks/405de186b610394b.js +0 -1
  411. package/dist/safe-a/_next/static/chunks/4064e59727cba9b0.js +0 -1
  412. package/dist/safe-a/_next/static/chunks/4385d9dba96b7614.js +0 -1
  413. package/dist/safe-a/_next/static/chunks/44e9e0394b7b6f31.js +0 -1
  414. package/dist/safe-a/_next/static/chunks/47c632214f4d3a5c.js +0 -1
  415. package/dist/safe-a/_next/static/chunks/4c85c84ca0d7ca5c.js +0 -1
  416. package/dist/safe-a/_next/static/chunks/4cd41b402679f77d.js +0 -1
  417. package/dist/safe-a/_next/static/chunks/5071381bdd700d6c.js +0 -1
  418. package/dist/safe-a/_next/static/chunks/50f270f87470ca73.js +0 -1
  419. package/dist/safe-a/_next/static/chunks/5153542043b58066.js +0 -1
  420. package/dist/safe-a/_next/static/chunks/523d30dc7b2f29be.js +0 -1
  421. package/dist/safe-a/_next/static/chunks/5385bf74559eeabd.js +0 -1
  422. package/dist/safe-a/_next/static/chunks/54169c1554845574.js +0 -1
  423. package/dist/safe-a/_next/static/chunks/5452d182bb136a51.js +0 -1
  424. package/dist/safe-a/_next/static/chunks/568061ca1300bae8.js +0 -5
  425. package/dist/safe-a/_next/static/chunks/592e7a6b713dc645.js +0 -1
  426. package/dist/safe-a/_next/static/chunks/599abea9ac64aaf1.js +0 -1
  427. package/dist/safe-a/_next/static/chunks/5ae21c9105c6abb4.js +0 -1
  428. package/dist/safe-a/_next/static/chunks/5b8ec6577fda27e2.js +0 -1
  429. package/dist/safe-a/_next/static/chunks/5cec026c430f6fc0.js +0 -1
  430. package/dist/safe-a/_next/static/chunks/68ca890844b706f0.js +0 -1
  431. package/dist/safe-a/_next/static/chunks/6960a33147147a27.js +0 -1
  432. package/dist/safe-a/_next/static/chunks/6f6140cbad7cdeea.js +0 -1
  433. package/dist/safe-a/_next/static/chunks/6faa53698dc67904.js +0 -1
  434. package/dist/safe-a/_next/static/chunks/727dc45d24782155.js +0 -1
  435. package/dist/safe-a/_next/static/chunks/743fcc76fa73e3f3.js +0 -1
  436. package/dist/safe-a/_next/static/chunks/74d8d2b653f61b70.js +0 -1
  437. package/dist/safe-a/_next/static/chunks/784ee151431c6634.js +0 -1
  438. package/dist/safe-a/_next/static/chunks/78e956ecc59759b3.js +0 -1
  439. package/dist/safe-a/_next/static/chunks/7afa34c1dc058648.js +0 -1
  440. package/dist/safe-a/_next/static/chunks/7b34873e2b22211d.js +0 -1
  441. package/dist/safe-a/_next/static/chunks/7bd04dff1e0d3a01.js +0 -1
  442. package/dist/safe-a/_next/static/chunks/7c10191806133cb4.js +0 -1
  443. package/dist/safe-a/_next/static/chunks/7d210744c047b2bb.js +0 -1
  444. package/dist/safe-a/_next/static/chunks/7f167fb0dbc03180.js +0 -1
  445. package/dist/safe-a/_next/static/chunks/80bd106b26a076af.js +0 -1
  446. package/dist/safe-a/_next/static/chunks/826c64c8601264b1.js +0 -1
  447. package/dist/safe-a/_next/static/chunks/83a80f59afe8f7f4.js +0 -1
  448. package/dist/safe-a/_next/static/chunks/84ac0be00d5a7734.js +0 -1
  449. package/dist/safe-a/_next/static/chunks/87b0002602934525.js +0 -1
  450. package/dist/safe-a/_next/static/chunks/882686dd3b63f9d1.js +0 -1
  451. package/dist/safe-a/_next/static/chunks/88e4cdcdeff36154.js +0 -1
  452. package/dist/safe-a/_next/static/chunks/8c8b1e40b00409f5.js +0 -1
  453. package/dist/safe-a/_next/static/chunks/92116f4ce954ae13.js +0 -1
  454. package/dist/safe-a/_next/static/chunks/95ef412230573b84.js +0 -1
  455. package/dist/safe-a/_next/static/chunks/996147dc11d8e745.js +0 -1
  456. package/dist/safe-a/_next/static/chunks/9a5e8d11c09774ed.js +0 -1
  457. package/dist/safe-a/_next/static/chunks/9bb97d9ab3f6de64.css +0 -4
  458. package/dist/safe-a/_next/static/chunks/9f8b67e210121299.js +0 -1
  459. package/dist/safe-a/_next/static/chunks/9fb7ffa11026935c.js +0 -1
  460. package/dist/safe-a/_next/static/chunks/a3044be9cf533501.js +0 -1
  461. package/dist/safe-a/_next/static/chunks/a333240ca95e9cf9.js +0 -1
  462. package/dist/safe-a/_next/static/chunks/a4b35c64097aeb05.js +0 -1
  463. package/dist/safe-a/_next/static/chunks/a6fda6a41633eb93.js +0 -1
  464. package/dist/safe-a/_next/static/chunks/a9a12415c8875ad5.js +0 -1
  465. package/dist/safe-a/_next/static/chunks/ab91b57996557cd5.js +0 -1
  466. package/dist/safe-a/_next/static/chunks/abd93c4f518b4209.js +0 -1
  467. package/dist/safe-a/_next/static/chunks/ac0062f74360e8a1.js +0 -1
  468. package/dist/safe-a/_next/static/chunks/b0f0f19c125de544.js +0 -1
  469. package/dist/safe-a/_next/static/chunks/b594aa86704b6429.js +0 -1
  470. package/dist/safe-a/_next/static/chunks/b882523826ac1c83.js +0 -1
  471. package/dist/safe-a/_next/static/chunks/b926ed38d7cc48d8.js +0 -1
  472. package/dist/safe-a/_next/static/chunks/bb781f225af4e1f8.js +0 -1
  473. package/dist/safe-a/_next/static/chunks/bbb9a4e020dec46d.js +0 -1
  474. package/dist/safe-a/_next/static/chunks/c158c0ddb31b1058.js +0 -1
  475. package/dist/safe-a/_next/static/chunks/c3bcc6eb84ed7d30.js +0 -1
  476. package/dist/safe-a/_next/static/chunks/c81f8c96b5d54dbb.js +0 -1
  477. package/dist/safe-a/_next/static/chunks/c9527036b1a95d19.js +0 -1
  478. package/dist/safe-a/_next/static/chunks/ca31fc9ca02421c7.js +0 -1
  479. package/dist/safe-a/_next/static/chunks/d1372ce458c4a584.js +0 -1
  480. package/dist/safe-a/_next/static/chunks/d3072ff0f4d0f613.js +0 -1
  481. package/dist/safe-a/_next/static/chunks/d3f94755bb60424c.js +0 -1
  482. package/dist/safe-a/_next/static/chunks/dbf36b536a6c59ef.js +0 -1
  483. package/dist/safe-a/_next/static/chunks/dda4e994ee3a92e1.js +0 -1
  484. package/dist/safe-a/_next/static/chunks/df25d932487a1417.js +0 -1
  485. package/dist/safe-a/_next/static/chunks/e69f953184729bfc.js +0 -1
  486. package/dist/safe-a/_next/static/chunks/e79d1db952916e66.js +0 -1
  487. package/dist/safe-a/_next/static/chunks/e814d6bb4f565a59.js +0 -1
  488. package/dist/safe-a/_next/static/chunks/f15c8b2639bebe0f.js +0 -1
  489. package/dist/safe-a/_next/static/chunks/f5e77b158443344d.js +0 -1
  490. package/dist/safe-a/_next/static/chunks/f75b1e4cbb975714.js +0 -1
  491. package/dist/safe-a/_next/static/chunks/fa951eecdf98ad7f.css +0 -1
  492. package/dist/safe-a/_next/static/chunks/fac51e37e04e662e.js +0 -1
  493. package/dist/safe-a/_next/static/chunks/fb7bf2e8cee9c72f.js +0 -1
  494. package/dist/safe-a/_next/static/chunks/fe4fddbf85e1554b.js +0 -1
  495. package/dist/safe-a/_next/static/chunks/fe5cb190c34add83.js +0 -1
  496. package/dist/safe-a/_next/static/chunks/turbopack-ab23c5c8fb4c9135.js +0 -3
  497. /package/dist/safe-a/_next/static/{GEpoLDHgyzXdgHMKRqrNr → dqDFW64gE_H1NTMvUHYb-}/_clientMiddlewareManifest.json +0 -0
  498. /package/dist/safe-a/_next/static/{GEpoLDHgyzXdgHMKRqrNr → dqDFW64gE_H1NTMvUHYb-}/_ssgManifest.js +0 -0
@@ -50,28 +50,27 @@
50
50
  const btnSkillMdCancel = $('btnSkillMdCancel')
51
51
  const btnSkillMdSave = $('btnSkillMdSave')
52
52
  let skillMdEditingName = ''
53
- const agentEnvModal = $('agentEnvModal')
54
- const agentEnvModalCard = $('agentEnvModalCard')
55
- const agentEnvModalBackdrop = $('agentEnvModalBackdrop')
56
- const agentEnvSessionTabStrip = $('agentEnvSessionTabStrip')
53
+ const agentSettingsView = $('agentSettingsView')
57
54
  const agentEnvSessionTabList = $('agentEnvSessionTabList')
58
- const agentEnvPanelEnv = $('agentEnvPanelEnv')
55
+ const agentEnvPanelUnified = $('agentEnvPanelUnified')
59
56
  const agentEnvPanelAgentMd = $('agentEnvPanelAgentMd')
60
- const agentEnvPanelSettings = $('agentEnvPanelSettings')
61
57
  const agentEnvAgentMdEditor = $('agentEnvAgentMdEditor')
62
- const agentEnvAgentTypeInput = $('agentEnvAgentTypeInput')
63
- const agentEnvWhenToUseInput = $('agentEnvWhenToUseInput')
64
- const agentEnvTeamEmpty = $('agentEnvTeamEmpty')
65
- const agentEnvTeamChips = $('agentEnvTeamChips')
66
- const agentEnvTeamPick = $('agentEnvTeamPick')
67
- const btnAgentEnvAddTeamMember = $('btnAgentEnvAddTeamMember')
68
- const agentEnvToolsInput = $('agentEnvToolsInput')
69
- const agentEnvModelInput = $('agentEnvModelInput')
70
- const agentEnvEffortInput = $('agentEnvEffortInput')
71
- const agentEnvBackgroundInput = $('agentEnvBackgroundInput')
72
- const agentEnvIsolationInput = $('agentEnvIsolationInput')
58
+ const llmProvidersSettingsBlock = $('llmProvidersSettingsBlock')
59
+ const llmFormId = $('llmFormId')
60
+ const llmFormName = $('llmFormName')
61
+ const llmFormProvider = $('llmFormProvider')
62
+ const llmFormBaseUrl = $('llmFormBaseUrl')
63
+ const llmFormApiKey = $('llmFormApiKey')
64
+ const llmFormAuthToken = $('llmFormAuthToken')
65
+ const llmFormModelId = $('llmFormModelId')
66
+ const llmFormModelLabel = $('llmFormModelLabel')
67
+ const llmProvidersEmptyHint = $('llmProvidersEmptyHint')
68
+ const llmProvidersList = $('llmProvidersList')
69
+ const btnLlmProvidersAdd = $('btnLlmProvidersAdd')
70
+ const LLM_MASKED_CREDENTIAL = '***'
71
+ /** 设置页 LLM 服务商草稿,保存时写入 agent.json.llmProviders */
72
+ let llmProvidersDraft = []
73
73
  const agentEnvList = $('agentEnvList')
74
- const btnAgentEnvModalClose = $('btnAgentEnvModalClose')
75
74
  const btnAgentEnvCancel = $('btnAgentEnvCancel')
76
75
  const btnAgentEnvSave = $('btnAgentEnvSave')
77
76
  const toolFilesModal = $('toolFilesModal')
@@ -147,6 +146,7 @@
147
146
  const repoFilePreviewBody = $('repoFilePreviewBody')
148
147
  const repoFilePreviewState = $('repoFilePreviewState')
149
148
  const btnRepoFileDownload = $('btnRepoFileDownload')
149
+ const btnRepoFileDelete = $('btnRepoFileDelete')
150
150
  const mainHeaderEl = document.querySelector('.main-header')
151
151
  const DEFAULT_AGENT_ID = 'qihoo'
152
152
  const mcpPackageMeta = $('mcpPackageMeta')
@@ -317,14 +317,14 @@
317
317
  isolation: '',
318
318
  whentouse: '',
319
319
  env: {},
320
+ llmProviders: [],
320
321
  }
321
322
  // session 级 overrides:只影响当前 sessionId 子进程;不写 agent.json
322
- let sessionOverrideState = { model: '', env: {} }
323
+ let sessionOverrideState = { providerId: '', model: '', env: {} }
323
324
  // 未分配 sessionId 时暂存,收到 {type:'session', sessionId} 后补写
324
325
  let pendingSessionOverrides = null
325
- const AGENT_ENV_GROUP_ORDER = ['llm', 'git', 'geelib', 'tutui', 'system']
326
+ const AGENT_ENV_GROUP_ORDER = ['git', 'geelib', 'tutui', 'system']
326
327
  const AGENT_ENV_GROUP_LABELS = {
327
- llm: 'llm设置',
328
328
  git: 'git设置',
329
329
  geelib: 'geelib设置',
330
330
  tutui: 'tutui设置',
@@ -332,7 +332,7 @@
332
332
  }
333
333
  let agentEnvSchema = []
334
334
  let agentEnvFieldValues = {}
335
- let agentEnvActiveTab = 'env'
335
+ let agentEnvActiveTab = 'settings'
336
336
  let agentEnvAgentMdLoadOk = false
337
337
  let pickerKind = 'tools'
338
338
  let pickerSelected = new Set()
@@ -342,6 +342,7 @@
342
342
  let remoteMcpServers = []
343
343
  const WS_PERMISSION_MODE_KEY = 'WS_PERMISSION_MODE'
344
344
  const LLM_MODEL_KEY = 'LLM_MODEL'
345
+ const LLM_PROVIDER_ID_KEY = 'LLM_PROVIDER_ID'
345
346
  const WS_ALLOW_TOOL_ASK_KEY = 'WS_ALLOW_TOOL_ASK'
346
347
  const TUITUI_CHANNEL_SESSION_KEY = 'TUITUI_CHANNEL_SESSION'
347
348
  const TUITUI_CHANNEL_SESSION_ALLOWED = new Set(['0', '1'])
@@ -363,10 +364,13 @@
363
364
 
364
365
  /** 项目根 .env 中的默认值(agent.json 未配置时用于新 session 展示) */
365
366
  let projectEnvDefaults = {
366
- LLM_MODEL: '',
367
367
  WS_PERMISSION_MODE: '',
368
368
  WS_ALLOW_TOOL_ASK: '',
369
369
  }
370
+
371
+ /** LLM providers merged 默认 provider/model(由刷新函数计算) */
372
+ let llmDefaultProviderId = ''
373
+ let llmDefaultModelId = ''
370
374
  /** 固定表单字段在项目 .env 的默认值(用于环境变量面板回显) */
371
375
  let projectEnvFormDefaults = {}
372
376
 
@@ -455,7 +459,7 @@
455
459
  /**
456
460
  * 业务逻辑:
457
461
  * 1) 环境变量固定表单必须由后端 schema 驱动,避免前后端字段漂移;
458
- * 2) 仅接收 5 个固定分组字段,其他分组直接忽略;
462
+ * 2) 仅接收 git/geelib/tutui/system 分组字段,其他分组直接忽略;
459
463
  * 3) 字段顺序保持后端下发顺序,确保展示和保存稳定可预期。
460
464
  */
461
465
  function normalizeAgentEnvSchema(rawSchema) {
@@ -481,22 +485,49 @@
481
485
  return out
482
486
  }
483
487
 
488
+ /** 读取设置页 whentouse 输入框(由 renderAgentEnvList 动态挂载在「系统设置」分组) */
489
+ function queryAgentEnvWhenToUseInput() {
490
+ return $('agentEnvWhenToUseInput')
491
+ }
492
+
493
+ /**
494
+ * 在「系统设置」分组渲染 agent.json.whentouse 输入框。
495
+ */
496
+ function appendAgentEnvWhentouseRow(section, whentouseValue) {
497
+ const row = document.createElement('div')
498
+ row.className = 'agent-env-fixed-row agent-env-fixed-row--whentouse'
499
+ const label = document.createElement('label')
500
+ label.className = 'agent-env-fixed-label'
501
+ label.setAttribute('for', 'agentEnvWhenToUseInput')
502
+ label.textContent = '使用时机(whentouse)'
503
+ const textarea = document.createElement('textarea')
504
+ textarea.id = 'agentEnvWhenToUseInput'
505
+ textarea.className = 'agent-md-editor settings-textarea--whentouse agent-env-kv-input'
506
+ textarea.rows = 3
507
+ textarea.spellcheck = false
508
+ textarea.placeholder = '输入该 agent 的使用时机描述'
509
+ textarea.setAttribute('aria-label', 'agent.json whentouse')
510
+ textarea.value = typeof whentouseValue === 'string' ? whentouseValue : ''
511
+ row.appendChild(label)
512
+ row.appendChild(textarea)
513
+ section.appendChild(row)
514
+ }
515
+
484
516
  /**
485
517
  * 业务逻辑:
486
518
  * 1) 固定表单只允许 schema 内字段,所有输入值写入内存 map;
487
519
  * 2) 保存前由 collectAndValidateAgentEnvDraft 统一做 trim 与空值过滤;
488
- * 3) 渲染时按分组插入标题,保证 UI 与需求分区一致。
520
+ * 3) 渲染时按分组插入标题;「系统设置」仅含 whentouse,不含全局 .env 变量。
489
521
  */
490
522
  function renderAgentEnvList() {
491
523
  if (!agentEnvList) return
524
+ const priorWhenInput = queryAgentEnvWhenToUseInput()
525
+ const priorWhentouse = priorWhenInput
526
+ ? String(priorWhenInput.value || '')
527
+ : typeof agentConfigState.whentouse === 'string'
528
+ ? agentConfigState.whentouse
529
+ : ''
492
530
  agentEnvList.innerHTML = ''
493
- if (!agentEnvSchema.length) {
494
- const empty = document.createElement('div')
495
- empty.className = 'tool-files-empty'
496
- empty.textContent = '未加载到环境变量表单配置'
497
- agentEnvList.appendChild(empty)
498
- return
499
- }
500
531
  const schemaByGroup = {}
501
532
  for (let i = 0; i < AGENT_ENV_GROUP_ORDER.length; i++) {
502
533
  schemaByGroup[AGENT_ENV_GROUP_ORDER[i]] = []
@@ -506,9 +537,22 @@
506
537
  schemaByGroup[field.group].push(field)
507
538
  }
508
539
  const frag = document.createDocumentFragment()
540
+ let renderedAny = false
509
541
  for (let i = 0; i < AGENT_ENV_GROUP_ORDER.length; i++) {
510
542
  const group = AGENT_ENV_GROUP_ORDER[i]
511
543
  const fields = schemaByGroup[group]
544
+ if (group === 'system') {
545
+ const section = document.createElement('section')
546
+ section.className = 'agent-env-fixed-section'
547
+ const title = document.createElement('h3')
548
+ title.className = 'agent-env-fixed-section-title'
549
+ title.textContent = AGENT_ENV_GROUP_LABELS.system
550
+ section.appendChild(title)
551
+ appendAgentEnvWhentouseRow(section, priorWhentouse)
552
+ frag.appendChild(section)
553
+ renderedAny = true
554
+ continue
555
+ }
512
556
  if (!fields || !fields.length) continue
513
557
  const section = document.createElement('section')
514
558
  section.className = 'agent-env-fixed-section'
@@ -554,36 +598,6 @@
554
598
  agentEnvFieldValues[field.key] = select.value
555
599
  })
556
600
  input = select
557
- } else if (field.key === 'LLM_PROVIDER') {
558
- /**
559
- * 业务逻辑:模型类型是受控枚举,使用下拉框约束可选值,
560
- * 避免手输导致 provider 非法。
561
- */
562
- const select = document.createElement('select')
563
- select.id = inputId
564
- select.className = 'agent-env-kv-input'
565
- const providerOptions = [
566
- { value: '', label: '请选择' },
567
- { value: 'anthropic', label: 'anthropic' },
568
- { value: 'openai', label: 'openai' },
569
- ]
570
- for (let k = 0; k < providerOptions.length; k++) {
571
- const option = document.createElement('option')
572
- option.value = providerOptions[k].value
573
- option.textContent = providerOptions[k].label
574
- select.appendChild(option)
575
- }
576
- const currentValue =
577
- typeof agentEnvFieldValues[field.key] === 'string'
578
- ? agentEnvFieldValues[field.key]
579
- : ''
580
- select.value = currentValue === 'anthropic' || currentValue === 'openai'
581
- ? currentValue
582
- : ''
583
- select.addEventListener('change', function () {
584
- agentEnvFieldValues[field.key] = select.value
585
- })
586
- input = select
587
601
  } else {
588
602
  const textInput = document.createElement('input')
589
603
  textInput.id = inputId
@@ -604,18 +618,29 @@
604
618
  section.appendChild(row)
605
619
  }
606
620
  frag.appendChild(section)
621
+ renderedAny = true
622
+ }
623
+ if (!renderedAny) {
624
+ const empty = document.createElement('div')
625
+ empty.className = 'tool-files-empty'
626
+ empty.textContent = '未加载到环境变量表单配置'
627
+ agentEnvList.appendChild(empty)
628
+ return
607
629
  }
608
630
  agentEnvList.appendChild(frag)
609
631
  }
610
632
 
611
- /** 新 session 默认模型:agent.json.env → agent.json.model → 项目 .env */
612
- function readDefaultLlmModel() {
613
- const fromAgentEnv = readAgentEnvString(LLM_MODEL_KEY)
614
- if (fromAgentEnv) return fromAgentEnv
615
- const fromAgentModel =
616
- typeof agentConfigState.model === 'string' ? agentConfigState.model.trim() : ''
617
- if (fromAgentModel) return fromAgentModel
618
- return projectEnvDefaults.LLM_MODEL || ''
633
+ /**
634
+ * session 的默认 provider + model:
635
+ * 由后端 /api/llm-providers 返回的 merged.defaultProviderId 与 provider.defaultModel 推导。
636
+ *
637
+ * 业务语义:若默认值尚未准备好,直接抛错暴露配置/加载时序问题,
638
+ * 不做静默兜底(避免错误模型运行)。
639
+ */
640
+ function readDefaultLlmProviderAndModel() {
641
+ const providerId = String(llmDefaultProviderId || '').trim()
642
+ const model = String(llmDefaultModelId || '').trim()
643
+ return { providerId, model }
619
644
  }
620
645
 
621
646
  /**
@@ -677,8 +702,10 @@
677
702
  * 3) 将结果投影为 sessionOverrideState,保证 UI 与后端 PATCH 入参一致。
678
703
  */
679
704
  function buildDefaultSessionOverrideState() {
705
+ const { providerId, model } = readDefaultLlmProviderAndModel()
680
706
  return {
681
- model: readDefaultLlmModel(),
707
+ providerId,
708
+ model,
682
709
  env: {
683
710
  [WS_PERMISSION_MODE_KEY]: readDefaultWsPermissionMode(),
684
711
  [WS_ALLOW_TOOL_ASK_KEY]: readDefaultWsAllowToolAsk(),
@@ -2496,10 +2523,27 @@
2496
2523
  expandedPaths: new Set(['']),
2497
2524
  previewFilePath: '',
2498
2525
  loading: false,
2526
+ /** 是否处于文件管理主视图(用于顶栏标题与会话标题隔离) */
2527
+ viewActive: false,
2499
2528
  /** 目录路径 -> { dirs, files },按展开逐级加载,无深度上限 */
2500
2529
  treeCache: new Map(),
2501
2530
  }
2502
2531
 
2532
+ /** Agent 设置主视图是否激活(与聊天区、文件管理互斥) */
2533
+ const agentSettingsState = {
2534
+ viewActive: false,
2535
+ }
2536
+
2537
+ /** 当前是否在文件管理视图 */
2538
+ function isRepoManageViewActive() {
2539
+ return repoManageState.viewActive
2540
+ }
2541
+
2542
+ /** 当前是否在 Agent 设置主视图 */
2543
+ function isAgentSettingsViewActive() {
2544
+ return agentSettingsState.viewActive
2545
+ }
2546
+
2503
2547
  /** 判断是否为可在页面内展示的文本类文件 */
2504
2548
  function isRepoTextFile(fileName) {
2505
2549
  const base = String(fileName || '').split('/').pop() || ''
@@ -2533,26 +2577,77 @@
2533
2577
  setRepoPanelState(repoFilePreviewState, '', false)
2534
2578
  }
2535
2579
 
2536
- /** 打开文件:文本类在页面预览,其他类型新标签下载 */
2537
- async function openRepoFile(path, fileName) {
2580
+ /** 同步预览区标题与右上角下载/删除按钮状态 */
2581
+ function setupRepoFilePreviewHeader(path, fileName) {
2538
2582
  const name = fileName || String(path || '').split('/').pop() || path
2539
- if (!isRepoTextFile(name)) {
2540
- window.open(buildRepoApiUrl('file', { path: path }), '_blank')
2541
- return
2583
+ if (repoFilePreviewTitle) repoFilePreviewTitle.textContent = name
2584
+ if (btnRepoFileDownload) {
2585
+ btnRepoFileDownload.href = buildRepoApiUrl('file', { path: path })
2586
+ btnRepoFileDownload.setAttribute('download', name)
2587
+ }
2588
+ if (btnRepoFileDelete) {
2589
+ btnRepoFileDelete.disabled = !path
2590
+ btnRepoFileDelete.dataset.path = path || ''
2542
2591
  }
2592
+ }
2593
+
2594
+ /** 在预览区展示不可页面内查看的说明文案 */
2595
+ function showRepoFileUnavailablePreview(message) {
2596
+ if (!repoFilePreviewBody) return
2597
+ repoFilePreviewBody.className = 'repo-file-preview-body repo-file-preview-unavailable'
2598
+ repoFilePreviewBody.innerHTML =
2599
+ '<p class="repo-file-preview-hint">' + escapeHtml(message) + '</p>'
2600
+ setRepoPanelState(repoFilePreviewState, '', false)
2601
+ }
2602
+
2603
+ /** 删除 workspace 内当前预览文件,并刷新目录树与列表 */
2604
+ async function deleteRepoFile(path) {
2605
+ const relPath = String(path || '').trim()
2606
+ if (!relPath) return
2607
+ if (!window.confirm('确认删除 workspace 内文件?\n' + relPath)) return
2608
+ if (btnRepoFileDelete) btnRepoFileDelete.disabled = true
2609
+ try {
2610
+ const res = await fetch(buildRepoApiUrl('file', { path: relPath }), {
2611
+ method: 'DELETE',
2612
+ })
2613
+ const data = await res.json().catch(function () {
2614
+ return null
2615
+ })
2616
+ if (!res.ok) {
2617
+ throw new Error(
2618
+ data && data.message ? String(data.message) : '删除失败 (' + res.status + ')',
2619
+ )
2620
+ }
2621
+ const slash = relPath.lastIndexOf('/')
2622
+ const parentPath = slash >= 0 ? relPath.slice(0, slash) : ''
2623
+ repoManageState.treeCache.clear()
2624
+ repoManageState.currentPath = parentPath
2625
+ closeRepoFilePreview()
2626
+ await loadRepoDirectoryView()
2627
+ } catch (e) {
2628
+ window.alert('删除失败: ' + (e && e.message ? e.message : e))
2629
+ if (btnRepoFileDelete) btnRepoFileDelete.disabled = false
2630
+ }
2631
+ }
2632
+
2633
+ /** 打开文件:可预览文本在页面展示,不可预览类型显示说明并提供下载/删除 */
2634
+ async function openRepoFile(path, fileName) {
2635
+ const name = fileName || String(path || '').split('/').pop() || path
2543
2636
  const slash = String(path || '').lastIndexOf('/')
2544
2637
  const parentPath = slash >= 0 ? path.slice(0, slash) : ''
2545
2638
  ensureRepoExpandedAncestors(parentPath)
2546
2639
  repoManageState.previewFilePath = path
2547
2640
  setRepoContentView('preview')
2548
- if (repoFilePreviewTitle) repoFilePreviewTitle.textContent = name
2549
- if (btnRepoFileDownload) {
2550
- btnRepoFileDownload.href = buildRepoApiUrl('file', { path: path })
2551
- btnRepoFileDownload.setAttribute('download', name)
2552
- }
2641
+ setupRepoFilePreviewHeader(path, name)
2553
2642
  if (repoFilePreviewBody) repoFilePreviewBody.innerHTML = ''
2554
- setRepoPanelState(repoFilePreviewState, '加载中…', false)
2555
2643
  void refreshRepoTreeOnly()
2644
+
2645
+ if (!isRepoTextFile(name)) {
2646
+ showRepoFileUnavailablePreview('该文件类型不支持页面内预览,请下载后查看。')
2647
+ return
2648
+ }
2649
+
2650
+ setRepoPanelState(repoFilePreviewState, '加载中…', false)
2556
2651
  try {
2557
2652
  const res = await fetch(buildRepoApiUrl('file', { path: path, preview: true }))
2558
2653
  if (!res.ok) {
@@ -2561,7 +2656,8 @@
2561
2656
  })
2562
2657
  const msg =
2563
2658
  data && data.message ? String(data.message) : '加载失败 (' + res.status + ')'
2564
- throw new Error(msg)
2659
+ showRepoFileUnavailablePreview(msg)
2660
+ return
2565
2661
  }
2566
2662
  const text = await res.text()
2567
2663
  if (repoFilePreviewBody) {
@@ -2575,18 +2671,36 @@
2575
2671
  }
2576
2672
  setRepoPanelState(repoFilePreviewState, '', false)
2577
2673
  } catch (e) {
2578
- if (repoFilePreviewBody) repoFilePreviewBody.innerHTML = ''
2579
- setRepoPanelState(repoFilePreviewState, String(e), true)
2674
+ showRepoFileUnavailablePreview(String(e))
2580
2675
  }
2581
2676
  }
2582
2677
 
2583
- /** 显示/隐藏文件浏览主区域、聊天区与会话标题 */
2678
+ if (btnRepoFileDelete) {
2679
+ btnRepoFileDelete.addEventListener('click', function () {
2680
+ const path = btnRepoFileDelete.dataset.path || repoManageState.previewFilePath
2681
+ void deleteRepoFile(path)
2682
+ })
2683
+ }
2684
+
2685
+ /** 显示/隐藏文件浏览主区域、聊天区;顶栏在文件视图下展示「文件」而非会话标题 */
2584
2686
  function setRepoManageVisible(visible) {
2687
+ if (visible) {
2688
+ closeAgentSettingsView()
2689
+ }
2690
+ repoManageState.viewActive = visible
2585
2691
  if (repoManageView) repoManageView.hidden = !visible
2586
2692
  if (chatWorkspace) chatWorkspace.hidden = visible
2587
2693
  if (chatComposer) chatComposer.hidden = visible
2588
- if (mainHeaderEl) mainHeaderEl.hidden = visible
2589
- if (!visible) updateMainHeader()
2694
+ if (mainHeaderEl) mainHeaderEl.hidden = false
2695
+ if (visible) {
2696
+ if (mainTitleEl) mainTitleEl.textContent = '文件'
2697
+ if (mainSubEl) {
2698
+ mainSubEl.textContent = ''
2699
+ mainSubEl.hidden = true
2700
+ }
2701
+ } else {
2702
+ updateMainHeader()
2703
+ }
2590
2704
  }
2591
2705
 
2592
2706
  /** 关闭文件浏览,回到聊天视图 */
@@ -2595,6 +2709,41 @@
2595
2709
  if (btnManageRepo) btnManageRepo.classList.remove('is-active')
2596
2710
  }
2597
2711
 
2712
+ /**
2713
+ * 切换 Agent 设置主视图与聊天区可见性。
2714
+ * 业务逻辑:设置页与文件管理、聊天区互斥,顶栏展示「设置」与当前 agent 名。
2715
+ */
2716
+ function setAgentSettingsVisible(visible) {
2717
+ if (visible) {
2718
+ repoManageState.viewActive = false
2719
+ if (repoManageView) repoManageView.hidden = true
2720
+ if (btnManageRepo) btnManageRepo.classList.remove('is-active')
2721
+ }
2722
+ agentSettingsState.viewActive = visible
2723
+ if (agentSettingsView) agentSettingsView.hidden = !visible
2724
+ if (chatWorkspace) chatWorkspace.hidden = visible
2725
+ if (chatComposer) chatComposer.hidden = visible
2726
+ if (mainHeaderEl) mainHeaderEl.hidden = false
2727
+ if (visible) {
2728
+ if (mainTitleEl) mainTitleEl.textContent = '设置'
2729
+ if (mainSubEl) {
2730
+ mainSubEl.textContent = currentAgentParam()
2731
+ mainSubEl.hidden = false
2732
+ }
2733
+ if (btnEditAgentEnv) btnEditAgentEnv.classList.add('is-active')
2734
+ } else {
2735
+ if (btnEditAgentEnv) btnEditAgentEnv.classList.remove('is-active')
2736
+ updateMainHeader()
2737
+ }
2738
+ }
2739
+
2740
+ /** 关闭设置主视图,回到聊天 */
2741
+ function closeAgentSettingsView() {
2742
+ if (!agentSettingsState.viewActive) return
2743
+ setAgentSettingsVisible(false)
2744
+ if (agentEnvSessionTabList) agentEnvSessionTabList.innerHTML = ''
2745
+ }
2746
+
2598
2747
  /** 设置 entries/history 面板加载或错误态 */
2599
2748
  function setRepoPanelState(el, message, isError) {
2600
2749
  if (!el) return
@@ -2623,10 +2772,227 @@
2623
2772
  return data
2624
2773
  }
2625
2774
 
2626
- /** 创建目录或文件类型图标(与侧栏一致的描边 SVG 风格) */
2627
- function createRepoTypeIcon(type) {
2775
+ /** 扩展名 -> 文件图标类型(用于目录树与文件表按类型展示不同图标) */
2776
+ const REPO_FILE_ICON_EXT_MAP = {
2777
+ md: 'md',
2778
+ markdown: 'md',
2779
+ json: 'json',
2780
+ yaml: 'yaml',
2781
+ yml: 'yaml',
2782
+ toml: 'yaml',
2783
+ ini: 'yaml',
2784
+ conf: 'yaml',
2785
+ config: 'yaml',
2786
+ html: 'html',
2787
+ htm: 'html',
2788
+ css: 'html',
2789
+ scss: 'html',
2790
+ less: 'html',
2791
+ js: 'js',
2792
+ mjs: 'js',
2793
+ cjs: 'js',
2794
+ jsx: 'js',
2795
+ ts: 'ts',
2796
+ tsx: 'ts',
2797
+ vue: 'vue',
2798
+ svelte: 'vue',
2799
+ py: 'code',
2800
+ go: 'code',
2801
+ java: 'code',
2802
+ c: 'code',
2803
+ cc: 'code',
2804
+ cpp: 'code',
2805
+ h: 'code',
2806
+ hpp: 'code',
2807
+ rs: 'code',
2808
+ rb: 'code',
2809
+ php: 'code',
2810
+ swift: 'code',
2811
+ kt: 'code',
2812
+ kts: 'code',
2813
+ scala: 'code',
2814
+ graphql: 'code',
2815
+ gql: 'code',
2816
+ proto: 'code',
2817
+ sql: 'sql',
2818
+ sh: 'shell',
2819
+ bash: 'shell',
2820
+ zsh: 'shell',
2821
+ png: 'image',
2822
+ jpg: 'image',
2823
+ jpeg: 'image',
2824
+ gif: 'image',
2825
+ webp: 'image',
2826
+ svg: 'image',
2827
+ ico: 'image',
2828
+ bmp: 'image',
2829
+ zip: 'archive',
2830
+ tar: 'archive',
2831
+ gz: 'archive',
2832
+ bz2: 'archive',
2833
+ xz: 'archive',
2834
+ rar: 'archive',
2835
+ '7z': 'archive',
2836
+ pdf: 'pdf',
2837
+ doc: 'doc',
2838
+ docx: 'doc',
2839
+ xls: 'doc',
2840
+ xlsx: 'doc',
2841
+ ppt: 'doc',
2842
+ pptx: 'doc',
2843
+ txt: 'text',
2844
+ log: 'text',
2845
+ env: 'text',
2846
+ csv: 'text',
2847
+ tsv: 'text',
2848
+ xml: 'xml',
2849
+ }
2850
+
2851
+ /** 根据文件名解析图标类型:目录固定为 dir,文件按扩展名或特殊文件名归类 */
2852
+ function resolveRepoFileIconKind(fileName) {
2853
+ const base = String(fileName || '').split('/').pop() || ''
2854
+ const lower = base.toLowerCase()
2855
+ if (!lower) return 'file'
2856
+ if (lower === 'dockerfile') return 'docker'
2857
+ if (lower === 'makefile' || lower === 'cmakelists.txt') return 'code'
2858
+ if (
2859
+ lower === 'readme' ||
2860
+ lower === 'license' ||
2861
+ lower === 'changelog' ||
2862
+ lower === 'contributing'
2863
+ ) {
2864
+ return 'md'
2865
+ }
2866
+ const dot = lower.lastIndexOf('.')
2867
+ if (dot < 0) return 'file'
2868
+ return REPO_FILE_ICON_EXT_MAP[lower.slice(dot + 1)] || 'file'
2869
+ }
2870
+
2871
+ function repoSvgEl(tag, attrs) {
2872
+ const el = document.createElementNS('http://www.w3.org/2000/svg', tag)
2873
+ const keys = Object.keys(attrs || {})
2874
+ for (let i = 0; i < keys.length; i++) {
2875
+ el.setAttribute(keys[i], attrs[keys[i]])
2876
+ }
2877
+ return el
2878
+ }
2879
+
2880
+ /** 在 SVG 上绘制通用文档底板(折角文件外形) */
2881
+ function appendRepoFileDocBase(svg) {
2882
+ svg.appendChild(
2883
+ repoSvgEl('path', {
2884
+ d: 'M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z',
2885
+ }),
2886
+ )
2887
+ svg.appendChild(repoSvgEl('polyline', { points: '14 2 14 8 20 8' }))
2888
+ }
2889
+
2890
+ /** 按图标类型绘制 SVG 内部图形 */
2891
+ function drawRepoIconGraphic(svg, kind) {
2892
+ if (kind === 'dir') {
2893
+ svg.appendChild(
2894
+ repoSvgEl('path', {
2895
+ d: 'M6 14a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h4.5L13 6H18a2 2 0 0 1 2 2v6a2 2 0 0 1-2 2H6z',
2896
+ }),
2897
+ )
2898
+ return
2899
+ }
2900
+ if (kind === 'image') {
2901
+ svg.appendChild(repoSvgEl('rect', { x: '4', y: '5', width: '16', height: '14', rx: '2' }))
2902
+ svg.appendChild(repoSvgEl('circle', { cx: '9', cy: '11', r: '1.2', fill: 'currentColor', stroke: 'none' }))
2903
+ svg.appendChild(repoSvgEl('path', { d: 'M4 16l4.5-4.5a1 1 0 0 1 1.4 0L14 16' }))
2904
+ svg.appendChild(repoSvgEl('path', { d: 'M14 12l2-2a1 1 0 0 1 1.4 0L20 14' }))
2905
+ return
2906
+ }
2907
+ if (kind === 'archive') {
2908
+ svg.appendChild(repoSvgEl('path', { d: 'M5 8h14v12a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V8z' }))
2909
+ svg.appendChild(repoSvgEl('path', { d: 'M5 8V6a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2v2' }))
2910
+ svg.appendChild(repoSvgEl('line', { x1: '10', y1: '12', x2: '14', y2: '12' }))
2911
+ return
2912
+ }
2913
+ if (kind === 'pdf') {
2914
+ appendRepoFileDocBase(svg)
2915
+ svg.appendChild(repoSvgEl('line', { x1: '8', y1: '13', x2: '16', y2: '13' }))
2916
+ svg.appendChild(repoSvgEl('line', { x1: '8', y1: '17', x2: '13', y2: '17' }))
2917
+ return
2918
+ }
2919
+ if (kind === 'docker') {
2920
+ svg.appendChild(repoSvgEl('rect', { x: '4', y: '8', width: '4', height: '3' }))
2921
+ svg.appendChild(repoSvgEl('rect', { x: '9', y: '8', width: '4', height: '3' }))
2922
+ svg.appendChild(repoSvgEl('rect', { x: '14', y: '8', width: '4', height: '3' }))
2923
+ svg.appendChild(repoSvgEl('path', { d: 'M4 11h16v5a3 3 0 0 1-3 3H7a3 3 0 0 1-3-3v-5z' }))
2924
+ return
2925
+ }
2926
+
2927
+ appendRepoFileDocBase(svg)
2928
+ if (kind === 'md' || kind === 'text') {
2929
+ svg.appendChild(repoSvgEl('line', { x1: '8', y1: '12', x2: '16', y2: '12' }))
2930
+ svg.appendChild(repoSvgEl('line', { x1: '8', y1: '16', x2: '14', y2: '16' }))
2931
+ return
2932
+ }
2933
+ if (kind === 'json') {
2934
+ svg.appendChild(repoSvgEl('path', { d: 'M9 11a1.5 1.5 0 1 0 0 3' }))
2935
+ svg.appendChild(repoSvgEl('path', { d: 'M15 11a1.5 1.5 0 1 1 0 3' }))
2936
+ return
2937
+ }
2938
+ if (kind === 'yaml') {
2939
+ svg.appendChild(repoSvgEl('line', { x1: '8', y1: '11', x2: '16', y2: '11' }))
2940
+ svg.appendChild(repoSvgEl('line', { x1: '8', y1: '14', x2: '16', y2: '14' }))
2941
+ svg.appendChild(repoSvgEl('line', { x1: '8', y1: '17', x2: '13', y2: '17' }))
2942
+ return
2943
+ }
2944
+ if (kind === 'html') {
2945
+ svg.appendChild(repoSvgEl('path', { d: 'M9 12l-2 2 2 2' }))
2946
+ svg.appendChild(repoSvgEl('path', { d: 'M15 12l2 2-2 2' }))
2947
+ return
2948
+ }
2949
+ if (kind === 'js') {
2950
+ svg.appendChild(repoSvgEl('path', { d: 'M9 11h2l1 4 1-4h2' }))
2951
+ return
2952
+ }
2953
+ if (kind === 'ts') {
2954
+ svg.appendChild(repoSvgEl('path', { d: 'M8 11h3a1.5 1.5 0 0 1 0 3H9v3' }))
2955
+ svg.appendChild(repoSvgEl('line', { x1: '14', y1: '11', x2: '17', y2: '11' }))
2956
+ svg.appendChild(repoSvgEl('line', { x1: '15.5', y1: '11', x2: '15.5', y2: '17' }))
2957
+ return
2958
+ }
2959
+ if (kind === 'vue') {
2960
+ svg.appendChild(repoSvgEl('path', { d: 'M12 10l6 8H6l6-8z' }))
2961
+ svg.appendChild(repoSvgEl('path', { d: 'M12 13l3 5H9l3-5z' }))
2962
+ return
2963
+ }
2964
+ if (kind === 'sql') {
2965
+ svg.appendChild(repoSvgEl('ellipse', { cx: '12', cy: '8', rx: '5', ry: '2' }))
2966
+ svg.appendChild(repoSvgEl('path', { d: 'M7 8v8c0 1.1 2.2 2 5 2s5-.9 5-2V8' }))
2967
+ return
2968
+ }
2969
+ if (kind === 'shell') {
2970
+ svg.appendChild(repoSvgEl('path', { d: 'M8 11l2 2-2 2' }))
2971
+ svg.appendChild(repoSvgEl('line', { x1: '12', y1: '15', x2: '16', y2: '15' }))
2972
+ return
2973
+ }
2974
+ if (kind === 'xml') {
2975
+ svg.appendChild(repoSvgEl('path', { d: 'M9 11l-2 2 2 2' }))
2976
+ svg.appendChild(repoSvgEl('path', { d: 'M12 11v4' }))
2977
+ svg.appendChild(repoSvgEl('path', { d: 'M15 11l2 2-2 2' }))
2978
+ return
2979
+ }
2980
+ if (kind === 'doc') {
2981
+ svg.appendChild(repoSvgEl('line', { x1: '8', y1: '12', x2: '16', y2: '12' }))
2982
+ svg.appendChild(repoSvgEl('line', { x1: '8', y1: '16', x2: '16', y2: '16' }))
2983
+ return
2984
+ }
2985
+ if (kind === 'code') {
2986
+ svg.appendChild(repoSvgEl('path', { d: 'M9 11l-2 2 2 2' }))
2987
+ svg.appendChild(repoSvgEl('path', { d: 'M15 11l2 2-2 2' }))
2988
+ }
2989
+ }
2990
+
2991
+ /** 创建目录或文件类型图标:文件按扩展名展示不同图形与配色 */
2992
+ function createRepoTypeIcon(type, fileName) {
2993
+ const kind = type === 'dir' ? 'dir' : resolveRepoFileIconKind(fileName)
2628
2994
  const wrap = document.createElement('span')
2629
- wrap.className = 'repo-type-icon repo-type-icon-' + (type === 'dir' ? 'dir' : 'file')
2995
+ wrap.className = 'repo-type-icon repo-type-icon-' + kind
2630
2996
  wrap.setAttribute('aria-hidden', 'true')
2631
2997
  const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg')
2632
2998
  svg.setAttribute('viewBox', '0 0 24 24')
@@ -2637,19 +3003,7 @@
2637
3003
  svg.setAttribute('stroke-width', '1.8')
2638
3004
  svg.setAttribute('stroke-linecap', 'round')
2639
3005
  svg.setAttribute('stroke-linejoin', 'round')
2640
- const path = document.createElementNS('http://www.w3.org/2000/svg', 'path')
2641
- if (type === 'dir') {
2642
- path.setAttribute(
2643
- 'd',
2644
- 'M6 14a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h4.5L13 6H18a2 2 0 0 1 2 2v6a2 2 0 0 1-2 2H6z',
2645
- )
2646
- } else {
2647
- path.setAttribute('d', 'M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z')
2648
- const fold = document.createElementNS('http://www.w3.org/2000/svg', 'polyline')
2649
- fold.setAttribute('points', '14 2 14 8 20 8')
2650
- svg.appendChild(fold)
2651
- }
2652
- svg.appendChild(path)
3006
+ drawRepoIconGraphic(svg, kind)
2653
3007
  wrap.appendChild(svg)
2654
3008
  return wrap
2655
3009
  }
@@ -2774,7 +3128,7 @@
2774
3128
  nameEl.textContent = node.path === '' ? 'workspace' : node.name
2775
3129
 
2776
3130
  row.appendChild(toggle)
2777
- row.appendChild(createRepoTypeIcon(isFile ? 'file' : 'dir'))
3131
+ row.appendChild(createRepoTypeIcon(isFile ? 'file' : 'dir', node.name))
2778
3132
  row.appendChild(nameEl)
2779
3133
  row.addEventListener('click', function () {
2780
3134
  if (isFile) {
@@ -2825,7 +3179,7 @@
2825
3179
  const tdName = document.createElement('td')
2826
3180
  const nameWrap = document.createElement('span')
2827
3181
  nameWrap.className = 'repo-entry-name-wrap'
2828
- nameWrap.appendChild(createRepoTypeIcon(e.type === 'dir' ? 'dir' : 'file'))
3182
+ nameWrap.appendChild(createRepoTypeIcon(e.type === 'dir' ? 'dir' : 'file', e.name))
2829
3183
  if (e.type === 'dir') {
2830
3184
  const btn = document.createElement('button')
2831
3185
  btn.type = 'button'
@@ -2879,6 +3233,7 @@
2879
3233
  async function openRepoManageView() {
2880
3234
  if (!repoManageView) return
2881
3235
  setRepoManageVisible(true)
3236
+ if (btnManageRepo) btnManageRepo.classList.add('is-active')
2882
3237
  repoManageState.currentPath = ''
2883
3238
  repoManageState.previewFilePath = ''
2884
3239
  repoManageState.expandedPaths = new Set([''])
@@ -4180,6 +4535,22 @@
4180
4535
  const sid = sessionIdInput ? sessionIdInput.value.trim() : ''
4181
4536
  updatePromptSessionInfo()
4182
4537
  if (!mainTitleEl) return
4538
+ if (isRepoManageViewActive()) {
4539
+ mainTitleEl.textContent = '文件'
4540
+ if (mainSubEl) {
4541
+ mainSubEl.textContent = ''
4542
+ mainSubEl.hidden = true
4543
+ }
4544
+ return
4545
+ }
4546
+ if (isAgentSettingsViewActive()) {
4547
+ mainTitleEl.textContent = '设置'
4548
+ if (mainSubEl) {
4549
+ mainSubEl.textContent = currentAgentParam()
4550
+ mainSubEl.hidden = false
4551
+ }
4552
+ return
4553
+ }
4183
4554
  if (typeof titleText === 'string' && titleText.trim()) {
4184
4555
  mainTitleEl.textContent = titleText.trim()
4185
4556
  return
@@ -4311,181 +4682,6 @@
4311
4682
  return u.toString()
4312
4683
  }
4313
4684
 
4314
- function buildAgentTeamMembersPostUrl(leaderId) {
4315
- return new URL(
4316
- '/api/agents/' + encodeURIComponent(String(leaderId || '').trim()) + '/team-members',
4317
- httpOriginForApi() + '/',
4318
- ).toString()
4319
- }
4320
-
4321
- function buildAgentTeamMemberDeleteUrl(leaderId, agentType) {
4322
- return new URL(
4323
- '/api/agents/' +
4324
- encodeURIComponent(String(leaderId || '').trim()) +
4325
- '/team-members/' +
4326
- encodeURIComponent(String(agentType || '').trim()),
4327
- httpOriginForApi() + '/',
4328
- ).toString()
4329
- }
4330
-
4331
- function buildAgentsListUrlForOffice() {
4332
- return new URL('/api/agents', httpOriginForApi() + '/').toString()
4333
- }
4334
-
4335
- /** 设置弹窗:可绑定队员仅来自 agent-runtime(GET /api/agents) */
4336
- async function fetchTeamMemberCatalogForSettings(leaderId) {
4337
- const leader = String(leaderId || '').trim()
4338
- const r = await fetch(buildAgentsListUrlForOffice())
4339
- const body = await r.json().catch(function () {
4340
- return {}
4341
- })
4342
- if (!r.ok) {
4343
- throw new Error(body.message || body.error || r.statusText)
4344
- }
4345
- const agents = Array.isArray(body.agents) ? body.agents : []
4346
- const out = []
4347
- for (let i = 0; i < agents.length; i++) {
4348
- const row = agents[i]
4349
- const id = String(row.id || '').trim()
4350
- if (!id || id === leader) continue
4351
- out.push({
4352
- agentType: id,
4353
- whenToUse: typeof row.whentouse === 'string' ? row.whentouse : '',
4354
- })
4355
- }
4356
- out.sort(function (a, b) {
4357
- return a.agentType.localeCompare(b.agentType)
4358
- })
4359
- return out
4360
- }
4361
-
4362
- /** 设置弹窗:渲染已绑定队员与添加下拉 */
4363
- async function renderAgentEnvTeamMembers() {
4364
- if (!agentEnvTeamChips) return
4365
- const leaderId = currentAgentParam()
4366
- const members = Array.isArray(agentConfigState.agentTeamMembers)
4367
- ? agentConfigState.agentTeamMembers
4368
- : []
4369
- if (agentEnvTeamEmpty) {
4370
- agentEnvTeamEmpty.hidden = members.length > 0
4371
- }
4372
- agentEnvTeamChips.innerHTML = ''
4373
- const boundSet = new Set()
4374
- for (let i = 0; i < members.length; i++) {
4375
- const m = members[i]
4376
- const agentType = String(m.agentType || '').trim()
4377
- if (!agentType) continue
4378
- boundSet.add(agentType)
4379
- const chip = document.createElement('span')
4380
- chip.className = 'agent-env-team-chip'
4381
- chip.title =
4382
- typeof m.whentouse === 'string' && m.whentouse.trim()
4383
- ? m.whentouse.trim()
4384
- : agentType
4385
- const label = document.createElement('span')
4386
- label.textContent = agentType
4387
- const rm = document.createElement('button')
4388
- rm.type = 'button'
4389
- rm.setAttribute('aria-label', '移除 ' + agentType)
4390
- rm.textContent = '×'
4391
- rm.addEventListener('click', function () {
4392
- void removeAgentEnvTeamMember(agentType)
4393
- })
4394
- chip.appendChild(label)
4395
- chip.appendChild(rm)
4396
- agentEnvTeamChips.appendChild(chip)
4397
- }
4398
- if (agentEnvTeamPick) {
4399
- agentEnvTeamPick.innerHTML = '<option value="">选择要添加的 Agent…</option>'
4400
- let catalog = []
4401
- try {
4402
- catalog = await fetchTeamMemberCatalogForSettings(leaderId)
4403
- } catch {
4404
- catalog = []
4405
- }
4406
- for (let j = 0; j < catalog.length; j++) {
4407
- const t = catalog[j]
4408
- const id = String(t.agentType || '').trim()
4409
- if (!id || id === leaderId || boundSet.has(id)) continue
4410
- const opt = document.createElement('option')
4411
- opt.value = id
4412
- const when =
4413
- typeof t.whenToUse === 'string' && t.whenToUse.trim() ? t.whenToUse.trim() : ''
4414
- opt.textContent = when ? id + ' — ' + when.slice(0, 36) : id
4415
- agentEnvTeamPick.appendChild(opt)
4416
- }
4417
- }
4418
- }
4419
-
4420
- function applyAgentTeamMembersFromApi(agentRow) {
4421
- if (!agentRow || typeof agentRow !== 'object') return
4422
- if (Array.isArray(agentRow.agentTeamMembers)) {
4423
- agentConfigState.agentTeamMembers = agentRow.agentTeamMembers.map(function (m) {
4424
- return {
4425
- agentType: String(m.agentType || ''),
4426
- whentouse: typeof m.whentouse === 'string' ? m.whentouse : '',
4427
- }
4428
- })
4429
- }
4430
- if (Array.isArray(agentRow.agentTeams)) {
4431
- agentConfigState.agentTeams = agentRow.agentTeams.map(String)
4432
- } else if (Array.isArray(agentRow.agentTeamMembers)) {
4433
- agentConfigState.agentTeams = agentRow.agentTeamMembers
4434
- .map(function (m) {
4435
- return String(m.agentType || '')
4436
- })
4437
- .filter(Boolean)
4438
- }
4439
- renderBindChips()
4440
- }
4441
-
4442
- async function addAgentEnvTeamMember() {
4443
- const leaderId = currentAgentParam()
4444
- if (!agentEnvTeamPick) return
4445
- const agentType = agentEnvTeamPick.value.trim()
4446
- if (!agentType) {
4447
- window.alert('请先选择要添加的队员')
4448
- return
4449
- }
4450
- const r = await fetch(buildAgentTeamMembersPostUrl(leaderId), {
4451
- method: 'POST',
4452
- headers: { 'content-type': 'application/json; charset=utf-8' },
4453
- body: JSON.stringify({ agentType: agentType }),
4454
- })
4455
- const body = await r.json().catch(function () {
4456
- return {}
4457
- })
4458
- if (!r.ok) {
4459
- window.alert('添加队员失败:' + (body.message || body.error || r.statusText))
4460
- return
4461
- }
4462
- applyAgentTeamMembersFromApi(body.agent)
4463
- agentEnvTeamPick.value = ''
4464
- await renderAgentEnvTeamMembers()
4465
- void persistAgentConfigAndRestartSession({ silent: true })
4466
- setStatus('已添加队员 ' + agentType, serverReady ? 'ready' : '')
4467
- }
4468
-
4469
- async function removeAgentEnvTeamMember(agentType) {
4470
- const leaderId = currentAgentParam()
4471
- if (!window.confirm('确定移除队员「' + agentType + '」?')) {
4472
- return
4473
- }
4474
- const r = await fetch(buildAgentTeamMemberDeleteUrl(leaderId, agentType), {
4475
- method: 'DELETE',
4476
- })
4477
- const body = await r.json().catch(function () {
4478
- return {}
4479
- })
4480
- if (!r.ok) {
4481
- window.alert('移除队员失败:' + (body.message || body.error || r.statusText))
4482
- return
4483
- }
4484
- applyAgentTeamMembersFromApi(body.agent)
4485
- await renderAgentEnvTeamMembers()
4486
- void persistAgentConfigAndRestartSession({ silent: true })
4487
- setStatus('已移除队员 ' + agentType, serverReady ? 'ready' : '')
4488
- }
4489
4685
  async function loadSessions(options) {
4490
4686
  sessionListMetaEl.textContent = '加载中…'
4491
4687
  let data
@@ -4536,6 +4732,7 @@
4536
4732
 
4537
4733
  function switchToSession(id) {
4538
4734
  closeRepoManageView()
4735
+ closeAgentSettingsView()
4539
4736
  const nextSid = typeof id === 'string' ? id : ''
4540
4737
  sessionIdInput.value = nextSid
4541
4738
  currentSessionContextPercent = null
@@ -5355,12 +5552,16 @@
5355
5552
 
5356
5553
  function buildModelsApiUrl() {
5357
5554
  const id = currentAgentParam()
5358
- const u = new URL('/api/models', httpOriginForApi() + '/')
5555
+ const u = new URL('/api/llm-providers', httpOriginForApi() + '/')
5359
5556
  u.searchParams.set('agent', id)
5360
5557
  return u.toString()
5361
5558
  }
5362
5559
 
5363
- /** GET /api/models 返回的动态列表(仅展示接口数据 + 浏览器最近使用) */
5560
+ /**
5561
+ * 会话模型候选:来自 /api/llm-providers.merged 的本地配置(不走云端探测)。
5562
+ *
5563
+ * 注意:同一个 model.id 在不同 provider 下可能重复,因此候选需要 providerId 一起参与。
5564
+ */
5364
5565
  let apiModelRows = []
5365
5566
  let lastModelsFetchTs = 0
5366
5567
 
@@ -5379,102 +5580,79 @@
5379
5580
  if (!r.ok) {
5380
5581
  throw new Error(b.message || b.error || r.statusText)
5381
5582
  }
5382
- const rows = Array.isArray(b.models) ? b.models : []
5383
- apiModelRows = rows
5384
- .filter(function (x) {
5385
- return x && typeof x.id === 'string' && x.id.trim()
5386
- })
5387
- .map(function (x) {
5388
- return {
5389
- id: String(x.id).trim(),
5390
- label:
5391
- typeof x.label === 'string' && x.label.trim()
5392
- ? String(x.label).trim()
5393
- : undefined,
5394
- }
5395
- })
5396
- logLine('models-api', { source: b.source, count: apiModelRows.length })
5397
- } catch (e) {
5398
- apiModelRows = []
5399
- logLine('models-api', 'load failed: ' + e)
5400
- }
5401
- }
5583
+ const providers = Array.isArray(b.providers) ? b.providers : []
5402
5584
 
5403
- function labelForModelId(modelId) {
5404
- for (let i = 0; i < apiModelRows.length; i++) {
5405
- if (apiModelRows[i].id === modelId) return apiModelRows[i].label
5406
- }
5407
- return undefined
5408
- }
5409
-
5410
- const RECENT_MODELS_KEY = 'ws-test-composer-recent-models'
5411
-
5412
- function readRecentModels() {
5413
- try {
5414
- const raw = localStorage.getItem(RECENT_MODELS_KEY)
5415
- const arr = raw ? JSON.parse(raw) : []
5416
- return Array.isArray(arr)
5417
- ? arr.filter(function (x) {
5418
- return typeof x === 'string' && x.trim()
5419
- }).slice(0, 12)
5420
- : []
5421
- } catch {
5422
- return []
5423
- }
5424
- }
5425
-
5426
- function pushRecentModel(m) {
5427
- if (!m || !String(m).trim()) return
5428
- const v = String(m).trim()
5429
- let arr = readRecentModels().filter(function (x) {
5430
- return x !== v
5431
- })
5432
- arr.unshift(v)
5433
- arr = arr.slice(0, 12)
5434
- try {
5435
- localStorage.setItem(RECENT_MODELS_KEY, JSON.stringify(arr))
5436
- } catch {
5437
- /* ignore */
5438
- }
5439
- }
5585
+ apiModelRows = []
5586
+ for (let i = 0; i < providers.length; i++) {
5587
+ const p = providers[i]
5588
+ const providerId = typeof p.id === 'string' ? p.id.trim() : ''
5589
+ const providerName = typeof p.name === 'string' ? p.name.trim() : ''
5590
+ const models = Array.isArray(p.models) ? p.models : []
5591
+ for (let j = 0; j < models.length; j++) {
5592
+ const m = models[j]
5593
+ const modelId = typeof m.id === 'string' ? m.id.trim() : ''
5594
+ if (!modelId) continue
5595
+ const label =
5596
+ typeof m.label === 'string' && m.label.trim() ? m.label.trim() : undefined
5597
+ const display = providerName
5598
+ ? providerName + ' · ' + (label ? label : modelId)
5599
+ : (label ? label : modelId)
5600
+ apiModelRows.push({
5601
+ providerId,
5602
+ providerName,
5603
+ id: modelId,
5604
+ label,
5605
+ display,
5606
+ })
5607
+ }
5608
+ }
5440
5609
 
5441
- function mergeModelCandidates() {
5442
- if (!apiModelRows.length) {
5443
- return []
5444
- }
5445
- const seen = new Set()
5446
- const out = []
5447
- function add(x) {
5448
- if (!x || !String(x).trim()) return
5449
- const s = String(x).trim()
5450
- if (seen.has(s)) return
5451
- seen.add(s)
5452
- out.push(s)
5453
- }
5454
- const recent = readRecentModels()
5455
- for (let i = 0; i < recent.length; i++) {
5456
- add(recent[i])
5457
- }
5458
- for (let a = 0; a < apiModelRows.length; a++) {
5459
- add(apiModelRows[a].id)
5610
+ // 计算 merged 默认 provider/model(给新 session 使用)
5611
+ const defaultProviderIdRaw =
5612
+ typeof b.defaultProviderId === 'string' ? b.defaultProviderId.trim() : ''
5613
+ const resolvedDefaultProviderId =
5614
+ defaultProviderIdRaw ||
5615
+ (apiModelRows.length ? apiModelRows[0].providerId : '')
5616
+ llmDefaultProviderId = resolvedDefaultProviderId
5617
+ const defaultProvider = providers.find(p => String(p.id) === resolvedDefaultProviderId) || providers[0]
5618
+ const defaultModelRaw =
5619
+ defaultProvider && typeof defaultProvider.defaultModel === 'string'
5620
+ ? defaultProvider.defaultModel.trim()
5621
+ : ''
5622
+ const defaultModelId =
5623
+ defaultModelRaw ||
5624
+ (defaultProvider && Array.isArray(defaultProvider.models) && defaultProvider.models[0]
5625
+ ? String(defaultProvider.models[0].id).trim()
5626
+ : '')
5627
+ llmDefaultModelId = defaultModelId
5628
+
5629
+ logLine('llm-providers-api', { count: apiModelRows.length, defaultProviderId: llmDefaultProviderId, defaultModelId: llmDefaultModelId })
5630
+ } catch (e) {
5631
+ apiModelRows = []
5632
+ llmDefaultProviderId = ''
5633
+ llmDefaultModelId = ''
5634
+ logLine('llm-providers-api', 'load failed: ' + e)
5460
5635
  }
5461
- return out
5462
5636
  }
5463
5637
 
5464
5638
  function filterModelCandidates(query) {
5465
- const all = mergeModelCandidates()
5466
5639
  const q = String(query || '')
5467
5640
  .trim()
5468
5641
  .toLowerCase()
5642
+ const all = Array.isArray(apiModelRows) ? apiModelRows : []
5469
5643
  if (!q) return all.slice(0, 50)
5470
5644
  const hit = []
5471
5645
  for (let i = 0; i < all.length; i++) {
5472
- const id = all[i]
5473
- const lab = labelForModelId(id)
5474
- const idHit = id.toLowerCase().indexOf(q) >= 0
5475
- const labHit = lab && lab.toLowerCase().indexOf(q) >= 0
5476
- if (idHit || labHit) hit.push(id)
5477
- if (hit.length >= 50) break
5646
+ const x = all[i]
5647
+ const idHit = x.id.toLowerCase().indexOf(q) >= 0
5648
+ const labelHit = x.label && x.label.toLowerCase().indexOf(q) >= 0
5649
+ const providerHit =
5650
+ x.providerName && x.providerName.toLowerCase().indexOf(q) >= 0
5651
+ const providerIdHit = x.providerId && x.providerId.toLowerCase().indexOf(q) >= 0
5652
+ if (idHit || labelHit || providerHit || providerIdHit) {
5653
+ hit.push(x)
5654
+ if (hit.length >= 50) break
5655
+ }
5478
5656
  }
5479
5657
  return hit
5480
5658
  }
@@ -5507,17 +5685,23 @@
5507
5685
  return
5508
5686
  }
5509
5687
  for (let i = 0; i < items.length; i++) {
5510
- const id = items[i]
5511
- const lab = labelForModelId(id)
5688
+ const entry = items[i]
5689
+ const id = entry && typeof entry.id === 'string' ? entry.id : ''
5512
5690
  const li = document.createElement('li')
5513
5691
  li.setAttribute('role', 'option')
5514
5692
  li.setAttribute('data-model', id)
5515
- li.textContent = lab ? lab + ' · ' + id : id
5693
+ if (entry && typeof entry.providerId === 'string') {
5694
+ li.setAttribute('data-provider-id', entry.providerId)
5695
+ }
5696
+ li.textContent = entry && entry.display ? entry.display : id
5516
5697
  if (i === composerModelHighlight) li.classList.add('is-active')
5517
5698
  li.addEventListener('mousedown', function (ev) {
5518
5699
  ev.preventDefault()
5519
5700
  composerModelSuppressBlurCommit = true
5520
5701
  if (composerModelInput) composerModelInput.value = id
5702
+ if (entry && typeof entry.providerId === 'string') {
5703
+ sessionOverrideState.providerId = entry.providerId
5704
+ }
5521
5705
  syncComposerModelTitle()
5522
5706
  hideComposerModelDropdown()
5523
5707
  void commitComposerModelFromInput()
@@ -5565,8 +5749,10 @@
5565
5749
  let idx = composerModelHighlight
5566
5750
  if (idx < 0 || idx >= opts.length) idx = 0
5567
5751
  const id = opts[idx].getAttribute('data-model')
5752
+ const pid = opts[idx].getAttribute('data-provider-id') || ''
5568
5753
  if (id) {
5569
5754
  composerModelInput.value = id
5755
+ if (pid) sessionOverrideState.providerId = pid
5570
5756
  syncComposerModelTitle()
5571
5757
  hideComposerModelDropdown()
5572
5758
  void commitComposerModelFromInput()
@@ -5576,25 +5762,83 @@
5576
5762
  async function commitComposerModelFromInput() {
5577
5763
  if (!composerModelInput) return
5578
5764
  const v = composerModelInput.value.trim()
5579
- if (v === (sessionOverrideState.model || '')) return
5580
- sessionOverrideState.model = v
5581
- if (v) pushRecentModel(v)
5765
+ const defaults = buildDefaultSessionOverrideState()
5766
+
5767
+ // 留空语义:清除 session 级 overrides,让 worker 依据项目/agent 默认配置自动选择 provider/model。
5768
+ if (!v) {
5769
+ const shouldUpdate =
5770
+ (sessionOverrideState.model || '') !== '' ||
5771
+ (sessionOverrideState.providerId || '') !== ''
5772
+ if (!shouldUpdate) return
5773
+ sessionOverrideState.model = ''
5774
+ sessionOverrideState.providerId = ''
5775
+ await persistSessionOverridesAndRestart({ silent: true })
5776
+ return
5777
+ }
5778
+
5779
+ const modelId = v
5780
+
5781
+ const matches = Array.isArray(apiModelRows)
5782
+ ? apiModelRows.filter(function (x) {
5783
+ return x && x.id === modelId
5784
+ })
5785
+ : []
5786
+
5787
+ let providerId = sessionOverrideState.providerId || ''
5788
+ if (matches.length === 1) {
5789
+ providerId = matches[0].providerId
5790
+ } else if (matches.length > 1) {
5791
+ // 相同 model.id 可能出现在多个 provider 下:
5792
+ // 若当前 provider 已匹配其中之一则沿用,否则阻止保存要求用户明确选择。
5793
+ const found = providerId
5794
+ ? matches.some(function (x) {
5795
+ return x.providerId === providerId
5796
+ })
5797
+ : false
5798
+ if (!found) {
5799
+ window.alert('该模型 ID 在多个服务商中重复,请从下拉列表选择完整项(服务商 · 模型)。')
5800
+ return
5801
+ }
5802
+ } else {
5803
+ // 没匹配到 model.id:不允许用不受控的 provider/model 组合运行。
5804
+ window.alert('模型 ID 未配置:' + modelId)
5805
+ return
5806
+ }
5807
+
5808
+ const shouldUpdate =
5809
+ modelId !== (sessionOverrideState.model || '') || providerId !== (sessionOverrideState.providerId || '')
5810
+ if (!shouldUpdate) return
5811
+
5812
+ sessionOverrideState.model = modelId
5813
+ sessionOverrideState.providerId = providerId
5582
5814
  await persistSessionOverridesAndRestart({ silent: true })
5583
5815
  }
5584
5816
 
5585
5817
  function syncComposerModelTitle() {
5586
5818
  if (!composerModelInput) return
5587
5819
  const v = composerModelInput.value.trim()
5588
- composerModelInput.title = v
5589
- ? 'session 级模型覆盖(完整 ID,悬停可复制核对):' + v
5590
- : '留空=跟随 agent.json 默认;模型 ID 须与网关控制台一致(区分大小写)'
5820
+ if (!v) {
5821
+ composerModelInput.title = '留空=跟随默认服务商与模型'
5822
+ return
5823
+ }
5824
+ const entry = Array.isArray(apiModelRows)
5825
+ ? apiModelRows.find(function (x) {
5826
+ return x && x.id === v && (!sessionOverrideState.providerId || x.providerId === sessionOverrideState.providerId)
5827
+ })
5828
+ : null
5829
+ composerModelInput.title = entry
5830
+ ? 'session 级模型覆盖(服务商 · 模型):' + entry.display
5831
+ : 'session 级模型覆盖(模型 ID,需与配置一致):' + v
5591
5832
  }
5592
5833
 
5593
5834
  function syncModelStateToEnv() {
5594
5835
  const env = getSessionOverrideEnv()
5595
- const model = typeof sessionOverrideState.model === 'string'
5596
- ? sessionOverrideState.model.trim()
5597
- : ''
5836
+ const model = typeof sessionOverrideState.model === 'string' ? sessionOverrideState.model.trim() : ''
5837
+ const providerId =
5838
+ typeof sessionOverrideState.providerId === 'string'
5839
+ ? sessionOverrideState.providerId.trim()
5840
+ : ''
5841
+ env[LLM_PROVIDER_ID_KEY] = providerId
5598
5842
  env[LLM_MODEL_KEY] = model
5599
5843
  }
5600
5844
 
@@ -5755,6 +5999,7 @@
5755
5999
  function resetSessionOverrideStateToDefault() {
5756
6000
  const defaults = buildDefaultSessionOverrideState()
5757
6001
  sessionOverrideState = {
6002
+ providerId: defaults.providerId,
5758
6003
  model: defaults.model,
5759
6004
  env: Object.assign({}, defaults.env),
5760
6005
  }
@@ -5786,6 +6031,10 @@
5786
6031
  )
5787
6032
  : {}
5788
6033
  sessionOverrideState = {
6034
+ providerId:
6035
+ typeof ovEnv[LLM_PROVIDER_ID_KEY] === 'string'
6036
+ ? String(ovEnv[LLM_PROVIDER_ID_KEY]).trim()
6037
+ : defaults.providerId,
5789
6038
  model:
5790
6039
  typeof ovEnv[LLM_MODEL_KEY] === 'string'
5791
6040
  ? String(ovEnv[LLM_MODEL_KEY]).trim()
@@ -5813,6 +6062,10 @@
5813
6062
  const env = getSessionOverrideEnv()
5814
6063
  const patchEnv = {}
5815
6064
  const defaults = buildDefaultSessionOverrideState()
6065
+ patchEnv[LLM_PROVIDER_ID_KEY] =
6066
+ typeof sessionOverrideState.providerId === 'string'
6067
+ ? sessionOverrideState.providerId.trim()
6068
+ : defaults.providerId
5816
6069
  patchEnv[LLM_MODEL_KEY] =
5817
6070
  typeof sessionOverrideState.model === 'string'
5818
6071
  ? sessionOverrideState.model.trim()
@@ -6028,6 +6281,7 @@
6028
6281
  isolation: '',
6029
6282
  whentouse: '',
6030
6283
  env: {},
6284
+ llmProviders: [],
6031
6285
  }
6032
6286
  renderBindChips()
6033
6287
  syncModelInputFromState()
@@ -6064,6 +6318,9 @@
6064
6318
  : '',
6065
6319
  whentouse: typeof c.whentouse === 'string' ? c.whentouse : '',
6066
6320
  env: c.env && typeof c.env === 'object' ? Object.fromEntries(Object.entries(c.env).map(function (kv) { return [String(kv[0]), String(kv[1])] })) : {},
6321
+ llmProviders: Array.isArray(c.llmProviders)
6322
+ ? cloneLlmProvidersDraft(c.llmProviders)
6323
+ : [],
6067
6324
  }
6068
6325
  } else {
6069
6326
  agentConfigState = {
@@ -6079,6 +6336,7 @@
6079
6336
  isolation: '',
6080
6337
  whentouse: '',
6081
6338
  env: {},
6339
+ llmProviders: [],
6082
6340
  }
6083
6341
  }
6084
6342
  if (body.agent && Array.isArray(body.agent.agentTeamMembers)) {
@@ -7334,6 +7592,7 @@
7334
7592
  ev.preventDefault()
7335
7593
  ev.stopPropagation()
7336
7594
  closeRepoManageView()
7595
+ closeAgentSettingsView()
7337
7596
  const items = sidebarNavEl.querySelectorAll('.sidebar-nav-row')
7338
7597
  for (let i = 0; i < items.length; i++) {
7339
7598
  items[i].classList.toggle('is-active', items[i] === btn)
@@ -7355,6 +7614,7 @@
7355
7614
  ev.preventDefault()
7356
7615
  ev.stopPropagation()
7357
7616
  closeRepoManageView()
7617
+ closeAgentSettingsView()
7358
7618
  const items = sidebarNavEl.querySelectorAll('.sidebar-nav-row')
7359
7619
  for (let i = 0; i < items.length; i++) {
7360
7620
  items[i].classList.toggle('is-active', items[i] === btn)
@@ -7583,6 +7843,7 @@
7583
7843
  ev.preventDefault()
7584
7844
  ev.stopPropagation()
7585
7845
  closeRepoManageView()
7846
+ closeAgentSettingsView()
7586
7847
  if (sidebarNavEl) {
7587
7848
  const items = sidebarNavEl.querySelectorAll('.sidebar-nav-row')
7588
7849
  for (let i = 0; i < items.length; i++) {
@@ -7671,40 +7932,40 @@
7671
7932
  }
7672
7933
  }
7673
7934
 
7674
- function closeAgentEnvModal() {
7675
- if (!agentEnvModal) return
7676
- agentEnvModal.classList.remove('is-open')
7677
- agentEnvModal.setAttribute('aria-hidden', 'true')
7678
- document.body.style.overflow = ''
7679
- if (agentEnvModalCard) {
7680
- agentEnvModalCard.removeAttribute('aria-label')
7681
- agentEnvModalCard.setAttribute('aria-labelledby', 'agentEnvModalTitle')
7682
- }
7683
- if (agentEnvSessionTabStrip) agentEnvSessionTabStrip.setAttribute('hidden', '')
7684
- if (agentEnvSessionTabList) agentEnvSessionTabList.innerHTML = ''
7685
- }
7686
-
7687
7935
  function syncAgentEnvTabPanels() {
7688
- if (!agentEnvPanelEnv || !agentEnvPanelAgentMd || !agentEnvPanelSettings) return
7689
- agentEnvPanelEnv.hidden = agentEnvActiveTab !== 'env'
7936
+ if (!agentEnvPanelUnified || !agentEnvPanelAgentMd) return
7937
+ agentEnvPanelUnified.hidden = agentEnvActiveTab !== 'settings'
7690
7938
  agentEnvPanelAgentMd.hidden = agentEnvActiveTab !== 'agentMd'
7691
- agentEnvPanelSettings.hidden = agentEnvActiveTab !== 'settings'
7692
- }
7693
- function renderAgentEnvHeaderTabs() {
7694
- renderHeaderTabsIn(
7695
- agentEnvSessionTabList,
7696
- [
7697
- { id: 'env', label: '环境变量' },
7698
- { id: 'agentMd', label: '编辑 agent.md' },
7699
- { id: 'settings', label: '设置' },
7700
- ],
7701
- agentEnvActiveTab,
7702
- function (id) {
7703
- agentEnvActiveTab = id
7704
- renderAgentEnvHeaderTabs()
7939
+ }
7940
+
7941
+ /** 渲染左侧配置导航(样式对齐文件管理目录树) */
7942
+ function renderAgentSettingsNav() {
7943
+ if (!agentEnvSessionTabList) return
7944
+ agentEnvSessionTabList.innerHTML = ''
7945
+ const tabs = [
7946
+ { id: 'settings', label: '设置' },
7947
+ { id: 'agentMd', label: '编辑 agent.md' },
7948
+ ]
7949
+ for (let i = 0; i < tabs.length; i++) {
7950
+ const tab = tabs[i]
7951
+ const btn = document.createElement('button')
7952
+ btn.type = 'button'
7953
+ btn.className =
7954
+ 'agent-settings-nav-item' + (tab.id === agentEnvActiveTab ? ' is-selected' : '')
7955
+ btn.setAttribute('role', 'tab')
7956
+ btn.setAttribute('aria-selected', tab.id === agentEnvActiveTab ? 'true' : 'false')
7957
+ btn.textContent = tab.label
7958
+ btn.addEventListener('click', function () {
7959
+ if (agentEnvActiveTab === tab.id) return
7960
+ agentEnvActiveTab = tab.id
7961
+ renderAgentSettingsNav()
7705
7962
  syncAgentEnvTabPanels()
7706
- },
7707
- )
7963
+ if (tab.id === 'agentMd') {
7964
+ void loadAgentEnvAgentMdFromApi()
7965
+ }
7966
+ })
7967
+ agentEnvSessionTabList.appendChild(btn)
7968
+ }
7708
7969
  }
7709
7970
 
7710
7971
  function loadAgentEnvAgentMdFromApi() {
@@ -7755,27 +8016,21 @@
7755
8016
  })
7756
8017
  }
7757
8018
 
7758
- function openAgentEnvModal(initialTab) {
7759
- if (!agentEnvModal) return
7760
- if (initialTab === 'env' || initialTab === 'agentMd' || initialTab === 'settings') {
8019
+ function openAgentSettingsView(initialTab) {
8020
+ if (!agentSettingsView) return
8021
+ closeRepoManageView()
8022
+ if (initialTab === 'agentMd' || initialTab === 'settings') {
7761
8023
  agentEnvActiveTab = initialTab
7762
8024
  } else {
7763
- agentEnvActiveTab = 'env'
8025
+ agentEnvActiveTab = 'settings'
7764
8026
  }
7765
8027
  const envObj =
7766
8028
  agentConfigState.env && typeof agentConfigState.env === 'object'
7767
8029
  ? agentConfigState.env
7768
8030
  : {}
7769
8031
  agentEnvFieldValues = buildAgentEnvFieldValues(envObj)
7770
- if (agentEnvModalCard) {
7771
- agentEnvModalCard.setAttribute('aria-label', '环境变量、编辑 agent.md 与设置')
7772
- agentEnvModalCard.removeAttribute('aria-labelledby')
7773
- }
7774
- if (agentEnvSessionTabStrip) {
7775
- agentEnvSessionTabStrip.setAttribute('aria-label', '环境变量、编辑 agent.md、设置')
7776
- agentEnvSessionTabStrip.removeAttribute('hidden')
7777
- }
7778
- /** 每次打开设置弹窗都拉最新 schema,避免后端新增字段后页面仍用旧缓存。 */
8032
+ setAgentSettingsVisible(true)
8033
+ /** 每次进入设置页都拉最新 schema,避免后端新增字段后页面仍用旧缓存。 */
7779
8034
  void loadProjectEnvDefaults().then(function () {
7780
8035
  const latestEnvObj =
7781
8036
  agentConfigState.env && typeof agentConfigState.env === 'object'
@@ -7784,104 +8039,188 @@
7784
8039
  agentEnvFieldValues = buildAgentEnvFieldValues(latestEnvObj)
7785
8040
  renderAgentEnvList()
7786
8041
  })
7787
- renderAgentEnvHeaderTabs()
8042
+ renderAgentSettingsNav()
7788
8043
  syncAgentEnvTabPanels()
7789
- agentEnvModal.classList.add('is-open')
7790
- agentEnvModal.setAttribute('aria-hidden', 'false')
7791
- document.body.style.overflow = 'hidden'
8044
+ initLlmProvidersSettingsUi()
7792
8045
  renderAgentEnvList()
7793
- if (agentEnvWhenToUseInput) {
7794
- agentEnvWhenToUseInput.value = typeof agentConfigState.whentouse === 'string'
8046
+ const whenInput = queryAgentEnvWhenToUseInput()
8047
+ if (whenInput) {
8048
+ whenInput.value = typeof agentConfigState.whentouse === 'string'
7795
8049
  ? agentConfigState.whentouse
7796
8050
  : ''
7797
8051
  }
7798
- if (agentEnvAgentTypeInput) {
7799
- agentEnvAgentTypeInput.value = currentAgentParam()
7800
- }
7801
- if (agentEnvToolsInput) {
7802
- agentEnvToolsInput.value = Array.isArray(agentConfigState.tools)
7803
- ? agentConfigState.tools.join('\n')
7804
- : ''
7805
- }
7806
- if (agentEnvModelInput) {
7807
- agentEnvModelInput.value = typeof agentConfigState.model === 'string'
7808
- ? agentConfigState.model
7809
- : ''
7810
- }
7811
- syncAgentEffortSelectValue(agentConfigState.effort)
7812
- if (agentEnvBackgroundInput) {
7813
- agentEnvBackgroundInput.value = agentConfigState.background === true ? 'true' : 'false'
7814
- }
7815
- if (agentEnvIsolationInput) {
7816
- const nextIsolation =
7817
- agentConfigState.isolation === 'worktree' || agentConfigState.isolation === 'remote'
7818
- ? agentConfigState.isolation
7819
- : ''
7820
- agentEnvIsolationInput.value = nextIsolation
7821
- }
7822
- void renderAgentEnvTeamMembers()
7823
8052
  void loadAgentEnvAgentMdFromApi()
7824
8053
  }
7825
8054
 
7826
8055
  /**
7827
- * effort 下拉框值转换为后端可接受的类型。
7828
- * 业务逻辑:
7829
- * 1) 空值表示不设置 effort,统一写回 null;
7830
- * 2) low/medium/high/max 直接透传;
7831
- * 3) 兼容历史整数值(旧版本允许手输整数),继续转成 number 写回;
7832
- * 4) 其他值视为非法,阻止保存并提示。
8056
+ * 深拷贝 agent.json.llmProviders 到设置页草稿。
7833
8057
  */
7834
- function parseAgentEffortFromInput(raw) {
7835
- const v = String(raw || '').trim()
7836
- if (!v) {
7837
- return { ok: true, value: null }
8058
+ function cloneLlmProvidersDraft(raw) {
8059
+ const list = Array.isArray(raw) ? raw : []
8060
+ return list.map(function (p) {
8061
+ const models = Array.isArray(p.models) ? p.models : []
8062
+ return {
8063
+ id: typeof p.id === 'string' ? p.id.trim() : '',
8064
+ name: typeof p.name === 'string' ? p.name.trim() : '',
8065
+ baseUrl: typeof p.baseUrl === 'string' ? p.baseUrl.trim() : '',
8066
+ apiKey: typeof p.apiKey === 'string' ? p.apiKey : '',
8067
+ authToken: typeof p.authToken === 'string' ? p.authToken : '',
8068
+ provider: p.provider === 'anthropic' ? 'anthropic' : 'openai',
8069
+ models: models.map(function (m) {
8070
+ return {
8071
+ id: typeof m.id === 'string' ? m.id.trim() : '',
8072
+ label: typeof m.label === 'string' ? m.label.trim() : '',
8073
+ }
8074
+ }),
8075
+ defaultModel: typeof p.defaultModel === 'string' ? p.defaultModel.trim() : '',
8076
+ }
8077
+ })
8078
+ }
8079
+
8080
+ function clearLlmProviderForm() {
8081
+ if (llmFormId) llmFormId.value = ''
8082
+ if (llmFormName) llmFormName.value = ''
8083
+ if (llmFormProvider) llmFormProvider.value = 'openai'
8084
+ if (llmFormBaseUrl) llmFormBaseUrl.value = ''
8085
+ if (llmFormApiKey) llmFormApiKey.value = ''
8086
+ if (llmFormAuthToken) llmFormAuthToken.value = ''
8087
+ if (llmFormModelId) llmFormModelId.value = ''
8088
+ if (llmFormModelLabel) llmFormModelLabel.value = ''
8089
+ }
8090
+
8091
+ /**
8092
+ * 从添加表单读取一条服务商配置;校验失败返回错误文案。
8093
+ */
8094
+ function readLlmProviderFromForm() {
8095
+ const id = llmFormId ? String(llmFormId.value || '').trim() : ''
8096
+ const name = llmFormName ? String(llmFormName.value || '').trim() : ''
8097
+ const provider =
8098
+ llmFormProvider && llmFormProvider.value === 'anthropic' ? 'anthropic' : 'openai'
8099
+ const baseUrl = llmFormBaseUrl ? String(llmFormBaseUrl.value || '').trim() : ''
8100
+ const apiKey = llmFormApiKey ? String(llmFormApiKey.value || '').trim() : ''
8101
+ const authToken = llmFormAuthToken ? String(llmFormAuthToken.value || '').trim() : ''
8102
+ const modelId = llmFormModelId ? String(llmFormModelId.value || '').trim() : ''
8103
+ const modelLabel = llmFormModelLabel ? String(llmFormModelLabel.value || '').trim() : ''
8104
+ if (!id) return { ok: false, message: '请填写服务商 ID' }
8105
+ if (!/^[A-Za-z0-9_-]+$/.test(id)) {
8106
+ return { ok: false, message: '服务商 id 仅允许字母数字下划线中划线' }
8107
+ }
8108
+ if (llmProvidersDraft.some(function (p) {
8109
+ return p.id === id
8110
+ })) {
8111
+ return { ok: false, message: '服务商 id 已存在: ' + id }
8112
+ }
8113
+ if (!name) return { ok: false, message: '请填写展示名称' }
8114
+ if (!baseUrl) return { ok: false, message: '请填写 Base URL' }
8115
+ if (!apiKey && !authToken) {
8116
+ return { ok: false, message: 'API Key 与 Auth Token 至少填写一项' }
8117
+ }
8118
+ if (!modelId) return { ok: false, message: '请填写模型 ID' }
8119
+ return {
8120
+ ok: true,
8121
+ entry: {
8122
+ id: id,
8123
+ name: name,
8124
+ baseUrl: baseUrl,
8125
+ apiKey: apiKey,
8126
+ authToken: authToken,
8127
+ provider: provider,
8128
+ models: [{ id: modelId, label: modelLabel }],
8129
+ defaultModel: modelId,
8130
+ },
7838
8131
  }
7839
- const lower = v.toLowerCase()
7840
- if (lower === 'low' || lower === 'medium' || lower === 'high' || lower === 'max') {
7841
- return { ok: true, value: lower }
8132
+ }
8133
+
8134
+ function renderLlmProvidersList() {
8135
+ if (!llmProvidersList) return
8136
+ llmProvidersList.innerHTML = ''
8137
+ if (llmProvidersEmptyHint) {
8138
+ llmProvidersEmptyHint.hidden = llmProvidersDraft.length > 0
7842
8139
  }
7843
- if (/^-?\d+$/.test(v)) {
7844
- return { ok: true, value: Number(v) }
8140
+ for (let i = 0; i < llmProvidersDraft.length; i++) {
8141
+ const p = llmProvidersDraft[i]
8142
+ const li = document.createElement('li')
8143
+ li.className = 'llm-provider-list-item'
8144
+
8145
+ const nameWrap = document.createElement('span')
8146
+ nameWrap.className = 'llm-provider-list-name'
8147
+ nameWrap.textContent = p.name || p.id
8148
+ if (i === 0) {
8149
+ const badge = document.createElement('span')
8150
+ badge.className = 'llm-provider-list-default'
8151
+ badge.textContent = '默认'
8152
+ nameWrap.appendChild(badge)
8153
+ }
8154
+
8155
+ const removeBtn = document.createElement('button')
8156
+ removeBtn.type = 'button'
8157
+ removeBtn.className = 'llm-provider-list-remove'
8158
+ removeBtn.textContent = '删除'
8159
+ removeBtn.addEventListener('click', function () {
8160
+ llmProvidersDraft.splice(i, 1)
8161
+ renderLlmProvidersList()
8162
+ })
8163
+
8164
+ li.appendChild(nameWrap)
8165
+ li.appendChild(removeBtn)
8166
+ llmProvidersList.appendChild(li)
7845
8167
  }
7846
- return { ok: false, message: 'effort 仅支持 low/medium/high/max 或整数' }
8168
+ }
8169
+
8170
+ function initLlmProvidersSettingsUi() {
8171
+ llmProvidersDraft = cloneLlmProvidersDraft(agentConfigState.llmProviders)
8172
+ clearLlmProviderForm()
8173
+ renderLlmProvidersList()
7847
8174
  }
7848
8175
 
7849
8176
  /**
7850
- * 同步 effort 下拉框可选项并回填当前值。
7851
- * 业务逻辑:
7852
- * 1) 常规场景只展示固定档位(low/medium/high/max);
7853
- * 2) 若 agent.json 中已有历史整数值,为避免用户打开弹窗后被意外清空,
7854
- * 动态追加一个“当前值”选项用于承载该值;
7855
- * 3) 每次打开弹窗先清理旧的动态选项,防止重复追加。
8177
+ * 保存前校验 llmProviders 草稿;首项为默认厂商,允许空数组。
7856
8178
  */
7857
- function syncAgentEffortSelectValue(rawEffort) {
7858
- if (!agentEnvEffortInput) return
7859
- const dynamicOptions = agentEnvEffortInput.querySelectorAll('option[data-dynamic-effort="true"]')
7860
- dynamicOptions.forEach(function (opt) {
7861
- if (opt && opt.parentNode) {
7862
- opt.parentNode.removeChild(opt)
8179
+ function validateLlmProvidersDraftForSave(providers) {
8180
+ const list = Array.isArray(providers) ? providers : []
8181
+ if (!list.length) return ''
8182
+ const seenIds = new Set()
8183
+ for (let i = 0; i < list.length; i++) {
8184
+ const p = list[i]
8185
+ const id = String(p.id || '').trim()
8186
+ if (!id) return '第 ' + (i + 1) + ' 个服务商缺少 id'
8187
+ if (!/^[A-Za-z0-9_-]+$/.test(id)) {
8188
+ return '服务商 id "' + id + '" 仅允许字母数字下划线中划线'
8189
+ }
8190
+ if (seenIds.has(id)) return '服务商 id 重复: ' + id
8191
+ seenIds.add(id)
8192
+ if (!String(p.name || '').trim()) return '服务商 "' + id + '" 缺少展示名称'
8193
+ if (!String(p.baseUrl || '').trim()) return '服务商 "' + id + '" 缺少 baseUrl'
8194
+ if (p.provider !== 'anthropic' && p.provider !== 'openai') {
8195
+ return '服务商 "' + id + '" 协议类型非法'
8196
+ }
8197
+ const apiKeyOk =
8198
+ p.apiKey === LLM_MASKED_CREDENTIAL || String(p.apiKey || '').trim().length > 0
8199
+ const authTokenOk =
8200
+ p.authToken === LLM_MASKED_CREDENTIAL ||
8201
+ String(p.authToken || '').trim().length > 0
8202
+ if (!apiKeyOk && !authTokenOk) {
8203
+ return '服务商 "' + id + '" 需配置 API Key 或 Auth Token 至少一项'
8204
+ }
8205
+ if (!Array.isArray(p.models) || p.models.length === 0) {
8206
+ return '服务商 "' + id + '" 至少配置 1 个模型'
8207
+ }
8208
+ for (let j = 0; j < p.models.length; j++) {
8209
+ if (!String(p.models[j].id || '').trim()) {
8210
+ return '服务商 "' + id + '" 第 ' + (j + 1) + ' 个模型缺少 id'
8211
+ }
7863
8212
  }
7864
- })
7865
- if (rawEffort === null || rawEffort === undefined || String(rawEffort).trim() === '') {
7866
- agentEnvEffortInput.value = 'low'
7867
- return
7868
- }
7869
- const raw = String(rawEffort).trim()
7870
- const lower = raw.toLowerCase()
7871
- if (lower === 'low' || lower === 'medium' || lower === 'high' || lower === 'max') {
7872
- agentEnvEffortInput.value = lower
7873
- return
7874
- }
7875
- if (/^-?\d+$/.test(raw)) {
7876
- const opt = document.createElement('option')
7877
- opt.value = raw
7878
- opt.textContent = '当前值:' + raw + '(历史整数)'
7879
- opt.setAttribute('data-dynamic-effort', 'true')
7880
- agentEnvEffortInput.appendChild(opt)
7881
- agentEnvEffortInput.value = raw
7882
- return
8213
+ const defaultModel = String(p.defaultModel || '').trim() || p.models[0].id
8214
+ if (
8215
+ !p.models.some(function (m) {
8216
+ return m.id === defaultModel
8217
+ })
8218
+ ) {
8219
+ return '服务商 "' + id + '" 默认模型不在模型列表中'
8220
+ }
8221
+ p.defaultModel = defaultModel
7883
8222
  }
7884
- agentEnvEffortInput.value = 'low'
8223
+ return ''
7885
8224
  }
7886
8225
 
7887
8226
  function openAgentMdModal() {
@@ -7955,30 +8294,11 @@
7955
8294
  btnAgentEnvSave.disabled = true
7956
8295
  }
7957
8296
  try {
7958
- const whentouseValue = agentEnvWhenToUseInput
7959
- ? String(agentEnvWhenToUseInput.value || '')
7960
- : ''
7961
- const nextModel = agentEnvModelInput
7962
- ? String(agentEnvModelInput.value || '').trim()
7963
- : ''
7964
- const effortParsed = parseAgentEffortFromInput(
7965
- agentEnvEffortInput ? agentEnvEffortInput.value : '',
7966
- )
7967
- if (!effortParsed.ok) {
7968
- window.alert(effortParsed.message)
7969
- return
7970
- }
7971
- const nextBackground =
7972
- agentEnvBackgroundInput && agentEnvBackgroundInput.value === 'true'
7973
- const nextIsolationRaw = agentEnvIsolationInput
7974
- ? String(agentEnvIsolationInput.value || '').trim()
7975
- : ''
7976
- if (
7977
- nextIsolationRaw !== '' &&
7978
- nextIsolationRaw !== 'worktree' &&
7979
- nextIsolationRaw !== 'remote'
7980
- ) {
7981
- window.alert('isolation 仅支持 worktree/remote 或留空')
8297
+ const whenInput = queryAgentEnvWhenToUseInput()
8298
+ const whentouseValue = whenInput ? String(whenInput.value || '') : ''
8299
+ const llmErr = validateLlmProvidersDraftForSave(llmProvidersDraft)
8300
+ if (llmErr) {
8301
+ window.alert('LLM:' + llmErr)
7982
8302
  return
7983
8303
  }
7984
8304
  const patchBody = {
@@ -7988,12 +8308,17 @@
7988
8308
  mcpServers: agentConfigState.mcpServers.slice(),
7989
8309
  skills: agentConfigState.skills.slice(),
7990
8310
  agentTeams: agentConfigState.agentTeams.slice(),
7991
- model: nextModel,
7992
- effort: effortParsed.value,
7993
- background: nextBackground,
7994
- isolation: nextIsolationRaw,
8311
+ model: typeof agentConfigState.model === 'string' ? agentConfigState.model : '',
8312
+ effort: agentConfigState.effort,
8313
+ background: agentConfigState.background === true,
8314
+ isolation:
8315
+ agentConfigState.isolation === 'worktree' ||
8316
+ agentConfigState.isolation === 'remote'
8317
+ ? agentConfigState.isolation
8318
+ : '',
7995
8319
  whentouse: whentouseValue,
7996
8320
  env: checked.env,
8321
+ llmProviders: cloneLlmProvidersDraft(llmProvidersDraft),
7997
8322
  },
7998
8323
  }
7999
8324
  const includeAgentMd =
@@ -8010,14 +8335,14 @@
8010
8335
  return {}
8011
8336
  })
8012
8337
  if (!r.ok) {
8013
- window.alert('保存失败:' + (body.message || body.error || r.statusText))
8338
+ window.alert(
8339
+ 'Agent 配置保存失败:' + (body.message || body.error || r.statusText),
8340
+ )
8014
8341
  return
8015
8342
  }
8343
+ void refreshModelCatalogFromApi(true)
8016
8344
  agentConfigState.env = Object.assign({}, checked.env)
8017
- agentConfigState.model = nextModel
8018
- agentConfigState.effort = effortParsed.value
8019
- agentConfigState.background = nextBackground
8020
- agentConfigState.isolation = nextIsolationRaw
8345
+ agentConfigState.llmProviders = cloneLlmProvidersDraft(llmProvidersDraft)
8021
8346
  agentConfigState.whentouse = whentouseValue
8022
8347
  syncPermissionModeSelectFromState()
8023
8348
  if (includeAgentMd) {
@@ -8029,15 +8354,15 @@
8029
8354
  window.alert('已保存到磁盘,但同步提示词到当前连接失败: ' + e)
8030
8355
  }
8031
8356
  }
8032
- restartCurrentSessionSubprocessWithReason('save-agent-env-prompt')
8357
+ restartCurrentSessionSubprocessWithReason('save-agent-settings-prompt')
8033
8358
  } else {
8034
- restartCurrentSessionSubprocessWithReason('save-agent-env')
8359
+ restartCurrentSessionSubprocessWithReason('save-agent-settings')
8035
8360
  }
8036
- closeAgentEnvModal()
8361
+ closeAgentSettingsView()
8037
8362
  setStatus('已保存', serverReady ? 'ready' : '')
8038
8363
  window.alert('已保存到磁盘,并已重连 / 尝试同步当前 session。')
8039
8364
  } catch (e) {
8040
- window.alert('保存失败: ' + e)
8365
+ window.alert(String(e && e.message ? e.message : e))
8041
8366
  } finally {
8042
8367
  if (btnAgentEnvSave) {
8043
8368
  btnAgentEnvSave.disabled = false
@@ -8083,7 +8408,7 @@
8083
8408
  }
8084
8409
  if (btnEditAgentEnv) {
8085
8410
  btnEditAgentEnv.addEventListener('click', function () {
8086
- openAgentEnvModal('env')
8411
+ openAgentSettingsView('settings')
8087
8412
  })
8088
8413
  }
8089
8414
  if (btnSkillPackageManager) {
@@ -8332,23 +8657,24 @@
8332
8657
  openToolFilesModal()
8333
8658
  })
8334
8659
  }
8335
- if (btnAgentEnvModalClose) {
8336
- btnAgentEnvModalClose.addEventListener('click', closeAgentEnvModal)
8337
- }
8338
8660
  if (btnAgentEnvCancel) {
8339
- btnAgentEnvCancel.addEventListener('click', closeAgentEnvModal)
8340
- }
8341
- if (agentEnvModalBackdrop) {
8342
- agentEnvModalBackdrop.addEventListener('click', closeAgentEnvModal)
8661
+ btnAgentEnvCancel.addEventListener('click', closeAgentSettingsView)
8343
8662
  }
8344
8663
  if (btnAgentEnvSave) {
8345
8664
  btnAgentEnvSave.addEventListener('click', function () {
8346
8665
  void saveAgentEnvAndReconnect()
8347
8666
  })
8348
8667
  }
8349
- if (btnAgentEnvAddTeamMember) {
8350
- btnAgentEnvAddTeamMember.addEventListener('click', function () {
8351
- void addAgentEnvTeamMember()
8668
+ if (btnLlmProvidersAdd) {
8669
+ btnLlmProvidersAdd.addEventListener('click', function () {
8670
+ const parsed = readLlmProviderFromForm()
8671
+ if (!parsed.ok) {
8672
+ window.alert(parsed.message)
8673
+ return
8674
+ }
8675
+ llmProvidersDraft.push(parsed.entry)
8676
+ clearLlmProviderForm()
8677
+ renderLlmProvidersList()
8352
8678
  })
8353
8679
  }
8354
8680
  if (btnAgentMdModalClose) {
@@ -8416,10 +8742,6 @@
8416
8742
  closeSkillMdModal()
8417
8743
  return
8418
8744
  }
8419
- if (agentEnvModal && agentEnvModal.classList.contains('is-open')) {
8420
- closeAgentEnvModal()
8421
- return
8422
- }
8423
8745
  if (scheduleRunsModal && scheduleRunsModal.classList.contains('is-open')) {
8424
8746
  closeScheduleRunsModal()
8425
8747
  return
@@ -8469,6 +8791,9 @@
8469
8791
  void bootstrapSessionSelection()
8470
8792
  void refreshModelCatalogFromApi(true)
8471
8793
  void loadAgentConfig()
8794
+ if (isAgentSettingsViewActive()) {
8795
+ openAgentSettingsView(agentEnvActiveTab)
8796
+ }
8472
8797
  }
8473
8798
  if (agentIdInput) {
8474
8799
  agentIdInput.addEventListener('change', onAgentChanged)