ai-agent-router 0.1.21 → 0.2.1

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 (368) 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/routes-manifest.json +84 -0
  6. package/.next/server/app/_global-error/page.js +1 -1
  7. package/.next/server/app/_global-error/page.js.nft.json +1 -1
  8. package/.next/server/app/_global-error.html +2 -2
  9. package/.next/server/app/_global-error.rsc +1 -1
  10. package/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  11. package/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  12. package/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  13. package/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  14. package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  15. package/.next/server/app/_not-found/page.js +1 -1
  16. package/.next/server/app/_not-found/page.js.nft.json +1 -1
  17. package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  18. package/.next/server/app/_not-found.html +1 -1
  19. package/.next/server/app/_not-found.rsc +2 -2
  20. package/.next/server/app/_not-found.segments/_full.segment.rsc +2 -2
  21. package/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  22. package/.next/server/app/_not-found.segments/_index.segment.rsc +2 -2
  23. package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  24. package/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  25. package/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  26. package/.next/server/app/api/config/route.js.nft.json +1 -1
  27. package/.next/server/app/api/gateway/[...path]/route.js.nft.json +1 -1
  28. package/.next/server/app/api/gateway/models/route.js.nft.json +1 -1
  29. package/.next/server/app/api/gateway/route.js.nft.json +1 -1
  30. package/.next/server/app/api/ide/claude/apply/route.js.nft.json +1 -1
  31. package/.next/server/app/api/ide/claude/available-models/route.js.nft.json +1 -1
  32. package/.next/server/app/api/ide/claude/save/route.js.nft.json +1 -1
  33. package/.next/server/app/api/ide/claude/status/route.js.nft.json +1 -1
  34. package/.next/server/app/api/ide/claude/test/route.js +1 -1
  35. package/.next/server/app/api/ide/claude/test/route.js.nft.json +1 -1
  36. package/.next/server/app/api/ide/openclaw/apply/route/app-paths-manifest.json +3 -0
  37. package/.next/server/app/api/ide/openclaw/apply/route/build-manifest.json +11 -0
  38. package/.next/server/app/api/ide/openclaw/apply/route/server-reference-manifest.json +4 -0
  39. package/.next/server/app/api/ide/openclaw/apply/route.js +7 -0
  40. package/.next/server/app/api/ide/openclaw/apply/route.js.map +5 -0
  41. package/.next/server/app/api/ide/openclaw/apply/route.js.nft.json +1 -0
  42. package/.next/server/app/api/ide/openclaw/apply/route_client-reference-manifest.js +2 -0
  43. package/.next/server/app/api/ide/openclaw/available-models/route/app-paths-manifest.json +3 -0
  44. package/.next/server/app/api/ide/openclaw/available-models/route/build-manifest.json +11 -0
  45. package/.next/server/app/api/ide/openclaw/available-models/route/server-reference-manifest.json +4 -0
  46. package/.next/server/app/api/ide/openclaw/available-models/route.js +7 -0
  47. package/.next/server/app/api/ide/openclaw/available-models/route.js.map +5 -0
  48. package/.next/server/app/api/ide/openclaw/available-models/route.js.nft.json +1 -0
  49. package/.next/server/app/api/ide/openclaw/available-models/route_client-reference-manifest.js +2 -0
  50. package/.next/server/app/api/ide/openclaw/preview/route/app-paths-manifest.json +3 -0
  51. package/.next/server/app/api/ide/openclaw/preview/route/build-manifest.json +11 -0
  52. package/.next/server/app/api/ide/openclaw/preview/route/server-reference-manifest.json +4 -0
  53. package/.next/server/app/api/ide/openclaw/preview/route.js +7 -0
  54. package/.next/server/app/api/ide/openclaw/preview/route.js.map +5 -0
  55. package/.next/server/app/api/ide/openclaw/preview/route.js.nft.json +1 -0
  56. package/.next/server/app/api/ide/openclaw/preview/route_client-reference-manifest.js +2 -0
  57. package/.next/server/app/api/ide/openclaw/restore/route/app-paths-manifest.json +3 -0
  58. package/.next/server/app/api/ide/openclaw/restore/route/build-manifest.json +11 -0
  59. package/.next/server/app/api/ide/openclaw/restore/route/server-reference-manifest.json +4 -0
  60. package/.next/server/app/api/ide/openclaw/restore/route.js +6 -0
  61. package/.next/server/app/api/ide/openclaw/restore/route.js.map +5 -0
  62. package/.next/server/app/api/ide/openclaw/restore/route.js.nft.json +1 -0
  63. package/.next/server/app/api/ide/openclaw/restore/route_client-reference-manifest.js +2 -0
  64. package/.next/server/app/api/ide/openclaw/save/route/app-paths-manifest.json +3 -0
  65. package/.next/server/app/api/ide/openclaw/save/route/build-manifest.json +11 -0
  66. package/.next/server/app/api/ide/openclaw/save/route/server-reference-manifest.json +4 -0
  67. package/.next/server/app/api/ide/openclaw/save/route.js +7 -0
  68. package/.next/server/app/api/ide/openclaw/save/route.js.map +5 -0
  69. package/.next/server/app/api/ide/openclaw/save/route.js.nft.json +1 -0
  70. package/.next/server/app/api/ide/openclaw/save/route_client-reference-manifest.js +2 -0
  71. package/.next/server/app/api/ide/openclaw/status/route/app-paths-manifest.json +3 -0
  72. package/.next/server/app/api/ide/openclaw/status/route/build-manifest.json +11 -0
  73. package/.next/server/app/api/ide/openclaw/status/route/server-reference-manifest.json +4 -0
  74. package/.next/server/app/api/ide/openclaw/status/route.js +7 -0
  75. package/.next/server/app/api/ide/openclaw/status/route.js.map +5 -0
  76. package/.next/server/app/api/ide/openclaw/status/route.js.nft.json +1 -0
  77. package/.next/server/app/api/ide/openclaw/status/route_client-reference-manifest.js +2 -0
  78. package/.next/server/app/api/ide/openclaw/test/route/app-paths-manifest.json +3 -0
  79. package/.next/server/app/api/ide/openclaw/test/route/build-manifest.json +11 -0
  80. package/.next/server/app/api/ide/openclaw/test/route/server-reference-manifest.json +4 -0
  81. package/.next/server/app/api/ide/openclaw/test/route.js +6 -0
  82. package/.next/server/app/api/ide/openclaw/test/route.js.map +5 -0
  83. package/.next/server/app/api/ide/openclaw/test/route.js.nft.json +1 -0
  84. package/.next/server/app/api/ide/openclaw/test/route_client-reference-manifest.js +2 -0
  85. package/.next/server/app/api/ide/opencode/apply/route/app-paths-manifest.json +3 -0
  86. package/.next/server/app/api/ide/opencode/apply/route/build-manifest.json +11 -0
  87. package/.next/server/app/api/ide/opencode/apply/route/server-reference-manifest.json +4 -0
  88. package/.next/server/app/api/ide/opencode/apply/route.js +7 -0
  89. package/.next/server/app/api/ide/opencode/apply/route.js.map +5 -0
  90. package/.next/server/app/api/ide/opencode/apply/route.js.nft.json +1 -0
  91. package/.next/server/app/api/ide/opencode/apply/route_client-reference-manifest.js +2 -0
  92. package/.next/server/app/api/ide/opencode/available-models/route/app-paths-manifest.json +3 -0
  93. package/.next/server/app/api/ide/opencode/available-models/route/build-manifest.json +11 -0
  94. package/.next/server/app/api/ide/opencode/available-models/route/server-reference-manifest.json +4 -0
  95. package/.next/server/app/api/ide/opencode/available-models/route.js +7 -0
  96. package/.next/server/app/api/ide/opencode/available-models/route.js.map +5 -0
  97. package/.next/server/app/api/ide/opencode/available-models/route.js.nft.json +1 -0
  98. package/.next/server/app/api/ide/opencode/available-models/route_client-reference-manifest.js +2 -0
  99. package/.next/server/app/api/ide/opencode/preview/route/app-paths-manifest.json +3 -0
  100. package/.next/server/app/api/ide/opencode/preview/route/build-manifest.json +11 -0
  101. package/.next/server/app/api/ide/opencode/preview/route/server-reference-manifest.json +4 -0
  102. package/.next/server/app/api/ide/opencode/preview/route.js +7 -0
  103. package/.next/server/app/api/ide/opencode/preview/route.js.map +5 -0
  104. package/.next/server/app/api/ide/opencode/preview/route.js.nft.json +1 -0
  105. package/.next/server/app/api/ide/opencode/preview/route_client-reference-manifest.js +2 -0
  106. package/.next/server/app/api/ide/opencode/restore/route/app-paths-manifest.json +3 -0
  107. package/.next/server/app/api/ide/opencode/restore/route/build-manifest.json +11 -0
  108. package/.next/server/app/api/ide/opencode/restore/route/server-reference-manifest.json +4 -0
  109. package/.next/server/app/api/ide/opencode/restore/route.js +6 -0
  110. package/.next/server/app/api/ide/opencode/restore/route.js.map +5 -0
  111. package/.next/server/app/api/ide/opencode/restore/route.js.nft.json +1 -0
  112. package/.next/server/app/api/ide/opencode/restore/route_client-reference-manifest.js +2 -0
  113. package/.next/server/app/api/ide/opencode/save/route/app-paths-manifest.json +3 -0
  114. package/.next/server/app/api/ide/opencode/save/route/build-manifest.json +11 -0
  115. package/.next/server/app/api/ide/opencode/save/route/server-reference-manifest.json +4 -0
  116. package/.next/server/app/api/ide/opencode/save/route.js +7 -0
  117. package/.next/server/app/api/ide/opencode/save/route.js.map +5 -0
  118. package/.next/server/app/api/ide/opencode/save/route.js.nft.json +1 -0
  119. package/.next/server/app/api/ide/opencode/save/route_client-reference-manifest.js +2 -0
  120. package/.next/server/app/api/ide/opencode/status/route/app-paths-manifest.json +3 -0
  121. package/.next/server/app/api/ide/opencode/status/route/build-manifest.json +11 -0
  122. package/.next/server/app/api/ide/opencode/status/route/server-reference-manifest.json +4 -0
  123. package/.next/server/app/api/ide/opencode/status/route.js +7 -0
  124. package/.next/server/app/api/ide/opencode/status/route.js.map +5 -0
  125. package/.next/server/app/api/ide/opencode/status/route.js.nft.json +1 -0
  126. package/.next/server/app/api/ide/opencode/status/route_client-reference-manifest.js +2 -0
  127. package/.next/server/app/api/ide/opencode/test/route/app-paths-manifest.json +3 -0
  128. package/.next/server/app/api/ide/opencode/test/route/build-manifest.json +11 -0
  129. package/.next/server/app/api/ide/opencode/test/route/server-reference-manifest.json +4 -0
  130. package/.next/server/app/api/ide/opencode/test/route.js +6 -0
  131. package/.next/server/app/api/ide/opencode/test/route.js.map +5 -0
  132. package/.next/server/app/api/ide/opencode/test/route.js.nft.json +1 -0
  133. package/.next/server/app/api/ide/opencode/test/route_client-reference-manifest.js +2 -0
  134. package/.next/server/app/api/logs/route.js.nft.json +1 -1
  135. package/.next/server/app/api/models/route.js.nft.json +1 -1
  136. package/.next/server/app/api/providers/route.js.nft.json +1 -1
  137. package/.next/server/app/api/providers/test/route.js.nft.json +1 -1
  138. package/.next/server/app/api/service/force-stop/route.js.nft.json +1 -1
  139. package/.next/server/app/api/service/start/route.js.nft.json +1 -1
  140. package/.next/server/app/api/service/status/route.js.nft.json +1 -1
  141. package/.next/server/app/api/service/stop/route.js.nft.json +1 -1
  142. package/.next/server/app/ide/page.js +1 -1
  143. package/.next/server/app/ide/page.js.nft.json +1 -1
  144. package/.next/server/app/ide/page_client-reference-manifest.js +1 -1
  145. package/.next/server/app/ide.html +1 -1
  146. package/.next/server/app/ide.rsc +3 -3
  147. package/.next/server/app/ide.segments/_full.segment.rsc +3 -3
  148. package/.next/server/app/ide.segments/_head.segment.rsc +1 -1
  149. package/.next/server/app/ide.segments/_index.segment.rsc +2 -2
  150. package/.next/server/app/ide.segments/_tree.segment.rsc +2 -2
  151. package/.next/server/app/ide.segments/ide/__PAGE__.segment.rsc +2 -2
  152. package/.next/server/app/ide.segments/ide.segment.rsc +1 -1
  153. package/.next/server/app/index.html +1 -1
  154. package/.next/server/app/index.rsc +2 -2
  155. package/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  156. package/.next/server/app/index.segments/_full.segment.rsc +2 -2
  157. package/.next/server/app/index.segments/_head.segment.rsc +1 -1
  158. package/.next/server/app/index.segments/_index.segment.rsc +2 -2
  159. package/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  160. package/.next/server/app/logs/page.js +1 -1
  161. package/.next/server/app/logs/page.js.nft.json +1 -1
  162. package/.next/server/app/logs/page_client-reference-manifest.js +1 -1
  163. package/.next/server/app/logs.html +1 -1
  164. package/.next/server/app/logs.rsc +3 -3
  165. package/.next/server/app/logs.segments/_full.segment.rsc +3 -3
  166. package/.next/server/app/logs.segments/_head.segment.rsc +1 -1
  167. package/.next/server/app/logs.segments/_index.segment.rsc +2 -2
  168. package/.next/server/app/logs.segments/_tree.segment.rsc +2 -2
  169. package/.next/server/app/logs.segments/logs/__PAGE__.segment.rsc +2 -2
  170. package/.next/server/app/logs.segments/logs.segment.rsc +1 -1
  171. package/.next/server/app/models/page.js +1 -1
  172. package/.next/server/app/models/page.js.nft.json +1 -1
  173. package/.next/server/app/models/page_client-reference-manifest.js +1 -1
  174. package/.next/server/app/models.html +1 -1
  175. package/.next/server/app/models.rsc +2 -2
  176. package/.next/server/app/models.segments/_full.segment.rsc +2 -2
  177. package/.next/server/app/models.segments/_head.segment.rsc +1 -1
  178. package/.next/server/app/models.segments/_index.segment.rsc +2 -2
  179. package/.next/server/app/models.segments/_tree.segment.rsc +2 -2
  180. package/.next/server/app/models.segments/models/__PAGE__.segment.rsc +1 -1
  181. package/.next/server/app/models.segments/models.segment.rsc +1 -1
  182. package/.next/server/app/page.js +1 -1
  183. package/.next/server/app/page.js.nft.json +1 -1
  184. package/.next/server/app/page_client-reference-manifest.js +1 -1
  185. package/.next/server/app/providers/page.js +1 -1
  186. package/.next/server/app/providers/page.js.nft.json +1 -1
  187. package/.next/server/app/providers/page_client-reference-manifest.js +1 -1
  188. package/.next/server/app/providers.html +1 -1
  189. package/.next/server/app/providers.rsc +2 -2
  190. package/.next/server/app/providers.segments/_full.segment.rsc +2 -2
  191. package/.next/server/app/providers.segments/_head.segment.rsc +1 -1
  192. package/.next/server/app/providers.segments/_index.segment.rsc +2 -2
  193. package/.next/server/app/providers.segments/_tree.segment.rsc +2 -2
  194. package/.next/server/app/providers.segments/providers/__PAGE__.segment.rsc +1 -1
  195. package/.next/server/app/providers.segments/providers.segment.rsc +1 -1
  196. package/.next/server/app-paths-manifest.json +14 -0
  197. package/.next/server/chunks/[root-of-the-server]__001d5756._.js +3 -0
  198. package/.next/server/chunks/[root-of-the-server]__001d5756._.js.map +1 -0
  199. package/.next/server/chunks/[root-of-the-server]__05f8578b._.js +3 -0
  200. package/.next/server/chunks/[root-of-the-server]__05f8578b._.js.map +1 -0
  201. package/.next/server/chunks/[root-of-the-server]__1480f018._.js +1 -1
  202. package/.next/server/chunks/[root-of-the-server]__1480f018._.js.map +1 -1
  203. package/.next/server/chunks/[root-of-the-server]__1909f3aa._.js +1 -1
  204. package/.next/server/chunks/[root-of-the-server]__1909f3aa._.js.map +1 -1
  205. package/.next/server/chunks/[root-of-the-server]__1d4b7fc5._.js +1 -1
  206. package/.next/server/chunks/[root-of-the-server]__1d4b7fc5._.js.map +1 -1
  207. package/.next/server/chunks/[root-of-the-server]__372ef2bf._.js +1 -1
  208. package/.next/server/chunks/[root-of-the-server]__372ef2bf._.js.map +1 -1
  209. package/.next/server/chunks/[root-of-the-server]__3aaf963c._.js +1 -1
  210. package/.next/server/chunks/[root-of-the-server]__3aaf963c._.js.map +1 -1
  211. package/.next/server/chunks/[root-of-the-server]__43810962._.js +3 -0
  212. package/.next/server/chunks/[root-of-the-server]__43810962._.js.map +1 -0
  213. package/.next/server/chunks/[root-of-the-server]__55cd88b8._.js +3 -0
  214. package/.next/server/chunks/[root-of-the-server]__55cd88b8._.js.map +1 -0
  215. package/.next/server/chunks/[root-of-the-server]__5e8276bc._.js +1 -1
  216. package/.next/server/chunks/[root-of-the-server]__5e8276bc._.js.map +1 -1
  217. package/.next/server/chunks/[root-of-the-server]__6ce199d2._.js +1 -1
  218. package/.next/server/chunks/[root-of-the-server]__6ce199d2._.js.map +1 -1
  219. package/.next/server/chunks/[root-of-the-server]__760eaa16._.js +3 -0
  220. package/.next/server/chunks/[root-of-the-server]__760eaa16._.js.map +1 -0
  221. package/.next/server/chunks/[root-of-the-server]__772134c6._.js +1 -1
  222. package/.next/server/chunks/[root-of-the-server]__772134c6._.js.map +1 -1
  223. package/.next/server/chunks/[root-of-the-server]__7b77f523._.js +1 -1
  224. package/.next/server/chunks/[root-of-the-server]__7b77f523._.js.map +1 -1
  225. package/.next/server/chunks/[root-of-the-server]__7c298a19._.js +3 -0
  226. package/.next/server/chunks/[root-of-the-server]__7c298a19._.js.map +1 -0
  227. package/.next/server/chunks/[root-of-the-server]__85540228._.js +3 -0
  228. package/.next/server/chunks/[root-of-the-server]__85540228._.js.map +1 -0
  229. package/.next/server/chunks/[root-of-the-server]__94fe8d3c._.js +3 -0
  230. package/.next/server/chunks/[root-of-the-server]__94fe8d3c._.js.map +1 -0
  231. package/.next/server/chunks/[root-of-the-server]__97622908._.js +3 -0
  232. package/.next/server/chunks/[root-of-the-server]__97622908._.js.map +1 -0
  233. package/.next/server/chunks/[root-of-the-server]__a02e6618._.js +3 -0
  234. package/.next/server/chunks/[root-of-the-server]__a02e6618._.js.map +1 -0
  235. package/.next/server/chunks/[root-of-the-server]__a32a20a7._.js +3 -0
  236. package/.next/server/chunks/[root-of-the-server]__a32a20a7._.js.map +1 -0
  237. package/.next/server/chunks/[root-of-the-server]__af5b556a._.js +3 -0
  238. package/.next/server/chunks/[root-of-the-server]__af5b556a._.js.map +1 -0
  239. package/.next/server/chunks/[root-of-the-server]__c1b4b601._.js +18 -18
  240. package/.next/server/chunks/[root-of-the-server]__c1b4b601._.js.map +1 -1
  241. package/.next/server/chunks/[root-of-the-server]__cafe113e._.js +3 -0
  242. package/.next/server/chunks/[root-of-the-server]__cafe113e._.js.map +1 -0
  243. package/.next/server/chunks/[root-of-the-server]__ccfc7f1d._.js +1 -1
  244. package/.next/server/chunks/[root-of-the-server]__ccfc7f1d._.js.map +1 -1
  245. package/.next/server/chunks/[root-of-the-server]__dc8b0bed._.js +3 -0
  246. package/.next/server/chunks/[root-of-the-server]__dc8b0bed._.js.map +1 -0
  247. package/.next/server/chunks/[root-of-the-server]__f8949f88._.js +1 -1
  248. package/.next/server/chunks/[root-of-the-server]__f8949f88._.js.map +1 -1
  249. package/.next/server/chunks/_next-internal_server_app_api_ide_openclaw_apply_route_actions_2cb9e4b4.js +3 -0
  250. package/.next/server/chunks/_next-internal_server_app_api_ide_openclaw_apply_route_actions_2cb9e4b4.js.map +1 -0
  251. package/.next/server/chunks/_next-internal_server_app_api_ide_openclaw_preview_route_actions_9814a8e4.js +3 -0
  252. package/.next/server/chunks/_next-internal_server_app_api_ide_openclaw_preview_route_actions_9814a8e4.js.map +1 -0
  253. package/.next/server/chunks/_next-internal_server_app_api_ide_openclaw_restore_route_actions_10ad8f9d.js +3 -0
  254. package/.next/server/chunks/_next-internal_server_app_api_ide_openclaw_restore_route_actions_10ad8f9d.js.map +1 -0
  255. package/.next/server/chunks/_next-internal_server_app_api_ide_openclaw_save_route_actions_044ad081.js +3 -0
  256. package/.next/server/chunks/_next-internal_server_app_api_ide_openclaw_save_route_actions_044ad081.js.map +1 -0
  257. package/.next/server/chunks/_next-internal_server_app_api_ide_openclaw_status_route_actions_ed9786d2.js +3 -0
  258. package/.next/server/chunks/_next-internal_server_app_api_ide_openclaw_status_route_actions_ed9786d2.js.map +1 -0
  259. package/.next/server/chunks/_next-internal_server_app_api_ide_openclaw_test_route_actions_ce2cb808.js +3 -0
  260. package/.next/server/chunks/_next-internal_server_app_api_ide_openclaw_test_route_actions_ce2cb808.js.map +1 -0
  261. package/.next/server/chunks/_next-internal_server_app_api_ide_opencode_apply_route_actions_6c422244.js +3 -0
  262. package/.next/server/chunks/_next-internal_server_app_api_ide_opencode_apply_route_actions_6c422244.js.map +1 -0
  263. package/.next/server/chunks/_next-internal_server_app_api_ide_opencode_preview_route_actions_256c82e0.js +3 -0
  264. package/.next/server/chunks/_next-internal_server_app_api_ide_opencode_preview_route_actions_256c82e0.js.map +1 -0
  265. package/.next/server/chunks/_next-internal_server_app_api_ide_opencode_restore_route_actions_371993d3.js +3 -0
  266. package/.next/server/chunks/_next-internal_server_app_api_ide_opencode_restore_route_actions_371993d3.js.map +1 -0
  267. package/.next/server/chunks/_next-internal_server_app_api_ide_opencode_save_route_actions_6e4c9c41.js +3 -0
  268. package/.next/server/chunks/_next-internal_server_app_api_ide_opencode_save_route_actions_6e4c9c41.js.map +1 -0
  269. package/.next/server/chunks/_next-internal_server_app_api_ide_opencode_status_route_actions_498ad77b.js +3 -0
  270. package/.next/server/chunks/_next-internal_server_app_api_ide_opencode_status_route_actions_498ad77b.js.map +1 -0
  271. package/.next/server/chunks/_next-internal_server_app_api_ide_opencode_test_route_actions_c71be510.js +3 -0
  272. package/.next/server/chunks/_next-internal_server_app_api_ide_opencode_test_route_actions_c71be510.js.map +1 -0
  273. package/.next/server/chunks/ce889_server_app_api_ide_openclaw_available-models_route_actions_e568e70b.js +3 -0
  274. package/.next/server/chunks/ce889_server_app_api_ide_openclaw_available-models_route_actions_e568e70b.js.map +1 -0
  275. package/.next/server/chunks/ce889_server_app_api_ide_opencode_available-models_route_actions_95230db3.js +3 -0
  276. package/.next/server/chunks/ce889_server_app_api_ide_opencode_available-models_route_actions_95230db3.js.map +1 -0
  277. package/.next/server/chunks/ssr/{[root-of-the-server]__bec95712._.js → [root-of-the-server]__81937253._.js} +2 -2
  278. package/.next/server/chunks/ssr/{[root-of-the-server]__bec95712._.js.map → [root-of-the-server]__81937253._.js.map} +1 -1
  279. package/.next/server/chunks/ssr/{[root-of-the-server]__71c85955._.js → [root-of-the-server]__976ad963._.js} +2 -2
  280. package/.next/server/chunks/ssr/{[root-of-the-server]__71c85955._.js.map → [root-of-the-server]__976ad963._.js.map} +1 -1
  281. package/.next/server/chunks/ssr/src_app_ide_page_tsx_8962793b._.js +1 -1
  282. package/.next/server/chunks/ssr/src_app_ide_page_tsx_8962793b._.js.map +1 -1
  283. package/.next/server/chunks/ssr/src_app_logs_page_tsx_7b7b7b83._.js +1 -1
  284. package/.next/server/chunks/ssr/src_app_logs_page_tsx_7b7b7b83._.js.map +1 -1
  285. package/.next/server/pages/404.html +1 -1
  286. package/.next/server/pages/500.html +2 -2
  287. package/.next/static/chunks/0f120c117962200b.css +1 -0
  288. package/.next/static/chunks/64f547b3bcd3aef4.js +1 -0
  289. package/.next/static/chunks/{81c904164fe81379.js → 7c8b7cbb3339f139.js} +1 -1
  290. package/.next/static/chunks/8ed839b2e4948968.js +1 -0
  291. package/.next/types/routes.d.ts +15 -1
  292. package/.next/types/validator.ts +126 -0
  293. package/README.md +100 -111
  294. package/dist/.next/dev/types/validator.js +56 -0
  295. package/dist/.next/types/validator.js +56 -0
  296. package/dist/src/app/api/gateway/[...path]/route.js +1 -1
  297. package/dist/src/app/api/gateway/route.js +1 -1
  298. package/dist/src/app/api/ide/claude/apply/route.js +42 -31
  299. package/dist/src/app/api/ide/claude/status/route.js +6 -1
  300. package/dist/src/app/api/ide/openclaw/apply/route.js +92 -0
  301. package/dist/src/app/api/ide/openclaw/available-models/route.js +46 -0
  302. package/dist/src/app/api/ide/openclaw/build-config.js +101 -0
  303. package/dist/src/app/api/ide/openclaw/preview/route.js +49 -0
  304. package/dist/src/app/api/ide/openclaw/restore/route.js +24 -0
  305. package/dist/src/app/api/ide/openclaw/save/route.js +54 -0
  306. package/dist/src/app/api/ide/openclaw/status/route.js +139 -0
  307. package/dist/src/app/api/ide/openclaw/test/route.js +158 -0
  308. package/dist/src/app/api/ide/opencode/apply/route.js +89 -0
  309. package/dist/src/app/api/ide/opencode/available-models/route.js +46 -0
  310. package/dist/src/app/api/ide/opencode/build-config.js +54 -0
  311. package/dist/src/app/api/ide/opencode/preview/route.js +36 -0
  312. package/dist/src/app/api/ide/opencode/restore/route.js +40 -0
  313. package/dist/src/app/api/ide/opencode/save/route.js +123 -0
  314. package/dist/src/app/api/ide/opencode/status/route.js +106 -0
  315. package/dist/src/app/api/ide/opencode/test/route.js +136 -0
  316. package/dist/src/app/api/logs/route.js +2 -2
  317. package/dist/src/app/api/models/route.js +5 -5
  318. package/dist/src/app/api/providers/route.js +4 -4
  319. package/dist/src/app/api/providers/test/route.js +1 -1
  320. package/dist/src/app/api/service/start/route.js +1 -1
  321. package/dist/src/app/api/service/status/route.js +1 -1
  322. package/dist/src/app/api/service/stop/route.js +1 -1
  323. package/dist/src/app/ide/page.js +591 -81
  324. package/dist/src/app/logs/page.js +15 -1
  325. package/dist/src/cli/index.js +218 -20
  326. package/dist/src/db/database.js +56 -5
  327. package/dist/src/db/queries.js +6 -6
  328. package/dist/src/server/logger.js +22 -4
  329. package/package.json +2 -1
  330. package/src/app/api/gateway/[...path]/route.ts +1 -1
  331. package/src/app/api/gateway/route.ts +1 -1
  332. package/src/app/api/ide/claude/apply/route.ts +46 -31
  333. package/src/app/api/ide/claude/status/route.ts +12 -2
  334. package/src/app/api/ide/openclaw/apply/route.ts +103 -0
  335. package/src/app/api/ide/openclaw/available-models/route.ts +59 -0
  336. package/src/app/api/ide/openclaw/build-config.ts +152 -0
  337. package/src/app/api/ide/openclaw/preview/route.ts +57 -0
  338. package/src/app/api/ide/openclaw/restore/route.ts +27 -0
  339. package/src/app/api/ide/openclaw/save/route.ts +67 -0
  340. package/src/app/api/ide/openclaw/status/route.ts +178 -0
  341. package/src/app/api/ide/openclaw/test/route.ts +194 -0
  342. package/src/app/api/ide/opencode/apply/route.ts +92 -0
  343. package/src/app/api/ide/opencode/available-models/route.ts +59 -0
  344. package/src/app/api/ide/opencode/build-config.ts +69 -0
  345. package/src/app/api/ide/opencode/preview/route.ts +40 -0
  346. package/src/app/api/ide/opencode/restore/route.ts +52 -0
  347. package/src/app/api/ide/opencode/save/route.ts +131 -0
  348. package/src/app/api/ide/opencode/status/route.ts +128 -0
  349. package/src/app/api/ide/opencode/test/route.ts +145 -0
  350. package/src/app/api/logs/route.ts +2 -2
  351. package/src/app/api/models/route.ts +5 -5
  352. package/src/app/api/providers/route.ts +4 -4
  353. package/src/app/api/providers/test/route.ts +1 -1
  354. package/src/app/api/service/start/route.ts +1 -1
  355. package/src/app/api/service/status/route.ts +1 -1
  356. package/src/app/api/service/stop/route.ts +1 -1
  357. package/src/app/globals.css +17 -0
  358. package/src/app/ide/page.tsx +1535 -132
  359. package/src/app/logs/page.tsx +17 -5
  360. package/src/cli/index.ts +228 -25
  361. package/src/db/database.ts +60 -8
  362. package/src/db/queries.ts +6 -6
  363. package/src/server/logger.ts +19 -4
  364. package/.next/static/chunks/6418ca50028376b7.css +0 -1
  365. package/.next/static/chunks/9ec3b97741b6575e.js +0 -1
  366. /package/.next/static/{PkfqdzwOZgX-UhSNUuhdp → dYin74gcpdlg8TGoGv-_d}/_buildManifest.js +0 -0
  367. /package/.next/static/{PkfqdzwOZgX-UhSNUuhdp → dYin74gcpdlg8TGoGv-_d}/_clientMiddlewareManifest.json +0 -0
  368. /package/.next/static/{PkfqdzwOZgX-UhSNUuhdp → dYin74gcpdlg8TGoGv-_d}/_ssgManifest.js +0 -0
