ai-agent-router 0.2.2 → 0.2.4
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 +4 -1
- package/.next/build/chunks/{[root-of-the-server]__6d51cb5d._.js → [root-of-the-server]__0iv9ksq._.js} +1 -1
- package/.next/build/chunks/[root-of-the-server]__0iv9ksq._.js.map +8 -0
- package/.next/build/chunks/{[root-of-the-server]__44695d76._.js → [root-of-the-server]__0rua-~2._.js} +30 -30
- package/.next/build/chunks/[root-of-the-server]__0rua-~2._.js.map +11 -0
- package/.next/build/chunks/{[turbopack-node]_transforms_postcss_ts_df7a5b11._.js → [turbopack-node]_transforms_postcss_ts_0nnejqq._.js} +2 -2
- package/.next/build/chunks/[turbopack]_runtime.js +155 -60
- package/.next/build/chunks/[turbopack]_runtime.js.map +6 -5
- package/.next/build/chunks/{node_modules_fe693df6._.js → node_modules_13sb.px._.js} +1 -1
- package/.next/build/chunks/{node_modules_fe693df6._.js.map → node_modules_13sb.px._.js.map} +42 -42
- package/.next/build/postcss.js +5 -5
- package/.next/build-manifest.json +8 -7
- package/.next/diagnostics/framework.json +1 -1
- package/.next/diagnostics/route-bundle-stats.json +93 -0
- package/.next/fallback-build-manifest.json +3 -2
- package/.next/images-manifest.json +1 -0
- package/.next/next-minimal-server.js.nft.json +1 -1
- package/.next/next-server.js.nft.json +1 -1
- package/.next/prerender-manifest.json +33 -9
- package/.next/required-server-files.js +18 -6
- package/.next/required-server-files.json +18 -6
- package/.next/routes-manifest.json +19 -0
- package/.next/server/app/_global-error/page/build-manifest.json +5 -5
- package/.next/server/app/_global-error/page.js +8 -9
- package/.next/server/app/_global-error/page.js.nft.json +1 -1
- package/.next/server/app/_global-error/page_client-reference-manifest.js +2 -1
- package/.next/server/app/_global-error.html +1 -2
- package/.next/server/app/_global-error.rsc +11 -9
- package/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +2 -2
- package/.next/server/app/_global-error.segments/_full.segment.rsc +11 -9
- package/.next/server/app/_global-error.segments/_head.segment.rsc +3 -3
- package/.next/server/app/_global-error.segments/_index.segment.rsc +4 -3
- package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/_not-found/page/build-manifest.json +5 -5
- package/.next/server/app/_not-found/page.js +11 -12
- package/.next/server/app/_not-found/page.js.nft.json +1 -1
- package/.next/server/app/_not-found/page_client-reference-manifest.js +2 -1
- package/.next/server/app/_not-found.html +1 -1
- package/.next/server/app/_not-found.rsc +13 -11
- package/.next/server/app/_not-found.segments/_full.segment.rsc +13 -11
- package/.next/server/app/_not-found.segments/_head.segment.rsc +3 -3
- package/.next/server/app/_not-found.segments/_index.segment.rsc +5 -5
- package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +2 -2
- package/.next/server/app/_not-found.segments/_not-found.segment.rsc +4 -3
- package/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/api/config/route/build-manifest.json +1 -3
- package/.next/server/app/api/config/route.js +4 -4
- package/.next/server/app/api/config/route.js.nft.json +1 -1
- package/.next/server/app/api/config/route_client-reference-manifest.js +2 -1
- package/.next/server/app/api/gateway/[...path]/route/build-manifest.json +1 -3
- package/.next/server/app/api/gateway/[...path]/route.js +5 -5
- package/.next/server/app/api/gateway/[...path]/route.js.nft.json +1 -1
- package/.next/server/app/api/gateway/[...path]/route_client-reference-manifest.js +2 -1
- package/.next/server/app/api/gateway/models/route/build-manifest.json +1 -3
- package/.next/server/app/api/gateway/models/route.js +4 -4
- package/.next/server/app/api/gateway/models/route.js.nft.json +1 -1
- package/.next/server/app/api/gateway/models/route_client-reference-manifest.js +2 -1
- package/.next/server/app/api/gateway/route/build-manifest.json +1 -3
- package/.next/server/app/api/gateway/route.js +5 -5
- package/.next/server/app/api/gateway/route.js.nft.json +1 -1
- package/.next/server/app/api/gateway/route_client-reference-manifest.js +2 -1
- package/.next/server/app/api/ide/claude/apply/route/build-manifest.json +1 -3
- package/.next/server/app/api/ide/claude/apply/route.js +4 -4
- package/.next/server/app/api/ide/claude/apply/route.js.nft.json +1 -1
- package/.next/server/app/api/ide/claude/apply/route_client-reference-manifest.js +2 -1
- package/.next/server/app/api/ide/claude/available-models/route/build-manifest.json +1 -3
- package/.next/server/app/api/ide/claude/available-models/route.js +4 -4
- package/.next/server/app/api/ide/claude/available-models/route.js.nft.json +1 -1
- package/.next/server/app/api/ide/claude/available-models/route_client-reference-manifest.js +2 -1
- package/.next/server/app/api/ide/claude/restore/route/build-manifest.json +1 -3
- package/.next/server/app/api/ide/claude/restore/route.js +3 -3
- package/.next/server/app/api/ide/claude/restore/route.js.nft.json +1 -1
- package/.next/server/app/api/ide/claude/restore/route_client-reference-manifest.js +2 -1
- package/.next/server/app/api/ide/claude/save/route/build-manifest.json +1 -3
- package/.next/server/app/api/ide/claude/save/route.js +4 -4
- package/.next/server/app/api/ide/claude/save/route.js.nft.json +1 -1
- package/.next/server/app/api/ide/claude/save/route_client-reference-manifest.js +2 -1
- package/.next/server/app/api/ide/claude/status/route/build-manifest.json +1 -3
- package/.next/server/app/api/ide/claude/status/route.js +4 -4
- package/.next/server/app/api/ide/claude/status/route.js.nft.json +1 -1
- package/.next/server/app/api/ide/claude/status/route_client-reference-manifest.js +2 -1
- package/.next/server/app/api/ide/claude/test/route/build-manifest.json +1 -3
- package/.next/server/app/api/ide/claude/test/route.js +5 -5
- package/.next/server/app/api/ide/claude/test/route.js.nft.json +1 -1
- package/.next/server/app/api/ide/claude/test/route_client-reference-manifest.js +2 -1
- package/.next/server/app/api/ide/openclaw/apply/route/build-manifest.json +1 -3
- package/.next/server/app/api/ide/openclaw/apply/route.js +4 -4
- package/.next/server/app/api/ide/openclaw/apply/route.js.nft.json +1 -1
- package/.next/server/app/api/ide/openclaw/apply/route_client-reference-manifest.js +2 -1
- package/.next/server/app/api/ide/openclaw/available-models/route/build-manifest.json +1 -3
- package/.next/server/app/api/ide/openclaw/available-models/route.js +4 -4
- package/.next/server/app/api/ide/openclaw/available-models/route.js.nft.json +1 -1
- package/.next/server/app/api/ide/openclaw/available-models/route_client-reference-manifest.js +2 -1
- package/.next/server/app/api/ide/openclaw/preview/route/build-manifest.json +1 -3
- package/.next/server/app/api/ide/openclaw/preview/route.js +4 -4
- package/.next/server/app/api/ide/openclaw/preview/route.js.nft.json +1 -1
- package/.next/server/app/api/ide/openclaw/preview/route_client-reference-manifest.js +2 -1
- package/.next/server/app/api/ide/openclaw/restore/route/build-manifest.json +1 -3
- package/.next/server/app/api/ide/openclaw/restore/route.js +3 -3
- package/.next/server/app/api/ide/openclaw/restore/route.js.nft.json +1 -1
- package/.next/server/app/api/ide/openclaw/restore/route_client-reference-manifest.js +2 -1
- package/.next/server/app/api/ide/openclaw/save/route/build-manifest.json +1 -3
- package/.next/server/app/api/ide/openclaw/save/route.js +4 -4
- package/.next/server/app/api/ide/openclaw/save/route.js.nft.json +1 -1
- package/.next/server/app/api/ide/openclaw/save/route_client-reference-manifest.js +2 -1
- package/.next/server/app/api/ide/openclaw/status/route/build-manifest.json +1 -3
- package/.next/server/app/api/ide/openclaw/status/route.js +4 -4
- package/.next/server/app/api/ide/openclaw/status/route.js.nft.json +1 -1
- package/.next/server/app/api/ide/openclaw/status/route_client-reference-manifest.js +2 -1
- package/.next/server/app/api/ide/openclaw/test/route/build-manifest.json +1 -3
- package/.next/server/app/api/ide/openclaw/test/route.js +3 -3
- package/.next/server/app/api/ide/openclaw/test/route.js.nft.json +1 -1
- package/.next/server/app/api/ide/openclaw/test/route_client-reference-manifest.js +2 -1
- package/.next/server/app/api/ide/opencode/apply/route/build-manifest.json +1 -3
- package/.next/server/app/api/ide/opencode/apply/route.js +4 -4
- package/.next/server/app/api/ide/opencode/apply/route.js.nft.json +1 -1
- package/.next/server/app/api/ide/opencode/apply/route_client-reference-manifest.js +2 -1
- package/.next/server/app/api/ide/opencode/available-models/route/build-manifest.json +1 -3
- package/.next/server/app/api/ide/opencode/available-models/route.js +4 -4
- package/.next/server/app/api/ide/opencode/available-models/route.js.nft.json +1 -1
- package/.next/server/app/api/ide/opencode/available-models/route_client-reference-manifest.js +2 -1
- package/.next/server/app/api/ide/opencode/preview/route/build-manifest.json +1 -3
- package/.next/server/app/api/ide/opencode/preview/route.js +4 -4
- package/.next/server/app/api/ide/opencode/preview/route.js.nft.json +1 -1
- package/.next/server/app/api/ide/opencode/preview/route_client-reference-manifest.js +2 -1
- package/.next/server/app/api/ide/opencode/restore/route/build-manifest.json +1 -3
- package/.next/server/app/api/ide/opencode/restore/route.js +3 -3
- package/.next/server/app/api/ide/opencode/restore/route.js.nft.json +1 -1
- package/.next/server/app/api/ide/opencode/restore/route_client-reference-manifest.js +2 -1
- package/.next/server/app/api/ide/opencode/save/route/build-manifest.json +1 -3
- package/.next/server/app/api/ide/opencode/save/route.js +4 -4
- package/.next/server/app/api/ide/opencode/save/route.js.nft.json +1 -1
- package/.next/server/app/api/ide/opencode/save/route_client-reference-manifest.js +2 -1
- package/.next/server/app/api/ide/opencode/status/route/build-manifest.json +1 -3
- package/.next/server/app/api/ide/opencode/status/route.js +4 -4
- package/.next/server/app/api/ide/opencode/status/route.js.nft.json +1 -1
- package/.next/server/app/api/ide/opencode/status/route_client-reference-manifest.js +2 -1
- package/.next/server/app/api/ide/opencode/test/route/build-manifest.json +1 -3
- package/.next/server/app/api/ide/opencode/test/route.js +3 -3
- package/.next/server/app/api/ide/opencode/test/route.js.nft.json +1 -1
- package/.next/server/app/api/ide/opencode/test/route_client-reference-manifest.js +2 -1
- package/.next/server/app/api/logs/route/build-manifest.json +1 -3
- package/.next/server/app/api/logs/route.js +4 -4
- package/.next/server/app/api/logs/route.js.nft.json +1 -1
- package/.next/server/app/api/logs/route_client-reference-manifest.js +2 -1
- package/.next/server/app/api/models/route/build-manifest.json +1 -3
- package/.next/server/app/api/models/route.js +5 -5
- package/.next/server/app/api/models/route.js.nft.json +1 -1
- package/.next/server/app/api/models/route_client-reference-manifest.js +2 -1
- package/.next/server/app/api/providers/route/build-manifest.json +1 -3
- package/.next/server/app/api/providers/route.js +5 -5
- package/.next/server/app/api/providers/route.js.nft.json +1 -1
- package/.next/server/app/api/providers/route_client-reference-manifest.js +2 -1
- package/.next/server/app/api/providers/test/route/build-manifest.json +1 -3
- package/.next/server/app/api/providers/test/route.js +5 -5
- package/.next/server/app/api/providers/test/route.js.nft.json +1 -1
- package/.next/server/app/api/providers/test/route_client-reference-manifest.js +2 -1
- package/.next/server/app/api/service/force-stop/route/build-manifest.json +1 -3
- package/.next/server/app/api/service/force-stop/route.js +4 -4
- package/.next/server/app/api/service/force-stop/route.js.nft.json +1 -1
- package/.next/server/app/api/service/force-stop/route_client-reference-manifest.js +2 -1
- package/.next/server/app/api/service/start/route/build-manifest.json +1 -3
- package/.next/server/app/api/service/start/route.js +4 -4
- package/.next/server/app/api/service/start/route.js.nft.json +1 -1
- package/.next/server/app/api/service/start/route_client-reference-manifest.js +2 -1
- package/.next/server/app/api/service/status/route/build-manifest.json +1 -3
- package/.next/server/app/api/service/status/route.js +4 -4
- package/.next/server/app/api/service/status/route.js.nft.json +1 -1
- package/.next/server/app/api/service/status/route_client-reference-manifest.js +2 -1
- package/.next/server/app/api/service/stop/route/build-manifest.json +1 -3
- package/.next/server/app/api/service/stop/route.js +4 -4
- package/.next/server/app/api/service/stop/route.js.nft.json +1 -1
- package/.next/server/app/api/service/stop/route_client-reference-manifest.js +2 -1
- package/.next/server/app/api/tokenizer/history/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/tokenizer/history/route/build-manifest.json +9 -0
- package/.next/server/app/api/tokenizer/history/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/tokenizer/history/route.js +7 -0
- package/.next/server/app/api/tokenizer/history/route.js.map +5 -0
- package/.next/server/app/api/tokenizer/history/route.js.nft.json +1 -0
- package/.next/server/app/api/tokenizer/history/route_client-reference-manifest.js +3 -0
- package/.next/server/app/api/tokenizer/test/route/app-paths-manifest.json +3 -0
- package/.next/server/app/api/tokenizer/test/route/build-manifest.json +9 -0
- package/.next/server/app/api/tokenizer/test/route/server-reference-manifest.json +4 -0
- package/.next/server/app/api/tokenizer/test/route.js +8 -0
- package/.next/server/app/api/tokenizer/test/route.js.map +5 -0
- package/.next/server/app/api/tokenizer/test/route.js.nft.json +1 -0
- package/.next/server/app/api/tokenizer/test/route_client-reference-manifest.js +3 -0
- package/.next/server/app/ide/page/build-manifest.json +5 -5
- package/.next/server/app/ide/page.js +12 -14
- package/.next/server/app/ide/page.js.nft.json +1 -1
- package/.next/server/app/ide/page_client-reference-manifest.js +2 -1
- package/.next/server/app/ide.html +1 -1
- package/.next/server/app/ide.rsc +15 -13
- package/.next/server/app/ide.segments/_full.segment.rsc +15 -13
- package/.next/server/app/ide.segments/_head.segment.rsc +3 -3
- package/.next/server/app/ide.segments/_index.segment.rsc +5 -5
- package/.next/server/app/ide.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/ide.segments/ide/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/ide.segments/ide.segment.rsc +4 -3
- package/.next/server/app/index.html +1 -1
- package/.next/server/app/index.rsc +11 -11
- package/.next/server/app/index.segments/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/index.segments/_full.segment.rsc +11 -11
- package/.next/server/app/index.segments/_head.segment.rsc +3 -3
- package/.next/server/app/index.segments/_index.segment.rsc +5 -5
- package/.next/server/app/index.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/logs/page/build-manifest.json +5 -5
- package/.next/server/app/logs/page.js +12 -14
- package/.next/server/app/logs/page.js.nft.json +1 -1
- package/.next/server/app/logs/page_client-reference-manifest.js +2 -1
- package/.next/server/app/logs.html +1 -1
- package/.next/server/app/logs.rsc +15 -13
- package/.next/server/app/logs.segments/_full.segment.rsc +15 -13
- package/.next/server/app/logs.segments/_head.segment.rsc +3 -3
- package/.next/server/app/logs.segments/_index.segment.rsc +5 -5
- package/.next/server/app/logs.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/logs.segments/logs/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/logs.segments/logs.segment.rsc +4 -3
- package/.next/server/app/models/page/build-manifest.json +5 -5
- package/.next/server/app/models/page.js +12 -14
- package/.next/server/app/models/page.js.nft.json +1 -1
- package/.next/server/app/models/page_client-reference-manifest.js +2 -1
- package/.next/server/app/models.html +1 -1
- package/.next/server/app/models.rsc +15 -13
- package/.next/server/app/models.segments/_full.segment.rsc +15 -13
- package/.next/server/app/models.segments/_head.segment.rsc +3 -3
- package/.next/server/app/models.segments/_index.segment.rsc +5 -5
- package/.next/server/app/models.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/models.segments/models/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/models.segments/models.segment.rsc +4 -3
- package/.next/server/app/page/build-manifest.json +5 -5
- package/.next/server/app/page.js +12 -14
- package/.next/server/app/page.js.nft.json +1 -1
- package/.next/server/app/page_client-reference-manifest.js +2 -1
- package/.next/server/app/providers/page/build-manifest.json +5 -5
- package/.next/server/app/providers/page.js +12 -14
- package/.next/server/app/providers/page.js.nft.json +1 -1
- package/.next/server/app/providers/page_client-reference-manifest.js +2 -1
- package/.next/server/app/providers.html +1 -1
- package/.next/server/app/providers.rsc +15 -13
- package/.next/server/app/providers.segments/_full.segment.rsc +15 -13
- package/.next/server/app/providers.segments/_head.segment.rsc +3 -3
- package/.next/server/app/providers.segments/_index.segment.rsc +5 -5
- package/.next/server/app/providers.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/providers.segments/providers/__PAGE__.segment.rsc +4 -4
- package/.next/server/app/providers.segments/providers.segment.rsc +4 -3
- package/.next/server/app/tokenizer/page/app-paths-manifest.json +3 -0
- package/.next/server/app/tokenizer/page/build-manifest.json +16 -0
- package/.next/server/app/tokenizer/page/next-font-manifest.json +6 -0
- package/.next/server/app/tokenizer/page/react-loadable-manifest.json +1 -0
- package/.next/server/app/tokenizer/page/server-reference-manifest.json +4 -0
- package/.next/server/app/tokenizer/page.js +13 -0
- package/.next/server/app/tokenizer/page.js.map +5 -0
- package/.next/server/app/tokenizer/page.js.nft.json +1 -0
- package/.next/server/app/tokenizer/page_client-reference-manifest.js +3 -0
- package/.next/server/app/tokenizer.html +1 -0
- package/.next/server/app/tokenizer.meta +15 -0
- package/.next/server/app/tokenizer.rsc +20 -0
- package/.next/server/app/tokenizer.segments/_full.segment.rsc +20 -0
- package/.next/server/app/tokenizer.segments/_head.segment.rsc +5 -0
- package/.next/server/app/tokenizer.segments/_index.segment.rsc +6 -0
- package/.next/server/app/tokenizer.segments/_tree.segment.rsc +2 -0
- package/.next/server/app/tokenizer.segments/tokenizer/__PAGE__.segment.rsc +9 -0
- package/.next/server/app/tokenizer.segments/tokenizer.segment.rsc +5 -0
- package/.next/server/app-paths-manifest.json +4 -1
- package/.next/server/chunks/0zjb_server_app_api_ide_openclaw_available-models_route_actions_0.gjr6a.js +3 -0
- package/.next/server/chunks/0zjb_server_app_api_ide_opencode_available-models_route_actions_0poyhyk.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__0-_5z3v._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__0-_5z3v._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__012ucp~._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__012ucp~._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__01atdgx._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__01atdgx._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__01~ft76._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__01~ft76._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__04sfkei._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__04sfkei._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__065r.wp._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__065r.wp._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__07pm7px._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__07pm7px._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__07vosna._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__07vosna._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__083j1v0._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__083j1v0._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__08_ekvs._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__08_ekvs._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__08ftz8n._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__08ftz8n._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__08oq8ma._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__08oq8ma._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__099b1my._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__099b1my._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__0aw-~h8._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__0aw-~h8._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__0dj43ut._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__0dj43ut._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__0efv_yh._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__0efv_yh._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__0el37wu._.js +7 -0
- package/.next/server/chunks/[root-of-the-server]__0el37wu._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__0g.1w-q._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__0g.1w-q._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__0im~-m7._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__0im~-m7._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__0jf1q27._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__0jf1q27._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__0kldv62._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__0kldv62._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__0lr16iw._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__0lr16iw._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__0m62mql._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__0m62mql._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__0qp1t_m._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__0qp1t_m._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__0qz-m.u._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__0qz-m.u._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__0r235yd._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__0r235yd._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__0rjkw2y._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__0rjkw2y._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__0uaqs.r._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__0uaqs.r._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__0vktxod._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__0vktxod._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__0vlh9um._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__0vlh9um._.js.map +1 -0
- package/.next/server/chunks/{[root-of-the-server]__c1b4b601._.js → [root-of-the-server]__0xb5i_t._.js} +21 -9
- package/.next/server/chunks/[root-of-the-server]__0xb5i_t._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__0xsal5d._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__0xsal5d._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__0yo.c6n._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__0yo.c6n._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__0yz0y4l._.js +13 -0
- package/.next/server/chunks/[root-of-the-server]__0yz0y4l._.js.map +1 -0
- package/.next/server/chunks/{[root-of-the-server]__e7623a6c._.js → [root-of-the-server]__11srlmi._.js} +2 -2
- package/.next/server/chunks/{[root-of-the-server]__e7623a6c._.js.map → [root-of-the-server]__11srlmi._.js.map} +1 -1
- package/.next/server/chunks/[root-of-the-server]__12d44rt._.js +3 -0
- package/.next/server/chunks/[root-of-the-server]__12d44rt._.js.map +1 -0
- package/.next/server/chunks/[turbopack]_runtime.js +168 -60
- package/.next/server/chunks/[turbopack]_runtime.js.map +6 -5
- package/.next/server/chunks/_0v0oe6c._.js +3 -0
- package/.next/server/chunks/{_b48847f5._.js.map → _0v0oe6c._.js.map} +1 -1
- package/.next/server/chunks/{_next-internal_server_app_api_config_route_actions_308a9f33.js → _next-internal_server_app_api_config_route_actions_08dm.dx.js} +1 -1
- package/.next/server/chunks/{_next-internal_server_app_api_gateway_[___path]_route_actions_835b2379.js → _next-internal_server_app_api_gateway_[___path]_route_actions_0mmqyo7.js} +1 -1
- package/.next/server/chunks/{_next-internal_server_app_api_gateway_models_route_actions_302c9983.js → _next-internal_server_app_api_gateway_models_route_actions_08b214z.js} +1 -1
- package/.next/server/chunks/{_next-internal_server_app_api_gateway_route_actions_e5e7405d.js → _next-internal_server_app_api_gateway_route_actions_0.jzdw1.js} +1 -1
- package/.next/server/chunks/{_next-internal_server_app_api_ide_claude_apply_route_actions_5056516c.js → _next-internal_server_app_api_ide_claude_apply_route_actions_0dw2_pf.js} +1 -1
- package/.next/server/chunks/{_next-internal_server_app_api_ide_claude_available-models_route_actions_94d710a0.js → _next-internal_server_app_api_ide_claude_available-models_route_actions_0pmwy75.js} +1 -1
- package/.next/server/chunks/{_next-internal_server_app_api_ide_claude_restore_route_actions_f37acc94.js → _next-internal_server_app_api_ide_claude_restore_route_actions_11x77hl.js} +1 -1
- package/.next/server/chunks/{_next-internal_server_app_api_ide_claude_save_route_actions_407c55f5.js → _next-internal_server_app_api_ide_claude_save_route_actions_0b35ro_.js} +1 -1
- package/.next/server/chunks/{_next-internal_server_app_api_ide_claude_status_route_actions_5ac73db8.js → _next-internal_server_app_api_ide_claude_status_route_actions_0fnw-w7.js} +1 -1
- package/.next/server/chunks/{_next-internal_server_app_api_ide_claude_test_route_actions_70587902.js → _next-internal_server_app_api_ide_claude_test_route_actions_0jc1czy.js} +1 -1
- package/.next/server/chunks/{_next-internal_server_app_api_ide_openclaw_apply_route_actions_2cb9e4b4.js → _next-internal_server_app_api_ide_openclaw_apply_route_actions_07re971.js} +1 -1
- package/.next/server/chunks/{_next-internal_server_app_api_ide_openclaw_preview_route_actions_9814a8e4.js → _next-internal_server_app_api_ide_openclaw_preview_route_actions_0q53p05.js} +1 -1
- package/.next/server/chunks/{_next-internal_server_app_api_ide_openclaw_restore_route_actions_10ad8f9d.js → _next-internal_server_app_api_ide_openclaw_restore_route_actions_02yog9-.js} +1 -1
- package/.next/server/chunks/{_next-internal_server_app_api_ide_openclaw_save_route_actions_044ad081.js → _next-internal_server_app_api_ide_openclaw_save_route_actions_00tjxsz.js} +1 -1
- package/.next/server/chunks/{_next-internal_server_app_api_ide_openclaw_status_route_actions_ed9786d2.js → _next-internal_server_app_api_ide_openclaw_status_route_actions_10wsun4.js} +1 -1
- package/.next/server/chunks/{_next-internal_server_app_api_ide_openclaw_test_route_actions_ce2cb808.js → _next-internal_server_app_api_ide_openclaw_test_route_actions_0zgwyon.js} +1 -1
- package/.next/server/chunks/{_next-internal_server_app_api_ide_opencode_apply_route_actions_6c422244.js → _next-internal_server_app_api_ide_opencode_apply_route_actions_0in-w.g.js} +1 -1
- package/.next/server/chunks/{_next-internal_server_app_api_ide_opencode_preview_route_actions_256c82e0.js → _next-internal_server_app_api_ide_opencode_preview_route_actions_06h6.w~.js} +1 -1
- package/.next/server/chunks/{_next-internal_server_app_api_ide_opencode_restore_route_actions_371993d3.js → _next-internal_server_app_api_ide_opencode_restore_route_actions_09ipt-l.js} +1 -1
- package/.next/server/chunks/{_next-internal_server_app_api_ide_opencode_save_route_actions_6e4c9c41.js → _next-internal_server_app_api_ide_opencode_save_route_actions_0i-~x79.js} +1 -1
- package/.next/server/chunks/{_next-internal_server_app_api_ide_opencode_status_route_actions_498ad77b.js → _next-internal_server_app_api_ide_opencode_status_route_actions_0cpf6rv.js} +1 -1
- package/.next/server/chunks/{_next-internal_server_app_api_ide_opencode_test_route_actions_c71be510.js → _next-internal_server_app_api_ide_opencode_test_route_actions_0y8aq8h.js} +1 -1
- package/.next/server/chunks/{_next-internal_server_app_api_logs_route_actions_30a87f47.js → _next-internal_server_app_api_logs_route_actions_08ef2j7.js} +1 -1
- package/.next/server/chunks/{_next-internal_server_app_api_models_route_actions_b6abdc83.js → _next-internal_server_app_api_models_route_actions_0vfccm4.js} +1 -1
- package/.next/server/chunks/{_next-internal_server_app_api_providers_route_actions_5388b373.js → _next-internal_server_app_api_providers_route_actions_0ee1p_m.js} +1 -1
- package/.next/server/chunks/{_next-internal_server_app_api_providers_test_route_actions_b97ab15a.js → _next-internal_server_app_api_providers_test_route_actions_0vyo652.js} +1 -1
- package/.next/server/chunks/{_next-internal_server_app_api_service_force-stop_route_actions_95eba80b.js → _next-internal_server_app_api_service_force-stop_route_actions_0pu9xrq.js} +1 -1
- package/.next/server/chunks/{_next-internal_server_app_api_service_start_route_actions_d50efb77.js → _next-internal_server_app_api_service_start_route_actions_0_o53a2.js} +1 -1
- package/.next/server/chunks/{_next-internal_server_app_api_service_status_route_actions_30149042.js → _next-internal_server_app_api_service_status_route_actions_08ag8v4.js} +1 -1
- package/.next/server/chunks/{_next-internal_server_app_api_service_stop_route_actions_19443941.js → _next-internal_server_app_api_service_stop_route_actions_04dp83p.js} +1 -1
- package/.next/server/chunks/_next-internal_server_app_api_tokenizer_history_route_actions_09~nqtd.js +3 -0
- package/.next/server/chunks/_next-internal_server_app_api_tokenizer_test_route_actions_0t2swp-.js +3 -0
- package/.next/server/chunks/{node_modules_next_dist_esm_build_templates_app-route_4be65264.js → node_modules_next_dist_esm_build_templates_app-route_0d1n5~u.js} +6 -6
- package/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_0d1n5~u.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__0.zquoa._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__0.zquoa._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__01dqyhh._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__01dqyhh._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__04qwc64._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__04qwc64._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__06r_ug4._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__06r_ug4._.js.map +1 -0
- package/.next/server/chunks/ssr/{[root-of-the-server]__f92001a5._.js → [root-of-the-server]__0814l01._.js} +2 -2
- package/.next/server/chunks/ssr/[root-of-the-server]__0814l01._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__0gb1hlj._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__0gb1hlj._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__0p8tmu2._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__0p8tmu2._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__0rf3.7n._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__0rf3.7n._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__0~6rwng._.js +33 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__0~6rwng._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__10xgshr._.js +33 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__10xgshr._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__11i~7lq._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__11i~7lq._.js.map +1 -0
- package/.next/server/chunks/ssr/[turbopack]_runtime.js +168 -60
- package/.next/server/chunks/ssr/[turbopack]_runtime.js.map +6 -5
- package/.next/server/chunks/ssr/_0k83omg._.js +6 -0
- package/.next/server/chunks/ssr/_0k83omg._.js.map +1 -0
- package/.next/server/chunks/ssr/_0yyi5po._.js +3 -0
- package/.next/server/chunks/ssr/_0yyi5po._.js.map +1 -0
- package/.next/server/chunks/ssr/{_next-internal_server_app__global-error_page_actions_75761787.js → _next-internal_server_app__global-error_page_actions_0k77kol.js} +1 -1
- package/.next/server/chunks/ssr/{_next-internal_server_app__not-found_page_actions_554ec2bf.js → _next-internal_server_app__not-found_page_actions_0eq97pa.js} +1 -1
- package/.next/server/chunks/ssr/{_next-internal_server_app_ide_page_actions_d521d6ae.js → _next-internal_server_app_ide_page_actions_0_opd4~.js} +1 -1
- package/.next/server/chunks/ssr/{_next-internal_server_app_logs_page_actions_a1c69041.js → _next-internal_server_app_logs_page_actions_0rvsl~d.js} +1 -1
- package/.next/server/chunks/ssr/{_next-internal_server_app_models_page_actions_543cf22f.js → _next-internal_server_app_models_page_actions_0eiz7f7.js} +1 -1
- package/.next/server/chunks/ssr/_next-internal_server_app_page_actions_09-gtaw.js +3 -0
- package/.next/server/chunks/ssr/_next-internal_server_app_page_actions_09-gtaw.js.map +1 -0
- package/.next/server/chunks/ssr/{_next-internal_server_app_providers_page_actions_c75f6cb3.js → _next-internal_server_app_providers_page_actions_0ya36nw.js} +1 -1
- package/.next/server/chunks/ssr/_next-internal_server_app_providers_page_actions_0ya36nw.js.map +1 -0
- package/.next/server/chunks/ssr/_next-internal_server_app_tokenizer_page_actions_0imc_ya.js +3 -0
- package/.next/server/chunks/ssr/_next-internal_server_app_tokenizer_page_actions_0imc_ya.js.map +1 -0
- package/.next/server/chunks/ssr/node_modules_09w7yel._.js +33 -0
- package/.next/server/chunks/ssr/node_modules_09w7yel._.js.map +1 -0
- package/.next/server/chunks/ssr/node_modules_next_dist_06hehg4._.js +19 -0
- package/.next/server/chunks/ssr/node_modules_next_dist_06hehg4._.js.map +1 -0
- package/.next/server/chunks/ssr/node_modules_next_dist_0e1izl_._.js +6 -0
- package/.next/server/chunks/ssr/node_modules_next_dist_0e1izl_._.js.map +1 -0
- package/.next/server/chunks/ssr/{node_modules_next_dist_client_components_9774470f._.js → node_modules_next_dist_client_components_0inhx6q._.js} +2 -2
- package/.next/server/chunks/ssr/{node_modules_next_dist_client_components_builtin_forbidden_45780354.js → node_modules_next_dist_client_components_builtin_forbidden_0ghu-f7.js} +2 -2
- package/.next/server/chunks/ssr/{node_modules_next_dist_client_components_builtin_global-error_ece394eb.js → node_modules_next_dist_client_components_builtin_global-error_0lgvd_..js} +2 -2
- package/.next/server/chunks/ssr/node_modules_next_dist_client_components_builtin_global-error_0lgvd_..js.map +1 -0
- package/.next/server/chunks/ssr/{node_modules_next_dist_client_components_builtin_unauthorized_15817684.js → node_modules_next_dist_client_components_builtin_unauthorized_0cjv-23.js} +2 -2
- package/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_05u.ff5.js +4 -0
- package/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_05u.ff5.js.map +1 -0
- package/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_06a5k-w.js +4 -0
- package/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_06a5k-w.js.map +1 -0
- package/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0_rrdx6.js +4 -0
- package/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0_rrdx6.js.map +1 -0
- package/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0a7b~p7.js +4 -0
- package/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0a7b~p7.js.map +1 -0
- package/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0bj8dkg.js +4 -0
- package/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0bj8dkg.js.map +1 -0
- package/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0cvrgh7.js +4 -0
- package/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0cvrgh7.js.map +1 -0
- package/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0nkcfme.js +4 -0
- package/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0nkcfme.js.map +1 -0
- package/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0rc3ul_.js +4 -0
- package/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0rc3ul_.js.map +1 -0
- package/.next/server/chunks/ssr/src_app_components_ConfirmDialog_tsx_0mm3plr._.js +3 -0
- package/.next/server/chunks/ssr/src_app_components_ConfirmDialog_tsx_0mm3plr._.js.map +1 -0
- package/.next/server/chunks/ssr/src_app_ide_page_tsx_0no40dj._.js +3 -0
- package/.next/server/chunks/ssr/{src_app_ide_page_tsx_8962793b._.js.map → src_app_ide_page_tsx_0no40dj._.js.map} +1 -1
- package/.next/server/chunks/ssr/src_app_logs_page_tsx_0l8mmxe._.js +3 -0
- package/.next/server/chunks/ssr/{src_app_logs_page_tsx_7b7b7b83._.js.map → src_app_logs_page_tsx_0l8mmxe._.js.map} +1 -1
- package/.next/server/chunks/ssr/src_app_models_page_tsx_10vsbc1._.js +3 -0
- package/.next/server/chunks/ssr/{src_app_models_page_tsx_ed71d32e._.js.map → src_app_models_page_tsx_10vsbc1._.js.map} +1 -1
- package/.next/server/chunks/ssr/src_app_page_tsx_0ss2.w7._.js +3 -0
- package/.next/server/chunks/ssr/src_app_page_tsx_0ss2.w7._.js.map +1 -0
- package/.next/server/chunks/ssr/src_app_providers_page_tsx_10ipz~8._.js +3 -0
- package/.next/server/chunks/ssr/{src_app_providers_page_tsx_eb8b5137._.js.map → src_app_providers_page_tsx_10ipz~8._.js.map} +1 -1
- package/.next/server/chunks/ssr/src_app_tokenizer_page_tsx_0eqhpbs._.js +3 -0
- package/.next/server/chunks/ssr/src_app_tokenizer_page_tsx_0eqhpbs._.js.map +1 -0
- package/.next/server/functions-config-manifest.json +3 -1
- package/.next/server/middleware-build-manifest.js +10 -10
- package/.next/server/pages/404.html +1 -1
- package/.next/server/pages/500.html +1 -2
- package/.next/server/prefetch-hints.json +1 -0
- package/.next/server/server-reference-manifest.js +1 -1
- package/.next/server/server-reference-manifest.json +1 -1
- package/.next/static/XHnu7Z1vWSrgmneps8rX4/_clientMiddlewareManifest.js +1 -0
- package/.next/static/chunks/01xlw8hd842-c.js +1 -0
- package/.next/static/chunks/0bzupvr5gt3k9.js +31 -0
- package/.next/static/chunks/0d3shmwh5_nmn.js +1 -0
- package/.next/static/chunks/0h7-_zr5_nt.5.js +1 -0
- package/.next/static/chunks/0mjx90nkvhsot.js +1 -0
- package/.next/static/chunks/0ntp1qkrtsgn0.js +1 -0
- package/.next/static/chunks/0tc5l6c1zalyc.css +1 -0
- package/.next/static/chunks/0v7.1nc4jyaet.js +1 -0
- package/.next/static/chunks/0vlwn301rv7dw.js +1 -0
- package/.next/static/chunks/0y3~cortx~or~.js +5 -0
- package/.next/static/chunks/0~c9fm3-3-f41.js +1 -0
- package/.next/static/chunks/11-7_fybhp2~y.js +1 -0
- package/.next/static/chunks/121-ofr4.6_5t.js +1 -0
- package/.next/static/chunks/16g.ca89g7fib.js +1 -0
- package/.next/static/chunks/turbopack-0griofc2i3wvs.js +1 -0
- package/.next/types/routes.d.ts +5 -2
- package/.next/types/validator.ts +27 -0
- package/CHANGELOG.md +15 -0
- package/README.md +6 -0
- package/dist/.next/dev/types/validator.js +12 -0
- package/dist/.next/types/validator.js +12 -0
- package/dist/package.json +3 -2
- package/dist/src/app/api/tokenizer/history/route.js +60 -0
- package/dist/src/app/api/tokenizer/test/route.js +97 -0
- package/dist/src/app/components/Nav.js +2 -1
- package/dist/src/app/tokenizer/page.js +318 -0
- package/dist/src/cli/index.js +3 -3
- package/dist/src/db/database.js +19 -21
- package/dist/src/db/queries.js +21 -0
- package/dist/src/server/tokenizer.js +215 -0
- package/package.json +3 -2
- package/src/app/api/tokenizer/history/route.ts +63 -0
- package/src/app/api/tokenizer/test/route.ts +151 -0
- package/src/app/components/Nav.tsx +2 -2
- package/src/app/tokenizer/page.tsx +813 -0
- package/src/cli/index.ts +4 -4
- package/src/db/database.ts +18 -25
- package/src/db/queries.ts +22 -0
- package/src/server/tokenizer.ts +285 -0
- package/.next/build/chunks/[root-of-the-server]__44695d76._.js.map +0 -11
- package/.next/build/chunks/[root-of-the-server]__6d51cb5d._.js.map +0 -8
- package/.next/server/chunks/[root-of-the-server]__001d5756._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__001d5756._.js.map +0 -1
- package/.next/server/chunks/[root-of-the-server]__05f8578b._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__05f8578b._.js.map +0 -1
- package/.next/server/chunks/[root-of-the-server]__1480f018._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__1480f018._.js.map +0 -1
- package/.next/server/chunks/[root-of-the-server]__1909f3aa._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__1909f3aa._.js.map +0 -1
- package/.next/server/chunks/[root-of-the-server]__1d4b7fc5._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__1d4b7fc5._.js.map +0 -1
- package/.next/server/chunks/[root-of-the-server]__33fec899._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__33fec899._.js.map +0 -1
- package/.next/server/chunks/[root-of-the-server]__372ef2bf._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__372ef2bf._.js.map +0 -1
- package/.next/server/chunks/[root-of-the-server]__3a204d25._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__3a204d25._.js.map +0 -1
- package/.next/server/chunks/[root-of-the-server]__3aaf963c._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__3aaf963c._.js.map +0 -1
- package/.next/server/chunks/[root-of-the-server]__43810962._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__43810962._.js.map +0 -1
- package/.next/server/chunks/[root-of-the-server]__4a8f9bc7._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__4a8f9bc7._.js.map +0 -1
- package/.next/server/chunks/[root-of-the-server]__55cd88b8._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__55cd88b8._.js.map +0 -1
- package/.next/server/chunks/[root-of-the-server]__59aacd30._.js +0 -21
- package/.next/server/chunks/[root-of-the-server]__59aacd30._.js.map +0 -1
- package/.next/server/chunks/[root-of-the-server]__5e8276bc._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__5e8276bc._.js.map +0 -1
- package/.next/server/chunks/[root-of-the-server]__64356cb2._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__64356cb2._.js.map +0 -1
- package/.next/server/chunks/[root-of-the-server]__6ce199d2._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__6ce199d2._.js.map +0 -1
- package/.next/server/chunks/[root-of-the-server]__760eaa16._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__760eaa16._.js.map +0 -1
- package/.next/server/chunks/[root-of-the-server]__772134c6._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__772134c6._.js.map +0 -1
- package/.next/server/chunks/[root-of-the-server]__7b77f523._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__7b77f523._.js.map +0 -1
- package/.next/server/chunks/[root-of-the-server]__7c298a19._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__7c298a19._.js.map +0 -1
- package/.next/server/chunks/[root-of-the-server]__85540228._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__85540228._.js.map +0 -1
- package/.next/server/chunks/[root-of-the-server]__94fe8d3c._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__94fe8d3c._.js.map +0 -1
- package/.next/server/chunks/[root-of-the-server]__97622908._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__97622908._.js.map +0 -1
- package/.next/server/chunks/[root-of-the-server]__a02e6618._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__a02e6618._.js.map +0 -1
- package/.next/server/chunks/[root-of-the-server]__a32a20a7._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__a32a20a7._.js.map +0 -1
- package/.next/server/chunks/[root-of-the-server]__a719d045._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__a719d045._.js.map +0 -1
- package/.next/server/chunks/[root-of-the-server]__af5b556a._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__af5b556a._.js.map +0 -1
- package/.next/server/chunks/[root-of-the-server]__c1b4b601._.js.map +0 -1
- package/.next/server/chunks/[root-of-the-server]__cafe113e._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__cafe113e._.js.map +0 -1
- package/.next/server/chunks/[root-of-the-server]__ccfc7f1d._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__ccfc7f1d._.js.map +0 -1
- package/.next/server/chunks/[root-of-the-server]__dc8b0bed._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__dc8b0bed._.js.map +0 -1
- package/.next/server/chunks/[root-of-the-server]__f0461b8d._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__f0461b8d._.js.map +0 -1
- package/.next/server/chunks/[root-of-the-server]__f8949f88._.js +0 -3
- package/.next/server/chunks/[root-of-the-server]__f8949f88._.js.map +0 -1
- package/.next/server/chunks/_b48847f5._.js +0 -3
- package/.next/server/chunks/ce889_server_app_api_ide_openclaw_available-models_route_actions_e568e70b.js +0 -3
- package/.next/server/chunks/ce889_server_app_api_ide_opencode_available-models_route_actions_95230db3.js +0 -3
- package/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_4be65264.js.map +0 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__083d944d._.js +0 -3
- package/.next/server/chunks/ssr/[root-of-the-server]__083d944d._.js.map +0 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__15600e29._.js +0 -3
- package/.next/server/chunks/ssr/[root-of-the-server]__15600e29._.js.map +0 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__1836f866._.js +0 -3
- package/.next/server/chunks/ssr/[root-of-the-server]__1836f866._.js.map +0 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__256a03fe._.js +0 -3
- package/.next/server/chunks/ssr/[root-of-the-server]__256a03fe._.js.map +0 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__31fde618._.js +0 -3
- package/.next/server/chunks/ssr/[root-of-the-server]__31fde618._.js.map +0 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__523c120c._.js +0 -3
- package/.next/server/chunks/ssr/[root-of-the-server]__523c120c._.js.map +0 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__70a81394._.js +0 -3
- package/.next/server/chunks/ssr/[root-of-the-server]__70a81394._.js.map +0 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__81937253._.js +0 -3
- package/.next/server/chunks/ssr/[root-of-the-server]__81937253._.js.map +0 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__976ad963._.js +0 -3
- package/.next/server/chunks/ssr/[root-of-the-server]__976ad963._.js.map +0 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__af2ad6aa._.js +0 -3
- package/.next/server/chunks/ssr/[root-of-the-server]__af2ad6aa._.js.map +0 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__b9356576._.js +0 -4
- package/.next/server/chunks/ssr/[root-of-the-server]__b9356576._.js.map +0 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__ccb6a4da._.js +0 -3
- package/.next/server/chunks/ssr/[root-of-the-server]__ccb6a4da._.js.map +0 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__cfa2d991._.js +0 -3
- package/.next/server/chunks/ssr/[root-of-the-server]__cfa2d991._.js.map +0 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__f437da88._.js +0 -3
- package/.next/server/chunks/ssr/[root-of-the-server]__f437da88._.js.map +0 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__f92001a5._.js.map +0 -1
- package/.next/server/chunks/ssr/_06262cbd._.js +0 -4
- package/.next/server/chunks/ssr/_06262cbd._.js.map +0 -1
- package/.next/server/chunks/ssr/_0cd72da5._.js +0 -4
- package/.next/server/chunks/ssr/_0cd72da5._.js.map +0 -1
- package/.next/server/chunks/ssr/_4828a6d2._.js +0 -4
- package/.next/server/chunks/ssr/_4828a6d2._.js.map +0 -1
- package/.next/server/chunks/ssr/_69468f4c._.js +0 -3
- package/.next/server/chunks/ssr/_69468f4c._.js.map +0 -1
- package/.next/server/chunks/ssr/_93850476._.js +0 -6
- package/.next/server/chunks/ssr/_93850476._.js.map +0 -1
- package/.next/server/chunks/ssr/_c1309523._.js +0 -4
- package/.next/server/chunks/ssr/_c1309523._.js.map +0 -1
- package/.next/server/chunks/ssr/_f7d273e3._.js +0 -4
- package/.next/server/chunks/ssr/_f7d273e3._.js.map +0 -1
- package/.next/server/chunks/ssr/_next-internal_server_app_page_actions_39d4fc33.js +0 -3
- package/.next/server/chunks/ssr/node_modules_next_dist_08570d7f._.js +0 -4
- package/.next/server/chunks/ssr/node_modules_next_dist_08570d7f._.js.map +0 -1
- package/.next/server/chunks/ssr/node_modules_next_dist_174ae28d._.js +0 -10
- package/.next/server/chunks/ssr/node_modules_next_dist_174ae28d._.js.map +0 -1
- package/.next/server/chunks/ssr/node_modules_next_dist_27457240._.js +0 -6
- package/.next/server/chunks/ssr/node_modules_next_dist_27457240._.js.map +0 -1
- package/.next/server/chunks/ssr/node_modules_next_dist_4b63a0e1._.js +0 -3
- package/.next/server/chunks/ssr/node_modules_next_dist_4b63a0e1._.js.map +0 -1
- package/.next/server/chunks/ssr/node_modules_next_dist_client_components_builtin_global-error_ece394eb.js.map +0 -1
- package/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_65a7265e.js +0 -4
- package/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_65a7265e.js.map +0 -1
- package/.next/server/chunks/ssr/node_modules_next_dist_f9713a08._.js +0 -3
- package/.next/server/chunks/ssr/node_modules_next_dist_f9713a08._.js.map +0 -1
- package/.next/server/chunks/ssr/src_app_ide_page_tsx_8962793b._.js +0 -3
- package/.next/server/chunks/ssr/src_app_logs_page_tsx_7b7b7b83._.js +0 -3
- package/.next/server/chunks/ssr/src_app_models_page_tsx_ed71d32e._.js +0 -3
- package/.next/server/chunks/ssr/src_app_providers_page_tsx_eb8b5137._.js +0 -3
- package/.next/static/cf2SWIkI5HVbnDjLExI42/_clientMiddlewareManifest.json +0 -1
- package/.next/static/chunks/5663c8696095f277.js +0 -1
- package/.next/static/chunks/64f547b3bcd3aef4.js +0 -1
- package/.next/static/chunks/6992685fe009e8fd.css +0 -1
- package/.next/static/chunks/6e0dee5b6681763c.js +0 -1
- package/.next/static/chunks/6f7efe5271343778.js +0 -1
- package/.next/static/chunks/75f76753fd97c8fd.js +0 -1
- package/.next/static/chunks/7c8b7cbb3339f139.js +0 -1
- package/.next/static/chunks/8ccc14e022ff6de3.js +0 -1
- package/.next/static/chunks/8cf1e5f00ebaea52.js +0 -1
- package/.next/static/chunks/a6dad97d9634a72d.js.map +0 -1
- package/.next/static/chunks/a7f539bf6487f4ff.js +0 -5
- package/.next/static/chunks/a89fdf03c5b0dfbd.js +0 -1
- package/.next/static/chunks/d2be314c3ece3fbe.js +0 -1
- package/.next/static/chunks/f2f58a7e93290fbb.js +0 -1
- package/.next/static/chunks/ff1a16fafef87110.js +0 -1
- package/.next/static/chunks/turbopack-fdb839c72e10c2ea.js +0 -4
- /package/.next/build/chunks/{[turbopack-node]_transforms_postcss_ts_df7a5b11._.js.map → [turbopack-node]_transforms_postcss_ts_0nnejqq._.js.map} +0 -0
- /package/.next/server/chunks/{_next-internal_server_app_api_config_route_actions_308a9f33.js.map → 0zjb_server_app_api_ide_openclaw_available-models_route_actions_0.gjr6a.js.map} +0 -0
- /package/.next/server/chunks/{_next-internal_server_app_api_gateway_[___path]_route_actions_835b2379.js.map → 0zjb_server_app_api_ide_opencode_available-models_route_actions_0poyhyk.js.map} +0 -0
- /package/.next/server/chunks/{_next-internal_server_app_api_gateway_models_route_actions_302c9983.js.map → _next-internal_server_app_api_config_route_actions_08dm.dx.js.map} +0 -0
- /package/.next/server/chunks/{_next-internal_server_app_api_gateway_route_actions_e5e7405d.js.map → _next-internal_server_app_api_gateway_[___path]_route_actions_0mmqyo7.js.map} +0 -0
- /package/.next/server/chunks/{_next-internal_server_app_api_ide_claude_apply_route_actions_5056516c.js.map → _next-internal_server_app_api_gateway_models_route_actions_08b214z.js.map} +0 -0
- /package/.next/server/chunks/{_next-internal_server_app_api_ide_claude_available-models_route_actions_94d710a0.js.map → _next-internal_server_app_api_gateway_route_actions_0.jzdw1.js.map} +0 -0
- /package/.next/server/chunks/{_next-internal_server_app_api_ide_claude_restore_route_actions_f37acc94.js.map → _next-internal_server_app_api_ide_claude_apply_route_actions_0dw2_pf.js.map} +0 -0
- /package/.next/server/chunks/{_next-internal_server_app_api_ide_claude_save_route_actions_407c55f5.js.map → _next-internal_server_app_api_ide_claude_available-models_route_actions_0pmwy75.js.map} +0 -0
- /package/.next/server/chunks/{_next-internal_server_app_api_ide_claude_status_route_actions_5ac73db8.js.map → _next-internal_server_app_api_ide_claude_restore_route_actions_11x77hl.js.map} +0 -0
- /package/.next/server/chunks/{_next-internal_server_app_api_ide_claude_test_route_actions_70587902.js.map → _next-internal_server_app_api_ide_claude_save_route_actions_0b35ro_.js.map} +0 -0
- /package/.next/server/chunks/{_next-internal_server_app_api_ide_openclaw_apply_route_actions_2cb9e4b4.js.map → _next-internal_server_app_api_ide_claude_status_route_actions_0fnw-w7.js.map} +0 -0
- /package/.next/server/chunks/{_next-internal_server_app_api_ide_openclaw_preview_route_actions_9814a8e4.js.map → _next-internal_server_app_api_ide_claude_test_route_actions_0jc1czy.js.map} +0 -0
- /package/.next/server/chunks/{_next-internal_server_app_api_ide_openclaw_restore_route_actions_10ad8f9d.js.map → _next-internal_server_app_api_ide_openclaw_apply_route_actions_07re971.js.map} +0 -0
- /package/.next/server/chunks/{_next-internal_server_app_api_ide_openclaw_save_route_actions_044ad081.js.map → _next-internal_server_app_api_ide_openclaw_preview_route_actions_0q53p05.js.map} +0 -0
- /package/.next/server/chunks/{_next-internal_server_app_api_ide_openclaw_status_route_actions_ed9786d2.js.map → _next-internal_server_app_api_ide_openclaw_restore_route_actions_02yog9-.js.map} +0 -0
- /package/.next/server/chunks/{_next-internal_server_app_api_ide_openclaw_test_route_actions_ce2cb808.js.map → _next-internal_server_app_api_ide_openclaw_save_route_actions_00tjxsz.js.map} +0 -0
- /package/.next/server/chunks/{_next-internal_server_app_api_ide_opencode_apply_route_actions_6c422244.js.map → _next-internal_server_app_api_ide_openclaw_status_route_actions_10wsun4.js.map} +0 -0
- /package/.next/server/chunks/{_next-internal_server_app_api_ide_opencode_preview_route_actions_256c82e0.js.map → _next-internal_server_app_api_ide_openclaw_test_route_actions_0zgwyon.js.map} +0 -0
- /package/.next/server/chunks/{_next-internal_server_app_api_ide_opencode_restore_route_actions_371993d3.js.map → _next-internal_server_app_api_ide_opencode_apply_route_actions_0in-w.g.js.map} +0 -0
- /package/.next/server/chunks/{_next-internal_server_app_api_ide_opencode_save_route_actions_6e4c9c41.js.map → _next-internal_server_app_api_ide_opencode_preview_route_actions_06h6.w~.js.map} +0 -0
- /package/.next/server/chunks/{_next-internal_server_app_api_ide_opencode_status_route_actions_498ad77b.js.map → _next-internal_server_app_api_ide_opencode_restore_route_actions_09ipt-l.js.map} +0 -0
- /package/.next/server/chunks/{_next-internal_server_app_api_ide_opencode_test_route_actions_c71be510.js.map → _next-internal_server_app_api_ide_opencode_save_route_actions_0i-~x79.js.map} +0 -0
- /package/.next/server/chunks/{_next-internal_server_app_api_logs_route_actions_30a87f47.js.map → _next-internal_server_app_api_ide_opencode_status_route_actions_0cpf6rv.js.map} +0 -0
- /package/.next/server/chunks/{_next-internal_server_app_api_models_route_actions_b6abdc83.js.map → _next-internal_server_app_api_ide_opencode_test_route_actions_0y8aq8h.js.map} +0 -0
- /package/.next/server/chunks/{_next-internal_server_app_api_providers_route_actions_5388b373.js.map → _next-internal_server_app_api_logs_route_actions_08ef2j7.js.map} +0 -0
- /package/.next/server/chunks/{_next-internal_server_app_api_providers_test_route_actions_b97ab15a.js.map → _next-internal_server_app_api_models_route_actions_0vfccm4.js.map} +0 -0
- /package/.next/server/chunks/{_next-internal_server_app_api_service_force-stop_route_actions_95eba80b.js.map → _next-internal_server_app_api_providers_route_actions_0ee1p_m.js.map} +0 -0
- /package/.next/server/chunks/{_next-internal_server_app_api_service_start_route_actions_d50efb77.js.map → _next-internal_server_app_api_providers_test_route_actions_0vyo652.js.map} +0 -0
- /package/.next/server/chunks/{_next-internal_server_app_api_service_status_route_actions_30149042.js.map → _next-internal_server_app_api_service_force-stop_route_actions_0pu9xrq.js.map} +0 -0
- /package/.next/server/chunks/{_next-internal_server_app_api_service_stop_route_actions_19443941.js.map → _next-internal_server_app_api_service_start_route_actions_0_o53a2.js.map} +0 -0
- /package/.next/server/chunks/{ce889_server_app_api_ide_openclaw_available-models_route_actions_e568e70b.js.map → _next-internal_server_app_api_service_status_route_actions_08ag8v4.js.map} +0 -0
- /package/.next/server/chunks/{ce889_server_app_api_ide_opencode_available-models_route_actions_95230db3.js.map → _next-internal_server_app_api_service_stop_route_actions_04dp83p.js.map} +0 -0
- /package/.next/server/chunks/{ssr/_next-internal_server_app__global-error_page_actions_75761787.js.map → _next-internal_server_app_api_tokenizer_history_route_actions_09~nqtd.js.map} +0 -0
- /package/.next/server/chunks/{ssr/_next-internal_server_app__not-found_page_actions_554ec2bf.js.map → _next-internal_server_app_api_tokenizer_test_route_actions_0t2swp-.js.map} +0 -0
- /package/.next/server/chunks/ssr/{_next-internal_server_app_ide_page_actions_d521d6ae.js.map → _next-internal_server_app__global-error_page_actions_0k77kol.js.map} +0 -0
- /package/.next/server/chunks/ssr/{_next-internal_server_app_logs_page_actions_a1c69041.js.map → _next-internal_server_app__not-found_page_actions_0eq97pa.js.map} +0 -0
- /package/.next/server/chunks/ssr/{_next-internal_server_app_models_page_actions_543cf22f.js.map → _next-internal_server_app_ide_page_actions_0_opd4~.js.map} +0 -0
- /package/.next/server/chunks/ssr/{_next-internal_server_app_page_actions_39d4fc33.js.map → _next-internal_server_app_logs_page_actions_0rvsl~d.js.map} +0 -0
- /package/.next/server/chunks/ssr/{_next-internal_server_app_providers_page_actions_c75f6cb3.js.map → _next-internal_server_app_models_page_actions_0eiz7f7.js.map} +0 -0
- /package/.next/server/chunks/ssr/{node_modules_next_dist_client_components_9774470f._.js.map → node_modules_next_dist_client_components_0inhx6q._.js.map} +0 -0
- /package/.next/server/chunks/ssr/{node_modules_next_dist_client_components_builtin_forbidden_45780354.js.map → node_modules_next_dist_client_components_builtin_forbidden_0ghu-f7.js.map} +0 -0
- /package/.next/server/chunks/ssr/{node_modules_next_dist_client_components_builtin_unauthorized_15817684.js.map → node_modules_next_dist_client_components_builtin_unauthorized_0cjv-23.js.map} +0 -0
- /package/.next/static/{cf2SWIkI5HVbnDjLExI42 → XHnu7Z1vWSrgmneps8rX4}/_buildManifest.js +0 -0
- /package/.next/static/{cf2SWIkI5HVbnDjLExI42 → XHnu7Z1vWSrgmneps8rX4}/_ssgManifest.js +0 -0
- /package/.next/static/chunks/{a6dad97d9634a72d.js → 03~yq9q893hmn.js} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/app/page.tsx"],"sourcesContent":["'use client';\n\nimport { useState, useEffect, useCallback } from 'react';\nimport Nav from './components/Nav';\nimport { useToast } from './components/ToastProvider';\n\ninterface Config {\n port?: string;\n api_key?: string;\n}\n\ninterface ServiceStatus {\n status: 'running' | 'stopped';\n port?: number;\n pid?: number | null;\n started_at?: string | null;\n error?: string;\n}\n\nexport default function Home() {\n const [config, setConfig] = useState<Config>({});\n const [loading, setLoading] = useState(true);\n const [saving, setSaving] = useState(false);\n const [serviceStatus, setServiceStatus] = useState<ServiceStatus>({ status: 'stopped' });\n const [starting, setStarting] = useState(false);\n const [stopping, setStopping] = useState(false);\n const [showApiKey, setShowApiKey] = useState(false);\n const { showToast } = useToast();\n\n const loadConfig = useCallback(async () => {\n try {\n const res = await fetch('/api/config');\n const data = await res.json();\n setConfig({\n port: data.port || '1357',\n api_key: data.api_key || '',\n });\n } catch (error) {\n console.error('Failed to load config:', error);\n } finally {\n setLoading(false);\n }\n }, []);\n\n const loadServiceStatus = useCallback(async () => {\n try {\n const res = await fetch('/api/service/status');\n const data = await res.json();\n setServiceStatus(data);\n } catch (error) {\n console.error('Failed to load service status:', error);\n }\n }, []);\n\n useEffect(() => {\n loadConfig();\n loadServiceStatus();\n\n // Poll service status every 2 seconds\n const interval = setInterval(loadServiceStatus, 2000);\n\n return () => clearInterval(interval);\n }, [loadConfig, loadServiceStatus]);\n\n const handleStart = async () => {\n if (starting || serviceStatus.status === 'running') return;\n\n setStarting(true);\n try {\n // Use default port if not configured\n const port = config.port ? parseInt(config.port, 10) : 1357;\n\n const res = await fetch('/api/service/start', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ port }),\n });\n const data = await res.json();\n\n if (data.error) {\n showToast(`启动失败: ${data.error}`, 'error');\n } else {\n showToast('服务已启动', 'success');\n setServiceStatus(data);\n }\n } catch (error: any) {\n console.error('Failed to start service:', error);\n showToast('启动失败', 'error');\n } finally {\n setStarting(false);\n // Reload status after a short delay\n setTimeout(loadServiceStatus, 500);\n }\n };\n\n const handleStop = async () => {\n if (stopping || serviceStatus.status === 'stopped') return;\n \n setStopping(true);\n try {\n const res = await fetch('/api/service/stop', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n });\n const data = await res.json();\n \n if (data.error) {\n showToast(`停止失败: ${data.error}`, 'error');\n } else {\n showToast('服务已停止', 'success');\n setServiceStatus(data);\n }\n } catch (error: any) {\n console.error('Failed to stop service:', error);\n showToast('停止失败', 'error');\n } finally {\n setStopping(false);\n // Reload status after a short delay\n setTimeout(loadServiceStatus, 500);\n }\n };\n\n const saveConfig = async () => {\n setSaving(true);\n try {\n // 保存端口配置\n const portRes = await fetch('/api/config', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n key: 'port',\n value: config.port,\n }),\n });\n if (!portRes.ok) {\n const errorData = await portRes.json();\n throw new Error(errorData.error || '保存端口配置失败');\n }\n\n // 保存 API Key 配置\n if (config.api_key) {\n const apiKeyRes = await fetch('/api/config', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n key: 'api_key',\n value: config.api_key,\n }),\n });\n if (!apiKeyRes.ok) {\n const errorData = await apiKeyRes.json();\n throw new Error(errorData.error || '保存 API Key 配置失败');\n }\n }\n\n showToast('配置已保存', 'success');\n } catch (error: any) {\n console.error('Failed to save config:', error);\n showToast(error.message || '保存失败', 'error');\n } finally {\n setSaving(false);\n }\n };\n\n if (loading) {\n return (\n <div className=\"min-h-screen flex items-center justify-center\">\n <div className=\"text-lg\">加载中...</div>\n </div>\n );\n }\n\n return (\n <div className=\"min-h-screen bg-gradient-to-br from-emerald-50/30 via-white to-slate-50/50\">\n <Nav />\n\n <main className=\"max-w-3xl mx-auto py-6 sm:px-6 lg:px-8\">\n <div className=\"px-4 py-4 sm:px-0\">\n <div className=\"bg-white/70 backdrop-blur-sm shadow-md rounded-2xl border border-emerald-100/50\">\n <div className=\"px-6 py-5 sm:p-6\">\n <div className=\"mb-5\">\n <h2 className=\"text-lg font-bold text-slate-800 mb-1\">网关配置</h2>\n <p className=\"text-xs text-slate-500\">配置 API 网关的运行参数</p>\n </div>\n \n <div className=\"space-y-3.5\">\n <div>\n <label className=\"block text-xs font-semibold text-slate-700 mb-1.5\">\n 端口\n </label>\n <input\n type=\"number\"\n value={config.port}\n onChange={(e) => setConfig({ ...config, port: e.target.value })}\n autoComplete=\"off\"\n className=\"block w-full rounded-lg border border-slate-200 bg-white/80 px-3 py-2 text-xs shadow-sm transition-all duration-300 focus:border-emerald-400 focus:ring-2 focus:ring-emerald-400/20 focus:ring-offset-1\"\n placeholder=\"1357\"\n />\n <p className=\"mt-1 text-xs text-slate-400\">\n 提示:API 网关默认端口为 1357\n </p>\n </div>\n\n <div>\n <label className=\"block text-xs font-semibold text-slate-700 mb-1.5\">\n API Key (可选)\n </label>\n <div className=\"relative\">\n <input\n type={showApiKey ? 'text' : 'password'}\n value={config.api_key}\n onChange={(e) => setConfig({ ...config, api_key: e.target.value })}\n autoComplete=\"new-password\"\n className=\"block w-full rounded-lg border border-slate-200 bg-white/80 px-3 py-2 pr-9 text-xs shadow-sm transition-all duration-300 focus:border-emerald-400 focus:ring-2 focus:ring-emerald-400/20 focus:ring-offset-1\"\n placeholder=\"留空则不验证\"\n />\n <button\n type=\"button\"\n onClick={() => setShowApiKey(!showApiKey)}\n className=\"absolute right-2 top-1/2 -translate-y-1/2 p-1 text-slate-400 hover:text-slate-600 transition-colors\"\n tabIndex={-1}\n >\n {showApiKey ? (\n <svg className=\"w-4 h-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M13.875 18.825A10.05 10.05 0 0112 19c-4.478 0-8.268-2.943-9.543-7a9.97 9.97 0 011.563-3.029m5.858.908a3 3 0 114.243 4.243M9.878 9.878l4.242 4.242M9.88 9.88l-3.29-3.29m7.532 7.532l3.29 3.29M3 3l3.59 3.59m0 0A9.953 9.953 0 0112 5c4.478 0 8.268 2.943 9.543 7a10.025 10.025 0 01-4.132 5.411m0 0L21 21\" />\n </svg>\n ) : (\n <svg className=\"w-4 h-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M15 12a3 3 0 11-6 0 3 3 0 016 0z\" />\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z\" />\n </svg>\n )}\n </button>\n </div>\n </div>\n\n <div className=\"flex items-center justify-between pt-3\">\n <div>\n <span className=\"text-xs text-slate-500\">状态: </span>\n <span className={`text-xs font-medium ${serviceStatus.status === 'running' ? 'text-emerald-600' : 'text-slate-500'}`}>\n {serviceStatus.status === 'running' ? '运行中' : '已停止'}\n </span>\n {serviceStatus.status === 'running' && serviceStatus.port && (\n <span className=\"text-xs text-slate-400 ml-2\">(端口: {serviceStatus.port})</span>\n )}\n </div>\n <div className=\"flex space-x-2\">\n <button\n onClick={saveConfig}\n disabled={saving || serviceStatus.status === 'running'}\n className=\"inline-flex items-center px-3.5 py-1.5 border border-transparent text-xs font-semibold rounded-lg shadow-sm text-white bg-emerald-600 hover:bg-emerald-700 focus:outline-none focus:ring-2 focus:ring-offset-1 focus:ring-emerald-500/50 disabled:opacity-50 disabled:cursor-not-allowed transition-all duration-300\"\n >\n {saving ? (\n <>\n <svg className=\"animate-spin -ml-1 mr-1.5 h-3 w-3 text-white\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\">\n <circle className=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" strokeWidth=\"4\"></circle>\n <path className=\"opacity-75\" fill=\"currentColor\" d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"></path>\n </svg>\n 保存中\n </>\n ) : (\n '保存配置'\n )}\n </button>\n <button\n onClick={serviceStatus.status === 'running' ? handleStop : handleStart}\n disabled={starting || stopping}\n className={`inline-flex items-center px-3.5 py-1.5 border border-transparent text-xs font-semibold rounded-lg shadow-sm text-white focus:outline-none focus:ring-2 focus:ring-offset-1 transition-all duration-300 disabled:opacity-50 disabled:cursor-not-allowed ${\n serviceStatus.status === 'running'\n ? 'bg-rose-500 hover:bg-rose-600 focus:ring-rose-500/50'\n : 'bg-emerald-600 hover:bg-emerald-700 focus:ring-emerald-500/50'\n }`}\n >\n {starting ? (\n <>\n <svg className=\"animate-spin -ml-1 mr-1.5 h-3 w-3 text-white\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\">\n <circle className=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" strokeWidth=\"4\"></circle>\n <path className=\"opacity-75\" fill=\"currentColor\" d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"></path>\n </svg>\n 启动中\n </>\n ) : stopping ? (\n <>\n <svg className=\"animate-spin -ml-1 mr-1.5 h-3 w-3 text-white\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\">\n <circle className=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" strokeWidth=\"4\"></circle>\n <path className=\"opacity-75\" fill=\"currentColor\" d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"></path>\n </svg>\n 停止中\n </>\n ) : serviceStatus.status === 'running' ? (\n <>\n <svg className=\"w-3 h-3 mr-1.5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M21 12a9 9 0 11-18 0 9 9 0 0118 0z\" />\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M9 10a1 1 0 011-1h4a1 1 0 011 1v4a1 1 0 01-1 1h-4a1 1 0 01-1-1v-4z\" />\n </svg>\n 停止\n </>\n ) : (\n <>\n <svg className=\"w-3 h-3 mr-1.5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M14.752 11.168l-3.197-2.132A1 1 0 0010 9.87v4.263a1 1 0 001.555.832l3.197-2.132a1 1 0 000-1.664z\" />\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M21 12a9 9 0 11-18 0 9 9 0 0118 0z\" />\n </svg>\n 启动\n </>\n )}\n </button>\n </div>\n </div>\n </div>\n </div>\n </div>\n\n </div>\n </main>\n </div>\n );\n}\n"],"names":["Home","config","setConfig","loading","setLoading","saving","setSaving","serviceStatus","setServiceStatus","status","starting","setStarting","stopping","setStopping","showApiKey","setShowApiKey","showToast","loadConfig","res","fetch","data","json","port","api_key","error","console","loadServiceStatus","interval","setInterval","clearInterval","handleStart","parseInt","method","headers","body","JSON","stringify","setTimeout","handleStop","saveConfig","portRes","key","value","ok","errorData","Error","apiKeyRes","message","className","type","onChange","e","target","autoComplete","placeholder","onClick","tabIndex","fill","stroke","viewBox","strokeLinecap","strokeLinejoin","strokeWidth","d","disabled","xmlns","cx","cy","r"],"mappings":"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"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
module.exports=[40835,a=>{"use strict";var b=a.i(87924),c=a.i(72131),d=a.i(81844),e=a.i(21215),f=a.i(71862);a.s(["default",0,function(){let[a,g]=(0,c.useState)([]),[h,i]=(0,c.useState)([]),[j,k]=(0,c.useState)(!0),[l,m]=(0,c.useState)(!1),[n,o]=(0,c.useState)(null),[p,q]=(0,c.useState)(!1),[r,s]=(0,c.useState)(null),[t,u]=(0,c.useState)(null),[v,w]=(0,c.useState)(""),[x,y]=(0,c.useState)(!1),[z,A]=(0,c.useState)(""),[B,C]=(0,c.useState)({name:"",protocol:"openai",base_url:"",api_key:""}),[D,E]=(0,c.useState)(!1),{showToast:F}=(0,e.useToast)();(0,c.useEffect)(()=>{G(),H()},[]);let G=async()=>{try{let a=await fetch("/api/providers"),b=await a.json();g(b)}catch(a){console.error("Failed to load providers:",a)}finally{k(!1)}},H=async()=>{try{let a=await fetch("/api/models"),b=await a.json();i(b)}catch(a){console.error("Failed to load models:",a)}},I=async a=>{try{let b=await fetch(`/api/providers?id=${a}&includeKey=true`);if(!b.ok)throw Error("Failed to load provider");return await b.json()}catch(a){throw console.error("Failed to load provider for edit:",a),a}},J=async a=>{a.preventDefault();try{let a;if(n){let b={id:n.id,name:B.name,protocol:B.protocol,base_url:B.base_url};B.api_key&&""!==B.api_key.trim()&&(b.api_key=B.api_key.trim()),a=await fetch("/api/providers",{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify(b)})}else{if(!B.api_key||""===B.api_key.trim())return void F("API Key 不能为空","error");a=await fetch("/api/providers",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({...B,api_key:B.api_key.trim()})})}if(!a.ok){let b=(await a.json().catch(()=>({}))).error||"保存失败";F(b,"error");return}m(!1),o(null),C({name:"",protocol:"openai",base_url:"",api_key:""}),E(!1),G(),F("供应商保存成功","success")}catch(a){console.error("Failed to save provider:",a),F("保存失败: "+(a.message||"未知错误"),"error")}},K=async a=>{try{let b=await I(a.id);o(a),C({name:b.name,protocol:b.protocol,base_url:b.base_url,api_key:b.api_key||""}),E(!1),m(!0)}catch(a){console.error("Failed to load provider for edit:",a),F("加载供应商信息失败","error")}},L=async()=>{if(r)try{await fetch(`/api/providers?id=${r}`,{method:"DELETE"}),G(),F("供应商已删除","success")}catch(a){console.error("Failed to delete provider:",a),F("删除失败","error")}q(!1),s(null)},M=async()=>{if(!t||!v)return void F("请选择要测试的模型","error");y(!0);try{let a=await fetch("/api/providers/test",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({provider_id:t,model_id:parseInt(v)})}),b=await a.json();b.success?F(b.message||"连接成功,模型可用","success"):F(b.error||"连接失败","error")}catch(a){console.error("Failed to test connection:",a),F("测试连接失败: "+(a.message||"未知错误"),"error")}finally{y(!1),w("")}},N=()=>{u(null),w(""),A("")},O=a=>{let b=h.filter(b=>b.provider_id===a&&b.enabled);if(!z.trim())return b;let c=z.toLowerCase().trim();return b.filter(a=>a.name.toLowerCase().includes(c)||a.model_id.toLowerCase().includes(c))};return j?(0,b.jsxs)(b.Fragment,{children:[(0,b.jsx)(d.default,{}),(0,b.jsx)("div",{className:"min-h-screen flex items-center justify-center",children:(0,b.jsx)("div",{className:"text-lg",children:"加载中..."})})]}):(0,b.jsxs)(b.Fragment,{children:[(0,b.jsx)(d.default,{}),(0,b.jsx)("main",{className:"max-w-6xl mx-auto py-6 sm:px-6 lg:px-8",children:(0,b.jsxs)("div",{className:"px-4 py-4 sm:px-0",children:[(0,b.jsxs)("div",{className:"flex justify-between items-center mb-5",children:[(0,b.jsxs)("div",{children:[(0,b.jsx)("h1",{className:"text-lg font-bold text-slate-800",children:"供应商管理"}),(0,b.jsx)("p",{className:"text-xs text-slate-500 mt-1",children:"管理 AI 模型供应商配置"})]}),(0,b.jsxs)("button",{onClick:()=>{o(null),C({name:"",protocol:"openai",base_url:"",api_key:""}),E(!1),m(!0)},className:"inline-flex items-center px-3.5 py-1.5 border border-transparent text-xs font-semibold rounded-lg shadow-sm text-white bg-emerald-600 hover:bg-emerald-700 focus:outline-none focus:ring-2 focus:ring-offset-1 focus:ring-emerald-500/50 transition-all duration-300",children:[(0,b.jsx)("svg",{className:"w-3.5 h-3.5 mr-1.5",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:(0,b.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M12 4v16m8-8H4"})}),"添加供应商"]})]}),(0,b.jsx)("div",{className:"bg-white/70 backdrop-blur-sm shadow-md rounded-2xl border border-emerald-100/50 overflow-hidden",children:(0,b.jsxs)("table",{className:"min-w-full divide-y divide-slate-100",children:[(0,b.jsx)("thead",{className:"bg-emerald-50/30",children:(0,b.jsxs)("tr",{children:[(0,b.jsx)("th",{className:"px-4 py-2.5 text-left text-xs font-semibold text-slate-600 uppercase tracking-wider",children:"名称"}),(0,b.jsx)("th",{className:"px-6 py-4 text-left text-xs font-semibold text-slate-600 uppercase tracking-wider",children:"协议"}),(0,b.jsx)("th",{className:"px-6 py-4 text-left text-xs font-semibold text-slate-600 uppercase tracking-wider",children:"Base URL"}),(0,b.jsx)("th",{className:"px-6 py-3.5 text-right text-xs font-semibold text-gray-700 uppercase tracking-wider",children:"操作"})]})}),(0,b.jsx)("tbody",{className:"bg-white divide-y divide-slate-100",children:0===a.length?(0,b.jsx)("tr",{children:(0,b.jsx)("td",{colSpan:4,className:"px-4 py-12 text-center",children:(0,b.jsxs)("div",{className:"text-slate-400",children:[(0,b.jsx)("svg",{className:"mx-auto h-10 w-10 mb-3 text-slate-300",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:(0,b.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:1.5,d:"M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10"})}),(0,b.jsx)("p",{className:"text-xs text-slate-500",children:"暂无供应商,请先添加供应商"})]})})}):a.map(a=>(0,b.jsxs)("tr",{className:"hover:bg-emerald-50/20 transition-colors duration-300",children:[(0,b.jsx)("td",{className:"px-4 py-3 whitespace-nowrap",children:(0,b.jsx)("div",{className:"text-xs font-medium text-slate-800",children:a.name})}),(0,b.jsx)("td",{className:"px-4 py-3 whitespace-nowrap",children:(0,b.jsx)("span",{className:"px-2 py-0.5 inline-flex text-xs leading-4 font-semibold rounded-full bg-emerald-100/80 text-emerald-700 border border-emerald-200/50",children:a.protocol})}),(0,b.jsx)("td",{className:"px-4 py-3 whitespace-nowrap",children:(0,b.jsx)("div",{className:"text-xs text-slate-600 font-mono",children:a.base_url})}),(0,b.jsx)("td",{className:"px-4 py-3 whitespace-nowrap text-right text-xs font-medium",children:(0,b.jsxs)("div",{className:"flex items-center justify-end space-x-3",children:[(0,b.jsx)("button",{onClick:()=>{var b;return b=a.id,void(0===h.filter(a=>a.provider_id===b).length?F("该供应商下没有模型,请先添加或拉取模型","error"):(u(b),w(""),A("")))},className:"text-blue-600 hover:text-blue-700 font-medium transition-colors duration-300",children:"测试连接"}),(0,b.jsx)("button",{onClick:()=>K(a),className:"text-emerald-600 hover:text-emerald-700 font-medium transition-colors duration-300",children:"编辑"}),(0,b.jsx)("button",{onClick:()=>{s(a.id),q(!0)},className:"text-rose-500 hover:text-rose-600 font-medium transition-colors duration-300",children:"删除"})]})})]},a.id))})]})})]})}),l&&(0,b.jsx)("div",{className:"fixed z-50 inset-0 overflow-y-auto",children:(0,b.jsxs)("div",{className:"flex items-center justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0",children:[(0,b.jsx)("div",{className:"fixed inset-0 bg-slate-900/40 backdrop-blur-sm transition-opacity",onClick:()=>m(!1)}),(0,b.jsx)("div",{className:"inline-block align-bottom bg-white rounded-2xl text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-md sm:w-full border border-emerald-100/50",children:(0,b.jsxs)("form",{onSubmit:J,className:"bg-white px-6 pt-5 pb-4 sm:p-6",children:[(0,b.jsxs)("div",{className:"mb-5",children:[(0,b.jsx)("h3",{className:"text-base font-bold text-slate-800 mb-1",children:n?"编辑供应商":"添加供应商"}),(0,b.jsx)("p",{className:"text-xs text-slate-500",children:"配置 AI 模型供应商信息"})]}),(0,b.jsxs)("div",{className:"space-y-4",children:[(0,b.jsxs)("div",{children:[(0,b.jsx)("label",{className:"block text-xs font-semibold text-slate-700 mb-1.5",children:"名称"}),(0,b.jsx)("input",{type:"text",required:!0,value:B.name,onChange:a=>C({...B,name:a.target.value}),autoComplete:"off",className:"block w-full rounded-lg border border-slate-200 bg-white/80 px-3 py-2 text-xs shadow-sm transition-all duration-300 focus:border-emerald-400 focus:ring-2 focus:ring-emerald-400/20 focus:ring-offset-1",placeholder:"例如: OpenAI"})]}),(0,b.jsxs)("div",{children:[(0,b.jsx)("label",{className:"block text-xs font-semibold text-slate-700 mb-1.5",children:"协议"}),(0,b.jsxs)("select",{value:B.protocol,onChange:a=>C({...B,protocol:a.target.value}),autoComplete:"off",className:"block w-full rounded-lg border border-slate-200 bg-white/80 px-3 py-2 text-xs shadow-sm transition-all duration-300 focus:border-emerald-400 focus:ring-2 focus:ring-emerald-400/20 focus:ring-offset-1",children:[(0,b.jsx)("option",{value:"openai",children:"OpenAI"}),(0,b.jsx)("option",{value:"anthropic",children:"Anthropic"}),(0,b.jsx)("option",{value:"gemini",children:"Gemini"})]})]}),(0,b.jsxs)("div",{children:[(0,b.jsx)("label",{className:"block text-xs font-semibold text-slate-700 mb-1.5",children:"Base URL"}),(0,b.jsx)("input",{type:"url",required:!0,value:B.base_url,onChange:a=>C({...B,base_url:a.target.value}),autoComplete:"off",className:"block w-full rounded-lg border border-slate-200 bg-white/80 px-3 py-2 text-xs shadow-sm transition-all duration-300 focus:border-emerald-400 focus:ring-2 focus:ring-emerald-400/20 focus:ring-offset-1",placeholder:"https://api.openai.com/v1"})]}),(0,b.jsxs)("div",{children:[(0,b.jsxs)("label",{className:"block text-xs font-semibold text-slate-700 mb-1.5",children:["API Key",n&&(0,b.jsx)("span",{className:"ml-1 text-[10px] text-slate-400 font-normal",children:"(已保存,输入新值可更新)"})]}),(0,b.jsxs)("div",{className:"relative",children:[(0,b.jsx)("input",{type:D?"text":"password",required:!n,value:B.api_key,onChange:a=>C({...B,api_key:a.target.value}),autoComplete:"new-password",className:"block w-full rounded-lg border border-slate-200 bg-white/80 px-3 py-2 pr-9 text-xs shadow-sm transition-all duration-300 focus:border-emerald-400 focus:ring-2 focus:ring-emerald-400/20 focus:ring-offset-1",placeholder:n?"留空则不更新,输入新值可更新 API Key":"输入 API Key"}),(0,b.jsx)("button",{type:"button",onClick:()=>E(!D),className:"absolute right-2 top-1/2 -translate-y-1/2 p-1 text-slate-400 hover:text-slate-600 transition-colors",tabIndex:-1,children:D?(0,b.jsx)("svg",{className:"w-4 h-4",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:(0,b.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M13.875 18.825A10.05 10.05 0 0112 19c-4.478 0-8.268-2.943-9.543-7a9.97 9.97 0 011.563-3.029m5.858.908a3 3 0 114.243 4.243M9.878 9.878l4.242 4.242M9.88 9.88l-3.29-3.29m7.532 7.532l3.29 3.29M3 3l3.59 3.59m0 0A9.953 9.953 0 0112 5c4.478 0 8.268 2.943 9.543 7a10.025 10.025 0 01-4.132 5.411m0 0L21 21"})}):(0,b.jsxs)("svg",{className:"w-4 h-4",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:[(0,b.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M15 12a3 3 0 11-6 0 3 3 0 016 0z"}),(0,b.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"})]})})]})]})]}),(0,b.jsxs)("div",{className:"mt-5 flex items-center justify-end space-x-2",children:[(0,b.jsx)("button",{type:"button",onClick:()=>{m(!1),o(null)},className:"px-3.5 py-1.5 border border-slate-200 rounded-lg text-xs font-semibold text-slate-600 bg-white hover:bg-slate-50 focus:outline-none focus:ring-2 focus:ring-offset-1 focus:ring-slate-400/30 transition-all duration-300",children:"取消"}),(0,b.jsx)("button",{type:"submit",className:"px-4 py-1.5 border border-transparent rounded-lg text-xs font-semibold text-white bg-emerald-600 hover:bg-emerald-700 focus:outline-none focus:ring-2 focus:ring-offset-1 focus:ring-emerald-500/50 transition-all duration-300",children:"保存"})]})]})})]})}),(0,b.jsx)(f.default,{open:p,title:"确认删除",message:"确定要删除这个供应商吗?此操作不可恢复。",onConfirm:L,onCancel:()=>{q(!1),s(null)},confirmText:"删除",cancelText:"取消",type:"danger"}),t&&(0,b.jsx)("div",{className:"fixed z-50 inset-0 overflow-y-auto",children:(0,b.jsxs)("div",{className:"flex items-center justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0",children:[(0,b.jsx)("div",{className:"fixed inset-0 bg-slate-900/40 backdrop-blur-sm transition-opacity",onClick:N}),(0,b.jsx)("div",{className:"inline-block align-bottom bg-white rounded-2xl text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-md sm:w-full border border-emerald-100/50",children:(0,b.jsxs)("div",{className:"bg-white px-6 pt-5 pb-4 sm:p-6",children:[(0,b.jsxs)("div",{className:"mb-5",children:[(0,b.jsx)("h3",{className:"text-base font-bold text-slate-800 mb-1",children:"测试连接"}),(0,b.jsx)("p",{className:"text-xs text-slate-500",children:"选择一个模型进行连接测试"})]}),(0,b.jsxs)("div",{className:"space-y-4",children:[(0,b.jsxs)("div",{children:[(0,b.jsx)("label",{className:"block text-xs font-semibold text-slate-700 mb-1.5",children:"搜索模型"}),(0,b.jsxs)("div",{className:"relative",children:[(0,b.jsx)("input",{type:"text",value:z,onChange:a=>A(a.target.value),disabled:x,autoComplete:"off",className:"block w-full rounded-lg border border-slate-200 bg-white/80 pl-9 pr-3 py-2 text-xs shadow-sm transition-all duration-300 focus:border-emerald-400 focus:ring-2 focus:ring-emerald-400/20 focus:ring-offset-1 disabled:opacity-50 disabled:cursor-not-allowed",placeholder:"输入模型名称或ID进行搜索..."}),(0,b.jsx)("svg",{className:"absolute left-3 top-1/2 -translate-y-1/2 w-3.5 h-3.5 text-slate-400",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:(0,b.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"})})]})]}),(0,b.jsxs)("div",{children:[(0,b.jsxs)("label",{className:"block text-xs font-semibold text-slate-700 mb-1.5",children:["选择模型",O(t).length>0&&(0,b.jsxs)("span",{className:"ml-2 text-[10px] text-slate-400 font-normal",children:["(共 ",O(t).length," 个模型)"]})]}),(0,b.jsx)("div",{className:"border border-slate-200 rounded-lg bg-white/80 overflow-hidden",children:(0,b.jsx)("div",{className:"max-h-[240px] overflow-y-auto scrollbar-thin scrollbar-thumb-slate-300 scrollbar-track-slate-100",children:0===O(t).length?(0,b.jsx)("div",{className:"px-3 py-6 text-center",children:(0,b.jsx)("p",{className:"text-xs text-slate-400",children:"没有找到可用的模型"})}):O(t).map(a=>(0,b.jsxs)("button",{type:"button",onClick:()=>w(a.id.toString()),disabled:x,className:`w-full text-left px-3 py-2.5 text-xs font-medium border-b border-slate-100 last:border-0 hover:bg-emerald-50/50 transition-colors duration-200 disabled:opacity-50 disabled:cursor-not-allowed ${v===a.id.toString()?"bg-emerald-100/50 text-emerald-700":"text-slate-700"}`,children:[(0,b.jsx)("div",{children:a.name}),(0,b.jsx)("div",{className:"text-[10px] text-slate-400 mt-0.5",children:a.model_id})]},a.id))})})]})]}),(0,b.jsxs)("div",{className:"mt-5 flex items-center justify-end space-x-2",children:[(0,b.jsx)("button",{type:"button",onClick:N,disabled:x,className:"px-3.5 py-1.5 border border-slate-200 rounded-lg text-xs font-semibold text-slate-600 bg-white hover:bg-slate-50 focus:outline-none focus:ring-2 focus:ring-offset-1 focus:ring-slate-400/30 transition-all duration-300 disabled:opacity-50 disabled:cursor-not-allowed",children:"取消"}),(0,b.jsx)("button",{type:"button",onClick:M,disabled:x||!v,className:"px-4 py-1.5 border border-transparent rounded-lg text-xs font-semibold text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-1 focus:ring-blue-500/50 transition-all duration-300 disabled:opacity-50 disabled:cursor-not-allowed inline-flex items-center",children:x?(0,b.jsxs)(b.Fragment,{children:[(0,b.jsxs)("svg",{className:"animate-spin -ml-1 mr-2 h-3 w-3 text-white",xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24",children:[(0,b.jsx)("circle",{className:"opacity-25",cx:"12",cy:"12",r:"10",stroke:"currentColor",strokeWidth:"4"}),(0,b.jsx)("path",{className:"opacity-75",fill:"currentColor",d:"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"})]}),"测试中..."]}):"开始测试"})]})]})})]})})]})}])}];
|
|
2
|
+
|
|
3
|
+
//# sourceMappingURL=src_app_providers_page_tsx_10ipz~8._.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/app/providers/page.tsx"],"sourcesContent":["'use client';\n\nimport { useState, useEffect } from 'react';\nimport Nav from '../components/Nav';\nimport { useToast } from '../components/ToastProvider';\nimport ConfirmDialog from '../components/ConfirmDialog';\n\ninterface Provider {\n id: number;\n name: string;\n protocol: string;\n base_url: string;\n api_key: string;\n}\n\ninterface Model {\n id: number;\n provider_id: number;\n name: string;\n model_id: string;\n enabled: boolean;\n}\n\nexport default function ProvidersPage() {\n const [providers, setProviders] = useState<Provider[]>([]);\n const [models, setModels] = useState<Model[]>([]);\n const [loading, setLoading] = useState(true);\n const [showModal, setShowModal] = useState(false);\n const [editing, setEditing] = useState<Provider | null>(null);\n const [showConfirm, setShowConfirm] = useState(false);\n const [deleteId, setDeleteId] = useState<number | null>(null);\n const [testingProviderId, setTestingProviderId] = useState<number | null>(null);\n const [selectedModelId, setSelectedModelId] = useState<string>('');\n const [testing, setTesting] = useState(false);\n const [searchQuery, setSearchQuery] = useState('');\n const [formData, setFormData] = useState({\n name: '',\n protocol: 'openai',\n base_url: '',\n api_key: '',\n });\n const [showApiKey, setShowApiKey] = useState(false);\n const { showToast } = useToast();\n\n useEffect(() => {\n loadProviders();\n loadModels();\n }, []);\n\n const loadProviders = async () => {\n try {\n const res = await fetch('/api/providers');\n const data = await res.json();\n setProviders(data);\n } catch (error) {\n console.error('Failed to load providers:', error);\n } finally {\n setLoading(false);\n }\n };\n\n const loadModels = async () => {\n try {\n const res = await fetch('/api/models');\n const data = await res.json();\n setModels(data);\n } catch (error) {\n console.error('Failed to load models:', error);\n }\n };\n\n const loadProviderForEdit = async (id: number) => {\n try {\n const res = await fetch(`/api/providers?id=${id}&includeKey=true`);\n if (!res.ok) {\n throw new Error('Failed to load provider');\n }\n const data = await res.json();\n return data;\n } catch (error) {\n console.error('Failed to load provider for edit:', error);\n throw error;\n }\n };\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault();\n try {\n let response: Response;\n if (editing) {\n const updateData: any = {\n id: editing.id,\n name: formData.name,\n protocol: formData.protocol,\n base_url: formData.base_url,\n };\n if (formData.api_key && formData.api_key.trim() !== '') {\n updateData.api_key = formData.api_key.trim();\n }\n response = await fetch('/api/providers', {\n method: 'PUT',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(updateData),\n });\n } else {\n if (!formData.api_key || formData.api_key.trim() === '') {\n showToast('API Key 不能为空', 'error');\n return;\n }\n response = await fetch('/api/providers', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n ...formData,\n api_key: formData.api_key.trim(),\n }),\n });\n }\n\n if (!response.ok) {\n const errorData = await response.json().catch(() => ({}));\n const errorMessage = errorData.error || '保存失败';\n showToast(errorMessage, 'error');\n return;\n }\n\n setShowModal(false);\n setEditing(null);\n setFormData({ name: '', protocol: 'openai', base_url: '', api_key: '' });\n setShowApiKey(false);\n loadProviders();\n showToast('供应商保存成功', 'success');\n } catch (error: any) {\n console.error('Failed to save provider:', error);\n showToast('保存失败: ' + (error.message || '未知错误'), 'error');\n }\n };\n\n const handleEdit = async (provider: Provider) => {\n try {\n // Load provider with API key for editing\n const providerWithKey = await loadProviderForEdit(provider.id);\n setEditing(provider);\n setFormData({\n name: providerWithKey.name,\n protocol: providerWithKey.protocol,\n base_url: providerWithKey.base_url,\n api_key: providerWithKey.api_key || '', // Show existing key\n });\n setShowApiKey(false); // Start with hidden\n setShowModal(true);\n } catch (error) {\n console.error('Failed to load provider for edit:', error);\n showToast('加载供应商信息失败', 'error');\n }\n };\n\n const handleDelete = (id: number) => {\n setDeleteId(id);\n setShowConfirm(true);\n };\n\n const confirmDelete = async () => {\n if (deleteId) {\n try {\n await fetch(`/api/providers?id=${deleteId}`, { method: 'DELETE' });\n loadProviders();\n showToast('供应商已删除', 'success');\n } catch (error) {\n console.error('Failed to delete provider:', error);\n showToast('删除失败', 'error');\n }\n }\n setShowConfirm(false);\n setDeleteId(null);\n };\n\n const handleTestConnection = (providerId: number) => {\n const providerModels = models.filter(m => m.provider_id === providerId);\n if (providerModels.length === 0) {\n showToast('该供应商下没有模型,请先添加或拉取模型', 'error');\n return;\n }\n setTestingProviderId(providerId);\n setSelectedModelId('');\n setSearchQuery('');\n };\n\n const startTest = async () => {\n if (!testingProviderId || !selectedModelId) {\n showToast('请选择要测试的模型', 'error');\n return;\n }\n\n setTesting(true);\n try {\n const res = await fetch('/api/providers/test', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n provider_id: testingProviderId,\n model_id: parseInt(selectedModelId),\n }),\n });\n\n const data = await res.json();\n if (data.success) {\n showToast(data.message || '连接成功,模型可用', 'success');\n } else {\n showToast(data.error || '连接失败', 'error');\n }\n } catch (error: any) {\n console.error('Failed to test connection:', error);\n showToast('测试连接失败: ' + (error.message || '未知错误'), 'error');\n } finally {\n setTesting(false);\n // 不关闭弹窗,只重置选中的模型\n setSelectedModelId('');\n }\n };\n\n const cancelTest = () => {\n setTestingProviderId(null);\n setSelectedModelId('');\n setSearchQuery('');\n };\n\n const getProviderModels = (providerId: number) => {\n // 仅显示已启动的模型\n const providerModels = models.filter(m => m.provider_id === providerId && m.enabled);\n if (!searchQuery.trim()) {\n return providerModels;\n }\n const query = searchQuery.toLowerCase().trim();\n return providerModels.filter(model =>\n model.name.toLowerCase().includes(query) ||\n model.model_id.toLowerCase().includes(query)\n );\n };\n\n if (loading) {\n return (\n <>\n <Nav />\n <div className=\"min-h-screen flex items-center justify-center\">\n <div className=\"text-lg\">加载中...</div>\n </div>\n </>\n );\n }\n\n return (\n <>\n <Nav />\n <main className=\"max-w-6xl mx-auto py-6 sm:px-6 lg:px-8\">\n <div className=\"px-4 py-4 sm:px-0\">\n <div className=\"flex justify-between items-center mb-5\">\n <div>\n <h1 className=\"text-lg font-bold text-slate-800\">供应商管理</h1>\n <p className=\"text-xs text-slate-500 mt-1\">管理 AI 模型供应商配置</p>\n </div>\n <button\n onClick={() => {\n setEditing(null);\n setFormData({ name: '', protocol: 'openai', base_url: '', api_key: '' });\n setShowApiKey(false);\n setShowModal(true);\n }}\n className=\"inline-flex items-center px-3.5 py-1.5 border border-transparent text-xs font-semibold rounded-lg shadow-sm text-white bg-emerald-600 hover:bg-emerald-700 focus:outline-none focus:ring-2 focus:ring-offset-1 focus:ring-emerald-500/50 transition-all duration-300\"\n >\n <svg className=\"w-3.5 h-3.5 mr-1.5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M12 4v16m8-8H4\" />\n </svg>\n 添加供应商\n </button>\n </div>\n\n <div className=\"bg-white/70 backdrop-blur-sm shadow-md rounded-2xl border border-emerald-100/50 overflow-hidden\">\n <table className=\"min-w-full divide-y divide-slate-100\">\n <thead className=\"bg-emerald-50/30\">\n <tr>\n <th className=\"px-4 py-2.5 text-left text-xs font-semibold text-slate-600 uppercase tracking-wider\">\n 名称\n </th>\n <th className=\"px-6 py-4 text-left text-xs font-semibold text-slate-600 uppercase tracking-wider\">\n 协议\n </th>\n <th className=\"px-6 py-4 text-left text-xs font-semibold text-slate-600 uppercase tracking-wider\">\n Base URL\n </th>\n <th className=\"px-6 py-3.5 text-right text-xs font-semibold text-gray-700 uppercase tracking-wider\">\n 操作\n </th>\n </tr>\n </thead>\n <tbody className=\"bg-white divide-y divide-slate-100\">\n {providers.length === 0 ? (\n <tr>\n <td colSpan={4} className=\"px-4 py-12 text-center\">\n <div className=\"text-slate-400\">\n <svg className=\"mx-auto h-10 w-10 mb-3 text-slate-300\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={1.5} d=\"M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10\" />\n </svg>\n <p className=\"text-xs text-slate-500\">暂无供应商,请先添加供应商</p>\n </div>\n </td>\n </tr>\n ) : (\n providers.map((provider) => (\n <tr key={provider.id} className=\"hover:bg-emerald-50/20 transition-colors duration-300\">\n <td className=\"px-4 py-3 whitespace-nowrap\">\n <div className=\"text-xs font-medium text-slate-800\">{provider.name}</div>\n </td>\n <td className=\"px-4 py-3 whitespace-nowrap\">\n <span className=\"px-2 py-0.5 inline-flex text-xs leading-4 font-semibold rounded-full bg-emerald-100/80 text-emerald-700 border border-emerald-200/50\">\n {provider.protocol}\n </span>\n </td>\n <td className=\"px-4 py-3 whitespace-nowrap\">\n <div className=\"text-xs text-slate-600 font-mono\">{provider.base_url}</div>\n </td>\n <td className=\"px-4 py-3 whitespace-nowrap text-right text-xs font-medium\">\n <div className=\"flex items-center justify-end space-x-3\">\n <button\n onClick={() => handleTestConnection(provider.id)}\n className=\"text-blue-600 hover:text-blue-700 font-medium transition-colors duration-300\"\n >\n 测试连接\n </button>\n <button\n onClick={() => handleEdit(provider)}\n className=\"text-emerald-600 hover:text-emerald-700 font-medium transition-colors duration-300\"\n >\n 编辑\n </button>\n <button\n onClick={() => handleDelete(provider.id)}\n className=\"text-rose-500 hover:text-rose-600 font-medium transition-colors duration-300\"\n >\n 删除\n </button>\n </div>\n </td>\n </tr>\n ))\n )}\n </tbody>\n </table>\n </div>\n </div>\n </main>\n\n {showModal && (\n <div className=\"fixed z-50 inset-0 overflow-y-auto\">\n <div className=\"flex items-center justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0\">\n <div className=\"fixed inset-0 bg-slate-900/40 backdrop-blur-sm transition-opacity\" onClick={() => setShowModal(false)}></div>\n <div className=\"inline-block align-bottom bg-white rounded-2xl text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-md sm:w-full border border-emerald-100/50\">\n <form onSubmit={handleSubmit} className=\"bg-white px-6 pt-5 pb-4 sm:p-6\">\n <div className=\"mb-5\">\n <h3 className=\"text-base font-bold text-slate-800 mb-1\">\n {editing ? '编辑供应商' : '添加供应商'}\n </h3>\n <p className=\"text-xs text-slate-500\">配置 AI 模型供应商信息</p>\n </div>\n <div className=\"space-y-4\">\n <div>\n <label className=\"block text-xs font-semibold text-slate-700 mb-1.5\">名称</label>\n <input\n type=\"text\"\n required\n value={formData.name}\n onChange={(e) => setFormData({ ...formData, name: e.target.value })}\n autoComplete=\"off\"\n className=\"block w-full rounded-lg border border-slate-200 bg-white/80 px-3 py-2 text-xs shadow-sm transition-all duration-300 focus:border-emerald-400 focus:ring-2 focus:ring-emerald-400/20 focus:ring-offset-1\"\n placeholder=\"例如: OpenAI\"\n />\n </div>\n <div>\n <label className=\"block text-xs font-semibold text-slate-700 mb-1.5\">协议</label>\n <select\n value={formData.protocol}\n onChange={(e) => setFormData({ ...formData, protocol: e.target.value })}\n autoComplete=\"off\"\n className=\"block w-full rounded-lg border border-slate-200 bg-white/80 px-3 py-2 text-xs shadow-sm transition-all duration-300 focus:border-emerald-400 focus:ring-2 focus:ring-emerald-400/20 focus:ring-offset-1\"\n >\n <option value=\"openai\">OpenAI</option>\n <option value=\"anthropic\">Anthropic</option>\n <option value=\"gemini\">Gemini</option>\n </select>\n </div>\n <div>\n <label className=\"block text-xs font-semibold text-slate-700 mb-1.5\">Base URL</label>\n <input\n type=\"url\"\n required\n value={formData.base_url}\n onChange={(e) => setFormData({ ...formData, base_url: e.target.value })}\n autoComplete=\"off\"\n className=\"block w-full rounded-lg border border-slate-200 bg-white/80 px-3 py-2 text-xs shadow-sm transition-all duration-300 focus:border-emerald-400 focus:ring-2 focus:ring-emerald-400/20 focus:ring-offset-1\"\n placeholder=\"https://api.openai.com/v1\"\n />\n </div>\n <div>\n <label className=\"block text-xs font-semibold text-slate-700 mb-1.5\">\n API Key\n {editing && (\n <span className=\"ml-1 text-[10px] text-slate-400 font-normal\">(已保存,输入新值可更新)</span>\n )}\n </label>\n <div className=\"relative\">\n <input\n type={showApiKey ? 'text' : 'password'}\n required={!editing}\n value={formData.api_key}\n onChange={(e) => setFormData({ ...formData, api_key: e.target.value })}\n autoComplete=\"new-password\"\n className=\"block w-full rounded-lg border border-slate-200 bg-white/80 px-3 py-2 pr-9 text-xs shadow-sm transition-all duration-300 focus:border-emerald-400 focus:ring-2 focus:ring-emerald-400/20 focus:ring-offset-1\"\n placeholder={editing ? '留空则不更新,输入新值可更新 API Key' : '输入 API Key'}\n />\n <button\n type=\"button\"\n onClick={() => setShowApiKey(!showApiKey)}\n className=\"absolute right-2 top-1/2 -translate-y-1/2 p-1 text-slate-400 hover:text-slate-600 transition-colors\"\n tabIndex={-1}\n >\n {showApiKey ? (\n <svg className=\"w-4 h-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M13.875 18.825A10.05 10.05 0 0112 19c-4.478 0-8.268-2.943-9.543-7a9.97 9.97 0 011.563-3.029m5.858.908a3 3 0 114.243 4.243M9.878 9.878l4.242 4.242M9.88 9.88l-3.29-3.29m7.532 7.532l3.29 3.29M3 3l3.59 3.59m0 0A9.953 9.953 0 0112 5c4.478 0 8.268 2.943 9.543 7a10.025 10.025 0 01-4.132 5.411m0 0L21 21\" />\n </svg>\n ) : (\n <svg className=\"w-4 h-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M15 12a3 3 0 11-6 0 3 3 0 016 0z\" />\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z\" />\n </svg>\n )}\n </button>\n </div>\n </div>\n </div>\n <div className=\"mt-5 flex items-center justify-end space-x-2\">\n <button\n type=\"button\"\n onClick={() => {\n setShowModal(false);\n setEditing(null);\n }}\n className=\"px-3.5 py-1.5 border border-slate-200 rounded-lg text-xs font-semibold text-slate-600 bg-white hover:bg-slate-50 focus:outline-none focus:ring-2 focus:ring-offset-1 focus:ring-slate-400/30 transition-all duration-300\"\n >\n 取消\n </button>\n <button\n type=\"submit\"\n className=\"px-4 py-1.5 border border-transparent rounded-lg text-xs font-semibold text-white bg-emerald-600 hover:bg-emerald-700 focus:outline-none focus:ring-2 focus:ring-offset-1 focus:ring-emerald-500/50 transition-all duration-300\"\n >\n 保存\n </button>\n </div>\n </form>\n </div>\n </div>\n </div>\n )}\n\n <ConfirmDialog\n open={showConfirm}\n title=\"确认删除\"\n message=\"确定要删除这个供应商吗?此操作不可恢复。\"\n onConfirm={confirmDelete}\n onCancel={() => {\n setShowConfirm(false);\n setDeleteId(null);\n }}\n confirmText=\"删除\"\n cancelText=\"取消\"\n type=\"danger\"\n />\n\n {/* Test Connection Modal */}\n {testingProviderId && (\n <div className=\"fixed z-50 inset-0 overflow-y-auto\">\n <div className=\"flex items-center justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0\">\n <div className=\"fixed inset-0 bg-slate-900/40 backdrop-blur-sm transition-opacity\" onClick={cancelTest}></div>\n <div className=\"inline-block align-bottom bg-white rounded-2xl text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-md sm:w-full border border-emerald-100/50\">\n <div className=\"bg-white px-6 pt-5 pb-4 sm:p-6\">\n <div className=\"mb-5\">\n <h3 className=\"text-base font-bold text-slate-800 mb-1\">测试连接</h3>\n <p className=\"text-xs text-slate-500\">选择一个模型进行连接测试</p>\n </div>\n <div className=\"space-y-4\">\n <div>\n <label className=\"block text-xs font-semibold text-slate-700 mb-1.5\">搜索模型</label>\n <div className=\"relative\">\n <input\n type=\"text\"\n value={searchQuery}\n onChange={(e) => setSearchQuery(e.target.value)}\n disabled={testing}\n autoComplete=\"off\"\n className=\"block w-full rounded-lg border border-slate-200 bg-white/80 pl-9 pr-3 py-2 text-xs shadow-sm transition-all duration-300 focus:border-emerald-400 focus:ring-2 focus:ring-emerald-400/20 focus:ring-offset-1 disabled:opacity-50 disabled:cursor-not-allowed\"\n placeholder=\"输入模型名称或ID进行搜索...\"\n />\n <svg className=\"absolute left-3 top-1/2 -translate-y-1/2 w-3.5 h-3.5 text-slate-400\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z\" />\n </svg>\n </div>\n </div>\n <div>\n <label className=\"block text-xs font-semibold text-slate-700 mb-1.5\">\n 选择模型\n {getProviderModels(testingProviderId).length > 0 && (\n <span className=\"ml-2 text-[10px] text-slate-400 font-normal\">\n (共 {getProviderModels(testingProviderId).length} 个模型)\n </span>\n )}\n </label>\n <div className=\"border border-slate-200 rounded-lg bg-white/80 overflow-hidden\">\n <div className=\"max-h-[240px] overflow-y-auto scrollbar-thin scrollbar-thumb-slate-300 scrollbar-track-slate-100\">\n {getProviderModels(testingProviderId).length === 0 ? (\n <div className=\"px-3 py-6 text-center\">\n <p className=\"text-xs text-slate-400\">没有找到可用的模型</p>\n </div>\n ) : (\n getProviderModels(testingProviderId).map((model) => (\n <button\n key={model.id}\n type=\"button\"\n onClick={() => setSelectedModelId(model.id.toString())}\n disabled={testing}\n className={`w-full text-left px-3 py-2.5 text-xs font-medium border-b border-slate-100 last:border-0 hover:bg-emerald-50/50 transition-colors duration-200 disabled:opacity-50 disabled:cursor-not-allowed ${\n selectedModelId === model.id.toString()\n ? 'bg-emerald-100/50 text-emerald-700'\n : 'text-slate-700'\n }`}\n >\n <div>{model.name}</div>\n <div className=\"text-[10px] text-slate-400 mt-0.5\">{model.model_id}</div>\n </button>\n ))\n )}\n </div>\n </div>\n </div>\n </div>\n <div className=\"mt-5 flex items-center justify-end space-x-2\">\n <button\n type=\"button\"\n onClick={cancelTest}\n disabled={testing}\n className=\"px-3.5 py-1.5 border border-slate-200 rounded-lg text-xs font-semibold text-slate-600 bg-white hover:bg-slate-50 focus:outline-none focus:ring-2 focus:ring-offset-1 focus:ring-slate-400/30 transition-all duration-300 disabled:opacity-50 disabled:cursor-not-allowed\"\n >\n 取消\n </button>\n <button\n type=\"button\"\n onClick={startTest}\n disabled={testing || !selectedModelId}\n className=\"px-4 py-1.5 border border-transparent rounded-lg text-xs font-semibold text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-1 focus:ring-blue-500/50 transition-all duration-300 disabled:opacity-50 disabled:cursor-not-allowed inline-flex items-center\"\n >\n {testing ? (\n <>\n <svg className=\"animate-spin -ml-1 mr-2 h-3 w-3 text-white\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\">\n <circle className=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" strokeWidth=\"4\"></circle>\n <path className=\"opacity-75\" fill=\"currentColor\" d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"></path>\n </svg>\n 测试中...\n </>\n ) : (\n '开始测试'\n )}\n </button>\n </div>\n </div>\n </div>\n </div>\n </div>\n )}\n </>\n );\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../src/app/providers/page.tsx"],"sourcesContent":["'use client';\n\nimport { useState, useEffect } from 'react';\nimport Nav from '../components/Nav';\nimport { useToast } from '../components/ToastProvider';\nimport ConfirmDialog from '../components/ConfirmDialog';\n\ninterface Provider {\n id: number;\n name: string;\n protocol: string;\n base_url: string;\n api_key: string;\n}\n\ninterface Model {\n id: number;\n provider_id: number;\n name: string;\n model_id: string;\n enabled: boolean;\n}\n\nexport default function ProvidersPage() {\n const [providers, setProviders] = useState<Provider[]>([]);\n const [models, setModels] = useState<Model[]>([]);\n const [loading, setLoading] = useState(true);\n const [showModal, setShowModal] = useState(false);\n const [editing, setEditing] = useState<Provider | null>(null);\n const [showConfirm, setShowConfirm] = useState(false);\n const [deleteId, setDeleteId] = useState<number | null>(null);\n const [testingProviderId, setTestingProviderId] = useState<number | null>(null);\n const [selectedModelId, setSelectedModelId] = useState<string>('');\n const [testing, setTesting] = useState(false);\n const [searchQuery, setSearchQuery] = useState('');\n const [formData, setFormData] = useState({\n name: '',\n protocol: 'openai',\n base_url: '',\n api_key: '',\n });\n const [showApiKey, setShowApiKey] = useState(false);\n const { showToast } = useToast();\n\n useEffect(() => {\n loadProviders();\n loadModels();\n }, []);\n\n const loadProviders = async () => {\n try {\n const res = await fetch('/api/providers');\n const data = await res.json();\n setProviders(data);\n } catch (error) {\n console.error('Failed to load providers:', error);\n } finally {\n setLoading(false);\n }\n };\n\n const loadModels = async () => {\n try {\n const res = await fetch('/api/models');\n const data = await res.json();\n setModels(data);\n } catch (error) {\n console.error('Failed to load models:', error);\n }\n };\n\n const loadProviderForEdit = async (id: number) => {\n try {\n const res = await fetch(`/api/providers?id=${id}&includeKey=true`);\n if (!res.ok) {\n throw new Error('Failed to load provider');\n }\n const data = await res.json();\n return data;\n } catch (error) {\n console.error('Failed to load provider for edit:', error);\n throw error;\n }\n };\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault();\n try {\n let response: Response;\n if (editing) {\n const updateData: any = {\n id: editing.id,\n name: formData.name,\n protocol: formData.protocol,\n base_url: formData.base_url,\n };\n if (formData.api_key && formData.api_key.trim() !== '') {\n updateData.api_key = formData.api_key.trim();\n }\n response = await fetch('/api/providers', {\n method: 'PUT',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(updateData),\n });\n } else {\n if (!formData.api_key || formData.api_key.trim() === '') {\n showToast('API Key 不能为空', 'error');\n return;\n }\n response = await fetch('/api/providers', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n ...formData,\n api_key: formData.api_key.trim(),\n }),\n });\n }\n\n if (!response.ok) {\n const errorData = await response.json().catch(() => ({}));\n const errorMessage = errorData.error || '保存失败';\n showToast(errorMessage, 'error');\n return;\n }\n\n setShowModal(false);\n setEditing(null);\n setFormData({ name: '', protocol: 'openai', base_url: '', api_key: '' });\n setShowApiKey(false);\n loadProviders();\n showToast('供应商保存成功', 'success');\n } catch (error: any) {\n console.error('Failed to save provider:', error);\n showToast('保存失败: ' + (error.message || '未知错误'), 'error');\n }\n };\n\n const handleEdit = async (provider: Provider) => {\n try {\n // Load provider with API key for editing\n const providerWithKey = await loadProviderForEdit(provider.id);\n setEditing(provider);\n setFormData({\n name: providerWithKey.name,\n protocol: providerWithKey.protocol,\n base_url: providerWithKey.base_url,\n api_key: providerWithKey.api_key || '', // Show existing key\n });\n setShowApiKey(false); // Start with hidden\n setShowModal(true);\n } catch (error) {\n console.error('Failed to load provider for edit:', error);\n showToast('加载供应商信息失败', 'error');\n }\n };\n\n const handleDelete = (id: number) => {\n setDeleteId(id);\n setShowConfirm(true);\n };\n\n const confirmDelete = async () => {\n if (deleteId) {\n try {\n await fetch(`/api/providers?id=${deleteId}`, { method: 'DELETE' });\n loadProviders();\n showToast('供应商已删除', 'success');\n } catch (error) {\n console.error('Failed to delete provider:', error);\n showToast('删除失败', 'error');\n }\n }\n setShowConfirm(false);\n setDeleteId(null);\n };\n\n const handleTestConnection = (providerId: number) => {\n const providerModels = models.filter(m => m.provider_id === providerId);\n if (providerModels.length === 0) {\n showToast('该供应商下没有模型,请先添加或拉取模型', 'error');\n return;\n }\n setTestingProviderId(providerId);\n setSelectedModelId('');\n setSearchQuery('');\n };\n\n const startTest = async () => {\n if (!testingProviderId || !selectedModelId) {\n showToast('请选择要测试的模型', 'error');\n return;\n }\n\n setTesting(true);\n try {\n const res = await fetch('/api/providers/test', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n provider_id: testingProviderId,\n model_id: parseInt(selectedModelId),\n }),\n });\n\n const data = await res.json();\n if (data.success) {\n showToast(data.message || '连接成功,模型可用', 'success');\n } else {\n showToast(data.error || '连接失败', 'error');\n }\n } catch (error: any) {\n console.error('Failed to test connection:', error);\n showToast('测试连接失败: ' + (error.message || '未知错误'), 'error');\n } finally {\n setTesting(false);\n // 不关闭弹窗,只重置选中的模型\n setSelectedModelId('');\n }\n };\n\n const cancelTest = () => {\n setTestingProviderId(null);\n setSelectedModelId('');\n setSearchQuery('');\n };\n\n const getProviderModels = (providerId: number) => {\n // 仅显示已启动的模型\n const providerModels = models.filter(m => m.provider_id === providerId && m.enabled);\n if (!searchQuery.trim()) {\n return providerModels;\n }\n const query = searchQuery.toLowerCase().trim();\n return providerModels.filter(model =>\n model.name.toLowerCase().includes(query) ||\n model.model_id.toLowerCase().includes(query)\n );\n };\n\n if (loading) {\n return (\n <>\n <Nav />\n <div className=\"min-h-screen flex items-center justify-center\">\n <div className=\"text-lg\">加载中...</div>\n </div>\n </>\n );\n }\n\n return (\n <>\n <Nav />\n <main className=\"max-w-6xl mx-auto py-6 sm:px-6 lg:px-8\">\n <div className=\"px-4 py-4 sm:px-0\">\n <div className=\"flex justify-between items-center mb-5\">\n <div>\n <h1 className=\"text-lg font-bold text-slate-800\">供应商管理</h1>\n <p className=\"text-xs text-slate-500 mt-1\">管理 AI 模型供应商配置</p>\n </div>\n <button\n onClick={() => {\n setEditing(null);\n setFormData({ name: '', protocol: 'openai', base_url: '', api_key: '' });\n setShowApiKey(false);\n setShowModal(true);\n }}\n className=\"inline-flex items-center px-3.5 py-1.5 border border-transparent text-xs font-semibold rounded-lg shadow-sm text-white bg-emerald-600 hover:bg-emerald-700 focus:outline-none focus:ring-2 focus:ring-offset-1 focus:ring-emerald-500/50 transition-all duration-300\"\n >\n <svg className=\"w-3.5 h-3.5 mr-1.5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M12 4v16m8-8H4\" />\n </svg>\n 添加供应商\n </button>\n </div>\n\n <div className=\"bg-white/70 backdrop-blur-sm shadow-md rounded-2xl border border-emerald-100/50 overflow-hidden\">\n <table className=\"min-w-full divide-y divide-slate-100\">\n <thead className=\"bg-emerald-50/30\">\n <tr>\n <th className=\"px-4 py-2.5 text-left text-xs font-semibold text-slate-600 uppercase tracking-wider\">\n 名称\n </th>\n <th className=\"px-6 py-4 text-left text-xs font-semibold text-slate-600 uppercase tracking-wider\">\n 协议\n </th>\n <th className=\"px-6 py-4 text-left text-xs font-semibold text-slate-600 uppercase tracking-wider\">\n Base URL\n </th>\n <th className=\"px-6 py-3.5 text-right text-xs font-semibold text-gray-700 uppercase tracking-wider\">\n 操作\n </th>\n </tr>\n </thead>\n <tbody className=\"bg-white divide-y divide-slate-100\">\n {providers.length === 0 ? (\n <tr>\n <td colSpan={4} className=\"px-4 py-12 text-center\">\n <div className=\"text-slate-400\">\n <svg className=\"mx-auto h-10 w-10 mb-3 text-slate-300\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={1.5} d=\"M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10\" />\n </svg>\n <p className=\"text-xs text-slate-500\">暂无供应商,请先添加供应商</p>\n </div>\n </td>\n </tr>\n ) : (\n providers.map((provider) => (\n <tr key={provider.id} className=\"hover:bg-emerald-50/20 transition-colors duration-300\">\n <td className=\"px-4 py-3 whitespace-nowrap\">\n <div className=\"text-xs font-medium text-slate-800\">{provider.name}</div>\n </td>\n <td className=\"px-4 py-3 whitespace-nowrap\">\n <span className=\"px-2 py-0.5 inline-flex text-xs leading-4 font-semibold rounded-full bg-emerald-100/80 text-emerald-700 border border-emerald-200/50\">\n {provider.protocol}\n </span>\n </td>\n <td className=\"px-4 py-3 whitespace-nowrap\">\n <div className=\"text-xs text-slate-600 font-mono\">{provider.base_url}</div>\n </td>\n <td className=\"px-4 py-3 whitespace-nowrap text-right text-xs font-medium\">\n <div className=\"flex items-center justify-end space-x-3\">\n <button\n onClick={() => handleTestConnection(provider.id)}\n className=\"text-blue-600 hover:text-blue-700 font-medium transition-colors duration-300\"\n >\n 测试连接\n </button>\n <button\n onClick={() => handleEdit(provider)}\n className=\"text-emerald-600 hover:text-emerald-700 font-medium transition-colors duration-300\"\n >\n 编辑\n </button>\n <button\n onClick={() => handleDelete(provider.id)}\n className=\"text-rose-500 hover:text-rose-600 font-medium transition-colors duration-300\"\n >\n 删除\n </button>\n </div>\n </td>\n </tr>\n ))\n )}\n </tbody>\n </table>\n </div>\n </div>\n </main>\n\n {showModal && (\n <div className=\"fixed z-50 inset-0 overflow-y-auto\">\n <div className=\"flex items-center justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0\">\n <div className=\"fixed inset-0 bg-slate-900/40 backdrop-blur-sm transition-opacity\" onClick={() => setShowModal(false)}></div>\n <div className=\"inline-block align-bottom bg-white rounded-2xl text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-md sm:w-full border border-emerald-100/50\">\n <form onSubmit={handleSubmit} className=\"bg-white px-6 pt-5 pb-4 sm:p-6\">\n <div className=\"mb-5\">\n <h3 className=\"text-base font-bold text-slate-800 mb-1\">\n {editing ? '编辑供应商' : '添加供应商'}\n </h3>\n <p className=\"text-xs text-slate-500\">配置 AI 模型供应商信息</p>\n </div>\n <div className=\"space-y-4\">\n <div>\n <label className=\"block text-xs font-semibold text-slate-700 mb-1.5\">名称</label>\n <input\n type=\"text\"\n required\n value={formData.name}\n onChange={(e) => setFormData({ ...formData, name: e.target.value })}\n autoComplete=\"off\"\n className=\"block w-full rounded-lg border border-slate-200 bg-white/80 px-3 py-2 text-xs shadow-sm transition-all duration-300 focus:border-emerald-400 focus:ring-2 focus:ring-emerald-400/20 focus:ring-offset-1\"\n placeholder=\"例如: OpenAI\"\n />\n </div>\n <div>\n <label className=\"block text-xs font-semibold text-slate-700 mb-1.5\">协议</label>\n <select\n value={formData.protocol}\n onChange={(e) => setFormData({ ...formData, protocol: e.target.value })}\n autoComplete=\"off\"\n className=\"block w-full rounded-lg border border-slate-200 bg-white/80 px-3 py-2 text-xs shadow-sm transition-all duration-300 focus:border-emerald-400 focus:ring-2 focus:ring-emerald-400/20 focus:ring-offset-1\"\n >\n <option value=\"openai\">OpenAI</option>\n <option value=\"anthropic\">Anthropic</option>\n <option value=\"gemini\">Gemini</option>\n </select>\n </div>\n <div>\n <label className=\"block text-xs font-semibold text-slate-700 mb-1.5\">Base URL</label>\n <input\n type=\"url\"\n required\n value={formData.base_url}\n onChange={(e) => setFormData({ ...formData, base_url: e.target.value })}\n autoComplete=\"off\"\n className=\"block w-full rounded-lg border border-slate-200 bg-white/80 px-3 py-2 text-xs shadow-sm transition-all duration-300 focus:border-emerald-400 focus:ring-2 focus:ring-emerald-400/20 focus:ring-offset-1\"\n placeholder=\"https://api.openai.com/v1\"\n />\n </div>\n <div>\n <label className=\"block text-xs font-semibold text-slate-700 mb-1.5\">\n API Key\n {editing && (\n <span className=\"ml-1 text-[10px] text-slate-400 font-normal\">(已保存,输入新值可更新)</span>\n )}\n </label>\n <div className=\"relative\">\n <input\n type={showApiKey ? 'text' : 'password'}\n required={!editing}\n value={formData.api_key}\n onChange={(e) => setFormData({ ...formData, api_key: e.target.value })}\n autoComplete=\"new-password\"\n className=\"block w-full rounded-lg border border-slate-200 bg-white/80 px-3 py-2 pr-9 text-xs shadow-sm transition-all duration-300 focus:border-emerald-400 focus:ring-2 focus:ring-emerald-400/20 focus:ring-offset-1\"\n placeholder={editing ? '留空则不更新,输入新值可更新 API Key' : '输入 API Key'}\n />\n <button\n type=\"button\"\n onClick={() => setShowApiKey(!showApiKey)}\n className=\"absolute right-2 top-1/2 -translate-y-1/2 p-1 text-slate-400 hover:text-slate-600 transition-colors\"\n tabIndex={-1}\n >\n {showApiKey ? (\n <svg className=\"w-4 h-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M13.875 18.825A10.05 10.05 0 0112 19c-4.478 0-8.268-2.943-9.543-7a9.97 9.97 0 011.563-3.029m5.858.908a3 3 0 114.243 4.243M9.878 9.878l4.242 4.242M9.88 9.88l-3.29-3.29m7.532 7.532l3.29 3.29M3 3l3.59 3.59m0 0A9.953 9.953 0 0112 5c4.478 0 8.268 2.943 9.543 7a10.025 10.025 0 01-4.132 5.411m0 0L21 21\" />\n </svg>\n ) : (\n <svg className=\"w-4 h-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M15 12a3 3 0 11-6 0 3 3 0 016 0z\" />\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z\" />\n </svg>\n )}\n </button>\n </div>\n </div>\n </div>\n <div className=\"mt-5 flex items-center justify-end space-x-2\">\n <button\n type=\"button\"\n onClick={() => {\n setShowModal(false);\n setEditing(null);\n }}\n className=\"px-3.5 py-1.5 border border-slate-200 rounded-lg text-xs font-semibold text-slate-600 bg-white hover:bg-slate-50 focus:outline-none focus:ring-2 focus:ring-offset-1 focus:ring-slate-400/30 transition-all duration-300\"\n >\n 取消\n </button>\n <button\n type=\"submit\"\n className=\"px-4 py-1.5 border border-transparent rounded-lg text-xs font-semibold text-white bg-emerald-600 hover:bg-emerald-700 focus:outline-none focus:ring-2 focus:ring-offset-1 focus:ring-emerald-500/50 transition-all duration-300\"\n >\n 保存\n </button>\n </div>\n </form>\n </div>\n </div>\n </div>\n )}\n\n <ConfirmDialog\n open={showConfirm}\n title=\"确认删除\"\n message=\"确定要删除这个供应商吗?此操作不可恢复。\"\n onConfirm={confirmDelete}\n onCancel={() => {\n setShowConfirm(false);\n setDeleteId(null);\n }}\n confirmText=\"删除\"\n cancelText=\"取消\"\n type=\"danger\"\n />\n\n {/* Test Connection Modal */}\n {testingProviderId && (\n <div className=\"fixed z-50 inset-0 overflow-y-auto\">\n <div className=\"flex items-center justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0\">\n <div className=\"fixed inset-0 bg-slate-900/40 backdrop-blur-sm transition-opacity\" onClick={cancelTest}></div>\n <div className=\"inline-block align-bottom bg-white rounded-2xl text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-md sm:w-full border border-emerald-100/50\">\n <div className=\"bg-white px-6 pt-5 pb-4 sm:p-6\">\n <div className=\"mb-5\">\n <h3 className=\"text-base font-bold text-slate-800 mb-1\">测试连接</h3>\n <p className=\"text-xs text-slate-500\">选择一个模型进行连接测试</p>\n </div>\n <div className=\"space-y-4\">\n <div>\n <label className=\"block text-xs font-semibold text-slate-700 mb-1.5\">搜索模型</label>\n <div className=\"relative\">\n <input\n type=\"text\"\n value={searchQuery}\n onChange={(e) => setSearchQuery(e.target.value)}\n disabled={testing}\n autoComplete=\"off\"\n className=\"block w-full rounded-lg border border-slate-200 bg-white/80 pl-9 pr-3 py-2 text-xs shadow-sm transition-all duration-300 focus:border-emerald-400 focus:ring-2 focus:ring-emerald-400/20 focus:ring-offset-1 disabled:opacity-50 disabled:cursor-not-allowed\"\n placeholder=\"输入模型名称或ID进行搜索...\"\n />\n <svg className=\"absolute left-3 top-1/2 -translate-y-1/2 w-3.5 h-3.5 text-slate-400\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z\" />\n </svg>\n </div>\n </div>\n <div>\n <label className=\"block text-xs font-semibold text-slate-700 mb-1.5\">\n 选择模型\n {getProviderModels(testingProviderId).length > 0 && (\n <span className=\"ml-2 text-[10px] text-slate-400 font-normal\">\n (共 {getProviderModels(testingProviderId).length} 个模型)\n </span>\n )}\n </label>\n <div className=\"border border-slate-200 rounded-lg bg-white/80 overflow-hidden\">\n <div className=\"max-h-[240px] overflow-y-auto scrollbar-thin scrollbar-thumb-slate-300 scrollbar-track-slate-100\">\n {getProviderModels(testingProviderId).length === 0 ? (\n <div className=\"px-3 py-6 text-center\">\n <p className=\"text-xs text-slate-400\">没有找到可用的模型</p>\n </div>\n ) : (\n getProviderModels(testingProviderId).map((model) => (\n <button\n key={model.id}\n type=\"button\"\n onClick={() => setSelectedModelId(model.id.toString())}\n disabled={testing}\n className={`w-full text-left px-3 py-2.5 text-xs font-medium border-b border-slate-100 last:border-0 hover:bg-emerald-50/50 transition-colors duration-200 disabled:opacity-50 disabled:cursor-not-allowed ${\n selectedModelId === model.id.toString()\n ? 'bg-emerald-100/50 text-emerald-700'\n : 'text-slate-700'\n }`}\n >\n <div>{model.name}</div>\n <div className=\"text-[10px] text-slate-400 mt-0.5\">{model.model_id}</div>\n </button>\n ))\n )}\n </div>\n </div>\n </div>\n </div>\n <div className=\"mt-5 flex items-center justify-end space-x-2\">\n <button\n type=\"button\"\n onClick={cancelTest}\n disabled={testing}\n className=\"px-3.5 py-1.5 border border-slate-200 rounded-lg text-xs font-semibold text-slate-600 bg-white hover:bg-slate-50 focus:outline-none focus:ring-2 focus:ring-offset-1 focus:ring-slate-400/30 transition-all duration-300 disabled:opacity-50 disabled:cursor-not-allowed\"\n >\n 取消\n </button>\n <button\n type=\"button\"\n onClick={startTest}\n disabled={testing || !selectedModelId}\n className=\"px-4 py-1.5 border border-transparent rounded-lg text-xs font-semibold text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-1 focus:ring-blue-500/50 transition-all duration-300 disabled:opacity-50 disabled:cursor-not-allowed inline-flex items-center\"\n >\n {testing ? (\n <>\n <svg className=\"animate-spin -ml-1 mr-2 h-3 w-3 text-white\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\">\n <circle className=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" strokeWidth=\"4\"></circle>\n <path className=\"opacity-75\" fill=\"currentColor\" d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"></path>\n </svg>\n 测试中...\n </>\n ) : (\n '开始测试'\n )}\n </button>\n </div>\n </div>\n </div>\n </div>\n </div>\n )}\n </>\n );\n}\n"],"names":["ProvidersPage","providers","setProviders","models","setModels","loading","setLoading","showModal","setShowModal","editing","setEditing","showConfirm","setShowConfirm","deleteId","setDeleteId","testingProviderId","setTestingProviderId","selectedModelId","setSelectedModelId","testing","setTesting","searchQuery","setSearchQuery","formData","setFormData","name","protocol","base_url","api_key","showApiKey","setShowApiKey","showToast","loadProviders","loadModels","res","fetch","data","json","error","console","loadProviderForEdit","id","ok","Error","handleSubmit","e","preventDefault","response","updateData","trim","method","headers","body","JSON","stringify","errorData","catch","errorMessage","message","handleEdit","provider","providerWithKey","handleDelete","confirmDelete","handleTestConnection","providerId","providerModels","filter","m","provider_id","length","startTest","model_id","parseInt","success","cancelTest","getProviderModels","enabled","query","toLowerCase","model","includes","className","onClick","fill","stroke","viewBox","strokeLinecap","strokeLinejoin","strokeWidth","d","colSpan","map","onSubmit","type","required","value","onChange","target","autoComplete","placeholder","tabIndex","open","title","onConfirm","onCancel","confirmText","cancelText","disabled","toString","xmlns","cx","cy","r"],"mappings":"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"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
module.exports=[43812,a=>{"use strict";var b=a.i(87924),c=a.i(72131),d=a.i(81844),e=a.i(21215);let f=[{value:"简体中文",label:"简体中文"},{value:"英文",label:"英文"},{value:"繁体中文",label:"繁体中文"},{value:"日语",label:"日语"},{value:"法语",label:"法语"},{value:"西班牙语",label:"西班牙语"}];function g({label:a,children:c}){return(0,b.jsxs)("label",{className:"block",children:[(0,b.jsx)("span",{className:"block text-xs font-semibold text-slate-700 mb-1.5",children:a}),c]})}function h({title:a,subtitle:c,language:d,text:e,onChange:f,result:g,accent:i}){return(0,b.jsxs)("section",{className:`backdrop-blur-sm shadow-md rounded-2xl border p-6 ${"emerald"===i?"border-emerald-100/60 bg-white/75":"border-amber-100/60 bg-white/75"}`,children:[(0,b.jsxs)("div",{className:"flex items-start justify-between gap-3",children:[(0,b.jsxs)("div",{children:[(0,b.jsx)("h2",{className:"text-sm font-bold text-slate-800",children:a}),(0,b.jsxs)("p",{className:"text-xs text-slate-500 mt-1",children:[d," · ",c]})]}),(0,b.jsx)("div",{className:`inline-flex items-center px-3 py-1.5 rounded-lg text-xs font-semibold shadow-sm ${"emerald"===i?"bg-emerald-600 hover:bg-emerald-700 text-white":"bg-amber-500 hover:bg-amber-600 text-white"}`,children:"emerald"===i?"Source":"Target"})]}),(0,b.jsx)("textarea",{value:e,onChange:a=>f(a.target.value),rows:8,placeholder:`请输入${d}文本`,className:"mt-4 block w-full rounded-xl border border-slate-200 bg-white/90 px-3 py-3 text-sm shadow-sm focus:border-emerald-400"}),g?(0,b.jsxs)("div",{className:"mt-4 rounded-xl border border-slate-200 bg-slate-50/80 p-4 space-y-4",children:[(0,b.jsxs)("div",{className:"grid grid-cols-3 gap-3",children:[(0,b.jsx)(l,{label:"输入",value:g.usage.input_tokens}),(0,b.jsx)(l,{label:"输出",value:g.usage.output_tokens}),(0,b.jsx)(l,{label:"总计",value:g.usage.total_tokens})]}),(0,b.jsxs)("div",{className:"flex items-center justify-between gap-2 text-[11px]",children:[(0,b.jsx)("span",{className:"font-medium text-slate-600",children:g.usage.estimated?"Estimated token usage":"Exact usage from provider response"}),(0,b.jsx)("span",{className:"text-slate-400",children:void 0!==g.response_time_ms?`${g.response_time_ms} ms`:"LLM 返回文本"})]}),(0,b.jsx)("pre",{className:"whitespace-pre-wrap break-words rounded-lg bg-white px-3 py-3 text-xs text-slate-700 border border-slate-200",children:g.text||"无返回文本"})]}):(0,b.jsx)("div",{className:"mt-4 rounded-xl border border-dashed border-slate-200 bg-slate-50/60 px-4 py-6 text-xs text-slate-400",children:"这里会展示 token 消耗和模型返回文本。"})]})}function i({label:a,value:c}){return(0,b.jsxs)("div",{className:"rounded-lg bg-slate-50 border border-slate-200 px-3 py-2",children:[(0,b.jsx)("div",{className:"text-[10px] text-slate-500",children:a}),(0,b.jsx)("div",{className:"mt-1 text-sm font-bold text-slate-800",children:c??"--"})]})}function j({title:a,content:c}){return(0,b.jsxs)("div",{className:"rounded-lg border border-slate-200 bg-slate-50/70 p-3",children:[(0,b.jsx)("div",{className:"text-[11px] font-semibold text-slate-600",children:a}),(0,b.jsx)("pre",{className:"mt-2 whitespace-pre-wrap break-words text-xs text-slate-700 max-h-40 overflow-auto",children:c||"无内容"})]})}function k(a){if(!a)return"等待结果";let b=a.usage.estimated?"estimated":"exact";return void 0!==a.response_time_ms?`${b} \xb7 ${a.response_time_ms} ms`:b}function l({label:a,value:c}){return(0,b.jsxs)("div",{className:"rounded-lg bg-white border border-slate-200 px-3 py-3",children:[(0,b.jsxs)("div",{className:"text-[11px] text-slate-500",children:[a," token"]}),(0,b.jsx)("div",{className:"mt-1 text-lg font-bold text-slate-800",children:c})]})}function m({title:a,value:c,note:d,signed:e=!1,suffix:f}){let g=null==c?"--":e&&c>0?`+${c}${f?` ${f}`:""}`:`${c}${f?` ${f}`:""}`;return(0,b.jsxs)("div",{className:"rounded-xl border border-slate-200 bg-slate-50/80 p-4",children:[(0,b.jsx)("div",{className:"text-xs font-semibold text-slate-600",children:a}),(0,b.jsx)("div",{className:"mt-2 text-2xl font-bold text-slate-800",children:g}),(0,b.jsx)("div",{className:"mt-1 text-[11px] text-slate-400",children:d})]})}a.s(["default",0,function(){let[a,l]=(0,c.useState)("test"),[n,o]=(0,c.useState)([]),[p,q]=(0,c.useState)(!0),[r,s]=(0,c.useState)(null),[t,u]=(0,c.useState)(""),[v,w]=(0,c.useState)("简体中文"),[x,y]=(0,c.useState)("英文"),[z,A]=(0,c.useState)("both"),[B,C]=(0,c.useState)("0"),[D,E]=(0,c.useState)("1"),[F,G]=(0,c.useState)(""),[H,I]=(0,c.useState)(""),[J,K]=(0,c.useState)(null),[L,M]=(0,c.useState)(null),[N,O]=(0,c.useState)(null),[P,Q]=(0,c.useState)(null),[R,S]=(0,c.useState)([]),[T,U]=(0,c.useState)(!1),{showToast:V}=(0,e.useToast)();(0,c.useEffect)(()=>{X()},[]),(0,c.useEffect)(()=>{"history"===a&&Y()},[a]);let W=(0,c.useMemo)(()=>n.find(a=>a.id===Number(t))||null,[n,t]),X=async()=>{try{let a=await fetch("/api/models?enabled=true"),b=await a.json();o(Array.isArray(b)?b:[])}catch(a){console.error("Failed to load tokenizer models:",a),V("模型加载失败","error")}finally{q(!1)}},Y=async()=>{U(!0);try{let a=await fetch("/api/tokenizer/history?limit=50"),b=await a.json();if(!a.ok)throw Error(b.error||"历史记录加载失败");S(Array.isArray(b.logs)?b.logs:[])}catch(a){console.error("Failed to load tokenizer history:",a),V(a.message||"历史记录加载失败","error")}finally{U(!1)}},Z=!!t,$=Number(B),_=Number(D),aa=a=>({model_id:Number(t),mode:a.mode,source_language:a.sourceLanguage,target_language:a.targetLanguage,text:a.text,temperature:Number.isFinite($)?$:0,top_p:Number.isFinite(_)?_:1}),ab=async(a,b,c)=>{if(!Z)return V("请先选择模型","error"),null;if(!b.trim())return V("source"===a?"请输入源语言文本":"请输入目标语言文本","error"),null;try{let d=await fetch("/api/tokenizer/test",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(aa({mode:"measure",sourceLanguage:c,text:b}))}),e=await d.json();if(!d.ok)throw Error(e.error||"测试失败");let f={text:e.text||"",usage:e.usage,response_time_ms:e.response_time_ms};return"source"===a?K(f):M(f),V("source"===a?"源语言测试完成":"目标语言测试完成","success"),f}catch(a){return console.error("Tokenizer measure failed:",a),V(a.message||"测试失败","error"),null}},ac=async()=>{if(!Z)return void V("请先选择模型","error");if(!F.trim())return void V("请输入源语言文本","error");s("translate");try{let a=await fetch("/api/tokenizer/test",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(aa({mode:"translate",sourceLanguage:v,targetLanguage:x,text:F}))}),b=await a.json();if(!a.ok)throw Error(b.error||"翻译失败");I(b.text||""),O(b.usage||null),Q(b.response_time_ms||null),M(null),await Y(),V("翻译完成,已填入目标语言文本","success")}catch(a){console.error("Tokenizer translate failed:",a),V(a.message||"翻译失败","error")}finally{s(null)}},ad=async()=>{if(!Z)return void V("请先选择模型","error");if("target"!==z&&!F.trim())return void V("请输入源语言文本","error");if("source"!==z&&!H.trim())return void V("请输入目标语言文本","error");s("test");try{if("source"===z){await ab("source",F,v),M(null),await Y();return}if("target"===z){await ab("target",H,x),K(null),await Y();return}let a=fetch("/api/tokenizer/test",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(aa({mode:"measure",sourceLanguage:v,text:F}))}),b=fetch("/api/tokenizer/test",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(aa({mode:"measure",sourceLanguage:x,text:H}))}),[c,d]=await Promise.all([a,b]),[e,f]=await Promise.all([c.json(),d.json()]);if(!c.ok)throw Error(e.error||"源语言测试失败");if(!d.ok)throw Error(f.error||"目标语言测试失败");K({text:e.text||"",usage:e.usage,response_time_ms:e.response_time_ms}),M({text:f.text||"",usage:f.usage,response_time_ms:f.response_time_ms}),await Y(),V("双语言测试完成","success")}catch(a){console.error("Tokenizer compare failed:",a),V(a.message||"测试失败","error")}finally{s(null)}},ae=J&&L?L.usage.total_tokens-J.usage.total_tokens:null;return(J?.response_time_ms,L?.response_time_ms,p)?(0,b.jsxs)(b.Fragment,{children:[(0,b.jsx)(d.default,{}),(0,b.jsx)("div",{className:"min-h-screen flex items-center justify-center",children:(0,b.jsx)("div",{className:"text-lg",children:"加载中..."})})]}):(0,b.jsxs)(b.Fragment,{children:[(0,b.jsx)(d.default,{}),(0,b.jsx)("main",{className:"max-w-6xl mx-auto py-6 sm:px-6 lg:px-8",children:(0,b.jsxs)("div",{className:"px-4 py-4 sm:px-0 space-y-5",children:[(0,b.jsxs)("div",{className:"inline-flex rounded-xl border border-slate-200 bg-white/80 p-1 shadow-sm",children:[(0,b.jsx)("button",{onClick:()=>l("test"),className:`rounded-lg px-4 py-2 text-xs font-semibold transition-colors ${"test"===a?"bg-emerald-600 text-white":"text-slate-600 hover:bg-slate-100"}`,children:"开始测试"}),(0,b.jsx)("button",{onClick:()=>l("history"),className:`rounded-lg px-4 py-2 text-xs font-semibold transition-colors ${"history"===a?"bg-emerald-600 text-white":"text-slate-600 hover:bg-slate-100"}`,children:"历史记录"})]}),"test"===a?(0,b.jsxs)(b.Fragment,{children:[(0,b.jsxs)("section",{className:"bg-white/75 backdrop-blur-sm shadow-md rounded-2xl border border-emerald-100/60 p-6",children:[(0,b.jsxs)("div",{className:"flex flex-col gap-4 lg:flex-row lg:items-end lg:justify-between",children:[(0,b.jsxs)("div",{children:[(0,b.jsx)("h1",{className:"text-lg font-bold text-slate-800",children:"Tokenizer"}),(0,b.jsx)("p",{className:"text-xs text-slate-500 mt-1",children:"选择模型后,可以先翻译,再默认一键测试两种语言的 token 消耗。"})]}),(0,b.jsxs)("div",{className:"grid grid-cols-1 gap-3 sm:grid-cols-3 lg:min-w-[620px]",children:[(0,b.jsx)(g,{label:"模型",children:(0,b.jsxs)("select",{value:t,onChange:a=>u(a.target.value),className:"block w-full rounded-lg border border-slate-200 bg-white/90 px-3 py-2 text-xs shadow-sm focus:border-emerald-400",children:[(0,b.jsx)("option",{value:"",children:"请选择模型"}),n.map(a=>(0,b.jsxs)("option",{value:a.id,children:[a.provider_name?`${a.provider_name} / `:"",a.name]},a.id))]})}),(0,b.jsx)(g,{label:"源语言",children:(0,b.jsx)("select",{value:v,onChange:a=>w(a.target.value),className:"block w-full rounded-lg border border-slate-200 bg-white/90 px-3 py-2 text-xs shadow-sm focus:border-emerald-400",children:f.map(a=>(0,b.jsx)("option",{value:a.value,children:a.label},a.value))})}),(0,b.jsx)(g,{label:"目标语言",children:(0,b.jsx)("select",{value:x,onChange:a=>y(a.target.value),className:"block w-full rounded-lg border border-slate-200 bg-white/90 px-3 py-2 text-xs shadow-sm focus:border-emerald-400",children:f.map(a=>(0,b.jsx)("option",{value:a.value,children:a.label},a.value))})})]})]}),W&&(0,b.jsxs)("div",{className:"mt-4 flex flex-wrap items-center gap-2 text-[11px] text-slate-500",children:[(0,b.jsx)("span",{className:"rounded-full bg-emerald-50 px-2.5 py-1 font-medium text-emerald-700",children:W.provider_name||"Provider"}),(0,b.jsx)("span",{className:"rounded-full bg-slate-100 px-2.5 py-1 font-medium text-slate-600",children:W.model_id})]}),(0,b.jsxs)("div",{className:"mt-5 rounded-2xl border border-slate-200 bg-gradient-to-r from-emerald-50/80 via-white to-amber-50/60 p-5",children:[(0,b.jsxs)("div",{className:"flex flex-col gap-4 xl:flex-row xl:items-end xl:justify-between",children:[(0,b.jsxs)("div",{children:[(0,b.jsx)("h2",{className:"text-sm font-bold text-slate-800",children:"翻译与对比"}),(0,b.jsx)("p",{className:"text-xs text-slate-500 mt-1",children:"测试模式默认是全部测试;如果只想测一侧,可以先切换范围再执行。"})]}),(0,b.jsxs)("div",{className:"grid grid-cols-1 gap-3 sm:grid-cols-3 xl:min-w-[520px]",children:[(0,b.jsx)(g,{label:"测试范围",children:(0,b.jsxs)("select",{value:z,onChange:a=>A(a.target.value),className:"block w-full rounded-lg border border-slate-200 bg-white/90 px-3 py-2 text-xs shadow-sm focus:border-emerald-400",children:[(0,b.jsx)("option",{value:"both",children:"全部测试"}),(0,b.jsx)("option",{value:"source",children:"仅源语言"}),(0,b.jsx)("option",{value:"target",children:"仅目标语言"})]})}),(0,b.jsx)(g,{label:"Temperature",children:(0,b.jsx)("input",{type:"number",step:"0.1",min:"0",max:"2",value:B,onChange:a=>C(a.target.value),className:"block w-full rounded-lg border border-slate-200 bg-white/90 px-3 py-2 text-xs shadow-sm focus:border-emerald-400"})}),(0,b.jsx)(g,{label:"Top P",children:(0,b.jsx)("input",{type:"number",step:"0.1",min:"0",max:"1",value:D,onChange:a=>E(a.target.value),className:"block w-full rounded-lg border border-slate-200 bg-white/90 px-3 py-2 text-xs shadow-sm focus:border-emerald-400"})})]})]}),(0,b.jsxs)("div",{className:"mt-4 flex flex-wrap gap-2",children:[(0,b.jsx)("button",{onClick:ac,disabled:!Z||null!==r,className:"inline-flex items-center px-3.5 py-1.5 rounded-lg text-xs font-semibold text-white bg-emerald-600 hover:bg-emerald-700 shadow-sm",children:"translate"===r?"翻译中...":`翻译为${x}`}),(0,b.jsx)("button",{onClick:ad,disabled:!Z||null!==r,className:"inline-flex items-center px-3.5 py-1.5 rounded-lg text-xs font-semibold text-emerald-700 bg-white hover:bg-emerald-50 border border-emerald-200 shadow-sm",children:"test"===r?"测试中...":"both"===z?"开始全部测试":"source"===z?"开始源语言测试":"开始目标语言测试"})]}),(0,b.jsxs)("div",{className:"mt-4 grid grid-cols-1 gap-4 lg:grid-cols-3",children:[(0,b.jsx)(m,{title:"源语言总计",value:J?.usage.total_tokens,note:k(J),signed:!1}),(0,b.jsx)(m,{title:"目标语言总计",value:L?.usage.total_tokens,note:k(L),signed:!1}),(0,b.jsx)(m,{title:"差值",value:ae,note:null===ae?"等待两侧结果":ae>=0?"目标语言更高":"源语言更高",signed:!0})]}),N&&(0,b.jsx)("div",{className:"mt-4 rounded-xl border border-slate-200 bg-slate-50/80 p-4",children:(0,b.jsxs)("div",{className:"flex items-center justify-between gap-3",children:[(0,b.jsxs)("div",{children:[(0,b.jsx)("div",{className:"text-xs font-semibold text-slate-700",children:"最近一次翻译消耗"}),(0,b.jsx)("div",{className:"text-[11px] text-slate-500 mt-1",children:N.estimated?"Estimated token usage":"Exact usage from provider response"})]}),(0,b.jsxs)("div",{className:"text-right",children:[(0,b.jsx)("div",{className:"text-lg font-bold text-slate-800",children:N.total_tokens}),(0,b.jsxs)("div",{className:"text-[11px] text-slate-500",children:["Total tokens",null!==P?` \xb7 ${P} ms`:""]})]})]})})]})]}),(0,b.jsxs)("section",{className:"grid grid-cols-1 gap-5 xl:grid-cols-2",children:[(0,b.jsx)(h,{title:"源语言输入",subtitle:"原文输入区",language:v,text:F,onChange:G,result:J,accent:"emerald"}),(0,b.jsx)(h,{title:"目标语言输入",subtitle:"可手动输入,或使用翻译结果",language:x,text:H,onChange:I,result:L,accent:"amber"})]})]}):(0,b.jsxs)("section",{className:"bg-white/75 backdrop-blur-sm shadow-md rounded-2xl border border-emerald-100/60 p-6",children:[(0,b.jsxs)("div",{className:"flex items-center justify-between gap-3",children:[(0,b.jsxs)("div",{children:[(0,b.jsx)("h2",{className:"text-sm font-bold text-slate-800",children:"历史记录"}),(0,b.jsx)("p",{className:"text-xs text-slate-500 mt-1",children:"展示最近 50 条 Tokenizer 调用记录,包括模式、token、耗时和文本摘要。"})]}),(0,b.jsx)("button",{onClick:Y,disabled:T,className:"inline-flex items-center px-3.5 py-1.5 rounded-lg text-xs font-semibold text-emerald-700 bg-emerald-50 hover:bg-emerald-100 border border-emerald-200",children:T?"刷新中...":"刷新"})]}),(0,b.jsx)("div",{className:"mt-5 space-y-3",children:0===R.length?(0,b.jsx)("div",{className:"rounded-xl border border-dashed border-slate-200 bg-slate-50/60 px-4 py-10 text-center text-xs text-slate-400",children:"暂无测试记录"}):R.map(a=>{var c;let d;return(0,b.jsxs)("article",{className:"rounded-xl border border-slate-200 bg-white/90 p-4",children:[(0,b.jsxs)("div",{className:"flex flex-col gap-3 lg:flex-row lg:items-start lg:justify-between",children:[(0,b.jsxs)("div",{className:"space-y-2",children:[(0,b.jsxs)("div",{className:"flex flex-wrap items-center gap-2 text-[11px]",children:[(0,b.jsx)("span",{className:"rounded-full bg-emerald-50 px-2.5 py-1 font-medium text-emerald-700",children:"translate"===a.mode?"翻译":"测试"}),a.provider_name&&(0,b.jsx)("span",{className:"rounded-full bg-slate-100 px-2.5 py-1 font-medium text-slate-600",children:a.provider_name}),a.model_id&&(0,b.jsx)("span",{className:"rounded-full bg-slate-100 px-2.5 py-1 font-medium text-slate-600",children:a.model_id}),(0,b.jsx)("span",{className:"text-slate-400",children:Number.isNaN((d=new Date(c=a.created_at)).getTime())?c:new Intl.DateTimeFormat("zh-CN",{month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit"}).format(d)})]}),(0,b.jsxs)("div",{className:"text-xs text-slate-600",children:[a.source_language||"--",a.target_language?` -> ${a.target_language}`:"",null!==a.response_time_ms?` \xb7 ${a.response_time_ms} ms`:"",a.usage?.estimated?" · estimated":" · exact"]})]}),(0,b.jsxs)("div",{className:"grid grid-cols-3 gap-2 min-w-[220px]",children:[(0,b.jsx)(i,{label:"输入",value:a.usage?.input_tokens}),(0,b.jsx)(i,{label:"输出",value:a.usage?.output_tokens}),(0,b.jsx)(i,{label:"总计",value:a.usage?.total_tokens})]})]}),(0,b.jsxs)("div",{className:"mt-4 grid grid-cols-1 gap-3 xl:grid-cols-2",children:[(0,b.jsx)(j,{title:"请求文本",content:a.source_text}),(0,b.jsx)(j,{title:"返回文本",content:a.result_text})]})]},a.id)})})]})]})})]})}])}];
|
|
2
|
+
|
|
3
|
+
//# sourceMappingURL=src_app_tokenizer_page_tsx_0eqhpbs._.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/app/tokenizer/page.tsx"],"sourcesContent":["'use client';\n\nimport { useEffect, useMemo, useState } from 'react';\nimport Nav from '../components/Nav';\nimport { useToast } from '../components/ToastProvider';\n\ninterface ModelOption {\n id: number;\n provider_id: number;\n name: string;\n model_id: string;\n enabled: boolean;\n provider_name?: string;\n protocol?: string;\n}\n\ninterface Usage {\n input_tokens: number;\n output_tokens: number;\n total_tokens: number;\n estimated: boolean;\n}\n\ninterface TestResult {\n text: string;\n usage: Usage;\n response_time_ms?: number;\n}\n\ninterface HistoryItem {\n id: number;\n created_at: string;\n status: number;\n response_time_ms: number | null;\n mode: 'measure' | 'translate' | null;\n source_language: string | null;\n target_language: string | null;\n source_text: string;\n result_text: string;\n usage: Usage | null;\n model_name: string | null;\n model_id: string | null;\n provider_name: string | null;\n}\n\nconst LANGUAGES = [\n { value: '简体中文', label: '简体中文' },\n { value: '英文', label: '英文' },\n { value: '繁体中文', label: '繁体中文' },\n { value: '日语', label: '日语' },\n { value: '法语', label: '法语' },\n { value: '西班牙语', label: '西班牙语' },\n];\n\nexport default function TokenizerPage() {\n const [activeTab, setActiveTab] = useState<'test' | 'history'>('test');\n const [models, setModels] = useState<ModelOption[]>([]);\n const [loading, setLoading] = useState(true);\n const [submitting, setSubmitting] = useState<'test' | 'translate' | null>(null);\n const [selectedModelId, setSelectedModelId] = useState('');\n const [sourceLanguage, setSourceLanguage] = useState('简体中文');\n const [targetLanguage, setTargetLanguage] = useState('英文');\n const [testScope, setTestScope] = useState<'both' | 'source' | 'target'>('both');\n const [temperature, setTemperature] = useState('0');\n const [topP, setTopP] = useState('1');\n const [sourceText, setSourceText] = useState('');\n const [targetText, setTargetText] = useState('');\n const [sourceResult, setSourceResult] = useState<TestResult | null>(null);\n const [targetResult, setTargetResult] = useState<TestResult | null>(null);\n const [translationUsage, setTranslationUsage] = useState<Usage | null>(null);\n const [translationTimeMs, setTranslationTimeMs] = useState<number | null>(null);\n const [historyItems, setHistoryItems] = useState<HistoryItem[]>([]);\n const [historyLoading, setHistoryLoading] = useState(false);\n const { showToast } = useToast();\n\n useEffect(() => {\n loadModels();\n }, []);\n\n useEffect(() => {\n if (activeTab === 'history') {\n loadHistory();\n }\n }, [activeTab]);\n\n const selectedModel = useMemo(\n () => models.find((model) => model.id === Number(selectedModelId)) || null,\n [models, selectedModelId]\n );\n\n const loadModels = async () => {\n try {\n const res = await fetch('/api/models?enabled=true');\n const data = await res.json();\n setModels(Array.isArray(data) ? data : []);\n } catch (error) {\n console.error('Failed to load tokenizer models:', error);\n showToast('模型加载失败', 'error');\n } finally {\n setLoading(false);\n }\n };\n\n const loadHistory = async () => {\n setHistoryLoading(true);\n try {\n const res = await fetch('/api/tokenizer/history?limit=50');\n const data = await res.json();\n if (!res.ok) {\n throw new Error(data.error || '历史记录加载失败');\n }\n setHistoryItems(Array.isArray(data.logs) ? data.logs : []);\n } catch (error: any) {\n console.error('Failed to load tokenizer history:', error);\n showToast(error.message || '历史记录加载失败', 'error');\n } finally {\n setHistoryLoading(false);\n }\n };\n\n const canSubmit = Boolean(selectedModelId);\n const parsedTemperature = Number(temperature);\n const parsedTopP = Number(topP);\n\n const createRequestBody = (payload: {\n mode: 'measure' | 'translate';\n text: string;\n sourceLanguage: string;\n targetLanguage?: string;\n }) => ({\n model_id: Number(selectedModelId),\n mode: payload.mode,\n source_language: payload.sourceLanguage,\n target_language: payload.targetLanguage,\n text: payload.text,\n temperature: Number.isFinite(parsedTemperature) ? parsedTemperature : 0,\n top_p: Number.isFinite(parsedTopP) ? parsedTopP : 1,\n });\n\n const runMeasure = async (side: 'source' | 'target', text: string, language: string) => {\n if (!canSubmit) {\n showToast('请先选择模型', 'error');\n return null;\n }\n\n if (!text.trim()) {\n showToast(side === 'source' ? '请输入源语言文本' : '请输入目标语言文本', 'error');\n return null;\n }\n\n try {\n const res = await fetch('/api/tokenizer/test', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(\n createRequestBody({\n mode: 'measure',\n sourceLanguage: language,\n text,\n })\n ),\n });\n\n const data = await res.json();\n if (!res.ok) {\n throw new Error(data.error || '测试失败');\n }\n\n const result = {\n text: data.text || '',\n usage: data.usage,\n response_time_ms: data.response_time_ms,\n } satisfies TestResult;\n\n if (side === 'source') {\n setSourceResult(result);\n } else {\n setTargetResult(result);\n }\n\n showToast(side === 'source' ? '源语言测试完成' : '目标语言测试完成', 'success');\n return result;\n } catch (error: any) {\n console.error('Tokenizer measure failed:', error);\n showToast(error.message || '测试失败', 'error');\n return null;\n }\n };\n\n const handleTranslate = async () => {\n if (!canSubmit) {\n showToast('请先选择模型', 'error');\n return;\n }\n\n if (!sourceText.trim()) {\n showToast('请输入源语言文本', 'error');\n return;\n }\n\n setSubmitting('translate');\n try {\n const res = await fetch('/api/tokenizer/test', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(\n createRequestBody({\n mode: 'translate',\n sourceLanguage,\n targetLanguage,\n text: sourceText,\n })\n ),\n });\n\n const data = await res.json();\n if (!res.ok) {\n throw new Error(data.error || '翻译失败');\n }\n\n setTargetText(data.text || '');\n setTranslationUsage(data.usage || null);\n setTranslationTimeMs(data.response_time_ms || null);\n setTargetResult(null);\n await loadHistory();\n showToast('翻译完成,已填入目标语言文本', 'success');\n } catch (error: any) {\n console.error('Tokenizer translate failed:', error);\n showToast(error.message || '翻译失败', 'error');\n } finally {\n setSubmitting(null);\n }\n };\n\n const handleRunTests = async () => {\n if (!canSubmit) {\n showToast('请先选择模型', 'error');\n return;\n }\n\n if (testScope !== 'target' && !sourceText.trim()) {\n showToast('请输入源语言文本', 'error');\n return;\n }\n\n if (testScope !== 'source' && !targetText.trim()) {\n showToast('请输入目标语言文本', 'error');\n return;\n }\n\n setSubmitting('test');\n try {\n if (testScope === 'source') {\n await runMeasure('source', sourceText, sourceLanguage);\n setTargetResult(null);\n await loadHistory();\n return;\n }\n\n if (testScope === 'target') {\n await runMeasure('target', targetText, targetLanguage);\n setSourceResult(null);\n await loadHistory();\n return;\n }\n\n const sourcePromise = fetch('/api/tokenizer/test', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(\n createRequestBody({\n mode: 'measure',\n sourceLanguage,\n text: sourceText,\n })\n ),\n });\n\n const targetPromise = fetch('/api/tokenizer/test', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(\n createRequestBody({\n mode: 'measure',\n sourceLanguage: targetLanguage,\n text: targetText,\n })\n ),\n });\n\n const [sourceRes, targetRes] = await Promise.all([sourcePromise, targetPromise]);\n const [sourceData, targetData] = await Promise.all([sourceRes.json(), targetRes.json()]);\n\n if (!sourceRes.ok) {\n throw new Error(sourceData.error || '源语言测试失败');\n }\n\n if (!targetRes.ok) {\n throw new Error(targetData.error || '目标语言测试失败');\n }\n\n setSourceResult({\n text: sourceData.text || '',\n usage: sourceData.usage,\n response_time_ms: sourceData.response_time_ms,\n });\n setTargetResult({\n text: targetData.text || '',\n usage: targetData.usage,\n response_time_ms: targetData.response_time_ms,\n });\n await loadHistory();\n showToast('双语言测试完成', 'success');\n } catch (error: any) {\n console.error('Tokenizer compare failed:', error);\n showToast(error.message || '测试失败', 'error');\n } finally {\n setSubmitting(null);\n }\n };\n\n const usageDelta =\n sourceResult && targetResult\n ? targetResult.usage.total_tokens - sourceResult.usage.total_tokens\n : null;\n const compareTimeMs =\n (sourceResult?.response_time_ms || 0) + (targetResult?.response_time_ms || 0);\n\n if (loading) {\n return (\n <>\n <Nav />\n <div className=\"min-h-screen flex items-center justify-center\">\n <div className=\"text-lg\">加载中...</div>\n </div>\n </>\n );\n }\n\n return (\n <>\n <Nav />\n <main className=\"max-w-6xl mx-auto py-6 sm:px-6 lg:px-8\">\n <div className=\"px-4 py-4 sm:px-0 space-y-5\">\n <div className=\"inline-flex rounded-xl border border-slate-200 bg-white/80 p-1 shadow-sm\">\n <button\n onClick={() => setActiveTab('test')}\n className={`rounded-lg px-4 py-2 text-xs font-semibold transition-colors ${\n activeTab === 'test'\n ? 'bg-emerald-600 text-white'\n : 'text-slate-600 hover:bg-slate-100'\n }`}\n >\n 开始测试\n </button>\n <button\n onClick={() => setActiveTab('history')}\n className={`rounded-lg px-4 py-2 text-xs font-semibold transition-colors ${\n activeTab === 'history'\n ? 'bg-emerald-600 text-white'\n : 'text-slate-600 hover:bg-slate-100'\n }`}\n >\n 历史记录\n </button>\n </div>\n\n {activeTab === 'test' ? (\n <>\n <section className=\"bg-white/75 backdrop-blur-sm shadow-md rounded-2xl border border-emerald-100/60 p-6\">\n <div className=\"flex flex-col gap-4 lg:flex-row lg:items-end lg:justify-between\">\n <div>\n <h1 className=\"text-lg font-bold text-slate-800\">Tokenizer</h1>\n <p className=\"text-xs text-slate-500 mt-1\">\n 选择模型后,可以先翻译,再默认一键测试两种语言的 token 消耗。\n </p>\n </div>\n <div className=\"grid grid-cols-1 gap-3 sm:grid-cols-3 lg:min-w-[620px]\">\n <Field label=\"模型\">\n <select\n value={selectedModelId}\n onChange={(e) => setSelectedModelId(e.target.value)}\n className=\"block w-full rounded-lg border border-slate-200 bg-white/90 px-3 py-2 text-xs shadow-sm focus:border-emerald-400\"\n >\n <option value=\"\">请选择模型</option>\n {models.map((model) => (\n <option key={model.id} value={model.id}>\n {model.provider_name ? `${model.provider_name} / ` : ''}\n {model.name}\n </option>\n ))}\n </select>\n </Field>\n <Field label=\"源语言\">\n <select\n value={sourceLanguage}\n onChange={(e) => setSourceLanguage(e.target.value)}\n className=\"block w-full rounded-lg border border-slate-200 bg-white/90 px-3 py-2 text-xs shadow-sm focus:border-emerald-400\"\n >\n {LANGUAGES.map((language) => (\n <option key={language.value} value={language.value}>\n {language.label}\n </option>\n ))}\n </select>\n </Field>\n <Field label=\"目标语言\">\n <select\n value={targetLanguage}\n onChange={(e) => setTargetLanguage(e.target.value)}\n className=\"block w-full rounded-lg border border-slate-200 bg-white/90 px-3 py-2 text-xs shadow-sm focus:border-emerald-400\"\n >\n {LANGUAGES.map((language) => (\n <option key={language.value} value={language.value}>\n {language.label}\n </option>\n ))}\n </select>\n </Field>\n </div>\n </div>\n\n {selectedModel && (\n <div className=\"mt-4 flex flex-wrap items-center gap-2 text-[11px] text-slate-500\">\n <span className=\"rounded-full bg-emerald-50 px-2.5 py-1 font-medium text-emerald-700\">\n {selectedModel.provider_name || 'Provider'}\n </span>\n <span className=\"rounded-full bg-slate-100 px-2.5 py-1 font-medium text-slate-600\">\n {selectedModel.model_id}\n </span>\n </div>\n )}\n\n <div className=\"mt-5 rounded-2xl border border-slate-200 bg-gradient-to-r from-emerald-50/80 via-white to-amber-50/60 p-5\">\n <div className=\"flex flex-col gap-4 xl:flex-row xl:items-end xl:justify-between\">\n <div>\n <h2 className=\"text-sm font-bold text-slate-800\">翻译与对比</h2>\n <p className=\"text-xs text-slate-500 mt-1\">\n 测试模式默认是全部测试;如果只想测一侧,可以先切换范围再执行。\n </p>\n </div>\n <div className=\"grid grid-cols-1 gap-3 sm:grid-cols-3 xl:min-w-[520px]\">\n <Field label=\"测试范围\">\n <select\n value={testScope}\n onChange={(e) => setTestScope(e.target.value as 'both' | 'source' | 'target')}\n className=\"block w-full rounded-lg border border-slate-200 bg-white/90 px-3 py-2 text-xs shadow-sm focus:border-emerald-400\"\n >\n <option value=\"both\">全部测试</option>\n <option value=\"source\">仅源语言</option>\n <option value=\"target\">仅目标语言</option>\n </select>\n </Field>\n <Field label=\"Temperature\">\n <input\n type=\"number\"\n step=\"0.1\"\n min=\"0\"\n max=\"2\"\n value={temperature}\n onChange={(e) => setTemperature(e.target.value)}\n className=\"block w-full rounded-lg border border-slate-200 bg-white/90 px-3 py-2 text-xs shadow-sm focus:border-emerald-400\"\n />\n </Field>\n <Field label=\"Top P\">\n <input\n type=\"number\"\n step=\"0.1\"\n min=\"0\"\n max=\"1\"\n value={topP}\n onChange={(e) => setTopP(e.target.value)}\n className=\"block w-full rounded-lg border border-slate-200 bg-white/90 px-3 py-2 text-xs shadow-sm focus:border-emerald-400\"\n />\n </Field>\n </div>\n </div>\n\n <div className=\"mt-4 flex flex-wrap gap-2\">\n <button\n onClick={handleTranslate}\n disabled={!canSubmit || submitting !== null}\n className=\"inline-flex items-center px-3.5 py-1.5 rounded-lg text-xs font-semibold text-white bg-emerald-600 hover:bg-emerald-700 shadow-sm\"\n >\n {submitting === 'translate' ? '翻译中...' : `翻译为${targetLanguage}`}\n </button>\n <button\n onClick={handleRunTests}\n disabled={!canSubmit || submitting !== null}\n className=\"inline-flex items-center px-3.5 py-1.5 rounded-lg text-xs font-semibold text-emerald-700 bg-white hover:bg-emerald-50 border border-emerald-200 shadow-sm\"\n >\n {submitting === 'test'\n ? '测试中...'\n : testScope === 'both'\n ? '开始全部测试'\n : testScope === 'source'\n ? '开始源语言测试'\n : '开始目标语言测试'}\n </button>\n </div>\n\n <div className=\"mt-4 grid grid-cols-1 gap-4 lg:grid-cols-3\">\n <CompareCard\n title=\"源语言总计\"\n value={sourceResult?.usage.total_tokens}\n note={buildUsageNote(sourceResult)}\n signed={false}\n />\n <CompareCard\n title=\"目标语言总计\"\n value={targetResult?.usage.total_tokens}\n note={buildUsageNote(targetResult)}\n signed={false}\n />\n <CompareCard\n title=\"差值\"\n value={usageDelta}\n note={usageDelta === null ? '等待两侧结果' : usageDelta >= 0 ? '目标语言更高' : '源语言更高'}\n signed\n />\n </div>\n\n {translationUsage && (\n <div className=\"mt-4 rounded-xl border border-slate-200 bg-slate-50/80 p-4\">\n <div className=\"flex items-center justify-between gap-3\">\n <div>\n <div className=\"text-xs font-semibold text-slate-700\">最近一次翻译消耗</div>\n <div className=\"text-[11px] text-slate-500 mt-1\">\n {translationUsage.estimated ? 'Estimated token usage' : 'Exact usage from provider response'}\n </div>\n </div>\n <div className=\"text-right\">\n <div className=\"text-lg font-bold text-slate-800\">{translationUsage.total_tokens}</div>\n <div className=\"text-[11px] text-slate-500\">\n Total tokens{translationTimeMs !== null ? ` · ${translationTimeMs} ms` : ''}\n </div>\n </div>\n </div>\n </div>\n )}\n </div>\n </section>\n\n <section className=\"grid grid-cols-1 gap-5 xl:grid-cols-2\">\n <LanguagePanel\n title=\"源语言输入\"\n subtitle=\"原文输入区\"\n language={sourceLanguage}\n text={sourceText}\n onChange={setSourceText}\n result={sourceResult}\n accent=\"emerald\"\n />\n\n <LanguagePanel\n title=\"目标语言输入\"\n subtitle=\"可手动输入,或使用翻译结果\"\n language={targetLanguage}\n text={targetText}\n onChange={setTargetText}\n result={targetResult}\n accent=\"amber\"\n />\n </section>\n </>\n ) : (\n <section className=\"bg-white/75 backdrop-blur-sm shadow-md rounded-2xl border border-emerald-100/60 p-6\">\n <div className=\"flex items-center justify-between gap-3\">\n <div>\n <h2 className=\"text-sm font-bold text-slate-800\">历史记录</h2>\n <p className=\"text-xs text-slate-500 mt-1\">\n 展示最近 50 条 Tokenizer 调用记录,包括模式、token、耗时和文本摘要。\n </p>\n </div>\n <button\n onClick={loadHistory}\n disabled={historyLoading}\n className=\"inline-flex items-center px-3.5 py-1.5 rounded-lg text-xs font-semibold text-emerald-700 bg-emerald-50 hover:bg-emerald-100 border border-emerald-200\"\n >\n {historyLoading ? '刷新中...' : '刷新'}\n </button>\n </div>\n\n <div className=\"mt-5 space-y-3\">\n {historyItems.length === 0 ? (\n <div className=\"rounded-xl border border-dashed border-slate-200 bg-slate-50/60 px-4 py-10 text-center text-xs text-slate-400\">\n 暂无测试记录\n </div>\n ) : (\n historyItems.map((item) => (\n <article key={item.id} className=\"rounded-xl border border-slate-200 bg-white/90 p-4\">\n <div className=\"flex flex-col gap-3 lg:flex-row lg:items-start lg:justify-between\">\n <div className=\"space-y-2\">\n <div className=\"flex flex-wrap items-center gap-2 text-[11px]\">\n <span className=\"rounded-full bg-emerald-50 px-2.5 py-1 font-medium text-emerald-700\">\n {item.mode === 'translate' ? '翻译' : '测试'}\n </span>\n {item.provider_name && (\n <span className=\"rounded-full bg-slate-100 px-2.5 py-1 font-medium text-slate-600\">\n {item.provider_name}\n </span>\n )}\n {item.model_id && (\n <span className=\"rounded-full bg-slate-100 px-2.5 py-1 font-medium text-slate-600\">\n {item.model_id}\n </span>\n )}\n <span className=\"text-slate-400\">{formatDateTime(item.created_at)}</span>\n </div>\n <div className=\"text-xs text-slate-600\">\n {item.source_language || '--'}\n {item.target_language ? ` -> ${item.target_language}` : ''}\n {item.response_time_ms !== null ? ` · ${item.response_time_ms} ms` : ''}\n {item.usage?.estimated ? ' · estimated' : ' · exact'}\n </div>\n </div>\n <div className=\"grid grid-cols-3 gap-2 min-w-[220px]\">\n <MiniMetric label=\"输入\" value={item.usage?.input_tokens} />\n <MiniMetric label=\"输出\" value={item.usage?.output_tokens} />\n <MiniMetric label=\"总计\" value={item.usage?.total_tokens} />\n </div>\n </div>\n\n <div className=\"mt-4 grid grid-cols-1 gap-3 xl:grid-cols-2\">\n <HistoryTextBlock title=\"请求文本\" content={item.source_text} />\n <HistoryTextBlock title=\"返回文本\" content={item.result_text} />\n </div>\n </article>\n ))\n )}\n </div>\n </section>\n )}\n </div>\n </main>\n </>\n );\n}\n\nfunction Field({\n label,\n children,\n}: {\n label: string;\n children: React.ReactNode;\n}) {\n return (\n <label className=\"block\">\n <span className=\"block text-xs font-semibold text-slate-700 mb-1.5\">{label}</span>\n {children}\n </label>\n );\n}\n\nfunction LanguagePanel({\n title,\n subtitle,\n language,\n text,\n onChange,\n result,\n accent,\n}: {\n title: string;\n subtitle: string;\n language: string;\n text: string;\n onChange: (value: string) => void;\n result: TestResult | null;\n accent: 'emerald' | 'amber';\n}) {\n const accentClass =\n accent === 'emerald'\n ? 'border-emerald-100/60 bg-white/75'\n : 'border-amber-100/60 bg-white/75';\n\n const buttonClass =\n accent === 'emerald'\n ? 'bg-emerald-600 hover:bg-emerald-700 text-white'\n : 'bg-amber-500 hover:bg-amber-600 text-white';\n\n return (\n <section className={`backdrop-blur-sm shadow-md rounded-2xl border p-6 ${accentClass}`}>\n <div className=\"flex items-start justify-between gap-3\">\n <div>\n <h2 className=\"text-sm font-bold text-slate-800\">{title}</h2>\n <p className=\"text-xs text-slate-500 mt-1\">\n {language} · {subtitle}\n </p>\n </div>\n <div className={`inline-flex items-center px-3 py-1.5 rounded-lg text-xs font-semibold shadow-sm ${buttonClass}`}>\n {accent === 'emerald' ? 'Source' : 'Target'}\n </div>\n </div>\n\n <textarea\n value={text}\n onChange={(e) => onChange(e.target.value)}\n rows={8}\n placeholder={`请输入${language}文本`}\n className=\"mt-4 block w-full rounded-xl border border-slate-200 bg-white/90 px-3 py-3 text-sm shadow-sm focus:border-emerald-400\"\n />\n\n {result ? (\n <div className=\"mt-4 rounded-xl border border-slate-200 bg-slate-50/80 p-4 space-y-4\">\n <div className=\"grid grid-cols-3 gap-3\">\n <MetricCard label=\"输入\" value={result.usage.input_tokens} />\n <MetricCard label=\"输出\" value={result.usage.output_tokens} />\n <MetricCard label=\"总计\" value={result.usage.total_tokens} />\n </div>\n <div className=\"flex items-center justify-between gap-2 text-[11px]\">\n <span className=\"font-medium text-slate-600\">\n {result.usage.estimated ? 'Estimated token usage' : 'Exact usage from provider response'}\n </span>\n <span className=\"text-slate-400\">\n {result.response_time_ms !== undefined ? `${result.response_time_ms} ms` : 'LLM 返回文本'}\n </span>\n </div>\n <pre className=\"whitespace-pre-wrap break-words rounded-lg bg-white px-3 py-3 text-xs text-slate-700 border border-slate-200\">\n {result.text || '无返回文本'}\n </pre>\n </div>\n ) : (\n <div className=\"mt-4 rounded-xl border border-dashed border-slate-200 bg-slate-50/60 px-4 py-6 text-xs text-slate-400\">\n 这里会展示 token 消耗和模型返回文本。\n </div>\n )}\n </section>\n );\n}\n\nfunction MiniMetric({ label, value }: { label: string; value: number | undefined }) {\n return (\n <div className=\"rounded-lg bg-slate-50 border border-slate-200 px-3 py-2\">\n <div className=\"text-[10px] text-slate-500\">{label}</div>\n <div className=\"mt-1 text-sm font-bold text-slate-800\">{value ?? '--'}</div>\n </div>\n );\n}\n\nfunction HistoryTextBlock({ title, content }: { title: string; content: string }) {\n return (\n <div className=\"rounded-lg border border-slate-200 bg-slate-50/70 p-3\">\n <div className=\"text-[11px] font-semibold text-slate-600\">{title}</div>\n <pre className=\"mt-2 whitespace-pre-wrap break-words text-xs text-slate-700 max-h-40 overflow-auto\">\n {content || '无内容'}\n </pre>\n </div>\n );\n}\n\nfunction formatDateTime(value: string) {\n const date = new Date(value);\n if (Number.isNaN(date.getTime())) {\n return value;\n }\n\n return new Intl.DateTimeFormat('zh-CN', {\n month: '2-digit',\n day: '2-digit',\n hour: '2-digit',\n minute: '2-digit',\n }).format(date);\n}\n\nfunction buildUsageNote(result: TestResult | null) {\n if (!result) {\n return '等待结果';\n }\n\n const base = result.usage.estimated ? 'estimated' : 'exact';\n return result.response_time_ms !== undefined\n ? `${base} · ${result.response_time_ms} ms`\n : base;\n}\n\nfunction MetricCard({ label, value }: { label: string; value: number }) {\n return (\n <div className=\"rounded-lg bg-white border border-slate-200 px-3 py-3\">\n <div className=\"text-[11px] text-slate-500\">{label} token</div>\n <div className=\"mt-1 text-lg font-bold text-slate-800\">{value}</div>\n </div>\n );\n}\n\nfunction CompareCard({\n title,\n value,\n note,\n signed = false,\n suffix,\n}: {\n title: string;\n value: number | null | undefined;\n note: string;\n signed?: boolean;\n suffix?: string;\n}) {\n const renderedValue =\n value === null || value === undefined\n ? '--'\n : signed && value > 0\n ? `+${value}${suffix ? ` ${suffix}` : ''}`\n : `${value}${suffix ? ` ${suffix}` : ''}`;\n\n return (\n <div className=\"rounded-xl border border-slate-200 bg-slate-50/80 p-4\">\n <div className=\"text-xs font-semibold text-slate-600\">{title}</div>\n <div className=\"mt-2 text-2xl font-bold text-slate-800\">{renderedValue}</div>\n <div className=\"mt-1 text-[11px] text-slate-400\">{note}</div>\n </div>\n );\n}\n"],"names":["LANGUAGES","value","label","TokenizerPage","activeTab","setActiveTab","models","setModels","loading","setLoading","submitting","setSubmitting","selectedModelId","setSelectedModelId","sourceLanguage","setSourceLanguage","targetLanguage","setTargetLanguage","testScope","setTestScope","temperature","setTemperature","topP","setTopP","sourceText","setSourceText","targetText","setTargetText","sourceResult","setSourceResult","targetResult","setTargetResult","translationUsage","setTranslationUsage","translationTimeMs","setTranslationTimeMs","historyItems","setHistoryItems","historyLoading","setHistoryLoading","showToast","loadModels","loadHistory","selectedModel","find","model","id","Number","res","fetch","data","json","Array","isArray","error","console","ok","Error","logs","message","canSubmit","Boolean","parsedTemperature","parsedTopP","createRequestBody","payload","model_id","mode","source_language","target_language","text","isFinite","top_p","runMeasure","side","language","trim","method","headers","body","JSON","stringify","result","usage","response_time_ms","handleTranslate","handleRunTests","sourcePromise","targetPromise","sourceRes","targetRes","Promise","all","sourceData","targetData","usageDelta","total_tokens","compareTimeMs","className","onClick","Field","onChange","e","target","map","provider_name","name","type","step","min","max","disabled","CompareCard","title","note","buildUsageNote","signed","estimated","LanguagePanel","subtitle","accent","length","item","formatDateTime","created_at","MiniMetric","input_tokens","output_tokens","HistoryTextBlock","content","source_text","result_text","children","accentClass","buttonClass","rows","placeholder","MetricCard","undefined","date","Date","isNaN","getTime","Intl","DateTimeFormat","month","day","hour","minute","format","base","suffix","renderedValue"],"mappings":"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"}
|
|
@@ -4,17 +4,17 @@ globalThis.__BUILD_MANIFEST = {
|
|
|
4
4
|
},
|
|
5
5
|
"devFiles": [],
|
|
6
6
|
"polyfillFiles": [
|
|
7
|
-
"static/chunks/
|
|
7
|
+
"static/chunks/03~yq9q893hmn.js"
|
|
8
|
+
],
|
|
9
|
+
"lowPriorityFiles": [
|
|
10
|
+
"static/XHnu7Z1vWSrgmneps8rX4/_buildManifest.js",
|
|
11
|
+
"static/XHnu7Z1vWSrgmneps8rX4/_ssgManifest.js",
|
|
12
|
+
"static/XHnu7Z1vWSrgmneps8rX4/_clientMiddlewareManifest.js"
|
|
8
13
|
],
|
|
9
|
-
"lowPriorityFiles": [],
|
|
10
14
|
"rootMainFiles": [
|
|
11
|
-
"static/chunks/
|
|
12
|
-
"static/chunks/
|
|
13
|
-
"static/chunks/
|
|
14
|
-
"static/chunks/turbopack-
|
|
15
|
+
"static/chunks/0bzupvr5gt3k9.js",
|
|
16
|
+
"static/chunks/0y3~cortx~or~.js",
|
|
17
|
+
"static/chunks/16g.ca89g7fib.js",
|
|
18
|
+
"static/chunks/turbopack-0griofc2i3wvs.js"
|
|
15
19
|
]
|
|
16
20
|
};
|
|
17
|
-
globalThis.__BUILD_MANIFEST.lowPriorityFiles = [
|
|
18
|
-
"/static/" + process.env.__NEXT_BUILD_ID + "/_buildManifest.js",
|
|
19
|
-
"/static/" + process.env.__NEXT_BUILD_ID + "/_ssgManifest.js"
|
|
20
|
-
];
|