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,447 @@
1
+ // ============================================================================
2
+ // SandboxExecutor - Isolated execution environment
3
+ // ============================================================================
4
+
5
+ import { spawn, ChildProcess } from 'node:child_process';
6
+ import * as path from 'node:path';
7
+ import * as os from 'node:os';
8
+ import { createLogger } from '../utils/Logger.js';
9
+
10
+ const logger = createLogger('SandboxExecutor');
11
+
12
+ // ============================================================================
13
+ // Types
14
+ // ============================================================================
15
+
16
+ /**
17
+ * Sandbox type
18
+ */
19
+ export type SandboxType = 'none' | 'docker' | 'isolate' | 'bubblewrap';
20
+
21
+ /**
22
+ * Sandbox configuration
23
+ */
24
+ export interface SandboxConfig {
25
+ enabled: boolean;
26
+ type: SandboxType;
27
+ network: 'none' | 'restricted' | 'full';
28
+ memory: string; // e.g., "2GB"
29
+ cpu: string; // e.g., "1.0" (100%)
30
+ timeout: number; // milliseconds
31
+ workDir?: string;
32
+ env?: Record<string, string>;
33
+ readOnlyPaths?: string[];
34
+ writablePaths?: string[];
35
+ }
36
+
37
+ /**
38
+ * Execution result
39
+ */
40
+ export interface ExecutionResult {
41
+ stdout: string;
42
+ stderr: string;
43
+ exitCode: number;
44
+ duration: number;
45
+ timedOut: boolean;
46
+ }
47
+
48
+ /**
49
+ * Default sandbox configuration
50
+ */
51
+ const DEFAULT_CONFIG: SandboxConfig = {
52
+ enabled: false,
53
+ type: 'none',
54
+ network: 'none',
55
+ memory: '2GB',
56
+ cpu: '1.0',
57
+ timeout: 60000,
58
+ };
59
+
60
+ // ============================================================================
61
+ // SandboxExecutor
62
+ // ============================================================================
63
+
64
+ /**
65
+ * Execute commands in an isolated sandbox environment
66
+ */
67
+ export class SandboxExecutor {
68
+ private config: SandboxConfig;
69
+ private dockerAvailable: boolean | null = null;
70
+
71
+ constructor(config: Partial<SandboxConfig> = {}) {
72
+ this.config = { ...DEFAULT_CONFIG, ...config };
73
+ }
74
+
75
+ // -----------------------------------------------------------------------
76
+ // Detection
77
+ // -----------------------------------------------------------------------
78
+
79
+ /**
80
+ * Check if Docker is available
81
+ */
82
+ async isDockerAvailable(): Promise<boolean> {
83
+ if (this.dockerAvailable !== null) return this.dockerAvailable;
84
+
85
+ try {
86
+ const result = await this.runCommand('docker', ['--version'], 5000);
87
+ this.dockerAvailable = result.exitCode === 0;
88
+ logger.debug(`Docker available: ${this.dockerAvailable}`);
89
+ } catch {
90
+ this.dockerAvailable = false;
91
+ }
92
+
93
+ return this.dockerAvailable;
94
+ }
95
+
96
+ /**
97
+ * Get the best available sandbox type
98
+ */
99
+ async getBestSandboxType(): Promise<SandboxType> {
100
+ if (await this.isDockerAvailable()) return 'docker';
101
+
102
+ // Check for Linux-specific sandbox tools
103
+ if (os.platform() === 'linux') {
104
+ try {
105
+ await this.runCommand('which', ['bwrap'], 1000);
106
+ return 'bubblewrap';
107
+ } catch {}
108
+
109
+ try {
110
+ await this.runCommand('which', ['isolate'], 1000);
111
+ return 'isolate';
112
+ } catch {}
113
+ }
114
+
115
+ return 'none';
116
+ }
117
+
118
+ // -----------------------------------------------------------------------
119
+ // Execution
120
+ // -----------------------------------------------------------------------
121
+
122
+ /**
123
+ * Execute a command in the sandbox
124
+ */
125
+ async execute(command: string, args: string[] = []): Promise<ExecutionResult> {
126
+ const startTime = Date.now();
127
+
128
+ if (!this.config.enabled) {
129
+ // No sandbox - direct execution
130
+ return this.runCommand(command, args, this.config.timeout);
131
+ }
132
+
133
+ switch (this.config.type) {
134
+ case 'docker':
135
+ return this.executeInDocker(command, args);
136
+
137
+ case 'bubblewrap':
138
+ return this.executeInBubblewrap(command, args);
139
+
140
+ case 'isolate':
141
+ return this.executeInIsolate(command, args);
142
+
143
+ default:
144
+ return this.runCommand(command, args, this.config.timeout);
145
+ }
146
+ }
147
+
148
+ /**
149
+ * Execute a shell command string
150
+ */
151
+ async executeShell(shellCommand: string): Promise<ExecutionResult> {
152
+ const isWin = os.platform() === 'win32';
153
+ const shell = isWin ? 'powershell.exe' : '/bin/sh';
154
+ const shellArgs = isWin ? ['-Command', shellCommand] : ['-c', shellCommand];
155
+
156
+ return this.execute(shell, shellArgs);
157
+ }
158
+
159
+ // -----------------------------------------------------------------------
160
+ // Docker Execution
161
+ // -----------------------------------------------------------------------
162
+
163
+ /**
164
+ * Execute command in Docker container
165
+ */
166
+ private async executeInDocker(command: string, args: string[]): Promise<ExecutionResult> {
167
+ if (!(await this.isDockerAvailable())) {
168
+ logger.warn('Docker not available, falling back to direct execution');
169
+ return this.runCommand(command, args, this.config.timeout);
170
+ }
171
+
172
+ const workDir = this.config.workDir ?? process.cwd();
173
+
174
+ // Build docker run arguments
175
+ const dockerArgs = [
176
+ 'run',
177
+ '--rm',
178
+ '-v', `${workDir}:/workspace`,
179
+ '-w', '/workspace',
180
+ ];
181
+
182
+ // Memory limit
183
+ dockerArgs.push('-m', this.config.memory);
184
+
185
+ // CPU limit
186
+ dockerArgs.push('--cpus', this.config.cpu);
187
+
188
+ // Network
189
+ if (this.config.network === 'none') {
190
+ dockerArgs.push('--network', 'none');
191
+ }
192
+
193
+ // Environment variables
194
+ if (this.config.env) {
195
+ for (const [key, value] of Object.entries(this.config.env)) {
196
+ dockerArgs.push('-e', `${key}=${value}`);
197
+ }
198
+ }
199
+
200
+ // Read-only paths
201
+ if (this.config.readOnlyPaths) {
202
+ for (const p of this.config.readOnlyPaths) {
203
+ dockerArgs.push('-v', `${p}:/ro-${path.basename(p)}:ro`);
204
+ }
205
+ }
206
+
207
+ // Image and command
208
+ dockerArgs.push('nova-sandbox:latest', command, ...args);
209
+
210
+ logger.debug(`Docker args: ${dockerArgs.join(' ')}`);
211
+
212
+ return this.runCommand('docker', dockerArgs, this.config.timeout);
213
+ }
214
+
215
+ // -----------------------------------------------------------------------
216
+ // Bubblewrap Execution (Linux)
217
+ // -----------------------------------------------------------------------
218
+
219
+ /**
220
+ * Execute command using Bubblewrap (Linux only)
221
+ */
222
+ private async executeInBubblewrap(command: string, args: string[]): Promise<ExecutionResult> {
223
+ if (os.platform() !== 'linux') {
224
+ logger.warn('Bubblewrap only available on Linux, falling back');
225
+ return this.runCommand(command, args, this.config.timeout);
226
+ }
227
+
228
+ const workDir = this.config.workDir ?? process.cwd();
229
+
230
+ // Build bwrap arguments
231
+ const bwrapArgs = [
232
+ '--ro-bind', '/usr', '/usr',
233
+ '--ro-bind', '/bin', '/bin',
234
+ '--ro-bind', '/lib', '/lib',
235
+ '--ro-bind', '/lib64', '/lib64',
236
+ '--bind', workDir, workDir,
237
+ '--unshare-all',
238
+ '--die-with-parent',
239
+ ];
240
+
241
+ // Network
242
+ if (this.config.network === 'none') {
243
+ bwrapArgs.push('--unshare-net');
244
+ }
245
+
246
+ // Command to execute
247
+ bwrapArgs.push('--', command, ...args);
248
+
249
+ return this.runCommand('bwrap', bwrapArgs, this.config.timeout);
250
+ }
251
+
252
+ // -----------------------------------------------------------------------
253
+ // Isolate Execution (Linux)
254
+ // -----------------------------------------------------------------------
255
+
256
+ /**
257
+ * Execute command using Isolate (Linux only)
258
+ */
259
+ private async executeInIsolate(command: string, args: string[]): Promise<ExecutionResult> {
260
+ if (os.platform() !== 'linux') {
261
+ logger.warn('Isolate only available on Linux, falling back');
262
+ return this.runCommand(command, args, this.config.timeout);
263
+ }
264
+
265
+ const workDir = this.config.workDir ?? process.cwd();
266
+
267
+ // Build isolate arguments
268
+ const isolateArgs = [
269
+ '--run',
270
+ '--dir=/work=' + workDir,
271
+ '--workdir=/work',
272
+ ];
273
+
274
+ // Memory limit (in KB)
275
+ const memKB = this.parseMemory(this.config.memory);
276
+ isolateArgs.push(`--mem=${memKB}`);
277
+
278
+ // Time limit (in seconds)
279
+ isolateArgs.push(`--time=${Math.ceil(this.config.timeout / 1000)}`);
280
+
281
+ // Network
282
+ if (this.config.network === 'none') {
283
+ isolateArgs.push('--no-direct-io');
284
+ }
285
+
286
+ // Command
287
+ isolateArgs.push('--', command, ...args);
288
+
289
+ return this.runCommand('isolate', isolateArgs, this.config.timeout);
290
+ }
291
+
292
+ // -----------------------------------------------------------------------
293
+ // Utilities
294
+ // -----------------------------------------------------------------------
295
+
296
+ /**
297
+ * Run a command with timeout
298
+ */
299
+ private runCommand(
300
+ command: string,
301
+ args: string[],
302
+ timeout: number
303
+ ): Promise<ExecutionResult> {
304
+ return new Promise((resolve) => {
305
+ const startTime = Date.now();
306
+ let stdout = '';
307
+ let stderr = '';
308
+ let timedOut = false;
309
+
310
+ const proc = spawn(command, args, {
311
+ cwd: this.config.workDir,
312
+ env: { ...process.env, ...this.config.env },
313
+ shell: os.platform() === 'win32',
314
+ });
315
+
316
+ const timeoutId = setTimeout(() => {
317
+ timedOut = true;
318
+ proc.kill('SIGKILL');
319
+ }, timeout);
320
+
321
+ proc.stdout?.on('data', (data) => {
322
+ stdout += data.toString();
323
+ });
324
+
325
+ proc.stderr?.on('data', (data) => {
326
+ stderr += data.toString();
327
+ });
328
+
329
+ proc.on('close', (code) => {
330
+ clearTimeout(timeoutId);
331
+ resolve({
332
+ stdout,
333
+ stderr,
334
+ exitCode: code ?? 1,
335
+ duration: Date.now() - startTime,
336
+ timedOut,
337
+ });
338
+ });
339
+
340
+ proc.on('error', (err) => {
341
+ clearTimeout(timeoutId);
342
+ stderr += err.message;
343
+ resolve({
344
+ stdout,
345
+ stderr,
346
+ exitCode: 1,
347
+ duration: Date.now() - startTime,
348
+ timedOut: false,
349
+ });
350
+ });
351
+ });
352
+ }
353
+
354
+ /**
355
+ * Parse memory string to KB
356
+ */
357
+ private parseMemory(mem: string): number {
358
+ const match = mem.match(/^(\d+(?:\.\d+)?)(GB|MB|KB)?$/i);
359
+ if (!match) return 2 * 1024 * 1024; // Default 2GB
360
+
361
+ const value = parseFloat(match[1] || '0');
362
+ const unit = (match[2] || 'MB').toUpperCase();
363
+
364
+ switch (unit) {
365
+ case 'GB': return value * 1024 * 1024;
366
+ case 'MB': return value * 1024;
367
+ case 'KB': return value;
368
+ default: return value * 1024;
369
+ }
370
+ }
371
+
372
+ // -----------------------------------------------------------------------
373
+ // Docker Image Management
374
+ // -----------------------------------------------------------------------
375
+
376
+ /**
377
+ * Build the sandbox Docker image
378
+ */
379
+ async buildDockerImage(): Promise<boolean> {
380
+ if (!(await this.isDockerAvailable())) {
381
+ logger.error('Docker not available');
382
+ return false;
383
+ }
384
+
385
+ const dockerfile = `
386
+ FROM node:20-slim
387
+ WORKDIR /workspace
388
+ RUN apt-get update && apt-get install -y \
389
+ git \
390
+ curl \
391
+ && rm -rf /var/lib/apt/lists/*
392
+ CMD ["/bin/bash"]
393
+ `;
394
+
395
+ try {
396
+ const result = await this.runCommand('docker', [
397
+ 'build',
398
+ '-t', 'nova-sandbox:latest',
399
+ '-',
400
+ ], 60000);
401
+
402
+ // Pass dockerfile via stdin would require more complex handling
403
+ // For now, create a temp file
404
+ logger.info('Docker image built successfully');
405
+ return result.exitCode === 0;
406
+ } catch (error) {
407
+ logger.error('Failed to build Docker image', { error });
408
+ return false;
409
+ }
410
+ }
411
+
412
+ /**
413
+ * Check if sandbox Docker image exists
414
+ */
415
+ async hasDockerImage(): Promise<boolean> {
416
+ if (!(await this.isDockerAvailable())) return false;
417
+
418
+ try {
419
+ const result = await this.runCommand('docker', [
420
+ 'image', 'inspect', 'nova-sandbox:latest',
421
+ ], 5000);
422
+ return result.exitCode === 0;
423
+ } catch {
424
+ return false;
425
+ }
426
+ }
427
+ }
428
+
429
+ // ============================================================================
430
+ // Factory function
431
+ // ============================================================================
432
+
433
+ /**
434
+ * Create a sandbox executor with default configuration
435
+ */
436
+ export function createSandboxExecutor(config: Partial<SandboxConfig> = {}): SandboxExecutor {
437
+ return new SandboxExecutor(config);
438
+ }
439
+
440
+ /**
441
+ * Check if sandbox is available
442
+ */
443
+ export async function isSandboxAvailable(): Promise<boolean> {
444
+ const executor = new SandboxExecutor();
445
+ const type = await executor.getBestSandboxType();
446
+ return type !== 'none';
447
+ }
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,YAAY,EAAE,sBAAsB,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAClG,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,YAAY,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAC7D,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,YAAY,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC"}
@@ -0,0 +1,8 @@
1
+ export { ApprovalManager } from './ApprovalManager.js';
2
+ export type { ApprovalManagerOptions, ApprovalRule, ApprovalHandler } from './ApprovalManager.js';
3
+ export { HookExecutor } from './HookExecutor.js';
4
+ export type { HookExecutorOptions } from './HookExecutor.js';
5
+ export { FileFilter } from './FileFilter.js';
6
+ // FileFilterConfig is exported from types/config.js
7
+ export { SandboxExecutor, createSandboxExecutor, isSandboxAvailable } from './SandboxExecutor.js';
8
+ export type { SandboxType, SandboxConfig, ExecutionResult } from './SandboxExecutor.js';
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AgentLoop.d.ts","sourceRoot":"","sources":["AgentLoop.ts"],"names":[],"mappings":"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"}