@yina-npm/openrouterx 0.4.23 → 0.4.24
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/app/.next/BUILD_ID +1 -1
- package/app/.next/app-path-routes-manifest.json +2 -2
- package/app/.next/build-manifest.json +2 -2
- package/app/.next/server/app/(dashboard)/dashboard/admin/keys/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/admin/users/page.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/admin/users/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/basic-chat/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/cli-tools/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/combos/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/console-log/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/endpoint/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/media-providers/[kind]/[id]/page.js +11 -11
- package/app/.next/server/app/(dashboard)/dashboard/media-providers/[kind]/[id]/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/media-providers/[kind]/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/media-providers/combo/[id]/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/media-providers/web/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/mitm/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/page.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/profile/page.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/profile/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/providers/[id]/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/providers/new/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/providers/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/proxy-pools/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/quota/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/skills/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/translator/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/usage/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/(dashboard)/dashboard/user/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/_global-error.html +1 -1
- package/app/.next/server/app/_global-error.rsc +1 -1
- package/app/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/app/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/app/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/app/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/app/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/app/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/app/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/_not-found.html +1 -1
- package/app/.next/server/app/_not-found.rsc +4 -4
- package/app/.next/server/app/_not-found.segments/_full.segment.rsc +4 -4
- package/app/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/app/.next/server/app/_not-found.segments/_index.segment.rsc +4 -4
- package/app/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/app/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/app/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
- package/app/.next/server/app/api/auth/login/route.js +1 -1
- package/app/.next/server/app/api/auth/me/route.js +1 -1
- package/app/.next/server/app/api/cli-tools/antigravity-mitm/alias/route.js +1 -1
- package/app/.next/server/app/api/cli-tools/antigravity-mitm/test/route.js +1 -1
- package/app/.next/server/app/api/cli-tools/claude-settings/route.js +1 -1
- package/app/.next/server/app/api/cli-tools/codex-settings/route.js +2 -2
- package/app/.next/server/app/api/cli-tools/cowork-mcp-registry/route.js +1 -1
- package/app/.next/server/app/api/cli-tools/cowork-settings/route.js +1 -1
- package/app/.next/server/app/api/cli-tools/droid-settings/route.js +1 -1
- package/app/.next/server/app/api/cli-tools/hermes-settings/route.js +1 -1
- package/app/.next/server/app/api/cli-tools/openclaw-settings/route.js +1 -1
- package/app/.next/server/app/api/cli-tools/opencode-settings/route.js +1 -1
- package/app/.next/server/app/api/cloud/auth/route.js +1 -1
- package/app/.next/server/app/api/cloud/credentials/update/route.js +1 -1
- package/app/.next/server/app/api/cloud/model/resolve/route.js +1 -1
- package/app/.next/server/app/api/cloud/models/alias/route.js +1 -1
- package/app/.next/server/app/api/combos/[id]/route.js +1 -1
- package/app/.next/server/app/api/combos/route.js +1 -1
- package/app/.next/server/app/api/keys/[id]/route.js +1 -1
- package/app/.next/server/app/api/keys/route.js +1 -1
- package/app/.next/server/app/api/media-providers/tts/deepgram/voices/route.js +1 -1
- package/app/.next/server/app/api/media-providers/tts/elevenlabs/voices/route.js +1 -1
- package/app/.next/server/app/api/media-providers/tts/inworld/voices/route.js +1 -1
- package/app/.next/server/app/api/models/alias/route.js +1 -1
- package/app/.next/server/app/api/models/availability/route.js +1 -1
- package/app/.next/server/app/api/models/custom/route.js +1 -1
- package/app/.next/server/app/api/models/disabled/route.js +1 -1
- package/app/.next/server/app/api/models/route.js +1 -1
- package/app/.next/server/app/api/models/test/route.js +1 -1
- package/app/.next/server/app/api/models/test/route.js.nft.json +1 -1
- package/app/.next/server/app/api/oauth/[provider]/[action]/route.js +2 -2
- package/app/.next/server/app/api/oauth/[provider]/[action]/route.js.nft.json +1 -1
- package/app/.next/server/app/api/oauth/cursor/import/route.js +1 -1
- package/app/.next/server/app/api/oauth/gitlab/pat/route.js +1 -1
- package/app/.next/server/app/api/oauth/iflow/cookie/route.js +1 -1
- package/app/.next/server/app/api/oauth/kiro/import/route.js +1 -1
- package/app/.next/server/app/api/oauth/kiro/social-exchange/route.js +1 -1
- package/app/.next/server/app/api/pricing/route.js +1 -1
- package/app/.next/server/app/api/provider-nodes/[id]/route.js +1 -1
- package/app/.next/server/app/api/provider-nodes/route.js +1 -1
- package/app/.next/server/app/api/provider-nodes/route.js.nft.json +1 -1
- package/app/.next/server/app/api/providers/[id]/models/route.js +1 -1
- package/app/.next/server/app/api/providers/[id]/models/route.js.nft.json +1 -1
- package/app/.next/server/app/api/providers/[id]/route.js +1 -1
- package/app/.next/server/app/api/providers/[id]/route.js.nft.json +1 -1
- package/app/.next/server/app/api/providers/[id]/test/route.js +1 -1
- package/app/.next/server/app/api/providers/[id]/test/route.js.nft.json +1 -1
- package/app/.next/server/app/api/providers/[id]/test-models/route.js +1 -1
- package/app/.next/server/app/api/providers/client/route.js +1 -1
- package/app/.next/server/app/api/providers/client/route.js.nft.json +1 -1
- package/app/.next/server/app/api/providers/route.js +1 -1
- package/app/.next/server/app/api/providers/route.js.nft.json +1 -1
- package/app/.next/server/app/api/providers/test-batch/route.js +1 -1
- package/app/.next/server/app/api/providers/test-batch/route.js.nft.json +1 -1
- package/app/.next/server/app/api/providers/validate/route.js +1 -1
- package/app/.next/server/app/api/providers/validate/route.js.nft.json +1 -1
- package/app/.next/server/app/api/proxy-pools/[id]/route.js +1 -1
- package/app/.next/server/app/api/proxy-pools/[id]/test/route.js +1 -1
- package/app/.next/server/app/api/proxy-pools/[id]/test/route.js.nft.json +1 -1
- package/app/.next/server/app/api/proxy-pools/route.js +1 -1
- package/app/.next/server/app/api/proxy-pools/vercel-deploy/route.js +1 -1
- package/app/.next/server/app/api/settings/database/route.js +1 -1
- package/app/.next/server/app/api/settings/proxy-test/route.js +1 -1
- package/app/.next/server/app/api/settings/proxy-test/route.js.nft.json +1 -1
- package/app/.next/server/app/api/settings/require-login/route.js +1 -1
- package/app/.next/server/app/api/settings/route.js +1 -1
- package/app/.next/server/app/api/translator/console-logs/route.js +1 -1
- package/app/.next/server/app/api/translator/console-logs/stream/route.js +1 -1
- package/app/.next/server/app/api/translator/send/route.js +1 -1
- package/app/.next/server/app/api/translator/send/route.js.nft.json +1 -1
- package/app/.next/server/app/api/translator/translate/route.js +1 -1
- package/app/.next/server/app/api/translator/translate/route.js.nft.json +1 -1
- package/app/.next/server/app/api/usage/[connectionId]/route.js +1 -1
- package/app/.next/server/app/api/usage/[connectionId]/route.js.nft.json +1 -1
- package/app/.next/server/app/api/usage/api-keys/route.js +1 -1
- package/app/.next/server/app/api/usage/chart/route.js +1 -1
- package/app/.next/server/app/api/usage/history/route.js +1 -1
- package/app/.next/server/app/api/usage/logs/route.js +1 -1
- package/app/.next/server/app/api/usage/providers/route.js +1 -1
- package/app/.next/server/app/api/usage/request-details/route.js +1 -1
- package/app/.next/server/app/api/usage/request-logs/route.js +1 -1
- package/app/.next/server/app/api/usage/stats/route.js +1 -1
- package/app/.next/server/app/api/usage/stream/route.js +2 -2
- package/app/.next/server/app/api/users/[id]/route.js +1 -1
- package/app/.next/server/app/api/users/route.js +1 -1
- package/app/.next/server/app/api/v1/api/chat/route.js +1 -1
- package/app/.next/server/app/api/v1/api/chat/route.js.nft.json +1 -1
- package/app/.next/server/app/api/v1/audio/speech/route.js +1 -1
- package/app/.next/server/app/api/v1/audio/speech/route.js.nft.json +1 -1
- package/app/.next/server/app/api/v1/audio/transcriptions/route.js +1 -1
- package/app/.next/server/app/api/v1/audio/transcriptions/route.js.nft.json +1 -1
- package/app/.next/server/app/api/v1/chat/completions/route.js +1 -1
- package/app/.next/server/app/api/v1/chat/completions/route.js.nft.json +1 -1
- package/app/.next/server/app/api/v1/embeddings/route.js +1 -1
- package/app/.next/server/app/api/v1/embeddings/route.js.nft.json +1 -1
- package/app/.next/server/app/api/v1/images/generations/route.js +2 -2
- package/app/.next/server/app/api/v1/images/generations/route.js.nft.json +1 -1
- package/app/.next/server/app/api/v1/messages/route.js +1 -1
- package/app/.next/server/app/api/v1/messages/route.js.nft.json +1 -1
- package/app/.next/server/app/api/v1/models/[kind]/route.js +1 -1
- package/app/.next/server/app/api/v1/models/[kind]/route.js.nft.json +1 -1
- package/app/.next/server/app/api/v1/models/route.js +1 -1
- package/app/.next/server/app/api/v1/models/route.js.nft.json +1 -1
- package/app/.next/server/app/api/v1/responses/compact/route.js +1 -1
- package/app/.next/server/app/api/v1/responses/compact/route.js.nft.json +1 -1
- package/app/.next/server/app/api/v1/responses/route.js +1 -1
- package/app/.next/server/app/api/v1/responses/route.js.nft.json +1 -1
- package/app/.next/server/app/api/v1/route.js +1 -1
- package/app/.next/server/app/api/v1/route.js.nft.json +1 -1
- package/app/.next/server/app/api/v1/search/route.js +1 -1
- package/app/.next/server/app/api/v1/search/route.js.nft.json +1 -1
- package/app/.next/server/app/api/v1/web/fetch/route.js +1 -1
- package/app/.next/server/app/api/v1/web/fetch/route.js.nft.json +1 -1
- package/app/.next/server/app/api/v1beta/models/[...path]/route.js +1 -1
- package/app/.next/server/app/api/v1beta/models/[...path]/route.js.nft.json +1 -1
- package/app/.next/server/app/api/version/route.js +1 -1
- package/app/.next/server/app/api/version/update/route.js +1 -1
- package/app/.next/server/app/callback/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/callback.html +1 -1
- package/app/.next/server/app/callback.rsc +4 -4
- package/app/.next/server/app/callback.segments/_full.segment.rsc +4 -4
- package/app/.next/server/app/callback.segments/_head.segment.rsc +1 -1
- package/app/.next/server/app/callback.segments/_index.segment.rsc +4 -4
- package/app/.next/server/app/callback.segments/_tree.segment.rsc +2 -2
- package/app/.next/server/app/callback.segments/callback/__PAGE__.segment.rsc +1 -1
- package/app/.next/server/app/callback.segments/callback.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/settings/pricing/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/dashboard/settings/pricing.html +1 -1
- package/app/.next/server/app/dashboard/settings/pricing.rsc +4 -4
- package/app/.next/server/app/dashboard/settings/pricing.segments/_full.segment.rsc +4 -4
- package/app/.next/server/app/dashboard/settings/pricing.segments/_head.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/settings/pricing.segments/_index.segment.rsc +4 -4
- package/app/.next/server/app/dashboard/settings/pricing.segments/_tree.segment.rsc +2 -2
- package/app/.next/server/app/dashboard/settings/pricing.segments/dashboard/settings/pricing/__PAGE__.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/settings/pricing.segments/dashboard/settings/pricing.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/settings/pricing.segments/dashboard/settings.segment.rsc +1 -1
- package/app/.next/server/app/dashboard/settings/pricing.segments/dashboard.segment.rsc +1 -1
- package/app/.next/server/app/index.html +1 -1
- package/app/.next/server/app/index.rsc +4 -4
- package/app/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
- package/app/.next/server/app/index.segments/_full.segment.rsc +4 -4
- package/app/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/app/.next/server/app/index.segments/_index.segment.rsc +4 -4
- package/app/.next/server/app/index.segments/_tree.segment.rsc +2 -2
- package/app/.next/server/app/landing/page.js +1 -1
- package/app/.next/server/app/landing/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/landing.html +1 -1
- package/app/.next/server/app/landing.rsc +5 -5
- package/app/.next/server/app/landing.segments/_full.segment.rsc +5 -5
- package/app/.next/server/app/landing.segments/_head.segment.rsc +1 -1
- package/app/.next/server/app/landing.segments/_index.segment.rsc +4 -4
- package/app/.next/server/app/landing.segments/_tree.segment.rsc +2 -2
- package/app/.next/server/app/landing.segments/landing/__PAGE__.segment.rsc +2 -2
- package/app/.next/server/app/landing.segments/landing.segment.rsc +1 -1
- package/app/.next/server/app/login/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/login.html +1 -1
- package/app/.next/server/app/login.rsc +5 -5
- package/app/.next/server/app/login.segments/_full.segment.rsc +5 -5
- package/app/.next/server/app/login.segments/_head.segment.rsc +1 -1
- package/app/.next/server/app/login.segments/_index.segment.rsc +4 -4
- package/app/.next/server/app/login.segments/_tree.segment.rsc +2 -2
- package/app/.next/server/app/login.segments/login/__PAGE__.segment.rsc +2 -2
- package/app/.next/server/app/login.segments/login.segment.rsc +1 -1
- package/app/.next/server/app/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app-paths-manifest.json +2 -2
- package/app/.next/server/chunks/1679.js +1 -0
- package/app/.next/server/chunks/2506.js +2 -2
- package/app/.next/server/chunks/2574.js +1 -0
- package/app/.next/server/chunks/3110.js +14 -0
- package/app/.next/server/chunks/3605.js +1 -0
- package/app/.next/server/chunks/3855.js +1 -1
- package/app/.next/server/chunks/4122.js +1 -1
- package/app/.next/server/chunks/4664.js +1 -1
- package/app/.next/server/chunks/4989.js +2 -2
- package/app/.next/server/chunks/5627.js +2 -2
- package/app/.next/server/chunks/5681.js +1 -1
- package/app/.next/server/chunks/6108.js +1 -1
- package/app/.next/server/chunks/6182.js +4 -3
- package/app/.next/server/chunks/6774.js +1 -1
- package/app/.next/server/chunks/7341.js +1 -1
- package/app/.next/server/chunks/7595.js +1 -1
- package/app/.next/server/chunks/7937.js +7 -16
- package/app/.next/server/chunks/8590.js +1 -1
- package/app/.next/server/chunks/8760.js +1 -1
- package/app/.next/server/chunks/8895.js +1 -1
- package/app/.next/server/chunks/9489.js +1 -1
- package/app/.next/server/chunks/9547.js +4 -14
- package/app/.next/server/chunks/9609.js +1 -1
- package/app/.next/server/chunks/9718.js +1 -1
- package/app/.next/server/middleware-build-manifest.js +1 -1
- package/app/.next/server/middleware.js +1 -1
- package/app/.next/server/pages/404.html +1 -1
- package/app/.next/server/pages/500.html +1 -1
- package/app/.next/static/chunks/1321-e48fd14f5bef6d7a.js +1 -0
- package/app/.next/static/chunks/2336-36a1f30358e691c6.js +28 -0
- package/app/.next/static/chunks/app/(dashboard)/dashboard/admin/users/page-adc5d5e8da3a0761.js +1 -0
- package/app/.next/static/chunks/app/(dashboard)/dashboard/media-providers/[kind]/[id]/{page-eb5193b550d3e8de.js → page-c77fedcd9ba7bcac.js} +14 -14
- package/app/.next/static/chunks/app/(dashboard)/dashboard/profile/page-ceb9bffbc34711bc.js +1 -0
- package/app/.next/static/chunks/app/landing/{page-c7ae6a40e2a2228d.js → page-4644660041715534.js} +1 -1
- package/app/.next/static/css/d726e4e5a2cfbfd1.css +1 -0
- package/app/package.json +1 -1
- package/app/public/providers/commandcode.png +0 -0
- package/app/src/mitm/cert/install.js +13 -8
- package/app/src/mitm/cert/rootCA.js +20 -5
- package/app/src/mitm/config.js +12 -1
- package/app/src/mitm/dns/dnsConfig.js +2 -2
- package/app/src/mitm/handlers/openrouter.js +82 -3
- package/app/src/mitm/manager.js +2 -2
- package/package.json +1 -1
- package/src/cli/api/client.js +2 -2
- package/src/cli/terminalUI.js +2 -2
- package/src/cli/tray/autostart.js +25 -24
- package/src/cli/tray/tray.js +3 -3
- package/app/.next/server/chunks/2343.js +0 -1
- package/app/.next/static/chunks/1321-c90a1f54884edb62.js +0 -1
- package/app/.next/static/chunks/2336-4ac589bb36571207.js +0 -38
- package/app/.next/static/chunks/app/(dashboard)/dashboard/admin/users/page-15091159f6d63fb7.js +0 -1
- package/app/.next/static/chunks/app/(dashboard)/dashboard/profile/page-6289612ce5f7c181.js +0 -1
- package/app/.next/static/css/81b7abc9204a4458.css +0 -1
- /package/app/.next/static/{s_c_Y_7O0OBMovBwrwXBp → SQn85l_D0P4BshNJQkGiZ}/_buildManifest.js +0 -0
- /package/app/.next/static/{s_c_Y_7O0OBMovBwrwXBp → SQn85l_D0P4BshNJQkGiZ}/_ssgManifest.js +0 -0
package/app/src/mitm/config.js
CHANGED
|
@@ -16,7 +16,18 @@ const URL_PATTERNS = {
|
|
|
16
16
|
copilot: ["/chat/completions", "/v1/messages", "/responses"],
|
|
17
17
|
kiro: ["/generateAssistantResponse"],
|
|
18
18
|
cursor: ["/BidiAppend", "/RunSSE", "/RunPoll", "/Run"],
|
|
19
|
-
openrouter: [
|
|
19
|
+
openrouter: [
|
|
20
|
+
"/models",
|
|
21
|
+
"/api/v1/models",
|
|
22
|
+
"/api/v1/key",
|
|
23
|
+
"/api/v1/auth/key",
|
|
24
|
+
"/chat/completions",
|
|
25
|
+
"/v1/chat/completions",
|
|
26
|
+
"/api/v1/chat/completions",
|
|
27
|
+
"/v1/messages",
|
|
28
|
+
"/responses",
|
|
29
|
+
"/api/v1/responses",
|
|
30
|
+
],
|
|
20
31
|
};
|
|
21
32
|
|
|
22
33
|
// Synonym map: rawModel from request → canonical alias key in mitmAlias DB
|
|
@@ -12,8 +12,8 @@ const { runElevatedPowerShell, isAdmin } = require("../winElevated.js");
|
|
|
12
12
|
* If anything fails mid-way, restore from `.bak`. Same-volume renames are atomic on NTFS.
|
|
13
13
|
*/
|
|
14
14
|
function atomicWriteHostsWin(target, originalContent, newContent) {
|
|
15
|
-
const tmpNew = `${target}.
|
|
16
|
-
const tmpBak = `${target}.
|
|
15
|
+
const tmpNew = `${target}.openrouterx.new`;
|
|
16
|
+
const tmpBak = `${target}.openrouterx.bak`;
|
|
17
17
|
try {
|
|
18
18
|
fs.writeFileSync(tmpNew, newContent, "utf8");
|
|
19
19
|
try { fs.unlinkSync(tmpBak); } catch { /* none */ }
|
|
@@ -4,21 +4,35 @@ const { err } = require("../logger");
|
|
|
4
4
|
const { fetchRouter, pipeSSE } = require("./base");
|
|
5
5
|
|
|
6
6
|
const URL_MAP = {
|
|
7
|
+
"/api/v1/chat/completions": "/v1/chat/completions",
|
|
7
8
|
"/v1/chat/completions": "/v1/chat/completions",
|
|
8
9
|
"/chat/completions": "/v1/chat/completions",
|
|
9
10
|
"/v1/messages": "/v1/messages",
|
|
11
|
+
"/api/v1/responses": "/v1/responses",
|
|
12
|
+
"/v1/responses": "/v1/responses",
|
|
10
13
|
"/responses": "/v1/responses",
|
|
14
|
+
"/api/v1/models": "/v1/models",
|
|
15
|
+
"/v1/models": "/v1/models",
|
|
11
16
|
};
|
|
12
17
|
|
|
13
18
|
function resolveRouterPath(reqUrl) {
|
|
19
|
+
const [pathname, query = ""] = String(reqUrl || "").split("?");
|
|
14
20
|
for (const [pattern, routerPath] of Object.entries(URL_MAP)) {
|
|
15
|
-
if (
|
|
21
|
+
if (pathname === pattern || pathname.endsWith(pattern)) {
|
|
22
|
+
return query ? `${routerPath}?${query}` : routerPath;
|
|
23
|
+
}
|
|
16
24
|
}
|
|
17
25
|
return "/v1/chat/completions";
|
|
18
26
|
}
|
|
19
27
|
|
|
20
28
|
function isModelsRequest(reqUrl) {
|
|
21
|
-
|
|
29
|
+
const pathname = String(reqUrl || "").split("?")[0];
|
|
30
|
+
return pathname === "/models" || pathname === "/v1/models" || pathname === "/api/v1/models" || pathname.endsWith("/models");
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function isKeyInfoRequest(reqUrl) {
|
|
34
|
+
const pathname = String(reqUrl || "").split("?")[0];
|
|
35
|
+
return pathname === "/api/v1/key" || pathname === "/api/v1/auth/key";
|
|
22
36
|
}
|
|
23
37
|
|
|
24
38
|
function getLocalModelsPayload() {
|
|
@@ -36,6 +50,52 @@ function sendJsonPayload(res, payload) {
|
|
|
36
50
|
res.end(payload);
|
|
37
51
|
}
|
|
38
52
|
|
|
53
|
+
function sendOptions(res) {
|
|
54
|
+
if (res.writableEnded) return;
|
|
55
|
+
res.writeHead(204, {
|
|
56
|
+
"Access-Control-Allow-Origin": "*",
|
|
57
|
+
"Access-Control-Allow-Methods": "GET, POST, OPTIONS",
|
|
58
|
+
"Access-Control-Allow-Headers": "*",
|
|
59
|
+
});
|
|
60
|
+
res.end();
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function buildKeyInfoPayload() {
|
|
64
|
+
return {
|
|
65
|
+
data: {
|
|
66
|
+
label: "openrouterX MITM API Key",
|
|
67
|
+
limit: null,
|
|
68
|
+
usage: 0,
|
|
69
|
+
usage_daily: 0,
|
|
70
|
+
usage_weekly: 0,
|
|
71
|
+
usage_monthly: 0,
|
|
72
|
+
byok_usage: 0,
|
|
73
|
+
byok_usage_daily: 0,
|
|
74
|
+
byok_usage_weekly: 0,
|
|
75
|
+
byok_usage_monthly: 0,
|
|
76
|
+
is_free_tier: false,
|
|
77
|
+
limit_remaining: null,
|
|
78
|
+
limit_reset: null,
|
|
79
|
+
include_byok_in_limit: false,
|
|
80
|
+
is_provisioning_key: false,
|
|
81
|
+
is_management_key: false,
|
|
82
|
+
rate_limit: { interval: "1h", requests: 100000 },
|
|
83
|
+
},
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function sendKeyInfo(res) {
|
|
88
|
+
if (res.writableEnded) return;
|
|
89
|
+
const payload = JSON.stringify(buildKeyInfoPayload());
|
|
90
|
+
res.writeHead(200, {
|
|
91
|
+
"Content-Type": "application/json; charset=utf-8",
|
|
92
|
+
"Access-Control-Allow-Origin": "*",
|
|
93
|
+
"Cache-Control": "no-store",
|
|
94
|
+
"Content-Length": Buffer.byteLength(payload),
|
|
95
|
+
});
|
|
96
|
+
res.end(payload);
|
|
97
|
+
}
|
|
98
|
+
|
|
39
99
|
function buildInjectedModel(publicModelId) {
|
|
40
100
|
const [provider = "openrouter"] = String(publicModelId || "").split("/");
|
|
41
101
|
return {
|
|
@@ -102,6 +162,16 @@ async function handleModelsRequest(req, res, bodyBuffer, passthrough, aliasMappi
|
|
|
102
162
|
*/
|
|
103
163
|
async function intercept(req, res, bodyBuffer, mappedModel, passthrough, aliasMappings = {}) {
|
|
104
164
|
try {
|
|
165
|
+
if (req.method === "OPTIONS") {
|
|
166
|
+
sendOptions(res);
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
if (req.method === "GET" && isKeyInfoRequest(req.url)) {
|
|
171
|
+
sendKeyInfo(res);
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
|
|
105
175
|
if (isModelsRequest(req.url)) {
|
|
106
176
|
return handleModelsRequest(req, res, bodyBuffer, passthrough, aliasMappings);
|
|
107
177
|
}
|
|
@@ -119,4 +189,13 @@ async function intercept(req, res, bodyBuffer, mappedModel, passthrough, aliasMa
|
|
|
119
189
|
}
|
|
120
190
|
}
|
|
121
191
|
|
|
122
|
-
module.exports = {
|
|
192
|
+
module.exports = {
|
|
193
|
+
intercept,
|
|
194
|
+
resolveRouterPath,
|
|
195
|
+
isModelsRequest,
|
|
196
|
+
isKeyInfoRequest,
|
|
197
|
+
sendKeyInfo,
|
|
198
|
+
buildKeyInfoPayload,
|
|
199
|
+
injectPublicModels,
|
|
200
|
+
buildInjectedModel,
|
|
201
|
+
};
|
package/app/src/mitm/manager.js
CHANGED
|
@@ -62,7 +62,7 @@ function resolveBundledServerPath() {
|
|
|
62
62
|
|
|
63
63
|
const SERVER_PATH = resolveBundledServerPath();
|
|
64
64
|
const ENCRYPT_ALGO = "aes-256-gcm";
|
|
65
|
-
const ENCRYPT_SALT = "
|
|
65
|
+
const ENCRYPT_SALT = "openrouterx-mitm-pwd";
|
|
66
66
|
|
|
67
67
|
function getProcessUsingPort443() {
|
|
68
68
|
try {
|
|
@@ -524,7 +524,7 @@ async function startServer(apiKey, sudoPassword, forceKillPort443 = false) {
|
|
|
524
524
|
log(`[MITM] server.js missing at ${effectiveServerPath} → recopying`);
|
|
525
525
|
effectiveServerPath = ensureRuntimeServer(resolveBundledServerPath());
|
|
526
526
|
if (!effectiveServerPath || !fs.existsSync(effectiveServerPath)) {
|
|
527
|
-
throw new Error(`MITM server.js not found at ${effectiveServerPath}. Reinstall
|
|
527
|
+
throw new Error(`MITM server.js not found at ${effectiveServerPath}. Reinstall openrouterX.`);
|
|
528
528
|
}
|
|
529
529
|
}
|
|
530
530
|
const mitmRouterBase = await resolveMitmRouterBaseUrl();
|
package/package.json
CHANGED
package/src/cli/api/client.js
CHANGED
|
@@ -10,8 +10,8 @@ const DEFAULT_CONFIG = {
|
|
|
10
10
|
protocol: "http:",
|
|
11
11
|
};
|
|
12
12
|
|
|
13
|
-
const CLI_TOKEN_HEADER = "x-
|
|
14
|
-
const CLI_TOKEN_SALT = "
|
|
13
|
+
const CLI_TOKEN_HEADER = "x-openrouterx-cli-token";
|
|
14
|
+
const CLI_TOKEN_SALT = "openrouterx-cli-auth";
|
|
15
15
|
|
|
16
16
|
let config = { ...DEFAULT_CONFIG };
|
|
17
17
|
let cachedCliToken = null;
|
package/src/cli/terminalUI.js
CHANGED
|
@@ -57,11 +57,11 @@ async function startTerminalUI(port) {
|
|
|
57
57
|
// Configure API client
|
|
58
58
|
api.configure({ port });
|
|
59
59
|
|
|
60
|
-
const basePath = ["
|
|
60
|
+
const basePath = ["openrouterX"];
|
|
61
61
|
|
|
62
62
|
// Main menu
|
|
63
63
|
await showMenuWithBack({
|
|
64
|
-
title: "📡
|
|
64
|
+
title: "📡 openrouterX Terminal UI",
|
|
65
65
|
breadcrumb: basePath,
|
|
66
66
|
headerContent: async () => await buildHeaderContent(port),
|
|
67
67
|
refresh: async () => ({}), // Refresh header on each loop
|
|
@@ -3,17 +3,18 @@ const path = require("path");
|
|
|
3
3
|
const os = require("os");
|
|
4
4
|
const { execSync } = require("child_process");
|
|
5
5
|
|
|
6
|
-
const APP_NAME = "
|
|
7
|
-
const
|
|
6
|
+
const APP_NAME = "openrouterX";
|
|
7
|
+
const APP_FILE_BASENAME = "openrouterx";
|
|
8
|
+
const APP_LABEL = "com.openrouterx.autostart";
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
|
-
* Get the command to run
|
|
11
|
+
* Get the command to run openrouterX in tray mode
|
|
11
12
|
*/
|
|
12
13
|
function getStartCommand() {
|
|
13
|
-
// Find the global npm bin path for
|
|
14
|
+
// Find the global npm bin path for openrouterX
|
|
14
15
|
try {
|
|
15
16
|
const npmBin = execSync("npm bin -g", { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] }).trim();
|
|
16
|
-
const routerPath = path.join(npmBin,
|
|
17
|
+
const routerPath = path.join(npmBin, APP_NAME);
|
|
17
18
|
if (fs.existsSync(routerPath)) {
|
|
18
19
|
return `"${routerPath}" --tray --skip-update`;
|
|
19
20
|
}
|
|
@@ -22,7 +23,7 @@ function getStartCommand() {
|
|
|
22
23
|
}
|
|
23
24
|
|
|
24
25
|
// Fallback: use npx
|
|
25
|
-
return "npx
|
|
26
|
+
return "npx @yina-npm/openrouterx --tray --skip-update";
|
|
26
27
|
}
|
|
27
28
|
|
|
28
29
|
/**
|
|
@@ -92,10 +93,10 @@ function isAutoStartEnabled() {
|
|
|
92
93
|
const plistPath = path.join(os.homedir(), "Library", "LaunchAgents", `${APP_LABEL}.plist`);
|
|
93
94
|
return fs.existsSync(plistPath);
|
|
94
95
|
} else if (platform === "win32") {
|
|
95
|
-
const startupPath = path.join(process.env.APPDATA, "Microsoft", "Windows", "Start Menu", "Programs", "Startup", `${
|
|
96
|
+
const startupPath = path.join(process.env.APPDATA, "Microsoft", "Windows", "Start Menu", "Programs", "Startup", `${APP_FILE_BASENAME}.vbs`);
|
|
96
97
|
return fs.existsSync(startupPath);
|
|
97
98
|
} else if (platform === "linux") {
|
|
98
|
-
const desktopPath = path.join(os.homedir(), ".config", "autostart", `${
|
|
99
|
+
const desktopPath = path.join(os.homedir(), ".config", "autostart", `${APP_FILE_BASENAME}.desktop`);
|
|
99
100
|
return fs.existsSync(desktopPath);
|
|
100
101
|
}
|
|
101
102
|
} catch (e) {}
|
|
@@ -114,7 +115,7 @@ function enableMacOS(cliPath) {
|
|
|
114
115
|
fs.mkdirSync(launchAgentsDir, { recursive: true });
|
|
115
116
|
}
|
|
116
117
|
|
|
117
|
-
// Get absolute paths for node and
|
|
118
|
+
// Get absolute paths for node and openrouterX script
|
|
118
119
|
const nodePath = process.execPath;
|
|
119
120
|
let routerScript;
|
|
120
121
|
|
|
@@ -125,11 +126,11 @@ function enableMacOS(cliPath) {
|
|
|
125
126
|
// Fallback: try to resolve from npm bin
|
|
126
127
|
try {
|
|
127
128
|
const npmBin = execSync("npm bin -g", { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] }).trim();
|
|
128
|
-
const routerLink = path.join(npmBin,
|
|
129
|
+
const routerLink = path.join(npmBin, APP_NAME);
|
|
129
130
|
routerScript = fs.realpathSync(routerLink);
|
|
130
131
|
} catch (e) {
|
|
131
132
|
// Last resort fallback
|
|
132
|
-
routerScript = "/usr/local/lib/node_modules/
|
|
133
|
+
routerScript = "/usr/local/lib/node_modules/@yina-npm/openrouterx/cli.js";
|
|
133
134
|
}
|
|
134
135
|
}
|
|
135
136
|
|
|
@@ -154,9 +155,9 @@ function enableMacOS(cliPath) {
|
|
|
154
155
|
<key>KeepAlive</key>
|
|
155
156
|
<false/>
|
|
156
157
|
<key>StandardOutPath</key>
|
|
157
|
-
<string>/tmp/
|
|
158
|
+
<string>/tmp/openrouterx.log</string>
|
|
158
159
|
<key>StandardErrorPath</key>
|
|
159
|
-
<string>/tmp/
|
|
160
|
+
<string>/tmp/openrouterx.error.log</string>
|
|
160
161
|
</dict>
|
|
161
162
|
</plist>`;
|
|
162
163
|
|
|
@@ -188,7 +189,7 @@ function disableMacOS() {
|
|
|
188
189
|
|
|
189
190
|
function enableWindows(cliPath) {
|
|
190
191
|
const startupDir = path.join(process.env.APPDATA, "Microsoft", "Windows", "Start Menu", "Programs", "Startup");
|
|
191
|
-
const vbsPath = path.join(startupDir, `${
|
|
192
|
+
const vbsPath = path.join(startupDir, `${APP_FILE_BASENAME}.vbs`);
|
|
192
193
|
|
|
193
194
|
// Ensure startup directory exists
|
|
194
195
|
if (!fs.existsSync(startupDir)) {
|
|
@@ -206,12 +207,12 @@ function enableWindows(cliPath) {
|
|
|
206
207
|
// Fallback: try to resolve from npm bin
|
|
207
208
|
try {
|
|
208
209
|
const npmBin = execSync("npm bin -g", { encoding: "utf8", shell: true, stdio: ["ignore", "pipe", "ignore"] }).trim();
|
|
209
|
-
const routerLink = path.join(npmBin,
|
|
210
|
+
const routerLink = path.join(npmBin, `${APP_NAME}.cmd`);
|
|
210
211
|
if (fs.existsSync(routerLink)) {
|
|
211
212
|
routerScript = routerLink;
|
|
212
213
|
} else {
|
|
213
214
|
// Try to resolve actual script
|
|
214
|
-
const routerJs = path.join(npmBin, "../lib/node_modules/
|
|
215
|
+
const routerJs = path.join(npmBin, "../lib/node_modules/@yina-npm/openrouterx/cli.js");
|
|
215
216
|
if (fs.existsSync(routerJs)) {
|
|
216
217
|
routerScript = routerJs;
|
|
217
218
|
}
|
|
@@ -236,7 +237,7 @@ WshShell.Run """${routerScript}"" --tray --skip-update", 0, False
|
|
|
236
237
|
} else {
|
|
237
238
|
// Fallback to npx
|
|
238
239
|
vbsContent = `Set WshShell = CreateObject("WScript.Shell")
|
|
239
|
-
WshShell.Run "npx
|
|
240
|
+
WshShell.Run "npx @yina-npm/openrouterx --tray --skip-update", 0, False
|
|
240
241
|
`;
|
|
241
242
|
}
|
|
242
243
|
|
|
@@ -245,7 +246,7 @@ WshShell.Run "npx 9router --tray --skip-update", 0, False
|
|
|
245
246
|
}
|
|
246
247
|
|
|
247
248
|
function disableWindows() {
|
|
248
|
-
const vbsPath = path.join(process.env.APPDATA, "Microsoft", "Windows", "Start Menu", "Programs", "Startup", `${
|
|
249
|
+
const vbsPath = path.join(process.env.APPDATA, "Microsoft", "Windows", "Start Menu", "Programs", "Startup", `${APP_FILE_BASENAME}.vbs`);
|
|
249
250
|
|
|
250
251
|
if (fs.existsSync(vbsPath)) {
|
|
251
252
|
fs.unlinkSync(vbsPath);
|
|
@@ -258,7 +259,7 @@ function disableWindows() {
|
|
|
258
259
|
|
|
259
260
|
function enableLinux(cliPath) {
|
|
260
261
|
const autostartDir = path.join(os.homedir(), ".config", "autostart");
|
|
261
|
-
const desktopPath = path.join(autostartDir, `${
|
|
262
|
+
const desktopPath = path.join(autostartDir, `${APP_FILE_BASENAME}.desktop`);
|
|
262
263
|
|
|
263
264
|
// Ensure directory exists
|
|
264
265
|
if (!fs.existsSync(autostartDir)) {
|
|
@@ -280,20 +281,20 @@ function enableLinux(cliPath) {
|
|
|
280
281
|
// Fallback: try to resolve from npm bin
|
|
281
282
|
try {
|
|
282
283
|
const npmBin = execSync("npm bin -g", { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] }).trim();
|
|
283
|
-
const routerLink = path.join(npmBin,
|
|
284
|
+
const routerLink = path.join(npmBin, APP_NAME);
|
|
284
285
|
if (fs.existsSync(routerLink)) {
|
|
285
286
|
routerScript = fs.realpathSync(routerLink);
|
|
286
287
|
}
|
|
287
288
|
} catch (e) {
|
|
288
289
|
// Last resort fallback
|
|
289
|
-
routerScript = "/usr/local/lib/node_modules/
|
|
290
|
+
routerScript = "/usr/local/lib/node_modules/@yina-npm/openrouterx/cli.js";
|
|
290
291
|
}
|
|
291
292
|
}
|
|
292
293
|
|
|
293
294
|
const desktopContent = `[Desktop Entry]
|
|
294
295
|
Type=Application
|
|
295
|
-
Name=
|
|
296
|
-
Comment=
|
|
296
|
+
Name=openrouterX
|
|
297
|
+
Comment=openrouterX API Proxy
|
|
297
298
|
Exec=${nodePath} ${routerScript} --tray --skip-update
|
|
298
299
|
Hidden=false
|
|
299
300
|
NoDisplay=false
|
|
@@ -305,7 +306,7 @@ X-GNOME-Autostart-enabled=true
|
|
|
305
306
|
}
|
|
306
307
|
|
|
307
308
|
function disableLinux() {
|
|
308
|
-
const desktopPath = path.join(os.homedir(), ".config", "autostart", `${
|
|
309
|
+
const desktopPath = path.join(os.homedir(), ".config", "autostart", `${APP_FILE_BASENAME}.desktop`);
|
|
309
310
|
|
|
310
311
|
if (fs.existsSync(desktopPath)) {
|
|
311
312
|
fs.unlinkSync(desktopPath);
|
package/src/cli/tray/tray.js
CHANGED
|
@@ -64,11 +64,11 @@ function initTray(options) {
|
|
|
64
64
|
const menu = {
|
|
65
65
|
icon: getIconBase64(),
|
|
66
66
|
// macOS requires empty title; Windows uses title as the tray icon tooltip
|
|
67
|
-
title: isWin ? `
|
|
68
|
-
tooltip: `
|
|
67
|
+
title: isWin ? `openrouterX - Port ${port}` : "",
|
|
68
|
+
tooltip: `openrouterX - Port ${port}`,
|
|
69
69
|
items: [
|
|
70
70
|
{
|
|
71
|
-
title: `
|
|
71
|
+
title: `openrouterX (Port ${port})`,
|
|
72
72
|
tooltip: "Server is running",
|
|
73
73
|
enabled: false
|
|
74
74
|
},
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
"use strict";exports.id=2343,exports.ids=[2343],exports.modules={2574:(a,b,c)=>{c.r(b),c.d(b,{GET:()=>p,OPTIONS:()=>o,buildModelsList:()=>n});var d=c(81329),e=c(75681),f=c(89718),g=c(9132),h=c(38775);let i=/[-_][0-9a-f]{8,}$/i,j={image:"image",tts:"tts",embedding:"embedding",stt:"stt",imageToText:"imageToText"};function k(a){return a?.type&&j[a.type]||"llm"}async function l(a){if(!a?.apiKey)return[];let b="string"==typeof a?.providerSpecificData?.baseUrl?a.providerSpecificData.baseUrl.trim().replace(/\/$/,""):"";if(!b)return[];let c=`${b}/models`,d={"Content-Type":"application/json"};if((0,e.mq)(a.provider))d.Authorization=`Bearer ${a.apiKey}`;else{if(!(0,e.gb)(a.provider))return[];c.endsWith("/messages/models")?c=c.slice(0,-9):c.endsWith("/messages")&&(c=`${c.slice(0,-9)}/models`),d["x-api-key"]=a.apiKey,d["anthropic-version"]="2023-06-01",d.Authorization=`Bearer ${a.apiKey}`}try{var f;let a=new AbortController,b=setTimeout(()=>a.abort(),5e3),e=await fetch(c,{method:"GET",headers:d,cache:"no-store",signal:a.signal});if(clearTimeout(b),!e.ok)return[];let g=(f=await e.json(),Array.isArray(f)?f:f?.data||f?.models||f?.results||[]);return Array.from(new Set(g.map(a=>a?.id||a?.name||a?.model).filter(a=>"string"==typeof a&&""!==a.trim())))}catch{return[]}}function m(a,b){let c=e.AI_PROVIDERS[a],d=Array.isArray(c?.serviceKinds)&&c.serviceKinds.length>0?c.serviceKinds:["llm"];return b.some(a=>d.includes(a))}async function n(a,b=null){let c=b?await (0,g.RG)(b):null,j=[];try{j=(j=await (0,f.getProviderConnections)()).filter(a=>!1!==a.isActive),c&&(j=j.filter(a=>(0,g.iI)(c,a.provider)))}catch(a){console.log("Could not fetch providers, returning all models")}let o=[];try{o=await (0,f.Uv)()}catch(a){console.log("Could not fetch combos")}let p=[];try{p=await (0,f.uv)()}catch(a){console.log("Could not fetch custom models")}let q={};try{q=await (0,f.OM)()}catch(a){console.log("Could not fetch model aliases")}let r=new Map;for(let a of j)r.has(a.provider)||r.set(a.provider,a);let s=[],t=Math.floor(Date.now()/1e3);for(let b of o){if(!function(a,b){let c=a?.kind||"llm";return b.includes(c)}(b,a))continue;if(c){let a=!0;for(let d of b.models||[]){let b=await (0,h.mA)(d);if(!b?.provider||!(0,g.iI)(c,b.provider)){a=!1;break}}if(!a)continue}let d={id:b.name,object:"model",created:t,owned_by:"combo"};("webSearch"===b.kind||"webFetch"===b.kind)&&(d.kind=b.kind),s.push(d)}if(0===j.length){let b=Object.fromEntries(Object.entries(d.Xg).map(([a,b])=>[b,a]));for(let[e,f]of Object.entries(d.vq)){let d=b[e]||e;if((!c||(0,g.iI)(c,d))&&m(d,a))for(let b of f)a.includes(k(b))&&s.push({id:`${e}/${b.id}`,object:"model",created:t,owned_by:e})}for(let b of p){if(!b?.id||b.type&&"llm"!==b.type||!a.includes("llm"))continue;let d=b.providerAlias;if(!d)continue;let e=String(b.id).trim();if(e){if(c){let a=await (0,h.mA)(`${d}/${e}`);if(!a?.provider||!(0,g.iI)(c,a.provider))continue}s.push({id:`${d}/${e}`,object:"model",created:t,owned_by:d})}}}else for(let[b,f]of r.entries()){if(c&&!(0,g.iI)(c,b)||!m(b,a))continue;let h=d.Xg[b]||b,j=(f?.providerSpecificData?.prefix||(0,e.wG)(b)||h).trim(),n=d.vq[h]||[],o=f?.providerSpecificData?.enabledModels,r=Array.isArray(o)&&o.length>0,u=(0,e.mq)(b)||(0,e.gb)(b),v=new Map(n.map(a=>[a.id,k(a)])),w=r?Array.from(new Set(o.filter(a=>"string"==typeof a&&""!==a.trim()))):n.map(a=>a.id);for(let c of(u&&0===w.length&&!i.test(b)&&(w=await l(f)),Array.from(new Set([...w.map(a=>a.startsWith(`${j}/`)?a.slice(j.length+1):a.startsWith(`${h}/`)?a.slice(h.length+1):a.startsWith(`${b}/`)?a.slice(b.length+1):a).filter(a=>"string"==typeof a&&""!==a.trim()),...p.filter(a=>{if(!a?.id||a.type&&"llm"!==a.type)return!1;let c=a.providerAlias;return c===h||c===j||c===b}).map(a=>String(a.id).trim()).filter(a=>""!==a),...Object.values(q||{}).filter(a=>"string"==typeof a&&!!a.includes("/")&&(a.startsWith(`${j}/`)||a.startsWith(`${h}/`)||a.startsWith(`${b}/`))).map(a=>a.startsWith(`${j}/`)?a.slice(j.length+1):a.startsWith(`${h}/`)?a.slice(h.length+1):a.startsWith(`${b}/`)?a.slice(b.length+1):a).filter(a=>"string"==typeof a&&""!==a.trim())])))){let b=v.get(c)||function(a){let b=String(a).toLowerCase();return/embed/.test(b)?"embedding":/tts|speech|audio|voice/.test(b)?"tts":/image|imagen|dall-?e|flux|sdxl|sd-|stable-diffusion/.test(b)?"image":"llm"}(c);a.includes(b)&&s.push({id:`${j}/${c}`,object:"model",created:t,owned_by:j})}let x=e.AI_PROVIDERS[b],y=[];if(a.includes("tts")&&Array.isArray(x?.ttsConfig?.models))for(let a of x.ttsConfig.models)a?.id&&y.push(a.id);if(a.includes("embedding")&&Array.isArray(x?.embeddingConfig?.models))for(let a of x.embeddingConfig.models)a?.id&&y.push(a.id);for(let a of y)s.push({id:`${j}/${a}`,object:"model",created:t,owned_by:j});a.includes("webSearch")&&x?.searchConfig&&s.push({id:`${j}/search`,object:"model",kind:"webSearch",created:t,owned_by:j}),a.includes("webFetch")&&x?.fetchConfig&&s.push({id:`${j}/fetch`,object:"model",kind:"webFetch",created:t,owned_by:j})}let u=[],v=new Set;for(let a of s)!a?.id||v.has(a.id)||(v.add(a.id),u.push(a));return u}async function o(){return new Response(null,{headers:{"Access-Control-Allow-Origin":"*","Access-Control-Allow-Methods":"GET, OPTIONS","Access-Control-Allow-Headers":"*"}})}async function p(a){try{let b=await (0,g.RG)(a),c=[];try{c=(c=await (0,f.getProviderConnections)()).filter(a=>!1!==a.isActive),b&&(c=c.filter(a=>(0,g.iI)(b,a.provider)))}catch(a){console.log("Could not fetch providers, returning all models")}let j=[];try{j=await (0,f.Uv)()}catch(a){console.log("Could not fetch combos")}let k=new Map;for(let a of c)k.has(a.provider)||k.set(a.provider,a);let m=[],n=Math.floor(Date.now()/1e3);for(let a of j){if(b){let c=!0;for(let d of a.models||[]){let a=await (0,h.mA)(d);if(!a?.provider||!(0,g.iI)(b,a.provider)){c=!1;break}}if(!c)continue}m.push({id:a.name,object:"model",created:n,owned_by:"combo",permission:[],root:a.name,parent:null})}if(0===c.length)for(let[a,c]of Object.entries(d.vq)){let e=Object.entries(d.Xg).find(([b,c])=>c===a)?.[0]||a;if((0,g.iI)(b,e))for(let b of c)m.push({id:`${a}/${b.id}`,object:"model",created:n,owned_by:a,permission:[],root:b.id,parent:null})}else for(let[a,c]of k.entries()){if(!(0,g.iI)(b,a))continue;let f=d.Xg[a]||a,h=(c?.providerSpecificData?.prefix||(0,e.wG)(a)||f).trim(),j=d.vq[f]||[],k=c?.providerSpecificData?.enabledModels,o=Array.isArray(k)&&k.length>0,p=(0,e.mq)(a)||(0,e.gb)(a),q=o?Array.from(new Set(k.filter(a=>"string"==typeof a&&""!==a.trim()))):j.map(a=>a.id);for(let b of(p&&0===q.length&&!i.test(a)&&(q=await l(c)),q.map(b=>b.startsWith(`${h}/`)?b.slice(h.length+1):b.startsWith(`${f}/`)?b.slice(f.length+1):b.startsWith(`${a}/`)?b.slice(a.length+1):b).filter(a=>"string"==typeof a&&""!==a.trim())))m.push({id:`${h}/${b}`,object:"model",created:n,owned_by:h,permission:[],root:b,parent:null})}return Response.json({object:"list",data:m},{headers:{"Access-Control-Allow-Origin":"*"}})}catch(a){return console.log("Error fetching models:",a),Response.json({error:{message:a.message,type:"server_error"}},{status:500})}}},9132:(a,b,c)=>{c.d(b,{Mv:()=>j,RG:()=>h,iI:()=>i});var d=c(68658),e=c(89718),f=c(54200);function g(a,b){return a&&"sub_user"===a.role?{role:"sub_user",userId:a.id,username:a.username||null,permissions:Array.isArray(a.permissions)?a.permissions:[],allowedProviders:(0,f.cc)(a),source:b}:null}async function h(a,b=null){let c=b||function(a){let b=a?.headers?.get("Authorization");if(b?.startsWith("Bearer "))return b.slice(7);let c=a?.headers?.get("x-api-key");return c||null}(a);if(c){let a=await (0,e.y7)(c);if(a?.userId){let b=g(await (0,e.kl)(a.userId),"api_key");if(b)return b}}let f=await (0,d.f1)(a);if(!f||"sub_user"!==f.role||!f.userId)return null;let i=await (0,e.kl)(f.userId);return i?g(i,"cookie"):g({id:f.userId,username:f.username||null,role:f.role,permissions:f.permissions||[],allowedProviders:f.allowedProviders},"cookie")}function i(a,b){return!a||"sub_user"!==a.role||a.allowedProviders.includes(b)}function j(a,b){return b&&"sub_user"===b.role?a.filter(a=>i(b,a.provider)):a}},38775:(a,b,c)=>{c.d(b,{d_:()=>g,mA:()=>f});var d=c(89718),e=c(40669);async function f(a){let b=(0,e.Xh)(a);if(!b.isAlias){let a=(await (0,d.getProviderNodes)({type:"openai-compatible"})).find(a=>a.prefix===b.providerAlias);if(a)return{provider:a.id,model:b.model};let c=(await (0,d.getProviderNodes)({type:"anthropic-compatible"})).find(a=>a.prefix===b.providerAlias);if(c)return{provider:c.id,model:b.model};let e=(await (0,d.getProviderNodes)({type:"custom-embedding"})).find(a=>a.prefix===b.providerAlias);if(e)return{provider:e.id,model:b.model};let f=(await (0,d.getProviderNodes)({type:"custom-image"})).find(a=>a.prefix===b.providerAlias);return f?{provider:f.id,model:b.model}:{provider:b.provider,model:b.model}}return await (0,d.Dj)(b.model)?{provider:null,model:b.model}:(0,e.js)(a,d.OM)}async function g(a){if(a.includes("/"))return null;let b=await (0,d.Dj)(a);return b&&b.models&&b.models.length>0?b.models:null}},40669:(a,b,c)=>{c.d(b,{Xh:()=>e,js:()=>f});let d={cc:"claude",cx:"codex",gc:"gemini-cli",qw:"qwen",if:"iflow",ag:"antigravity",gh:"github",kr:"kiro",cu:"cursor",kc:"kilocode",kmc:"kimi-coding",cl:"cline",oc:"opencode",ocg:"opencode-go",el:"elevenlabs",openai:"openai",anthropic:"anthropic",gemini:"gemini",openrouter:"openrouter",glm:"glm",kimi:"kimi",minimax:"minimax","minimax-cn":"minimax-cn",ds:"deepseek",deepseek:"deepseek",groq:"groq",xai:"xai",mistral:"mistral",pplx:"perplexity",perplexity:"perplexity",together:"together",fireworks:"fireworks",cerebras:"cerebras",cohere:"cohere",nvidia:"nvidia",nebius:"nebius",siliconflow:"siliconflow",hyp:"hyperbolic",hyperbolic:"hyperbolic",dg:"deepgram",deepgram:"deepgram",aai:"assemblyai",assemblyai:"assemblyai",nb:"nanobanana",nanobanana:"nanobanana",ch:"chutes",chutes:"chutes",ark:"volcengine-ark","volcengine-ark":"volcengine-ark",byteplus:"byteplus",bpm:"byteplus",cursor:"cursor",vx:"vertex",vertex:"vertex",vxp:"vertex-partner","vertex-partner":"vertex-partner",gw:"grok-web","grok-web":"grok-web",pw:"perplexity-web","perplexity-web":"perplexity-web",mimo:"xiaomi-mimo","xiaomi-mimo":"xiaomi-mimo",cf:"cloudflare-ai","cloudflare-ai":"cloudflare-ai",fal:"fal-ai","fal-ai":"fal-ai",stability:"stability-ai","stability-ai":"stability-ai",bfl:"black-forest-labs","black-forest-labs":"black-forest-labs",recraft:"recraft",topaz:"topaz",runway:"runwayml",runwayml:"runwayml",jina:"jina-ai","jina-ai":"jina-ai",polly:"aws-polly","aws-polly":"aws-polly"};function e(a){if(!a)return{provider:null,model:null,isAlias:!1,providerAlias:null};if(a.includes("/")){let b=a.indexOf("/"),c=a.slice(0,b),e=a.slice(b+1);return{provider:d[c]||c,model:e,isAlias:!1,providerAlias:c}}return{provider:null,model:a,isAlias:!0,providerAlias:null}}async function f(a,b){let c=e(a);if(!c.isAlias)return{provider:c.provider,model:c.model};let f="function"==typeof b?await b():b,g=function(a,b){var c,e;if(!b)return null;let f=b[a];if(!f)return null;if("string"==typeof f&&f.includes("/")){let a=f.indexOf("/");return{provider:d[c=f.slice(0,a)]||c,model:f.slice(a+1)}}return"object"==typeof f&&f.provider&&f.model?{provider:d[e=f.provider]||e,model:f.model}:null}(c.model,f);return g||{provider:function(a){if(!a)return"openai";let b=a.toLowerCase();return b.startsWith("claude-")?"anthropic":b.startsWith("gemini-")?"gemini":b.startsWith("gpt-")||b.startsWith("o1")||b.startsWith("o3")||b.startsWith("o4")?"openai":b.startsWith("deepseek-")?"openrouter":"openai"}(c.model),model:c.model}}},49120:(a,b,c)=>{c.d(b,{n:()=>i}),c(29021);var d,e=c(33873),f=c.n(e),g=c(21820),h=c.n(g);let i=process.env.DATA_DIR?process.env.DATA_DIR:(d="openrouterx","win32"===process.platform?f().join(process.env.APPDATA||f().join(h().homedir(),"AppData","Roaming"),d):f().join(h().homedir(),`.${d}`))},54200:(a,b,c)=>{c.d(b,{cc:()=>f,vJ:()=>e});let d=["codex","alicode"];function e(a){return Array.isArray(a)?Array.from(new Set(a.map(a=>"string"==typeof a?a.trim():"").filter(Boolean))):[]}function f(a,b=d){return a&&"object"==typeof a&&Object.prototype.hasOwnProperty.call(a,"allowedProviders")?e(a.allowedProviders):e(b)}},54603:(a,b,c)=>{c.d(b,{Xj:()=>e});var d=c(19713);async function e(a=null){let b=a||process.env.MACHINE_ID_SALT||"endpoint-proxy-salt";try{let a=(0,d.machineIdSync)();return(await Promise.resolve().then(c.t.bind(c,55511,23))).createHash("sha256").update(a+b).digest("hex").substring(0,16)}catch(a){return console.log("Error getting machine ID:",a),crypto.randomUUID?crypto.randomUUID():"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,function(a){let b=16*Math.random()|0;return("x"==a?b:3&b|8).toString(16)})}}},68658:(a,b,c)=>{c.d(b,{f1:()=>f}),c(23211);var d=c(69614);c(89718),c(54603);let e=new TextEncoder().encode(process.env.JWT_SECRET||"9router-default-secret-change-me");async function f(a){let b=a.cookies.get("auth_token")?.value;if(!b)return null;try{let{payload:a}=await (0,d.V)(b,e);return a}catch{return null}}},69614:(a,b,c)=>{c.d(b,{V:()=>p});var d=c(88888),e=c(91356),f=c(99129),g=c(73575),h=c(41570),i=c(19035),j=c(24762),k=c(80308),l=c(55956);async function m(a,b,c){if(!(0,i.Gv)(a))throw new f.Ye("Flattened JWS must be an object");if(void 0===a.protected&&void 0===a.header)throw new f.Ye('Flattened JWS must have either of the "protected" or "header" members');if(void 0!==a.protected&&"string"!=typeof a.protected)throw new f.Ye("JWS Protected Header incorrect type");if(void 0===a.payload)throw new f.Ye("JWS Payload missing");if("string"!=typeof a.signature)throw new f.Ye("JWS Signature missing or incorrect type");if(void 0!==a.header&&!(0,i.Gv)(a.header))throw new f.Ye("JWS Unprotected Header incorrect type");let m={};if(a.protected)try{let b=(0,d.D)(a.protected);m=JSON.parse(g.D0.decode(b))}catch{throw new f.Ye("JWS Protected Header is invalid")}if(!(0,i.fz)(m,a.header))throw new f.Ye("JWS Protected and JWS Unprotected Header Parameter names must be disjoint");let n={...m,...a.header},o=(0,k.n)(f.Ye,new Map([["b64",!0]]),c?.crit,m,n),p=!0;if(o.has("b64")&&"boolean"!=typeof(p=m.b64))throw new f.Ye('The "b64" (base64url-encode payload) Header Parameter must be a boolean');let{alg:q}=n;if("string"!=typeof q||!q)throw new f.Ye('JWS "alg" (Algorithm) Header Parameter missing or invalid');let r=c&&function(a,b){if(void 0!==b&&(!Array.isArray(b)||b.some(a=>"string"!=typeof a)))throw TypeError(`"${a}" option must be an array of strings`);if(b)return new Set(b)}("algorithms",c.algorithms);if(r&&!r.has(q))throw new f.Rb('"alg" (Algorithm) Header Parameter value not allowed');if(p){if("string"!=typeof a.payload)throw new f.Ye("JWS Payload must be a string")}else if("string"!=typeof a.payload&&!(a.payload instanceof Uint8Array))throw new f.Ye("JWS Payload must be a string or an Uint8Array instance");let s=!1;"function"==typeof b&&(b=await b(m,a),s=!0),(0,j.y)(q,b,"verify");let t=(0,g.xW)(void 0!==a.protected?(0,g.lF)(a.protected):new Uint8Array,(0,g.lF)("."),"string"==typeof a.payload?p?(0,g.lF)(a.payload):g.Rd.encode(a.payload):a.payload),u=(0,h.h2)(a.signature,"signature",f.Ye),v=await (0,l.l)(b,q);if(!await (0,e.MX)(q,v,u,t))throw new f.h2;let w={payload:p?(0,h.h2)(a.payload,"payload",f.Ye):"string"==typeof a.payload?g.Rd.encode(a.payload):a.payload};return(void 0!==a.protected&&(w.protectedHeader=m),void 0!==a.header&&(w.unprotectedHeader=a.header),s)?{...w,key:v}:w}async function n(a,b,c){if(a instanceof Uint8Array&&(a=g.D0.decode(a)),"string"!=typeof a)throw new f.Ye("Compact JWS must be a string or Uint8Array");let{0:d,1:e,2:h,length:i}=a.split(".");if(3!==i)throw new f.Ye("Invalid Compact JWS");let j=await m({payload:e,protected:d,signature:h},b,c),k={payload:j.payload,protectedHeader:j.protectedHeader};return"function"==typeof b?{...k,key:j.key}:k}var o=c(17347);async function p(a,b,c){let d=await n(a,b,c);if(d.protectedHeader.crit?.includes("b64")&&!1===d.protectedHeader.b64)throw new f.Dp("JWTs MUST NOT use unencoded payload");let e={payload:(0,o.k6)(d.protectedHeader,d.payload,c),protectedHeader:d.protectedHeader};return"function"==typeof b?{...e,key:d.key}:e}},81329:(a,b,c)=>{c.d(b,{Xg:()=>d.Xg,eh:()=>e,vq:()=>d.vq});var d=c(44404);Object.entries(c(75681).AI_PROVIDERS).filter(([,a])=>a.passthroughModels).map(([a])=>a);let e=Object.entries(d.vq).flatMap(([a,b])=>b.map(b=>({provider:a,model:b.id,name:b.name})))}};
|