primocode 4.3.1 → 7.0.1
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/README.md +91 -107
- package/bin/primocode.js +274 -476
- package/lib/act.js +43 -471
- package/lib/api.js +5 -3
- package/lib/config.js +99 -35
- package/lib/desktop.js +142 -0
- package/lib/tools.js +68 -467
- package/lib/ui.js +135 -78
- package/package.json +7 -18
- package/lib/mascot.js +0 -121
- package/lib/memory.js +0 -179
- package/lib/mouse.js +0 -144
- package/lib/platform.js +0 -245
package/lib/mouse.js
DELETED
|
@@ -1,144 +0,0 @@
|
|
|
1
|
-
// Mouse Virtual — controle completo da interface do computador
|
|
2
|
-
// Suporta: Windows, macOS, Linux, Termux (Android)
|
|
3
|
-
|
|
4
|
-
'use strict';
|
|
5
|
-
|
|
6
|
-
const { execSync } = require('child_process');
|
|
7
|
-
const os = require('os');
|
|
8
|
-
const path = require('path');
|
|
9
|
-
const platform = require('./platform');
|
|
10
|
-
|
|
11
|
-
// Estado do mouse virtual
|
|
12
|
-
let mouseVisible = false;
|
|
13
|
-
let currentX = 0;
|
|
14
|
-
let currentY = 0;
|
|
15
|
-
|
|
16
|
-
// Mostra/esconde o cursor virtual no terminal
|
|
17
|
-
function showCursor(x, y) {
|
|
18
|
-
mouseVisible = true;
|
|
19
|
-
currentX = x;
|
|
20
|
-
currentY = y;
|
|
21
|
-
return { x, y, visible: true };
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
function hideCursor() {
|
|
25
|
-
mouseVisible = false;
|
|
26
|
-
return { visible: false };
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
// Move o mouse para coordenadas absolutas
|
|
30
|
-
async function moveTo(x, y) {
|
|
31
|
-
if (platform.isAndroid()) {
|
|
32
|
-
return platform.moveMouse(x, y);
|
|
33
|
-
}
|
|
34
|
-
try {
|
|
35
|
-
const p = process.platform;
|
|
36
|
-
if (p === 'win32') {
|
|
37
|
-
const ps = `Add-Type -AssemblyName System.Windows.Forms; [System.Windows.Forms.Cursor]::Position = New-Object System.Drawing.Point(${x}, ${y})`;
|
|
38
|
-
execSync(`powershell -Command "${ps}"`, { stdio: 'ignore' });
|
|
39
|
-
} else if (p === 'darwin') {
|
|
40
|
-
execSync(`cliclick m:${x},${y}`, { stdio: 'ignore' });
|
|
41
|
-
} else {
|
|
42
|
-
execSync(`xdotool mousemove ${x} ${y}`, { stdio: 'ignore' });
|
|
43
|
-
}
|
|
44
|
-
return showCursor(x, y);
|
|
45
|
-
} catch (e) {
|
|
46
|
-
return { ok: false, error: e.message };
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
// Clica em coordenadas específicas
|
|
51
|
-
async function clickAt(x, y, button = 'left') {
|
|
52
|
-
if (platform.isAndroid()) {
|
|
53
|
-
return platform.clickMouse(x, y);
|
|
54
|
-
}
|
|
55
|
-
try {
|
|
56
|
-
await moveTo(x, y);
|
|
57
|
-
const p = process.platform;
|
|
58
|
-
if (p === 'win32') {
|
|
59
|
-
const clickPs = `Add-Type -MemberDefinition '[DllImport(\"user32.dll\")] public static extern void mouse_event(int flags, int dx, int dy, int data, int extraInfo);' -Name Mouse -Namespace Win32; [Win32.Mouse]::mouse_event(0x02, 0, 0, 0, 0); [Win32.Mouse]::mouse_event(0x04, 0, 0, 0, 0)`;
|
|
60
|
-
execSync(`powershell -Command "${clickPs}"`, { stdio: 'ignore' });
|
|
61
|
-
} else if (p === 'darwin') {
|
|
62
|
-
execSync(`cliclick c:${x},${y}`, { stdio: 'ignore' });
|
|
63
|
-
} else {
|
|
64
|
-
execSync(`xdotool mousemove ${x} ${y} click 1`, { stdio: 'ignore' });
|
|
65
|
-
}
|
|
66
|
-
return { ok: true, x, y, button };
|
|
67
|
-
} catch (e) {
|
|
68
|
-
return { ok: false, error: e.message };
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
// Clica em um elemento pelo texto (via browser CDP)
|
|
73
|
-
async function clickText(text, browser) {
|
|
74
|
-
try {
|
|
75
|
-
const result = await browser.clickText(text);
|
|
76
|
-
return { ok: true, ...result };
|
|
77
|
-
} catch (e) {
|
|
78
|
-
return { ok: false, error: e.message };
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
// Clica em um seletor CSS (via browser CDP)
|
|
83
|
-
async function clickSelector(selector, browser) {
|
|
84
|
-
try {
|
|
85
|
-
const result = await browser.clickSelector(selector);
|
|
86
|
-
return { ok: true, ...result };
|
|
87
|
-
} catch (e) {
|
|
88
|
-
return { ok: false, error: e.message };
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
// Digita texto em um campo (via browser CDP)
|
|
93
|
-
async function typeIn(selector, text, browser) {
|
|
94
|
-
try {
|
|
95
|
-
const result = await browser.typeInSelector(selector, text);
|
|
96
|
-
return { ok: true, ...result };
|
|
97
|
-
} catch (e) {
|
|
98
|
-
return { ok: false, error: e.message };
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
// Pressiona uma tecla (via browser CDP)
|
|
103
|
-
async function pressKey(key, browser) {
|
|
104
|
-
try {
|
|
105
|
-
const result = await browser.key(key);
|
|
106
|
-
return { ok: true, ...result };
|
|
107
|
-
} catch (e) {
|
|
108
|
-
return { ok: false, error: e.message };
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
// Scroll em uma posição
|
|
113
|
-
async function scrollAt(x, y, dy, browser) {
|
|
114
|
-
try {
|
|
115
|
-
await browser.scroll(dy);
|
|
116
|
-
return { ok: true, dy };
|
|
117
|
-
} catch (e) {
|
|
118
|
-
return { ok: false, error: e.message };
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
// Tira screenshot da tela
|
|
123
|
-
async function screenshot(savePath) {
|
|
124
|
-
return platform.screenshot(savePath);
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
// Abre um aplicativo pelo nome
|
|
128
|
-
async function openApp(appName) {
|
|
129
|
-
return platform.openApp(appName);
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
module.exports = {
|
|
133
|
-
moveTo,
|
|
134
|
-
clickAt,
|
|
135
|
-
clickText,
|
|
136
|
-
clickSelector,
|
|
137
|
-
typeIn,
|
|
138
|
-
pressKey,
|
|
139
|
-
scrollAt,
|
|
140
|
-
screenshot,
|
|
141
|
-
openApp,
|
|
142
|
-
showCursor,
|
|
143
|
-
hideCursor,
|
|
144
|
-
};
|
package/lib/platform.js
DELETED
|
@@ -1,245 +0,0 @@
|
|
|
1
|
-
// Platform — Detecção e adaptação de plataforma
|
|
2
|
-
// Suporta: Windows, macOS, Linux, Termux (Android)
|
|
3
|
-
|
|
4
|
-
'use strict';
|
|
5
|
-
|
|
6
|
-
const os = require('os');
|
|
7
|
-
const path = require('path');
|
|
8
|
-
const { execSync } = require('child_process');
|
|
9
|
-
|
|
10
|
-
// Detecta se está rodando no Termux (Android)
|
|
11
|
-
function isTermux() {
|
|
12
|
-
return process.env.TERMUX_VERSION !== undefined ||
|
|
13
|
-
process.env.PREFIX?.includes('termux') ||
|
|
14
|
-
process.env.HOME?.includes('termux') ||
|
|
15
|
-
(process.platform === 'android') ||
|
|
16
|
-
fs.existsSync('/data/data/com.termux/files/usr/bin/termux-open');
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
// Detecta se está rodando no Android (não necessariamente Termux)
|
|
20
|
-
function isAndroid() {
|
|
21
|
-
return isTermux() || process.platform === 'android';
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
// Diretório base para projetos
|
|
25
|
-
function getProjectsDir() {
|
|
26
|
-
if (isTermux()) {
|
|
27
|
-
// Termux: armazenamento interno acessível
|
|
28
|
-
const termuxStorage = '/data/data/com.termux/files/home/storage/shared/primocode';
|
|
29
|
-
return termuxStorage;
|
|
30
|
-
}
|
|
31
|
-
if (process.platform === 'win32') {
|
|
32
|
-
return path.join('C:', 'primocode');
|
|
33
|
-
}
|
|
34
|
-
return path.join(os.homedir(), 'primocode');
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
// Diretório de configuração
|
|
38
|
-
function getConfigDir() {
|
|
39
|
-
if (isTermux()) {
|
|
40
|
-
return '/data/data/com.termux/files/home/.primocode';
|
|
41
|
-
}
|
|
42
|
-
return path.join(os.homedir(), '.primocode');
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
// Abrir arquivo no navegador
|
|
46
|
-
function openBrowser(target) {
|
|
47
|
-
if (isTermux()) {
|
|
48
|
-
// Termux: usar termux-open
|
|
49
|
-
try {
|
|
50
|
-
execSync(`termux-open "${target}"`, { stdio: 'ignore' });
|
|
51
|
-
return { ok: true };
|
|
52
|
-
} catch (e) {
|
|
53
|
-
// Fallback: am start (Activity Manager)
|
|
54
|
-
try {
|
|
55
|
-
execSync(`am start -a android.intent.action.VIEW -d "file://${target}"`, { stdio: 'ignore' });
|
|
56
|
-
return { ok: true };
|
|
57
|
-
} catch (e2) {
|
|
58
|
-
return { ok: false, error: e2.message };
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
if (process.platform === 'win32') {
|
|
63
|
-
execSync(`start "" "${target}"`, { stdio: 'ignore' });
|
|
64
|
-
} else if (process.platform === 'darwin') {
|
|
65
|
-
execSync(`open "${target}"`, { stdio: 'ignore' });
|
|
66
|
-
} else {
|
|
67
|
-
execSync(`xdg-open "${target}"`, { stdio: 'ignore' });
|
|
68
|
-
}
|
|
69
|
-
return { ok: true };
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
// Abrir aplicativo
|
|
73
|
-
function openApp(appName) {
|
|
74
|
-
if (isTermux()) {
|
|
75
|
-
// Termux: usar am start para abrir apps Android
|
|
76
|
-
const appMap = {
|
|
77
|
-
'chrome': 'com.android.chrome/com.google.android.apps.chrome.Main',
|
|
78
|
-
'firefox': 'org.mozilla.firefox/.App',
|
|
79
|
-
'browser': 'com.android.browser/.BrowserActivity',
|
|
80
|
-
'vscode': 'com.termux.api/.TermuxApiService',
|
|
81
|
-
'files': 'com.android.documentsui/.FilesActivity',
|
|
82
|
-
'settings': 'com.android.settings/.Settings',
|
|
83
|
-
};
|
|
84
|
-
const activity = appMap[appName.toLowerCase()];
|
|
85
|
-
if (activity) {
|
|
86
|
-
try {
|
|
87
|
-
execSync(`am start -n ${activity}`, { stdio: 'ignore' });
|
|
88
|
-
return { ok: true };
|
|
89
|
-
} catch (e) {
|
|
90
|
-
return { ok: false, error: e.message };
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
// Tentar como package name genérico
|
|
94
|
-
try {
|
|
95
|
-
execSync(`am start -a android.intent.action.MAIN -n ${appName}/.MainActivity`, { stdio: 'ignore' });
|
|
96
|
-
return { ok: true };
|
|
97
|
-
} catch (e) {
|
|
98
|
-
return { ok: false, error: e.message };
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
if (process.platform === 'win32') {
|
|
102
|
-
execSync(`start "" "${appName}"`, { stdio: 'ignore' });
|
|
103
|
-
} else if (process.platform === 'darwin') {
|
|
104
|
-
execSync(`open -a "${appName}"`, { stdio: 'ignore' });
|
|
105
|
-
} else {
|
|
106
|
-
execSync(`${appName} &`, { stdio: 'ignore' });
|
|
107
|
-
}
|
|
108
|
-
return { ok: true };
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
// Abrir terminal
|
|
112
|
-
function openTerminal() {
|
|
113
|
-
if (isTermux()) {
|
|
114
|
-
// Já está no Termux, apenas informar
|
|
115
|
-
return { ok: true, message: 'Já está no Termux!' };
|
|
116
|
-
}
|
|
117
|
-
if (process.platform === 'win32') {
|
|
118
|
-
execSync('start cmd', { stdio: 'ignore' });
|
|
119
|
-
} else if (process.platform === 'darwin') {
|
|
120
|
-
execSync('open -a Terminal', { stdio: 'ignore' });
|
|
121
|
-
} else {
|
|
122
|
-
execSync('gnome-terminal &', { stdio: 'ignore' });
|
|
123
|
-
}
|
|
124
|
-
return { ok: true };
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
// Pesquisar na web
|
|
128
|
-
function webSearch(query) {
|
|
129
|
-
const encoded = encodeURIComponent(query);
|
|
130
|
-
const url = `https://www.google.com/search?q=${encoded}`;
|
|
131
|
-
|
|
132
|
-
if (isTermux()) {
|
|
133
|
-
try {
|
|
134
|
-
execSync(`termux-open-url "${url}"`, { stdio: 'ignore' });
|
|
135
|
-
return { ok: true };
|
|
136
|
-
} catch (e) {
|
|
137
|
-
try {
|
|
138
|
-
execSync(`am start -a android.intent.action.VIEW -d "${url}"`, { stdio: 'ignore' });
|
|
139
|
-
return { ok: true };
|
|
140
|
-
} catch (e2) {
|
|
141
|
-
return { ok: false, error: e2.message };
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
if (process.platform === 'win32') {
|
|
146
|
-
execSync(`start "" "${url}"`, { stdio: 'ignore' });
|
|
147
|
-
} else if (process.platform === 'darwin') {
|
|
148
|
-
execSync(`open "${url}"`, { stdio: 'ignore' });
|
|
149
|
-
} else {
|
|
150
|
-
execSync(`xdg-open "${url}"`, { stdio: 'ignore' });
|
|
151
|
-
}
|
|
152
|
-
return { ok: true };
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
// Screenshot
|
|
156
|
-
function screenshot(savePath) {
|
|
157
|
-
const filename = savePath || path.join(os.tmpdir(), `screenshot-${Date.now()}.png`);
|
|
158
|
-
|
|
159
|
-
if (isTermux()) {
|
|
160
|
-
try {
|
|
161
|
-
// Android screencap
|
|
162
|
-
execSync(`screencap -p "${filename}"`, { stdio: 'ignore' });
|
|
163
|
-
return { ok: true, path: filename };
|
|
164
|
-
} catch (e) {
|
|
165
|
-
// Fallback: termux-api
|
|
166
|
-
try {
|
|
167
|
-
execSync(`termux-camera-photo -c 0 "${filename}"`, { stdio: 'ignore' });
|
|
168
|
-
return { ok: true, path: filename };
|
|
169
|
-
} catch (e2) {
|
|
170
|
-
return { ok: false, error: e2.message };
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
if (process.platform === 'win32') {
|
|
175
|
-
const ps = `Add-Type -AssemblyName System.Windows.Forms; Add-Type -AssemblyName System.Drawing; $b = New-Object System.Drawing.Bitmap([System.Windows.Forms.Screen]::PrimaryScreen.Bounds.Width, [System.Windows.Forms.Screen]::PrimaryScreen.Bounds.Height); $g = [System.Drawing.Graphics]::FromImage($b); $g.CopyFromScreen([System.Windows.Forms.Screen]::PrimaryScreen.Bounds.Location, [System.Drawing.Point]::Empty, $b.Size); $b.Save('${filename}'); $g.Dispose(); $b.Dispose()`;
|
|
176
|
-
execSync(`powershell -Command "${ps}"`, { stdio: 'ignore' });
|
|
177
|
-
} else if (process.platform === 'darwin') {
|
|
178
|
-
execSync(`screencapture -x "${filename}"`, { stdio: 'ignore' });
|
|
179
|
-
} else {
|
|
180
|
-
execSync(`gnome-screenshot -f "${filename}" || import -window root "${filename}"`, { stdio: 'ignore' });
|
|
181
|
-
}
|
|
182
|
-
return { ok: true, path: filename };
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
// Mover mouse (simulado via ADB no Android)
|
|
186
|
-
function moveMouse(x, y) {
|
|
187
|
-
if (isTermux()) {
|
|
188
|
-
try {
|
|
189
|
-
// Usar input tap como fallback se ADB não disponível
|
|
190
|
-
execSync(`input tap ${x} ${y}`, { stdio: 'ignore' });
|
|
191
|
-
return { ok: true, x, y };
|
|
192
|
-
} catch (e) {
|
|
193
|
-
return { ok: false, error: e.message };
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
// Desktop...
|
|
197
|
-
return { ok: true };
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
// Clicar
|
|
201
|
-
function clickMouse(x, y) {
|
|
202
|
-
return moveMouse(x, y); // No Android, tap = move + click
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
// Verificar permissões do Termux
|
|
206
|
-
function checkTermuxSetup() {
|
|
207
|
-
if (!isTermux()) return { ok: true };
|
|
208
|
-
|
|
209
|
-
const issues = [];
|
|
210
|
-
|
|
211
|
-
// Verificar storage
|
|
212
|
-
if (!fs.existsSync('/data/data/com.termux/files/home/storage')) {
|
|
213
|
-
issues.push('Execute: termux-setup-storage');
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
// Verificar termux-api
|
|
217
|
-
try {
|
|
218
|
-
execSync('which termux-open', { stdio: 'ignore' });
|
|
219
|
-
} catch {
|
|
220
|
-
issues.push('Instale: pkg install termux-api');
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
return {
|
|
224
|
-
ok: issues.length === 0,
|
|
225
|
-
issues,
|
|
226
|
-
message: issues.length ? 'Configurações necessárias:' : 'Termux configurado!'
|
|
227
|
-
};
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
const fs = require('fs');
|
|
231
|
-
|
|
232
|
-
module.exports = {
|
|
233
|
-
isTermux,
|
|
234
|
-
isAndroid,
|
|
235
|
-
getProjectsDir,
|
|
236
|
-
getConfigDir,
|
|
237
|
-
openBrowser,
|
|
238
|
-
openApp,
|
|
239
|
-
openTerminal,
|
|
240
|
-
webSearch,
|
|
241
|
-
screenshot,
|
|
242
|
-
moveMouse,
|
|
243
|
-
clickMouse,
|
|
244
|
-
checkTermuxSetup,
|
|
245
|
-
};
|