@@ -10,6 +10,20 @@ 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 格式化为本地显示。数据库存储的是本地时间,无需追加 Z 后缀。 */
14
+ function formatCreatedAt(createdAt) {
15
+ if (!createdAt || typeof createdAt !== 'string')
16
+ return '';
17
+ const s = createdAt.trim();
18
+ if (!s)
19
+ return '';
20
+ // 数据库使用 datetime('now','localtime') 存储的已经是本地时间,
21
+ // 不带时区后缀时直接按本地时间解析,不要追加 'Z'(否则会多偏移 8 小时)
22
+ const hasTz = /[Z+-]\d{2}:?\d{2}$/.test(s);
23
+ const iso = hasTz ? s : s.replace(' ', 'T');
24
+ const date = new Date(iso);
25
+ return Number.isNaN(date.getTime()) ? s : date.toLocaleString('zh-CN');
26
+ }
13
27
  function LogsPage() {
14
28
  const [logs, setLogs] = (0, react_1.useState)([]);
15
29
  const [selectedLog, setSelectedLog] = (0, react_1.useState)(null);
@@ -244,7 +258,7 @@ function LogsPage() {
244
258
  }, className: "mt-2 text-xs text-emerald-600 hover:text-emerald-700", children: "\u6E05\u9664\u641C\u7D22" }))] }) }) })) : (logs.map((log) => {
245
259
  const parsedModel = parseModelFromRequest(log.request_query, log.request_body);
246
260
  const displayModel = parsedModel || log.model_name || 'Gateway';
247
- return ((0, jsx_runtime_1.jsxs)("tr", { className: "hover:bg-emerald-50/20 transition-colors duration-300", children: [(0, jsx_runtime_1.jsx)("td", { className: "px-4 py-3", children: (0, jsx_runtime_1.jsx)("input", { type: "checkbox", checked: selectedIds.includes(log.id), onChange: (e) => handleSelectLog(log.id, e.target.checked), className: "w-4 h-4 rounded border-slate-300 text-emerald-600 focus:ring-emerald-500", onClick: (e) => e.stopPropagation() }) }), (0, jsx_runtime_1.jsx)("td", { className: "px-4 py-3 whitespace-nowrap", children: (0, jsx_runtime_1.jsx)("div", { className: "text-xs text-slate-600", children: new Date(log.created_at + 'Z').toLocaleString('zh-CN') }) }), (0, jsx_runtime_1.jsx)("td", { className: "px-4 py-3 whitespace-nowrap", children: (0, jsx_runtime_1.jsxs)("div", { className: "text-xs", children: [(0, jsx_runtime_1.jsx)("div", { className: "font-medium text-slate-800", children: displayModel }), log.provider_name && ((0, jsx_runtime_1.jsx)("div", { className: "text-[10px] text-slate-500", children: log.provider_name }))] }) }), (0, jsx_runtime_1.jsx)("td", { className: "px-4 py-3 whitespace-nowrap", children: (0, jsx_runtime_1.jsx)("span", { className: `px-2 py-0.5 inline-flex text-xs leading-4 font-semibold rounded-lg border ${log.request_method === 'GET' ? 'bg-sky-50 text-sky-700 border-sky-200/50' :
261
+ return ((0, jsx_runtime_1.jsxs)("tr", { className: "hover:bg-emerald-50/20 transition-colors duration-300", children: [(0, jsx_runtime_1.jsx)("td", { className: "px-4 py-3", children: (0, jsx_runtime_1.jsx)("input", { type: "checkbox", checked: selectedIds.includes(log.id), onChange: (e) => handleSelectLog(log.id, e.target.checked), className: "w-4 h-4 rounded border-slate-300 text-emerald-600 focus:ring-emerald-500", onClick: (e) => e.stopPropagation() }) }), (0, jsx_runtime_1.jsx)("td", { className: "px-4 py-3 whitespace-nowrap", children: (0, jsx_runtime_1.jsx)("div", { className: "text-xs text-slate-600", children: formatCreatedAt(log.created_at) }) }), (0, jsx_runtime_1.jsx)("td", { className: "px-4 py-3 whitespace-nowrap", children: (0, jsx_runtime_1.jsxs)("div", { className: "text-xs", children: [(0, jsx_runtime_1.jsx)("div", { className: "font-medium text-slate-800", children: displayModel }), log.provider_name && ((0, jsx_runtime_1.jsx)("div", { className: "text-[10px] text-slate-500", children: log.provider_name }))] }) }), (0, jsx_runtime_1.jsx)("td", { className: "px-4 py-3 whitespace-nowrap", children: (0, jsx_runtime_1.jsx)("span", { className: `px-2 py-0.5 inline-flex text-xs leading-4 font-semibold rounded-lg border ${log.request_method === 'GET' ? 'bg-sky-50 text-sky-700 border-sky-200/50' :
248
262
  log.request_method === 'POST' ? 'bg-emerald-50 text-emerald-700 border-emerald-200/50' :
249
263
  'bg-slate-50 text-slate-600 border-slate-200/50'}`, children: log.request_method }) }), (0, jsx_runtime_1.jsx)("td", { className: "px-4 py-3", children: (0, jsx_runtime_1.jsx)("div", { className: "text-xs text-slate-600 font-mono max-w-xs truncate", children: log.request_path }) }), (0, jsx_runtime_1.jsx)("td", { className: "px-4 py-3 whitespace-nowrap", children: (0, jsx_runtime_1.jsx)("span", { className: `px-2 py-0.5 inline-flex text-xs leading-4 font-semibold rounded-full border ${log.response_status >= 200 && log.response_status < 300 ? 'bg-emerald-100/80 text-emerald-700 border-emerald-200/50' :
250
264
  log.response_status >= 400 && log.response_status < 500 ? 'bg-amber-100/80 text-amber-700 border-amber-200/50' :
@@ -7,51 +7,249 @@ Object.defineProperty(exports, "__esModule", { value: true });
7
7
  const commander_1 = require("commander");
8
8
  const child_process_1 = require("child_process");
9
9
  const path_1 = __importDefault(require("path"));
10
+ const fs_1 = __importDefault(require("fs"));
11
+ const os_1 = __importDefault(require("os"));
12
+ const http_1 = __importDefault(require("http"));
10
13
  const database_1 = require("../db/database");
11
14
  const queries_1 = require("../db/queries");
12
15
  const program = new commander_1.Command();
13
16
  const packageJsonPath = require.resolve('../../../package.json');
14
17
  const packageJson = require(packageJsonPath);
18
+ const AAR_DIR = path_1.default.join(os_1.default.homedir(), '.aar');
19
+ const UI_PID_FILE = path_1.default.join(AAR_DIR, 'ui.pid');
20
+ const GATEWAY_PID_FILE = path_1.default.join(AAR_DIR, 'gateway.pid');
21
+ const GATEWAY_PORT_FILE = path_1.default.join(AAR_DIR, 'gateway.port');
22
+ function ensureAarDir() {
23
+ if (!fs_1.default.existsSync(AAR_DIR)) {
24
+ fs_1.default.mkdirSync(AAR_DIR, { recursive: true });
25
+ }
26
+ }
27
+ function getPackageRoot() {
28
+ return path_1.default.dirname(path_1.default.dirname(path_1.default.dirname(__dirname)));
29
+ }
30
+ /** Wait for HTTP server to respond (e.g. UI or gateway ready) */
31
+ function waitForReady(baseUrl, maxWaitMs = 30000) {
32
+ const url = new URL(baseUrl);
33
+ return new Promise((resolve) => {
34
+ const start = Date.now();
35
+ const tryOnce = () => {
36
+ const req = http_1.default.request({
37
+ hostname: url.hostname,
38
+ port: url.port || '80',
39
+ path: url.pathname || '/',
40
+ method: 'GET',
41
+ timeout: 2000,
42
+ }, (res) => {
43
+ resolve(res.statusCode !== undefined && res.statusCode < 500);
44
+ });
45
+ req.on('error', () => {
46
+ if (Date.now() - start >= maxWaitMs) {
47
+ resolve(false);
48
+ return;
49
+ }
50
+ setTimeout(tryOnce, 800);
51
+ });
52
+ req.on('timeout', () => {
53
+ req.destroy();
54
+ if (Date.now() - start >= maxWaitMs)
55
+ resolve(false);
56
+ else
57
+ setTimeout(tryOnce, 800);
58
+ });
59
+ req.end();
60
+ };
61
+ tryOnce();
62
+ });
63
+ }
64
+ function printStatus(uiPort, gatewayPort, gatewayRunning, background) {
65
+ const uiUrl = `http://localhost:${uiPort}`;
66
+ const gatewayUrl = `http://localhost:${gatewayPort}`;
67
+ console.log('');
68
+ console.log('-------------------------------------------');
69
+ console.log(' AI Agent Router');
70
+ console.log('-------------------------------------------');
71
+ console.log(` 前台 UI: ${uiUrl}`);
72
+ console.log(` 网关地址: ${gatewayUrl}`);
73
+ console.log(` 网关状态: ${gatewayRunning ? '运行中' : '未启动'}`);
74
+ if (background) {
75
+ console.log(' 运行模式: 后台运行(关闭终端不影响)');
76
+ console.log(' 停止服务: aar stop');
77
+ }
78
+ console.log('-------------------------------------------');
79
+ console.log('');
80
+ }
15
81
  program
16
82
  .name('aar')
17
83
  .description('AI Agent Router - Web UI for managing the API gateway')
18
84
  .version(packageJson.version);
19
85
  program
20
86
  .command('start')
21
- .description('Start the Web UI management interface')
87
+ .description('Start the Web UI and gateway (default: both; use --no-gateway for UI only)')
22
88
  .option('-p, --port <port>', 'Port for Web UI', '9527')
89
+ .option('-g, --gateway-port <port>', 'Port for gateway (default: from config or 1357)')
90
+ .option('--no-gateway', 'Only start Web UI, do not start gateway')
91
+ .option('--no-background', 'Run in foreground (attach to terminal)')
23
92
  .action(async (options) => {
24
- const port = parseInt(options.port || '9527');
25
- console.log(`Starting AI Agent Router Web UI`);
26
- console.log(` Port: ${port}`);
27
- console.log(` Access the UI at: http://localhost:${port}`);
28
- console.log('');
29
- // Get the package root directory (where package.json is located)
30
- const packageRoot = path_1.default.dirname(path_1.default.dirname(path_1.default.dirname(__dirname)));
31
- // Start Web UI using Next.js
32
- // Always use production mode for globally installed package
93
+ const uiPort = parseInt(options.port || '9527', 10);
94
+ const startGateway = options.gateway !== false;
95
+ const background = options.background !== false;
96
+ const packageRoot = getPackageRoot();
97
+ let gatewayPort = 1357;
98
+ if (startGateway) {
99
+ try {
100
+ await (0, database_1.getDatabase)();
101
+ const portConfig = await (0, queries_1.getConfig)('port');
102
+ gatewayPort = options.gatewayPort
103
+ ? parseInt(options.gatewayPort, 10)
104
+ : parseInt(portConfig?.value || '1357', 10);
105
+ }
106
+ catch (e) {
107
+ gatewayPort = options.gatewayPort ? parseInt(options.gatewayPort, 10) : 1357;
108
+ }
109
+ }
33
110
  const serverPath = path_1.default.join(packageRoot, 'node_modules', 'next', 'dist', 'bin', 'next');
34
- const uiProcess = (0, child_process_1.spawn)(process.execPath, [serverPath, 'start', '-p', port.toString()], {
111
+ const gatewayScriptPath = path_1.default.join(packageRoot, 'dist', 'src', 'cli', 'gateway-server.js');
112
+ if (background) {
113
+ ensureAarDir();
114
+ const envBase = { ...process.env, NODE_ENV: 'production' };
115
+ const uiProc = (0, child_process_1.spawn)(process.execPath, [serverPath, 'start', '-p', uiPort.toString()], {
116
+ cwd: packageRoot,
117
+ env: { ...envBase, PORT: uiPort.toString() },
118
+ detached: true,
119
+ stdio: 'ignore',
120
+ });
121
+ uiProc.unref();
122
+ if (uiProc.pid) {
123
+ fs_1.default.writeFileSync(UI_PID_FILE, String(uiProc.pid));
124
+ }
125
+ let gatewayRunning = false;
126
+ if (startGateway && fs_1.default.existsSync(gatewayScriptPath)) {
127
+ const gwProc = (0, child_process_1.spawn)(process.execPath, [gatewayScriptPath, '--port', String(gatewayPort)], {
128
+ cwd: packageRoot,
129
+ env: envBase,
130
+ detached: true,
131
+ stdio: 'ignore',
132
+ });
133
+ gwProc.unref();
134
+ if (gwProc.pid) {
135
+ fs_1.default.writeFileSync(GATEWAY_PID_FILE, String(gwProc.pid));
136
+ fs_1.default.writeFileSync(GATEWAY_PORT_FILE, String(gatewayPort));
137
+ gatewayRunning = true;
138
+ }
139
+ try {
140
+ await (0, database_1.getDatabase)();
141
+ await (0, queries_1.setServiceStatus)({
142
+ status: 'running',
143
+ port: gatewayPort,
144
+ pid: gwProc.pid ?? null,
145
+ started_at: new Date().toISOString(),
146
+ });
147
+ }
148
+ catch {
149
+ // ignore db errors
150
+ }
151
+ }
152
+ printStatus(uiPort, gatewayPort, gatewayRunning, true);
153
+ process.exit(0);
154
+ }
155
+ // Foreground: start UI first
156
+ console.log('Starting AI Agent Router...');
157
+ const uiProcess = (0, child_process_1.spawn)(process.execPath, [serverPath, 'start', '-p', uiPort.toString()], {
35
158
  cwd: packageRoot,
36
159
  stdio: ['ignore', 'inherit', 'inherit'],
37
- env: { ...process.env, PORT: port.toString(), NODE_ENV: 'production' },
38
- });
39
- // Handle UI process exit
40
- uiProcess.on('exit', (code) => {
41
- console.log(`Web UI process exited with code ${code}`);
42
- process.exit(code || 0);
160
+ env: { ...process.env, PORT: uiPort.toString(), NODE_ENV: 'production' },
43
161
  });
44
162
  uiProcess.on('error', (error) => {
45
163
  console.error(`Failed to start Web UI: ${error.message}`);
46
164
  process.exit(1);
47
165
  });
48
- // Keep the process alive
49
- process.on('SIGINT', () => {
50
- console.log('\nShutting down...');
166
+ const gatewayProcess = startGateway && fs_1.default.existsSync(gatewayScriptPath)
167
+ ? (0, child_process_1.spawn)(process.execPath, [gatewayScriptPath, '--port', String(gatewayPort)], {
168
+ cwd: packageRoot,
169
+ stdio: ['ignore', 'pipe', 'pipe'],
170
+ env: { ...process.env, NODE_ENV: 'production' },
171
+ })
172
+ : null;
173
+ if (gatewayProcess?.stdout) {
174
+ gatewayProcess.stdout.on('data', (d) => process.stdout.write(d));
175
+ }
176
+ if (gatewayProcess?.stderr) {
177
+ gatewayProcess.stderr.on('data', (d) => process.stderr.write(d));
178
+ }
179
+ const ready = await waitForReady(`http://localhost:${uiPort}`);
180
+ if (ready) {
181
+ printStatus(uiPort, gatewayPort, !!gatewayProcess, false);
182
+ }
183
+ const shutdown = (signal) => {
184
+ console.log(`\nShutting down (${signal})...`);
185
+ if (gatewayProcess?.pid) {
186
+ try {
187
+ process.kill(gatewayProcess.pid, 'SIGTERM');
188
+ }
189
+ catch {
190
+ // ignore
191
+ }
192
+ }
51
193
  uiProcess.kill('SIGTERM');
52
194
  process.exit(0);
195
+ };
196
+ process.on('SIGINT', () => shutdown('SIGINT'));
197
+ process.on('SIGTERM', () => shutdown('SIGTERM'));
198
+ uiProcess.on('exit', (code) => {
199
+ if (gatewayProcess?.pid) {
200
+ try {
201
+ process.kill(gatewayProcess.pid, 'SIGTERM');
202
+ }
203
+ catch {
204
+ // ignore
205
+ }
206
+ }
207
+ process.exit(code ?? 0);
53
208
  });
54
209
  });
210
+ program
211
+ .command('stop')
212
+ .description('Stop AI Agent Router when running in background')
213
+ .action(async () => {
214
+ ensureAarDir();
215
+ let stopped = 0;
216
+ const killPidFile = (file, name) => {
217
+ if (!fs_1.default.existsSync(file))
218
+ return;
219
+ try {
220
+ const pid = parseInt(fs_1.default.readFileSync(file, 'utf8').trim(), 10);
221
+ if (!isNaN(pid)) {
222
+ try {
223
+ process.kill(pid, 'SIGTERM');
224
+ console.log(`Stopped ${name} (PID ${pid})`);
225
+ stopped++;
226
+ }
227
+ catch (e) {
228
+ if (e?.code !== 'ESRCH')
229
+ console.warn(`${name} (PID ${pid}): ${e.message}`);
230
+ }
231
+ }
232
+ fs_1.default.unlinkSync(file);
233
+ }
234
+ catch (e) {
235
+ // ignore
236
+ }
237
+ };
238
+ killPidFile(GATEWAY_PID_FILE, 'gateway');
239
+ killPidFile(UI_PID_FILE, 'Web UI');
240
+ if (fs_1.default.existsSync(GATEWAY_PORT_FILE))
241
+ fs_1.default.unlinkSync(GATEWAY_PORT_FILE);
242
+ try {
243
+ await (0, database_1.getDatabase)();
244
+ await (0, queries_1.updateServiceStatus)({ status: 'stopped', pid: null });
245
+ }
246
+ catch {
247
+ // ignore
248
+ }
249
+ if (stopped === 0) {
250
+ console.log('No background processes found (or already stopped).');
251
+ }
252
+ });
55
253
  program
56
254
  .command('config')
57
255
  .description('Manage gateway configuration')
@@ -15,14 +15,55 @@ const path_1 = __importDefault(require("path"));
15
15
  const fs_1 = __importDefault(require("fs"));
16
16
  const os_1 = __importDefault(require("os"));
17
17
  const DB_PATH = process.env.DB_PATH || path_1.default.join(os_1.default.homedir(), '.aar', 'gateway.db');
18
+ // Use hardcoded path for the built/distributed WASM file
19
+ // Next.js copies sql-wasm.wasm to its chunks directory
20
+ function findSqlJsWasmPath() {
21
+ // Try Next.js chunks directory first (works in dev and production)
22
+ const nextChunksPath = path_1.default.join(process.cwd(), '.next', 'dev', 'server', 'chunks', 'sql-wasm.wasm');
23
+ if (fs_1.default.existsSync(nextChunksPath)) {
24
+ return nextChunksPath;
25
+ }
26
+ // Try production .next directory
27
+ const prodChunksPath = path_1.default.join(process.cwd(), '.next', 'server', 'chunks', 'sql-wasm.wasm');
28
+ if (fs_1.default.existsSync(prodChunksPath)) {
29
+ return prodChunksPath;
30
+ }
31
+ // Try node_modules as fallback
32
+ const nodeModulesPath = path_1.default.join(process.cwd(), 'node_modules', 'sql.js', 'dist', 'sql-wasm.wasm');
33
+ if (fs_1.default.existsSync(nodeModulesPath)) {
34
+ return nodeModulesPath;
35
+ }
36
+ // Use the most likely location as default
37
+ return nodeModulesPath;
38
+ }
39
+ const SQLJS_WASM_PATH = findSqlJsWasmPath();
18
40
  let dbInstance = null;
19
41
  let sqlJsInstance = null;
42
+ let lastLoadMtimeMs = 0;
43
+ function reloadFromFileIfNewer() {
44
+ if (!dbInstance || !fs_1.default.existsSync(DB_PATH))
45
+ return;
46
+ const mtime = fs_1.default.statSync(DB_PATH).mtimeMs;
47
+ if (mtime <= lastLoadMtimeMs)
48
+ return;
49
+ try {
50
+ const fresh = loadDatabase();
51
+ if (fresh) {
52
+ dbInstance.close();
53
+ dbInstance = fresh;
54
+ lastLoadMtimeMs = fs_1.default.statSync(DB_PATH).mtimeMs;
55
+ }
56
+ }
57
+ catch (e) {
58
+ console.warn('[Database] Reload from file failed:', e.message);
59
+ }
60
+ }
20
61
  async function initSqlJsEngine() {
21
62
  if (!sqlJsInstance) {
22
63
  sqlJsInstance = await (0, sql_js_1.default)({
23
64
  locateFile: (file) => {
24
65
  if (file.endsWith('.wasm')) {
25
- return path_1.default.join(process.cwd(), 'node_modules', 'sql.js', 'dist', file);
66
+ return SQLJS_WASM_PATH;
26
67
  }
27
68
  return `https://sql.js.org/dist/${file}`;
28
69
  }
@@ -39,6 +80,9 @@ function saveDatabase(db) {
39
80
  fs_1.default.mkdirSync(dbDir, { recursive: true });
40
81
  }
41
82
  fs_1.default.writeFileSync(DB_PATH, buffer);
83
+ if (fs_1.default.existsSync(DB_PATH)) {
84
+ lastLoadMtimeMs = fs_1.default.statSync(DB_PATH).mtimeMs;
85
+ }
42
86
  }
43
87
  catch (error) {
44
88
  console.error('Failed to save database:', error);
@@ -59,7 +103,16 @@ function loadDatabase() {
59
103
  async function getDatabase() {
60
104
  if (!dbInstance) {
61
105
  const engine = await initSqlJsEngine();
62
- dbInstance = loadDatabase() || new engine.Database();
106
+ const loaded = loadDatabase();
107
+ if (loaded) {
108
+ dbInstance = loaded;
109
+ if (fs_1.default.existsSync(DB_PATH))
110
+ lastLoadMtimeMs = fs_1.default.statSync(DB_PATH).mtimeMs;
111
+ }
112
+ else {
113
+ dbInstance = new engine.Database();
114
+ lastLoadMtimeMs = 0;
115
+ }
63
116
  try {
64
117
  dbInstance.run(schema_1.CREATE_TABLES_SQL);
65
118
  // Migration: Allow NULL model_id in request_logs table
@@ -113,6 +166,7 @@ async function getDatabase() {
113
166
  }
114
167
  }
115
168
  }
169
+ reloadFromFileIfNewer();
116
170
  return dbInstance;
117
171
  }
118
172
  async function closeDatabase() {
@@ -125,7 +179,6 @@ async function closeDatabase() {
125
179
  function getDbPath() {
126
180
  return DB_PATH;
127
181
  }
128
- // Helper to run a query and get single result
129
182
  async function queryOne(sql, params = []) {
130
183
  const db = await getDatabase();
131
184
  const stmt = db.prepare(sql);
@@ -138,7 +191,6 @@ async function queryOne(sql, params = []) {
138
191
  stmt.free();
139
192
  return null;
140
193
  }
141
- // Helper to run a query and get all results
142
194
  async function queryAll(sql, params = []) {
143
195
  const db = await getDatabase();
144
196
  const results = [];
@@ -150,7 +202,6 @@ async function queryAll(sql, params = []) {
150
202
  stmt.free();
151
203
  return results;
152
204
  }
153
- // Helper to run INSERT/UPDATE/DELETE
154
205
  async function run(sql, params = []) {
155
206
  const db = await getDatabase();
156
207
  db.run(sql, params);
@@ -155,9 +155,9 @@ async function createRequestLog(log) {
155
155
  try {
156
156
  const result = await (0, database_1.run)(`INSERT INTO request_logs (
157
157
  model_id, request_method, request_path, request_headers,
158
- request_query, request_body, response_status, response_body, response_time_ms
159
- ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`, [
160
- log.model_id || null,
158
+ request_query, request_body, response_status, response_body, response_time_ms, created_at
159
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, datetime('now', 'localtime'))`, [
160
+ log.model_id === undefined ? null : log.model_id,
161
161
  log.request_method,
162
162
  log.request_path,
163
163
  log.request_headers,
@@ -178,9 +178,9 @@ async function createRequestLog(log) {
178
178
  console.warn(`[RequestLog] Foreign key constraint failed for model_id ${log.model_id}, retrying with NULL`);
179
179
  const result = await (0, database_1.run)(`INSERT INTO request_logs (
180
180
  model_id, request_method, request_path, request_headers,
181
- request_query, request_body, response_status, response_body, response_time_ms
182
- ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`, [
183
- null,
181
+ request_query, request_body, response_status, response_body, response_time_ms, created_at
182
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, datetime('now', 'localtime'))`, [
183
+ log.model_id === undefined ? null : log.model_id,
184
184
  log.request_method,
185
185
  log.request_path,
186
186
  log.request_headers,
@@ -3,6 +3,24 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.logRequest = logRequest;
4
4
  const queries_1 = require("../db/queries");
5
5
  const crypto_1 = require("./crypto");
6
+ /** Safe JSON.stringify that never throws; use for logging arbitrary response/request bodies. */
7
+ function safeStringify(value) {
8
+ if (value === undefined)
9
+ return '';
10
+ if (value === null)
11
+ return 'null';
12
+ try {
13
+ return JSON.stringify(value);
14
+ }
15
+ catch {
16
+ try {
17
+ return String(value);
18
+ }
19
+ catch {
20
+ return '[Non-serializable]';
21
+ }
22
+ }
23
+ }
6
24
  async function logRequest(request, response) {
7
25
  try {
8
26
  // Mask sensitive information
@@ -12,11 +30,11 @@ async function logRequest(request, response) {
12
30
  model_id: request.modelId,
13
31
  request_method: request.method,
14
32
  request_path: request.path,
15
- request_headers: JSON.stringify(maskedHeaders),
16
- request_query: JSON.stringify(request.query),
17
- request_body: JSON.stringify(maskedBody),
33
+ request_headers: safeStringify(maskedHeaders),
34
+ request_query: safeStringify(request.query),
35
+ request_body: safeStringify(maskedBody),
18
36
  response_status: response.status,
19
- response_body: JSON.stringify(response.body),
37
+ response_body: safeStringify(response.body),
20
38
  response_time_ms: response.responseTimeMs,
21
39
  });
22
40
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-agent-router",
3
- "version": "0.1.21",
3
+ "version": "0.2.1",
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": {
@@ -10,6 +10,7 @@
10
10
  "dev": "next dev -p 9527",
11
11
  "build": "next build && tsc",
12
12
  "start": "node dist/src/cli/index.js start",
13
+ "stop": "node dist/src/cli/index.js stop",
13
14
  "lint": "eslint .",
14
15
  "pub": "npm run build && npm publish",
15
16
  "type-check": "tsc --noEmit"
@@ -51,7 +51,7 @@ async function handleRequest(
51
51
  method: string
52
52
  ) {
53
53
  try {
54
- getDatabase();
54
+ await getDatabase();
55
55
 
56
56
  const path = params.path.join('/');
57
57
  const searchParams = request.nextUrl.searchParams;
@@ -19,7 +19,7 @@ async function handleGatewayRequestDirect(
19
19
  method: string
20
20
  ) {
21
21
  try {
22
- getDatabase();
22
+ await getDatabase();
23
23
  const searchParams = request.nextUrl.searchParams;
24
24
  let modelId = searchParams.get('model') || searchParams.get('model_id');
25
25
  const providerName = searchParams.get('provider');
@@ -38,11 +38,9 @@ export async function POST(request: NextRequest) {
38
38
  const gatewayAddress = await getGatewayAddress();
39
39
  const gatewayApiKey = await getGatewayApiKey();
40
40
 
41
- // 生成配置对象
42
41
  const modelMapping = { haiku, sonnet, opus, default: defaultModel, reasoning: reasoningModel };
43
- const config = generateClaudeConfig(gatewayAddress, gatewayApiKey, modelMapping);
42
+ const aarEnv = buildAarEnv(gatewayAddress, gatewayApiKey, modelMapping);
44
43
 
45
- // 备份原有配置
46
44
  const backupResult = backupOriginalConfig();
47
45
  if (!backupResult.success) {
48
46
  return NextResponse.json(
@@ -51,13 +49,27 @@ export async function POST(request: NextRequest) {
51
49
  );
52
50
  }
53
51
 
54
- // 确保目录存在
55
52
  if (!existsSync(CLAUDE_DIR)) {
56
53
  mkdirSync(CLAUDE_DIR, { recursive: true });
57
54
  }
58
55
 
59
- // 验证并写入新配置
60
- const validationResult = validateAndWriteConfig(config);
56
+ let configToWrite: any;
57
+ if (existsSync(SETTINGS_FILE)) {
58
+ try {
59
+ const existing = JSON.parse(readFileSync(SETTINGS_FILE, 'utf-8'));
60
+ configToWrite = {
61
+ ...existing,
62
+ env: { ...(existing.env || {}), ...aarEnv },
63
+ router_provider: 'aar',
64
+ };
65
+ } catch {
66
+ configToWrite = generateClaudeConfig(gatewayAddress, gatewayApiKey, modelMapping);
67
+ }
68
+ } else {
69
+ configToWrite = generateClaudeConfig(gatewayAddress, gatewayApiKey, modelMapping);
70
+ }
71
+
72
+ const validationResult = validateAndWriteConfig(configToWrite);
61
73
  if (!validationResult.success) {
62
74
  return NextResponse.json(
63
75
  { error: validationResult.error },
@@ -68,7 +80,7 @@ export async function POST(request: NextRequest) {
68
80
  return NextResponse.json({
69
81
  success: true,
70
82
  message: 'Configuration applied successfully',
71
- config,
83
+ config: configToWrite,
72
84
  backup: backupResult.existed ? 'Created backup' : 'No existing config to backup',
73
85
  previousWasFromAar: backupResult.existed && backupResult.isFromAar,
74
86
  });
@@ -101,57 +113,60 @@ async function getGatewayApiKey(): Promise<string> {
101
113
  return apiKeyConfig?.value || 'your-gateway-api-key';
102
114
  }
103
115
 
104
- /**
105
- * 生成 Claude 配置
106
- */
116
+ /** 仅生成 AAR 相关的 env 字段,用于合并到现有配置 */
117
+ function buildAarEnv(
118
+ gatewayAddress: string,
119
+ gatewayApiKey: string,
120
+ modelMapping: { haiku: string; sonnet: string; opus: string; default: string; reasoning: string }
121
+ ): Record<string, unknown> {
122
+ return {
123
+ ANTHROPIC_AUTH_TOKEN: gatewayApiKey,
124
+ ANTHROPIC_BASE_URL: gatewayAddress,
125
+ ANTHROPIC_DEFAULT_HAIKU_MODEL: modelMapping.haiku,
126
+ ANTHROPIC_DEFAULT_OPUS_MODEL: modelMapping.opus,
127
+ ANTHROPIC_DEFAULT_SONNET_MODEL: modelMapping.sonnet,
128
+ ANTHROPIC_MODEL: modelMapping.default,
129
+ ANTHROPIC_REASONING_MODEL: modelMapping.reasoning,
130
+ API_TIMEOUT_MS: '3000000',
131
+ CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC: 1,
132
+ hasCompletedOnboarding: true,
133
+ };
134
+ }
135
+
136
+ /** 生成完整 Claude 配置(仅在无现有文件时使用) */
107
137
  function generateClaudeConfig(
108
138
  gatewayAddress: string,
109
139
  gatewayApiKey: string,
110
140
  modelMapping: { haiku: string; sonnet: string; opus: string; default: string; reasoning: string }
111
141
  ): any {
112
142
  return {
113
- // 路由提供者标识,标识配置来自当前工具 aar
114
143
  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
- },
144
+ env: buildAarEnv(gatewayAddress, gatewayApiKey, modelMapping),
127
145
  };
128
146
  }
129
147
 
130
148
  /**
131
149
  * 备份原有配置
132
- * 返回原有配置是否来自当前工具(router_provider === 'aar')
150
+ * 仅在当前配置不是 AAR 时写入备份,这样「还原」才能恢复到应用 AAR 前的状态
133
151
  */
134
152
  function backupOriginalConfig(): { success: boolean; existed: boolean; isFromAar: boolean; error?: string } {
135
153
  try {
136
- // 检查原有配置是否存在
137
154
  const existing = existsSync(SETTINGS_FILE);
138
155
 
139
156
  if (existing) {
140
- // 读取原有配置
141
157
  const originalConfig = readFileSync(SETTINGS_FILE, 'utf-8');
142
158
 
143
- // 解析配置检查 router_provider
144
159
  let isFromAar = false;
145
160
  try {
146
161
  const parsedConfig = JSON.parse(originalConfig);
147
162
  isFromAar = parsedConfig.router_provider === 'aar';
148
- } catch (error) {
149
- // 解析失败,不影响备份操作
163
+ } catch {
150
164
  isFromAar = false;
151
165
  }
152
166
 
153
- // 写入备份文件
154
- writeFileSync(BACKUP_FILE, originalConfig, 'utf-8');
167
+ if (!isFromAar) {
168
+ writeFileSync(BACKUP_FILE, originalConfig, 'utf-8');
169
+ }
155
170
 
156
171
  return { success: true, existed: true, isFromAar };
157
172
  }