ai-agent-router 0.2.0 → 0.2.2

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 (354) hide show
  1. package/.next/BUILD_ID +1 -1
  2. package/.next/app-path-routes-manifest.json +14 -0
  3. package/.next/build-manifest.json +2 -2
  4. package/.next/fallback-build-manifest.json +2 -2
  5. package/.next/next-server.js.nft.json +1 -1
  6. package/.next/prerender-manifest.json +3 -3
  7. package/.next/required-server-files.js +4 -4
  8. package/.next/required-server-files.json +4 -4
  9. package/.next/routes-manifest.json +84 -0
  10. package/.next/server/app/_global-error/page.js +1 -1
  11. package/.next/server/app/_global-error/page.js.nft.json +1 -1
  12. package/.next/server/app/_global-error.html +2 -2
  13. package/.next/server/app/_global-error.rsc +1 -1
  14. package/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  15. package/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  16. package/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  17. package/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  18. package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  19. package/.next/server/app/_not-found/page.js +2 -2
  20. package/.next/server/app/_not-found/page.js.nft.json +1 -1
  21. package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  22. package/.next/server/app/_not-found.html +1 -1
  23. package/.next/server/app/_not-found.rsc +2 -2
  24. package/.next/server/app/_not-found.segments/_full.segment.rsc +2 -2
  25. package/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  26. package/.next/server/app/_not-found.segments/_index.segment.rsc +2 -2
  27. package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  28. package/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  29. package/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  30. package/.next/server/app/api/config/route.js.nft.json +1 -1
  31. package/.next/server/app/api/gateway/[...path]/route.js.nft.json +1 -1
  32. package/.next/server/app/api/gateway/models/route.js.nft.json +1 -1
  33. package/.next/server/app/api/gateway/route.js.nft.json +1 -1
  34. package/.next/server/app/api/ide/claude/apply/route.js.nft.json +1 -1
  35. package/.next/server/app/api/ide/claude/available-models/route.js.nft.json +1 -1
  36. package/.next/server/app/api/ide/claude/restore/route.js.nft.json +1 -1
  37. package/.next/server/app/api/ide/claude/save/route.js.nft.json +1 -1
  38. package/.next/server/app/api/ide/claude/status/route.js.nft.json +1 -1
  39. package/.next/server/app/api/ide/claude/test/route.js +1 -1
  40. package/.next/server/app/api/ide/claude/test/route.js.nft.json +1 -1
  41. package/.next/server/app/api/ide/openclaw/apply/route/app-paths-manifest.json +3 -0
  42. package/.next/server/app/api/ide/openclaw/apply/route/build-manifest.json +11 -0
  43. package/.next/server/app/api/ide/openclaw/apply/route/server-reference-manifest.json +4 -0
  44. package/.next/server/app/api/ide/openclaw/apply/route.js +7 -0
  45. package/.next/server/app/api/ide/openclaw/apply/route.js.map +5 -0
  46. package/.next/server/app/api/ide/openclaw/apply/route.js.nft.json +1 -0
  47. package/.next/server/app/api/ide/openclaw/apply/route_client-reference-manifest.js +2 -0
  48. package/.next/server/app/api/ide/openclaw/available-models/route/app-paths-manifest.json +3 -0
  49. package/.next/server/app/api/ide/openclaw/available-models/route/build-manifest.json +11 -0
  50. package/.next/server/app/api/ide/openclaw/available-models/route/server-reference-manifest.json +4 -0
  51. package/.next/server/app/api/ide/openclaw/available-models/route.js +7 -0
  52. package/.next/server/app/api/ide/openclaw/available-models/route.js.map +5 -0
  53. package/.next/server/app/api/ide/openclaw/available-models/route.js.nft.json +1 -0
  54. package/.next/server/app/api/ide/openclaw/available-models/route_client-reference-manifest.js +2 -0
  55. package/.next/server/app/api/ide/openclaw/preview/route/app-paths-manifest.json +3 -0
  56. package/.next/server/app/api/ide/openclaw/preview/route/build-manifest.json +11 -0
  57. package/.next/server/app/api/ide/openclaw/preview/route/server-reference-manifest.json +4 -0
  58. package/.next/server/app/api/ide/openclaw/preview/route.js +7 -0
  59. package/.next/server/app/api/ide/openclaw/preview/route.js.map +5 -0
  60. package/.next/server/app/api/ide/openclaw/preview/route.js.nft.json +1 -0
  61. package/.next/server/app/api/ide/openclaw/preview/route_client-reference-manifest.js +2 -0
  62. package/.next/server/app/api/ide/openclaw/restore/route/app-paths-manifest.json +3 -0
  63. package/.next/server/app/api/ide/openclaw/restore/route/build-manifest.json +11 -0
  64. package/.next/server/app/api/ide/openclaw/restore/route/server-reference-manifest.json +4 -0
  65. package/.next/server/app/api/ide/openclaw/restore/route.js +6 -0
  66. package/.next/server/app/api/ide/openclaw/restore/route.js.map +5 -0
  67. package/.next/server/app/api/ide/openclaw/restore/route.js.nft.json +1 -0
  68. package/.next/server/app/api/ide/openclaw/restore/route_client-reference-manifest.js +2 -0
  69. package/.next/server/app/api/ide/openclaw/save/route/app-paths-manifest.json +3 -0
  70. package/.next/server/app/api/ide/openclaw/save/route/build-manifest.json +11 -0
  71. package/.next/server/app/api/ide/openclaw/save/route/server-reference-manifest.json +4 -0
  72. package/.next/server/app/api/ide/openclaw/save/route.js +7 -0
  73. package/.next/server/app/api/ide/openclaw/save/route.js.map +5 -0
  74. package/.next/server/app/api/ide/openclaw/save/route.js.nft.json +1 -0
  75. package/.next/server/app/api/ide/openclaw/save/route_client-reference-manifest.js +2 -0
  76. package/.next/server/app/api/ide/openclaw/status/route/app-paths-manifest.json +3 -0
  77. package/.next/server/app/api/ide/openclaw/status/route/build-manifest.json +11 -0
  78. package/.next/server/app/api/ide/openclaw/status/route/server-reference-manifest.json +4 -0
  79. package/.next/server/app/api/ide/openclaw/status/route.js +7 -0
  80. package/.next/server/app/api/ide/openclaw/status/route.js.map +5 -0
  81. package/.next/server/app/api/ide/openclaw/status/route.js.nft.json +1 -0
  82. package/.next/server/app/api/ide/openclaw/status/route_client-reference-manifest.js +2 -0
  83. package/.next/server/app/api/ide/openclaw/test/route/app-paths-manifest.json +3 -0
  84. package/.next/server/app/api/ide/openclaw/test/route/build-manifest.json +11 -0
  85. package/.next/server/app/api/ide/openclaw/test/route/server-reference-manifest.json +4 -0
  86. package/.next/server/app/api/ide/openclaw/test/route.js +6 -0
  87. package/.next/server/app/api/ide/openclaw/test/route.js.map +5 -0
  88. package/.next/server/app/api/ide/openclaw/test/route.js.nft.json +1 -0
  89. package/.next/server/app/api/ide/openclaw/test/route_client-reference-manifest.js +2 -0
  90. package/.next/server/app/api/ide/opencode/apply/route/app-paths-manifest.json +3 -0
  91. package/.next/server/app/api/ide/opencode/apply/route/build-manifest.json +11 -0
  92. package/.next/server/app/api/ide/opencode/apply/route/server-reference-manifest.json +4 -0
  93. package/.next/server/app/api/ide/opencode/apply/route.js +7 -0
  94. package/.next/server/app/api/ide/opencode/apply/route.js.map +5 -0
  95. package/.next/server/app/api/ide/opencode/apply/route.js.nft.json +1 -0
  96. package/.next/server/app/api/ide/opencode/apply/route_client-reference-manifest.js +2 -0
  97. package/.next/server/app/api/ide/opencode/available-models/route/app-paths-manifest.json +3 -0
  98. package/.next/server/app/api/ide/opencode/available-models/route/build-manifest.json +11 -0
  99. package/.next/server/app/api/ide/opencode/available-models/route/server-reference-manifest.json +4 -0
  100. package/.next/server/app/api/ide/opencode/available-models/route.js +7 -0
  101. package/.next/server/app/api/ide/opencode/available-models/route.js.map +5 -0
  102. package/.next/server/app/api/ide/opencode/available-models/route.js.nft.json +1 -0
  103. package/.next/server/app/api/ide/opencode/available-models/route_client-reference-manifest.js +2 -0
  104. package/.next/server/app/api/ide/opencode/preview/route/app-paths-manifest.json +3 -0
  105. package/.next/server/app/api/ide/opencode/preview/route/build-manifest.json +11 -0
  106. package/.next/server/app/api/ide/opencode/preview/route/server-reference-manifest.json +4 -0
  107. package/.next/server/app/api/ide/opencode/preview/route.js +7 -0
  108. package/.next/server/app/api/ide/opencode/preview/route.js.map +5 -0
  109. package/.next/server/app/api/ide/opencode/preview/route.js.nft.json +1 -0
  110. package/.next/server/app/api/ide/opencode/preview/route_client-reference-manifest.js +2 -0
  111. package/.next/server/app/api/ide/opencode/restore/route/app-paths-manifest.json +3 -0
  112. package/.next/server/app/api/ide/opencode/restore/route/build-manifest.json +11 -0
  113. package/.next/server/app/api/ide/opencode/restore/route/server-reference-manifest.json +4 -0
  114. package/.next/server/app/api/ide/opencode/restore/route.js +6 -0
  115. package/.next/server/app/api/ide/opencode/restore/route.js.map +5 -0
  116. package/.next/server/app/api/ide/opencode/restore/route.js.nft.json +1 -0
  117. package/.next/server/app/api/ide/opencode/restore/route_client-reference-manifest.js +2 -0
  118. package/.next/server/app/api/ide/opencode/save/route/app-paths-manifest.json +3 -0
  119. package/.next/server/app/api/ide/opencode/save/route/build-manifest.json +11 -0
  120. package/.next/server/app/api/ide/opencode/save/route/server-reference-manifest.json +4 -0
  121. package/.next/server/app/api/ide/opencode/save/route.js +7 -0
  122. package/.next/server/app/api/ide/opencode/save/route.js.map +5 -0
  123. package/.next/server/app/api/ide/opencode/save/route.js.nft.json +1 -0
  124. package/.next/server/app/api/ide/opencode/save/route_client-reference-manifest.js +2 -0
  125. package/.next/server/app/api/ide/opencode/status/route/app-paths-manifest.json +3 -0
  126. package/.next/server/app/api/ide/opencode/status/route/build-manifest.json +11 -0
  127. package/.next/server/app/api/ide/opencode/status/route/server-reference-manifest.json +4 -0
  128. package/.next/server/app/api/ide/opencode/status/route.js +7 -0
  129. package/.next/server/app/api/ide/opencode/status/route.js.map +5 -0
  130. package/.next/server/app/api/ide/opencode/status/route.js.nft.json +1 -0
  131. package/.next/server/app/api/ide/opencode/status/route_client-reference-manifest.js +2 -0
  132. package/.next/server/app/api/ide/opencode/test/route/app-paths-manifest.json +3 -0
  133. package/.next/server/app/api/ide/opencode/test/route/build-manifest.json +11 -0
  134. package/.next/server/app/api/ide/opencode/test/route/server-reference-manifest.json +4 -0
  135. package/.next/server/app/api/ide/opencode/test/route.js +6 -0
  136. package/.next/server/app/api/ide/opencode/test/route.js.map +5 -0
  137. package/.next/server/app/api/ide/opencode/test/route.js.nft.json +1 -0
  138. package/.next/server/app/api/ide/opencode/test/route_client-reference-manifest.js +2 -0
  139. package/.next/server/app/api/logs/route.js.nft.json +1 -1
  140. package/.next/server/app/api/models/route.js.nft.json +1 -1
  141. package/.next/server/app/api/providers/route.js.nft.json +1 -1
  142. package/.next/server/app/api/providers/test/route.js.nft.json +1 -1
  143. package/.next/server/app/api/service/force-stop/route.js.nft.json +1 -1
  144. package/.next/server/app/api/service/start/route.js.nft.json +1 -1
  145. package/.next/server/app/api/service/status/route.js.nft.json +1 -1
  146. package/.next/server/app/api/service/stop/route.js.nft.json +1 -1
  147. package/.next/server/app/ide/page.js +2 -2
  148. package/.next/server/app/ide/page.js.nft.json +1 -1
  149. package/.next/server/app/ide/page_client-reference-manifest.js +1 -1
  150. package/.next/server/app/ide.html +1 -1
  151. package/.next/server/app/ide.rsc +3 -3
  152. package/.next/server/app/ide.segments/_full.segment.rsc +3 -3
  153. package/.next/server/app/ide.segments/_head.segment.rsc +1 -1
  154. package/.next/server/app/ide.segments/_index.segment.rsc +2 -2
  155. package/.next/server/app/ide.segments/_tree.segment.rsc +2 -2
  156. package/.next/server/app/ide.segments/ide/__PAGE__.segment.rsc +2 -2
  157. package/.next/server/app/ide.segments/ide.segment.rsc +1 -1
  158. package/.next/server/app/index.html +1 -1
  159. package/.next/server/app/index.rsc +2 -2
  160. package/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  161. package/.next/server/app/index.segments/_full.segment.rsc +2 -2
  162. package/.next/server/app/index.segments/_head.segment.rsc +1 -1
  163. package/.next/server/app/index.segments/_index.segment.rsc +2 -2
  164. package/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  165. package/.next/server/app/logs/page.js +2 -2
  166. package/.next/server/app/logs/page.js.nft.json +1 -1
  167. package/.next/server/app/logs/page_client-reference-manifest.js +1 -1
  168. package/.next/server/app/logs.html +1 -1
  169. package/.next/server/app/logs.rsc +3 -3
  170. package/.next/server/app/logs.segments/_full.segment.rsc +3 -3
  171. package/.next/server/app/logs.segments/_head.segment.rsc +1 -1
  172. package/.next/server/app/logs.segments/_index.segment.rsc +2 -2
  173. package/.next/server/app/logs.segments/_tree.segment.rsc +2 -2
  174. package/.next/server/app/logs.segments/logs/__PAGE__.segment.rsc +2 -2
  175. package/.next/server/app/logs.segments/logs.segment.rsc +1 -1
  176. package/.next/server/app/models/page.js +2 -2
  177. package/.next/server/app/models/page.js.nft.json +1 -1
  178. package/.next/server/app/models/page_client-reference-manifest.js +1 -1
  179. package/.next/server/app/models.html +1 -1
  180. package/.next/server/app/models.rsc +2 -2
  181. package/.next/server/app/models.segments/_full.segment.rsc +2 -2
  182. package/.next/server/app/models.segments/_head.segment.rsc +1 -1
  183. package/.next/server/app/models.segments/_index.segment.rsc +2 -2
  184. package/.next/server/app/models.segments/_tree.segment.rsc +2 -2
  185. package/.next/server/app/models.segments/models/__PAGE__.segment.rsc +1 -1
  186. package/.next/server/app/models.segments/models.segment.rsc +1 -1
  187. package/.next/server/app/page.js +2 -2
  188. package/.next/server/app/page.js.nft.json +1 -1
  189. package/.next/server/app/page_client-reference-manifest.js +1 -1
  190. package/.next/server/app/providers/page.js +2 -2
  191. package/.next/server/app/providers/page.js.nft.json +1 -1
  192. package/.next/server/app/providers/page_client-reference-manifest.js +1 -1
  193. package/.next/server/app/providers.html +1 -1
  194. package/.next/server/app/providers.rsc +2 -2
  195. package/.next/server/app/providers.segments/_full.segment.rsc +2 -2
  196. package/.next/server/app/providers.segments/_head.segment.rsc +1 -1
  197. package/.next/server/app/providers.segments/_index.segment.rsc +2 -2
  198. package/.next/server/app/providers.segments/_tree.segment.rsc +2 -2
  199. package/.next/server/app/providers.segments/providers/__PAGE__.segment.rsc +1 -1
  200. package/.next/server/app/providers.segments/providers.segment.rsc +1 -1
  201. package/.next/server/app-paths-manifest.json +14 -0
  202. package/.next/server/chunks/[root-of-the-server]__001d5756._.js +3 -0
  203. package/.next/server/chunks/[root-of-the-server]__001d5756._.js.map +1 -0
  204. package/.next/server/chunks/[root-of-the-server]__05f8578b._.js +3 -0
  205. package/.next/server/chunks/[root-of-the-server]__05f8578b._.js.map +1 -0
  206. package/.next/server/chunks/[root-of-the-server]__3a204d25._.js +1 -1
  207. package/.next/server/chunks/[root-of-the-server]__3a204d25._.js.map +1 -1
  208. package/.next/server/chunks/[root-of-the-server]__43810962._.js +3 -0
  209. package/.next/server/chunks/[root-of-the-server]__43810962._.js.map +1 -0
  210. package/.next/server/chunks/[root-of-the-server]__4a8f9bc7._.js +1 -1
  211. package/.next/server/chunks/[root-of-the-server]__4a8f9bc7._.js.map +1 -1
  212. package/.next/server/chunks/[root-of-the-server]__55cd88b8._.js +3 -0
  213. package/.next/server/chunks/[root-of-the-server]__55cd88b8._.js.map +1 -0
  214. package/.next/server/chunks/[root-of-the-server]__5e8276bc._.js +1 -1
  215. package/.next/server/chunks/[root-of-the-server]__5e8276bc._.js.map +1 -1
  216. package/.next/server/chunks/[root-of-the-server]__760eaa16._.js +3 -0
  217. package/.next/server/chunks/[root-of-the-server]__760eaa16._.js.map +1 -0
  218. package/.next/server/chunks/[root-of-the-server]__7c298a19._.js +3 -0
  219. package/.next/server/chunks/[root-of-the-server]__7c298a19._.js.map +1 -0
  220. package/.next/server/chunks/[root-of-the-server]__85540228._.js +3 -0
  221. package/.next/server/chunks/[root-of-the-server]__85540228._.js.map +1 -0
  222. package/.next/server/chunks/[root-of-the-server]__94fe8d3c._.js +3 -0
  223. package/.next/server/chunks/[root-of-the-server]__94fe8d3c._.js.map +1 -0
  224. package/.next/server/chunks/[root-of-the-server]__97622908._.js +3 -0
  225. package/.next/server/chunks/[root-of-the-server]__97622908._.js.map +1 -0
  226. package/.next/server/chunks/[root-of-the-server]__a02e6618._.js +3 -0
  227. package/.next/server/chunks/[root-of-the-server]__a02e6618._.js.map +1 -0
  228. package/.next/server/chunks/[root-of-the-server]__a32a20a7._.js +3 -0
  229. package/.next/server/chunks/[root-of-the-server]__a32a20a7._.js.map +1 -0
  230. package/.next/server/chunks/[root-of-the-server]__af5b556a._.js +3 -0
  231. package/.next/server/chunks/[root-of-the-server]__af5b556a._.js.map +1 -0
  232. package/.next/server/chunks/[root-of-the-server]__c1b4b601._.js +16 -16
  233. package/.next/server/chunks/[root-of-the-server]__c1b4b601._.js.map +1 -1
  234. package/.next/server/chunks/[root-of-the-server]__cafe113e._.js +3 -0
  235. package/.next/server/chunks/[root-of-the-server]__cafe113e._.js.map +1 -0
  236. package/.next/server/chunks/[root-of-the-server]__dc8b0bed._.js +3 -0
  237. package/.next/server/chunks/[root-of-the-server]__dc8b0bed._.js.map +1 -0
  238. package/.next/server/chunks/[root-of-the-server]__f0461b8d._.js +1 -1
  239. package/.next/server/chunks/[root-of-the-server]__f0461b8d._.js.map +1 -1
  240. package/.next/server/chunks/[root-of-the-server]__f8949f88._.js +1 -1
  241. package/.next/server/chunks/[root-of-the-server]__f8949f88._.js.map +1 -1
  242. package/.next/server/chunks/_next-internal_server_app_api_ide_openclaw_apply_route_actions_2cb9e4b4.js +3 -0
  243. package/.next/server/chunks/_next-internal_server_app_api_ide_openclaw_apply_route_actions_2cb9e4b4.js.map +1 -0
  244. package/.next/server/chunks/_next-internal_server_app_api_ide_openclaw_preview_route_actions_9814a8e4.js +3 -0
  245. package/.next/server/chunks/_next-internal_server_app_api_ide_openclaw_preview_route_actions_9814a8e4.js.map +1 -0
  246. package/.next/server/chunks/_next-internal_server_app_api_ide_openclaw_restore_route_actions_10ad8f9d.js +3 -0
  247. package/.next/server/chunks/_next-internal_server_app_api_ide_openclaw_restore_route_actions_10ad8f9d.js.map +1 -0
  248. package/.next/server/chunks/_next-internal_server_app_api_ide_openclaw_save_route_actions_044ad081.js +3 -0
  249. package/.next/server/chunks/_next-internal_server_app_api_ide_openclaw_save_route_actions_044ad081.js.map +1 -0
  250. package/.next/server/chunks/_next-internal_server_app_api_ide_openclaw_status_route_actions_ed9786d2.js +3 -0
  251. package/.next/server/chunks/_next-internal_server_app_api_ide_openclaw_status_route_actions_ed9786d2.js.map +1 -0
  252. package/.next/server/chunks/_next-internal_server_app_api_ide_openclaw_test_route_actions_ce2cb808.js +3 -0
  253. package/.next/server/chunks/_next-internal_server_app_api_ide_openclaw_test_route_actions_ce2cb808.js.map +1 -0
  254. package/.next/server/chunks/_next-internal_server_app_api_ide_opencode_apply_route_actions_6c422244.js +3 -0
  255. package/.next/server/chunks/_next-internal_server_app_api_ide_opencode_apply_route_actions_6c422244.js.map +1 -0
  256. package/.next/server/chunks/_next-internal_server_app_api_ide_opencode_preview_route_actions_256c82e0.js +3 -0
  257. package/.next/server/chunks/_next-internal_server_app_api_ide_opencode_preview_route_actions_256c82e0.js.map +1 -0
  258. package/.next/server/chunks/_next-internal_server_app_api_ide_opencode_restore_route_actions_371993d3.js +3 -0
  259. package/.next/server/chunks/_next-internal_server_app_api_ide_opencode_restore_route_actions_371993d3.js.map +1 -0
  260. package/.next/server/chunks/_next-internal_server_app_api_ide_opencode_save_route_actions_6e4c9c41.js +3 -0
  261. package/.next/server/chunks/_next-internal_server_app_api_ide_opencode_save_route_actions_6e4c9c41.js.map +1 -0
  262. package/.next/server/chunks/_next-internal_server_app_api_ide_opencode_status_route_actions_498ad77b.js +3 -0
  263. package/.next/server/chunks/_next-internal_server_app_api_ide_opencode_status_route_actions_498ad77b.js.map +1 -0
  264. package/.next/server/chunks/_next-internal_server_app_api_ide_opencode_test_route_actions_c71be510.js +3 -0
  265. package/.next/server/chunks/_next-internal_server_app_api_ide_opencode_test_route_actions_c71be510.js.map +1 -0
  266. package/.next/server/chunks/ce889_server_app_api_ide_openclaw_available-models_route_actions_e568e70b.js +3 -0
  267. package/.next/server/chunks/ce889_server_app_api_ide_openclaw_available-models_route_actions_e568e70b.js.map +1 -0
  268. package/.next/server/chunks/ce889_server_app_api_ide_opencode_available-models_route_actions_95230db3.js +3 -0
  269. package/.next/server/chunks/ce889_server_app_api_ide_opencode_available-models_route_actions_95230db3.js.map +1 -0
  270. package/.next/server/chunks/ssr/{[root-of-the-server]__bec95712._.js → [root-of-the-server]__81937253._.js} +2 -2
  271. package/.next/server/chunks/ssr/{[root-of-the-server]__bec95712._.js.map → [root-of-the-server]__81937253._.js.map} +1 -1
  272. package/.next/server/chunks/ssr/{[root-of-the-server]__71c85955._.js → [root-of-the-server]__976ad963._.js} +2 -2
  273. package/.next/server/chunks/ssr/{[root-of-the-server]__71c85955._.js.map → [root-of-the-server]__976ad963._.js.map} +1 -1
  274. package/.next/server/chunks/ssr/_69468f4c._.js +3 -0
  275. package/.next/server/chunks/ssr/_69468f4c._.js.map +1 -0
  276. package/.next/server/chunks/ssr/src_app_ide_page_tsx_8962793b._.js +1 -1
  277. package/.next/server/chunks/ssr/src_app_ide_page_tsx_8962793b._.js.map +1 -1
  278. package/.next/server/chunks/ssr/src_app_logs_page_tsx_7b7b7b83._.js +1 -1
  279. package/.next/server/chunks/ssr/src_app_logs_page_tsx_7b7b7b83._.js.map +1 -1
  280. package/.next/server/pages/404.html +1 -1
  281. package/.next/server/pages/500.html +2 -2
  282. package/.next/server/server-reference-manifest.js +1 -1
  283. package/.next/server/server-reference-manifest.json +1 -1
  284. package/.next/static/chunks/64f547b3bcd3aef4.js +1 -0
  285. package/.next/static/chunks/6992685fe009e8fd.css +1 -0
  286. package/.next/static/chunks/{b6b258e8582e47c4.js → 7c8b7cbb3339f139.js} +1 -1
  287. package/.next/static/chunks/8ccc14e022ff6de3.js +1 -0
  288. package/.next/types/routes.d.ts +15 -1
  289. package/.next/types/validator.ts +126 -0
  290. package/README.md +31 -4
  291. package/dist/.next/dev/types/validator.js +56 -0
  292. package/dist/.next/types/validator.js +56 -0
  293. package/dist/package.json +55 -0
  294. package/dist/src/app/api/config/route.js +17 -0
  295. package/dist/src/app/api/ide/claude/apply/route.js +126 -31
  296. package/dist/src/app/api/ide/claude/restore/route.js +30 -0
  297. package/dist/src/app/api/ide/claude/save/route.js +79 -0
  298. package/dist/src/app/api/ide/claude/status/route.js +6 -1
  299. package/dist/src/app/api/ide/openclaw/apply/route.js +92 -0
  300. package/dist/src/app/api/ide/openclaw/available-models/route.js +46 -0
  301. package/dist/src/app/api/ide/openclaw/build-config.js +101 -0
  302. package/dist/src/app/api/ide/openclaw/preview/route.js +49 -0
  303. package/dist/src/app/api/ide/openclaw/restore/route.js +24 -0
  304. package/dist/src/app/api/ide/openclaw/save/route.js +54 -0
  305. package/dist/src/app/api/ide/openclaw/status/route.js +139 -0
  306. package/dist/src/app/api/ide/openclaw/test/route.js +158 -0
  307. package/dist/src/app/api/ide/opencode/apply/route.js +89 -0
  308. package/dist/src/app/api/ide/opencode/available-models/route.js +46 -0
  309. package/dist/src/app/api/ide/opencode/build-config.js +54 -0
  310. package/dist/src/app/api/ide/opencode/preview/route.js +36 -0
  311. package/dist/src/app/api/ide/opencode/restore/route.js +40 -0
  312. package/dist/src/app/api/ide/opencode/save/route.js +123 -0
  313. package/dist/src/app/api/ide/opencode/status/route.js +106 -0
  314. package/dist/src/app/api/ide/opencode/test/route.js +136 -0
  315. package/dist/src/app/components/Footer.js +11 -0
  316. package/dist/src/app/ide/page.js +651 -81
  317. package/dist/src/app/layout.js +5 -1
  318. package/dist/src/app/logs/page.js +4 -2
  319. package/dist/src/db/database.js +44 -8
  320. package/package.json +1 -1
  321. package/src/app/api/config/route.ts +17 -0
  322. package/src/app/api/ide/claude/apply/route.ts +140 -31
  323. package/src/app/api/ide/claude/restore/route.ts +36 -1
  324. package/src/app/api/ide/claude/save/route.ts +91 -1
  325. package/src/app/api/ide/claude/status/route.ts +12 -2
  326. package/src/app/api/ide/openclaw/apply/route.ts +103 -0
  327. package/src/app/api/ide/openclaw/available-models/route.ts +59 -0
  328. package/src/app/api/ide/openclaw/build-config.ts +152 -0
  329. package/src/app/api/ide/openclaw/preview/route.ts +57 -0
  330. package/src/app/api/ide/openclaw/restore/route.ts +27 -0
  331. package/src/app/api/ide/openclaw/save/route.ts +67 -0
  332. package/src/app/api/ide/openclaw/status/route.ts +178 -0
  333. package/src/app/api/ide/openclaw/test/route.ts +194 -0
  334. package/src/app/api/ide/opencode/apply/route.ts +92 -0
  335. package/src/app/api/ide/opencode/available-models/route.ts +59 -0
  336. package/src/app/api/ide/opencode/build-config.ts +69 -0
  337. package/src/app/api/ide/opencode/preview/route.ts +40 -0
  338. package/src/app/api/ide/opencode/restore/route.ts +52 -0
  339. package/src/app/api/ide/opencode/save/route.ts +131 -0
  340. package/src/app/api/ide/opencode/status/route.ts +128 -0
  341. package/src/app/api/ide/opencode/test/route.ts +145 -0
  342. package/src/app/components/Footer.tsx +9 -0
  343. package/src/app/globals.css +17 -0
  344. package/src/app/ide/page.tsx +1587 -118
  345. package/src/app/layout.tsx +3 -1
  346. package/src/app/logs/page.tsx +4 -2
  347. package/src/db/database.ts +55 -8
  348. package/.next/server/chunks/ssr/src_app_b2b1d928._.js +0 -3
  349. package/.next/server/chunks/ssr/src_app_b2b1d928._.js.map +0 -1
  350. package/.next/static/chunks/6418ca50028376b7.css +0 -1
  351. package/.next/static/chunks/9ec3b97741b6575e.js +0 -1
  352. /package/.next/static/{ryTeHAYUvjT1bYolc-x9Z → cf2SWIkI5HVbnDjLExI42}/_buildManifest.js +0 -0
  353. /package/.next/static/{ryTeHAYUvjT1bYolc-x9Z → cf2SWIkI5HVbnDjLExI42}/_clientMiddlewareManifest.json +0 -0
  354. /package/.next/static/{ryTeHAYUvjT1bYolc-x9Z → cf2SWIkI5HVbnDjLExI42}/_ssgManifest.js +0 -0
