@intentic/desktop-automation 1.325.0 → 1.327.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 (83) hide show
  1. package/README.md +37 -8
  2. package/dist/actions.d.ts +21 -0
  3. package/dist/actions.d.ts.map +1 -0
  4. package/dist/actions.js +76 -0
  5. package/dist/actions.js.map +1 -0
  6. package/dist/cua.d.ts +49 -0
  7. package/dist/cua.d.ts.map +1 -0
  8. package/dist/cua.js +315 -0
  9. package/dist/cua.js.map +1 -0
  10. package/dist/frames.d.ts +42 -0
  11. package/dist/frames.d.ts.map +1 -0
  12. package/dist/frames.js +91 -0
  13. package/dist/frames.js.map +1 -0
  14. package/dist/index.d.ts +13 -4
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +97 -11
  17. package/dist/index.js.map +1 -1
  18. package/dist/{apps-linux.d.ts → linux/apps-linux.d.ts} +1 -1
  19. package/dist/linux/apps-linux.d.ts.map +1 -0
  20. package/dist/{apps-linux.js → linux/apps-linux.js} +10 -9
  21. package/dist/linux/apps-linux.js.map +1 -0
  22. package/dist/{input-linux.d.ts → linux/input-linux.d.ts} +2 -1
  23. package/dist/linux/input-linux.d.ts.map +1 -0
  24. package/dist/{input-linux.js → linux/input-linux.js} +10 -5
  25. package/dist/linux/input-linux.js.map +1 -0
  26. package/dist/parse.d.ts +9 -1
  27. package/dist/parse.d.ts.map +1 -1
  28. package/dist/parse.js +120 -1
  29. package/dist/parse.js.map +1 -1
  30. package/dist/png.d.ts +11 -0
  31. package/dist/png.d.ts.map +1 -0
  32. package/dist/png.js +348 -0
  33. package/dist/png.js.map +1 -0
  34. package/dist/run.d.ts +8 -1
  35. package/dist/run.d.ts.map +1 -1
  36. package/dist/run.js +10 -5
  37. package/dist/run.js.map +1 -1
  38. package/dist/screen.d.ts +4 -2
  39. package/dist/screen.d.ts.map +1 -1
  40. package/dist/screen.js +56 -15
  41. package/dist/screen.js.map +1 -1
  42. package/dist/types.d.ts +38 -7
  43. package/dist/types.d.ts.map +1 -1
  44. package/dist/types.js.map +1 -1
  45. package/dist/view.d.ts +46 -0
  46. package/dist/view.d.ts.map +1 -0
  47. package/dist/view.js +114 -0
  48. package/dist/view.js.map +1 -0
  49. package/dist/{apps-windows.d.ts → windows/apps-windows.d.ts} +3 -1
  50. package/dist/windows/apps-windows.d.ts.map +1 -0
  51. package/dist/{apps-windows.js → windows/apps-windows.js} +13 -7
  52. package/dist/windows/apps-windows.js.map +1 -0
  53. package/dist/windows/elements-windows.d.ts +8 -0
  54. package/dist/windows/elements-windows.d.ts.map +1 -0
  55. package/dist/windows/elements-windows.js +223 -0
  56. package/dist/windows/elements-windows.js.map +1 -0
  57. package/dist/{input-windows.d.ts → windows/input-windows.d.ts} +2 -1
  58. package/dist/windows/input-windows.d.ts.map +1 -0
  59. package/dist/{input-windows.js → windows/input-windows.js} +16 -13
  60. package/dist/windows/input-windows.js.map +1 -0
  61. package/dist/{notice-windows.d.ts → windows/notice-windows.d.ts} +1 -1
  62. package/dist/windows/notice-windows.d.ts.map +1 -0
  63. package/dist/{notice-windows.js → windows/notice-windows.js} +1 -1
  64. package/dist/windows/notice-windows.js.map +1 -0
  65. package/dist/windows/powershell.d.ts +2 -0
  66. package/dist/windows/powershell.d.ts.map +1 -0
  67. package/dist/windows/powershell.js +2 -0
  68. package/dist/windows/powershell.js.map +1 -0
  69. package/dist/windows/windows-dpi.d.ts +2 -0
  70. package/dist/windows/windows-dpi.d.ts.map +1 -0
  71. package/dist/windows/windows-dpi.js +5 -0
  72. package/dist/windows/windows-dpi.js.map +1 -0
  73. package/package.json +4 -3
  74. package/dist/apps-linux.d.ts.map +0 -1
  75. package/dist/apps-linux.js.map +0 -1
  76. package/dist/apps-windows.d.ts.map +0 -1
  77. package/dist/apps-windows.js.map +0 -1
  78. package/dist/input-linux.d.ts.map +0 -1
  79. package/dist/input-linux.js.map +0 -1
  80. package/dist/input-windows.d.ts.map +0 -1
  81. package/dist/input-windows.js.map +0 -1
  82. package/dist/notice-windows.d.ts.map +0 -1
  83. package/dist/notice-windows.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frames.d.ts","sourceRoot":"","sources":["../src/frames.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,OAAO,EAAgB,KAAK,KAAK,EAAE,KAAK,IAAI,EAAE,MAAM,YAAY,CAAC;AAQ/E,MAAM,WAAW,WAAW;IAExB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAEzB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC9B;AAED,eAAO,MAAM,kBAAkB;;;CAAgE,CAAC;AAGhG,eAAO,MAAM,OAAO,UAAW,MAAM,UAAU,MAAM,WAAU,WAAW;IAE7D,KAAK;IAA0C,MAAM;CACjE,CAAC;AAEF,MAAM,WAAW,KAAK;IAClB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IAEpB,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC;IAEtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAExB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CAC3B;AAMD,eAAO,MAAM,SAAS,UAAW,KAAK,MAAM,KAAK,KAAG,KAQnD,CAAC;AAGF,eAAO,MAAM,OAAO,UAAW,KAAK,QAAQ,IAAI,KAAG,IAKlD,CAAC;AAGF,eAAO,MAAM,QAAQ,UAAW,KAAK,QAAQ,IAAI,KAAG,IAanD,CAAC;AAUF,qBAAa,QAAQ;;IAOjB,MAAM,IAAI,KAAK,GAAG,SAAS,CAE1B;IAGD,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,SAAS,GAAG,KAAK,GAAG,SAAS,CAWjD;IAGD,MAAM,CAAC,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;;;MAYjE;IAGD,eAAe,IAAI,MAAM,CAExB;IAGD,IAAI,IAAI,IAAI,CAEX;CACJ;AAED,MAAM,WAAW,IAAI;IACjB,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IAErB,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;CAC/B;AAGD,eAAO,MAAM,KAAK,YAAmB,OAAO,OAAO,QAAQ,WAAW,IAAI,WAAU,WAAW,KAAwB,OAAO,CAAC,IAAI,CAUlI,CAAC;AAIF,eAAO,MAAM,YAAY,YAAmB,OAAO,WAAU,WAAW,KAAwB,OAAO,CAAC,KAAK,CAG5G,CAAC"}
