npm-noxyai 1.0.6 → 1.0.8
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/index-noxyai.js +141 -33
- package/package.json +1 -1
- package/tic_tac_toe.py +111 -0
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 { spawn } = require('child_process'); // 🚨 CHANGED from exec to spawn
|
|
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,17 @@ 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
|
+
function printLogo() {
|
|
16
|
+
console.log('\x1b[36m' + `
|
|
17
|
+
███╗ ██╗ ██████╗ ██╗ ██╗██╗ ██╗ █████╗ ██╗
|
|
18
|
+
████╗ ██║██╔═══██╗╚██╗██╔╝╚██╗ ██╔╝██╔══██╗██║
|
|
19
|
+
██╔██╗ ██║██║ ██║ ╚███╔╝ ╚████╔╝ ███████║██║
|
|
20
|
+
██║╚██╗██║██║ ██║ ██╔██╗ ╚██╔╝ ██╔══██║██║
|
|
21
|
+
██║ ╚████║╚██████╔╝██╔╝ ██╗ ██║ ██║ ██║██║
|
|
22
|
+
╚═╝ ╚═══╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝╚═╝
|
|
23
|
+
` + '\x1b[0m');
|
|
24
|
+
}
|
|
25
|
+
|
|
13
26
|
function saveToken(token) {
|
|
14
27
|
fs.writeFileSync(CONFIG_FILE, JSON.stringify({ token }));
|
|
15
28
|
}
|
|
@@ -22,17 +35,46 @@ function getToken() {
|
|
|
22
35
|
return null;
|
|
23
36
|
}
|
|
24
37
|
|
|
38
|
+
function logout() {
|
|
39
|
+
if (fs.existsSync(CONFIG_FILE)) {
|
|
40
|
+
fs.unlinkSync(CONFIG_FILE);
|
|
41
|
+
console.log('✅ Successfully logged out.');
|
|
42
|
+
} else {
|
|
43
|
+
console.log('You are already logged out.');
|
|
44
|
+
}
|
|
45
|
+
process.exit(0);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function openBrowser(url) {
|
|
49
|
+
const platform = os.platform();
|
|
50
|
+
if (platform === 'android') {
|
|
51
|
+
spawn('termux-open-url', [url], { stdio: 'ignore' });
|
|
52
|
+
} else if (platform === 'darwin') {
|
|
53
|
+
spawn('open', [url], { stdio: 'ignore' });
|
|
54
|
+
} else if (platform === 'win32') {
|
|
55
|
+
spawn('cmd.exe', ['/c', 'start', '""', url], { stdio: 'ignore' });
|
|
56
|
+
} else {
|
|
57
|
+
spawn('xdg-open', [url], { stdio: 'ignore' });
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
25
61
|
async function login() {
|
|
26
|
-
|
|
62
|
+
printLogo();
|
|
63
|
+
console.log('Initializing secure login...\n');
|
|
27
64
|
try {
|
|
28
65
|
const initRes = await fetch(BASE_URL + '/api/cli/init', { method: 'POST' });
|
|
29
66
|
const { deviceCode, verificationUrl, interval } = await initRes.json();
|
|
30
67
|
|
|
31
|
-
console.log('
|
|
32
|
-
console.log(
|
|
33
|
-
console.log('Open this URL in your browser:\n\n -> ' + verificationUrl + ' <-');
|
|
68
|
+
console.log('=============================================');
|
|
69
|
+
console.log(`URL: ${verificationUrl}`);
|
|
34
70
|
console.log('=============================================\n');
|
|
35
|
-
|
|
71
|
+
|
|
72
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
73
|
+
rl.question('Press ENTER to automatically open the browser...', () => {
|
|
74
|
+
openBrowser(verificationUrl);
|
|
75
|
+
rl.close();
|
|
76
|
+
console.log('\n⏳ Waiting for authentication...');
|
|
77
|
+
});
|
|
36
78
|
|
|
37
79
|
const pollInterval = setInterval(async () => {
|
|
38
80
|
try {
|
|
@@ -49,20 +91,9 @@ async function login() {
|
|
|
49
91
|
saveToken(data.token);
|
|
50
92
|
|
|
51
93
|
console.clear();
|
|
52
|
-
|
|
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');
|
|
94
|
+
printLogo();
|
|
95
|
+
console.log('✅ Login successful! Terminal connected.');
|
|
96
|
+
console.log('Type "noxyai help" for commands.\n');
|
|
66
97
|
process.exit(0);
|
|
67
98
|
} else if (data.error) {
|
|
68
99
|
clearInterval(pollInterval);
|
|
@@ -77,22 +108,41 @@ async function login() {
|
|
|
77
108
|
}
|
|
78
109
|
}
|
|
79
110
|
|
|
80
|
-
|
|
111
|
+
// 🚨 THE FIX: Upgraded to spawn with interactive stdio
|
|
112
|
+
function runTerminalCommand(cmd) {
|
|
113
|
+
return new Promise((resolve, reject) => {
|
|
114
|
+
console.log(`\n\x1b[33m⚡ Running:\x1b[0m ${cmd}\n`);
|
|
115
|
+
|
|
116
|
+
const child = spawn(cmd, {
|
|
117
|
+
shell: true,
|
|
118
|
+
stdio: 'inherit' // This connects your live keyboard to the Python script!
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
child.on('close', (code) => {
|
|
122
|
+
if (code !== 0) reject(`Command failed with exit code ${code}`);
|
|
123
|
+
else resolve();
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
child.on('error', (error) => reject(error.message));
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
async function chat(prompt, depth = 0) {
|
|
81
131
|
const token = getToken();
|
|
82
132
|
if (!token) {
|
|
83
|
-
console.error('❌ You
|
|
133
|
+
console.error('❌ Unauthorized: You must log in first. Run "noxyai login"');
|
|
84
134
|
process.exit(1);
|
|
85
135
|
}
|
|
86
136
|
|
|
87
|
-
if (
|
|
88
|
-
console.error('❌ Please
|
|
137
|
+
if (depth > 3) {
|
|
138
|
+
console.error('\n❌ Agent reached maximum retry depth. Please fix the error manually.');
|
|
89
139
|
process.exit(1);
|
|
90
140
|
}
|
|
91
141
|
|
|
92
142
|
const model = 'auto';
|
|
93
143
|
|
|
94
144
|
try {
|
|
95
|
-
const res = await fetch(BASE_URL + '/api/
|
|
145
|
+
const res = await fetch(BASE_URL + '/api/io', {
|
|
96
146
|
method: 'POST',
|
|
97
147
|
headers: {
|
|
98
148
|
'Content-Type': 'application/json',
|
|
@@ -107,10 +157,12 @@ async function chat(prompt) {
|
|
|
107
157
|
process.exit(1);
|
|
108
158
|
}
|
|
109
159
|
|
|
110
|
-
console.log('\n🤖
|
|
160
|
+
if (depth === 0) console.log('\n🤖 \x1b[36mNoxyAI\x1b[0m is thinking...\n');
|
|
161
|
+
else console.log('\n🤖 \x1b[36mNoxyAI\x1b[0m is analyzing the error and rewriting...\n');
|
|
111
162
|
|
|
112
163
|
const reader = res.body.getReader();
|
|
113
164
|
const decoder = new TextDecoder('utf-8');
|
|
165
|
+
let fullResponse = "";
|
|
114
166
|
|
|
115
167
|
while (true) {
|
|
116
168
|
const { done, value } = await reader.read();
|
|
@@ -122,29 +174,85 @@ async function chat(prompt) {
|
|
|
122
174
|
for (const line of lines) {
|
|
123
175
|
if (line.startsWith('data: ')) {
|
|
124
176
|
const data = line.slice(6).trim();
|
|
125
|
-
if (data === '[DONE]')
|
|
126
|
-
console.log('\n');
|
|
127
|
-
process.exit(0);
|
|
128
|
-
}
|
|
177
|
+
if (data === '[DONE]') break;
|
|
129
178
|
try {
|
|
130
179
|
const parsed = JSON.parse(data);
|
|
131
180
|
if (parsed.text) {
|
|
181
|
+
fullResponse += parsed.text;
|
|
132
182
|
process.stdout.write(parsed.text);
|
|
133
183
|
}
|
|
134
184
|
} catch (e) {}
|
|
135
185
|
}
|
|
136
186
|
}
|
|
137
187
|
}
|
|
188
|
+
|
|
189
|
+
console.log('\n\n\x1b[32m[Agent] Response complete. Processing actions...\x1b[0m');
|
|
190
|
+
|
|
191
|
+
const fileRegex = /<file path="([^"]+)">([\s\S]*?)<\/file>/g;
|
|
192
|
+
let match;
|
|
193
|
+
while ((match = fileRegex.exec(fullResponse)) !== null) {
|
|
194
|
+
const filePath = match[1];
|
|
195
|
+
const content = match[2];
|
|
196
|
+
|
|
197
|
+
const dir = path.dirname(filePath);
|
|
198
|
+
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
|
199
|
+
fs.writeFileSync(filePath, content.trim());
|
|
200
|
+
console.log(`\x1b[32m✔ Created file:\x1b[0m ${filePath}`);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
const execRegex = /<execute>([\s\S]*?)<\/execute>/g;
|
|
204
|
+
const commands = [];
|
|
205
|
+
while ((match = execRegex.exec(fullResponse)) !== null) {
|
|
206
|
+
commands.push(match[1].trim());
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
for (const cmd of commands) {
|
|
210
|
+
try {
|
|
211
|
+
await runTerminalCommand(cmd);
|
|
212
|
+
} catch (err) {
|
|
213
|
+
console.error(`\n\x1b[31m❌ Command Failed:\x1b[0m ${err}`);
|
|
214
|
+
console.log(`\x1b[33m🔄 Triggering Auto-Heal Loop...\x1b[0m`);
|
|
215
|
+
const errorPrompt = `I ran the command "${cmd}" and got this error:\n\n${err}\n\nPlease fix the issue. Use <file> tags to rewrite files or <execute> to run commands.`;
|
|
216
|
+
await chat(errorPrompt, depth + 1);
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
process.exit(0);
|
|
221
|
+
|
|
138
222
|
} catch (error) {
|
|
139
223
|
console.error('\n❌ Connection error: ' + error.message);
|
|
224
|
+
process.exit(1);
|
|
140
225
|
}
|
|
141
226
|
}
|
|
142
227
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
228
|
+
function showHelp() {
|
|
229
|
+
printLogo();
|
|
230
|
+
console.log(`
|
|
231
|
+
\x1b[33mNoxyAI Agent CLI - Available Commands\x1b[0m
|
|
232
|
+
|
|
233
|
+
\x1b[32mnoxyai login\x1b[0m Authenticate your terminal
|
|
234
|
+
\x1b[32mnoxyai logout\x1b[0m Remove authentication from this device
|
|
235
|
+
\x1b[32mnoxyai chat "<prompt>"\x1b[0m Chat with the AI. It can build apps, create files, and fix errors.
|
|
236
|
+
\x1b[32mnoxyai help\x1b[0m Show this menu
|
|
237
|
+
|
|
238
|
+
\x1b[33mExamples:\x1b[0m
|
|
239
|
+
noxyai chat "Create a snake game in python and run it"
|
|
240
|
+
noxyai chat "Initialize a react app called my-app"
|
|
241
|
+
noxyai chat "Create an express server that returns hello world on port 3000"
|
|
242
|
+
`);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
if (command === 'login') login();
|
|
246
|
+
else if (command === 'logout') logout();
|
|
247
|
+
else if (command === 'help' || command === '--help' || !command) showHelp();
|
|
248
|
+
else if (command === 'chat') {
|
|
146
249
|
const prompt = args.slice(1).join(' ');
|
|
250
|
+
if (!prompt) {
|
|
251
|
+
console.error('❌ Please provide a prompt. Example: noxyai chat "Create a python script"');
|
|
252
|
+
process.exit(1);
|
|
253
|
+
}
|
|
147
254
|
chat(prompt);
|
|
148
255
|
} else {
|
|
149
|
-
console.
|
|
256
|
+
console.error(`❌ Unknown command: ${command}`);
|
|
257
|
+
console.log('Run "noxyai help" for a list of commands.');
|
|
150
258
|
}
|
package/package.json
CHANGED
package/tic_tac_toe.py
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import random
|
|
2
|
+
|
|
3
|
+
class TicTacToe:
|
|
4
|
+
def __init__(self):
|
|
5
|
+
self.board = [' ' for _ in range(9)]
|
|
6
|
+
|
|
7
|
+
def print_board(self):
|
|
8
|
+
row1 = '| {} | {} | {} |'.format(self.board[0], self.board[1], self.board[2])
|
|
9
|
+
row2 = '| {} | {} | {} |'.format(self.board[3], self.board[4], self.board[5])
|
|
10
|
+
row3 = '| {} | {} | {} |'.format(self.board[6], self.board[7], self.board[8])
|
|
11
|
+
|
|
12
|
+
print()
|
|
13
|
+
print(row1)
|
|
14
|
+
print(row2)
|
|
15
|
+
print(row3)
|
|
16
|
+
print()
|
|
17
|
+
|
|
18
|
+
def available_moves(self):
|
|
19
|
+
return [i for i, spot in enumerate(self.board) if spot == ' ']
|
|
20
|
+
|
|
21
|
+
def empty_cells(self):
|
|
22
|
+
return ' ' in self.board
|
|
23
|
+
|
|
24
|
+
def num_empty_cells(self):
|
|
25
|
+
return self.board.count(' ')
|
|
26
|
+
|
|
27
|
+
def make_move(self, letter, move):
|
|
28
|
+
self.board[move] = letter
|
|
29
|
+
|
|
30
|
+
def winner(self):
|
|
31
|
+
winning_combos = [(0, 1, 2), (3, 4, 5), (6, 7, 8), (0, 3, 6), (1, 4, 7), (2, 5, 8), (0, 4, 8), (2, 4, 6)]
|
|
32
|
+
for combo in winning_combos:
|
|
33
|
+
if self.board[combo[0]] == self.board[combo[1]] == self.board[combo[2]] != ' ':
|
|
34
|
+
return self.board[combo[0]]
|
|
35
|
+
if ' ' not in self.board:
|
|
36
|
+
return 'Tie'
|
|
37
|
+
return False
|
|
38
|
+
|
|
39
|
+
def minimax(board, depth, is_maximizing):
|
|
40
|
+
result = board.winner()
|
|
41
|
+
if result:
|
|
42
|
+
if result == 'X':
|
|
43
|
+
return -10 + depth
|
|
44
|
+
elif result == 'O':
|
|
45
|
+
return 10 - depth
|
|
46
|
+
elif result == 'Tie':
|
|
47
|
+
return 0
|
|
48
|
+
|
|
49
|
+
if is_maximizing:
|
|
50
|
+
best_score = float('-inf')
|
|
51
|
+
for move in board.available_moves():
|
|
52
|
+
board.make_move('O', move)
|
|
53
|
+
score = minimax(board, depth + 1, False)
|
|
54
|
+
board.board[move] = ' '
|
|
55
|
+
best_score = max(score, best_score)
|
|
56
|
+
return best_score
|
|
57
|
+
else:
|
|
58
|
+
best_score = float('inf')
|
|
59
|
+
for move in board.available_moves():
|
|
60
|
+
board.make_move('X', move)
|
|
61
|
+
score = minimax(board, depth + 1, True)
|
|
62
|
+
board.board[move] = ' '
|
|
63
|
+
best_score = min(score, best_score)
|
|
64
|
+
return best_score
|
|
65
|
+
|
|
66
|
+
def ai_move(board):
|
|
67
|
+
best_score = float('-inf')
|
|
68
|
+
best_move = 0
|
|
69
|
+
for move in board.available_moves():
|
|
70
|
+
board.make_move('O', move)
|
|
71
|
+
score = minimax(board, 0, False)
|
|
72
|
+
board.board[move] = ' '
|
|
73
|
+
if score > best_score:
|
|
74
|
+
best_score = score
|
|
75
|
+
best_move = move
|
|
76
|
+
return best_move
|
|
77
|
+
|
|
78
|
+
def main():
|
|
79
|
+
board = TicTacToe()
|
|
80
|
+
while True:
|
|
81
|
+
board.print_board()
|
|
82
|
+
move = input("Enter your move (1-9): ")
|
|
83
|
+
if board.board[int(move) - 1] != ' ':
|
|
84
|
+
print("Invalid move, try again.")
|
|
85
|
+
continue
|
|
86
|
+
board.make_move('X', int(move) - 1)
|
|
87
|
+
result = board.winner()
|
|
88
|
+
if result:
|
|
89
|
+
board.print_board()
|
|
90
|
+
if result == 'X':
|
|
91
|
+
print("You win!")
|
|
92
|
+
elif result == 'O':
|
|
93
|
+
print("AI wins!")
|
|
94
|
+
else:
|
|
95
|
+
print("It's a tie!")
|
|
96
|
+
break
|
|
97
|
+
move = ai_move(board)
|
|
98
|
+
board.make_move('O', move)
|
|
99
|
+
result = board.winner()
|
|
100
|
+
if result:
|
|
101
|
+
board.print_board()
|
|
102
|
+
if result == 'X':
|
|
103
|
+
print("You win!")
|
|
104
|
+
elif result == 'O':
|
|
105
|
+
print("AI wins!")
|
|
106
|
+
else:
|
|
107
|
+
print("It's a tie!")
|
|
108
|
+
break
|
|
109
|
+
|
|
110
|
+
if __name__ == '__main__':
|
|
111
|
+
main()
|