@@ -1,14 +1,18 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
6
  exports.metadata = void 0;
4
7
  exports.default = RootLayout;
5
8
  const jsx_runtime_1 = require("react/jsx-runtime");
6
9
  require("./globals.css");
7
10
  const ToastProvider_1 = require("./components/ToastProvider");
11
+ const Footer_1 = __importDefault(require("./components/Footer"));
8
12
  exports.metadata = {
9
13
  title: 'AAR - AI Agent Router',
10
14
  description: 'Unified API gateway for managing multiple AI model providers',
11
15
  };
12
16
  function RootLayout({ children, }) {
13
- return ((0, jsx_runtime_1.jsx)("html", { lang: "zh-CN", suppressHydrationWarning: true, children: (0, jsx_runtime_1.jsx)("body", { children: (0, jsx_runtime_1.jsx)(ToastProvider_1.ToastProvider, { children: children }) }) }));
17
+ return ((0, jsx_runtime_1.jsx)("html", { lang: "zh-CN", suppressHydrationWarning: true, children: (0, jsx_runtime_1.jsxs)("body", { className: "pb-10", children: [(0, jsx_runtime_1.jsx)(ToastProvider_1.ToastProvider, { children: children }), (0, jsx_runtime_1.jsx)(Footer_1.default, {})] }) }));
14
18
  }