package/dist/frames.js ADDED
@@ -0,0 +1,91 @@
1
+ import { createHash, randomBytes } from "node:crypto";
2
+ import { crop, decodePng, downscale, encodePng } from "./png.js";
3
+ import { DesktopError } from "./types.js";
4
+ export const MODEL_IMAGE_LIMITS = { maxEdge: 1456, maxPixels: 1_150_000 };
5
+ export const fitSize = (width, height, limits = MODEL_IMAGE_LIMITS) => {
6
+ const scale = Math.min(1, limits.maxEdge / Math.max(width, height), Math.sqrt(limits.maxPixels / (width * height)));
7
+ return { width: Math.max(1, Math.floor(width * scale)), height: Math.max(1, Math.floor(height * scale)) };
8
+ };
9
+ const ratio = (frame) => ({ x: frame.region.width / frame.width, y: frame.region.height / frame.height });
10
+ export const toDesktop = (frame, at) => {
11
+ if (at.x < 0 || at.y < 0 || at.x >= frame.width || at.y >= frame.height) {
12
+ throw new DesktopError(`(${at.x}, ${at.y}) is outside screenshot ${frame.id}, which is ${frame.width}×${frame.height}. Read the coordinates off the image.`);
13
+ }
14
+ const { x, y } = ratio(frame);
15
+ return { x: Math.floor(frame.region.x + (at.x + 0.5) * x), y: Math.floor(frame.region.y + (at.y + 0.5) * y) };
16
+ };
17
+ export const toImage = (frame, rect) => {
18
+ const { x, y } = ratio(frame);
19
+ const left = Math.round((rect.x - frame.region.x) / x);
20
+ const top = Math.round((rect.y - frame.region.y) / y);
21
+ return { x: left, y: top, width: Math.max(1, Math.round(rect.width / x)), height: Math.max(1, Math.round(rect.height / y)) };
22
+ };
23
+ export const regionOf = (frame, rect) => {
24
+ if (rect.width <= 0 || rect.height <= 0) {
25
+ throw new DesktopError("A region needs a width and a height above zero.");
26
+ }
27
+ const { x, y } = ratio(frame);
28
+ const left = Math.max(frame.region.x, frame.region.x + rect.x * x);
29
+ const top = Math.max(frame.region.y, frame.region.y + rect.y * y);
30
+ const right = Math.min(frame.region.x + frame.region.width, frame.region.x + (rect.x + rect.width) * x);
31
+ const bottom = Math.min(frame.region.y + frame.region.height, frame.region.y + (rect.y + rect.height) * y);
32
+ if (right <= left || bottom <= top) {
33
+ throw new DesktopError(`That region is outside screenshot ${frame.id}, which is ${frame.width}×${frame.height}.`);
34
+ }
35
+ return { x: Math.floor(left), y: Math.floor(top), width: Math.ceil(right - left), height: Math.ceil(bottom - top) };
36
+ };
37
+ const sameRegion = (a, b) => a.x === b.x && a.y === b.y && a.width === b.width && a.height === b.height;
38
+ const REMEMBERED = 16;
39
+ export class FrameLog {
40
+ #frames = [];
41
+ #tag = randomBytes(2).toString("hex");
42
+ #counter = 0;
43
+ #unchangedStreak = 0;
44
+ latest() {
45
+ return this.#frames.at(-1);
46
+ }
47
+ resolve(id) {
48
+ const latest = this.latest();
49
+ if (id === undefined || id === latest?.id) {
50
+ return latest;
51
+ }
52
+ const known = this.#frames.some((frame) => frame.id === id);
53
+ throw new DesktopError(known
54
+ ? `Screenshot ${id} is out of date: the screen was captured again since (${latest?.id ?? "?"}). Read the coordinates off the latest one.`
55
+ : `There is no screenshot ${id} on this device${latest === undefined ? "" : `; the latest is ${latest.id}`}. Take a screenshot first.`);
56
+ }
57
+ record(region, width, height, digest) {
58
+ const latest = this.latest();
59
+ if (latest !== undefined && latest.digest === digest && sameRegion(latest.region, region)) {
60
+ this.#unchangedStreak++;
61
+ return { frame: latest, unchanged: true };
62
+ }
63
+ this.#unchangedStreak = 0;
64
+ this.#counter++;
65
+ const frame = { id: `${this.#tag}-${this.#counter}`, region, width, height, digest };
66
+ this.#frames.push(frame);
67
+ this.#frames.splice(0, Math.max(0, this.#frames.length - REMEMBERED));
68
+ return { frame, unchanged: false };
69
+ }
70
+ unchangedStreak() {
71
+ return this.#unchangedStreak;
72
+ }
73
+ sent() {
74
+ this.#unchangedStreak = 0;
75
+ }
76
+ }
77
+ export const shoot = async (desktop, log, region, limits = MODEL_IMAGE_LIMITS) => {
78
+ const captured = decodePng(await desktop.capture(region));
79
+ const area = region ?? { x: 0, y: 0, width: captured.width, height: captured.height };
80
+ const pixels = captured.width === area.width && captured.height === area.height ? captured : crop(captured, area);
81
+ const size = fitSize(pixels.width, pixels.height, limits);
82
+ const shown = downscale(pixels, size.width, size.height);
83
+ const digest = createHash("sha256").update(shown.data).digest("hex");
84
+ const { frame, unchanged } = log.record({ ...area, width: pixels.width, height: pixels.height }, shown.width, shown.height, digest);
85
+ return { frame, png: encodePng(shown), unchanged };
86
+ };
87
+ export const defaultFrame = async (desktop, limits = MODEL_IMAGE_LIMITS) => {
88
+ const { width, height } = await desktop.frame();
89
+ return { id: "", region: { x: 0, y: 0, width, height }, ...fitSize(width, height, limits), digest: "" };
90
+ };
91
+ //# sourceMappingURL=frames.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frames.js","sourceRoot":"","sources":["../src/frames.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,9 +1,18 @@
1
1
  import { type Desktop, type Notice, type NoticeEvents } from "./types.js";
2
- export { windowsSession } from "./apps-windows.js";
2
+ export { windowsSession } from "./windows/apps-windows.js";
3
+ export { CuaClient, cuaDesktop, cuaDriverCandidates, cuaKey, findCuaDriver, parseCuaElements, parseCuaWindows } from "./cua.js";
3
4
  export { parseChord, windowsChord, wtypeArgs, xdotoolChord, type Chord, type Modifier } from "./keys.js";
4
5
  export { focusRefusal, looksLikeUrl, parseSessionJson, parseSwayTree, parseWindowsJson, parseWmctrl } from "./parse.js";
