erosolar-cli 1.7.414 → 1.7.415

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.
@@ -0,0 +1,282 @@
1
+ /**
2
+ * Comprehensive Tool Validation System
3
+ *
4
+ * Provides proactive validation for AI tool usage with:
5
+ * - Pre-flight validation before tool execution
6
+ * - Real-time AI flow guidance
7
+ * - Pattern-based anti-pattern detection
8
+ * - Recovery suggestions for common failures
9
+ */
10
+ import { analyzeBashFlow } from './bashCommandGuidance.js';
11
+ /**
12
+ * Comprehensive tool validator
13
+ */
14
+ export class ToolValidator {
15
+ patterns = [
16
+ {
17
+ pattern: 'edit_without_read',
18
+ description: 'Attempting Edit tool without first reading the file',
19
+ guidance: 'ALWAYS use Read tool before Edit tool to get exact text including whitespace and indentation',
20
+ examples: [
21
+ 'Edit tool called without preceding Read tool',
22
+ 'old_string contains guessed content instead of exact file content'
23
+ ]
24
+ },
25
+ {
26
+ pattern: 'broad_search_pattern',
27
+ description: 'Using overly broad search patterns that may cause context overflow',
28
+ guidance: 'Use specific search patterns like "**/*.ts" or "src/**/*.js" instead of "*" or "."',
29
+ examples: [
30
+ 'Glob(".") or Glob("*") without head_limit',
31
+ 'Search patterns that could return thousands of files'
32
+ ]
33
+ },
34
+ {
35
+ pattern: 'redundant_git_operations',
36
+ description: 'Running multiple git status calls or inefficient git command chains',
37
+ guidance: 'Use single combined commands: "git add -A && git commit -m msg && git push"',
38
+ examples: [
39
+ 'git status → git add → git status → git commit → git push',
40
+ 'Multiple git status calls in sequence'
41
+ ]
42
+ },
43
+ {
44
+ pattern: 'incomplete_npm_publish',
45
+ description: 'npm publish detected without confirming release prerequisites',
46
+ guidance: 'Ensure auth, version bump, build/tests, publish, and git push follow the project release process; automation (npm_publish) is preferred but not required',
47
+ examples: [
48
+ 'Running npm publish before bumping version',
49
+ 'Publishing without build/test steps required by the project'
50
+ ]
51
+ },
52
+ {
53
+ pattern: 'sequential_file_reads',
54
+ description: 'Reading files sequentially when parallel execution is possible',
55
+ guidance: 'Use parallel tool calls for independent file reads to improve performance',
56
+ examples: [
57
+ 'Multiple Read calls in separate tool calls',
58
+ 'Sequential file operations that could be parallelized'
59
+ ]
60
+ },
61
+ {
62
+ pattern: 'validation_after_each_edit',
63
+ description: 'Running validation after each individual edit',
64
+ guidance: 'Complete ALL edits first, run ONE validation at the end only if needed',
65
+ examples: [
66
+ 'Running type-check after each file edit',
67
+ 'Running build/test after every small change'
68
+ ]
69
+ }
70
+ ];
71
+ /**
72
+ * Validate tool usage before execution
73
+ */
74
+ validateToolUsage(tool, context) {
75
+ const warnings = [];
76
+ const suggestions = [];
77
+ const criticalErrors = [];
78
+ // Tool-specific validation
79
+ this.validateToolSpecific(tool, context, warnings, suggestions, criticalErrors);
80
+ // AI flow pattern validation
81
+ this.validateAIFlowPatterns(tool, context, warnings, suggestions);
82
+ // Performance optimization validation
83
+ this.validatePerformance(tool, context, warnings, suggestions);
84
+ return {
85
+ valid: criticalErrors.length === 0,
86
+ warnings,
87
+ suggestions,
88
+ criticalErrors
89
+ };
90
+ }
91
+ /**
92
+ * Validate tool-specific patterns
93
+ */
94
+ validateToolSpecific(tool, context, warnings, suggestions, criticalErrors) {
95
+ switch (tool.name) {
96
+ case 'Edit':
97
+ this.validateEditTool(tool, context, warnings, criticalErrors);
98
+ break;
99
+ case 'Glob':
100
+ case 'Grep':
101
+ this.validateSearchTools(tool, context, warnings, suggestions);
102
+ break;
103
+ case 'execute_bash':
104
+ this.validateBashCommands(tool, context, warnings, suggestions);
105
+ break;
106
+ }
107
+ }
108
+ /**
109
+ * Validate Edit tool usage
110
+ */
111
+ validateEditTool(tool, context, warnings, criticalErrors) {
112
+ const params = tool.parameters;
113
+ // Check for placeholder patterns in old_string
114
+ if (params.old_string && this.containsPlaceholderPattern(params.old_string)) {
115
+ warnings.push({
116
+ code: 'EDIT_PLACEHOLDER_DETECTED',
117
+ message: 'Edit tool old_string contains placeholder patterns',
118
+ severity: 'high',
119
+ suggestion: 'Use Read tool first to get exact file content instead of guessing'
120
+ });
121
+ }
122
+ // Check for long single lines (likely guessed content)
123
+ if (params.old_string && this.isLongSingleLine(params.old_string)) {
124
+ warnings.push({
125
+ code: 'EDIT_LONG_SINGLE_LINE',
126
+ message: 'Edit tool old_string is a long single line (likely guessed content)',
127
+ severity: 'medium',
128
+ suggestion: 'Read the file first to get exact multi-line content'
129
+ });
130
+ }
131
+ // Check for indentation mismatches
132
+ if (params.old_string && params.new_string && this.hasIndentationMismatch(params.old_string, params.new_string)) {
133
+ warnings.push({
134
+ code: 'EDIT_INDENTATION_MISMATCH',
135
+ message: 'Edit tool old_string and new_string have indentation mismatches',
136
+ severity: 'high',
137
+ suggestion: 'Ensure exact whitespace matching between old and new strings'
138
+ });
139
+ }
140
+ }
141
+ /**
142
+ * Validate search tools (Glob, Grep)
143
+ */
144
+ validateSearchTools(tool, context, warnings, suggestions) {
145
+ const params = tool.parameters;
146
+ // Check for overly broad patterns
147
+ if (params.pattern && this.isOverlyBroadPattern(params.pattern)) {
148
+ warnings.push({
149
+ code: 'SEARCH_OVERLY_BROAD',
150
+ message: `Search pattern "${params.pattern}" is overly broad`,
151
+ severity: 'medium',
152
+ suggestion: 'Use specific patterns like "**/*.ts" or add head_limit parameter'
153
+ });
154
+ }
155
+ // Suggest head_limit for broad patterns
156
+ if (params.pattern && this.isBroadPattern(params.pattern) && !params.head_limit) {
157
+ suggestions.push({
158
+ code: 'SEARCH_SUGGEST_HEAD_LIMIT',
159
+ message: 'Broad search pattern detected without head_limit',
160
+ action: 'Add head_limit parameter to prevent context overflow'
161
+ });
162
+ }
163
+ }
164
+ /**
165
+ * Validate bash commands
166
+ */
167
+ validateBashCommands(tool, context, warnings, suggestions) {
168
+ const params = tool.parameters;
169
+ if (!params.command)
170
+ return;
171
+ const flowWarnings = analyzeBashFlow(params.command);
172
+ for (const flow of flowWarnings) {
173
+ warnings.push({
174
+ code: flow.code,
175
+ message: flow.message,
176
+ severity: this.mapFlowSeverity(flow.severity),
177
+ suggestion: flow.suggestion,
178
+ });
179
+ if (flow.suggestion) {
180
+ suggestions.push({
181
+ code: flow.code,
182
+ message: flow.message,
183
+ action: flow.suggestion,
184
+ });
185
+ }
186
+ }
187
+ }
188
+ /**
189
+ * Validate AI flow patterns
190
+ */
191
+ validateAIFlowPatterns(tool, context, warnings, suggestions) {
192
+ // Check for sequential file reads
193
+ if (tool.name === 'read_file' && context.workspaceContext?.recentOperations) {
194
+ const recentReads = context.workspaceContext.recentOperations
195
+ .filter(op => op === 'read_file')
196
+ .length;
197
+ if (recentReads > 2) {
198
+ suggestions.push({
199
+ code: 'PARALLEL_READ_SUGGESTION',
200
+ message: 'Multiple sequential file reads detected',
201
+ action: 'Use parallel tool calls (e.g., read_files) for independent file reads to improve performance'
202
+ });
203
+ }
204
+ }
205
+ }
206
+ /**
207
+ * Validate performance optimizations
208
+ */
209
+ validatePerformance(tool, context, warnings, suggestions) {
210
+ // Add performance optimization suggestions
211
+ if (tool.name === 'execute_bash' && context.workspaceContext?.recentOperations) {
212
+ const recentValidations = context.workspaceContext.recentOperations
213
+ .filter(op => op.includes('validate') || op.includes('test') || op.includes('build'))
214
+ .length;
215
+ if (recentValidations > 1) {
216
+ warnings.push({
217
+ code: 'EXCESSIVE_VALIDATION',
218
+ message: 'Multiple validation operations detected',
219
+ severity: 'low',
220
+ suggestion: 'Complete ALL edits first, run ONE validation at the end only if needed'
221
+ });
222
+ }
223
+ }
224
+ }
225
+ // Helper methods
226
+ containsPlaceholderPattern(text) {
227
+ const patterns = [
228
+ /\.\.\./,
229
+ /\[.*\]/,
230
+ /\/\/.*\.\.\./,
231
+ /TODO/,
232
+ /FIXME/
233
+ ];
234
+ return patterns.some(pattern => pattern.test(text));
235
+ }
236
+ isLongSingleLine(text) {
237
+ const lines = text.split('\n');
238
+ return lines.length === 1 && text.length > 100;
239
+ }
240
+ hasIndentationMismatch(oldString, newString) {
241
+ const oldIndent = this.detectIndentation(oldString);
242
+ const newIndent = this.detectIndentation(newString);
243
+ return oldIndent !== newIndent;
244
+ }
245
+ detectIndentation(text) {
246
+ const firstLine = text.split('\n')[0] || '';
247
+ const match = firstLine.match(/^(\s+)/);
248
+ return match?.[1] ?? '';
249
+ }
250
+ isOverlyBroadPattern(pattern) {
251
+ const broadPatterns = ['.', '*', '**'];
252
+ return broadPatterns.includes(pattern);
253
+ }
254
+ isBroadPattern(pattern) {
255
+ return pattern.includes('*') && !pattern.includes('.');
256
+ }
257
+ mapFlowSeverity(severity) {
258
+ switch (severity) {
259
+ case 'critical':
260
+ return 'high';
261
+ case 'info':
262
+ return 'low';
263
+ default:
264
+ return 'medium';
265
+ }
266
+ }
267
+ /**
268
+ * Get AI flow guidance for a specific pattern
269
+ */
270
+ getAIFlowGuidance(patternId) {
271
+ return this.patterns.find(p => p.pattern === patternId);
272
+ }
273
+ /**
274
+ * Get all AI flow patterns
275
+ */
276
+ getAllAIFlowPatterns() {
277
+ return [...this.patterns];
278
+ }
279
+ }
280
+ // Global tool validator instance
281
+ export const globalToolValidator = new ToolValidator();
282
+ //# sourceMappingURL=toolValidation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toolValidation.js","sourceRoot":"","sources":["../../src/core/toolValidation.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { ProviderToolDefinition } from '../core/types.js';
2
+ export declare function buildInteractiveSystemPrompt(basePrompt: string, profileLabel: string, tools: ProviderToolDefinition[], workspaceDir?: string): string;
3
+ //# sourceMappingURL=systemPrompt.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"systemPrompt.d.ts","sourceRoot":"","sources":["../../src/shell/systemPrompt.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAE/D,wBAAgB,4BAA4B,CAC1C,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,sBAAsB,EAAE,EAC/B,YAAY,CAAC,EAAE,MAAM,GACpB,MAAM,CA8DR"}
@@ -0,0 +1,81 @@
1
+ export function buildInteractiveSystemPrompt(basePrompt, profileLabel, tools, workspaceDir) {
2
+ const name = profileLabel || 'Active Agent';
3
+ const toolSummary = formatToolSummary(tools, { maxDescriptionLength: 80 });
4
+ const workspace = workspaceDir || process.cwd();
5
+ const identityBlock = `
6
+ CRITICAL IDENTITY: You ARE ${name}, an autonomous coding agent running INSIDE the erosolar-cli tool.
7
+ You have FULL ACCESS to the workspace at: ${workspace}
8
+ You are NOT a chatbot - you are an agent with tools. When users ask you to modify code, UI, or features, you CAN and MUST do so using your tools.
9
+ The erosolar-cli IS your codebase. When users ask to change "the UI" or "this tool", they mean this workspace.
10
+ `;
11
+ const capabilityLines = [
12
+ '✓ Full file system read/write access',
13
+ '✓ Bash command execution (including git commands)',
14
+ '✓ Git operations: status, diff, add, commit, push, branch management',
15
+ '✓ Advanced code search and analysis',
16
+ '✓ Workspace snapshot is guaranteed and immutable',
17
+ '✓ Tool usage is narrated to the operator in real time',
18
+ ];
19
+ const behaviorGuidelines = [
20
+ 'AMBIGUOUS REQUESTS: If user input is vague, single-word, or could mean multiple things (e.g., "typing", "fix it", "help", "update"), ASK for clarification FIRST before doing any exploration. Do NOT guess. Example response: "I can help with that. Could you clarify what you mean by [X]? For example: [option A], [option B], or [option C]?"',
21
+ 'CLAUDE CODE PACE: Move fast in tight read/edit/test loops. After each tool result, immediately decide the next action; avoid long monologues.',
22
+ 'RAPID HYPOTHESIS TESTING: For bugs, list 2–3 likely root causes ordered by speed to check. Try the fastest, pivot quickly if evidence does not support it.',
23
+ 'SOLUTION FORKING: For complex changes, note 2–3 viable approaches, pick the simplest that can ship now, and be ready to switch if blockers appear.',
24
+ 'Keep responses CONCISE - avoid lengthy explanations, bullet lists, and markdown headers unless explicitly asked',
25
+ 'Execute continuously until complete: analyze → plan → implement → report',
26
+ 'Use README, package.json, and workspace context as evidence',
27
+ 'Read before editing; re-read after to confirm',
28
+ 'VALIDATION: Do NOT run type-check, build, test, health-check, lint, or quality-gate after each tool. Complete ALL edits first, run ONE validation at the end only if needed',
29
+ 'GIT EFFICIENCY: Do NOT run redundant git commands. Use single combined commands: "git add -A && git commit -m msg && git push" instead of separate status/add/status/commit/push calls',
30
+ 'NPM PUBLISH: For npm releases, ensure the full flow (auth, version bump, build/tests, publish, git push) using npm_publish or project-specific steps—avoid rigid command chains',
31
+ 'PYPI PUBLISH: When user says "push to pypi", "publish to pypi", "release python package", or similar, use the python_publish tool',
32
+ 'CARGO PUBLISH: When user says "push to crates.io", "publish crate", "release rust package", or similar, use the cargo_publish tool',
33
+ 'TOOL USAGE: ALWAYS use tools to complete tasks. Do NOT describe what you would do - actually DO it by calling tools. If you need to read a file, call read_file. If you need to edit, call Edit. Never output "I will..." or "Let me..." without immediately following with a tool call.',
34
+ 'FILE EDITING: ALWAYS use the Edit tool for file modifications. The Edit tool performs exact string replacements - you must provide the exact text to replace (old_string) and the replacement text (new_string). To create new files, use Edit with an empty old_string. The edit will FAIL if old_string is not unique unless replace_all is true.',
35
+ 'TYPESCRIPT ENGINEERING: Use strict TypeScript patterns - prefer interfaces over types for object shapes, use readonly for immutable data, leverage discriminated unions for complex state, and use utility types for better type safety.',
36
+ 'ERROR HANDLING: Use structured error handling with Result types for functional error handling, implement recovery strategies for common failures, and provide actionable error messages with recovery suggestions.',
37
+ 'PERFORMANCE OPTIMIZATION: Use parallel tool calls for independent operations, avoid sequential file reads when parallel execution is possible, and use targeted search patterns with head_limit to prevent context overflow.',
38
+ 'AI FLOW DESIGN: Follow the complete AI flow: analyze (read/search) → plan (describe changes) → implement (edit/write) → validate (single final check). Do not skip phases or mix them.',
39
+ 'TOOL VALIDATION: Use the tool validation system to detect anti-patterns before execution - check for Edit without Read, broad search patterns, redundant git operations, and incomplete workflows.',
40
+ ];
41
+ const behaviorSection = behaviorGuidelines
42
+ .map((line, index) => `${index + 1}. ${line}`)
43
+ .join('\n');
44
+ return `${basePrompt}
45
+ ${identityBlock}
46
+ You are ${name}, running in an interactive shell with full capabilities:
47
+
48
+ AVAILABLE TOOLS:
49
+ ${toolSummary}
50
+
51
+ CAPABILITIES:
52
+ ${capabilityLines.join('\n')}
53
+
54
+ BEHAVIOR GUIDELINES:
55
+ ${behaviorSection}
56
+
57
+ Remember: answer truthfully, ground everything in the workspace, and let the logs show what you actually did. You CAN modify this codebase.`;
58
+ }
59
+ function formatToolSummary(tools, options = {}) {
60
+ if (!tools.length) {
61
+ return '- (no tools are registered in this session)';
62
+ }
63
+ return tools
64
+ .map((tool) => {
65
+ const description = tool.description ? sanitizeWhitespace(tool.description) : 'No description provided.';
66
+ const summary = truncate(description, options.maxDescriptionLength);
67
+ return `- ${tool.name}: ${summary}`;
68
+ })
69
+ .join('\n');
70
+ }
71
+ function sanitizeWhitespace(value) {
72
+ return value.replace(/\s+/g, ' ').trim();
73
+ }
74
+ function truncate(value, maxLength) {
75
+ if (!maxLength || value.length <= maxLength) {
76
+ return value;
77
+ }
78
+ const safeLength = Math.max(0, maxLength - 3);
79
+ return `${value.slice(0, safeLength).trimEnd()}...`;
80
+ }
81
+ //# sourceMappingURL=systemPrompt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"systemPrompt.js","sourceRoot":"","sources":["../../src/shell/systemPrompt.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,4BAA4B,CAC1C,UAAkB,EAClB,YAAoB,EACpB,KAA+B,EAC/B,YAAqB;IAErB,MAAM,IAAI,GAAG,YAAY,IAAI,cAAc,CAAC;IAC5C,MAAM,WAAW,GAAG,iBAAiB,CAAC,KAAK,EAAE,EAAE,oBAAoB,EAAE,EAAE,EAAE,CAAC,CAAC;IAC3E,MAAM,SAAS,GAAG,YAAY,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IAEhD,MAAM,aAAa,GAAG;6BACK,IAAI;4CACW,SAAS;;;CAGpD,CAAC;IAEA,MAAM,eAAe,GAAG;QACtB,sCAAsC;QACtC,mDAAmD;QACnD,sEAAsE;QACtE,qCAAqC;QACrC,kDAAkD;QAClD,uDAAuD;KACxD,CAAC;IAEF,MAAM,kBAAkB,GAAG;QACzB,oVAAoV;QACpV,+IAA+I;QAC/I,4JAA4J;QAC5J,oJAAoJ;QACpJ,iHAAiH;QACjH,0EAA0E;QAC1E,6DAA6D;QAC7D,+CAA+C;QAC/C,6KAA6K;QAC7K,wLAAwL;QACxL,iLAAiL;QACjL,mIAAmI;QACnI,oIAAoI;QACpI,0RAA0R;QAC1R,qVAAqV;QACrV,0OAA0O;QAC1O,oNAAoN;QACpN,8NAA8N;QAC9N,wLAAwL;QACxL,oMAAoM;KACrM,CAAC;IAEF,MAAM,eAAe,GAAG,kBAAkB;SACvC,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,GAAG,KAAK,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC;SAC7C,IAAI,CAAC,IAAI,CAAC,CAAC;IAEd,OAAO,GAAG,UAAU;EACpB,aAAa;UACL,IAAI;;;EAGZ,WAAW;;;EAGX,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC;;;EAG1B,eAAe;;4IAE2H,CAAC;AAC7I,CAAC;AAMD,SAAS,iBAAiB,CAAC,KAA+B,EAAE,UAA8B,EAAE;IAC1F,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;QAClB,OAAO,6CAA6C,CAAC;IACvD,CAAC;IACD,OAAO,KAAK;SACT,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;QACZ,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,kBAAkB,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,0BAA0B,CAAC;QACzG,MAAM,OAAO,GAAG,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC,oBAAoB,CAAC,CAAC;QACpE,OAAO,KAAK,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;IACtC,CAAC,CAAC;SACD,IAAI,CAAC,IAAI,CAAC,CAAC;AAChB,CAAC;AAED,SAAS,kBAAkB,CAAC,KAAa;IACvC,OAAO,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;AAC3C,CAAC;AAED,SAAS,QAAQ,CAAC,KAAa,EAAE,SAAkB;IACjD,IAAI,CAAC,SAAS,IAAI,KAAK,CAAC,MAAM,IAAI,SAAS,EAAE,CAAC;QAC5C,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,SAAS,GAAG,CAAC,CAAC,CAAC;IAC9C,OAAO,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,OAAO,EAAE,KAAK,CAAC;AACtD,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { ToolDefinition } from '../core/toolRuntime.js';
2
+ export declare function createBashTools(workingDir: string): ToolDefinition[];
3
+ interface SandboxEnvOptions {
4
+ preserveHome?: boolean;
5
+ }
6
+ export declare function buildSandboxEnv(workingDir: string, options?: SandboxEnvOptions): Promise<NodeJS.ProcessEnv>;
7
+ export {};
8
+ //# sourceMappingURL=bashTools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bashTools.d.ts","sourceRoot":"","sources":["../../src/tools/bashTools.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAyF7D,wBAAgB,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,cAAc,EAAE,CA2KpE;AAED,UAAU,iBAAiB;IACzB,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,wBAAsB,eAAe,CACnC,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC,CA6B5B"}
@@ -0,0 +1,240 @@
1
+ import { exec } from 'node:child_process';
2
+ import { mkdir } from 'node:fs/promises';
3
+ import { join } from 'node:path';
4
+ import { promisify } from 'node:util';
5
+ import { createBackgroundBashTools, startBackgroundShell } from './backgroundBashTools.js';
6
+ import { validateBashCommand, SmartFixer } from '../core/errors/safetyValidator.js';
7
+ import { toStructuredError } from '../core/errors/errorTypes.js';
8
+ import { analyzeBashFlow } from '../core/bashCommandGuidance.js';
9
+ import { verifiedSuccess, verifiedFailure, analyzeOutput, OutputPatterns, createCommandCheck, } from '../core/resultVerification.js';
10
+ import { createErrorFixer } from '../core/aiErrorFixer.js';
11
+ const execAsync = promisify(exec);
12
+ // Shared error fixer instance (lazy initialized per working dir)
13
+ const errorFixerCache = new Map();
14
+ function getErrorFixer(workingDir) {
15
+ let fixer = errorFixerCache.get(workingDir);
16
+ if (!fixer) {
17
+ fixer = createErrorFixer({ workingDir });
18
+ errorFixerCache.set(workingDir, fixer);
19
+ }
20
+ return fixer;
21
+ }
22
+ const sandboxCache = new Map();
23
+ /**
24
+ * Smart timeout detection for bash commands.
25
+ * Returns appropriate timeout based on command type.
26
+ * - npm install/ci: 5 minutes
27
+ * - npm build/test: 5 minutes
28
+ * - npx create-*: 5 minutes
29
+ * - docker build/pull: 10 minutes
30
+ * - git clone: 3 minutes
31
+ * - Default: 30 seconds
32
+ */
33
+ function getSmartTimeout(command) {
34
+ const cmd = command.toLowerCase().trim();
35
+ // NPM/Yarn/PNPM package operations (5 minutes)
36
+ if (/\b(npm|yarn|pnpm)\s+(install|ci|i|add|update|upgrade)\b/.test(cmd)) {
37
+ return 300000;
38
+ }
39
+ // NPM/Yarn build and test operations (5 minutes)
40
+ if (/\b(npm|yarn|pnpm)\s+(run\s+)?(build|test|lint|start|dev)\b/.test(cmd)) {
41
+ return 300000;
42
+ }
43
+ // NPX create commands (5 minutes)
44
+ if (/\bnpx\s+(create-|degit|giget)\b/.test(cmd)) {
45
+ return 300000;
46
+ }
47
+ // Prisma operations (3 minutes)
48
+ if (/\b(prisma|npx prisma)\s+(generate|migrate|db push|db pull)\b/.test(cmd)) {
49
+ return 180000;
50
+ }
51
+ // Docker operations (10 minutes)
52
+ if (/\bdocker\s+(build|pull|push|compose)\b/.test(cmd)) {
53
+ return 600000;
54
+ }
55
+ // Git clone (3 minutes)
56
+ if (/\bgit\s+clone\b/.test(cmd)) {
57
+ return 180000;
58
+ }
59
+ // Pip install (3 minutes)
60
+ if (/\bpip\s+install\b/.test(cmd)) {
61
+ return 180000;
62
+ }
63
+ // Default timeout
64
+ return 30000;
65
+ }
66
+ export function createBashTools(workingDir) {
67
+ const backgroundTools = createBackgroundBashTools(workingDir);
68
+ return [
69
+ {
70
+ name: 'execute_bash',
71
+ description: 'Execute a bash command in the working directory. Commands auto-timeout based on type: npm/docker/git commands get extended timeouts. Exit code 0 = success, non-zero = failure. Use run_in_background: true for long-running servers/watchers. IMPORTANT: Always check command output for errors even if exit code is 0.',
72
+ parameters: {
73
+ type: 'object',
74
+ properties: {
75
+ command: {
76
+ type: 'string',
77
+ description: 'The bash command to execute (e.g., "npm test", "git status", "ls -la"). Will be validated for safety before execution.',
78
+ },
79
+ timeout: {
80
+ type: 'number',
81
+ description: 'Timeout in milliseconds. Default is smart: 30s for most commands, 5min for npm/docker, 3min for git clone. Not used when run_in_background is true.',
82
+ },
83
+ run_in_background: {
84
+ type: 'boolean',
85
+ description: 'Set to true to run this command in the background (for servers, watchers, long-running processes). Returns a shell ID that can be used with BashOutput to monitor output.',
86
+ },
87
+ },
88
+ required: ['command'],
89
+ },
90
+ handler: async (args) => {
91
+ const command = args['command'];
92
+ const runInBackground = args['run_in_background'] === true;
93
+ // Smart timeout: auto-extend for known long-running commands
94
+ const userTimeout = args['timeout'];
95
+ const timeout = userTimeout ?? getSmartTimeout(command);
96
+ // Lightweight flow guidance (publish/git) without blocking execution
97
+ const flowWarnings = analyzeBashFlow(command);
98
+ for (const warning of flowWarnings) {
99
+ const suffix = warning.suggestion ? ` — ${warning.suggestion}` : '';
100
+ console.warn(`[Bash Flow] ${warning.message}${suffix}`);
101
+ }
102
+ // Enhanced safety validation with structured errors
103
+ const validation = validateBashCommand(command);
104
+ if (!validation.valid) {
105
+ const structuredError = validation.error ? toStructuredError(validation.error) : null;
106
+ if (structuredError) {
107
+ // Return formatted error with suggestions
108
+ let errorMsg = structuredError.toDisplayString();
109
+ // Add auto-fix suggestion if available
110
+ if (validation.autoFix?.available) {
111
+ const { fixed, changes } = SmartFixer.fixDangerousCommand(command);
112
+ if (changes.length > 0) {
113
+ errorMsg += '\n\nAuto-fix available:';
114
+ for (const change of changes) {
115
+ errorMsg += `\n - ${change}`;
116
+ }
117
+ errorMsg += `\n\nFixed command: ${fixed}`;
118
+ }
119
+ }
120
+ return errorMsg;
121
+ }
122
+ return 'Error: Command validation failed';
123
+ }
124
+ // Log warnings if any
125
+ if (validation.warnings.length > 0) {
126
+ for (const warning of validation.warnings) {
127
+ console.warn(`[Bash Safety] ${warning}`);
128
+ }
129
+ }
130
+ // Handle background execution
131
+ if (runInBackground) {
132
+ const shellId = startBackgroundShell(command, workingDir);
133
+ return `Background shell started: ${shellId}\n\nUse BashOutput with bash_id="${shellId}" to monitor output.\nUse KillShell with shell_id="${shellId}" to terminate.`;
134
+ }
135
+ // Handle foreground execution
136
+ const startTime = Date.now();
137
+ try {
138
+ const env = await buildSandboxEnv(workingDir);
139
+ const { stdout, stderr } = await execAsync(command, {
140
+ cwd: workingDir,
141
+ timeout,
142
+ maxBuffer: 1024 * 1024 * 10, // 10MB
143
+ env,
144
+ });
145
+ const durationMs = Date.now() - startTime;
146
+ const combinedOutput = [stdout, stderr].filter(Boolean).join('\n');
147
+ // Select appropriate patterns based on command type
148
+ const commandLower = command.toLowerCase().trim();
149
+ let patterns = OutputPatterns.command;
150
+ if (commandLower.startsWith('git ') || commandLower === 'git') {
151
+ patterns = OutputPatterns.git;
152
+ }
153
+ else if (commandLower.startsWith('npm ') || commandLower.startsWith('npx ')) {
154
+ patterns = OutputPatterns.npm;
155
+ }
156
+ // Analyze the output to determine actual success
157
+ const analysis = analyzeOutput(combinedOutput, patterns, 0);
158
+ const commandCheck = createCommandCheck('Command execution', 0, combinedOutput);
159
+ // Check for explicit failure patterns in output despite exit code 0
160
+ // Some commands exit 0 but print errors (e.g., "error:" in output)
161
+ if (analysis.isFailure) {
162
+ return verifiedFailure(`Command completed with exit code 0 but output indicates failure`, `Command: ${command}\n\nOutput:\n${combinedOutput || '(no output)'}`, ['Review the error message in the output', 'Fix the underlying issue and retry'], [commandCheck, { check: 'Output analysis', passed: false, details: `Failure pattern matched: ${analysis.matchedPattern}` }], durationMs);
163
+ }
164
+ // Exit code 0 + no failure patterns = success
165
+ // This is how Unix commands work - exit code 0 means success
166
+ // We don't require explicit "success" words in output
167
+ return verifiedSuccess(combinedOutput.trim() ? `Command executed successfully` : `Command executed successfully (no output)`, `Command: ${command}${combinedOutput.trim() ? `\n\nOutput:\n${combinedOutput}` : ''}`, [commandCheck, ...(analysis.isSuccess ? [{ check: 'Output analysis', passed: true, details: `Success pattern matched` }] : [])], durationMs);
168
+ }
169
+ catch (error) {
170
+ const durationMs = Date.now() - startTime;
171
+ const exitCode = error.code ?? 1;
172
+ const combinedError = [error.stdout, error.stderr, error.message].filter(Boolean).join('\n');
173
+ if (error.killed) {
174
+ return verifiedFailure(`Command timed out after ${timeout}ms`, `Command: ${command}\n\nThe command was killed after exceeding the timeout.\nPartial output:\n${combinedError || '(none)'}`, ['Increase timeout if command legitimately needs more time', 'Check if command is hanging on input'], [{ check: 'Timeout', passed: false, details: `Exceeded ${timeout}ms` }], durationMs);
175
+ }
176
+ // AI Error Analysis - automatically analyze failures
177
+ const errorFixer = getErrorFixer(workingDir);
178
+ const aiErrors = errorFixer.analyzeOutput(combinedError, command);
179
+ const aiGuidance = aiErrors.length > 0 ? errorFixer.formatForAI(aiErrors) : '';
180
+ // Build suggestions with AI help
181
+ const suggestions = ['Review the error message', 'Fix the issue and retry the command'];
182
+ const firstError = aiErrors[0];
183
+ if (firstError && firstError.suggestedFixes.length > 0) {
184
+ const bestFix = firstError.suggestedFixes[0];
185
+ if (bestFix) {
186
+ suggestions.unshift(`AI Suggestion: ${bestFix.description}`);
187
+ }
188
+ }
189
+ return verifiedFailure(`Command failed with exit code ${exitCode}`, `Command: ${command}\n\nError output:\n${combinedError || '(none)'}${aiGuidance}`, suggestions, [createCommandCheck('Command execution', exitCode, combinedError)], durationMs);
190
+ }
191
+ },
192
+ },
193
+ ...backgroundTools,
194
+ ];
195
+ }
196
+ export async function buildSandboxEnv(workingDir, options) {
197
+ const envPreference = process.env['EROSOLAR_PRESERVE_HOME'];
198
+ const preserveHome = envPreference === '1'
199
+ ? true
200
+ : envPreference === '0'
201
+ ? false
202
+ : Boolean(options?.preserveHome);
203
+ const paths = await ensureSandboxPaths(workingDir);
204
+ const env = {
205
+ ...process.env,
206
+ EROSOLAR_SANDBOX_ROOT: paths.root,
207
+ EROSOLAR_SANDBOX_HOME: paths.home,
208
+ EROSOLAR_SANDBOX_TMP: paths.tmp,
209
+ };
210
+ if (!preserveHome) {
211
+ env['HOME'] = paths.home;
212
+ }
213
+ env['XDG_CACHE_HOME'] = paths.cache;
214
+ env['XDG_CONFIG_HOME'] = paths.config;
215
+ env['XDG_DATA_HOME'] = paths.data;
216
+ env['TMPDIR'] = paths.tmp;
217
+ env['TMP'] = paths.tmp;
218
+ env['TEMP'] = paths.tmp;
219
+ return env;
220
+ }
221
+ async function ensureSandboxPaths(workingDir) {
222
+ const key = workingDir;
223
+ let pending = sandboxCache.get(key);
224
+ if (!pending) {
225
+ pending = createSandboxPaths(workingDir);
226
+ sandboxCache.set(key, pending);
227
+ }
228
+ return pending;
229
+ }
230
+ async function createSandboxPaths(workingDir) {
231
+ const root = join(workingDir, '.erosolar', 'shell-sandbox');
232
+ const home = join(root, 'home');
233
+ const cache = join(root, 'cache');
234
+ const config = join(root, 'config');
235
+ const data = join(root, 'data');
236
+ const tmp = join(root, 'tmp');
237
+ await Promise.all([home, cache, config, data, tmp].map((dir) => mkdir(dir, { recursive: true })));
238
+ return { root, home, cache, config, data, tmp };
239
+ }
240
+ //# sourceMappingURL=bashTools.js.map