@@ -10,15 +10,17 @@ const react_1 = require("react");
10
10
  const Nav_1 = __importDefault(require("../components/Nav"));
11
11
  const ToastProvider_1 = require("../components/ToastProvider");
12
12
  const ConfirmDialog_1 = __importDefault(require("../components/ConfirmDialog"));
13
- /** 将服务端返回的 created_at 格式化为本地显示。无时区后缀时按 UTC 解析再转本地,避免差 8 小时。 */
13
+ /** 将服务端返回的 created_at 格式化为本地显示。数据库存储的是本地时间,无需追加 Z 后缀。 */
14
14
  function formatCreatedAt(createdAt) {
15
15
  if (!createdAt || typeof createdAt !== 'string')
16
16
  return '';
17
17
  const s = createdAt.trim();
18
18
  if (!s)
19
19
  return '';
20
+ // 数据库使用 datetime('now','localtime') 存储的已经是本地时间,
21
+ // 不带时区后缀时直接按本地时间解析,不要追加 'Z'(否则会多偏移 8 小时)
20
22
  const hasTz = /[Z+-]\d{2}:?\d{2}$/.test(s);
21
- const iso = hasTz ? s : s.replace(' ', 'T') + 'Z';
23
+ const iso = hasTz ? s : s.replace(' ', 'T');
22
24
  const date = new Date(iso);
23
25
  return Number.isNaN(date.getTime()) ? s : date.toLocaleString('zh-CN');
24
26
  }