5
- export { capture, frame, hasGraphicalSession, isWayland, pngSize } from "./screen.js";
6
- export { DesktopError, type Desktop, type ForegroundWindow, type MouseButton, type Notice, type NoticeEvents, type Point, type ScreenFrame, type ScrollDirection, type SessionState, type WindowInfo, } from "./types.js";
7
- export declare const desktop: () => Desktop;
6
+ export { capture, displays, frame, hasGraphicalSession, isWayland, pngSize } from "./screen.js";
7
+ export { crop, decodePng, downscale, encodePng, type Pixels } from "./png.js";
8
+ export { defaultFrame, fitSize, type Frame, FrameLog, type ImageLimits, MODEL_IMAGE_LIMITS, regionOf, type Shot, shoot, toDesktop, toImage, } from "./frames.js";
9
+ export { describeInput, type InputAction, type InputCall, keyboardText, MAX_WAIT_MS, perform, SETTLE_MS, settle, } from "./actions.js";
10
+ export { describeDisplays, describeShot, desktopPointing, ElementRefs, elementNow, frameName, type Pointing, pointingFor, regionFor, reshoot, type ScreenshotTarget, viewFrame, } from "./view.js";
11
+ export { parseDisplaysJson, parseElementJson, parseElementTreeJson, parseSwayOutputs, parseXrandrMonitors, roleOf } from "./parse.js";
12
+ export { DesktopError, type Desktop, type DisplayInfo, type ElementAction, type ElementTree, type Rect, type UiElement, type ForegroundWindow, type MouseButton, type Notice, type NoticeEvents, type Point, type ScreenFrame, type ScrollDirection, type SessionState, type WindowInfo, } from "./types.js";
13
+ export interface DesktopOptions {
14
+ readonly env?: NodeJS.ProcessEnv;
15
+ }
16
+ export declare const desktop: (options?: DesktopOptions) => Desktop;
8
17
  export declare const notice: (hotkey: string, events: NoticeEvents) => Notice | undefined;
9
18
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,KAAK,OAAO,EAAgB,KAAK,MAAM,EAAE,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AAExF,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,SAAS,EAAE,YAAY,EAAE,KAAK,KAAK,EAAE,KAAK,QAAQ,EAAE,MAAM,WAAW,CAAC;AACzG,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,gBAAgB,EAAE,aAAa,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACxH,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,mBAAmB,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AACtF,OAAO,EACH,YAAY,EACZ,KAAK,OAAO,EACZ,KAAK,gBAAgB,EACrB,KAAK,WAAW,EAChB,KAAK,MAAM,EACX,KAAK,YAAY,EACjB,KAAK,KAAK,EACV,KAAK,WAAW,EAChB,KAAK,eAAe,EACpB,KAAK,YAAY,EACjB,KAAK,UAAU,GAClB,MAAM,YAAY,CAAC;AAUpB,eAAO,MAAM,OAAO,QAAO,OAkC1B,CAAC;AAGF,eAAO,MAAM,MAAM,WAAY,MAAM,UAAU,YAAY,KAAG,MAAM,GAAG,SACK,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,KAAK,OAAO,EAAgB,KAAK,MAAM,EAAE,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AAExF,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,mBAAmB,EAAE,MAAM,EAAE,aAAa,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAChI,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,SAAS,EAAE,YAAY,EAAE,KAAK,KAAK,EAAE,KAAK,QAAQ,EAAE,MAAM,WAAW,CAAC;AACzG,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,gBAAgB,EAAE,aAAa,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACxH,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,mBAAmB,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAChG,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,KAAK,MAAM,EAAE,MAAM,UAAU,CAAC;AAC9E,OAAO,EACH,YAAY,EACZ,OAAO,EACP,KAAK,KAAK,EACV,QAAQ,EACR,KAAK,WAAW,EAChB,kBAAkB,EAClB,QAAQ,EACR,KAAK,IAAI,EACT,KAAK,EACL,SAAS,EACT,OAAO,GACV,MAAM,aAAa,CAAC;AACrB,OAAO,EACH,aAAa,EACb,KAAK,WAAW,EAChB,KAAK,SAAS,EACd,YAAY,EACZ,WAAW,EACX,OAAO,EACP,SAAS,EACT,MAAM,GACT,MAAM,cAAc,CAAC;AACtB,OAAO,EACH,gBAAgB,EAChB,YAAY,EACZ,eAAe,EACf,WAAW,EACX,UAAU,EACV,SAAS,EACT,KAAK,QAAQ,EACb,WAAW,EACX,SAAS,EACT,OAAO,EACP,KAAK,gBAAgB,EACrB,SAAS,GACZ,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AACtI,OAAO,EACH,YAAY,EACZ,KAAK,OAAO,EACZ,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,KAAK,IAAI,EACT,KAAK,SAAS,EACd,KAAK,gBAAgB,EACrB,KAAK,WAAW,EAChB,KAAK,MAAM,EACX,KAAK,YAAY,EACjB,KAAK,KAAK,EACV,KAAK,WAAW,EAChB,KAAK,eAAe,EACpB,KAAK,YAAY,EACjB,KAAK,UAAU,GAClB,MAAM,YAAY,CAAC;AAuBpB,MAAM,WAAW,cAAc;IAG3B,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;CACpC;AA4ED,eAAO,MAAM,OAAO,aAAa,cAAc,KAAQ,OAItD,CAAC;AAiDF,eAAO,MAAM,MAAM,WAAY,MAAM,UAAU,YAAY,KAAG,MAAM,GAAG,SACK,CAAC"}
package/dist/index.js CHANGED
@@ -1,23 +1,104 @@
1
- import { linuxApps } from "./apps-linux.js";
2
- import { windowsApps } from "./apps-windows.js";
3
- import { linuxInput } from "./input-linux.js";
4
- import { windowsInput } from "./input-windows.js";
5
- import { windowsNotice } from "./notice-windows.js";
6
- import { capture, frame } from "./screen.js";
1
+ import { linuxApps } from "./linux/apps-linux.js";
2
+ import { windowsApps } from "./windows/apps-windows.js";
3
+ import { CuaClient, cuaDesktop, findCuaDriver } from "./cua.js";
4
+ import { windowsElements } from "./windows/elements-windows.js";
5
+ import { linuxInput } from "./linux/input-linux.js";
6
+ import { windowsInput } from "./windows/input-windows.js";
7
+ import { windowsNotice } from "./windows/notice-windows.js";
8
+ import { withEnvironment } from "./run.js";
9
+ import { capture, displays, frame } from "./screen.js";
7
10
  import { DesktopError } from "./types.js";
8
- export { windowsSession } from "./apps-windows.js";
11
+ export { windowsSession } from "./windows/apps-windows.js";
12
+ export { CuaClient, cuaDesktop, cuaDriverCandidates, cuaKey, findCuaDriver, parseCuaElements, parseCuaWindows } from "./cua.js";
9
13
  export { parseChord, windowsChord, wtypeArgs, xdotoolChord } from "./keys.js";
