mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-20 14:12:59 +03:00
Merge main into release/v3.7.9
This commit is contained in:
@@ -21,8 +21,6 @@
|
||||
|
||||
### 🐛 Bug Fixes
|
||||
|
||||
- **fix(providers):** resolve ChatGPT Web authentication failure by aligning TLS fingerprint User-Agent strings (fixes #1925)
|
||||
- **fix(infrastructure):** move `wreq-js` to optionalDependencies to unblock ARM64/Android Termux installations and add Node 25/26 to secure runtime policy (fixes #1924)
|
||||
- **fix(providers):** allow local OpenAI-compatible endpoints (like Ollama) to be added without an API key (fixes #1893)
|
||||
- **fix(providers):** bypass AgentRouter unauthorized_client_error by spoofing Claude CLI headers via Anthropic endpoints (fixes #1921)
|
||||
- **fix(copilot):** emit compatible reasoning text deltas (#1919 — thanks @ivan-mezentsev)
|
||||
@@ -44,8 +42,6 @@
|
||||
- **fix(migrations):** duplicate-column no-op fix (#1886 — thanks @smartenok-ops)
|
||||
- **fix(auth):** per-connection OAuth refresh mutex (#1885 — thanks @smartenok-ops)
|
||||
- **fix(auth):** require dashboard management auth for compression preview
|
||||
- **fix(mitm):** add root user and system-level certificate authority support for MITM proxy on Linux/Android (#1948)
|
||||
- **fix(registry):** remove deprecated GPT-5.5 pricing tiers, GPT-5.4-nano, and update Grok vision model catalog (#1949)
|
||||
|
||||
### 📝 Documentation
|
||||
|
||||
|
||||
@@ -934,11 +934,9 @@ function isCopilotClient(
|
||||
if (isMatch(userAgent)) return true;
|
||||
|
||||
if (headers instanceof Headers) {
|
||||
let found = false;
|
||||
headers.forEach((value, key) => {
|
||||
if (isMatch(key) || isMatch(value)) found = true;
|
||||
});
|
||||
if (found) return true;
|
||||
for (const [key, value] of headers) {
|
||||
if (isMatch(key) || isMatch(value)) return true;
|
||||
}
|
||||
} else if (headers && typeof headers === "object") {
|
||||
for (const [key, value] of Object.entries(headers)) {
|
||||
if (isMatch(key) || isMatch(value)) return true;
|
||||
|
||||
@@ -67,7 +67,7 @@ export function compressMcpDescription(description: string): DescriptionCompress
|
||||
.replace(/[ \t]{2,}/g, " ")
|
||||
.replace(/[ \t]+([,.;:!?])/g, "$1")
|
||||
.replace(/\n{3,}/g, "\n\n")
|
||||
.replace(/(^|[.!?]\s+|^\s+)([a-z])/gm, (_match, prefix: string, char: string) => {
|
||||
.replace(/(^|[.!?][ \t]+|\n+[ \t]*)([a-z])/g, (_match, prefix: string, char: string) => {
|
||||
return `${prefix}${char.toUpperCase()}`;
|
||||
})
|
||||
.trim();
|
||||
|
||||
@@ -216,9 +216,12 @@ function cleanupArtifacts(text: string): string {
|
||||
}
|
||||
|
||||
function recapitalizeSentences(text: string): string {
|
||||
return text.replace(/(^|[.!?]\s+|^\s+)([a-z])/gm, (_match, prefix: string, char: string) => {
|
||||
return `${prefix}${char.toUpperCase()}`;
|
||||
});
|
||||
return text.replace(
|
||||
/(^|[.!?][ \t]+|\n+[ \t]*)([a-z])/g,
|
||||
(_match, prefix: string, char: string) => {
|
||||
return `${prefix}${char.toUpperCase()}`;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function createCavemanStats(
|
||||
|
||||
@@ -67,13 +67,13 @@ export function validateCompression(original: string, compressed: string): Valid
|
||||
requireExactPresence("heading", collectMatches(original, /^#{1,6}\s+.+$/gm), compressed, errors);
|
||||
requireExactPresence(
|
||||
"table row",
|
||||
collectMatches(original, /^[ \t]*\|(?:[^|\n]*\|)+[ \t]*$/gm),
|
||||
collectMatches(original, /^[ \t]*\|(?:[^|\n]{0,1000}\|){1,100}[ \t]*$/gm),
|
||||
compressed,
|
||||
errors
|
||||
);
|
||||
requireExactPresence(
|
||||
"math block",
|
||||
collectMatches(original, /\$\$[^$]*(?:\$(?!\$)[^$]*)*\$\$/g),
|
||||
collectMatches(original, /\$\$[\s\S]{0,10000}?\$\$/g),
|
||||
compressed,
|
||||
errors
|
||||
);
|
||||
@@ -85,10 +85,7 @@ export function validateCompression(original: string, compressed: string): Valid
|
||||
);
|
||||
requireExactPresence(
|
||||
"LaTeX block",
|
||||
collectMatches(
|
||||
original,
|
||||
/\\begin\{[A-Za-z*]{1,50}\}(?:(?!\\end\{)[^])*\\end\{[A-Za-z*]{1,50}\}/g
|
||||
),
|
||||
collectMatches(original, /\\begin\{[A-Za-z*]{1,50}\}[\s\S]{0,10000}?\\end\{[A-Za-z*]{1,50}\}/g),
|
||||
compressed,
|
||||
errors
|
||||
);
|
||||
|
||||
101
package-lock.json
generated
101
package-lock.json
generated
@@ -13,29 +13,29 @@
|
||||
"open-sse"
|
||||
],
|
||||
"dependencies": {
|
||||
"@lobehub/icons": "^5.6.0",
|
||||
"@modelcontextprotocol/sdk": "^1.29.0",
|
||||
"@lobehub/icons": "^5.5.4",
|
||||
"@modelcontextprotocol/sdk": "^1.27.1",
|
||||
"@monaco-editor/react": "^4.7.0",
|
||||
"@ngrok/ngrok": "^1.7.0",
|
||||
"@swc/helpers": "0.5.21",
|
||||
"axios": "^1.16.0",
|
||||
"axios": "^1.15.0",
|
||||
"bcryptjs": "^3.0.3",
|
||||
"better-sqlite3": "^12.9.0",
|
||||
"better-sqlite3": "^12.6.2",
|
||||
"bottleneck": "^2.19.5",
|
||||
"express": "^5.2.1",
|
||||
"fetch-socks": "^1.3.3",
|
||||
"fetch-socks": "^1.3.2",
|
||||
"http-proxy-middleware": "^3.0.5",
|
||||
"https-proxy-agent": "^9.0.0",
|
||||
"jose": "^6.2.3",
|
||||
"js-yaml": "^4.1.1",
|
||||
"jose": "^6.1.3",
|
||||
"js-yaml": "^4.1.0",
|
||||
"jsonc-parser": "^3.3.1",
|
||||
"lowdb": "^7.0.1",
|
||||
"monaco-editor": "^0.55.1",
|
||||
"next": "^16.2.4",
|
||||
"next": "^16.2.3",
|
||||
"next-intl": "^4.11.0",
|
||||
"node-machine-id": "^1.1.12",
|
||||
"open": "^11.0.0",
|
||||
"ora": "^9.4.0",
|
||||
"ora": "^9.1.0",
|
||||
"pino": "^10.3.1",
|
||||
"pino-abstract-transport": "^3.0.0",
|
||||
"pino-pretty": "^13.1.3",
|
||||
@@ -43,56 +43,56 @@
|
||||
"react-dom": "19.2.5",
|
||||
"react-is": "^19.2.5",
|
||||
"react-markdown": "^10.1.0",
|
||||
"recharts": "^3.8.1",
|
||||
"recharts": "^3.7.0",
|
||||
"selfsigned": "^5.5.0",
|
||||
"tls-client-node": "^0.1.13",
|
||||
"tsx": "^4.21.0",
|
||||
"undici": "^8.2.0",
|
||||
"undici": "^8.1.0",
|
||||
"uuid": "^14.0.0",
|
||||
"wreq-js": "^2.0.1",
|
||||
"xxhash-wasm": "^1.1.0",
|
||||
"yazl": "^3.3.1",
|
||||
"zod": "^4.4.3",
|
||||
"zustand": "^5.0.12"
|
||||
"zod": "^4.3.6",
|
||||
"zustand": "^5.0.10"
|
||||
},
|
||||
"bin": {
|
||||
"omniroute": "bin/omniroute.mjs",
|
||||
"omniroute-reset-password": "bin/reset-password.mjs"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@playwright/test": "^1.59.1",
|
||||
"@tailwindcss/postcss": "^4.2.4",
|
||||
"@playwright/test": "^1.58.2",
|
||||
"@tailwindcss/postcss": "^4.1.18",
|
||||
"@testing-library/jest-dom": "^6.9.1",
|
||||
"@testing-library/react": "^16.3.2",
|
||||
"@types/bcryptjs": "^3.0.0",
|
||||
"@types/better-sqlite3": "^7.6.13",
|
||||
"@types/keytar": "^4.4.2",
|
||||
"@types/node": "^25.6.0",
|
||||
"@types/keytar": "^4.4.0",
|
||||
"@types/node": "^25.2.3",
|
||||
"@types/react": "^19.2.14",
|
||||
"@types/react-dom": "^19.2.3",
|
||||
"@vitejs/plugin-react": "^6.0.1",
|
||||
"c8": "^11.0.0",
|
||||
"concurrently": "^9.2.1",
|
||||
"cross-env": "^10.1.0",
|
||||
"eslint": "^9.39.4",
|
||||
"eslint": "^9.39.2",
|
||||
"eslint-config-next": "16.2.4",
|
||||
"husky": "^9.1.7",
|
||||
"jsdom": "^29.1.1",
|
||||
"lint-staged": "^16.4.0",
|
||||
"jsdom": "^29.0.1",
|
||||
"lint-staged": "^16.2.7",
|
||||
"node-loader": "^2.1.0",
|
||||
"prettier": "^3.8.3",
|
||||
"prettier": "^3.8.1",
|
||||
"tailwindcss": "^4",
|
||||
"typescript": "^6.0.3",
|
||||
"typescript-eslint": "^8.59.1",
|
||||
"vitest": "^4.1.5",
|
||||
"wait-on": "^9.0.5",
|
||||
"typescript": "^6.0.2",
|
||||
"typescript-eslint": "^8.56.0",
|
||||
"vitest": "^4.1.2",
|
||||
"wait-on": "^9.0.4",
|
||||
"wtfnode": "^0.10.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20.20.2 <21 || >=22.22.2 <23 || >=24.0.0 <27"
|
||||
"node": ">=20.20.2 <21 || >=22.22.2 <23 || >=24.0.0 <25"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"keytar": "^7.9.0",
|
||||
"wreq-js": "^2.3.0"
|
||||
"keytar": "^7.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@adobe/css-tools": {
|
||||
@@ -1487,9 +1487,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@hono/node-server": {
|
||||
"version": "1.19.14",
|
||||
"resolved": "https://registry.npmjs.org/@hono/node-server/-/node-server-1.19.14.tgz",
|
||||
"integrity": "sha512-GwtvgtXxnWsucXvbQXkRgqksiH2Qed37H9xHZocE5sA3N8O8O8/8FA3uclQXxXVzc9XBZuEOMK7+r02FmSpHtw==",
|
||||
"version": "1.19.13",
|
||||
"resolved": "https://registry.npmjs.org/@hono/node-server/-/node-server-1.19.13.tgz",
|
||||
"integrity": "sha512-TsQLe4i2gvoTtrHje625ngThGBySOgSK3Xo2XRYOdqGN1teR8+I7vchQC46uLJi8OF62YTYA3AhSpumtkhsaKQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18.14.1"
|
||||
@@ -5453,12 +5453,12 @@
|
||||
}
|
||||
},
|
||||
"node_modules/axios": {
|
||||
"version": "1.16.0",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.16.0.tgz",
|
||||
"integrity": "sha512-6hp5CwvTPlN2A31g5dxnwAX0orzM7pmCRDLnZSX772mv8WDqICwFjowHuPs04Mc8deIld1+ejhtaMn5vp6b+1w==",
|
||||
"version": "1.15.2",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.15.2.tgz",
|
||||
"integrity": "sha512-wLrXxPtcrPTsNlJmKjkPnNPK2Ihe0hn0wGSaTEiHRPxwjvJwT3hKmXF4dpqxmPO9SoNb2FsYXj/xEo0gHN+D5A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"follow-redirects": "^1.16.0",
|
||||
"follow-redirects": "^1.15.11",
|
||||
"form-data": "^4.0.5",
|
||||
"proxy-from-env": "^2.1.0"
|
||||
}
|
||||
@@ -8519,9 +8519,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/hono": {
|
||||
"version": "4.12.16",
|
||||
"resolved": "https://registry.npmjs.org/hono/-/hono-4.12.16.tgz",
|
||||
"integrity": "sha512-jN0ZewiNAWSe5khM3EyCmBb250+b40wWbwNILNfEvq84VREWwOIkuUsFONk/3i3nqkz7Oe1PcpM2mwQEK2L9Kg==",
|
||||
"version": "4.12.14",
|
||||
"resolved": "https://registry.npmjs.org/hono/-/hono-4.12.14.tgz",
|
||||
"integrity": "sha512-am5zfg3yu6sqn5yjKBNqhnTX7Cv+m00ox+7jbaKkrLMRJ4rAdldd1xPd/JzbBWspqaQv6RSTrgFN95EsfhC+7w==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=16.9.0"
|
||||
@@ -9570,9 +9570,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/jsdom": {
|
||||
"version": "29.1.1",
|
||||
"resolved": "https://registry.npmjs.org/jsdom/-/jsdom-29.1.1.tgz",
|
||||
"integrity": "sha512-ECi4Fi2f7BdJtUKTflYRTiaMxIB0O6zfR1fX0GXpUrf6flp8QIYn1UT20YQqdSOfk2dfkCwS8LAFoJDEppNK5Q==",
|
||||
"version": "29.1.0",
|
||||
"resolved": "https://registry.npmjs.org/jsdom/-/jsdom-29.1.0.tgz",
|
||||
"integrity": "sha512-YNUc7fB9QuvSSQWfrH0xF+TyABkxUwx8sswgIDaCrw4Hol8BghdZDkITtZheRJeMtzWlnTfsM3bBBusRvpO1wg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -11973,9 +11973,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/postcss": {
|
||||
"version": "8.5.13",
|
||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.13.tgz",
|
||||
"integrity": "sha512-qif0+jGGZoLWdHey3UFHHWP0H7Gbmsk8T5VEqyYFbWqPr1XqvLGBbk/sl8V5exGmcYJklJOhOQq1pV9IcsiFag==",
|
||||
"version": "8.5.10",
|
||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.10.tgz",
|
||||
"integrity": "sha512-pMMHxBOZKFU6HgAZ4eyGnwXF/EvPGGqUr0MnZ5+99485wwW41kW91A4LOGxSHhgugZmSChL5AlElNdwlNgcnLQ==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "opencollective",
|
||||
@@ -14220,9 +14220,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/undici": {
|
||||
"version": "8.2.0",
|
||||
"resolved": "https://registry.npmjs.org/undici/-/undici-8.2.0.tgz",
|
||||
"integrity": "sha512-Z+4Hx9GE26Lh9Upwfnc8C7SsrpBPGaM/Gm6kMFtiG7c+5IvQKlXi/t+9x9DrrCh29cww5TSP9YdVaBcnLDs5fQ==",
|
||||
"version": "8.1.0",
|
||||
"resolved": "https://registry.npmjs.org/undici/-/undici-8.1.0.tgz",
|
||||
"integrity": "sha512-E9MkTS4xXLnRPYqxH2e6Hr2/49e7WFDKczKcCaFH4VaZs2iNvHMqeIkyUAD9vM8kujy9TjVrRlQ5KkdEJxB2pw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=22.19.0"
|
||||
@@ -14991,7 +14991,6 @@
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin",
|
||||
"linux",
|
||||
@@ -15192,9 +15191,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/zod": {
|
||||
"version": "4.4.3",
|
||||
"resolved": "https://registry.npmjs.org/zod/-/zod-4.4.3.tgz",
|
||||
"integrity": "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==",
|
||||
"version": "4.3.6",
|
||||
"resolved": "https://registry.npmjs.org/zod/-/zod-4.3.6.tgz",
|
||||
"integrity": "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==",
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/colinhacks"
|
||||
|
||||
64
package.json
64
package.json
@@ -36,7 +36,7 @@
|
||||
"open-sse"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=20.20.2 <21 || >=22.22.2 <23 || >=24.0.0 <27"
|
||||
"node": ">=20.20.2 <21 || >=22.22.2 <23 || >=24.0.0 <25"
|
||||
},
|
||||
"keywords": [
|
||||
"ai",
|
||||
@@ -109,29 +109,29 @@
|
||||
"system-info": "node scripts/system-info.mjs"
|
||||
},
|
||||
"dependencies": {
|
||||
"@lobehub/icons": "^5.6.0",
|
||||
"@modelcontextprotocol/sdk": "^1.29.0",
|
||||
"@lobehub/icons": "^5.5.4",
|
||||
"@modelcontextprotocol/sdk": "^1.27.1",
|
||||
"@monaco-editor/react": "^4.7.0",
|
||||
"@ngrok/ngrok": "^1.7.0",
|
||||
"@swc/helpers": "0.5.21",
|
||||
"axios": "^1.16.0",
|
||||
"axios": "^1.15.0",
|
||||
"bcryptjs": "^3.0.3",
|
||||
"better-sqlite3": "^12.9.0",
|
||||
"better-sqlite3": "^12.6.2",
|
||||
"bottleneck": "^2.19.5",
|
||||
"express": "^5.2.1",
|
||||
"fetch-socks": "^1.3.3",
|
||||
"fetch-socks": "^1.3.2",
|
||||
"http-proxy-middleware": "^3.0.5",
|
||||
"https-proxy-agent": "^9.0.0",
|
||||
"jose": "^6.2.3",
|
||||
"js-yaml": "^4.1.1",
|
||||
"jose": "^6.1.3",
|
||||
"js-yaml": "^4.1.0",
|
||||
"jsonc-parser": "^3.3.1",
|
||||
"lowdb": "^7.0.1",
|
||||
"monaco-editor": "^0.55.1",
|
||||
"next": "^16.2.4",
|
||||
"next": "^16.2.3",
|
||||
"next-intl": "^4.11.0",
|
||||
"node-machine-id": "^1.1.12",
|
||||
"open": "^11.0.0",
|
||||
"ora": "^9.4.0",
|
||||
"ora": "^9.1.0",
|
||||
"pino": "^10.3.1",
|
||||
"pino-abstract-transport": "^3.0.0",
|
||||
"pino-pretty": "^13.1.3",
|
||||
@@ -139,48 +139,48 @@
|
||||
"react-dom": "19.2.5",
|
||||
"react-is": "^19.2.5",
|
||||
"react-markdown": "^10.1.0",
|
||||
"recharts": "^3.8.1",
|
||||
"recharts": "^3.7.0",
|
||||
"selfsigned": "^5.5.0",
|
||||
"tls-client-node": "^0.1.13",
|
||||
"tsx": "^4.21.0",
|
||||
"undici": "^8.2.0",
|
||||
"undici": "^8.1.0",
|
||||
"uuid": "^14.0.0",
|
||||
"wreq-js": "^2.0.1",
|
||||
"xxhash-wasm": "^1.1.0",
|
||||
"yazl": "^3.3.1",
|
||||
"zod": "^4.4.3",
|
||||
"zustand": "^5.0.12"
|
||||
"zod": "^4.3.6",
|
||||
"zustand": "^5.0.10"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"keytar": "^7.9.0",
|
||||
"wreq-js": "^2.3.0"
|
||||
"keytar": "^7.9.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@playwright/test": "^1.59.1",
|
||||
"@tailwindcss/postcss": "^4.2.4",
|
||||
"@playwright/test": "^1.58.2",
|
||||
"@tailwindcss/postcss": "^4.1.18",
|
||||
"@testing-library/jest-dom": "^6.9.1",
|
||||
"@testing-library/react": "^16.3.2",
|
||||
"@types/bcryptjs": "^3.0.0",
|
||||
"@types/better-sqlite3": "^7.6.13",
|
||||
"@types/keytar": "^4.4.2",
|
||||
"@types/node": "^25.6.0",
|
||||
"@types/keytar": "^4.4.0",
|
||||
"@types/node": "^25.2.3",
|
||||
"@types/react": "^19.2.14",
|
||||
"@types/react-dom": "^19.2.3",
|
||||
"@vitejs/plugin-react": "^6.0.1",
|
||||
"c8": "^11.0.0",
|
||||
"concurrently": "^9.2.1",
|
||||
"cross-env": "^10.1.0",
|
||||
"eslint": "^9.39.4",
|
||||
"eslint": "^9.39.2",
|
||||
"eslint-config-next": "16.2.4",
|
||||
"husky": "^9.1.7",
|
||||
"jsdom": "^29.1.1",
|
||||
"lint-staged": "^16.4.0",
|
||||
"jsdom": "^29.0.1",
|
||||
"lint-staged": "^16.2.7",
|
||||
"node-loader": "^2.1.0",
|
||||
"prettier": "^3.8.3",
|
||||
"prettier": "^3.8.1",
|
||||
"tailwindcss": "^4",
|
||||
"typescript": "^6.0.3",
|
||||
"typescript-eslint": "^8.59.1",
|
||||
"vitest": "^4.1.5",
|
||||
"wait-on": "^9.0.5",
|
||||
"typescript": "^6.0.2",
|
||||
"typescript-eslint": "^8.56.0",
|
||||
"vitest": "^4.1.2",
|
||||
"wait-on": "^9.0.4",
|
||||
"wtfnode": "^0.10.1"
|
||||
},
|
||||
"lint-staged": {
|
||||
@@ -205,10 +205,10 @@
|
||||
"overrides": {
|
||||
"lodash-es": "^4.18.1",
|
||||
"dompurify": "^3.4.2",
|
||||
"path-to-regexp": "^8.4.2",
|
||||
"postcss": "^8.5.13",
|
||||
"hono": "^4.12.16",
|
||||
"@hono/node-server": "^1.19.14",
|
||||
"path-to-regexp": "^8.4.0",
|
||||
"postcss": "^8.5.10",
|
||||
"hono": "^4.12.14",
|
||||
"@hono/node-server": "^1.19.13",
|
||||
"react": "$react",
|
||||
"react-dom": "$react-dom"
|
||||
}
|
||||
|
||||
@@ -64,44 +64,6 @@ function findKeyInsensitive(obj: Record<string, any> | undefined | null, key: st
|
||||
return obj[key.toLowerCase()];
|
||||
}
|
||||
|
||||
function uniqueValues(values: Array<string | null | undefined>): string[] {
|
||||
const seen = new Set<string>();
|
||||
const result: string[] = [];
|
||||
for (const value of values) {
|
||||
const normalized = typeof value === "string" ? value.trim().toLowerCase() : "";
|
||||
if (!normalized || seen.has(normalized)) continue;
|
||||
seen.add(normalized);
|
||||
result.push(normalized);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function stripCodexEffortSuffix(model: string): string {
|
||||
return model.replace(/-(?:xhigh|high|medium|low|none)$/i, "");
|
||||
}
|
||||
|
||||
function getPricingModelCandidates(
|
||||
model: string,
|
||||
normalizeModelName: (model: string) => string
|
||||
): string[] {
|
||||
const normalizedModel = normalizeModelName(model);
|
||||
const lowerModel = model.toLowerCase();
|
||||
const lowerNormalized = normalizedModel.toLowerCase();
|
||||
const hyphenModel = lowerModel.replace(/\./g, "-");
|
||||
const hyphenNormalized = lowerNormalized.replace(/\./g, "-");
|
||||
const effortBaseModel = stripCodexEffortSuffix(lowerNormalized);
|
||||
|
||||
return uniqueValues([
|
||||
lowerModel,
|
||||
lowerNormalized,
|
||||
hyphenModel,
|
||||
hyphenNormalized,
|
||||
effortBaseModel,
|
||||
effortBaseModel.replace(/\./g, "-"),
|
||||
lowerNormalized === "codex-auto-review" ? "gpt-5.5" : null,
|
||||
]);
|
||||
}
|
||||
|
||||
function resolveModelPricing(
|
||||
pricingByProvider: PricingByProvider,
|
||||
providerAliasMap: Record<string, string>,
|
||||
@@ -129,15 +91,22 @@ function resolveModelPricing(
|
||||
if (pLower === "antigravity") providerPricing = findKeyInsensitive(pricingByProvider, "ag");
|
||||
}
|
||||
|
||||
const modelCandidates = getPricingModelCandidates(model, normalizeModelName);
|
||||
const normalizedModel = normalizeModelName(model).toLowerCase();
|
||||
const shortModel = normalizedModel; // normalizeModelName behaves exactly like shortModelName
|
||||
const hyphenModel = model.toLowerCase().replace(/\./g, "-");
|
||||
const hyphenNormalized = normalizedModel.replace(/\./g, "-");
|
||||
const lowerModel = model.toLowerCase();
|
||||
|
||||
const tryFind = (prov: Record<string, unknown> | null | undefined) => {
|
||||
if (!prov || typeof prov !== "object") return null;
|
||||
for (const candidate of modelCandidates) {
|
||||
const pricing = findKeyInsensitive(prov as Record<string, unknown>, candidate);
|
||||
if (pricing) return pricing;
|
||||
}
|
||||
return null;
|
||||
return (
|
||||
findKeyInsensitive(prov as Record<string, unknown>, lowerModel) ||
|
||||
findKeyInsensitive(prov as Record<string, unknown>, normalizedModel) ||
|
||||
findKeyInsensitive(prov as Record<string, unknown>, shortModel) ||
|
||||
findKeyInsensitive(prov as Record<string, unknown>, hyphenModel) ||
|
||||
findKeyInsensitive(prov as Record<string, unknown>, hyphenNormalized) ||
|
||||
null
|
||||
);
|
||||
};
|
||||
|
||||
let pricing = providerPricing ? tryFind(providerPricing) : null;
|
||||
@@ -509,20 +478,10 @@ export async function GET(request: Request) {
|
||||
COUNT(*) as total,
|
||||
SUM(CASE WHEN requested_model IS NOT NULL AND requested_model != '' THEN 1 ELSE 0 END) as with_requested,
|
||||
SUM(CASE
|
||||
WHEN (combo_name IS NULL OR combo_name = '')
|
||||
AND requested_model IS NOT NULL
|
||||
WHEN requested_model IS NOT NULL
|
||||
AND requested_model != ''
|
||||
AND model IS NOT NULL
|
||||
AND model != ''
|
||||
THEN 1 ELSE 0 END
|
||||
) as fallback_eligible,
|
||||
SUM(CASE
|
||||
WHEN (combo_name IS NULL OR combo_name = '')
|
||||
AND requested_model IS NOT NULL
|
||||
AND requested_model != ''
|
||||
AND model IS NOT NULL
|
||||
AND model != ''
|
||||
AND LOWER(requested_model) != LOWER(model)
|
||||
AND requested_model != model
|
||||
THEN 1 ELSE 0 END
|
||||
) as fallbacks
|
||||
FROM call_logs
|
||||
@@ -556,11 +515,10 @@ export async function GET(request: Request) {
|
||||
lastRequest: summaryRow?.lastRequest || "",
|
||||
fallbackCount: Number(fallbackRow?.fallbacks || 0),
|
||||
fallbackRatePct:
|
||||
Number(fallbackRow?.fallback_eligible || 0) > 0
|
||||
Number(fallbackRow?.with_requested || 0) > 0
|
||||
? Number(
|
||||
(
|
||||
(Number(fallbackRow?.fallbacks || 0) /
|
||||
Number(fallbackRow?.fallback_eligible || 1)) *
|
||||
(Number(fallbackRow?.fallbacks || 0) / Number(fallbackRow?.with_requested || 1)) *
|
||||
100
|
||||
).toFixed(2)
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user