@@ -14,12 +14,39 @@ const schema_1 = require("./schema");
14
14
  const path_1 = __importDefault(require("path"));
15
15
  const fs_1 = __importDefault(require("fs"));
16
16
  const os_1 = __importDefault(require("os"));
17
+ const crypto_1 = __importDefault(require("crypto"));
17
18
  const DB_PATH = process.env.DB_PATH || path_1.default.join(os_1.default.homedir(), '.aar', 'gateway.db');
19
+ /**
20
+ * 生成随机的 API Key(用于网关密码默认值)
21
+ */
22
+ function generateRandomApiKey() {
23
+ return `aar-${crypto_1.default.randomBytes(16).toString('hex')}`;
24
+ }
25
+ // Use hardcoded path for the built/distributed WASM file
26
+ // Next.js copies sql-wasm.wasm to its chunks directory
27
+ function findSqlJsWasmPath() {
28
+ // Try Next.js chunks directory first (works in dev and production)
29
+ const nextChunksPath = path_1.default.join(process.cwd(), '.next', 'dev', 'server', 'chunks', 'sql-wasm.wasm');
30
+ if (fs_1.default.existsSync(nextChunksPath)) {
31
+ return nextChunksPath;
32
+ }
33
+ // Try production .next directory
34
+ const prodChunksPath = path_1.default.join(process.cwd(), '.next', 'server', 'chunks', 'sql-wasm.wasm');
35
+ if (fs_1.default.existsSync(prodChunksPath)) {
36
+ return prodChunksPath;
37
+ }
38
+ // Try node_modules as fallback
39
+ const nodeModulesPath = path_1.default.join(process.cwd(), 'node_modules', 'sql.js', 'dist', 'sql-wasm.wasm');
40
+ if (fs_1.default.existsSync(nodeModulesPath)) {
41
+ return nodeModulesPath;
42
+ }
43
+ // Use the most likely location as default
44
+ return nodeModulesPath;
45
+ }
46
+ const SQLJS_WASM_PATH = findSqlJsWasmPath();
18
47
  let dbInstance = null;
