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.

Files changed (192) hide show
  1. package/README.md +358 -0
  2. package/bin/nova +38 -0
  3. package/bin/nova.js +12 -0
  4. package/package.json +67 -0
  5. package/src/cli/commands/SmartCompletion.ts +458 -0
  6. package/src/cli/index.ts +5 -0
  7. package/src/cli/startup/IFlowRepl.ts +212 -0
  8. package/src/cli/startup/InkBasedRepl.ts +1056 -0
  9. package/src/cli/startup/InteractiveRepl.ts +2833 -0
  10. package/src/cli/startup/NovaApp.ts +1861 -0
  11. package/src/cli/startup/index.ts +4 -0
  12. package/src/cli/startup/parseArgs.ts +293 -0
  13. package/src/cli/test-modules.ts +27 -0
  14. package/src/cli/ui/IFlowDropdown.ts +425 -0
  15. package/src/cli/ui/ModernReplUI.ts +276 -0
  16. package/src/cli/ui/SimpleSelector2.ts +215 -0
  17. package/src/cli/ui/components/ConfirmDialog.ts +176 -0
  18. package/src/cli/ui/components/ErrorPanel.ts +364 -0
  19. package/src/cli/ui/components/InkAppRunner.tsx +67 -0
  20. package/src/cli/ui/components/InkComponents.tsx +613 -0
  21. package/src/cli/ui/components/NovaInkApp.tsx +312 -0
  22. package/src/cli/ui/components/ProgressBar.ts +177 -0
  23. package/src/cli/ui/components/ProgressIndicator.ts +298 -0
  24. package/src/cli/ui/components/QuickActions.ts +396 -0
  25. package/src/cli/ui/components/SimpleErrorPanel.ts +231 -0
  26. package/src/cli/ui/components/StatusBar.ts +194 -0
  27. package/src/cli/ui/components/ThinkingBlockRenderer.ts +401 -0
  28. package/src/cli/ui/components/index.ts +27 -0
  29. package/src/cli/ui/ink-prototype.tsx +347 -0
  30. package/src/cli/utils/CliUI.ts +336 -0
  31. package/src/cli/utils/CompletionHelper.ts +388 -0
  32. package/src/cli/utils/EnhancedCompleter.test.ts +226 -0
  33. package/src/cli/utils/EnhancedCompleter.ts +513 -0
  34. package/src/cli/utils/ErrorEnhancer.ts +429 -0
  35. package/src/cli/utils/OutputFormatter.ts +193 -0
  36. package/src/cli/utils/index.ts +9 -0
  37. package/src/core/agents/AgentOrchestrator.ts +515 -0
  38. package/src/core/agents/index.ts +17 -0
  39. package/src/core/audit/AuditLogger.ts +509 -0
  40. package/src/core/audit/index.ts +11 -0
  41. package/src/core/auth/AuthManager.d.ts.map +1 -0
  42. package/src/core/auth/AuthManager.ts +138 -0
  43. package/src/core/auth/index.d.ts.map +1 -0
  44. package/src/core/auth/index.ts +2 -0
  45. package/src/core/config/ConfigManager.d.ts.map +1 -0
  46. package/src/core/config/ConfigManager.test.ts +183 -0
  47. package/src/core/config/ConfigManager.ts +1219 -0
  48. package/src/core/config/index.d.ts.map +1 -0
  49. package/src/core/config/index.ts +1 -0
  50. package/src/core/context/ContextBuilder.d.ts.map +1 -0
  51. package/src/core/context/ContextBuilder.ts +171 -0
  52. package/src/core/context/ContextCompressor.d.ts.map +1 -0
  53. package/src/core/context/ContextCompressor.ts +642 -0
  54. package/src/core/context/LayeredMemoryManager.ts +657 -0
  55. package/src/core/context/MemoryDiscovery.d.ts.map +1 -0
  56. package/src/core/context/MemoryDiscovery.ts +175 -0
  57. package/src/core/context/defaultSystemPrompt.d.ts.map +1 -0
  58. package/src/core/context/defaultSystemPrompt.ts +35 -0
  59. package/src/core/context/index.d.ts.map +1 -0
  60. package/src/core/context/index.ts +22 -0
  61. package/src/core/extensions/SkillGenerator.ts +421 -0
  62. package/src/core/extensions/SkillInstaller.d.ts.map +1 -0
  63. package/src/core/extensions/SkillInstaller.ts +257 -0
  64. package/src/core/extensions/SkillRegistry.d.ts.map +1 -0
  65. package/src/core/extensions/SkillRegistry.ts +361 -0
  66. package/src/core/extensions/SkillValidator.ts +525 -0
  67. package/src/core/extensions/index.ts +15 -0
  68. package/src/core/index.d.ts.map +1 -0
  69. package/src/core/index.ts +42 -0
  70. package/src/core/mcp/McpManager.d.ts.map +1 -0
  71. package/src/core/mcp/McpManager.ts +632 -0
  72. package/src/core/mcp/index.d.ts.map +1 -0
  73. package/src/core/mcp/index.ts +2 -0
  74. package/src/core/model/ModelClient.d.ts.map +1 -0
  75. package/src/core/model/ModelClient.ts +217 -0
  76. package/src/core/model/ModelConnectionTester.ts +363 -0
  77. package/src/core/model/ModelValidator.ts +348 -0
  78. package/src/core/model/index.d.ts.map +1 -0
  79. package/src/core/model/index.ts +6 -0
  80. package/src/core/model/providers/AnthropicProvider.d.ts.map +1 -0
  81. package/src/core/model/providers/AnthropicProvider.ts +279 -0
  82. package/src/core/model/providers/CodingPlanProvider.d.ts.map +1 -0
  83. package/src/core/model/providers/CodingPlanProvider.ts +210 -0
  84. package/src/core/model/providers/OllamaCloudProvider.d.ts.map +1 -0
  85. package/src/core/model/providers/OllamaCloudProvider.ts +405 -0
  86. package/src/core/model/providers/OllamaManager.d.ts.map +1 -0
  87. package/src/core/model/providers/OllamaManager.ts +201 -0
  88. package/src/core/model/providers/OllamaProvider.d.ts.map +1 -0
  89. package/src/core/model/providers/OllamaProvider.ts +73 -0
  90. package/src/core/model/providers/OpenAICompatibleProvider.d.ts.map +1 -0
  91. package/src/core/model/providers/OpenAICompatibleProvider.ts +327 -0
  92. package/src/core/model/providers/OpenAIProvider.d.ts.map +1 -0
  93. package/src/core/model/providers/OpenAIProvider.ts +29 -0
  94. package/src/core/model/providers/index.d.ts.map +1 -0
  95. package/src/core/model/providers/index.ts +12 -0
  96. package/src/core/model/types.d.ts.map +1 -0
  97. package/src/core/model/types.ts +77 -0
  98. package/src/core/security/ApprovalManager.d.ts.map +1 -0
  99. package/src/core/security/ApprovalManager.ts +174 -0
  100. package/src/core/security/FileFilter.d.ts.map +1 -0
  101. package/src/core/security/FileFilter.ts +141 -0
  102. package/src/core/security/HookExecutor.d.ts.map +1 -0
  103. package/src/core/security/HookExecutor.ts +178 -0
  104. package/src/core/security/SandboxExecutor.ts +447 -0
  105. package/src/core/security/index.d.ts.map +1 -0
  106. package/src/core/security/index.ts +8 -0
  107. package/src/core/session/AgentLoop.d.ts.map +1 -0
  108. package/src/core/session/AgentLoop.ts +501 -0
  109. package/src/core/session/SessionManager.d.ts.map +1 -0
  110. package/src/core/session/SessionManager.test.ts +183 -0
  111. package/src/core/session/SessionManager.ts +460 -0
  112. package/src/core/session/index.d.ts.map +1 -0
  113. package/src/core/session/index.ts +3 -0
  114. package/src/core/telemetry/Telemetry.d.ts.map +1 -0
  115. package/src/core/telemetry/Telemetry.ts +90 -0
  116. package/src/core/telemetry/TelemetryService.ts +531 -0
  117. package/src/core/telemetry/index.d.ts.map +1 -0
  118. package/src/core/telemetry/index.ts +12 -0
  119. package/src/core/testing/AutoFixer.ts +385 -0
  120. package/src/core/testing/ErrorAnalyzer.ts +499 -0
  121. package/src/core/testing/TestRunner.ts +265 -0
  122. package/src/core/testing/agent-cli-tests.ts +538 -0
  123. package/src/core/testing/index.ts +11 -0
  124. package/src/core/tools/ToolRegistry.d.ts.map +1 -0
  125. package/src/core/tools/ToolRegistry.test.ts +206 -0
  126. package/src/core/tools/ToolRegistry.ts +260 -0
  127. package/src/core/tools/impl/EditFileTool.d.ts.map +1 -0
  128. package/src/core/tools/impl/EditFileTool.ts +97 -0
  129. package/src/core/tools/impl/ListDirectoryTool.d.ts.map +1 -0
  130. package/src/core/tools/impl/ListDirectoryTool.ts +142 -0
  131. package/src/core/tools/impl/MemoryTool.d.ts.map +1 -0
  132. package/src/core/tools/impl/MemoryTool.ts +102 -0
  133. package/src/core/tools/impl/ReadFileTool.d.ts.map +1 -0
  134. package/src/core/tools/impl/ReadFileTool.ts +58 -0
  135. package/src/core/tools/impl/SearchContentTool.d.ts.map +1 -0
  136. package/src/core/tools/impl/SearchContentTool.ts +94 -0
  137. package/src/core/tools/impl/SearchFileTool.d.ts.map +1 -0
  138. package/src/core/tools/impl/SearchFileTool.ts +61 -0
  139. package/src/core/tools/impl/ShellTool.d.ts.map +1 -0
  140. package/src/core/tools/impl/ShellTool.ts +118 -0
  141. package/src/core/tools/impl/TaskTool.d.ts.map +1 -0
  142. package/src/core/tools/impl/TaskTool.ts +207 -0
  143. package/src/core/tools/impl/TodoTool.d.ts.map +1 -0
  144. package/src/core/tools/impl/TodoTool.ts +122 -0
  145. package/src/core/tools/impl/WebFetchTool.d.ts.map +1 -0
  146. package/src/core/tools/impl/WebFetchTool.ts +103 -0
  147. package/src/core/tools/impl/WebSearchTool.d.ts.map +1 -0
  148. package/src/core/tools/impl/WebSearchTool.ts +89 -0
  149. package/src/core/tools/impl/WriteFileTool.d.ts.map +1 -0
  150. package/src/core/tools/impl/WriteFileTool.ts +49 -0
  151. package/src/core/tools/impl/index.d.ts.map +1 -0
  152. package/src/core/tools/impl/index.ts +16 -0
  153. package/src/core/tools/index.d.ts.map +1 -0
  154. package/src/core/tools/index.ts +7 -0
  155. package/src/core/tools/schemas/execution.d.ts.map +1 -0
  156. package/src/core/tools/schemas/execution.ts +42 -0
  157. package/src/core/tools/schemas/file.d.ts.map +1 -0
  158. package/src/core/tools/schemas/file.ts +119 -0
  159. package/src/core/tools/schemas/index.d.ts.map +1 -0
  160. package/src/core/tools/schemas/index.ts +11 -0
  161. package/src/core/tools/schemas/memory.d.ts.map +1 -0
  162. package/src/core/tools/schemas/memory.ts +52 -0
  163. package/src/core/tools/schemas/orchestration.d.ts.map +1 -0
  164. package/src/core/tools/schemas/orchestration.ts +44 -0
  165. package/src/core/tools/schemas/search.d.ts.map +1 -0
  166. package/src/core/tools/schemas/search.ts +112 -0
  167. package/src/core/tools/schemas/todo.d.ts.map +1 -0
  168. package/src/core/tools/schemas/todo.ts +32 -0
  169. package/src/core/tools/schemas/web.d.ts.map +1 -0
  170. package/src/core/tools/schemas/web.ts +86 -0
  171. package/src/core/types/config.d.ts.map +1 -0
  172. package/src/core/types/config.ts +200 -0
  173. package/src/core/types/errors.d.ts.map +1 -0
  174. package/src/core/types/errors.ts +204 -0
  175. package/src/core/types/index.d.ts.map +1 -0
  176. package/src/core/types/index.ts +8 -0
  177. package/src/core/types/session.d.ts.map +1 -0
  178. package/src/core/types/session.ts +216 -0
  179. package/src/core/types/tools.d.ts.map +1 -0
  180. package/src/core/types/tools.ts +157 -0
  181. package/src/core/utils/CheckpointManager.d.ts.map +1 -0
  182. package/src/core/utils/CheckpointManager.ts +327 -0
  183. package/src/core/utils/Logger.d.ts.map +1 -0
  184. package/src/core/utils/Logger.ts +98 -0
  185. package/src/core/utils/RetryManager.ts +471 -0
  186. package/src/core/utils/TokenCounter.d.ts.map +1 -0
  187. package/src/core/utils/TokenCounter.ts +414 -0
  188. package/src/core/utils/VectorMemoryStore.ts +440 -0
  189. package/src/core/utils/helpers.d.ts.map +1 -0
  190. package/src/core/utils/helpers.ts +89 -0
  191. package/src/core/utils/index.d.ts.map +1 -0
  192. package/src/core/utils/index.ts +19 -0
