shennian 0.2.88 → 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.
Files changed (143) hide show
  1. package/dist/assets/wechat-channel/macos/manifest.json +22 -0
  2. package/dist/assets/wechat-channel/macos/shennian-wechat-channel-helper +0 -0
  3. package/dist/bin/shennian.js +1 -1
  4. package/dist/publish-build-manifest.json +548 -0
  5. package/dist/scripts/wechat-rpa-confirmation.mjs +5 -97
  6. package/dist/src/agent-env.js +4 -105
  7. package/dist/src/agents/adapter.d.ts +6 -0
  8. package/dist/src/agents/adapter.js +1 -19
  9. package/dist/src/agents/claude.js +8 -305
  10. package/dist/src/agents/codex-control.d.ts +35 -0
  11. package/dist/src/agents/codex-control.js +2 -0
  12. package/dist/src/agents/codex-utils.js +7 -200
  13. package/dist/src/agents/codex.d.ts +8 -0
  14. package/dist/src/agents/codex.js +15 -863
  15. package/dist/src/agents/command-spec.js +2 -413
  16. package/dist/src/agents/config-status.js +1 -226
  17. package/dist/src/agents/cursor.js +1 -249
  18. package/dist/src/agents/custom.js +4 -271
  19. package/dist/src/agents/detect.js +1 -56
  20. package/dist/src/agents/external-channel-instructions.js +10 -94
  21. package/dist/src/agents/gemini.js +1 -173
  22. package/dist/src/agents/manager.js +13 -157
  23. package/dist/src/agents/model-registry/cache.js +1 -37
  24. package/dist/src/agents/model-registry/discovery.js +2 -187
  25. package/dist/src/agents/model-registry/parsers.js +4 -447
  26. package/dist/src/agents/model-registry/runner.js +1 -30
  27. package/dist/src/agents/model-registry/service.js +1 -78
  28. package/dist/src/agents/model-registry/types.js +1 -8
  29. package/dist/src/agents/model-registry.js +1 -18
  30. package/dist/src/agents/openclaw.js +2 -275
  31. package/dist/src/agents/opencode.js +1 -231
  32. package/dist/src/agents/pi-context.js +12 -217
  33. package/dist/src/agents/pi.js +14 -723
  34. package/dist/src/agents/platform-instructions.js +9 -54
  35. package/dist/src/channels/base.d.ts +4 -1
  36. package/dist/src/channels/base.js +1 -3
  37. package/dist/src/channels/registry.js +1 -30
  38. package/dist/src/channels/reply-split.js +10 -89
  39. package/dist/src/channels/runtime.d.ts +1 -0
  40. package/dist/src/channels/runtime.js +5 -533
  41. package/dist/src/channels/secret-registry.d.ts +1 -0
  42. package/dist/src/channels/secret-registry.js +1 -46
  43. package/dist/src/channels/websocket.js +8 -378
  44. package/dist/src/channels/wechat-channel/anchor.d.ts +10 -0
  45. package/dist/src/channels/wechat-channel/anchor.js +1 -0
  46. package/dist/src/channels/wechat-channel/client.d.ts +74 -0
  47. package/dist/src/channels/wechat-channel/client.js +1 -0
  48. package/dist/src/channels/wechat-channel/cooldown.d.ts +15 -0
  49. package/dist/src/channels/wechat-channel/cooldown.js +1 -0
  50. package/dist/src/channels/wechat-channel/fingerprint.d.ts +28 -0
  51. package/dist/src/channels/wechat-channel/fingerprint.js +1 -0
  52. package/dist/src/channels/wechat-channel/helper-assets.d.ts +37 -0
  53. package/dist/src/channels/wechat-channel/helper-assets.js +1 -0
  54. package/dist/src/channels/wechat-channel/helper-client.d.ts +25 -0
  55. package/dist/src/channels/wechat-channel/helper-client.js +3 -0
  56. package/dist/src/channels/wechat-channel/helper-protocol.d.ts +84 -0
  57. package/dist/src/channels/wechat-channel/helper-protocol.js +1 -0
  58. package/dist/src/channels/wechat-channel/index.d.ts +17 -0
  59. package/dist/src/channels/wechat-channel/index.js +1 -0
  60. package/dist/src/channels/wechat-channel/ledger.d.ts +33 -0
  61. package/dist/src/channels/wechat-channel/ledger.js +1 -0
  62. package/dist/src/channels/wechat-channel/media-resolver.d.ts +32 -0
  63. package/dist/src/channels/wechat-channel/media-resolver.js +1 -0
  64. package/dist/src/channels/wechat-channel/message-key.d.ts +19 -0
  65. package/dist/src/channels/wechat-channel/message-key.js +1 -0
  66. package/dist/src/channels/wechat-channel/observer.d.ts +64 -0
  67. package/dist/src/channels/wechat-channel/observer.js +1 -0
  68. package/dist/src/channels/wechat-channel/outbound-ledger.d.ts +69 -0
  69. package/dist/src/channels/wechat-channel/outbound-ledger.js +2 -0
  70. package/dist/src/channels/wechat-channel/outbound-sender.d.ts +26 -0
  71. package/dist/src/channels/wechat-channel/outbound-sender.js +1 -0
  72. package/dist/src/channels/wechat-channel/preflight.d.ts +37 -0
  73. package/dist/src/channels/wechat-channel/preflight.js +1 -0
  74. package/dist/src/channels/wechat-channel/runner.d.ts +34 -0
  75. package/dist/src/channels/wechat-channel/runner.js +1 -0
  76. package/dist/src/channels/wechat-channel/runtime.d.ts +45 -0
  77. package/dist/src/channels/wechat-channel/runtime.js +1 -0
  78. package/dist/src/channels/wechat-channel/scheduler.d.ts +35 -0
  79. package/dist/src/channels/wechat-channel/scheduler.js +1 -0
  80. package/dist/src/channels/wechat-rpa/macos-flow.js +1 -96
  81. package/dist/src/channels/wechat-rpa/macos.js +6 -48
  82. package/dist/src/channels/wechat-rpa/normalizer.js +7 -127
  83. package/dist/src/channels/wechat-rpa.d.ts +21 -0
  84. package/dist/src/channels/wechat-rpa.js +6 -1022
  85. package/dist/src/channels/wecom.js +4 -357
  86. package/dist/src/commands/agent.js +6 -131
  87. package/dist/src/commands/daemon-windows.js +8 -48
  88. package/dist/src/commands/daemon.js +19 -1013
  89. package/dist/src/commands/external-attachments.js +1 -51
  90. package/dist/src/commands/external.js +1 -137
  91. package/dist/src/commands/manager.js +2 -389
  92. package/dist/src/commands/pair-qr.js +1 -6
  93. package/dist/src/commands/pair.js +9 -287
  94. package/dist/src/commands/tools.js +1 -34
  95. package/dist/src/commands/upgrade.js +1 -198
  96. package/dist/src/config/index.js +1 -35
  97. package/dist/src/daemon-log.js +6 -58
  98. package/dist/src/env-path.js +1 -64
  99. package/dist/src/fs/boundary.js +1 -126
  100. package/dist/src/fs/handler.js +1 -130
  101. package/dist/src/fs/security.js +1 -32
  102. package/dist/src/fs/text-decoder.d.ts +10 -0
  103. package/dist/src/fs/text-decoder.js +1 -0
  104. package/dist/src/index.js +2 -404
  105. package/dist/src/log-reporter.js +1 -16
  106. package/dist/src/manager/prompt.js +29 -34
  107. package/dist/src/manager/registry.js +2 -269
  108. package/dist/src/manager/runtime.js +19 -1003
  109. package/dist/src/native-fusion/config.js +1 -5
  110. package/dist/src/native-fusion/opencode-parser.js +3 -123
  111. package/dist/src/native-fusion/parser-common.js +8 -264
  112. package/dist/src/native-fusion/parsers.js +8 -729
  113. package/dist/src/native-fusion/service.d.ts +10 -0
  114. package/dist/src/native-fusion/service.js +2 -198
  115. package/dist/src/native-fusion/state.js +1 -22
  116. package/dist/src/native-fusion/types.js +1 -1
  117. package/dist/src/region.js +1 -88
  118. package/dist/src/relay/client.js +1 -343
  119. package/dist/src/session/archive-zip.js +1 -220
  120. package/dist/src/session/handlers/agent-config.js +1 -150
  121. package/dist/src/session/handlers/agents.js +1 -55
  122. package/dist/src/session/handlers/chat.js +2 -733
  123. package/dist/src/session/handlers/control.js +1 -55
  124. package/dist/src/session/handlers/fs.js +1 -747
  125. package/dist/src/session/handlers/session-refresh.js +1 -35
  126. package/dist/src/session/handlers/skills.js +1 -121
  127. package/dist/src/session/handlers/title.js +1 -60
  128. package/dist/src/session/handlers/tool-detail.d.ts +3 -0
  129. package/dist/src/session/handlers/tool-detail.js +1 -0
  130. package/dist/src/session/manager.d.ts +3 -0
  131. package/dist/src/session/manager.js +1 -261
  132. package/dist/src/session/projection.js +1 -54
  133. package/dist/src/session/queue.js +4 -317
  134. package/dist/src/session/remote-attachments.js +1 -72
  135. package/dist/src/session/store.js +3 -109
  136. package/dist/src/session/types.d.ts +4 -0
  137. package/dist/src/session/types.js +1 -4
  138. package/dist/src/skills/registry.js +15 -148
  139. package/dist/src/skills/setup.js +1 -101
  140. package/dist/src/tools/markdown-to-pdf.js +10 -346
  141. package/dist/src/upgrade/engine.js +3 -347
  142. package/package.json +3 -2
  143. package/dist/scripts/wechat-rpa-download-candidates.mjs +0 -105
@@ -1,187 +1,2 @@
1
- // @arch docs/architecture/cli/model-discovery.md
2
- // @test src/__tests__/model-switching.test.ts
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
- // @arch docs/architecture/cli/model-discovery.md
2
- // @test src/__tests__/model-switching.test.ts
3
- export function stripAnsi(text) {
4
- return text
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};