@mearl/native-host 2.2.1 → 2.2.2

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/index.js CHANGED
@@ -9,40 +9,102 @@ var __export = (target, all) => {
9
9
  __defProp(target, name, { get: all[name], enumerable: true });
10
10
  };
11
11
 
12
+ // ../setup/dist/nativeHost.js
13
+ import fs9 from "node:fs";
14
+ import os6 from "node:os";
15
+ import path10 from "node:path";
16
+ import { execFileSync } from "node:child_process";
17
+ function resolveNativeHostDirectory(options = {}) {
18
+ const env = options.env ?? process.env;
19
+ const home = (options.homedir ?? os6.homedir)();
20
+ switch (options.platform ?? process.platform) {
21
+ case "darwin":
22
+ return path10.join(home, "Library/Application Support/Google/Chrome/NativeMessagingHosts");
23
+ case "linux":
24
+ return path10.join(home, ".config/google-chrome/NativeMessagingHosts");
25
+ case "win32":
26
+ return path10.join(env.PROGRAMDATA || "C:\\ProgramData", "Google\\Chrome\\NativeMessagingHosts");
27
+ default:
28
+ throw new Error(`Unsupported platform: ${String(options.platform ?? process.platform)}`);
29
+ }
30
+ }
31
+ function unregisterWindowsNativeHost(hostName) {
32
+ const registryKey = `HKCU\\SOFTWARE\\Google\\Chrome\\NativeMessagingHosts\\${hostName}`;
33
+ try {
34
+ execFileSync("reg", ["delete", registryKey, "/f"], { stdio: "pipe" });
35
+ } catch {
36
+ }
37
+ }
38
+ function uninstallNativeHostArtifacts(options = {}, dependencies = {}) {
39
+ const { mode = "both", silent = false } = options;
40
+ if (mode === "both") {
41
+ return ["skills", "mcp"].map((integrationMode) => uninstallNativeHostArtifacts({ ...options, mode: integrationMode }, dependencies)).every(Boolean);
42
+ }
43
+ const writeLine = dependencies.writeLine ?? ((line) => console.error(line));
44
+ const log2 = (line) => {
45
+ if (!silent)
46
+ writeLine(line);
47
+ };
48
+ try {
49
+ const existsSync4 = dependencies.existsSync ?? fs9.existsSync;
50
+ const platform = dependencies.platform ?? process.platform;
51
+ const hostDir = dependencies.hostDir ?? resolveNativeHostDirectory({
52
+ env: dependencies.env,
53
+ homedir: dependencies.homedir,
54
+ platform
55
+ });
56
+ const unlinkSync = dependencies.unlinkSync ?? fs9.unlinkSync;
57
+ const unregister = dependencies.unregisterWindowsNativeHost ?? unregisterWindowsNativeHost;
58
+ const hostName = MEARL_NATIVE_HOST_NAMES[mode];
59
+ const launcherExtension = platform === "win32" ? "cmd" : "sh";
60
+ const artifacts = [
61
+ path10.join(hostDir, `${hostName}.json`),
62
+ path10.join(hostDir, `${hostName}-launcher.${launcherExtension}`)
63
+ ];
64
+ for (const artifact of artifacts) {
65
+ if (!existsSync4(artifact))
66
+ continue;
67
+ unlinkSync(artifact);
68
+ log2(`✅ Removed: ${artifact}`);
69
+ }
70
+ if (platform === "win32")
71
+ unregister(hostName);
72
+ return true;
73
+ } catch (error48) {
74
+ log2(`❌ Uninstall failed: ${error48 instanceof Error ? error48.message : String(error48)}`);
75
+ return false;
76
+ }
77
+ }
78
+ var MEARL_NATIVE_HOST_NAMES;
79
+ var init_nativeHost = __esm({
80
+ "../setup/dist/nativeHost.js"() {
81
+ "use strict";
82
+ MEARL_NATIVE_HOST_NAMES = {
83
+ skills: "com.alibaba.mearl.skills",
84
+ mcp: "com.alibaba.mearl.mcp"
85
+ };
86
+ }
87
+ });
88
+
12
89
  // src/install.ts
13
90
  var install_exports = {};
14
91
  __export(install_exports, {
15
92
  installNativeHost: () => installNativeHost,
16
93
  resolveHostDir: () => resolveHostDir,
17
- runCli: () => runCli
94
+ runCli: () => runCli,
95
+ uninstallNativeHost: () => uninstallNativeHost
18
96
  });
19
- import fs8 from "node:fs";
20
- import path10 from "node:path";
21
- import os6 from "node:os";
22
- import { execFileSync } from "node:child_process";
97
+ import fs10 from "node:fs";
98
+ import path11 from "node:path";
99
+ import { execFileSync as execFileSync2 } from "node:child_process";
23
100
  import { createRequire } from "node:module";
24
101
  import { fileURLToPath } from "node:url";
25
102
  function resolveHostDir() {
26
- switch (process.platform) {
27
- case "darwin":
28
- return path10.join(
29
- os6.homedir(),
30
- "Library/Application Support/Google/Chrome/NativeMessagingHosts"
31
- );
32
- case "linux":
33
- return path10.join(os6.homedir(), ".config/google-chrome/NativeMessagingHosts");
34
- case "win32":
35
- return path10.join(
36
- process.env.PROGRAMDATA || "C:\\ProgramData",
37
- "Google\\Chrome\\NativeMessagingHosts"
38
- );
39
- default:
40
- throw new Error(`Unsupported platform: ${process.platform}`);
41
- }
103
+ return resolveNativeHostDirectory();
42
104
  }
