@mmmbuto/nexuscli 0.7.0 → 0.7.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.
@@ -59,7 +59,7 @@
59
59
 
60
60
  <!-- Prevent Scaling on iOS -->
61
61
  <meta name="format-detection" content="telephone=no" />
62
- <script type="module" crossorigin src="/assets/index-DuqGKSR-.js"></script>
62
+ <script type="module" crossorigin src="/assets/index-DgHku52j.js"></script>
63
63
  <link rel="stylesheet" crossorigin href="/assets/index-Bn_l1e6e.css">
64
64
  </head>
65
65
  <body>
package/lib/cli/model.js CHANGED
@@ -4,9 +4,38 @@
4
4
  */
5
5
 
6
6
  const chalk = require('chalk');
7
- const { getConfig, setConfigValue } = require('../config/manager');
7
+ const {
8
+ getConfig,
9
+ setConfigValue,
10
+ isInitialized
11
+ } = require('../config/manager');
12
+ const {
13
+ getCliTools,
14
+ isValidModelId,
15
+ getAllModels
16
+ } = require('../config/models');
8
17
 
9
18
  async function modelCommand(modelId) {
19
+ if (!isInitialized()) {
20
+ console.log(chalk.red('NexusCLI non è inizializzato.'));
21
+ console.log(chalk.yellow('Esegui prima: nexuscli init'));
22
+ return;
23
+ }
24
+
25
+ const cliTools = getCliTools();
26
+ const allModels = getAllModels();
27
+
28
+ const printAvailableModels = () => {
29
+ console.log(chalk.bold('\nModelli disponibili:'));
30
+ for (const [key, cli] of Object.entries(cliTools)) {
31
+ console.log(chalk.dim(`${cli.name}:`));
32
+ for (const model of cli.models || []) {
33
+ const label = model.label || model.name;
34
+ const defaultTag = model.default ? chalk.green(' (default)') : '';
35
+ console.log(` ${model.id} ${chalk.gray(`- ${label}`)}${defaultTag}`);
36
+ }
37
+ }
38
+ };
10
39
 
11
40
  // If no model specified, show current default
12
41
  if (!modelId) {
@@ -21,23 +50,15 @@ async function modelCommand(modelId) {
21
50
  console.log(chalk.dim('Usage: nexuscli model <model-id>'));
22
51
  }
23
52
 
24
- // Show available models
25
- console.log(chalk.bold('\nAvailable models:'));
26
- console.log(chalk.dim('Claude:'));
27
- console.log(' claude-sonnet-4-5-20250929');
28
- console.log(' claude-opus-4-5-20250514');
29
- console.log(' claude-3-7-sonnet-20250219');
30
- console.log(' claude-haiku-4-5-20250514');
31
- console.log(chalk.dim('OpenAI (Codex):'));
32
- console.log(' gpt-5.1-codex-max');
33
- console.log(' gpt-5.1');
34
- console.log(' o1-preview');
35
- console.log(' o1-mini');
36
- console.log(chalk.dim('Google (Gemini):'));
37
- console.log(' gemini-3-pro-preview');
38
- console.log(' gemini-2-5-pro-exp-0827');
39
- console.log(' gemini-2-0-flash-exp');
53
+ printAvailableModels();
54
+
55
+ return;
56
+ }
40
57
 
58
+ if (!isValidModelId(modelId)) {
59
+ console.log(chalk.red(`✗ Modello non valido: ${modelId}`));
60
+ printAvailableModels();
61
+ process.exitCode = 1;
41
62
  return;
42
63
  }
43
64
 
@@ -0,0 +1,157 @@
1
+ /**
2
+ * Shared model catalog for NexusCLI (backend + CLI)
3
+ * Keep this as the single source of truth for available engines/models.
4
+ */
5
+
6
+ /**
7
+ * Returns the available CLI tools and their models.
8
+ * Shape is consumed by API, frontend, and CLI commands.
9
+ */
10
+ function getCliTools() {
11
+ return {
12
+ // ============================================================
13
+ // CLAUDE - Anthropic Claude Code CLI
14
+ // ============================================================
15
+ 'claude': {
16
+ name: 'Claude Code',
17
+ icon: 'Terminal',
18
+ enabled: true,
19
+ endpoint: '/api/v1/chat',
20
+ thinkModes: ['think', 'no-think'],
21
+ defaultThinkMode: 'think',
22
+ models: [
23
+ // === Claude Opus 4.5 (Most Intelligent) ===
24
+ {
25
+ id: 'claude-opus-4-5-20251101',
26
+ name: 'claude-opus-4-5-20251101',
27
+ label: 'Opus 4.5',
28
+ description: '🧠 Most Intelligent',
29
+ category: 'claude'
30
+ },
31
+ // === Claude Sonnet 4.5 (Best Balance) ===
32
+ {
33
+ id: 'claude-sonnet-4-5-20250929',
34
+ name: 'claude-sonnet-4-5-20250929',
35
+ label: 'Sonnet 4.5',
36
+ description: '🧠 Extended Thinking (default)',
37
+ category: 'claude',
38
+ default: true
39
+ },
40
+ // === Claude Haiku 4.5 (Fastest) ===
41
+ {
42
+ id: 'claude-haiku-4-5-20251001',
43
+ name: 'claude-haiku-4-5-20251001',
44
+ label: 'Haiku 4.5',
45
+ description: '⚡ Fast & Efficient',
46
+ category: 'claude'
47
+ },
48
+ // === DeepSeek (Alternative Models) ===
49
+ {
50
+ id: 'deepseek-reasoner',
51
+ name: 'deepseek-reasoner',
52
+ label: 'DeepSeek Reasoner',
53
+ description: '🧠 Deep Reasoning',
54
+ category: 'claude'
55
+ },
56
+ {
57
+ id: 'deepseek-chat',
58
+ name: 'deepseek-chat',
59
+ label: 'DeepSeek Chat',
60
+ description: '💬 Fast Chat',
61
+ category: 'claude'
62
+ }
63
+ ]
64
+ },
65
+
66
+ // ============================================================
67
+ // CODEX - OpenAI Codex CLI
68
+ // ============================================================
69
+ 'codex': {
70
+ name: 'Codex',
71
+ icon: 'Code2',
72
+ enabled: true,
73
+ endpoint: '/api/v1/codex',
74
+ models: [
75
+ {
76
+ id: 'gpt-5.1-codex-max',
77
+ name: 'gpt-5.1-codex-max',
78
+ label: 'GPT-5.1 Codex Max',
79
+ description: '💎 Extra High reasoning (best)',
80
+ category: 'codex',
81
+ reasoningEfforts: ['low', 'medium', 'high', 'xhigh'],
82
+ defaultReasoning: 'xhigh',
83
+ default: true
84
+ },
85
+ {
86
+ id: 'gpt-5.1-codex',
87
+ name: 'gpt-5.1-codex',
88
+ label: 'GPT-5.1 Codex',
89
+ description: '🧠 High reasoning',
90
+ category: 'codex',
91
+ reasoningEfforts: ['low', 'medium', 'high'],
92
+ defaultReasoning: 'high'
93
+ },
94
+ {
95
+ id: 'gpt-5.1-codex-mini',
96
+ name: 'gpt-5.1-codex-mini',
97
+ label: 'GPT-5.1 Codex Mini',
98
+ description: '⚡ Compact & Fast',
99
+ category: 'codex',
100
+ reasoningEfforts: ['medium', 'high'],
101
+ defaultReasoning: 'high'
102
+ },
103
+ {
104
+ id: 'gpt-5.1',
105
+ name: 'gpt-5.1',
106
+ label: 'GPT-5.1',
107
+ description: '🧠 General Purpose',
108
+ category: 'codex',
109
+ reasoningEfforts: ['low', 'medium', 'high'],
110
+ defaultReasoning: 'high'
111
+ }
112
+ ]
113
+ },
114
+
115
+ // ============================================================
116
+ // GEMINI - Google Gemini CLI
117
+ // ============================================================
118
+ 'gemini': {
119
+ name: 'Gemini',
120
+ icon: 'Sparkles',
121
+ enabled: true,
122
+ endpoint: '/api/v1/gemini',
123
+ models: [
124
+ {
125
+ id: 'gemini-3-pro-preview',
126
+ name: 'gemini-3-pro-preview',
127
+ label: 'Gemini 3 Pro',
128
+ description: '🚀 Latest Preview',
129
+ category: 'gemini',
130
+ default: true
131
+ }
132
+ ]
133
+ }
134
+ };
135
+ }
136
+
137
+ function getAllModels() {
138
+ return Object.values(getCliTools()).flatMap(cli => cli.models || []);
139
+ }
140
+
141
+ function isValidModelId(modelId) {
142
+ if (!modelId) return false;
143
+ return getAllModels().some(m => m.id === modelId);
144
+ }
145
+
146
+ function getDefaultModelId() {
147
+ const models = getAllModels();
148
+ const withDefault = models.find(m => m.default);
149
+ return withDefault ? withDefault.id : (models[0]?.id || null);
150
+ }
151
+
152
+ module.exports = {
153
+ getCliTools,
154
+ getAllModels,
155
+ isValidModelId,
156
+ getDefaultModelId
157
+ };
@@ -6,6 +6,10 @@
6
6
  const express = require('express');
7
7
  const router = express.Router();
8
8
  const { getConfig } = require('../../config/manager');
9
+ const {
10
+ isValidModelId,
11
+ getDefaultModelId
12
+ } = require('../../config/models');
9
13
 
10
14
  /**
11
15
  * GET /api/v1/config
@@ -15,10 +19,21 @@ router.get('/', (req, res) => {
15
19
  try {
16
20
  const config = getConfig();
17
21
 
22
+ const preferred = config.preferences?.defaultModel || null;
23
+ let defaultModel = preferred;
24
+
25
+ // Sanitize preferred model; fallback to catalog default to avoid broken UI
26
+ if (defaultModel && !isValidModelId(defaultModel)) {
27
+ console.warn('[Config API] Invalid defaultModel in config:', defaultModel);
28
+ defaultModel = null;
29
+ }
30
+
31
+ if (!defaultModel) {
32
+ defaultModel = getDefaultModelId();
33
+ }
34
+
18
35
  // Return only preferences (not sensitive data like auth)
19
- const preferences = {
20
- defaultModel: config.preferences?.defaultModel || null
21
- };
36
+ const preferences = { defaultModel };
22
37
 
23
38
  res.json(preferences);
24
39
  } catch (error) {
@@ -1,5 +1,6 @@
1
1
  const express = require('express');
2
2
  const router = express.Router();
3
+ const { getCliTools } = require('../../config/models');
3
4
 
4
5
  /**
5
6
  * GET /api/v1/models
@@ -12,131 +13,7 @@ const router = express.Router();
12
13
  */
13
14
  router.get('/', (req, res) => {
14
15
  try {
15
- const cliTools = {
16
- // ============================================================
17
- // CLAUDE - Anthropic Claude Code CLI
18
- // ============================================================
19
- 'claude': {
20
- name: 'Claude Code',
21
- icon: 'Terminal',
22
- enabled: true,
23
- endpoint: '/api/v1/chat',
24
- thinkModes: ['think', 'no-think'],
25
- defaultThinkMode: 'think',
26
- models: [
27
- // === Claude Opus 4.5 (Most Intelligent) ===
28
- {
29
- id: 'claude-opus-4-5-20251101',
30
- name: 'claude-opus-4-5-20251101',
31
- label: 'Opus 4.5',
32
- description: '🧠 Most Intelligent',
33
- category: 'claude'
34
- },
35
- // === Claude Sonnet 4.5 (Best Balance) ===
36
- {
37
- id: 'claude-sonnet-4-5-20250929',
38
- name: 'claude-sonnet-4-5-20250929',
39
- label: 'Sonnet 4.5',
40
- description: '🧠 Extended Thinking (default)',
41
- category: 'claude',
42
- default: true
43
- },
44
- // === Claude Haiku 4.5 (Fastest) ===
45
- {
46
- id: 'claude-haiku-4-5-20251001',
47
- name: 'claude-haiku-4-5-20251001',
48
- label: 'Haiku 4.5',
49
- description: '⚡ Fast & Efficient',
50
- category: 'claude'
51
- },
52
- // === DeepSeek (Alternative Models) ===
53
- {
54
- id: 'deepseek-reasoner',
55
- name: 'deepseek-reasoner',
56
- label: 'DeepSeek Reasoner',
57
- description: '🧠 Deep Reasoning',
58
- category: 'claude'
59
- },
60
- {
61
- id: 'deepseek-chat',
62
- name: 'deepseek-chat',
63
- label: 'DeepSeek Chat',
64
- description: '💬 Fast Chat',
65
- category: 'claude'
66
- }
67
- ]
68
- },
69
-
70
- // ============================================================
71
- // CODEX - OpenAI Codex CLI
72
- // ============================================================
73
- 'codex': {
74
- name: 'Codex',
75
- icon: 'Code2',
76
- enabled: true,
77
- endpoint: '/api/v1/codex',
78
- models: [
79
- {
80
- id: 'gpt-5.1-codex-max',
81
- name: 'gpt-5.1-codex-max',
82
- label: 'GPT-5.1 Codex Max',
83
- description: '💎 Extra High reasoning (best)',
84
- category: 'codex',
85
- reasoningEfforts: ['low', 'medium', 'high', 'xhigh'],
86
- defaultReasoning: 'xhigh',
87
- default: true
88
- },
89
- {
90
- id: 'gpt-5.1-codex',
91
- name: 'gpt-5.1-codex',
92
- label: 'GPT-5.1 Codex',
93
- description: '🧠 High reasoning',
94
- category: 'codex',
95
- reasoningEfforts: ['low', 'medium', 'high'],
96
- defaultReasoning: 'high'
97
- },
98
- {
99
- id: 'gpt-5.1-codex-mini',
100
- name: 'gpt-5.1-codex-mini',
101
- label: 'GPT-5.1 Codex Mini',
102
- description: '⚡ Compact & Fast',
103
- category: 'codex',
104
- reasoningEfforts: ['medium', 'high'],
105
- defaultReasoning: 'high'
106
- },
107
- {
108
- id: 'gpt-5.1',
109
- name: 'gpt-5.1',
110
- label: 'GPT-5.1',
111
- description: '🧠 General Purpose',
112
- category: 'codex',
113
- reasoningEfforts: ['low', 'medium', 'high'],
114
- defaultReasoning: 'high'
115
- }
116
- ]
117
- },
118
-
119
- // ============================================================
120
- // GEMINI - Google Gemini CLI
121
- // ============================================================
122
- 'gemini': {
123
- name: 'Gemini',
124
- icon: 'Sparkles',
125
- enabled: true,
126
- endpoint: '/api/v1/gemini',
127
- models: [
128
- {
129
- id: 'gemini-3-pro-preview',
130
- name: 'gemini-3-pro-preview',
131
- label: 'Gemini 3 Pro',
132
- description: '🚀 Latest Preview',
133
- category: 'gemini',
134
- default: true
135
- }
136
- ]
137
- }
138
- };
139
-
16
+ const cliTools = getCliTools();
140
17
  res.json(cliTools);
141
18
  } catch (error) {
142
19
  console.error('[Models] Error fetching models:', error);
@@ -151,6 +28,7 @@ router.get('/', (req, res) => {
151
28
  router.get('/:engine', (req, res) => {
152
29
  try {
153
30
  const { engine } = req.params;
31
+ const cliTools = getCliTools();
154
32
 
155
33
  // Normalize engine name
156
34
  let normalizedEngine = engine.toLowerCase();
@@ -158,37 +36,12 @@ router.get('/:engine', (req, res) => {
158
36
  if (normalizedEngine.includes('codex') || normalizedEngine.includes('openai')) normalizedEngine = 'codex';
159
37
  if (normalizedEngine.includes('gemini') || normalizedEngine.includes('google')) normalizedEngine = 'gemini';
160
38
 
161
- const cliTools = {
162
- 'claude': {
163
- name: 'Claude Code',
164
- models: [
165
- { id: 'claude-opus-4-5-20251101', label: 'Opus 4.5', description: '🧠 Most Intelligent' },
166
- { id: 'claude-sonnet-4-5-20250929', label: 'Sonnet 4.5', description: '🧠 Extended Thinking', default: true },
167
- { id: 'claude-haiku-4-5-20251001', label: 'Haiku 4.5', description: '⚡ Fast & Efficient' },
168
- ]
169
- },
170
- 'codex': {
171
- name: 'Codex',
172
- models: [
173
- { id: 'gpt-5.1-codex-max', label: 'GPT-5.1 Codex Max', description: '💎 Best Quality', default: true },
174
- { id: 'gpt-5.1-codex', label: 'GPT-5.1 Codex', description: '🧠 High reasoning' },
175
- { id: 'gpt-5.1-codex-mini', label: 'GPT-5.1 Codex Mini', description: '⚡ Fast' },
176
- { id: 'gpt-5.1', label: 'GPT-5.1', description: '🧠 General Purpose' },
177
- ]
178
- },
179
- 'gemini': {
180
- name: 'Gemini',
181
- models: [
182
- { id: 'gemini-3-pro-preview', label: 'Gemini 3 Pro', description: '🚀 Latest', default: true },
183
- ]
184
- }
185
- };
186
-
187
39
  if (!cliTools[normalizedEngine]) {
188
40
  return res.status(404).json({ error: `Engine not found: ${engine}` });
189
41
  }
190
42
 
191
- res.json(cliTools[normalizedEngine]);
43
+ const { name, models } = cliTools[normalizedEngine];
44
+ res.json({ name, models });
192
45
  } catch (error) {
193
46
  console.error('[Models] Error fetching engine models:', error);
194
47
  res.status(500).json({ error: 'Failed to fetch models' });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mmmbuto/nexuscli",
3
- "version": "0.7.0",
3
+ "version": "0.7.1",
4
4
  "description": "NexusCLI - TRI CLI Control Plane (Claude/Codex/Gemini)",
5
5
  "main": "lib/server/server.js",
6
6
  "bin": {