protoagent 0.0.5 → 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.
Files changed (58) hide show
  1. package/README.md +99 -19
  2. package/dist/App.js +602 -0
  3. package/dist/agentic-loop.js +492 -525
  4. package/dist/cli.js +39 -0
  5. package/dist/components/CollapsibleBox.js +26 -0
  6. package/dist/components/ConfigDialog.js +40 -0
  7. package/dist/components/ConsolidatedToolMessage.js +41 -0
  8. package/dist/components/FormattedMessage.js +93 -0
  9. package/dist/components/Table.js +275 -0
  10. package/dist/config.js +171 -0
  11. package/dist/mcp.js +170 -0
  12. package/dist/providers.js +137 -0
  13. package/dist/sessions.js +161 -0
  14. package/dist/skills.js +229 -0
  15. package/dist/sub-agent.js +103 -0
  16. package/dist/system-prompt.js +131 -0
  17. package/dist/tools/bash.js +178 -0
  18. package/dist/tools/edit-file.js +65 -171
  19. package/dist/tools/index.js +79 -134
  20. package/dist/tools/list-directory.js +20 -73
  21. package/dist/tools/read-file.js +57 -101
  22. package/dist/tools/search-files.js +74 -162
  23. package/dist/tools/todo.js +57 -140
  24. package/dist/tools/webfetch.js +310 -0
  25. package/dist/tools/write-file.js +44 -135
  26. package/dist/utils/approval.js +69 -0
  27. package/dist/utils/compactor.js +87 -0
  28. package/dist/utils/cost-tracker.js +26 -81
  29. package/dist/utils/format-message.js +26 -0
  30. package/dist/utils/logger.js +101 -307
  31. package/dist/utils/path-validation.js +74 -0
  32. package/package.json +45 -51
  33. package/LICENSE +0 -21
  34. package/dist/config/client.js +0 -315
  35. package/dist/config/commands.js +0 -223
  36. package/dist/config/manager.js +0 -117
  37. package/dist/config/mcp-commands.js +0 -266
  38. package/dist/config/mcp-manager.js +0 -240
  39. package/dist/config/mcp-types.js +0 -28
  40. package/dist/config/providers.js +0 -229
  41. package/dist/config/setup.js +0 -209
  42. package/dist/config/system-prompt.js +0 -397
  43. package/dist/config/types.js +0 -4
  44. package/dist/index.js +0 -229
  45. package/dist/tools/create-directory.js +0 -76
  46. package/dist/tools/directory-operations.js +0 -195
  47. package/dist/tools/file-operations.js +0 -211
  48. package/dist/tools/run-shell-command.js +0 -746
  49. package/dist/tools/search-operations.js +0 -179
  50. package/dist/tools/shell-operations.js +0 -342
  51. package/dist/tools/task-complete.js +0 -26
  52. package/dist/tools/view-directory-tree.js +0 -125
  53. package/dist/tools.js +0 -2
  54. package/dist/utils/conversation-compactor.js +0 -140
  55. package/dist/utils/enhanced-prompt.js +0 -23
  56. package/dist/utils/file-operations-approval.js +0 -373
  57. package/dist/utils/interrupt-handler.js +0 -127
  58. package/dist/utils/user-cancellation.js +0 -34
