uwonbot 1.2.2 → 1.2.4
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/package.json +1 -1
- package/src/agent.js +113 -47
package/package.json
CHANGED
package/src/agent.js
CHANGED
|
@@ -85,17 +85,21 @@ async function loadNativeModules() {
|
|
|
85
85
|
}
|
|
86
86
|
console.log(chalk.green(' ✓ nut-js loaded (mouse/keyboard control)'));
|
|
87
87
|
if (!accessOk) {
|
|
88
|
-
console.log(chalk.yellow(' ⚠ 접근성 권한이 없어
|
|
88
|
+
console.log(chalk.yellow(' ⚠ 접근성 권한이 없어 CoreGraphics 폴백을 사용합니다.'));
|
|
89
89
|
}
|
|
90
|
-
} catch {
|
|
90
|
+
} catch (nutErr) {
|
|
91
91
|
try {
|
|
92
92
|
const rjs = await import('robotjs');
|
|
93
93
|
robot = rjs.default || rjs;
|
|
94
94
|
console.log(chalk.green(' ✓ robotjs loaded (mouse/keyboard control)'));
|
|
95
95
|
} catch {
|
|
96
|
-
console.log(chalk.yellow(' ⚠ No mouse/keyboard module found.'));
|
|
97
|
-
console.log(chalk.yellow(' Install: npm install -g @nut-tree-fork/nut-js'));
|
|
98
96
|
robot = null;
|
|
97
|
+
if (platform === 'darwin') {
|
|
98
|
+
console.log(chalk.green(' ✓ CoreGraphics 직접 제어 모드 (macOS 네이티브)'));
|
|
99
|
+
} else {
|
|
100
|
+
console.log(chalk.yellow(' ⚠ No mouse/keyboard module found.'));
|
|
101
|
+
console.log(chalk.yellow(' Install: npm install -g @nut-tree-fork/nut-js'));
|
|
102
|
+
}
|
|
99
103
|
}
|
|
100
104
|
}
|
|
101
105
|
|
|
@@ -129,10 +133,25 @@ async function getScreenSize() {
|
|
|
129
133
|
return { width: 1920, height: 1080 };
|
|
130
134
|
}
|
|
131
135
|
|
|
136
|
+
async function cgMoveMouse(px, py) {
|
|
137
|
+
await execAsync(`osascript -l JavaScript -e 'ObjC.import("CoreGraphics"); $.CGWarpMouseCursorPosition($.CGPointMake(${px}, ${py}))'`);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
async function cgMouseEvent(eventType, px, py, mouseButton = 0) {
|
|
141
|
+
const script = `ObjC.import("CoreGraphics");
|
|
142
|
+
var pt = $.CGPointMake(${px}, ${py});
|
|
143
|
+
var e = $.CGEventCreateMouseEvent($(), ${eventType}, pt, ${mouseButton});
|
|
144
|
+
$.CGEventPost($.kCGHIDEventTap, e);`;
|
|
145
|
+
await execAsync(`osascript -l JavaScript -e '${script.replace(/\n/g, ' ')}'`);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
let _lastKnownPos = { x: 960, y: 540 };
|
|
149
|
+
|
|
132
150
|
async function moveMouse(x, y) {
|
|
133
151
|
const screen = await getScreenSize();
|
|
134
152
|
const px = Math.round(x * screen.width);
|
|
135
153
|
const py = Math.round(y * screen.height);
|
|
154
|
+
_lastKnownPos = { x: px, y: py };
|
|
136
155
|
|
|
137
156
|
try {
|
|
138
157
|
if (robot?.mouse?.setPosition) {
|
|
@@ -143,9 +162,11 @@ async function moveMouse(x, y) {
|
|
|
143
162
|
robot.moveMouse(px, py);
|
|
144
163
|
return;
|
|
145
164
|
}
|
|
146
|
-
} catch {
|
|
165
|
+
} catch (e) {
|
|
166
|
+
console.log(chalk.gray(` [mouse] nut-js fallback: ${e.message}`));
|
|
167
|
+
}
|
|
147
168
|
if (platform === 'darwin') {
|
|
148
|
-
try { await
|
|
169
|
+
try { await cgMoveMouse(px, py); } catch {}
|
|
149
170
|
}
|
|
150
171
|
}
|
|
151
172
|
|
|
@@ -161,39 +182,86 @@ async function mouseClick(button = 'left', double = false) {
|
|
|
161
182
|
robot.mouseClick(button, double);
|
|
162
183
|
return;
|
|
163
184
|
}
|
|
164
|
-
} catch {
|
|
185
|
+
} catch (e) {
|
|
186
|
+
console.log(chalk.gray(` [click] nut-js fallback: ${e.message}`));
|
|
187
|
+
}
|
|
165
188
|
if (platform === 'darwin') {
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
189
|
+
try {
|
|
190
|
+
const { x, y } = _lastKnownPos;
|
|
191
|
+
if (button === 'right') {
|
|
192
|
+
await cgMouseEvent('$.kCGEventRightMouseDown', x, y, '$.kCGMouseButtonRight');
|
|
193
|
+
await cgMouseEvent('$.kCGEventRightMouseUp', x, y, '$.kCGMouseButtonRight');
|
|
194
|
+
} else {
|
|
195
|
+
await cgMouseEvent('$.kCGEventLeftMouseDown', x, y, 0);
|
|
196
|
+
await cgMouseEvent('$.kCGEventLeftMouseUp', x, y, 0);
|
|
197
|
+
if (double) {
|
|
198
|
+
await new Promise(r => setTimeout(r, 50));
|
|
199
|
+
await cgMouseEvent('$.kCGEventLeftMouseDown', x, y, 0);
|
|
200
|
+
await cgMouseEvent('$.kCGEventLeftMouseUp', x, y, 0);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
} catch {}
|
|
169
204
|
}
|
|
170
205
|
}
|
|
171
206
|
|
|
172
207
|
async function mouseDown(button = 'left') {
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
208
|
+
try {
|
|
209
|
+
if (robot?.mouse?.pressButton) {
|
|
210
|
+
const { Button } = await import('@nut-tree-fork/nut-js');
|
|
211
|
+
await robot.mouse.pressButton(button === 'right' ? Button.RIGHT : Button.LEFT);
|
|
212
|
+
return;
|
|
213
|
+
} else if (robot?.mouseToggle) {
|
|
214
|
+
robot.mouseToggle('down', button);
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
} catch {}
|
|
218
|
+
if (platform === 'darwin') {
|
|
219
|
+
const { x, y } = _lastKnownPos;
|
|
220
|
+
try {
|
|
221
|
+
if (button === 'right') await cgMouseEvent('$.kCGEventRightMouseDown', x, y, '$.kCGMouseButtonRight');
|
|
222
|
+
else await cgMouseEvent('$.kCGEventLeftMouseDown', x, y, 0);
|
|
223
|
+
} catch {}
|
|
178
224
|
}
|
|
179
225
|
}
|
|
180
226
|
|
|
181
227
|
async function mouseUp(button = 'left') {
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
228
|
+
try {
|
|
229
|
+
if (robot?.mouse?.releaseButton) {
|
|
230
|
+
const { Button } = await import('@nut-tree-fork/nut-js');
|
|
231
|
+
await robot.mouse.releaseButton(button === 'right' ? Button.RIGHT : Button.LEFT);
|
|
232
|
+
return;
|
|
233
|
+
} else if (robot?.mouseToggle) {
|
|
234
|
+
robot.mouseToggle('up', button);
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
} catch {}
|
|
238
|
+
if (platform === 'darwin') {
|
|
239
|
+
const { x, y } = _lastKnownPos;
|
|
240
|
+
try {
|
|
241
|
+
if (button === 'right') await cgMouseEvent('$.kCGEventRightMouseUp', x, y, '$.kCGMouseButtonRight');
|
|
242
|
+
else await cgMouseEvent('$.kCGEventLeftMouseUp', x, y, 0);
|
|
243
|
+
} catch {}
|
|
187
244
|
}
|
|
188
245
|
}
|
|
189
246
|
|
|
190
247
|
async function mouseScroll(dx, dy) {
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
248
|
+
try {
|
|
249
|
+
if (robot?.mouse?.scrollDown && robot?.mouse?.scrollUp) {
|
|
250
|
+
const amount = Math.abs(dy);
|
|
251
|
+
if (dy > 0) await robot.mouse.scrollDown(amount);
|
|
252
|
+
else await robot.mouse.scrollUp(amount);
|
|
253
|
+
return;
|
|
254
|
+
} else if (robot?.scrollMouse) {
|
|
255
|
+
robot.scrollMouse(dx, dy);
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
} catch {}
|
|
259
|
+
if (platform === 'darwin') {
|
|
260
|
+
const lines = Math.round(dy / 10) || (dy > 0 ? 1 : -1);
|
|
261
|
+
try {
|
|
262
|
+
const script = `ObjC.import("CoreGraphics"); var e = $.CGEventCreateScrollWheelEvent($(), 0, 1, ${-lines}); $.CGEventPost($.kCGHIDEventTap, e);`;
|
|
263
|
+
await execAsync(`osascript -l JavaScript -e '${script}'`);
|
|
264
|
+
} catch {}
|
|
197
265
|
}
|
|
198
266
|
}
|
|
199
267
|
|
|
@@ -207,10 +275,18 @@ async function mouseDrag(fromX, fromY, toX, toY) {
|
|
|
207
275
|
}
|
|
208
276
|
|
|
209
277
|
async function typeText(text) {
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
278
|
+
try {
|
|
279
|
+
if (robot?.keyboard?.type) {
|
|
280
|
+
await robot.keyboard.type(text);
|
|
281
|
+
return;
|
|
282
|
+
} else if (robot?.typeString) {
|
|
283
|
+
robot.typeString(text);
|
|
284
|
+
return;
|
|
285
|
+
}
|
|
286
|
+
} catch {}
|
|
287
|
+
if (platform === 'darwin') {
|
|
288
|
+
const escaped = text.replace(/'/g, "'\\''").replace(/"/g, '\\"');
|
|
289
|
+
try { await execAsync(`osascript -e 'tell application "System Events" to keystroke "${escaped}"'`); } catch {}
|
|
214
290
|
}
|
|
215
291
|
}
|
|
216
292
|
|
|
@@ -513,10 +589,10 @@ async function openWebAssistant(assistantId) {
|
|
|
513
589
|
|
|
514
590
|
async function activateAllAssistants(assistants) {
|
|
515
591
|
const opened = [];
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
592
|
+
const first = assistants[0];
|
|
593
|
+
if (first) {
|
|
594
|
+
await openWebAssistant(first.id);
|
|
595
|
+
opened.push({ name: first.name, mode: 'web' });
|
|
520
596
|
}
|
|
521
597
|
return opened;
|
|
522
598
|
}
|
|
@@ -632,19 +708,9 @@ export async function startAgent(port = 9876, options = {}) {
|
|
|
632
708
|
return;
|
|
633
709
|
}
|
|
634
710
|
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
console.log(chalk.gray(` ✓ ${o.name} (${o.mode})`));
|
|
639
|
-
});
|
|
640
|
-
|
|
641
|
-
const geminiKey = userAssistants.find(a => a.apiKey)?.apiKey;
|
|
642
|
-
if (geminiKey) {
|
|
643
|
-
await listenForName(userAssistants, geminiKey);
|
|
644
|
-
} else {
|
|
645
|
-
console.log(chalk.gray(' → 모든 비서가 활성 상태로 유지됩니다.'));
|
|
646
|
-
console.log(chalk.gray(' (비서 이름을 말해 선택하려면 API 키가 필요합니다)'));
|
|
647
|
-
}
|
|
711
|
+
const first = userAssistants[0];
|
|
712
|
+
console.log(chalk.green(` → ${first.name} 웹 실행 (비서 ${userAssistants.length}개 중 첫 번째)`));
|
|
713
|
+
await openWebAssistant(first.id);
|
|
648
714
|
});
|
|
649
715
|
await clapListener.start();
|
|
650
716
|
console.log('');
|