@melaya/runner 1.1.68 → 1.1.70
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/dist/browserBridge.js +178 -0
- package/dist/browserFast.d.ts +144 -0
- package/dist/browserFast.js +363 -0
- package/dist/browserProvisioner.d.ts +39 -0
- package/dist/browserProvisioner.js +96 -0
- package/dist/cli.js +190 -65
- package/dist/codeWorker.js +33 -17
- package/dist/computerHelperManifest.d.ts +5 -0
- package/dist/computerHelperManifest.js +18 -0
- package/dist/computerHostCli.d.ts +233 -0
- package/dist/computerHostCli.js +815 -0
- package/dist/computerRelay.d.ts +73 -0
- package/dist/computerRelay.js +280 -0
- package/dist/connection.d.ts +18 -2
- package/dist/connection.js +322 -82
- package/dist/detect.d.ts +40 -1
- package/dist/detect.js +194 -36
- package/dist/hostChannel.d.ts +126 -0
- package/dist/hostChannel.js +117 -0
- package/dist/hostFiles.d.ts +25 -0
- package/dist/hostFiles.js +90 -0
- package/dist/linkedinLogin.js +13 -17
- package/dist/lumaLogin.js +11 -17
- package/dist/modelRescan.d.ts +36 -0
- package/dist/modelRescan.js +80 -0
- package/dist/processTree.d.ts +65 -0
- package/dist/processTree.js +237 -0
- package/dist/publishGate.js +14 -4
- package/dist/pythonEnv.js +6 -7
- package/dist/sharedVendor.js +3 -1
- package/dist/singleInstance.js +10 -1
- package/dist/startupCache.d.ts +22 -0
- package/dist/startupCache.js +45 -0
- package/dist/startupTimings.d.ts +34 -0
- package/dist/startupTimings.js +81 -0
- package/dist/uvBootstrap.js +32 -24
- package/dist/vaults.js +3 -1
- package/package.json +1 -1
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Computer control hosted by the runner CLI: `npx @melaya/runner --computer`.
|
|
3
|
+
*
|
|
4
|
+
* On a headless Linux machine or VM (and on any computer without the Melaya
|
|
5
|
+
* desktop app) the runner itself hosts the computer executor: it starts the
|
|
6
|
+
* native helper for this platform (desktop/native/computer-linux on Linux; the
|
|
7
|
+
* Windows / macOS helpers speak the same protocol) and drives it over stdio
|
|
8
|
+
* exactly as the desktop app's helperProcess.ts does. The protocol is
|
|
9
|
+
* desktop/native/PROTOCOL.md (v1):
|
|
10
|
+
*
|
|
11
|
+
* helper -> {"event":"ready",...} first line
|
|
12
|
+
* host -> {"id","op":"init","denyPatterns","selfPids"} <- {"id","ok":true}
|
|
13
|
+
* host -> {"id","op":"capabilities"} <- {"id","capabilities"}
|
|
14
|
+
* host -> {"id","op":"ping"} <- {"id","pong":true,"busy","current"}
|
|
15
|
+
* host -> {"id","op":"command","action","allowedAppIds","allowedApps","deadlineMs"} <- {"id","result"}
|
|
16
|
+
* host -> {"op":"cancel","target?"} / {"op":"shutdown"}
|
|
17
|
+
* helper -> events: target, user_input, log
|
|
18
|
+
*
|
|
19
|
+
* Like the desktop app, this host runs `batch` (step by step, per-step
|
|
20
|
+
* `expect`), `keep_awake` (systemd-inhibit / caffeinate) and `handoff` (no one
|
|
21
|
+
* is at a headless screen: unsupported) itself, and never sends them to the
|
|
22
|
+
* helper.
|
|
23
|
+
*
|
|
24
|
+
* computerRelay.ts (server socket <-> executor) loads this module lazily and
|
|
25
|
+
* calls createCliComputerHost({ send, verbose }) when the runner is not inside
|
|
26
|
+
* the desktop app. It returns null unless the CLI was started with --computer
|
|
27
|
+
* (enableCliComputerHost) or MELAYA_COMPUTER=1.
|
|
28
|
+
*
|
|
29
|
+
* Before anything reaches the helper this file enforces what the desktop app's
|
|
30
|
+
* bridge does (the runner cannot import desktop/): known kinds, batch limits,
|
|
31
|
+
* the allowlist, per-app tiers (the server's requiredTierOf,
|
|
32
|
+
* server/src/services/computer/computerEffects.ts) and a hard-deny list of apps
|
|
33
|
+
* no agent may touch (Melaya itself, authentication prompts, lock screens). The
|
|
34
|
+
* helper enforces the allowlist and tiers again per window.
|
|
35
|
+
*
|
|
36
|
+
* Helper binary: --computer-helper <path> or MELAYA_COMPUTER_HELPER, else
|
|
37
|
+
* <package>/native/<platform>-<arch>/, else the per-user cache
|
|
38
|
+
* ~/.melaya/computer/<version>/<platform>-<arch>/ where a pinned release (url +
|
|
39
|
+
* sha256 in HELPER_MANIFEST) is downloaded and verified. Types MIRROR
|
|
40
|
+
* packages/desktop-contract/src/computer.ts (this package cannot import it).
|
|
41
|
+
*/
|
|
42
|
+
import { type ChildProcess } from "child_process";
|
|
43
|
+
export type ComputerAppTier = "view" | "click" | "full";
|
|
44
|
+
export interface AllowedApp {
|
|
45
|
+
appId: string;
|
|
46
|
+
tier: ComputerAppTier;
|
|
47
|
+
}
|
|
48
|
+
export type ComputerRunnerToHost = {
|
|
49
|
+
type: "computer.command";
|
|
50
|
+
id: string;
|
|
51
|
+
action: unknown;
|
|
52
|
+
deadlineMs: number;
|
|
53
|
+
allowedAppIds: string[];
|
|
54
|
+
allowedApps?: AllowedApp[];
|
|
55
|
+
} | {
|
|
56
|
+
type: "computer.stop";
|
|
57
|
+
reason: string;
|
|
58
|
+
} | {
|
|
59
|
+
type: "computer.capabilities.request";
|
|
60
|
+
};
|
|
61
|
+
export type ComputerHostToRunner = {
|
|
62
|
+
type: "computer.result";
|
|
63
|
+
id: string;
|
|
64
|
+
result: ComputerResultLike;
|
|
65
|
+
} | {
|
|
66
|
+
type: "computer.capabilities";
|
|
67
|
+
capabilities: ComputerCapabilitiesLike | null;
|
|
68
|
+
};
|
|
69
|
+
export type ComputerResultLike = Record<string, unknown> & {
|
|
70
|
+
ok: boolean;
|
|
71
|
+
kind: string;
|
|
72
|
+
elapsedMs: number;
|
|
73
|
+
};
|
|
74
|
+
export type ComputerCapabilitiesLike = Record<string, unknown> & {
|
|
75
|
+
platform: string;
|
|
76
|
+
backend: string;
|
|
77
|
+
kinds: string[];
|
|
78
|
+
host?: "desktop" | "cli";
|
|
79
|
+
};
|
|
80
|
+
export declare const COMPUTER_ACTION_KINDS: readonly ["screen", "screenshot", "find", "get_text", "current_app", "list_windows", "list_apps", "list_displays", "clipboard_read", "ocr", "wait", "hover", "move", "scroll", "focus_window", "open_app", "open_url", "open_file", "click", "type", "press", "drag", "select", "set_value", "toggle", "window", "clipboard_write", "file_dialog", "batch", "zoom", "cursor_position", "read_table", "expect", "mouse", "hold_key", "select_text", "quit_app", "save_dialog", "handoff", "keep_awake"];
|
|
81
|
+
/** Kinds that do not act on an app window: an empty allowlist does not block them. */
|
|
82
|
+
export declare const APP_INDEPENDENT_KINDS: Set<string>;
|
|
83
|
+
export declare const COMPUTER_MAX_BATCH_STEPS = 100;
|
|
84
|
+
/** The lowest app tier that allows this action (same rule as the server and the helpers). */
|
|
85
|
+
export declare function requiredTierOf(action: Record<string, unknown>): ComputerAppTier;
|
|
86
|
+
/**
|
|
87
|
+
* Apps no agent may read or drive, whatever the allowlist says. Sent to the
|
|
88
|
+
* helper at init (it adds them to its own built-in list) and checked here for
|
|
89
|
+
* actions that name an app and for app / window lists coming back. Plain
|
|
90
|
+
* regexes valid in JS, .NET and Rust.
|
|
91
|
+
*/
|
|
92
|
+
export declare const HARD_DENY_SOURCES: string[];
|
|
93
|
+
export declare function isHardDenied(appId: string): boolean;
|
|
94
|
+
export type PolicyCheck = {
|
|
95
|
+
ok: true;
|
|
96
|
+
action: Record<string, unknown>;
|
|
97
|
+
allowedApps: AllowedApp[];
|
|
98
|
+
allowedAppIds: string[];
|
|
99
|
+
deadlineMs: number;
|
|
100
|
+
} | {
|
|
101
|
+
ok: false;
|
|
102
|
+
result: ComputerResultLike;
|
|
103
|
+
};
|
|
104
|
+
/**
|
|
105
|
+
* Everything the CLI host checks before a command reaches the helper: shape,
|
|
106
|
+
* kinds, batch limits, allowlist (minus hard-denied apps), the tier ceiling and
|
|
107
|
+
* the app an action names. Returns the sanitized allowlist to forward.
|
|
108
|
+
*/
|
|
109
|
+
export declare function checkCommand(msg: {
|
|
110
|
+
action?: unknown;
|
|
111
|
+
allowedAppIds?: unknown;
|
|
112
|
+
allowedApps?: unknown;
|
|
113
|
+
deadlineMs?: unknown;
|
|
114
|
+
}): PolicyCheck;
|
|
115
|
+
/**
|
|
116
|
+
* Pinned helper releases, one per platform-arch, from computerHelperManifest.ts:
|
|
117
|
+
* generated by the release job (desktop-release.yml,
|
|
118
|
+
* .github/scripts/write-computer-helper-manifest.mjs) with the published URL
|
|
119
|
+
* and its sha256, and committed with the release. A download is only ever
|
|
120
|
+
* accepted when its sha256 matches. Empty until the first release: use
|
|
121
|
+
* MELAYA_COMPUTER_HELPER or --computer-helper meanwhile.
|
|
122
|
+
*/
|
|
123
|
+
export declare const HELPER_VERSION = "1.0.1";
|
|
124
|
+
export declare const HELPER_MANIFEST: Record<string, {
|
|
125
|
+
url: string;
|
|
126
|
+
sha256: string;
|
|
127
|
+
} | undefined>;
|
|
128
|
+
export declare function platformKey(platform?: string, arch?: string): string;
|
|
129
|
+
export declare function helperCacheDir(env?: NodeJS.ProcessEnv): string;
|
|
130
|
+
/** Finds the helper binary on disk (no download). */
|
|
131
|
+
export declare function resolveHelperPath(opts?: {
|
|
132
|
+
helperPath?: string;
|
|
133
|
+
env?: NodeJS.ProcessEnv;
|
|
134
|
+
exists?: (p: string) => boolean;
|
|
135
|
+
}): string | null;
|
|
136
|
+
/** Downloads the pinned helper for this platform into the per-user cache and verifies its sha256. */
|
|
137
|
+
export declare function downloadHelper(opts?: {
|
|
138
|
+
env?: NodeJS.ProcessEnv;
|
|
139
|
+
fetchFn?: typeof fetch;
|
|
140
|
+
log?: (l: string) => void;
|
|
141
|
+
manifest?: typeof HELPER_MANIFEST;
|
|
142
|
+
}): Promise<string | null>;
|
|
143
|
+
export declare const HELPER_MISSING_MESSAGE = "The computer helper is not installed on this machine. Build it (desktop/native/computer-linux: ./build.sh) and start the runner with MELAYA_COMPUTER_HELPER=/path/to/melaya-computer, or pass --computer-helper.";
|
|
144
|
+
export type SpawnFn = (command: string, args: string[], options: {
|
|
145
|
+
stdio: ["pipe", "pipe", "pipe"];
|
|
146
|
+
env?: NodeJS.ProcessEnv;
|
|
147
|
+
}) => ChildProcess;
|
|
148
|
+
/** Splits a byte stream into JSON objects, one per line; tolerant of partial chunks, CRLF and noise. */
|
|
149
|
+
export declare class LineDecoder {
|
|
150
|
+
private buf;
|
|
151
|
+
push(chunk: string, onObject: (o: Record<string, unknown>) => void, onNoise?: (line: string) => void): void;
|
|
152
|
+
}
|
|
153
|
+
export interface HelperOptions {
|
|
154
|
+
spawn?: SpawnFn;
|
|
155
|
+
env?: NodeJS.ProcessEnv;
|
|
156
|
+
log?: (l: string) => void;
|
|
157
|
+
onEvent?: (e: Record<string, unknown>) => void;
|
|
158
|
+
/** How long a cancelled command may take to answer before the helper is killed (PROTOCOL.md §5). */
|
|
159
|
+
abortGraceMs?: number;
|
|
160
|
+
}
|
|
161
|
+
export declare class HelperProcess {
|
|
162
|
+
private readonly path;
|
|
163
|
+
private readonly opts;
|
|
164
|
+
private child;
|
|
165
|
+
private waiters;
|
|
166
|
+
private aborted;
|
|
167
|
+
private seq;
|
|
168
|
+
private restarts;
|
|
169
|
+
private disposed;
|
|
170
|
+
private starting;
|
|
171
|
+
private readyResolve;
|
|
172
|
+
ready: Record<string, unknown> | null;
|
|
173
|
+
constructor(path: string, opts?: HelperOptions);
|
|
174
|
+
private log;
|
|
175
|
+
start(): Promise<void>;
|
|
176
|
+
private onMessage;
|
|
177
|
+
private onExit;
|
|
178
|
+
get crashLooping(): boolean;
|
|
179
|
+
/** Writes one request and waits for the line with the same id. */
|
|
180
|
+
request(msg: Record<string, unknown>, timeoutMs: number): Promise<Record<string, unknown>>;
|
|
181
|
+
/** Fire-and-forget line. */
|
|
182
|
+
send(msg: Record<string, unknown>): void;
|
|
183
|
+
/**
|
|
184
|
+
* Aborts one command (or every one). A command that has not answered `stopped`
|
|
185
|
+
* within the grace period gets the helper killed; it restarts on the next command.
|
|
186
|
+
*/
|
|
187
|
+
cancel(target?: string): void;
|
|
188
|
+
get running(): boolean;
|
|
189
|
+
dispose(): void;
|
|
190
|
+
}
|
|
191
|
+
/** Holds a sleep inhibitor child process: systemd-inhibit (Linux) or caffeinate (macOS). */
|
|
192
|
+
export declare class KeepAwake {
|
|
193
|
+
private readonly opts;
|
|
194
|
+
private child;
|
|
195
|
+
constructor(opts?: {
|
|
196
|
+
spawn?: SpawnFn;
|
|
197
|
+
env?: NodeJS.ProcessEnv;
|
|
198
|
+
platform?: string;
|
|
199
|
+
});
|
|
200
|
+
available(): string | null;
|
|
201
|
+
get active(): boolean;
|
|
202
|
+
acquire(): string | null;
|
|
203
|
+
release(): void;
|
|
204
|
+
}
|
|
205
|
+
export interface CliComputerHostOptions {
|
|
206
|
+
/** Results / capabilities pushed outside a handle() call (the relay's executor callback). */
|
|
207
|
+
send?: (msg: ComputerHostToRunner) => void;
|
|
208
|
+
verbose?: boolean;
|
|
209
|
+
/** Path to the helper binary (else MELAYA_COMPUTER_HELPER, the package's native/ folder, the per-user cache). */
|
|
210
|
+
helperPath?: string;
|
|
211
|
+
/** Force on / off (else enableCliComputerHost() or MELAYA_COMPUTER=1). */
|
|
212
|
+
enabled?: boolean;
|
|
213
|
+
/** Download the pinned helper when none is installed (default: true). */
|
|
214
|
+
download?: boolean;
|
|
215
|
+
env?: NodeJS.ProcessEnv;
|
|
216
|
+
spawn?: SpawnFn;
|
|
217
|
+
log?: (line: string) => void;
|
|
218
|
+
/** Test seam for keep_awake. */
|
|
219
|
+
keepAwake?: KeepAwake;
|
|
220
|
+
abortGraceMs?: number;
|
|
221
|
+
}
|
|
222
|
+
export interface CliComputerHostApi {
|
|
223
|
+
handle(msg: ComputerRunnerToHost): Promise<ComputerHostToRunner | void>;
|
|
224
|
+
capabilities(): Promise<ComputerCapabilitiesLike | null>;
|
|
225
|
+
stopAll(reason: string): void;
|
|
226
|
+
dispose(): void;
|
|
227
|
+
}
|
|
228
|
+
/** Called by cli.ts for `--computer`: later createCliComputerHost() calls (from the relay) are enabled. */
|
|
229
|
+
export declare function enableCliComputerHost(opts?: Partial<CliComputerHostOptions>): void;
|
|
230
|
+
export declare function isCliComputerEnabled(env?: NodeJS.ProcessEnv): boolean;
|
|
231
|
+
/** Test seam: forget enableCliComputerHost(). */
|
|
232
|
+
export declare function _resetCliComputerHost(): void;
|
|
233
|
+
export declare function createCliComputerHost(options?: CliComputerHostOptions): CliComputerHostApi | null;
|