@ycheung5/pi-computer-use 0.0.0-stage → 0.1.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 (92) hide show
  1. package/GLOSSARY.md +38 -0
  2. package/LICENSE +21 -0
  3. package/README.md +165 -2
  4. package/assets/accessibility.cs +208 -0
  5. package/assets/browser-indicators.cs +37 -0
  6. package/assets/capture.cs +215 -0
  7. package/assets/clipboard.cs +197 -0
  8. package/assets/controls.cs +249 -0
  9. package/assets/indicator-preview.png +0 -0
  10. package/assets/indicators.cs +252 -0
  11. package/assets/node-LICENSE.txt +2732 -0
  12. package/assets/ocr.cs +86 -0
  13. package/assets/ownership.cs +59 -0
  14. package/assets/pointer.cs +229 -0
  15. package/assets/puppeteer-LICENSE.txt +202 -0
  16. package/assets/readme-banner.svg +33 -0
  17. package/assets/stop.cs +197 -0
  18. package/assets/text.cs +249 -0
  19. package/assets/wgc.cs +167 -0
  20. package/assets/window-management.cs +217 -0
  21. package/assets/window-marker.cs +23 -0
  22. package/assets/window-references.cs +80 -0
  23. package/assets/windows.cs +127 -0
  24. package/dist/accessibility.d.ts +29 -0
  25. package/dist/accessibility.js +258 -0
  26. package/dist/browser-actions.d.ts +21 -0
  27. package/dist/browser-actions.js +213 -0
  28. package/dist/browser-indicators.d.ts +23 -0
  29. package/dist/browser-indicators.js +69 -0
  30. package/dist/browser-profiles.d.ts +10 -0
  31. package/dist/browser-profiles.js +174 -0
  32. package/dist/browser.d.ts +11 -0
  33. package/dist/browser.js +2071 -0
  34. package/dist/capture.d.ts +74 -0
  35. package/dist/capture.js +199 -0
  36. package/dist/client.d.ts +38 -0
  37. package/dist/client.js +331 -0
  38. package/dist/desktop.d.ts +20 -0
  39. package/dist/desktop.js +42 -0
  40. package/dist/extension.d.ts +4 -0
  41. package/dist/extension.js +409 -0
  42. package/dist/launcher.d.ts +6 -0
  43. package/dist/launcher.js +85 -0
  44. package/dist/native.d.ts +11 -0
  45. package/dist/native.js +145 -0
  46. package/dist/ocr.d.ts +52 -0
  47. package/dist/ocr.js +246 -0
  48. package/dist/ownership.d.ts +4 -0
  49. package/dist/ownership.js +24 -0
  50. package/dist/pointer.d.ts +108 -0
  51. package/dist/pointer.js +174 -0
  52. package/dist/protocol.d.ts +15 -0
  53. package/dist/protocol.js +1 -0
  54. package/dist/runtime.d.ts +8 -0
  55. package/dist/runtime.js +72 -0
  56. package/dist/settings.d.ts +85 -0
  57. package/dist/settings.js +449 -0
  58. package/dist/stop.d.ts +24 -0
  59. package/dist/stop.js +156 -0
  60. package/dist/text.d.ts +100 -0
  61. package/dist/text.js +183 -0
  62. package/dist/waits.d.ts +19 -0
  63. package/dist/waits.js +262 -0
  64. package/dist/window-management.d.ts +25 -0
  65. package/dist/window-management.js +167 -0
  66. package/dist/worker.d.ts +1 -0
  67. package/dist/worker.js +540 -0
  68. package/docs/README.md +54 -0
  69. package/docs/adr/0001-preserve-reference-behavior.md +9 -0
  70. package/docs/adr/0002-window-lifetime-references.md +11 -0
  71. package/docs/adr/0003-exclusive-desktop-control.md +11 -0
  72. package/docs/adr/0004-pi-first-acceptance.md +9 -0
  73. package/docs/adr/0005-default-apps-and-workspace-reuse.md +7 -0
  74. package/docs/agents/domain.md +9 -0
  75. package/docs/agents/issue-tracker.md +10 -0
  76. package/docs/agents/triage-labels.md +9 -0
  77. package/docs/browser.md +113 -0
  78. package/docs/implementation-plan.md +139 -0
  79. package/docs/indicators.md +53 -0
  80. package/docs/native-interop-research.md +17 -0
  81. package/docs/ownership.md +25 -0
  82. package/docs/pi-extension-research.md +57 -0
  83. package/docs/pointer.md +65 -0
  84. package/docs/runtime.md +42 -0
  85. package/docs/settings.md +33 -0
  86. package/docs/spec.md +161 -0
  87. package/docs/stopping.md +83 -0
  88. package/docs/text.md +79 -0
  89. package/docs/tickets.md +84 -0
  90. package/docs/validation.md +1372 -0
  91. package/docs/windows.md +171 -0
  92. package/package.json +134 -4