10
14
  export { focusRefusal, looksLikeUrl, parseSessionJson, parseSwayTree, parseWindowsJson, parseWmctrl } from "./parse.js";
11
- export { capture, frame, hasGraphicalSession, isWayland, pngSize } from "./screen.js";
15
+ export { capture, displays, frame, hasGraphicalSession, isWayland, pngSize } from "./screen.js";
16
+ export { crop, decodePng, downscale, encodePng } from "./png.js";
17
+ export { defaultFrame, fitSize, FrameLog, MODEL_IMAGE_LIMITS, regionOf, shoot, toDesktop, toImage, } from "./frames.js";
18
+ export { describeInput, keyboardText, MAX_WAIT_MS, perform, SETTLE_MS, settle, } from "./actions.js";
19
+ export { describeDisplays, describeShot, desktopPointing, ElementRefs, elementNow, frameName, pointingFor, regionFor, reshoot, viewFrame, } from "./view.js";
20
+ export { parseDisplaysJson, parseElementJson, parseElementTreeJson, parseSwayOutputs, parseXrandrMonitors, roleOf } from "./parse.js";
12
21
  export { DesktopError, } from "./types.js";
13
22
  const unsupported = async () => {
14
- throw new DesktopError(`Controlling the screen is not supported on ${process.platform} yet: only Windows and Linux.`);
23
+ throw new DesktopError(`Controlling the screen on ${process.platform} needs cua-driver, and none is installed here.`, "Install cua-driver (https://cua.ai/driver): curl -fsSL https://cua.ai/driver/install.sh | bash");
15
24
  };
