@ycheung5/pi-computer-use 0.0.0-stage → 0.1.1
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/GLOSSARY.md +38 -0
- package/LICENSE +21 -0
- package/README.md +165 -2
- package/assets/accessibility.cs +208 -0
- package/assets/browser-indicators.cs +37 -0
- package/assets/capture.cs +215 -0
- package/assets/clipboard.cs +197 -0
- package/assets/controls.cs +249 -0
- package/assets/indicator-preview.png +0 -0
- package/assets/indicators.cs +252 -0
- package/assets/input-timing.cs +42 -0
- package/assets/node-LICENSE.txt +2732 -0
- package/assets/ocr.cs +86 -0
- package/assets/ownership.cs +59 -0
- package/assets/pointer.cs +241 -0
- package/assets/puppeteer-LICENSE.txt +202 -0
- package/assets/readme-banner.svg +33 -0
- package/assets/stop.cs +197 -0
- package/assets/text.cs +279 -0
- package/assets/wgc.cs +167 -0
- package/assets/window-management.cs +217 -0
- package/assets/window-marker.cs +23 -0
- package/assets/window-references.cs +80 -0
- package/assets/windows.cs +127 -0
- package/dist/accessibility.d.ts +29 -0
- package/dist/accessibility.js +258 -0
- package/dist/browser-actions.d.ts +22 -0
- package/dist/browser-actions.js +246 -0
- package/dist/browser-indicators.d.ts +23 -0
- package/dist/browser-indicators.js +69 -0
- package/dist/browser-profiles.d.ts +10 -0
- package/dist/browser-profiles.js +174 -0
- package/dist/browser.d.ts +11 -0
- package/dist/browser.js +2071 -0
- package/dist/capture.d.ts +74 -0
- package/dist/capture.js +199 -0
- package/dist/client.d.ts +39 -0
- package/dist/client.js +384 -0
- package/dist/desktop.d.ts +20 -0
- package/dist/desktop.js +42 -0
- package/dist/extension.d.ts +4 -0
- package/dist/extension.js +409 -0
- package/dist/input-timing.d.ts +24 -0
- package/dist/input-timing.js +70 -0
- package/dist/launcher.d.ts +6 -0
- package/dist/launcher.js +85 -0
- package/dist/native.d.ts +11 -0
- package/dist/native.js +146 -0
- package/dist/ocr.d.ts +52 -0
- package/dist/ocr.js +246 -0
- package/dist/ownership.d.ts +4 -0
- package/dist/ownership.js +24 -0
- package/dist/pointer.d.ts +128 -0
- package/dist/pointer.js +198 -0
- package/dist/protocol.d.ts +15 -0
- package/dist/protocol.js +1 -0
- package/dist/runtime.d.ts +8 -0
- package/dist/runtime.js +72 -0
- package/dist/settings.d.ts +85 -0
- package/dist/settings.js +449 -0
- package/dist/stop.d.ts +24 -0
- package/dist/stop.js +156 -0
- package/dist/text.d.ts +120 -0
- package/dist/text.js +212 -0
- package/dist/waits.d.ts +19 -0
- package/dist/waits.js +262 -0
- package/dist/window-management.d.ts +25 -0
- package/dist/window-management.js +167 -0
- package/dist/worker.d.ts +1 -0
- package/dist/worker.js +553 -0
- package/docs/README.md +55 -0
- package/docs/adr/0001-preserve-reference-behavior.md +9 -0
- package/docs/adr/0002-window-lifetime-references.md +11 -0
- package/docs/adr/0003-exclusive-desktop-control.md +11 -0
- package/docs/adr/0004-pi-first-acceptance.md +9 -0
- package/docs/adr/0005-default-apps-and-workspace-reuse.md +7 -0
- package/docs/agents/domain.md +9 -0
- package/docs/agents/issue-tracker.md +10 -0
- package/docs/agents/triage-labels.md +9 -0
- package/docs/browser.md +113 -0
- package/docs/implementation-plan.md +153 -0
- package/docs/indicators.md +53 -0
- package/docs/native-interop-research.md +17 -0
- package/docs/ownership.md +25 -0
- package/docs/pi-extension-research.md +57 -0
- package/docs/pointer.md +77 -0
- package/docs/runtime.md +42 -0
- package/docs/settings.md +33 -0
- package/docs/spec.md +230 -0
- package/docs/stopping.md +83 -0
- package/docs/text.md +99 -0
- package/docs/tickets.md +85 -0
- package/docs/validation.md +1420 -0
- package/docs/windows.md +171 -0
- package/package.json +134 -4
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import type { WorkerResult } from "./protocol.js";
|
|
2
|
+
export declare const pointerTools: {
|
|
3
|
+
action: string;
|
|
4
|
+
parameters: {
|
|
5
|
+
required?: string[] | undefined;
|
|
6
|
+
type: string;
|
|
7
|
+
additionalProperties: boolean;
|
|
8
|
+
properties: {
|
|
9
|
+
dispatch?: {
|
|
10
|
+
type: string;
|
|
11
|
+
enum: string[];
|
|
12
|
+
default: string;
|
|
13
|
+
} | undefined;
|
|
14
|
+
button?: {
|
|
15
|
+
type: string;
|
|
16
|
+
enum: string[];
|
|
17
|
+
default: string;
|
|
18
|
+
} | undefined;
|
|
19
|
+
path: {
|
|
20
|
+
type: string;
|
|
21
|
+
items: {
|
|
22
|
+
type: string;
|
|
23
|
+
additionalProperties: boolean;
|
|
24
|
+
properties: {
|
|
25
|
+
x: {
|
|
26
|
+
type: string;
|
|
27
|
+
};
|
|
28
|
+
y: {
|
|
29
|
+
type: string;
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
required: string[];
|
|
33
|
+
};
|
|
34
|
+
minItems: number;
|
|
35
|
+
maxItems: number;
|
|
36
|
+
};
|
|
37
|
+
holdMs?: {
|
|
38
|
+
type: string;
|
|
39
|
+
minimum: number;
|
|
40
|
+
maximum: number;
|
|
41
|
+
} | undefined;
|
|
42
|
+
timeoutMs?: {
|
|
43
|
+
type: string;
|
|
44
|
+
minimum: number;
|
|
45
|
+
maximum: number;
|
|
46
|
+
} | undefined;
|
|
47
|
+
windowRef: {
|
|
48
|
+
type: string;
|
|
49
|
+
minLength: number;
|
|
50
|
+
};
|
|
51
|
+
windowTitle: {
|
|
52
|
+
type: string;
|
|
53
|
+
};
|
|
54
|
+
processId: {
|
|
55
|
+
minimum: number;
|
|
56
|
+
type: string;
|
|
57
|
+
};
|
|
58
|
+
nativeWindowHandle: {
|
|
59
|
+
minimum: number;
|
|
60
|
+
type: string;
|
|
61
|
+
};
|
|
62
|
+
activate: {
|
|
63
|
+
type: string;
|
|
64
|
+
};
|
|
65
|
+
} | {
|
|
66
|
+
dispatch?: {
|
|
67
|
+
type: string;
|
|
68
|
+
enum: string[];
|
|
69
|
+
default: string;
|
|
70
|
+
} | undefined;
|
|
71
|
+
button?: {
|
|
72
|
+
type: string;
|
|
73
|
+
enum: string[];
|
|
74
|
+
default: string;
|
|
75
|
+
} | undefined;
|
|
76
|
+
elementId: {
|
|
77
|
+
type: string;
|
|
78
|
+
minLength: number;
|
|
79
|
+
};
|
|
80
|
+
x: {
|
|
81
|
+
type: string;
|
|
82
|
+
};
|
|
83
|
+
y: {
|
|
84
|
+
type: string;
|
|
85
|
+
};
|
|
86
|
+
viewMode: {
|
|
87
|
+
type: string;
|
|
88
|
+
enum: string[];
|
|
89
|
+
default: string;
|
|
90
|
+
};
|
|
91
|
+
includeOffscreen: {
|
|
92
|
+
type: string;
|
|
93
|
+
default: boolean;
|
|
94
|
+
};
|
|
95
|
+
holdMs?: {
|
|
96
|
+
type: string;
|
|
97
|
+
minimum: number;
|
|
98
|
+
maximum: number;
|
|
99
|
+
} | undefined;
|
|
100
|
+
timeoutMs?: {
|
|
101
|
+
type: string;
|
|
102
|
+
minimum: number;
|
|
103
|
+
maximum: number;
|
|
104
|
+
} | undefined;
|
|
105
|
+
windowRef: {
|
|
106
|
+
type: string;
|
|
107
|
+
minLength: number;
|
|
108
|
+
};
|
|
109
|
+
windowTitle: {
|
|
110
|
+
type: string;
|
|
111
|
+
};
|
|
112
|
+
processId: {
|
|
113
|
+
minimum: number;
|
|
114
|
+
type: string;
|
|
115
|
+
};
|
|
116
|
+
nativeWindowHandle: {
|
|
117
|
+
minimum: number;
|
|
118
|
+
type: string;
|
|
119
|
+
};
|
|
120
|
+
activate: {
|
|
121
|
+
type: string;
|
|
122
|
+
};
|
|
123
|
+
};
|
|
124
|
+
};
|
|
125
|
+
}[];
|
|
126
|
+
export declare function validatePointer(action: string, args: Record<string, unknown>): WorkerResult | undefined;
|
|
127
|
+
export declare function awaitPointerCleanup(): Promise<void>;
|
|
128
|
+
export declare function executePointer(action: string, args: Record<string, unknown>, cancelEvent: string, operationId: string, listenerProcessId?: number, signal?: AbortSignal): Promise<WorkerResult>;
|
package/dist/pointer.js
ADDED
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
import { pressTiming, timingMilliseconds } from "./input-timing.js";
|
|
2
|
+
import { confirmInputCleanup, nativeDesktop, retainInput } from "./native.js";
|
|
3
|
+
const integer = { type: "integer" };
|
|
4
|
+
const target = {
|
|
5
|
+
windowRef: { type: "string", minLength: 1 },
|
|
6
|
+
windowTitle: { type: "string" },
|
|
7
|
+
processId: { ...integer, minimum: 1 },
|
|
8
|
+
nativeWindowHandle: { ...integer, minimum: 1 },
|
|
9
|
+
activate: { type: "boolean" },
|
|
10
|
+
};
|
|
11
|
+
const point = {
|
|
12
|
+
type: "object",
|
|
13
|
+
additionalProperties: false,
|
|
14
|
+
properties: { x: integer, y: integer },
|
|
15
|
+
required: ["x", "y"],
|
|
16
|
+
};
|
|
17
|
+
export const pointerTools = ["click", "double_click", "move", "drag"].map((action) => ({
|
|
18
|
+
action,
|
|
19
|
+
parameters: {
|
|
20
|
+
type: "object",
|
|
21
|
+
additionalProperties: false,
|
|
22
|
+
properties: {
|
|
23
|
+
...target,
|
|
24
|
+
...(action === "click"
|
|
25
|
+
? { holdMs: timingMilliseconds, timeoutMs: timingMilliseconds }
|
|
26
|
+
: {}),
|
|
27
|
+
...(action === "drag"
|
|
28
|
+
? {
|
|
29
|
+
path: {
|
|
30
|
+
type: "array",
|
|
31
|
+
items: point,
|
|
32
|
+
minItems: 2,
|
|
33
|
+
maxItems: 1000,
|
|
34
|
+
},
|
|
35
|
+
}
|
|
36
|
+
: {
|
|
37
|
+
elementId: { type: "string", minLength: 1 },
|
|
38
|
+
x: integer,
|
|
39
|
+
y: integer,
|
|
40
|
+
viewMode: {
|
|
41
|
+
type: "string",
|
|
42
|
+
enum: ["control", "content", "raw"],
|
|
43
|
+
default: "control",
|
|
44
|
+
},
|
|
45
|
+
includeOffscreen: { type: "boolean", default: false },
|
|
46
|
+
}),
|
|
47
|
+
...(action !== "move"
|
|
48
|
+
? {
|
|
49
|
+
button: {
|
|
50
|
+
type: "string",
|
|
51
|
+
enum: ["left", "right", "middle"],
|
|
52
|
+
default: "left",
|
|
53
|
+
},
|
|
54
|
+
}
|
|
55
|
+
: {}),
|
|
56
|
+
...(["click", "double_click"].includes(action)
|
|
57
|
+
? {
|
|
58
|
+
dispatch: {
|
|
59
|
+
type: "string",
|
|
60
|
+
enum: ["auto", "background", "foreground"],
|
|
61
|
+
default: "auto",
|
|
62
|
+
},
|
|
63
|
+
}
|
|
64
|
+
: {}),
|
|
65
|
+
},
|
|
66
|
+
...(action === "drag" ? { required: ["path"] } : {}),
|
|
67
|
+
},
|
|
68
|
+
}));
|
|
69
|
+
export function validatePointer(action, args) {
|
|
70
|
+
const bad = (message) => ({
|
|
71
|
+
ok: false,
|
|
72
|
+
action,
|
|
73
|
+
error: `INVALID_ARGUMENTS: ${message}`,
|
|
74
|
+
});
|
|
75
|
+
const keys = new Set([
|
|
76
|
+
"windowRef",
|
|
77
|
+
"windowTitle",
|
|
78
|
+
"processId",
|
|
79
|
+
"nativeWindowHandle",
|
|
80
|
+
"activate",
|
|
81
|
+
...(action === "drag"
|
|
82
|
+
? ["path", "button"]
|
|
83
|
+
: [
|
|
84
|
+
"elementId",
|
|
85
|
+
"x",
|
|
86
|
+
"y",
|
|
87
|
+
"viewMode",
|
|
88
|
+
"includeOffscreen",
|
|
89
|
+
...(action === "move" ? [] : ["button", "dispatch"]),
|
|
90
|
+
]),
|
|
91
|
+
...(action === "click" ? ["holdMs", "timeoutMs"] : []),
|
|
92
|
+
...(action === "scroll" ? ["deltaX", "deltaY", "browserTab"] : []),
|
|
93
|
+
]);
|
|
94
|
+
if (args.windowRef !== undefined &&
|
|
95
|
+
(typeof args.windowRef !== "string" || !args.windowRef.trim()))
|
|
96
|
+
return bad("windowRef must be nonempty");
|
|
97
|
+
for (const key of Object.keys(args))
|
|
98
|
+
if (!keys.has(key))
|
|
99
|
+
return bad(`unknown option ${key}`);
|
|
100
|
+
for (const key of ["processId", "nativeWindowHandle"])
|
|
101
|
+
if (args[key] !== undefined &&
|
|
102
|
+
(!Number.isSafeInteger(args[key]) || Number(args[key]) < 1))
|
|
103
|
+
return bad(`${key} must be a positive integer`);
|
|
104
|
+
for (const key of ["x", "y", "deltaX", "deltaY"])
|
|
105
|
+
if (args[key] !== undefined &&
|
|
106
|
+
(!Number.isSafeInteger(args[key]) ||
|
|
107
|
+
Math.abs(Number(args[key])) > 2147483647))
|
|
108
|
+
return bad(`${key} must be a 32-bit integer`);
|
|
109
|
+
for (const key of ["activate", "includeOffscreen"])
|
|
110
|
+
if (args[key] !== undefined && typeof args[key] !== "boolean")
|
|
111
|
+
return bad(`${key} must be boolean`);
|
|
112
|
+
if (args.windowTitle !== undefined && typeof args.windowTitle !== "string")
|
|
113
|
+
return bad("windowTitle must be a string");
|
|
114
|
+
if (args.viewMode !== undefined &&
|
|
115
|
+
!["control", "content", "raw"].includes(String(args.viewMode)))
|
|
116
|
+
return bad("unsupported viewMode");
|
|
117
|
+
if (args.button !== undefined &&
|
|
118
|
+
!["left", "right", "middle"].includes(String(args.button)))
|
|
119
|
+
return bad("unsupported button");
|
|
120
|
+
if (args.dispatch !== undefined &&
|
|
121
|
+
!["auto", "background", "foreground"].includes(String(args.dispatch)))
|
|
122
|
+
return bad("unsupported dispatch");
|
|
123
|
+
if (action === "click") {
|
|
124
|
+
try {
|
|
125
|
+
pressTiming(args, 90_000);
|
|
126
|
+
}
|
|
127
|
+
catch (cause) {
|
|
128
|
+
return {
|
|
129
|
+
ok: false,
|
|
130
|
+
action,
|
|
131
|
+
error: cause instanceof Error ? cause.message : String(cause),
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
if ((args.holdMs !== undefined || args.timeoutMs !== undefined) &&
|
|
135
|
+
(args.dispatch === "background" || args.activate === false))
|
|
136
|
+
return {
|
|
137
|
+
ok: false,
|
|
138
|
+
action,
|
|
139
|
+
error: "TIMING_UNSUPPORTED: click timing requires native foreground dispatch without explicit activate: false",
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
if (action === "drag") {
|
|
143
|
+
if (!Array.isArray(args.path) ||
|
|
144
|
+
args.path.length < 2 ||
|
|
145
|
+
args.path.length > 1000)
|
|
146
|
+
return bad("path needs 2–1000 screen points");
|
|
147
|
+
for (const p of args.path)
|
|
148
|
+
if (!p ||
|
|
149
|
+
typeof p !== "object" ||
|
|
150
|
+
Object.keys(p).some((k) => k !== "x" && k !== "y") ||
|
|
151
|
+
!Number.isInteger(p.x) ||
|
|
152
|
+
!Number.isInteger(p.y) ||
|
|
153
|
+
Math.abs(p.x) > 2147483647 ||
|
|
154
|
+
Math.abs(p.y) > 2147483647)
|
|
155
|
+
return bad("path requires integer x/y screen points");
|
|
156
|
+
}
|
|
157
|
+
else {
|
|
158
|
+
if (args.elementId !== undefined &&
|
|
159
|
+
(typeof args.elementId !== "string" || !args.elementId.length))
|
|
160
|
+
return bad("elementId must be nonempty");
|
|
161
|
+
if (!args.elementId && (args.x === undefined || args.y === undefined))
|
|
162
|
+
return bad("provide elementId or both x and y");
|
|
163
|
+
if ((args.x === undefined) !== (args.y === undefined))
|
|
164
|
+
return bad("provide both x and y");
|
|
165
|
+
}
|
|
166
|
+
return undefined;
|
|
167
|
+
}
|
|
168
|
+
// A missing native acknowledgment keeps the lease held. Never kill a bridge that
|
|
169
|
+
// could still have a button down, including after a timeout/transport failure.
|
|
170
|
+
let cleanup;
|
|
171
|
+
let cleanupFailure;
|
|
172
|
+
export async function awaitPointerCleanup() {
|
|
173
|
+
await cleanup;
|
|
174
|
+
if (cleanupFailure)
|
|
175
|
+
throw cleanupFailure;
|
|
176
|
+
}
|
|
177
|
+
export async function executePointer(action, args, cancelEvent, operationId, listenerProcessId, signal) {
|
|
178
|
+
await awaitPointerCleanup();
|
|
179
|
+
if (!cancelEvent)
|
|
180
|
+
return nativeDesktop.execute(action, { ...args, _cancelEvent: "" }, signal, operationId);
|
|
181
|
+
retainInput();
|
|
182
|
+
const execution = nativeDesktop.execute(action, { ...args, _cancelEvent: cancelEvent, _stopProcessId: listenerProcessId }, undefined, operationId);
|
|
183
|
+
cleanup = execution
|
|
184
|
+
.then((result) => {
|
|
185
|
+
if (result.cleanupConfirmed !== true)
|
|
186
|
+
throw new Error("INPUT_CLEANUP_UNCONFIRMED: retain desktop ownership");
|
|
187
|
+
confirmInputCleanup();
|
|
188
|
+
})
|
|
189
|
+
.catch((error) => {
|
|
190
|
+
cleanupFailure = error;
|
|
191
|
+
throw error;
|
|
192
|
+
});
|
|
193
|
+
// Attach immediately; dispatch will await the same completion below.
|
|
194
|
+
void cleanup.catch(() => undefined);
|
|
195
|
+
const result = await execution;
|
|
196
|
+
await cleanup;
|
|
197
|
+
return result;
|
|
198
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export interface WorkerRequest {
|
|
2
|
+
id: number;
|
|
3
|
+
action: string;
|
|
4
|
+
args: Record<string, unknown>;
|
|
5
|
+
operationId?: string;
|
|
6
|
+
}
|
|
7
|
+
export interface WorkerResult {
|
|
8
|
+
ok: boolean;
|
|
9
|
+
action: string;
|
|
10
|
+
[key: string]: unknown;
|
|
11
|
+
}
|
|
12
|
+
export interface WorkerResponse {
|
|
13
|
+
id: number;
|
|
14
|
+
result: WorkerResult;
|
|
15
|
+
}
|
package/dist/protocol.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export declare const WINDOWS_NODE_VERSION = "22.23.4";
|
|
2
|
+
export interface RuntimeOptions {
|
|
3
|
+
directory: string;
|
|
4
|
+
architecture: string;
|
|
5
|
+
signal?: AbortSignal;
|
|
6
|
+
download?: typeof fetch;
|
|
7
|
+
}
|
|
8
|
+
export declare function provisionRuntime(options: RuntimeOptions): Promise<string>;
|
package/dist/runtime.js
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { createHash, randomUUID } from "node:crypto";
|
|
2
|
+
import { mkdir, readFile, rename, rm, writeFile } from "node:fs/promises";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
export const WINDOWS_NODE_VERSION = "22.23.4";
|
|
5
|
+
const checksums = {
|
|
6
|
+
x64: "dccc52de28d8df2ee22d2062424f8c563070d95d8ad70c54c4bf01d590dec14f",
|
|
7
|
+
arm64: "64d9f6e69b4703870e8cd30a3477127df8b683ea04feb03660e439396549042a",
|
|
8
|
+
};
|
|
9
|
+
function verify(bytes, checksum) {
|
|
10
|
+
if (createHash("sha256").update(bytes).digest("hex") !== checksum) {
|
|
11
|
+
throw new Error("RUNTIME_CHECKSUM_MISMATCH: private Windows Node is corrupt; remove the runtime cache and retry on a trusted connection");
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
export async function provisionRuntime(options) {
|
|
15
|
+
const { architecture, directory, signal } = options;
|
|
16
|
+
if (architecture !== "x64" && architecture !== "arm64") {
|
|
17
|
+
throw new Error(`UNSUPPORTED_ARCHITECTURE: Windows ${architecture}; supported: x64, arm64`);
|
|
18
|
+
}
|
|
19
|
+
signal?.throwIfAborted();
|
|
20
|
+
const folder = join(directory, `node-${WINDOWS_NODE_VERSION}-win-${architecture}`);
|
|
21
|
+
const executable = join(folder, "node.exe");
|
|
22
|
+
const checksum = checksums[architecture];
|
|
23
|
+
try {
|
|
24
|
+
const bytes = await readFile(executable);
|
|
25
|
+
signal?.throwIfAborted();
|
|
26
|
+
verify(bytes, checksum);
|
|
27
|
+
return executable;
|
|
28
|
+
}
|
|
29
|
+
catch (error) {
|
|
30
|
+
if (!(error instanceof Error && "code" in error && error.code === "ENOENT"))
|
|
31
|
+
throw error;
|
|
32
|
+
}
|
|
33
|
+
const timeout = AbortSignal.timeout(120_000);
|
|
34
|
+
const downloadSignal = signal ? AbortSignal.any([signal, timeout]) : timeout;
|
|
35
|
+
const response = await (options.download ?? fetch)(`https://nodejs.org/dist/v${WINDOWS_NODE_VERSION}/win-${architecture}/node.exe`, { signal: downloadSignal });
|
|
36
|
+
if (!response.ok || !response.body) {
|
|
37
|
+
throw new Error(`RUNTIME_DOWNLOAD_FAILED: HTTP ${response.status}; allow HTTPS access to nodejs.org and retry`);
|
|
38
|
+
}
|
|
39
|
+
const parts = [];
|
|
40
|
+
let size = 0;
|
|
41
|
+
for await (const chunk of response.body) {
|
|
42
|
+
downloadSignal.throwIfAborted();
|
|
43
|
+
size += chunk.byteLength;
|
|
44
|
+
if (size > 128 * 1024 * 1024)
|
|
45
|
+
throw new Error("RUNTIME_DOWNLOAD_FAILED: executable exceeds 128 MiB");
|
|
46
|
+
parts.push(chunk);
|
|
47
|
+
}
|
|
48
|
+
const bytes = Buffer.concat(parts);
|
|
49
|
+
verify(bytes, checksum);
|
|
50
|
+
downloadSignal.throwIfAborted();
|
|
51
|
+
await mkdir(folder, { recursive: true });
|
|
52
|
+
const temporary = join(folder, `node-${randomUUID()}.tmp`);
|
|
53
|
+
try {
|
|
54
|
+
await writeFile(temporary, bytes, { flag: "wx" });
|
|
55
|
+
signal?.throwIfAborted();
|
|
56
|
+
try {
|
|
57
|
+
await rename(temporary, executable);
|
|
58
|
+
}
|
|
59
|
+
catch (error) {
|
|
60
|
+
// A concurrent Pi session may have installed the same pinned runtime.
|
|
61
|
+
if (!(error instanceof Error &&
|
|
62
|
+
"code" in error &&
|
|
63
|
+
(error.code === "EEXIST" || error.code === "EPERM")))
|
|
64
|
+
throw error;
|
|
65
|
+
verify(await readFile(executable), checksum);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
finally {
|
|
69
|
+
await rm(temporary, { force: true });
|
|
70
|
+
}
|
|
71
|
+
return executable;
|
|
72
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import type { WorkerResult } from "./protocol.js";
|
|
2
|
+
export declare const TOOL_PREFIX = "windows_computer_use_";
|
|
3
|
+
export declare const TOOL_NAMES: string[];
|
|
4
|
+
export declare const DEFAULT_SETTINGS: {
|
|
5
|
+
browserFirst: boolean;
|
|
6
|
+
browserVisible: boolean;
|
|
7
|
+
browserApp: string;
|
|
8
|
+
browserSignIn: boolean;
|
|
9
|
+
mode: string;
|
|
10
|
+
toolPreset: string;
|
|
11
|
+
enabledTools: string[];
|
|
12
|
+
indicatorEnabled: boolean;
|
|
13
|
+
cursorIndicatorEnabled: boolean;
|
|
14
|
+
remoteIndicatorVisible: boolean;
|
|
15
|
+
indicatorText: string;
|
|
16
|
+
indicatorPosition: string;
|
|
17
|
+
indicatorIdleMs: number;
|
|
18
|
+
stopShortcut: string;
|
|
19
|
+
resumeToken: number;
|
|
20
|
+
previewToken: number;
|
|
21
|
+
};
|
|
22
|
+
export type PersonalSettings = typeof DEFAULT_SETTINGS;
|
|
23
|
+
export declare function personalSettingsPath(host?: boolean): Promise<string | undefined>;
|
|
24
|
+
export declare function readPersonalSettings(host?: boolean): Promise<{
|
|
25
|
+
path: undefined;
|
|
26
|
+
exists: boolean;
|
|
27
|
+
source: string;
|
|
28
|
+
settings: PersonalSettings;
|
|
29
|
+
notices: string[];
|
|
30
|
+
} | {
|
|
31
|
+
path: string;
|
|
32
|
+
exists: boolean;
|
|
33
|
+
source: string;
|
|
34
|
+
settings: PersonalSettings;
|
|
35
|
+
notices: string[];
|
|
36
|
+
}>;
|
|
37
|
+
export declare function allowedToolNames(settings: PersonalSettings): string[];
|
|
38
|
+
export declare const managementParameters: {
|
|
39
|
+
type: string;
|
|
40
|
+
additionalProperties: boolean;
|
|
41
|
+
properties: {
|
|
42
|
+
operation: {
|
|
43
|
+
type: string;
|
|
44
|
+
enum: string[];
|
|
45
|
+
default: string;
|
|
46
|
+
};
|
|
47
|
+
names: {
|
|
48
|
+
type: string;
|
|
49
|
+
items: {
|
|
50
|
+
type: string;
|
|
51
|
+
};
|
|
52
|
+
maxItems: number;
|
|
53
|
+
};
|
|
54
|
+
};
|
|
55
|
+
};
|
|
56
|
+
export declare class PersonalSettingsManager {
|
|
57
|
+
private readonly available;
|
|
58
|
+
currentSettings: PersonalSettings | undefined;
|
|
59
|
+
currentFileExists: boolean;
|
|
60
|
+
currentNotices: string[];
|
|
61
|
+
currentSource: string;
|
|
62
|
+
private selection;
|
|
63
|
+
private enabled;
|
|
64
|
+
private allowed;
|
|
65
|
+
constructor(available: Map<string, {
|
|
66
|
+
description: string;
|
|
67
|
+
parameters?: unknown;
|
|
68
|
+
}>);
|
|
69
|
+
synchronize(): Promise<{
|
|
70
|
+
path: undefined;
|
|
71
|
+
exists: boolean;
|
|
72
|
+
source: string;
|
|
73
|
+
settings: PersonalSettings;
|
|
74
|
+
notices: string[];
|
|
75
|
+
} | {
|
|
76
|
+
path: string;
|
|
77
|
+
exists: boolean;
|
|
78
|
+
source: string;
|
|
79
|
+
settings: PersonalSettings;
|
|
80
|
+
notices: string[];
|
|
81
|
+
}>;
|
|
82
|
+
authorize(action: string): Promise<string | undefined>;
|
|
83
|
+
private toolList;
|
|
84
|
+
handle(action: string, args: Record<string, unknown>): Promise<WorkerResult>;
|
|
85
|
+
}
|