nova-terminal-assistant 0.2.2 → 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.
@@ -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
- category = 'auth';
86
- code = 'AUTH_ERROR';
87
- suggestion = ['Check your API key configuration', 'Verify provider settings'];
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
- if(error, message, includes) { }
90
- }
91
- ('network') || error.message.includes('connection');
92
- {
93
- category = 'network';
94
- code = 'NETWORK_ERROR';
95
- suggestion = ['Check internet connection', 'Verify proxy settings', 'Try again later'];
96
- }
97
- if (error.message.includes('config') || error.message.includes('yaml')) {
98
- category = 'config';
99
- code = 'CONFIG_ERROR';
100
- suggestion = ['Check config file syntax', 'Run nova config edit to fix'];
101
- }
102
- return {
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('Context:'));
133
- if (typeof context === 'object') {
134
- Object.entries(context).forEach(([key, value]) => {
135
- console.log(chalk.gray(` ${key}: ${String(value)}`));
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
- else {
139
- console.log(chalk.gray(` ${context}`));
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
- // Suggestions
143
- ,
144
- // Suggestions
145
- if(errorInfo) { }, : .suggestion.length > 0 && this.options.showSuggestions
146
- };
147
- {
148
- console.log('');
149
- console.log(chalk.white('Suggested actions:'));
150
- errorInfo.suggestion.forEach((s, i) => {
151
- console.log(chalk.green(` ${i + 1}. ${s}`));
152
- });
153
- // Quick commands
154
- console.log('');
155
- console.log(chalk.cyan('Quick commands:'));
156
- switch (errorInfo.category) {
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
- // Stack trace (if enabled and not too long)
176
- if (errorInfo.stack && this.options.showStack && errorInfo.stack.split('\n').length <= this.options.maxLines) {
177
- console.log('');
178
- console.log(chalk.white('Stack trace:'));
179
- console.log(chalk.gray(errorInfo.stack));
180
- }
181
- else if (errorInfo.stack) {
182
- console.log('');
183
- console.log(chalk.gray('(Stack trace truncated. Use --verbose for full trace.)'));
184
- }
185
- console.log('');
186
- console.log(chalk.red('-'.repeat(50)));
187
- console.log('');
188
- getIcon(category, ErrorCategory);
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
- return suggestions;
279
- }
280
- async;
281
- handleAsyncError(promise, (Promise), context ? : any);
282
- Promise < T > {
283
- try: {
284
- return: await promise
285
- }, catch(error) {
286
- const panel = new ErrorPanel();
287
- panel.display(error, context);
288
- throw error; // Re-throw after display
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
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nova-terminal-assistant",
3
- "version": "0.2.2",
3
+ "version": "0.2.4",
4
4
  "description": "Nova - AI-powered terminal assistant with multi-model support",
5
5
  "type": "module",
6
6
  "main": "dist/startup/NovaApp.js",
@@ -21,6 +21,10 @@
21
21
  "node": ">=18.0.0"
22
22
  },
23
23
  "dependencies": {
24
+ "uuid": "^10.0.0",
25
+ "glob": "^11.0.0",
26
+ "node-fetch": "^3.3.2",
27
+ "ink-text-input": "^6.0.0",
24
28
  "@anthropic-ai/sdk": "^0.30.0",
25
29
  "@google/generative-ai": "^0.21.0",
26
30
  "chalk": "^5.3.0",