16
- export const desktop = () => {
25
+ const noElements = async () => {
26
+ throw new DesktopError("Reading a window's controls here needs cua-driver, which is not installed. Use a screenshot and its coordinates.", "Install cua-driver (https://cua.ai/driver): curl -fsSL https://cua.ai/driver/install.sh | bash");
27
+ };
28
+ const clients = new Map();
29
+ const cuaClient = (env) => {
30
+ const binary = findCuaDriver(env);
31
+ if (binary === undefined) {
32
+ return undefined;
33
+ }
34
+ const key = `${binary}\u0000${env["DISPLAY"] ?? ""}`;
35
+ let client = clients.get(key);
36
+ if (client === undefined) {
37
+ client = new CuaClient(binary, env);
38
+ clients.set(key, client);
39
+ }
40
+ return client;
41
+ };
42
+ const wantsCua = (env) => env["INTENTIC_DESKTOP_DRIVER"] === "cua";
43
+ const linuxElements = (env) => {
44
+ const client = cuaClient(env);
45
+ if (client === undefined) {
46
+ return { elements: noElements, element: noElements, elementAct: noElements };
47
+ }
48
+ const cua = cuaDesktop(client);
49
+ return {
50
+ elements: async (window) => {
51
+ if (window === undefined) {
52
+ return await cua.elements();
53
+ }
54
+ const matched = (await cua.windows()).find((candidate) => Number(candidate.id.split(":")[1]) === Number(window) || candidate.id === window);
55
+ if (matched === undefined) {
56
+ throw new DesktopError(`cua-driver does not see window ${window}. List the windows again.`);
57
+ }
58
+ return await cua.elements(matched.id);
59
+ },
60
+ element: cua.element,
61
+ elementAct: cua.elementAct,
62
+ };
63
+ };
64
+ const scopedTo = (env, desktop) => {
65
+ const within = (method) => async (...args) => await withEnvironment(env, async () => await method(...args));
66
+ return {
67
+ frame: within(desktop.frame),
68
+ capture: within(desktop.capture),
69
+ displays: within(desktop.displays),
70
+ move: within(desktop.move),
71
+ click: within(desktop.click),
72
+ doubleClick: within(desktop.doubleClick),
73
+ drag: within(desktop.drag),
74
+ type: within(desktop.type),
75
+ key: within(desktop.key),
76
+ scroll: within(desktop.scroll),
77
+ windows: within(desktop.windows),
78
+ focusWindow: within(desktop.focusWindow),
79
+ launch: within(desktop.launch),
80
+ readClipboard: within(desktop.readClipboard),
81
+ writeClipboard: within(desktop.writeClipboard),
82
+ elements: within(desktop.elements),
83
+ element: within(desktop.element),
84
+ elementAct: within(desktop.elementAct),
85
+ };
86
+ };
87
+ export const desktop = (options = {}) => {
88
+ const env = options.env ?? process.env;
89
+ const chosen = platformDesktop(env);
90
+ return options.env === undefined ? chosen : scopedTo(options.env, chosen);
91
+ };
92
+ const platformDesktop = (env) => {
93
+ const driver = wantsCua(env) || (process.platform !== "win32" && process.platform !== "linux") ? cuaClient(env) : undefined;
94
+ if (driver !== undefined) {
95
+ return cuaDesktop(driver);
96
+ }
17
97
  if (process.platform === "win32") {
18
98
  return {
19
99
  frame,
20
100
  capture,
101
+ displays,
21
102
  move: async (to) => await windowsInput.move(to, (await frame()).origin),
22
103
  click: async (at, button) => await windowsInput.click(at, button, (await frame()).origin),
23
104
  doubleClick: async (at) => await windowsInput.doubleClick(at, (await frame()).origin),
@@ -26,14 +107,16 @@ export const desktop = () => {
26
107
  key: windowsInput.key,
27
108
  scroll: async (at, direction, amount) => await windowsInput.scroll(at, direction, amount, (await frame()).origin),
28
109
  ...windowsApps,
110
+ ...windowsElements,
29
111
  };
30
112
  }
31
113
  if (process.platform === "linux") {
32
- return { frame, capture, ...linuxInput, ...linuxApps };
114
+ return { frame, capture, displays, ...linuxInput, ...linuxApps, ...linuxElements(env) };
33
115
  }
34
116
  return {
35
117
  frame,
36
118
  capture,
119
+ displays,
37
120
  move: unsupported,
38
121
  click: unsupported,
39
122
  doubleClick: unsupported,
@@ -46,6 +129,9 @@ export const desktop = () => {
46
129
  launch: unsupported,
47
130
  readClipboard: unsupported,
48
131
  writeClipboard: unsupported,
132
+ elements: unsupported,
133
+ element: unsupported,
134
+ elementAct: unsupported,
49
135
  };
50
136
  };
51
137
  export const notice = (hotkey, events) => process.platform === "win32" ? windowsNotice(hotkey, events) : undefined;
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { type WindowInfo } from "./types.js";
1
+ import { type WindowInfo } from "../types.js";
2
2
  export declare const linuxApps: {
3
3
  windows: () => Promise<WindowInfo[]>;
4
4
  focusWindow: (id: string) => Promise<void>;
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apps-linux.d.ts","sourceRoot":"","sources":["../../src/linux/apps-linux.ts"],"names":[],"mappings":"AAKA,OAAO,EAAgB,KAAK,UAAU,EAAE,MAAM,aAAa,CAAC;AAa5D,eAAO,MAAM,SAAS;IAClB,OAAO,QAAY,OAAO,CAAC,UAAU,EAAE,CAAC;IAkBxC,WAAW,OAAa,MAAM,KAAG,OAAO,CAAC,IAAI,CAAC;IAgB9C,MAAM,WAAiB,MAAM,KAAG,OAAO,CAAC,IAAI,CAAC;IAiB7C,aAAa,QAAY,OAAO,CAAC,MAAM,CAAC;IAKxC,cAAc,SAAe,MAAM,KAAG,OAAO,CAAC,IAAI,CAAC;CAWtD,CAAC"}
@@ -1,14 +1,14 @@
1
1
  import { spawn } from "node:child_process";
2
2
  import { existsSync } from "node:fs";
3
- import { looksLikeUrl, parseSwayTree, parseWmctrl } from "./parse.js";
4
- import { has, run } from "./run.js";
5
- import { isWayland } from "./screen.js";
6
- import { DesktopError } from "./types.js";
3
+ import { looksLikeUrl, parseSwayTree, parseWmctrl, parseXwininfoTree, withAbsoluteBounds } from "../parse.js";
4
+ import { environment, has, run } from "../run.js";
5
+ import { isWayland } from "../screen.js";
6
+ import { DesktopError } from "../types.js";
7
7
  import { XDOTOOL_INSTALL } from "./input-linux.js";
8
8
  const WMCTRL_INSTALL = "sudo apt install wmctrl (or your distro's package)";
9
9
  const CLIP_INSTALL_X11 = "sudo apt install xclip";
10
10
  const CLIP_INSTALL_WAYLAND = "sudo apt install wl-clipboard";
11
- const swayRunning = () => process.env["SWAYSOCK"] !== undefined || process.env["I3SOCK"] !== undefined;
11
+ const swayRunning = () => environment()["SWAYSOCK"] !== undefined || environment()["I3SOCK"] !== undefined;
12
12
  export const linuxApps = {
13
13
  windows: async () => {
14
14
  if (isWayland()) {
@@ -18,8 +18,9 @@ export const linuxApps = {
18
18
  throw new DesktopError("This Wayland session does not let a program list other windows: the compositor refuses it by design, and only sway/Hyprland offer an IPC that answers. Use a screenshot to see what is open, or log in to an X11 session for full window control.");
19
19
  }
20
20
  const active = await run("xdotool", ["getactivewindow"], XDOTOOL_INSTALL).catch(() => "");
21
- const listed = await run("wmctrl", ["-lGpx"], WMCTRL_INSTALL);
22
- return parseWmctrl(listed, active.trim() === "" ? undefined : active.trim());
21
+ const listed = parseWmctrl(await run("wmctrl", ["-lGpx"], WMCTRL_INSTALL), active.trim() === "" ? undefined : active.trim());
22
+ const tree = (await has("xwininfo")) ? await run("xwininfo", ["-root", "-tree"]).catch(() => "") : "";
23
+ return withAbsoluteBounds(listed, parseXwininfoTree(tree));
23
24
  },
24
25
  focusWindow: async (id) => {
25
26
  if (isWayland()) {
@@ -39,7 +40,7 @@ export const linuxApps = {
39
40
  const [command, args] = viaOpener
40
41
  ? ["xdg-open", [target]]
41
42
  : [target.split(/\s+/)[0] ?? target, target.split(/\s+/).slice(1)];
42
- const child = spawn(command, [...args], { detached: true, stdio: "ignore" });
43
+ const child = spawn(command, [...args], { detached: true, stdio: "ignore", env: environment() });
43
44
  child.unref();
44
45
  await new Promise((resolvePromise, reject) => {
45
46
  child.once("error", (error) => reject(new DesktopError(`Could not start "${target}": ${error.message}`)));
@@ -54,7 +55,7 @@ export const linuxApps = {
54
55
  ? ["wl-copy", [], CLIP_INSTALL_WAYLAND]
55
56
  : ["xclip", ["-selection", "clipboard"], CLIP_INSTALL_X11];
56
57
  await new Promise((resolvePromise, reject) => {
57
- const child = spawn(command, [...args], { stdio: ["pipe", "ignore", "ignore"] });
58
+ const child = spawn(command, [...args], { stdio: ["pipe", "ignore", "ignore"], env: environment() });
58
59
  child.once("error", (error) => reject(new DesktopError(`Could not set the clipboard with "${command}": ${error.message}`, install)));
59
60
  child.once("close", () => resolvePromise());
60
61
  child.stdin.end(text);
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apps-linux.js","sourceRoot":"","sources":["../../src/linux/apps-linux.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAC9G,OAAO,EAAE,WAAW,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,YAAY,EAAmB,MAAM,aAAa,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAMnD,MAAM,cAAc,GAAG,qDAAqD,CAAC;AAC7E,MAAM,gBAAgB,GAAG,wBAAwB,CAAC;AAClD,MAAM,oBAAoB,GAAG,+BAA+B,CAAC;AAE7D,MAAM,WAAW,GAAG,GAAY,EAAE,CAAC,WAAW,EAAE,CAAC,UAAU,CAAC,KAAK,SAAS,IAAI,WAAW,EAAE,CAAC,QAAQ,CAAC,KAAK,SAAS,CAAC;AAEpH,MAAM,CAAC,MAAM,SAAS,GAAG;IACrB,OAAO,EAAE,KAAK,IAA2B,EAAE;QACvC,IAAI,SAAS,EAAE,EAAE,CAAC;YACd,IAAI,WAAW,EAAE,IAAI,CAAC,MAAM,GAAG,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC;gBAC1C,OAAO,aAAa,CAAC,MAAM,GAAG,CAAC,SAAS,EAAE,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC;YACnE,CAAC;YACD,MAAM,IAAI,YAAY,CAClB,mPAAmP,CACtP,CAAC;QACN,CAAC;QAGD,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,SAAS,EAAE,CAAC,iBAAiB,CAAC,EAAE,eAAe,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;QAC1F,MAAM,MAAM,GAAG,WAAW,CAAC,MAAM,GAAG,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,EAAE,cAAc,CAAC,EAAE,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;QAE7H,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,UAAU,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACtG,OAAO,kBAAkB,CAAC,MAAM,EAAE,iBAAiB,CAAC,IAAI,CAAC,CAAC,CAAC;IAC/D,CAAC;IAED,WAAW,EAAE,KAAK,EAAE,EAAU,EAAiB,EAAE;QAC7C,IAAI,SAAS,EAAE,EAAE,CAAC;YACd,IAAI,WAAW,EAAE,IAAI,CAAC,MAAM,GAAG,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC;gBAC1C,MAAM,GAAG,CAAC,SAAS,EAAE,CAAC,WAAW,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC;gBAClD,OAAO;YACX,CAAC;YACD,MAAM,IAAI,YAAY,CAClB,6HAA6H,CAChI,CAAC;QACN,CAAC;QAED,MAAM,GAAG,CAAC,SAAS,EAAE,CAAC,gBAAgB,EAAE,QAAQ,EAAE,EAAE,CAAC,EAAE,eAAe,CAAC,CAAC;IAC5E,CAAC;IAID,MAAM,EAAE,KAAK,EAAE,MAAc,EAAiB,EAAE;QAC5C,MAAM,SAAS,GAAG,YAAY,CAAC,MAAM,CAAC,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC;QAC7D,IAAI,SAAS,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC;YACxC,MAAM,IAAI,YAAY,CAAC,0CAA0C,MAAM,SAAS,EAAE,4BAA4B,CAAC,CAAC;QACpH,CAAC;QACD,MAAM,CAAC,OAAO,EAAE,IAAI,CAAC,GAAG,SAAS;YAC7B,CAAC,CAAE,CAAC,UAAU,EAAE,CAAC,MAAM,CAAC,CAAW;YACnC,CAAC,CAAE,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAW,CAAC;QAClF,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,EAAE,CAAC,GAAG,IAAI,CAAC,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,EAAE,WAAW,EAAE,EAAE,CAAC,CAAC;QACjG,KAAK,CAAC,KAAK,EAAE,CAAC;QAEd,MAAM,IAAI,OAAO,CAAO,CAAC,cAAc,EAAE,MAAM,EAAE,EAAE;YAC/C,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,YAAY,CAAC,oBAAoB,MAAM,MAAM,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC;YAC1G,UAAU,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC;QACnC,CAAC,CAAC,CAAC;IACP,CAAC;IAED,aAAa,EAAE,KAAK,IAAqB,EAAE,CACvC,SAAS,EAAE;QACP,CAAC,CAAC,MAAM,GAAG,CAAC,UAAU,EAAE,CAAC,cAAc,CAAC,EAAE,oBAAoB,CAAC;QAC/D,CAAC,CAAC,MAAM,GAAG,CAAC,OAAO,EAAE,CAAC,YAAY,EAAE,WAAW,EAAE,IAAI,CAAC,EAAE,gBAAgB,CAAC;IAEjF,cAAc,EAAE,KAAK,EAAE,IAAY,EAAiB,EAAE;QAClD,MAAM,CAAC,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC,GAAG,SAAS,EAAE;YACxC,CAAC,CAAE,CAAC,SAAS,EAAE,EAAE,EAAE,oBAAoB,CAAW;YAClD,CAAC,CAAE,CAAC,OAAO,EAAE,CAAC,YAAY,EAAE,WAAW,CAAC,EAAE,gBAAgB,CAAW,CAAC;QAC1E,MAAM,IAAI,OAAO,CAAO,CAAC,cAAc,EAAE,MAAM,EAAE,EAAE;YAC/C,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,EAAE,CAAC,GAAG,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,CAAC,MAAM,EAAE,QAAQ,EAAE,QAAQ,CAAC,EAAE,GAAG,EAAE,WAAW,EAAE,EAAE,CAAC,CAAC;YACrG,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,YAAY,CAAC,qCAAqC,OAAO,MAAM,KAAK,CAAC,OAAO,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;YACrI,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,cAAc,EAAE,CAAC,CAAC;YAC5C,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC1B,CAAC,CAAC,CAAC;IACP,CAAC;CACJ,CAAC"}
@@ -1,5 +1,6 @@
1
- import { type MouseButton, type Point, type ScrollDirection } from "./types.js";
1
+ import { type MouseButton, type Point, type ScrollDirection } from "../types.js";
2
2
  export declare const XDOTOOL_INSTALL = "sudo apt install xdotool (or your distro's package)";
3
+ export declare const unknownKeyIn: (stderr: string) => string | undefined;
3
4
  export declare const linuxInput: {
4
5
  move: (to: Point) => Promise<void>;
5
6
  click: (at: Point, button: MouseButton) => Promise<void>;
@@ -0,0 +1 @@
1
+ {"version":3,"file":"input-linux.d.ts","sourceRoot":"","sources":["../../src/linux/input-linux.ts"],"names":[],"mappings":"AAGA,OAAO,EAAgB,KAAK,WAAW,EAAE,KAAK,KAAK,EAAE,KAAK,eAAe,EAAE,MAAM,aAAa,CAAC;AAO/F,eAAO,MAAM,eAAe,yDAAyD,CAAC;AAetF,eAAO,MAAM,YAAY,WAAY,MAAM,KAAG,MAAM,GAAG,SAA2D,CAAC;AAEnH,eAAO,MAAM,UAAU;IACnB,IAAI,OAAa,KAAK,KAAG,OAAO,CAAC,IAAI,CAAC;IAQtC,KAAK,OAAa,KAAK,UAAU,WAAW,KAAG,OAAO,CAAC,IAAI,CAAC;IAS5D,WAAW,OAAa,KAAK,KAAG,OAAO,CAAC,IAAI,CAAC;IAqB7C,IAAI,SAAe,KAAK,MAAM,KAAK,KAAG,OAAO,CAAC,IAAI,CAAC;IAcnD,IAAI,SAAe,MAAM,KAAG,OAAO,CAAC,IAAI,CAAC;IAczC,GAAG,UAAgB,MAAM,KAAG,OAAO,CAAC,IAAI,CAAC;IAgBzC,MAAM,OAAa,KAAK,aAAa,eAAe,UAAU,MAAM,KAAG,OAAO,CAAC,IAAI,CAAC;CAavF,CAAC"}
@@ -1,7 +1,7 @@
1
- import { wtypeArgs, xdotoolChord } from "./keys.js";
2
- import { has, run } from "./run.js";
3
- import { isWayland } from "./screen.js";
4
- import { DesktopError } from "./types.js";
1
+ import { wtypeArgs, xdotoolChord } from "../keys.js";
2
+ import { has, run, runOutput } from "../run.js";
3
+ import { isWayland } from "../screen.js";
4
+ import { DesktopError } from "../types.js";
5
5
  export const XDOTOOL_INSTALL = "sudo apt install xdotool (or your distro's package)";
6
6
  const YDOTOOL_INSTALL = "sudo apt install ydotool, then add yourself to the input group: sudo usermod -aG input $USER (log out and back in)";
7
7
  const WTYPE_INSTALL = "sudo apt install wtype";
@@ -10,6 +10,7 @@ const YDOTOOL_BUTTON = { left: "0xC0", right: "0xC1", middle: "0xC2" };
10
10
  const wayland = () => isWayland();
11
11
  const xdotool = (args) => run("xdotool", args, XDOTOOL_INSTALL);
12
12
  const ydotool = (args) => run("ydotool", args, YDOTOOL_INSTALL);
13
+ export const unknownKeyIn = (stderr) => /No such key name '([^']*)'/.exec(stderr)?.[1];
13
14
  export const linuxInput = {
14
15
  move: async (to) => {
15
16
  if (wayland()) {
@@ -76,7 +77,11 @@ export const linuxInput = {
76
77
  }
77
78
  throw new DesktopError("Pressing key combinations on Wayland needs wtype.", WTYPE_INSTALL);
78
79
  }
79
- await xdotool(["key", "--clearmodifiers", xdotoolChord(combo)]);
80
+ const { stderr } = await runOutput("xdotool", ["key", "--clearmodifiers", xdotoolChord(combo)], XDOTOOL_INSTALL);
81
+ const unknown = unknownKeyIn(stderr);
82
+ if (unknown !== undefined) {
83
+ throw new DesktopError(`"${unknown}" is not a key this desktop knows, so nothing was pressed. Name it as a letter, a digit, F1–F12, or an X11 key name like Return, Tab, Escape, Page_Up.`);
84
+ }
80
85
  },
81
86
  scroll: async (at, direction, amount) => {
82
87
  const clicks = Math.max(1, Math.round(amount));
@@ -0,0 +1 @@
1
+ {"version":3,"file":"input-linux.js","sourceRoot":"","sources":["../../src/linux/input-linux.ts"],"names":[],"mappings":"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"}
package/dist/parse.d.ts CHANGED
@@ -1,8 +1,16 @@
1
- import { type SessionState, type WindowInfo } from "./types.js";
1
+ import { type DisplayInfo, type ElementTree, type Rect, type SessionState, type UiElement, type WindowInfo } from "./types.js";
2
2
  export declare const parseWmctrl: (output: string, focusedId?: string) => WindowInfo[];
3
3
  export declare const parseSwayTree: (json: string) => WindowInfo[];
4
4
  export declare const parseWindowsJson: (json: string) => WindowInfo[];
5
5
  export declare const parseSessionJson: (json: string) => SessionState | undefined;
6
6
  export declare const focusRefusal: (id: string, attempts: number, state: SessionState | undefined) => string;
7
7
  export declare const looksLikeUrl: (target: string) => boolean;
8
+ export declare const parseDisplaysJson: (json: string) => DisplayInfo[];
9
+ export declare const parseXrandrMonitors: (output: string) => DisplayInfo[];
10
+ export declare const parseSwayOutputs: (json: string) => DisplayInfo[];
11
+ export declare const roleOf: (programmatic: string) => string;
12
+ export declare const parseElementJson: (json: string) => UiElement | undefined;
13
+ export declare const parseElementTreeJson: (json: string) => ElementTree;
14
+ export declare const parseXwininfoTree: (output: string) => Map<number, Rect>;
15
+ export declare const withAbsoluteBounds: (windows: readonly WindowInfo[], tree: ReadonlyMap<number, Rect>) => WindowInfo[];
8
16
  //# sourceMappingURL=parse.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"parse.d.ts","sourceRoot":"","sources":["../src/parse.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,KAAK,YAAY,EAAE,KAAK,UAAU,EAAE,MAAM,YAAY,CAAC;AAO9E,eAAO,MAAM,WAAW,WAAY,MAAM,cAAc,MAAM,KAAG,UAAU,EA2BjE,CAAC;AA8CX,eAAO,MAAM,aAAa,SAAU,MAAM,KAAG,UAAU,EAA2D,CAAC;AAInH,eAAO,MAAM,gBAAgB,SAAU,MAAM,KAAG,UAAU,EAwBzD,CAAC;AAKF,eAAO,MAAM,gBAAgB,SAAU,MAAM,KAAG,YAAY,GAAG,SAe9D,CAAC;AASF,eAAO,MAAM,YAAY,OAAQ,MAAM,YAAY,MAAM,SAAS,YAAY,GAAG,SAAS,KAAG,MAU5F,CAAC;AAIF,eAAO,MAAM,YAAY,WAAY,MAAM,KAAG,OAAsF,CAAC"}
1
+ {"version":3,"file":"parse.d.ts","sourceRoot":"","sources":["../src/parse.ts"],"names":[],"mappings":"AACA,OAAO,EACH,KAAK,WAAW,EAGhB,KAAK,WAAW,EAChB,KAAK,IAAI,EACT,KAAK,YAAY,EACjB,KAAK,SAAS,EACd,KAAK,UAAU,EAClB,MAAM,YAAY,CAAC;AAOpB,eAAO,MAAM,WAAW,WAAY,MAAM,cAAc,MAAM,KAAG,UAAU,EA2BjE,CAAC;AA8CX,eAAO,MAAM,aAAa,SAAU,MAAM,KAAG,UAAU,EAA2D,CAAC;AAInH,eAAO,MAAM,gBAAgB,SAAU,MAAM,KAAG,UAAU,EAwBzD,CAAC;AAKF,eAAO,MAAM,gBAAgB,SAAU,MAAM,KAAG,YAAY,GAAG,SAe9D,CAAC;AASF,eAAO,MAAM,YAAY,OAAQ,MAAM,YAAY,MAAM,SAAS,YAAY,GAAG,SAAS,KAAG,MAU5F,CAAC;AAIF,eAAO,MAAM,YAAY,WAAY,MAAM,KAAG,OAAsF,CAAC;AA4CrI,eAAO,MAAM,iBAAiB,SAAU,MAAM,KAAG,WAAW,EAKrD,CAAC;AAGR,eAAO,MAAM,mBAAmB,WAAY,MAAM,KAAG,WAAW,EAQ1D,CAAC;AASP,eAAO,MAAM,gBAAgB,SAAU,MAAM,KAAG,WAAW,EAGtD,CAAC;AAIN,eAAO,MAAM,MAAM,iBAAkB,MAAM,KAAG,MAIxB,CAAC;AAqDvB,eAAO,MAAM,gBAAgB,SAAU,MAAM,KAAG,SAAS,GAAG,SAG3D,CAAC;AAQF,eAAO,MAAM,oBAAoB,SAAU,MAAM,KAAG,WAGnD,CAAC;AAIF,eAAO,MAAM,iBAAiB,WAAY,MAAM,KAAG,GAAG,CAAC,MAAM,EAAE,IAAI,CAU9D,CAAC;AAKN,eAAO,MAAM,kBAAkB,YAAa,SAAS,UAAU,EAAE,QAAQ,WAAW,CAAC,MAAM,EAAE,IAAI,CAAC,KAAG,UAAU,EAIzG,CAAC"}
package/dist/parse.js CHANGED
@@ -1,4 +1,5 @@
1
- import { DesktopError } from "./types.js";
1
+ import { z } from "zod";
2
+ import { DesktopError, } from "./types.js";
2
3
  export const parseWmctrl = (output, focusedId) => output
3
4
  .split(/\r?\n/)
4
5
  .map((line) => line.trim())
@@ -106,4 +107,122 @@ export const focusRefusal = (id, attempts, state) => {
106
107
  return `Windows would not give window ${id} the keyboard after ${attempts} attempts: ${cause}.`;
107
108
  };
108
109
  export const looksLikeUrl = (target) => /^[a-z][a-z0-9+.-]*:\/\//i.test(target) || /^(www\.|mailto:)/i.test(target);
110
+ const measured = z.number().refine(Number.isFinite);
111
+ const jsonFrom = (json, schema, lister, what) => {
112
+ const said = json.trim().slice(0, 200);
113
+ const refuse = () => {
114
+ throw new DesktopError(`${lister} answered something that is not ${what}: ${said === "" ? "nothing" : said}`);
115
+ };
116
+ let parsed;
117
+ try {
118
+ parsed = schema.safeParse(JSON.parse(json));
119
+ }
120
+ catch {
121
+ return refuse();
122
+ }
123
+ return parsed.success ? parsed.data : refuse();
124
+ };
125
+ const rowsOf = (row) => z.array(z.unknown()).transform((rows) => rows.flatMap((candidate) => {
126
+ const parsed = row.safeParse(candidate);
127
+ return parsed.success ? [parsed.data] : [];
128
+ }));
129
+ const psListOf = (row) => z.union([z.array(z.unknown()), z.unknown().transform((one) => [one])]).pipe(rowsOf(row));
130
+ const DisplayRowSchema = z.object({
131
+ name: z.string().catch(""),
132
+ primary: z.boolean().catch(false),
133
+ x: measured,
134
+ y: measured,
135
+ width: measured.refine((width) => width > 0),
136
+ height: measured.refine((height) => height > 0),
137
+ });
138
+ export const parseDisplaysJson = (json) => jsonFrom(json, psListOf(DisplayRowSchema), "PowerShell", "a display list").map((row) => ({
139
+ name: row.name,
140
+ primary: row.primary,
141
+ bounds: { x: row.x, y: row.y, width: row.width, height: row.height },
142
+ }));
143
+ export const parseXrandrMonitors = (output) => output.split(/\r?\n/).flatMap((line) => {
144
+ const fields = /^\s*\d+:\s+\+?(\*)?(\S+)\s+(\d+)\/\d+x(\d+)\/\d+\+(-?\d+)\+(-?\d+)/.exec(line);
145
+ if (fields === null) {
146
+ return [];
147
+ }
148
+ const [, star, name, width, height, x, y] = fields;
149
+ return [{ name: name ?? "", primary: star === "*", bounds: { x: Number(x), y: Number(y), width: Number(width), height: Number(height) } }];
150
+ });
151
+ const SwayOutputSchema = z.object({
152
+ name: z.string().catch(""),
153
+ active: z.boolean().catch(true),
154
+ rect: z.object({ x: measured, y: measured, width: measured, height: measured }).optional().catch(undefined),
155
+ });
156
+ export const parseSwayOutputs = (json) => jsonFrom(json, rowsOf(SwayOutputSchema), "swaymsg", "an output list").flatMap(({ name, active, rect }) => !active || rect === undefined ? [] : [{ name, primary: rect.x === 0 && rect.y === 0, bounds: { ...rect } }]);
157
+ export const roleOf = (programmatic) => programmatic
158
+ .replace(/^ControlType\./, "")
159
+ .replace(/([a-z])([A-Z])/g, "$1 $2")
160
+ .toLowerCase();
161
+ const ElementRowSchema = z.object({
162
+ id: z.string().min(1),
163
+ type: z.string().catch(""),
164
+ name: z.string().catch(""),
165
+ value: z.string().optional().catch(undefined),
166
+ x: measured.optional().catch(undefined),
167
+ y: measured.optional().catch(undefined),
168
+ width: measured.optional().catch(undefined),
169
+ height: measured.optional().catch(undefined),
170
+ enabled: z.boolean().catch(true),
171
+ focused: z.boolean().catch(false),
172
+ offscreen: z.boolean().catch(false),
173
+ focusable: z.boolean().catch(false),
174
+ invoke: z.boolean().catch(false),
175
+ settable: z.boolean().catch(false),
176
+ toggle: z.boolean().catch(false),
177
+ expand: z.boolean().catch(false),
178
+ select: z.boolean().catch(false),
179
+ depth: measured.catch(0),
180
+ });
181
+ const actionsOf = (row) => [
182
+ ...(row.invoke ? ["invoke"] : []),
183
+ ...(row.settable ? ["set_value"] : []),
184
+ ...(row.toggle ? ["toggle"] : []),
185
+ ...(row.select ? ["select"] : []),
186
+ ...(row.expand ? ["expand", "collapse"] : []),
187
+ ...(row.focusable ? ["focus"] : []),
188
+ ];
189
+ const elementOf = (row) => {
190
+ const shown = !row.offscreen;
191
+ return {
192
+ id: row.id,
193
+ role: roleOf(row.type),
194
+ name: row.name,
195
+ value: row.value,
196
+ bounds: { x: row.x ?? 0, y: row.y ?? 0, width: shown ? (row.width ?? 0) : 0, height: shown ? (row.height ?? 0) : 0 },
197
+ enabled: row.enabled,
198
+ focused: row.focused,
199
+ actions: actionsOf(row),
200
+ depth: row.depth,
201
+ };
202
+ };
203
+ export const parseElementJson = (json) => {
204
+ const [row] = jsonFrom(json, psListOf(ElementRowSchema), "UI Automation", "an element");
205
+ return row === undefined ? undefined : elementOf(row);
206
+ };
207
+ const ElementTreeSchema = z.object({
208
+ window: z.object({ id: z.string().catch(""), title: z.string().catch(""), app: z.string().catch("") }),
209
+ elements: rowsOf(ElementRowSchema).catch([]),
210
+ truncated: z.boolean().catch(false),
211
+ });
212
+ export const parseElementTreeJson = (json) => {
213
+ const tree = jsonFrom(json, ElementTreeSchema, "UI Automation", "an element tree");
214
+ return { window: tree.window, elements: tree.elements.map(elementOf), truncated: tree.truncated };
215
+ };
216
+ export const parseXwininfoTree = (output) => new Map(output.split(/\r?\n/).flatMap((line) => {
217
+ const fields = /^\s*(0x[0-9a-f]+)\s.*\s(\d+)x(\d+)[+-]-?\d+[+-]-?\d+\s+\+?(-?\d+)\+?(-?\d+)\s*$/i.exec(line);
218
+ if (fields === null) {
219
+ return [];
220
+ }
221
+ const [, id, width, height, x, y] = fields;
222
+ return [[Number(id), { x: Number(x), y: Number(y), width: Number(width), height: Number(height) }]];
223
+ }));
224
+ export const withAbsoluteBounds = (windows, tree) => windows.map((window) => {
225
+ const exact = tree.get(Number(window.id));
226
+ return exact === undefined ? window : { ...window, bounds: exact };
227
+ });
109
228
  //# sourceMappingURL=parse.js.map