19
48
  let sqlJsInstance = null;
20
- /** 上次从磁盘加载 DB 的时间(用于多进程时发现磁盘被其他进程更新则重新加载) */
21
49
  let lastLoadMtimeMs = 0;
22
- /** 若磁盘上的 DB 被其他进程更新则重新加载,以便读到最新数据 */
23
50
  function reloadFromFileIfNewer() {
24
51
  if (!dbInstance || !fs_1.default.existsSync(DB_PATH))
25
52
  return;
@@ -43,7 +70,7 @@ async function initSqlJsEngine() {
43
70
  sqlJsInstance = await (0, sql_js_1.default)({
44
71
  locateFile: (file) => {
45
72
  if (file.endsWith('.wasm')) {
46
- return path_1.default.join(process.cwd(), 'node_modules', 'sql.js', 'dist', file);
73
+ return SQLJS_WASM_PATH;
47
74
  }
48
75
  return `https://sql.js.org/dist/${file}`;
49
76
  }
@@ -84,6 +111,7 @@ async function getDatabase() {
84
111
  if (!dbInstance) {
85
112
  const engine = await initSqlJsEngine();
86
113
  const loaded = loadDatabase();
114
+ let isNewDatabase = false;
87
115
  if (loaded) {
88
116
  dbInstance = loaded;
89
117
  if (fs_1.default.existsSync(DB_PATH))
@@ -92,7 +120,9 @@ async function getDatabase() {
92
120
  else {
93
121
  dbInstance = new engine.Database();
94
122
  lastLoadMtimeMs = 0;
123
+ isNewDatabase = true; // 标记为新数据库
95
124
  }
125
+ let migrationPerformed = false;
96
126
  try {
97
127
  dbInstance.run(schema_1.CREATE_TABLES_SQL);
98
128
  // Migration: Allow NULL model_id in request_logs table
@@ -124,7 +154,7 @@ async function getDatabase() {
124
154
  dbInstance.run(`INSERT INTO request_logs_new SELECT * FROM request_logs;`);
125
155
  dbInstance.run(`DROP TABLE request_logs;`);
126
156
  dbInstance.run(`ALTER TABLE request_logs_new RENAME TO request_logs;`);
127
- saveDatabase(dbInstance);
157
+ migrationPerformed = true;
128
158
  console.log('[Database] Migration completed successfully');
129
159
  }
130
160
  }
@@ -137,7 +167,16 @@ async function getDatabase() {
137
167
  console.warn('[Database] Migration warning (non-critical):', migrationError.message);
138
168
  }
139
169
  }
140
- saveDatabase(dbInstance);
170
+ // 只在新数据库创建或执行了 migration 时才保存,避免覆盖现有数据
171
+ if (isNewDatabase || migrationPerformed) {
172
+ // 为新数据库初始化默认的 api_key
173
+ if (isNewDatabase) {
174
+ const defaultApiKey = generateRandomApiKey();
175
+ dbInstance.run(`INSERT OR IGNORE INTO config (key, value, updated_at) VALUES ('api_key', ?, datetime('now'))`, [defaultApiKey]);
176
+ console.log('[Database] Generated default API key for new database');
177
+ }
178
+ saveDatabase(dbInstance);
179
+ }
141
180
  }
142
181
  catch (schemaError) {
143
182
  if (!schemaError.message.includes('already exists') &&
@@ -159,7 +198,6 @@ async function closeDatabase() {
159
198
  function getDbPath() {
160
199
  return DB_PATH;
161
200
  }
162
- // Helper to run a query and get single result
163
201
  async function queryOne(sql, params = []) {
164
202
  const db = await getDatabase();
165
203
  const stmt = db.prepare(sql);
@@ -172,7 +210,6 @@ async function queryOne(sql, params = []) {
172
210
  stmt.free();
173
211
  return null;
174
212
  }
175
- // Helper to run a query and get all results
176
213
  async function queryAll(sql, params = []) {
177
214
  const db = await getDatabase();
178
215
  const results = [];
@@ -184,7 +221,6 @@ async function queryAll(sql, params = []) {
184
221
  stmt.free();
185
222
  return results;
186
223
  }
187
- // Helper to run INSERT/UPDATE/DELETE
188
224
  async function run(sql, params = []) {
189
225
  const db = await getDatabase();
190
226
  db.run(sql, params);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-agent-router",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "description": "A unified API gateway for managing multiple AI model providers (Anthropic, OpenAI, Gemini, etc.)",
5
5
  "main": "dist/src/cli/index.js",
6
6
  "bin": {
@@ -1,10 +1,18 @@
1
1
  import { NextRequest, NextResponse } from 'next/server';
2
2
  import { getDatabase } from '@/db/database';
3
3
  import { getConfig, setConfig, getAllConfig } from '@/db/queries';
4
+ import crypto from 'crypto';
4
5
 
5
6
  // Ensure Node.js runtime (required for SQLite)
6
7
  export const runtime = 'nodejs';
7
8
 
9
+ /**
10
+ * 生成随机的 API Key(用于网关密码默认值)
11
+ */
12
+ function generateRandomApiKey(): string {
13
+ return `aar-${crypto.randomBytes(16).toString('hex')}`;
14
+ }
15
+
8
16
  export async function GET(request: NextRequest) {
9
17
  try {
10
18
  // Initialize database on request (safer than module load)
@@ -25,6 +33,15 @@ export async function GET(request: NextRequest) {
25
33
  }
26
34
 
27
35
  const configs = await getAllConfig();
36
+
37
+ // 如果 api_key 为空,生成一个随机默认值
38
+ if (!configs.api_key) {
39
+ const defaultApiKey = generateRandomApiKey();
40
+ await setConfig('api_key', defaultApiKey);
41
+ configs.api_key = defaultApiKey;
42
+ console.log('[Config API] Generated default API key');
43
+ }
44
+
28
45
  return NextResponse.json(configs);
29
46
  } catch (error: any) {
30
47
  console.error('Config API error:', error);
@@ -10,6 +10,12 @@ const CLAUDE_DIR = join(homedir(), '.claude');
10
10
  const SETTINGS_FILE = join(CLAUDE_DIR, 'settings.json');
11
11
  const BACKUP_FILE = join(CLAUDE_DIR, 'settings.json.aar.bak');
12
12
 
13
+ // Claude 登录配置文件(用于 hasCompletedOnboarding)
14
+ const CLAUDE_JSON_FILE = join(homedir(), '.claude.json');
15
+
16
+ // AAR 备份目录
17
+ const AAR_BACKUP_DIR = join(homedir(), '.aar', 'backups');
18
+
13
19
  // 默认模型映射
14
20
  const DEFAULT_MODEL_MAPPING = {
15
21
  haiku: 'GLM-4.5-air',
@@ -38,11 +44,20 @@ export async function POST(request: NextRequest) {
38
44
  const gatewayAddress = await getGatewayAddress();
39
45
  const gatewayApiKey = await getGatewayApiKey();
40
46
 
41
- // 生成配置对象
42
47
  const modelMapping = { haiku, sonnet, opus, default: defaultModel, reasoning: reasoningModel };
43
- const config = generateClaudeConfig(gatewayAddress, gatewayApiKey, modelMapping);
48
+ const aarEnv = buildAarEnv(gatewayAddress, gatewayApiKey, modelMapping);
49
+
50
+ // 在修改配置前,先备份到 ~/.aar/backups 目录
51
+ const settingsBackup = backupToAar(SETTINGS_FILE, 'settings');
52
+ const claudeJsonBackup = backupToAar(CLAUDE_JSON_FILE, 'claude');
53
+
54
+ if (!settingsBackup.success) {
55
+ console.warn('[Claude Apply] Settings backup warning:', settingsBackup.error);
56
+ }
57
+ if (!claudeJsonBackup.success) {
58
+ console.warn('[Claude Apply] Claude.json backup warning:', claudeJsonBackup.error);
59
+ }
44
60
 
45
- // 备份原有配置
46
61
  const backupResult = backupOriginalConfig();
47
62
  if (!backupResult.success) {
48
63
  return NextResponse.json(
@@ -51,13 +66,27 @@ export async function POST(request: NextRequest) {
51
66
  );
52
67
  }
53
68
 
54
- // 确保目录存在
55
69
  if (!existsSync(CLAUDE_DIR)) {
56
70
  mkdirSync(CLAUDE_DIR, { recursive: true });
57
71
  }
58
72
 
59
- // 验证并写入新配置
60
- const validationResult = validateAndWriteConfig(config);
73
+ let configToWrite: any;
74
+ if (existsSync(SETTINGS_FILE)) {
75
+ try {
76
+ const existing = JSON.parse(readFileSync(SETTINGS_FILE, 'utf-8'));
77
+ configToWrite = {
78
+ ...existing,
79
+ env: { ...(existing.env || {}), ...aarEnv },
80
+ router_provider: 'aar',
81
+ };
82
+ } catch {
83
+ configToWrite = generateClaudeConfig(gatewayAddress, gatewayApiKey, modelMapping);
84
+ }
85
+ } else {
86
+ configToWrite = generateClaudeConfig(gatewayAddress, gatewayApiKey, modelMapping);
87
+ }
88
+
89
+ const validationResult = validateAndWriteConfig(configToWrite);
61
90
  if (!validationResult.success) {
62
91
  return NextResponse.json(
63
92
  { error: validationResult.error },
@@ -65,12 +94,23 @@ export async function POST(request: NextRequest) {
65
94
  );
66
95
  }
67
96
 
97
+ // 处理 ~/.claude.json,确保包含 hasCompletedOnboarding: true
98
+ const onboardingResult = ensureClaudeOnboarding();
99
+ if (!onboardingResult.success) {
100
+ console.warn('[Claude Apply] Onboarding update warning:', onboardingResult.error);
101
+ }
102
+
68
103
  return NextResponse.json({
69
104
  success: true,
70
105
  message: 'Configuration applied successfully',
71
- config,
106
+ config: configToWrite,
72
107
  backup: backupResult.existed ? 'Created backup' : 'No existing config to backup',
73
108
  previousWasFromAar: backupResult.existed && backupResult.isFromAar,
109
+ onboarding: onboardingResult.created ? 'Created ~/.claude.json' : 'Updated ~/.claude.json',
110
+ aarBackups: {
111
+ settings: settingsBackup.backupPath,
112
+ claudeJson: claudeJsonBackup.backupPath,
113
+ },
74
114
  });
75
115
  } catch (error: any) {
76
116
  console.error('IDE Apply API error:', error);
@@ -101,57 +141,60 @@ async function getGatewayApiKey(): Promise<string> {
101
141
  return apiKeyConfig?.value || 'your-gateway-api-key';
102
142
  }
103
143
 
104
- /**
105
- * 生成 Claude 配置
106
- */
144
+ /** 仅生成 AAR 相关的 env 字段,用于合并到现有配置 */
145
+ function buildAarEnv(
146
+ gatewayAddress: string,
147
+ gatewayApiKey: string,
148
+ modelMapping: { haiku: string; sonnet: string; opus: string; default: string; reasoning: string }
149
+ ): Record<string, unknown> {
150
+ return {
151
+ ANTHROPIC_AUTH_TOKEN: gatewayApiKey,
152
+ ANTHROPIC_BASE_URL: gatewayAddress,
153
+ ANTHROPIC_DEFAULT_HAIKU_MODEL: modelMapping.haiku,
154
+ ANTHROPIC_DEFAULT_OPUS_MODEL: modelMapping.opus,
155
+ ANTHROPIC_DEFAULT_SONNET_MODEL: modelMapping.sonnet,
156
+ ANTHROPIC_MODEL: modelMapping.default,
157
+ ANTHROPIC_REASONING_MODEL: modelMapping.reasoning,
158
+ API_TIMEOUT_MS: '3000000',
159
+ CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC: 1,
160
+ hasCompletedOnboarding: true,
161
+ };
162
+ }
163
+
164
+ /** 生成完整 Claude 配置(仅在无现有文件时使用) */
107
165
  function generateClaudeConfig(
108
166
  gatewayAddress: string,
109
167
  gatewayApiKey: string,
110
168
  modelMapping: { haiku: string; sonnet: string; opus: string; default: string; reasoning: string }
111
169
  ): any {
112
170
  return {
113
- // 路由提供者标识,标识配置来自当前工具 aar
114
171
  router_provider: 'aar',
115
- env: {
116
- ANTHROPIC_AUTH_TOKEN: gatewayApiKey,
117
- ANTHROPIC_BASE_URL: gatewayAddress,
118
- ANTHROPIC_DEFAULT_HAIKU_MODEL: modelMapping.haiku,
119
- ANTHROPIC_DEFAULT_OPUS_MODEL: modelMapping.opus,
120
- ANTHROPIC_DEFAULT_SONNET_MODEL: modelMapping.sonnet,
121
- ANTHROPIC_MODEL: modelMapping.default,
122
- ANTHROPIC_REASONING_MODEL: modelMapping.reasoning,
123
- API_TIMEOUT_MS: '3000000',
124
- CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC: 1,
125
- hasCompletedOnboarding: true,
126
- },
172
+ env: buildAarEnv(gatewayAddress, gatewayApiKey, modelMapping),
127
173
  };
128
174
  }
129
175
 
130
176
  /**
131
177
  * 备份原有配置
132
- * 返回原有配置是否来自当前工具(router_provider === 'aar')
178
+ * 仅在当前配置不是 AAR 时写入备份,这样「还原」才能恢复到应用 AAR 前的状态
133
179
  */
134
180
  function backupOriginalConfig(): { success: boolean; existed: boolean; isFromAar: boolean; error?: string } {
135
181
  try {
136
- // 检查原有配置是否存在
137
182
  const existing = existsSync(SETTINGS_FILE);
138
183
 
139
184
  if (existing) {
140
- // 读取原有配置
141
185
  const originalConfig = readFileSync(SETTINGS_FILE, 'utf-8');
142
186
 
143
- // 解析配置检查 router_provider
144
187
  let isFromAar = false;
145
188
  try {
146
189
  const parsedConfig = JSON.parse(originalConfig);
147
190
  isFromAar = parsedConfig.router_provider === 'aar';
148
- } catch (error) {
149
- // 解析失败,不影响备份操作
191
+ } catch {
150
192
  isFromAar = false;
151
193
  }
152
194
 
153
- // 写入备份文件
154
- writeFileSync(BACKUP_FILE, originalConfig, 'utf-8');
195
+ if (!isFromAar) {
196
+ writeFileSync(BACKUP_FILE, originalConfig, 'utf-8');
197
+ }
155
198
 
156
199
  return { success: true, existed: true, isFromAar };
157
200
  }
@@ -189,3 +232,69 @@ function validateAndWriteConfig(config: any): { success: boolean; error?: string
189
232
  };
190
233
  }
191
234
  }
235
+
236
+ /**
237
+ * 备份文件到 ~/.aar/backups 目录
238
+ */
239
+ function backupToAar(filePath: string, backupName: string): { success: boolean; backupPath?: string; error?: string } {
240
+ try {
241
+ if (!existsSync(filePath)) {
242
+ return { success: true }; // 文件不存在,无需备份
243
+ }
244
+
245
+ if (!existsSync(AAR_BACKUP_DIR)) {
246
+ mkdirSync(AAR_BACKUP_DIR, { recursive: true });
247
+ }
248
+
249
+ const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
250
+ const backupPath = join(AAR_BACKUP_DIR, `${backupName}-${timestamp}.json`);
251
+ copyFileSync(filePath, backupPath);
252
+
253
+ return { success: true, backupPath };
254
+ } catch (error: any) {
255
+ return {
256
+ success: false,
257
+ error: `Backup to AAR failed: ${error.message}`,
258
+ };
259
+ }
260
+ }
261
+
262
+ /**
263
+ * 确保 ~/.claude.json 文件中包含 hasCompletedOnboarding: true
264
+ * 这允许用户跳过 Claude 登录使用自定义模型
265
+ */
266
+ function ensureClaudeOnboarding(): { success: boolean; created: boolean; error?: string } {
267
+ try {
268
+ let config: any = {};
269
+ let created = false;
270
+
271
+ if (existsSync(CLAUDE_JSON_FILE)) {
272
+ try {
273
+ const content = readFileSync(CLAUDE_JSON_FILE, 'utf-8');
274
+ config = JSON.parse(content);
275
+ } catch {
276
+ // 文件存在但解析失败,使用空对象
277
+ config = {};
278
+ }
279
+ } else {
280
+ created = true;
281
+ }
282
+
283
+ // 检查是否已经有 hasCompletedOnboarding
284
+ if (config.hasCompletedOnboarding === true) {
285
+ return { success: true, created: false };
286
+ }
287
+
288
+ // 添加 hasCompletedOnboarding
289
+ config.hasCompletedOnboarding = true;
290
+ writeFileSync(CLAUDE_JSON_FILE, JSON.stringify(config, null, 2), 'utf-8');
291
+
292
+ return { success: true, created };
293
+ } catch (error: any) {
294
+ return {
295
+ success: false,
296
+ created: false,
297
+ error: `Failed to update claude.json: ${error.message}`,
298
+ };
299
+ }
300
+ }
@@ -1,5 +1,5 @@
1
1
  import { NextRequest, NextResponse } from 'next/server';
2
- import { existsSync, readFileSync, copyFileSync, unlinkSync } from 'fs';
2
+ import { existsSync, readFileSync, copyFileSync, unlinkSync, mkdirSync } from 'fs';
3
3
  import { join } from 'path';
4
4
  import { homedir } from 'os';
5
5
 
@@ -8,6 +8,9 @@ const CLAUDE_DIR = join(homedir(), '.claude');
8
8
  const SETTINGS_FILE = join(CLAUDE_DIR, 'settings.json');
9
9
  const BACKUP_FILE = join(CLAUDE_DIR, 'settings.json.aar.bak');
10
10
 
11
+ // AAR 备份目录
12
+ const AAR_BACKUP_DIR = join(homedir(), '.aar', 'backups');
13
+
11
14
  /**
12
15
  * 还原 Claude IDE 配置
13
16
  */
@@ -34,6 +37,12 @@ export async function POST(request: NextRequest) {
34
37
  );
35
38
  }
36
39
 
40
+ // 在还原前,先备份当前配置到 ~/.aar/backups 目录
41
+ const currentBackup = backupToAar(SETTINGS_FILE, 'settings-before-restore');
42
+ if (!currentBackup.success) {
43
+ console.warn('[IDE Restore] Current config backup warning:', currentBackup.error);
44
+ }
45
+
37
46
  // 将备份内容复制到原配置文件
38
47
  copyFileSync(BACKUP_FILE, SETTINGS_FILE);
39
48
 
@@ -93,3 +102,29 @@ export async function DELETE(request: NextRequest) {
93
102
  );
94
103
  }
95
104
  }
105
+
106
+ /**
107
+ * 备份文件到 ~/.aar/backups 目录
108
+ */
109
+ function backupToAar(filePath: string, backupName: string): { success: boolean; backupPath?: string; error?: string } {
110
+ try {
111
+ if (!existsSync(filePath)) {
112
+ return { success: true }; // 文件不存在,无需备份
113
+ }
114
+
115
+ if (!existsSync(AAR_BACKUP_DIR)) {
116
+ mkdirSync(AAR_BACKUP_DIR, { recursive: true });
117
+ }
118
+
119
+ const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
120
+ const backupPath = join(AAR_BACKUP_DIR, `${backupName}-${timestamp}.json`);
121
+ copyFileSync(filePath, backupPath);
122
+
123
+ return { success: true, backupPath };
124
+ } catch (error: any) {
125
+ return {
126
+ success: false,
127
+ error: `Backup to AAR failed: ${error.message}`,
128
+ };
129
+ }
130
+ }
@@ -1,5 +1,5 @@
1
1
  import { NextRequest, NextResponse } from 'next/server';
2
- import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'fs';
2
+ import { existsSync, readFileSync, writeFileSync, mkdirSync, copyFileSync } from 'fs';
3
3
  import { join } from 'path';
4
4
  import { homedir } from 'os';
5
5
  import { getDatabase } from '@/db/database';
@@ -9,10 +9,16 @@ import { getConfig } from '@/db/queries';
9
9
  const CLAUDE_DIR = join(homedir(), '.claude');
10
10
  const SETTINGS_FILE = join(CLAUDE_DIR, 'settings.json');
11
11
 
12
+ // Claude 登录配置文件(用于 hasCompletedOnboarding)
13
+ const CLAUDE_JSON_FILE = join(homedir(), '.claude.json');
14
+
12
15
  // AAR 临时配置目录和文件
13
16
  const AAR_DIR = join(homedir(), '.aar');
14
17
  const TEMP_SETTINGS_FILE = join(AAR_DIR, 'settings.tmp.json');
15
18
 
19
+ // AAR 备份目录
20
+ const AAR_BACKUP_DIR = join(AAR_DIR, 'backups');
21
+
16
22
  type SaveRequest = {
17
23
  haiku?: string;
18
24
  sonnet?: string;
@@ -64,6 +70,18 @@ export async function POST(request: NextRequest) {
64
70
  // 已应用当前网关配置,更新 settings.json
65
71
  savePath = SETTINGS_FILE;
66
72
  saveType = 'applied';
73
+
74
+ // 备份到 ~/.aar/backups 目录
75
+ const settingsBackup = backupToAar(SETTINGS_FILE, 'settings');
76
+ const claudeJsonBackup = backupToAar(CLAUDE_JSON_FILE, 'claude');
77
+
78
+ if (!settingsBackup.success) {
79
+ console.warn('[IDE Save] Settings backup warning:', settingsBackup.error);
80
+ }
81
+ if (!claudeJsonBackup.success) {
82
+ console.warn('[IDE Save] Claude.json backup warning:', claudeJsonBackup.error);
83
+ }
84
+
67
85
  mergedConfig = generateClaudeConfig(gatewayAddress, gatewayApiKey, {
68
86
  haiku: haiku,
69
87
  sonnet: sonnet,
@@ -71,6 +89,12 @@ export async function POST(request: NextRequest) {
71
89
  default: defaultModel,
72
90
  reasoning: reasoningModel
73
91
  });
92
+
93
+ // 确保 ~/.claude.json 包含 hasCompletedOnboarding: true
94
+ const onboardingResult = ensureClaudeOnboarding();
95
+ if (!onboardingResult.success) {
96
+ console.warn('[IDE Save] Onboarding update warning:', onboardingResult.error);
97
+ }
74
98
  } else {
75
99
  // 未应用网络关配置,保存到临时文件 ~/.aar/settings.tmp.json
76
100
  savePath = TEMP_SETTINGS_FILE;
@@ -179,3 +203,69 @@ function generateClaudeConfig(
179
203
  },
180
204
  };
181
205
  }
206
+
207
+ /**
208
+ * 备份文件到 ~/.aar/backups 目录
209
+ */
210
+ function backupToAar(filePath: string, backupName: string): { success: boolean; backupPath?: string; error?: string } {
211
+ try {
212
+ if (!existsSync(filePath)) {
213
+ return { success: true }; // 文件不存在,无需备份
214
+ }
215
+
216
+ if (!existsSync(AAR_BACKUP_DIR)) {
217
+ mkdirSync(AAR_BACKUP_DIR, { recursive: true });
218
+ }
219
+
220
+ const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
221
+ const backupPath = join(AAR_BACKUP_DIR, `${backupName}-${timestamp}.json`);
222
+ copyFileSync(filePath, backupPath);
223
+
224
+ return { success: true, backupPath };
225
+ } catch (error: any) {
226
+ return {
227
+ success: false,
228
+ error: `Backup to AAR failed: ${error.message}`,
229
+ };
230
+ }
231
+ }
232
+
233
+ /**
234
+ * 确保 ~/.claude.json 文件中包含 hasCompletedOnboarding: true
235
+ * 这允许用户跳过 Claude 登录使用自定义模型
236
+ */
237
+ function ensureClaudeOnboarding(): { success: boolean; created: boolean; error?: string } {
238
+ try {
239
+ let config: any = {};
240
+ let created = false;
241
+
242
+ if (existsSync(CLAUDE_JSON_FILE)) {
243
+ try {
244
+ const content = readFileSync(CLAUDE_JSON_FILE, 'utf-8');
245
+ config = JSON.parse(content);
246
+ } catch {
247
+ // 文件存在但解析失败,使用空对象
248
+ config = {};
249
+ }
250
+ } else {
251
+ created = true;
252
+ }
253
+
254
+ // 检查是否已经有 hasCompletedOnboarding
255
+ if (config.hasCompletedOnboarding === true) {
256
+ return { success: true, created: false };
257
+ }
258
+
259
+ // 添加 hasCompletedOnboarding
260
+ config.hasCompletedOnboarding = true;
261
+ writeFileSync(CLAUDE_JSON_FILE, JSON.stringify(config, null, 2), 'utf-8');
262
+
263
+ return { success: true, created };
264
+ } catch (error: any) {
265
+ return {
266
+ success: false,
267
+ created: false,
268
+ error: `Failed to update claude.json: ${error.message}`,
269
+ };
270
+ }
271
+ }
@@ -29,9 +29,14 @@ type ConfigStatus = {
29
29
  apiKey?: string;
30
30
  lastUpdated?: string | null;
31
31
  backupExists: boolean;
32
- matchCurrentGateway?: boolean; // 是否匹配当前网关配置
32
+ matchCurrentGateway?: boolean; // 是否匹配当前网关配置(仅当 routerProvider === 'aar' 时有效)
33
33
  routerProvider?: string; // 路由提供者标识,'aar' 表示配置来自当前工具
34
34
  tempMapping?: { haiku?: string; sonnet?: string; opus?: string; default?: string; reasoning?: string }; // 临时配置模型映射
35
+ config?: Record<string, unknown>; // 当前配置文件完整内容,用于「生效中」展示
36
+ /** 当前网关地址(来自数据库),用于预览 */
37
+ currentGatewayAddress?: string;
38
+ /** 当前网关 API Key(来自数据库,脱敏),用于预览 */
39
+ currentGatewayApiKey?: string;
35
40
  };
36
41
 
37
42
  /**
@@ -60,6 +65,8 @@ export async function GET(request: NextRequest) {
60
65
  lastUpdated: undefined,
61
66
  matchCurrentGateway: false,
62
67
  routerProvider: undefined,
68
+ currentGatewayAddress: gatewayAddress,
69
+ currentGatewayApiKey: gatewayApiKey,
63
70
  });
64
71
  }
65
72
 
@@ -98,7 +105,7 @@ export async function GET(request: NextRequest) {
98
105
  }
99
106
  }
100
107
 
101
- // 提取配置状态
108
+ // 提取配置状态;返回完整 config 供前端在非 AAR 时展示原有配置文件
102
109
  const status: ConfigStatus = {
103
110
  applied: true,
104
111
  modelMapping: extractModelMapping(config),
@@ -109,6 +116,9 @@ export async function GET(request: NextRequest) {
109
116
  matchCurrentGateway,
110
117
  routerProvider: config.router_provider,
111
118
  tempMapping,
119
+ config,
120
+ currentGatewayAddress: gatewayAddress,
121
+ currentGatewayApiKey: gatewayApiKey,
112
122
  };
113
123
 
114
124
  return NextResponse.json(status);