nova-terminal-assistant 0.2.3 → 0.2.4
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/startup/NovaApp.js +8 -0
- package/dist/ui/components/ErrorPanel.js +199 -234
- package/package.json +1 -1
package/dist/startup/NovaApp.js
CHANGED
|
@@ -1692,3 +1692,11 @@ export class NovaApp {
|
|
|
1692
1692
|
});
|
|
1693
1693
|
}
|
|
1694
1694
|
}
|
|
1695
|
+
// Entry point
|
|
1696
|
+
if (import.meta.url === `file://${process.argv[1].replace(/\\/g, '/')}`) {
|
|
1697
|
+
const app = new NovaApp();
|
|
1698
|
+
app.run().catch((err) => {
|
|
1699
|
+
console.error('Fatal error:', err);
|
|
1700
|
+
process.exit(1);
|
|
1701
|
+
});
|
|
1702
|
+
}
|
|
@@ -82,247 +82,212 @@ export class ErrorPanel {
|
|
|
82
82
|
code = 'UNKNOWN_ERROR';
|
|
83
83
|
suggestion = ['Check the Nova CLI documentation', 'Search for your error online', 'Contact support if issue persists'];
|
|
84
84
|
}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
85
|
+
return {
|
|
86
|
+
name: errorObj.name,
|
|
87
|
+
message: errorObj.message,
|
|
88
|
+
code,
|
|
89
|
+
category,
|
|
90
|
+
suggestion,
|
|
91
|
+
stack: this.options.showStack ? errorObj.stack : undefined
|
|
92
|
+
};
|
|
88
93
|
}
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
{
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
name: errorObj.name,
|
|
104
|
-
message: errorObj.message,
|
|
105
|
-
code,
|
|
106
|
-
category,
|
|
107
|
-
suggestion,
|
|
108
|
-
stack: this.options.showStack ? errorObj.stack : undefined
|
|
109
|
-
};
|
|
110
|
-
displayCompact(errorInfo, ErrorInfo);
|
|
111
|
-
void {
|
|
112
|
-
const: icon = this.getIcon(errorInfo.category),
|
|
113
|
-
const: color = this.getColor(errorInfo.category),
|
|
114
|
-
console, : .log(chalk[color](`${icon} ${errorInfo.message}`))
|
|
115
|
-
};
|
|
116
|
-
displayFull(errorInfo, ErrorInfo, context ? : any);
|
|
117
|
-
void {
|
|
118
|
-
console, : .log('\n'),
|
|
119
|
-
console, : .log(chalk.bgRed.white.bold(' ERROR ')),
|
|
120
|
-
console, : .log(chalk.red('-'.repeat(50))),
|
|
121
|
-
// Error header with category
|
|
122
|
-
const: categoryLabel = this.formatCategory(errorInfo.category),
|
|
123
|
-
const: codeLabel = errorInfo.code ? ` [${errorInfo.code}]` : '',
|
|
124
|
-
console, : .log(chalk.red(` ${categoryLabel}${codeLabel}`)),
|
|
125
|
-
// Error message
|
|
126
|
-
console, : .log(''),
|
|
127
|
-
console, : .log(chalk.white('Message:')),
|
|
128
|
-
console, : .log(chalk.yellow(` ${errorInfo.message}`)),
|
|
129
|
-
// Context info
|
|
130
|
-
if(context) {
|
|
94
|
+
displayCompact(errorInfo) {
|
|
95
|
+
const icon = this.getIcon(errorInfo.category);
|
|
96
|
+
const color = this.getColor(errorInfo.category);
|
|
97
|
+
console.log(chalk[color](`${icon} ${errorInfo.message}`));
|
|
98
|
+
}
|
|
99
|
+
displayFull(errorInfo, context) {
|
|
100
|
+
console.log('\n');
|
|
101
|
+
console.log(chalk.bgRed.white.bold(' ERROR '));
|
|
102
|
+
console.log(chalk.red('-'.repeat(50)));
|
|
103
|
+
// Error header with category
|
|
104
|
+
const categoryLabel = this.formatCategory(errorInfo.category);
|
|
105
|
+
const codeLabel = errorInfo.code ? ` [${errorInfo.code}]` : '';
|
|
106
|
+
console.log(chalk.red(` ${categoryLabel}${codeLabel}`));
|
|
107
|
+
// Error message
|
|
131
108
|
console.log('');
|
|
132
|
-
console.log(chalk.white('
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
109
|
+
console.log(chalk.white('Message:'));
|
|
110
|
+
console.log(chalk.yellow(` ${errorInfo.message}`));
|
|
111
|
+
// Context info
|
|
112
|
+
if (context) {
|
|
113
|
+
console.log('');
|
|
114
|
+
console.log(chalk.white('Context:'));
|
|
115
|
+
if (typeof context === 'object') {
|
|
116
|
+
Object.entries(context).forEach(([key, value]) => {
|
|
117
|
+
console.log(chalk.gray(` ${key}: ${String(value)}`));
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
console.log(chalk.gray(` ${context}`));
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
// Suggestions
|
|
125
|
+
if (errorInfo.suggestion.length > 0 && this.options.showSuggestions) {
|
|
126
|
+
console.log('');
|
|
127
|
+
console.log(chalk.white('Suggested actions:'));
|
|
128
|
+
errorInfo.suggestion.forEach((s, i) => {
|
|
129
|
+
console.log(chalk.green(` ${i + 1}. ${s}`));
|
|
136
130
|
});
|
|
131
|
+
// Quick commands
|
|
132
|
+
console.log('');
|
|
133
|
+
console.log(chalk.cyan('Quick commands:'));
|
|
134
|
+
switch (errorInfo.category) {
|
|
135
|
+
case 'auth':
|
|
136
|
+
console.log(chalk.cyan(' • nova auth set <provider>'));
|
|
137
|
+
console.log(chalk.cyan(' • Check environment variables'));
|
|
138
|
+
break;
|
|
139
|
+
case 'config':
|
|
140
|
+
console.log(chalk.cyan(' • nova config edit'));
|
|
141
|
+
console.log(chalk.cyan(' • Check ~/.nova/config.yaml'));
|
|
142
|
+
break;
|
|
143
|
+
case 'network':
|
|
144
|
+
console.log(chalk.cyan(' • Check internet connection'));
|
|
145
|
+
console.log(chalk.cyan(' • Try nova ollama status'));
|
|
146
|
+
break;
|
|
147
|
+
case 'model':
|
|
148
|
+
console.log(chalk.cyan(' • nova model list'));
|
|
149
|
+
console.log(chalk.cyan(' • Check provider configuration'));
|
|
150
|
+
break;
|
|
151
|
+
}
|
|
137
152
|
}
|
|
138
|
-
|
|
139
|
-
|
|
153
|
+
// Stack trace (if enabled and not too long)
|
|
154
|
+
if (errorInfo.stack && this.options.showStack && errorInfo.stack.split('\n').length <= this.options.maxLines) {
|
|
155
|
+
console.log('');
|
|
156
|
+
console.log(chalk.white('Stack trace:'));
|
|
157
|
+
console.log(chalk.gray(errorInfo.stack));
|
|
158
|
+
}
|
|
159
|
+
else if (errorInfo.stack) {
|
|
160
|
+
console.log('');
|
|
161
|
+
console.log(chalk.gray('(Stack trace truncated. Use --verbose for full trace.)'));
|
|
140
162
|
}
|
|
163
|
+
console.log('');
|
|
164
|
+
console.log(chalk.red('-'.repeat(50)));
|
|
165
|
+
console.log('');
|
|
141
166
|
}
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
case 'auth':
|
|
158
|
-
console.log(chalk.cyan(' • nova auth set <provider>'));
|
|
159
|
-
console.log(chalk.cyan(' • Check environment variables'));
|
|
160
|
-
break;
|
|
161
|
-
case 'config':
|
|
162
|
-
console.log(chalk.cyan(' • nova config edit'));
|
|
163
|
-
console.log(chalk.cyan(' • Check ~/.nova/config.yaml'));
|
|
164
|
-
break;
|
|
165
|
-
case 'network':
|
|
166
|
-
console.log(chalk.cyan(' • Check internet connection'));
|
|
167
|
-
console.log(chalk.cyan(' • Try nova ollama status'));
|
|
168
|
-
break;
|
|
169
|
-
case 'model':
|
|
170
|
-
console.log(chalk.cyan(' • nova model list'));
|
|
171
|
-
console.log(chalk.cyan(' • Check provider configuration'));
|
|
172
|
-
break;
|
|
167
|
+
getIcon(category) {
|
|
168
|
+
const icons = {
|
|
169
|
+
auth: '🔑',
|
|
170
|
+
config: '⚙️',
|
|
171
|
+
network: '🌐',
|
|
172
|
+
model: '🤖',
|
|
173
|
+
file: '📁',
|
|
174
|
+
execution: '⚡',
|
|
175
|
+
validation: '⚠️',
|
|
176
|
+
permission: '🚫',
|
|
177
|
+
timeout: '⏰',
|
|
178
|
+
quota: '💰',
|
|
179
|
+
unknown: '❌'
|
|
180
|
+
};
|
|
181
|
+
return icons[category] || icons.unknown;
|
|
173
182
|
}
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
string;
|
|
190
|
-
{
|
|
191
|
-
const icons = {
|
|
192
|
-
auth: '🔑',
|
|
193
|
-
config: '⚙️',
|
|
194
|
-
network: '🌐',
|
|
195
|
-
model: '🤖',
|
|
196
|
-
file: '📁',
|
|
197
|
-
execution: '⚡',
|
|
198
|
-
validation: '⚠️',
|
|
199
|
-
permission: '🚫',
|
|
200
|
-
timeout: '⏰',
|
|
201
|
-
quota: '💰',
|
|
202
|
-
unknown: '❌'
|
|
203
|
-
};
|
|
204
|
-
return icons[category] || icons.unknown;
|
|
205
|
-
}
|
|
206
|
-
getColor(category, ErrorCategory);
|
|
207
|
-
keyof;
|
|
208
|
-
typeof chalk;
|
|
209
|
-
{
|
|
210
|
-
const colors = {
|
|
211
|
-
auth: 'red',
|
|
212
|
-
config: 'yellow',
|
|
213
|
-
network: 'blue',
|
|
214
|
-
model: 'cyan',
|
|
215
|
-
file: 'green',
|
|
216
|
-
execution: 'magenta',
|
|
217
|
-
validation: 'yellow',
|
|
218
|
-
permission: 'red',
|
|
219
|
-
timeout: 'yellow',
|
|
220
|
-
quota: 'red',
|
|
221
|
-
unknown: 'red'
|
|
222
|
-
};
|
|
223
|
-
return colors[category] || colors.unknown;
|
|
224
|
-
}
|
|
225
|
-
formatCategory(category, ErrorCategory);
|
|
226
|
-
string;
|
|
227
|
-
{
|
|
228
|
-
const labels = {
|
|
229
|
-
auth: 'Authentication Error',
|
|
230
|
-
config: 'Configuration Error',
|
|
231
|
-
network: 'Network Error',
|
|
232
|
-
model: 'Model Error',
|
|
233
|
-
file: 'File System Error',
|
|
234
|
-
execution: 'Execution Error',
|
|
235
|
-
validation: 'Validation Error',
|
|
236
|
-
permission: 'Permission Error',
|
|
237
|
-
timeout: 'Timeout Error',
|
|
238
|
-
quota: 'Quota Exceeded',
|
|
239
|
-
unknown: 'Unknown Error'
|
|
240
|
-
};
|
|
241
|
-
return labels[category] || labels.unknown;
|
|
242
|
-
}
|
|
243
|
-
getErrorSuggestions(category, ErrorCategory, code ? : string);
|
|
244
|
-
string[];
|
|
245
|
-
{
|
|
246
|
-
const suggestions = [];
|
|
247
|
-
// Generic suggestions based on category
|
|
248
|
-
switch (category) {
|
|
249
|
-
case 'auth':
|
|
250
|
-
suggestions.push('Check your API key in nova auth status');
|
|
251
|
-
suggestions.push('Verify the provider supports your selected model');
|
|
252
|
-
break;
|
|
253
|
-
case 'config':
|
|
254
|
-
suggestions.push('Validate your config.yaml file syntax');
|
|
255
|
-
suggestions.push('Run nova config edit to fix configuration');
|
|
256
|
-
break;
|
|
257
|
-
case 'model':
|
|
258
|
-
suggestions.push('Use nova model list to see available models');
|
|
259
|
-
suggestions.push('Check model alias configuration');
|
|
260
|
-
break;
|
|
261
|
-
case 'network':
|
|
262
|
-
suggestions.push('Check internet connection');
|
|
263
|
-
suggestions.push('Verify proxy settings');
|
|
264
|
-
break;
|
|
265
|
-
case 'timeout':
|
|
266
|
-
suggestions.push('Request timed out');
|
|
267
|
-
suggestions.push('Try again with a simpler request');
|
|
268
|
-
break;
|
|
269
|
-
case 'quota':
|
|
270
|
-
suggestions.push('Check your account billing status');
|
|
271
|
-
suggestions.push('Contact support for quota increase');
|
|
272
|
-
break;
|
|
273
|
-
default:
|
|
274
|
-
suggestions.push('Check the Nova CLI documentation');
|
|
275
|
-
suggestions.push('Search for your error code online');
|
|
276
|
-
break;
|
|
183
|
+
getColor(category) {
|
|
184
|
+
const colors = {
|
|
185
|
+
auth: 'red',
|
|
186
|
+
config: 'yellow',
|
|
187
|
+
network: 'blue',
|
|
188
|
+
model: 'cyan',
|
|
189
|
+
file: 'green',
|
|
190
|
+
execution: 'magenta',
|
|
191
|
+
validation: 'yellow',
|
|
192
|
+
permission: 'red',
|
|
193
|
+
timeout: 'yellow',
|
|
194
|
+
quota: 'red',
|
|
195
|
+
unknown: 'red'
|
|
196
|
+
};
|
|
197
|
+
return colors[category] || colors.unknown;
|
|
277
198
|
}
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
199
|
+
formatCategory(category) {
|
|
200
|
+
const labels = {
|
|
201
|
+
auth: 'Authentication Error',
|
|
202
|
+
config: 'Configuration Error',
|
|
203
|
+
network: 'Network Error',
|
|
204
|
+
model: 'Model Error',
|
|
205
|
+
file: 'File System Error',
|
|
206
|
+
execution: 'Execution Error',
|
|
207
|
+
validation: 'Validation Error',
|
|
208
|
+
permission: 'Permission Error',
|
|
209
|
+
timeout: 'Timeout Error',
|
|
210
|
+
quota: 'Quota Exceeded',
|
|
211
|
+
unknown: 'Unknown Error'
|
|
212
|
+
};
|
|
213
|
+
return labels[category] || labels.unknown;
|
|
214
|
+
}
|
|
215
|
+
getErrorSuggestions(category, code) {
|
|
216
|
+
const suggestions = [];
|
|
217
|
+
// Generic suggestions based on category
|
|
218
|
+
switch (category) {
|
|
219
|
+
case 'auth':
|
|
220
|
+
suggestions.push('Check your API key in nova auth status');
|
|
221
|
+
suggestions.push('Verify the provider supports your selected model');
|
|
222
|
+
break;
|
|
223
|
+
case 'config':
|
|
224
|
+
suggestions.push('Validate your config.yaml file syntax');
|
|
225
|
+
suggestions.push('Run nova config edit to fix configuration');
|
|
226
|
+
break;
|
|
227
|
+
case 'model':
|
|
228
|
+
suggestions.push('Use nova model list to see available models');
|
|
229
|
+
suggestions.push('Check model alias configuration');
|
|
230
|
+
break;
|
|
231
|
+
case 'network':
|
|
232
|
+
suggestions.push('Check internet connection');
|
|
233
|
+
suggestions.push('Verify proxy settings');
|
|
234
|
+
break;
|
|
235
|
+
case 'timeout':
|
|
236
|
+
suggestions.push('Request timed out');
|
|
237
|
+
suggestions.push('Try again with a simpler request');
|
|
238
|
+
break;
|
|
239
|
+
case 'quota':
|
|
240
|
+
suggestions.push('Check your account billing status');
|
|
241
|
+
suggestions.push('Contact support for quota increase');
|
|
242
|
+
break;
|
|
243
|
+
default:
|
|
244
|
+
suggestions.push('Check the Nova CLI documentation');
|
|
245
|
+
suggestions.push('Search for your error code online');
|
|
246
|
+
break;
|
|
247
|
+
}
|
|
248
|
+
return suggestions;
|
|
249
|
+
}
|
|
250
|
+
// Static utility methods
|
|
251
|
+
static async handleAsyncError(promise, context) {
|
|
252
|
+
try {
|
|
253
|
+
return await promise;
|
|
254
|
+
}
|
|
255
|
+
catch (error) {
|
|
256
|
+
const panel = new ErrorPanel();
|
|
257
|
+
panel.display(error, context);
|
|
258
|
+
throw error; // Re-throw after display
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
static formatErrorForLogging(error) {
|
|
262
|
+
return {
|
|
263
|
+
timestamp: new Date().toISOString(),
|
|
264
|
+
name: error.name,
|
|
265
|
+
message: error.message,
|
|
266
|
+
stack: error.stack,
|
|
267
|
+
category: this.inferCategory(error),
|
|
268
|
+
code: this.extractErrorCode(error)
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
static inferCategory(error) {
|
|
272
|
+
const msg = error.message.toLowerCase();
|
|
273
|
+
if (msg.includes('api key') || msg.includes('authentication'))
|
|
274
|
+
return 'auth';
|
|
275
|
+
if (msg.includes('config') || msg.includes('yaml'))
|
|
276
|
+
return 'config';
|
|
277
|
+
if (msg.includes('network') || msg.includes('connection'))
|
|
278
|
+
return 'network';
|
|
279
|
+
if (msg.includes('model'))
|
|
280
|
+
return 'model';
|
|
281
|
+
if (msg.includes('file') || msg.includes('permission'))
|
|
282
|
+
return 'file';
|
|
283
|
+
if (msg.includes('timeout'))
|
|
284
|
+
return 'timeout';
|
|
285
|
+
if (msg.includes('quota') || msg.includes('billing'))
|
|
286
|
+
return 'quota';
|
|
287
|
+
return 'unknown';
|
|
288
|
+
}
|
|
289
|
+
static extractErrorCode(error) {
|
|
290
|
+
const match = error.message.match(/\[(\w+)\]/);
|
|
291
|
+
return match ? match[1] : undefined;
|
|
289
292
|
}
|
|
290
|
-
};
|
|
291
|
-
formatErrorForLogging(error, Error);
|
|
292
|
-
LoggableError;
|
|
293
|
-
{
|
|
294
|
-
return {
|
|
295
|
-
timestamp: new Date().toISOString(),
|
|
296
|
-
name: error.name,
|
|
297
|
-
message: error.message,
|
|
298
|
-
stack: error.stack,
|
|
299
|
-
category: this.inferCategory(error),
|
|
300
|
-
code: this.extractErrorCode(error)
|
|
301
|
-
};
|
|
302
|
-
}
|
|
303
|
-
inferCategory(error, Error);
|
|
304
|
-
ErrorCategory;
|
|
305
|
-
{
|
|
306
|
-
const msg = error.message.toLowerCase();
|
|
307
|
-
if (msg.includes('api key') || msg.includes('authentication'))
|
|
308
|
-
return 'auth';
|
|
309
|
-
if (msg.includes('config') || msg.includes('yaml'))
|
|
310
|
-
return 'config';
|
|
311
|
-
if (msg.includes('network') || msg.includes('connection'))
|
|
312
|
-
return 'network';
|
|
313
|
-
if (msg.includes('model'))
|
|
314
|
-
return 'model';
|
|
315
|
-
if (msg.includes('file') || msg.includes('permission'))
|
|
316
|
-
return 'file';
|
|
317
|
-
if (msg.includes('timeout'))
|
|
318
|
-
return 'timeout';
|
|
319
|
-
if (msg.includes('quota') || msg.includes('billing'))
|
|
320
|
-
return 'quota';
|
|
321
|
-
return 'unknown';
|
|
322
|
-
}
|
|
323
|
-
extractErrorCode(error, Error);
|
|
324
|
-
string | undefined;
|
|
325
|
-
{
|
|
326
|
-
const match = error.message.match(/\[(\w+)\]/);
|
|
327
|
-
return match ? match[1] : undefined;
|
|
328
293
|
}
|