package/dist/text.d.ts ADDED
@@ -0,0 +1,100 @@
1
+ import type { WorkerResult } from "./protocol.js";
2
+ export declare const textTools: ({
3
+ action: string;
4
+ parameters: {
5
+ type: string;
6
+ additionalProperties: boolean;
7
+ properties: {
8
+ text: {
9
+ type: string;
10
+ minLength: number;
11
+ maxLength: number;
12
+ };
13
+ method: {
14
+ type: string;
15
+ enum: string[];
16
+ default: string;
17
+ };
18
+ focusMode: {
19
+ type: string;
20
+ enum: string[];
21
+ default: string;
22
+ };
23
+ restoreClipboard: {
24
+ type: string;
25
+ default: boolean;
26
+ };
27
+ windowRef: {
28
+ type: string;
29
+ minLength: number;
30
+ };
31
+ windowTitle: {
32
+ type: string;
33
+ };
34
+ processId: {
35
+ type: string;
36
+ minimum: number;
37
+ };
38
+ nativeWindowHandle: {
39
+ type: string;
40
+ minimum: number;
41
+ };
42
+ activate: {
43
+ type: string;
44
+ };
45
+ browserTab: {
46
+ type: string;
47
+ minLength: number;
48
+ };
49
+ };
50
+ required: string[];
51
+ };
52
+ } | {
53
+ action: string;
54
+ parameters: {
55
+ type: string;
56
+ additionalProperties: boolean;
57
+ properties: {
58
+ keys: {
59
+ type: string;
60
+ items: {
61
+ type: string;
62
+ minLength: number;
63
+ };
64
+ minItems: number;
65
+ maxItems: number;
66
+ };
67
+ dispatch: {
68
+ type: string;
69
+ enum: string[];
70
+ default: string;
71
+ };
72
+ windowRef: {
73
+ type: string;
74
+ minLength: number;
75
+ };
76
+ windowTitle: {
77
+ type: string;
78
+ };
79
+ processId: {
80
+ type: string;
81
+ minimum: number;
82
+ };
83
+ nativeWindowHandle: {
84
+ type: string;
85
+ minimum: number;
86
+ };
87
+ activate: {
88
+ type: string;
89
+ };
90
+ browserTab: {
91
+ type: string;
92
+ minLength: number;
93
+ };
94
+ };
95
+ required: string[];
96
+ };
97
+ })[];
98
+ export declare function validateText(action: string, args: Record<string, unknown>): WorkerResult | undefined;
99
+ export declare function prepareTextInput(action: string, args: Record<string, unknown>, signal?: AbortSignal): Promise<Record<string, unknown>>;
100
+ export declare function executeText(action: string, args: Record<string, unknown>, cancelEvent: string, operationId: string, listenerProcessId?: number, signal?: AbortSignal): Promise<WorkerResult>;
package/dist/text.js ADDED
@@ -0,0 +1,183 @@
1
+ import { compileNative } from "./native.js";
2
+ import { executePointer } from "./pointer.js";
3
+ const target = {
4
+ windowRef: { type: "string", minLength: 1 },
5
+ windowTitle: { type: "string" },
6
+ processId: { type: "integer", minimum: 1 },
7
+ nativeWindowHandle: { type: "integer", minimum: 1 },
8
+ activate: { type: "boolean" },
9
+ browserTab: { type: "string", minLength: 1 },
10
+ };
11
+ export const textTools = [
12
+ {
13
+ action: "type_text",
14
+ parameters: {
15
+ type: "object",
16
+ additionalProperties: false,
17
+ properties: {
18
+ ...target,
19
+ text: { type: "string", minLength: 1, maxLength: 1000000 },
20
+ method: {
21
+ type: "string",
22
+ enum: ["auto", "clipboard", "sendinput", "background"],
23
+ default: "auto",
24
+ },
25
+ focusMode: {
26
+ type: "string",
27
+ enum: ["preserve", "main"],
28
+ default: "preserve",
29
+ },
30
+ restoreClipboard: { type: "boolean", default: true },
31
+ },
32
+ required: ["text"],
33
+ },
34
+ },
35
+ {
36
+ action: "keypress",
37
+ parameters: {
38
+ type: "object",
39
+ additionalProperties: false,
40
+ properties: {
41
+ ...target,
42
+ keys: {
43
+ type: "array",
44
+ items: { type: "string", minLength: 1 },
45
+ minItems: 1,
46
+ maxItems: 4,
47
+ },
48
+ dispatch: {
49
+ type: "string",
50
+ enum: ["foreground", "background"],
51
+ default: "foreground",
52
+ },
53
+ },
54
+ required: ["keys"],
55
+ },
56
+ },
57
+ ];
58
+ const modifiers = ["ctrl", "control", "alt", "option", "shift"];
59
+ const special = new Set([
60
+ "enter",
61
+ "return",
62
+ "tab",
63
+ "esc",
64
+ "escape",
65
+ "backspace",
66
+ "delete",
67
+ "del",
68
+ "home",
69
+ "end",
70
+ "pageup",
71
+ "pgup",
72
+ "pagedown",
73
+ "pgdn",
74
+ "up",
75
+ "down",
76
+ "left",
77
+ "right",
78
+ "space",
79
+ "insert",
80
+ "ins",
81
+ "pause",
82
+ "capslock",
83
+ "numlock",
84
+ "scrolllock",
85
+ ...Array.from({ length: 24 }, (_, i) => `f${i + 1}`),
86
+ ]);
87
+ export function validateText(action, args) {
88
+ const error = (message) => ({
89
+ ok: false,
90
+ action,
91
+ error: message,
92
+ });
93
+ const bad = (message) => error(`INVALID_ARGUMENTS: ${message}`);
94
+ const allowed = new Set([
95
+ ...Object.keys(target),
96
+ ...(action === "type_text"
97
+ ? ["text", "method", "focusMode", "restoreClipboard"]
98
+ : ["keys", "dispatch"]),
99
+ ]);
100
+ if (args.windowRef !== undefined &&
101
+ (typeof args.windowRef !== "string" || !args.windowRef.trim()))
102
+ return bad("windowRef must be nonempty");
103
+ for (const key of Object.keys(args))
104
+ if (!allowed.has(key))
105
+ return bad(`unknown option ${key}`);
106
+ for (const key of ["processId", "nativeWindowHandle"])
107
+ if (args[key] !== undefined &&
108
+ (!Number.isSafeInteger(args[key]) || Number(args[key]) < 1))
109
+ return bad(`${key} must be a positive integer`);
110
+ if (args.windowTitle !== undefined &&
111
+ (typeof args.windowTitle !== "string" || !args.windowTitle.trim()))
112
+ return bad("windowTitle must be nonempty");
113
+ if (args.activate !== undefined && typeof args.activate !== "boolean")
114
+ return bad("activate must be boolean");
115
+ if (action === "type_text") {
116
+ if (typeof args.text !== "string" ||
117
+ args.text.length === 0 ||
118
+ args.text.length > 1000000 ||
119
+ args.text.includes("\0"))
120
+ return bad("text must be nonempty, without NUL, at most 1000000 UTF-16 units");
121
+ if (args.method !== undefined &&
122
+ !["auto", "clipboard", "sendinput", "background"].includes(String(args.method)))
123
+ return bad("unsupported method");
124
+ if (args.focusMode !== undefined &&
125
+ !["preserve", "main"].includes(String(args.focusMode)))
126
+ return bad("unsupported focusMode");
127
+ if (args.restoreClipboard !== undefined &&
128
+ typeof args.restoreClipboard !== "boolean")
129
+ return bad("restoreClipboard must be boolean");
130
+ }
131
+ else {
132
+ if (!Array.isArray(args.keys) ||
133
+ args.keys.length < 1 ||
134
+ args.keys.length > 4 ||
135
+ args.keys.some((k) => typeof k !== "string" || !k.length))
136
+ return bad("keys requires 1–4 key names");
137
+ let main = 0;
138
+ const seen = new Set();
139
+ for (const raw of args.keys) {
140
+ const key = raw.toLowerCase().trim();
141
+ if (["win", "windows", "cmd", "meta"].includes(key))
142
+ return error("KEY_BLOCKED: Windows key is blocked by design");
143
+ if (modifiers.includes(key)) {
144
+ const canonical = key === "control" ? "ctrl" : key === "option" ? "alt" : key;
145
+ if (seen.has(canonical))
146
+ return bad("duplicate modifier");
147
+ seen.add(canonical);
148
+ }
149
+ else {
150
+ main++;
151
+ if (!special.has(key) &&
152
+ !(raw.length === 1 &&
153
+ raw.charCodeAt(0) >= 32 &&
154
+ raw.charCodeAt(0) !== 127))
155
+ return bad("unsupported key");
156
+ }
157
+ }
158
+ if (main !== 1)
159
+ return bad("exactly one non-modifier key is required");
160
+ if (args.dispatch !== undefined &&
161
+ !["foreground", "background"].includes(String(args.dispatch)))
162
+ return bad("unsupported dispatch");
163
+ if (args.dispatch === "background" &&
164
+ (args.keys.length !== 1 ||
165
+ args.keys[0].length !== 1 ||
166
+ args.keys[0].charCodeAt(0) < 32))
167
+ return error("BACKGROUND_UNAVAILABLE: only one printable character can be posted");
168
+ }
169
+ return undefined;
170
+ }
171
+ export async function prepareTextInput(action, args, signal) {
172
+ if (action === "type_text" &&
173
+ ["auto", "clipboard"].includes(String(args.method ?? "auto")))
174
+ return {
175
+ ...args,
176
+ _clipboardExecutable: (await compileNative(["clipboard.cs"], [], signal))
177
+ .executable,
178
+ };
179
+ return args;
180
+ }
181
+ export async function executeText(action, args, cancelEvent, operationId, listenerProcessId, signal) {
182
+ return executePointer(action, args, cancelEvent, operationId, listenerProcessId, signal);
183
+ }
@@ -0,0 +1,19 @@
1
+ import type { WorkerResult } from "./protocol.js";
2
+ type Rule = {
3
+ type: "integer" | "string" | "boolean";
4
+ default?: unknown;
5
+ minimum?: number;
6
+ maximum?: number;
7
+ minLength?: number;
8
+ enum?: string[];
9
+ };
10
+ export declare const waitTools: {
11
+ action: string;
12
+ parameters: {
13
+ type: string;
14
+ additionalProperties: boolean;
15
+ properties: Record<string, Rule>;
16
+ };
17
+ }[];
18
+ export declare function waitDesktop(action: string, input: Record<string, unknown>, signal?: AbortSignal): Promise<WorkerResult>;
19
+ export {};
package/dist/waits.js ADDED
@@ -0,0 +1,262 @@
1
+ import { setTimeout as delay } from "node:timers/promises";
2
+ import { executeAccessibility } from "./accessibility.js";
3
+ import { retireDesktop } from "./desktop.js";
4
+ import { nativeDesktop } from "./native.js";
5
+ import { ocrDesktop } from "./ocr.js";
6
+ const waitDefinition = {
7
+ milliseconds: { type: "integer", minimum: 1, maximum: 30000, default: 500 },
8
+ };
9
+ const conditionDefinition = {
10
+ windowRef: { type: "string", minLength: 1 },
11
+ windowTitle: { type: "string" },
12
+ processId: { type: "integer", minimum: 1 },
13
+ nativeWindowHandle: { type: "integer", minimum: 1 },
14
+ activate: { type: "boolean", default: false },
15
+ scope: {
16
+ type: "string",
17
+ enum: ["active_window", "desktop"],
18
+ default: "active_window",
19
+ },
20
+ condition: {
21
+ type: "string",
22
+ enum: ["window", "element", "text"],
23
+ default: "window",
24
+ },
25
+ query: { type: "string" },
26
+ controlType: { type: "string" },
27
+ viewMode: {
28
+ type: "string",
29
+ enum: ["control", "content", "raw"],
30
+ default: "control",
31
+ },
32
+ includeOffscreen: { type: "boolean", default: false },
33
+ treeTimeoutMs: {
34
+ type: "integer",
35
+ minimum: 100,
36
+ maximum: 30000,
37
+ default: 1000,
38
+ },
39
+ maxDepth: { type: "integer", minimum: 0, maximum: 12, default: 8 },
40
+ maxNodes: { type: "integer", minimum: 1, maximum: 5000, default: 1200 },
41
+ appear: { type: "boolean", default: true },
42
+ timeoutMs: { type: "integer", minimum: 100, maximum: 60000, default: 5000 },
43
+ intervalMs: { type: "integer", minimum: 50, maximum: 5000, default: 250 },
44
+ };
45
+ export const waitTools = [
46
+ {
47
+ action: "wait",
48
+ parameters: {
49
+ type: "object",
50
+ additionalProperties: false,
51
+ properties: waitDefinition,
52
+ },
53
+ },
54
+ {
55
+ action: "wait_for",
56
+ parameters: {
57
+ type: "object",
58
+ additionalProperties: false,
59
+ properties: conditionDefinition,
60
+ },
61
+ },
62
+ ];
63
+ async function observation(args, signal) {
64
+ if (args.condition === "window") {
65
+ // Internal enumeration has a higher cap than the model-facing listing tool.
66
+ const result = await nativeDesktop.execute("list_windows", {
67
+ includeInvisible: true,
68
+ maxWindows: 4096,
69
+ _metadataOnly: true,
70
+ ...(args.windowRef === undefined
71
+ ? {}
72
+ : {
73
+ windowRef: args.windowRef,
74
+ ...(args.nativeWindowHandle === undefined
75
+ ? {}
76
+ : { nativeWindowHandle: args.nativeWindowHandle }),
77
+ ...(args.processId === undefined
78
+ ? {}
79
+ : { processId: args.processId }),
80
+ ...(args.windowTitle === undefined
81
+ ? {}
82
+ : { windowTitle: args.windowTitle }),
83
+ }),
84
+ }, signal);
85
+ if (!result.ok)
86
+ return { found: false, conclusive: false, error: String(result.error) };
87
+ if (typeof result.referencePresent === "boolean")
88
+ return { found: result.referencePresent, conclusive: true };
89
+ const windows = result.windows;
90
+ const found = windows.some((window) => (args.nativeWindowHandle === undefined ||
91
+ window.nativeWindowHandle === args.nativeWindowHandle) &&
92
+ (args.processId === undefined || window.processId === args.processId) &&
93
+ (args.windowTitle === undefined ||
94
+ String(window.name)
95
+ .toLowerCase()
96
+ .includes(String(args.windowTitle).toLowerCase())));
97
+ return {
98
+ found,
99
+ conclusive: found || result.truncated !== true,
100
+ truncated: result.truncated === true,
101
+ };
102
+ }
103
+ const target = {
104
+ scope: args.scope,
105
+ activate: false,
106
+ };
107
+ for (const key of [
108
+ "windowRef",
109
+ "windowTitle",
110
+ "processId",
111
+ "nativeWindowHandle",
112
+ ])
113
+ if (args[key] !== undefined)
114
+ target[key] = args[key];
115
+ if (args.condition === "text") {
116
+ const result = await ocrDesktop({ ...target, query: args.query, resolveControl: false }, signal);
117
+ const found = result.ok && Array.isArray(result.matched) && result.matched.length > 0;
118
+ return {
119
+ found,
120
+ conclusive: result.ok &&
121
+ result.captureConclusive === true &&
122
+ result.occludedPossible !== true &&
123
+ result.truncated !== true,
124
+ ...(!result.ok ? { error: String(result.error) } : {}),
125
+ };
126
+ }
127
+ const result = await executeAccessibility("find", {
128
+ ...target,
129
+ query: args.query,
130
+ ...(args.controlType !== undefined
131
+ ? { controlType: args.controlType }
132
+ : {}),
133
+ viewMode: args.viewMode,
134
+ includeOffscreen: args.includeOffscreen,
135
+ treeTimeoutMs: args.treeTimeoutMs,
136
+ maxDepth: args.maxDepth,
137
+ maxNodes: args.maxNodes,
138
+ maxResults: 1,
139
+ ocrFallback: false,
140
+ }, signal);
141
+ const found = result.ok && Array.isArray(result.matches) && result.matches.length > 0;
142
+ return {
143
+ found,
144
+ conclusive: result.ok &&
145
+ (found ||
146
+ (result.truncated !== true && result.providerError === undefined)),
147
+ truncated: result.truncated === true,
148
+ ...(!result.ok ? { error: String(result.error) } : {}),
149
+ };
150
+ }
151
+ export async function waitDesktop(action, input, signal) {
152
+ const definition = action === "wait" ? waitDefinition : conditionDefinition;
153
+ const fail = (message) => ({
154
+ ok: false,
155
+ action,
156
+ error: `INVALID_ARGUMENTS: ${message}`,
157
+ });
158
+ if (action !== "wait" && action !== "wait_for")
159
+ return fail("unknown wait action");
160
+ const args = {};
161
+ for (const key of Object.keys(input))
162
+ if (!(key in definition))
163
+ return fail(`unknown option ${key}`);
164
+ for (const [key, rule] of Object.entries(definition)) {
165
+ const value = Object.hasOwn(input, key) ? input[key] : rule.default;
166
+ if (value === undefined)
167
+ continue;
168
+ if (rule.type === "integer"
169
+ ? !Number.isSafeInteger(value)
170
+ : typeof value !== rule.type)
171
+ return fail(`invalid ${key}`);
172
+ if (typeof value === "number" &&
173
+ ((rule.minimum !== undefined && value < rule.minimum) ||
174
+ (rule.maximum !== undefined && value > rule.maximum)))
175
+ return fail(`${key} outside bounds`);
176
+ if (typeof value === "string" &&
177
+ ((rule.enum && !rule.enum.includes(value)) ||
178
+ ((key === "query" || key === "windowTitle" || key === "windowRef") &&
179
+ !value.trim())))
180
+ return fail(`invalid ${key}`);
181
+ args[key] = value;
182
+ }
183
+ signal?.throwIfAborted();
184
+ if (action === "wait") {
185
+ await delay(Number(args.milliseconds), undefined, { signal });
186
+ return { ok: true, action, milliseconds: args.milliseconds };
187
+ }
188
+ if (args.condition === "window" &&
189
+ args.windowRef === undefined &&
190
+ args.nativeWindowHandle === undefined &&
191
+ args.processId === undefined &&
192
+ args.windowTitle === undefined)
193
+ return fail("window condition requires an explicit target");
194
+ if (args.condition !== "window" && !String(args.query ?? "").trim())
195
+ return fail("element/text condition requires query");
196
+ const start = performance.now(), timeout = Number(args.timeoutMs);
197
+ let last = { found: false, conclusive: false };
198
+ let attempts = 0;
199
+ const outcome = (observed) => {
200
+ return {
201
+ ok: observed,
202
+ action,
203
+ condition: args.condition,
204
+ appear: args.appear,
205
+ ...(args.query !== undefined ? { query: args.query } : {}),
206
+ found: last.found,
207
+ conclusive: last.conclusive,
208
+ verification: observed
209
+ ? "observed"
210
+ : last.conclusive
211
+ ? "timeout"
212
+ : "inconclusive",
213
+ timedOut: !observed,
214
+ waitedMs: Math.round(performance.now() - start),
215
+ attempts,
216
+ ...(last.truncated ? { observationTruncated: true } : {}),
217
+ ...(last.error ? { observationError: last.error } : {}),
218
+ ...(args.condition === "text"
219
+ ? {
220
+ verificationNote: "Condition describes literal OCR output from a complete reliable capture, not universal proof of application text.",
221
+ }
222
+ : {}),
223
+ };
224
+ };
225
+ for (;;) {
226
+ if (attempts > 0 && performance.now() - start >= timeout)
227
+ return outcome(false);
228
+ signal?.throwIfAborted();
229
+ const remaining = Math.max(1, Math.ceil(timeout - (performance.now() - start)));
230
+ if (attempts > 0 && remaining < 100) {
231
+ await delay(remaining, undefined, { signal });
232
+ return outcome(false);
233
+ }
234
+ const deadline = AbortSignal.timeout(remaining);
235
+ const pollSignal = signal ? AbortSignal.any([signal, deadline]) : deadline;
236
+ try {
237
+ last = await observation({
238
+ ...args,
239
+ treeTimeoutMs: Math.max(100, Math.min(Number(args.treeTimeoutMs), remaining)),
240
+ }, pollSignal);
241
+ }
242
+ catch (error) {
243
+ signal?.throwIfAborted();
244
+ last = {
245
+ found: false,
246
+ conclusive: false,
247
+ error: deadline.aborted
248
+ ? "OBSERVATION_TIMEOUT: condition could not be established before its deadline"
249
+ : String(error),
250
+ };
251
+ if (deadline.aborted)
252
+ await retireDesktop();
253
+ }
254
+ attempts++;
255
+ signal?.throwIfAborted();
256
+ const observed = last.conclusive && last.found === args.appear;
257
+ const waitedMs = Math.round(performance.now() - start);
258
+ if (observed || waitedMs >= timeout)
259
+ return outcome(observed);
260
+ await delay(Math.min(Number(args.intervalMs), Math.max(1, timeout - (performance.now() - start))), undefined, { signal });
261
+ }
262
+ }
@@ -0,0 +1,25 @@
1
+ import type { WorkerResult } from "./protocol.js";
2
+ type Rule = {
3
+ type: "string" | "integer" | "boolean";
4
+ minimum?: number;
5
+ maximum?: number;
6
+ minLength?: number;
7
+ maxLength?: number;
8
+ default?: unknown;
9
+ };
10
+ export declare const windowTools: {
11
+ action: string;
12
+ parameters: {
13
+ properties: Record<string, Rule> | {
14
+ browserTab: {
15
+ type: string;
16
+ minLength: number;
17
+ };
18
+ };
19
+ required?: string[];
20
+ type: string;
21
+ additionalProperties: boolean;
22
+ };
23
+ }[];
24
+ export declare function manageWindow(action: string, input: Record<string, unknown>, signal?: AbortSignal): Promise<WorkerResult>;
25
+ export {};