43
105
  function resolveNativeHostPath() {
44
- const siblingPath = path10.join(__dirname, "index.js");
45
- if (fs8.existsSync(siblingPath)) {
106
+ const siblingPath = path11.join(__dirname, "index.js");
107
+ if (fs10.existsSync(siblingPath)) {
46
108
  return siblingPath;
47
109
  }
48
110
  try {
@@ -56,21 +118,21 @@ function resolveNativeHostPath() {
56
118
  }
57
119
  function registerWindowsNativeHost(hostName, manifestPath) {
58
120
  const regKey = `HKCU\\SOFTWARE\\Google\\Chrome\\NativeMessagingHosts\\${hostName}`;
59
- execFileSync("reg", ["add", regKey, "/ve", "/t", "REG_SZ", "/d", manifestPath, "/f"], {
121
+ execFileSync2("reg", ["add", regKey, "/ve", "/t", "REG_SZ", "/d", manifestPath, "/f"], {
60
122
  stdio: "pipe"
61
123
  });
62
124
  }
63
125
  function createLauncherScript(hostDir, hostPath, hostName) {
64
- const nodePath = path10.resolve(process.execPath);
126
+ const nodePath = path11.resolve(process.execPath);
65
127
  if (process.platform === "win32") {
66
- const launcherPath2 = path10.join(hostDir, `${hostName}-launcher.cmd`);
128
+ const launcherPath2 = path11.join(hostDir, `${hostName}-launcher.cmd`);
67
129
  const content2 = `@echo off\r
68
130
  "${nodePath}" "${hostPath}" %*\r
69
131
  `;
70
- fs8.writeFileSync(launcherPath2, content2, "utf-8");
132
+ fs10.writeFileSync(launcherPath2, content2, "utf-8");
71
133
  return launcherPath2;
72
134
  }
73
- const launcherPath = path10.join(hostDir, `${hostName}-launcher.sh`);
135
+ const launcherPath = path11.join(hostDir, `${hostName}-launcher.sh`);
74
136
  const content = [
75
137
  "#!/bin/sh",
76
138
  `NODE_BIN=${JSON.stringify(nodePath)}`,
@@ -78,8 +140,8 @@ function createLauncherScript(hostDir, hostPath, hostName) {
78
140
  'exec "$NODE_BIN" "$HOST_SCRIPT" "$@"',
79
141
  ""
80
142
  ].join("\n");
81
- fs8.writeFileSync(launcherPath, content, "utf-8");
82
- fs8.chmodSync(launcherPath, 493);
143
+ fs10.writeFileSync(launcherPath, content, "utf-8");
144
+ fs10.chmodSync(launcherPath, 493);
83
145
  return launcherPath;
84
146
  }
85
147
  async function installNativeHost(options = {}) {
@@ -95,7 +157,7 @@ async function installNativeHost(options = {}) {
95
157
  );
96
158
  return results.every(Boolean);
97
159
  }
98
- const hostName = HOST_NAME_BY_MODE[mode];
160
+ const hostName = MEARL_NATIVE_HOST_NAMES[mode];
99
161
  if (!hostName) {
100
162
  throw new Error(`Unknown mode: ${mode}. Expected 'skills' or 'mcp'.`);
101
163
  }
@@ -105,14 +167,14 @@ async function installNativeHost(options = {}) {
105
167
  try {
106
168
  const hostDir = resolveHostDir();
107
169
  if (skipIfExists) {
108
- const manifestPath2 = path10.join(hostDir, `${hostName}.json`);
109
- if (fs8.existsSync(manifestPath2)) {
170
+ const manifestPath2 = path11.join(hostDir, `${hostName}.json`);
171
+ if (fs10.existsSync(manifestPath2)) {
110
172
  log2(`✅ Already installed: ${manifestPath2}`);
111
173
  return true;
112
174
  }
113
175
  }
114
- if (!fs8.existsSync(hostDir)) {
115
- fs8.mkdirSync(hostDir, { recursive: true });
176
+ if (!fs10.existsSync(hostDir)) {
177
+ fs10.mkdirSync(hostDir, { recursive: true });
116
178
  log2(`✅ Created directory: ${hostDir}`);
117
179
  }
118
180
  const resolvedHostPath = resolveNativeHostPath();
@@ -126,13 +188,13 @@ async function installNativeHost(options = {}) {
126
188
  type: "stdio",
127
189
  allowed_origins: [`chrome-extension://${extensionId}/`]
128
190
  };
129
- const manifestPath = path10.join(hostDir, `${hostName}.json`);
130
- fs8.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2));
191
+ const manifestPath = path11.join(hostDir, `${hostName}.json`);
192
+ fs10.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2));
131
193
  if (process.platform === "win32") {
132
194
  registerWindowsNativeHost(hostName, manifestPath);
133
195
  log2(`✅ Windows registry key created for: ${hostName}`);
134
196
  } else {
135
- fs8.chmodSync(manifestPath, 420);
197
+ fs10.chmodSync(manifestPath, 420);
136
198
  }
137
199
  log2(`✅ Manifest installed: ${manifestPath}`);
138
200
  log2(`✅ Extension ID: ${extensionId}`);
@@ -146,14 +208,18 @@ async function installNativeHost(options = {}) {
146
208
  return false;
147
209
  }
148
210
  }
211
+ async function uninstallNativeHost(options = {}, dependencies = {}) {
212
+ return uninstallNativeHostArtifacts(options, dependencies);
213
+ }
149
214
  function parseCliArgs(argv) {
150
215
  let mode = "both";
151
216
  let extensionId;
152
217
  let skipIfExists = false;
218
+ let uninstall = false;
153
219
  for (let i = 0; i < argv.length; i += 1) {
154
220
  const arg = argv[i];
155
221
  if (arg === "--help" || arg === "-h") {
156
- return { showHelp: true, mode, skipIfExists };
222
+ return { showHelp: true, uninstall, mode, skipIfExists };
157
223
  }
158
224
  if (arg === "--mode" || arg.startsWith("--mode=")) {
159
225
  const value = arg.includes("=") ? arg.slice("--mode=".length) : argv[++i];
@@ -172,24 +238,31 @@ function parseCliArgs(argv) {
172
238
  skipIfExists = true;
173
239
  continue;
174
240
  }
241
+ if (arg === "--uninstall") {
242
+ uninstall = true;
243
+ continue;
244
+ }
175
245
  if (arg === "--init") {
176
246
  continue;
177
247
  }
178
248
  }
179
- return { showHelp: false, mode, extensionId, skipIfExists };
249
+ return { showHelp: false, uninstall, mode, extensionId, skipIfExists };
180
250
  }
181
251
  function printHelp() {
182
252
  console.error(`Usage:
183
253
  mearl-native-host --init [options]
254
+ mearl-native-host --uninstall [options]
184
255
 
185
256
  Options:
186
257
  --mode <skills|mcp|both> Integration mode (default: both — installs both hosts)
187
258
  --extension-id <id> Chrome extension ID (default: ${DEFAULT_EXTENSION_ID})
259
+ --uninstall Remove the selected Native Messaging manifests
188
260
  -h, --help Show this help message
189
261
 
190
262
  Examples:
191
263
  mearl-native-host --init
192
264
  mearl-native-host --init --mode mcp
265
+ mearl-native-host --uninstall --mode skills
193
266
  mearl-native-host --init --extension-id abcdefghijklmnopqrstuvwxyzabcdef`);
194
267
  }
195
268
  async function runCli(argv) {
@@ -203,6 +276,11 @@ async function runCli(argv) {
203
276
  console.error(" Must be a 32-character lowercase string (see chrome://extensions/)");
204
277
  process.exit(1);
205
278
  }
279
+ if (parsed.uninstall) {
280
+ const success3 = await uninstallNativeHost({ mode: parsed.mode });
281
+ if (success3) console.error("\n✅ Uninstall complete!\n");
282
+ process.exit(success3 ? 0 : 1);
283
+ }
206
284
  const success2 = await installNativeHost({
207
285
  mode: parsed.mode,
208
286
  extensionId: parsed.extensionId,
@@ -222,27 +300,24 @@ Verify:
222
300
  }
223
301
  process.exit(success2 ? 0 : 1);
224
302
  }
225
- var DEFAULT_EXTENSION_ID, HOST_NAME_BY_MODE, __filename, __dirname, ALL_MODES;
303
+ var DEFAULT_EXTENSION_ID, __filename, __dirname, ALL_MODES;
226
304
  var init_install = __esm({
227
305
  "src/install.ts"() {
228
306
  "use strict";
307
+ init_nativeHost();
229
308
  DEFAULT_EXTENSION_ID = "aoehhjnofngknnjefamjbplchbolghkm";
230
- HOST_NAME_BY_MODE = {
231
- skills: "com.alibaba.mearl.skills",
232
- mcp: "com.alibaba.mearl.mcp"
233
- };
234
309
  __filename = fileURLToPath(import.meta.url);
235
- __dirname = path10.dirname(__filename);
310
+ __dirname = path11.dirname(__filename);
236
311
  ALL_MODES = ["skills", "mcp"];
237
312
  }
238
313
  });
239
314
 
240
315
  // src/index.ts
241
316
  import net from "node:net";
242
- import fs9 from "node:fs";
317
+ import fs11 from "node:fs";
243
318
  import http5 from "node:http";
244
319
  import os7 from "node:os";
245
- import path11 from "node:path";
320
+ import path12 from "node:path";
246
321
  import { fileURLToPath as fileURLToPath2 } from "node:url";
247
322
 
248
323
  // src/cdp-backend/cdp-session.ts
@@ -1088,13 +1163,13 @@ function queryTrackingEvents(buffer, options = {}) {
1088
1163
  }
1089
1164
 
1090
1165
  // ../browser-core/dist/requestSerializer.js
1091
- function parsePath(path12) {
1092
- if (path12.length > 1e3)
1166
+ function parsePath(path13) {
1167
+ if (path13.length > 1e3)
1093
1168
  throw new Error("Path too long: maximum 1000 characters allowed");
1094
1169
  const keys = [];
1095
1170
  let current = "";
1096
- for (let i = 0; i < path12.length; i++) {
1097
- const char = path12[i];
1171
+ for (let i = 0; i < path13.length; i++) {
1172
+ const char = path13[i];
1098
1173
  if (char === ".") {
1099
1174
  if (current) {
1100
1175
  keys.push(current);
@@ -1106,10 +1181,10 @@ function parsePath(path12) {
1106
1181
  current = "";
1107
1182
  }
1108
1183
  let j = i + 1;
1109
- while (j < path12.length && path12[j] !== "]")
1184
+ while (j < path13.length && path13[j] !== "]")
1110
1185
  j++;
1111
- if (j < path12.length) {
1112
- const index = parseInt(path12.substring(i + 1, j), 10);
1186
+ if (j < path13.length) {
1187
+ const index = parseInt(path13.substring(i + 1, j), 10);
1113
1188
  if (!isNaN(index)) {
1114
1189
  if (index < 0 || index > 1e5)
1115
1190
  throw new Error(`Array index out of safe range: ${index}`);
@@ -1127,8 +1202,8 @@ function parsePath(path12) {
1127
1202
  throw new Error("Path too deep: maximum 50 levels allowed");
1128
1203
  return keys;
1129
1204
  }
1130
- function getValueByPath(obj, path12) {
1131
- const keys = parsePath(path12);
1205
+ function getValueByPath(obj, path13) {
1206
+ const keys = parsePath(path13);
1132
1207
  let current = obj;
1133
1208
  for (const key of keys) {
1134
1209
  if (current === null || current === void 0)
@@ -1137,8 +1212,8 @@ function getValueByPath(obj, path12) {
1137
1212
  }
1138
1213
  return current;
1139
1214
  }
1140
- function setValueByPath(obj, path12, value) {
1141
- const keys = parsePath(path12);
1215
+ function setValueByPath(obj, path13, value) {
1216
+ const keys = parsePath(path13);
1142
1217
  let current = obj;
1143
1218
  for (let i = 0; i < keys.length - 1; i++) {
1144
1219
  const key = keys[i];
@@ -2141,6 +2216,24 @@ var CHECKABLE_AX_ROLES = /* @__PURE__ */ new Set([
2141
2216
  "radio",
2142
2217
  "switch"
2143
2218
  ]);
2219
+ function resolveDOMSnapshotViewportBounds(metrics) {
2220
+ const viewport = metrics.visualViewport ?? metrics.cssVisualViewport;
2221
+ return normalizePageViewportBounds({
2222
+ left: viewport?.pageX ?? 0,
2223
+ top: viewport?.pageY ?? 0,
2224
+ width: viewport?.clientWidth,
2225
+ height: viewport?.clientHeight
2226
+ });
2227
+ }
2228
+ function normalizePageViewportBounds(value) {
2229
+ if (!value || typeof value !== "object")
2230
+ return null;
2231
+ const { left, top, width, height } = value;
2232
+ if (typeof left !== "number" || typeof top !== "number" || typeof width !== "number" || typeof height !== "number" || !Number.isFinite(left) || !Number.isFinite(top) || !Number.isFinite(width) || !Number.isFinite(height) || width <= 0 || height <= 0) {
2233
+ return null;
2234
+ }
2235
+ return { left, top, width, height };
2236
+ }
2144
2237
  function readDOMCheckedState() {
2145
2238
  const tag = String(this && this.tagName || "").toLowerCase();
2146
2239
  const type = String(this && this.type || "").toLowerCase();
@@ -2648,19 +2741,19 @@ function installPageObserverInPage(maxBatches = 50) {
2648
2741
  }
2649
2742
  }
2650
2743
  }
2651
- const path12 = [];
2744
+ const path13 = [];
2652
2745
  let current = input;
2653
- while (current && current !== document.documentElement && path12.length < 6) {
2746
+ while (current && current !== document.documentElement && path13.length < 6) {
2654
2747
  const parent = current.parentElement;
2655
2748
  const currentTag = current.tagName.toLowerCase();
2656
2749
  if (!parent) {
2657
- path12.unshift(currentTag);
2750
+ path13.unshift(currentTag);
2658
2751
  break;
2659
2752
  }
2660
2753
  const siblings = Array.from(parent.children).filter((item) => item.tagName === current.tagName);
2661
2754
  const position = siblings.indexOf(current) + 1;
2662
- path12.unshift(siblings.length > 1 ? `${currentTag}:nth-of-type(${position})` : currentTag);
2663
- const candidate = path12.join(" > ");
2755
+ path13.unshift(siblings.length > 1 ? `${currentTag}:nth-of-type(${position})` : currentTag);
2756
+ const candidate = path13.join(" > ");
2664
2757
  if (input.isConnected) {
2665
2758
  try {
2666
2759
  if (document.querySelectorAll(candidate).length === 1)
@@ -2670,7 +2763,7 @@ function installPageObserverInPage(maxBatches = 50) {
2670
2763
  }
2671
2764
  current = parent;
2672
2765
  }
2673
- return path12.join(" > ") || void 0;
2766
+ return path13.join(" > ") || void 0;
2674
2767
  };
2675
2768
  const inferredRole = (element) => {
2676
2769
  const explicit = element.getAttribute("role");
@@ -4278,12 +4371,12 @@ function resolveGetCookieTarget(currentUrl, input) {
4278
4371
  const url2 = parseCurrentUrl(currentUrl, action);
4279
4372
  const name = validateCookieName(input?.name, action);
4280
4373
  const domain2 = resolveExplicitDomain(url2, input?.domain, action);
4281
- const path12 = validateCookiePath(input?.path, action);
4374
+ const path13 = validateCookiePath(input?.path, action);
4282
4375
  return {
4283
4376
  cookieName: name,
4284
- cookieUrl: `${url2.protocol}//${url2.hostname}${(path12 ?? url2.pathname) || "/"}`,
4377
+ cookieUrl: `${url2.protocol}//${url2.hostname}${(path13 ?? url2.pathname) || "/"}`,
4285
4378
  ...domain2 ? { domain: domain2 } : {},
4286
- ...path12 ? { path: path12 } : {}
4379
+ ...path13 ? { path: path13 } : {}
4287
4380
  };
4288
4381
  }
4289
4382
  function resolveSetCookieTarget(currentUrl, input) {
@@ -4291,7 +4384,7 @@ function resolveSetCookieTarget(currentUrl, input) {
4291
4384
  const url2 = parseCurrentUrl(currentUrl, action);
4292
4385
  const name = validateCookieName(input?.name, action);
4293
4386
  const value = validateCookieValue(input?.value);
4294
- const path12 = validateCookiePath(input?.path, action) ?? "/";
4387
+ const path13 = validateCookiePath(input?.path, action) ?? "/";
4295
4388
  if (input.reload !== void 0 && typeof input.reload !== "boolean") {
4296
4389
  throw new Error('set_cookie: "reload" must be a boolean');
4297
4390
  }
@@ -4301,9 +4394,9 @@ function resolveSetCookieTarget(currentUrl, input) {
4301
4394
  cookieName: name,
4302
4395
  cookieValue: value,
4303
4396
  ...explicitDomain ? { cookieDomain: explicitDomain.includes(".") ? `.${explicitDomain}` : explicitDomain } : {},
4304
- cookieUrl: `${url2.protocol}//${url2.hostname.toLowerCase()}${path12}`,
4397
+ cookieUrl: `${url2.protocol}//${url2.hostname.toLowerCase()}${path13}`,
4305
4398
  domain: domain2,
4306
- path: path12,
4399
+ path: path13,
4307
4400
  reload: input.reload === true
4308
4401
  };
4309
4402
  }
@@ -4319,10 +4412,7 @@ var SOURCE_BADGES = {
4319
4412
  <circle cx="104" cy="104" r="21" fill="#16A34A" stroke="#FFFFFF" stroke-width="6"/>
4320
4413
  `,
4321
4414
  cloud: `
4322
- <path d="M91 116H116C123 116 128 111 128 104C128 97 123 92 116 92H114
4323
- C111 85 106 82 100 82C91 82 85 89 84 97C78 99 75 104 75 109
4324
- C75 116 81 121 89 121H91Z" fill="#7C3AED" stroke="#FFFFFF" stroke-width="6"
4325
- stroke-linejoin="round"/>
4415
+ <circle cx="104" cy="104" r="21" fill="#FF7A00" stroke="#FFFFFF" stroke-width="6"/>
4326
4416
  `
4327
4417
  };
4328
4418
  function createControlledFaviconDataUrl(source) {
@@ -7215,8 +7305,8 @@ registerActions([
7215
7305
  ]);
7216
7306
 
7217
7307
  // src/cdp-backend/tdbank-handlers.ts
7218
- async function cdpFetchTdbank(session, path12, options = {}) {
7219
- const url2 = new URL(`https://tdbank.alibaba-inc.com${path12}`);
7308
+ async function cdpFetchTdbank(session, path13, options = {}) {
7309
+ const url2 = new URL(`https://tdbank.alibaba-inc.com${path13}`);
7220
7310
  for (const [key, value] of Object.entries(options.params ?? {})) {
7221
7311
  if (value !== void 0 && value !== null) {
7222
7312
  url2.searchParams.set(key, String(value));
@@ -8506,12 +8596,9 @@ async function getViewportBackendNodeIds(session) {
8506
8596
  includePaintOrder: false
8507
8597
  })
8508
8598
  ]);
8509
- const viewport = metrics.cssVisualViewport ?? metrics.visualViewport;
8510
- const left = viewport?.pageX ?? 0;
8511
- const top = viewport?.pageY ?? 0;
8512
- const width = viewport?.clientWidth;
8513
- const height = viewport?.clientHeight;
8514
- if (!width || !height) throw new Error("page_snapshot: viewport metrics are unavailable");
8599
+ const viewport = resolveDOMSnapshotViewportBounds(metrics);
8600
+ if (!viewport) throw new Error("page_snapshot: viewport metrics are unavailable");
8601
+ const { left, top, width, height } = viewport;
8515
8602
  const right = left + width;
8516
8603
  const bottom = top + height;
8517
8604
  const visible = /* @__PURE__ */ new Set();
@@ -9346,7 +9433,7 @@ import os2 from "node:os";
9346
9433
  import { randomUUID as randomUUID4 } from "node:crypto";
9347
9434
 
9348
9435
  // src/version.ts
9349
- var NATIVE_HOST_VERSION = true ? "2.2.1" : "unknown";
9436
+ var NATIVE_HOST_VERSION = true ? "2.2.2" : "unknown";
9350
9437
 
9351
9438
  // src/analytics.ts
9352
9439
  var MEASUREMENT_ID = "G-W84LJDZ6PH";
@@ -10209,15 +10296,28 @@ var AgentChatManager = class {
10209
10296
  import os3 from "node:os";
10210
10297
  import path7 from "node:path";
10211
10298
  import readline from "node:readline";
10212
- import { spawn as spawn5 } from "node:child_process";
10299
+ import { spawn as spawn6 } from "node:child_process";
10213
10300
 
10214
10301
  // src/agent/executable-resolver.ts
10215
- import fs5 from "node:fs";
10216
- import { spawn as spawn4 } from "node:child_process";
10302
+ import fs6 from "node:fs";
10303
+ import { spawn as spawn5 } from "node:child_process";
10217
10304
 
10218
- // src/agent/process-env.ts
10305
+ // ../setup/dist/process.js
10306
+ import fs5 from "node:fs";
10219
10307
  import path6 from "node:path";
10220
- function agentSpawnCommand(executable, args, platform = process.platform, commandInterpreter = process.env.ComSpec) {
10308
+ import { spawn as spawn4 } from "node:child_process";
10309
+ function isExecutable(filePath, platform = process.platform) {
10310
+ try {
10311
+ fs5.accessSync(filePath, platform === "win32" ? fs5.constants.F_OK : fs5.constants.X_OK);
10312
+ return true;
10313
+ } catch {
10314
+ return false;
10315
+ }
10316
+ }
10317
+ function executableNames(name, platform = process.platform) {
10318
+ return platform === "win32" ? [`${name}.cmd`, `${name}.exe`, name] : [name];
10319
+ }
10320
+ function resolveSpawnCommand(executable, args, platform = process.platform, commandInterpreter = process.env.ComSpec) {
10221
10321
  if (platform === "win32" && /\.(?:cmd|bat)$/i.test(executable)) {
10222
10322
  return {
10223
10323
  command: commandInterpreter || "cmd.exe",
@@ -10226,13 +10326,21 @@ function agentSpawnCommand(executable, args, platform = process.platform, comman
10226
10326
  }
10227
10327
  return { command: executable, args };
10228
10328
  }
10229
- function createAgentChildEnv(sourceEnv = process.env, nodeExecutable = process.execPath) {
10230
- const pathKey = Object.keys(sourceEnv).find((key) => key.toLowerCase() === "path") || "PATH";
10231
- const nodeDirectory = path6.dirname(nodeExecutable);
10232
- const inheritedPath = sourceEnv[pathKey] || "";
10233
- const pathEntries = inheritedPath.split(path6.delimiter).filter(Boolean);
10234
- const nextPath = pathEntries.includes(nodeDirectory) ? inheritedPath : [nodeDirectory, ...pathEntries].join(path6.delimiter);
10235
- return { ...sourceEnv, [pathKey]: nextPath };
10329
+ function prependCommandPath(command, env = process.env) {
10330
+ if (!path6.isAbsolute(command))
10331
+ return env;
10332
+ return prependPath(path6.dirname(command), env);
10333
+ }
10334
+ function prependNodePath(env = process.env, nodeExecutable = process.execPath) {
10335
+ return prependPath(path6.dirname(nodeExecutable), env);
10336
+ }
10337
+ function prependPath(directory, env) {
10338
+ const pathKey = Object.keys(env).find((key) => key.toLowerCase() === "path") || "PATH";
10339
+ const inherited = env[pathKey] || "";
10340
+ const entries = inherited.split(path6.delimiter).filter(Boolean);
10341
+ if (entries.includes(directory))
10342
+ return env;
10343
+ return { ...env, [pathKey]: [directory, ...entries].join(path6.delimiter) };
10236
10344
  }
10237
10345
 
10238
10346
  // src/agent/executable-resolver.ts
@@ -10306,11 +10414,11 @@ function probeAgentExecutable(executable, options) {
10306
10414
  return new Promise((resolve) => {
10307
10415
  let settled = false;
10308
10416
  let stderr = "";
10309
- const launch = agentSpawnCommand(executable, options.args);
10310
- const child = spawn4(launch.command, launch.args, {
10417
+ const launch = resolveSpawnCommand(executable, options.args);
10418
+ const child = spawn5(launch.command, launch.args, {
10311
10419
  stdio: ["ignore", "ignore", "pipe"],
10312
10420
  windowsHide: true,
10313
- env: createAgentChildEnv()
10421
+ env: prependNodePath()
10314
10422
  });
10315
10423
  const finish = (error48) => {
10316
10424
  if (settled) return;
@@ -10337,8 +10445,8 @@ function probeAgentExecutable(executable, options) {
10337
10445
  }
10338
10446
  function isExecutableFile(candidate) {
10339
10447
  try {
10340
- fs5.accessSync(candidate, process.platform === "win32" ? fs5.constants.F_OK : fs5.constants.X_OK);
10341
- return fs5.statSync(candidate).isFile();
10448
+ fs6.accessSync(candidate, process.platform === "win32" ? fs6.constants.F_OK : fs6.constants.X_OK);
10449
+ return fs6.statSync(candidate).isFile();
10342
10450
  } catch {
10343
10451
  return false;
10344
10452
  }
@@ -10433,7 +10541,7 @@ function externalOpenCommand(url2, platform = process.platform) {
10433
10541
  function openExternalUrl(url2) {
10434
10542
  const { command, args } = externalOpenCommand(url2);
10435
10543
  return new Promise((resolve, reject) => {
10436
- const child = spawn5(command, args, { stdio: "ignore", windowsHide: true });
10544
+ const child = spawn6(command, args, { stdio: "ignore", windowsHide: true });
10437
10545
  child.once("error", (error48) => {
10438
10546
  reject(new Error(`Unable to open Codex App: ${error48.message}`));
10439
10547
  });
@@ -10664,10 +10772,10 @@ var CodexAgentProvider = class {
10664
10772
  throw new Error(resolution.error);
10665
10773
  }
10666
10774
  const { executable } = resolution;
10667
- const launch = agentSpawnCommand(executable, ["app-server", "--listen", "stdio://"]);
10668
- const childEnv = createAgentChildEnv();
10775
+ const launch = resolveSpawnCommand(executable, ["app-server", "--listen", "stdio://"]);
10776
+ const childEnv = prependNodePath();
10669
10777
  if (this.mearlSocketPath) childEnv.MEARL_SOCKET_PATH = this.mearlSocketPath;
10670
- const child = spawn5(launch.command, launch.args, {
10778
+ const child = spawn6(launch.command, launch.args, {
10671
10779
  stdio: ["pipe", "pipe", "pipe"],
10672
10780
  windowsHide: true,
10673
10781
  env: childEnv
@@ -10846,10 +10954,10 @@ var CodexAgentProvider = class {
10846
10954
  };
10847
10955
 
10848
10956
  // src/agent/qoder-provider.ts
10849
- import fs6 from "node:fs";
10957
+ import fs7 from "node:fs";
10850
10958
  import os4 from "node:os";
10851
10959
  import path8 from "node:path";
10852
- import { spawn as spawn6 } from "node:child_process";
10960
+ import { spawn as spawn7 } from "node:child_process";
10853
10961
  import { Readable, Writable } from "node:stream";
10854
10962
 
10855
10963
  // ../../node_modules/.pnpm/@agentclientprotocol+sdk@1.2.1_zod@4.3.6/node_modules/@agentclientprotocol/sdk/dist/schema/index.js
@@ -11671,10 +11779,10 @@ function mergeDefs(...defs) {
11671
11779
  function cloneDef(schema) {
11672
11780
  return mergeDefs(schema._zod.def);
11673
11781
  }
11674
- function getElementAtPath(obj, path12) {
11675
- if (!path12)
11782
+ function getElementAtPath(obj, path13) {
11783
+ if (!path13)
11676
11784
  return obj;
11677
- return path12.reduce((acc, key) => acc?.[key], obj);
11785
+ return path13.reduce((acc, key) => acc?.[key], obj);
11678
11786
  }
11679
11787
  function promiseAllObject(promisesObj) {
11680
11788
  const keys = Object.keys(promisesObj);
@@ -12057,11 +12165,11 @@ function aborted(x, startIndex = 0) {
12057
12165
  }
12058
12166
  return false;
12059
12167
  }
12060
- function prefixIssues(path12, issues) {
12168
+ function prefixIssues(path13, issues) {
12061
12169
  return issues.map((iss) => {
12062
12170
  var _a2;
12063
12171
  (_a2 = iss).path ?? (_a2.path = []);
12064
- iss.path.unshift(path12);
12172
+ iss.path.unshift(path13);
12065
12173
  return iss;
12066
12174
  });
12067
12175
  }
@@ -12244,7 +12352,7 @@ function formatError(error48, mapper = (issue2) => issue2.message) {
12244
12352
  }
12245
12353
  function treeifyError(error48, mapper = (issue2) => issue2.message) {
12246
12354
  const result = { errors: [] };
12247
- const processError = (error49, path12 = []) => {
12355
+ const processError = (error49, path13 = []) => {
12248
12356
  var _a2, _b;
12249
12357
  for (const issue2 of error49.issues) {
12250
12358
  if (issue2.code === "invalid_union" && issue2.errors.length) {
@@ -12254,7 +12362,7 @@ function treeifyError(error48, mapper = (issue2) => issue2.message) {
12254
12362
  } else if (issue2.code === "invalid_element") {
12255
12363
  processError({ issues: issue2.issues }, issue2.path);
12256
12364
  } else {
12257
- const fullpath = [...path12, ...issue2.path];
12365
+ const fullpath = [...path13, ...issue2.path];
12258
12366
  if (fullpath.length === 0) {
12259
12367
  result.errors.push(mapper(issue2));
12260
12368
  continue;
@@ -12286,8 +12394,8 @@ function treeifyError(error48, mapper = (issue2) => issue2.message) {
12286
12394
  }
12287
12395
  function toDotPath(_path) {
12288
12396
  const segs = [];
12289
- const path12 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
12290
- for (const seg of path12) {
12397
+ const path13 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
12398
+ for (const seg of path13) {
12291
12399
  if (typeof seg === "number")
12292
12400
  segs.push(`[${seg}]`);
12293
12401
  else if (typeof seg === "symbol")
@@ -24264,13 +24372,13 @@ function resolveRef(ref, ctx) {
24264
24372
  if (!ref.startsWith("#")) {
24265
24373
  throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
24266
24374
  }
24267
- const path12 = ref.slice(1).split("/").filter(Boolean);
24268
- if (path12.length === 0) {
24375
+ const path13 = ref.slice(1).split("/").filter(Boolean);
24376
+ if (path13.length === 0) {
24269
24377
  return ctx.rootSchema;
24270
24378
  }
24271
24379
  const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
24272
- if (path12[0] === defsKey) {
24273
- const key = path12[1];
24380
+ if (path13[0] === defsKey) {
24381
+ const key = path13[1];
24274
24382
  if (!key || !ctx.defs[key]) {
24275
24383
  throw new Error(`Reference not found: ${ref}`);
24276
24384
  }
@@ -28198,7 +28306,7 @@ function parseQoderSkillsList(output, cwd, home = os4.homedir()) {
28198
28306
  function qoderManagedExecutableCandidates(home) {
28199
28307
  const directory = path8.join(home, ".qoder", "bin", "qodercli");
28200
28308
  try {
28201
- return fs6.readdirSync(directory, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.startsWith("qodercli-")).sort((left, right) => right.name.localeCompare(left.name, void 0, { numeric: true })).map((entry) => path8.join(directory, entry.name));
28309
+ return fs7.readdirSync(directory, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.startsWith("qodercli-")).sort((left, right) => right.name.localeCompare(left.name, void 0, { numeric: true })).map((entry) => path8.join(directory, entry.name));
28202
28310
  } catch {
28203
28311
  return [];
28204
28312
  }
@@ -28618,11 +28726,11 @@ ${message}` : message;
28618
28726
  throw new Error(resolution.error);
28619
28727
  }
28620
28728
  const { executable } = resolution;
28621
- const launch = agentSpawnCommand(executable, ["--acp"]);
28622
- const child = spawn6(launch.command, launch.args, {
28729
+ const launch = resolveSpawnCommand(executable, ["--acp"]);
28730
+ const child = spawn7(launch.command, launch.args, {
28623
28731
  stdio: ["pipe", "pipe", "pipe"],
28624
28732
  windowsHide: true,
28625
- env: createAgentChildEnv()
28733
+ env: prependNodePath()
28626
28734
  });
28627
28735
  this.process = child;
28628
28736
  child.stderr.on("data", (chunk) => {
@@ -28965,12 +29073,12 @@ ${message}` : message;
28965
29073
  }
28966
29074
  runSkillsList(executable, cwd) {
28967
29075
  return new Promise((resolve, reject) => {
28968
- const launch = agentSpawnCommand(executable, ["skill", "list", "--all"]);
28969
- const child = spawn6(launch.command, launch.args, {
29076
+ const launch = resolveSpawnCommand(executable, ["skill", "list", "--all"]);
29077
+ const child = spawn7(launch.command, launch.args, {
28970
29078
  cwd,
28971
29079
  stdio: ["ignore", "pipe", "pipe"],
28972
29080
  windowsHide: true,
28973
- env: createAgentChildEnv()
29081
+ env: prependNodePath()
28974
29082
  });
28975
29083
  let stdout = "";
28976
29084
  let stderr = "";
@@ -29004,16 +29112,16 @@ ${message}` : message;
29004
29112
  return this.executableResolver.resolve();
29005
29113
  }
29006
29114
  resolveExecutableCandidates() {
29007
- const executableNames = process.platform === "win32" ? ["qodercli.exe", "qodercli.cmd"] : ["qodercli"];
29115
+ const executableNames2 = process.platform === "win32" ? ["qodercli.exe", "qodercli.cmd"] : ["qodercli"];
29008
29116
  const configured = process.env.MEARL_QODER_PATH;
29009
29117
  const home = os4.homedir();
29010
- const pathCandidates = (process.env.PATH || "").split(path8.delimiter).filter(Boolean).flatMap((dir) => executableNames.map((name) => path8.join(dir, name)));
29118
+ const pathCandidates = (process.env.PATH || "").split(path8.delimiter).filter(Boolean).flatMap((dir) => executableNames2.map((name) => path8.join(dir, name)));
29011
29119
  return executableFileCandidates([
29012
29120
  configured,
29013
- ...executableNames.map((name) => path8.join(path8.dirname(process.execPath), name)),
29014
- ...executableNames.map((name) => path8.join(home, ".local", "bin", name)),
29121
+ ...executableNames2.map((name) => path8.join(path8.dirname(process.execPath), name)),
29122
+ ...executableNames2.map((name) => path8.join(home, ".local", "bin", name)),
29015
29123
  ...qoderManagedExecutableCandidates(home),
29016
- ...executableNames.map((name) => path8.join(home, ".qoder", "bin", name)),
29124
+ ...executableNames2.map((name) => path8.join(home, ".qoder", "bin", name)),
29017
29125
  ...process.platform === "win32" ? [] : ["/opt/homebrew/bin/qodercli", "/usr/local/bin/qodercli", "/usr/bin/qodercli"],
29018
29126
  ...pathCandidates
29019
29127
  ]);
@@ -29023,70 +29131,65 @@ ${message}` : message;
29023
29131
  }
29024
29132
  };
29025
29133
 
29026
- // src/agent/skill-manager.ts
29027
- import fs7 from "node:fs";
29134
+ // ../setup/dist/aliSkills.js
29135
+ import fs8 from "node:fs";
29028
29136
  import os5 from "node:os";
29029
29137
  import path9 from "node:path";
29030
- import { spawn as spawn7 } from "node:child_process";
29138
+ import { spawn as spawn8 } from "node:child_process";
29031
29139
  var COMMAND_TIMEOUT_MS = 12e4;
29032
29140
  var MAX_OUTPUT_LENGTH = 1e6;
29033
29141
  var ANSI_ESCAPE_PATTERN = new RegExp(String.raw`\u001B\[[0-?]*[ -/]*[@-~]`, "g");
29034
- var SETUP_COMMAND = "npm install -g ali-skills";
29035
- function existingExecutable(candidates) {
29036
- for (const candidate of candidates) {
29037
- if (!candidate) continue;
29038
- try {
29039
- fs7.accessSync(
29040
- candidate,
29041
- process.platform === "win32" ? fs7.constants.F_OK : fs7.constants.X_OK
29042
- );
29043
- return candidate;
29044
- } catch {
29045
- }
29046
- }
29047
- return null;
29142
+ function existingExecutable(candidates, existsSync4) {
29143
+ return candidates.find((candidate) => candidate && existsSync4(candidate)) ?? null;
29048
29144
  }
29049
- function versionManagerCandidates(home, executableNames) {
29145
+ function versionManagerCandidates(home, executableNames2, readdirSync2) {
29050
29146
  const roots = [
29051
29147
  path9.join(home, ".nvm", "versions", "node"),
29052
29148
  path9.join(home, ".fnm", "node-versions")
29053
29149
  ];
29054
29150
  return roots.flatMap((root) => {
29055
29151
  try {
29056
- return fs7.readdirSync(root, { withFileTypes: true }).filter((entry) => entry.isDirectory()).sort((left, right) => right.name.localeCompare(left.name, void 0, { numeric: true })).flatMap(
29057
- (entry) => executableNames.flatMap((name) => [
29058
- path9.join(root, entry.name, "bin", name),
29059
- path9.join(root, entry.name, "installation", "bin", name)
29060
- ])
29061
- );
29152
+ return readdirSync2(root, { withFileTypes: true }).filter((entry) => entry.isDirectory()).sort((left, right) => right.name.localeCompare(left.name, void 0, { numeric: true })).flatMap((entry) => executableNames2.flatMap((name) => [
29153
+ path9.join(root, entry.name, "bin", name),
29154
+ path9.join(root, entry.name, "installation", "bin", name)
29155
+ ]));
29062
29156
  } catch {
29063
29157
  return [];
29064
29158
  }
29065
29159
  });
29066
29160
  }
29067
- function resolveAliSkillsExecutable() {
29068
- const executableNames = process.platform === "win32" ? ["ali-skills.cmd", "ali-skills.exe", "ali-skills"] : ["ali-skills"];
29069
- const home = os5.homedir();
29070
- const pathCandidates = (process.env.PATH || "").split(path9.delimiter).filter(Boolean).flatMap((directory) => executableNames.map((name) => path9.join(directory, name)));
29161
+ function stripAnsi(value) {
29162
+ return value.replace(ANSI_ESCAPE_PATTERN, "");
29163
+ }
29164
+ function resolveAliSkillsExecutable(options = {}) {
29165
+ const env = options.env ?? process.env;
29166
+ const home = (options.homedir ?? os5.homedir)();
29167
+ const platform = options.platform ?? process.platform;
29168
+ const existsSync4 = options.existsSync ?? ((candidate) => isExecutable(candidate, platform));
29169
+ const processExecPath = options.processExecPath ?? process.execPath;
29170
+ const readdirSync2 = options.readdirSync ?? fs8.readdirSync;
29171
+ const names = executableNames("ali-skills", platform);
29172
+ const pathKey = Object.keys(env).find((key) => key.toLowerCase() === "path") || "PATH";
29173
+ const pathCandidates = (env[pathKey] || "").split(path9.delimiter).filter(Boolean).flatMap((directory) => names.map((name) => path9.join(directory, name)));
29071
29174
  const candidates = [
29072
- process.env.MEARL_ALI_SKILLS_PATH,
29073
- ...executableNames.map((name) => path9.join(path9.dirname(process.execPath), name)),
29074
- ...executableNames.map((name) => path9.join(home, ".local", "bin", name)),
29075
- ...executableNames.map((name) => path9.join(home, ".npm-global", "bin", name)),
29076
- ...executableNames.map((name) => path9.join(home, ".volta", "bin", name)),
29077
- ...executableNames.map((name) => path9.join(home, ".local", "share", "pnpm", name)),
29078
- ...executableNames.map((name) => path9.join(home, "Library", "pnpm", name)),
29079
- ...versionManagerCandidates(home, executableNames),
29080
- ...process.platform === "win32" ? [] : ["/opt/homebrew/bin/ali-skills", "/usr/local/bin/ali-skills", "/usr/bin/ali-skills"],
29175
+ env.MEARL_ALI_SKILLS_PATH,
29176
+ ...names.map((name) => path9.join(path9.dirname(processExecPath), name)),
29177
+ ...names.map((name) => path9.join(home, ".local", "bin", name)),
29178
+ ...names.map((name) => path9.join(home, ".npm-global", "bin", name)),
29179
+ ...names.map((name) => path9.join(home, ".volta", "bin", name)),
29180
+ ...names.map((name) => path9.join(home, ".local", "share", "pnpm", name)),
29181
+ ...names.map((name) => path9.join(home, "Library", "pnpm", name)),
29182
+ ...versionManagerCandidates(home, names, readdirSync2),
29183
+ ...platform === "win32" ? [] : ["/opt/homebrew/bin/ali-skills", "/usr/local/bin/ali-skills", "/usr/bin/ali-skills"],
29081
29184
  ...pathCandidates
29082
29185
  ];
29083
- return existingExecutable(candidates);
29186
+ return existingExecutable(candidates, existsSync4);
29084
29187
  }
29085
- var runSkillCli = (executable, args, cwd) => new Promise((resolve, reject) => {
29086
- const launch = agentSpawnCommand(executable, args);
29087
- const child = spawn7(launch.command, launch.args, {
29188
+ var runAliSkillsCli = (executable, args, cwd) => new Promise((resolve, reject) => {
29189
+ const launch = resolveSpawnCommand(executable, args);
29190
+ const child = spawn8(launch.command, launch.args, {
29088
29191
  cwd,
29089
- env: createAgentChildEnv(),
29192
+ env: prependNodePath(prependCommandPath(executable)),
29090
29193
  stdio: ["ignore", "pipe", "pipe"],
29091
29194
  windowsHide: true
29092
29195
  });
@@ -29095,11 +29198,14 @@ var runSkillCli = (executable, args, cwd) => new Promise((resolve, reject) => {
29095
29198
  let settled = false;
29096
29199
  const append = (current, chunk) => current.length >= MAX_OUTPUT_LENGTH ? current : (current + chunk.toString("utf8")).slice(0, MAX_OUTPUT_LENGTH);
29097
29200
  const finish = (error48) => {
29098
- if (settled) return;
29201
+ if (settled)
29202
+ return;
29099
29203
  settled = true;
29100
29204
  clearTimeout(timer);
29101
- if (error48) reject(error48);
29102
- else resolve({ stdout, stderr });
29205
+ if (error48)
29206
+ reject(error48);
29207
+ else
29208
+ resolve({ stdout, stderr });
29103
29209
  };
29104
29210
  const timer = setTimeout(() => {
29105
29211
  child.kill("SIGTERM");
@@ -29117,9 +29223,10 @@ var runSkillCli = (executable, args, cwd) => new Promise((resolve, reject) => {
29117
29223
  finish(new Error(detail || `Ali Skills command exited with code ${String(code)}`));
29118
29224
  });
29119
29225
  });
29120
- function stripAnsi(value) {
29121
- return value.replace(ANSI_ESCAPE_PATTERN, "");
29122
- }
29226
+
29227
+ // src/agent/skill-manager.ts
29228
+ var SETUP_COMMAND = "npm install -g ali-skills";
29229
+ var runSkillCli = runAliSkillsCli;
29123
29230
  function validateProvider(value) {
29124
29231
  if (value !== "codex" && value !== "qoder") {
29125
29232
  throw new Error("Skill provider must be codex or qoder");
@@ -29304,7 +29411,7 @@ var CDP_PORT = positivePort(cliOption("--cdp-port"), 9222);
29304
29411
  var CDP_USER_DATA_DIR = cliOption("--cdp-user-data-dir");
29305
29412
  var CDP_BROWSER_ID = cliOption("--browser-id") ?? "cdp";
29306
29413
  var CDP_BROWSER_NAME = cliOption("--browser-name") ?? "CDP";
29307
- if (cliArg === "--init") {
29414
+ if (cliArg === "--init" || cliArg === "--uninstall") {
29308
29415
  const { runCli: runCli2 } = await Promise.resolve().then(() => (init_install(), install_exports));
29309
29416
  await runCli2(process.argv.slice(2));
29310
29417
  process.exit(0);
@@ -29323,6 +29430,8 @@ Options:
29323
29430
  --init [--mode <skills|mcp|both>] [--extension-id <id>]
29324
29431
  Initialize Native Messaging Host
29325
29432
  (default: both — installs the Skills and MCP hosts)
29433
+ --uninstall [--mode <skills|mcp|both>]
29434
+ Remove Native Messaging Host registration
29326
29435
  --daemon Start as standalone CDP daemon (no extension needed)
29327
29436
  --cdp-port <port> CDP port for daemon mode (default 9222)
29328
29437
  --cdp-user-data-dir <dir> Read DevToolsActivePort from this Chrome profile
@@ -29340,17 +29449,18 @@ Connection modes (auto-detected at runtime):
29340
29449
  Examples:
29341
29450
  mearl-native-host --init
29342
29451
  mearl-native-host --init --mode skills
29452
+ mearl-native-host --uninstall --mode skills
29343
29453
  mearl-native-host --init --extension-id abcdefghijklmnopqrstuvwxyzabcdef
29344
29454
  mearl-native-host --daemon
29345
29455
  mearl-native-host --version`);
29346
29456
  process.exit(0);
29347
29457
  }
29348
29458
  function socketPathFor(suffix) {
29349
- return process.platform === "win32" ? `\\\\.\\pipe\\mearl-agent${suffix}` : path11.join(os7.tmpdir(), `mearl-agent${suffix}.sock`);
29459
+ return process.platform === "win32" ? `\\\\.\\pipe\\mearl-agent${suffix}` : path12.join(os7.tmpdir(), `mearl-agent${suffix}.sock`);
29350
29460
  }
29351
29461
  var LEGACY_SOCKET_PATH = socketPathFor("");
29352
29462
  var INSTANCE_SOCKET_PATH = socketPathFor(`-${process.pid}`);
29353
- var LOG_FILE = path11.join(os7.tmpdir(), "mearl-native-host.log");
29463
+ var LOG_FILE = path12.join(os7.tmpdir(), "mearl-native-host.log");
29354
29464
  var DEFAULT_TIMEOUT_MS = 15e3;
29355
29465
  var INVENTORY_IDLE_EXIT_MS = 1e3;
29356
29466
  var MAX_SOCKET_BUFFER_SIZE = 64 * 1024 * 1024;
@@ -29449,7 +29559,7 @@ function log(...args) {
29449
29559
  const msg = `[${(/* @__PURE__ */ new Date()).toISOString()}] [NativeHost] ${args.join(" ")}
29450
29560
  `;
29451
29561
  try {
29452
- fs9.appendFileSync(LOG_FILE, msg);
29562
+ fs11.appendFileSync(LOG_FILE, msg);
29453
29563
  } catch {
29454
29564
  }
29455
29565
  }
@@ -29983,7 +30093,7 @@ function onSocketConnection(socket) {
29983
30093
  }
29984
30094
  function isPathAlive(socketPath) {
29985
30095
  return new Promise((resolve) => {
29986
- if (process.platform !== "win32" && !fs9.existsSync(socketPath)) {
30096
+ if (process.platform !== "win32" && !fs11.existsSync(socketPath)) {
29987
30097
  resolve(false);
29988
30098
  return;
29989
30099
  }
@@ -30006,9 +30116,9 @@ function isPathAlive(socketPath) {
30006
30116
  }
30007
30117
  function listenOn(socketPath) {
30008
30118
  return new Promise((resolve, reject) => {
30009
- if (process.platform !== "win32" && fs9.existsSync(socketPath)) {
30119
+ if (process.platform !== "win32" && fs11.existsSync(socketPath)) {
30010
30120
  try {
30011
- fs9.unlinkSync(socketPath);
30121
+ fs11.unlinkSync(socketPath);
30012
30122
  } catch {
30013
30123
  }
30014
30124
  }
@@ -30017,11 +30127,11 @@ function listenOn(socketPath) {
30017
30127
  server.listen(socketPath, () => {
30018
30128
  if (process.platform !== "win32") {
30019
30129
  try {
30020
- fs9.chmodSync(socketPath, 384);
30130
+ fs11.chmodSync(socketPath, 384);
30021
30131
  } catch (error48) {
30022
30132
  server.close();
30023
30133
  try {
30024
- fs9.unlinkSync(socketPath);
30134
+ fs11.unlinkSync(socketPath);
30025
30135
  } catch {
30026
30136
  }
30027
30137
  reject(error48);
@@ -30057,7 +30167,7 @@ function releaseLegacySocket() {
30057
30167
  }
30058
30168
  if (process.platform !== "win32") {
30059
30169
  try {
30060
- if (fs9.existsSync(LEGACY_SOCKET_PATH)) fs9.unlinkSync(LEGACY_SOCKET_PATH);
30170
+ if (fs11.existsSync(LEGACY_SOCKET_PATH)) fs11.unlinkSync(LEGACY_SOCKET_PATH);
30061
30171
  } catch {
30062
30172
  }
30063
30173
  }
@@ -30069,8 +30179,8 @@ async function startSocketServer() {
30069
30179
  function cleanupInstanceSocketFile() {
30070
30180
  if (process.platform === "win32") return;
30071
30181
  try {
30072
- if (fs9.existsSync(INSTANCE_SOCKET_PATH)) {
30073
- fs9.unlinkSync(INSTANCE_SOCKET_PATH);
30182
+ if (fs11.existsSync(INSTANCE_SOCKET_PATH)) {
30183
+ fs11.unlinkSync(INSTANCE_SOCKET_PATH);
30074
30184
  }
30075
30185
  } catch (error48) {
30076
30186
  log("cleanup socket file failed:", String(error48));