primocode 1.1.0 → 4.1.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 +146 -67
- package/bin/primocode.js +573 -388
- package/lib/act.js +500 -495
- package/lib/api.js +39 -39
- package/lib/browser.js +492 -492
- package/lib/config.js +76 -71
- package/lib/mascot.js +121 -0
- package/lib/memory.js +179 -0
- package/lib/mouse.js +144 -0
- package/lib/platform.js +245 -0
- package/lib/tools.js +503 -503
- package/lib/ui.js +104 -132
- package/package.json +40 -37
- package/lib/jarvis.js +0 -68
package/lib/config.js
CHANGED
|
@@ -1,71 +1,76 @@
|
|
|
1
|
-
// Configuracao PrimoCode
|
|
2
|
-
|
|
3
|
-
'use strict';
|
|
4
|
-
|
|
5
|
-
const fs = require('fs');
|
|
6
|
-
const path = require('path');
|
|
7
|
-
const os = require('os');
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
1
|
+
// Configuracao PrimoCode — Cross-Platform (Windows, macOS, Linux, Termux)
|
|
2
|
+
|
|
3
|
+
'use strict';
|
|
4
|
+
|
|
5
|
+
const fs = require('fs');
|
|
6
|
+
const path = require('path');
|
|
7
|
+
const os = require('os');
|
|
8
|
+
|
|
9
|
+
// Detecta Termux (Android)
|
|
10
|
+
function isTermux() {
|
|
11
|
+
return process.env.TERMUX_VERSION !== undefined ||
|
|
12
|
+
process.env.PREFIX?.includes('termux') ||
|
|
13
|
+
process.env.HOME?.includes('termux');
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// Diretório base
|
|
17
|
+
const HOME = isTermux() ? '/data/data/com.termux/files/home' : os.homedir();
|
|
18
|
+
const CONFIG_DIR = path.join(HOME, '.primocode');
|
|
19
|
+
const CONFIG_FILE = path.join(CONFIG_DIR, 'config.json');
|
|
20
|
+
const HISTORY_FILE = path.join(CONFIG_DIR, 'history.jsonl');
|
|
21
|
+
|
|
22
|
+
function ensureDir() {
|
|
23
|
+
try { fs.mkdirSync(CONFIG_DIR, { recursive: true }); } catch {}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Mapeamento de modos para modelos do servidor
|
|
27
|
+
const MODEL_MAP = {
|
|
28
|
+
'Primo Code': 'main',
|
|
29
|
+
'Chat': 'fast',
|
|
30
|
+
'chat': 'fast',
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
// Resolve o modelo correto baseado no modo
|
|
34
|
+
function resolveModel(mode) {
|
|
35
|
+
return MODEL_MAP[mode] || MODEL_MAP['Primo Code'];
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function loadConfig() {
|
|
39
|
+
ensureDir();
|
|
40
|
+
let file = {};
|
|
41
|
+
try {
|
|
42
|
+
if (fs.existsSync(CONFIG_FILE)) file = JSON.parse(fs.readFileSync(CONFIG_FILE, 'utf8'));
|
|
43
|
+
} catch { file = {}; }
|
|
44
|
+
|
|
45
|
+
const mode = process.env.PRIMOCODE_MODE || file.mode || 'Primo Code';
|
|
46
|
+
const model = resolveModel(mode);
|
|
47
|
+
|
|
48
|
+
return {
|
|
49
|
+
server: process.env.PRIMOCODE_SERVER || file.server || 'https://primocode-server.onrender.com',
|
|
50
|
+
model: model,
|
|
51
|
+
mode: mode,
|
|
52
|
+
autoApply: file.autoApply === true,
|
|
53
|
+
isTermux: isTermux(),
|
|
54
|
+
_file: file,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function saveConfig(partial) {
|
|
59
|
+
ensureDir();
|
|
60
|
+
const cur = (() => { try { return JSON.parse(fs.readFileSync(CONFIG_FILE, 'utf8')); } catch { return {}; } })();
|
|
61
|
+
const next = { ...cur, ...partial };
|
|
62
|
+
if (partial.mode && MODEL_MAP[partial.mode]) {
|
|
63
|
+
next.model = MODEL_MAP[partial.mode];
|
|
64
|
+
}
|
|
65
|
+
fs.writeFileSync(CONFIG_FILE, JSON.stringify(next, null, 2), 'utf8');
|
|
66
|
+
return next;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function appendHistory(entry) {
|
|
70
|
+
ensureDir();
|
|
71
|
+
try {
|
|
72
|
+
fs.appendFileSync(HISTORY_FILE, JSON.stringify({ ts: Date.now(), ...entry }) + '\n', 'utf8');
|
|
73
|
+
} catch {}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
module.exports = { loadConfig, saveConfig, appendHistory, resolveModel, isTermux, CONFIG_DIR, CONFIG_FILE, HISTORY_FILE, MODEL_MAP };
|
package/lib/mascot.js
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
// Mascote PrimoCode — animações ASCII conforme estado da IA
|
|
2
|
+
// Baseado no anexo do usuário: IDLE, THINKING, CODING, HAPPY
|
|
3
|
+
|
|
4
|
+
'use strict';
|
|
5
|
+
|
|
6
|
+
const c = require('./ui').c;
|
|
7
|
+
|
|
8
|
+
// Frames do mascote (cada estado tem múltiplos frames para animação)
|
|
9
|
+
const FRAMES = {
|
|
10
|
+
idle: [
|
|
11
|
+
` ╭─────────╮
|
|
12
|
+
│ ◠ ◠ │
|
|
13
|
+
│ ‿ │
|
|
14
|
+
╰─────────╯`,
|
|
15
|
+
` ╭─────────╮
|
|
16
|
+
│ ◠ ◠ │
|
|
17
|
+
│ ‿ │
|
|
18
|
+
╰─────────╯`,
|
|
19
|
+
],
|
|
20
|
+
thinking: [
|
|
21
|
+
` ╭─────────╮
|
|
22
|
+
│ ◠ ◠ │
|
|
23
|
+
│ ‿ │
|
|
24
|
+
╰────?────╯`,
|
|
25
|
+
` ╭─────────╮
|
|
26
|
+
│ ◡ ◠ │
|
|
27
|
+
│ ‿ │
|
|
28
|
+
╰────?────╯`,
|
|
29
|
+
` ╭─────────╮
|
|
30
|
+
│ ◠ ◡ │
|
|
31
|
+
│ ‿ │
|
|
32
|
+
╰────?────╯`,
|
|
33
|
+
],
|
|
34
|
+
coding: [
|
|
35
|
+
` ╭─────────╮
|
|
36
|
+
│ ◕ ◕ │
|
|
37
|
+
│ ‿ │
|
|
38
|
+
╰──⌨️─────╯`,
|
|
39
|
+
` ╭─────────╮
|
|
40
|
+
│ ◕ ◕ │
|
|
41
|
+
│ ‿ │
|
|
42
|
+
╰───⌨️────╯`,
|
|
43
|
+
` ╭─────────╮
|
|
44
|
+
│ ◕ ◕ │
|
|
45
|
+
│ ‿ │
|
|
46
|
+
╰────⌨️───╯`,
|
|
47
|
+
],
|
|
48
|
+
happy: [
|
|
49
|
+
` ╭─────────╮
|
|
50
|
+
│ ◠ ◠ │
|
|
51
|
+
│ ▽ │
|
|
52
|
+
╰─────────╯`,
|
|
53
|
+
` ╭─────────╮
|
|
54
|
+
│ ◡ ◡ │
|
|
55
|
+
│ ▽ │
|
|
56
|
+
╰─────────╯`,
|
|
57
|
+
],
|
|
58
|
+
searching: [
|
|
59
|
+
` ╭─────────╮
|
|
60
|
+
│ ◠ ◠ │
|
|
61
|
+
│ ‿ │
|
|
62
|
+
╰──🔍─────╯`,
|
|
63
|
+
` ╭─────────╮
|
|
64
|
+
│ ◠ ◠ │
|
|
65
|
+
│ ‿ │
|
|
66
|
+
╰───🔍────╯`,
|
|
67
|
+
],
|
|
68
|
+
mouse: [
|
|
69
|
+
` ╭─────────╮
|
|
70
|
+
│ ◠ ◠ │
|
|
71
|
+
│ ‿ │
|
|
72
|
+
╰──🖱️─────╯`,
|
|
73
|
+
` ╭─────────╮
|
|
74
|
+
│ ◠ ◠ │
|
|
75
|
+
│ ‿ │
|
|
76
|
+
╰────🖱️───╯`,
|
|
77
|
+
],
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
let currentState = 'idle';
|
|
81
|
+
let currentFrame = 0;
|
|
82
|
+
let animationInterval = null;
|
|
83
|
+
|
|
84
|
+
function render(state = 'idle', message = '') {
|
|
85
|
+
const frames = FRAMES[state] || FRAMES.idle;
|
|
86
|
+
const frame = frames[currentFrame % frames.length];
|
|
87
|
+
const label = message ? ` ${c.muted(message)}` : '';
|
|
88
|
+
return `\n${c.brand(frame)}${label}\n`;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function setState(state, message = '') {
|
|
92
|
+
currentState = state;
|
|
93
|
+
currentFrame = 0;
|
|
94
|
+
return render(state, message);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function startAnimation(state, message = '', intervalMs = 500) {
|
|
98
|
+
currentState = state;
|
|
99
|
+
currentFrame = 0;
|
|
100
|
+
if (animationInterval) clearInterval(animationInterval);
|
|
101
|
+
animationInterval = setInterval(() => {
|
|
102
|
+
currentFrame++;
|
|
103
|
+
process.stdout.write('\x1b[2A\x1b[0J'); // sobe 2 linhas e limpa
|
|
104
|
+
process.stdout.write(render(currentState, message));
|
|
105
|
+
}, intervalMs);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function stopAnimation() {
|
|
109
|
+
if (animationInterval) {
|
|
110
|
+
clearInterval(animationInterval);
|
|
111
|
+
animationInterval = null;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function nextFrame(state, message = '') {
|
|
116
|
+
currentState = state;
|
|
117
|
+
currentFrame++;
|
|
118
|
+
return render(state, message);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
module.exports = { render, setState, startAnimation, stopAnimation, nextFrame, FRAMES };
|
package/lib/memory.js
ADDED
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
// Sistema de Memória e Projetos do PrimoCode
|
|
2
|
+
//
|
|
3
|
+
// Estrutura de pastas:
|
|
4
|
+
// Windows: C:\primocode\
|
|
5
|
+
// Linux/Mac: ~/primocode/
|
|
6
|
+
// Termux/Android: /storage/shared/primocode/ (acessível pelo usuário)
|
|
7
|
+
// ├── memory.md ← Memória geral do usuário
|
|
8
|
+
// ├── projeto-1\ ← Pasta de projeto
|
|
9
|
+
// │ ├── index.html
|
|
10
|
+
// │ ├── style.css
|
|
11
|
+
// │ └── primocode-projeto-1.md ← Memória do projeto
|
|
12
|
+
// └── projeto-2\
|
|
13
|
+
// └── ...
|
|
14
|
+
|
|
15
|
+
'use strict';
|
|
16
|
+
|
|
17
|
+
const fs = require('fs');
|
|
18
|
+
const path = require('path');
|
|
19
|
+
const platform = require('./platform');
|
|
20
|
+
|
|
21
|
+
// Diretório principal de projetos (cross-platform)
|
|
22
|
+
const PRIMOCODE_DIR = platform.getProjectsDir();
|
|
23
|
+
const MEMORY_FILE = path.join(PRIMOCODE_DIR, 'memory.md');
|
|
24
|
+
|
|
25
|
+
function ensureDir(dir) {
|
|
26
|
+
try { fs.mkdirSync(dir, { recursive: true }); } catch {}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Inicializa a estrutura de pastas
|
|
30
|
+
function init() {
|
|
31
|
+
ensureDir(PRIMOCODE_DIR);
|
|
32
|
+
if (!fs.existsSync(MEMORY_FILE)) {
|
|
33
|
+
fs.writeFileSync(MEMORY_FILE, `# Memória PrimoCode
|
|
34
|
+
|
|
35
|
+
## Sobre o Usuário
|
|
36
|
+
- Nome:
|
|
37
|
+
- Preferências:
|
|
38
|
+
|
|
39
|
+
## Estilo de Resposta Preferido
|
|
40
|
+
- Código sempre em arquivos, nunca no chat
|
|
41
|
+
- Abrir automaticamente no navegador quando aplicável
|
|
42
|
+
- Pesquisar na web para garantir qualidade
|
|
43
|
+
|
|
44
|
+
## Projetos Anteriores
|
|
45
|
+
`, 'utf8');
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Carrega a memória geral
|
|
50
|
+
function loadMemory() {
|
|
51
|
+
init();
|
|
52
|
+
try {
|
|
53
|
+
return fs.readFileSync(MEMORY_FILE, 'utf8');
|
|
54
|
+
} catch {
|
|
55
|
+
return '';
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Salva na memória geral
|
|
60
|
+
function saveMemory(content) {
|
|
61
|
+
init();
|
|
62
|
+
fs.writeFileSync(MEMORY_FILE, content, 'utf8');
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Adiciona informação à memória
|
|
66
|
+
function appendMemory(section, info) {
|
|
67
|
+
const mem = loadMemory();
|
|
68
|
+
const sectionHeader = `## ${section}`;
|
|
69
|
+
const idx = mem.indexOf(sectionHeader);
|
|
70
|
+
if (idx >= 0) {
|
|
71
|
+
const before = mem.slice(0, idx + sectionHeader.length);
|
|
72
|
+
const after = mem.slice(idx + sectionHeader.length);
|
|
73
|
+
saveMemory(`${before}\n- ${info}${after}`);
|
|
74
|
+
} else {
|
|
75
|
+
saveMemory(`${mem}\n## ${section}\n- ${info}\n`);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Lista todos os projetos existentes
|
|
80
|
+
function listProjects() {
|
|
81
|
+
init();
|
|
82
|
+
try {
|
|
83
|
+
const entries = fs.readdirSync(PRIMOCODE_DIR, { withFileTypes: true });
|
|
84
|
+
return entries
|
|
85
|
+
.filter(e => e.isDirectory())
|
|
86
|
+
.map(e => e.name);
|
|
87
|
+
} catch {
|
|
88
|
+
return [];
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Cria um novo projeto (pasta + arquivo de memória)
|
|
93
|
+
function createProject(projectName) {
|
|
94
|
+
init();
|
|
95
|
+
const safeName = projectName.replace(/[^a-zA-Z0-9\-_]/g, '-').toLowerCase();
|
|
96
|
+
const projectDir = path.join(PRIMOCODE_DIR, safeName);
|
|
97
|
+
ensureDir(projectDir);
|
|
98
|
+
|
|
99
|
+
const projectMemoryFile = path.join(projectDir, `primocode-${safeName}.md`);
|
|
100
|
+
if (!fs.existsSync(projectMemoryFile)) {
|
|
101
|
+
fs.writeFileSync(projectMemoryFile, `# PrimoCode — ${projectName}
|
|
102
|
+
|
|
103
|
+
## Descrição
|
|
104
|
+
Projeto iniciado em ${new Date().toLocaleString('pt-BR')}
|
|
105
|
+
|
|
106
|
+
## Contexto
|
|
107
|
+
|
|
108
|
+
## Arquivos
|
|
109
|
+
|
|
110
|
+
## Decisões Técnicas
|
|
111
|
+
|
|
112
|
+
## Notas
|
|
113
|
+
`, 'utf8');
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Atualiza memória geral
|
|
117
|
+
appendMemory('Projetos Anteriores', `${safeName} — ${projectName} (${new Date().toLocaleDateString('pt-BR')})`);
|
|
118
|
+
|
|
119
|
+
return { dir: projectDir, name: safeName, memoryFile: projectMemoryFile };
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Carrega memória de um projeto
|
|
123
|
+
function loadProjectMemory(projectName) {
|
|
124
|
+
const safeName = projectName.replace(/[^a-zA-Z0-9\-_]/g, '-').toLowerCase();
|
|
125
|
+
const projectMemoryFile = path.join(PRIMOCODE_DIR, safeName, `primocode-${safeName}.md`);
|
|
126
|
+
try {
|
|
127
|
+
return fs.readFileSync(projectMemoryFile, 'utf8');
|
|
128
|
+
} catch {
|
|
129
|
+
return '';
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Salva memória de um projeto
|
|
134
|
+
function saveProjectMemory(projectName, content) {
|
|
135
|
+
const safeName = projectName.replace(/[^a-zA-Z0-9\-_]/g, '-').toLowerCase();
|
|
136
|
+
const projectDir = path.join(PRIMOCODE_DIR, safeName);
|
|
137
|
+
ensureDir(projectDir);
|
|
138
|
+
const projectMemoryFile = path.join(projectDir, `primocode-${safeName}.md`);
|
|
139
|
+
fs.writeFileSync(projectMemoryFile, content, 'utf8');
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Verifica se projeto existe
|
|
143
|
+
function projectExists(projectName) {
|
|
144
|
+
const safeName = projectName.replace(/[^a-zA-Z0-9\-_]/g, '-').toLowerCase();
|
|
145
|
+
return fs.existsSync(path.join(PRIMOCODE_DIR, safeName));
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// Salva arquivo em um projeto
|
|
149
|
+
function saveProjectFile(projectName, filename, content) {
|
|
150
|
+
const safeName = projectName.replace(/[^a-zA-Z0-9\-_]/g, '-').toLowerCase();
|
|
151
|
+
const projectDir = path.join(PRIMOCODE_DIR, safeName);
|
|
152
|
+
ensureDir(projectDir);
|
|
153
|
+
const filePath = path.join(projectDir, filename);
|
|
154
|
+
fs.writeFileSync(filePath, content, 'utf8');
|
|
155
|
+
|
|
156
|
+
// Atualiza memória do projeto
|
|
157
|
+
const mem = loadProjectMemory(safeName);
|
|
158
|
+
if (!mem.includes(filename)) {
|
|
159
|
+
const updated = mem.replace('## Arquivos', `## Arquivos\n- ${filename}`);
|
|
160
|
+
saveProjectMemory(safeName, updated);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
return filePath;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
module.exports = {
|
|
167
|
+
PRIMOCODE_DIR,
|
|
168
|
+
MEMORY_FILE,
|
|
169
|
+
init,
|
|
170
|
+
loadMemory,
|
|
171
|
+
saveMemory,
|
|
172
|
+
appendMemory,
|
|
173
|
+
listProjects,
|
|
174
|
+
createProject,
|
|
175
|
+
loadProjectMemory,
|
|
176
|
+
saveProjectMemory,
|
|
177
|
+
projectExists,
|
|
178
|
+
saveProjectFile,
|
|
179
|
+
};
|
package/lib/mouse.js
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
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
|
+
};
|