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.
- package/.next/BUILD_ID +1 -1
- package/.next/app-path-routes-manifest.json +14 -0
- package/.next/build-manifest.json +2 -2
- package/.next/fallback-build-manifest.json +2 -2
- package/.next/next-server.js.nft.json +1 -1
- package/.next/prerender-manifest.json +3 -3
- package/.next/required-server-files.js +4 -4
- package/.next/required-server-files.json +4 -4
- package/.next/routes-manifest.json +84 -0
- package/.next/server/app/_global-error/page.js +1 -1
- package/.next/server/app/_global-error/page.js.nft.json +1 -1
- package/.next/server/app/_global-error.html +2 -2
- package/.next/server/app/_global-error.rsc +1 -1
- package/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/_not-found/page.js +2 -2
- package/.next/server/app/_not-found/page.js.nft.json +1 -1
- package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/server/app/_not-found.html +1 -1
- package/.next/server/app/_not-found.rsc +2 -2
- package/.next/server/app/_not-found.segments/_full.segment.rsc +2 -2
- package/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/.next/server/app/_not-found.segments/_index.segment.rsc +2 -2
- package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/api/config/route.js.nft.json +1 -1
- package/.next/server/app/api/gateway/[...path]/route.js.nft.json +1 -1
- package/.next/server/app/api/gateway/models/route.js.nft.json +1 -1
- package/.next/server/app/api/gateway/route.js.nft.json +1 -1
- package/.next/server/app/api/ide/claude/apply/route.js.nft.json +1 -1
- package/.next/server/app/api/ide/claude/available-models/route.js.nft.json +1 -1
- package/.next/server/app/api/ide/claude/restore/route.js.nft.json +1 -1
- package/.next/server/app/api/ide/claude/save/route.js.nft.json +1 -1
- package/.next/server/app/api/ide/claude/status/route.js.nft.json +1 -1
- package/.next/server/app/api/ide/claude/test/route.js +1 -1
- package/.next/server/app/api/ide/claude/test/route.js.nft.json +1 -1
- package/.next/server/app/api/ide/openclaw/apply/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/ide/openclaw/apply/route/build-manifest.json +11 -0
- package/.next/server/app/api/ide/openclaw/apply/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/ide/openclaw/apply/route.js +7 -0
- package/.next/server/app/api/ide/openclaw/apply/route.js.map +5 -0
- package/.next/server/app/api/ide/openclaw/apply/route.js.nft.json +1 -0
- package/.next/server/app/api/ide/openclaw/apply/route_client-reference-manifest.js +2 -0
- package/.next/server/app/api/ide/openclaw/available-models/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/ide/openclaw/available-models/route/build-manifest.json +11 -0
- package/.next/server/app/api/ide/openclaw/available-models/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/ide/openclaw/available-models/route.js +7 -0
- package/.next/server/app/api/ide/openclaw/available-models/route.js.map +5 -0
- package/.next/server/app/api/ide/openclaw/available-models/route.js.nft.json +1 -0
- package/.next/server/app/api/ide/openclaw/available-models/route_client-reference-manifest.js +2 -0
- package/.next/server/app/api/ide/openclaw/preview/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/ide/openclaw/preview/route/build-manifest.json +11 -0
- package/.next/server/app/api/ide/openclaw/preview/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/ide/openclaw/preview/route.js +7 -0
- package/.next/server/app/api/ide/openclaw/preview/route.js.map +5 -0
- package/.next/server/app/api/ide/openclaw/preview/route.js.nft.json +1 -0
- package/.next/server/app/api/ide/openclaw/preview/route_client-reference-manifest.js +2 -0
- package/.next/server/app/api/ide/openclaw/restore/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/ide/openclaw/restore/route/build-manifest.json +11 -0
- package/.next/server/app/api/ide/openclaw/restore/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/ide/openclaw/restore/route.js +6 -0
- package/.next/server/app/api/ide/openclaw/restore/route.js.map +5 -0
- package/.next/server/app/api/ide/openclaw/restore/route.js.nft.json +1 -0
- package/.next/server/app/api/ide/openclaw/restore/route_client-reference-manifest.js +2 -0
- package/.next/server/app/api/ide/openclaw/save/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/ide/openclaw/save/route/build-manifest.json +11 -0
- package/.next/server/app/api/ide/openclaw/save/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/ide/openclaw/save/route.js +7 -0
- package/.next/server/app/api/ide/openclaw/save/route.js.map +5 -0
- package/.next/server/app/api/ide/openclaw/save/route.js.nft.json +1 -0
- package/.next/server/app/api/ide/openclaw/save/route_client-reference-manifest.js +2 -0
- package/.next/server/app/api/ide/openclaw/status/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/ide/openclaw/status/route/build-manifest.json +11 -0
- package/.next/server/app/api/ide/openclaw/status/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/ide/openclaw/status/route.js +7 -0
- package/.next/server/app/api/ide/openclaw/status/route.js.map +5 -0
- package/.next/server/app/api/ide/openclaw/status/route.js.nft.json +1 -0
- package/.next/server/app/api/ide/openclaw/status/route_client-reference-manifest.js +2 -0
- package/.next/server/app/api/ide/openclaw/test/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/ide/openclaw/test/route/build-manifest.json +11 -0
- package/.next/server/app/api/ide/openclaw/test/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/ide/openclaw/test/route.js +6 -0
- package/.next/server/app/api/ide/openclaw/test/route.js.map +5 -0
- package/.next/server/app/api/ide/openclaw/test/route.js.nft.json +1 -0
- package/.next/server/app/api/ide/openclaw/test/route_client-reference-manifest.js +2 -0
- package/.next/server/app/api/ide/opencode/apply/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/ide/opencode/apply/route/build-manifest.json +11 -0
- package/.next/server/app/api/ide/opencode/apply/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/ide/opencode/apply/route.js +7 -0
- package/.next/server/app/api/ide/opencode/apply/route.js.map +5 -0
- package/.next/server/app/api/ide/opencode/apply/route.js.nft.json +1 -0
- package/.next/server/app/api/ide/opencode/apply/route_client-reference-manifest.js +2 -0
- package/.next/server/app/api/ide/opencode/available-models/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/ide/opencode/available-models/route/build-manifest.json +11 -0
- package/.next/server/app/api/ide/opencode/available-models/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/ide/opencode/available-models/route.js +7 -0
- package/.next/server/app/api/ide/opencode/available-models/route.js.map +5 -0
- package/.next/server/app/api/ide/opencode/available-models/route.js.nft.json +1 -0
- package/.next/server/app/api/ide/opencode/available-models/route_client-reference-manifest.js +2 -0
- package/.next/server/app/api/ide/opencode/preview/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/ide/opencode/preview/route/build-manifest.json +11 -0
- package/.next/server/app/api/ide/opencode/preview/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/ide/opencode/preview/route.js +7 -0
- package/.next/server/app/api/ide/opencode/preview/route.js.map +5 -0
- package/.next/server/app/api/ide/opencode/preview/route.js.nft.json +1 -0
- package/.next/server/app/api/ide/opencode/preview/route_client-reference-manifest.js +2 -0
- package/.next/server/app/api/ide/opencode/restore/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/ide/opencode/restore/route/build-manifest.json +11 -0
- package/.next/server/app/api/ide/opencode/restore/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/ide/opencode/restore/route.js +6 -0
- package/.next/server/app/api/ide/opencode/restore/route.js.map +5 -0
- package/.next/server/app/api/ide/opencode/restore/route.js.nft.json +1 -0
- package/.next/server/app/api/ide/opencode/restore/route_client-reference-manifest.js +2 -0
- package/.next/server/app/api/ide/opencode/save/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/ide/opencode/save/route/build-manifest.json +11 -0
- package/.next/server/app/api/ide/opencode/save/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/ide/opencode/save/route.js +7 -0
- package/.next/server/app/api/ide/opencode/save/route.js.map +5 -0
- package/.next/server/app/api/ide/opencode/save/route.js.nft.json +1 -0
- package/.next/server/app/api/ide/opencode/save/route_client-reference-manifest.js +2 -0
- package/.next/server/app/api/ide/opencode/status/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/ide/opencode/status/route/build-manifest.json +11 -0
- package/.next/server/app/api/ide/opencode/status/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/ide/opencode/status/route.js +7 -0
- package/.next/server/app/api/ide/opencode/status/route.js.map +5 -0
- package/.next/server/app/api/ide/opencode/status/route.js.nft.json +1 -0
- package/.next/server/app/api/ide/opencode/status/route_client-reference-manifest.js +2 -0
- package/.next/server/app/api/ide/opencode/test/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/ide/opencode/test/route/build-manifest.json +11 -0
- package/.next/server/app/api/ide/opencode/test/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/ide/opencode/test/route.js +6 -0
- package/.next/server/app/api/ide/opencode/test/route.js.map +5 -0
- package/.next/server/app/api/ide/opencode/test/route.js.nft.json +1 -0
- package/.next/server/app/api/ide/opencode/test/route_client-reference-manifest.js +2 -0
- package/.next/server/app/api/logs/route.js.nft.json +1 -1
- package/.next/server/app/api/models/route.js.nft.json +1 -1
- package/.next/server/app/api/providers/route.js.nft.json +1 -1
- package/.next/server/app/api/providers/test/route.js.nft.json +1 -1
- package/.next/server/app/api/service/force-stop/route.js.nft.json +1 -1
- package/.next/server/app/api/service/start/route.js.nft.json +1 -1
- package/.next/server/app/api/service/status/route.js.nft.json +1 -1
- package/.next/server/app/api/service/stop/route.js.nft.json +1 -1
- package/.next/server/app/ide/page.js +2 -2
- package/.next/server/app/ide/page.js.nft.json +1 -1
- package/.next/server/app/ide/page_client-reference-manifest.js +1 -1
- package/.next/server/app/ide.html +1 -1
- package/.next/server/app/ide.rsc +3 -3
- package/.next/server/app/ide.segments/_full.segment.rsc +3 -3
- package/.next/server/app/ide.segments/_head.segment.rsc +1 -1
- package/.next/server/app/ide.segments/_index.segment.rsc +2 -2
- package/.next/server/app/ide.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/ide.segments/ide/__PAGE__.segment.rsc +2 -2
- package/.next/server/app/ide.segments/ide.segment.rsc +1 -1
- package/.next/server/app/index.html +1 -1
- package/.next/server/app/index.rsc +2 -2
- package/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/index.segments/_full.segment.rsc +2 -2
- package/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/.next/server/app/index.segments/_index.segment.rsc +2 -2
- package/.next/server/app/index.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/logs/page.js +2 -2
- package/.next/server/app/logs/page.js.nft.json +1 -1
- package/.next/server/app/logs/page_client-reference-manifest.js +1 -1
- package/.next/server/app/logs.html +1 -1
- package/.next/server/app/logs.rsc +3 -3
- package/.next/server/app/logs.segments/_full.segment.rsc +3 -3
- package/.next/server/app/logs.segments/_head.segment.rsc +1 -1
- package/.next/server/app/logs.segments/_index.segment.rsc +2 -2
- package/.next/server/app/logs.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/logs.segments/logs/__PAGE__.segment.rsc +2 -2
- package/.next/server/app/logs.segments/logs.segment.rsc +1 -1
- package/.next/server/app/models/page.js +2 -2
- package/.next/server/app/models/page.js.nft.json +1 -1
- package/.next/server/app/models/page_client-reference-manifest.js +1 -1
- package/.next/server/app/models.html +1 -1
- package/.next/server/app/models.rsc +2 -2
- package/.next/server/app/models.segments/_full.segment.rsc +2 -2
- package/.next/server/app/models.segments/_head.segment.rsc +1 -1
- package/.next/server/app/models.segments/_index.segment.rsc +2 -2
- package/.next/server/app/models.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/models.segments/models/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/models.segments/models.segment.rsc +1 -1
- package/.next/server/app/page.js +2 -2
- package/.next/server/app/page.js.nft.json +1 -1
- package/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/server/app/providers/page.js +2 -2
- package/.next/server/app/providers/page.js.nft.json +1 -1
- package/.next/server/app/providers/page_client-reference-manifest.js +1 -1
- package/.next/server/app/providers.html +1 -1
- package/.next/server/app/providers.rsc +2 -2
- package/.next/server/app/providers.segments/_full.segment.rsc +2 -2
- package/.next/server/app/providers.segments/_head.segment.rsc +1 -1
- package/.next/server/app/providers.segments/_index.segment.rsc +2 -2
- package/.next/server/app/providers.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/providers.segments/providers/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/providers.segments/providers.segment.rsc +1 -1
- package/.next/server/app-paths-manifest.json +14 -0
- package/.next/server/chunks/[root-of-the-server]__001d5756._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__001d5756._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__05f8578b._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__05f8578b._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__3a204d25._.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__3a204d25._.js.map +1 -1
- package/.next/server/chunks/[root-of-the-server]__43810962._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__43810962._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__4a8f9bc7._.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__4a8f9bc7._.js.map +1 -1
- package/.next/server/chunks/[root-of-the-server]__55cd88b8._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__55cd88b8._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__5e8276bc._.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__5e8276bc._.js.map +1 -1
- package/.next/server/chunks/[root-of-the-server]__760eaa16._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__760eaa16._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__7c298a19._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__7c298a19._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__85540228._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__85540228._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__94fe8d3c._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__94fe8d3c._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__97622908._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__97622908._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__a02e6618._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__a02e6618._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__a32a20a7._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__a32a20a7._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__af5b556a._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__af5b556a._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__c1b4b601._.js +16 -16
- package/.next/server/chunks/[root-of-the-server]__c1b4b601._.js.map +1 -1
- package/.next/server/chunks/[root-of-the-server]__cafe113e._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__cafe113e._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__dc8b0bed._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__dc8b0bed._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__f0461b8d._.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__f0461b8d._.js.map +1 -1
- package/.next/server/chunks/[root-of-the-server]__f8949f88._.js +1 -1
- package/.next/server/chunks/[root-of-the-server]__f8949f88._.js.map +1 -1
- package/.next/server/chunks/_next-internal_server_app_api_ide_openclaw_apply_route_actions_2cb9e4b4.js +3 -0
- package/.next/server/chunks/_next-internal_server_app_api_ide_openclaw_apply_route_actions_2cb9e4b4.js.map +1 -0
- package/.next/server/chunks/_next-internal_server_app_api_ide_openclaw_preview_route_actions_9814a8e4.js +3 -0
- package/.next/server/chunks/_next-internal_server_app_api_ide_openclaw_preview_route_actions_9814a8e4.js.map +1 -0
- package/.next/server/chunks/_next-internal_server_app_api_ide_openclaw_restore_route_actions_10ad8f9d.js +3 -0
- package/.next/server/chunks/_next-internal_server_app_api_ide_openclaw_restore_route_actions_10ad8f9d.js.map +1 -0
- package/.next/server/chunks/_next-internal_server_app_api_ide_openclaw_save_route_actions_044ad081.js +3 -0
- package/.next/server/chunks/_next-internal_server_app_api_ide_openclaw_save_route_actions_044ad081.js.map +1 -0
- package/.next/server/chunks/_next-internal_server_app_api_ide_openclaw_status_route_actions_ed9786d2.js +3 -0
- package/.next/server/chunks/_next-internal_server_app_api_ide_openclaw_status_route_actions_ed9786d2.js.map +1 -0
- package/.next/server/chunks/_next-internal_server_app_api_ide_openclaw_test_route_actions_ce2cb808.js +3 -0
- package/.next/server/chunks/_next-internal_server_app_api_ide_openclaw_test_route_actions_ce2cb808.js.map +1 -0
- package/.next/server/chunks/_next-internal_server_app_api_ide_opencode_apply_route_actions_6c422244.js +3 -0
- package/.next/server/chunks/_next-internal_server_app_api_ide_opencode_apply_route_actions_6c422244.js.map +1 -0
- package/.next/server/chunks/_next-internal_server_app_api_ide_opencode_preview_route_actions_256c82e0.js +3 -0
- package/.next/server/chunks/_next-internal_server_app_api_ide_opencode_preview_route_actions_256c82e0.js.map +1 -0
- package/.next/server/chunks/_next-internal_server_app_api_ide_opencode_restore_route_actions_371993d3.js +3 -0
- package/.next/server/chunks/_next-internal_server_app_api_ide_opencode_restore_route_actions_371993d3.js.map +1 -0
- package/.next/server/chunks/_next-internal_server_app_api_ide_opencode_save_route_actions_6e4c9c41.js +3 -0
- package/.next/server/chunks/_next-internal_server_app_api_ide_opencode_save_route_actions_6e4c9c41.js.map +1 -0
- package/.next/server/chunks/_next-internal_server_app_api_ide_opencode_status_route_actions_498ad77b.js +3 -0
- package/.next/server/chunks/_next-internal_server_app_api_ide_opencode_status_route_actions_498ad77b.js.map +1 -0
- package/.next/server/chunks/_next-internal_server_app_api_ide_opencode_test_route_actions_c71be510.js +3 -0
- package/.next/server/chunks/_next-internal_server_app_api_ide_opencode_test_route_actions_c71be510.js.map +1 -0
- package/.next/server/chunks/ce889_server_app_api_ide_openclaw_available-models_route_actions_e568e70b.js +3 -0
- package/.next/server/chunks/ce889_server_app_api_ide_openclaw_available-models_route_actions_e568e70b.js.map +1 -0
- package/.next/server/chunks/ce889_server_app_api_ide_opencode_available-models_route_actions_95230db3.js +3 -0
- package/.next/server/chunks/ce889_server_app_api_ide_opencode_available-models_route_actions_95230db3.js.map +1 -0
- package/.next/server/chunks/ssr/{[root-of-the-server]__bec95712._.js → [root-of-the-server]__81937253._.js} +2 -2
- package/.next/server/chunks/ssr/{[root-of-the-server]__bec95712._.js.map → [root-of-the-server]__81937253._.js.map} +1 -1
- package/.next/server/chunks/ssr/{[root-of-the-server]__71c85955._.js → [root-of-the-server]__976ad963._.js} +2 -2
- package/.next/server/chunks/ssr/{[root-of-the-server]__71c85955._.js.map → [root-of-the-server]__976ad963._.js.map} +1 -1
- package/.next/server/chunks/ssr/_69468f4c._.js +3 -0
- package/.next/server/chunks/ssr/_69468f4c._.js.map +1 -0
- package/.next/server/chunks/ssr/src_app_ide_page_tsx_8962793b._.js +1 -1
- package/.next/server/chunks/ssr/src_app_ide_page_tsx_8962793b._.js.map +1 -1
- package/.next/server/chunks/ssr/src_app_logs_page_tsx_7b7b7b83._.js +1 -1
- package/.next/server/chunks/ssr/src_app_logs_page_tsx_7b7b7b83._.js.map +1 -1
- package/.next/server/pages/404.html +1 -1
- package/.next/server/pages/500.html +2 -2
- package/.next/server/server-reference-manifest.js +1 -1
- package/.next/server/server-reference-manifest.json +1 -1
- package/.next/static/chunks/64f547b3bcd3aef4.js +1 -0
- package/.next/static/chunks/6992685fe009e8fd.css +1 -0
- package/.next/static/chunks/{b6b258e8582e47c4.js → 7c8b7cbb3339f139.js} +1 -1
- package/.next/static/chunks/8ccc14e022ff6de3.js +1 -0
- package/.next/types/routes.d.ts +15 -1
- package/.next/types/validator.ts +126 -0
- package/README.md +31 -4
- package/dist/.next/dev/types/validator.js +56 -0
- package/dist/.next/types/validator.js +56 -0
- package/dist/package.json +55 -0
- package/dist/src/app/api/config/route.js +17 -0
- package/dist/src/app/api/ide/claude/apply/route.js +126 -31
- package/dist/src/app/api/ide/claude/restore/route.js +30 -0
- package/dist/src/app/api/ide/claude/save/route.js +79 -0
- package/dist/src/app/api/ide/claude/status/route.js +6 -1
- package/dist/src/app/api/ide/openclaw/apply/route.js +92 -0
- package/dist/src/app/api/ide/openclaw/available-models/route.js +46 -0
- package/dist/src/app/api/ide/openclaw/build-config.js +101 -0
- package/dist/src/app/api/ide/openclaw/preview/route.js +49 -0
- package/dist/src/app/api/ide/openclaw/restore/route.js +24 -0
- package/dist/src/app/api/ide/openclaw/save/route.js +54 -0
- package/dist/src/app/api/ide/openclaw/status/route.js +139 -0
- package/dist/src/app/api/ide/openclaw/test/route.js +158 -0
- package/dist/src/app/api/ide/opencode/apply/route.js +89 -0
- package/dist/src/app/api/ide/opencode/available-models/route.js +46 -0
- package/dist/src/app/api/ide/opencode/build-config.js +54 -0
- package/dist/src/app/api/ide/opencode/preview/route.js +36 -0
- package/dist/src/app/api/ide/opencode/restore/route.js +40 -0
- package/dist/src/app/api/ide/opencode/save/route.js +123 -0
- package/dist/src/app/api/ide/opencode/status/route.js +106 -0
- package/dist/src/app/api/ide/opencode/test/route.js +136 -0
- package/dist/src/app/components/Footer.js +11 -0
- package/dist/src/app/ide/page.js +651 -81
- package/dist/src/app/layout.js +5 -1
- package/dist/src/app/logs/page.js +4 -2
- package/dist/src/db/database.js +44 -8
- package/package.json +1 -1
- package/src/app/api/config/route.ts +17 -0
- package/src/app/api/ide/claude/apply/route.ts +140 -31
- package/src/app/api/ide/claude/restore/route.ts +36 -1
- package/src/app/api/ide/claude/save/route.ts +91 -1
- package/src/app/api/ide/claude/status/route.ts +12 -2
- package/src/app/api/ide/openclaw/apply/route.ts +103 -0
- package/src/app/api/ide/openclaw/available-models/route.ts +59 -0
- package/src/app/api/ide/openclaw/build-config.ts +152 -0
- package/src/app/api/ide/openclaw/preview/route.ts +57 -0
- package/src/app/api/ide/openclaw/restore/route.ts +27 -0
- package/src/app/api/ide/openclaw/save/route.ts +67 -0
- package/src/app/api/ide/openclaw/status/route.ts +178 -0
- package/src/app/api/ide/openclaw/test/route.ts +194 -0
- package/src/app/api/ide/opencode/apply/route.ts +92 -0
- package/src/app/api/ide/opencode/available-models/route.ts +59 -0
- package/src/app/api/ide/opencode/build-config.ts +69 -0
- package/src/app/api/ide/opencode/preview/route.ts +40 -0
- package/src/app/api/ide/opencode/restore/route.ts +52 -0
- package/src/app/api/ide/opencode/save/route.ts +131 -0
- package/src/app/api/ide/opencode/status/route.ts +128 -0
- package/src/app/api/ide/opencode/test/route.ts +145 -0
- package/src/app/components/Footer.tsx +9 -0
- package/src/app/globals.css +17 -0
- package/src/app/ide/page.tsx +1587 -118
- package/src/app/layout.tsx +3 -1
- package/src/app/logs/page.tsx +4 -2
- package/src/db/database.ts +55 -8
- package/.next/server/chunks/ssr/src_app_b2b1d928._.js +0 -3
- package/.next/server/chunks/ssr/src_app_b2b1d928._.js.map +0 -1
- package/.next/static/chunks/6418ca50028376b7.css +0 -1
- package/.next/static/chunks/9ec3b97741b6575e.js +0 -1
- /package/.next/static/{ryTeHAYUvjT1bYolc-x9Z → cf2SWIkI5HVbnDjLExI42}/_buildManifest.js +0 -0
- /package/.next/static/{ryTeHAYUvjT1bYolc-x9Z → cf2SWIkI5HVbnDjLExI42}/_clientMiddlewareManifest.json +0 -0
- /package/.next/static/{ryTeHAYUvjT1bYolc-x9Z → cf2SWIkI5HVbnDjLExI42}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import { NextRequest, NextResponse } from 'next/server';
|
|
2
|
+
import { existsSync, readFileSync } from 'fs';
|
|
3
|
+
import { join } from 'path';
|
|
4
|
+
import { homedir } from 'os';
|
|
5
|
+
import { spawn } from 'child_process';
|
|
6
|
+
|
|
7
|
+
const OPENCLAW_DIR = join(homedir(), '.openclaw');
|
|
8
|
+
const OPENCLAW_FILE = join(OPENCLAW_DIR, 'openclaw.json');
|
|
9
|
+
|
|
10
|
+
const RUN_TIMEOUT_MS = 30_000;
|
|
11
|
+
|
|
12
|
+
interface TestResult {
|
|
13
|
+
success: boolean;
|
|
14
|
+
error?: string;
|
|
15
|
+
message?: string;
|
|
16
|
+
checks?: Record<string, boolean>;
|
|
17
|
+
configSummary?: {
|
|
18
|
+
baseUrl?: string;
|
|
19
|
+
apiKey?: string;
|
|
20
|
+
routerProvider?: string;
|
|
21
|
+
primaryModel?: string;
|
|
22
|
+
fallbackModels?: string[];
|
|
23
|
+
imageModel?: string;
|
|
24
|
+
fallbackImageModels?: string[];
|
|
25
|
+
};
|
|
26
|
+
probeResult?: {
|
|
27
|
+
success: boolean;
|
|
28
|
+
stdout: string;
|
|
29
|
+
stderr: string;
|
|
30
|
+
error?: string;
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function runCommand(args: string[]): Promise<{ success: boolean; stdout: string; stderr: string; error?: string; code?: number }> {
|
|
35
|
+
return new Promise((resolve) => {
|
|
36
|
+
const child = spawn('openclaw', args, {
|
|
37
|
+
shell: process.platform === 'win32',
|
|
38
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
let stdout = '';
|
|
42
|
+
let stderr = '';
|
|
43
|
+
|
|
44
|
+
child.stdout?.on('data', (chunk: Buffer) => {
|
|
45
|
+
stdout += chunk.toString('utf-8');
|
|
46
|
+
});
|
|
47
|
+
child.stderr?.on('data', (chunk: Buffer) => {
|
|
48
|
+
stderr += chunk.toString('utf-8');
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
child.on('error', (err) => {
|
|
52
|
+
resolve({ success: false, stdout, stderr, error: err.message });
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
child.on('close', (code) => {
|
|
56
|
+
resolve({ success: code === 0, stdout, stderr, code: code ?? undefined });
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
setTimeout(() => {
|
|
60
|
+
if (!child.killed) {
|
|
61
|
+
child.kill();
|
|
62
|
+
resolve({ success: false, stdout, stderr, error: 'Timeout' });
|
|
63
|
+
}
|
|
64
|
+
}, RUN_TIMEOUT_MS);
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function maskApiKey(apiKey: string): string {
|
|
69
|
+
if (!apiKey || apiKey === 'your-gateway-api-key') return apiKey;
|
|
70
|
+
if (apiKey.length <= 8) return apiKey.slice(0, 2) + '***' + apiKey.slice(-2);
|
|
71
|
+
return apiKey.slice(0, 4) + '****' + apiKey.slice(-4);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export async function GET(request: NextRequest) {
|
|
75
|
+
try {
|
|
76
|
+
// Check config file exists
|
|
77
|
+
if (!existsSync(OPENCLAW_FILE)) {
|
|
78
|
+
return NextResponse.json({
|
|
79
|
+
success: false,
|
|
80
|
+
error: 'Configuration file not found',
|
|
81
|
+
suggestion: 'Please apply configuration first',
|
|
82
|
+
} as TestResult);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const content = readFileSync(OPENCLAW_FILE, 'utf-8');
|
|
86
|
+
let config: any;
|
|
87
|
+
try {
|
|
88
|
+
config = JSON.parse(content);
|
|
89
|
+
} catch {
|
|
90
|
+
return NextResponse.json({
|
|
91
|
+
success: false,
|
|
92
|
+
error: 'Invalid configuration format',
|
|
93
|
+
} as TestResult);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Extract config summary
|
|
97
|
+
const modelsConfig = config.models || {};
|
|
98
|
+
const providers = modelsConfig.providers || {};
|
|
99
|
+
const aarProvider = providers['aar-gateway'];
|
|
100
|
+
|
|
101
|
+
const configSummary: TestResult['configSummary'] = {
|
|
102
|
+
baseUrl: aarProvider?.baseUrl,
|
|
103
|
+
apiKey: maskApiKey(aarProvider?.apiKey || ''),
|
|
104
|
+
routerProvider: aarProvider ? 'aar' : undefined,
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
const primaryModel = config.agents?.defaults?.model?.primary;
|
|
108
|
+
if (primaryModel) {
|
|
109
|
+
configSummary.primaryModel = primaryModel;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const fallbackModels = config.agents?.defaults?.model?.fallbacks;
|
|
113
|
+
if (Array.isArray(fallbackModels)) {
|
|
114
|
+
configSummary.fallbackModels = fallbackModels;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
const imageModel = config.agents?.defaults?.imageModel?.primary;
|
|
118
|
+
if (imageModel) {
|
|
119
|
+
configSummary.imageModel = imageModel;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const fallbackImageModels = config.agents?.defaults?.imageModel?.fallbacks;
|
|
123
|
+
if (Array.isArray(fallbackImageModels)) {
|
|
124
|
+
configSummary.fallbackImageModels = fallbackImageModels;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Run probe command to test provider accessibility
|
|
128
|
+
const probeResult = await runCommand([
|
|
129
|
+
'models', 'status',
|
|
130
|
+
'--probe',
|
|
131
|
+
'--probe-provider', 'aar-gateway',
|
|
132
|
+
'--json'
|
|
133
|
+
]);
|
|
134
|
+
|
|
135
|
+
let probeSuccess = false;
|
|
136
|
+
let probeMessage = 'Provider not found or not accessible';
|
|
137
|
+
|
|
138
|
+
if (probeResult.success) {
|
|
139
|
+
// Try to parse JSON output
|
|
140
|
+
try {
|
|
141
|
+
const parsed = JSON.parse(probeResult.stdout);
|
|
142
|
+
// Check if probe was successful
|
|
143
|
+
probeSuccess = parsed?.success === true || parsed?.status === 'ok';
|
|
144
|
+
if (probeSuccess) {
|
|
145
|
+
probeMessage = 'Provider is accessible and responding';
|
|
146
|
+
} else {
|
|
147
|
+
probeMessage = parsed?.message || 'Probe returned unsuccessful status';
|
|
148
|
+
}
|
|
149
|
+
} catch {
|
|
150
|
+
// If not JSON, check for success indicators in text
|
|
151
|
+
probeSuccess = probeResult.stdout.toLowerCase().includes('ok') ||
|
|
152
|
+
probeResult.stdout.toLowerCase().includes('success') ||
|
|
153
|
+
probeResult.stdout.toLowerCase().includes('aar-gateway');
|
|
154
|
+
probeMessage = probeSuccess
|
|
155
|
+
? 'Provider is accessible'
|
|
156
|
+
: 'Could not verify provider status';
|
|
157
|
+
}
|
|
158
|
+
} else {
|
|
159
|
+
probeMessage = probeResult.error || `Command failed (code ${probeResult.code})`;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const checks: Record<string, boolean> = {
|
|
163
|
+
hasBaseUrl: !!aarProvider?.baseUrl,
|
|
164
|
+
hasApiKey: !!aarProvider?.apiKey && aarProvider?.apiKey !== 'your-gateway-api-key',
|
|
165
|
+
hasModels: Array.isArray(aarProvider?.models) && aarProvider.models.length > 0,
|
|
166
|
+
hasPrimaryModel: !!primaryModel,
|
|
167
|
+
hasProvider: !!aarProvider,
|
|
168
|
+
probeSuccess,
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
const success = checks.hasBaseUrl && checks.hasApiKey && checks.hasProvider && probeSuccess;
|
|
172
|
+
|
|
173
|
+
const result: TestResult = {
|
|
174
|
+
success,
|
|
175
|
+
message: success ? 'Configuration verified successfully' : 'Configuration verification failed',
|
|
176
|
+
checks,
|
|
177
|
+
configSummary,
|
|
178
|
+
probeResult: {
|
|
179
|
+
success: probeSuccess,
|
|
180
|
+
stdout: probeResult.stdout.slice(-3000),
|
|
181
|
+
stderr: probeResult.stderr.slice(-500),
|
|
182
|
+
error: probeResult.error,
|
|
183
|
+
},
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
return NextResponse.json(result);
|
|
187
|
+
} catch (error: any) {
|
|
188
|
+
console.error('OpenClaw Test API error:', error);
|
|
189
|
+
return NextResponse.json({
|
|
190
|
+
success: false,
|
|
191
|
+
error: error.message || 'Internal server error',
|
|
192
|
+
} as TestResult);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { NextRequest, NextResponse } from 'next/server';
|
|
2
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'fs';
|
|
3
|
+
import { join } from 'path';
|
|
4
|
+
import { homedir } from 'os';
|
|
5
|
+
import { buildMergedConfig } from '../build-config';
|
|
6
|
+
|
|
7
|
+
const OPENCODE_DIR =
|
|
8
|
+
process.platform === 'win32'
|
|
9
|
+
? join(process.env.APPDATA || homedir(), 'opencode')
|
|
10
|
+
: join(homedir(), '.config', 'opencode');
|
|
11
|
+
const OPENCODE_FILE = join(OPENCODE_DIR, 'opencode.json');
|
|
12
|
+
const BACKUP_FILE = join(OPENCODE_DIR, 'opencode.json.aar.bak');
|
|
13
|
+
|
|
14
|
+
function backupOriginalConfig(): { success: boolean; existed: boolean; isFromAar: boolean; error?: string } {
|
|
15
|
+
try {
|
|
16
|
+
const existing = existsSync(OPENCODE_FILE);
|
|
17
|
+
if (existing) {
|
|
18
|
+
const original = readFileSync(OPENCODE_FILE, 'utf-8');
|
|
19
|
+
let isFromAar = false;
|
|
20
|
+
try {
|
|
21
|
+
const parsed = JSON.parse(original);
|
|
22
|
+
isFromAar = !!(parsed.provider && parsed.provider['aar-gateway']);
|
|
23
|
+
} catch {}
|
|
24
|
+
// 仅在当前配置不是 AAR 时写入备份,这样「还原」才能恢复到应用 AAR 前的状态;若已是 AAR 则保留原有备份不覆盖
|
|
25
|
+
if (!isFromAar) {
|
|
26
|
+
writeFileSync(BACKUP_FILE, original, 'utf-8');
|
|
27
|
+
}
|
|
28
|
+
return { success: true, existed: true, isFromAar };
|
|
29
|
+
}
|
|
30
|
+
return { success: true, existed: false, isFromAar: false };
|
|
31
|
+
} catch (error: any) {
|
|
32
|
+
return { success: false, existed: false, isFromAar: false, error: `Backup failed: ${error.message}` };
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export async function POST(request: NextRequest) {
|
|
37
|
+
try {
|
|
38
|
+
const body = await request.json();
|
|
39
|
+
const { default_model: defaultModel, config: customConfigStr } = body;
|
|
40
|
+
|
|
41
|
+
let existing: Record<string, any> | null = null;
|
|
42
|
+
if (existsSync(OPENCODE_FILE)) {
|
|
43
|
+
try {
|
|
44
|
+
existing = JSON.parse(readFileSync(OPENCODE_FILE, 'utf-8'));
|
|
45
|
+
} catch {
|
|
46
|
+
existing = null;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
let config: Record<string, any>;
|
|
51
|
+
if (typeof customConfigStr === 'string' && customConfigStr.trim()) {
|
|
52
|
+
try {
|
|
53
|
+
config = JSON.parse(customConfigStr);
|
|
54
|
+
if (!config || typeof config !== 'object') throw new Error('Invalid config object');
|
|
55
|
+
} catch (e: any) {
|
|
56
|
+
return NextResponse.json({ error: 'Invalid config JSON: ' + (e.message || 'parse error') }, { status: 400 });
|
|
57
|
+
}
|
|
58
|
+
} else {
|
|
59
|
+
if (defaultModel === undefined || defaultModel === '') {
|
|
60
|
+
return NextResponse.json({ error: 'Missing required field: default_model' }, { status: 400 });
|
|
61
|
+
}
|
|
62
|
+
config = await buildMergedConfig(defaultModel, existing);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const backupResult = backupOriginalConfig();
|
|
66
|
+
if (!backupResult.success) {
|
|
67
|
+
return NextResponse.json({ error: backupResult.error }, { status: 500 });
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (!existsSync(OPENCODE_DIR)) {
|
|
71
|
+
mkdirSync(OPENCODE_DIR, { recursive: true });
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const jsonString = JSON.stringify(config, null, 2);
|
|
75
|
+
writeFileSync(OPENCODE_FILE, jsonString, 'utf-8');
|
|
76
|
+
|
|
77
|
+
const alreadyHadAar = !!(existing?.provider?.['aar-gateway']);
|
|
78
|
+
return NextResponse.json({
|
|
79
|
+
success: true,
|
|
80
|
+
message: alreadyHadAar ? 'OpenCode 配置已更新为最新网关信息' : 'OpenCode configuration applied successfully',
|
|
81
|
+
config,
|
|
82
|
+
backup: backupResult.existed ? 'Created backup' : 'No existing config to backup',
|
|
83
|
+
previousWasFromAar: backupResult.existed && backupResult.isFromAar,
|
|
84
|
+
});
|
|
85
|
+
} catch (error: any) {
|
|
86
|
+
console.error('OpenCode Apply API error:', error);
|
|
87
|
+
return NextResponse.json(
|
|
88
|
+
{ error: error.message || 'Internal server error', stack: process.env.NODE_ENV === 'development' ? error.stack : undefined },
|
|
89
|
+
{ status: 500 }
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { NextRequest, NextResponse } from 'next/server';
|
|
2
|
+
import { getAllModels, getProviderById } from '@/db/queries';
|
|
3
|
+
|
|
4
|
+
type AvailableModel = {
|
|
5
|
+
id: number;
|
|
6
|
+
name: string;
|
|
7
|
+
model_id: string;
|
|
8
|
+
provider_id: number;
|
|
9
|
+
provider_name: string;
|
|
10
|
+
enabled: boolean;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
type GroupedModels = { [providerName: string]: AvailableModel[] };
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* 查询可用模型列表(与 Claude 共用网关,用于 OpenCode 配置)
|
|
17
|
+
*/
|
|
18
|
+
export async function GET(request: NextRequest) {
|
|
19
|
+
try {
|
|
20
|
+
const allModels = (await getAllModels()).filter((m: any) => m.enabled);
|
|
21
|
+
|
|
22
|
+
if (allModels.length === 0) {
|
|
23
|
+
return NextResponse.json({
|
|
24
|
+
models: {},
|
|
25
|
+
count: 0,
|
|
26
|
+
message: 'No enabled models found. Please enable some models first.',
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const grouped = await allModels.reduce(async (acc: Promise<GroupedModels>, model: any) => {
|
|
31
|
+
const resolvedAcc = await acc;
|
|
32
|
+
const provider = await getProviderById(model.provider_id);
|
|
33
|
+
if (provider) {
|
|
34
|
+
if (!resolvedAcc[provider.name]) resolvedAcc[provider.name] = [];
|
|
35
|
+
resolvedAcc[provider.name].push({
|
|
36
|
+
id: model.id,
|
|
37
|
+
name: model.name,
|
|
38
|
+
model_id: model.model_id,
|
|
39
|
+
provider_id: model.provider_id,
|
|
40
|
+
provider_name: provider.name,
|
|
41
|
+
enabled: model.enabled,
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
return resolvedAcc;
|
|
45
|
+
}, Promise.resolve({} as GroupedModels));
|
|
46
|
+
|
|
47
|
+
return NextResponse.json({
|
|
48
|
+
models: grouped,
|
|
49
|
+
count: allModels.length,
|
|
50
|
+
providers: Object.keys(grouped),
|
|
51
|
+
});
|
|
52
|
+
} catch (error: any) {
|
|
53
|
+
console.error('OpenCode Available Models API error:', error);
|
|
54
|
+
return NextResponse.json(
|
|
55
|
+
{ error: error.message || 'Internal server error', stack: process.env.NODE_ENV === 'development' ? error.stack : undefined },
|
|
56
|
+
{ status: 500 }
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { getDatabase } from '@/db/database';
|
|
2
|
+
import { getConfig } from '@/db/queries';
|
|
3
|
+
import { getAllModels, getProviderById } from '@/db/queries';
|
|
4
|
+
|
|
5
|
+
export async function getGatewayAddress(): Promise<string> {
|
|
6
|
+
await getDatabase();
|
|
7
|
+
const portConfig = await getConfig('port');
|
|
8
|
+
const port = portConfig?.value || '1357';
|
|
9
|
+
return `http://localhost:${port}/v1`;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export async function getGatewayApiKey(): Promise<string> {
|
|
13
|
+
await getDatabase();
|
|
14
|
+
const apiKeyConfig = await getConfig('api_key');
|
|
15
|
+
return apiKeyConfig?.value || 'your-gateway-api-key';
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/** OpenCode provider 下单个 provider 的结构(与官方 provider 文档一致) */
|
|
19
|
+
export type AarGatewayProviderEntry = {
|
|
20
|
+
npm: string;
|
|
21
|
+
name: string;
|
|
22
|
+
options: { baseURL: string; apiKey: string };
|
|
23
|
+
models: Record<string, { name: string; limit?: { context: number; output?: number } }>;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export async function buildAarGatewayProvider(): Promise<AarGatewayProviderEntry> {
|
|
27
|
+
const gatewayAddress = await getGatewayAddress();
|
|
28
|
+
const gatewayApiKey = await getGatewayApiKey();
|
|
29
|
+
const allModels = (await getAllModels()).filter((m: any) => m.enabled);
|
|
30
|
+
const models: Record<string, { name: string; limit: { context: number; output: number } }> = {};
|
|
31
|
+
for (const m of allModels) {
|
|
32
|
+
await getProviderById(m.provider_id);
|
|
33
|
+
models[m.model_id] = { name: m.name, limit: { context: 128000, output: 65536 } };
|
|
34
|
+
}
|
|
35
|
+
return {
|
|
36
|
+
npm: '@ai-sdk/openai-compatible',
|
|
37
|
+
name: 'AAR Model Router',
|
|
38
|
+
options: { baseURL: gatewayAddress, apiKey: gatewayApiKey },
|
|
39
|
+
models,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const AAR_PROVIDER_ID = 'aar-gateway';
|
|
44
|
+
|
|
45
|
+
/** 合并现有配置与 AAR 网关:写入 config.provider["aar-gateway"],并设置 config.model = "aar-gateway/{defaultModel}" */
|
|
46
|
+
export function mergeConfigWithAar(
|
|
47
|
+
existing: Record<string, any> | null,
|
|
48
|
+
defaultModel: string,
|
|
49
|
+
aarProvider: AarGatewayProviderEntry
|
|
50
|
+
): Record<string, any> {
|
|
51
|
+
const base = existing && typeof existing === 'object' ? { ...existing } : {};
|
|
52
|
+
const provider: Record<string, any> =
|
|
53
|
+
base.provider && typeof base.provider === 'object' ? { ...base.provider } : {};
|
|
54
|
+
provider[AAR_PROVIDER_ID] = aarProvider;
|
|
55
|
+
return {
|
|
56
|
+
...base,
|
|
57
|
+
provider,
|
|
58
|
+
model: `${AAR_PROVIDER_ID}/${defaultModel}`,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** 生成合并后的配置(不写入磁盘),供预览或应用使用 */
|
|
63
|
+
export async function buildMergedConfig(
|
|
64
|
+
defaultModel: string,
|
|
65
|
+
existing: Record<string, any> | null
|
|
66
|
+
): Promise<Record<string, any>> {
|
|
67
|
+
const aarProvider = await buildAarGatewayProvider();
|
|
68
|
+
return mergeConfigWithAar(existing, defaultModel, aarProvider);
|
|
69
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { NextRequest, NextResponse } from 'next/server';
|
|
2
|
+
import { existsSync, readFileSync } from 'fs';
|
|
3
|
+
import { join } from 'path';
|
|
4
|
+
import { homedir } from 'os';
|
|
5
|
+
import { buildMergedConfig } from '../build-config';
|
|
6
|
+
|
|
7
|
+
const OPENCODE_FILE =
|
|
8
|
+
process.platform === 'win32'
|
|
9
|
+
? join(process.env.APPDATA || homedir(), 'opencode', 'opencode.json')
|
|
10
|
+
: join(homedir(), '.config', 'opencode', 'opencode.json');
|
|
11
|
+
|
|
12
|
+
/** GET ?default_model=xxx 返回配置预览:始终返回「现有配置 + AAR provider + 默认模型」的合并结果,即应用后将写入的内容 */
|
|
13
|
+
export async function GET(request: NextRequest) {
|
|
14
|
+
try {
|
|
15
|
+
const { searchParams } = new URL(request.url);
|
|
16
|
+
const defaultModel = searchParams.get('default_model') || '';
|
|
17
|
+
|
|
18
|
+
if (!defaultModel) {
|
|
19
|
+
return NextResponse.json({ error: 'Missing query: default_model' }, { status: 400 });
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
let existing: Record<string, any> | null = null;
|
|
23
|
+
if (existsSync(OPENCODE_FILE)) {
|
|
24
|
+
try {
|
|
25
|
+
existing = JSON.parse(readFileSync(OPENCODE_FILE, 'utf-8'));
|
|
26
|
+
} catch {
|
|
27
|
+
/* 文件损坏时 existing 保持 null */
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const config = await buildMergedConfig(defaultModel, existing);
|
|
32
|
+
return NextResponse.json({ config });
|
|
33
|
+
} catch (error: any) {
|
|
34
|
+
console.error('OpenCode Preview API error:', error);
|
|
35
|
+
return NextResponse.json(
|
|
36
|
+
{ error: error.message || 'Internal server error', stack: process.env.NODE_ENV === 'development' ? error.stack : undefined },
|
|
37
|
+
{ status: 500 }
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { NextRequest, NextResponse } from 'next/server';
|
|
2
|
+
import { existsSync, readFileSync, copyFileSync } from 'fs';
|
|
3
|
+
import { join } from 'path';
|
|
4
|
+
import { homedir } from 'os';
|
|
5
|
+
|
|
6
|
+
const OPENCODE_DIR =
|
|
7
|
+
process.platform === 'win32'
|
|
8
|
+
? join(process.env.APPDATA || homedir(), 'opencode')
|
|
9
|
+
: join(homedir(), '.config', 'opencode');
|
|
10
|
+
const OPENCODE_FILE = join(OPENCODE_DIR, 'opencode.json');
|
|
11
|
+
const BACKUP_FILE = join(OPENCODE_DIR, 'opencode.json.aar.bak');
|
|
12
|
+
|
|
13
|
+
export async function POST(request: NextRequest) {
|
|
14
|
+
try {
|
|
15
|
+
if (!existsSync(BACKUP_FILE)) {
|
|
16
|
+
return NextResponse.json(
|
|
17
|
+
{ error: 'No backup file found. Please apply configuration first before restoring.' },
|
|
18
|
+
{ status: 404 }
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const backupContent = readFileSync(BACKUP_FILE, 'utf-8');
|
|
23
|
+
|
|
24
|
+
if (!existsSync(OPENCODE_DIR)) {
|
|
25
|
+
return NextResponse.json({ error: 'OpenCode config directory does not exist' }, { status: 500 });
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
copyFileSync(BACKUP_FILE, OPENCODE_FILE);
|
|
29
|
+
|
|
30
|
+
let parsedBackup: any;
|
|
31
|
+
try {
|
|
32
|
+
parsedBackup = JSON.parse(backupContent);
|
|
33
|
+
} catch {
|
|
34
|
+
return NextResponse.json(
|
|
35
|
+
{ error: 'Backup file is corrupted or invalid JSON', backupContent },
|
|
36
|
+
{ status: 500 }
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return NextResponse.json({
|
|
41
|
+
success: true,
|
|
42
|
+
message: 'OpenCode configuration restored successfully',
|
|
43
|
+
config: parsedBackup,
|
|
44
|
+
});
|
|
45
|
+
} catch (error: any) {
|
|
46
|
+
console.error('OpenCode Restore API error:', error);
|
|
47
|
+
return NextResponse.json(
|
|
48
|
+
{ error: error.message || 'Internal server error', stack: process.env.NODE_ENV === 'development' ? error.stack : undefined },
|
|
49
|
+
{ status: 500 }
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { NextRequest, NextResponse } from 'next/server';
|
|
2
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'fs';
|
|
3
|
+
import { join } from 'path';
|
|
4
|
+
import { homedir } from 'os';
|
|
5
|
+
import { getDatabase } from '@/db/database';
|
|
6
|
+
import { getConfig } from '@/db/queries';
|
|
7
|
+
import { buildMergedConfig } from '../build-config';
|
|
8
|
+
|
|
9
|
+
const OPENCODE_DIR =
|
|
10
|
+
process.platform === 'win32'
|
|
11
|
+
? join(process.env.APPDATA || homedir(), 'opencode')
|
|
12
|
+
: join(homedir(), '.config', 'opencode');
|
|
13
|
+
const OPENCODE_FILE = join(OPENCODE_DIR, 'opencode.json');
|
|
14
|
+
const BACKUP_FILE = join(OPENCODE_DIR, 'opencode.json.aar.bak');
|
|
15
|
+
const AAR_DIR = join(homedir(), '.aar');
|
|
16
|
+
const TEMP_OPENCODE_FILE = join(AAR_DIR, 'opencode.tmp.json');
|
|
17
|
+
|
|
18
|
+
function backupIfExists(): { success: boolean; error?: string } {
|
|
19
|
+
try {
|
|
20
|
+
if (existsSync(OPENCODE_FILE)) {
|
|
21
|
+
const original = readFileSync(OPENCODE_FILE, 'utf-8');
|
|
22
|
+
writeFileSync(BACKUP_FILE, original, 'utf-8');
|
|
23
|
+
}
|
|
24
|
+
return { success: true };
|
|
25
|
+
} catch (error: any) {
|
|
26
|
+
return { success: false, error: `Backup failed: ${error.message}` };
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async function getGatewayAddress(): Promise<string> {
|
|
31
|
+
await getDatabase();
|
|
32
|
+
const portConfig = await getConfig('port');
|
|
33
|
+
return `http://localhost:${portConfig?.value || '1357'}/v1`;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
async function getGatewayApiKey(): Promise<string> {
|
|
37
|
+
await getDatabase();
|
|
38
|
+
const apiKeyConfig = await getConfig('api_key');
|
|
39
|
+
return apiKeyConfig?.value || 'your-gateway-api-key';
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export async function POST(request: NextRequest) {
|
|
43
|
+
try {
|
|
44
|
+
const body = await request.json();
|
|
45
|
+
const { default_model: defaultModel, config: customConfigStr } = body;
|
|
46
|
+
|
|
47
|
+
// 若前端传了编辑后的 config,直接写入 opencode.json(与「应用配置」一致)
|
|
48
|
+
if (typeof customConfigStr === 'string' && customConfigStr.trim()) {
|
|
49
|
+
let config: Record<string, any>;
|
|
50
|
+
try {
|
|
51
|
+
config = JSON.parse(customConfigStr);
|
|
52
|
+
if (!config || typeof config !== 'object') throw new Error('Invalid config object');
|
|
53
|
+
} catch (e: any) {
|
|
54
|
+
return NextResponse.json({ error: 'Invalid config JSON: ' + (e.message || 'parse error') }, { status: 400 });
|
|
55
|
+
}
|
|
56
|
+
const backupResult = backupIfExists();
|
|
57
|
+
if (!backupResult.success) {
|
|
58
|
+
return NextResponse.json({ error: backupResult.error }, { status: 500 });
|
|
59
|
+
}
|
|
60
|
+
if (!existsSync(OPENCODE_DIR)) mkdirSync(OPENCODE_DIR, { recursive: true });
|
|
61
|
+
writeFileSync(OPENCODE_FILE, JSON.stringify(config, null, 2), 'utf-8');
|
|
62
|
+
return NextResponse.json({
|
|
63
|
+
success: true,
|
|
64
|
+
message: '配置已更新到 OpenCode',
|
|
65
|
+
saveType: 'applied',
|
|
66
|
+
savePath: '~/.config/opencode/opencode.json',
|
|
67
|
+
config,
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (defaultModel === undefined || defaultModel === '') {
|
|
72
|
+
return NextResponse.json({ error: 'No default model provided' }, { status: 400 });
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const gatewayAddress = await getGatewayAddress();
|
|
76
|
+
const gatewayApiKey = await getGatewayApiKey();
|
|
77
|
+
|
|
78
|
+
const fileExists = existsSync(OPENCODE_FILE);
|
|
79
|
+
let current: Record<string, any> | null = null;
|
|
80
|
+
if (fileExists) {
|
|
81
|
+
try {
|
|
82
|
+
current = JSON.parse(readFileSync(OPENCODE_FILE, 'utf-8'));
|
|
83
|
+
} catch {
|
|
84
|
+
current = null;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
const aar = current?.provider?.['aar-gateway'];
|
|
88
|
+
const isCurrentGatewayApplied =
|
|
89
|
+
!!aar &&
|
|
90
|
+
aar?.options?.baseURL === gatewayAddress &&
|
|
91
|
+
aar?.options?.apiKey === gatewayApiKey;
|
|
92
|
+
|
|
93
|
+
let savePath: string;
|
|
94
|
+
let saveType: string;
|
|
95
|
+
let mergedConfig: any;
|
|
96
|
+
|
|
97
|
+
if (fileExists && isCurrentGatewayApplied && current) {
|
|
98
|
+
mergedConfig = await buildMergedConfig(defaultModel, current);
|
|
99
|
+
savePath = OPENCODE_FILE;
|
|
100
|
+
saveType = 'applied';
|
|
101
|
+
} else {
|
|
102
|
+
savePath = TEMP_OPENCODE_FILE;
|
|
103
|
+
saveType = 'temp';
|
|
104
|
+
mergedConfig = {
|
|
105
|
+
defaultModel,
|
|
106
|
+
isTemp: true,
|
|
107
|
+
savedAt: new Date().toISOString(),
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const targetDir = savePath === OPENCODE_FILE ? OPENCODE_DIR : AAR_DIR;
|
|
112
|
+
if (!existsSync(targetDir)) {
|
|
113
|
+
mkdirSync(targetDir, { recursive: true });
|
|
114
|
+
}
|
|
115
|
+
writeFileSync(savePath, JSON.stringify(mergedConfig, null, 2), 'utf-8');
|
|
116
|
+
|
|
117
|
+
return NextResponse.json({
|
|
118
|
+
success: true,
|
|
119
|
+
message: saveType === 'applied' ? '配置已更新到 OpenCode' : '配置已保存(临时)',
|
|
120
|
+
saveType,
|
|
121
|
+
savePath: savePath === OPENCODE_FILE ? '~/.config/opencode/opencode.json' : '~/.aar/opencode.tmp.json',
|
|
122
|
+
config: mergedConfig,
|
|
123
|
+
});
|
|
124
|
+
} catch (error: any) {
|
|
125
|
+
console.error('OpenCode Save API error:', error);
|
|
126
|
+
return NextResponse.json(
|
|
127
|
+
{ error: error.message || 'Internal server error', stack: process.env.NODE_ENV === 'development' ? error.stack : undefined },
|
|
128
|
+
{ status: 500 }
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
}
|