cli-surf 0.11.0 → 0.12.1

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/cliUi.js CHANGED
@@ -4,6 +4,8 @@
4
4
  * pipe или не-TTY, чтобы вывод оставался пригодным для скриптов.
5
5
  */
6
6
  import { emitKeypressEvents } from 'node:readline';
7
+ import { OPUS_MODEL_IDS } from './opusModels.js';
8
+ export { OPUS_MODEL_IDS };
7
9
  let cliLanguage = 'ru';
8
10
  export function setCliLanguage(value) {
9
11
  cliLanguage = value === 'en' || value === 'English' ? 'en' : 'ru';
@@ -15,45 +17,91 @@ export function isRussian() {
15
17
  export function tr(ru, en) {
16
18
  return isRussian() ? ru : en;
17
19
  }
18
- export const OPUS_MODEL_IDS = [
19
- 'auto', 'fast', 'advanced', 'sol', 'terra', 'luna',
20
- 'gpt54mini', 'gpt54nano', 'gpt5mini', 'gpt5nano',
21
- 'o3', 'o3mini', 'o4mini',
22
- 'gemini37flash', 'gemini35flashlite', 'gemini31pro', 'gemini25pro',
23
- 'musespark13', 'musespark12',
24
- 'grok46',
25
- ];
26
20
  /** Человеческие имена — один в один как в мессенджере (OPUS_MODELS). */
27
21
  const MODEL_DISPLAY = {
22
+ // По умолчанию
28
23
  auto: 'Auto',
29
- fast: 'GPT-4o mini',
30
- advanced: 'GPT-4o',
24
+ // Для сложных задач
25
+ claudeopus5: 'Claude Opus 5',
26
+ astra: 'GPT-6 Astra',
27
+ kimik3: 'Kimi K3',
28
+ // Claude
29
+ claudesonnet5: 'Claude Sonnet 5',
30
+ claudehaiku45: 'Claude Haiku 4.5',
31
+ claudefable51: 'Claude Fable 5.1',
32
+ // OpenAI
31
33
  sol: 'GPT-5.6 Sol',
32
34
  terra: 'GPT-5.6 Terra',
33
35
  luna: 'GPT-5.6 Luna',
34
36
  gpt54mini: 'GPT-5.4 Mini',
37
+ // SpaceXAI
38
+ grok46: 'Grok 4.6',
39
+ grok45: 'Grok 4.5',
40
+ grok43: 'Grok 4.3',
41
+ // Google
42
+ gemini38flash: 'Gemini 3.8 Flash',
43
+ gemini37flash: 'Gemini 3.7 Flash',
44
+ gemini35flashlite: 'Gemini 3.5 Flash-Lite',
45
+ // Открытые модели
46
+ glm53flash: 'GLM-5.3 Flash',
47
+ musespark13: 'Muse Spark 1.3',
48
+ // Предыдущие модели
49
+ advanced: 'GPT-4o',
50
+ fast: 'GPT-4o mini',
35
51
  gpt54nano: 'GPT-5.4 Nano',
36
52
  gpt5mini: 'GPT-5 Mini',
37
53
  gpt5nano: 'GPT-5 Nano',
38
54
  o3: 'o3',
39
55
  o3mini: 'o3-mini',
40
56
  o4mini: 'o4-mini',
41
- gemini37flash: 'Gemini 3.7 Flash',
42
- gemini35flashlite: 'Gemini 3.5 Flash-Lite',
57
+ gemini36flash: 'Gemini 3.6 Flash',
58
+ gemini35flash: 'Gemini 3.5 Flash',
43
59
  gemini31pro: 'Gemini 3.1 Pro',
44
- gemini25pro: 'Gemini 2.5 Pro',
45
- musespark13: 'Muse Spark 1.3',
46
- musespark12: 'Muse Spark 1.2',
47
- grok46: 'Grok 4.6',
60
+ gemini31flashlite: 'Gemini 3.1 Flash-Lite',
61
+ kimik26: 'Kimi K2.6',
62
+ kimik27code: 'Kimi K2.7 Code',
48
63
  };
49
64
  export function modelDisplayName(id) {
50
65
  return MODEL_DISPLAY[id] ?? id;
51
66
  }
52
- /** Вручную выбираются настоящие модели. Скрыты только режимы:
53
- * auto (дефолт), fast (дешёвая для free), advanced (legacy GPT-4o).
54
- * Скрытые работают, если задать явно: /model fast, --model auto. */
55
- const HIDDEN_ALIASES = new Set(['auto', 'fast', 'advanced']);
56
- export const PICKABLE_MODEL_IDS = OPUS_MODEL_IDS.filter(id => !HIDDEN_ALIASES.has(id));
67
+ /** Категории/подсказки секций в точности как в разделах мессенджера */
68
+ export const MODEL_HINTS = {
69
+ auto: { ru: 'баланс скорости, качества и цены (по умолчанию)', en: 'balances speed, effort, and cost (default)' },
70
+ claudeopus5: { ru: 'для сложных задач', en: 'for hardest tasks' },
71
+ astra: { ru: 'для сложных задач', en: 'for hardest tasks' },
72
+ kimik3: { ru: 'для сложных задач', en: 'for hardest tasks' },
73
+ claudesonnet5: { ru: 'Claude', en: 'Claude' },
74
+ claudehaiku45: { ru: 'Claude', en: 'Claude' },
75
+ claudefable51: { ru: 'Claude', en: 'Claude' },
76
+ sol: { ru: 'OpenAI', en: 'OpenAI' },
77
+ terra: { ru: 'OpenAI', en: 'OpenAI' },
78
+ luna: { ru: 'OpenAI', en: 'OpenAI' },
79
+ gpt54mini: { ru: 'OpenAI', en: 'OpenAI' },
80
+ grok46: { ru: 'SpaceXAI', en: 'SpaceXAI' },
81
+ grok45: { ru: 'SpaceXAI', en: 'SpaceXAI' },
82
+ grok43: { ru: 'SpaceXAI', en: 'SpaceXAI' },
83
+ gemini38flash: { ru: 'Google', en: 'Google' },
84
+ gemini37flash: { ru: 'Google', en: 'Google' },
85
+ gemini35flashlite: { ru: 'Google', en: 'Google' },
86
+ glm53flash: { ru: 'открытые модели', en: 'open models' },
87
+ musespark13: { ru: 'открытые модели', en: 'open models' },
88
+ advanced: { ru: 'предыдущие модели', en: 'older models' },
89
+ fast: { ru: 'предыдущие модели', en: 'older models' },
90
+ gpt54nano: { ru: 'предыдущие модели', en: 'older models' },
91
+ gpt5mini: { ru: 'предыдущие модели', en: 'older models' },
92
+ gpt5nano: { ru: 'предыдущие модели', en: 'older models' },
93
+ o3: { ru: 'предыдущие модели', en: 'older models' },
94
+ o3mini: { ru: 'предыдущие модели', en: 'older models' },
95
+ o4mini: { ru: 'предыдущие модели', en: 'older models' },
96
+ gemini36flash: { ru: 'предыдущие модели', en: 'older models' },
97
+ gemini35flash: { ru: 'предыдущие модели', en: 'older models' },
98
+ gemini31pro: { ru: 'предыдущие модели', en: 'older models' },
99
+ gemini31flashlite: { ru: 'предыдущие модели', en: 'older models' },
100
+ kimik26: { ru: 'предыдущие модели', en: 'older models' },
101
+ kimik27code: { ru: 'предыдущие модели', en: 'older models' },
102
+ };
103
+ /** Список моделей для выбора — в точности как в мессенджере (все модели включая Auto). */
104
+ export const PICKABLE_MODEL_IDS = OPUS_MODEL_IDS;
57
105
  /** «GPT-5 Mini» → «gpt5mini»: регистр, пробелы, точки и дефисы не важны. */
58
106
  export function normModelKey(raw) {
59
107
  return raw.toLowerCase().replace(/[^a-z0-9]/g, '');
@@ -143,7 +191,12 @@ export function statusLabel(status) {
143
191
  case 'gitlab': return tr('Работаю с GitLab…', 'Working with GitLab…');
144
192
  case 'notion': return tr('Работаю с Notion…', 'Working with Notion…');
145
193
  case 'google-calendar': return tr('Работаю с Google Calendar…', 'Working with Google Calendar…');
194
+ case 'google-drive': return tr('Работаю с Google Drive…', 'Working with Google Drive…');
195
+ case 'google-sheets': return tr('Работаю с Google Sheets…', 'Working with Google Sheets…');
146
196
  case '101': return tr('Работаю с 101…', 'Working with 101…');
197
+ case 'airtable': return tr('Работаю с Airtable…', 'Working with Airtable…');
198
+ case 'todoist': return tr('Работаю с Todoist…', 'Working with Todoist…');
199
+ case 'linear': return tr('Работаю с Linear…', 'Working with Linear…');
147
200
  case 'calling': return tr('Звоню…', 'Calling…');
148
201
  default: return tr('Думаю…', 'Thinking…');
149
202
  }
@@ -303,7 +356,7 @@ export function assistantHead(model) {
303
356
  }
304
357
  /** Автокомплит для readline: /команды и id моделей после /model. */
305
358
  export function completer(line) {
306
- const commands = ['/usage', '/model', '/permissions', '/clear', '/help', '/skills', '/logout', '/exit', '/quit'];
359
+ const commands = ['/usage', '/model', '/permissions', '/open', '/get', '/clear', '/help', '/skills', '/logout', '/exit', '/quit'];
307
360
  if (line.startsWith('/model ')) {
308
361
  const frag = line.slice('/model '.length);
309
362
  return [PICKABLE_MODEL_IDS.filter(m => m.startsWith(frag)).map(m => `/model ${m}`), line];
@@ -344,6 +397,8 @@ export function chatHelp() {
344
397
  ['/usage', tr('общий лимит с мессенджером', 'shared messenger limit')],
345
398
  ['/model [name]', tr('выбор стрелками, запоминается', 'choose with arrows; saved')],
346
399
  ['/permissions', tr('режим подтверждений агента', 'agent confirmation mode')],
400
+ ['/open [файл]', tr('открыть файл (или последний созданный)', 'open file (or last created)')],
401
+ ['/get <url>', tr('скачать вложение Opus', 'download Opus attachment')],
347
402
  ['! text', tr('выполнить как задачу с файлами', 'run as a task with files')],
348
403
  ['/clear', tr('очистить историю чата', 'clear chat history')],
349
404
  ['/logout', tr('выйти из аккаунта', 'sign out')],
package/opusModels.js CHANGED
@@ -1,5 +1,49 @@
1
+ export const OPUS_MODEL_IDS = [
2
+ // По умолчанию
3
+ 'auto',
4
+ // Для сложных задач (Hardest tasks)
5
+ 'claudeopus5',
6
+ 'astra',
7
+ 'kimik3',
8
+ // Claude
9
+ 'claudesonnet5',
10
+ 'claudehaiku45',
11
+ 'claudefable51',
12
+ // OpenAI
13
+ 'sol',
14
+ 'terra',
15
+ 'luna',
16
+ 'gpt54mini',
17
+ // SpaceXAI
18
+ 'grok46',
19
+ 'grok45',
20
+ 'grok43',
21
+ // Google
22
+ 'gemini38flash',
23
+ 'gemini37flash',
24
+ 'gemini35flashlite',
25
+ // Открытые модели (Open models)
26
+ 'glm53flash',
27
+ 'musespark13',
28
+ // Предыдущие модели (Older models)
29
+ 'advanced',
30
+ 'fast',
31
+ 'gpt54nano',
32
+ 'gpt5mini',
33
+ 'gpt5nano',
34
+ 'o3',
35
+ 'o3mini',
36
+ 'o4mini',
37
+ 'gemini36flash',
38
+ 'gemini35flash',
39
+ 'gemini31pro',
40
+ 'gemini31flashlite',
41
+ 'kimik26',
42
+ 'kimik27code',
43
+ ];
1
44
  export function normalizeOpusModelId(value) {
2
45
  if (value === 'auto'
46
+ || value === 'astra'
3
47
  || value === 'sol'
4
48
  || value === 'terra'
5
49
  || value === 'luna'
@@ -10,21 +54,94 @@ export function normalizeOpusModelId(value) {
10
54
  || value === 'o3'
11
55
  || value === 'o3mini'
12
56
  || value === 'o4mini'
57
+ || value === 'glm53flash'
58
+ || value === 'musespark13'
59
+ || value === 'muse-spark-1.3'
60
+ || value === 'meta/muse-spark-1.3'
61
+ || value === 'meta/muse-spark-1.3-contributor'
62
+ || value === 'gemini38flash'
13
63
  || value === 'gemini37flash'
14
64
  || value === 'gemini35flashlite'
65
+ || value === 'gemini36flash'
66
+ || value === 'gemini35flash'
15
67
  || value === 'gemini31pro'
16
- || value === 'gemini25pro'
17
- || value === 'musespark13'
18
- || value === 'musespark12'
19
- || value === 'grok46')
68
+ || value === 'gemini31flashlite'
69
+ || value === 'claudehaiku45'
70
+ || value === 'claude-haiku-4-5'
71
+ || value === 'claudefable51'
72
+ || value === 'claude-fable-5-1'
73
+ || value === 'claudeopus5'
74
+ || value === 'claude-opus-5'
75
+ || value === 'claudesonnet5'
76
+ || value === 'claude-sonnet-5'
77
+ || value === 'grok46'
78
+ || value === 'grok45'
79
+ || value === 'grok-4-5'
80
+ || value === 'grok43'
81
+ || value === 'grok-4-3'
82
+ || value === 'kimik3'
83
+ || value === 'kimik26'
84
+ || value === 'kimik27code') {
85
+ if (value === 'claude-haiku-4-5')
86
+ return 'claudehaiku45';
87
+ if (value === 'claude-fable-5-1')
88
+ return 'claudefable51';
89
+ if (value === 'claude-opus-5')
90
+ return 'claudeopus5';
91
+ if (value === 'claude-sonnet-5')
92
+ return 'claudesonnet5';
93
+ if (value === 'grok-4-5')
94
+ return 'grok45';
95
+ if (value === 'grok-4-3')
96
+ return 'grok43';
97
+ if (value === 'muse-spark-1.3' || value === 'meta/muse-spark-1.3' || value === 'meta/muse-spark-1.3-contributor')
98
+ return 'musespark13';
20
99
  return value;
100
+ }
21
101
  if (value === 'fast' || value === 'advanced')
22
102
  return value;
103
+ // Алиасы для удобства ввода в CLI
104
+ if (value === 'astra' || value === 'gpt-6-astra' || value === 'gpt6-astra' || value === 'gpt6astra' || value === 'gpt6' || value === 'gpt-6' || value === 'openai/gpt-6-astra')
105
+ return 'astra';
106
+ if (value === 'opus' || value === 'opus5')
107
+ return 'claudeopus5';
108
+ if (value === 'sonnet' || value === 'sonnet5')
109
+ return 'claudesonnet5';
110
+ if (value === 'haiku' || value === 'haiku45')
111
+ return 'claudehaiku45';
112
+ if (value === 'fable' || value === 'fable51')
113
+ return 'claudefable51';
114
+ if (value === 'gpt4o' || value === '4o')
115
+ return 'advanced';
116
+ if (value === 'gpt4omini' || value === '4omini')
117
+ return 'fast';
118
+ if (value === 'gemini')
119
+ return 'gemini38flash';
120
+ if (value === 'gemini-3.7-flash' || value === 'gemini37flash' || value === 'google/gemini-3.7-flash')
121
+ return 'gemini37flash';
122
+ if (value === 'gemini-3.5-flash-lite' || value === 'gemini35flashlite' || value === 'google/gemini-3.5-flash-lite')
123
+ return 'gemini35flashlite';
124
+ if (value === 'gemini-3.6-flash' || value === 'gemini36flash' || value === 'google/gemini-3.6-flash')
125
+ return 'gemini36flash';
126
+ if (value === 'gemini-3.5-flash' || value === 'gemini35flash' || value === 'google/gemini-3.5-flash')
127
+ return 'gemini35flash';
128
+ if (value === 'gemini-3.1-pro' || value === 'gemini31pro' || value === 'google/gemini-3.1-pro')
129
+ return 'gemini31pro';
130
+ if (value === 'gemini-3.1-flash-lite' || value === 'gemini31flashlite' || value === 'google/gemini-3.1-flash-lite')
131
+ return 'gemini31flashlite';
132
+ if (value === 'glm')
133
+ return 'glm53flash';
134
+ if (value === 'kimi')
135
+ return 'kimik3';
136
+ if (value === 'muse' || value === 'musespark' || value === 'muse13' || value === 'muse-spark' || value === 'muse-spark-1.3' || value === 'meta/muse-spark-1.3' || value === 'meta/muse-spark-1.3-contributor')
137
+ return 'musespark13';
23
138
  return 'auto';
24
139
  }
25
140
  export function opusProviderModel(model) {
26
141
  if (model === 'auto')
27
142
  return 'openai/gpt-5.6-terra';
143
+ if (model === 'astra')
144
+ return 'openai/gpt-6-astra';
28
145
  if (model === 'sol')
29
146
  return 'openai/gpt-5.6-sol';
30
147
  if (model === 'terra')
@@ -45,37 +162,73 @@ export function opusProviderModel(model) {
45
162
  return 'openai/o3-mini';
46
163
  if (model === 'o4mini')
47
164
  return 'openai/o4-mini';
165
+ if (model === 'claudehaiku45')
166
+ return 'anthropic/claude-haiku-4-5';
167
+ if (model === 'claudefable51')
168
+ return 'anthropic/claude-fable-5-1';
169
+ if (model === 'claudeopus5')
170
+ return 'anthropic/claude-opus-5';
171
+ if (model === 'claudesonnet5')
172
+ return 'anthropic/claude-sonnet-5';
173
+ if (model === 'glm53flash')
174
+ return 'z-ai/glm-5.3-flash';
175
+ if (model === 'musespark13')
176
+ return 'meta/muse-spark-1.3-contributor';
177
+ if (model === 'gemini38flash')
178
+ return 'google/gemini-3.8-flash';
48
179
  if (model === 'gemini37flash')
49
- return 'gemini/gemini-3.7-flash';
180
+ return 'google/gemini-3.7-flash';
50
181
  if (model === 'gemini35flashlite')
51
- return 'gemini/gemini-3.5-flash-lite';
182
+ return 'google/gemini-3.5-flash-lite';
183
+ if (model === 'gemini36flash')
184
+ return 'google/gemini-3.6-flash';
185
+ if (model === 'gemini35flash')
186
+ return 'google/gemini-3.5-flash';
52
187
  if (model === 'gemini31pro')
53
- return 'gemini/gemini-3.1-pro-preview';
54
- if (model === 'gemini25pro')
55
- return 'gemini/gemini-2.5-pro';
56
- if (model === 'musespark13')
57
- return 'meta/muse-spark-1.3-contributor';
58
- if (model === 'musespark12')
59
- return 'meta/muse-spark-1.2-contributor';
188
+ return 'google/gemini-3.1-pro';
189
+ if (model === 'gemini31flashlite')
190
+ return 'google/gemini-3.1-flash-lite';
60
191
  if (model === 'grok46')
61
192
  return 'x-ai/grok-4.6';
193
+ if (model === 'grok45')
194
+ return 'x-ai/grok-4.5';
195
+ if (model === 'grok43')
196
+ return 'x-ai/grok-4.3';
197
+ if (model === 'kimik3')
198
+ return 'moonshotai/kimi-k3';
199
+ if (model === 'kimik26')
200
+ return 'moonshotai/kimi-k2.6';
201
+ if (model === 'kimik27code')
202
+ return 'moonshotai/kimi-k2.7-code';
62
203
  return model === 'advanced' ? 'openai/gpt-4o' : 'openai/gpt-4o-mini';
63
204
  }
64
205
  export function isReasoningProviderModel(model) {
65
206
  return typeof model === 'string' && model.startsWith('openai/o');
66
207
  }
208
+ export const PRO_PLUS_MODELS = [
209
+ 'claudeopus5',
210
+ 'astra',
211
+ 'sol',
212
+ 'o3',
213
+ 'grok46',
214
+ 'kimik3',
215
+ ];
216
+ export function isProPlusModel(model) {
217
+ return PRO_PLUS_MODELS.includes(model);
218
+ }
67
219
  export function normalizeReasoningEffort(value) {
68
220
  if (value === 'low' || value === 'high')
69
221
  return value;
70
222
  return 'medium';
71
223
  }
72
- export function autoOpusModelForRequest(text, history, attachments) {
224
+ export function autoOpusModelForRequest(text, history, attachments, isProPlusUser) {
73
225
  const prompt = typeof text === 'string' ? text.trim() : '';
74
226
  const historyLength = Array.isArray(history) ? history.length : 0;
75
227
  const attachmentCount = Array.isArray(attachments) ? attachments.length : 0;
76
228
  const complexRequest = /(?:анализ|проанализ|исслед|сравни|документ|архитектур|код|программ|план|стратег|математ|доказ|analy[sz]|research|compare|document|architect|\bcode\b|program|strategy|math|prove)/i.test(prompt);
77
- if (attachmentCount > 0 || prompt.length > 1000 || historyLength >= 8 || complexRequest)
78
- return 'sol';
229
+ if (attachmentCount > 0 || prompt.length > 1000 || historyLength >= 8 || complexRequest) {
230
+ return isProPlusUser ? 'astra' : 'terra';
231
+ }
79
232
  if (prompt.length < 180 && historyLength <= 2)
80
233
  return 'luna';
81
234
  return 'terra';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cli-surf",
3
- "version": "0.11.0",
3
+ "version": "0.12.1",
4
4
  "description": "Surf Opus CLI — terminal client for Surf messenger with shared AI limits",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -14,6 +14,7 @@
14
14
  "cliPrompt.js",
15
15
  "cliTools.js",
16
16
  "cliSkills.js",
17
+ "cliMcp.js",
17
18
  "opusModels.js",
18
19
  "skills/**/*",
19
20
  "README.md"