shennian 0.2.89 → 0.2.90
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/dist/assets/wechat-channel/macos/manifest.json +13 -4
- package/dist/assets/wechat-channel/macos/shennian-wechat-channel-helper +0 -0
- package/dist/bin/shennian.js +1 -1
- package/dist/publish-build-manifest.json +548 -0
- package/dist/scripts/wechat-rpa-confirmation.mjs +5 -97
- package/dist/src/agent-env.js +4 -105
- package/dist/src/agents/adapter.js +1 -19
- package/dist/src/agents/claude.js +8 -305
- package/dist/src/agents/codex-control.js +2 -188
- package/dist/src/agents/codex-utils.js +7 -200
- package/dist/src/agents/codex.js +15 -916
- package/dist/src/agents/command-spec.js +2 -413
- package/dist/src/agents/config-status.js +1 -226
- package/dist/src/agents/cursor.js +1 -249
- package/dist/src/agents/custom.js +4 -271
- package/dist/src/agents/detect.js +1 -56
- package/dist/src/agents/external-channel-instructions.js +10 -94
- package/dist/src/agents/gemini.js +1 -173
- package/dist/src/agents/manager.js +13 -157
- package/dist/src/agents/model-registry/cache.js +1 -37
- package/dist/src/agents/model-registry/discovery.js +2 -187
- package/dist/src/agents/model-registry/parsers.js +4 -447
- package/dist/src/agents/model-registry/runner.js +1 -30
- package/dist/src/agents/model-registry/service.js +1 -78
- package/dist/src/agents/model-registry/types.js +1 -8
- package/dist/src/agents/model-registry.js +1 -18
- package/dist/src/agents/openclaw.js +2 -275
- package/dist/src/agents/opencode.js +1 -231
- package/dist/src/agents/pi-context.js +12 -217
- package/dist/src/agents/pi.js +14 -723
- package/dist/src/agents/platform-instructions.js +9 -54
- package/dist/src/channels/base.js +1 -3
- package/dist/src/channels/registry.js +1 -30
- package/dist/src/channels/reply-split.js +10 -89
- package/dist/src/channels/runtime.js +5 -564
- package/dist/src/channels/secret-registry.js +1 -46
- package/dist/src/channels/websocket.js +8 -378
- package/dist/src/channels/wechat-channel/anchor.js +1 -65
- package/dist/src/channels/wechat-channel/client.js +1 -96
- package/dist/src/channels/wechat-channel/cooldown.js +1 -38
- package/dist/src/channels/wechat-channel/fingerprint.js +1 -71
- package/dist/src/channels/wechat-channel/helper-assets.d.ts +10 -1
- package/dist/src/channels/wechat-channel/helper-assets.js +1 -68
- package/dist/src/channels/wechat-channel/helper-client.js +3 -149
- package/dist/src/channels/wechat-channel/helper-protocol.d.ts +1 -1
- package/dist/src/channels/wechat-channel/helper-protocol.js +1 -115
- package/dist/src/channels/wechat-channel/index.d.ts +1 -0
- package/dist/src/channels/wechat-channel/index.js +1 -19
- package/dist/src/channels/wechat-channel/ledger.js +1 -54
- package/dist/src/channels/wechat-channel/media-resolver.js +1 -181
- package/dist/src/channels/wechat-channel/message-key.js +1 -105
- package/dist/src/channels/wechat-channel/observer.js +1 -118
- package/dist/src/channels/wechat-channel/outbound-ledger.d.ts +3 -0
- package/dist/src/channels/wechat-channel/outbound-ledger.js +2 -112
- package/dist/src/channels/wechat-channel/outbound-sender.d.ts +26 -0
- package/dist/src/channels/wechat-channel/outbound-sender.js +1 -0
- package/dist/src/channels/wechat-channel/preflight.js +1 -48
- package/dist/src/channels/wechat-channel/runner.js +1 -84
- package/dist/src/channels/wechat-channel/runtime.js +1 -66
- package/dist/src/channels/wechat-channel/scheduler.d.ts +5 -0
- package/dist/src/channels/wechat-channel/scheduler.js +1 -152
- package/dist/src/channels/wechat-rpa/macos-flow.js +1 -96
- package/dist/src/channels/wechat-rpa/macos.js +6 -48
- package/dist/src/channels/wechat-rpa/normalizer.js +7 -127
- package/dist/src/channels/wechat-rpa.js +6 -1028
- package/dist/src/channels/wecom.js +4 -357
- package/dist/src/commands/agent.js +6 -131
- package/dist/src/commands/daemon-windows.js +8 -48
- package/dist/src/commands/daemon.js +19 -1013
- package/dist/src/commands/external-attachments.js +1 -51
- package/dist/src/commands/external.js +1 -137
- package/dist/src/commands/manager.js +2 -391
- package/dist/src/commands/pair-qr.js +1 -6
- package/dist/src/commands/pair.js +9 -287
- package/dist/src/commands/tools.js +1 -34
- package/dist/src/commands/upgrade.js +1 -198
- package/dist/src/config/index.js +1 -35
- package/dist/src/daemon-log.js +6 -58
- package/dist/src/env-path.js +1 -64
- package/dist/src/fs/boundary.js +1 -126
- package/dist/src/fs/handler.js +1 -130
- package/dist/src/fs/security.js +1 -32
- package/dist/src/fs/text-decoder.js +1 -110
- package/dist/src/index.js +2 -404
- package/dist/src/log-reporter.js +1 -16
- package/dist/src/manager/prompt.js +29 -34
- package/dist/src/manager/registry.js +2 -269
- package/dist/src/manager/runtime.js +19 -1007
- package/dist/src/native-fusion/config.js +1 -5
- package/dist/src/native-fusion/opencode-parser.js +3 -123
- package/dist/src/native-fusion/parser-common.js +8 -264
- package/dist/src/native-fusion/parsers.js +8 -729
- package/dist/src/native-fusion/service.js +2 -225
- package/dist/src/native-fusion/state.js +1 -22
- package/dist/src/native-fusion/types.js +1 -1
- package/dist/src/region.js +1 -88
- package/dist/src/relay/client.js +1 -343
- package/dist/src/session/archive-zip.js +1 -220
- package/dist/src/session/handlers/agent-config.js +1 -150
- package/dist/src/session/handlers/agents.js +1 -55
- package/dist/src/session/handlers/chat.js +2 -751
- package/dist/src/session/handlers/control.js +1 -55
- package/dist/src/session/handlers/fs.js +1 -783
- package/dist/src/session/handlers/session-refresh.js +1 -47
- package/dist/src/session/handlers/skills.js +1 -121
- package/dist/src/session/handlers/title.js +1 -60
- package/dist/src/session/handlers/tool-detail.js +1 -218
- package/dist/src/session/manager.js +1 -319
- package/dist/src/session/projection.js +1 -54
- package/dist/src/session/queue.js +4 -317
- package/dist/src/session/remote-attachments.js +1 -72
- package/dist/src/session/store.js +3 -109
- package/dist/src/session/types.js +1 -4
- package/dist/src/skills/registry.js +15 -148
- package/dist/src/skills/setup.js +1 -101
- package/dist/src/tools/markdown-to-pdf.js +10 -346
- package/dist/src/upgrade/engine.js +3 -347
- package/package.json +3 -2
|
@@ -1,187 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
import { createInterface } from 'node:readline';
|
|
4
|
-
import { resolveBuiltinCommand, spawnResolvedCommand } from '../command-spec.js';
|
|
5
|
-
import { fallbackClaudeAliasModels, discoverClaudeAliasModelsFromEnv, fallbackGeminiModels, parseCodexAppServerModels, parseCursorModels, parseOpenCodeModels, } from './parsers.js';
|
|
6
|
-
import { runResolvedCommand } from './runner.js';
|
|
7
|
-
import { DISCOVERY_WORKDIR } from './types.js';
|
|
8
|
-
import { buildAgentProcessEnv, readLatestUserEnv } from '../../agent-env.js';
|
|
9
|
-
import { CODEX_APP_SERVER_CLIENT_INFO } from '../codex-utils.js';
|
|
10
|
-
function sendAppServerRpc(proc, pending, id, method, params, timeoutMs) {
|
|
11
|
-
if (!proc.stdin)
|
|
12
|
-
return Promise.reject(new Error('codex app-server stdin unavailable'));
|
|
13
|
-
return new Promise((resolve, reject) => {
|
|
14
|
-
const timer = setTimeout(() => {
|
|
15
|
-
pending.delete(id);
|
|
16
|
-
reject(new Error(`codex app-server request timed out: ${method}`));
|
|
17
|
-
}, timeoutMs);
|
|
18
|
-
pending.set(id, { resolve, reject, timer });
|
|
19
|
-
proc.stdin.write(`${JSON.stringify({ id, method, params })}\n`, (error) => {
|
|
20
|
-
if (!error)
|
|
21
|
-
return;
|
|
22
|
-
clearTimeout(timer);
|
|
23
|
-
pending.delete(id);
|
|
24
|
-
reject(error);
|
|
25
|
-
});
|
|
26
|
-
});
|
|
27
|
-
}
|
|
28
|
-
async function discoverCodexModelsViaAppServer(spec) {
|
|
29
|
-
const proc = spawnResolvedCommand(spec, ['app-server', '--listen', 'stdio://'], {
|
|
30
|
-
cwd: DISCOVERY_WORKDIR,
|
|
31
|
-
stdio: ['pipe', 'pipe', 'pipe'],
|
|
32
|
-
env: buildAgentProcessEnv({ NO_COLOR: '1' }),
|
|
33
|
-
});
|
|
34
|
-
const pending = new Map();
|
|
35
|
-
let seq = 1;
|
|
36
|
-
const rl = createInterface({ input: proc.stdout });
|
|
37
|
-
rl.on('line', (line) => {
|
|
38
|
-
if (!line.trim())
|
|
39
|
-
return;
|
|
40
|
-
let msg;
|
|
41
|
-
try {
|
|
42
|
-
msg = JSON.parse(line);
|
|
43
|
-
}
|
|
44
|
-
catch {
|
|
45
|
-
return;
|
|
46
|
-
}
|
|
47
|
-
if (msg.id == null)
|
|
48
|
-
return;
|
|
49
|
-
const request = pending.get(msg.id);
|
|
50
|
-
if (!request)
|
|
51
|
-
return;
|
|
52
|
-
clearTimeout(request.timer);
|
|
53
|
-
pending.delete(msg.id);
|
|
54
|
-
if (msg.error) {
|
|
55
|
-
request.reject(new Error(msg.error.message || `codex app-server error ${msg.error.code ?? ''}`.trim()));
|
|
56
|
-
}
|
|
57
|
-
else {
|
|
58
|
-
request.resolve(msg.result);
|
|
59
|
-
}
|
|
60
|
-
});
|
|
61
|
-
try {
|
|
62
|
-
await sendAppServerRpc(proc, pending, seq++, 'initialize', {
|
|
63
|
-
clientInfo: CODEX_APP_SERVER_CLIENT_INFO,
|
|
64
|
-
capabilities: { experimentalApi: true },
|
|
65
|
-
}, 10_000);
|
|
66
|
-
const [modelList, configRead] = await Promise.all([
|
|
67
|
-
sendAppServerRpc(proc, pending, seq++, 'model/list', {}, 15_000),
|
|
68
|
-
sendAppServerRpc(proc, pending, seq++, 'config/read', {}, 15_000).catch(() => null),
|
|
69
|
-
]);
|
|
70
|
-
const config = typeof configRead === 'object' && configRead !== null && 'config' in configRead
|
|
71
|
-
? configRead.config
|
|
72
|
-
: undefined;
|
|
73
|
-
return parseCodexAppServerModels({
|
|
74
|
-
...(typeof modelList === 'object' && modelList !== null ? modelList : {}),
|
|
75
|
-
config,
|
|
76
|
-
});
|
|
77
|
-
}
|
|
78
|
-
finally {
|
|
79
|
-
for (const [id, request] of pending) {
|
|
80
|
-
clearTimeout(request.timer);
|
|
81
|
-
request.reject(new Error('codex app-server stopped'));
|
|
82
|
-
pending.delete(id);
|
|
83
|
-
}
|
|
84
|
-
proc.kill('SIGTERM');
|
|
85
|
-
setTimeout(() => proc.kill('SIGKILL'), 1000).unref();
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
async function discoverCursorModels() {
|
|
89
|
-
const spec = resolveBuiltinCommand('cursor');
|
|
90
|
-
if (!spec)
|
|
91
|
-
return [];
|
|
92
|
-
const result = await runResolvedCommand(spec, ['--list-models']);
|
|
93
|
-
return parseCursorModels(result.stdout);
|
|
94
|
-
}
|
|
95
|
-
// OpenClaw support is intentionally disabled.
|
|
96
|
-
// async function discoverOpenClawModels(): Promise<ModelInfo[]> {
|
|
97
|
-
// const spec = resolveBuiltinCommand('openclaw')
|
|
98
|
-
// if (!spec) return []
|
|
99
|
-
// const result = await runResolvedCommand(spec, ['models', 'list', '--json'])
|
|
100
|
-
// return parseOpenClawModels(result.stdout)
|
|
101
|
-
// }
|
|
102
|
-
async function discoverOpenCodeModels() {
|
|
103
|
-
const spec = resolveBuiltinCommand('opencode');
|
|
104
|
-
if (!spec)
|
|
105
|
-
return [];
|
|
106
|
-
const result = await runResolvedCommand(spec, ['models']);
|
|
107
|
-
return parseOpenCodeModels(result.stdout);
|
|
108
|
-
}
|
|
109
|
-
async function discoverClaudeModels() {
|
|
110
|
-
if (!resolveBuiltinCommand('claude'))
|
|
111
|
-
return [];
|
|
112
|
-
const shellEnvModels = discoverClaudeAliasModelsFromEnv(readLatestUserEnv());
|
|
113
|
-
if (shellEnvModels.length > 0)
|
|
114
|
-
return shellEnvModels;
|
|
115
|
-
return fallbackClaudeAliasModels();
|
|
116
|
-
}
|
|
117
|
-
async function discoverCodexModels() {
|
|
118
|
-
const spec = resolveBuiltinCommand('codex');
|
|
119
|
-
if (!spec)
|
|
120
|
-
return [];
|
|
121
|
-
const appServerModels = await discoverCodexModelsViaAppServer(spec).catch(() => []);
|
|
122
|
-
return appServerModels;
|
|
123
|
-
}
|
|
124
|
-
async function discoverGeminiModels() {
|
|
125
|
-
if (!resolveBuiltinCommand('gemini'))
|
|
126
|
-
return [];
|
|
127
|
-
return fallbackGeminiModels();
|
|
128
|
-
}
|
|
129
|
-
const fallbackPiModels = [
|
|
130
|
-
{ id: 'qwen3.6-plus', name: 'Qwen 3.6 Plus', provider: 'dashscope', isDefault: true },
|
|
131
|
-
{ id: 'qwen3.6-flash', name: 'Qwen 3.6 Flash', provider: 'dashscope' },
|
|
132
|
-
];
|
|
133
|
-
const managerModels = [
|
|
134
|
-
{ id: 'codex', name: 'Codex', provider: 'shennian', isDefault: true },
|
|
135
|
-
{ id: 'claude', name: 'Claude Code', provider: 'shennian' },
|
|
136
|
-
];
|
|
137
|
-
async function discoverPiModels(context) {
|
|
138
|
-
if (!context.serverUrl || !context.authToken)
|
|
139
|
-
return fallbackPiModels;
|
|
140
|
-
try {
|
|
141
|
-
const response = await fetch(`${context.serverUrl.replace(/\/$/, '')}/api/models`, {
|
|
142
|
-
headers: {
|
|
143
|
-
Authorization: `Bearer ${context.authToken}`,
|
|
144
|
-
},
|
|
145
|
-
});
|
|
146
|
-
if (!response.ok)
|
|
147
|
-
return fallbackPiModels;
|
|
148
|
-
const data = (await response.json());
|
|
149
|
-
const models = (data.models ?? []).map((model) => ({
|
|
150
|
-
id: model.id,
|
|
151
|
-
name: model.name?.trim() || model.id,
|
|
152
|
-
provider: model.provider,
|
|
153
|
-
isDefault: model.id === data.default,
|
|
154
|
-
}));
|
|
155
|
-
return models.length > 0 ? models : fallbackPiModels;
|
|
156
|
-
}
|
|
157
|
-
catch {
|
|
158
|
-
return fallbackPiModels;
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
async function discoverBuiltinModels(type, context) {
|
|
162
|
-
switch (type) {
|
|
163
|
-
case 'claude':
|
|
164
|
-
return discoverClaudeModels();
|
|
165
|
-
case 'codex':
|
|
166
|
-
return discoverCodexModels();
|
|
167
|
-
case 'gemini':
|
|
168
|
-
return discoverGeminiModels();
|
|
169
|
-
case 'cursor':
|
|
170
|
-
return discoverCursorModels();
|
|
171
|
-
case 'openclaw':
|
|
172
|
-
// OpenClaw support is intentionally disabled.
|
|
173
|
-
return [];
|
|
174
|
-
case 'opencode':
|
|
175
|
-
return discoverOpenCodeModels();
|
|
176
|
-
case 'pi':
|
|
177
|
-
return discoverPiModels(context);
|
|
178
|
-
case 'manager':
|
|
179
|
-
return managerModels;
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
export async function discoverModelsForAgent(agent, context) {
|
|
183
|
-
if (agent.type.startsWith('custom:')) {
|
|
184
|
-
return agent.models ?? [];
|
|
185
|
-
}
|
|
186
|
-
return discoverBuiltinModels(agent.type, context);
|
|
187
|
-
}
|
|
1
|
+
import{createInterface as m}from"node:readline";import{resolveBuiltinCommand as c,spawnResolvedCommand as v}from"../command-spec.js";import{fallbackClaudeAliasModels as w,discoverClaudeAliasModelsFromEnv as M,fallbackGeminiModels as C,parseCodexAppServerModels as h,parseCursorModels as y,parseOpenCodeModels as g}from"./parsers.js";import{runResolvedCommand as f}from"./runner.js";import{DISCOVERY_WORKDIR as E}from"./types.js";import{buildAgentProcessEnv as O,readLatestUserEnv as R}from"../../agent-env.js";import{CODEX_APP_SERVER_CLIENT_INFO as S}from"../codex-utils.js";function l(e,r,o,i,a,n){return e.stdin?new Promise((t,s)=>{const u=setTimeout(()=>{r.delete(o),s(new Error(`codex app-server request timed out: ${i}`))},n);r.set(o,{resolve:t,reject:s,timer:u}),e.stdin.write(`${JSON.stringify({id:o,method:i,params:a})}
|
|
2
|
+
`,p=>{p&&(clearTimeout(u),r.delete(o),s(p))})}):Promise.reject(new Error("codex app-server stdin unavailable"))}async function x(e){const r=v(e,["app-server","--listen","stdio://"],{cwd:E,stdio:["pipe","pipe","pipe"],env:O({NO_COLOR:"1"})}),o=new Map;let i=1;m({input:r.stdout}).on("line",n=>{if(!n.trim())return;let t;try{t=JSON.parse(n)}catch{return}if(t.id==null)return;const s=o.get(t.id);s&&(clearTimeout(s.timer),o.delete(t.id),t.error?s.reject(new Error(t.error.message||`codex app-server error ${t.error.code??""}`.trim())):s.resolve(t.result))});try{await l(r,o,i++,"initialize",{clientInfo:S,capabilities:{experimentalApi:!0}},1e4);const[n,t]=await Promise.all([l(r,o,i++,"model/list",{},15e3),l(r,o,i++,"config/read",{},15e3).catch(()=>null)]),s=typeof t=="object"&&t!==null&&"config"in t?t.config:void 0;return h({...typeof n=="object"&&n!==null?n:{},config:s})}finally{for(const[n,t]of o)clearTimeout(t.timer),t.reject(new Error("codex app-server stopped")),o.delete(n);r.kill("SIGTERM"),setTimeout(()=>r.kill("SIGKILL"),1e3).unref()}}async function A(){const e=c("cursor");if(!e)return[];const r=await f(e,["--list-models"]);return y(r.stdout)}async function I(){const e=c("opencode");if(!e)return[];const r=await f(e,["models"]);return g(r.stdout)}async function P(){if(!c("claude"))return[];const e=M(R());return e.length>0?e:w()}async function T(){const e=c("codex");return e?await x(e).catch(()=>[]):[]}async function _(){return c("gemini")?C():[]}const d=[{id:"qwen3.6-plus",name:"Qwen 3.6 Plus",provider:"dashscope",isDefault:!0},{id:"qwen3.6-flash",name:"Qwen 3.6 Flash",provider:"dashscope"}],b=[{id:"codex",name:"Codex",provider:"shennian",isDefault:!0},{id:"claude",name:"Claude Code",provider:"shennian"}];async function k(e){if(!e.serverUrl||!e.authToken)return d;try{const r=await fetch(`${e.serverUrl.replace(/\/$/,"")}/api/models`,{headers:{Authorization:`Bearer ${e.authToken}`}});if(!r.ok)return d;const o=await r.json(),i=(o.models??[]).map(a=>({id:a.id,name:a.name?.trim()||a.id,provider:a.provider,isDefault:a.id===o.default}));return i.length>0?i:d}catch{return d}}async function q(e,r){switch(e){case"claude":return P();case"codex":return T();case"gemini":return _();case"cursor":return A();case"openclaw":return[];case"opencode":return I();case"pi":return k(r);case"manager":return b}}async function B(e,r){return e.type.startsWith("custom:")?e.models??[]:q(e.type,r)}export{B as discoverModelsForAgent};
|
|
@@ -1,447 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
.replace(/\u001b\[[0-9;?]*[a-zA-Z]/g, '') // eslint-disable-line no-control-regex
|
|
6
|
-
.replace(/\u001b\][^\u0007]*\u0007/g, '') // eslint-disable-line no-control-regex
|
|
7
|
-
.replace(/[\u0000-\u0008\u000b-\u001f\u007f]/g, ''); // eslint-disable-line no-control-regex
|
|
8
|
-
}
|
|
9
|
-
function uniqueModels(models) {
|
|
10
|
-
const seen = new Set();
|
|
11
|
-
const unique = [];
|
|
12
|
-
for (const model of models) {
|
|
13
|
-
if (!model.id || seen.has(model.id))
|
|
14
|
-
continue;
|
|
15
|
-
seen.add(model.id);
|
|
16
|
-
unique.push(model);
|
|
17
|
-
}
|
|
18
|
-
return unique;
|
|
19
|
-
}
|
|
20
|
-
function titleCaseSegment(segment) {
|
|
21
|
-
if (!segment)
|
|
22
|
-
return segment;
|
|
23
|
-
return segment[0].toUpperCase() + segment.slice(1);
|
|
24
|
-
}
|
|
25
|
-
function prettifyCodexModel(id) {
|
|
26
|
-
return id
|
|
27
|
-
.split('-')
|
|
28
|
-
.map((segment) => {
|
|
29
|
-
if (segment === 'gpt')
|
|
30
|
-
return 'GPT';
|
|
31
|
-
if (segment === 'codex')
|
|
32
|
-
return 'Codex';
|
|
33
|
-
return /^\d/.test(segment) ? segment : titleCaseSegment(segment);
|
|
34
|
-
})
|
|
35
|
-
.join('-');
|
|
36
|
-
}
|
|
37
|
-
function prettifyReasoningEffort(id) {
|
|
38
|
-
switch (id) {
|
|
39
|
-
case 'low':
|
|
40
|
-
return 'Low';
|
|
41
|
-
case 'medium':
|
|
42
|
-
return 'Medium';
|
|
43
|
-
case 'high':
|
|
44
|
-
return 'High';
|
|
45
|
-
case 'xhigh':
|
|
46
|
-
return 'Extra High';
|
|
47
|
-
default:
|
|
48
|
-
return titleCaseSegment(id);
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
function prettifyCursorModel(id) {
|
|
52
|
-
return id
|
|
53
|
-
.split('-')
|
|
54
|
-
.map((segment) => (/^\d/.test(segment) ? segment : titleCaseSegment(segment)))
|
|
55
|
-
.join(' ');
|
|
56
|
-
}
|
|
57
|
-
function buildGeminiId(version, flavor, preview = false) {
|
|
58
|
-
const normalizedFlavor = flavor.toLowerCase().replace(/\s+/g, '-');
|
|
59
|
-
return `gemini-${version}-${normalizedFlavor}${preview ? '-preview' : ''}`;
|
|
60
|
-
}
|
|
61
|
-
export function parseCursorModels(raw) {
|
|
62
|
-
const models = [];
|
|
63
|
-
const clean = stripAnsi(raw);
|
|
64
|
-
for (const line of clean.split('\n')) {
|
|
65
|
-
const match = line.trim().match(/^(\S+)\s+-\s+(.+?)(?:\s+\(([^)]+)\))?$/);
|
|
66
|
-
if (!match)
|
|
67
|
-
continue;
|
|
68
|
-
const [, id, name, flags] = match;
|
|
69
|
-
const tags = flags?.split(',').map((flag) => flag.trim().toLowerCase()) ?? [];
|
|
70
|
-
models.push({
|
|
71
|
-
id,
|
|
72
|
-
name: name.trim() || prettifyCursorModel(id),
|
|
73
|
-
description: flags?.trim(),
|
|
74
|
-
isDefault: tags.includes('default') || tags.includes('current'),
|
|
75
|
-
});
|
|
76
|
-
}
|
|
77
|
-
return uniqueModels(models);
|
|
78
|
-
}
|
|
79
|
-
export function parseOpenClawModels(raw) {
|
|
80
|
-
try {
|
|
81
|
-
const data = JSON.parse(raw);
|
|
82
|
-
const models = (data.models ?? [])
|
|
83
|
-
.filter((model) => model.available)
|
|
84
|
-
.map((model) => ({
|
|
85
|
-
id: model.key,
|
|
86
|
-
name: model.name?.trim() || model.key,
|
|
87
|
-
provider: model.key.split('/')[0],
|
|
88
|
-
description: model.tags?.join(', '),
|
|
89
|
-
isDefault: model.tags?.includes('default') ?? false,
|
|
90
|
-
}));
|
|
91
|
-
return uniqueModels(models);
|
|
92
|
-
}
|
|
93
|
-
catch {
|
|
94
|
-
return [];
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
export function parseOpenCodeModels(raw) {
|
|
98
|
-
const models = stripAnsi(raw)
|
|
99
|
-
.split('\n')
|
|
100
|
-
.map((line) => line.trim())
|
|
101
|
-
.filter(Boolean)
|
|
102
|
-
.filter((line) => !line.includes(' '))
|
|
103
|
-
.map((id) => ({
|
|
104
|
-
id,
|
|
105
|
-
name: id,
|
|
106
|
-
provider: id.includes('/') ? id.split('/')[0] : undefined,
|
|
107
|
-
}));
|
|
108
|
-
return uniqueModels(models);
|
|
109
|
-
}
|
|
110
|
-
export function parseClaudeModels(raw) {
|
|
111
|
-
const rawClean = stripAnsi(raw).replace(/\s+/g, ' ');
|
|
112
|
-
const patterns = [
|
|
113
|
-
[
|
|
114
|
-
/\d+\.Default\(recommended\).*?(?:Sonnet|currently\s*Sonnet)\s*([\d.]+)/i,
|
|
115
|
-
'default',
|
|
116
|
-
'Default (recommended)',
|
|
117
|
-
],
|
|
118
|
-
[/\d+\.Sonnet.*?Sonnet\s*([\d.]+)/i, 'sonnet', 'Sonnet'],
|
|
119
|
-
[/\d+\.Opus.*?Opus\s*([\d.]+)/i, 'opus', 'Opus'],
|
|
120
|
-
[/\d+\.Haiku.*?Haiku\s*([\d.]+)/i, 'haiku', 'Haiku'],
|
|
121
|
-
];
|
|
122
|
-
const models = [];
|
|
123
|
-
for (const [pattern, id, name] of patterns) {
|
|
124
|
-
const match = rawClean.match(pattern);
|
|
125
|
-
if (match) {
|
|
126
|
-
models.push(withClaudeReasoningEfforts({
|
|
127
|
-
id,
|
|
128
|
-
name,
|
|
129
|
-
description: `v${match[1]}`,
|
|
130
|
-
provider: 'anthropic',
|
|
131
|
-
isDefault: id === 'default',
|
|
132
|
-
}));
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
if (models.length > 0)
|
|
136
|
-
return uniqueModels(models);
|
|
137
|
-
const fallback = [];
|
|
138
|
-
const defaultMatch = rawClean.match(/currently\s*(Sonnet|Opus|Haiku)\s*([34](?:\.\d)?)/i);
|
|
139
|
-
const aliasMap = { sonnet: 'sonnet', opus: 'opus', haiku: 'haiku' };
|
|
140
|
-
for (const match of rawClean.matchAll(/\b(Sonnet|Opus|Haiku)\s*([34](?:\.\d)?)\b/gi)) {
|
|
141
|
-
const family = (match[1] ?? '').toLowerCase();
|
|
142
|
-
const alias = aliasMap[family];
|
|
143
|
-
if (!alias)
|
|
144
|
-
continue;
|
|
145
|
-
const version = match[2] ?? '';
|
|
146
|
-
const isDefault = defaultMatch && defaultMatch[1]?.toLowerCase() === family && defaultMatch[2] === version;
|
|
147
|
-
fallback.push(withClaudeReasoningEfforts({
|
|
148
|
-
id: alias,
|
|
149
|
-
name: `${titleCaseSegment(family)} ${version}`,
|
|
150
|
-
provider: 'anthropic',
|
|
151
|
-
isDefault: Boolean(isDefault),
|
|
152
|
-
}));
|
|
153
|
-
}
|
|
154
|
-
return uniqueModels(fallback);
|
|
155
|
-
}
|
|
156
|
-
function compareVersionNumbers(a, b) {
|
|
157
|
-
const length = Math.max(a.length, b.length);
|
|
158
|
-
for (let index = 0; index < length; index++) {
|
|
159
|
-
const left = a[index] ?? -1;
|
|
160
|
-
const right = b[index] ?? -1;
|
|
161
|
-
if (left === right)
|
|
162
|
-
continue;
|
|
163
|
-
return left - right;
|
|
164
|
-
}
|
|
165
|
-
return 0;
|
|
166
|
-
}
|
|
167
|
-
function extractClaudeFamilyVersion(id, family) {
|
|
168
|
-
const match = id.match(new RegExp(`^claude-${family}-([0-9]+(?:-[0-9]+)*)$`, 'i'));
|
|
169
|
-
if (!match?.[1])
|
|
170
|
-
return null;
|
|
171
|
-
const parts = match[1]
|
|
172
|
-
.split('-')
|
|
173
|
-
.map((part) => Number.parseInt(part, 10))
|
|
174
|
-
.filter((part) => Number.isFinite(part));
|
|
175
|
-
if (parts.length === 0 || parts.length > 2)
|
|
176
|
-
return null;
|
|
177
|
-
return parts;
|
|
178
|
-
}
|
|
179
|
-
function formatClaudeVersion(version) {
|
|
180
|
-
if (!version?.length)
|
|
181
|
-
return undefined;
|
|
182
|
-
return `v${version.join('.')}`;
|
|
183
|
-
}
|
|
184
|
-
const CLAUDE_ALIAS_LABELS = {
|
|
185
|
-
default: 'Default (recommended)',
|
|
186
|
-
sonnet: 'Sonnet',
|
|
187
|
-
opus: 'Opus',
|
|
188
|
-
haiku: 'Haiku',
|
|
189
|
-
};
|
|
190
|
-
const CLAUDE_ALIAS_MODEL_ENV = {
|
|
191
|
-
default: 'ANTHROPIC_MODEL',
|
|
192
|
-
sonnet: 'ANTHROPIC_DEFAULT_SONNET_MODEL',
|
|
193
|
-
opus: 'ANTHROPIC_DEFAULT_OPUS_MODEL',
|
|
194
|
-
haiku: 'ANTHROPIC_DEFAULT_HAIKU_MODEL',
|
|
195
|
-
};
|
|
196
|
-
const CLAUDE_DEEPSEEK_REASONING_EFFORTS = [
|
|
197
|
-
{ id: 'max', name: 'Max' },
|
|
198
|
-
];
|
|
199
|
-
const CLAUDE_REASONING_EFFORTS = [
|
|
200
|
-
{ id: 'low', name: 'Low' },
|
|
201
|
-
{ id: 'medium', name: 'Medium' },
|
|
202
|
-
{ id: 'high', name: 'High' },
|
|
203
|
-
{ id: 'xhigh', name: 'Extra High' },
|
|
204
|
-
{ id: 'max', name: 'Max' },
|
|
205
|
-
];
|
|
206
|
-
function withClaudeReasoningEfforts(model) {
|
|
207
|
-
return {
|
|
208
|
-
...model,
|
|
209
|
-
supportedReasoningEfforts: CLAUDE_REASONING_EFFORTS,
|
|
210
|
-
defaultReasoningEffort: 'medium',
|
|
211
|
-
};
|
|
212
|
-
}
|
|
213
|
-
export function readEnvValue(env, key) {
|
|
214
|
-
const value = env[key]?.trim();
|
|
215
|
-
return value || null;
|
|
216
|
-
}
|
|
217
|
-
export function inferClaudeOverrideProvider(modelName, env) {
|
|
218
|
-
const baseUrl = readEnvValue(env, 'ANTHROPIC_BASE_URL')?.toLowerCase() ?? '';
|
|
219
|
-
if (baseUrl.includes('deepseek.com') || modelName.toLowerCase().startsWith('deepseek-')) {
|
|
220
|
-
return 'deepseek';
|
|
221
|
-
}
|
|
222
|
-
return baseUrl ? 'custom' : 'anthropic';
|
|
223
|
-
}
|
|
224
|
-
function configuredClaudeAliasModels(env) {
|
|
225
|
-
const configured = new Set();
|
|
226
|
-
for (const key of Object.values(CLAUDE_ALIAS_MODEL_ENV)) {
|
|
227
|
-
const modelName = readEnvValue(env, key);
|
|
228
|
-
if (modelName)
|
|
229
|
-
configured.add(modelName);
|
|
230
|
-
}
|
|
231
|
-
const models = Array.from(configured).map((modelName, index) => {
|
|
232
|
-
const provider = inferClaudeOverrideProvider(modelName, env);
|
|
233
|
-
const model = {
|
|
234
|
-
id: modelName,
|
|
235
|
-
name: modelName,
|
|
236
|
-
provider,
|
|
237
|
-
isDefault: index === 0,
|
|
238
|
-
};
|
|
239
|
-
if (provider === 'deepseek') {
|
|
240
|
-
return {
|
|
241
|
-
...model,
|
|
242
|
-
supportedReasoningEfforts: CLAUDE_DEEPSEEK_REASONING_EFFORTS,
|
|
243
|
-
defaultReasoningEffort: readEnvValue(env, 'CLAUDE_CODE_EFFORT_LEVEL') ?? 'max',
|
|
244
|
-
};
|
|
245
|
-
}
|
|
246
|
-
return withClaudeReasoningEfforts(model);
|
|
247
|
-
});
|
|
248
|
-
return uniqueModels(models);
|
|
249
|
-
}
|
|
250
|
-
export function discoverClaudeAliasModelsFromEnv(env = process.env) {
|
|
251
|
-
return configuredClaudeAliasModels(env);
|
|
252
|
-
}
|
|
253
|
-
export function applyClaudeModelEnvOverrides(models, env = process.env) {
|
|
254
|
-
return models.map((model) => {
|
|
255
|
-
if (!['default', 'sonnet', 'opus', 'haiku'].includes(model.id))
|
|
256
|
-
return model;
|
|
257
|
-
const alias = model.id;
|
|
258
|
-
const configuredModel = readEnvValue(env, CLAUDE_ALIAS_MODEL_ENV[alias]);
|
|
259
|
-
if (!configuredModel)
|
|
260
|
-
return model;
|
|
261
|
-
const aliasLabel = CLAUDE_ALIAS_LABELS[alias];
|
|
262
|
-
const aliasDescription = `Claude Code alias: ${aliasLabel}`;
|
|
263
|
-
return {
|
|
264
|
-
...model,
|
|
265
|
-
name: configuredModel,
|
|
266
|
-
description: model.description
|
|
267
|
-
? `${aliasDescription} · ${model.description}`
|
|
268
|
-
: aliasDescription,
|
|
269
|
-
provider: inferClaudeOverrideProvider(configuredModel, env),
|
|
270
|
-
};
|
|
271
|
-
});
|
|
272
|
-
}
|
|
273
|
-
export function parseClaudeBinaryModels(raw) {
|
|
274
|
-
const clean = stripAnsi(raw);
|
|
275
|
-
const familyVersions = new Map();
|
|
276
|
-
for (const family of ['sonnet', 'opus', 'haiku']) {
|
|
277
|
-
for (const match of clean.matchAll(new RegExp(`\\bclaude-${family}-[0-9.-]+\\b`, 'gi'))) {
|
|
278
|
-
const normalized = match[0].trim().toLowerCase().replace(/\./g, '-').replace(/-+$/g, '');
|
|
279
|
-
const version = extractClaudeFamilyVersion(normalized, family);
|
|
280
|
-
if (!version)
|
|
281
|
-
continue;
|
|
282
|
-
const current = familyVersions.get(family);
|
|
283
|
-
if (!current || compareVersionNumbers(current, version) < 0) {
|
|
284
|
-
familyVersions.set(family, version);
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
const models = [];
|
|
289
|
-
for (const alias of ['default', 'sonnet', 'opus', 'haiku']) {
|
|
290
|
-
if (!new RegExp(`\\b${alias}\\b`, 'i').test(clean))
|
|
291
|
-
continue;
|
|
292
|
-
const version = (alias === 'default' ? familyVersions.get('sonnet') : familyVersions.get(alias)) ?? null;
|
|
293
|
-
models.push(withClaudeReasoningEfforts({
|
|
294
|
-
id: alias,
|
|
295
|
-
name: CLAUDE_ALIAS_LABELS[alias],
|
|
296
|
-
description: formatClaudeVersion(version),
|
|
297
|
-
provider: 'anthropic',
|
|
298
|
-
isDefault: alias === 'default',
|
|
299
|
-
}));
|
|
300
|
-
}
|
|
301
|
-
return uniqueModels(models);
|
|
302
|
-
}
|
|
303
|
-
export function fallbackClaudeAliasModels(env = process.env) {
|
|
304
|
-
const configuredModels = configuredClaudeAliasModels(env);
|
|
305
|
-
if (configuredModels.length > 0)
|
|
306
|
-
return configuredModels;
|
|
307
|
-
return applyClaudeModelEnvOverrides([
|
|
308
|
-
{ id: 'default', name: 'Default (recommended)', provider: 'anthropic', isDefault: true },
|
|
309
|
-
{ id: 'sonnet', name: 'Sonnet', provider: 'anthropic' },
|
|
310
|
-
{ id: 'opus', name: 'Opus', provider: 'anthropic' },
|
|
311
|
-
{ id: 'haiku', name: 'Haiku', provider: 'anthropic' },
|
|
312
|
-
], env).map(withClaudeReasoningEfforts);
|
|
313
|
-
}
|
|
314
|
-
export function parseCodexModels(raw) {
|
|
315
|
-
const clean = stripAnsi(raw);
|
|
316
|
-
const models = [];
|
|
317
|
-
for (const line of clean.split('\n')) {
|
|
318
|
-
const match = line.match(/\b(gpt-[a-z0-9][a-z0-9.-]*)\b/i);
|
|
319
|
-
if (!match)
|
|
320
|
-
continue;
|
|
321
|
-
const id = match[1].trim();
|
|
322
|
-
const description = line
|
|
323
|
-
.replace(id, '')
|
|
324
|
-
.replace(/^[^\w]+/, '')
|
|
325
|
-
.trim() || undefined;
|
|
326
|
-
models.push({
|
|
327
|
-
id,
|
|
328
|
-
name: prettifyCodexModel(id),
|
|
329
|
-
description,
|
|
330
|
-
provider: 'openai',
|
|
331
|
-
isDefault: /\bcurrent\b/i.test(line) || /\bselected\b/i.test(line),
|
|
332
|
-
});
|
|
333
|
-
}
|
|
334
|
-
return uniqueModels(models);
|
|
335
|
-
}
|
|
336
|
-
export function parseCodexAppServerModels(raw) {
|
|
337
|
-
const data = typeof raw === 'object' && raw !== null
|
|
338
|
-
? raw
|
|
339
|
-
: {};
|
|
340
|
-
const currentModel = typeof data.config?.model === 'string' ? data.config.model : undefined;
|
|
341
|
-
const currentReasoningEffort = typeof data.config?.model_reasoning_effort === 'string'
|
|
342
|
-
? data.config.model_reasoning_effort
|
|
343
|
-
: undefined;
|
|
344
|
-
const models = [];
|
|
345
|
-
for (const entry of data.data ?? []) {
|
|
346
|
-
if (typeof entry !== 'object' || entry === null)
|
|
347
|
-
continue;
|
|
348
|
-
const item = entry;
|
|
349
|
-
const id = typeof item.id === 'string' ? item.id : typeof item.model === 'string' ? item.model : '';
|
|
350
|
-
if (!id)
|
|
351
|
-
continue;
|
|
352
|
-
const displayName = typeof item.displayName === 'string'
|
|
353
|
-
? item.displayName
|
|
354
|
-
: typeof item.name === 'string'
|
|
355
|
-
? item.name
|
|
356
|
-
: undefined;
|
|
357
|
-
const description = typeof item.description === 'string' ? item.description : undefined;
|
|
358
|
-
const defaultReasoningEffort = typeof item.defaultReasoningEffort === 'string' ? item.defaultReasoningEffort : undefined;
|
|
359
|
-
const supportedReasoningEfforts = Array.isArray(item.supportedReasoningEfforts)
|
|
360
|
-
? item.supportedReasoningEfforts
|
|
361
|
-
.map((effort) => {
|
|
362
|
-
if (typeof effort !== 'object' || effort === null)
|
|
363
|
-
return null;
|
|
364
|
-
const rawEffort = effort;
|
|
365
|
-
const effortId = typeof rawEffort.reasoningEffort === 'string'
|
|
366
|
-
? rawEffort.reasoningEffort
|
|
367
|
-
: typeof rawEffort.id === 'string'
|
|
368
|
-
? rawEffort.id
|
|
369
|
-
: '';
|
|
370
|
-
if (!effortId)
|
|
371
|
-
return null;
|
|
372
|
-
return {
|
|
373
|
-
id: effortId,
|
|
374
|
-
name: prettifyReasoningEffort(effortId),
|
|
375
|
-
description: typeof rawEffort.description === 'string' ? rawEffort.description : undefined,
|
|
376
|
-
};
|
|
377
|
-
})
|
|
378
|
-
.filter((effort) => effort != null)
|
|
379
|
-
: undefined;
|
|
380
|
-
const additionalSpeedTiers = Array.isArray(item.additionalSpeedTiers)
|
|
381
|
-
? item.additionalSpeedTiers.filter((tier) => typeof tier === 'string')
|
|
382
|
-
: undefined;
|
|
383
|
-
models.push({
|
|
384
|
-
id,
|
|
385
|
-
name: displayName || prettifyCodexModel(id),
|
|
386
|
-
description,
|
|
387
|
-
provider: 'openai',
|
|
388
|
-
isDefault: currentModel ? currentModel === id : item.isDefault === true,
|
|
389
|
-
supportedReasoningEfforts,
|
|
390
|
-
defaultReasoningEffort,
|
|
391
|
-
additionalSpeedTiers,
|
|
392
|
-
});
|
|
393
|
-
}
|
|
394
|
-
if (currentModel && !models.some((model) => model.id === currentModel)) {
|
|
395
|
-
models.unshift({
|
|
396
|
-
id: currentModel,
|
|
397
|
-
name: prettifyCodexModel(currentModel),
|
|
398
|
-
provider: 'openai',
|
|
399
|
-
isDefault: true,
|
|
400
|
-
defaultReasoningEffort: currentReasoningEffort,
|
|
401
|
-
});
|
|
402
|
-
}
|
|
403
|
-
return uniqueModels(models);
|
|
404
|
-
}
|
|
405
|
-
export function parseGeminiModels(raw) {
|
|
406
|
-
const clean = stripAnsi(raw);
|
|
407
|
-
const models = [];
|
|
408
|
-
for (const match of clean.matchAll(/\b(?:auto-)?gemini-[a-z0-9.-]+\b/gi)) {
|
|
409
|
-
const id = match[0].trim();
|
|
410
|
-
models.push({
|
|
411
|
-
id,
|
|
412
|
-
name: id,
|
|
413
|
-
provider: 'google',
|
|
414
|
-
isDefault: /\bcurrent\b/i.test(clean) && clean.includes(id),
|
|
415
|
-
});
|
|
416
|
-
}
|
|
417
|
-
for (const match of clean.matchAll(/\bGemini\s*(\d(?:\.\d)?)\s*(Pro|Flash(?:[- ]Lite)?)\s*(Preview)?\b/gi)) {
|
|
418
|
-
const version = match[1] ?? '';
|
|
419
|
-
const flavor = (match[2] ?? '').replace(/\s+/g, '-');
|
|
420
|
-
const preview = Boolean(match[3]);
|
|
421
|
-
const id = buildGeminiId(version, flavor, preview);
|
|
422
|
-
models.push({
|
|
423
|
-
id,
|
|
424
|
-
name: `Gemini ${version} ${flavor.replace(/-/g, ' ')}`.trim(),
|
|
425
|
-
provider: 'google',
|
|
426
|
-
isDefault: /\bcurrent\b/i.test(clean) && clean.includes(match[0] ?? ''),
|
|
427
|
-
});
|
|
428
|
-
}
|
|
429
|
-
for (const match of clean.matchAll(/\bAuto\s*Gemini\s*(\d(?:\.\d)?)\b/gi)) {
|
|
430
|
-
const version = match[1] ?? '';
|
|
431
|
-
const id = `auto-gemini-${version}`;
|
|
432
|
-
models.push({
|
|
433
|
-
id,
|
|
434
|
-
name: `Auto Gemini ${version}`,
|
|
435
|
-
provider: 'google',
|
|
436
|
-
isDefault: /\bcurrent\b/i.test(clean) && clean.includes(match[0] ?? ''),
|
|
437
|
-
});
|
|
438
|
-
}
|
|
439
|
-
return uniqueModels(models);
|
|
440
|
-
}
|
|
441
|
-
export function fallbackGeminiModels() {
|
|
442
|
-
return [
|
|
443
|
-
{ id: 'gemini-2.5-pro', name: 'Gemini 2.5 Pro', provider: 'google', isDefault: true },
|
|
444
|
-
{ id: 'gemini-2.5-flash', name: 'Gemini 2.5 Flash', provider: 'google' },
|
|
445
|
-
{ id: 'auto-gemini-2.5', name: 'Auto Gemini 2.5', provider: 'google' },
|
|
446
|
-
];
|
|
447
|
-
}
|
|
1
|
+
function m(n){return n.replace(/\u001b\[[0-9;?]*[a-zA-Z]/g,"").replace(/\u001b\][^\u0007]*\u0007/g,"").replace(/[\u0000-\u0008\u000b-\u001f\u007f]/g,"")}function c(n){const e=new Set,o=[];for(const t of n)!t.id||e.has(t.id)||(e.add(t.id),o.push(t));return o}function h(n){return n&&n[0].toUpperCase()+n.slice(1)}function A(n){return n.split("-").map(e=>e==="gpt"?"GPT":e==="codex"?"Codex":/^\d/.test(e)?e:h(e)).join("-")}function M(n){switch(n){case"low":return"Low";case"medium":return"Medium";case"high":return"High";case"xhigh":return"Extra High";default:return h(n)}}function O(n){return n.split("-").map(e=>/^\d/.test(e)?e:h(e)).join(" ")}function S(n,e,o=!1){const t=e.toLowerCase().replace(/\s+/g,"-");return`gemini-${n}-${t}${o?"-preview":""}`}function H(n){const e=[],o=m(n);for(const t of o.split(`
|
|
2
|
+
`)){const i=t.trim().match(/^(\S+)\s+-\s+(.+?)(?:\s+\(([^)]+)\))?$/);if(!i)continue;const[,s,r,a]=i,u=a?.split(",").map(d=>d.trim().toLowerCase())??[];e.push({id:s,name:r.trim()||O(s),description:a?.trim(),isDefault:u.includes("default")||u.includes("current")})}return c(e)}function T(n){try{const o=(JSON.parse(n).models??[]).filter(t=>t.available).map(t=>({id:t.key,name:t.name?.trim()||t.key,provider:t.key.split("/")[0],description:t.tags?.join(", "),isDefault:t.tags?.includes("default")??!1}));return c(o)}catch{return[]}}function F(n){const e=m(n).split(`
|
|
3
|
+
`).map(o=>o.trim()).filter(Boolean).filter(o=>!o.includes(" ")).map(o=>({id:o,name:o,provider:o.includes("/")?o.split("/")[0]:void 0}));return c(e)}function G(n){const e=m(n).replace(/\s+/g," "),o=[[/\d+\.Default\(recommended\).*?(?:Sonnet|currently\s*Sonnet)\s*([\d.]+)/i,"default","Default (recommended)"],[/\d+\.Sonnet.*?Sonnet\s*([\d.]+)/i,"sonnet","Sonnet"],[/\d+\.Opus.*?Opus\s*([\d.]+)/i,"opus","Opus"],[/\d+\.Haiku.*?Haiku\s*([\d.]+)/i,"haiku","Haiku"]],t=[];for(const[a,u,d]of o){const l=e.match(a);l&&t.push(g({id:u,name:d,description:`v${l[1]}`,provider:"anthropic",isDefault:u==="default"}))}if(t.length>0)return c(t);const i=[],s=e.match(/currently\s*(Sonnet|Opus|Haiku)\s*([34](?:\.\d)?)/i),r={sonnet:"sonnet",opus:"opus",haiku:"haiku"};for(const a of e.matchAll(/\b(Sonnet|Opus|Haiku)\s*([34](?:\.\d)?)\b/gi)){const u=(a[1]??"").toLowerCase(),d=r[u];if(!d)continue;const l=a[2]??"",v=s&&s[1]?.toLowerCase()===u&&s[2]===l;i.push(g({id:d,name:`${h(u)} ${l}`,provider:"anthropic",isDefault:!!v}))}return c(i)}function _(n,e){const o=Math.max(n.length,e.length);for(let t=0;t<o;t++){const i=n[t]??-1,s=e[t]??-1;if(i!==s)return i-s}return 0}function R(n,e){const o=n.match(new RegExp(`^claude-${e}-([0-9]+(?:-[0-9]+)*)$`,"i"));if(!o?.[1])return null;const t=o[1].split("-").map(i=>Number.parseInt(i,10)).filter(i=>Number.isFinite(i));return t.length===0||t.length>2?null:t}function k(n){if(n?.length)return`v${n.join(".")}`}const C={default:"Default (recommended)",sonnet:"Sonnet",opus:"Opus",haiku:"Haiku"},y={default:"ANTHROPIC_MODEL",sonnet:"ANTHROPIC_DEFAULT_SONNET_MODEL",opus:"ANTHROPIC_DEFAULT_OPUS_MODEL",haiku:"ANTHROPIC_DEFAULT_HAIKU_MODEL"},w=[{id:"max",name:"Max"}],$=[{id:"low",name:"Low"},{id:"medium",name:"Medium"},{id:"high",name:"High"},{id:"xhigh",name:"Extra High"},{id:"max",name:"Max"}];function g(n){return{...n,supportedReasoningEfforts:$,defaultReasoningEffort:"medium"}}function E(n,e){return n[e]?.trim()||null}function D(n,e){const o=E(e,"ANTHROPIC_BASE_URL")?.toLowerCase()??"";return o.includes("deepseek.com")||n.toLowerCase().startsWith("deepseek-")?"deepseek":o?"custom":"anthropic"}function x(n){const e=new Set;for(const t of Object.values(y)){const i=E(n,t);i&&e.add(i)}const o=Array.from(e).map((t,i)=>{const s=D(t,n),r={id:t,name:t,provider:s,isDefault:i===0};return s==="deepseek"?{...r,supportedReasoningEfforts:w,defaultReasoningEffort:E(n,"CLAUDE_CODE_EFFORT_LEVEL")??"max"}:g(r)});return c(o)}function I(n=process.env){return x(n)}function N(n,e=process.env){return n.map(o=>{if(!["default","sonnet","opus","haiku"].includes(o.id))return o;const t=o.id,i=E(e,y[t]);if(!i)return o;const r=`Claude Code alias: ${C[t]}`;return{...o,name:i,description:o.description?`${r} \xB7 ${o.description}`:r,provider:D(i,e)}})}function U(n){const e=m(n),o=new Map;for(const i of["sonnet","opus","haiku"])for(const s of e.matchAll(new RegExp(`\\bclaude-${i}-[0-9.-]+\\b`,"gi"))){const r=s[0].trim().toLowerCase().replace(/\./g,"-").replace(/-+$/g,""),a=R(r,i);if(!a)continue;const u=o.get(i);(!u||_(u,a)<0)&&o.set(i,a)}const t=[];for(const i of["default","sonnet","opus","haiku"]){if(!new RegExp(`\\b${i}\\b`,"i").test(e))continue;const s=(i==="default"?o.get("sonnet"):o.get(i))??null;t.push(g({id:i,name:C[i],description:k(s),provider:"anthropic",isDefault:i==="default"}))}return c(t)}function P(n=process.env){const e=x(n);return e.length>0?e:N([{id:"default",name:"Default (recommended)",provider:"anthropic",isDefault:!0},{id:"sonnet",name:"Sonnet",provider:"anthropic"},{id:"opus",name:"Opus",provider:"anthropic"},{id:"haiku",name:"Haiku",provider:"anthropic"}],n).map(g)}function j(n){const e=m(n),o=[];for(const t of e.split(`
|
|
4
|
+
`)){const i=t.match(/\b(gpt-[a-z0-9][a-z0-9.-]*)\b/i);if(!i)continue;const s=i[1].trim(),r=t.replace(s,"").replace(/^[^\w]+/,"").trim()||void 0;o.push({id:s,name:A(s),description:r,provider:"openai",isDefault:/\bcurrent\b/i.test(t)||/\bselected\b/i.test(t)})}return c(o)}function V(n){const e=typeof n=="object"&&n!==null?n:{},o=typeof e.config?.model=="string"?e.config.model:void 0,t=typeof e.config?.model_reasoning_effort=="string"?e.config.model_reasoning_effort:void 0,i=[];for(const s of e.data??[]){if(typeof s!="object"||s===null)continue;const r=s,a=typeof r.id=="string"?r.id:typeof r.model=="string"?r.model:"";if(!a)continue;const u=typeof r.displayName=="string"?r.displayName:typeof r.name=="string"?r.name:void 0,d=typeof r.description=="string"?r.description:void 0,l=typeof r.defaultReasoningEffort=="string"?r.defaultReasoningEffort:void 0,v=Array.isArray(r.supportedReasoningEfforts)?r.supportedReasoningEfforts.map(f=>{if(typeof f!="object"||f===null)return null;const p=f,b=typeof p.reasoningEffort=="string"?p.reasoningEffort:typeof p.id=="string"?p.id:"";return b?{id:b,name:M(b),description:typeof p.description=="string"?p.description:void 0}:null}).filter(f=>f!=null):void 0,L=Array.isArray(r.additionalSpeedTiers)?r.additionalSpeedTiers.filter(f=>typeof f=="string"):void 0;i.push({id:a,name:u||A(a),description:d,provider:"openai",isDefault:o?o===a:r.isDefault===!0,supportedReasoningEfforts:v,defaultReasoningEffort:l,additionalSpeedTiers:L})}return o&&!i.some(s=>s.id===o)&&i.unshift({id:o,name:A(o),provider:"openai",isDefault:!0,defaultReasoningEffort:t}),c(i)}function z(n){const e=m(n),o=[];for(const t of e.matchAll(/\b(?:auto-)?gemini-[a-z0-9.-]+\b/gi)){const i=t[0].trim();o.push({id:i,name:i,provider:"google",isDefault:/\bcurrent\b/i.test(e)&&e.includes(i)})}for(const t of e.matchAll(/\bGemini\s*(\d(?:\.\d)?)\s*(Pro|Flash(?:[- ]Lite)?)\s*(Preview)?\b/gi)){const i=t[1]??"",s=(t[2]??"").replace(/\s+/g,"-"),r=!!t[3],a=S(i,s,r);o.push({id:a,name:`Gemini ${i} ${s.replace(/-/g," ")}`.trim(),provider:"google",isDefault:/\bcurrent\b/i.test(e)&&e.includes(t[0]??"")})}for(const t of e.matchAll(/\bAuto\s*Gemini\s*(\d(?:\.\d)?)\b/gi)){const i=t[1]??"",s=`auto-gemini-${i}`;o.push({id:s,name:`Auto Gemini ${i}`,provider:"google",isDefault:/\bcurrent\b/i.test(e)&&e.includes(t[0]??"")})}return c(o)}function B(){return[{id:"gemini-2.5-pro",name:"Gemini 2.5 Pro",provider:"google",isDefault:!0},{id:"gemini-2.5-flash",name:"Gemini 2.5 Flash",provider:"google"},{id:"auto-gemini-2.5",name:"Auto Gemini 2.5",provider:"google"}]}export{N as applyClaudeModelEnvOverrides,I as discoverClaudeAliasModelsFromEnv,P as fallbackClaudeAliasModels,B as fallbackGeminiModels,D as inferClaudeOverrideProvider,U as parseClaudeBinaryModels,G as parseClaudeModels,V as parseCodexAppServerModels,j as parseCodexModels,H as parseCursorModels,z as parseGeminiModels,T as parseOpenClawModels,F as parseOpenCodeModels,E as readEnvValue,m as stripAnsi};
|