@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.
@@ -0,0 +1,114 @@
1
+ # AI Man Library Interface
2
+
3
+ This module exposes the core AI Assistant capabilities as a structured library, allowing integration into other AI agents, tools, or applications.
4
+
5
+ ## Overview
6
+
7
+ The `AiMan` class provides a high-level interface to the AI system. It supports:
8
+ - **Dependency Injection**: Plug in your own LLM provider and status reporting mechanisms.
9
+ - **Agent Integration**: Easily expose the system as a tool for other AI agents (e.g., LangChain, AutoGPT).
10
+ - **Callback Statusing**: Receive real-time updates on progress, tool execution, and logs.
11
+
12
+ ## Usage
13
+
14
+ ### Basic Usage
15
+
16
+ ```javascript
17
+ import { AiMan } from 'ai-assistant/lib';
18
+
19
+ // Initialize with default settings (uses internal LLM and console output)
20
+ const ai = new AiMan();
21
+
22
+ // Execute a complex task
23
+ const result = await ai.execute("Create a new feature for user authentication in the current project");
24
+
25
+ console.log(result);
26
+ ```
27
+
28
+ ### Advanced Usage with Custom Adapters
29
+
30
+ You can inject custom adapters to control how the AI communicates and reports status.
31
+
32
+ ```javascript
33
+ import { AiMan } from 'ai-assistant/lib';
34
+
35
+ // Custom LLM Adapter (must implement generateContent)
36
+ const myLLMAdapter = {
37
+ async generateContent(request) {
38
+ // request follows OpenAI Chat Completion API format
39
+ // Call your own model service here...
40
+ return {
41
+ choices: [{
42
+ message: { role: 'assistant', content: '...' }
43
+ }]
44
+ };
45
+ }
46
+ };
47
+
48
+ // Custom Status Adapter (must implement log, onProgress, etc.)
49
+ const myStatusAdapter = {
50
+ log(level, message, meta) {
51
+ // Send logs to your dashboard/frontend
52
+ socket.emit('log', { level, message, meta });
53
+ },
54
+ onProgress(percent, status) {
55
+ updateProgressBar(percent, status);
56
+ },
57
+ onToolStart(name, args) {
58
+ console.log(`Tool Started: ${name}`);
59
+ },
60
+ onToolEnd(name, result) {
61
+ console.log(`Tool Ended: ${name}`);
62
+ }
63
+ };
64
+
65
+ // Initialize with adapters
66
+ const ai = new AiMan({
67
+ workingDir: '/path/to/project',
68
+ llmAdapter: myLLMAdapter,
69
+ statusAdapter: myStatusAdapter
70
+ });
71
+
72
+ await ai.execute("Refactor the login module");
73
+ ```
74
+
75
+ ## Agent Integration
76
+
77
+ To use AI Man as a tool within another agent (e.g., a "Manager" agent delegating coding tasks), use `getToolDefinition()`:
78
+
79
+ ```javascript
80
+ const aiMan = new AiMan();
81
+ const toolDef = aiMan.getToolDefinition();
82
+
83
+ // toolDef matches standard JSON Schema for function calling:
84
+ // {
85
+ // "name": "execute_software_development_task",
86
+ // "description": "...",
87
+ // "parameters": { ... }
88
+ // }
89
+
90
+ // Register this tool with your primary agent
91
+ myAgent.registerTool(toolDef, async (args) => {
92
+ return await aiMan.execute(args.task);
93
+ });
94
+ ```
95
+
96
+ ## API Reference
97
+
98
+ ### `AiMan` Class
99
+
100
+ #### `constructor(config)`
101
+ - `config.workingDir`: Path to the project root (default: `process.cwd()`).
102
+ - `config.llmAdapter`: Object implementing `LLMAdapter` interface.
103
+ - `config.statusAdapter`: Object implementing `StatusAdapter` interface.
104
+ - `config.overrides`: Optional configuration overrides (model, etc.).
105
+
106
+ #### `async execute(task)`
107
+ Executes the given natural language task. Returns a Promise resolving to the final output string.
108
+
109
+ #### `getToolDefinition()`
110
+ Returns a JSON Schema object describing the `execute` capability, suitable for LLM function calling.
111
+
112
+ ### Interfaces
113
+
114
+ See `src/lib/interfaces.d.ts` for TypeScript definitions of `LLMAdapter` and `StatusAdapter`.
@@ -0,0 +1,48 @@
1
+ import { consoleStyler } from '../../ui/console-styler.mjs';
2
+
3
+ /**
4
+ * Status Adapter that outputs to the console using consoleStyler
5
+ * This is the default behavior if no adapter is provided
6
+ */
7
+ export class ConsoleStatusAdapter {
8
+ constructor() {}
9
+
10
+ /**
11
+ * Log a message
12
+ * @param {string} level - Log level/category
13
+ * @param {string} message - Message content
14
+ * @param {Object} [metadata] - Optional metadata
15
+ */
16
+ log(level, message, metadata = {}) {
17
+ consoleStyler.log(level, message, metadata);
18
+ }
19
+
20
+ /**
21
+ * Report progress
22
+ * @param {number} progress - 0-100
23
+ * @param {string} status - Status description
24
+ */
25
+ onProgress(progress, status) {
26
+ consoleStyler.log('progress', `[${progress}%] ${status}`);
27
+ }
28
+
29
+ /**
30
+ * Called when a tool starts
31
+ * @param {string} toolName
32
+ * @param {Object} args
33
+ */
34
+ onToolStart(toolName, args) {
35
+ // consoleStyler handles tool logging internally via logs typically,
36
+ // but we can make it explicit here
37
+ // consoleStyler.log('working', `Executing tool: ${toolName}`);
38
+ }
39
+
40
+ /**
41
+ * Called when a tool ends
42
+ * @param {string} toolName
43
+ * @param {any} result
44
+ */
45
+ onToolEnd(toolName, result) {
46
+ // consoleStyler.log('tools', `✓ Tool completed: ${toolName}`);
47
+ }
48
+ }
@@ -0,0 +1,37 @@
1
+ import { callProvider, callProviderStream } from '../../core/ai-provider.mjs';
2
+
3
+ /**
4
+ * Default LLM Adapter that uses the built-in network provider (OpenAI/Gemini/Local)
5
+ */
6
+ export class NetworkLLMAdapter {
7
+ constructor(config = {}) {
8
+ this.config = config;
9
+ }
10
+
11
+ /**
12
+ * Call the LLM provider
13
+ * @param {Object} requestBody - OpenAI compatible request
14
+ * @returns {Promise<Object>} OpenAI compatible response
15
+ */
16
+ async generateContent(requestBody) {
17
+ // Merge config overrides if any
18
+ const finalRequest = {
19
+ ...requestBody,
20
+ ...this.config
21
+ };
22
+ return await callProvider(finalRequest);
23
+ }
24
+
25
+ /**
26
+ * Stream the LLM response
27
+ * @param {Object} requestBody
28
+ * @returns {Promise<Response>} Fetch response or stream
29
+ */
30
+ async generateContentStream(requestBody) {
31
+ const finalRequest = {
32
+ ...requestBody,
33
+ ...this.config
34
+ };
35
+ return await callProviderStream(finalRequest);
36
+ }
37
+ }
@@ -0,0 +1,101 @@
1
+ import { MiniAIAssistant } from '../core/ai-assistant.mjs';
2
+ import { ConsoleStatusAdapter } from './adapters/console-status-adapter.mjs';
3
+ import { NetworkLLMAdapter } from './adapters/network-llm-adapter.mjs';
4
+ import { consoleStyler } from '../ui/console-styler.mjs';
5
+
6
+ /**
7
+ * Main entry point for the AI Man Library.
8
+ * Provides a structured interface for integrating the AI system into other agents or applications.
9
+ */
10
+ export class AiMan {
11
+ /**
12
+ * Create a new AI Man instance
13
+ * @param {Object} config - Configuration options
14
+ * @param {string} [config.workingDir] - Working directory (defaults to process.cwd())
15
+ * @param {Object} [config.llmAdapter] - Adapter for LLM calls (defaults to NetworkLLMAdapter)
16
+ * @param {Object} [config.statusAdapter] - Adapter for status/logging (defaults to ConsoleStatusAdapter)
17
+ * @param {Object} [config.overrides] - Overrides for internal components (model, temperature, etc.)
18
+ */
19
+ constructor(config = {}) {
20
+ this.workingDir = config.workingDir || process.cwd();
21
+
22
+ // Initialize adapters
23
+ this.llmAdapter = config.llmAdapter || new NetworkLLMAdapter(config.overrides || {});
24
+ this.statusAdapter = config.statusAdapter || new ConsoleStatusAdapter();
25
+
26
+ // Configure global logger redirect if a custom status adapter is provided
27
+ // This ensures that internal components using consoleStyler route logs through the adapter
28
+ if (config.statusAdapter) {
29
+ consoleStyler.setListener(this.statusAdapter);
30
+ }
31
+
32
+ // Initialize the core assistant with injected dependencies
33
+ this.assistant = new MiniAIAssistant(this.workingDir, {
34
+ llmAdapter: this.llmAdapter
35
+ });
36
+ }
37
+
38
+ /**
39
+ * Initialize the system (loads tools, manifests, etc.)
40
+ */
41
+ async initialize() {
42
+ await this.assistant.initializeCustomTools();
43
+ }
44
+
45
+ /**
46
+ * Execute a high-level task
47
+ * @param {string} task - The task description
48
+ * @returns {Promise<string>} The result of the task execution
49
+ */
50
+ async execute(task) {
51
+ // Ensure initialized
52
+ if (!this.assistant.customToolsLoaded) {
53
+ await this.initialize();
54
+ }
55
+
56
+ this.statusAdapter.onToolStart('ai_man_execute', { task });
57
+
58
+ try {
59
+ const result = await this.assistant.run(task);
60
+ this.statusAdapter.onToolEnd('ai_man_execute', result);
61
+ return result;
62
+ } catch (error) {
63
+ const errorMessage = `Execution failed: ${error.message}`;
64
+ this.statusAdapter.log('error', errorMessage);
65
+ throw error;
66
+ }
67
+ }
68
+
69
+ /**
70
+ * Get the tool definition for integrating this library as a tool in another agent
71
+ * @returns {Object} JSON Schema for the tool
72
+ */
73
+ getToolDefinition() {
74
+ return {
75
+ name: "execute_software_development_task",
76
+ description: "Execute a complex software development task using the AI Man system. Capable of planning, coding, debugging, and verifying software features.",
77
+ parameters: {
78
+ type: "object",
79
+ properties: {
80
+ task: {
81
+ type: "string",
82
+ description: "The detailed description of the task to perform. Be specific about requirements."
83
+ }
84
+ },
85
+ required: ["task"]
86
+ }
87
+ };
88
+ }
89
+
90
+ /**
91
+ * Get the current status/context of the assistant
92
+ * @returns {Object} Context object
93
+ */
94
+ getContext() {
95
+ return this.assistant.getContext();
96
+ }
97
+ }
98
+
99
+ // Re-export adapters for convenience
100
+ export { ConsoleStatusAdapter } from './adapters/console-status-adapter.mjs';
101
+ export { NetworkLLMAdapter } from './adapters/network-llm-adapter.mjs';
@@ -0,0 +1,98 @@
1
+ /**
2
+ * Interface for the AI Man Library Configuration
3
+ */
4
+ export interface AiManConfig {
5
+ /** The working directory for the project */
6
+ workingDir: string;
7
+ /** Adapter for the host LLM service */
8
+ llmAdapter?: LLMAdapter;
9
+ /** Adapter for status reporting */
10
+ statusAdapter?: StatusAdapter;
11
+ /** Optional overrides for internal components */
12
+ overrides?: {
13
+ model?: string;
14
+ temperature?: number;
15
+ };
16
+ }
17
+
18
+ /**
19
+ * Adapter interface for providing LLM capabilities
20
+ * Conforms to OpenAI-compatible request/response structure
21
+ */
22
+ export interface LLMAdapter {
23
+ /**
24
+ * call the LLM provider
25
+ * @param requestBody The standard OpenAI chat completion request body
26
+ * @returns The standard OpenAI chat completion response
27
+ */
28
+ generateContent(requestBody: any): Promise<any>;
29
+
30
+ /**
31
+ * (Optional) Stream the LLM response
32
+ * @param requestBody The standard OpenAI chat completion request body
33
+ * @returns A stream or async iterable of content chunks
34
+ */
35
+ generateContentStream?(requestBody: any): AsyncIterable<string> | Promise<ReadableStream>;
36
+ }
37
+
38
+ /**
39
+ * Adapter interface for status reporting and logging
40
+ */
41
+ export interface StatusAdapter {
42
+ /**
43
+ * Log a message from the system
44
+ * @param level The log level or category (e.g., 'info', 'error', 'step', 'thought')
45
+ * @param message The message content
46
+ * @param metadata Optional metadata
47
+ */
48
+ log(level: string, message: string, metadata?: any): void;
49
+
50
+ /**
51
+ * Report progress on a long-running operation
52
+ * @param progress 0-100 completion percentage
53
+ * @param status Current status description
54
+ */
55
+ onProgress(progress: number, status: string): void;
56
+
57
+ /**
58
+ * Called when a tool execution starts
59
+ * @param toolName Name of the tool
60
+ * @param args Tool arguments
61
+ */
62
+ onToolStart(toolName: string, args: any): void;
63
+
64
+ /**
65
+ * Called when a tool execution completes
66
+ * @param toolName Name of the tool
67
+ * @param result Tool result
68
+ */
69
+ onToolEnd(toolName: string, result: any): void;
70
+ }
71
+
72
+ /**
73
+ * The main interface for the library
74
+ */
75
+ export interface AiManInterface {
76
+ /**
77
+ * Initialize the library
78
+ */
79
+ initialize(): Promise<void>;
80
+
81
+ /**
82
+ * Execute a high-level task
83
+ * @param taskDescription The user's request
84
+ * @returns The final result or confirmation
85
+ */
86
+ executeTask(taskDescription: string): Promise<string>;
87
+
88
+ /**
89
+ * Get the current status of the project/workspace
90
+ */
91
+ getProjectStatus(): Promise<any>;
92
+
93
+ /**
94
+ * Get the tool definition for integrating this library into an agent
95
+ * @returns JSON Schema for the tool
96
+ */
97
+ getToolDefinition(): object;
98
+ }
package/src/main.mjs ADDED
@@ -0,0 +1,61 @@
1
+ // Main entry point for the AI Assistant
2
+ // Orchestrates CLI interface and AI assistant initialization
3
+
4
+ import { MiniAIAssistant } from './core/ai-assistant.mjs';
5
+ import { CLIInterface } from './cli/cli-interface.mjs';
6
+
7
+ // Main execution function
8
+ async function main() {
9
+ const cli = new CLIInterface();
10
+
11
+ try {
12
+ // Set up signal handlers for graceful shutdown
13
+ cli.setupSignalHandlers();
14
+
15
+ // Parse command line arguments
16
+ const { args, workingDir, isInteractive, userInput, resume } = cli.parseArguments();
17
+
18
+ // Display startup information
19
+ cli.displayStartupInfo(workingDir);
20
+
21
+ // Initialize AI assistant
22
+ const assistant = new MiniAIAssistant(workingDir);
23
+
24
+ // Load custom tools before starting
25
+ await assistant.initializeCustomTools();
26
+
27
+ // Resume session if requested
28
+ if (resume) {
29
+ await assistant.loadSession('.ai-session');
30
+ }
31
+
32
+ if (isInteractive) {
33
+ // Interactive mode
34
+ await cli.startInteractiveMode(assistant, workingDir);
35
+ } else {
36
+ // Single-shot mode
37
+ await cli.runSingleShot(assistant, userInput, workingDir);
38
+ }
39
+
40
+ } catch (error) {
41
+ cli.displayError(error);
42
+ process.exit(1);
43
+ } finally {
44
+ cli.close();
45
+ }
46
+ }
47
+
48
+ // Handle module execution
49
+ if (import.meta.url === `file://${process.argv[1]}`) {
50
+ main().catch(err => {
51
+ // Import consoleStyler for error display
52
+ import('./ui/console-styler.mjs').then(({ consoleStyler }) => {
53
+ consoleStyler.log('error', `An unexpected error occurred: ${err.message}`);
54
+ }).catch(() => {
55
+ console.error("\x1b[31mAn unexpected error occurred:\x1b[0m", err);
56
+ });
57
+ process.exit(1);
58
+ });
59
+ }
60
+
61
+ export { main };
@@ -0,0 +1,223 @@
1
+ // Package management utilities
2
+ // Handles npm package installation with Node.js compatibility checks
3
+
4
+ import { exec } from 'child_process';
5
+ import util from 'util';
6
+ import path from 'path';
7
+ import { fileURLToPath } from 'url';
8
+
9
+ const execPromise = util.promisify(exec);
10
+
11
+ export class PackageManager {
12
+ constructor() {
13
+ // Node.js v18 compatibility - packages with known issues
14
+ this.problematicPackages = [
15
+ 'axios', 'undici', 'node-fetch', 'cheerio', 'jsdom',
16
+ 'puppeteer', 'playwright', 'got', 'superagent', 'request'
17
+ ];
18
+
19
+ this.nodeMajorVersion = parseInt(process.version.slice(1).split('.')[0]);
20
+ }
21
+
22
+ // Install a single npm package with compatibility checks
23
+ async installPackage(packageName) {
24
+ // Node.js compatibility check - proactively avoid packages with known issues
25
+ if (this.nodeMajorVersion < 20 && this.problematicPackages.includes(packageName)) {
26
+ consoleStyler.log('system', `Skipping ${packageName} - Node.js v${this.nodeMajorVersion} compatibility issue`);
27
+ consoleStyler.log('system', 'Will use built-in alternatives (fetch for HTTP, regex for HTML parsing)');
28
+
29
+ // Throw a specific error that can be caught and handled
30
+ throw new Error(`COMPATIBILITY_SKIP: ${packageName} incompatible with Node.js v${this.nodeMajorVersion}`);
31
+ }
32
+
33
+ // Check if package might have undici dependencies in Node.js v18
34
+ if (this.nodeMajorVersion < 20 && packageName.includes('fetch')) {
35
+ consoleStyler.log('warning', `Warning: ${packageName} may have Node.js v${this.nodeMajorVersion} compatibility issues`);
36
+ throw new Error(`COMPATIBILITY_SKIP: ${packageName} may be incompatible with Node.js v${this.nodeMajorVersion}`);
37
+ }
38
+
39
+ try {
40
+ // Install in the script's directory
41
+ const __filename = fileURLToPath(import.meta.url);
42
+ const scriptDir = path.dirname(path.dirname(path.dirname(__filename))); // Go up two levels from src/package
43
+ const { stdout, stderr } = await execPromise(`cd "${scriptDir}" && npm install ${packageName}`);
44
+
45
+ if (stderr) {
46
+ // Check stderr for undici/File errors
47
+ if (stderr.includes('File is not defined') || stderr.includes('undici')) {
48
+ consoleStyler.log('system', `Node.js compatibility issue - skipping ${packageName}`);
49
+ return;
50
+ }
51
+ }
52
+ } catch (error) {
53
+ // Don't log error for compatibility skips
54
+ if (!error.message.startsWith('COMPATIBILITY_SKIP:')) {
55
+ console.error(`\x1b[31m[SYSTEM] Failed to install package '${packageName}': ${error.message}\x1b[0m`);
56
+
57
+ // Enhanced Node.js compatibility detection
58
+ if (error.message.includes('File is not defined') ||
59
+ error.message.includes('undici') ||
60
+ error.message.includes('webidl') ||
61
+ error.stdout?.includes('File is not defined') ||
62
+ error.stderr?.includes('File is not defined')) {
63
+ console.log(`\x1b[33m[SYSTEM] Node.js v${this.nodeMajorVersion} compatibility issue detected with ${packageName}\x1b[0m`);
64
+ console.log(`\x1b[33m[SYSTEM] Skipping ${packageName} - will use built-in alternatives (fetch, fs, etc.)\x1b[0m`);
65
+ throw new Error(`COMPATIBILITY_SKIP: ${packageName} incompatible with Node.js v${this.nodeMajorVersion}`);
66
+ }
67
+ }
68
+
69
+ throw error;
70
+ }
71
+ }
72
+
73
+ // Install multiple packages with error handling
74
+ async installPackages(packages) {
75
+ const skippedPackages = [];
76
+ const installedPackages = [];
77
+ const failedPackages = [];
78
+
79
+ // Helper function to handle single package installation
80
+ const processPackage = async (pkg) => {
81
+ try {
82
+ // First check if package is already available
83
+ await import(pkg);
84
+ installedPackages.push(pkg);
85
+ } catch (e) {
86
+ if (e.code === 'ERR_MODULE_NOT_FOUND') {
87
+ try {
88
+ await this.installPackage(pkg);
89
+ // Verify the package is accessible after installation
90
+ try {
91
+ await import(pkg);
92
+ installedPackages.push(pkg);
93
+ } catch (e2) {
94
+ try {
95
+ const __filename = fileURLToPath(import.meta.url);
96
+ const scriptDir = path.dirname(path.dirname(__filename));
97
+ const modulePath = `file://${path.join(scriptDir, 'node_modules', pkg)}`;
98
+ await import(modulePath);
99
+ installedPackages.push(pkg);
100
+ } catch (e3) {
101
+ // For CommonJS modules, just ensure they're installed
102
+ installedPackages.push(pkg);
103
+ }
104
+ }
105
+ } catch (installError) {
106
+ if (installError.message.startsWith('COMPATIBILITY_SKIP:')) {
107
+ skippedPackages.push(pkg);
108
+ consoleStyler.log('system', `Skipped ${pkg} - will need to use built-in alternatives`);
109
+ } else {
110
+ failedPackages.push({ package: pkg, error: installError.message });
111
+ }
112
+ }
113
+ } else {
114
+ failedPackages.push({ package: pkg, error: e.message });
115
+ }
116
+ }
117
+ };
118
+
119
+ // Process packages in parallel batches of 3 to avoid overwhelming system
120
+ const BATCH_SIZE = 3;
121
+ for (let i = 0; i < packages.length; i += BATCH_SIZE) {
122
+ const batch = packages.slice(i, i + BATCH_SIZE);
123
+ await Promise.all(batch.map(pkg => processPackage(pkg)));
124
+ }
125
+
126
+ return {
127
+ installed: installedPackages,
128
+ skipped: skippedPackages,
129
+ failed: failedPackages
130
+ };
131
+ }
132
+
133
+ // Attempt to import a package with multiple strategies
134
+ async importPackage(packageName) {
135
+ try {
136
+ // Try direct import first
137
+ return await import(packageName);
138
+ } catch (e) {
139
+ if (e.code === 'ERR_MODULE_NOT_FOUND') {
140
+ try {
141
+ // Try from script directory with file:// protocol
142
+ const __filename = fileURLToPath(import.meta.url);
143
+ const scriptDir = path.dirname(path.dirname(path.dirname(__filename)));
144
+ const modulePath = `file://${path.join(scriptDir, 'node_modules', packageName)}`;
145
+ return await import(modulePath);
146
+ } catch (e2) {
147
+ try {
148
+ // Try with require for CommonJS modules
149
+ const { createRequire } = await import('module');
150
+ const require = createRequire(import.meta.url);
151
+ return { default: require(packageName) };
152
+ } catch (e3) {
153
+ throw e; // Re-throw original error
154
+ }
155
+ }
156
+ } else {
157
+ throw e; // Re-throw other import errors
158
+ }
159
+ }
160
+ }
161
+
162
+ // Check if a package is problematic for the current Node.js version
163
+ isProblematicPackage(packageName) {
164
+ if (this.nodeMajorVersion < 20 && this.problematicPackages.includes(packageName)) {
165
+ return true;
166
+ }
167
+
168
+ if (this.nodeMajorVersion < 20 && packageName.includes('fetch')) {
169
+ return true;
170
+ }
171
+
172
+ return false;
173
+ }
174
+
175
+ // Get alternative suggestions for problematic packages
176
+ getAlternatives(packageName) {
177
+ const alternatives = {
178
+ 'axios': 'Use built-in fetch() for HTTP requests',
179
+ 'node-fetch': 'Use built-in fetch() for HTTP requests',
180
+ 'cheerio': 'Use regex patterns or built-in string methods for HTML parsing',
181
+ 'jsdom': 'Use regex patterns for simple HTML parsing',
182
+ 'puppeteer': 'Consider using simpler HTTP requests with fetch()',
183
+ 'playwright': 'Consider using simpler HTTP requests with fetch()',
184
+ 'got': 'Use built-in fetch() for HTTP requests',
185
+ 'superagent': 'Use built-in fetch() for HTTP requests',
186
+ 'request': 'Use built-in fetch() for HTTP requests (request is deprecated)'
187
+ };
188
+
189
+ return alternatives[packageName] || 'Consider using built-in Node.js modules or simpler alternatives';
190
+ }
191
+
192
+ // Log package installation results
193
+ logInstallationResults(results) {
194
+ if (results.installed.length > 0) {
195
+ consoleStyler.log('packages', `✓ Installed/Available: ${results.installed.join(', ')}`);
196
+ }
197
+
198
+ if (results.skipped.length > 0) {
199
+ consoleStyler.log('packages', `⚠ Skipped (compatibility): ${results.skipped.join(', ')}`);
200
+ consoleStyler.log('packages', 'Use built-in alternatives instead');
201
+ }
202
+
203
+ if (results.failed.length > 0) {
204
+ consoleStyler.log('packages', '✗ Failed installations:', { box: true });
205
+ results.failed.forEach(({ package: pkg, error }) => {
206
+ consoleStyler.log('packages', ` - ${pkg}: ${error}`, { indent: true });
207
+ });
208
+ }
209
+ }
210
+
211
+ // Set up require function for CommonJS modules
212
+ async setupCommonJSRequire() {
213
+ const { createRequire } = await import('module');
214
+ const __filename = fileURLToPath(import.meta.url);
215
+ const scriptDir = path.dirname(path.dirname(path.dirname(__filename)));
216
+ const require = createRequire(path.join(scriptDir, 'package.json'));
217
+
218
+ // Make require available globally
219
+ global.require = require;
220
+
221
+ return require;
222
+ }
223
+ }