@@ -0,0 +1,265 @@
1
+ // ============================================================================
2
+ // TestRunner - Execute test commands and parse results
3
+ // Reference: Aider-style automatic test execution
4
+ // ============================================================================
5
+
6
+ import { exec } from 'node:child_process';
7
+ import { promisify } from 'node:util';
8
+
9
+ const execAsync = promisify(exec);
10
+
11
+ export interface FailedTest {
12
+ /** Test file or test name */
13
+ file: string;
14
+ /** Error message */
15
+ error: string;
16
+ /** Line number if available */
17
+ line?: number;
18
+ /** Test framework that reported the failure */
19
+ framework?: string;
20
+ }
21
+
22
+ export interface TestResult {
23
+ /** Whether all tests passed */
24
+ success: boolean;
25
+ /** Raw stdout output */
26
+ output: string;
27
+ /** Raw stderr output */
28
+ errors: string;
29
+ /** List of failed tests */
30
+ failedTests: FailedTest[];
31
+ /** Total number of tests run (if parseable) */
32
+ totalTests?: number;
33
+ /** Number of passed tests (if parseable) */
34
+ passedTests?: number;
35
+ /** Duration in ms */
36
+ duration: number;
37
+ /** Exit code */
38
+ exitCode: number;
39
+ }
40
+
41
+ export interface TestRunnerOptions {
42
+ /** Working directory for the test command */
43
+ cwd?: string;
44
+ /** Timeout in ms (default: 60000) */
45
+ timeout?: number;
46
+ /** Environment variables */
47
+ env?: Record<string, string>;
48
+ }
49
+
50
+ // --- Test result parsing patterns ---
51
+
52
+ const TEST_PATTERNS: Array<{
53
+ framework: string;
54
+ failPattern: RegExp;
55
+ totalCountPattern?: RegExp;
56
+ passCountPattern?: RegExp;
57
+ errorLinePattern?: RegExp;
58
+ }> = [
59
+ {
60
+ framework: 'jest',
61
+ failPattern: /FAIL\s+([^\s]+)/g,
62
+ totalCountPattern: /Tests:\s+(\d+)\s+failed/,
63
+ passCountPattern: /Tests:\s+(\d+)\s+passed,\s+(\d+)\s+total/,
64
+ errorLinePattern: /at\s+([^\n]+):(\d+):\d+/,
65
+ },
66
+ {
67
+ framework: 'vitest',
68
+ failPattern: /×\s+([^\s]+)\s*\([^\)]*\)/g,
69
+ totalCountPattern: /Tests\s+(\d+)\s+failed/,
70
+ passCountPattern: /Tests\s+(\d+)\s+passed\s+\|/,
71
+ errorLinePattern: /at\s+([^\n]+):(\d+):\d+/,
72
+ },
73
+ {
74
+ framework: 'mocha',
75
+ failPattern: /\s+\d+\)\s+([^\n:]+):/g,
76
+ totalCountPattern: /(\d+)\s+passing/,
77
+ errorLinePattern: /at\s+([^\n]+):(\d+):\d+/,
78
+ },
79
+ {
80
+ framework: 'pytest',
81
+ failPattern: /FAILED\s+([^\s-]+)/g,
82
+ totalCountPattern: /(\d+)\s+failed/,
83
+ passCountPattern: /(\d+)\s+passed/,
84
+ errorLinePattern: /File\s+"([^"]+)",\s+line\s+(\d+)/,
85
+ },
86
+ {
87
+ framework: 'go-test',
88
+ failPattern: /---\s+FAIL:\s+([^\s]+)/g,
89
+ totalCountPattern: /FAIL\s+\d+/,
90
+ errorLinePattern: /([^/\\]+\.go):(\d+)/,
91
+ },
92
+ {
93
+ framework: 'cargo-test',
94
+ failPattern: /test\s+\.\.\.\s+FAILED/g,
95
+ errorLinePattern: /----\s+([^\n]+)\s+stdout/,
96
+ },
97
+ {
98
+ framework: 'generic',
99
+ failPattern: /(?:FAIL|FAILED|ERROR|error)\s*[:\s]+(.+)/gi,
100
+ errorLinePattern: /at\s+([^\n]+):(\d+):\d+/,
101
+ },
102
+ ];
103
+
104
+ // --- TestRunner ---
105
+
106
+ export class TestRunner {
107
+ private options: TestRunnerOptions;
108
+
109
+ constructor(options?: TestRunnerOptions) {
110
+ this.options = {
111
+ cwd: process.cwd(),
112
+ timeout: 60000,
113
+ ...options,
114
+ };
115
+ }
116
+
117
+ /**
118
+ * Run a test command and parse the results.
119
+ */
120
+ async run(testCommand: string): Promise<TestResult> {
121
+ const startTime = Date.now();
122
+
123
+ try {
124
+ const { stdout, stderr } = await execAsync(testCommand, {
125
+ cwd: this.options.cwd,
126
+ timeout: this.options.timeout,
127
+ env: { ...process.env, ...this.options.env },
128
+ maxBuffer: 1024 * 1024, // 1MB
129
+ });
130
+
131
+ const duration = Date.now() - startTime;
132
+ const combinedOutput = `${stdout}\n${stderr}`;
133
+ const failedTests = this.parseFailedTests(combinedOutput);
134
+ const { totalTests, passedTests } = this.parseTestCounts(combinedOutput);
135
+
136
+ return {
137
+ success: failedTests.length === 0,
138
+ output: stdout,
139
+ errors: stderr,
140
+ failedTests,
141
+ totalTests,
142
+ passedTests,
143
+ duration,
144
+ exitCode: 0,
145
+ };
146
+ } catch (err: any) {
147
+ const duration = Date.now() - startTime;
148
+ const output = err.stdout || '';
149
+ const stderr = err.stderr || '';
150
+ const combinedOutput = `${output}\n${stderr}`;
151
+ const failedTests = this.parseFailedTests(combinedOutput);
152
+ const { totalTests, passedTests } = this.parseTestCounts(combinedOutput);
153
+
154
+ return {
155
+ success: false,
156
+ output,
157
+ errors: stderr || err.message,
158
+ failedTests,
159
+ totalTests,
160
+ passedTests,
161
+ duration,
162
+ exitCode: err.code || 1,
163
+ };
164
+ }
165
+ }
166
+
167
+ /**
168
+ * Auto-detect the test command for the current project.
169
+ */
170
+ async detectTestCommand(): Promise<string | null> {
171
+ const fs = await import('node:fs/promises');
172
+
173
+ // Check for test scripts in package.json
174
+ try {
175
+ const pkg = JSON.parse(await fs.readFile('package.json', 'utf-8'));
176
+ if (pkg.scripts?.test) return pkg.scripts.test;
177
+ if (pkg.scripts?.['test:unit']) return pkg.scripts['test:unit'];
178
+ if (pkg.scripts?.['test:ci']) return pkg.scripts['test:ci'];
179
+ } catch {
180
+ // No package.json
181
+ }
182
+
183
+ // Check for test files
184
+ const testIndicators = [
185
+ { file: 'jest.config.js', cmd: 'npx jest' },
186
+ { file: 'jest.config.ts', cmd: 'npx jest' },
187
+ { file: 'vitest.config.ts', cmd: 'npx vitest run' },
188
+ { file: 'vitest.config.js', cmd: 'npx vitest run' },
189
+ { file: '.mocharc.yml', cmd: 'npx mocha' },
190
+ { file: 'pytest.ini', cmd: 'python -m pytest' },
191
+ { file: 'Cargo.toml', cmd: 'cargo test' },
192
+ ];
193
+
194
+ for (const indicator of testIndicators) {
195
+ try {
196
+ await fs.access(indicator.file);
197
+ return indicator.cmd;
198
+ } catch {
199
+ // File doesn't exist
200
+ }
201
+ }
202
+
203
+ return null;
204
+ }
205
+
206
+ /**
207
+ * Parse failed tests from test output.
208
+ */
209
+ private parseFailedTests(output: string): FailedTest[] {
210
+ const failures: FailedTest[] = [];
211
+
212
+ for (const pattern of TEST_PATTERNS) {
213
+ const failRegex = new RegExp(pattern.failPattern.source, pattern.failPattern.flags);
214
+ const matches = output.matchAll(failRegex);
215
+
216
+ for (const match of matches) {
217
+ const testName = match[1]?.trim() || '';
218
+ if (!testName || testName.length < 2) continue;
219
+ // Skip internal framework messages
220
+ if (testName.startsWith('PASS') || testName.startsWith('FAIL')) continue;
221
+
222
+ let line: number | undefined;
223
+ const errorLineRegex = new RegExp(pattern.errorLinePattern.source, 'g');
224
+ const lineMatch = errorLineRegex.exec(output);
225
+ if (lineMatch) {
226
+ line = parseInt(lineMatch[2], 10) || undefined;
227
+ }
228
+
229
+ failures.push({
230
+ file: testName,
231
+ error: '',
232
+ line,
233
+ framework: pattern.framework,
234
+ });
235
+ }
236
+ }
237
+
238
+ // Deduplicate by file name
239
+ const seen = new Set<string>();
240
+ return failures.filter((f) => {
241
+ if (seen.has(f.file)) return false;
242
+ seen.add(f.file);
243
+ return true;
244
+ });
245
+ }
246
+
247
+ /**
248
+ * Parse total and passed test counts from output.
249
+ */
250
+ private parseTestCounts(output: string): { totalTests?: number; passedTests?: number } {
251
+ for (const pattern of TEST_PATTERNS) {
252
+ if (pattern.passCountPattern) {
253
+ const match = output.match(pattern.passCountPattern);
254
+ if (match) {
255
+ return {
256
+ totalTests: parseInt(match[2], 10) || undefined,
257
+ passedTests: parseInt(match[1], 10) || undefined,
258
+ };
259
+ }
260
+ }
261
+ }
262
+
263
+ return {};
264
+ }
265
+ }