@sschepis/robodev 1.0.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.
- package/ai.mjs +8 -0
- package/package.json +48 -0
- package/src/cli/cli-interface.mjs +271 -0
- package/src/config.mjs +64 -0
- package/src/core/ai-assistant.mjs +540 -0
- package/src/core/ai-provider.mjs +579 -0
- package/src/core/history-manager.mjs +330 -0
- package/src/core/system-prompt.mjs +182 -0
- package/src/custom-tools/custom-tools-manager.mjs +310 -0
- package/src/execution/tool-executor.mjs +892 -0
- package/src/lib/README.md +114 -0
- package/src/lib/adapters/console-status-adapter.mjs +48 -0
- package/src/lib/adapters/network-llm-adapter.mjs +37 -0
- package/src/lib/index.mjs +101 -0
- package/src/lib/interfaces.d.ts +98 -0
- package/src/main.mjs +61 -0
- package/src/package/package-manager.mjs +223 -0
- package/src/quality/code-validator.mjs +126 -0
- package/src/quality/quality-evaluator.mjs +248 -0
- package/src/reasoning/reasoning-system.mjs +258 -0
- package/src/structured-dev/flow-manager.mjs +321 -0
- package/src/structured-dev/implementation-planner.mjs +223 -0
- package/src/structured-dev/manifest-manager.mjs +423 -0
- package/src/structured-dev/plan-executor.mjs +113 -0
- package/src/structured-dev/project-bootstrapper.mjs +523 -0
- package/src/tools/desktop-automation-tools.mjs +172 -0
- package/src/tools/file-tools.mjs +141 -0
- package/src/tools/tool-definitions.mjs +872 -0
- package/src/ui/console-styler.mjs +503 -0
- package/src/workspace/workspace-manager.mjs +215 -0
- package/themes.json +66 -0
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
// Native file system tools
|
|
2
|
+
// Provides safe file operations with path validation
|
|
3
|
+
|
|
4
|
+
import fs from 'fs';
|
|
5
|
+
import path from 'path';
|
|
6
|
+
import { consoleStyler } from '../ui/console-styler.mjs';
|
|
7
|
+
import { config } from '../config.mjs';
|
|
8
|
+
|
|
9
|
+
export class FileTools {
|
|
10
|
+
constructor(workspaceRoot) {
|
|
11
|
+
this.workspaceRoot = path.resolve(workspaceRoot || config.system.workspaceRoot || process.cwd());
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// Validate path is within workspace
|
|
15
|
+
validatePath(filePath) {
|
|
16
|
+
const resolvedPath = path.resolve(this.workspaceRoot, filePath);
|
|
17
|
+
|
|
18
|
+
// Check if path starts with workspace root
|
|
19
|
+
if (!resolvedPath.startsWith(this.workspaceRoot)) {
|
|
20
|
+
// Allow access to temporary files if needed, but for now strict workspace confinement
|
|
21
|
+
throw new Error(`Access denied: Path '${filePath}' is outside the workspace root.`);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return resolvedPath;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Read file content
|
|
28
|
+
async readFile(args) {
|
|
29
|
+
const { path: filePath, encoding = 'utf8' } = args;
|
|
30
|
+
|
|
31
|
+
consoleStyler.log('working', `Reading file: ${filePath}`);
|
|
32
|
+
|
|
33
|
+
try {
|
|
34
|
+
const resolvedPath = this.validatePath(filePath);
|
|
35
|
+
|
|
36
|
+
if (!fs.existsSync(resolvedPath)) {
|
|
37
|
+
throw new Error(`File not found: ${filePath}`);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const content = await fs.promises.readFile(resolvedPath, encoding);
|
|
41
|
+
consoleStyler.log('working', `✓ Read ${content.length} characters`);
|
|
42
|
+
|
|
43
|
+
return content;
|
|
44
|
+
} catch (error) {
|
|
45
|
+
consoleStyler.log('error', `Read file failed: ${error.message}`);
|
|
46
|
+
return `Error reading file: ${error.message}`;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Write content to file
|
|
51
|
+
async writeFile(args) {
|
|
52
|
+
const { path: filePath, content, encoding = 'utf8' } = args;
|
|
53
|
+
|
|
54
|
+
consoleStyler.log('working', `Writing file: ${filePath}`);
|
|
55
|
+
|
|
56
|
+
try {
|
|
57
|
+
const resolvedPath = this.validatePath(filePath);
|
|
58
|
+
|
|
59
|
+
// Ensure directory exists
|
|
60
|
+
const dirPath = path.dirname(resolvedPath);
|
|
61
|
+
if (!fs.existsSync(dirPath)) {
|
|
62
|
+
await fs.promises.mkdir(dirPath, { recursive: true });
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Check allowed extensions if configured
|
|
66
|
+
if (config.tools.allowedFileExtensions && config.tools.allowedFileExtensions.length > 0) {
|
|
67
|
+
const ext = path.extname(filePath);
|
|
68
|
+
if (!config.tools.allowedFileExtensions.includes(ext) && !config.tools.enableUnsafeTools) {
|
|
69
|
+
throw new Error(`File extension '${ext}' not allowed. Allowed: ${config.tools.allowedFileExtensions.join(', ')}`);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
await fs.promises.writeFile(resolvedPath, content, encoding);
|
|
74
|
+
consoleStyler.log('working', `✓ Wrote ${content.length} characters to ${filePath}`);
|
|
75
|
+
|
|
76
|
+
return `Successfully wrote to ${filePath}`;
|
|
77
|
+
} catch (error) {
|
|
78
|
+
consoleStyler.log('error', `Write file failed: ${error.message}`);
|
|
79
|
+
return `Error writing file: ${error.message}`;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// List files in directory
|
|
84
|
+
async listFiles(args) {
|
|
85
|
+
const { path: dirPath = '.', recursive = false } = args;
|
|
86
|
+
|
|
87
|
+
consoleStyler.log('working', `Listing files in: ${dirPath} (recursive: ${recursive})`);
|
|
88
|
+
|
|
89
|
+
try {
|
|
90
|
+
const resolvedPath = this.validatePath(dirPath);
|
|
91
|
+
|
|
92
|
+
if (!fs.existsSync(resolvedPath)) {
|
|
93
|
+
throw new Error(`Directory not found: ${dirPath}`);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const files = [];
|
|
97
|
+
const MAX_FILES = 5000;
|
|
98
|
+
const MAX_DEPTH = 10;
|
|
99
|
+
|
|
100
|
+
async function scanDir(currentPath, relativePath, depth = 0) {
|
|
101
|
+
if (depth > MAX_DEPTH) return;
|
|
102
|
+
if (files.length >= MAX_FILES) return;
|
|
103
|
+
|
|
104
|
+
const entries = await fs.promises.readdir(currentPath, { withFileTypes: true });
|
|
105
|
+
|
|
106
|
+
for (const entry of entries) {
|
|
107
|
+
if (files.length >= MAX_FILES) break;
|
|
108
|
+
|
|
109
|
+
// Skip hidden files/dirs (starting with .) except specific allowed ones if needed
|
|
110
|
+
// And explicitly skip node_modules and .git
|
|
111
|
+
if (entry.name === 'node_modules' || entry.name === '.git' || (entry.name.startsWith('.') && entry.name !== '.cursorrules' && entry.name !== '.env')) {
|
|
112
|
+
continue;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const entryRelativePath = path.join(relativePath, entry.name);
|
|
116
|
+
|
|
117
|
+
if (entry.isDirectory()) {
|
|
118
|
+
files.push(`${entryRelativePath}/`);
|
|
119
|
+
if (recursive) {
|
|
120
|
+
await scanDir(path.join(currentPath, entry.name), entryRelativePath, depth + 1);
|
|
121
|
+
}
|
|
122
|
+
} else {
|
|
123
|
+
files.push(entryRelativePath);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
await scanDir(resolvedPath, dirPath === '.' ? '' : dirPath);
|
|
129
|
+
|
|
130
|
+
if (files.length >= MAX_FILES) {
|
|
131
|
+
consoleStyler.log('warning', `⚠️ File listing truncated at ${MAX_FILES} entries`);
|
|
132
|
+
}
|
|
133
|
+
consoleStyler.log('working', `✓ Found ${files.length} files/directories`);
|
|
134
|
+
return files.join('\n');
|
|
135
|
+
|
|
136
|
+
} catch (error) {
|
|
137
|
+
consoleStyler.log('error', `List files failed: ${error.message}`);
|
|
138
|
+
return `Error listing files: ${error.message}`;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|