uwonbot 1.1.8 → 1.2.0
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 +139 -0
package/package.json
CHANGED
package/src/agent.js
CHANGED
|
@@ -93,6 +93,13 @@ async function loadNativeModules() {
|
|
|
93
93
|
}
|
|
94
94
|
|
|
95
95
|
async function getScreenSize() {
|
|
96
|
+
if (platform === 'darwin') {
|
|
97
|
+
try {
|
|
98
|
+
const { stdout } = await execAsync(`osascript -e 'tell application "Finder" to get bounds of window of desktop' 2>/dev/null || osascript -e 'tell application "System Events" to get {0, 0, 1920, 1080}'`);
|
|
99
|
+
const nums = stdout.trim().split(/[,\s]+/).map(Number);
|
|
100
|
+
if (nums.length >= 4) return { width: nums[2], height: nums[3] };
|
|
101
|
+
} catch {}
|
|
102
|
+
}
|
|
96
103
|
if (robot?.screen?.width) {
|
|
97
104
|
const w = await robot.screen.width();
|
|
98
105
|
const h = await robot.screen.height();
|
|
@@ -221,6 +228,118 @@ async function takeScreenshot() {
|
|
|
221
228
|
}
|
|
222
229
|
}
|
|
223
230
|
|
|
231
|
+
// ─── Window Management ───
|
|
232
|
+
|
|
233
|
+
async function windowFrontmost() {
|
|
234
|
+
try {
|
|
235
|
+
if (platform === 'darwin') {
|
|
236
|
+
const { stdout } = await execAsync(`osascript -e '
|
|
237
|
+
tell application "System Events"
|
|
238
|
+
set fp to first application process whose frontmost is true
|
|
239
|
+
set appName to name of fp
|
|
240
|
+
try
|
|
241
|
+
set w to front window of fp
|
|
242
|
+
set {px, py} to position of w
|
|
243
|
+
set {sw, sh} to size of w
|
|
244
|
+
return appName & "||" & px & "," & py & "||" & sw & "," & sh
|
|
245
|
+
end try
|
|
246
|
+
return appName & "||0,0||800,600"
|
|
247
|
+
end tell'`);
|
|
248
|
+
const parts = stdout.trim().split('||');
|
|
249
|
+
const [px, py] = (parts[1] || '0,0').split(',').map(Number);
|
|
250
|
+
const [sw, sh] = (parts[2] || '800,600').split(',').map(Number);
|
|
251
|
+
return { app: parts[0], x: px, y: py, width: sw, height: sh };
|
|
252
|
+
} else if (platform === 'win32') {
|
|
253
|
+
const { stdout } = await execAsync(`powershell -Command "[Console]::OutputEncoding = [Text.Encoding]::UTF8; Add-Type -TypeDefinition 'using System; using System.Runtime.InteropServices; public class Win { [DllImport(\\\"user32.dll\\\")] public static extern IntPtr GetForegroundWindow(); [DllImport(\\\"user32.dll\\\")] public static extern bool GetWindowRect(IntPtr h, out RECT r); [StructLayout(LayoutKind.Sequential)] public struct RECT { public int L,T,R,B; } }'; $h=[Win]::GetForegroundWindow(); $r=New-Object Win+RECT; [Win]::GetWindowRect($h,[ref]$r); Write-Output ($r.L.ToString()+','+$r.T.ToString()+'||'+($r.R-$r.L).ToString()+','+($r.B-$r.T).ToString())"`);
|
|
254
|
+
const parts = stdout.trim().split('||');
|
|
255
|
+
const [px, py] = (parts[0] || '0,0').split(',').map(Number);
|
|
256
|
+
const [sw, sh] = (parts[1] || '800,600').split(',').map(Number);
|
|
257
|
+
return { app: 'foreground', x: px, y: py, width: sw, height: sh };
|
|
258
|
+
}
|
|
259
|
+
return { app: 'unknown', x: 0, y: 0, width: 800, height: 600 };
|
|
260
|
+
} catch (e) { return { app: 'unknown', x: 0, y: 0, width: 800, height: 600 }; }
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
async function windowMove(app, x, y) {
|
|
264
|
+
try {
|
|
265
|
+
if (platform === 'darwin') {
|
|
266
|
+
const script = app
|
|
267
|
+
? `tell application "System Events" to tell process "${app}" to set position of front window to {${Math.round(x)}, ${Math.round(y)}}`
|
|
268
|
+
: `tell application "System Events"
|
|
269
|
+
set fp to first application process whose frontmost is true
|
|
270
|
+
set position of front window of fp to {${Math.round(x)}, ${Math.round(y)}}
|
|
271
|
+
end tell`;
|
|
272
|
+
await execAsync(`osascript -e '${script}'`);
|
|
273
|
+
} else if (platform === 'win32') {
|
|
274
|
+
await execAsync(`powershell -Command "Add-Type -TypeDefinition 'using System; using System.Runtime.InteropServices; public class WM { [DllImport(\\\"user32.dll\\\")] public static extern IntPtr GetForegroundWindow(); [DllImport(\\\"user32.dll\\\")] public static extern bool MoveWindow(IntPtr h,int x,int y,int w,int h2,bool r); [DllImport(\\\"user32.dll\\\")] public static extern bool GetWindowRect(IntPtr h,out RECT r); [StructLayout(LayoutKind.Sequential)] public struct RECT{public int L,T,R,B;} }'; $h=[WM]::GetForegroundWindow(); $r=New-Object WM+RECT; [WM]::GetWindowRect($h,[ref]$r); [WM]::MoveWindow($h,${Math.round(x)},${Math.round(y)},$r.R-$r.L,$r.B-$r.T,$true)"`);
|
|
275
|
+
}
|
|
276
|
+
return true;
|
|
277
|
+
} catch { return false; }
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
async function windowResize(app, w, h) {
|
|
281
|
+
try {
|
|
282
|
+
if (platform === 'darwin') {
|
|
283
|
+
const script = app
|
|
284
|
+
? `tell application "System Events" to tell process "${app}" to set size of front window to {${Math.round(w)}, ${Math.round(h)}}`
|
|
285
|
+
: `tell application "System Events"
|
|
286
|
+
set fp to first application process whose frontmost is true
|
|
287
|
+
set size of front window of fp to {${Math.round(w)}, ${Math.round(h)}}
|
|
288
|
+
end tell`;
|
|
289
|
+
await execAsync(`osascript -e '${script}'`);
|
|
290
|
+
} else if (platform === 'win32') {
|
|
291
|
+
await execAsync(`powershell -Command "Add-Type -TypeDefinition 'using System; using System.Runtime.InteropServices; public class WR { [DllImport(\\\"user32.dll\\\")] public static extern IntPtr GetForegroundWindow(); [DllImport(\\\"user32.dll\\\")] public static extern bool MoveWindow(IntPtr h,int x,int y,int w,int h2,bool r); [DllImport(\\\"user32.dll\\\")] public static extern bool GetWindowRect(IntPtr h,out RECT r); [StructLayout(LayoutKind.Sequential)] public struct RECT{public int L,T,R,B;} }'; $h=[WR]::GetForegroundWindow(); $r=New-Object WR+RECT; [WR]::GetWindowRect($h,[ref]$r); [WR]::MoveWindow($h,$r.L,$r.T,${Math.round(w)},${Math.round(h)},$true)"`);
|
|
292
|
+
}
|
|
293
|
+
return true;
|
|
294
|
+
} catch { return false; }
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
async function windowClose(app) {
|
|
298
|
+
try {
|
|
299
|
+
if (platform === 'darwin') {
|
|
300
|
+
const script = app
|
|
301
|
+
? `tell application "${app}" to close front window`
|
|
302
|
+
: `tell application "System Events"
|
|
303
|
+
set fp to first application process whose frontmost is true
|
|
304
|
+
tell fp to click (first button of front window whose subrole is "AXCloseButton")
|
|
305
|
+
end tell`;
|
|
306
|
+
await execAsync(`osascript -e '${script}'`);
|
|
307
|
+
} else if (platform === 'win32') {
|
|
308
|
+
await execAsync(`powershell -Command "Add-Type -TypeDefinition 'using System; using System.Runtime.InteropServices; public class WC { [DllImport(\\\"user32.dll\\\")] public static extern IntPtr GetForegroundWindow(); [DllImport(\\\"user32.dll\\\")] public static extern bool PostMessage(IntPtr h,uint m,IntPtr w,IntPtr l); }'; [WC]::PostMessage([WC]::GetForegroundWindow(),0x0010,[IntPtr]::Zero,[IntPtr]::Zero)"`);
|
|
309
|
+
}
|
|
310
|
+
return true;
|
|
311
|
+
} catch { return false; }
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
async function windowList() {
|
|
315
|
+
try {
|
|
316
|
+
if (platform === 'darwin') {
|
|
317
|
+
const { stdout } = await execAsync(`osascript -e '
|
|
318
|
+
set output to ""
|
|
319
|
+
tell application "System Events"
|
|
320
|
+
repeat with p in (every application process whose visible is true)
|
|
321
|
+
set pName to name of p
|
|
322
|
+
try
|
|
323
|
+
repeat with w in (every window of p)
|
|
324
|
+
set {px, py} to position of w
|
|
325
|
+
set {sw, sh} to size of w
|
|
326
|
+
set output to output & pName & "||" & px & "," & py & "||" & sw & "," & sh & "\\n"
|
|
327
|
+
end repeat
|
|
328
|
+
end try
|
|
329
|
+
end repeat
|
|
330
|
+
end tell
|
|
331
|
+
return output'`);
|
|
332
|
+
return stdout.trim().split('\n').filter(Boolean).map(line => {
|
|
333
|
+
const [app, pos, sz] = line.split('||');
|
|
334
|
+
const [x, y] = (pos || '0,0').split(',').map(Number);
|
|
335
|
+
const [w, h] = (sz || '800,600').split(',').map(Number);
|
|
336
|
+
return { app, x, y, width: w, height: h };
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
return [];
|
|
340
|
+
} catch { return []; }
|
|
341
|
+
}
|
|
342
|
+
|
|
224
343
|
async function openApp(appName) {
|
|
225
344
|
const name = appName.toLowerCase();
|
|
226
345
|
try {
|
|
@@ -312,6 +431,26 @@ async function handleCommand(msg) {
|
|
|
312
431
|
case 'open_terminal':
|
|
313
432
|
const termOk = await openTerminalWithChat(cmd.assistantName || cmd.name);
|
|
314
433
|
return { ok: termOk };
|
|
434
|
+
case 'window_frontmost': {
|
|
435
|
+
const wf = await windowFrontmost();
|
|
436
|
+
return { ok: true, ...wf };
|
|
437
|
+
}
|
|
438
|
+
case 'window_move': {
|
|
439
|
+
const wm = await windowMove(cmd.app, cmd.x, cmd.y);
|
|
440
|
+
return { ok: wm };
|
|
441
|
+
}
|
|
442
|
+
case 'window_resize': {
|
|
443
|
+
const wr = await windowResize(cmd.app, cmd.w, cmd.h);
|
|
444
|
+
return { ok: wr };
|
|
445
|
+
}
|
|
446
|
+
case 'window_close': {
|
|
447
|
+
const wc = await windowClose(cmd.app);
|
|
448
|
+
return { ok: wc };
|
|
449
|
+
}
|
|
450
|
+
case 'window_list': {
|
|
451
|
+
const wl = await windowList();
|
|
452
|
+
return { ok: true, windows: wl };
|
|
453
|
+
}
|
|
315
454
|
case 'ping':
|
|
316
455
|
return { ok: true, pong: true };
|
|
317
456
|
default:
|