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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/agent.js +139 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "uwonbot",
3
- "version": "1.1.8",
3
+ "version": "1.2.0",
4
4
  "description": "Uwonbot AI Assistant CLI — Your AI controls your computer",
5
5
  "main": "src/index.js",
6
6
  "bin": {
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: