npm-noxyai 1.0.6 → 1.0.7

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 (2) hide show
  1. package/index-noxyai.js +154 -30
  2. package/package.json +1 -1
package/index-noxyai.js CHANGED
@@ -3,6 +3,8 @@
3
3
  const fs = require('fs');
4
4
  const os = require('os');
5
5
  const path = require('path');
6
+ const { exec } = require('child_process');
7
+ const readline = require('readline');
6
8
 
7
9
  const BASE_URL = 'https://www.noxyai.com';
8
10
  const CONFIG_FILE = path.join(os.homedir(), '.noxyai.json');
@@ -10,6 +12,19 @@ const CONFIG_FILE = path.join(os.homedir(), '.noxyai.json');
10
12
  const args = process.argv.slice(2);
11
13
  const command = args[0];
12
14
 
15
+ // --- HELPER: ASCII ART ---
16
+ function printLogo() {
17
+ console.log('\x1b[36m' + `
18
+ ███╗ ██╗ ██████╗ ██╗ ██╗██╗ ██╗ █████╗ ██╗
19
+ ████╗ ██║██╔═══██╗╚██╗██╔╝╚██╗ ██╔╝██╔══██╗██║
20
+ ██╔██╗ ██║██║ ██║ ╚███╔╝ ╚████╔╝ ███████║██║
21
+ ██║╚██╗██║██║ ██║ ██╔██╗ ╚██╔╝ ██╔══██║██║
22
+ ██║ ╚████║╚██████╔╝██╔╝ ██╗ ██║ ██║ ██║██║
23
+ ╚═╝ ╚═══╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝╚═╝
24
+ ` + '\x1b[0m');
25
+ }
26
+
27
+ // --- HELPER: AUTHENTICATION ---
13
28
  function saveToken(token) {
14
29
  fs.writeFileSync(CONFIG_FILE, JSON.stringify({ token }));
15
30
  }
@@ -22,17 +37,48 @@ function getToken() {
22
37
  return null;
23
38
  }
24
39
 
