@mearl/native-host 2.3.0 → 2.4.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.
- package/dist/host-updater.d.ts +39 -0
- package/dist/index.js +557 -86
- package/package.json +4 -4
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { type CommandRunner } from '@mearl/setup/process';
|
|
2
|
+
export declare const NATIVE_HOST_UPDATE_TIMEOUT_MS: number;
|
|
3
|
+
export type NativeHostUpdateError = 'lock-timeout' | 'network' | 'package-unavailable' | 'setup-failed' | 'timeout' | 'verification-failed' | 'unknown';
|
|
4
|
+
export interface NativeHostUpdateCommand {
|
|
5
|
+
args: string[];
|
|
6
|
+
}
|
|
7
|
+
type UpdateLockRunner = <T>(targetVersion: string, operation: () => Promise<T>) => Promise<T>;
|
|
8
|
+
export interface RunNativeHostUpdateOptions {
|
|
9
|
+
areTargetsInstalled?: (targetReleaseLine: string, environment: NodeJS.ProcessEnv) => Promise<boolean>;
|
|
10
|
+
environment?: NodeJS.ProcessEnv;
|
|
11
|
+
nodePath?: string;
|
|
12
|
+
packageBinDirectory?: string | null;
|
|
13
|
+
packageManagerCommand?: string | null;
|
|
14
|
+
packageRunner?: string;
|
|
15
|
+
platform?: NodeJS.Platform;
|
|
16
|
+
runner?: CommandRunner;
|
|
17
|
+
timeoutMs?: number;
|
|
18
|
+
updateLockPath?: string;
|
|
19
|
+
withUpdateLock?: UpdateLockRunner;
|
|
20
|
+
}
|
|
21
|
+
export interface NativeHostUpdateCoordinatorOptions {
|
|
22
|
+
hostVersion: string;
|
|
23
|
+
log: (...args: unknown[]) => void;
|
|
24
|
+
requestRestart: () => void | Promise<void>;
|
|
25
|
+
runUpdate: (targetVersion: string) => Promise<void>;
|
|
26
|
+
}
|
|
27
|
+
export declare class NativeHostUpdateFailure extends Error {
|
|
28
|
+
readonly updateError: NativeHostUpdateError;
|
|
29
|
+
constructor(updateError: NativeHostUpdateError, message: string);
|
|
30
|
+
}
|
|
31
|
+
export declare function nativeHostUpdateCommand(targetVersion: string): NativeHostUpdateCommand;
|
|
32
|
+
export declare function runNativeHostUpdate(targetVersion: string, options?: RunNativeHostUpdateOptions): Promise<void>;
|
|
33
|
+
export declare class NativeHostUpdateCoordinator {
|
|
34
|
+
#private;
|
|
35
|
+
private readonly options;
|
|
36
|
+
constructor(options: NativeHostUpdateCoordinatorOptions);
|
|
37
|
+
evaluate(extensionVersion: unknown, checkForUpdates: unknown): void;
|
|
38
|
+
}
|
|
39
|
+
export {};
|
package/dist/index.js
CHANGED
|
@@ -10,20 +10,20 @@ var __export = (target, all) => {
|
|
|
10
10
|
};
|
|
11
11
|
|
|
12
12
|
// ../setup/dist/nativeHost.js
|
|
13
|
-
import
|
|
13
|
+
import fs11 from "node:fs";
|
|
14
14
|
import os6 from "node:os";
|
|
15
|
-
import
|
|
15
|
+
import path12 from "node:path";
|
|
16
16
|
import { execFileSync } from "node:child_process";
|
|
17
17
|
function resolveNativeHostDirectory(options = {}) {
|
|
18
18
|
const env = options.env ?? process.env;
|
|
19
19
|
const home = (options.homedir ?? os6.homedir)();
|
|
20
20
|
switch (options.platform ?? process.platform) {
|
|
21
21
|
case "darwin":
|
|
22
|
-
return
|
|
22
|
+
return path12.join(home, "Library/Application Support/Google/Chrome/NativeMessagingHosts");
|
|
23
23
|
case "linux":
|
|
24
|
-
return
|
|
24
|
+
return path12.join(home, ".config/google-chrome/NativeMessagingHosts");
|
|
25
25
|
case "win32":
|
|
26
|
-
return
|
|
26
|
+
return path12.join(env.PROGRAMDATA || "C:\\ProgramData", "Google\\Chrome\\NativeMessagingHosts");
|
|
27
27
|
default:
|
|
28
28
|
throw new Error(`Unsupported platform: ${String(options.platform ?? process.platform)}`);
|
|
29
29
|
}
|
|
@@ -46,20 +46,20 @@ function uninstallNativeHostArtifacts(options = {}, dependencies = {}) {
|
|
|
46
46
|
writeLine(line);
|
|
47
47
|
};
|
|
48
48
|
try {
|
|
49
|
-
const existsSync4 = dependencies.existsSync ??
|
|
49
|
+
const existsSync4 = dependencies.existsSync ?? fs11.existsSync;
|
|
50
50
|
const platform = dependencies.platform ?? process.platform;
|
|
51
51
|
const hostDir = dependencies.hostDir ?? resolveNativeHostDirectory({
|
|
52
52
|
env: dependencies.env,
|
|
53
53
|
homedir: dependencies.homedir,
|
|
54
54
|
platform
|
|
55
55
|
});
|
|
56
|
-
const unlinkSync = dependencies.unlinkSync ??
|
|
56
|
+
const unlinkSync = dependencies.unlinkSync ?? fs11.unlinkSync;
|
|
57
57
|
const unregister = dependencies.unregisterWindowsNativeHost ?? unregisterWindowsNativeHost;
|
|
58
58
|
const hostName = MEARL_NATIVE_HOST_NAMES[mode];
|
|
59
59
|
const launcherExtension = platform === "win32" ? "cmd" : "sh";
|
|
60
60
|
const artifacts = [
|
|
61
|
-
|
|
62
|
-
|
|
61
|
+
path12.join(hostDir, `${hostName}.json`),
|
|
62
|
+
path12.join(hostDir, `${hostName}-launcher.${launcherExtension}`)
|
|
63
63
|
];
|
|
64
64
|
for (const artifact of artifacts) {
|
|
65
65
|
if (!existsSync4(artifact))
|
|
@@ -94,17 +94,17 @@ __export(install_exports, {
|
|
|
94
94
|
runCli: () => runCli,
|
|
95
95
|
uninstallNativeHost: () => uninstallNativeHost
|
|
96
96
|
});
|
|
97
|
-
import
|
|
98
|
-
import
|
|
97
|
+
import fs12 from "node:fs";
|
|
98
|
+
import path13 from "node:path";
|
|
99
99
|
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
100
100
|
import { createRequire } from "node:module";
|
|
101
|
-
import { fileURLToPath } from "node:url";
|
|
101
|
+
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
102
102
|
function resolveHostDir() {
|
|
103
103
|
return resolveNativeHostDirectory();
|
|
104
104
|
}
|
|
105
105
|
function resolveNativeHostPath() {
|
|
106
|
-
const siblingPath =
|
|
107
|
-
if (
|
|
106
|
+
const siblingPath = path13.join(__dirname, "index.js");
|
|
107
|
+
if (fs12.existsSync(siblingPath)) {
|
|
108
108
|
return siblingPath;
|
|
109
109
|
}
|
|
110
110
|
try {
|
|
@@ -123,16 +123,16 @@ function registerWindowsNativeHost(hostName, manifestPath) {
|
|
|
123
123
|
});
|
|
124
124
|
}
|
|
125
125
|
function createLauncherScript(hostDir, hostPath, hostName) {
|
|
126
|
-
const nodePath =
|
|
126
|
+
const nodePath = path13.resolve(process.execPath);
|
|
127
127
|
if (process.platform === "win32") {
|
|
128
|
-
const launcherPath2 =
|
|
128
|
+
const launcherPath2 = path13.join(hostDir, `${hostName}-launcher.cmd`);
|
|
129
129
|
const content2 = `@echo off\r
|
|
130
130
|
"${nodePath}" "${hostPath}" %*\r
|
|
131
131
|
`;
|
|
132
|
-
|
|
132
|
+
fs12.writeFileSync(launcherPath2, content2, "utf-8");
|
|
133
133
|
return launcherPath2;
|
|
134
134
|
}
|
|
135
|
-
const launcherPath =
|
|
135
|
+
const launcherPath = path13.join(hostDir, `${hostName}-launcher.sh`);
|
|
136
136
|
const content = [
|
|
137
137
|
"#!/bin/sh",
|
|
138
138
|
`NODE_BIN=${JSON.stringify(nodePath)}`,
|
|
@@ -140,8 +140,8 @@ function createLauncherScript(hostDir, hostPath, hostName) {
|
|
|
140
140
|
'exec "$NODE_BIN" "$HOST_SCRIPT" "$@"',
|
|
141
141
|
""
|
|
142
142
|
].join("\n");
|
|
143
|
-
|
|
144
|
-
|
|
143
|
+
fs12.writeFileSync(launcherPath, content, "utf-8");
|
|
144
|
+
fs12.chmodSync(launcherPath, 493);
|
|
145
145
|
return launcherPath;
|
|
146
146
|
}
|
|
147
147
|
async function installNativeHost(options = {}) {
|
|
@@ -167,14 +167,14 @@ async function installNativeHost(options = {}) {
|
|
|
167
167
|
try {
|
|
168
168
|
const hostDir = resolveHostDir();
|
|
169
169
|
if (skipIfExists) {
|
|
170
|
-
const manifestPath2 =
|
|
171
|
-
if (
|
|
170
|
+
const manifestPath2 = path13.join(hostDir, `${hostName}.json`);
|
|
171
|
+
if (fs12.existsSync(manifestPath2)) {
|
|
172
172
|
log2(`✅ Already installed: ${manifestPath2}`);
|
|
173
173
|
return true;
|
|
174
174
|
}
|
|
175
175
|
}
|
|
176
|
-
if (!
|
|
177
|
-
|
|
176
|
+
if (!fs12.existsSync(hostDir)) {
|
|
177
|
+
fs12.mkdirSync(hostDir, { recursive: true });
|
|
178
178
|
log2(`✅ Created directory: ${hostDir}`);
|
|
179
179
|
}
|
|
180
180
|
const resolvedHostPath = resolveNativeHostPath();
|
|
@@ -188,13 +188,13 @@ async function installNativeHost(options = {}) {
|
|
|
188
188
|
type: "stdio",
|
|
189
189
|
allowed_origins: [`chrome-extension://${extensionId}/`]
|
|
190
190
|
};
|
|
191
|
-
const manifestPath =
|
|
192
|
-
|
|
191
|
+
const manifestPath = path13.join(hostDir, `${hostName}.json`);
|
|
192
|
+
fs12.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2));
|
|
193
193
|
if (process.platform === "win32") {
|
|
194
194
|
registerWindowsNativeHost(hostName, manifestPath);
|
|
195
195
|
log2(`✅ Windows registry key created for: ${hostName}`);
|
|
196
196
|
} else {
|
|
197
|
-
|
|
197
|
+
fs12.chmodSync(manifestPath, 420);
|
|
198
198
|
}
|
|
199
199
|
log2(`✅ Manifest installed: ${manifestPath}`);
|
|
200
200
|
log2(`✅ Extension ID: ${extensionId}`);
|
|
@@ -306,19 +306,19 @@ var init_install = __esm({
|
|
|
306
306
|
"use strict";
|
|
307
307
|
init_nativeHost();
|
|
308
308
|
DEFAULT_EXTENSION_ID = "aoehhjnofngknnjefamjbplchbolghkm";
|
|
309
|
-
__filename =
|
|
310
|
-
__dirname =
|
|
309
|
+
__filename = fileURLToPath2(import.meta.url);
|
|
310
|
+
__dirname = path13.dirname(__filename);
|
|
311
311
|
ALL_MODES = ["skills", "mcp"];
|
|
312
312
|
}
|
|
313
313
|
});
|
|
314
314
|
|
|
315
315
|
// src/index.ts
|
|
316
316
|
import net from "node:net";
|
|
317
|
-
import
|
|
317
|
+
import fs13 from "node:fs";
|
|
318
318
|
import http5 from "node:http";
|
|
319
319
|
import os7 from "node:os";
|
|
320
|
-
import
|
|
321
|
-
import { fileURLToPath as
|
|
320
|
+
import path14 from "node:path";
|
|
321
|
+
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
322
322
|
|
|
323
323
|
// src/cdp-backend/cdp-session.ts
|
|
324
324
|
import http3 from "node:http";
|
|
@@ -1166,13 +1166,13 @@ function queryTrackingEvents(buffer, options = {}) {
|
|
|
1166
1166
|
}
|
|
1167
1167
|
|
|
1168
1168
|
// ../browser-core/dist/requestSerializer.js
|
|
1169
|
-
function parsePath(
|
|
1170
|
-
if (
|
|
1169
|
+
function parsePath(path15) {
|
|
1170
|
+
if (path15.length > 1e3)
|
|
1171
1171
|
throw new Error("Path too long: maximum 1000 characters allowed");
|
|
1172
1172
|
const keys = [];
|
|
1173
1173
|
let current = "";
|
|
1174
|
-
for (let i = 0; i <
|
|
1175
|
-
const char =
|
|
1174
|
+
for (let i = 0; i < path15.length; i++) {
|
|
1175
|
+
const char = path15[i];
|
|
1176
1176
|
if (char === ".") {
|
|
1177
1177
|
if (current) {
|
|
1178
1178
|
keys.push(current);
|
|
@@ -1184,10 +1184,10 @@ function parsePath(path13) {
|
|
|
1184
1184
|
current = "";
|
|
1185
1185
|
}
|
|
1186
1186
|
let j = i + 1;
|
|
1187
|
-
while (j <
|
|
1187
|
+
while (j < path15.length && path15[j] !== "]")
|
|
1188
1188
|
j++;
|
|
1189
|
-
if (j <
|
|
1190
|
-
const index = parseInt(
|
|
1189
|
+
if (j < path15.length) {
|
|
1190
|
+
const index = parseInt(path15.substring(i + 1, j), 10);
|
|
1191
1191
|
if (!isNaN(index)) {
|
|
1192
1192
|
if (index < 0 || index > 1e5)
|
|
1193
1193
|
throw new Error(`Array index out of safe range: ${index}`);
|
|
@@ -1205,8 +1205,8 @@ function parsePath(path13) {
|
|
|
1205
1205
|
throw new Error("Path too deep: maximum 50 levels allowed");
|
|
1206
1206
|
return keys;
|
|
1207
1207
|
}
|
|
1208
|
-
function getValueByPath(obj,
|
|
1209
|
-
const keys = parsePath(
|
|
1208
|
+
function getValueByPath(obj, path15) {
|
|
1209
|
+
const keys = parsePath(path15);
|
|
1210
1210
|
let current = obj;
|
|
1211
1211
|
for (const key of keys) {
|
|
1212
1212
|
if (current === null || current === void 0)
|
|
@@ -1215,8 +1215,8 @@ function getValueByPath(obj, path13) {
|
|
|
1215
1215
|
}
|
|
1216
1216
|
return current;
|
|
1217
1217
|
}
|
|
1218
|
-
function setValueByPath(obj,
|
|
1219
|
-
const keys = parsePath(
|
|
1218
|
+
function setValueByPath(obj, path15, value) {
|
|
1219
|
+
const keys = parsePath(path15);
|
|
1220
1220
|
let current = obj;
|
|
1221
1221
|
for (let i = 0; i < keys.length - 1; i++) {
|
|
1222
1222
|
const key = keys[i];
|
|
@@ -2752,19 +2752,19 @@ function installPageObserverInPage(maxBatches = 50) {
|
|
|
2752
2752
|
}
|
|
2753
2753
|
}
|
|
2754
2754
|
}
|
|
2755
|
-
const
|
|
2755
|
+
const path15 = [];
|
|
2756
2756
|
let current = input;
|
|
2757
|
-
while (current && current !== document.documentElement &&
|
|
2757
|
+
while (current && current !== document.documentElement && path15.length < 6) {
|
|
2758
2758
|
const parent = current.parentElement;
|
|
2759
2759
|
const currentTag = current.tagName.toLowerCase();
|
|
2760
2760
|
if (!parent) {
|
|
2761
|
-
|
|
2761
|
+
path15.unshift(currentTag);
|
|
2762
2762
|
break;
|
|
2763
2763
|
}
|
|
2764
2764
|
const siblings = Array.from(parent.children).filter((item) => item.tagName === current.tagName);
|
|
2765
2765
|
const position = siblings.indexOf(current) + 1;
|
|
2766
|
-
|
|
2767
|
-
const candidate =
|
|
2766
|
+
path15.unshift(siblings.length > 1 ? `${currentTag}:nth-of-type(${position})` : currentTag);
|
|
2767
|
+
const candidate = path15.join(" > ");
|
|
2768
2768
|
if (input.isConnected) {
|
|
2769
2769
|
try {
|
|
2770
2770
|
if (document.querySelectorAll(candidate).length === 1)
|
|
@@ -2774,7 +2774,7 @@ function installPageObserverInPage(maxBatches = 50) {
|
|
|
2774
2774
|
}
|
|
2775
2775
|
current = parent;
|
|
2776
2776
|
}
|
|
2777
|
-
return
|
|
2777
|
+
return path15.join(" > ") || void 0;
|
|
2778
2778
|
};
|
|
2779
2779
|
const inferredRole = (element) => {
|
|
2780
2780
|
const explicit = element.getAttribute("role");
|
|
@@ -4409,12 +4409,12 @@ function resolveGetCookieTarget(currentUrl, input) {
|
|
|
4409
4409
|
const url2 = parseCurrentUrl(currentUrl, action);
|
|
4410
4410
|
const name = validateCookieName(input?.name, action);
|
|
4411
4411
|
const domain2 = resolveExplicitDomain(url2, input?.domain, action);
|
|
4412
|
-
const
|
|
4412
|
+
const path15 = validateCookiePath(input?.path, action);
|
|
4413
4413
|
return {
|
|
4414
4414
|
cookieName: name,
|
|
4415
|
-
cookieUrl: `${url2.protocol}//${url2.hostname}${(
|
|
4415
|
+
cookieUrl: `${url2.protocol}//${url2.hostname}${(path15 ?? url2.pathname) || "/"}`,
|
|
4416
4416
|
...domain2 ? { domain: domain2 } : {},
|
|
4417
|
-
...
|
|
4417
|
+
...path15 ? { path: path15 } : {}
|
|
4418
4418
|
};
|
|
4419
4419
|
}
|
|
4420
4420
|
function resolveSetCookieTarget(currentUrl, input) {
|
|
@@ -4422,7 +4422,7 @@ function resolveSetCookieTarget(currentUrl, input) {
|
|
|
4422
4422
|
const url2 = parseCurrentUrl(currentUrl, action);
|
|
4423
4423
|
const name = validateCookieName(input?.name, action);
|
|
4424
4424
|
const value = validateCookieValue(input?.value);
|
|
4425
|
-
const
|
|
4425
|
+
const path15 = validateCookiePath(input?.path, action) ?? "/";
|
|
4426
4426
|
if (input.reload !== void 0 && typeof input.reload !== "boolean") {
|
|
4427
4427
|
throw new Error('set_cookie: "reload" must be a boolean');
|
|
4428
4428
|
}
|
|
@@ -4432,9 +4432,9 @@ function resolveSetCookieTarget(currentUrl, input) {
|
|
|
4432
4432
|
cookieName: name,
|
|
4433
4433
|
cookieValue: value,
|
|
4434
4434
|
...explicitDomain ? { cookieDomain: explicitDomain.includes(".") ? `.${explicitDomain}` : explicitDomain } : {},
|
|
4435
|
-
cookieUrl: `${url2.protocol}//${url2.hostname.toLowerCase()}${
|
|
4435
|
+
cookieUrl: `${url2.protocol}//${url2.hostname.toLowerCase()}${path15}`,
|
|
4436
4436
|
domain: domain2,
|
|
4437
|
-
path:
|
|
4437
|
+
path: path15,
|
|
4438
4438
|
reload: input.reload === true
|
|
4439
4439
|
};
|
|
4440
4440
|
}
|
|
@@ -7612,8 +7612,8 @@ registerActions([
|
|
|
7612
7612
|
]);
|
|
7613
7613
|
|
|
7614
7614
|
// src/cdp-backend/tdbank-handlers.ts
|
|
7615
|
-
async function cdpFetchTdbank(session,
|
|
7616
|
-
const url2 = new URL(`https://tdbank.alibaba-inc.com${
|
|
7615
|
+
async function cdpFetchTdbank(session, path15, options = {}) {
|
|
7616
|
+
const url2 = new URL(`https://tdbank.alibaba-inc.com${path15}`);
|
|
7617
7617
|
for (const [key, value] of Object.entries(options.params ?? {})) {
|
|
7618
7618
|
if (value !== void 0 && value !== null) {
|
|
7619
7619
|
url2.searchParams.set(key, String(value));
|
|
@@ -9752,7 +9752,7 @@ import os2 from "node:os";
|
|
|
9752
9752
|
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
9753
9753
|
|
|
9754
9754
|
// src/version.ts
|
|
9755
|
-
var NATIVE_HOST_VERSION = true ? "2.
|
|
9755
|
+
var NATIVE_HOST_VERSION = true ? "2.4.0" : "unknown";
|
|
9756
9756
|
|
|
9757
9757
|
// src/analytics.ts
|
|
9758
9758
|
var MEASUREMENT_ID = "G-W84LJDZ6PH";
|
|
@@ -10625,6 +10625,7 @@ import path7 from "node:path";
|
|
|
10625
10625
|
import fs5 from "node:fs";
|
|
10626
10626
|
import path6 from "node:path";
|
|
10627
10627
|
import { spawn as spawn4 } from "node:child_process";
|
|
10628
|
+
var MAX_CAPTURE_LENGTH = 1e6;
|
|
10628
10629
|
function isExecutable(filePath, platform = process.platform) {
|
|
10629
10630
|
try {
|
|
10630
10631
|
fs5.accessSync(filePath, platform === "win32" ? fs5.constants.F_OK : fs5.constants.X_OK);
|
|
@@ -10669,12 +10670,12 @@ function resolveSpawnCommand(executable, args, platform = process.platform, comm
|
|
|
10669
10670
|
function prependCommandPath(command, env = process.env) {
|
|
10670
10671
|
if (!path6.isAbsolute(command))
|
|
10671
10672
|
return env;
|
|
10672
|
-
return
|
|
10673
|
+
return prependPathDirectory(path6.dirname(command), env);
|
|
10673
10674
|
}
|
|
10674
10675
|
function prependNodePath(env = process.env, nodeExecutable = process.execPath) {
|
|
10675
|
-
return
|
|
10676
|
+
return prependPathDirectory(path6.dirname(nodeExecutable), env);
|
|
10676
10677
|
}
|
|
10677
|
-
function
|
|
10678
|
+
function prependPathDirectory(directory, env = process.env) {
|
|
10678
10679
|
const pathKey = Object.keys(env).find((key) => key.toLowerCase() === "path") || "PATH";
|
|
10679
10680
|
const inherited = env[pathKey] || "";
|
|
10680
10681
|
const entries = inherited.split(path6.delimiter).filter(Boolean);
|
|
@@ -10682,6 +10683,59 @@ function prependPath(directory, env) {
|
|
|
10682
10683
|
return env;
|
|
10683
10684
|
return { ...env, [pathKey]: [directory, ...entries].join(path6.delimiter) };
|
|
10684
10685
|
}
|
|
10686
|
+
function findExecutable(name, options = {}) {
|
|
10687
|
+
const env = options.env ?? process.env;
|
|
10688
|
+
const platform = options.platform ?? process.platform;
|
|
10689
|
+
const existsSync4 = options.existsSync ?? ((candidate) => isExecutable(candidate, platform));
|
|
10690
|
+
const pathKey = Object.keys(env).find((key) => key.toLowerCase() === "path") || "PATH";
|
|
10691
|
+
const directories = [
|
|
10692
|
+
...options.extraDirectories ?? [],
|
|
10693
|
+
...(env[pathKey] ?? "").split(path6.delimiter).filter(Boolean)
|
|
10694
|
+
];
|
|
10695
|
+
for (const directory of directories) {
|
|
10696
|
+
for (const executableName of executableNames(name, platform)) {
|
|
10697
|
+
const candidate = path6.join(directory, executableName);
|
|
10698
|
+
if (existsSync4(candidate))
|
|
10699
|
+
return candidate;
|
|
10700
|
+
}
|
|
10701
|
+
}
|
|
10702
|
+
return null;
|
|
10703
|
+
}
|
|
10704
|
+
var runCommand = (command, args, options = {}) => new Promise((resolve, reject) => {
|
|
10705
|
+
const capture = options.capture === true;
|
|
10706
|
+
const launch = resolveSpawnCommand(command, args);
|
|
10707
|
+
const child = spawn4(launch.command, launch.args, {
|
|
10708
|
+
cwd: options.cwd,
|
|
10709
|
+
env: options.env,
|
|
10710
|
+
stdio: capture ? ["ignore", "pipe", "pipe"] : "inherit",
|
|
10711
|
+
windowsHide: true
|
|
10712
|
+
});
|
|
10713
|
+
let stdout = "";
|
|
10714
|
+
let stderr = "";
|
|
10715
|
+
let settled = false;
|
|
10716
|
+
const append = (current, chunk) => current.length >= MAX_CAPTURE_LENGTH ? current : (current + chunk.toString("utf8")).slice(0, MAX_CAPTURE_LENGTH);
|
|
10717
|
+
const finish = (error48, code = 1) => {
|
|
10718
|
+
if (settled)
|
|
10719
|
+
return;
|
|
10720
|
+
settled = true;
|
|
10721
|
+
if (timer)
|
|
10722
|
+
clearTimeout(timer);
|
|
10723
|
+
if (error48)
|
|
10724
|
+
reject(error48);
|
|
10725
|
+
else
|
|
10726
|
+
resolve({ code, stdout, stderr });
|
|
10727
|
+
};
|
|
10728
|
+
const timer = options.timeoutMs === void 0 ? void 0 : setTimeout(() => {
|
|
10729
|
+
child.kill("SIGTERM");
|
|
10730
|
+
finish(new Error(`Command timed out after ${options.timeoutMs}ms`));
|
|
10731
|
+
}, options.timeoutMs);
|
|
10732
|
+
if (capture) {
|
|
10733
|
+
child.stdout?.on("data", (chunk) => stdout = append(stdout, chunk));
|
|
10734
|
+
child.stderr?.on("data", (chunk) => stderr = append(stderr, chunk));
|
|
10735
|
+
}
|
|
10736
|
+
child.once("error", (error48) => finish(error48));
|
|
10737
|
+
child.once("close", (code) => finish(void 0, code ?? 1));
|
|
10738
|
+
});
|
|
10685
10739
|
|
|
10686
10740
|
// src/agent/executable-resolver.ts
|
|
10687
10741
|
function agentExecutableCandidatePaths({
|
|
@@ -12163,10 +12217,10 @@ function mergeDefs(...defs) {
|
|
|
12163
12217
|
function cloneDef(schema) {
|
|
12164
12218
|
return mergeDefs(schema._zod.def);
|
|
12165
12219
|
}
|
|
12166
|
-
function getElementAtPath(obj,
|
|
12167
|
-
if (!
|
|
12220
|
+
function getElementAtPath(obj, path15) {
|
|
12221
|
+
if (!path15)
|
|
12168
12222
|
return obj;
|
|
12169
|
-
return
|
|
12223
|
+
return path15.reduce((acc, key) => acc?.[key], obj);
|
|
12170
12224
|
}
|
|
12171
12225
|
function promiseAllObject(promisesObj) {
|
|
12172
12226
|
const keys = Object.keys(promisesObj);
|
|
@@ -12549,11 +12603,11 @@ function aborted(x, startIndex = 0) {
|
|
|
12549
12603
|
}
|
|
12550
12604
|
return false;
|
|
12551
12605
|
}
|
|
12552
|
-
function prefixIssues(
|
|
12606
|
+
function prefixIssues(path15, issues) {
|
|
12553
12607
|
return issues.map((iss) => {
|
|
12554
12608
|
var _a2;
|
|
12555
12609
|
(_a2 = iss).path ?? (_a2.path = []);
|
|
12556
|
-
iss.path.unshift(
|
|
12610
|
+
iss.path.unshift(path15);
|
|
12557
12611
|
return iss;
|
|
12558
12612
|
});
|
|
12559
12613
|
}
|
|
@@ -12736,7 +12790,7 @@ function formatError(error48, mapper = (issue2) => issue2.message) {
|
|
|
12736
12790
|
}
|
|
12737
12791
|
function treeifyError(error48, mapper = (issue2) => issue2.message) {
|
|
12738
12792
|
const result = { errors: [] };
|
|
12739
|
-
const processError = (error49,
|
|
12793
|
+
const processError = (error49, path15 = []) => {
|
|
12740
12794
|
var _a2, _b;
|
|
12741
12795
|
for (const issue2 of error49.issues) {
|
|
12742
12796
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
@@ -12746,7 +12800,7 @@ function treeifyError(error48, mapper = (issue2) => issue2.message) {
|
|
|
12746
12800
|
} else if (issue2.code === "invalid_element") {
|
|
12747
12801
|
processError({ issues: issue2.issues }, issue2.path);
|
|
12748
12802
|
} else {
|
|
12749
|
-
const fullpath = [...
|
|
12803
|
+
const fullpath = [...path15, ...issue2.path];
|
|
12750
12804
|
if (fullpath.length === 0) {
|
|
12751
12805
|
result.errors.push(mapper(issue2));
|
|
12752
12806
|
continue;
|
|
@@ -12778,8 +12832,8 @@ function treeifyError(error48, mapper = (issue2) => issue2.message) {
|
|
|
12778
12832
|
}
|
|
12779
12833
|
function toDotPath(_path) {
|
|
12780
12834
|
const segs = [];
|
|
12781
|
-
const
|
|
12782
|
-
for (const seg of
|
|
12835
|
+
const path15 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
|
|
12836
|
+
for (const seg of path15) {
|
|
12783
12837
|
if (typeof seg === "number")
|
|
12784
12838
|
segs.push(`[${seg}]`);
|
|
12785
12839
|
else if (typeof seg === "symbol")
|
|
@@ -24756,13 +24810,13 @@ function resolveRef(ref, ctx) {
|
|
|
24756
24810
|
if (!ref.startsWith("#")) {
|
|
24757
24811
|
throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
|
|
24758
24812
|
}
|
|
24759
|
-
const
|
|
24760
|
-
if (
|
|
24813
|
+
const path15 = ref.slice(1).split("/").filter(Boolean);
|
|
24814
|
+
if (path15.length === 0) {
|
|
24761
24815
|
return ctx.rootSchema;
|
|
24762
24816
|
}
|
|
24763
24817
|
const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
|
|
24764
|
-
if (
|
|
24765
|
-
const key =
|
|
24818
|
+
if (path15[0] === defsKey) {
|
|
24819
|
+
const key = path15[1];
|
|
24766
24820
|
if (!key || !ctx.defs[key]) {
|
|
24767
24821
|
throw new Error(`Reference not found: ${ref}`);
|
|
24768
24822
|
}
|
|
@@ -29769,6 +29823,409 @@ function createExtensionRequestMessage(id, action, data, trustedInternal = false
|
|
|
29769
29823
|
};
|
|
29770
29824
|
}
|
|
29771
29825
|
|
|
29826
|
+
// src/host-updater.ts
|
|
29827
|
+
import fs10 from "node:fs";
|
|
29828
|
+
import path11 from "node:path";
|
|
29829
|
+
import { fileURLToPath } from "node:url";
|
|
29830
|
+
|
|
29831
|
+
// ../setup/dist/packageManager.js
|
|
29832
|
+
import fs9 from "node:fs";
|
|
29833
|
+
import path10 from "node:path";
|
|
29834
|
+
function normalizePath(filePath) {
|
|
29835
|
+
return filePath.replaceAll("\\", "/").replace(/\/+$/, "");
|
|
29836
|
+
}
|
|
29837
|
+
function firstExisting(candidates, existsSync4) {
|
|
29838
|
+
return candidates.find((candidate) => existsSync4(candidate));
|
|
29839
|
+
}
|
|
29840
|
+
function fallbackCommand(name, platform) {
|
|
29841
|
+
if (platform !== "win32")
|
|
29842
|
+
return name;
|
|
29843
|
+
if (name === "bun" || name === "volta")
|
|
29844
|
+
return `${name}.exe`;
|
|
29845
|
+
return `${name}.cmd`;
|
|
29846
|
+
}
|
|
29847
|
+
function resolvePackageManagerInstallation(packageRoot, packageName, options = {}) {
|
|
29848
|
+
const env = options.env ?? process.env;
|
|
29849
|
+
const platform = options.platform ?? process.platform;
|
|
29850
|
+
const existsSync4 = options.existsSync ?? ((candidate) => isExecutable(candidate, platform));
|
|
29851
|
+
const processExecPath = options.processExecPath ?? process.execPath;
|
|
29852
|
+
const normalizedRoot = normalizePath(path10.resolve(packageRoot));
|
|
29853
|
+
const lowerRoot = normalizedRoot.toLowerCase();
|
|
29854
|
+
const lowerPackageName = packageName.toLowerCase();
|
|
29855
|
+
const pnpmGlobalRoot = /\/global\/\d+\/(?:\.pnpm\/.*\/)?node_modules\//.exec(lowerRoot);
|
|
29856
|
+
if (pnpmGlobalRoot && lowerRoot.endsWith(`/node_modules/${lowerPackageName}`)) {
|
|
29857
|
+
const pnpmHome = normalizedRoot.slice(0, pnpmGlobalRoot.index);
|
|
29858
|
+
const command = firstExisting([
|
|
29859
|
+
...executableNames("pnpm", platform).map((name) => path10.join(pnpmHome, name)),
|
|
29860
|
+
...executableNames("pnpm", platform).map((name) => path10.join(path10.dirname(processExecPath), name))
|
|
29861
|
+
], existsSync4) ?? fallbackCommand("pnpm", platform);
|
|
29862
|
+
return { manager: "pnpm", command, binDirectory: pnpmHome };
|
|
29863
|
+
}
|
|
29864
|
+
const bunMarker = `/.bun/install/global/node_modules/${lowerPackageName}`;
|
|
29865
|
+
if (lowerRoot.endsWith(bunMarker)) {
|
|
29866
|
+
const bunHome = normalizedRoot.slice(0, lowerRoot.indexOf("/.bun/"));
|
|
29867
|
+
const command = firstExisting(executableNames("bun", platform).map((name) => path10.join(bunHome, ".bun", "bin", name)), existsSync4) ?? fallbackCommand("bun", platform);
|
|
29868
|
+
return {
|
|
29869
|
+
manager: "bun",
|
|
29870
|
+
command,
|
|
29871
|
+
binDirectory: path10.join(bunHome, ".bun", "bin")
|
|
29872
|
+
};
|
|
29873
|
+
}
|
|
29874
|
+
if ((lowerRoot.includes("/.config/yarn/global/node_modules/") || lowerRoot.includes("/.yarn/global/node_modules/") || lowerRoot.includes("/yarn/global/node_modules/") || lowerRoot.includes("/yarn/data/global/node_modules/")) && lowerRoot.endsWith(`/node_modules/${lowerPackageName}`)) {
|
|
29875
|
+
const layout = [
|
|
29876
|
+
{ marker: "/.config/yarn/global/", binSegments: [".yarn", "bin"] },
|
|
29877
|
+
{ marker: "/.yarn/global/", binSegments: [".yarn", "bin"] },
|
|
29878
|
+
{ marker: "/yarn/data/global/", binSegments: ["yarn", "bin"] },
|
|
29879
|
+
{ marker: "/yarn/global/", binSegments: ["yarn", "bin"] }
|
|
29880
|
+
].find((candidate) => lowerRoot.includes(candidate.marker));
|
|
29881
|
+
const prefix = normalizedRoot.slice(0, lowerRoot.indexOf(layout.marker));
|
|
29882
|
+
const binDirectory = path10.join(prefix, ...layout.binSegments);
|
|
29883
|
+
const command = firstExisting([
|
|
29884
|
+
...executableNames("yarn", platform).map((name) => path10.join(binDirectory, name)),
|
|
29885
|
+
...executableNames("yarn", platform).map((name) => path10.join(path10.dirname(processExecPath), name))
|
|
29886
|
+
], existsSync4) ?? findExecutable("yarn", { env, existsSync: existsSync4, platform }) ?? fallbackCommand("yarn", platform);
|
|
29887
|
+
return { manager: "yarn", command, binDirectory };
|
|
29888
|
+
}
|
|
29889
|
+
if (lowerRoot.includes("/.volta/tools/image/packages/") && lowerRoot.endsWith(`/lib/node_modules/${lowerPackageName}`)) {
|
|
29890
|
+
const voltaHome = normalizedRoot.slice(0, lowerRoot.indexOf("/.volta/"));
|
|
29891
|
+
const command = firstExisting(executableNames("volta", platform).map((name) => path10.join(voltaHome, ".volta", "bin", name)), existsSync4) ?? fallbackCommand("volta", platform);
|
|
29892
|
+
return {
|
|
29893
|
+
manager: "volta",
|
|
29894
|
+
command,
|
|
29895
|
+
binDirectory: path10.join(voltaHome, ".volta", "bin")
|
|
29896
|
+
};
|
|
29897
|
+
}
|
|
29898
|
+
const npmMarker = `/lib/node_modules/${lowerPackageName}`;
|
|
29899
|
+
if (lowerRoot.endsWith(npmMarker)) {
|
|
29900
|
+
const prefix = normalizedRoot.slice(0, lowerRoot.length - npmMarker.length);
|
|
29901
|
+
const command = firstExisting([
|
|
29902
|
+
...executableNames("npm", platform).map((name) => path10.join(prefix, "bin", name)),
|
|
29903
|
+
...executableNames("npm", platform).map((name) => path10.join(path10.dirname(processExecPath), name))
|
|
29904
|
+
], existsSync4) ?? fallbackCommand("npm", platform);
|
|
29905
|
+
return { manager: "npm", command, binDirectory: path10.join(prefix, "bin") };
|
|
29906
|
+
}
|
|
29907
|
+
if (platform === "win32" && env.APPDATA) {
|
|
29908
|
+
const npmRoot = normalizePath(path10.join(env.APPDATA, "npm", "node_modules", packageName));
|
|
29909
|
+
if (lowerRoot === npmRoot.toLowerCase()) {
|
|
29910
|
+
const binDirectory = path10.join(env.APPDATA, "npm");
|
|
29911
|
+
const command = firstExisting([
|
|
29912
|
+
...executableNames("npm", platform).map((name) => path10.join(binDirectory, name)),
|
|
29913
|
+
...executableNames("npm", platform).map((name) => path10.join(path10.dirname(processExecPath), name))
|
|
29914
|
+
], existsSync4) ?? fallbackCommand("npm", platform);
|
|
29915
|
+
return { manager: "npm", command, binDirectory };
|
|
29916
|
+
}
|
|
29917
|
+
}
|
|
29918
|
+
return null;
|
|
29919
|
+
}
|
|
29920
|
+
|
|
29921
|
+
// ../setup/dist/version.js
|
|
29922
|
+
var MEARL_RELEASE_VERSION_MAX_LENGTH = 64;
|
|
29923
|
+
var RELEASE_VERSION_PATTERN = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-beta\.(0|[1-9]\d*))?$/;
|
|
29924
|
+
var RELEASE_LINE_PATTERN = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.x$/;
|
|
29925
|
+
var RELEASE_COMPONENT_MAXIMUM = 65535;
|
|
29926
|
+
function parseComponent(value) {
|
|
29927
|
+
const component = Number(value);
|
|
29928
|
+
return Number.isSafeInteger(component) && component <= RELEASE_COMPONENT_MAXIMUM ? component : null;
|
|
29929
|
+
}
|
|
29930
|
+
function parseMearlReleaseVersion(value) {
|
|
29931
|
+
if (typeof value !== "string" || value.length > MEARL_RELEASE_VERSION_MAX_LENGTH)
|
|
29932
|
+
return null;
|
|
29933
|
+
const match = RELEASE_VERSION_PATTERN.exec(value);
|
|
29934
|
+
if (!match)
|
|
29935
|
+
return null;
|
|
29936
|
+
const major = parseComponent(match[1]);
|
|
29937
|
+
const minor = parseComponent(match[2]);
|
|
29938
|
+
const patch = parseComponent(match[3]);
|
|
29939
|
+
const beta = match[4] === void 0 ? void 0 : parseComponent(match[4]);
|
|
29940
|
+
if (major === null || minor === null || patch === null || beta === null)
|
|
29941
|
+
return null;
|
|
29942
|
+
return {
|
|
29943
|
+
raw: value,
|
|
29944
|
+
major,
|
|
29945
|
+
minor,
|
|
29946
|
+
patch,
|
|
29947
|
+
channel: beta === void 0 ? "stable" : "beta",
|
|
29948
|
+
...beta === void 0 ? {} : { beta }
|
|
29949
|
+
};
|
|
29950
|
+
}
|
|
29951
|
+
function isMearlReleaseVersion(value) {
|
|
29952
|
+
return parseMearlReleaseVersion(value) !== null;
|
|
29953
|
+
}
|
|
29954
|
+
function parseMearlReleaseLine(value) {
|
|
29955
|
+
if (typeof value !== "string" || value.length > MEARL_RELEASE_VERSION_MAX_LENGTH)
|
|
29956
|
+
return null;
|
|
29957
|
+
const match = RELEASE_LINE_PATTERN.exec(value);
|
|
29958
|
+
if (!match)
|
|
29959
|
+
return null;
|
|
29960
|
+
const major = parseComponent(match[1]);
|
|
29961
|
+
const minor = parseComponent(match[2]);
|
|
29962
|
+
if (major === null || minor === null)
|
|
29963
|
+
return null;
|
|
29964
|
+
return { raw: value, major, minor };
|
|
29965
|
+
}
|
|
29966
|
+
function mearlReleaseLineForVersion(version2) {
|
|
29967
|
+
const parsed = parseMearlReleaseVersion(version2);
|
|
29968
|
+
if (!parsed)
|
|
29969
|
+
throw new Error("A valid Mearl release version is required");
|
|
29970
|
+
return `${parsed.major}.${parsed.minor}.x`;
|
|
29971
|
+
}
|
|
29972
|
+
function isMearlReleaseVersionInLine(version2, releaseLine) {
|
|
29973
|
+
const parsedVersion = parseMearlReleaseVersion(version2);
|
|
29974
|
+
const parsedLine = parseMearlReleaseLine(releaseLine);
|
|
29975
|
+
return parsedVersion !== null && parsedLine !== null && parsedVersion.major === parsedLine.major && parsedVersion.minor === parsedLine.minor;
|
|
29976
|
+
}
|
|
29977
|
+
function compareMearlReleaseLines(leftVersion, rightVersion) {
|
|
29978
|
+
const left = parseMearlReleaseVersion(leftVersion);
|
|
29979
|
+
const right = parseMearlReleaseVersion(rightVersion);
|
|
29980
|
+
if (!left || !right) {
|
|
29981
|
+
throw new Error("Mearl release-line comparison requires valid release versions");
|
|
29982
|
+
}
|
|
29983
|
+
for (const key of ["major", "minor"]) {
|
|
29984
|
+
if (left[key] < right[key])
|
|
29985
|
+
return -1;
|
|
29986
|
+
if (left[key] > right[key])
|
|
29987
|
+
return 1;
|
|
29988
|
+
}
|
|
29989
|
+
return 0;
|
|
29990
|
+
}
|
|
29991
|
+
|
|
29992
|
+
// src/host-updater.ts
|
|
29993
|
+
var NATIVE_HOST_UPDATE_TIMEOUT_MS = 5 * 6e4;
|
|
29994
|
+
var UPDATE_LOCK_PATH = path11.join(DAEMON_HOME, "native-host-update.lock");
|
|
29995
|
+
var UPDATE_LOCK_POLL_MS = 500;
|
|
29996
|
+
var INVALID_UPDATE_LOCK_GRACE_MS = 1e4;
|
|
29997
|
+
var NativeHostUpdateFailure = class extends Error {
|
|
29998
|
+
constructor(updateError, message) {
|
|
29999
|
+
super(message);
|
|
30000
|
+
this.updateError = updateError;
|
|
30001
|
+
this.name = "NativeHostUpdateFailure";
|
|
30002
|
+
}
|
|
30003
|
+
};
|
|
30004
|
+
function wait(delayMs) {
|
|
30005
|
+
return new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
30006
|
+
}
|
|
30007
|
+
function readLockState(lockPath) {
|
|
30008
|
+
try {
|
|
30009
|
+
const stat2 = fs10.lstatSync(lockPath);
|
|
30010
|
+
if (!stat2.isFile() || stat2.isSymbolicLink() || stat2.size > 4096) {
|
|
30011
|
+
return { modifiedAt: stat2.mtimeMs, owner: null };
|
|
30012
|
+
}
|
|
30013
|
+
try {
|
|
30014
|
+
const value = JSON.parse(fs10.readFileSync(lockPath, "utf8"));
|
|
30015
|
+
const owner = Number.isInteger(value.pid) && value.pid > 0 && typeof value.startedAt === "number" && Number.isFinite(value.startedAt) && value.startedAt > 0 ? { pid: value.pid, startedAt: value.startedAt } : null;
|
|
30016
|
+
return { modifiedAt: stat2.mtimeMs, owner };
|
|
30017
|
+
} catch {
|
|
30018
|
+
return { modifiedAt: stat2.mtimeMs, owner: null };
|
|
30019
|
+
}
|
|
30020
|
+
} catch {
|
|
30021
|
+
return null;
|
|
30022
|
+
}
|
|
30023
|
+
}
|
|
30024
|
+
async function withNativeHostUpdateLock(lockPath, targetVersion, operation) {
|
|
30025
|
+
fs10.mkdirSync(path11.dirname(lockPath), { recursive: true, mode: 448 });
|
|
30026
|
+
const startedAt = Date.now();
|
|
30027
|
+
const owner = `${JSON.stringify({ pid: process.pid, startedAt, targetVersion })}
|
|
30028
|
+
`;
|
|
30029
|
+
while (true) {
|
|
30030
|
+
try {
|
|
30031
|
+
const handle = fs10.openSync(lockPath, "wx", 384);
|
|
30032
|
+
try {
|
|
30033
|
+
fs10.writeFileSync(handle, owner, "utf8");
|
|
30034
|
+
} finally {
|
|
30035
|
+
fs10.closeSync(handle);
|
|
30036
|
+
}
|
|
30037
|
+
break;
|
|
30038
|
+
} catch (error48) {
|
|
30039
|
+
if (!(error48 instanceof Error) || !("code" in error48) || error48.code !== "EEXIST") throw error48;
|
|
30040
|
+
const existing = readLockState(lockPath);
|
|
30041
|
+
const staleAfter = existing?.owner ? NATIVE_HOST_UPDATE_TIMEOUT_MS : INVALID_UPDATE_LOCK_GRACE_MS;
|
|
30042
|
+
const referenceTime = existing?.owner?.startedAt ?? existing?.modifiedAt;
|
|
30043
|
+
const expired = referenceTime !== void 0 && Date.now() - referenceTime > staleAfter;
|
|
30044
|
+
const ownerAlive = existing?.owner ? isAlive(existing.owner.pid) : false;
|
|
30045
|
+
if (expired && !ownerAlive) {
|
|
30046
|
+
try {
|
|
30047
|
+
fs10.unlinkSync(lockPath);
|
|
30048
|
+
continue;
|
|
30049
|
+
} catch {
|
|
30050
|
+
}
|
|
30051
|
+
}
|
|
30052
|
+
if (Date.now() - startedAt > NATIVE_HOST_UPDATE_TIMEOUT_MS + 1e4) {
|
|
30053
|
+
throw new NativeHostUpdateFailure(
|
|
30054
|
+
"lock-timeout",
|
|
30055
|
+
"Another Mearl Native Host update did not finish in time"
|
|
30056
|
+
);
|
|
30057
|
+
}
|
|
30058
|
+
await wait(UPDATE_LOCK_POLL_MS);
|
|
30059
|
+
}
|
|
30060
|
+
}
|
|
30061
|
+
try {
|
|
30062
|
+
return await operation();
|
|
30063
|
+
} finally {
|
|
30064
|
+
try {
|
|
30065
|
+
if (fs10.readFileSync(lockPath, "utf8") === owner) fs10.unlinkSync(lockPath);
|
|
30066
|
+
} catch {
|
|
30067
|
+
}
|
|
30068
|
+
}
|
|
30069
|
+
}
|
|
30070
|
+
function classifyUpdateFailure(output) {
|
|
30071
|
+
if (/\b(?:E404|ETARGET)\b|no matching version found|404\s+not found|package.+not found/i.test(
|
|
30072
|
+
output
|
|
30073
|
+
)) {
|
|
30074
|
+
return "package-unavailable";
|
|
30075
|
+
}
|
|
30076
|
+
if (/\b(?:EAI_AGAIN|ECONNREFUSED|ECONNRESET|ENETUNREACH|ENOTFOUND|ERR_SOCKET_TIMEOUT)\b|fetch failed|network request/i.test(
|
|
30077
|
+
output
|
|
30078
|
+
)) {
|
|
30079
|
+
return "network";
|
|
30080
|
+
}
|
|
30081
|
+
return "setup-failed";
|
|
30082
|
+
}
|
|
30083
|
+
function nativeHostUpdateCommand(targetVersion) {
|
|
30084
|
+
if (!isMearlReleaseVersion(targetVersion)) {
|
|
30085
|
+
throw new Error("The Native Host update target must be a valid Mearl release");
|
|
30086
|
+
}
|
|
30087
|
+
const releaseLine = mearlReleaseLineForVersion(targetVersion);
|
|
30088
|
+
const packageSpec = `@mearl/setup@${releaseLine}`;
|
|
30089
|
+
const args = [
|
|
30090
|
+
"--yes",
|
|
30091
|
+
packageSpec,
|
|
30092
|
+
"update",
|
|
30093
|
+
"--local",
|
|
30094
|
+
"--yes",
|
|
30095
|
+
"--target-line",
|
|
30096
|
+
releaseLine,
|
|
30097
|
+
"--skip-skill"
|
|
30098
|
+
];
|
|
30099
|
+
return {
|
|
30100
|
+
args
|
|
30101
|
+
};
|
|
30102
|
+
}
|
|
30103
|
+
function currentNativeHostPackageRoot(entryPath) {
|
|
30104
|
+
let current = path11.dirname(entryPath);
|
|
30105
|
+
for (let depth = 0; depth < 12; depth += 1) {
|
|
30106
|
+
try {
|
|
30107
|
+
const manifest = JSON.parse(fs10.readFileSync(path11.join(current, "package.json"), "utf8"));
|
|
30108
|
+
if (manifest.name === "@mearl/native-host") return current;
|
|
30109
|
+
} catch {
|
|
30110
|
+
}
|
|
30111
|
+
const parent = path11.dirname(current);
|
|
30112
|
+
if (parent === current) break;
|
|
30113
|
+
current = parent;
|
|
30114
|
+
}
|
|
30115
|
+
return null;
|
|
30116
|
+
}
|
|
30117
|
+
function currentPackageManagerInstallation(environment, nodePath, platform) {
|
|
30118
|
+
const packageRoot = currentNativeHostPackageRoot(fileURLToPath(import.meta.url));
|
|
30119
|
+
if (!packageRoot) return null;
|
|
30120
|
+
return resolvePackageManagerInstallation(packageRoot, "@mearl/native-host", {
|
|
30121
|
+
env: environment,
|
|
30122
|
+
platform,
|
|
30123
|
+
processExecPath: nodePath
|
|
30124
|
+
});
|
|
30125
|
+
}
|
|
30126
|
+
async function installedLocalPackagesMatch(targetReleaseLine, environment, runner) {
|
|
30127
|
+
const installedVersions = [];
|
|
30128
|
+
for (const executableName of ["mearl-native-host", "mearl"]) {
|
|
30129
|
+
const executable = findExecutable(executableName, { env: environment });
|
|
30130
|
+
if (!executable) return false;
|
|
30131
|
+
try {
|
|
30132
|
+
const result = await runner(executable, ["--version"], {
|
|
30133
|
+
capture: true,
|
|
30134
|
+
env: environment,
|
|
30135
|
+
timeoutMs: 5e3
|
|
30136
|
+
});
|
|
30137
|
+
const installedVersion = result.stdout.trim();
|
|
30138
|
+
if (result.code !== 0 || !isMearlReleaseVersionInLine(installedVersion, targetReleaseLine)) {
|
|
30139
|
+
return false;
|
|
30140
|
+
}
|
|
30141
|
+
installedVersions.push(installedVersion);
|
|
30142
|
+
} catch {
|
|
30143
|
+
return false;
|
|
30144
|
+
}
|
|
30145
|
+
}
|
|
30146
|
+
return new Set(installedVersions).size === 1;
|
|
30147
|
+
}
|
|
30148
|
+
async function runNativeHostUpdate(targetVersion, options = {}) {
|
|
30149
|
+
const command = nativeHostUpdateCommand(targetVersion);
|
|
30150
|
+
const targetReleaseLine = mearlReleaseLineForVersion(targetVersion);
|
|
30151
|
+
const environment = options.environment ?? process.env;
|
|
30152
|
+
const platform = options.platform ?? process.platform;
|
|
30153
|
+
const nodePath = options.nodePath ?? process.execPath;
|
|
30154
|
+
const currentInstallation = currentPackageManagerInstallation(environment, nodePath, platform);
|
|
30155
|
+
const managerCommand = options.packageManagerCommand === void 0 ? currentInstallation?.command ?? null : options.packageManagerCommand;
|
|
30156
|
+
const packageBinDirectory = options.packageBinDirectory === void 0 ? currentInstallation?.binDirectory ?? null : options.packageBinDirectory;
|
|
30157
|
+
let childEnvironment = prependNodePath(environment, nodePath);
|
|
30158
|
+
if (managerCommand) childEnvironment = prependCommandPath(managerCommand, childEnvironment);
|
|
30159
|
+
if (packageBinDirectory) {
|
|
30160
|
+
childEnvironment = prependPathDirectory(packageBinDirectory, childEnvironment);
|
|
30161
|
+
}
|
|
30162
|
+
const packageRunner = options.packageRunner ?? findExecutable("npx", {
|
|
30163
|
+
env: childEnvironment,
|
|
30164
|
+
extraDirectories: [path11.dirname(nodePath)],
|
|
30165
|
+
platform
|
|
30166
|
+
});
|
|
30167
|
+
if (!packageRunner) {
|
|
30168
|
+
throw new NativeHostUpdateFailure("package-unavailable", "The package runner is unavailable");
|
|
30169
|
+
}
|
|
30170
|
+
const runner = options.runner ?? runCommand;
|
|
30171
|
+
const areTargetsInstalled = options.areTargetsInstalled ?? ((version2, env) => installedLocalPackagesMatch(version2, env, runner));
|
|
30172
|
+
const withUpdateLock = options.withUpdateLock ?? ((version2, operation) => withNativeHostUpdateLock(options.updateLockPath ?? UPDATE_LOCK_PATH, version2, operation));
|
|
30173
|
+
await withUpdateLock(targetVersion, async () => {
|
|
30174
|
+
let result;
|
|
30175
|
+
try {
|
|
30176
|
+
result = await runner(packageRunner, command.args, {
|
|
30177
|
+
capture: true,
|
|
30178
|
+
env: childEnvironment,
|
|
30179
|
+
timeoutMs: options.timeoutMs ?? NATIVE_HOST_UPDATE_TIMEOUT_MS
|
|
30180
|
+
});
|
|
30181
|
+
} catch (error48) {
|
|
30182
|
+
const message = error48 instanceof Error ? error48.message : String(error48);
|
|
30183
|
+
const classified = classifyUpdateFailure(message);
|
|
30184
|
+
throw new NativeHostUpdateFailure(
|
|
30185
|
+
/timed out/i.test(message) ? "timeout" : classified === "setup-failed" ? "unknown" : classified,
|
|
30186
|
+
"The Native Host update process did not complete"
|
|
30187
|
+
);
|
|
30188
|
+
}
|
|
30189
|
+
if (result.code !== 0) {
|
|
30190
|
+
throw new NativeHostUpdateFailure(
|
|
30191
|
+
classifyUpdateFailure(`${result.stderr.slice(0, 8192)}
|
|
30192
|
+
${result.stdout.slice(0, 8192)}`),
|
|
30193
|
+
"The Mearl setup release line did not complete successfully"
|
|
30194
|
+
);
|
|
30195
|
+
}
|
|
30196
|
+
if (!await areTargetsInstalled(targetReleaseLine, childEnvironment)) {
|
|
30197
|
+
throw new NativeHostUpdateFailure(
|
|
30198
|
+
"verification-failed",
|
|
30199
|
+
"The installed Native Host and client do not match the Extension release line"
|
|
30200
|
+
);
|
|
30201
|
+
}
|
|
30202
|
+
});
|
|
30203
|
+
}
|
|
30204
|
+
var NativeHostUpdateCoordinator = class {
|
|
30205
|
+
constructor(options) {
|
|
30206
|
+
this.options = options;
|
|
30207
|
+
}
|
|
30208
|
+
#automaticAttempted = false;
|
|
30209
|
+
#operation = null;
|
|
30210
|
+
evaluate(extensionVersion2, checkForUpdates) {
|
|
30211
|
+
if (checkForUpdates !== true || this.#automaticAttempted || this.#operation) return;
|
|
30212
|
+
if (!isMearlReleaseVersion(extensionVersion2) || !isMearlReleaseVersion(this.options.hostVersion)) {
|
|
30213
|
+
this.options.log("Skipped Native Host update check because a release version was invalid");
|
|
30214
|
+
return;
|
|
30215
|
+
}
|
|
30216
|
+
const targetVersion = extensionVersion2;
|
|
30217
|
+
if (compareMearlReleaseLines(this.options.hostVersion, targetVersion) >= 0) return;
|
|
30218
|
+
this.#automaticAttempted = true;
|
|
30219
|
+
const operation = this.options.runUpdate(targetVersion).then(() => this.options.requestRestart()).catch((error48) => {
|
|
30220
|
+
const category = error48 instanceof NativeHostUpdateFailure ? error48.updateError : "unknown";
|
|
30221
|
+
this.options.log(`Native Host automatic update failed (${category})`);
|
|
30222
|
+
}).finally(() => {
|
|
30223
|
+
if (this.#operation === operation) this.#operation = null;
|
|
30224
|
+
});
|
|
30225
|
+
this.#operation = operation;
|
|
30226
|
+
}
|
|
30227
|
+
};
|
|
30228
|
+
|
|
29772
30229
|
// src/index.ts
|
|
29773
30230
|
var cliArgs = process.argv.slice(2);
|
|
29774
30231
|
var cliArg = cliArgs[0];
|
|
@@ -29835,11 +30292,11 @@ Examples:
|
|
|
29835
30292
|
process.exit(0);
|
|
29836
30293
|
}
|
|
29837
30294
|
function socketPathFor(suffix) {
|
|
29838
|
-
return process.platform === "win32" ? `\\\\.\\pipe\\mearl-agent${suffix}` :
|
|
30295
|
+
return process.platform === "win32" ? `\\\\.\\pipe\\mearl-agent${suffix}` : path14.join(os7.tmpdir(), `mearl-agent${suffix}.sock`);
|
|
29839
30296
|
}
|
|
29840
30297
|
var LEGACY_SOCKET_PATH = socketPathFor("");
|
|
29841
30298
|
var INSTANCE_SOCKET_PATH = socketPathFor(`-${process.pid}`);
|
|
29842
|
-
var LOG_FILE =
|
|
30299
|
+
var LOG_FILE = path14.join(os7.tmpdir(), "mearl-native-host.log");
|
|
29843
30300
|
var DEFAULT_TIMEOUT_MS = 15e3;
|
|
29844
30301
|
var INVENTORY_IDLE_EXIT_MS = 1e3;
|
|
29845
30302
|
var MAX_SOCKET_BUFFER_SIZE = 64 * 1024 * 1024;
|
|
@@ -29938,7 +30395,7 @@ function log(...args) {
|
|
|
29938
30395
|
const msg = `[${(/* @__PURE__ */ new Date()).toISOString()}] [NativeHost] ${args.join(" ")}
|
|
29939
30396
|
`;
|
|
29940
30397
|
try {
|
|
29941
|
-
|
|
30398
|
+
fs13.appendFileSync(LOG_FILE, msg);
|
|
29942
30399
|
} catch {
|
|
29943
30400
|
}
|
|
29944
30401
|
}
|
|
@@ -29950,6 +30407,14 @@ function sendToExtension(message) {
|
|
|
29950
30407
|
process.stdout.write(header);
|
|
29951
30408
|
process.stdout.write(json2);
|
|
29952
30409
|
}
|
|
30410
|
+
var nativeHostUpdateCoordinator = new NativeHostUpdateCoordinator({
|
|
30411
|
+
hostVersion: NATIVE_HOST_VERSION,
|
|
30412
|
+
log,
|
|
30413
|
+
runUpdate: (targetVersion) => runNativeHostUpdate(targetVersion),
|
|
30414
|
+
requestRestart: () => {
|
|
30415
|
+
restartAfterUpdate();
|
|
30416
|
+
}
|
|
30417
|
+
});
|
|
29953
30418
|
var agentChatManager = null;
|
|
29954
30419
|
var agentSkillManager = new AgentSkillManager();
|
|
29955
30420
|
function getAgentChatManager() {
|
|
@@ -30060,6 +30525,7 @@ function handleExtensionMessage(message) {
|
|
|
30060
30525
|
extensionVersion: extensionVersion ?? void 0
|
|
30061
30526
|
});
|
|
30062
30527
|
sendToExtension({ type: "pong", timestamp: Date.now(), version: NATIVE_HOST_VERSION });
|
|
30528
|
+
nativeHostUpdateCoordinator.evaluate(message.version, message.checkForUpdates);
|
|
30063
30529
|
return;
|
|
30064
30530
|
}
|
|
30065
30531
|
if (message && message.type === "browser_focus") {
|
|
@@ -30343,7 +30809,7 @@ async function handleSocketLine(socket, line) {
|
|
|
30343
30809
|
return result2.cookies ?? [];
|
|
30344
30810
|
} : (domains) => cdpExportCookies(getCdpSession(), domains);
|
|
30345
30811
|
const result = await launchManagedBrowser(data, {
|
|
30346
|
-
nativeHostScript:
|
|
30812
|
+
nativeHostScript: fileURLToPath3(import.meta.url),
|
|
30347
30813
|
prepareTdbankSso,
|
|
30348
30814
|
exportCookies,
|
|
30349
30815
|
log
|
|
@@ -30472,7 +30938,7 @@ function onSocketConnection(socket) {
|
|
|
30472
30938
|
}
|
|
30473
30939
|
function isPathAlive(socketPath) {
|
|
30474
30940
|
return new Promise((resolve) => {
|
|
30475
|
-
if (process.platform !== "win32" && !
|
|
30941
|
+
if (process.platform !== "win32" && !fs13.existsSync(socketPath)) {
|
|
30476
30942
|
resolve(false);
|
|
30477
30943
|
return;
|
|
30478
30944
|
}
|
|
@@ -30495,9 +30961,9 @@ function isPathAlive(socketPath) {
|
|
|
30495
30961
|
}
|
|
30496
30962
|
function listenOn(socketPath) {
|
|
30497
30963
|
return new Promise((resolve, reject) => {
|
|
30498
|
-
if (process.platform !== "win32" &&
|
|
30964
|
+
if (process.platform !== "win32" && fs13.existsSync(socketPath)) {
|
|
30499
30965
|
try {
|
|
30500
|
-
|
|
30966
|
+
fs13.unlinkSync(socketPath);
|
|
30501
30967
|
} catch {
|
|
30502
30968
|
}
|
|
30503
30969
|
}
|
|
@@ -30506,11 +30972,11 @@ function listenOn(socketPath) {
|
|
|
30506
30972
|
server.listen(socketPath, () => {
|
|
30507
30973
|
if (process.platform !== "win32") {
|
|
30508
30974
|
try {
|
|
30509
|
-
|
|
30975
|
+
fs13.chmodSync(socketPath, 384);
|
|
30510
30976
|
} catch (error48) {
|
|
30511
30977
|
server.close();
|
|
30512
30978
|
try {
|
|
30513
|
-
|
|
30979
|
+
fs13.unlinkSync(socketPath);
|
|
30514
30980
|
} catch {
|
|
30515
30981
|
}
|
|
30516
30982
|
reject(error48);
|
|
@@ -30546,7 +31012,7 @@ function releaseLegacySocket() {
|
|
|
30546
31012
|
}
|
|
30547
31013
|
if (process.platform !== "win32") {
|
|
30548
31014
|
try {
|
|
30549
|
-
if (
|
|
31015
|
+
if (fs13.existsSync(LEGACY_SOCKET_PATH)) fs13.unlinkSync(LEGACY_SOCKET_PATH);
|
|
30550
31016
|
} catch {
|
|
30551
31017
|
}
|
|
30552
31018
|
}
|
|
@@ -30558,8 +31024,8 @@ async function startSocketServer() {
|
|
|
30558
31024
|
function cleanupInstanceSocketFile() {
|
|
30559
31025
|
if (process.platform === "win32") return;
|
|
30560
31026
|
try {
|
|
30561
|
-
if (
|
|
30562
|
-
|
|
31027
|
+
if (fs13.existsSync(INSTANCE_SOCKET_PATH)) {
|
|
31028
|
+
fs13.unlinkSync(INSTANCE_SOCKET_PATH);
|
|
30563
31029
|
}
|
|
30564
31030
|
} catch (error48) {
|
|
30565
31031
|
log("cleanup socket file failed:", String(error48));
|
|
@@ -30586,6 +31052,11 @@ function cleanupAndExit(code) {
|
|
|
30586
31052
|
}
|
|
30587
31053
|
finish();
|
|
30588
31054
|
}
|
|
31055
|
+
function restartAfterUpdate() {
|
|
31056
|
+
const forcedExit = setTimeout(() => process.exit(0), 2e3);
|
|
31057
|
+
forcedExit.unref();
|
|
31058
|
+
cleanupAndExit(0);
|
|
31059
|
+
}
|
|
30589
31060
|
async function main() {
|
|
30590
31061
|
initBrowserRegistry({ log });
|
|
30591
31062
|
pruneDeadBrowsers();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mearl/native-host",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.4.0",
|
|
4
4
|
"description": "Native Messaging Host for Mearl — bridges Chrome Extension and local socket server",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/install.js",
|
|
@@ -32,9 +32,9 @@
|
|
|
32
32
|
"@types/node": "^24.9.1",
|
|
33
33
|
"esbuild": "^0.25.2",
|
|
34
34
|
"typescript": "^5.8.3",
|
|
35
|
-
"@mearl/
|
|
36
|
-
"@mearl/
|
|
37
|
-
"@mearl/setup": "2.
|
|
35
|
+
"@mearl/browser-core": "2.4.0",
|
|
36
|
+
"@mearl/daemon-core": "2.4.0",
|
|
37
|
+
"@mearl/setup": "2.4.0"
|
|
38
38
|
},
|
|
39
39
|
"scripts": {
|
|
40
40
|
"build": "rm -rf dist/ && node build.mjs",
|