@melra/computer-runtime 0.3.0-alpha.10 → 0.3.0-alpha.12

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 CHANGED
@@ -2,7 +2,9 @@
2
2
 
3
3
  Screen and input control for [MELRA](https://github.com/XAGI-Lab/melra):
4
4
  capabilities, inspect, screenshot, click, move, drag, type, key, and scroll,
5
- driven through the host's own automation tooling.
5
+ driven through the host's own automation tooling: native scripts on macOS,
6
+ Windows PowerShell and .NET on Windows, and screenshot tools plus `xdotool` on
7
+ Linux/X11.
6
8
 
7
9
  ```bash
8
10
  npm install @melra/computer-runtime
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@melra/computer-runtime",
3
- "version": "0.3.0-alpha.10",
3
+ "version": "0.3.0-alpha.12",
4
4
  "description": "Computer-use reference effect adapter for the MELRA kernel.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -21,12 +21,12 @@
21
21
  "dist"
22
22
  ],
23
23
  "dependencies": {
24
- "@melra/protocol": "0.3.0-alpha.10"
24
+ "@melra/protocol": "0.3.0-alpha.12"
25
25
  },
26
26
  "scripts": {
27
27
  "build": "tsc -p tsconfig.json",
28
28
  "clean": "rm -rf dist",
29
29
  "test": "vitest run",
30
- "typecheck": "tsc -p tsconfig.json --noEmit"
30
+ "typecheck": "tsc -p tsconfig.test.json"
31
31
  }
32
32
  }
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=index.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.test.d.ts","sourceRoot":"","sources":["../src/index.test.ts"],"names":[],"mappings":""}
@@ -1,259 +0,0 @@
1
- // Copyright 2026 XAGI Labs Private Limited
2
- // SPDX-License-Identifier: Apache-2.0
3
- import { describe, expect, it } from "vitest";
4
- import { ComputerOperationSchema } from "@melra/protocol";
5
- import { ComputerRuntime, matchElement, parseOcrElements, parseSecureInput, } from "./index.js";
6
- class TestAdapter {
7
- overrides;
8
- calls = [];
9
- operations = [];
10
- /** What `inspect` reports back; a live desktop is the only other source. */
11
- elements = [];
12
- constructor(overrides = {}) {
13
- this.overrides = overrides;
14
- }
15
- async capabilities() {
16
- return {
17
- platform: "darwin",
18
- adapter: "macos-native",
19
- available: true,
20
- screenshot: true,
21
- pointer: true,
22
- keyboard: true,
23
- scroll: true,
24
- inspect: true,
25
- elements: true,
26
- ocr: false,
27
- drag: true,
28
- coordinateSpaces: ["normalized", "pixel"],
29
- limitations: [],
30
- ...this.overrides,
31
- };
32
- }
33
- async execute(operation) {
34
- this.calls.push(operation.action);
35
- this.operations.push(operation);
36
- return {
37
- success: true,
38
- action: operation.action,
39
- ...(operation.action === "inspect" ? { elements: this.elements } : {}),
40
- };
41
- }
42
- }
43
- const BUTTON = (name, x) => ({
44
- role: "AXButton",
45
- name,
46
- x,
47
- y: 40,
48
- width: 80,
49
- height: 20,
50
- });
51
- describe("ComputerRuntime", () => {
52
- it("reports adapter capabilities without a mutation", async () => {
53
- const adapter = new TestAdapter();
54
- const runtime = new ComputerRuntime({
55
- artifactDirectory: "/tmp",
56
- adapter,
57
- });
58
- const result = await runtime.execute(ComputerOperationSchema.parse({
59
- kind: "computer",
60
- action: "capabilities",
61
- }));
62
- expect(result.available).toBe(true);
63
- expect(adapter.calls).toEqual([]);
64
- });
65
- it("requires explicit bounded coordinates for pointer actions", async () => {
66
- const runtime = new ComputerRuntime({
67
- artifactDirectory: "/tmp",
68
- adapter: new TestAdapter(),
69
- });
70
- await expect(runtime.execute(ComputerOperationSchema.parse({
71
- kind: "computer",
72
- action: "click",
73
- }))).rejects.toThrow("computer_click_requires_coordinates");
74
- await expect(runtime.execute(ComputerOperationSchema.parse({
75
- kind: "computer",
76
- action: "click",
77
- coordinateSpace: "normalized",
78
- x: 2,
79
- y: 0.5,
80
- }))).rejects.toThrow("computer_normalized_coordinates_out_of_range");
81
- });
82
- it.each([
83
- ["screenshot", "screenshot", "computer_screenshot_unavailable"],
84
- ["inspect", "inspect", "computer_inspect_unavailable"],
85
- ["click", "pointer", "computer_pointer_unavailable"],
86
- ["drag", "drag", "computer_drag_unavailable"],
87
- ["type", "keyboard", "computer_keyboard_unavailable"],
88
- ["scroll", "scroll", "computer_scroll_unavailable"],
89
- ])("rejects %s when its adapter capability is unavailable", async (action, capability, error) => {
90
- const adapter = new TestAdapter({ [capability]: false });
91
- const runtime = new ComputerRuntime({
92
- artifactDirectory: "/tmp",
93
- adapter,
94
- });
95
- const operation = {
96
- kind: "computer",
97
- action,
98
- ...(action === "click"
99
- ? { coordinateSpace: "pixel", x: 10, y: 10 }
100
- : {}),
101
- ...(action === "drag"
102
- ? { coordinateSpace: "pixel", x: 10, y: 10, toX: 40, toY: 40 }
103
- : {}),
104
- ...(action === "type" ? { text: "safe" } : {}),
105
- };
106
- await expect(runtime.execute(ComputerOperationSchema.parse(operation))).rejects.toThrow(error);
107
- expect(adapter.calls).toEqual([]);
108
- });
109
- it("requires a destination for a drag and bounds it like the press point", async () => {
110
- const adapter = new TestAdapter();
111
- const runtime = new ComputerRuntime({
112
- artifactDirectory: "/tmp",
113
- adapter,
114
- });
115
- await expect(runtime.execute(ComputerOperationSchema.parse({
116
- kind: "computer",
117
- action: "drag",
118
- coordinateSpace: "pixel",
119
- x: 10,
120
- y: 10,
121
- }))).rejects.toThrow("computer_drag_requires_destination");
122
- // The destination shares the coordinate space, so it has to be bounded by
123
- // the same rule — an out-of-range `toY` used to slip through untouched.
124
- await expect(runtime.execute(ComputerOperationSchema.parse({
125
- kind: "computer",
126
- action: "drag",
127
- coordinateSpace: "normalized",
128
- x: 0.1,
129
- y: 0.1,
130
- toX: 0.5,
131
- toY: 4,
132
- }))).rejects.toThrow("computer_normalized_coordinates_out_of_range");
133
- expect(adapter.calls).toEqual([]);
134
- });
135
- it("passes a bounded drag and a read-only inspect to the adapter", async () => {
136
- const adapter = new TestAdapter();
137
- const runtime = new ComputerRuntime({
138
- artifactDirectory: "/tmp",
139
- adapter,
140
- });
141
- await runtime.execute(ComputerOperationSchema.parse({ kind: "computer", action: "inspect" }));
142
- await runtime.execute(ComputerOperationSchema.parse({
143
- kind: "computer",
144
- action: "drag",
145
- coordinateSpace: "normalized",
146
- x: 0.1,
147
- y: 0.2,
148
- toX: 0.8,
149
- toY: 0.9,
150
- }));
151
- expect(adapter.calls).toEqual(["inspect", "drag"]);
152
- });
153
- });
154
- describe("matchElement", () => {
155
- const elements = [
156
- BUTTON("Save", 0),
157
- BUTTON("Save As…", 100),
158
- { role: "AXTextField", name: "Save", x: 200, y: 40, width: 60, height: 20 },
159
- ];
160
- it("prefers an exact name over the substring it is a prefix of", () => {
161
- expect(matchElement(elements, { role: "AXButton", name: "Save" }).x).toBe(0);
162
- });
163
- it("matches a role case-insensitively and a name by substring", () => {
164
- expect(matchElement(elements, { role: "axbutton", name: "as…" }).x).toBe(100);
165
- });
166
- it("refuses rather than guessing between equally good candidates", () => {
167
- // Two exact "Save" matches across roles: picking either would be a coin
168
- // flip on which control gets clicked.
169
- expect(() => matchElement(elements, { name: "Save" })).toThrow("computer_target_ambiguous");
170
- expect(() => matchElement(elements, { name: "Print" })).toThrow("computer_target_not_found");
171
- expect(() => matchElement(elements, {})).toThrow("computer_target_requires_role_or_name");
172
- });
173
- it("refuses to click a reading it is not sure of", () => {
174
- // Reported by `inspect` — a caller may want to know the word is there — but
175
- // not clickable, because the point under a doubtful reading is a guess.
176
- const read = [{ ...BUTTON("Delete", 0), role: "text", confidence: 0.42 }];
177
- expect(() => matchElement(read, { name: "Delete" })).toThrow("computer_target_confidence_too_low");
178
- expect(matchElement([{ ...read[0], confidence: 0.91 }], { name: "Delete" }).x).toBe(0);
179
- });
180
- });
181
- describe("parseOcrElements", () => {
182
- // Real `tesseract 5 … tsv` output, trimmed: a page row, the block/para/line
183
- // rows above a word, and the words themselves.
184
- const tsv = [
185
- "level\tpage_num\tblock_num\tpar_num\tline_num\tword_num\tleft\ttop\twidth\theight\tconf\ttext",
186
- "1\t1\t0\t0\t0\t0\t0\t0\t2940\t1912\t-1\t",
187
- "4\t1\t1\t1\t1\t0\t42\t15\t167\t31\t-1\t",
188
- "5\t1\t1\t1\t1\t1\t100\t40\t80\t20\t96.720352\tSave",
189
- "5\t1\t1\t1\t1\t2\t300\t40\t90\t20\t41.5\tCancel",
190
- "5\t1\t1\t1\t1\t3\t500\t40\t60\t20\t12.25\tl1lI",
191
- "5\t1\t1\t1\t1\t4\t600\t40\t60\t20\t95.0\t ",
192
- ].join("\n");
193
- it("scales a Retina capture back onto the display it came from", () => {
194
- // The image measured 2940 wide, the display is 1470: every box halves, so a
195
- // click computed from one lands where the word actually is.
196
- expect(parseOcrElements(tsv, 1470)).toEqual([
197
- { role: "text", name: "Save", x: 50, y: 20, width: 40, height: 10, confidence: 0.97 },
198
- { role: "text", name: "Cancel", x: 150, y: 20, width: 45, height: 10, confidence: 0.42 },
199
- ]);
200
- });
201
- it("drops noise and reads nothing at all from a capture with no page row", () => {
202
- // `l1lI` is under the reporting floor and the blank token has no name;
203
- // without a page row there is no scale, and guessing one would move a click.
204
- expect(parseOcrElements(tsv, 1470).map((e) => e.name)).not.toContain("l1lI");
205
- expect(parseOcrElements("level\tpage_num\n4\t1", 1470)).toEqual([]);
206
- });
207
- });
208
- describe("named targets", () => {
209
- const click = (target, extra = {}) => ComputerOperationSchema.parse({
210
- kind: "computer",
211
- action: "click",
212
- target,
213
- ...extra,
214
- });
215
- it("inspects, then clicks the centre of the resolved element", async () => {
216
- const adapter = new TestAdapter();
217
- adapter.elements = [BUTTON("Save", 300)];
218
- const runtime = new ComputerRuntime({ artifactDirectory: "/tmp", adapter });
219
- const result = await runtime.execute(click({ name: "Save" }));
220
- expect(adapter.calls).toEqual(["inspect", "click"]);
221
- const acted = adapter.operations[1];
222
- // 300 + 80/2, 40 + 20/2 — in pixels, because that is what the tree measures.
223
- expect([acted.coordinateSpace, acted.x, acted.y]).toEqual(["pixel", 340, 50]);
224
- expect(acted.target).toBe(undefined);
225
- expect(result.element).toEqual(BUTTON("Save", 300));
226
- });
227
- it("refuses a target the platform or the request cannot support", async () => {
228
- const adapter = new TestAdapter();
229
- const runtime = new ComputerRuntime({ artifactDirectory: "/tmp", adapter });
230
- adapter.elements = [BUTTON("Save", 300)];
231
- await expect(runtime.execute(click({ name: "Save" }, { x: 10, y: 10 }))).rejects.toThrow("computer_target_conflicts_with_coordinates");
232
- adapter.elements = [];
233
- await expect(runtime.execute(click({ name: "Save" }))).rejects.toThrow("computer_elements_unavailable");
234
- const blind = new ComputerRuntime({
235
- artifactDirectory: "/tmp",
236
- adapter: new TestAdapter({ elements: false }),
237
- });
238
- await expect(blind.execute(click({ name: "Save" }))).rejects.toThrow("computer_elements_unavailable");
239
- });
240
- });
241
- describe("parseSecureInput", () => {
242
- // Trimmed from real `ioreg -l -d 1 -w 0 -r -c IOResources` output on macOS 26.
243
- const session = '"IOConsoleUsers" = ({"kCGSSessionOnConsoleKey"=Yes,"kSCSecuritySessionID"=100024,' +
244
- '"kCGSSessionIDKey"=257,"kCGSSessionUserNameKey"="dheeraj"';
245
- it("reads a held secure-input session as active", () => {
246
- expect(parseSecureInput(`${session},"kCGSSessionSecureInputPID"=843})`)).toBe(true);
247
- });
248
- it("reads a session without the key, or with it cleared, as inactive", () => {
249
- expect(parseSecureInput(`${session}})`)).toBe(false);
250
- expect(parseSecureInput(`${session},"kCGSSessionSecureInputPID"=0})`)).toBe(false);
251
- });
252
- it("reports no reading at all when no console session was dumped", () => {
253
- // Absence of the key in output that never described a session is not
254
- // evidence that secure input is off — reporting `false` here would let a
255
- // keystroke-swallowing state through as verified.
256
- expect(parseSecureInput("+-o Root <class IORegistryEntry>")).toBe(undefined);
257
- });
258
- });
259
- //# sourceMappingURL=index.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.test.js","sourceRoot":"","sources":["../src/index.test.ts"],"names":[],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=windows.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"windows.test.d.ts","sourceRoot":"","sources":["../src/windows.test.ts"],"names":[],"mappings":""}
@@ -1,129 +0,0 @@
1
- // Copyright 2026 XAGI Labs Private Limited
2
- // SPDX-License-Identifier: Apache-2.0
3
- import { mkdtemp, rm, stat } from "node:fs/promises";
4
- import { tmpdir } from "node:os";
5
- import { join } from "node:path";
6
- import { ComputerOperationSchema } from "@melra/protocol";
7
- import { afterEach, describe, expect, it } from "vitest";
8
- import { ComputerRuntime, createSystemComputerAdapter, escapeSendKeys } from "./index.js";
9
- /**
10
- * Windows computer use was entirely absent: the factory had no `win32` branch,
11
- * so `capabilities` reported `unavailable` and every input action threw a bare
12
- * `computer_use_unavailable`. CI ran on `windows-latest` and stayed green
13
- * because nothing exercised Windows behaviour — which is why the adapter tests
14
- * below run for real on Windows rather than against a stub.
15
- */
16
- const onWindows = process.platform === "win32";
17
- const roots = [];
18
- /**
19
- * Two clocks, and both have to clear the same wait: vitest's own default killed
20
- * these tests at 5s, and once that was raised the operation's `timeoutMs` cap
21
- * killed them at 30s — which is why the schema now allows 120s for a computer
22
- * action like every other operation kind.
23
- *
24
- * The wait is real, not slack. A computer action spawns a whole interpreter:
25
- * `powershell.exe` cold-starts in seconds, the pointer script's
26
- * `Add-Type -TypeDefinition` runs the C# compiler to build the P/Invoke shim,
27
- * and the first such spawn after boot pays for a cold disk on top. That cost is
28
- * per-process, so it is paid on every action, and a caller who leaves
29
- * `timeoutMs` at its 10s default is closer to the edge on a cold or loaded
30
- * machine than the number suggests.
31
- */
32
- const POWERSHELL_TEST_TIMEOUT_MS = 120_000;
33
- afterEach(async () => {
34
- await Promise.all(roots.splice(0).map((root) => rm(root, { recursive: true, force: true })));
35
- });
36
- async function workspace() {
37
- const root = await mkdtemp(join(tmpdir(), "melra-computer-"));
38
- roots.push(root);
39
- return root;
40
- }
41
- describe("escapeSendKeys", () => {
42
- it("neutralizes the characters SendKeys reads as modifiers", () => {
43
- // Unescaped, `+` is Shift, `^` is Ctrl, `%` is Alt, `~` is Enter, and the
44
- // brackets group — so this password would have typed a chord and pressed
45
- // Enter instead of entering any of these characters.
46
- expect(escapeSendKeys("a+b^c%d~e")).toBe("a{+}b{^}c{%}d{~}e");
47
- expect(escapeSendKeys("({x})[y]")).toBe("{(}{{}x{}}{)}{[}y{]}");
48
- });
49
- it("leaves ordinary text alone", () => {
50
- expect(escapeSendKeys("Hello, world 123")).toBe("Hello, world 123");
51
- });
52
- });
53
- describe.runIf(onWindows)("Windows computer adapter", () => {
54
- it("reports itself as available rather than unavailable", async () => {
55
- const runtime = new ComputerRuntime({
56
- artifactDirectory: await workspace(),
57
- adapter: createSystemComputerAdapter(),
58
- });
59
- const observed = await runtime.execute(ComputerOperationSchema.parse({ kind: "computer", action: "capabilities" }));
60
- expect(observed.platform).toBe("win32");
61
- expect(observed.adapter).toBe("windows-powershell");
62
- expect(observed.available).toBe(true);
63
- expect(observed.screenshot).toBe(true);
64
- expect(observed.pointer).toBe(true);
65
- // The honest ceiling of SendKeys-based input, stated rather than implied.
66
- expect(observed.limitations.join(" ")).toContain("focus");
67
- });
68
- it("captures a real screenshot to the artifact directory", async () => {
69
- const artifactDirectory = join(await workspace(), "artifacts");
70
- const runtime = new ComputerRuntime({
71
- artifactDirectory,
72
- adapter: createSystemComputerAdapter(),
73
- });
74
- const observed = await runtime.execute(ComputerOperationSchema.parse({
75
- kind: "computer",
76
- action: "screenshot",
77
- timeoutMs: 90_000,
78
- }));
79
- expect(observed.captured).toBe(true);
80
- expect(String(observed.path).startsWith(artifactDirectory)).toBe(true);
81
- const written = await stat(String(observed.path));
82
- expect(written.size).toBeGreaterThan(0);
83
- expect(observed.size).toBe(written.size);
84
- expect(String(observed.sha256)).toHaveLength(64);
85
- }, POWERSHELL_TEST_TIMEOUT_MS);
86
- it("resolves a normalized coordinate against the virtual desktop", async () => {
87
- const runtime = new ComputerRuntime({
88
- artifactDirectory: await workspace(),
89
- adapter: createSystemComputerAdapter(),
90
- });
91
- // A pointer move is the P/Invoke path — the part most likely to be wrong —
92
- // and moving the cursor on a headless runner has no side effect worth
93
- // avoiding. Clicking would, so this does not click.
94
- const observed = await runtime.execute(ComputerOperationSchema.parse({
95
- kind: "computer",
96
- action: "move",
97
- x: 0.5,
98
- y: 0.5,
99
- coordinateSpace: "normalized",
100
- timeoutMs: 90_000,
101
- }));
102
- expect(observed.success).toBe(true);
103
- // The pixel point comes back from the script rather than being recomputed
104
- // here, so a normalized centre must land somewhere other than the origin.
105
- expect(observed.x).toBeGreaterThan(0);
106
- expect(observed.y).toBeGreaterThan(0);
107
- }, POWERSHELL_TEST_TIMEOUT_MS);
108
- it("names a timeout as a timeout instead of echoing the script", async () => {
109
- const runtime = new ComputerRuntime({
110
- artifactDirectory: await workspace(),
111
- adapter: createSystemComputerAdapter(),
112
- });
113
- /**
114
- * This is how the screenshot failure first presented: Node builds the
115
- * rejection message from the whole command line, so the caller received
116
- * fifteen lines of echoed PowerShell with an empty stderr and no way to
117
- * tell a killed helper from a script that failed instantly.
118
- *
119
- * 100ms is unreachable for a process that has to load the CLR, so this is a
120
- * timeout by construction rather than by timing luck.
121
- */
122
- await expect(runtime.execute(ComputerOperationSchema.parse({
123
- kind: "computer",
124
- action: "screenshot",
125
- timeoutMs: 100,
126
- }))).rejects.toThrow(/^computer_helper_timeout:powershell\.exe:100ms$/);
127
- }, POWERSHELL_TEST_TIMEOUT_MS);
128
- });
129
- //# sourceMappingURL=windows.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"windows.test.js","sourceRoot":"","sources":["../src/windows.test.ts"],"names":[],"mappings":"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"}