nova-terminal-assistant 0.1.0
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.
Potentially problematic release.
This version of nova-terminal-assistant might be problematic. Click here for more details.
- package/README.md +358 -0
- package/bin/nova +38 -0
- package/bin/nova.js +12 -0
- package/package.json +67 -0
- package/src/cli/commands/SmartCompletion.ts +458 -0
- package/src/cli/index.ts +5 -0
- package/src/cli/startup/IFlowRepl.ts +212 -0
- package/src/cli/startup/InkBasedRepl.ts +1056 -0
- package/src/cli/startup/InteractiveRepl.ts +2833 -0
- package/src/cli/startup/NovaApp.ts +1861 -0
- package/src/cli/startup/index.ts +4 -0
- package/src/cli/startup/parseArgs.ts +293 -0
- package/src/cli/test-modules.ts +27 -0
- package/src/cli/ui/IFlowDropdown.ts +425 -0
- package/src/cli/ui/ModernReplUI.ts +276 -0
- package/src/cli/ui/SimpleSelector2.ts +215 -0
- package/src/cli/ui/components/ConfirmDialog.ts +176 -0
- package/src/cli/ui/components/ErrorPanel.ts +364 -0
- package/src/cli/ui/components/InkAppRunner.tsx +67 -0
- package/src/cli/ui/components/InkComponents.tsx +613 -0
- package/src/cli/ui/components/NovaInkApp.tsx +312 -0
- package/src/cli/ui/components/ProgressBar.ts +177 -0
- package/src/cli/ui/components/ProgressIndicator.ts +298 -0
- package/src/cli/ui/components/QuickActions.ts +396 -0
- package/src/cli/ui/components/SimpleErrorPanel.ts +231 -0
- package/src/cli/ui/components/StatusBar.ts +194 -0
- package/src/cli/ui/components/ThinkingBlockRenderer.ts +401 -0
- package/src/cli/ui/components/index.ts +27 -0
- package/src/cli/ui/ink-prototype.tsx +347 -0
- package/src/cli/utils/CliUI.ts +336 -0
- package/src/cli/utils/CompletionHelper.ts +388 -0
- package/src/cli/utils/EnhancedCompleter.test.ts +226 -0
- package/src/cli/utils/EnhancedCompleter.ts +513 -0
- package/src/cli/utils/ErrorEnhancer.ts +429 -0
- package/src/cli/utils/OutputFormatter.ts +193 -0
- package/src/cli/utils/index.ts +9 -0
- package/src/core/agents/AgentOrchestrator.ts +515 -0
- package/src/core/agents/index.ts +17 -0
- package/src/core/audit/AuditLogger.ts +509 -0
- package/src/core/audit/index.ts +11 -0
- package/src/core/auth/AuthManager.d.ts.map +1 -0
- package/src/core/auth/AuthManager.ts +138 -0
- package/src/core/auth/index.d.ts.map +1 -0
- package/src/core/auth/index.ts +2 -0
- package/src/core/config/ConfigManager.d.ts.map +1 -0
- package/src/core/config/ConfigManager.test.ts +183 -0
- package/src/core/config/ConfigManager.ts +1219 -0
- package/src/core/config/index.d.ts.map +1 -0
- package/src/core/config/index.ts +1 -0
- package/src/core/context/ContextBuilder.d.ts.map +1 -0
- package/src/core/context/ContextBuilder.ts +171 -0
- package/src/core/context/ContextCompressor.d.ts.map +1 -0
- package/src/core/context/ContextCompressor.ts +642 -0
- package/src/core/context/LayeredMemoryManager.ts +657 -0
- package/src/core/context/MemoryDiscovery.d.ts.map +1 -0
- package/src/core/context/MemoryDiscovery.ts +175 -0
- package/src/core/context/defaultSystemPrompt.d.ts.map +1 -0
- package/src/core/context/defaultSystemPrompt.ts +35 -0
- package/src/core/context/index.d.ts.map +1 -0
- package/src/core/context/index.ts +22 -0
- package/src/core/extensions/SkillGenerator.ts +421 -0
- package/src/core/extensions/SkillInstaller.d.ts.map +1 -0
- package/src/core/extensions/SkillInstaller.ts +257 -0
- package/src/core/extensions/SkillRegistry.d.ts.map +1 -0
- package/src/core/extensions/SkillRegistry.ts +361 -0
- package/src/core/extensions/SkillValidator.ts +525 -0
- package/src/core/extensions/index.ts +15 -0
- package/src/core/index.d.ts.map +1 -0
- package/src/core/index.ts +42 -0
- package/src/core/mcp/McpManager.d.ts.map +1 -0
- package/src/core/mcp/McpManager.ts +632 -0
- package/src/core/mcp/index.d.ts.map +1 -0
- package/src/core/mcp/index.ts +2 -0
- package/src/core/model/ModelClient.d.ts.map +1 -0
- package/src/core/model/ModelClient.ts +217 -0
- package/src/core/model/ModelConnectionTester.ts +363 -0
- package/src/core/model/ModelValidator.ts +348 -0
- package/src/core/model/index.d.ts.map +1 -0
- package/src/core/model/index.ts +6 -0
- package/src/core/model/providers/AnthropicProvider.d.ts.map +1 -0
- package/src/core/model/providers/AnthropicProvider.ts +279 -0
- package/src/core/model/providers/CodingPlanProvider.d.ts.map +1 -0
- package/src/core/model/providers/CodingPlanProvider.ts +210 -0
- package/src/core/model/providers/OllamaCloudProvider.d.ts.map +1 -0
- package/src/core/model/providers/OllamaCloudProvider.ts +405 -0
- package/src/core/model/providers/OllamaManager.d.ts.map +1 -0
- package/src/core/model/providers/OllamaManager.ts +201 -0
- package/src/core/model/providers/OllamaProvider.d.ts.map +1 -0
- package/src/core/model/providers/OllamaProvider.ts +73 -0
- package/src/core/model/providers/OpenAICompatibleProvider.d.ts.map +1 -0
- package/src/core/model/providers/OpenAICompatibleProvider.ts +327 -0
- package/src/core/model/providers/OpenAIProvider.d.ts.map +1 -0
- package/src/core/model/providers/OpenAIProvider.ts +29 -0
- package/src/core/model/providers/index.d.ts.map +1 -0
- package/src/core/model/providers/index.ts +12 -0
- package/src/core/model/types.d.ts.map +1 -0
- package/src/core/model/types.ts +77 -0
- package/src/core/security/ApprovalManager.d.ts.map +1 -0
- package/src/core/security/ApprovalManager.ts +174 -0
- package/src/core/security/FileFilter.d.ts.map +1 -0
- package/src/core/security/FileFilter.ts +141 -0
- package/src/core/security/HookExecutor.d.ts.map +1 -0
- package/src/core/security/HookExecutor.ts +178 -0
- package/src/core/security/SandboxExecutor.ts +447 -0
- package/src/core/security/index.d.ts.map +1 -0
- package/src/core/security/index.ts +8 -0
- package/src/core/session/AgentLoop.d.ts.map +1 -0
- package/src/core/session/AgentLoop.ts +501 -0
- package/src/core/session/SessionManager.d.ts.map +1 -0
- package/src/core/session/SessionManager.test.ts +183 -0
- package/src/core/session/SessionManager.ts +460 -0
- package/src/core/session/index.d.ts.map +1 -0
- package/src/core/session/index.ts +3 -0
- package/src/core/telemetry/Telemetry.d.ts.map +1 -0
- package/src/core/telemetry/Telemetry.ts +90 -0
- package/src/core/telemetry/TelemetryService.ts +531 -0
- package/src/core/telemetry/index.d.ts.map +1 -0
- package/src/core/telemetry/index.ts +12 -0
- package/src/core/testing/AutoFixer.ts +385 -0
- package/src/core/testing/ErrorAnalyzer.ts +499 -0
- package/src/core/testing/TestRunner.ts +265 -0
- package/src/core/testing/agent-cli-tests.ts +538 -0
- package/src/core/testing/index.ts +11 -0
- package/src/core/tools/ToolRegistry.d.ts.map +1 -0
- package/src/core/tools/ToolRegistry.test.ts +206 -0
- package/src/core/tools/ToolRegistry.ts +260 -0
- package/src/core/tools/impl/EditFileTool.d.ts.map +1 -0
- package/src/core/tools/impl/EditFileTool.ts +97 -0
- package/src/core/tools/impl/ListDirectoryTool.d.ts.map +1 -0
- package/src/core/tools/impl/ListDirectoryTool.ts +142 -0
- package/src/core/tools/impl/MemoryTool.d.ts.map +1 -0
- package/src/core/tools/impl/MemoryTool.ts +102 -0
- package/src/core/tools/impl/ReadFileTool.d.ts.map +1 -0
- package/src/core/tools/impl/ReadFileTool.ts +58 -0
- package/src/core/tools/impl/SearchContentTool.d.ts.map +1 -0
- package/src/core/tools/impl/SearchContentTool.ts +94 -0
- package/src/core/tools/impl/SearchFileTool.d.ts.map +1 -0
- package/src/core/tools/impl/SearchFileTool.ts +61 -0
- package/src/core/tools/impl/ShellTool.d.ts.map +1 -0
- package/src/core/tools/impl/ShellTool.ts +118 -0
- package/src/core/tools/impl/TaskTool.d.ts.map +1 -0
- package/src/core/tools/impl/TaskTool.ts +207 -0
- package/src/core/tools/impl/TodoTool.d.ts.map +1 -0
- package/src/core/tools/impl/TodoTool.ts +122 -0
- package/src/core/tools/impl/WebFetchTool.d.ts.map +1 -0
- package/src/core/tools/impl/WebFetchTool.ts +103 -0
- package/src/core/tools/impl/WebSearchTool.d.ts.map +1 -0
- package/src/core/tools/impl/WebSearchTool.ts +89 -0
- package/src/core/tools/impl/WriteFileTool.d.ts.map +1 -0
- package/src/core/tools/impl/WriteFileTool.ts +49 -0
- package/src/core/tools/impl/index.d.ts.map +1 -0
- package/src/core/tools/impl/index.ts +16 -0
- package/src/core/tools/index.d.ts.map +1 -0
- package/src/core/tools/index.ts +7 -0
- package/src/core/tools/schemas/execution.d.ts.map +1 -0
- package/src/core/tools/schemas/execution.ts +42 -0
- package/src/core/tools/schemas/file.d.ts.map +1 -0
- package/src/core/tools/schemas/file.ts +119 -0
- package/src/core/tools/schemas/index.d.ts.map +1 -0
- package/src/core/tools/schemas/index.ts +11 -0
- package/src/core/tools/schemas/memory.d.ts.map +1 -0
- package/src/core/tools/schemas/memory.ts +52 -0
- package/src/core/tools/schemas/orchestration.d.ts.map +1 -0
- package/src/core/tools/schemas/orchestration.ts +44 -0
- package/src/core/tools/schemas/search.d.ts.map +1 -0
- package/src/core/tools/schemas/search.ts +112 -0
- package/src/core/tools/schemas/todo.d.ts.map +1 -0
- package/src/core/tools/schemas/todo.ts +32 -0
- package/src/core/tools/schemas/web.d.ts.map +1 -0
- package/src/core/tools/schemas/web.ts +86 -0
- package/src/core/types/config.d.ts.map +1 -0
- package/src/core/types/config.ts +200 -0
- package/src/core/types/errors.d.ts.map +1 -0
- package/src/core/types/errors.ts +204 -0
- package/src/core/types/index.d.ts.map +1 -0
- package/src/core/types/index.ts +8 -0
- package/src/core/types/session.d.ts.map +1 -0
- package/src/core/types/session.ts +216 -0
- package/src/core/types/tools.d.ts.map +1 -0
- package/src/core/types/tools.ts +157 -0
- package/src/core/utils/CheckpointManager.d.ts.map +1 -0
- package/src/core/utils/CheckpointManager.ts +327 -0
- package/src/core/utils/Logger.d.ts.map +1 -0
- package/src/core/utils/Logger.ts +98 -0
- package/src/core/utils/RetryManager.ts +471 -0
- package/src/core/utils/TokenCounter.d.ts.map +1 -0
- package/src/core/utils/TokenCounter.ts +414 -0
- package/src/core/utils/VectorMemoryStore.ts +440 -0
- package/src/core/utils/helpers.d.ts.map +1 -0
- package/src/core/utils/helpers.ts +89 -0
- package/src/core/utils/index.d.ts.map +1 -0
- package/src/core/utils/index.ts +19 -0
|
@@ -0,0 +1,364 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// ErrorPanel - Modern error display component for Nova CLI
|
|
3
|
+
// ============================================================================
|
|
4
|
+
|
|
5
|
+
import chalk from 'chalk';
|
|
6
|
+
// import type { NovaError } from '../../../core/types/errors.js';
|
|
7
|
+
|
|
8
|
+
export interface ErrorPanelOptions {
|
|
9
|
+
showStack?: boolean;
|
|
10
|
+
showSuggestions?: boolean;
|
|
11
|
+
maxLines?: number;
|
|
12
|
+
compact?: boolean;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export class ErrorPanel {
|
|
16
|
+
private options: ErrorPanelOptions = {};
|
|
17
|
+
|
|
18
|
+
constructor(options: ErrorPanelOptions = {}) {
|
|
19
|
+
this.options = {
|
|
20
|
+
showStack: false,
|
|
21
|
+
showSuggestions: true,
|
|
22
|
+
maxLines: 20,
|
|
23
|
+
compact: false,
|
|
24
|
+
...options
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
display(error: Error | string, context?: any): void {
|
|
29
|
+
const errorInfo = this.parseError(error);
|
|
30
|
+
|
|
31
|
+
if (this.options.compact) {
|
|
32
|
+
this.displayCompact(errorInfo);
|
|
33
|
+
} else {
|
|
34
|
+
this.displayFull(errorInfo, context);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
private parseError(error: Error | string): ErrorInfo {
|
|
39
|
+
const errorObj = typeof error === 'string' ? new Error(error) : error;
|
|
40
|
+
|
|
41
|
+
// Try to identify Nova-specific errors
|
|
42
|
+
let code: string | undefined;
|
|
43
|
+
let category: ErrorCategory = 'unknown';
|
|
44
|
+
let suggestion: string[] = [];
|
|
45
|
+
|
|
46
|
+
// Check for API key related errors
|
|
47
|
+
if (error.message.includes('API key') ||
|
|
48
|
+
(error as any).name === 'AUTH_ERROR' ||
|
|
49
|
+
(error as any).code === 'AUTH_ERROR') {
|
|
50
|
+
category = 'auth';
|
|
51
|
+
code = 'AUTH_ERROR';
|
|
52
|
+
suggestion = ['Check your API key configuration', 'Verify provider settings'];
|
|
53
|
+
} else if (error.message.includes('config') ||
|
|
54
|
+
error.message.includes('yaml')) {
|
|
55
|
+
category = 'config';
|
|
56
|
+
code = 'CONFIG_ERROR';
|
|
57
|
+
suggestion = ['Validate your config file syntax', 'Run nova config edit to fix'];
|
|
58
|
+
} else if (error.message.includes('network') ||
|
|
59
|
+
error.message.includes('connection')) {
|
|
60
|
+
category = 'network';
|
|
61
|
+
code = 'NETWORK_ERROR';
|
|
62
|
+
suggestion = ['Check internet connection', 'Verify proxy settings', 'Try again later'];
|
|
63
|
+
} else if (error.message.includes('model')) {
|
|
64
|
+
category = 'model';
|
|
65
|
+
code = 'MODEL_ERROR';
|
|
66
|
+
suggestion = ['Use nova model list to see available models', 'Check provider configuration'];
|
|
67
|
+
} else if (error.message.includes('timeout')) {
|
|
68
|
+
category = 'timeout';
|
|
69
|
+
code = 'TIMEOUT_ERROR';
|
|
70
|
+
suggestion = ['Request timed out', 'Try again with a simpler request'];
|
|
71
|
+
} else if (error.message.includes('quota') ||
|
|
72
|
+
error.message.includes('billing')) {
|
|
73
|
+
category = 'quota';
|
|
74
|
+
code = 'QUOTA_EXCEEDED';
|
|
75
|
+
suggestion = ['Check your account billing status', 'Contact support for quota increase'];
|
|
76
|
+
} else if (error.message.includes('file') ||
|
|
77
|
+
error.message.includes('permission')) {
|
|
78
|
+
category = 'permission';
|
|
79
|
+
code = 'PERMISSION_ERROR';
|
|
80
|
+
suggestion = ['Check file permissions', 'Verify you have access to the requested resource'];
|
|
81
|
+
} else if (error.message.includes('rate limit') ||
|
|
82
|
+
error.message.includes('too many requests')) {
|
|
83
|
+
category = 'validation';
|
|
84
|
+
code = 'RATE_LIMIT_EXCEEDED';
|
|
85
|
+
suggestion = ['Wait a few minutes before trying again', 'Consider upgrading your plan for higher limits'];
|
|
86
|
+
} else {
|
|
87
|
+
// Generic error handling
|
|
88
|
+
category = 'unknown';
|
|
89
|
+
code = 'UNKNOWN_ERROR';
|
|
90
|
+
suggestion = ['Check the Nova CLI documentation', 'Search for your error online', 'Contact support if issue persists'];
|
|
91
|
+
}
|
|
92
|
+
category = 'auth';
|
|
93
|
+
code = 'AUTH_ERROR';
|
|
94
|
+
suggestion = ['Check your API key configuration', 'Verify provider settings'];
|
|
95
|
+
} else if (error.message.includes('network') || error.message.includes('connection')) {
|
|
96
|
+
category = 'network';
|
|
97
|
+
code = 'NETWORK_ERROR';
|
|
98
|
+
suggestion = ['Check internet connection', 'Verify proxy settings', 'Try again later'];
|
|
99
|
+
} else if (error.message.includes('config') || error.message.includes('yaml')) {
|
|
100
|
+
category = 'config';
|
|
101
|
+
code = 'CONFIG_ERROR';
|
|
102
|
+
suggestion = ['Check config file syntax', 'Run nova config edit to fix'];
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return {
|
|
106
|
+
name: errorObj.name,
|
|
107
|
+
message: errorObj.message,
|
|
108
|
+
code,
|
|
109
|
+
category,
|
|
110
|
+
suggestion,
|
|
111
|
+
stack: this.options.showStack ? errorObj.stack : undefined
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
private displayCompact(errorInfo: ErrorInfo): void {
|
|
116
|
+
const icon = this.getIcon(errorInfo.category);
|
|
117
|
+
const color = this.getColor(errorInfo.category);
|
|
118
|
+
|
|
119
|
+
console.log(
|
|
120
|
+
chalk[color](`${icon} ${errorInfo.message}`)
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
private displayFull(errorInfo: ErrorInfo, context?: any): void {
|
|
125
|
+
console.log('\n');
|
|
126
|
+
console.log(chalk.bgRed.white.bold(' ERROR '));
|
|
127
|
+
console.log(chalk.red('-'.repeat(50)));
|
|
128
|
+
|
|
129
|
+
// Error header with category
|
|
130
|
+
const categoryLabel = this.formatCategory(errorInfo.category);
|
|
131
|
+
const codeLabel = errorInfo.code ? ` [${errorInfo.code}]` : '';
|
|
132
|
+
|
|
133
|
+
console.log(chalk.red(` ${categoryLabel}${codeLabel}`));
|
|
134
|
+
|
|
135
|
+
// Error message
|
|
136
|
+
console.log('');
|
|
137
|
+
console.log(chalk.white('Message:'));
|
|
138
|
+
console.log(chalk.yellow(` ${errorInfo.message}`));
|
|
139
|
+
|
|
140
|
+
// Context info
|
|
141
|
+
if (context) {
|
|
142
|
+
console.log('');
|
|
143
|
+
console.log(chalk.white('Context:'));
|
|
144
|
+
if (typeof context === 'object') {
|
|
145
|
+
Object.entries(context).forEach(([key, value]) => {
|
|
146
|
+
console.log(chalk.gray(` ${key}: ${String(value)}`));
|
|
147
|
+
});
|
|
148
|
+
} else {
|
|
149
|
+
console.log(chalk.gray(` ${context}`));
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// Suggestions
|
|
154
|
+
if (errorInfo.suggestion.length > 0 && this.options.showSuggestions) {
|
|
155
|
+
console.log('');
|
|
156
|
+
console.log(chalk.white('Suggested actions:'));
|
|
157
|
+
errorInfo.suggestion.forEach((s, i) => {
|
|
158
|
+
console.log(chalk.green(` ${i + 1}. ${s}`));
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
// Quick commands
|
|
162
|
+
console.log('');
|
|
163
|
+
console.log(chalk.cyan('Quick commands:'));
|
|
164
|
+
switch (errorInfo.category) {
|
|
165
|
+
case 'auth':
|
|
166
|
+
console.log(chalk.cyan(' • nova auth set <provider>'));
|
|
167
|
+
console.log(chalk.cyan(' • Check environment variables'));
|
|
168
|
+
break;
|
|
169
|
+
case 'config':
|
|
170
|
+
console.log(chalk.cyan(' • nova config edit'));
|
|
171
|
+
console.log(chalk.cyan(' • Check ~/.nova/config.yaml'));
|
|
172
|
+
break;
|
|
173
|
+
case 'network':
|
|
174
|
+
console.log(chalk.cyan(' • Check internet connection'));
|
|
175
|
+
console.log(chalk.cyan(' • Try nova ollama status'));
|
|
176
|
+
break;
|
|
177
|
+
case 'model':
|
|
178
|
+
console.log(chalk.cyan(' • nova model list'));
|
|
179
|
+
console.log(chalk.cyan(' • Check provider configuration'));
|
|
180
|
+
break;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// Stack trace (if enabled and not too long)
|
|
185
|
+
if (errorInfo.stack && this.options.showStack && errorInfo.stack.split('\n').length <= this.options.maxLines) {
|
|
186
|
+
console.log('');
|
|
187
|
+
console.log(chalk.white('Stack trace:'));
|
|
188
|
+
console.log(chalk.gray(errorInfo.stack));
|
|
189
|
+
} else if (errorInfo.stack) {
|
|
190
|
+
console.log('');
|
|
191
|
+
console.log(chalk.gray('(Stack trace truncated. Use --verbose for full trace.)'));
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
console.log('');
|
|
195
|
+
console.log(chalk.red('-'.repeat(50)));
|
|
196
|
+
console.log('');
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
private getIcon(category: ErrorCategory): string {
|
|
200
|
+
const icons = {
|
|
201
|
+
auth: '🔑',
|
|
202
|
+
config: '⚙️',
|
|
203
|
+
network: '🌐',
|
|
204
|
+
model: '🤖',
|
|
205
|
+
file: '📁',
|
|
206
|
+
execution: '⚡',
|
|
207
|
+
validation: '⚠️',
|
|
208
|
+
permission: '🚫',
|
|
209
|
+
timeout: '⏰',
|
|
210
|
+
quota: '💰',
|
|
211
|
+
unknown: '❌'
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
return icons[category] || icons.unknown;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
private getColor(category: ErrorCategory): keyof typeof chalk {
|
|
218
|
+
const colors = {
|
|
219
|
+
auth: 'red',
|
|
220
|
+
config: 'yellow',
|
|
221
|
+
network: 'blue',
|
|
222
|
+
model: 'cyan',
|
|
223
|
+
file: 'green',
|
|
224
|
+
execution: 'magenta',
|
|
225
|
+
validation: 'yellow',
|
|
226
|
+
permission: 'red',
|
|
227
|
+
timeout: 'yellow',
|
|
228
|
+
quota: 'red',
|
|
229
|
+
unknown: 'red'
|
|
230
|
+
};
|
|
231
|
+
|
|
232
|
+
return colors[category] || colors.unknown;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
private formatCategory(category: ErrorCategory): string {
|
|
236
|
+
const labels = {
|
|
237
|
+
auth: 'Authentication Error',
|
|
238
|
+
config: 'Configuration Error',
|
|
239
|
+
network: 'Network Error',
|
|
240
|
+
model: 'Model Error',
|
|
241
|
+
file: 'File System Error',
|
|
242
|
+
execution: 'Execution Error',
|
|
243
|
+
validation: 'Validation Error',
|
|
244
|
+
permission: 'Permission Error',
|
|
245
|
+
timeout: 'Timeout Error',
|
|
246
|
+
quota: 'Quota Exceeded',
|
|
247
|
+
unknown: 'Unknown Error'
|
|
248
|
+
};
|
|
249
|
+
|
|
250
|
+
return labels[category] || labels.unknown;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
private getErrorSuggestions(category: ErrorCategory, code?: string): string[] {
|
|
254
|
+
const suggestions: string[] = [];
|
|
255
|
+
|
|
256
|
+
// Generic suggestions based on category
|
|
257
|
+
switch (category) {
|
|
258
|
+
case 'auth':
|
|
259
|
+
suggestions.push('Check your API key in nova auth status');
|
|
260
|
+
suggestions.push('Verify the provider supports your selected model');
|
|
261
|
+
break;
|
|
262
|
+
|
|
263
|
+
case 'config':
|
|
264
|
+
suggestions.push('Validate your config.yaml file syntax');
|
|
265
|
+
suggestions.push('Run nova config edit to fix configuration');
|
|
266
|
+
break;
|
|
267
|
+
|
|
268
|
+
case 'model':
|
|
269
|
+
suggestions.push('Use nova model list to see available models');
|
|
270
|
+
suggestions.push('Check model alias configuration');
|
|
271
|
+
break;
|
|
272
|
+
|
|
273
|
+
case 'network':
|
|
274
|
+
suggestions.push('Check internet connection');
|
|
275
|
+
suggestions.push('Verify proxy settings');
|
|
276
|
+
break;
|
|
277
|
+
|
|
278
|
+
case 'timeout':
|
|
279
|
+
suggestions.push('Request timed out');
|
|
280
|
+
suggestions.push('Try again with a simpler request');
|
|
281
|
+
break;
|
|
282
|
+
|
|
283
|
+
case 'quota':
|
|
284
|
+
suggestions.push('Check your account billing status');
|
|
285
|
+
suggestions.push('Contact support for quota increase');
|
|
286
|
+
break;
|
|
287
|
+
|
|
288
|
+
default:
|
|
289
|
+
suggestions.push('Check the Nova CLI documentation');
|
|
290
|
+
suggestions.push('Search for your error code online');
|
|
291
|
+
break;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
return suggestions;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
// Static utility methods
|
|
298
|
+
static async handleAsyncError<T>(
|
|
299
|
+
promise: Promise<T>,
|
|
300
|
+
context?: any
|
|
301
|
+
): Promise<T> {
|
|
302
|
+
try {
|
|
303
|
+
return await promise;
|
|
304
|
+
} catch (error) {
|
|
305
|
+
const panel = new ErrorPanel();
|
|
306
|
+
panel.display(error, context);
|
|
307
|
+
throw error; // Re-throw after display
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
static formatErrorForLogging(error: Error): LoggableError {
|
|
312
|
+
return {
|
|
313
|
+
timestamp: new Date().toISOString(),
|
|
314
|
+
name: error.name,
|
|
315
|
+
message: error.message,
|
|
316
|
+
stack: error.stack,
|
|
317
|
+
category: this.inferCategory(error),
|
|
318
|
+
code: this.extractErrorCode(error)
|
|
319
|
+
};
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
private static inferCategory(error: Error): ErrorCategory {
|
|
323
|
+
const msg = error.message.toLowerCase();
|
|
324
|
+
|
|
325
|
+
if (msg.includes('api key') || msg.includes('authentication')) return 'auth';
|
|
326
|
+
if (msg.includes('config') || msg.includes('yaml')) return 'config';
|
|
327
|
+
if (msg.includes('network') || msg.includes('connection')) return 'network';
|
|
328
|
+
if (msg.includes('model')) return 'model';
|
|
329
|
+
if (msg.includes('file') || msg.includes('permission')) return 'file';
|
|
330
|
+
if (msg.includes('timeout')) return 'timeout';
|
|
331
|
+
if (msg.includes('quota') || msg.includes('billing')) return 'quota';
|
|
332
|
+
|
|
333
|
+
return 'unknown';
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
private static extractErrorCode(error: Error): string | undefined {
|
|
337
|
+
const match = error.message.match(/\[(\w+)\]/);
|
|
338
|
+
return match ? match[1] : undefined;
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
// Type definitions
|
|
343
|
+
interface ErrorInfo {
|
|
344
|
+
name: string;
|
|
345
|
+
message: string;
|
|
346
|
+
code?: string;
|
|
347
|
+
category: ErrorCategory;
|
|
348
|
+
suggestion: string[];
|
|
349
|
+
stack?: string;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
type ErrorCategory =
|
|
353
|
+
| 'auth' | 'config' | 'network' | 'model' | 'file'
|
|
354
|
+
| 'execution' | 'validation' | 'permission'
|
|
355
|
+
| 'timeout' | 'quota' | 'unknown';
|
|
356
|
+
|
|
357
|
+
interface LoggableError {
|
|
358
|
+
timestamp: string;
|
|
359
|
+
name: string;
|
|
360
|
+
message: string;
|
|
361
|
+
stack?: string;
|
|
362
|
+
category: ErrorCategory;
|
|
363
|
+
code?: string;
|
|
364
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// InkAppRunner - Simple Ink UI entry point
|
|
3
|
+
// This is a lightweight bridge that only handles UI rendering.
|
|
4
|
+
// Business logic is handled by the caller (NovaApp/InteractiveRepl)
|
|
5
|
+
// ============================================================================
|
|
6
|
+
|
|
7
|
+
import React from 'react';
|
|
8
|
+
import { render, RenderOptions } from 'ink';
|
|
9
|
+
import { NovaInkApp } from './NovaInkApp.js';
|
|
10
|
+
|
|
11
|
+
// ============================================================================
|
|
12
|
+
// Types
|
|
13
|
+
// ============================================================================
|
|
14
|
+
|
|
15
|
+
export interface InkAppOptions {
|
|
16
|
+
initialModel?: string;
|
|
17
|
+
initialMode?: 'auto' | 'plan' | 'ask';
|
|
18
|
+
sessionId?: string;
|
|
19
|
+
onSubmit?: (input: string) => Promise<void>;
|
|
20
|
+
onCommand?: (command: string) => Promise<void>;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// ============================================================================
|
|
24
|
+
// InkAppRunner Class
|
|
25
|
+
// ============================================================================
|
|
26
|
+
|
|
27
|
+
export class InkAppRunner {
|
|
28
|
+
private options: InkAppOptions;
|
|
29
|
+
|
|
30
|
+
constructor(options: InkAppOptions) {
|
|
31
|
+
this.options = options;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Start the Ink UI application
|
|
36
|
+
*/
|
|
37
|
+
async start(): Promise<void> {
|
|
38
|
+
const { waitUntilExit } = render(
|
|
39
|
+
<NovaInkApp
|
|
40
|
+
initialModel={this.options.initialModel || 'claude-3-sonnet'}
|
|
41
|
+
initialMode={this.options.initialMode || 'auto'}
|
|
42
|
+
sessionId={this.options.sessionId}
|
|
43
|
+
onSubmit={this.options.onSubmit}
|
|
44
|
+
onCommand={this.options.onCommand}
|
|
45
|
+
/>
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
await waitUntilExit();
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// ============================================================================
|
|
53
|
+
// Factory Function
|
|
54
|
+
// ============================================================================
|
|
55
|
+
|
|
56
|
+
export function createInkApp(options: InkAppOptions): InkAppRunner {
|
|
57
|
+
return new InkAppRunner(options);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// ============================================================================
|
|
61
|
+
// Standalone Run (for testing)
|
|
62
|
+
// ============================================================================
|
|
63
|
+
|
|
64
|
+
export async function runInkApp(options: InkAppOptions = {}): Promise<void> {
|
|
65
|
+
const app = createInkApp(options);
|
|
66
|
+
await app.start();
|
|
67
|
+
}
|