@adversity/coding-tool-x 3.1.2 → 3.1.3
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/CHANGELOG.md +17 -0
- package/dist/web/assets/Analytics-BIqc8Rin.css +1 -0
- package/dist/web/assets/Analytics-D2V09DHH.js +39 -0
- package/dist/web/assets/{ConfigTemplates-DvcbKKdS.js → ConfigTemplates-Bf_11LhH.js} +1 -1
- package/dist/web/assets/{Home-Cw-F_Wnu.js → Home-BRnW4FTS.js} +1 -1
- package/dist/web/assets/{Home-BJKPCBuk.css → Home-CyCIx4BA.css} +1 -1
- package/dist/web/assets/{PluginManager-jy_4GVxI.js → PluginManager-B9J32GhW.js} +1 -1
- package/dist/web/assets/{ProjectList-Df1-NcNr.js → ProjectList-5a19MWJk.js} +1 -1
- package/dist/web/assets/SessionList-CXUr6S7w.css +1 -0
- package/dist/web/assets/SessionList-Cxg5bAdT.js +1 -0
- package/dist/web/assets/{SkillManager-IRdseMKB.js → SkillManager-CVBr0CLi.js} +1 -1
- package/dist/web/assets/{Terminal-BasTyDut.js → Terminal-D2Xe_Q0H.js} +1 -1
- package/dist/web/assets/{WorkspaceManager-D-D2kK1V.js → WorkspaceManager-C7dwV94C.js} +1 -1
- package/dist/web/assets/icons-BxcwoY5F.js +1 -0
- package/dist/web/assets/index-BS9RA6SN.js +2 -0
- package/dist/web/assets/index-DUNAVDGb.css +1 -0
- package/dist/web/assets/naive-ui-BIXcURHZ.js +1 -0
- package/dist/web/assets/{vendors-CO3Upi1d.js → vendors-i5CBGnlm.js} +1 -1
- package/dist/web/assets/{vue-vendor-DqyWIXEb.js → vue-vendor-PKd8utv_.js} +1 -1
- package/dist/web/index.html +6 -6
- package/package.json +1 -1
- package/src/config/default.js +7 -29
- package/src/config/loader.js +6 -3
- package/src/config/model-metadata.js +102 -350
- package/src/config/model-metadata.json +125 -0
- package/src/server/api/channels.js +16 -39
- package/src/server/api/codex-channels.js +15 -43
- package/src/server/api/commands.js +0 -77
- package/src/server/api/config.js +4 -1
- package/src/server/api/gemini-channels.js +16 -40
- package/src/server/api/opencode-channels.js +25 -51
- package/src/server/api/opencode-proxy.js +1 -1
- package/src/server/api/opencode-sessions.js +0 -7
- package/src/server/api/sessions.js +11 -68
- package/src/server/api/settings.js +66 -39
- package/src/server/api/skills.js +0 -44
- package/src/server/api/statistics.js +115 -1
- package/src/server/codex-proxy-server.js +26 -55
- package/src/server/gemini-proxy-server.js +15 -14
- package/src/server/index.js +0 -3
- package/src/server/opencode-proxy-server.js +45 -121
- package/src/server/proxy-server.js +2 -4
- package/src/server/services/commands-service.js +0 -29
- package/src/server/services/config-templates-service.js +38 -28
- package/src/server/services/env-checker.js +73 -8
- package/src/server/services/plugins-service.js +37 -28
- package/src/server/services/pty-manager.js +22 -18
- package/src/server/services/skill-service.js +1 -49
- package/src/server/services/speed-test.js +40 -3
- package/src/server/services/statistics-service.js +238 -1
- package/src/server/utils/pricing.js +51 -60
- package/dist/web/assets/SessionList-BGJWyneI.css +0 -1
- package/dist/web/assets/SessionList-UWcZtC2r.js +0 -1
- package/dist/web/assets/icons-kcfLIMBB.js +0 -1
- package/dist/web/assets/index-CoB3zF0K.css +0 -1
- package/dist/web/assets/index-CryrSLv8.js +0 -2
- package/dist/web/assets/naive-ui-CSrLusZZ.js +0 -1
- package/src/server/api/convert.js +0 -260
- package/src/server/services/session-converter.js +0 -577
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{g as t,c as e,a as n}from"./markdown-C9MYpaSi.js";import{S as r}from"./vue-vendor-
|
|
1
|
+
import{g as t,c as e,a as n}from"./markdown-C9MYpaSi.js";import{S as r}from"./vue-vendor-PKd8utv_.js";var o={exports:{}};
|
|
2
2
|
/**!
|
|
3
3
|
* Sortable 1.14.0
|
|
4
4
|
* @author RubaXa <trash@rubaxa.org>
|
|
@@ -42,4 +42,4 @@ let lc;const cc=e=>lc=e,ac=Symbol();function uc(e){return e&&"object"==typeof e&
|
|
|
42
42
|
* vue-router v4.6.4
|
|
43
43
|
* (c) 2025 Eduardo San Martin Morote
|
|
44
44
|
* @license MIT
|
|
45
|
-
*/(e,t);n=Pa(o.reverse(),"beforeRouteLeave",e,t);for(const s of o)s.leaveGuards.forEach(o=>{n.push(Na(o,e,t))});const c=y.bind(null,e,t);return n.push(c),M(n).then(()=>{n=[];for(const o of s.list())n.push(Na(o,e,t));return n.push(c),M(n)}).then(()=>{n=Pa(r,"beforeRouteUpdate",e,t);for(const o of r)o.updateGuards.forEach(o=>{n.push(Na(o,e,t))});return n.push(c),M(n)}).then(()=>{n=[];for(const o of l)if(o.beforeEnter)if(Ic(o.beforeEnter))for(const r of o.beforeEnter)n.push(Na(r,e,t));else n.push(Na(o.beforeEnter,e,t));return n.push(c),M(n)}).then(()=>(e.matched.forEach(e=>e.enterCallbacks={}),n=Pa(l,"beforeRouteEnter",e,t,b),n.push(c),M(n))).then(()=>{n=[];for(const o of i.list())n.push(Na(o,e,t));return n.push(c),M(n)}).catch(e=>Ea(e,_a.NAVIGATION_CANCELLED)?e:Promise.reject(e))}function S(e,t,n){l.list().forEach(o=>b(()=>o(e,t,n)))}function C(e,t,n,o,s){const i=g(e,t);if(i)return i;const l=t===la,a=kc?history.state:{};n&&(o||l?r.replace(e.fullPath,Rc({scroll:l&&a&&a.scroll},s)):r.push(e.fullPath,s)),c.value=e,N(e,t,n,l),R()}let w;function x(){w||(w=r.listen((e,t,n)=>{if(!L.listening)return;const o=d(e),s=v(o,L.currentRoute.value);if(s)return void _(Rc(s,{replace:!0,force:!0}),o).catch(Pc);a=o;const i=c.value;var l,u;kc&&(l=ga(i.fullPath,n.delta),u=da(),ma.set(l,u)),E(o,i).catch(e=>Ea(e,_a.NAVIGATION_ABORTED|_a.NAVIGATION_CANCELLED)?e:Ea(e,_a.NAVIGATION_GUARD_REDIRECT)?(_(Rc(h(e.to),{force:!0}),o).then(e=>{Ea(e,_a.NAVIGATION_ABORTED|_a.NAVIGATION_DUPLICATED)&&!n.delta&&n.type===ca.pop&&r.go(-1,!1)}).catch(Pc),Promise.reject()):(n.delta&&r.go(-n.delta,!1),O(e,o,i))).then(e=>{(e=e||C(o,i,!1))&&(n.delta&&!Ea(e,_a.NAVIGATION_CANCELLED)?r.go(-n.delta,!1):n.type===ca.pop&&Ea(e,_a.NAVIGATION_ABORTED|_a.NAVIGATION_DUPLICATED)&&r.go(-1,!1)),S(o,i,e)}).catch(Pc)}))}let A,T=Ra(),k=Ra();function O(e,t,n){R(e);const o=k.list();return o.length&&o.forEach(o=>o(e,t,n)),Promise.reject(e)}function R(e){return A||(A=!e,x(),T.list().forEach(([t,n])=>e?n(e):t()),T.reset()),e}function N(t,n,o,r){const{scrollBehavior:s}=e;if(!kc||!s)return Promise.resolve();const i=!o&&function(e){const t=ma.get(e);return ma.delete(e),t}(ga(t.fullPath,0))||(r||!o)&&history.state&&history.state.scroll||null;return un().then(()=>s(t,n,i)).then(e=>e&&ha(e)).catch(e=>O(e,t,n))}const P=e=>r.go(e);let I;const D=new Set,L={currentRoute:c,listening:!0,addRoute:function(e,n){let o,r;return va(e)?(o=t.getRecordMatcher(e),r=n):r=e,t.addRoute(r,o)},removeRoute:function(e){const n=t.getRecordMatcher(e);n&&t.removeRoute(n)},clearRoutes:t.clearRoutes,hasRoute:function(e){return!!t.getRecordMatcher(e)},getRoutes:function(){return t.getRoutes().map(e=>e.record)},resolve:d,options:e,push:m,replace:function(e){return m(Rc(h(e),{replace:!0}))},go:P,back:()=>P(-1),forward:()=>P(1),beforeEach:s.add,beforeResolve:i.add,afterEach:l.add,onError:k.add,isReady:function(){return A&&c.value!==la?Promise.resolve():new Promise((e,t)=>{T.add([e,t])})},install(e){e.component("RouterLink",ru),e.component("RouterView",cu),e.config.globalProperties.$router=L,Object.defineProperty(e.config.globalProperties,"$route",{enumerable:!0,get:()=>Lt(c)}),kc&&!I&&c.value===la&&(I=!0,m(r.location).catch(e=>{}));const t={};for(const o in la)Object.defineProperty(t,o,{get:()=>c.value[o],enumerable:!0});e.provide(Ta,L),e.provide(ka,_t(t)),e.provide(Oa,c);const n=e.unmount;D.add(e),e.unmount=function(){D.delete(e),D.size<1&&(a=la,w&&w(),w=null,c.value=la,I=!1,A=!1),n()}}};function M(e){return e.reduce((e,t)=>e.then(()=>b(t)),Promise.resolve())}return L}function uu(){return Tn(Ta)}function fu(e){return Tn(ka)}const pu=e(ic);export{er as $,Pt as A,Nn as B,_s as C,Ni as D,wl as E,ms as F,qi as G,Ms as H,vs as I,Tt as J,Ho as K,K as L,tc as M,Lt as N,xt as O,At as P,Ut as Q,B as R,pu as S,Kn as T,au as U,Ma as V,js as W,Ds as X,Cn as Y,Kl as Z,Z as _,Is as a,ks as a0,Ac as a1,tr as a2,Xo as a3,Tc as a4,fu as a5,uu as a6,zl as a7,Yo as a8,ko as a9,dc as aa,Vs as b,Ts as c,ao as d,yt as e,fi as f,Ys as g,jo as h,$o as i,Vo as j,vt as k,Tn as l,Ro as m,No as n,Ss as o,Fs as p,An as q,Nt as r,wn as s,pi as t,Ht as u,un as v,In as w,nr as x,Hs as y,Os as z};
|
|
45
|
+
*/(e,t);n=Pa(o.reverse(),"beforeRouteLeave",e,t);for(const s of o)s.leaveGuards.forEach(o=>{n.push(Na(o,e,t))});const c=y.bind(null,e,t);return n.push(c),M(n).then(()=>{n=[];for(const o of s.list())n.push(Na(o,e,t));return n.push(c),M(n)}).then(()=>{n=Pa(r,"beforeRouteUpdate",e,t);for(const o of r)o.updateGuards.forEach(o=>{n.push(Na(o,e,t))});return n.push(c),M(n)}).then(()=>{n=[];for(const o of l)if(o.beforeEnter)if(Ic(o.beforeEnter))for(const r of o.beforeEnter)n.push(Na(r,e,t));else n.push(Na(o.beforeEnter,e,t));return n.push(c),M(n)}).then(()=>(e.matched.forEach(e=>e.enterCallbacks={}),n=Pa(l,"beforeRouteEnter",e,t,b),n.push(c),M(n))).then(()=>{n=[];for(const o of i.list())n.push(Na(o,e,t));return n.push(c),M(n)}).catch(e=>Ea(e,_a.NAVIGATION_CANCELLED)?e:Promise.reject(e))}function S(e,t,n){l.list().forEach(o=>b(()=>o(e,t,n)))}function C(e,t,n,o,s){const i=g(e,t);if(i)return i;const l=t===la,a=kc?history.state:{};n&&(o||l?r.replace(e.fullPath,Rc({scroll:l&&a&&a.scroll},s)):r.push(e.fullPath,s)),c.value=e,N(e,t,n,l),R()}let w;function x(){w||(w=r.listen((e,t,n)=>{if(!L.listening)return;const o=d(e),s=v(o,L.currentRoute.value);if(s)return void _(Rc(s,{replace:!0,force:!0}),o).catch(Pc);a=o;const i=c.value;var l,u;kc&&(l=ga(i.fullPath,n.delta),u=da(),ma.set(l,u)),E(o,i).catch(e=>Ea(e,_a.NAVIGATION_ABORTED|_a.NAVIGATION_CANCELLED)?e:Ea(e,_a.NAVIGATION_GUARD_REDIRECT)?(_(Rc(h(e.to),{force:!0}),o).then(e=>{Ea(e,_a.NAVIGATION_ABORTED|_a.NAVIGATION_DUPLICATED)&&!n.delta&&n.type===ca.pop&&r.go(-1,!1)}).catch(Pc),Promise.reject()):(n.delta&&r.go(-n.delta,!1),O(e,o,i))).then(e=>{(e=e||C(o,i,!1))&&(n.delta&&!Ea(e,_a.NAVIGATION_CANCELLED)?r.go(-n.delta,!1):n.type===ca.pop&&Ea(e,_a.NAVIGATION_ABORTED|_a.NAVIGATION_DUPLICATED)&&r.go(-1,!1)),S(o,i,e)}).catch(Pc)}))}let A,T=Ra(),k=Ra();function O(e,t,n){R(e);const o=k.list();return o.length&&o.forEach(o=>o(e,t,n)),Promise.reject(e)}function R(e){return A||(A=!e,x(),T.list().forEach(([t,n])=>e?n(e):t()),T.reset()),e}function N(t,n,o,r){const{scrollBehavior:s}=e;if(!kc||!s)return Promise.resolve();const i=!o&&function(e){const t=ma.get(e);return ma.delete(e),t}(ga(t.fullPath,0))||(r||!o)&&history.state&&history.state.scroll||null;return un().then(()=>s(t,n,i)).then(e=>e&&ha(e)).catch(e=>O(e,t,n))}const P=e=>r.go(e);let I;const D=new Set,L={currentRoute:c,listening:!0,addRoute:function(e,n){let o,r;return va(e)?(o=t.getRecordMatcher(e),r=n):r=e,t.addRoute(r,o)},removeRoute:function(e){const n=t.getRecordMatcher(e);n&&t.removeRoute(n)},clearRoutes:t.clearRoutes,hasRoute:function(e){return!!t.getRecordMatcher(e)},getRoutes:function(){return t.getRoutes().map(e=>e.record)},resolve:d,options:e,push:m,replace:function(e){return m(Rc(h(e),{replace:!0}))},go:P,back:()=>P(-1),forward:()=>P(1),beforeEach:s.add,beforeResolve:i.add,afterEach:l.add,onError:k.add,isReady:function(){return A&&c.value!==la?Promise.resolve():new Promise((e,t)=>{T.add([e,t])})},install(e){e.component("RouterLink",ru),e.component("RouterView",cu),e.config.globalProperties.$router=L,Object.defineProperty(e.config.globalProperties,"$route",{enumerable:!0,get:()=>Lt(c)}),kc&&!I&&c.value===la&&(I=!0,m(r.location).catch(e=>{}));const t={};for(const o in la)Object.defineProperty(t,o,{get:()=>c.value[o],enumerable:!0});e.provide(Ta,L),e.provide(ka,_t(t)),e.provide(Oa,c);const n=e.unmount;D.add(e),e.unmount=function(){D.delete(e),D.size<1&&(a=la,w&&w(),w=null,c.value=la,I=!1,A=!1),n()}}};function M(e){return e.reduce((e,t)=>e.then(()=>b(t)),Promise.resolve())}return L}function uu(){return Tn(Ta)}function fu(e){return Tn(ka)}const pu=e(ic);export{er as $,Pt as A,Nn as B,_s as C,Ni as D,wl as E,ms as F,qi as G,Ms as H,vs as I,Tt as J,Ho as K,K as L,tc as M,Lt as N,xt as O,At as P,Ut as Q,B as R,pu as S,Kn as T,au as U,Ma as V,js as W,Ds as X,Cn as Y,Kl as Z,Z as _,Is as a,ks as a0,Ac as a1,tr as a2,Xo as a3,Tc as a4,fu as a5,uu as a6,zl as a7,Yo as a8,ko as a9,dc as aa,Rt as ab,Vs as b,Ts as c,ao as d,yt as e,fi as f,Ys as g,jo as h,$o as i,Vo as j,vt as k,Tn as l,Ro as m,No as n,Ss as o,Fs as p,An as q,Nt as r,wn as s,pi as t,Ht as u,un as v,In as w,nr as x,Hs as y,Os as z};
|
package/dist/web/index.html
CHANGED
|
@@ -5,14 +5,14 @@
|
|
|
5
5
|
<link rel="icon" href="/favicon.ico">
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
7
7
|
<title>CC-TOOL - ClaudeCode增强工作助手</title>
|
|
8
|
-
<script type="module" crossorigin src="/assets/index-
|
|
8
|
+
<script type="module" crossorigin src="/assets/index-BS9RA6SN.js"></script>
|
|
9
9
|
<link rel="modulepreload" crossorigin href="/assets/markdown-C9MYpaSi.js">
|
|
10
|
-
<link rel="modulepreload" crossorigin href="/assets/vue-vendor-
|
|
11
|
-
<link rel="modulepreload" crossorigin href="/assets/vendors-
|
|
12
|
-
<link rel="modulepreload" crossorigin href="/assets/naive-ui-
|
|
13
|
-
<link rel="modulepreload" crossorigin href="/assets/icons-
|
|
10
|
+
<link rel="modulepreload" crossorigin href="/assets/vue-vendor-PKd8utv_.js">
|
|
11
|
+
<link rel="modulepreload" crossorigin href="/assets/vendors-i5CBGnlm.js">
|
|
12
|
+
<link rel="modulepreload" crossorigin href="/assets/naive-ui-BIXcURHZ.js">
|
|
13
|
+
<link rel="modulepreload" crossorigin href="/assets/icons-BxcwoY5F.js">
|
|
14
14
|
<link rel="stylesheet" crossorigin href="/assets/markdown-BfC0goYb.css">
|
|
15
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
15
|
+
<link rel="stylesheet" crossorigin href="/assets/index-DUNAVDGb.css">
|
|
16
16
|
</head>
|
|
17
17
|
<body>
|
|
18
18
|
<div id="app"></div>
|
package/package.json
CHANGED
package/src/config/default.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// 默认配置
|
|
2
2
|
const path = require('path');
|
|
3
3
|
const os = require('os');
|
|
4
|
+
const modelMetadataConfig = require('./model-metadata.json');
|
|
4
5
|
|
|
5
6
|
const DEFAULT_CONFIG = {
|
|
6
7
|
projectsDir: path.join(os.homedir(), '.claude', 'projects'),
|
|
@@ -17,38 +18,15 @@ const DEFAULT_CONFIG = {
|
|
|
17
18
|
},
|
|
18
19
|
maxLogs: 100,
|
|
19
20
|
statsInterval: 30,
|
|
20
|
-
defaultModels: {
|
|
21
|
-
claude: [
|
|
22
|
-
'claude-opus-4-6',
|
|
23
|
-
'claude-sonnet-4-6',
|
|
24
|
-
'claude-opus-4-5-20251101',
|
|
25
|
-
'claude-sonnet-4-5-20250929',
|
|
26
|
-
'claude-haiku-4-5-20251001'
|
|
27
|
-
],
|
|
28
|
-
codex: [
|
|
29
|
-
'gpt-5.3-codex',
|
|
30
|
-
'gpt-5.2-codex',
|
|
31
|
-
'gpt-5.1-codex-max',
|
|
32
|
-
'gpt-5.1-codex',
|
|
33
|
-
'gpt-5.1-codex-mini',
|
|
34
|
-
'gpt-5-codex',
|
|
35
|
-
'gpt-5.2',
|
|
36
|
-
'gpt-5.1',
|
|
37
|
-
'gpt-5'
|
|
38
|
-
],
|
|
39
|
-
gemini: [
|
|
40
|
-
'gemini-3.1-pro',
|
|
41
|
-
'gemini-3-pro-preview',
|
|
42
|
-
'gemini-3-flash-preview',
|
|
43
|
-
'gemini-2.5-pro',
|
|
44
|
-
'gemini-2.5-flash',
|
|
45
|
-
'gemini-2.5-flash-lite'
|
|
46
|
-
]
|
|
47
|
-
},
|
|
48
21
|
modelDiscovery: {
|
|
49
|
-
// 是否优先使用 /v1/models 获取可用模型;默认关闭,直接走默认模型探测
|
|
50
22
|
useV1ModelsEndpoint: false
|
|
51
23
|
},
|
|
24
|
+
defaultModels: modelMetadataConfig.defaultModels || { claude: [], codex: [], gemini: [] },
|
|
25
|
+
defaultSpeedTestModels: modelMetadataConfig.defaultSpeedTestModels || {
|
|
26
|
+
claude: 'claude-haiku-4-5',
|
|
27
|
+
codex: 'gpt-5.2',
|
|
28
|
+
gemini: 'gemini-2.5-pro'
|
|
29
|
+
},
|
|
52
30
|
pricing: {
|
|
53
31
|
claude: {
|
|
54
32
|
mode: 'auto',
|
package/src/config/loader.js
CHANGED
|
@@ -49,9 +49,9 @@ function mergeDefaultModels(defaultModels, overrides = {}) {
|
|
|
49
49
|
return merged;
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
function
|
|
52
|
+
function mergeDefaultSpeedTestModels(defaultModels, overrides = {}) {
|
|
53
53
|
return {
|
|
54
|
-
...
|
|
54
|
+
...defaultModels,
|
|
55
55
|
...(overrides || {})
|
|
56
56
|
};
|
|
57
57
|
}
|
|
@@ -99,7 +99,10 @@ function loadConfig() {
|
|
|
99
99
|
config.ports = { ...DEFAULT_CONFIG.ports, ...userConfig.ports };
|
|
100
100
|
config.pricing = mergePricing(DEFAULT_CONFIG.pricing, userConfig.pricing);
|
|
101
101
|
config.defaultModels = mergeDefaultModels(DEFAULT_CONFIG.defaultModels, userConfig.defaultModels);
|
|
102
|
-
config.
|
|
102
|
+
config.defaultSpeedTestModels = mergeDefaultSpeedTestModels(
|
|
103
|
+
DEFAULT_CONFIG.defaultSpeedTestModels,
|
|
104
|
+
userConfig.defaultSpeedTestModels
|
|
105
|
+
);
|
|
103
106
|
|
|
104
107
|
// 确保有 currentProject,使用 defaultProject 作为 currentProject
|
|
105
108
|
if (!config.currentProject && config.defaultProject) {
|
|
@@ -1,344 +1,44 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
* Single source of truth for all mainstream Claude, Codex (OpenAI), and Gemini model metadata.
|
|
5
|
-
* Includes:
|
|
6
|
-
* - limit: context window (tokens) and max output (tokens)
|
|
7
|
-
* - pricing: input/output/cache prices in USD per million tokens
|
|
8
|
-
*
|
|
9
|
-
* Sources (as of 2026-02):
|
|
10
|
-
* - Claude: https://docs.anthropic.com/en/docs/about-claude/models
|
|
11
|
-
* - OpenAI: https://platform.openai.com/docs/models
|
|
12
|
-
* - Gemini: https://ai.google.dev/gemini-api/docs/models
|
|
2
|
+
* Model metadata runtime helpers.
|
|
3
|
+
* Data source: ./model-metadata.json
|
|
13
4
|
*/
|
|
14
5
|
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
'
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
},
|
|
29
|
-
|
|
30
|
-
// ─── Claude 4.5 ───────────────────────────────────────────────────────────
|
|
31
|
-
'claude-opus-4-5': {
|
|
32
|
-
limit: { context: 200000, output: 32000 },
|
|
33
|
-
pricing: { input: 5, output: 25, cacheCreation: 6.25, cacheRead: 0.50 }
|
|
34
|
-
},
|
|
35
|
-
'claude-opus-4-5-20250929': {
|
|
36
|
-
limit: { context: 200000, output: 32000 },
|
|
37
|
-
pricing: { input: 5, output: 25, cacheCreation: 6.25, cacheRead: 0.50 }
|
|
38
|
-
},
|
|
39
|
-
'claude-opus-4-5-20251101': {
|
|
40
|
-
limit: { context: 200000, output: 32000 },
|
|
41
|
-
pricing: { input: 5, output: 25, cacheCreation: 6.25, cacheRead: 0.50 }
|
|
42
|
-
},
|
|
43
|
-
'claude-sonnet-4-5': {
|
|
44
|
-
limit: { context: 200000, output: 64000 },
|
|
45
|
-
pricing: { input: 3, output: 15, cacheCreation: 3.75, cacheRead: 0.30 }
|
|
46
|
-
},
|
|
47
|
-
'claude-sonnet-4-5-20250929': {
|
|
48
|
-
limit: { context: 200000, output: 64000 },
|
|
49
|
-
pricing: { input: 3, output: 15, cacheCreation: 3.75, cacheRead: 0.30 }
|
|
50
|
-
},
|
|
51
|
-
'claude-haiku-4-5': {
|
|
52
|
-
limit: { context: 200000, output: 8096 },
|
|
53
|
-
pricing: { input: 1, output: 5, cacheCreation: 1.25, cacheRead: 0.10 }
|
|
54
|
-
},
|
|
55
|
-
'claude-haiku-4-5-20250929': {
|
|
56
|
-
limit: { context: 200000, output: 8096 },
|
|
57
|
-
pricing: { input: 1, output: 5, cacheCreation: 1.25, cacheRead: 0.10 }
|
|
58
|
-
},
|
|
59
|
-
'claude-haiku-4-5-20251001': {
|
|
60
|
-
limit: { context: 200000, output: 8096 },
|
|
61
|
-
pricing: { input: 1, output: 5, cacheCreation: 1.25, cacheRead: 0.10 }
|
|
62
|
-
},
|
|
63
|
-
|
|
64
|
-
// ─── Claude 4 ─────────────────────────────────────────────────────────────
|
|
65
|
-
'claude-opus-4': {
|
|
66
|
-
limit: { context: 200000, output: 32000 },
|
|
67
|
-
pricing: { input: 5, output: 25, cacheCreation: 6.25, cacheRead: 0.50 }
|
|
68
|
-
},
|
|
69
|
-
'claude-opus-4-20250514': {
|
|
70
|
-
limit: { context: 200000, output: 32000 },
|
|
71
|
-
pricing: { input: 5, output: 25, cacheCreation: 6.25, cacheRead: 0.50 }
|
|
72
|
-
},
|
|
73
|
-
'claude-sonnet-4': {
|
|
74
|
-
limit: { context: 200000, output: 64000 },
|
|
75
|
-
pricing: { input: 3, output: 15, cacheCreation: 3.75, cacheRead: 0.30 }
|
|
76
|
-
},
|
|
77
|
-
'claude-sonnet-4-20250514': {
|
|
78
|
-
limit: { context: 200000, output: 64000 },
|
|
79
|
-
pricing: { input: 3, output: 15, cacheCreation: 3.75, cacheRead: 0.30 }
|
|
80
|
-
},
|
|
81
|
-
|
|
82
|
-
// ─── Claude 3.7 ───────────────────────────────────────────────────────────
|
|
83
|
-
'claude-sonnet-3-7': {
|
|
84
|
-
limit: { context: 200000, output: 64000 },
|
|
85
|
-
pricing: { input: 3, output: 15, cacheCreation: 3.75, cacheRead: 0.30 }
|
|
86
|
-
},
|
|
87
|
-
'claude-sonnet-3-7-20250219': {
|
|
88
|
-
limit: { context: 200000, output: 64000 },
|
|
89
|
-
pricing: { input: 3, output: 15, cacheCreation: 3.75, cacheRead: 0.30 }
|
|
90
|
-
},
|
|
91
|
-
|
|
92
|
-
// ─── Claude 3.5 ───────────────────────────────────────────────────────────
|
|
93
|
-
'claude-sonnet-3-5': {
|
|
94
|
-
limit: { context: 200000, output: 8096 },
|
|
95
|
-
pricing: { input: 3, output: 15, cacheCreation: 3.75, cacheRead: 0.30 }
|
|
96
|
-
},
|
|
97
|
-
'claude-sonnet-3-5-20241022': {
|
|
98
|
-
limit: { context: 200000, output: 8096 },
|
|
99
|
-
pricing: { input: 3, output: 15, cacheCreation: 3.75, cacheRead: 0.30 }
|
|
100
|
-
},
|
|
101
|
-
'claude-sonnet-3-5-20240620': {
|
|
102
|
-
limit: { context: 200000, output: 8096 },
|
|
103
|
-
pricing: { input: 3, output: 15, cacheCreation: 3.75, cacheRead: 0.30 }
|
|
104
|
-
},
|
|
105
|
-
'claude-3-5-sonnet-20241022': {
|
|
106
|
-
limit: { context: 200000, output: 8096 },
|
|
107
|
-
pricing: { input: 3, output: 15, cacheCreation: 3.75, cacheRead: 0.30 }
|
|
108
|
-
},
|
|
109
|
-
'claude-3-5-sonnet-20240620': {
|
|
110
|
-
limit: { context: 200000, output: 8096 },
|
|
111
|
-
pricing: { input: 3, output: 15, cacheCreation: 3.75, cacheRead: 0.30 }
|
|
112
|
-
},
|
|
113
|
-
'claude-haiku-3-5': {
|
|
114
|
-
limit: { context: 200000, output: 8096 },
|
|
115
|
-
pricing: { input: 1, output: 5, cacheCreation: 1.25, cacheRead: 0.10 }
|
|
116
|
-
},
|
|
117
|
-
'claude-haiku-3-5-20241022': {
|
|
118
|
-
limit: { context: 200000, output: 8096 },
|
|
119
|
-
pricing: { input: 1, output: 5, cacheCreation: 1.25, cacheRead: 0.10 }
|
|
120
|
-
},
|
|
121
|
-
'claude-haiku-3-5-20250307': {
|
|
122
|
-
limit: { context: 200000, output: 8096 },
|
|
123
|
-
pricing: { input: 1, output: 5, cacheCreation: 1.25, cacheRead: 0.10 }
|
|
124
|
-
},
|
|
125
|
-
'claude-3-5-haiku-20241022': {
|
|
126
|
-
limit: { context: 200000, output: 8096 },
|
|
127
|
-
pricing: { input: 1, output: 5, cacheCreation: 1.25, cacheRead: 0.10 }
|
|
128
|
-
},
|
|
129
|
-
|
|
130
|
-
// ─── Claude 3 (legacy) ────────────────────────────────────────────────────
|
|
131
|
-
'claude-opus-3': {
|
|
132
|
-
limit: { context: 200000, output: 4096 },
|
|
133
|
-
pricing: { input: 15, output: 75, cacheCreation: 18.75, cacheRead: 1.50 }
|
|
134
|
-
},
|
|
135
|
-
'claude-opus-3-20240229': {
|
|
136
|
-
limit: { context: 200000, output: 4096 },
|
|
137
|
-
pricing: { input: 15, output: 75, cacheCreation: 18.75, cacheRead: 1.50 }
|
|
138
|
-
},
|
|
139
|
-
'claude-3-opus-20240229': {
|
|
140
|
-
limit: { context: 200000, output: 4096 },
|
|
141
|
-
pricing: { input: 15, output: 75, cacheCreation: 18.75, cacheRead: 1.50 }
|
|
142
|
-
},
|
|
143
|
-
|
|
144
|
-
// ─── OpenAI GPT-4o ────────────────────────────────────────────────────────
|
|
145
|
-
'gpt-4o': {
|
|
146
|
-
limit: { context: 128000, output: 16384 },
|
|
147
|
-
pricing: { input: 2.50, output: 10.00 }
|
|
148
|
-
},
|
|
149
|
-
'gpt-4o-2024-11-20': {
|
|
150
|
-
limit: { context: 128000, output: 16384 },
|
|
151
|
-
pricing: { input: 2.50, output: 10.00 }
|
|
152
|
-
},
|
|
153
|
-
'gpt-4o-2024-08-06': {
|
|
154
|
-
limit: { context: 128000, output: 16384 },
|
|
155
|
-
pricing: { input: 2.50, output: 10.00 }
|
|
156
|
-
},
|
|
157
|
-
'gpt-4o-mini': {
|
|
158
|
-
limit: { context: 128000, output: 16384 },
|
|
159
|
-
pricing: { input: 0.15, output: 0.60 }
|
|
160
|
-
},
|
|
161
|
-
'gpt-4o-mini-2024-07-18': {
|
|
162
|
-
limit: { context: 128000, output: 16384 },
|
|
163
|
-
pricing: { input: 0.15, output: 0.60 }
|
|
164
|
-
},
|
|
165
|
-
'gpt-4-turbo': {
|
|
166
|
-
limit: { context: 128000, output: 4096 },
|
|
167
|
-
pricing: { input: 10.00, output: 30.00 }
|
|
168
|
-
},
|
|
169
|
-
|
|
170
|
-
// ─── OpenAI o-series ──────────────────────────────────────────────────────
|
|
171
|
-
'o1': {
|
|
172
|
-
limit: { context: 200000, output: 100000 },
|
|
173
|
-
pricing: { input: 15.00, output: 60.00 }
|
|
174
|
-
},
|
|
175
|
-
'o1-2024-12-17': {
|
|
176
|
-
limit: { context: 200000, output: 100000 },
|
|
177
|
-
pricing: { input: 15.00, output: 60.00 }
|
|
178
|
-
},
|
|
179
|
-
'o1-mini': {
|
|
180
|
-
limit: { context: 128000, output: 65536 },
|
|
181
|
-
pricing: { input: 1.10, output: 4.40 }
|
|
182
|
-
},
|
|
183
|
-
'o1-mini-2024-09-12': {
|
|
184
|
-
limit: { context: 128000, output: 65536 },
|
|
185
|
-
pricing: { input: 1.10, output: 4.40 }
|
|
186
|
-
},
|
|
187
|
-
'o3': {
|
|
188
|
-
limit: { context: 200000, output: 100000 },
|
|
189
|
-
pricing: { input: 10.00, output: 40.00 }
|
|
190
|
-
},
|
|
191
|
-
'o3-mini': {
|
|
192
|
-
limit: { context: 200000, output: 100000 },
|
|
193
|
-
pricing: { input: 1.10, output: 4.40 }
|
|
194
|
-
},
|
|
195
|
-
'o3-mini-2025-01-31': {
|
|
196
|
-
limit: { context: 200000, output: 100000 },
|
|
197
|
-
pricing: { input: 1.10, output: 4.40 }
|
|
198
|
-
},
|
|
199
|
-
'o4-mini': {
|
|
200
|
-
limit: { context: 200000, output: 100000 },
|
|
201
|
-
pricing: { input: 1.10, output: 4.40 }
|
|
202
|
-
},
|
|
203
|
-
|
|
204
|
-
// ─── OpenAI GPT-5 / Codex ─────────────────────────────────────────────────
|
|
205
|
-
'gpt-5': {
|
|
206
|
-
limit: { context: 1000000, output: 32768 },
|
|
207
|
-
pricing: { input: 2.00, output: 8.00 }
|
|
208
|
-
},
|
|
209
|
-
'gpt-5.1': {
|
|
210
|
-
limit: { context: 1000000, output: 32768 },
|
|
211
|
-
pricing: { input: 2.00, output: 8.00 }
|
|
212
|
-
},
|
|
213
|
-
'gpt-5.2': {
|
|
214
|
-
limit: { context: 1000000, output: 32768 },
|
|
215
|
-
pricing: { input: 2.00, output: 8.00 }
|
|
216
|
-
},
|
|
217
|
-
'gpt-5-codex': {
|
|
218
|
-
limit: { context: 1000000, output: 32768 },
|
|
219
|
-
pricing: { input: 2.00, output: 8.00 }
|
|
220
|
-
},
|
|
221
|
-
'gpt-5.1-codex': {
|
|
222
|
-
limit: { context: 1000000, output: 32768 },
|
|
223
|
-
pricing: { input: 2.00, output: 8.00 }
|
|
224
|
-
},
|
|
225
|
-
'gpt-5.1-codex-mini': {
|
|
226
|
-
limit: { context: 1000000, output: 32768 },
|
|
227
|
-
pricing: { input: 1.50, output: 6.00 }
|
|
228
|
-
},
|
|
229
|
-
'gpt-5.1-codex-max': {
|
|
230
|
-
limit: { context: 1000000, output: 32768 },
|
|
231
|
-
pricing: { input: 3.00, output: 12.00 }
|
|
232
|
-
},
|
|
233
|
-
'gpt-5.2-codex': {
|
|
234
|
-
limit: { context: 1000000, output: 32768 },
|
|
235
|
-
pricing: { input: 2.00, output: 8.00 }
|
|
236
|
-
},
|
|
237
|
-
'gpt-5.3-codex': {
|
|
238
|
-
limit: { context: 1000000, output: 32768 },
|
|
239
|
-
pricing: { input: 2.00, output: 8.00 }
|
|
240
|
-
},
|
|
241
|
-
|
|
242
|
-
// ─── Gemini 2.5 ───────────────────────────────────────────────────────────
|
|
243
|
-
'gemini-2.5-pro': {
|
|
244
|
-
limit: { context: 1048576, output: 65536 },
|
|
245
|
-
pricing: { input: 1.25, output: 10.00 }
|
|
246
|
-
},
|
|
247
|
-
'gemini-2.5-pro-preview': {
|
|
248
|
-
limit: { context: 1048576, output: 65536 },
|
|
249
|
-
pricing: { input: 1.25, output: 10.00 }
|
|
250
|
-
},
|
|
251
|
-
'gemini-2.5-pro-exp-03-25': {
|
|
252
|
-
limit: { context: 1048576, output: 65536 },
|
|
253
|
-
pricing: { input: 1.25, output: 10.00 }
|
|
254
|
-
},
|
|
255
|
-
'gemini-2.5-flash': {
|
|
256
|
-
limit: { context: 1048576, output: 65536 },
|
|
257
|
-
pricing: { input: 0.15, output: 0.60 }
|
|
258
|
-
},
|
|
259
|
-
'gemini-2.5-flash-preview': {
|
|
260
|
-
limit: { context: 1048576, output: 65536 },
|
|
261
|
-
pricing: { input: 0.15, output: 0.60 }
|
|
262
|
-
},
|
|
263
|
-
'gemini-2.5-flash-lite': {
|
|
264
|
-
limit: { context: 1048576, output: 65536 },
|
|
265
|
-
pricing: { input: 0.10, output: 0.40 }
|
|
266
|
-
},
|
|
267
|
-
|
|
268
|
-
// ─── Gemini 2.0 ───────────────────────────────────────────────────────────
|
|
269
|
-
'gemini-2.0-flash': {
|
|
270
|
-
limit: { context: 1048576, output: 8192 },
|
|
271
|
-
pricing: { input: 0.10, output: 0.40 }
|
|
272
|
-
},
|
|
273
|
-
'gemini-2.0-flash-exp': {
|
|
274
|
-
limit: { context: 1048576, output: 8192 },
|
|
275
|
-
pricing: { input: 0.10, output: 0.40 }
|
|
276
|
-
},
|
|
277
|
-
'gemini-2.0-flash-lite': {
|
|
278
|
-
limit: { context: 1048576, output: 8192 },
|
|
279
|
-
pricing: { input: 0.075, output: 0.30 }
|
|
280
|
-
},
|
|
6
|
+
const fs = require('fs');
|
|
7
|
+
const path = require('path');
|
|
8
|
+
const metadataConfig = require('./model-metadata.json');
|
|
9
|
+
const METADATA_FILE_PATH = path.join(__dirname, 'model-metadata.json');
|
|
10
|
+
|
|
11
|
+
const MODEL_METADATA = metadataConfig.models || {};
|
|
12
|
+
const MODEL_ALIASES = metadataConfig.aliases || {};
|
|
13
|
+
const DEFAULT_MODELS = metadataConfig.defaultModels || { claude: [], codex: [], gemini: [] };
|
|
14
|
+
const DEFAULT_SPEED_TEST_MODELS = metadataConfig.defaultSpeedTestModels || {
|
|
15
|
+
claude: 'claude-haiku-4-5',
|
|
16
|
+
codex: 'gpt-5.2',
|
|
17
|
+
gemini: 'gemini-2.5-pro'
|
|
18
|
+
};
|
|
281
19
|
|
|
282
|
-
|
|
283
|
-
'
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
'gemini-1.5-pro-002': {
|
|
288
|
-
limit: { context: 2097152, output: 8192 },
|
|
289
|
-
pricing: { input: 1.25, output: 5.00 }
|
|
290
|
-
},
|
|
291
|
-
'gemini-1.5-flash': {
|
|
292
|
-
limit: { context: 1048576, output: 8192 },
|
|
293
|
-
pricing: { input: 0.075, output: 0.30 }
|
|
294
|
-
},
|
|
295
|
-
'gemini-1.5-flash-002': {
|
|
296
|
-
limit: { context: 1048576, output: 8192 },
|
|
297
|
-
pricing: { input: 0.075, output: 0.30 }
|
|
298
|
-
},
|
|
299
|
-
'gemini-1.5-flash-8b': {
|
|
300
|
-
limit: { context: 1048576, output: 8192 },
|
|
301
|
-
pricing: { input: 0.0375, output: 0.15 }
|
|
302
|
-
},
|
|
20
|
+
function normalizeNonEmptyString(value) {
|
|
21
|
+
if (typeof value !== 'string') return null;
|
|
22
|
+
const trimmed = value.trim();
|
|
23
|
+
return trimmed || null;
|
|
24
|
+
}
|
|
303
25
|
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
'gemini-3-flash-preview': {
|
|
314
|
-
limit: { context: 1048576, output: 65536 },
|
|
315
|
-
pricing: { input: 0.30, output: 1.20 }
|
|
26
|
+
function loadMetadataConfigFromFile() {
|
|
27
|
+
try {
|
|
28
|
+
const raw = fs.readFileSync(METADATA_FILE_PATH, 'utf8');
|
|
29
|
+
const parsed = JSON.parse(raw);
|
|
30
|
+
if (parsed && typeof parsed === 'object') {
|
|
31
|
+
return parsed;
|
|
32
|
+
}
|
|
33
|
+
} catch (error) {
|
|
34
|
+
console.warn(`[model-metadata] Failed to read metadata file, fallback to in-memory config: ${error.message}`);
|
|
316
35
|
}
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
/**
|
|
320
|
-
* Model aliases: short name → canonical model ID
|
|
321
|
-
* Used for prefix/alias lookups
|
|
322
|
-
*/
|
|
323
|
-
const MODEL_ALIASES = {
|
|
324
|
-
// Claude aliases
|
|
325
|
-
'claude-opus-4-6': 'claude-opus-4-6',
|
|
326
|
-
'claude-sonnet-4-6': 'claude-sonnet-4-6',
|
|
327
|
-
'claude-haiku-4-6': 'claude-haiku-4-6',
|
|
328
|
-
'claude-opus-4-5': 'claude-opus-4-5-20250929',
|
|
329
|
-
'claude-sonnet-4-5': 'claude-sonnet-4-5-20250929',
|
|
330
|
-
'claude-haiku-4-5': 'claude-haiku-4-5-20250929',
|
|
331
|
-
'claude-opus-4': 'claude-opus-4-20250514',
|
|
332
|
-
'claude-sonnet-4': 'claude-sonnet-4-20250514',
|
|
333
|
-
'claude-sonnet-3-7': 'claude-sonnet-3-7-20250219',
|
|
334
|
-
'claude-haiku-3-5': 'claude-haiku-3-5-20241022',
|
|
335
|
-
'claude-sonnet-3-5': 'claude-sonnet-3-5-20241022',
|
|
336
|
-
'claude-opus-3': 'claude-opus-3-20240229'
|
|
337
|
-
};
|
|
36
|
+
return metadataConfig;
|
|
37
|
+
}
|
|
338
38
|
|
|
339
39
|
/**
|
|
340
40
|
* Resolve model metadata (limit + pricing) for a given model ID.
|
|
341
|
-
* Supports: exact match
|
|
41
|
+
* Supports: exact match -> alias match -> prefix match -> generic Claude fallback
|
|
342
42
|
*
|
|
343
43
|
* @param {string} modelId
|
|
344
44
|
* @returns {{ limit: {context, output}, pricing: {input, output, cacheCreation?, cacheRead?} } | null}
|
|
@@ -352,7 +52,7 @@ function resolveModelMetadata(modelId) {
|
|
|
352
52
|
if (id === key.toLowerCase()) return meta;
|
|
353
53
|
}
|
|
354
54
|
|
|
355
|
-
// Alias match
|
|
55
|
+
// Alias match -> canonical
|
|
356
56
|
for (const [alias, canonical] of Object.entries(MODEL_ALIASES)) {
|
|
357
57
|
if (id === alias.toLowerCase()) {
|
|
358
58
|
const meta = MODEL_METADATA[canonical];
|
|
@@ -360,7 +60,7 @@ function resolveModelMetadata(modelId) {
|
|
|
360
60
|
}
|
|
361
61
|
}
|
|
362
62
|
|
|
363
|
-
// Prefix match
|
|
63
|
+
// Prefix match
|
|
364
64
|
for (const [key, meta] of Object.entries(MODEL_METADATA)) {
|
|
365
65
|
if (id.startsWith(key.toLowerCase())) return meta;
|
|
366
66
|
}
|
|
@@ -369,47 +69,99 @@ function resolveModelMetadata(modelId) {
|
|
|
369
69
|
if (id.startsWith('claude-')) {
|
|
370
70
|
return {
|
|
371
71
|
limit: { context: 200000, output: 32000 },
|
|
372
|
-
pricing: { input: 3, output: 15, cacheCreation: 3.75, cacheRead: 0.
|
|
72
|
+
pricing: { input: 3, output: 15, cacheCreation: 3.75, cacheRead: 0.3 }
|
|
373
73
|
};
|
|
374
74
|
}
|
|
375
75
|
|
|
376
76
|
return null;
|
|
377
77
|
}
|
|
378
78
|
|
|
379
|
-
/**
|
|
380
|
-
* Get just the limit (context + output) for a model.
|
|
381
|
-
* @param {string} modelId
|
|
382
|
-
* @returns {{ context: number, output: number } | null}
|
|
383
|
-
*/
|
|
384
79
|
function resolveModelLimit(modelId) {
|
|
385
80
|
const meta = resolveModelMetadata(modelId);
|
|
386
81
|
return meta ? meta.limit : null;
|
|
387
82
|
}
|
|
388
83
|
|
|
389
|
-
/**
|
|
390
|
-
* Get just the pricing for a model.
|
|
391
|
-
* @param {string} modelId
|
|
392
|
-
* @returns {{ input: number, output: number, cacheCreation?: number, cacheRead?: number } | null}
|
|
393
|
-
*/
|
|
394
84
|
function resolveModelPricing(modelId) {
|
|
395
85
|
const meta = resolveModelMetadata(modelId);
|
|
396
86
|
return meta ? meta.pricing : null;
|
|
397
87
|
}
|
|
398
88
|
|
|
399
|
-
/**
|
|
400
|
-
* Get all model IDs in the metadata table.
|
|
401
|
-
* @returns {string[]}
|
|
402
|
-
*/
|
|
403
89
|
function getAllModelIds() {
|
|
404
90
|
return Object.keys(MODEL_METADATA);
|
|
405
91
|
}
|
|
406
92
|
|
|
93
|
+
function getDefaultModels() {
|
|
94
|
+
return {
|
|
95
|
+
claude: [...(DEFAULT_MODELS.claude || [])],
|
|
96
|
+
codex: [...(DEFAULT_MODELS.codex || [])],
|
|
97
|
+
gemini: [...(DEFAULT_MODELS.gemini || [])]
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function getDefaultModelsByToolType(toolType) {
|
|
102
|
+
const key = String(toolType || '').trim().toLowerCase();
|
|
103
|
+
if (key === 'openai_compatible') return [...(DEFAULT_MODELS.codex || [])];
|
|
104
|
+
if (key === 'claude' || key === 'codex' || key === 'gemini') {
|
|
105
|
+
return [...(DEFAULT_MODELS[key] || [])];
|
|
106
|
+
}
|
|
107
|
+
return [];
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function getDefaultSpeedTestModels() {
|
|
111
|
+
const fileConfig = loadMetadataConfigFromFile();
|
|
112
|
+
const raw = fileConfig.defaultSpeedTestModels || DEFAULT_SPEED_TEST_MODELS;
|
|
113
|
+
return {
|
|
114
|
+
claude: normalizeNonEmptyString(raw.claude) || DEFAULT_SPEED_TEST_MODELS.claude,
|
|
115
|
+
codex: normalizeNonEmptyString(raw.codex) || DEFAULT_SPEED_TEST_MODELS.codex,
|
|
116
|
+
gemini: normalizeNonEmptyString(raw.gemini) || DEFAULT_SPEED_TEST_MODELS.gemini
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function getDefaultSpeedTestModelByToolType(toolType) {
|
|
121
|
+
const key = String(toolType || '').trim().toLowerCase();
|
|
122
|
+
const defaults = getDefaultSpeedTestModels();
|
|
123
|
+
if (key === 'openai_compatible') return defaults.codex;
|
|
124
|
+
if (key === 'claude' || key === 'codex' || key === 'gemini') {
|
|
125
|
+
return defaults[key];
|
|
126
|
+
}
|
|
127
|
+
return defaults.codex;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function saveDefaultSpeedTestModels(nextDefaults) {
|
|
131
|
+
const current = loadMetadataConfigFromFile();
|
|
132
|
+
const merged = {
|
|
133
|
+
...getDefaultSpeedTestModels(),
|
|
134
|
+
...(nextDefaults || {})
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
const normalized = {
|
|
138
|
+
claude: normalizeNonEmptyString(merged.claude) || DEFAULT_SPEED_TEST_MODELS.claude,
|
|
139
|
+
codex: normalizeNonEmptyString(merged.codex) || DEFAULT_SPEED_TEST_MODELS.codex,
|
|
140
|
+
gemini: normalizeNonEmptyString(merged.gemini) || DEFAULT_SPEED_TEST_MODELS.gemini
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
const nextConfig = {
|
|
144
|
+
...current,
|
|
145
|
+
defaultSpeedTestModels: normalized
|
|
146
|
+
};
|
|
147
|
+
fs.writeFileSync(METADATA_FILE_PATH, `${JSON.stringify(nextConfig, null, 2)}\n`, 'utf8');
|
|
148
|
+
metadataConfig.defaultSpeedTestModels = normalized;
|
|
149
|
+
return normalized;
|
|
150
|
+
}
|
|
151
|
+
|
|
407
152
|
module.exports = {
|
|
408
153
|
MODEL_METADATA,
|
|
409
154
|
MODEL_ALIASES,
|
|
155
|
+
DEFAULT_MODELS,
|
|
156
|
+
DEFAULT_SPEED_TEST_MODELS,
|
|
410
157
|
resolveModelMetadata,
|
|
411
158
|
resolveModelLimit,
|
|
412
159
|
resolveModelPricing,
|
|
413
160
|
getAllModelIds,
|
|
414
|
-
|
|
161
|
+
getDefaultModels,
|
|
162
|
+
getDefaultModelsByToolType,
|
|
163
|
+
getDefaultSpeedTestModels,
|
|
164
|
+
getDefaultSpeedTestModelByToolType,
|
|
165
|
+
saveDefaultSpeedTestModels,
|
|
166
|
+
METADATA_LAST_UPDATED: metadataConfig.lastUpdated || '2026-02-27'
|
|
415
167
|
};
|