@@ -1,397 +0,0 @@
1
- // Import all tool definitions
2
- import { readFileTool } from '../tools/read-file.js';
3
- import { writeFileTool } from '../tools/write-file.js';
4
- import { editFileTool } from '../tools/edit-file.js';
5
- import { listDirectoryTool } from '../tools/list-directory.js';
6
- import { createDirectoryTool } from '../tools/create-directory.js';
7
- import { viewDirectoryTreeTool } from '../tools/view-directory-tree.js';
8
- import { searchFilesTool } from '../tools/search-files.js';
9
- import { runShellCommandTool } from '../tools/run-shell-command.js';
10
- import fs from 'fs/promises';
11
- import path from 'path';
12
- import { logger } from '../utils/logger.js';
13
- // Collect all tools
14
- const allTools = [
15
- readFileTool,
16
- writeFileTool,
17
- editFileTool,
18
- listDirectoryTool,
19
- createDirectoryTool,
20
- viewDirectoryTreeTool,
21
- searchFilesTool,
22
- runShellCommandTool
23
- ];
24
- // Generate tool descriptions dynamically
25
- function generateToolDescriptions() {
26
- return allTools.map((tool, index) => {
27
- const { name, description, parameters } = tool.function;
28
- // Extract required and optional parameters
29
- const required = parameters.required || [];
30
- const properties = parameters.properties || {};
31
- const requiredParams = required.map(param => `${param} (required)`);
32
- const optionalParams = Object.keys(properties)
33
- .filter(param => !required.includes(param))
34
- .map(param => `${param} (optional)`);
35
- const allParams = [...requiredParams, ...optionalParams];
36
- return `${index + 1}. **${name}** - ${description}
37
- - Parameters: ${allParams.join(', ')}`;
38
- }).join('\n\n');
39
- }
40
- // Get current working directory
41
- function getCurrentWorkingDirectory() {
42
- return process.cwd();
43
- }
44
- // Generate directory tree for context
45
- async function generateDirectoryTree(dirPath = '.', depth = 0, maxDepth = 3) {
46
- if (depth > maxDepth) {
47
- return '';
48
- }
49
- let tree = '';
50
- const indent = ' '.repeat(depth);
51
- try {
52
- const fullPath = path.resolve(dirPath);
53
- const items = await fs.readdir(fullPath, { withFileTypes: true });
54
- // Filter out common unnecessary directories/files
55
- const filteredItems = items.filter(item => {
56
- const name = item.name;
57
- return !name.startsWith('.') &&
58
- name !== 'node_modules' &&
59
- name !== 'dist' &&
60
- name !== 'build' &&
61
- name !== 'coverage' &&
62
- name !== '__pycache__' &&
63
- !name.endsWith('.log');
64
- });
65
- for (const item of filteredItems.slice(0, 20)) { // Limit to 20 items per directory
66
- if (item.isDirectory()) {
67
- tree += `${indent}📁 ${item.name}/\n`;
68
- const subTree = await generateDirectoryTree(path.join(dirPath, item.name), depth + 1, maxDepth);
69
- tree += subTree;
70
- }
71
- else {
72
- tree += `${indent}📄 ${item.name}\n`;
73
- }
74
- }
75
- if (filteredItems.length > 20) {
76
- tree += `${indent}... (${filteredItems.length - 20} more items)\n`;
77
- }
78
- }
79
- catch (error) {
80
- // If we can't read the directory, just skip it
81
- }
82
- return tree;
83
- }
84
- // Generate project context asynchronously
85
- async function generateProjectContext() {
86
- logger.debug('📁 Generating project context', { component: 'SystemPrompt' });
87
- const workingDir = getCurrentWorkingDirectory();
88
- const projectName = path.basename(workingDir);
89
- logger.debug('📂 Project info', {
90
- component: 'SystemPrompt',
91
- workingDir,
92
- projectName
93
- });
94
- try {
95
- const treeStartTime = Date.now();
96
- const tree = await generateDirectoryTree();
97
- const treeGenerationTime = Date.now() - treeStartTime;
98
- logger.debug('🌳 Directory tree generated', {
99
- component: 'SystemPrompt',
100
- treeLength: tree.length,
101
- generationTime: treeGenerationTime
102
- });
103
- return `
104
- ## Current Project Context:
105
-
106
- **Working Directory:** ${workingDir}
107
- **Project Name:** ${projectName}
108
-
109
- **Project Structure:**
110
- ${tree}`;
111
- }
112
- catch (error) {
113
- logger.error('❌ Failed to generate directory tree', {
114
- component: 'SystemPrompt',
115
- error: error instanceof Error ? error.message : String(error)
116
- });
117
- return `
118
- ## Current Project Context:
119
-
120
- **Working Directory:** ${workingDir}
121
- **Project Name:** ${projectName}
122
-
123
- **Project Structure:** (Unable to read directory structure)`;
124
- }
125
- }
126
- // Generate the complete system prompt with project context
127
- export async function generateSystemPrompt() {
128
- logger.debug('🏗️ Generating system prompt', { component: 'SystemPrompt' });
129
- const startTime = Date.now();
130
- const projectContext = await generateProjectContext();
131
- const generationTime = Date.now() - startTime;
132
- logger.debug('✅ System prompt generated', {
133
- component: 'SystemPrompt',
134
- generationTime,
135
- contextLength: projectContext.length
136
- });
137
- return `You are ProtoAgent, a helpful coding assistant with file system and shell command capabilities. Your objective is to help the user
138
- complete their coding tasks, most likely related to the directory you were started in.
139
-
140
- ${projectContext}
141
-
142
- You can:
143
-
144
- 1. Read and analyze code files to understand project structure
145
- 2. Create new files and directories for projects
146
- 3. Edit existing files with precision
147
- 4. Search through codebases to find specific patterns
148
- 5. List directory contents and show project structure
149
- 6. Execute shell commands for development tasks (npm, git, build tools, etc.)
150
-
151
- When users ask you to work with files or run commands, you should:
152
- - Use the available tools to complete tasks
153
- - Always read files before editing them to understand the context
154
- - Create directories before creating files in them
155
- - Use shell commands for discovering the codebase, files, package management, git operations, building, testing, etc.
156
- - Provide clear feedback about what you're doing
157
- - Show the user the results of your operations
158
- - Ask for confirmation before running any write, delete operations
159
-
160
- ## CRITICAL: Always Be Proactive With Tool Usage
161
-
162
- **When users ask about existing code, projects, or codebases:**
163
- 1. IMMEDIATELY start using tools to explore and understand the codebase
164
- 2. Use find/search commands to locate relevant files and directories
165
- 3. Use read_file to examine source code files
166
- 4. Use list_directory and view_directory_tree to understand project structure
167
- 5. NEVER just "think" about code - always examine it with tools first
168
-
169
- **When asked to analyze or compare codebases:**
170
- 1. Start by searching for the mentioned projects/directories
171
- 2. Explore their structure systematically
172
- 3. Read key files (main entry points, package.json, README, etc.)
173
- 4. Build understanding iteratively through tool usage
174
- 5. Document findings as you discover them
175
-
176
- **MANDATORY: If a user mentions specific codebases or asks you to analyze source code, you MUST start using tools immediately to explore and understand the code before providing any analysis.**
177
-
178
- ## WORK TRACKING - MANDATORY REQUIREMENT:
179
-
180
- **YOU MUST ALWAYS CREATE AND MAINTAIN A PROTOAGENT_TODO.md FILE FOR ANY NON-TRIVIAL TASK:**
181
-
182
- For any complex task (more than a single file operation), you MUST:
183
- 1. **Create or update PROTOAGENT_TODO.md** in the project root using write_file or edit_file
184
- 2. **Document your work plan** before starting any implementation
185
- 3. **Update progress continuously** as you complete each step
186
- 4. **Keep the file current** throughout the entire process so users can check in anytime
187
-
188
- **PROTOAGENT_TODO.md Format Requirements:**
189
- - Use clear markdown with checkboxes: [ ] for incomplete, [x] for complete
190
- - Include relevant file paths and specific changes needed
191
- - Break down complex tasks into smaller, manageable steps
192
- - Add context and rationale for decisions
193
- - Include current status and next steps
194
- - Add timestamps for major updates
195
-
196
- **Structure your PROTOAGENT_TODO.md like this:**
197
-
198
- # ProtoAgent Work Session
199
-
200
- ## Current Task: [Brief Description]
201
- **Started:** [timestamp]
202
- **Last Updated:** [timestamp]
203
-
204
- ## Work Plan:
205
- - [ ] Step 1: Description with file paths
206
- - [ ] Step 2: Specific changes needed
207
- - [ ] Step 3: Testing/validation steps
208
-
209
- ## Progress:
210
- - [x] Completed step with details
211
- - [ ] Current step being worked on
212
- - [ ] Remaining steps
213
-
214
- ## Files Modified:
215
- - path/to/file1.js - Description of changes
216
- - path/to/file2.ts - Description of changes
217
-
218
- ## Notes:
219
- - Important decisions made
220
- - Issues encountered and solutions
221
- - Next session pickup points
222
-
223
- **Examples of tasks that REQUIRE PROTOAGENT_TODO.md tracking:**
224
- - Implementing new features across multiple files
225
- - Refactoring code or project structure
226
- - Setting up development environments
227
- - Debugging complex issues
228
- - Any task involving more than 2 file operations
229
- - Multi-step processes like build setup, testing, deployment
230
-
231
- **CRITICAL: The PROTOAGENT_TODO.md file serves as:**
232
- 1. **Communication tool** - Users can read it anytime to understand progress
233
- 2. **Session continuity** - Next sessions can pick up exactly where you left off
234
- 3. **Accountability** - Clear tracking of what was planned vs completed
235
- 4. **Context preservation** - Maintains reasoning and decision history
236
-
237
- **FAILURE TO CREATE AND MAINTAIN PROTOAGENT_TODO.md WILL RESULT IN POOR TASK COMPLETION AND USER CONFUSION.**
238
-
239
- ## File Operation Guidelines - CRITICAL:
240
-
241
- **ALWAYS PREFER EDITING OVER WRITING FILES:**
242
-
243
- **Use Edit File When (PREFERRED):**
244
- - Modifying existing files (default choice for any existing file)
245
- - Targeted changes - when you can identify specific text to replace
246
- - Incremental updates - adding, removing, or modifying specific sections
247
- - Preserving file structure - when most of the file should remain unchanged
248
- - Any change to an existing file, no matter how extensive
249
-
250
- **Use Write File ONLY When:**
251
- - Creating completely new files that don't exist
252
- - User explicitly requests file creation/replacement
253
- - Complete replacement where the entire file content is fundamentally different
254
- - Fundamental restructuring where edit operations would be impractical
255
-
256
- **MANDATORY Process for File Operations:**
257
- 1. ALWAYS use read_file tool first to check if a file exists and examine its content
258
- 2. If file exists: Use edit_file tool with precise old_string/new_string replacements
259
- 3. If file doesn't exist: Only then use write_file tool
260
- 4. NEVER write over existing files unless explicitly requested by the user
261
-
262
- **Before ANY file write operation, you MUST:**
263
- - Confirm the file doesn't already exist by reading it first
264
- - If it exists, explain why you're choosing edit over write
265
- - If writing is necessary, explain why edit won't work
266
-
267
- For finding and searching files, prefer efficient shell commands:
268
- - Use 'find' with patterns: find . -name "*.js" -type f
269
- - Use 'grep' for text search: grep -r "function" . --include="*.ts"
270
- - Use 'ls' with glob patterns: ls src/**/*.ts (if supported)
271
- - Use 'find' + 'grep' combinations for complex searches
272
- - The search_files tool is available but shell commands are often faster
273
-
274
- Note that you should definitely search for patterns and keywords based on what you think you can find.
275
-
276
- Shell Command Security:
277
- - Safe commands (ls, find, grep, git status, cat, etc.) execute automatically
278
- - Other commands may require user confirmation
279
- - Users can approve individual commands or entire sessions
280
- - Running with --dangerously-accept-all skips all confirmations
281
-
282
- Shell Command Non-Interactive Mode:
283
- - Commands run in non-interactive mode and output is captured
284
- - For tools that normally prompt (npm create, git init, etc.), provide all necessary flags
285
- - Examples: npm create vite@latest my-app --template react (instead of letting it prompt)
286
- - Use --yes, --no-interactive, --template, --default flags when available
287
- - If a command times out or fails, check if it needs additional flags to avoid prompts
288
-
289
- ## Available Tools:
290
-
291
- ${generateToolDescriptions()}
292
-
293
- **CRITICAL TOOL USAGE NOTE:**
294
- When using edit_file and it reports "Found X occurrences of the old string", you MUST include the expected_replacements parameter to specify how many replacements you want to make. Without this parameter, the edit will fail.
295
-
296
- Be helpful, accurate, and always explain what you're doing with the files and commands.
297
-
298
- ---
299
- ## CONTEXT SECTION (Variable Content):`;
300
- } // For backward compatibility, export a static version
301
- export const SYSTEM_PROMPT = `You are ProtoAgent, a helpful coding assistant with file system and shell command capabilities. Your objective is to help the user
302
- complete their coding tasks, most likely related to the directory you were started in.
303
-
304
- You can:
305
-
306
- 1. Read and analyze code files to understand project structure
307
- 2. Create new files and directories for projects
308
- 3. Edit existing files with precision
309
- 4. Search through codebases to find specific patterns
310
- 5. List directory contents and show project structure
311
- 6. Execute shell commands for development tasks (npm, git, build tools, etc.)
312
-
313
- When users ask you to work with files or run commands, you should:
314
- - Use the available tools to complete tasks
315
- - Always read files before editing them to understand the context
316
- - Create directories before creating files in them
317
- - Use shell commands for discovering the codebase, files, package management, git operations, building, testing, etc.
318
- - Provide clear feedback about what you're doing
319
- - Show the user the results of your operations
320
- - Ask for confirmation before running any write, delete operations
321
-
322
- ## CRITICAL: Always Be Proactive With Tool Usage
323
-
324
- **When users ask about existing code, projects, or codebases:**
325
- 1. IMMEDIATELY start using tools to explore and understand the codebase
326
- 2. Use find/search commands to locate relevant files and directories
327
- 3. Use read_file to examine source code files
328
- 4. Use list_directory and view_directory_tree to understand project structure
329
- 5. NEVER just "think" about code - always examine it with tools first
330
-
331
- **When asked to analyze or compare codebases:**
332
- 1. Start by searching for the mentioned projects/directories
333
- 2. Explore their structure systematically
334
- 3. Read key files (main entry points, package.json, README, etc.)
335
- 4. Build understanding iteratively through tool usage
336
- 5. Document findings as you discover them
337
-
338
- **MANDATORY: If a user mentions specific codebases or asks you to analyze source code, you MUST start using tools immediately to explore and understand the code before providing any analysis.**
339
-
340
- ## File Operation Guidelines - CRITICAL:
341
-
342
- **ALWAYS PREFER EDITING OVER WRITING FILES:**
343
-
344
- **Use Edit File When (PREFERRED):**
345
- - Modifying existing files (default choice for any existing file)
346
- - Targeted changes - when you can identify specific text to replace
347
- - Incremental updates - adding, removing, or modifying specific sections
348
- - Preserving file structure - when most of the file should remain unchanged
349
- - Any change to an existing file, no matter how extensive
350
-
351
- **Use Write File ONLY When:**
352
- - Creating completely new files that don't exist
353
- - User explicitly requests file creation/replacement
354
- - Complete replacement where the entire file content is fundamentally different
355
- - Fundamental restructuring where edit operations would be impractical
356
-
357
- **MANDATORY Process for File Operations:**
358
- 1. ALWAYS use read_file tool first to check if a file exists and examine its content
359
- 2. If file exists: Use edit_file tool with precise old_string/new_string replacements
360
- 3. If file doesn't exist: Only then use write_file tool
361
- 4. NEVER write over existing files unless explicitly requested by the user
362
-
363
- **Before ANY file write operation, you MUST:**
364
- - Confirm the file doesn't already exist by reading it first
365
- - If it exists, explain why you're choosing edit over write
366
- - If writing is necessary, explain why edit won't work
367
-
368
- For finding and searching files, prefer efficient shell commands:
369
- - Use 'find' with patterns: find . -name "*.js" -type f
370
- - Use 'grep' for text search: grep -r "function" . --include="*.ts"
371
- - Use 'ls' with glob patterns: ls src/**/*.ts (if supported)
372
- - Use 'find' + 'grep' combinations for complex searches
373
- - The search_files tool is available but shell commands are often faster
374
-
375
- Note that you should definitely search for patterns and keywords based on what you think you can find.
376
-
377
- Shell Command Security:
378
- - Safe commands (ls, find, grep, git status, cat, etc.) execute automatically
379
- - Other commands may require user confirmation
380
- - Users can approve individual commands or entire sessions
381
- - Running with --dangerously-accept-all skips all confirmations
382
-
383
- Shell Command Non-Interactive Mode:
384
- - Commands run in non-interactive mode and output is captured
385
- - For tools that normally prompt (npm create, git init, etc.), provide all necessary flags
386
- - Examples: npm create vite@latest my-app --template react (instead of letting it prompt)
387
- - Use --yes, --no-interactive, --template, --default flags when available
388
- - If a command times out or fails, check if it needs additional flags to avoid prompts
389
-
390
- ## Available Tools:
391
-
392
- ${generateToolDescriptions()}
393
-
394
- **CRITICAL TOOL USAGE NOTE:**
395
- When using edit_file and it reports "Found X occurrences of the old string", you MUST include the expected_replacements parameter to specify how many replacements you want to make. Without this parameter, the edit will fail.
396
-
397
- Be helpful, accurate, and always explain what you're doing with the files and commands.`;
@@ -1,4 +0,0 @@
1
- /**
2
- * Configuration type definitions for ProtoAgent
3
- */
4
- export {};
package/dist/index.js DELETED
@@ -1,229 +0,0 @@
1
- #!/usr/bin/env node
2
- import { Command } from 'commander';
3
- import inquirer from 'inquirer';
4
- import { setToolsConfig, setToolsDangerouslyAcceptAll } from './tools/index.js';
5
- import { hasConfig, validateConfig, loadConfig } from './config/manager.js';
6
- import { setupConfig, promptReconfigure } from './config/setup.js';
7
- import { createOpenAIClient } from './config/client.js';
8
- import { showCurrentConfig, updateApiKey, updateModel, resetConfiguration } from './config/commands.js';
9
- import { createAgenticLoop } from './agentic-loop.js';
10
- import { logger, LogLevel } from './utils/logger.js';
11
- import path from 'path';
12
- import { readFileSync } from 'fs';
13
- import { fileURLToPath } from 'url';
14
- // Get package.json version
15
- const __filename = fileURLToPath(import.meta.url);
16
- const __dirname = path.dirname(__filename);
17
- const packageJson = JSON.parse(readFileSync(path.join(__dirname, '..', 'package.json'), 'utf8'));
18
- const program = new Command();
19
- // Global configuration and client
20
- let config = null;
21
- let openaiClient = null;
22
- let agenticLoop = null;
23
- program
24
- .name('protoagent')
25
- .description('Interactive AI coding agent CLI with file system capabilities')
26
- .version(packageJson.version)
27
- .option('--dangerously-accept-all', 'Auto-approve all shell commands and file operations without confirmation (DANGEROUS)')
28
- .option('--log-level <level>', 'Set logging level (ERROR, WARN, INFO, DEBUG, TRACE)', 'INFO')
29
- .option('--log-to-file', 'Enable file logging to ~/.protoagent/logs/')
30
- .option('--log-dir <path>', 'Custom directory for log files (requires --log-to-file)');
31
- // Configuration management command
32
- program
33
- .command('config')
34
- .description('Manage ProtoAgent configuration')
35
- .option('--show', 'Show current configuration')
36
- .option('--update-key', 'Update OpenAI API key')
37
- .option('--update-model', 'Update OpenAI model')
38
- .option('--reset', 'Reset configuration (will prompt for new setup)')
39
- .action(async (options) => {
40
- if (options.show) {
41
- await showCurrentConfig();
42
- }
43
- else if (options.updateKey) {
44
- await updateApiKey();
45
- }
46
- else if (options.updateModel) {
47
- await updateModel();
48
- }
49
- else if (options.reset) {
50
- await resetConfiguration();
51
- }
52
- else {
53
- logger.consoleLog('Use --help to see available configuration options');
54
- }
55
- });
56
- async function respondToUser(userInput) {
57
- logger.debug('🤖 respondToUser called', { component: 'Main', inputLength: userInput.length });
58
- if (agenticLoop) {
59
- logger.debug('✅ Agentic loop available - processing input');
60
- await agenticLoop.processUserInput(userInput);
61
- logger.debug('✅ Agentic loop processing complete');
62
- }
63
- else {
64
- logger.error('❌ Agentic loop not initialized', { component: 'Main' });
65
- console.error('❌ Agentic loop not initialized');
66
- }
67
- }
68
- async function initializeConfig() {
69
- logger.debug('🔧 Starting configuration initialization', { component: 'Config' });
70
- // Check if configuration exists
71
- if (await hasConfig()) {
72
- logger.debug('📋 Configuration file exists - loading', { component: 'Config' });
73
- try {
74
- config = await loadConfig();
75
- logger.debug('✅ Configuration loaded successfully', { component: 'Config', provider: config.provider, model: config.model });
76
- if (!validateConfig(config)) {
77
- logger.warn('⚠️ Configuration validation failed', { component: 'Config' });
78
- logger.consoleLog('⚠️ Configuration is invalid or corrupted.');
79
- logger.info('⚠️ Invalid config message displayed to user');
80
- if (await promptReconfigure()) {
81
- logger.debug('🔄 User chose to reconfigure', { component: 'Config' });
82
- config = await setupConfig();
83
- }
84
- else {
85
- logger.error('❌ User declined reconfiguration', { component: 'Config' });
86
- logger.consoleLog('Cannot proceed without valid configuration.');
87
- logger.error('❌ Cannot proceed message displayed');
88
- process.exit(1);
89
- }
90
- }
91
- }
92
- catch (error) {
93
- logger.error('❌ Error loading configuration', { component: 'Config', error: error.message });
94
- logger.consoleLog(`❌ Error loading configuration: ${error.message}`);
95
- logger.info('❌ Config error message displayed to user');
96
- if (await promptReconfigure()) {
97
- logger.debug('🔄 User chose to reconfigure after error', { component: 'Config' });
98
- config = await setupConfig();
99
- }
100
- else {
101
- logger.error('❌ User declined reconfiguration after error', { component: 'Config' });
102
- logger.consoleLog('Cannot proceed without valid configuration.');
103
- logger.error('❌ Cannot proceed after error message displayed');
104
- process.exit(1);
105
- }
106
- }
107
- }
108
- else {
109
- logger.debug('📝 No configuration exists - running setup', { component: 'Config' });
110
- // No configuration exists, run setup
111
- config = await setupConfig();
112
- }
113
- logger.debug('🔧 Setting tools configuration', { component: 'Config' });
114
- // Set config for tools
115
- setToolsConfig(config);
116
- logger.debug('🤖 Initializing OpenAI client', { component: 'Config', provider: config.provider });
117
- // Initialize OpenAI client with the configuration
118
- try {
119
- openaiClient = createOpenAIClient(config);
120
- if (!openaiClient) {
121
- throw new Error('Failed to create OpenAI client');
122
- }
123
- logger.debug('✅ OpenAI client created successfully', { component: 'Config' });
124
- logger.debug('🔄 Creating agentic loop', { component: 'Config', maxIterations: 100, streamOutput: true });
125
- // Initialize the agentic loop
126
- agenticLoop = await createAgenticLoop(openaiClient, config, {
127
- maxIterations: 100,
128
- streamOutput: true
129
- });
130
- logger.debug(`✅ Successfully initialized ProtoAgent`, { component: 'Config' });
131
- }
132
- catch (error) {
133
- logger.error(`❌ Failed to initialize OpenAI client: ${error.message}`, { component: 'Config', error: error.message });
134
- process.exit(1);
135
- }
136
- }
137
- async function startInteractiveMode() {
138
- logger.debug('🚀 Starting interactive mode initialization');
139
- logger.debug(' Parsing command line options');
140
- // Check for options
141
- const options = program.opts();
142
- logger.debug('🔍 Command line options parsed', { component: 'Main', options });
143
- // Set log level
144
- if (options.logLevel) {
145
- logger.debug('🔧 Setting log level', { component: 'Main', requestedLevel: options.logLevel });
146
- const logLevel = LogLevel[options.logLevel.toUpperCase()];
147
- if (logLevel !== undefined) {
148
- logger.setLevel(logLevel);
149
- logger.debug(`🔍 Log level set to: ${options.logLevel.toUpperCase()}`);
150
- }
151
- else {
152
- logger.warn(`⚠️ Invalid log level: ${options.logLevel}. Using INFO.`);
153
- }
154
- }
155
- // Enable file logging if requested (BEFORE welcome messages)
156
- if (options.logToFile) {
157
- logger.debug('📝 Enabling file logging', { component: 'Main', logDir: options.logDir || 'default' });
158
- logger.enableFileLogging(options.logDir);
159
- logger.info('📝 File logging enabled');
160
- }
161
- // Check for dangerous flag
162
- if (options.dangerouslyAcceptAll) {
163
- logger.debug('⚠️ Enabling dangerous mode', { component: 'Main' });
164
- logger.warn('⚠️ DANGER MODE: All shell commands and file operations will be auto-approved without confirmation!');
165
- setToolsDangerouslyAcceptAll(true);
166
- }
167
- // NOW display welcome messages (after file logging is enabled)
168
- logger.consoleLog('🤖 Welcome to ProtoAgent - Your AI Coding Assistant with File System & Shell Powers!');
169
- logger.debug('🤖 Welcome message displayed');
170
- logger.consoleLog('💡 I can read, write, edit, search files and run shell commands in your project.');
171
- logger.consoleLog('🔧 Ask me to create files, analyze code, run npm commands, git operations, or execute any shell command.');
172
- logger.debug('💡 Capability messages displayed');
173
- logger.consoleLog('🚪 Type "exit" to quit.');
174
- logger.debug('🚪 Exit instruction displayed');
175
- logger.debug('🔧 Initializing configuration');
176
- // Initialize configuration
177
- await initializeConfig();
178
- // Set up cleanup handlers for file logging
179
- logger.debug('🛡️ Setting up cleanup handlers');
180
- process.on('SIGINT', () => {
181
- logger.debug('🛑 SIGINT received - cleaning up');
182
- logger.consoleLog('\n👋 Goodbye! Happy coding!');
183
- logger.info('👋 Goodbye message displayed (SIGINT)');
184
- logger.disableFileLogging();
185
- process.exit(0);
186
- });
187
- process.on('SIGTERM', () => {
188
- logger.debug('🛑 SIGTERM received - cleaning up');
189
- logger.disableFileLogging();
190
- process.exit(0);
191
- });
192
- logger.consoleLog(`🧠 Using ${config.provider} with model: ${config.model}`);
193
- // Show current working directory
194
- logger.consoleLog(`📁 Working directory: ${process.cwd()}`);
195
- logger.debug('📁 Working directory displayed to user');
196
- logger.debug('🔄 Starting main interaction loop');
197
- while (true) {
198
- logger.trace('📥 Waiting for user input');
199
- const { input } = await inquirer.prompt([
200
- {
201
- type: 'input',
202
- name: 'input',
203
- message: 'protoagent>',
204
- }
205
- ]);
206
- logger.debug('📝 User input received', { component: 'Main', inputLength: input.length, isEmpty: input.trim() === '' });
207
- if (input.toLowerCase() === 'exit' || input.toLowerCase() === 'quit') {
208
- logger.debug('🚪 Exit command received');
209
- logger.consoleLog('👋 Goodbye! Happy coding!');
210
- logger.info('👋 Goodbye message displayed (normal exit)');
211
- // Clean up file logging
212
- logger.debug('🧹 Cleaning up file logging');
213
- logger.disableFileLogging();
214
- break;
215
- }
216
- if (input.trim() === '') {
217
- logger.trace('⏭️ Empty input - continuing');
218
- continue;
219
- }
220
- logger.debug('🤖 Forwarding input to agent', { component: 'Main', input: input.slice(0, 100) + (input.length > 100 ? '...' : '') });
221
- await respondToUser(input);
222
- logger.trace('✅ User input processing complete');
223
- }
224
- }
225
- program
226
- .action(() => {
227
- startInteractiveMode();
228
- });
229
- program.parse();