40
+ function logout() {
41
+ if (fs.existsSync(CONFIG_FILE)) {
42
+ fs.unlinkSync(CONFIG_FILE);
43
+ console.log('✅ Successfully logged out.');
44
+ } else {
45
+ console.log('You are already logged out.');
46
+ }
47
+ process.exit(0);
48
+ }
49
+
50
+ // --- HELPER: AUTO-OPEN URL ---
51
+ function openBrowser(url) {
52
+ const platform = os.platform();
53
+ if (platform === 'android') {
54
+ exec(`termux-open-url "${url}"`);
55
+ } else if (platform === 'darwin') {
56
+ exec(`open "${url}"`);
57
+ } else if (platform === 'win32') {
58
+ exec(`start "" "${url}"`);
59
+ } else {
60
+ exec(`xdg-open "${url}"`);
61
+ }
62
+ }
63
+
64
+ // --- COMMAND: LOGIN ---
25
65
  async function login() {
26
- console.log('Initializing login...');
66
+ printLogo();
67
+ console.log('Initializing secure login...\n');
27
68
  try {
28
69
  const initRes = await fetch(BASE_URL + '/api/cli/init', { method: 'POST' });
29
70
  const { deviceCode, verificationUrl, interval } = await initRes.json();
30
71
 
31
- console.log('\n=============================================');
32
- console.log('Action Required: Please authenticate your terminal');
33
- console.log('Open this URL in your browser:\n\n -> ' + verificationUrl + ' <-');
72
+ console.log('=============================================');
73
+ console.log(`URL: ${verificationUrl}`);
34
74
  console.log('=============================================\n');
35
- console.log('Waiting for confirmation...');
75
+
76
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
77
+ rl.question('Press ENTER to automatically open the browser...', () => {
78
+ openBrowser(verificationUrl);
79
+ rl.close();
80
+ console.log('\n⏳ Waiting for authentication...');
81
+ });
36
82
 
37
83
  const pollInterval = setInterval(async () => {
38
84
  try {
@@ -49,20 +95,9 @@ async function login() {
49
95
  saveToken(data.token);
50
96
 
51
97
  console.clear();
52
- console.log('\x1b[36m' +
53
- ` ___ ___ ___ ___ ___
54
- /\\__\\ /\\ \\ |\\__\\ |\\__\\ /\\ \\ ___
55
- /::| | /::\\ \\ |:| | |:| | /::\\ \\ /\\ \\
56
- /:|:| | /:/\\:\\ \\ |:| | |:| | /:/\\:\\ \\ \\:\\ \\
57
- /:/|:| |__ /:/ \\:\\ \\ |:|__|__ |:|__|__ /::\\~\\:\\ \\ /::\\__\\
58
- /:/ |:| /\\__\\ /:/__/ \\:\\__\\ ____/::::\\__\\ /::::\\__\\ /:/\\:\\ \\:\\__\\ __/:/\\/__/
59
- \\/__|:|/:/ / \\:\\ \\ /:/ / \\::::/~~/~ /:/~~/~ \\/__\\:\\/:/ / /\\/:/ /
60
- |:/:/ / \\:\\ /:/ / ~~|:|~~| /:/ / \\::/ / \\::/__/
61
- |::/ / \\:\\/:/ / |:| | \\/__/ /:/ / \\:\\__\\
62
- /:/ / \\::/ / |:| | /:/ / \\/__/
63
- \\/__/ \\/__/ \\|__| \\/__/` + '\x1b[0m');
64
- console.log('\n✅ Login successful! Terminal connected.');
65
- console.log('Try running: noxyai chat "Hello, world!"\n');
98
+ printLogo();
99
+ console.log('✅ Login successful! Terminal connected.');
100
+ console.log('Type "noxyai help" for commands.\n');
66
101
  process.exit(0);
67
102
  } else if (data.error) {
68
103
  clearInterval(pollInterval);
@@ -77,22 +112,41 @@ async function login() {
77
112
  }
78
113
  }
79
114
 
80
- async function chat(prompt) {
115
+ // --- HELPER: EXECUTE COMMANDS & ERROR HANDLING ---
116
+ function runTerminalCommand(cmd) {
117
+ return new Promise((resolve, reject) => {
118
+ console.log(`\n\x1b[33m⚡ Running:\x1b[0m ${cmd}`);
119
+ const child = exec(cmd, (error, stdout, stderr) => {
120
+ if (error) {
121
+ reject(stderr || error.message);
122
+ return;
123
+ }
124
+ resolve(stdout);
125
+ });
126
+
127
+ // Pipe output live to the terminal so user can see servers/logs
128
+ child.stdout.pipe(process.stdout);
129
+ child.stderr.pipe(process.stderr);
130
+ });
131
+ }
132
+
133
+ // --- COMMAND: CHAT & AGENT EXECUTION ---
134
+ async function chat(prompt, depth = 0) {
81
135
  const token = getToken();
82
136
  if (!token) {
83
- console.error('❌ You are not logged in. Please run: noxyai login');
137
+ console.error('❌ Unauthorized: You must log in first. Run "noxyai login"');
84
138
  process.exit(1);
85
139
  }
86
140
 
87
- if (!prompt) {
88
- console.error('❌ Please provide a prompt.');
141
+ if (depth > 3) {
142
+ console.error('\nAgent reached maximum retry depth. Please fix the error manually.');
89
143
  process.exit(1);
90
144
  }
91
145
 
92
146
  const model = 'auto';
93
147
 
94
148
  try {
95
- const res = await fetch(BASE_URL + '/api/cli/execute', {
149
+ const res = await fetch(BASE_URL + '/api/io', {
96
150
  method: 'POST',
97
151
  headers: {
98
152
  'Content-Type': 'application/json',
@@ -107,10 +161,12 @@ async function chat(prompt) {
107
161
  process.exit(1);
108
162
  }
109
163
 
110
- console.log('\n🤖 NoxyAI (' + model + '):\n');
164
+ if (depth === 0) console.log('\n🤖 \x1b[36mNoxyAI\x1b[0m is thinking...\n');
165
+ else console.log('\n🤖 \x1b[36mNoxyAI\x1b[0m is analyzing the error and rewriting...\n');
111
166
 
112
167
  const reader = res.body.getReader();
113
168
  const decoder = new TextDecoder('utf-8');
169
+ let fullResponse = "";
114
170
 
115
171
  while (true) {
116
172
  const { done, value } = await reader.read();
@@ -122,29 +178,97 @@ async function chat(prompt) {
122
178
  for (const line of lines) {
123
179
  if (line.startsWith('data: ')) {
124
180
  const data = line.slice(6).trim();
125
- if (data === '[DONE]') {
126
- console.log('\n');
127
- process.exit(0);
128
- }
181
+ if (data === '[DONE]') break;
129
182
  try {
130
183
  const parsed = JSON.parse(data);
131
184
  if (parsed.text) {
185
+ fullResponse += parsed.text;
132
186
  process.stdout.write(parsed.text);
133
187
  }
134
188
  } catch (e) {}
135
189
  }
136
190
  }
137
191
  }
192
+
193
+ console.log('\n\n\x1b[32m[Agent] Response complete. Processing actions...\x1b[0m');
194
+
195
+ // 1. EXTRACT AND CREATE FILES
196
+ const fileRegex = /<file path="([^"]+)">([\s\S]*?)<\/file>/g;
197
+ let match;
198
+ while ((match = fileRegex.exec(fullResponse)) !== null) {
199
+ const filePath = match[1];
200
+ const content = match[2];
201
+
202
+ const dir = path.dirname(filePath);
203
+ if (!fs.existsSync(dir)) {
204
+ fs.mkdirSync(dir, { recursive: true });
205
+ }
206
+ fs.writeFileSync(filePath, content.trim());
207
+ console.log(`\x1b[32m✔ Created file:\x1b[0m ${filePath}`);
208
+ }
209
+
210
+ // 2. EXTRACT AND RUN COMMANDS
211
+ const execRegex = /<execute>([\s\S]*?)<\/execute>/g;
212
+ const commands = [];
213
+ while ((match = execRegex.exec(fullResponse)) !== null) {
214
+ commands.push(match[1].trim());
215
+ }
216
+
217
+ for (const cmd of commands) {
218
+ try {
219
+ await runTerminalCommand(cmd);
220
+ } catch (err) {
221
+ console.error(`\n\x1b[31m❌ Command Failed:\x1b[0m ${err.trim()}`);
222
+ console.log(`\x1b[33m🔄 Triggering Auto-Heal Loop...\x1b[0m`);
223
+
224
+ const errorPrompt = `I ran the command "${cmd}" and got this error:\n\n${err}\n\nPlease fix the issue. If you need to rewrite a file, use the <file> tags. If you need to install a missing library, use the <execute> tag.`;
225
+
226
+ await chat(errorPrompt, depth + 1);
227
+ return;
228
+ }
229
+ }
230
+
231
+ process.exit(0);
232
+
138
233
  } catch (error) {
139
234
  console.error('\n❌ Connection error: ' + error.message);
235
+ process.exit(1);
140
236
  }
141
237
  }
142
238
 
239
+ // --- COMMAND: HELP ---
240
+ function showHelp() {
241
+ printLogo();
242
+ console.log(`
243
+ \x1b[33mNoxyAI Agent CLI - Available Commands\x1b[0m
244
+
245
+ \x1b[32mnoxyai login\x1b[0m Authenticate your terminal
246
+ \x1b[32mnoxyai logout\x1b[0m Remove authentication from this device
247
+ \x1b[32mnoxyai chat "<prompt>"\x1b[0m Chat with the AI. It can build apps, create files, and fix errors.
248
+ \x1b[32mnoxyai help\x1b[0m Show this menu
249
+
250
+ \x1b[33mExamples:\x1b[0m
251
+ noxyai chat "Create a snake game in python and run it"
252
+ noxyai chat "Initialize a react app called my-app"
253
+ noxyai chat "Create an express server that returns hello world on port 3000"
254
+ `);
255
+ }
256
+
257
+ // --- ROUTER ---
143
258
  if (command === 'login') {
144
259
  login();
260
+ } else if (command === 'logout') {
261
+ logout();
262
+ } else if (command === 'help' || command === '--help' || !command) {
263
+ showHelp();
145
264
  } else if (command === 'chat') {
146
265
  const prompt = args.slice(1).join(' ');
266
+ if (!prompt) {
267
+ console.error('❌ Please provide a prompt. Example: noxyai chat "Create a python script"');
268
+ process.exit(1);
269
+ }
147
270
  chat(prompt);
148
271
  } else {
149
- console.log('\nUsage:\n noxyai login\n noxyai chat <prompt>\n');
272
+ console.error(`❌ Unknown command: ${command}`);
273
+ console.log('Run "noxyai help" for a list of commands.');
150
274
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "npm-noxyai",
3
- "version": "1.0.6",
3
+ "version": "1.0.7",
4
4
  "description": "CLI for NoxyAI",
5
5
  "main": "index-noxyai.js",
6
6
  "bin": {