@introspection-ai/recipes 0.25.0 → 0.26.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. package/dist/mcp-chunks/{auth-command-4WFRNU2I.js → auth-command-JBYNHHMV.js} +23 -27
  2. package/dist/mcp-chunks/call-arguments-S4EGFKUQ.js +15 -0
  3. package/dist/mcp-chunks/{call-command-JBIKXOGC.js → call-command-467BVXTE.js} +32 -33
  4. package/dist/mcp-chunks/{chunk-IPNSPKQK.js → chunk-3Q2Q7SBU.js} +12 -14
  5. package/dist/mcp-chunks/chunk-66P5FXP3.js +31 -0
  6. package/dist/mcp-chunks/{chunk-TF2YTYE4.js → chunk-6DVS7RBO.js} +1 -1
  7. package/dist/mcp-chunks/{chunk-IME7DGLJ.js → chunk-AK5ZEDEF.js} +2 -2
  8. package/dist/mcp-chunks/{chunk-OP3IW2V6.js → chunk-AP5VHS73.js} +2 -2
  9. package/dist/mcp-chunks/{chunk-B2LNXGAP.js → chunk-AS27BTCS.js} +1 -1
  10. package/dist/mcp-chunks/{chunk-MOEZ43ZL.js → chunk-BC2HDCYV.js} +1 -1
  11. package/dist/mcp-chunks/{chunk-RSTKSBVF.js → chunk-BSCNF4NY.js} +2 -2
  12. package/dist/mcp-chunks/chunk-BTU34BUG.js +1182 -0
  13. package/dist/mcp-chunks/{chunk-HN7WPMCA.js → chunk-CN5YF3IQ.js} +21042 -3688
  14. package/dist/mcp-chunks/{chunk-G6OMDUNG.js → chunk-CZ43ZITK.js} +1 -1
  15. package/dist/mcp-chunks/{chunk-JG4TRUPF.js → chunk-D2P2IV4H.js} +1 -1
  16. package/dist/mcp-chunks/{chunk-3R2WK3NB.js → chunk-DMBE47LM.js} +6 -6
  17. package/dist/mcp-chunks/{chunk-WTMJMM3B.js → chunk-EP22XMWK.js} +3 -30
  18. package/dist/mcp-chunks/{chunk-ITCCROID.js → chunk-EUDC3ICZ.js} +5 -5
  19. package/dist/mcp-chunks/{chunk-FX5NYWBH.js → chunk-G4H535MI.js} +3 -21
  20. package/dist/mcp-chunks/{chunk-HCOKLSOB.js → chunk-GA4ZYSRX.js} +4 -4
  21. package/dist/mcp-chunks/{chunk-C2KNLFZR.js → chunk-GEVQ2GJW.js} +2 -2
  22. package/dist/mcp-chunks/{chunk-WYLHHXI6.js → chunk-GK4LA4E6.js} +26 -11
  23. package/dist/mcp-chunks/{chunk-QZUC2T72.js → chunk-GL4AA5QV.js} +2 -2
  24. package/dist/mcp-chunks/{chunk-KW3ANJ36.js → chunk-HBN3ESMH.js} +4 -4
  25. package/dist/mcp-chunks/{chunk-ELA77TDC.js → chunk-HKZZGSDV.js} +4 -4
  26. package/dist/mcp-chunks/{chunk-36VIJRYY.js → chunk-HTXQPQPB.js} +4 -4
  27. package/dist/mcp-chunks/{chunk-3JGS7LQB.js → chunk-I7JR2GIC.js} +2 -2
  28. package/dist/mcp-chunks/{chunk-AIKLVBYU.js → chunk-IO2IMWYS.js} +2 -2
  29. package/dist/mcp-chunks/{chunk-RD7NHCRK.js → chunk-J2WP6ERZ.js} +39 -42
  30. package/dist/mcp-chunks/{chunk-HLRCUHNO.js → chunk-KJNNO5Z6.js} +1 -1
  31. package/dist/mcp-chunks/{chunk-4ZNBWL65.js → chunk-L2LGMX5P.js} +2 -2
  32. package/dist/mcp-chunks/chunk-LG3GLOSA.js +513 -0
  33. package/dist/mcp-chunks/{chunk-CZKDJZER.js → chunk-LTR626QF.js} +1 -1
  34. package/dist/mcp-chunks/{chunk-FS5JIKT6.js → chunk-LYWEATXZ.js} +6 -6
  35. package/dist/mcp-chunks/{chunk-YIRGLKDA.js → chunk-M62ESEOY.js} +45 -14
  36. package/dist/mcp-chunks/{chunk-V5AYEKSL.js → chunk-MJHMXYMO.js} +52 -81
  37. package/dist/mcp-chunks/{chunk-7WOKCV6Q.js → chunk-N7ZWX3WW.js} +1 -1
  38. package/dist/mcp-chunks/chunk-NTABJCUL.js +123 -0
  39. package/dist/mcp-chunks/{chunk-EPT4MYOF.js → chunk-OABFKFSL.js} +11 -11
  40. package/dist/mcp-chunks/{chunk-SCOMDV54.js → chunk-OB256NMD.js} +1 -1
  41. package/dist/mcp-chunks/{chunk-IYWYVHHD.js → chunk-OZQTZWW4.js} +1 -1
  42. package/dist/mcp-chunks/{chunk-ITR7FQM3.js → chunk-QIBGY4IX.js} +2 -2
  43. package/dist/mcp-chunks/{chunk-ZOAQDFAO.js → chunk-REEFOL44.js} +1 -1
  44. package/dist/mcp-chunks/{chunk-ED2WN5BI.js → chunk-SUNOYTQJ.js} +3 -3
  45. package/dist/mcp-chunks/{chunk-Y3EDWN2P.js → chunk-TFU4NKFJ.js} +1 -1
  46. package/dist/mcp-chunks/{chunk-EMSNQHZZ.js → chunk-TGPIW6F6.js} +1 -1
  47. package/dist/mcp-chunks/{chunk-SNKXMWDB.js → chunk-UCJ7YDFN.js} +1 -1
  48. package/dist/mcp-chunks/{chunk-TPHPAEDH.js → chunk-WUEDIOR5.js} +1 -1
  49. package/dist/mcp-chunks/{chunk-FAJPJTOC.js → chunk-XCNWICLD.js} +1 -1
  50. package/dist/mcp-chunks/{chunk-6YZW3XAE.js → chunk-XFQSUC7T.js} +5 -5
  51. package/dist/mcp-chunks/{chunk-GQ6NSIDS.js → chunk-Y3L5LWBY.js} +3037 -747
  52. package/dist/mcp-chunks/{chunk-53NRFMB3.js → chunk-YI5SMRFH.js} +46 -25
  53. package/dist/mcp-chunks/{chunk-GUXMP7QB.js → chunk-YPTN46JQ.js} +2 -2
  54. package/dist/mcp-chunks/{chunk-I5GI2A2D.js → chunk-YVH36MGQ.js} +2 -2
  55. package/dist/mcp-chunks/{chunk-ASG4OY3M.js → chunk-Z6QEOUMK.js} +22 -23
  56. package/dist/mcp-chunks/{cli-XU26MUCN.js → cli-TN6JTLTS.js} +108 -77
  57. package/dist/mcp-chunks/client-G33HPQAC.js +29 -0
  58. package/dist/mcp-chunks/{config-command-UQMMIK2U.js → config-command-LICU56ZH.js} +27 -28
  59. package/dist/mcp-chunks/daemon-command-JLVHGWHB.js +29 -0
  60. package/dist/mcp-chunks/{dist-DM2RXZMU.js → dist-MFAWSKGH.js} +80 -46
  61. package/dist/mcp-chunks/{emit-ts-command-KAOL6DAN.js → emit-ts-command-FVX3JMSN.js} +18 -18
  62. package/dist/mcp-chunks/{generate-cli-runner-AK6XNRTK.js → generate-cli-runner-L2L7VMCA.js} +53 -51
  63. package/dist/mcp-chunks/generated-daemon-runtime-DC6IL7E7.js +29 -0
  64. package/dist/mcp-chunks/{inspect-cli-command-6FVJO7H2.js → inspect-cli-command-Y5D3GRE2.js} +9 -10
  65. package/dist/mcp-chunks/{launch-EIT73HX4.js → launch-ZFY6CM2A.js} +1 -1
  66. package/dist/mcp-chunks/{lifecycle-QH4TUI3K.js → lifecycle-H7DIW5DM.js} +1 -1
  67. package/dist/mcp-chunks/{list-command-UOB2XZK7.js → list-command-55LCLW4S.js} +34 -35
  68. package/dist/mcp-chunks/{output-utils-6YXH23T7.js → output-utils-YYHI637S.js} +3 -3
  69. package/dist/mcp-chunks/{prompt-CH6TK0bC-ZB6RFAXR.js → prompt-CH6TK0bC-DZLFAAPK.js} +1 -1
  70. package/dist/mcp-chunks/{record-command-FO5TTERC.js → record-command-PWIBYC5J.js} +5 -5
  71. package/dist/mcp-chunks/{replay-command-SCBPCGQ7.js → replay-command-QHZZZMXF.js} +6 -6
  72. package/dist/mcp-chunks/{resource-command-S2J7XEMV.js → resource-command-HMR2KXWK.js} +9 -10
  73. package/dist/mcp-chunks/{result-utils-OME6HGS6.js → result-utils-UGCQSRJ4.js} +3 -4
  74. package/dist/mcp-chunks/runtime-ZNFPZXKE.js +36 -0
  75. package/dist/mcp-chunks/runtime-wrapper-I4B3OROR.js +10 -0
  76. package/dist/mcp-chunks/{serve-command-DDBZZSG6.js → serve-command-NTDI3YPN.js} +29 -34
  77. package/dist/mcp-chunks/{timeouts-HNGNKDQN.js → timeouts-35UDWFA7.js} +3 -3
  78. package/dist/mcp-chunks/{vault-command-TJZYS3YI.js → vault-command-D5QZL4FI.js} +4 -6
  79. package/dist/mcp-daemon.js +26 -31
  80. package/dist/mcp-run-worker.js +26 -31
  81. package/dist/pi-extension.d.ts.map +1 -1
  82. package/dist/pi-extension.js +27 -0
  83. package/dist/pi-extension.js.map +1 -1
  84. package/docs/pi-extension.md +1 -1
  85. package/docs/recipe-format.md +7 -3
  86. package/docs/recipe-templates.md +46 -0
  87. package/package.json +14 -14
  88. package/dist/mcp-chunks/call-arguments-4DWPBLQP.js +0 -15
  89. package/dist/mcp-chunks/chunk-3Z7MFS6K.js +0 -86
  90. package/dist/mcp-chunks/chunk-AD3FQ73K.js +0 -39
  91. package/dist/mcp-chunks/chunk-BWW4XRUC.js +0 -1931
  92. package/dist/mcp-chunks/chunk-DTZHEVKC.js +0 -12
  93. package/dist/mcp-chunks/chunk-H3JCYHGS.js +0 -1018
  94. package/dist/mcp-chunks/chunk-IRTJXFWA.js +0 -28
  95. package/dist/mcp-chunks/chunk-NTHUNCXJ.js +0 -526
  96. package/dist/mcp-chunks/chunk-OD3MSMXY.js +0 -15
  97. package/dist/mcp-chunks/chunk-PZ323CXI.js +0 -17394
  98. package/dist/mcp-chunks/client-OT34CKRH.js +0 -21
  99. package/dist/mcp-chunks/daemon-command-YCIOZGPZ.js +0 -35
  100. package/dist/mcp-chunks/runtime-QIPMLIJI.js +0 -39
  101. package/dist/mcp-chunks/runtime-wrapper-X4YFKMJI.js +0 -16
@@ -1,43 +1,69 @@
1
1
  import { createRequire as __createRequire } from "node:module"; const require = __createRequire(import.meta.url);
2
+ import {
3
+ stableJsonStringify
4
+ } from "./chunk-AS27BTCS.js";
2
5
  import {
3
6
  NON_INTERACTIVE_ELICITATION_HINT,
4
7
  createNonInteractiveElicitationResponder,
5
8
  registerElicitationHandler
6
- } from "./chunk-ZOAQDFAO.js";
9
+ } from "./chunk-REEFOL44.js";
7
10
  import {
8
11
  RecordTransport,
9
12
  resolveRecordingPath
10
- } from "./chunk-OP3IW2V6.js";
13
+ } from "./chunk-AP5VHS73.js";
11
14
  import {
12
15
  OAuthTimeoutError,
13
16
  connectWithAuth,
14
17
  createOAuthSession,
15
18
  isOAuthFlowError,
16
19
  isPostAuthConnectError,
20
+ isUnauthorizedError,
21
+ maybeEnableOAuth,
17
22
  resolveOAuthTimeoutFromEnv
18
- } from "./chunk-YIRGLKDA.js";
23
+ } from "./chunk-M62ESEOY.js";
19
24
  import {
20
25
  readCachedAccessToken
21
- } from "./chunk-ASG4OY3M.js";
26
+ } from "./chunk-Z6QEOUMK.js";
22
27
  import {
23
- isUnauthorizedError,
24
- maybeEnableOAuth
25
- } from "./chunk-IRTJXFWA.js";
28
+ withRuntimeEnvironment
29
+ } from "./chunk-YI5SMRFH.js";
30
+ import {
31
+ createPrefixedConsoleLogger,
32
+ resolveLogLevelFromEnv
33
+ } from "./chunk-N7ZWX3WW.js";
26
34
  import {
27
35
  STDIO_TRACE_ENABLED,
28
36
  flushStdioLogs,
29
37
  ignoreStdioEmitterError
30
- } from "./chunk-EMSNQHZZ.js";
38
+ } from "./chunk-TGPIW6F6.js";
31
39
  import {
32
40
  MCPORTER_VERSION
33
- } from "./chunk-OD3MSMXY.js";
41
+ } from "./chunk-NTABJCUL.js";
34
42
  import {
35
- createPrefixedConsoleLogger,
36
- resolveLogLevelFromEnv
37
- } from "./chunk-7WOKCV6Q.js";
43
+ normalizeTimeout,
44
+ raceWithTimeout,
45
+ resolveCommandArgument,
46
+ resolveCommandArguments
47
+ } from "./chunk-YVH36MGQ.js";
48
+ import {
49
+ loadServerDefinitions,
50
+ normalizeServerEntry,
51
+ parseTree,
52
+ readConfigFile
53
+ } from "./chunk-J2WP6ERZ.js";
54
+ import {
55
+ pathExists
56
+ } from "./chunk-G4H535MI.js";
57
+ import {
58
+ mcporterConfigCandidates
59
+ } from "./chunk-LYWEATXZ.js";
60
+ import {
61
+ resolveEnvPlaceholders,
62
+ resolveEnvValue
63
+ } from "./chunk-EP22XMWK.js";
38
64
  import {
39
65
  analyzeConnectionError
40
- } from "./chunk-QZUC2T72.js";
66
+ } from "./chunk-GL4AA5QV.js";
41
67
  import {
42
68
  Client,
43
69
  DEFAULT_REQUEST_TIMEOUT_MSEC,
@@ -50,28 +76,7 @@ import {
50
76
  StreamableHTTPClientTransport,
51
77
  serializeMessage,
52
78
  specTypeSchemas
53
- } from "./chunk-PZ323CXI.js";
54
- import {
55
- ChromeDevtoolsRelayRequiredError,
56
- formatChromeDevtoolsRelayDecision,
57
- recordChromeDevtoolsRelayDecision,
58
- resolveChromeDevtoolsAutoConnectCommand,
59
- resolveChromeDevtoolsRelayEnvironment,
60
- rewriteChromeDevtoolsArgsForRelay
61
- } from "./chunk-BWW4XRUC.js";
62
- import {
63
- normalizeTimeout,
64
- raceWithTimeout,
65
- resolveCommandArgument,
66
- resolveCommandArguments
67
- } from "./chunk-I5GI2A2D.js";
68
- import {
69
- loadServerDefinitions
70
- } from "./chunk-RD7NHCRK.js";
71
- import {
72
- resolveEnvPlaceholders,
73
- withEnvOverrides
74
- } from "./chunk-WTMJMM3B.js";
79
+ } from "./chunk-CN5YF3IQ.js";
75
80
  import {
76
81
  __commonJS,
77
82
  __require,
@@ -83,8 +88,8 @@ var require_windows = __commonJS({
83
88
  "node_modules/.pnpm/isexe@2.0.0/node_modules/isexe/windows.js"(exports, module) {
84
89
  module.exports = isexe;
85
90
  isexe.sync = sync;
86
- var fs5 = __require("fs");
87
- function checkPathExt(path4, options) {
91
+ var fs8 = __require("fs");
92
+ function checkPathExt(path9, options) {
88
93
  var pathext = options.pathExt !== void 0 ? options.pathExt : process.env.PATHEXT;
89
94
  if (!pathext) {
90
95
  return true;
@@ -95,25 +100,25 @@ var require_windows = __commonJS({
95
100
  }
96
101
  for (var i = 0; i < pathext.length; i++) {
97
102
  var p = pathext[i].toLowerCase();
98
- if (p && path4.substr(-p.length).toLowerCase() === p) {
103
+ if (p && path9.substr(-p.length).toLowerCase() === p) {
99
104
  return true;
100
105
  }
101
106
  }
102
107
  return false;
103
108
  }
104
- function checkStat(stat, path4, options) {
109
+ function checkStat(stat, path9, options) {
105
110
  if (!stat.isSymbolicLink() && !stat.isFile()) {
106
111
  return false;
107
112
  }
108
- return checkPathExt(path4, options);
113
+ return checkPathExt(path9, options);
109
114
  }
110
- function isexe(path4, options, cb) {
111
- fs5.stat(path4, function(er, stat) {
112
- cb(er, er ? false : checkStat(stat, path4, options));
115
+ function isexe(path9, options, cb) {
116
+ fs8.stat(path9, function(er, stat) {
117
+ cb(er, er ? false : checkStat(stat, path9, options));
113
118
  });
114
119
  }
115
- function sync(path4, options) {
116
- return checkStat(fs5.statSync(path4), path4, options);
120
+ function sync(path9, options) {
121
+ return checkStat(fs8.statSync(path9), path9, options);
117
122
  }
118
123
  }
119
124
  });
@@ -123,14 +128,14 @@ var require_mode = __commonJS({
123
128
  "node_modules/.pnpm/isexe@2.0.0/node_modules/isexe/mode.js"(exports, module) {
124
129
  module.exports = isexe;
125
130
  isexe.sync = sync;
126
- var fs5 = __require("fs");
127
- function isexe(path4, options, cb) {
128
- fs5.stat(path4, function(er, stat) {
131
+ var fs8 = __require("fs");
132
+ function isexe(path9, options, cb) {
133
+ fs8.stat(path9, function(er, stat) {
129
134
  cb(er, er ? false : checkStat(stat, options));
130
135
  });
131
136
  }
132
- function sync(path4, options) {
133
- return checkStat(fs5.statSync(path4), options);
137
+ function sync(path9, options) {
138
+ return checkStat(fs8.statSync(path9), options);
134
139
  }
135
140
  function checkStat(stat, options) {
136
141
  return stat.isFile() && checkMode(stat, options);
@@ -154,7 +159,7 @@ var require_mode = __commonJS({
154
159
  // node_modules/.pnpm/isexe@2.0.0/node_modules/isexe/index.js
155
160
  var require_isexe = __commonJS({
156
161
  "node_modules/.pnpm/isexe@2.0.0/node_modules/isexe/index.js"(exports, module) {
157
- var fs5 = __require("fs");
162
+ var fs8 = __require("fs");
158
163
  var core;
159
164
  if (process.platform === "win32" || global.TESTING_WINDOWS) {
160
165
  core = require_windows();
@@ -163,7 +168,7 @@ var require_isexe = __commonJS({
163
168
  }
164
169
  module.exports = isexe;
165
170
  isexe.sync = sync;
166
- function isexe(path4, options, cb) {
171
+ function isexe(path9, options, cb) {
167
172
  if (typeof options === "function") {
168
173
  cb = options;
169
174
  options = {};
@@ -173,7 +178,7 @@ var require_isexe = __commonJS({
173
178
  throw new TypeError("callback not provided");
174
179
  }
175
180
  return new Promise(function(resolve, reject) {
176
- isexe(path4, options || {}, function(er, is) {
181
+ isexe(path9, options || {}, function(er, is) {
177
182
  if (er) {
178
183
  reject(er);
179
184
  } else {
@@ -182,7 +187,7 @@ var require_isexe = __commonJS({
182
187
  });
183
188
  });
184
189
  }
185
- core(path4, options || {}, function(er, is) {
190
+ core(path9, options || {}, function(er, is) {
186
191
  if (er) {
187
192
  if (er.code === "EACCES" || options && options.ignoreErrors) {
188
193
  er = null;
@@ -192,9 +197,9 @@ var require_isexe = __commonJS({
192
197
  cb(er, is);
193
198
  });
194
199
  }
195
- function sync(path4, options) {
200
+ function sync(path9, options) {
196
201
  try {
197
- return core.sync(path4, options || {});
202
+ return core.sync(path9, options || {});
198
203
  } catch (er) {
199
204
  if (options && options.ignoreErrors || er.code === "EACCES") {
200
205
  return false;
@@ -210,7 +215,7 @@ var require_isexe = __commonJS({
210
215
  var require_which = __commonJS({
211
216
  "node_modules/.pnpm/which@2.0.2/node_modules/which/which.js"(exports, module) {
212
217
  var isWindows = process.platform === "win32" || process.env.OSTYPE === "cygwin" || process.env.OSTYPE === "msys";
213
- var path4 = __require("path");
218
+ var path9 = __require("path");
214
219
  var COLON = isWindows ? ";" : ":";
215
220
  var isexe = require_isexe();
216
221
  var getNotFoundError = (cmd) => Object.assign(new Error(`not found: ${cmd}`), { code: "ENOENT" });
@@ -248,7 +253,7 @@ var require_which = __commonJS({
248
253
  return opt.all && found.length ? resolve(found) : reject(getNotFoundError(cmd));
249
254
  const ppRaw = pathEnv[i];
250
255
  const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw;
251
- const pCmd = path4.join(pathPart, cmd);
256
+ const pCmd = path9.join(pathPart, cmd);
252
257
  const p = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd : pCmd;
253
258
  resolve(subStep(p, i, 0));
254
259
  });
@@ -275,7 +280,7 @@ var require_which = __commonJS({
275
280
  for (let i = 0; i < pathEnv.length; i++) {
276
281
  const ppRaw = pathEnv[i];
277
282
  const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw;
278
- const pCmd = path4.join(pathPart, cmd);
283
+ const pCmd = path9.join(pathPart, cmd);
279
284
  const p = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd : pCmd;
280
285
  for (let j = 0; j < pathExt.length; j++) {
281
286
  const cur = p + pathExt[j];
@@ -323,7 +328,7 @@ var require_path_key = __commonJS({
323
328
  var require_resolveCommand = __commonJS({
324
329
  "node_modules/.pnpm/cross-spawn@7.0.6/node_modules/cross-spawn/lib/util/resolveCommand.js"(exports, module) {
325
330
  "use strict";
326
- var path4 = __require("path");
331
+ var path9 = __require("path");
327
332
  var which = require_which();
328
333
  var getPathKey = require_path_key();
329
334
  function resolveCommandAttempt(parsed, withoutPathExt) {
@@ -341,7 +346,7 @@ var require_resolveCommand = __commonJS({
341
346
  try {
342
347
  resolved = which.sync(parsed.command, {
343
348
  path: env[getPathKey({ env })],
344
- pathExt: withoutPathExt ? path4.delimiter : void 0
349
+ pathExt: withoutPathExt ? path9.delimiter : void 0
345
350
  });
346
351
  } catch (e) {
347
352
  } finally {
@@ -350,7 +355,7 @@ var require_resolveCommand = __commonJS({
350
355
  }
351
356
  }
352
357
  if (resolved) {
353
- resolved = path4.resolve(hasCustomCwd ? parsed.options.cwd : "", resolved);
358
+ resolved = path9.resolve(hasCustomCwd ? parsed.options.cwd : "", resolved);
354
359
  }
355
360
  return resolved;
356
361
  }
@@ -404,8 +409,8 @@ var require_shebang_command = __commonJS({
404
409
  if (!match) {
405
410
  return null;
406
411
  }
407
- const [path4, argument] = match[0].replace(/#! ?/, "").split(" ");
408
- const binary = path4.split("/").pop();
412
+ const [path9, argument] = match[0].replace(/#! ?/, "").split(" ");
413
+ const binary = path9.split("/").pop();
409
414
  if (binary === "env") {
410
415
  return argument;
411
416
  }
@@ -418,16 +423,16 @@ var require_shebang_command = __commonJS({
418
423
  var require_readShebang = __commonJS({
419
424
  "node_modules/.pnpm/cross-spawn@7.0.6/node_modules/cross-spawn/lib/util/readShebang.js"(exports, module) {
420
425
  "use strict";
421
- var fs5 = __require("fs");
426
+ var fs8 = __require("fs");
422
427
  var shebangCommand = require_shebang_command();
423
428
  function readShebang(command) {
424
429
  const size = 150;
425
430
  const buffer = Buffer.alloc(size);
426
431
  let fd;
427
432
  try {
428
- fd = fs5.openSync(command, "r");
429
- fs5.readSync(fd, buffer, 0, size, 0);
430
- fs5.closeSync(fd);
433
+ fd = fs8.openSync(command, "r");
434
+ fs8.readSync(fd, buffer, 0, size, 0);
435
+ fs8.closeSync(fd);
431
436
  } catch (e) {
432
437
  }
433
438
  return shebangCommand(buffer.toString());
@@ -440,7 +445,7 @@ var require_readShebang = __commonJS({
440
445
  var require_parse = __commonJS({
441
446
  "node_modules/.pnpm/cross-spawn@7.0.6/node_modules/cross-spawn/lib/parse.js"(exports, module) {
442
447
  "use strict";
443
- var path4 = __require("path");
448
+ var path9 = __require("path");
444
449
  var resolveCommand = require_resolveCommand();
445
450
  var escape = require_escape();
446
451
  var readShebang = require_readShebang();
@@ -465,7 +470,7 @@ var require_parse = __commonJS({
465
470
  const needsShell = !isExecutableRegExp.test(commandFile);
466
471
  if (parsed.options.forceShell || needsShell) {
467
472
  const needsDoubleEscapeMetaChars = isCmdShimRegExp.test(commandFile);
468
- parsed.command = path4.normalize(parsed.command);
473
+ parsed.command = path9.normalize(parsed.command);
469
474
  parsed.command = escape.command(parsed.command);
470
475
  parsed.args = parsed.args.map((arg) => escape.argument(arg, needsDoubleEscapeMetaChars));
471
476
  const shellCommand = [parsed.command].concat(parsed.args).join(" ");
@@ -555,7 +560,7 @@ var require_cross_spawn = __commonJS({
555
560
  var cp = __require("child_process");
556
561
  var parse = require_parse();
557
562
  var enoent = require_enoent();
558
- function spawn2(command, args, options) {
563
+ function spawn3(command, args, options) {
559
564
  const parsed = parse(command, args, options);
560
565
  const spawned = cp.spawn(parsed.command, parsed.args, parsed.options);
561
566
  enoent.hookChildProcess(spawned, parsed);
@@ -567,178 +572,2651 @@ var require_cross_spawn = __commonJS({
567
572
  result.error = result.error || enoent.verifyENOENTSync(result.status, parsed);
568
573
  return result;
569
574
  }
570
- module.exports = spawn2;
571
- module.exports.spawn = spawn2;
575
+ module.exports = spawn3;
576
+ module.exports.spawn = spawn3;
572
577
  module.exports.sync = spawnSync2;
573
578
  module.exports._parse = parse;
574
579
  module.exports._enoent = enoent;
575
580
  }
576
581
  });
577
582
 
578
- // node_modules/.pnpm/mcporter@0.13.8/node_modules/mcporter/dist/runtime-process-utils.js
579
- import { execFile } from "node:child_process";
580
- async function closeTransportAndWait(logger, transport, options = {}) {
581
- const pidBeforeClose = getTransportPid(transport);
582
- const targetsBeforeClose = pidBeforeClose ? await collectProcessTreePids(pidBeforeClose) : [];
583
- let closeError;
584
- let closeSettled = false;
585
- const closePromise = (options.close ?? (() => transport.close()))().catch((error) => {
586
- closeError = error;
587
- if (!options.throwOnCloseError) {
588
- logger.warn(`Failed to close transport cleanly: ${error.message}`);
583
+ // node_modules/.pnpm/mcporter@0.13.10/node_modules/mcporter/dist/daemon/connection-identity.js
584
+ import { createHash as createHash4 } from "node:crypto";
585
+ import fs2 from "node:fs/promises";
586
+ import path3 from "node:path";
587
+
588
+ // node_modules/.pnpm/mcporter@0.13.10/node_modules/mcporter/dist/chrome-devtools-relay.js
589
+ import { createHash as createHash3 } from "node:crypto";
590
+ import fs from "node:fs";
591
+ import os from "node:os";
592
+ import path2 from "node:path";
593
+
594
+ // node_modules/.pnpm/mcporter@0.13.10/node_modules/mcporter/dist/chrome-devtools-command.js
595
+ var AUTO_CONNECT_FLAGS = /* @__PURE__ */ new Set(["--autoConnect", "--auto-connect"]);
596
+ var NEGATED_AUTO_CONNECT_FLAGS = /* @__PURE__ */ new Set(["--no-autoConnect", "--no-auto-connect"]);
597
+ var CONNECTION_VALUE_FLAGS = /* @__PURE__ */ new Set([
598
+ "--browserUrl",
599
+ "--browser-url",
600
+ "--channel",
601
+ "--executablePath",
602
+ "--executable-path",
603
+ "--userDataDir",
604
+ "--user-data-dir",
605
+ "--wsEndpoint",
606
+ "--ws-endpoint",
607
+ "--wsHeaders",
608
+ "--ws-headers",
609
+ "-e",
610
+ "-u",
611
+ "-w"
612
+ ]);
613
+ var NPX_VALUE_OPTIONS = /* @__PURE__ */ new Set([
614
+ "--cache",
615
+ "--package",
616
+ "--prefix",
617
+ "--registry",
618
+ "--userconfig",
619
+ "--workspace",
620
+ "-p",
621
+ "-w"
622
+ ]);
623
+ var NPX_COMMAND_STRING_OPTIONS = /* @__PURE__ */ new Set(["--call", "-c"]);
624
+ var NPX_NO_VALUE_OPTIONS = /* @__PURE__ */ new Set(["--ignore-existing", "--no-install", "--quiet", "--silent", "--yes", "-y"]);
625
+ var COMMON_WRAPPERS = /* @__PURE__ */ new Set([
626
+ "ash",
627
+ "bash",
628
+ "csh",
629
+ "dash",
630
+ "cmd",
631
+ "doas",
632
+ "env",
633
+ "fish",
634
+ "ksh",
635
+ "mksh",
636
+ "node",
637
+ "npm",
638
+ "npx",
639
+ "bunx",
640
+ "pnpm",
641
+ "powershell",
642
+ "pwsh",
643
+ "sh",
644
+ "sudo",
645
+ "tcsh",
646
+ "yarn",
647
+ "zsh"
648
+ ]);
649
+ function isChromeDevtoolsToken(token) {
650
+ const normalized = token.replaceAll("\\", "/").toLowerCase();
651
+ const basename = normalized.slice(normalized.lastIndexOf("/") + 1);
652
+ return /^chrome-devtools-mcp(?:@[^/]+)?(?:\.(?:bat|cjs|cmd|exe|js|mjs))?$/u.test(basename) || normalized.includes("/chrome-devtools-mcp/") && /\.(?:bat|cjs|cmd|exe|js|mjs)$/u.test(basename);
653
+ }
654
+ function isAmbiguousChromeDevtoolsAutoConnectCommand(command, args) {
655
+ if (isChromeDevtoolsToken(command))
656
+ return false;
657
+ if (isSupportedPackageLauncher(command)) {
658
+ const target = findPackageLauncherTarget(args);
659
+ if (!target)
660
+ return false;
661
+ if (target.ambiguous)
662
+ return true;
663
+ const nestedTarget = commandBasename(args[target.index] ?? "");
664
+ return COMMON_WRAPPERS.has(nestedTarget) && containsChromeAutoConnectInvocation(args.slice(target.index + 1));
665
+ }
666
+ const launcher = commandBasename(command);
667
+ if (COMMON_WRAPPERS.has(launcher))
668
+ return containsChromeAutoConnectInvocation(args);
669
+ const scopedArgs = args.slice(0, optionTerminator(args));
670
+ const tokenIndex = scopedArgs.findIndex(isChromeDevtoolsToken);
671
+ return tokenIndex >= 0 && parseChromeDevtoolsAutoConnectArgs(scopedArgs.slice(tokenIndex + 1)).enabled;
672
+ }
673
+ function resolveChromeDevtoolsAutoConnectCommand(command, args) {
674
+ const target = resolveChromeDevtoolsTarget(command, args);
675
+ if (!target)
676
+ return { enabled: false, withoutAutoConnect: args };
677
+ const parsed = parseChromeDevtoolsAutoConnectArgs(target.args);
678
+ return {
679
+ enabled: parsed.enabled,
680
+ withoutAutoConnect: [...target.prefix, ...parsed.withoutAutoConnect]
681
+ };
682
+ }
683
+ function replaceChromeDevtoolsAutoConnectArgs(command, args, replacement) {
684
+ const target = resolveChromeDevtoolsTarget(command, args);
685
+ if (!target)
686
+ return args;
687
+ const parsed = parseChromeDevtoolsAutoConnectArgs(target.args);
688
+ const stripped = stripConnectionSelectionArgs(parsed.withoutAutoConnect);
689
+ const targetArgs = [...stripped.args];
690
+ targetArgs.splice(stripped.insertionIndex, 0, ...replacement);
691
+ return [...target.prefix, ...targetArgs];
692
+ }
693
+ function resolveChromeDevtoolsTarget(command, args) {
694
+ if (isChromeDevtoolsToken(command))
695
+ return { prefix: [], args };
696
+ if (!isSupportedPackageLauncher(command))
697
+ return void 0;
698
+ const target = findPackageLauncherTarget(args);
699
+ if (!target || target.ambiguous || !isChromeDevtoolsToken(args[target.index] ?? ""))
700
+ return void 0;
701
+ const separatorIndex = target.index + 1;
702
+ const consumesSeparator = target.consumePostTargetSeparator && args[separatorIndex] === "--";
703
+ const targetStart = consumesSeparator ? separatorIndex + 1 : separatorIndex;
704
+ return { prefix: args.slice(0, targetStart), args: args.slice(targetStart) };
705
+ }
706
+ function findPackageLauncherTarget(args) {
707
+ for (let index = 0; index < args.length; index += 1) {
708
+ const arg = args[index];
709
+ if (arg === void 0)
710
+ continue;
711
+ if (arg === "--") {
712
+ return index + 1 < args.length ? { index: index + 1, ambiguous: false, consumePostTargetSeparator: false } : void 0;
589
713
  }
590
- }).finally(() => {
591
- closeSettled = true;
592
- });
593
- if (pidBeforeClose) {
594
- destroyTransportStreams(transport);
595
- await ensureProcessTreeTerminated(logger, pidBeforeClose, targetsBeforeClose);
596
- if (!closeSettled) {
597
- await Promise.race([closePromise, delay(100)]);
714
+ if (arg.startsWith("--call=")) {
715
+ const value = arg.slice("--call=".length);
716
+ return containsInlineChromeAutoConnect([value]) ? { index, ambiguous: true, consumePostTargetSeparator: false } : void 0;
598
717
  }
599
- } else {
600
- await closePromise;
601
- }
602
- if (closeError && options.throwOnCloseError) {
603
- throw closeError;
604
- }
605
- }
606
- function getTransportPid(transport) {
607
- if ("pid" in transport) {
608
- const candidate = transport.pid;
609
- if (typeof candidate === "number" && candidate > 0) {
610
- return candidate;
718
+ if (NPX_COMMAND_STRING_OPTIONS.has(arg)) {
719
+ const value = args[index + 1] ?? "";
720
+ return containsInlineChromeAutoConnect([value]) ? { index: index + 1, ambiguous: true, consumePostTargetSeparator: false } : void 0;
721
+ }
722
+ if (NPX_VALUE_OPTIONS.has(arg)) {
723
+ index += 1;
724
+ continue;
725
+ }
726
+ if (NPX_NO_VALUE_OPTIONS.has(arg) || /^--[^=]+=.+/u.test(arg))
727
+ continue;
728
+ if (arg.startsWith("-")) {
729
+ return {
730
+ index,
731
+ ambiguous: containsChromeAutoConnectInvocation(args.slice(index)),
732
+ consumePostTargetSeparator: false
733
+ };
611
734
  }
735
+ return { index, ambiguous: false, consumePostTargetSeparator: true };
612
736
  }
613
- return null;
737
+ return void 0;
614
738
  }
615
- function isProcessAlive(pid) {
616
- try {
617
- process.kill(pid, 0);
618
- return true;
619
- } catch {
620
- return false;
621
- }
739
+ function isSupportedPackageLauncher(command) {
740
+ const launcher = commandBasename(command);
741
+ return launcher === "npx" || launcher === "bunx";
622
742
  }
623
- async function ensureProcessTreeTerminated(logger, rootPid, capturedTargets = []) {
624
- let targets = uniquePids([...capturedTargets, ...await collectProcessTreePids(rootPid)]);
625
- if (targets.length === 0 || await waitForTreeExit(targets, 700)) {
626
- return;
627
- }
628
- await sendSignalToTargets(targets, "SIGTERM");
629
- targets = uniquePids([...targets, ...await collectProcessTreePids(rootPid)]);
630
- if (await waitForTreeExit(targets, 700)) {
631
- return;
632
- }
633
- targets = uniquePids([...targets, ...await collectProcessTreePids(rootPid)]);
634
- await sendSignalToTargets(targets, "SIGKILL");
635
- if (await waitForTreeExit(targets, 500)) {
636
- return;
637
- }
638
- logger.warn(`Process tree rooted at pid=${rootPid} did not exit after SIGKILL.`);
743
+ function containsChromeAutoConnectInvocation(args) {
744
+ const tokenIndex = args.findIndex(isChromeDevtoolsToken);
745
+ if (tokenIndex >= 0)
746
+ return parseChromeDevtoolsAutoConnectArgs(args.slice(tokenIndex + 1)).enabled;
747
+ return containsInlineChromeAutoConnect(args);
639
748
  }
640
- function uniquePids(pids) {
641
- return [...new Set(pids.filter((pid) => Number.isInteger(pid) && pid > 0))];
749
+ function containsInlineChromeAutoConnect(args) {
750
+ const rendered = args.join(" ").toLowerCase();
751
+ return rendered.includes("chrome-devtools-mcp") && /--(?:auto-connect|autoconnect)(?:=true)?(?:[;'"&|)\]}]|\s|$)/u.test(rendered);
642
752
  }
643
- function destroyTransportStreams(transport) {
644
- const candidate = transport;
645
- for (const key of ["stdin", "stdout", "stderr"]) {
646
- try {
647
- const stream = candidate[key];
648
- stream?.destroy?.();
649
- } catch {
753
+ function commandBasename(command) {
754
+ const normalized = command.replaceAll("\\", "/").toLowerCase();
755
+ return normalized.slice(normalized.lastIndexOf("/") + 1).replace(/\.(?:cmd|exe)$/u, "");
756
+ }
757
+ function optionTerminator(args) {
758
+ const index = args.indexOf("--");
759
+ return index >= 0 ? index : args.length;
760
+ }
761
+ function stripConnectionSelectionArgs(args) {
762
+ const result = [];
763
+ for (let index = 0; index < args.length; index += 1) {
764
+ const arg = args[index];
765
+ if (arg === void 0)
766
+ continue;
767
+ if (arg === "--") {
768
+ result.push(...args.slice(index));
769
+ break;
650
770
  }
771
+ if (CONNECTION_VALUE_FLAGS.has(arg)) {
772
+ index += 1;
773
+ continue;
774
+ }
775
+ if ([...CONNECTION_VALUE_FLAGS].some((flag) => arg.startsWith(`${flag}=`)))
776
+ continue;
777
+ result.push(arg);
651
778
  }
779
+ const terminatorIndex = result.indexOf("--");
780
+ return { args: result, insertionIndex: terminatorIndex >= 0 ? terminatorIndex : result.length };
652
781
  }
653
- async function sendSignalToTargets(pids, signal) {
654
- const seen = /* @__PURE__ */ new Set();
655
- for (const pid of pids) {
656
- if (seen.has(pid)) {
782
+ function parseChromeDevtoolsAutoConnectArgs(args) {
783
+ const consumed = /* @__PURE__ */ new Set();
784
+ let enabled = false;
785
+ let sawOption = false;
786
+ let terminatorIndex = args.length;
787
+ for (let index = 0; index < args.length; index += 1) {
788
+ const arg = args[index];
789
+ if (arg === void 0)
790
+ continue;
791
+ if (arg === "--") {
792
+ terminatorIndex = index;
793
+ break;
794
+ }
795
+ if (NEGATED_AUTO_CONNECT_FLAGS.has(arg)) {
796
+ sawOption = true;
797
+ enabled = false;
798
+ consumed.add(index);
657
799
  continue;
658
800
  }
659
- seen.add(pid);
660
- sendSignal(pid, signal);
801
+ let matchedNegatedInline = false;
802
+ for (const flag of NEGATED_AUTO_CONNECT_FLAGS) {
803
+ if (!arg.startsWith(`${flag}=`))
804
+ continue;
805
+ sawOption = true;
806
+ enabled = false;
807
+ consumed.add(index);
808
+ matchedNegatedInline = true;
809
+ break;
810
+ }
811
+ if (matchedNegatedInline)
812
+ continue;
813
+ if (AUTO_CONNECT_FLAGS.has(arg)) {
814
+ sawOption = true;
815
+ consumed.add(index);
816
+ const pairedValue = booleanLiteral(args[index + 1]);
817
+ if (pairedValue !== void 0) {
818
+ enabled = pairedValue;
819
+ consumed.add(index + 1);
820
+ index += 1;
821
+ } else {
822
+ enabled = true;
823
+ }
824
+ continue;
825
+ }
826
+ for (const flag of AUTO_CONNECT_FLAGS) {
827
+ if (!arg.startsWith(`${flag}=`))
828
+ continue;
829
+ sawOption = true;
830
+ enabled = arg.slice(flag.length + 1) === "true";
831
+ consumed.add(index);
832
+ break;
833
+ }
661
834
  }
835
+ const withoutAutoConnect = args.filter((_arg, index) => !consumed.has(index));
836
+ let insertionIndex = 0;
837
+ for (let index = 0; index < terminatorIndex; index += 1) {
838
+ if (!consumed.has(index))
839
+ insertionIndex += 1;
840
+ }
841
+ return { enabled: sawOption && enabled, withoutAutoConnect, insertionIndex };
662
842
  }
663
- function sendSignal(pid, signal) {
664
- try {
665
- process.kill(pid, signal);
666
- } catch (error) {
667
- if (typeof error === "object" && error && "code" in error && error.code === "ESRCH") {
843
+ function booleanLiteral(value) {
844
+ if (value === "true")
845
+ return true;
846
+ if (value === "false")
847
+ return false;
848
+ return void 0;
849
+ }
850
+
851
+ // node_modules/.pnpm/mcporter@0.13.10/node_modules/mcporter/dist/chrome-devtools-relay-proxy.js
852
+ import { createHash, randomBytes, timingSafeEqual } from "node:crypto";
853
+ import http, {} from "node:http";
854
+ var WEBSOCKET_GUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
855
+ async function startChromeDevtoolsRelayProxy(options) {
856
+ const sockets = /* @__PURE__ */ new Set();
857
+ const clientAuthorization = `Bearer ${randomBytes(32).toString("base64url")}`;
858
+ let downstreamAccepted = false;
859
+ let closed = false;
860
+ const server = http.createServer((_request, response) => {
861
+ response.writeHead(404, { Connection: "close", "Content-Length": "0" }).end();
862
+ });
863
+ server.on("connection", (socket) => trackSocket(sockets, socket));
864
+ server.on("upgrade", (request, downstream, head) => {
865
+ if (closed || downstreamAccepted || !isValidDownstreamUpgrade(request, clientAuthorization) || options.upstream.socket.destroyed) {
866
+ downstream.end("HTTP/1.1 404 Not Found\r\nConnection: close\r\nContent-Length: 0\r\n\r\n");
867
+ return;
868
+ }
869
+ downstreamAccepted = true;
870
+ const key = request.headers["sec-websocket-key"];
871
+ if (typeof key !== "string") {
872
+ downstream.destroy();
668
873
  return;
669
874
  }
875
+ const accept = createHash("sha1").update(`${key}${WEBSOCKET_GUID}`).digest("base64");
876
+ downstream.write([
877
+ "HTTP/1.1 101 Switching Protocols",
878
+ "Connection: Upgrade",
879
+ "Upgrade: websocket",
880
+ `Sec-WebSocket-Accept: ${accept}`,
881
+ "",
882
+ ""
883
+ ].join("\r\n"));
884
+ if (options.upstream.head.length > 0)
885
+ downstream.write(options.upstream.head);
886
+ if (head.length > 0)
887
+ options.upstream.socket.write(head);
888
+ options.upstream.socket.once("error", () => downstream.destroy());
889
+ options.upstream.socket.once("close", () => downstream.destroy());
890
+ downstream.once("error", () => options.upstream.socket.destroy());
891
+ downstream.once("close", () => options.upstream.socket.destroy());
892
+ downstream.pipe(options.upstream.socket).pipe(downstream);
893
+ server.close();
894
+ });
895
+ const onUpstreamClose = () => {
896
+ void closeServer(server, sockets);
897
+ };
898
+ options.upstream.socket.once("close", onUpstreamClose);
899
+ try {
900
+ await new Promise((resolve, reject) => {
901
+ const onError = (error) => reject(error);
902
+ server.once("error", onError);
903
+ server.listen(0, "127.0.0.1", () => {
904
+ server.off("error", onError);
905
+ resolve();
906
+ });
907
+ });
908
+ } catch (error) {
909
+ closeUpstream(options.upstream.socket);
670
910
  throw error;
671
911
  }
912
+ const address = server.address();
913
+ if (!address || address.address !== "127.0.0.1") {
914
+ closeUpstream(options.upstream.socket);
915
+ server.close();
916
+ throw new Error("Chrome relay proxy failed to bind to IPv4 loopback.");
917
+ }
918
+ let authorizationAvailable = true;
919
+ return {
920
+ endpoint: `ws://127.0.0.1:${address.port}/cdp`,
921
+ consumeClientAuthorization() {
922
+ if (!authorizationAvailable)
923
+ throw new Error("Chrome relay authorization handoff already consumed.");
924
+ authorizationAvailable = false;
925
+ return clientAuthorization;
926
+ },
927
+ async close() {
928
+ if (closed)
929
+ return;
930
+ closed = true;
931
+ options.upstream.socket.off("close", onUpstreamClose);
932
+ closeUpstream(options.upstream.socket);
933
+ await closeServer(server, sockets);
934
+ }
935
+ };
672
936
  }
673
- async function listDescendantPids(rootPid) {
674
- if (!isProcessAlive(rootPid)) {
675
- return [];
937
+ function isValidDownstreamUpgrade(request, expectedAuthorization) {
938
+ if (request.url !== "/cdp" || request.method !== "GET" || request.headers.upgrade?.toLowerCase() !== "websocket" || !hasToken(request.headers.connection, "upgrade") || request.headers["sec-websocket-version"] !== "13" || countRawHeader(request, "authorization") !== 1 || countRawHeader(request, "sec-websocket-key") !== 1 || !safeHeaderEqual(request.headers.authorization, expectedAuthorization)) {
939
+ return false;
676
940
  }
677
- if (process.platform === "win32") {
678
- return listDescendantPidsWindows(rootPid);
941
+ const key = request.headers["sec-websocket-key"];
942
+ if (typeof key !== "string" || !/^[A-Za-z0-9+/]{22}==$/u.test(key))
943
+ return false;
944
+ const decoded = Buffer.from(key, "base64");
945
+ return decoded.byteLength === 16 && decoded.toString("base64") === key;
946
+ }
947
+ function countRawHeader(request, expectedName) {
948
+ let count = 0;
949
+ for (let index = 0; index < request.rawHeaders.length; index += 2) {
950
+ if (request.rawHeaders[index]?.toLowerCase() === expectedName)
951
+ count += 1;
952
+ }
953
+ return count;
954
+ }
955
+ function safeHeaderEqual(actual, expected) {
956
+ if (!actual)
957
+ return false;
958
+ const actualBytes = Buffer.from(actual);
959
+ const expectedBytes = Buffer.from(expected);
960
+ return actualBytes.length === expectedBytes.length && timingSafeEqual(actualBytes, expectedBytes);
961
+ }
962
+ function hasToken(value, expected) {
963
+ return Boolean(value?.split(",").some((token) => token.trim().toLowerCase() === expected));
964
+ }
965
+ function trackSocket(sockets, socket) {
966
+ if (sockets.has(socket))
967
+ return;
968
+ sockets.add(socket);
969
+ socket.once("close", () => sockets.delete(socket));
970
+ }
971
+ function closeUpstream(socket) {
972
+ if (socket.destroyed)
973
+ return;
974
+ if (!socket.remoteAddress) {
975
+ socket.destroy();
976
+ return;
679
977
  }
680
978
  try {
681
- const { stdout } = await execFileAsync("ps", ["-eo", "pid=,ppid="]);
682
- const children = /* @__PURE__ */ new Map();
683
- for (const line of stdout.split("\n")) {
684
- const trimmed = line.trim();
685
- if (!trimmed) {
686
- continue;
687
- }
688
- const [pidText, ppidText] = trimmed.split(/\s+/, 2);
689
- const pid = Number.parseInt(pidText ?? "", 10);
690
- const ppid = Number.parseInt(ppidText ?? "", 10);
691
- if (!Number.isFinite(pid) || !Number.isFinite(ppid)) {
692
- continue;
693
- }
694
- const bucket = children.get(ppid) ?? [];
695
- bucket.push(pid);
696
- children.set(ppid, bucket);
697
- }
698
- return collectDescendantsFromChildren(rootPid, children);
979
+ socket.resetAndDestroy();
699
980
  } catch {
700
- return [];
981
+ socket.destroy();
701
982
  }
702
983
  }
703
- async function listDescendantPidsWindows(rootPid) {
704
- try {
705
- const powershellScript = "Get-CimInstance Win32_Process | Select-Object ProcessId,ParentProcessId | ConvertTo-Json -Compress";
706
- const { stdout } = await execFileAsync("powershell.exe", ["-NoProfile", "-Command", powershellScript]);
707
- const trimmed = stdout.trim();
708
- if (!trimmed) {
709
- return [];
710
- }
711
- const parsed = JSON.parse(trimmed);
712
- const entries = Array.isArray(parsed) ? parsed : [parsed];
713
- const children = /* @__PURE__ */ new Map();
714
- for (const entry of entries) {
715
- const pidCandidate = entry?.ProcessId;
716
- const ppidCandidate = entry?.ParentProcessId;
717
- if (typeof pidCandidate !== "number" || typeof ppidCandidate !== "number") {
718
- continue;
719
- }
720
- const pid = Number.isFinite(pidCandidate) ? pidCandidate : void 0;
721
- const ppid = Number.isFinite(ppidCandidate) ? ppidCandidate : void 0;
722
- if (pid === void 0 || ppid === void 0) {
723
- continue;
724
- }
725
- const bucket = children.get(ppid) ?? [];
726
- bucket.push(pid);
727
- children.set(ppid, bucket);
984
+ async function closeServer(server, sockets) {
985
+ for (const socket of sockets)
986
+ socket.destroy();
987
+ if (!server.listening)
988
+ return;
989
+ await new Promise((resolve) => server.close(() => resolve()));
990
+ }
991
+
992
+ // node_modules/.pnpm/mcporter@0.13.10/node_modules/mcporter/dist/browser-relay-auth-v2.js
993
+ import { createHmac, hash, timingSafeEqual as timingSafeEqual2 } from "node:crypto";
994
+ var BROWSER_RELAY_AUTH_LABEL = "openclaw.browser-relay.auth";
995
+ var BROWSER_RELAY_AUTH_VERSION = 2;
996
+ var BROWSER_RELAY_CHALLENGE_MAX_LIFETIME_MS = 1e4;
997
+ var BROWSER_RELAY_CLOCK_SKEW_MS = 3e4;
998
+ var BROWSER_RELAY_AUTH_CHALLENGE_PATH = "/_openclaw/relay/auth/v2/challenge";
999
+ var BROWSER_RELAY_AUTH_COMPLETE_PATH = "/_openclaw/relay/auth/v2/complete";
1000
+ var BROWSER_RELAY_CDP_PATH = "/cdp";
1001
+ var BROWSER_RELAY_CDP_ROLE = "cdp";
1002
+ var BROWSER_RELAY_CDP_TRANSPORT = "connection";
1003
+ var BROWSER_RELAY_CDP_METHOD = "SEQUENCE";
1004
+ var BROWSER_RELAY_CDP_RESOURCE = "/json/version -> /cdp";
1005
+ var BROWSER_RELAY_CDP_FLOW = "cdp";
1006
+ var BROWSER_RELAY_VERSION_PATH = "/json/version";
1007
+ function deriveBrowserRelayKeyId(key) {
1008
+ assertRelayKey(key);
1009
+ return hash("sha256", key, "base64url").slice(0, 22);
1010
+ }
1011
+ function canonicalizeBrowserRelayProof(proofKind, fields, clientProof) {
1012
+ const canonical = [
1013
+ BROWSER_RELAY_AUTH_LABEL,
1014
+ BROWSER_RELAY_AUTH_VERSION,
1015
+ proofKind,
1016
+ fields.keyId,
1017
+ fields.instanceId,
1018
+ fields.sessionId,
1019
+ fields.clientNonce,
1020
+ fields.serverNonce,
1021
+ fields.issuedAtMs,
1022
+ fields.expiresAtMs,
1023
+ fields.role,
1024
+ fields.transport,
1025
+ fields.method,
1026
+ fields.resource,
1027
+ fields.flow
1028
+ ];
1029
+ if (proofKind === "accept") {
1030
+ if (!clientProof || !isCanonicalBase64Url(clientProof, 32)) {
1031
+ throw new Error("Browser relay accept proof requires a 32-byte client proof.");
728
1032
  }
729
- return collectDescendantsFromChildren(rootPid, children);
730
- } catch {
731
- return [];
1033
+ canonical.push(clientProof);
1034
+ } else if (clientProof !== void 0) {
1035
+ throw new Error("Browser relay client proof is only valid for an accept proof.");
732
1036
  }
1037
+ return Buffer.from(JSON.stringify(canonical), "utf8");
733
1038
  }
734
- function execFileAsync(command, args) {
735
- return new Promise((resolve, reject) => {
736
- execFile(command, args, { encoding: "utf8" }, (error, stdout, stderr) => {
737
- if (error) {
1039
+ function createBrowserRelayProof(key, proofKind, fields, clientProof) {
1040
+ assertRelayKey(key);
1041
+ return createHmac("sha256", key).update(canonicalizeBrowserRelayProof(proofKind, fields, clientProof)).digest("base64url");
1042
+ }
1043
+ function verifyBrowserRelayProof(key, proofKind, fields, proof, clientProof) {
1044
+ if (!isCanonicalBase64Url(proof, 32))
1045
+ return false;
1046
+ const actual = Buffer.from(proof, "base64url");
1047
+ const expected = Buffer.from(createBrowserRelayProof(key, proofKind, fields, clientProof), "base64url");
1048
+ return actual.byteLength === expected.byteLength && timingSafeEqual2(actual, expected);
1049
+ }
1050
+ function assertRelayKey(key) {
1051
+ if (key.byteLength !== 32)
1052
+ throw new Error("Browser relay key must contain 32 bytes.");
1053
+ }
1054
+ function isCanonicalBase64Url(value, bytes) {
1055
+ if (!/^[A-Za-z0-9_-]+$/u.test(value))
1056
+ return false;
1057
+ const decoded = Buffer.from(value, "base64url");
1058
+ return decoded.byteLength === bytes && decoded.toString("base64url") === value;
1059
+ }
1060
+
1061
+ // node_modules/.pnpm/mcporter@0.13.10/node_modules/mcporter/dist/chrome-devtools-relay-client.js
1062
+ import { createHash as createHash2, randomBytes as randomBytes2 } from "node:crypto";
1063
+ import { lookup } from "node:dns/promises";
1064
+ import net from "node:net";
1065
+ import { TextDecoder } from "node:util";
1066
+ var MAX_HEADER_BYTES = 16 * 1024;
1067
+ var MAX_JSON_BYTES = 64 * 1024;
1068
+ var WEBSOCKET_GUID2 = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
1069
+ var RelayV2Error = class extends Error {
1070
+ reason;
1071
+ status;
1072
+ constructor(reason, status) {
1073
+ super(`Chrome relay authentication failed (${reason}).`);
1074
+ this.reason = reason;
1075
+ this.status = status;
1076
+ this.name = "RelayV2Error";
1077
+ }
1078
+ };
1079
+ async function connectChromeDevtoolsRelayV2(options) {
1080
+ const startedAt = performance.now();
1081
+ const durationMs = () => Math.max(0, Math.round(performance.now() - startedAt));
1082
+ let socket;
1083
+ let timer;
1084
+ try {
1085
+ let timedOut = false;
1086
+ const timeout = new Promise((_resolve, reject) => {
1087
+ timer = setTimeout(() => {
1088
+ timedOut = true;
1089
+ const error = new RelayV2Error("timeout");
1090
+ socket?.destroy(error);
738
1091
  reject(error);
739
- return;
1092
+ }, options.timeoutMs);
1093
+ });
1094
+ timer?.unref();
1095
+ const addresses = await Promise.race([
1096
+ resolveLoopbackAddresses(options.baseUrl.hostname, options.resolve ?? lookup),
1097
+ timeout
1098
+ ]);
1099
+ const port = resolvePort(options.baseUrl);
1100
+ let lastConnectionError;
1101
+ for (const address of addresses) {
1102
+ socket = net.createConnection({ host: address.address, family: address.family, port });
1103
+ try {
1104
+ await waitForConnect(socket);
1105
+ lastConnectionError = void 0;
1106
+ break;
1107
+ } catch (error) {
1108
+ socket.destroy();
1109
+ if (timedOut || isTimeoutError(error))
1110
+ throw new RelayV2Error("timeout");
1111
+ lastConnectionError = error;
740
1112
  }
741
- resolve({ stdout, stderr });
1113
+ }
1114
+ if (lastConnectionError)
1115
+ throw lastConnectionError;
1116
+ if (!socket || socket.destroyed)
1117
+ throw new RelayV2Error(timedOut ? "timeout" : "network-error");
1118
+ if (!socket.remoteAddress || !isNumericLoopback(socket.remoteAddress))
1119
+ throw new RelayV2Error("protocol");
1120
+ const reader = new SocketReader(socket);
1121
+ const flow = options.flow ?? "cdp";
1122
+ const clientNonce = randomBytes2(32).toString("base64url");
1123
+ const hello = {
1124
+ v: BROWSER_RELAY_AUTH_VERSION,
1125
+ keyId: options.credential.keyId,
1126
+ clientNonce,
1127
+ role: BROWSER_RELAY_CDP_ROLE,
1128
+ transport: BROWSER_RELAY_CDP_TRANSPORT,
1129
+ method: flow === BROWSER_RELAY_CDP_FLOW ? BROWSER_RELAY_CDP_METHOD : "GET",
1130
+ resource: flow === BROWSER_RELAY_CDP_FLOW ? BROWSER_RELAY_CDP_RESOURCE : "/json/list",
1131
+ flow
1132
+ };
1133
+ await writeJsonRequest(socket, options.baseUrl.host, BROWSER_RELAY_AUTH_CHALLENGE_PATH, hello);
1134
+ const challengeResponse = await reader.readHttpResponse(MAX_JSON_BYTES);
1135
+ ensureAuthStatus(challengeResponse, "challenge");
1136
+ const challenge = parseStrictJsonObject(challengeResponse.body);
1137
+ const fields = validateChallenge(challenge, hello, options.now?.() ?? Date.now());
1138
+ const serverProof = requireString(challenge, "serverProof");
1139
+ if (!verifyBrowserRelayProof(options.credential.key, "server", fields, serverProof)) {
1140
+ throw new RelayV2Error("bad-server-proof");
1141
+ }
1142
+ const clientProof = createBrowserRelayProof(options.credential.key, "client", fields);
1143
+ await writeJsonRequest(socket, options.baseUrl.host, BROWSER_RELAY_AUTH_COMPLETE_PATH, {
1144
+ v: BROWSER_RELAY_AUTH_VERSION,
1145
+ sessionId: fields.sessionId,
1146
+ clientProof
1147
+ });
1148
+ const completeResponse = await reader.readHttpResponse(MAX_JSON_BYTES);
1149
+ ensureAuthStatus(completeResponse, "complete");
1150
+ const accepted = parseStrictJsonObject(completeResponse.body);
1151
+ validateAccept(accepted, fields.sessionId);
1152
+ if (!verifyBrowserRelayProof(options.credential.key, "accept", fields, requireString(accepted, "acceptProof"), clientProof)) {
1153
+ throw new RelayV2Error("bad-server-proof");
1154
+ }
1155
+ if (flow === "json-list") {
1156
+ await writeRequest(socket, options.baseUrl.host, "GET", "/json/list", []);
1157
+ const listResponse = await reader.readHttpResponse(MAX_JSON_BYTES, true);
1158
+ if (listResponse.status !== 200)
1159
+ throw classifyStatus(listResponse.status, true);
1160
+ const json = parseStrictJson(listResponse.body);
1161
+ if (!Array.isArray(json))
1162
+ throw new RelayV2Error("protocol", 200);
1163
+ socket.destroy();
1164
+ return { reason: "success", durationMs: durationMs(), status: 200, json };
1165
+ }
1166
+ await writeRequest(socket, options.baseUrl.host, "GET", BROWSER_RELAY_VERSION_PATH, []);
1167
+ const versionResponse = await reader.readHttpResponse(MAX_JSON_BYTES);
1168
+ if (versionResponse.status === 503) {
1169
+ socket.destroy();
1170
+ return { reason: "extension-disconnected", durationMs: durationMs(), status: 503 };
1171
+ }
1172
+ if (versionResponse.status !== 200)
1173
+ throw classifyStatus(versionResponse.status, true);
1174
+ parseStrictJsonObject(versionResponse.body);
1175
+ const websocketKey = randomBytes2(16).toString("base64");
1176
+ await writeRequest(socket, options.baseUrl.host, "GET", BROWSER_RELAY_CDP_PATH, [
1177
+ ["Connection", "Upgrade"],
1178
+ ["Upgrade", "websocket"],
1179
+ ["Sec-WebSocket-Key", websocketKey],
1180
+ ["Sec-WebSocket-Version", "13"]
1181
+ ]);
1182
+ const upgrade = await reader.readHttpUpgrade();
1183
+ if (upgrade.status !== 101)
1184
+ throw classifyStatus(upgrade.status, true);
1185
+ const expectedAccept = createHash2("sha1").update(`${websocketKey}${WEBSOCKET_GUID2}`).digest("base64");
1186
+ if (upgrade.headers.get("upgrade")?.toLowerCase() !== "websocket" || !hasToken2(upgrade.headers.get("connection"), "upgrade") || upgrade.headers.get("sec-websocket-accept") !== expectedAccept) {
1187
+ throw new RelayV2Error("sequence", 101);
1188
+ }
1189
+ const head = reader.release();
1190
+ if (timer)
1191
+ clearTimeout(timer);
1192
+ return { reason: "success", durationMs: durationMs(), status: 200, upstream: { socket, head } };
1193
+ } catch (error) {
1194
+ socket?.destroy();
1195
+ if (error instanceof RelayV2Error) {
1196
+ return { reason: error.reason, durationMs: durationMs(), status: error.status };
1197
+ }
1198
+ return { reason: isTimeoutError(error) ? "timeout" : "network-error", durationMs: durationMs() };
1199
+ } finally {
1200
+ if (timer)
1201
+ clearTimeout(timer);
1202
+ }
1203
+ }
1204
+ async function resolveLoopbackAddresses(hostname, resolver) {
1205
+ const normalized = hostname.replace(/^\[(.*)\]$/u, "$1");
1206
+ const addresses = await resolver(normalized, { all: true, verbatim: true });
1207
+ if (addresses.length === 0 || addresses.some((address) => !isNumericLoopback(address.address))) {
1208
+ throw new RelayV2Error("protocol");
1209
+ }
1210
+ return addresses;
1211
+ }
1212
+ function resolvePort(url) {
1213
+ const port = url.port === "" ? 80 : Number(url.port);
1214
+ if (!Number.isSafeInteger(port) || port < 1 || port > 65535)
1215
+ throw new RelayV2Error("protocol");
1216
+ return port;
1217
+ }
1218
+ function isNumericLoopback(address) {
1219
+ if (net.isIPv4(address))
1220
+ return address.startsWith("127.");
1221
+ if (!net.isIPv6(address))
1222
+ return false;
1223
+ const normalized = address.toLowerCase();
1224
+ return normalized === "::1" || normalized.startsWith("::ffff:127.");
1225
+ }
1226
+ async function waitForConnect(socket) {
1227
+ await new Promise((resolve, reject) => {
1228
+ const onConnect = () => {
1229
+ cleanup();
1230
+ resolve();
1231
+ };
1232
+ const onError = (error) => {
1233
+ cleanup();
1234
+ reject(error);
1235
+ };
1236
+ const cleanup = () => {
1237
+ socket.off("connect", onConnect);
1238
+ socket.off("error", onError);
1239
+ };
1240
+ socket.once("connect", onConnect);
1241
+ socket.once("error", onError);
1242
+ });
1243
+ }
1244
+ var SocketReader = class {
1245
+ socket;
1246
+ buffered = Buffer.alloc(0);
1247
+ failure;
1248
+ ended = false;
1249
+ onData = (chunk) => {
1250
+ this.buffered = Buffer.concat([this.buffered, chunk]);
1251
+ };
1252
+ onError = (error) => {
1253
+ this.failure = error;
1254
+ };
1255
+ onClose = () => {
1256
+ this.ended = true;
1257
+ };
1258
+ constructor(socket) {
1259
+ this.socket = socket;
1260
+ socket.on("data", this.onData);
1261
+ socket.on("error", this.onError);
1262
+ socket.on("close", this.onClose);
1263
+ }
1264
+ async readHttpResponse(maxBodyBytes, allowConnectionClose = false) {
1265
+ const parsed = await this.readHeaders();
1266
+ if (parsed.status === 101)
1267
+ throw new RelayV2Error("protocol", 101);
1268
+ if (parsed.headers.has("transfer-encoding"))
1269
+ throw new RelayV2Error("protocol", parsed.status);
1270
+ if (!allowConnectionClose && parsed.status === 200 && hasToken2(parsed.headers.get("connection"), "close")) {
1271
+ throw new RelayV2Error("protocol", parsed.status);
1272
+ }
1273
+ const rawLength = parsed.headers.get("content-length");
1274
+ if (!rawLength || !/^\d+$/u.test(rawLength))
1275
+ throw new RelayV2Error("protocol", parsed.status);
1276
+ const length = Number(rawLength);
1277
+ if (!Number.isSafeInteger(length) || length > maxBodyBytes)
1278
+ throw new RelayV2Error("protocol", parsed.status);
1279
+ await this.waitForBytes(length);
1280
+ const body = this.buffered.subarray(0, length);
1281
+ this.buffered = this.buffered.subarray(length);
1282
+ if (this.buffered.length > 0)
1283
+ throw new RelayV2Error("protocol", parsed.status);
1284
+ return { ...parsed, body };
1285
+ }
1286
+ async readHttpUpgrade() {
1287
+ const parsed = await this.readHeaders();
1288
+ if (parsed.headers.has("transfer-encoding"))
1289
+ throw new RelayV2Error("protocol", parsed.status);
1290
+ if (parsed.status === 101) {
1291
+ if (parsed.headers.has("content-length"))
1292
+ throw new RelayV2Error("protocol", parsed.status);
1293
+ return { ...parsed, body: Buffer.alloc(0) };
1294
+ }
1295
+ const rawLength = parsed.headers.get("content-length");
1296
+ if (!rawLength || !/^\d+$/u.test(rawLength))
1297
+ throw new RelayV2Error("protocol", parsed.status);
1298
+ const length = Number(rawLength);
1299
+ if (!Number.isSafeInteger(length) || length > MAX_JSON_BYTES)
1300
+ throw new RelayV2Error("protocol", parsed.status);
1301
+ await this.waitForBytes(length);
1302
+ const body = this.buffered.subarray(0, length);
1303
+ this.buffered = this.buffered.subarray(length);
1304
+ if (this.buffered.length > 0)
1305
+ throw new RelayV2Error("protocol", parsed.status);
1306
+ return { ...parsed, body };
1307
+ }
1308
+ release() {
1309
+ this.socket.off("data", this.onData);
1310
+ this.socket.off("error", this.onError);
1311
+ this.socket.off("close", this.onClose);
1312
+ const head = this.buffered;
1313
+ this.buffered = Buffer.alloc(0);
1314
+ return head;
1315
+ }
1316
+ async readHeaders() {
1317
+ let boundary = this.buffered.indexOf("\r\n\r\n");
1318
+ while (boundary < 0) {
1319
+ if (this.buffered.length > MAX_HEADER_BYTES)
1320
+ throw new RelayV2Error("protocol");
1321
+ await this.waitForData();
1322
+ boundary = this.buffered.indexOf("\r\n\r\n");
1323
+ }
1324
+ if (boundary > MAX_HEADER_BYTES)
1325
+ throw new RelayV2Error("protocol");
1326
+ const raw = this.buffered.subarray(0, boundary).toString("latin1");
1327
+ this.buffered = this.buffered.subarray(boundary + 4);
1328
+ const lines = raw.split("\r\n");
1329
+ const statusLine = lines.shift();
1330
+ const match = /^HTTP\/1\.1 ([1-5]\d\d)(?: [\x20-\x7e]*)?$/u.exec(statusLine ?? "");
1331
+ if (!match)
1332
+ throw new RelayV2Error("protocol");
1333
+ const status = Number(match[1]);
1334
+ const headers = /* @__PURE__ */ new Map();
1335
+ for (const line of lines) {
1336
+ if (/^[ \t]/u.test(line))
1337
+ throw new RelayV2Error("protocol", status);
1338
+ const separator = line.indexOf(":");
1339
+ if (separator <= 0)
1340
+ throw new RelayV2Error("protocol", status);
1341
+ const name = line.slice(0, separator).toLowerCase();
1342
+ const value = line.slice(separator + 1).trim();
1343
+ if (!/^[!#$%&'*+.^_`|~0-9a-z-]+$/u.test(name) || value.includes("\0") || value.includes("\r") || value.includes("\n") || value.includes("\x7F")) {
1344
+ throw new RelayV2Error("protocol", status);
1345
+ }
1346
+ if (headers.has(name))
1347
+ throw new RelayV2Error("protocol", status);
1348
+ headers.set(name, value);
1349
+ }
1350
+ return { status, headers };
1351
+ }
1352
+ async waitForBytes(length) {
1353
+ while (this.buffered.length < length)
1354
+ await this.waitForData();
1355
+ }
1356
+ async waitForData() {
1357
+ if (this.failure)
1358
+ throw this.failure;
1359
+ if (this.ended)
1360
+ throw new RelayV2Error("network-error");
1361
+ await new Promise((resolve, reject) => {
1362
+ const onData = () => {
1363
+ cleanup();
1364
+ resolve();
1365
+ };
1366
+ const onError = (error) => {
1367
+ cleanup();
1368
+ reject(error);
1369
+ };
1370
+ const onClose = () => {
1371
+ cleanup();
1372
+ reject(new RelayV2Error("network-error"));
1373
+ };
1374
+ const cleanup = () => {
1375
+ this.socket.off("data", onData);
1376
+ this.socket.off("error", onError);
1377
+ this.socket.off("close", onClose);
1378
+ };
1379
+ this.socket.once("data", onData);
1380
+ this.socket.once("error", onError);
1381
+ this.socket.once("close", onClose);
1382
+ });
1383
+ }
1384
+ };
1385
+ async function writeJsonRequest(socket, host, pathname, body) {
1386
+ const encoded = Buffer.from(JSON.stringify(body), "utf8");
1387
+ await writeRequest(socket, host, "POST", pathname, [
1388
+ ["Content-Type", "application/json"],
1389
+ ["Content-Length", String(encoded.byteLength)]
1390
+ ], encoded);
1391
+ }
1392
+ async function writeRequest(socket, host, method, pathname, headers, body) {
1393
+ const lines = [`${method} ${pathname} HTTP/1.1`, `Host: ${host}`, "Connection: keep-alive"];
1394
+ for (const [name, value] of headers) {
1395
+ if (name.toLowerCase() === "connection")
1396
+ lines[2] = `${name}: ${value}`;
1397
+ else
1398
+ lines.push(`${name}: ${value}`);
1399
+ }
1400
+ const head = Buffer.from(`${lines.join("\r\n")}\r
1401
+ \r
1402
+ `, "ascii");
1403
+ const output = body ? Buffer.concat([head, body]) : head;
1404
+ await new Promise((resolve, reject) => {
1405
+ socket.write(output, (error) => error ? reject(error) : resolve());
1406
+ });
1407
+ }
1408
+ function ensureAuthStatus(response, phase) {
1409
+ if (response.status === 200)
1410
+ return;
1411
+ if (phase === "challenge" && response.status === 401 && responseError(response) === "Relay auth challenge rejected") {
1412
+ throw new RelayV2Error("replay", response.status);
1413
+ }
1414
+ if (response.status === 409)
1415
+ throw new RelayV2Error("sequence", response.status);
1416
+ throw classifyStatus(response.status, false);
1417
+ }
1418
+ function classifyStatus(status, authenticated) {
1419
+ if (!authenticated && (status === 401 || status === 404 || status === 426)) {
1420
+ return new RelayV2Error("unsupported-auth", status);
1421
+ }
1422
+ if (!authenticated && status === 503)
1423
+ return new RelayV2Error("server-auth-failed", status);
1424
+ if (status === 408 || status === 410)
1425
+ return new RelayV2Error("freshness", status);
1426
+ if (status === 409)
1427
+ return new RelayV2Error("sequence", status);
1428
+ if (status === 412)
1429
+ return new RelayV2Error("sequence", status);
1430
+ return new RelayV2Error("protocol", status);
1431
+ }
1432
+ function responseError(response) {
1433
+ try {
1434
+ const value = parseStrictJsonObject(response.body);
1435
+ return typeof value.error === "string" ? value.error : void 0;
1436
+ } catch {
1437
+ return void 0;
1438
+ }
1439
+ }
1440
+ function validateChallenge(value, hello, nowMs) {
1441
+ assertExactKeys(value, [
1442
+ "type",
1443
+ "v",
1444
+ "keyId",
1445
+ "instanceId",
1446
+ "sessionId",
1447
+ "clientNonce",
1448
+ "serverNonce",
1449
+ "issuedAtMs",
1450
+ "expiresAtMs",
1451
+ "role",
1452
+ "transport",
1453
+ "method",
1454
+ "resource",
1455
+ "flow",
1456
+ "serverProof"
1457
+ ]);
1458
+ if (value.type !== "auth.challenge")
1459
+ throw new RelayV2Error("protocol");
1460
+ if (value.v !== BROWSER_RELAY_AUTH_VERSION)
1461
+ throw new RelayV2Error("protocol");
1462
+ for (const key of ["keyId", "clientNonce", "role", "transport", "method", "resource", "flow"]) {
1463
+ if (value[key] !== hello[key])
1464
+ throw new RelayV2Error("protocol");
1465
+ }
1466
+ const fields = {
1467
+ keyId: requireToken(value, "keyId", 22),
1468
+ instanceId: requireEncoded(value, "instanceId", 22),
1469
+ sessionId: requireEncoded(value, "sessionId", 22),
1470
+ clientNonce: requireEncoded(value, "clientNonce", 43),
1471
+ serverNonce: requireEncoded(value, "serverNonce", 43),
1472
+ issuedAtMs: requireInteger(value, "issuedAtMs"),
1473
+ expiresAtMs: requireInteger(value, "expiresAtMs"),
1474
+ role: requireString(value, "role"),
1475
+ transport: requireString(value, "transport"),
1476
+ method: requireString(value, "method"),
1477
+ resource: requireString(value, "resource"),
1478
+ flow: requireString(value, "flow")
1479
+ };
1480
+ requireEncoded(value, "serverProof", 43);
1481
+ const lifetime = fields.expiresAtMs - fields.issuedAtMs;
1482
+ if (lifetime <= 0 || lifetime > BROWSER_RELAY_CHALLENGE_MAX_LIFETIME_MS || fields.issuedAtMs - nowMs > BROWSER_RELAY_CLOCK_SKEW_MS || nowMs > fields.expiresAtMs) {
1483
+ throw new RelayV2Error("freshness");
1484
+ }
1485
+ return fields;
1486
+ }
1487
+ function validateAccept(value, sessionId) {
1488
+ assertExactKeys(value, ["type", "v", "sessionId", "acceptProof"]);
1489
+ if (value.type !== "auth.ok")
1490
+ throw new RelayV2Error("protocol");
1491
+ if (value.v !== BROWSER_RELAY_AUTH_VERSION || value.sessionId !== sessionId)
1492
+ throw new RelayV2Error("protocol");
1493
+ requireEncoded(value, "acceptProof", 43);
1494
+ }
1495
+ function parseStrictJsonObject(body) {
1496
+ const value = parseStrictJson(body);
1497
+ if (!value || typeof value !== "object" || Array.isArray(value))
1498
+ throw new RelayV2Error("protocol");
1499
+ return value;
1500
+ }
1501
+ function parseStrictJson(body) {
1502
+ let source;
1503
+ try {
1504
+ source = new TextDecoder("utf-8", { fatal: true }).decode(body);
1505
+ } catch {
1506
+ throw new RelayV2Error("protocol");
1507
+ }
1508
+ const errors = [];
1509
+ const tree = parseTree(source, errors, { allowTrailingComma: false, disallowComments: true });
1510
+ if (!tree || errors.length > 0)
1511
+ throw new RelayV2Error("protocol");
1512
+ rejectDuplicateJsonKeys(tree);
1513
+ try {
1514
+ return JSON.parse(source);
1515
+ } catch {
1516
+ throw new RelayV2Error("protocol");
1517
+ }
1518
+ }
1519
+ function rejectDuplicateJsonKeys(node) {
1520
+ if (node.type === "object") {
1521
+ const keys = /* @__PURE__ */ new Set();
1522
+ for (const property of node.children ?? []) {
1523
+ const key = property.children?.[0]?.value;
1524
+ if (typeof key !== "string" || keys.has(key))
1525
+ throw new RelayV2Error("protocol");
1526
+ keys.add(key);
1527
+ }
1528
+ }
1529
+ for (const child of node.children ?? [])
1530
+ rejectDuplicateJsonKeys(child);
1531
+ }
1532
+ function assertExactKeys(value, required) {
1533
+ const actual = Object.keys(value);
1534
+ if (actual.length !== required.length || required.some((key) => !Object.hasOwn(value, key))) {
1535
+ throw new RelayV2Error("protocol");
1536
+ }
1537
+ }
1538
+ function requireString(value, key) {
1539
+ const field = value[key];
1540
+ if (typeof field !== "string")
1541
+ throw new RelayV2Error("protocol");
1542
+ return field;
1543
+ }
1544
+ function requireEncoded(value, key, length) {
1545
+ const field = requireString(value, key);
1546
+ const bytes = length === 22 ? 16 : length === 43 ? 32 : 0;
1547
+ const decoded = Buffer.from(field, "base64url");
1548
+ if (bytes === 0 || field.length !== length || !/^[A-Za-z0-9_-]+$/u.test(field) || decoded.byteLength !== bytes || decoded.toString("base64url") !== field) {
1549
+ throw new RelayV2Error("protocol");
1550
+ }
1551
+ return field;
1552
+ }
1553
+ function requireToken(value, key, length) {
1554
+ const field = requireString(value, key);
1555
+ if (field.length !== length || !/^[A-Za-z0-9_-]+$/u.test(field))
1556
+ throw new RelayV2Error("protocol");
1557
+ return field;
1558
+ }
1559
+ function requireInteger(value, key) {
1560
+ const field = value[key];
1561
+ if (typeof field !== "number" || !Number.isSafeInteger(field))
1562
+ throw new RelayV2Error("protocol");
1563
+ return field;
1564
+ }
1565
+ function hasToken2(value, expected) {
1566
+ return Boolean(value?.split(",").some((token) => token.trim().toLowerCase() === expected));
1567
+ }
1568
+ function isTimeoutError(error) {
1569
+ return Boolean(error && typeof error === "object" && error.reason === "timeout");
1570
+ }
1571
+
1572
+ // node_modules/.pnpm/mcporter@0.13.10/node_modules/mcporter/dist/chrome-devtools-relay-discovery.js
1573
+ import { spawn } from "node:child_process";
1574
+ import { statSync } from "node:fs";
1575
+ import net2 from "node:net";
1576
+ import path from "node:path";
1577
+ var OPENCLAW_CDP_ARGS = ["browser", "extension", "cdp", "--json"];
1578
+ var OPENCLAW_WINDOWS_COMMAND_SUFFIX = "browser extension cdp --json";
1579
+ var OPENCLAW_WINDOWS_DEFAULT_PATHEXT = ".COM;.EXE;.BAT;.CMD";
1580
+ var OPENCLAW_WINDOWS_TREE_KILL_TIMEOUT_MS = 1e3;
1581
+ var OPENCLAW_PROFILE_PATTERN = /^[a-z0-9][a-z0-9_-]{0,63}$/i;
1582
+ var OPENCLAW_RELAY_DISCOVERY_MAX_OUTPUT_BYTES = 64 * 1024;
1583
+ var OPENCLAW_RELAY_DISCOVERY_ENV_KEYS = [
1584
+ "APPDATA",
1585
+ "COMSPEC",
1586
+ "ComSpec",
1587
+ "HOME",
1588
+ "HOMEDRIVE",
1589
+ "HOMEPATH",
1590
+ "LANG",
1591
+ "LC_ALL",
1592
+ "LOCALAPPDATA",
1593
+ "OPENCLAW_CONFIG_PATH",
1594
+ "OPENCLAW_GATEWAY_PORT",
1595
+ "OPENCLAW_HOME",
1596
+ "OPENCLAW_OAUTH_DIR",
1597
+ "OPENCLAW_PROFILE",
1598
+ "OPENCLAW_STATE_DIR",
1599
+ "PATH",
1600
+ "Path",
1601
+ "PATHEXT",
1602
+ "SYSTEMROOT",
1603
+ "SystemRoot",
1604
+ "TEMP",
1605
+ "TMP",
1606
+ "TMPDIR",
1607
+ "USERPROFILE",
1608
+ "WINDIR",
1609
+ "XDG_CONFIG_HOME",
1610
+ "XDG_STATE_HOME"
1611
+ ];
1612
+ function normalizeOpenClawProfile(raw) {
1613
+ const profile = raw?.trim();
1614
+ if (!profile || profile.toLowerCase() === "default" || !OPENCLAW_PROFILE_PATTERN.test(profile)) {
1615
+ return void 0;
1616
+ }
1617
+ return profile;
1618
+ }
1619
+ async function discoverOpenClawRelayUrl(options) {
1620
+ const platform = options.platform ?? process.platform;
1621
+ const cwd = options.cwd ?? process.cwd();
1622
+ const filteredEnv = openClawDiscoveryEnvironment(options.env);
1623
+ const command = resolveOpenClawRelayDiscoveryCommandPlan(filteredEnv, platform, options.isFile, cwd);
1624
+ if (!command)
1625
+ return { reason: "unavailable" };
1626
+ const env = sanitizeOpenClawDiscoveryCommandEnvironment(filteredEnv, command, platform, cwd);
1627
+ const result = await (options.run ?? runOpenClawRelayDiscovery)({
1628
+ ...command,
1629
+ env,
1630
+ timeoutMs: options.timeoutMs,
1631
+ maxOutputBytes: OPENCLAW_RELAY_DISCOVERY_MAX_OUTPUT_BYTES,
1632
+ shell: false
1633
+ });
1634
+ return validateDiscoveryCommandResult(result, options.keyId);
1635
+ }
1636
+ function runOpenClawRelayDiscovery(options, runtime = {}) {
1637
+ return new Promise((resolve) => {
1638
+ const child = (runtime.spawn ?? spawn)(options.executable, [...options.args], {
1639
+ cwd: options.cwd,
1640
+ env: options.env,
1641
+ shell: options.shell,
1642
+ stdio: ["ignore", "pipe", "pipe"],
1643
+ windowsVerbatimArguments: options.platform === "win32",
1644
+ windowsHide: true
1645
+ });
1646
+ const stdout = [];
1647
+ let outputBytes = 0;
1648
+ let settled = false;
1649
+ let terminating = false;
1650
+ let timer;
1651
+ const finish = (result) => {
1652
+ if (settled)
1653
+ return;
1654
+ settled = true;
1655
+ if (timer)
1656
+ clearTimeout(timer);
1657
+ resolve(result);
1658
+ };
1659
+ const terminate = (kind) => {
1660
+ if (settled || terminating)
1661
+ return;
1662
+ terminating = true;
1663
+ child.stdout.destroy();
1664
+ child.stderr.destroy();
1665
+ const plan = createOpenClawRelayDiscoveryTerminationPlan(options, child.pid);
1666
+ const terminateProcessTree = runtime.terminateProcessTree ?? terminateOpenClawRelayDiscoveryProcessTree;
1667
+ let termination = Promise.resolve();
1668
+ if (plan) {
1669
+ try {
1670
+ termination = terminateProcessTree(plan, child);
1671
+ } catch {
1672
+ }
1673
+ }
1674
+ void boundedTreeTermination(termination).finally(() => {
1675
+ child.unref();
1676
+ finish({ kind });
1677
+ });
1678
+ };
1679
+ const collect = (chunk, keep) => {
1680
+ if (settled || terminating)
1681
+ return;
1682
+ outputBytes += chunk.byteLength;
1683
+ if (outputBytes > options.maxOutputBytes) {
1684
+ terminate("overflow");
1685
+ return;
1686
+ }
1687
+ if (keep)
1688
+ stdout.push(chunk);
1689
+ };
1690
+ child.stdout.on("data", (chunk) => collect(chunk, true));
1691
+ child.stderr.on("data", (chunk) => collect(chunk, false));
1692
+ child.once("error", (error) => {
1693
+ if (!terminating)
1694
+ finish({ kind: classifyCommandError(error) });
1695
+ });
1696
+ child.once("close", (code) => {
1697
+ if (!terminating) {
1698
+ finish(code === 0 ? { kind: "success", stdout: Buffer.concat(stdout) } : { kind: "nonzero" });
1699
+ }
1700
+ });
1701
+ timer = setTimeout(() => terminate("timeout"), options.timeoutMs);
1702
+ timer.unref();
1703
+ });
1704
+ }
1705
+ function resolveOpenClawRelayDiscoveryCommandPlan(env, platform = process.platform, isFile = isRegularFile, cwd = process.cwd()) {
1706
+ if (platform !== "win32")
1707
+ return { executable: "openclaw", args: OPENCLAW_CDP_ARGS, platform };
1708
+ const executable = resolveWindowsCommandInterpreter(env);
1709
+ const openClawShim = resolveWindowsOpenClawShim(env, isFile, cwd);
1710
+ if (!executable || !openClawShim)
1711
+ return void 0;
1712
+ const taskkillExecutable = path.win32.join(path.win32.dirname(executable), "taskkill.exe");
1713
+ if (!isSafeWindowsSystemToolPath(taskkillExecutable, "taskkill.exe"))
1714
+ return void 0;
1715
+ return {
1716
+ executable,
1717
+ // The only variable bytes are the validated absolute shim path. No config,
1718
+ // profile, URL, metadata, or unresolved command name reaches cmd.exe.
1719
+ args: ["/d", "/s", "/c", `""${openClawShim}" ${OPENCLAW_WINDOWS_COMMAND_SUFFIX}"`],
1720
+ cwd: path.win32.dirname(openClawShim),
1721
+ platform,
1722
+ taskkillExecutable
1723
+ };
1724
+ }
1725
+ function resolveWindowsCommandInterpreter(env) {
1726
+ const systemRoot = env.SYSTEMROOT?.trim() || env.SystemRoot?.trim();
1727
+ const systemCmd = systemRoot && isSafeWindowsSystemRoot(systemRoot) ? path.win32.join(systemRoot, "System32", "cmd.exe") : void 0;
1728
+ const comSpec = env.COMSPEC?.trim() || env.ComSpec?.trim();
1729
+ if (comSpec && isSafeWindowsCmdPath(comSpec)) {
1730
+ const normalizedComSpec = path.win32.normalize(comSpec);
1731
+ if (systemCmd && normalizedComSpec.toLowerCase() === systemCmd.toLowerCase() || !systemCmd && isConventionalWindowsSystemCmd(normalizedComSpec)) {
1732
+ return normalizedComSpec;
1733
+ }
1734
+ }
1735
+ return systemCmd;
1736
+ }
1737
+ function resolveWindowsOpenClawShim(env, isFile, cwd) {
1738
+ const pathEntries = safeWindowsPathEntries(env.PATH ?? env.Path, cwd);
1739
+ const extensions = windowsPathExtensions(env.PATHEXT);
1740
+ for (const directory of pathEntries) {
1741
+ for (const extension of extensions) {
1742
+ if (extension.toLowerCase() !== ".cmd")
1743
+ continue;
1744
+ const candidate = path.win32.join(directory, `openclaw${extension}`);
1745
+ if (isSafeWindowsCommandPath(candidate) && isFile(candidate))
1746
+ return path.win32.normalize(candidate);
1747
+ }
1748
+ }
1749
+ return void 0;
1750
+ }
1751
+ function isSafeWindowsCmdPath(value) {
1752
+ return isSafeWindowsSystemToolPath(value, "cmd.exe");
1753
+ }
1754
+ function isSafeWindowsSystemToolPath(value, basename) {
1755
+ const parent = path.win32.dirname(value);
1756
+ const root = path.win32.dirname(parent);
1757
+ return isSafeWindowsCommandPath(value) && path.win32.basename(value).toLowerCase() === basename && path.win32.basename(parent).toLowerCase() === "system32" && ["windows", "winnt"].includes(path.win32.basename(root).toLowerCase());
1758
+ }
1759
+ function isSafeWindowsSystemRoot(value) {
1760
+ const basename = path.win32.basename(value).toLowerCase();
1761
+ return isSafeWindowsAbsolutePath(value) && basename !== "cmd.exe" && basename !== "system32";
1762
+ }
1763
+ function isConventionalWindowsSystemCmd(value) {
1764
+ const parent = path.win32.dirname(value);
1765
+ const root = path.win32.dirname(parent);
1766
+ return path.win32.basename(parent).toLowerCase() === "system32" && ["windows", "winnt"].includes(path.win32.basename(root).toLowerCase());
1767
+ }
1768
+ function isSafeWindowsAbsolutePath(value) {
1769
+ if (!/^[a-z]:[\\/]/i.test(value) || /["<>|?*]/u.test(value) || hasControlCharacter(value) || value.slice(2).includes(":")) {
1770
+ return false;
1771
+ }
1772
+ const segments = value.replaceAll("/", "\\").split("\\");
1773
+ return !segments.some((segment) => segment === "." || segment === "..");
1774
+ }
1775
+ function isSafeWindowsCommandPath(value) {
1776
+ return isSafeWindowsAbsolutePath(value) && !/["%&|<>^!]/u.test(value) && !hasControlCharacter(value);
1777
+ }
1778
+ function hasControlCharacter(value) {
1779
+ for (let index = 0; index < value.length; index += 1) {
1780
+ if (value.charCodeAt(index) < 32)
1781
+ return true;
1782
+ }
1783
+ return false;
1784
+ }
1785
+ function safeWindowsPathEntries(value, excludedDirectory) {
1786
+ if (!value)
1787
+ return [];
1788
+ const excluded = excludedDirectory && isSafeWindowsCommandPath(excludedDirectory) ? path.win32.resolve(excludedDirectory).toLowerCase() : void 0;
1789
+ return value.split(";").map((entry) => entry.trim()).filter((entry) => entry !== "" && path.win32.isAbsolute(entry) && isSafeWindowsCommandPath(entry)).map((entry) => path.win32.resolve(entry)).filter((entry) => entry.toLowerCase() !== excluded);
1790
+ }
1791
+ function windowsPathExtensions(value) {
1792
+ const raw = value?.trim() || OPENCLAW_WINDOWS_DEFAULT_PATHEXT;
1793
+ return raw.split(";").map((extension) => extension.trim()).filter((extension) => /^\.[a-z0-9]+$/iu.test(extension));
1794
+ }
1795
+ function isRegularFile(candidate) {
1796
+ try {
1797
+ return statSync(candidate).isFile();
1798
+ } catch {
1799
+ return false;
1800
+ }
1801
+ }
1802
+ function sanitizeOpenClawDiscoveryCommandEnvironment(env, command, platform, sourceCwd) {
1803
+ if (platform !== "win32")
1804
+ return env;
1805
+ const sanitized = { ...env };
1806
+ delete sanitized.ComSpec;
1807
+ delete sanitized.COMSPEC;
1808
+ sanitized.ComSpec = command.executable;
1809
+ const safePath = safeWindowsPathEntries(sanitized.PATH ?? sanitized.Path, sourceCwd).join(";");
1810
+ delete sanitized.Path;
1811
+ delete sanitized.PATH;
1812
+ if (safePath)
1813
+ sanitized.Path = safePath;
1814
+ const systemRoot = sanitized.SYSTEMROOT?.trim() || sanitized.SystemRoot?.trim();
1815
+ if (systemRoot && !isSafeWindowsSystemRoot(systemRoot)) {
1816
+ delete sanitized.SystemRoot;
1817
+ delete sanitized.SYSTEMROOT;
1818
+ }
1819
+ return sanitized;
1820
+ }
1821
+ function createOpenClawRelayDiscoveryTerminationPlan(options, pid) {
1822
+ if (!Number.isSafeInteger(pid) || !pid || pid <= 0)
1823
+ return void 0;
1824
+ if (options.platform !== "win32")
1825
+ return { kind: "posix-sigkill", pid, signal: "SIGKILL" };
1826
+ if (!options.taskkillExecutable || !isSafeWindowsSystemToolPath(options.taskkillExecutable, "taskkill.exe")) {
1827
+ return void 0;
1828
+ }
1829
+ return {
1830
+ kind: "windows-taskkill",
1831
+ pid,
1832
+ executable: options.taskkillExecutable,
1833
+ args: ["/PID", String(pid), "/T", "/F"],
1834
+ shell: false,
1835
+ windowsHide: true
1836
+ };
1837
+ }
1838
+ async function terminateOpenClawRelayDiscoveryProcessTree(plan, child) {
1839
+ if (plan.kind === "posix-sigkill") {
1840
+ try {
1841
+ child.kill(plan.signal);
1842
+ } catch {
1843
+ }
1844
+ return;
1845
+ }
1846
+ await new Promise((resolve) => {
1847
+ let killer;
1848
+ try {
1849
+ killer = spawn(plan.executable, [...plan.args], {
1850
+ shell: plan.shell,
1851
+ stdio: "ignore",
1852
+ windowsHide: plan.windowsHide
1853
+ });
1854
+ } catch {
1855
+ resolve();
1856
+ return;
1857
+ }
1858
+ let done = false;
1859
+ const finish = () => {
1860
+ if (done)
1861
+ return;
1862
+ done = true;
1863
+ clearTimeout(timer);
1864
+ resolve();
1865
+ };
1866
+ killer.once("error", finish);
1867
+ killer.once("close", finish);
1868
+ const timer = setTimeout(() => {
1869
+ try {
1870
+ killer.kill("SIGKILL");
1871
+ } catch {
1872
+ }
1873
+ finish();
1874
+ }, OPENCLAW_WINDOWS_TREE_KILL_TIMEOUT_MS);
1875
+ timer.unref();
1876
+ });
1877
+ }
1878
+ async function boundedTreeTermination(termination) {
1879
+ let timer;
1880
+ try {
1881
+ await Promise.race([
1882
+ termination.catch(() => void 0),
1883
+ new Promise((resolve) => {
1884
+ timer = setTimeout(resolve, OPENCLAW_WINDOWS_TREE_KILL_TIMEOUT_MS + 250);
1885
+ timer.unref();
1886
+ })
1887
+ ]);
1888
+ } finally {
1889
+ if (timer)
1890
+ clearTimeout(timer);
1891
+ }
1892
+ }
1893
+ function classifyCommandError(error) {
1894
+ const details = error;
1895
+ if (details.code === "ENOENT")
1896
+ return "unavailable";
1897
+ if (details.code === "ETIMEDOUT" || details.killed === true)
1898
+ return "timeout";
1899
+ if (details.code === "ERR_CHILD_PROCESS_STDIO_MAXBUFFER" || details.code === "ENOBUFS")
1900
+ return "overflow";
1901
+ return "nonzero";
1902
+ }
1903
+ function validateDiscoveryCommandResult(result, expectedKeyId) {
1904
+ if (result.kind !== "success")
1905
+ return { reason: result.kind };
1906
+ if (result.stdout.byteLength > OPENCLAW_RELAY_DISCOVERY_MAX_OUTPUT_BYTES)
1907
+ return { reason: "overflow" };
1908
+ const encoded = result.stdout.toString("utf8").trim();
1909
+ const parseErrors = [];
1910
+ const tree = parseTree(encoded, parseErrors, { allowTrailingComma: false, disallowComments: true });
1911
+ if (!tree || parseErrors.length > 0 || hasDuplicateObjectKeys(tree))
1912
+ return { reason: "malformed" };
1913
+ let metadata;
1914
+ try {
1915
+ metadata = JSON.parse(encoded);
1916
+ } catch {
1917
+ return { reason: "malformed" };
1918
+ }
1919
+ if (!isPlainObject(metadata) || !hasExactKeys(metadata, ["auth", "browserUrl", "wsEndpoint"])) {
1920
+ return { reason: "incompatible" };
1921
+ }
1922
+ if (!isPlainObject(metadata.auth) || !hasExactKeys(metadata.auth, [
1923
+ "challengeUrl",
1924
+ "completeUrl",
1925
+ "flow",
1926
+ "keyId",
1927
+ "label",
1928
+ "method",
1929
+ "resource",
1930
+ "role",
1931
+ "transport",
1932
+ "version"
1933
+ ])) {
1934
+ return { reason: "incompatible" };
1935
+ }
1936
+ const browserUrl = parseBrowserUrl(metadata.browserUrl);
1937
+ if (!browserUrl)
1938
+ return { reason: "unsafe" };
1939
+ const wsEndpoint = parseWebSocketUrl(metadata.wsEndpoint);
1940
+ if (!wsEndpoint || wsEndpoint.host !== browserUrl.host)
1941
+ return { reason: "unsafe" };
1942
+ const auth = metadata.auth;
1943
+ if (auth.label !== BROWSER_RELAY_AUTH_LABEL || auth.version !== BROWSER_RELAY_AUTH_VERSION || auth.role !== BROWSER_RELAY_CDP_ROLE || auth.transport !== BROWSER_RELAY_CDP_TRANSPORT || auth.method !== BROWSER_RELAY_CDP_METHOD || auth.resource !== BROWSER_RELAY_CDP_RESOURCE || auth.flow !== BROWSER_RELAY_CDP_FLOW || auth.challengeUrl !== new URL(BROWSER_RELAY_AUTH_CHALLENGE_PATH, browserUrl).toString() || auth.completeUrl !== new URL(BROWSER_RELAY_AUTH_COMPLETE_PATH, browserUrl).toString()) {
1944
+ return { reason: "incompatible" };
1945
+ }
1946
+ if (auth.keyId !== expectedKeyId)
1947
+ return { reason: "key-id-mismatch" };
1948
+ return { reason: "success", url: browserUrl };
1949
+ }
1950
+ function parseBrowserUrl(value) {
1951
+ if (typeof value !== "string")
1952
+ return void 0;
1953
+ let url;
1954
+ try {
1955
+ url = new URL(value);
1956
+ } catch {
1957
+ return void 0;
1958
+ }
1959
+ if (url.protocol !== "http:" || !isLoopbackHostname(url.hostname) || url.username !== "" || url.password !== "" || !hasValidPort(url) || url.pathname !== "/" || url.search !== "" || url.hash !== "") {
1960
+ return void 0;
1961
+ }
1962
+ return new URL(url.origin);
1963
+ }
1964
+ function parseWebSocketUrl(value) {
1965
+ if (typeof value !== "string")
1966
+ return void 0;
1967
+ let url;
1968
+ try {
1969
+ url = new URL(value);
1970
+ } catch {
1971
+ return void 0;
1972
+ }
1973
+ if (url.protocol !== "ws:" || !isLoopbackHostname(url.hostname) || url.username !== "" || url.password !== "" || !hasValidPort(url) || url.pathname !== BROWSER_RELAY_CDP_PATH || url.search !== "" || url.hash !== "") {
1974
+ return void 0;
1975
+ }
1976
+ return url;
1977
+ }
1978
+ function isLoopbackHostname(hostname) {
1979
+ const normalized = hostname.replace(/^\[(.*)\]$/u, "$1").toLowerCase();
1980
+ if (normalized === "localhost" || normalized === "::1")
1981
+ return true;
1982
+ if (net2.isIPv4(normalized))
1983
+ return normalized.startsWith("127.");
1984
+ if (!net2.isIPv6(normalized))
1985
+ return false;
1986
+ return normalized.startsWith("::ffff:127.") || /^::ffff:7f[0-9a-f]{2}:[0-9a-f]{1,4}$/u.test(normalized);
1987
+ }
1988
+ function hasValidPort(url) {
1989
+ if (url.port === "")
1990
+ return true;
1991
+ const port = Number(url.port);
1992
+ return Number.isSafeInteger(port) && port >= 1 && port <= 65535;
1993
+ }
1994
+ function isPlainObject(value) {
1995
+ return Boolean(value && typeof value === "object" && !Array.isArray(value));
1996
+ }
1997
+ function hasExactKeys(value, expected) {
1998
+ const actual = Object.keys(value).toSorted();
1999
+ return actual.length === expected.length && actual.every((key, index) => key === expected[index]);
2000
+ }
2001
+ function hasDuplicateObjectKeys(node) {
2002
+ if (node.type === "object") {
2003
+ const seen = /* @__PURE__ */ new Set();
2004
+ for (const property of node.children ?? []) {
2005
+ const key = property.children?.[0]?.value;
2006
+ if (typeof key !== "string" || seen.has(key))
2007
+ return true;
2008
+ seen.add(key);
2009
+ }
2010
+ }
2011
+ return (node.children ?? []).some(hasDuplicateObjectKeys);
2012
+ }
2013
+ function openClawDiscoveryEnvironment(env) {
2014
+ const filtered = Object.fromEntries(OPENCLAW_RELAY_DISCOVERY_ENV_KEYS.flatMap((key) => {
2015
+ const value = env[key];
2016
+ return value === void 0 ? [] : [[key, value]];
2017
+ }));
2018
+ const profile = normalizeOpenClawProfile(filtered.OPENCLAW_PROFILE);
2019
+ if (profile)
2020
+ filtered.OPENCLAW_PROFILE = profile;
2021
+ else
2022
+ delete filtered.OPENCLAW_PROFILE;
2023
+ return filtered;
2024
+ }
2025
+
2026
+ // node_modules/.pnpm/mcporter@0.13.10/node_modules/mcporter/dist/chrome-devtools-relay.js
2027
+ var DEFAULT_RELAY_PROBE_TIMEOUT_MS = 5e3;
2028
+ var MIN_RELAY_PROBE_TIMEOUT_MS = 100;
2029
+ var MAX_RELAY_PROBE_TIMEOUT_MS = 3e4;
2030
+ var DEFAULT_RELAY_URL = "http://127.0.0.1:18799";
2031
+ var DEFAULT_RELAY_IDENTITY_URL = new URL(DEFAULT_RELAY_URL).toString();
2032
+ var RELAY_DEPENDENCY_SENTINEL = "$MCPORTER_CHROME_RELAY_DEPENDENCY:";
2033
+ var RELAY_DISCOVERY_SENTINEL = "$MCPORTER_CHROME_RELAY_DISCOVERY:";
2034
+ var CHROME_DEVTOOLS_RELAY_RUNTIME_ENV_KEYS = [
2035
+ "MCPORTER_CHROME_DEVTOOLS_RELAY_POLICY",
2036
+ "MCPORTER_DISABLE_CHROME_DEVTOOLS_RELAY",
2037
+ "MCPORTER_CHROME_DEVTOOLS_RELAY_URL",
2038
+ "MCPORTER_CHROME_DEVTOOLS_RELAY_TIMEOUT_MS",
2039
+ ...OPENCLAW_RELAY_DISCOVERY_ENV_KEYS
2040
+ ];
2041
+ var ChromeDevtoolsRelayRequiredError = class extends Error {
2042
+ decision;
2043
+ constructor(decision) {
2044
+ super(`Chrome DevTools relay policy 'require' could not use the OpenClaw extension relay (${decision.reason}). No chrome-devtools-mcp process was launched.`);
2045
+ this.decision = decision;
2046
+ this.name = "ChromeDevtoolsRelayRequiredError";
2047
+ }
2048
+ };
2049
+ var lastDecisions = /* @__PURE__ */ new Map();
2050
+ function recordChromeDevtoolsRelayDecision(server, decision) {
2051
+ lastDecisions.set(server, decision);
2052
+ }
2053
+ function getChromeDevtoolsRelayDecision(server) {
2054
+ return lastDecisions.get(server);
2055
+ }
2056
+ function formatChromeDevtoolsRelayDecision(decision) {
2057
+ return JSON.stringify(decision);
2058
+ }
2059
+ function resolveChromeDevtoolsRelayProbeTimeoutMs(env = process.env) {
2060
+ const raw = env.MCPORTER_CHROME_DEVTOOLS_RELAY_TIMEOUT_MS?.trim();
2061
+ if (!raw || !/^\d+$/.test(raw))
2062
+ return DEFAULT_RELAY_PROBE_TIMEOUT_MS;
2063
+ const parsed = Number(raw);
2064
+ if (!Number.isSafeInteger(parsed) || parsed <= 0)
2065
+ return DEFAULT_RELAY_PROBE_TIMEOUT_MS;
2066
+ return Math.min(MAX_RELAY_PROBE_TIMEOUT_MS, Math.max(MIN_RELAY_PROBE_TIMEOUT_MS, parsed));
2067
+ }
2068
+ function resolveChromeDevtoolsRelayPolicy(configured, env = process.env) {
2069
+ if (env.MCPORTER_DISABLE_CHROME_DEVTOOLS_RELAY === "1")
2070
+ return "off";
2071
+ const raw = env.MCPORTER_CHROME_DEVTOOLS_RELAY_POLICY?.trim().toLowerCase();
2072
+ if (!raw)
2073
+ return configured ?? "prefer";
2074
+ if (raw === "off" || raw === "prefer" || raw === "require")
2075
+ return raw;
2076
+ throw new Error(`Invalid MCPORTER_CHROME_DEVTOOLS_RELAY_POLICY '${raw}'. Expected off, prefer, or require.`);
2077
+ }
2078
+ function isChromeDevtoolsAutoConnectCommand(command, args) {
2079
+ return resolveChromeDevtoolsAutoConnectCommand(command, args).enabled;
2080
+ }
2081
+ function explicitRelayBaseUrl(env) {
2082
+ const raw = env.MCPORTER_CHROME_DEVTOOLS_RELAY_URL?.trim();
2083
+ if (!raw)
2084
+ return { explicit: false };
2085
+ let url;
2086
+ try {
2087
+ url = new URL(raw);
2088
+ } catch {
2089
+ return { explicit: true };
2090
+ }
2091
+ if (url.protocol !== "http:" || !["127.0.0.1", "localhost", "[::1]", "::1"].includes(url.hostname) || url.username !== "" || url.password !== "" || url.search !== "" || url.hash !== "") {
2092
+ return { explicit: true };
2093
+ }
2094
+ return { explicit: true, url };
2095
+ }
2096
+ function resolveOpenClawCredentialDir(env) {
2097
+ const oauthOverride = env.OPENCLAW_OAUTH_DIR?.trim();
2098
+ if (oauthOverride)
2099
+ return resolveOpenClawPath(oauthOverride, env);
2100
+ const stateOverride = env.OPENCLAW_STATE_DIR?.trim();
2101
+ const profile = normalizeOpenClawProfile(env.OPENCLAW_PROFILE);
2102
+ const stateDir = stateOverride ? resolveOpenClawPath(stateOverride, env) : path2.join(resolveOpenClawHome(env), profile ? `.openclaw-${profile}` : ".openclaw");
2103
+ return path2.join(stateDir, "credentials");
2104
+ }
2105
+ function resolveOpenClawHome(env) {
2106
+ const override = env.OPENCLAW_HOME?.trim();
2107
+ const osHome = resolveOpenClawOsHome(env);
2108
+ if (!override)
2109
+ return osHome;
2110
+ if (override === "~")
2111
+ return osHome;
2112
+ if (override.startsWith("~/") || override.startsWith("~\\")) {
2113
+ return path2.resolve(osHome, override.slice(2));
2114
+ }
2115
+ return path2.resolve(override);
2116
+ }
2117
+ function resolveOpenClawOsHome(env) {
2118
+ for (const value of [env.HOME, env.USERPROFILE]) {
2119
+ const normalized = value?.trim();
2120
+ if (normalized && normalized !== "undefined" && normalized !== "null")
2121
+ return path2.resolve(normalized);
2122
+ }
2123
+ return os.homedir();
2124
+ }
2125
+ function resolveOpenClawPath(value, env) {
2126
+ if (value === "~")
2127
+ return resolveOpenClawHome(env);
2128
+ if (value.startsWith("~/") || value.startsWith("~\\")) {
2129
+ return path2.resolve(resolveOpenClawHome(env), value.slice(2));
2130
+ }
2131
+ return path2.resolve(value);
2132
+ }
2133
+ function defaultReadCredential(env) {
2134
+ const secretPath = path2.join(resolveOpenClawCredentialDir(env), "browser-extension-relay.secret");
2135
+ return readCredentialPath(secretPath);
2136
+ }
2137
+ function readCredentialPath(secretPath) {
2138
+ let descriptor;
2139
+ try {
2140
+ descriptor = fs.openSync(secretPath, fs.constants.O_RDONLY | (fs.constants.O_NOFOLLOW ?? 0));
2141
+ } catch (error) {
2142
+ return { reason: isErrno(error, "ENOENT") ? "missing-credential" : "invalid-credential" };
2143
+ }
2144
+ try {
2145
+ const stat = fs.fstatSync(descriptor);
2146
+ if (!stat.isFile())
2147
+ return { reason: "invalid-credential" };
2148
+ if (process.platform !== "win32") {
2149
+ if ((stat.mode & 63) !== 0)
2150
+ return { reason: "invalid-credential" };
2151
+ if (typeof process.getuid === "function" && stat.uid !== process.getuid())
2152
+ return { reason: "invalid-credential" };
2153
+ }
2154
+ const encoded = fs.readFileSync(descriptor, "utf8").trim();
2155
+ if (!/^[0-9a-f]{64}$/.test(encoded))
2156
+ return { reason: "invalid-credential" };
2157
+ const key = Buffer.from(encoded, "hex");
2158
+ return { credential: { key, keyId: deriveBrowserRelayKeyId(key) } };
2159
+ } catch {
2160
+ return { reason: "invalid-credential" };
2161
+ } finally {
2162
+ fs.closeSync(descriptor);
2163
+ }
2164
+ }
2165
+ async function defaultConnect(baseUrl, credential, timeoutMs) {
2166
+ return await connectChromeDevtoolsRelayV2({ baseUrl, credential, timeoutMs });
2167
+ }
2168
+ async function rewriteChromeDevtoolsArgsForRelay(command, args, env = process.env, options = {}, configuredPolicy) {
2169
+ const relayEnv = selectChromeDevtoolsRelayRuntimeEnvironment(env);
2170
+ const eligible = isChromeDevtoolsAutoConnectCommand(command, args);
2171
+ if (!eligible) {
2172
+ const ambiguous = isAmbiguousChromeDevtoolsAutoConnectCommand(command, args);
2173
+ if (!ambiguous) {
2174
+ return decide({
2175
+ args,
2176
+ applied: false,
2177
+ decision: { route: "legacy", reason: "not-eligible", policy: configuredPolicy ?? "prefer" }
2178
+ }, options);
2179
+ }
2180
+ const ambiguousPolicy = resolveChromeDevtoolsRelayPolicy(configuredPolicy, relayEnv);
2181
+ if (ambiguousPolicy === "require") {
2182
+ return unavailableOrLegacy(args, ambiguousPolicy, "unsupported-command", void 0, options);
2183
+ }
2184
+ return decide({
2185
+ args,
2186
+ applied: false,
2187
+ decision: { route: "legacy", reason: "not-eligible", policy: ambiguousPolicy }
2188
+ }, options);
2189
+ }
2190
+ const policy = resolveChromeDevtoolsRelayPolicy(configuredPolicy, relayEnv);
2191
+ if (policy === "off") {
2192
+ return decide({ args, applied: false, decision: { route: "legacy", reason: "disabled", policy } }, options);
2193
+ }
2194
+ const explicitBase = explicitRelayBaseUrl(relayEnv);
2195
+ if (explicitBase.explicit && !explicitBase.url) {
2196
+ return unavailableOrLegacy(args, policy, "invalid-endpoint", void 0, options);
2197
+ }
2198
+ const loaded = options.readToken ? (() => {
2199
+ const encoded = options.readToken?.();
2200
+ if (!encoded)
2201
+ return { reason: "missing-credential" };
2202
+ if (!/^[0-9a-f]{64}$/u.test(encoded))
2203
+ return { reason: "invalid-credential" };
2204
+ const key = Buffer.from(encoded, "hex");
2205
+ return { credential: { key, keyId: deriveBrowserRelayKeyId(key) } };
2206
+ })() : defaultReadCredential(relayEnv);
2207
+ if (!loaded.credential) {
2208
+ const base = explicitBase.url ?? new URL(DEFAULT_RELAY_URL);
2209
+ const upstreamEndpoint = new URL("/cdp", base);
2210
+ upstreamEndpoint.protocol = "ws:";
2211
+ return unavailableOrLegacy(args, policy, loaded.reason ?? "invalid-credential", upstreamEndpoint.toString(), options);
2212
+ }
2213
+ const timeoutMs = resolveChromeDevtoolsRelayProbeTimeoutMs(relayEnv);
2214
+ try {
2215
+ const base = explicitBase.url ?? (await discoverOpenClawRelayUrl({
2216
+ env: relayEnv,
2217
+ keyId: loaded.credential.keyId,
2218
+ timeoutMs,
2219
+ run: options.discover,
2220
+ platform: options.discovery?.platform,
2221
+ isFile: options.discovery?.isFile,
2222
+ cwd: options.discovery?.cwd
2223
+ })).url ?? new URL(DEFAULT_RELAY_URL);
2224
+ const upstreamEndpoint = new URL("/cdp", base);
2225
+ upstreamEndpoint.protocol = "ws:";
2226
+ const endpoint = upstreamEndpoint.toString();
2227
+ let probe;
2228
+ try {
2229
+ probe = await (options.connect ?? defaultConnect)(base, loaded.credential, timeoutMs);
2230
+ } catch {
2231
+ return unavailableOrLegacy(args, policy, "network-error", endpoint, options);
2232
+ }
2233
+ const probeDetails = { probeDurationMs: probe.durationMs, probeStatus: probe.status };
2234
+ if (probe.reason !== "success" || !probe.upstream) {
2235
+ probe.upstream?.socket.destroy();
2236
+ const reason = probe.reason === "success" ? "protocol" : probe.reason;
2237
+ return unavailableOrLegacy(args, policy, reason, endpoint, options, probeDetails);
2238
+ }
2239
+ let proxy;
2240
+ try {
2241
+ proxy = await (options.startProxy ?? startChromeDevtoolsRelayProxy)({ upstream: probe.upstream });
2242
+ } catch {
2243
+ probe.upstream.socket.destroy();
2244
+ return unavailableOrLegacy(args, policy, "network-error", endpoint, options, probeDetails);
2245
+ }
2246
+ const rewritten = replaceChromeDevtoolsAutoConnectArgs(command, args, ["--wsEndpoint", proxy.endpoint]);
2247
+ try {
2248
+ return decide({
2249
+ args: rewritten,
2250
+ applied: true,
2251
+ endpoint: proxy.endpoint,
2252
+ proxy,
2253
+ decision: { route: "relay", reason: "success", policy, endpoint, ...probeDetails }
2254
+ }, options);
2255
+ } catch (error) {
2256
+ await proxy.close().catch(() => {
2257
+ });
2258
+ throw error;
2259
+ }
2260
+ } finally {
2261
+ loaded.credential.key.fill(0);
2262
+ }
2263
+ }
2264
+ function unavailableOrLegacy(args, policy, reason, endpoint, options, probe = {}) {
2265
+ const decision = {
2266
+ route: policy === "require" ? "unavailable" : "legacy",
2267
+ reason,
2268
+ policy,
2269
+ endpoint,
2270
+ ...probe
2271
+ };
2272
+ options.onDecision?.(decision);
2273
+ if (policy === "require")
2274
+ throw new ChromeDevtoolsRelayRequiredError(decision);
2275
+ return { args, applied: false, decision };
2276
+ }
2277
+ function decide(result, options) {
2278
+ options.onDecision?.(result.decision);
2279
+ return result;
2280
+ }
2281
+ function resolveChromeDevtoolsRelayEnvironment(overrides, env = process.env) {
2282
+ return { ...env, ...resolveRelayDefinitionEnvOverrides(overrides, env) };
2283
+ }
2284
+ function selectChromeDevtoolsRelayRuntimeEnvironment(env) {
2285
+ return Object.fromEntries(CHROME_DEVTOOLS_RELAY_RUNTIME_ENV_KEYS.flatMap((key) => {
2286
+ const value = env[key];
2287
+ return value === void 0 ? [] : [[key, value]];
2288
+ }));
2289
+ }
2290
+ function sanitizeRelayIdentityEnvironment(env) {
2291
+ const selected = selectChromeDevtoolsRelayRuntimeEnvironment(env);
2292
+ if (selected.MCPORTER_CHROME_DEVTOOLS_RELAY_URL !== void 0) {
2293
+ const explicit = explicitRelayBaseUrl(selected);
2294
+ selected.MCPORTER_CHROME_DEVTOOLS_RELAY_URL = explicit.explicit ? explicit.url?.toString() ?? "invalid-endpoint" : "";
2295
+ }
2296
+ return selected;
2297
+ }
2298
+ function chromeDevtoolsRelayEnvironmentKeys(definitions, env = process.env) {
2299
+ const keys = /* @__PURE__ */ new Set();
2300
+ for (const definition of definitions) {
2301
+ if (definition.command.kind !== "stdio")
2302
+ continue;
2303
+ const commandValues = [definition.command.command, ...definition.command.args];
2304
+ const commandEnvironmentKeys = new Set(commandValues.flatMap(referencedEnvironmentVariables));
2305
+ const relevant = commandEnvironmentKeys.size > 0 || isChromeDevtoolsAutoConnectCommand(definition.command.command, definition.command.args) || isAmbiguousChromeDevtoolsAutoConnectCommand(definition.command.command, definition.command.args);
2306
+ if (!relevant) {
2307
+ continue;
2308
+ }
2309
+ for (const key of commandEnvironmentKeys)
2310
+ keys.add(`${RELAY_DEPENDENCY_SENTINEL}${key}`);
2311
+ const resolvedDefinitionEnv = resolveRelayIdentityEnvOverrides(definition.env, env);
2312
+ for (const key of CHROME_DEVTOOLS_RELAY_RUNTIME_ENV_KEYS) {
2313
+ const override = definition.env?.[key];
2314
+ if (!override)
2315
+ continue;
2316
+ for (const referenced of referencedEnvironmentVariables(override))
2317
+ keys.add(`${RELAY_DEPENDENCY_SENTINEL}${referenced}`);
2318
+ }
2319
+ const resolvedCommand = resolveCommandArgument(definition.command.command, env);
2320
+ const resolvedArgs = resolveCommandArguments(definition.command.args, env);
2321
+ const eligible = isChromeDevtoolsAutoConnectCommand(resolvedCommand, resolvedArgs);
2322
+ if (!eligible && !isAmbiguousChromeDevtoolsAutoConnectCommand(resolvedCommand, resolvedArgs))
2323
+ continue;
2324
+ const environment = sanitizeRelayIdentityEnvironment(resolvedDefinitionEnv);
2325
+ keys.add(`${RELAY_DISCOVERY_SENTINEL}${Buffer.from(JSON.stringify({
2326
+ server: definition.name,
2327
+ eligible,
2328
+ environment,
2329
+ configuredPolicy: definition.chromeDevtoolsRelay
2330
+ }), "utf8").toString("base64url")}`);
2331
+ }
2332
+ return [...keys].toSorted();
2333
+ }
2334
+ async function resolveChromeDevtoolsRelayRuntimeIdentity(keys, env = process.env, options = {}) {
2335
+ const { values, relays } = relayEnvironmentIdentityValues(keys, env);
2336
+ for (const relay of relays) {
2337
+ let endpoint = relay.endpoint;
2338
+ if (relay.discover && relay.keyId !== "missing-credential" && relay.keyId !== "invalid-credential") {
2339
+ try {
2340
+ const discovered = await discoverOpenClawRelayUrl({
2341
+ env: relay.env,
2342
+ keyId: relay.keyId,
2343
+ timeoutMs: relay.timeoutMs,
2344
+ run: options.discover,
2345
+ platform: options.discovery?.platform,
2346
+ isFile: options.discovery?.isFile,
2347
+ cwd: options.discovery?.cwd
2348
+ });
2349
+ endpoint = discovered.url?.toString() ?? DEFAULT_RELAY_IDENTITY_URL;
2350
+ } catch {
2351
+ endpoint = DEFAULT_RELAY_IDENTITY_URL;
2352
+ }
2353
+ }
2354
+ values.push([relay.server, endpoint]);
2355
+ }
2356
+ return hashRelayIdentityValues(values);
2357
+ }
2358
+ function createRelayCredentialIdResolver() {
2359
+ const credentialIds = /* @__PURE__ */ new Map();
2360
+ return (credentialPath) => {
2361
+ const cached = credentialIds.get(credentialPath);
2362
+ if (cached)
2363
+ return cached;
2364
+ const loaded = readCredentialPath(credentialPath);
2365
+ const value = loaded.credential?.keyId ?? loaded.reason ?? "missing-credential";
2366
+ loaded.credential?.key.fill(0);
2367
+ credentialIds.set(credentialPath, value);
2368
+ return value;
2369
+ };
2370
+ }
2371
+ function relayEnvironmentIdentityValues(keys, env) {
2372
+ const credentialId = createRelayCredentialIdResolver();
2373
+ const values = [];
2374
+ const relays = [];
2375
+ for (const key of keys) {
2376
+ if (key.startsWith(RELAY_DEPENDENCY_SENTINEL)) {
2377
+ values.push([key, env[key.slice(RELAY_DEPENDENCY_SENTINEL.length)] ?? null]);
2378
+ continue;
2379
+ }
2380
+ if (!key.startsWith(RELAY_DISCOVERY_SENTINEL)) {
2381
+ values.push([key, relayEnvironmentIdentityValue(key, env)]);
2382
+ continue;
2383
+ }
2384
+ const payload = parseRelayDiscoveryIdentity(key.slice(RELAY_DISCOVERY_SENTINEL.length));
2385
+ if (!payload)
2386
+ throw new Error("Invalid Chrome DevTools relay identity metadata");
2387
+ const effectiveEnv = { ...selectChromeDevtoolsRelayRuntimeEnvironment(env), ...payload.environment };
2388
+ const policy = resolveChromeDevtoolsRelayPolicy(payload.configuredPolicy, effectiveEnv);
2389
+ const timeoutMs = resolveChromeDevtoolsRelayProbeTimeoutMs(effectiveEnv);
2390
+ const explicit = explicitRelayBaseUrl(effectiveEnv);
2391
+ const credentialDir = resolveOpenClawCredentialDir(effectiveEnv);
2392
+ const keyId = payload.eligible ? credentialId(path2.join(credentialDir, "browser-extension-relay.secret")) : "not-eligible";
2393
+ const server = `$relay:${payload.server}`;
2394
+ values.push([
2395
+ server,
2396
+ JSON.stringify({
2397
+ policy,
2398
+ timeoutMs,
2399
+ eligible: payload.eligible,
2400
+ credentialDir,
2401
+ keyId,
2402
+ // These values also reach the discovery subprocess; retain inputs whose equivalence it does not guarantee.
2403
+ discovery: OPENCLAW_RELAY_DISCOVERY_ENV_KEYS.map((name) => [
2404
+ name,
2405
+ relayEnvironmentIdentityValue(name, effectiveEnv)
2406
+ ]),
2407
+ cwd: relayIdentityDependsOnCwd(effectiveEnv) ? process.cwd() : null
2408
+ })
2409
+ ]);
2410
+ relays.push({
2411
+ server,
2412
+ env: effectiveEnv,
2413
+ timeoutMs,
2414
+ keyId,
2415
+ endpoint: policy === "off" ? "disabled" : explicit.explicit ? explicit.url?.toString() ?? "invalid-endpoint" : DEFAULT_RELAY_IDENTITY_URL,
2416
+ discover: payload.eligible && policy !== "off" && !explicit.explicit
2417
+ });
2418
+ }
2419
+ if (keys.length > 0)
2420
+ values.push(["$relayAuth", "v2-effective-metadata-discovery"]);
2421
+ return { values, relays };
2422
+ }
2423
+ function relayEnvironmentIdentityValue(key, env) {
2424
+ switch (key) {
2425
+ case "MCPORTER_CHROME_DEVTOOLS_RELAY_POLICY":
2426
+ case "MCPORTER_DISABLE_CHROME_DEVTOOLS_RELAY":
2427
+ return resolveChromeDevtoolsRelayPolicy(void 0, env);
2428
+ case "MCPORTER_CHROME_DEVTOOLS_RELAY_TIMEOUT_MS":
2429
+ return resolveChromeDevtoolsRelayProbeTimeoutMs(env);
2430
+ case "MCPORTER_CHROME_DEVTOOLS_RELAY_URL": {
2431
+ const explicit = explicitRelayBaseUrl(env);
2432
+ return explicit.explicit ? explicit.url?.toString() ?? "invalid-endpoint" : DEFAULT_RELAY_IDENTITY_URL;
2433
+ }
2434
+ case "OPENCLAW_PROFILE":
2435
+ return normalizeOpenClawProfile(env.OPENCLAW_PROFILE) ?? null;
2436
+ default:
2437
+ return env[key] ?? null;
2438
+ }
2439
+ }
2440
+ function relayIdentityDependsOnCwd(env) {
2441
+ const paths = [
2442
+ env.HOME,
2443
+ env.USERPROFILE,
2444
+ env.OPENCLAW_HOME,
2445
+ env.OPENCLAW_STATE_DIR,
2446
+ env.OPENCLAW_OAUTH_DIR,
2447
+ env.OPENCLAW_CONFIG_PATH,
2448
+ ...(env.PATH ?? env.Path)?.split(path2.delimiter) ?? []
2449
+ ];
2450
+ return paths.some((value) => value !== void 0 && !path2.isAbsolute(value) && !value.startsWith("~"));
2451
+ }
2452
+ function hashRelayIdentityValues(values) {
2453
+ return createHash3("sha256").update(JSON.stringify(values.toSorted((a, b) => a[0].localeCompare(b[0]) || JSON.stringify(a[1]).localeCompare(JSON.stringify(b[1]))))).digest("hex").slice(0, 16);
2454
+ }
2455
+ function parseRelayDiscoveryIdentity(encoded) {
2456
+ try {
2457
+ const value = JSON.parse(Buffer.from(encoded, "base64url").toString("utf8"));
2458
+ if (!value || typeof value !== "object" || Array.isArray(value))
2459
+ return void 0;
2460
+ const candidate = value;
2461
+ if (typeof candidate.server !== "string" || typeof candidate.eligible !== "boolean" || !candidate.environment || typeof candidate.environment !== "object")
2462
+ return void 0;
2463
+ if (candidate.configuredPolicy !== void 0 && !["off", "prefer", "require"].includes(candidate.configuredPolicy))
2464
+ return void 0;
2465
+ const environment = {};
2466
+ for (const [key, raw] of Object.entries(candidate.environment)) {
2467
+ if (!CHROME_DEVTOOLS_RELAY_RUNTIME_ENV_KEYS.includes(key) || typeof raw !== "string")
2468
+ return void 0;
2469
+ environment[key] = raw;
2470
+ }
2471
+ return {
2472
+ server: candidate.server,
2473
+ eligible: candidate.eligible,
2474
+ environment,
2475
+ configuredPolicy: candidate.configuredPolicy
2476
+ };
2477
+ } catch {
2478
+ return void 0;
2479
+ }
2480
+ }
2481
+ function referencedEnvironmentVariables(value) {
2482
+ const names = /* @__PURE__ */ new Set();
2483
+ if (value.startsWith("$env:"))
2484
+ names.add(value.slice("$env:".length));
2485
+ for (const match of value.matchAll(/\$\{([A-Za-z_][A-Za-z0-9_]*)/gu)) {
2486
+ if (match[1])
2487
+ names.add(match[1]);
2488
+ }
2489
+ return [...names];
2490
+ }
2491
+ function resolveRelayDefinitionEnvOverrides(overrides, env) {
2492
+ const resolved = {};
2493
+ for (const [key, raw] of Object.entries(overrides ?? {})) {
2494
+ const value = resolveEnvValue(raw, env);
2495
+ if (value !== "")
2496
+ resolved[key] = value;
2497
+ }
2498
+ return resolved;
2499
+ }
2500
+ function resolveRelayIdentityEnvOverrides(overrides, env) {
2501
+ const relevant = Object.fromEntries(CHROME_DEVTOOLS_RELAY_RUNTIME_ENV_KEYS.flatMap((key) => {
2502
+ const value = overrides?.[key];
2503
+ return value === void 0 ? [] : [[key, value]];
2504
+ }));
2505
+ return resolveRelayDefinitionEnvOverrides(relevant, env);
2506
+ }
2507
+ function isErrno(error, code) {
2508
+ return Boolean(error && typeof error === "object" && error.code === code);
2509
+ }
2510
+
2511
+ // node_modules/.pnpm/mcporter@0.13.10/node_modules/mcporter/dist/daemon/connection-identity.js
2512
+ var BROKER_ENV = /* @__PURE__ */ new Set([
2513
+ "MCPORTER_DAEMON_DIR",
2514
+ "MCPORTER_DAEMON_CHILD",
2515
+ "MCPORTER_DAEMON_SOCKET",
2516
+ "MCPORTER_DAEMON_METADATA",
2517
+ "MCPORTER_CONFIG",
2518
+ "MCPORTER_DISABLE_AUTORUN",
2519
+ "MCPORTER_DAEMON_LOG",
2520
+ "MCPORTER_DAEMON_LOG_PATH",
2521
+ "MCPORTER_DAEMON_LOG_SERVERS",
2522
+ "MCPORTER_NO_FORCE_EXIT"
2523
+ ]);
2524
+ async function effectiveDefinition(definition, inherited = process.env, purpose = "connection") {
2525
+ const env = Object.fromEntries(Object.entries(resolveChromeDevtoolsRelayEnvironment(definition.env, inherited)).filter(([key, value]) => value !== void 0 && !BROKER_ENV.has(key)));
2526
+ const configuredEnv = Object.fromEntries(Object.keys(definition.env ?? {}).filter((key) => !BROKER_ENV.has(key)).map((key) => [key, env[key] ?? ""]));
2527
+ normalizeChromeEnvironment(definition, env);
2528
+ const chrome = isChromeDefinition(definition);
2529
+ const launchCommand = definition.command.kind === "stdio" ? resolveCommandArgument(definition.command.command, env) : void 0;
2530
+ const command = definition.command.kind === "stdio" ? {
2531
+ ...definition.command,
2532
+ command: chrome && purpose === "view" ? launchCommand : await resolveExecutable(launchCommand, env, definition.command.cwd),
2533
+ args: resolveCommandArguments(definition.command.args, env),
2534
+ cwd: await fs2.realpath(definition.command.cwd)
2535
+ } : { ...definition.command, url: new URL(definition.command.url) };
2536
+ if (command.kind === "stdio") {
2537
+ if (!Object.hasOwn(configuredEnv, "PWD"))
2538
+ env.PWD = command.cwd;
2539
+ if (!Object.hasOwn(configuredEnv, "SHLVL"))
2540
+ delete env.SHLVL;
2541
+ }
2542
+ return { ...definition, command, env, configuredEnv, ...chrome ? { launchCommand } : {} };
2543
+ }
2544
+ function normalizeChromeEnvironment(definition, env) {
2545
+ if (isChromeDefinition(definition)) {
2546
+ env.MCPORTER_CHROME_DEVTOOLS_RELAY_POLICY = resolveChromeDevtoolsRelayPolicy(definition.chromeDevtoolsRelay, env);
2547
+ env.MCPORTER_CHROME_DEVTOOLS_RELAY_TIMEOUT_MS = String(resolveChromeDevtoolsRelayProbeTimeoutMs(env));
2548
+ delete env.MCPORTER_DISABLE_CHROME_DEVTOOLS_RELAY;
2549
+ if (!env.OPENCLAW_PROFILE?.trim() || env.OPENCLAW_PROFILE.trim() === "default")
2550
+ delete env.OPENCLAW_PROFILE;
2551
+ if (env.MCPORTER_CHROME_DEVTOOLS_RELAY_URL?.trim())
2552
+ env.MCPORTER_CHROME_DEVTOOLS_RELAY_URL = new URL(env.MCPORTER_CHROME_DEVTOOLS_RELAY_URL.trim()).toString();
2553
+ else
2554
+ delete env.MCPORTER_CHROME_DEVTOOLS_RELAY_URL;
2555
+ }
2556
+ }
2557
+ async function resolveExecutable(command, env, cwd) {
2558
+ const roots = /[/\\]/.test(command) ? [path3.resolve(cwd, command)] : (env.PATH ?? env.Path ?? "").split(path3.delimiter).map((dir) => path3.resolve(cwd, dir, command));
2559
+ const extensions = process.platform === "win32" && !path3.extname(command) ? ["", ...(env.PATHEXT ?? ".COM;.EXE;.BAT;.CMD").split(";")] : [""];
2560
+ const candidates = roots.flatMap((root) => extensions.map((extension) => root + extension));
2561
+ for (const candidate of candidates) {
2562
+ try {
2563
+ await fs2.access(candidate, fs2.constants.X_OK);
2564
+ return path3.join(await fs2.realpath(path3.dirname(candidate)), path3.basename(candidate));
2565
+ } catch {
2566
+ }
2567
+ }
2568
+ throw new Error("Unable to resolve configured executable from the effective PATH.");
2569
+ }
2570
+ function connectionIdentity(definition) {
2571
+ const { name, description: _description, source: _source, sources: _sources, allowedTools: _allowed, blockedTools: _blocked, lifecycle: _lifecycle, configuredEnv: _configuredEnv, launchCommand: _launchCommand, logging: _logging, ...connection } = definition;
2572
+ const credentialOwner = definition.auth || definition.command.kind === "http" ? name : void 0;
2573
+ const env = { ...definition.env };
2574
+ const chrome = isChromeDefinition(definition);
2575
+ if (chrome) {
2576
+ env.MCPORTER_CHROME_DEVTOOLS_RELAY_POLICY = resolveChromeDevtoolsRelayPolicy(definition.chromeDevtoolsRelay, env);
2577
+ delete env.MCPORTER_DISABLE_CHROME_DEVTOOLS_RELAY;
2578
+ env.MCPORTER_CHROME_DEVTOOLS_RELAY_TIMEOUT_MS = String(resolveChromeDevtoolsRelayProbeTimeoutMs(env));
2579
+ }
2580
+ return createHash4("sha256").update(stableJsonStringify({
2581
+ ...connection,
2582
+ env,
2583
+ credentialOwner,
2584
+ idleTimeoutMs: !chrome && definition.lifecycle?.mode === "keep-alive" ? definition.lifecycle.idleTimeoutMs : void 0,
2585
+ protocolVersion: definition.protocolVersion ?? "auto",
2586
+ httpFetch: definition.httpFetch ?? "default",
2587
+ chromeDevtoolsRelay: chrome ? env.MCPORTER_CHROME_DEVTOOLS_RELAY_POLICY : void 0
2588
+ })).digest("hex");
2589
+ }
2590
+ function isChromeDefinition(definition) {
2591
+ return definition.command.kind === "stdio" && [definition.name, definition.command.command, ...definition.command.args].some((value) => /chrome[-_]devtools(?:[-_]mcp)?/i.test(value));
2592
+ }
2593
+
2594
+ // node_modules/.pnpm/mcporter@0.13.10/node_modules/mcporter/dist/daemon/browser-owner.js
2595
+ import os4 from "node:os";
2596
+ import path6 from "node:path";
2597
+
2598
+ // node_modules/.pnpm/mcporter@0.13.10/node_modules/mcporter/dist/daemon/paths.js
2599
+ import fs4 from "node:fs/promises";
2600
+ import { constants } from "node:fs";
2601
+ import { createHash as createHash5 } from "node:crypto";
2602
+
2603
+ // node_modules/.pnpm/mcporter@0.13.10/node_modules/mcporter/dist/chrome-devtools-relay-handoff.js
2604
+ import { spawnSync } from "node:child_process";
2605
+ import { randomBytes as randomBytes3 } from "node:crypto";
2606
+ import fs3 from "node:fs";
2607
+ import os2 from "node:os";
2608
+ import path4 from "node:path";
2609
+ import { pathToFileURL } from "node:url";
2610
+ var CHROME_RELAY_HANDOFF_ENV = "MCPORTER_CHROME_RELAY_HANDOFF_PATH";
2611
+ var HANDOFF_DIR_PREFIX = "mcporter-chrome-relay-";
2612
+ var HANDOFF_FILENAME = "headers.json";
2613
+ var PRELOAD_FILENAME = "preload.mjs";
2614
+ var WINDOWS_ACL_PATH_ENV = "MCPORTER_CHROME_RELAY_ACL_PATH";
2615
+ function createChromeDevtoolsRelayHandoff(env, clientAuthorization) {
2616
+ let directory;
2617
+ try {
2618
+ if (process.platform === "win32")
2619
+ directory = createWindowsHandoffDirectory();
2620
+ else {
2621
+ directory = fs3.mkdtempSync(path4.join(os2.tmpdir(), HANDOFF_DIR_PREFIX));
2622
+ fs3.chmodSync(directory, 448);
2623
+ }
2624
+ assertSecurePath(directory, "directory");
2625
+ const handoffPath = path4.join(directory, HANDOFF_FILENAME);
2626
+ const preloadPath = path4.join(directory, PRELOAD_FILENAME);
2627
+ writeExclusiveFile(preloadPath, renderChromeDevtoolsRelayPreloadSource());
2628
+ writeExclusiveFile(handoffPath, JSON.stringify({ Authorization: clientAuthorization }));
2629
+ const importFlag = `--import=${pathToFileURL(preloadPath).href}`;
2630
+ const existingOptions = env.NODE_OPTIONS?.trim();
2631
+ let closed = false;
2632
+ return {
2633
+ env: {
2634
+ ...env,
2635
+ NODE_OPTIONS: existingOptions ? `${existingOptions} ${importFlag}` : importFlag,
2636
+ [CHROME_RELAY_HANDOFF_ENV]: handoffPath
2637
+ },
2638
+ handoffPath,
2639
+ preloadPath,
2640
+ async close() {
2641
+ if (closed)
2642
+ return;
2643
+ closed = true;
2644
+ cleanupHandoff(directory, handoffPath, preloadPath);
2645
+ }
2646
+ };
2647
+ } catch (error) {
2648
+ if (directory)
2649
+ cleanupHandoff(directory, path4.join(directory, HANDOFF_FILENAME), path4.join(directory, PRELOAD_FILENAME));
2650
+ const diagnostic = error instanceof Error && error.message.startsWith("Windows ACL setup failed:") ? ` ${error.message}` : "";
2651
+ throw new Error(`Unable to install secure Chrome relay authorization handoff.${diagnostic}`, { cause: error });
2652
+ }
2653
+ }
2654
+ function createWindowsHandoffDirectory() {
2655
+ const directory = path4.join(os2.tmpdir(), `${HANDOFF_DIR_PREFIX}${randomBytes3(16).toString("hex")}`);
2656
+ ensureWindowsPrivateDirectory(directory);
2657
+ return directory;
2658
+ }
2659
+ function ensureWindowsPrivateDirectory(directory, allowExisting = false) {
2660
+ const script = String.raw`
2661
+ $ErrorActionPreference = 'Stop'
2662
+ $stage = 'identity'
2663
+ try {
2664
+ $target = $env:${WINDOWS_ACL_PATH_ENV}
2665
+ ${allowExisting ? "" : "if ([System.IO.Directory]::Exists($target)) { throw 'handoff path already exists' }"}
2666
+ if ([System.IO.Directory]::Exists($target) -and (([System.IO.File]::GetAttributes($target) -band [System.IO.FileAttributes]::ReparsePoint) -ne 0)) { throw 'unsafe reparse point' }
2667
+ $sid = [System.Security.Principal.WindowsIdentity]::GetCurrent().User
2668
+ $stage = 'descriptor'
2669
+ $security = New-Object System.Security.AccessControl.DirectorySecurity
2670
+ $sidValue = $sid.Value
2671
+ $security.SetSecurityDescriptorSddlForm("O:$($sidValue)G:$($sidValue)D:P(A;OICI;FA;;;$($sidValue))")
2672
+ $directory = New-Object System.IO.DirectoryInfo -ArgumentList @($target)
2673
+ $stage = 'create'
2674
+ $directory.Create($security)
2675
+ $stage = 'acl-read'
2676
+ $check = $directory.GetAccessControl([System.Security.AccessControl.AccessControlSections]::All)
2677
+ $rules = @($check.GetAccessRules($true, $true, [System.Security.Principal.SecurityIdentifier]))
2678
+ $ownerSid = $check.GetOwner([System.Security.Principal.SecurityIdentifier]).Value
2679
+ $stage = 'acl-verify'
2680
+ if (-not $check.AreAccessRulesProtected -or $ownerSid -ne $sid.Value -or $rules.Count -ne 1) { throw 'unsafe ACL' }
2681
+ $ruleSid = $rules[0].IdentityReference.Value
2682
+ $hasFullControl = ($rules[0].FileSystemRights -band [System.Security.AccessControl.FileSystemRights]::FullControl) -eq [System.Security.AccessControl.FileSystemRights]::FullControl
2683
+ if ($ruleSid -ne $sid.Value -or $rules[0].IsInherited -or -not $hasFullControl -or $rules[0].AccessControlType -ne [System.Security.AccessControl.AccessControlType]::Allow) { throw 'unsafe ACL' }
2684
+ } catch {
2685
+ $type = $_.Exception.GetType().FullName
2686
+ $hresult = ('0x{0:X8}' -f ($_.Exception.HResult -band 0xffffffffL))
2687
+ [Console]::Error.WriteLine("stage=$stage type=$type hresult=$hresult")
2688
+ exit 1
2689
+ }
2690
+ `;
2691
+ const result = spawnSync(resolveSystemPowerShellPath(), ["-NoLogo", "-NoProfile", "-NonInteractive", "-Command", script], {
2692
+ encoding: "utf8",
2693
+ env: { ...process.env, [WINDOWS_ACL_PATH_ENV]: directory },
2694
+ stdio: ["ignore", "ignore", "pipe"],
2695
+ windowsHide: true
2696
+ });
2697
+ if (result.status !== 0) {
2698
+ try {
2699
+ if (!allowExisting)
2700
+ fs3.rmdirSync(directory);
2701
+ } catch {
2702
+ }
2703
+ const stderr = typeof result.stderr === "string" ? result.stderr.trim() : "";
2704
+ const safeDetail = /^[A-Za-z0-9_.:=\- ]{1,240}$/u.test(stderr) ? stderr : `stage=spawn type=${result.error?.code ?? "unknown"} hresult=unknown`;
2705
+ throw new Error(`Windows ACL setup failed: ${safeDetail}`);
2706
+ }
2707
+ }
2708
+ function resolveSystemPowerShellPath() {
2709
+ const systemRoot = process.env.SystemRoot?.trim() || process.env.WINDIR?.trim();
2710
+ if (!systemRoot || !path4.win32.isAbsolute(systemRoot))
2711
+ throw new Error("unsafe Windows system root");
2712
+ const executable = path4.win32.join(systemRoot, "System32", "WindowsPowerShell", "v1.0", "powershell.exe");
2713
+ const stat = fs3.lstatSync(executable);
2714
+ if (!stat.isFile() || stat.isSymbolicLink())
2715
+ throw new Error("unsafe Windows PowerShell path");
2716
+ return executable;
2717
+ }
2718
+ function writeExclusiveFile(filePath, contents) {
2719
+ const descriptor = fs3.openSync(filePath, fs3.constants.O_WRONLY | fs3.constants.O_CREAT | fs3.constants.O_EXCL | (fs3.constants.O_NOFOLLOW ?? 0), 384);
2720
+ try {
2721
+ if (process.platform !== "win32")
2722
+ fs3.fchmodSync(descriptor, 384);
2723
+ fs3.writeFileSync(descriptor, contents, "utf8");
2724
+ } finally {
2725
+ fs3.closeSync(descriptor);
2726
+ }
2727
+ assertSecurePath(filePath, "file");
2728
+ }
2729
+ function assertSecurePath(filePath, kind) {
2730
+ const stat = fs3.lstatSync(filePath);
2731
+ if ((kind === "directory" ? !stat.isDirectory() : !stat.isFile()) || stat.isSymbolicLink())
2732
+ throw new Error("unsafe");
2733
+ if (process.platform === "win32")
2734
+ return;
2735
+ if ((stat.mode & 63) !== 0)
2736
+ throw new Error("unsafe");
2737
+ if (typeof process.getuid === "function" && stat.uid !== process.getuid())
2738
+ throw new Error("unsafe");
2739
+ }
2740
+ function cleanupHandoff(directory, handoffPath, preloadPath) {
2741
+ for (const filePath of [handoffPath, preloadPath]) {
2742
+ try {
2743
+ fs3.unlinkSync(filePath);
2744
+ } catch {
2745
+ }
2746
+ }
2747
+ try {
2748
+ fs3.rmdirSync(directory);
2749
+ } catch {
2750
+ }
2751
+ }
2752
+ function renderChromeDevtoolsRelayPreloadSource() {
2753
+ return `import fs from 'node:fs';
2754
+ import path from 'node:path';
2755
+
2756
+ const targetPath = process.argv[1]?.replaceAll('\\\\', '/').toLowerCase();
2757
+ if (targetPath?.includes('chrome-devtools-mcp')) {
2758
+ const failureMessage = 'MCPorter Chrome relay authorization handoff unavailable.';
2759
+ const fail = () => {
2760
+ throw new Error(failureMessage);
2761
+ };
2762
+ const envName = ${JSON.stringify(CHROME_RELAY_HANDOFF_ENV)};
2763
+ const handoffPath = process.env[envName];
2764
+ delete process.env[envName];
2765
+ if (!handoffPath || !path.isAbsolute(handoffPath)) fail();
2766
+
2767
+ const directoryStat = (() => {
2768
+ try {
2769
+ return fs.lstatSync(path.dirname(handoffPath));
2770
+ } catch {
2771
+ return fail();
2772
+ }
2773
+ })();
2774
+ if (!directoryStat.isDirectory() || directoryStat.isSymbolicLink()) fail();
2775
+ if (process.platform !== 'win32') {
2776
+ if ((directoryStat.mode & 0o077) !== 0) fail();
2777
+ if (typeof process.getuid === 'function' && directoryStat.uid !== process.getuid()) fail();
2778
+ }
2779
+
2780
+ const descriptor = (() => {
2781
+ try {
2782
+ return fs.openSync(handoffPath, fs.constants.O_RDONLY | (fs.constants.O_NOFOLLOW ?? 0));
2783
+ } catch {
2784
+ return fail();
2785
+ }
2786
+ })();
2787
+
2788
+ let raw = '';
2789
+ let consumed = false;
2790
+ try {
2791
+ const stat = fs.fstatSync(descriptor);
2792
+ if (!stat.isFile() || stat.size <= 0 || stat.size > 4_096) fail();
2793
+ if (process.platform !== 'win32') {
2794
+ if ((stat.mode & 0o077) !== 0) fail();
2795
+ if (typeof process.getuid === 'function' && stat.uid !== process.getuid()) fail();
2796
+ }
2797
+ raw = fs.readFileSync(descriptor, 'utf8');
2798
+ try {
2799
+ fs.unlinkSync(handoffPath);
2800
+ consumed = true;
2801
+ } catch {
2802
+ try {
2803
+ fs.ftruncateSync(descriptor, 0);
2804
+ consumed = true;
2805
+ } catch {
2806
+ fail();
2807
+ }
2808
+ }
2809
+ } finally {
2810
+ fs.closeSync(descriptor);
2811
+ }
2812
+ if (!consumed) fail();
2813
+
2814
+ let parsed;
2815
+ try {
2816
+ parsed = JSON.parse(raw);
2817
+ } catch {
2818
+ fail();
2819
+ }
2820
+ if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) fail();
2821
+ const entries = Object.entries(parsed);
2822
+ if (entries.length !== 1 || entries[0]?.[0] !== 'Authorization') fail();
2823
+ const authorization = entries[0]?.[1];
2824
+ if (typeof authorization !== 'string' || !/^Bearer [A-Za-z0-9_-]{43}$/u.test(authorization)) fail();
2825
+
2826
+ const terminatorIndex = process.argv.indexOf('--', 2);
2827
+ const insertionIndex = terminatorIndex >= 0 ? terminatorIndex : process.argv.length;
2828
+ process.argv.splice(insertionIndex, 0, '--wsHeaders', JSON.stringify({ Authorization: authorization }));
2829
+ }
2830
+ `;
2831
+ }
2832
+
2833
+ // node_modules/.pnpm/mcporter@0.13.10/node_modules/mcporter/dist/daemon/paths.js
2834
+ import os3 from "node:os";
2835
+ import path5 from "node:path";
2836
+ function daemonBaseDir() {
2837
+ const override = process.env.MCPORTER_DAEMON_DIR?.trim();
2838
+ if (override)
2839
+ return path5.resolve(override);
2840
+ return path5.join(os3.userInfo().homedir, ".mcporter");
2841
+ }
2842
+ function daemonRunDir() {
2843
+ return path5.join(daemonBaseDir(), "daemon");
2844
+ }
2845
+ var verifiedWindowsDirectory;
2846
+ async function secureDaemonDirectory() {
2847
+ if (process.platform === "win32") {
2848
+ const directory = daemonRunDir();
2849
+ const previous = await fs4.lstat(directory).catch((error) => {
2850
+ if (error.code !== "ENOENT")
2851
+ throw error;
2852
+ return void 0;
2853
+ });
2854
+ await verifyWindowsDaemonDirectory(directory, previous);
2855
+ return;
2856
+ }
2857
+ await fs4.mkdir(daemonRunDir(), { recursive: true, mode: 448 });
2858
+ assertPosixDaemonDirectory(await fs4.lstat(daemonRunDir()), false);
2859
+ }
2860
+ async function verifyWindowsDaemonDirectory(directory, previous) {
2861
+ if (previous && (!previous.isDirectory() || previous.isSymbolicLink()))
2862
+ throw new Error("Unsafe daemon directory.");
2863
+ if (verifiedWindowsDirectory?.path !== directory || !previous || previous.dev !== verifiedWindowsDirectory.dev || previous.ino !== verifiedWindowsDirectory.ino || previous.birthtimeMs !== verifiedWindowsDirectory.birthtimeMs) {
2864
+ ensureWindowsPrivateDirectory(directory, true);
2865
+ const info = await fs4.lstat(directory);
2866
+ if (!info.isDirectory() || info.isSymbolicLink())
2867
+ throw new Error("Unsafe daemon directory.");
2868
+ verifiedWindowsDirectory = { path: directory, dev: info.dev, ino: info.ino, birthtimeMs: info.birthtimeMs };
2869
+ }
2870
+ }
2871
+ function assertPosixDaemonDirectory(info, allowLegacy) {
2872
+ if (info.isDirectory() && !info.isSymbolicLink() && info.uid === process.getuid?.()) {
2873
+ const mode = info.mode & 4095;
2874
+ if (mode === 448 || allowLegacy && mode === 493)
2875
+ return;
2876
+ if (mode === 493)
2877
+ throw new Error("Legacy daemon directory has mode 0755. Inspect with daemon migrate; after draining all old clients, run daemon migrate --stop-legacy --confirmed-drained to upgrade it to mode 0700.");
2878
+ }
2879
+ throw new Error("Daemon directory must be a current-user-owned directory (mode 0700), without symlinks.");
2880
+ }
2881
+ async function inspectLegacyDaemonDirectory(directory) {
2882
+ const info = await fs4.lstat(directory).catch((error) => {
2883
+ if (error.code !== "ENOENT")
2884
+ throw error;
2885
+ return void 0;
2886
+ });
2887
+ if (!info)
2888
+ return false;
2889
+ if (process.platform === "win32") {
2890
+ await verifyWindowsDaemonDirectory(directory, info);
2891
+ } else
2892
+ assertPosixDaemonDirectory(info, true);
2893
+ return true;
2894
+ }
2895
+ async function upgradeLegacyDaemonDirectory(directory) {
2896
+ if (!await inspectLegacyDaemonDirectory(directory) || process.platform === "win32")
2897
+ return;
2898
+ const before = await fs4.lstat(directory);
2899
+ assertPosixDaemonDirectory(before, true);
2900
+ const handle = await fs4.open(directory, constants.O_RDONLY | constants.O_DIRECTORY | constants.O_NOFOLLOW);
2901
+ const assertIdentity = (info) => {
2902
+ assertPosixDaemonDirectory(info, true);
2903
+ if (info.dev !== before.dev || info.ino !== before.ino)
2904
+ throw new Error("Daemon directory changed during migration; inspect it before retrying.");
2905
+ };
2906
+ try {
2907
+ const opened = await handle.stat();
2908
+ assertIdentity(opened);
2909
+ assertIdentity(await fs4.lstat(directory));
2910
+ if ((opened.mode & 4095) === 493)
2911
+ await handle.chmod(448);
2912
+ assertPosixDaemonDirectory(await handle.stat(), false);
2913
+ const after = await fs4.lstat(directory);
2914
+ assertIdentity(after);
2915
+ assertPosixDaemonDirectory(after, false);
2916
+ } finally {
2917
+ await handle.close();
2918
+ }
2919
+ }
2920
+ function getDaemonMetadataPath(_configKey) {
2921
+ return path5.join(daemonRunDir(), "user.json");
2922
+ }
2923
+ function getDaemonSocketPath(_configKey) {
2924
+ if (process.platform === "win32")
2925
+ return `\\\\.\\pipe\\mcporter-user-${createHash5("sha256").update(daemonRunDir().toLowerCase()).digest("hex").slice(0, 24)}`;
2926
+ return path5.join(daemonRunDir(), "user.sock");
2927
+ }
2928
+ function getDaemonLogPath(_configKey) {
2929
+ return path5.join(daemonRunDir(), "user.log");
2930
+ }
2931
+
2932
+ // node_modules/.pnpm/mcporter@0.13.10/node_modules/mcporter/dist/daemon/browser-owner.js
2933
+ var BrowserOwnerConflict = class extends Error {
2934
+ code = "browser_owner_conflict";
2935
+ constructor(reason) {
2936
+ super(`Existing Chrome owner conflict: ${reason}. Use the canonical Chrome definition; drain and stop the daemon before deliberately changing ownership. This request was not retried.`);
2937
+ }
2938
+ };
2939
+ function isCanonicalChromeNamespace() {
2940
+ return path6.resolve(daemonBaseDir()) === path6.join(os4.userInfo().homedir, ".mcporter");
2941
+ }
2942
+ async function canonicalUserConfiguration() {
2943
+ if (!isCanonicalChromeNamespace())
2944
+ return { definitions: [] };
2945
+ const home = os4.userInfo().homedir;
2946
+ const file = mcporterConfigCandidates({ home }).find(pathExists);
2947
+ if (!file)
2948
+ return { definitions: [] };
2949
+ const definitions = [];
2950
+ const canonicalEnv = { ...process.env, HOME: home };
2951
+ if (canonicalEnv.USERPROFILE !== void 0)
2952
+ canonicalEnv.USERPROFILE = home;
2953
+ for (const name of Object.keys(canonicalEnv))
2954
+ if (name.startsWith("MCPORTER_CHROME_DEVTOOLS_RELAY_") || name === "MCPORTER_DISABLE_CHROME_DEVTOOLS_RELAY" || name.startsWith("OPENCLAW_"))
2955
+ delete canonicalEnv[name];
2956
+ const raw = await readConfigFile(file, true);
2957
+ for (const [name, entry] of Object.entries(raw.mcpServers)) {
2958
+ const launchTokens = [
2959
+ name,
2960
+ ...Array.isArray(entry.command) ? entry.command : [entry.command ?? ""],
2961
+ ...entry.args ?? []
2962
+ ];
2963
+ if (!launchTokens.some((token) => /chrome[-_]devtools(?:[-_]mcp)?/i.test(token)))
2964
+ continue;
2965
+ const definition = normalizeServerEntry(name, entry, path6.dirname(file), { kind: "local", path: file }, [], {
2966
+ env: canonicalEnv,
2967
+ home
2968
+ });
2969
+ if (supportedOwner(definition))
2970
+ definitions.push(await effectiveDefinition(definition, canonicalEnv));
2971
+ }
2972
+ return { definitions, idleTimeoutMs: raw.daemonIdleTimeoutMs ?? raw.daemon_idle_timeout_ms };
2973
+ }
2974
+ function supportedOwner(definition) {
2975
+ return isChromeDefinition(definition) && definition.command.kind === "stdio" && resolveChromeDevtoolsAutoConnectCommand(definition.command.command, definition.command.args).enabled;
2976
+ }
2977
+ var BrowserOwner = class {
2978
+ identity;
2979
+ logicalIdentity;
2980
+ canonicalKeys;
2981
+ canonical;
2982
+ get reserved() {
2983
+ return this.identity !== void 0;
2984
+ }
2985
+ constructor(canonical) {
2986
+ this.canonical = canonical.filter(supportedOwner);
2987
+ this.canonicalKeys = new Set(this.canonical.map(connectionIdentity));
2988
+ }
2989
+ reserve(definition) {
2990
+ if (!isChromeDefinition(definition))
2991
+ return definition;
2992
+ if (!isCanonicalChromeNamespace())
2993
+ throw new BrowserOwnerConflict("existing local Chrome is forbidden in an isolated daemon directory");
2994
+ if (definition.command.kind !== "stdio")
2995
+ return definition;
2996
+ if (!resolveChromeDevtoolsAutoConnectCommand(definition.command.command, definition.command.args).enabled)
2997
+ throw new BrowserOwnerConflict("direct endpoints, wrappers and profile labels do not prove a distinct browser");
2998
+ const configured = this.canonical[0];
2999
+ if (this.canonicalKeys.size !== 1 || !configured)
3000
+ throw new BrowserOwnerConflict("canonical global Chrome definitions are missing or conflicting");
3001
+ const overrides = definition.configuredEnv ?? definition.env;
3002
+ if (definition.chromeDevtoolsRelay && resolveChromeDevtoolsRelayPolicy(definition.chromeDevtoolsRelay, overrides ?? {}) !== resolveChromeDevtoolsRelayPolicy(configured.chromeDevtoolsRelay, configured.env))
3003
+ throw new BrowserOwnerConflict("canonical relay policy differs");
3004
+ const env = { ...configured.env, ...overrides };
3005
+ normalizeChromeEnvironment(definition, env);
3006
+ const command = configured.command.kind === "stdio" && definition.command.command === configured.launchCommand ? { ...definition.command, command: configured.command.command } : definition.command;
3007
+ const candidate = { ...definition, command, env };
3008
+ const identity = connectionIdentity(candidate);
3009
+ if (!this.canonicalKeys.has(identity))
3010
+ throw new BrowserOwnerConflict("request does not match the complete canonical global Chrome connection contract");
3011
+ const policy = resolveChromeDevtoolsRelayPolicy(definition.chromeDevtoolsRelay, env);
3012
+ if (policy !== resolveChromeDevtoolsRelayPolicy(configured.chromeDevtoolsRelay, configured.env))
3013
+ throw new BrowserOwnerConflict("canonical relay policy differs");
3014
+ if (this.identity && this.identity !== identity)
3015
+ throw new BrowserOwnerConflict("an incompatible pending or live connection already owns the browser");
3016
+ this.identity = identity;
3017
+ return configured;
3018
+ }
3019
+ async resolveIdentity(definition) {
3020
+ const resolve = () => resolveChromeDevtoolsRelayRuntimeIdentity(chromeDevtoolsRelayEnvironmentKeys([definition], definition.env), definition.env);
3021
+ if (!this.logicalIdentity)
3022
+ this.logicalIdentity = resolve();
3023
+ const retained = await this.logicalIdentity;
3024
+ const current = await resolve();
3025
+ if (retained !== current)
3026
+ throw new BrowserOwnerConflict("relay endpoint, credential generation or security context changed; explicit retirement is required");
3027
+ return retained;
3028
+ }
3029
+ };
3030
+
3031
+ // node_modules/.pnpm/mcporter@0.13.10/node_modules/mcporter/dist/daemon/transport-authority.js
3032
+ var authority = /* @__PURE__ */ Symbol("broker transport authority");
3033
+ function authorizeBrokerDefinition(definition, validateRequest) {
3034
+ Object.defineProperty(definition, authority, { value: { validateRequest }, enumerable: true });
3035
+ }
3036
+ function validateBrokerRequestAuthority(definition) {
3037
+ return definition?.[authority]?.validateRequest?.();
3038
+ }
3039
+ function isBrokerDefinition(definition) {
3040
+ return Boolean(definition?.[authority]);
3041
+ }
3042
+ function assertChromeBrokerAuthority(definition) {
3043
+ if (isChromeDefinition(definition) && !isBrokerDefinition(definition)) {
3044
+ throw new BrowserOwnerConflict("programmatic or ephemeral Chrome attachment must use the daemon-backed runtime");
3045
+ }
3046
+ }
3047
+
3048
+ // node_modules/.pnpm/mcporter@0.13.10/node_modules/mcporter/dist/runtime-process-utils.js
3049
+ import { execFile } from "node:child_process";
3050
+ async function closeTransportAndWait(logger, transport, options = {}) {
3051
+ const pidBeforeClose = getTransportPid(transport);
3052
+ const targetsBeforeClose = pidBeforeClose ? await collectProcessTreePids(pidBeforeClose) : [];
3053
+ let closeError;
3054
+ let closeSettled = false;
3055
+ const closePromise = (options.close ?? (() => transport.close()))().catch((error) => {
3056
+ closeError = error;
3057
+ if (!options.throwOnCloseError) {
3058
+ logger.warn(`Failed to close transport cleanly: ${error.message}`);
3059
+ }
3060
+ }).finally(() => {
3061
+ closeSettled = true;
3062
+ });
3063
+ if (pidBeforeClose) {
3064
+ destroyTransportStreams(transport);
3065
+ await ensureProcessTreeTerminated(logger, pidBeforeClose, targetsBeforeClose, options.requireRetirement);
3066
+ if (!closeSettled) {
3067
+ await Promise.race([closePromise, delay(100)]);
3068
+ }
3069
+ } else {
3070
+ await closePromise;
3071
+ }
3072
+ if (closeError && options.throwOnCloseError) {
3073
+ if (options.requireRetirement)
3074
+ throw Object.assign(new Error("Transport retirement failed.", { cause: closeError }), {
3075
+ code: "transport_retirement_failed"
3076
+ });
3077
+ throw closeError;
3078
+ }
3079
+ }
3080
+ function getTransportPid(transport) {
3081
+ if ("pid" in transport) {
3082
+ const candidate = transport.pid;
3083
+ if (typeof candidate === "number" && candidate > 0) {
3084
+ return candidate;
3085
+ }
3086
+ }
3087
+ return null;
3088
+ }
3089
+ function isProcessAlive(pid) {
3090
+ try {
3091
+ process.kill(pid, 0);
3092
+ return true;
3093
+ } catch {
3094
+ return false;
3095
+ }
3096
+ }
3097
+ async function ensureProcessTreeTerminated(logger, rootPid, capturedTargets = [], requireRetirement = false) {
3098
+ let targets = uniquePids([...capturedTargets, ...await collectProcessTreePids(rootPid)]);
3099
+ if (targets.length === 0 || await waitForTreeExit(targets, 700)) {
3100
+ return;
3101
+ }
3102
+ await sendSignalToTargets(targets, "SIGTERM");
3103
+ targets = uniquePids([...targets, ...await collectProcessTreePids(rootPid)]);
3104
+ if (await waitForTreeExit(targets, 700)) {
3105
+ return;
3106
+ }
3107
+ targets = uniquePids([...targets, ...await collectProcessTreePids(rootPid)]);
3108
+ await sendSignalToTargets(targets, "SIGKILL");
3109
+ if (await waitForTreeExit(targets, 500)) {
3110
+ return;
3111
+ }
3112
+ if (requireRetirement)
3113
+ throw Object.assign(new Error("Transport process retirement could not be verified."), {
3114
+ code: "transport_retirement_failed"
3115
+ });
3116
+ logger.warn(`Process tree rooted at pid=${rootPid} did not exit after SIGKILL.`);
3117
+ }
3118
+ function uniquePids(pids) {
3119
+ return [...new Set(pids.filter((pid) => Number.isInteger(pid) && pid > 0))];
3120
+ }
3121
+ function destroyTransportStreams(transport) {
3122
+ const candidate = transport;
3123
+ for (const key of ["stdin", "stdout", "stderr"]) {
3124
+ try {
3125
+ const stream = candidate[key];
3126
+ stream?.destroy?.();
3127
+ } catch {
3128
+ }
3129
+ }
3130
+ }
3131
+ async function sendSignalToTargets(pids, signal) {
3132
+ const seen = /* @__PURE__ */ new Set();
3133
+ for (const pid of pids) {
3134
+ if (seen.has(pid)) {
3135
+ continue;
3136
+ }
3137
+ seen.add(pid);
3138
+ sendSignal(pid, signal);
3139
+ }
3140
+ }
3141
+ function sendSignal(pid, signal) {
3142
+ try {
3143
+ process.kill(pid, signal);
3144
+ } catch (error) {
3145
+ if (typeof error === "object" && error && "code" in error && error.code === "ESRCH") {
3146
+ return;
3147
+ }
3148
+ throw error;
3149
+ }
3150
+ }
3151
+ async function listDescendantPids(rootPid) {
3152
+ if (!isProcessAlive(rootPid)) {
3153
+ return [];
3154
+ }
3155
+ if (process.platform === "win32") {
3156
+ return listDescendantPidsWindows(rootPid);
3157
+ }
3158
+ try {
3159
+ const { stdout } = await execFileAsync("ps", ["-eo", "pid=,ppid="]);
3160
+ const children = /* @__PURE__ */ new Map();
3161
+ for (const line of stdout.split("\n")) {
3162
+ const trimmed = line.trim();
3163
+ if (!trimmed) {
3164
+ continue;
3165
+ }
3166
+ const [pidText, ppidText] = trimmed.split(/\s+/, 2);
3167
+ const pid = Number.parseInt(pidText ?? "", 10);
3168
+ const ppid = Number.parseInt(ppidText ?? "", 10);
3169
+ if (!Number.isFinite(pid) || !Number.isFinite(ppid)) {
3170
+ continue;
3171
+ }
3172
+ const bucket = children.get(ppid) ?? [];
3173
+ bucket.push(pid);
3174
+ children.set(ppid, bucket);
3175
+ }
3176
+ return collectDescendantsFromChildren(rootPid, children);
3177
+ } catch {
3178
+ return [];
3179
+ }
3180
+ }
3181
+ async function listDescendantPidsWindows(rootPid) {
3182
+ try {
3183
+ const powershellScript = "Get-CimInstance Win32_Process | Select-Object ProcessId,ParentProcessId | ConvertTo-Json -Compress";
3184
+ const { stdout } = await execFileAsync("powershell.exe", ["-NoProfile", "-Command", powershellScript]);
3185
+ const trimmed = stdout.trim();
3186
+ if (!trimmed) {
3187
+ return [];
3188
+ }
3189
+ const parsed = JSON.parse(trimmed);
3190
+ const entries = Array.isArray(parsed) ? parsed : [parsed];
3191
+ const children = /* @__PURE__ */ new Map();
3192
+ for (const entry of entries) {
3193
+ const pidCandidate = entry?.ProcessId;
3194
+ const ppidCandidate = entry?.ParentProcessId;
3195
+ if (typeof pidCandidate !== "number" || typeof ppidCandidate !== "number") {
3196
+ continue;
3197
+ }
3198
+ const pid = Number.isFinite(pidCandidate) ? pidCandidate : void 0;
3199
+ const ppid = Number.isFinite(ppidCandidate) ? ppidCandidate : void 0;
3200
+ if (pid === void 0 || ppid === void 0) {
3201
+ continue;
3202
+ }
3203
+ const bucket = children.get(ppid) ?? [];
3204
+ bucket.push(pid);
3205
+ children.set(ppid, bucket);
3206
+ }
3207
+ return collectDescendantsFromChildren(rootPid, children);
3208
+ } catch {
3209
+ return [];
3210
+ }
3211
+ }
3212
+ function execFileAsync(command, args) {
3213
+ return new Promise((resolve, reject) => {
3214
+ execFile(command, args, { encoding: "utf8" }, (error, stdout, stderr) => {
3215
+ if (error) {
3216
+ reject(error);
3217
+ return;
3218
+ }
3219
+ resolve({ stdout, stderr });
742
3220
  });
743
3221
  });
744
3222
  }
@@ -782,7 +3260,7 @@ function delay(ms) {
782
3260
  return new Promise((resolve) => setTimeout(resolve, ms));
783
3261
  }
784
3262
 
785
- // node_modules/.pnpm/mcporter@0.13.8/node_modules/mcporter/dist/runtime/errors.js
3263
+ // node_modules/.pnpm/mcporter@0.13.10/node_modules/mcporter/dist/runtime/errors.js
786
3264
  var NON_FATAL_MCP_ERROR_CODES = /* @__PURE__ */ new Set([
787
3265
  ProtocolErrorCode.InvalidRequest,
788
3266
  ProtocolErrorCode.MethodNotFound,
@@ -804,8 +3282,8 @@ function protocolErrorCode(error) {
804
3282
  return typeof error.code === "number" ? error.code : void 0;
805
3283
  }
806
3284
 
807
- // node_modules/.pnpm/mcporter@0.13.8/node_modules/mcporter/dist/runtime/replay-transport.js
808
- import fs from "node:fs";
3285
+ // node_modules/.pnpm/mcporter@0.13.10/node_modules/mcporter/dist/runtime/replay-transport.js
3286
+ import fs5 from "node:fs";
809
3287
  import { isDeepStrictEqual } from "node:util";
810
3288
  var CLIENT_IDENTITY_META_KEYS = [
811
3289
  "io.modelcontextprotocol/clientInfo",
@@ -860,7 +3338,7 @@ var ReplayTransport = class {
860
3338
  };
861
3339
  function readRecordedMessages(recordPath) {
862
3340
  try {
863
- const contents = fs.readFileSync(recordPath, "utf8");
3341
+ const contents = fs5.readFileSync(recordPath, "utf8");
864
3342
  return contents.split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0).map((line, index) => {
865
3343
  try {
866
3344
  return JSON.parse(line);
@@ -997,44 +3475,250 @@ function adaptInitializeResponse(method, response, requestParams) {
997
3475
  if (typeof protocolVersion !== "string" || !isJsonRpcRecord(response.result)) {
998
3476
  return response;
999
3477
  }
1000
- return {
1001
- ...response,
1002
- result: { ...response.result, protocolVersion }
1003
- };
1004
- }
1005
- function isJsonRpcRecord(value) {
1006
- return typeof value === "object" && value !== null && !Array.isArray(value);
1007
- }
1008
- function withActiveRequestId(response, requestId) {
1009
- if (requestId === void 0) {
1010
- return response;
3478
+ return {
3479
+ ...response,
3480
+ result: { ...response.result, protocolVersion }
3481
+ };
3482
+ }
3483
+ function isJsonRpcRecord(value) {
3484
+ return typeof value === "object" && value !== null && !Array.isArray(value);
3485
+ }
3486
+ function withActiveRequestId(response, requestId) {
3487
+ if (requestId === void 0) {
3488
+ return response;
3489
+ }
3490
+ return {
3491
+ ...response,
3492
+ id: requestId
3493
+ };
3494
+ }
3495
+ function formatReplayMismatch(server, request, expected) {
3496
+ const expectedText = expected ? `${expected.method} ${JSON.stringify(expected.params ?? {})}` : "no remaining recorded recv";
3497
+ return `Replay mismatch for server '${server}': request ${request.method} ${JSON.stringify(request.params ?? {})} did not match next expected recv ${expectedText}.`;
3498
+ }
3499
+ function formatReplayRemainder(server, expectedSends) {
3500
+ const expected = expectedSends[0];
3501
+ const count = expectedSends.length;
3502
+ const requestText = count === 1 ? "request" : "requests";
3503
+ const expectedText = expected ? `${expected.method} ${JSON.stringify(expected.params ?? {})}` : "no remaining recorded recv";
3504
+ return `Replay ended for server '${server}' with ${count} recorded ${requestText} still unused; next expected recv ${expectedText}.`;
3505
+ }
3506
+
3507
+ // node_modules/.pnpm/@modelcontextprotocol+client@2.0.0/node_modules/@modelcontextprotocol/client/dist/stdio.mjs
3508
+ var import_cross_spawn = __toESM(require_cross_spawn(), 1);
3509
+ import process2 from "node:process";
3510
+ import { PassThrough } from "node:stream";
3511
+ var DEFAULT_INHERITED_ENV_VARS = process2.platform === "win32" ? [
3512
+ "APPDATA",
3513
+ "HOMEDRIVE",
3514
+ "HOMEPATH",
3515
+ "LOCALAPPDATA",
3516
+ "PATH",
3517
+ "PROCESSOR_ARCHITECTURE",
3518
+ "SYSTEMDRIVE",
3519
+ "SYSTEMROOT",
3520
+ "TEMP",
3521
+ "USERNAME",
3522
+ "USERPROFILE",
3523
+ "PROGRAMFILES"
3524
+ ] : [
3525
+ "HOME",
3526
+ "LOGNAME",
3527
+ "PATH",
3528
+ "SHELL",
3529
+ "TERM",
3530
+ "USER"
3531
+ ];
3532
+ function getDefaultEnvironment() {
3533
+ const env = {};
3534
+ for (const key of DEFAULT_INHERITED_ENV_VARS) {
3535
+ const value = process2.env[key];
3536
+ if (value === void 0) continue;
3537
+ if (value.startsWith("()")) continue;
3538
+ env[key] = value;
3539
+ }
3540
+ return env;
3541
+ }
3542
+ var StdioClientTransport = class {
3543
+ _process;
3544
+ _readBuffer;
3545
+ _serverParams;
3546
+ _stderrStream = null;
3547
+ onclose;
3548
+ onerror;
3549
+ onmessage;
3550
+ constructor(server) {
3551
+ this._serverParams = server;
3552
+ this._readBuffer = new ReadBuffer({ maxBufferSize: server.maxBufferSize });
3553
+ if (server.stderr === "pipe" || server.stderr === "overlapped") this._stderrStream = new PassThrough();
3554
+ }
3555
+ /**
3556
+ * Starts the server process and prepares to communicate with it.
3557
+ */
3558
+ async start() {
3559
+ if (this._process) throw new Error("StdioClientTransport already started! If using Client class, note that connect() calls start() automatically.");
3560
+ return new Promise((resolve, reject) => {
3561
+ this._process = (0, import_cross_spawn.default)(this._serverParams.command, this._serverParams.args ?? [], {
3562
+ env: {
3563
+ ...getDefaultEnvironment(),
3564
+ ...this._serverParams.env
3565
+ },
3566
+ stdio: [
3567
+ "pipe",
3568
+ "pipe",
3569
+ this._serverParams.stderr ?? "inherit"
3570
+ ],
3571
+ shell: false,
3572
+ windowsHide: process2.platform === "win32",
3573
+ cwd: this._serverParams.cwd
3574
+ });
3575
+ this._process.on("error", (error) => {
3576
+ reject(error);
3577
+ this.onerror?.(error);
3578
+ });
3579
+ this._process.on("spawn", () => {
3580
+ resolve();
3581
+ });
3582
+ this._process.on("close", (_code) => {
3583
+ this._process = void 0;
3584
+ this.onclose?.();
3585
+ });
3586
+ this._process.stdin?.on("error", (error) => {
3587
+ this.onerror?.(error);
3588
+ });
3589
+ this._process.stdout?.on("data", (chunk) => {
3590
+ try {
3591
+ this._readBuffer.append(chunk);
3592
+ this.processReadBuffer();
3593
+ } catch (error) {
3594
+ this.onerror?.(error);
3595
+ this.close().catch(() => {
3596
+ });
3597
+ }
3598
+ });
3599
+ this._process.stdout?.on("error", (error) => {
3600
+ this.onerror?.(error);
3601
+ });
3602
+ if (this._stderrStream && this._process.stderr) this._process.stderr.pipe(this._stderrStream);
3603
+ });
3604
+ }
3605
+ /**
3606
+ * The `stderr` stream of the child process, if {@linkcode StdioServerParameters.stderr} was set to `"pipe"` or `"overlapped"`.
3607
+ *
3608
+ * If `stderr` piping was requested, a `PassThrough` stream is returned _immediately_, allowing callers to
3609
+ * attach listeners before the `start` method is invoked. This prevents loss of any early
3610
+ * error output emitted by the child process.
3611
+ */
3612
+ get stderr() {
3613
+ if (this._stderrStream) return this._stderrStream;
3614
+ return this._process?.stderr ?? null;
3615
+ }
3616
+ /**
3617
+ * The child process pid spawned by this transport.
3618
+ *
3619
+ * This is only available after the transport has been started.
3620
+ */
3621
+ get pid() {
3622
+ return this._process?.pid ?? null;
3623
+ }
3624
+ processReadBuffer() {
3625
+ while (true) try {
3626
+ const message = this._readBuffer.readMessage();
3627
+ if (message === null) break;
3628
+ this.onmessage?.(message);
3629
+ } catch (error) {
3630
+ this.onerror?.(error);
3631
+ }
3632
+ }
3633
+ /**
3634
+ * Reap a disposable probe sibling (see the version-negotiation sibling
3635
+ * flow): signal-first teardown awaiting process `exit` — never the `close`
3636
+ * event, so a helper process holding the child's stdio pipes can never
3637
+ * block disposal. Not part of the public transport lifecycle.
3638
+ *
3639
+ * @internal
3640
+ */
3641
+ async _dispose() {
3642
+ const proc = this._process;
3643
+ this._process = void 0;
3644
+ if (proc && proc.exitCode === null && proc.signalCode === null) {
3645
+ const exited = new Promise((resolve) => proc.once("exit", () => resolve()));
3646
+ try {
3647
+ proc.stdin?.end();
3648
+ } catch {
3649
+ }
3650
+ try {
3651
+ proc.kill("SIGTERM");
3652
+ } catch {
3653
+ }
3654
+ await Promise.race([exited, new Promise((resolve) => setTimeout(resolve, 1e3).unref())]);
3655
+ if (proc.exitCode === null && proc.signalCode === null) try {
3656
+ proc.kill("SIGKILL");
3657
+ } catch {
3658
+ }
3659
+ await exited;
3660
+ }
3661
+ try {
3662
+ proc?.stdout?.destroy();
3663
+ } catch {
3664
+ }
3665
+ try {
3666
+ proc?.stdin?.destroy();
3667
+ } catch {
3668
+ }
3669
+ try {
3670
+ proc?.stderr?.destroy();
3671
+ } catch {
3672
+ }
3673
+ this._readBuffer.clear();
3674
+ }
3675
+ async close() {
3676
+ if (this._process) {
3677
+ const processToClose = this._process;
3678
+ this._process = void 0;
3679
+ const closePromise = new Promise((resolve) => {
3680
+ processToClose.once("close", () => {
3681
+ resolve();
3682
+ });
3683
+ });
3684
+ try {
3685
+ processToClose.stdin?.end();
3686
+ } catch {
3687
+ }
3688
+ await Promise.race([closePromise, new Promise((resolve) => setTimeout(resolve, 2e3).unref())]);
3689
+ if (processToClose.exitCode === null) {
3690
+ try {
3691
+ processToClose.kill("SIGTERM");
3692
+ } catch {
3693
+ }
3694
+ await Promise.race([closePromise, new Promise((resolve) => setTimeout(resolve, 2e3).unref())]);
3695
+ }
3696
+ if (processToClose.exitCode === null) try {
3697
+ processToClose.kill("SIGKILL");
3698
+ } catch {
3699
+ }
3700
+ }
3701
+ this._readBuffer.clear();
3702
+ }
3703
+ send(message) {
3704
+ return new Promise((resolve) => {
3705
+ if (!this._process?.stdin) throw new SdkError(SdkErrorCode.NotConnected, "Not connected");
3706
+ const json = serializeMessage(message);
3707
+ if (this._process.stdin.write(json)) resolve();
3708
+ else this._process.stdin.once("drain", resolve);
3709
+ });
1011
3710
  }
1012
- return {
1013
- ...response,
1014
- id: requestId
1015
- };
1016
- }
1017
- function formatReplayMismatch(server, request, expected) {
1018
- const expectedText = expected ? `${expected.method} ${JSON.stringify(expected.params ?? {})}` : "no remaining recorded recv";
1019
- return `Replay mismatch for server '${server}': request ${request.method} ${JSON.stringify(request.params ?? {})} did not match next expected recv ${expectedText}.`;
1020
- }
1021
- function formatReplayRemainder(server, expectedSends) {
1022
- const expected = expectedSends[0];
1023
- const count = expectedSends.length;
1024
- const requestText = count === 1 ? "request" : "requests";
1025
- const expectedText = expected ? `${expected.method} ${JSON.stringify(expected.params ?? {})}` : "no remaining recorded recv";
1026
- return `Replay ended for server '${server}' with ${count} recorded ${requestText} still unused; next expected recv ${expectedText}.`;
1027
- }
3711
+ };
1028
3712
 
1029
- // node_modules/.pnpm/mcporter@0.13.8/node_modules/mcporter/dist/chrome-devtools-compat.js
1030
- import fs3 from "node:fs";
1031
- import os from "node:os";
1032
- import path2 from "node:path";
1033
- import { fileURLToPath, pathToFileURL } from "node:url";
3713
+ // node_modules/.pnpm/mcporter@0.13.10/node_modules/mcporter/dist/chrome-devtools-compat.js
3714
+ import fs7 from "node:fs";
3715
+ import os5 from "node:os";
3716
+ import path8 from "node:path";
3717
+ import { fileURLToPath, pathToFileURL as pathToFileURL2 } from "node:url";
1034
3718
 
1035
- // node_modules/.pnpm/mcporter@0.13.8/node_modules/mcporter/dist/chrome-devtools-auto-connect-patch.js
1036
- import fs2 from "node:fs";
1037
- import path from "node:path";
3719
+ // node_modules/.pnpm/mcporter@0.13.10/node_modules/mcporter/dist/chrome-devtools-auto-connect-patch.js
3720
+ import fs6 from "node:fs";
3721
+ import path7 from "node:path";
1038
3722
  var MARKER = "MCPORTER_DEVTOOLS_TIMEOUT_PATCH";
1039
3723
  var HELPER = `// ${MARKER}
1040
3724
  const MCPORTER_DEVTOOLS_DETECTION_TIMEOUT = 1_000;
@@ -1064,7 +3748,7 @@ var PATCHED_DETECTION_BLOCK = `if (await mcporterWithTimeout(page.hasDevTools(),
1064
3748
  }`;
1065
3749
  patchChromeDevtoolsMcp();
1066
3750
  function patchChromeDevtoolsMcp(mainPath = process.argv[1]) {
1067
- patchChromeDevtoolsMcpWithDependencies(mainPath, fs2, path, MARKER, HELPER, DETECTION_BLOCK, PATCHED_DETECTION_BLOCK);
3751
+ patchChromeDevtoolsMcpWithDependencies(mainPath, fs6, path7, MARKER, HELPER, DETECTION_BLOCK, PATCHED_DETECTION_BLOCK);
1068
3752
  }
1069
3753
  function renderChromeDevtoolsAutoConnectPatchSource() {
1070
3754
  return `import fs from 'node:fs';
@@ -1119,7 +3803,7 @@ ${helper}`);
1119
3803
  }
1120
3804
  }
1121
3805
 
1122
- // node_modules/.pnpm/mcporter@0.13.8/node_modules/mcporter/dist/chrome-devtools-compat.js
3806
+ // node_modules/.pnpm/mcporter@0.13.10/node_modules/mcporter/dist/chrome-devtools-compat.js
1123
3807
  var FALLBACK_PATCH_FILENAME = "mcporter-chrome-devtools-auto-connect-patch.js";
1124
3808
  function applyChromeDevtoolsCompat(env, command, args) {
1125
3809
  if (!shouldApplyChromeDevtoolsCompat(command, args, env)) {
@@ -1129,276 +3813,51 @@ function applyChromeDevtoolsCompat(env, command, args) {
1129
3813
  if (!patchPath) {
1130
3814
  return { env, applied: false };
1131
3815
  }
1132
- const importFlag = `--import=${pathToFileURL(patchPath).href}`;
3816
+ const importFlag = `--import=${pathToFileURL2(patchPath).href}`;
1133
3817
  const existingOptions = env.NODE_OPTIONS?.trim();
1134
3818
  if (existingOptions?.includes(importFlag)) {
1135
- return { env, applied: true, patchPath };
1136
- }
1137
- return {
1138
- env: {
1139
- ...env,
1140
- NODE_OPTIONS: existingOptions ? `${existingOptions} ${importFlag}` : importFlag
1141
- },
1142
- applied: true,
1143
- patchPath
1144
- };
1145
- }
1146
- function shouldApplyChromeDevtoolsCompat(command, args, env = process.env) {
1147
- if (env.MCPORTER_DISABLE_CHROME_DEVTOOLS_COMPAT === "1") {
1148
- return false;
1149
- }
1150
- return resolveChromeDevtoolsAutoConnectCommand(command, args).enabled;
1151
- }
1152
- function resolveChromeDevtoolsCompatPatchPath(candidates = defaultChromeDevtoolsPatchCandidates(), fallbackDir = os.tmpdir()) {
1153
- const existing = candidates.find((candidate) => fs3.existsSync(candidate));
1154
- if (existing) {
1155
- return existing;
1156
- }
1157
- return writeFallbackPatch(fallbackDir);
1158
- }
1159
- function defaultChromeDevtoolsPatchCandidates() {
1160
- const here = path2.dirname(fileURLToPath(import.meta.url));
1161
- return [
1162
- path2.join(here, "chrome-devtools-auto-connect-patch.js"),
1163
- path2.resolve(here, "..", "dist", "chrome-devtools-auto-connect-patch.js")
1164
- ];
1165
- }
1166
- function writeFallbackPatch(fallbackDir) {
1167
- const patchPath = path2.join(fallbackDir, FALLBACK_PATCH_FILENAME);
1168
- try {
1169
- fs3.writeFileSync(patchPath, renderChromeDevtoolsAutoConnectPatchSource(), { mode: 384 });
1170
- return patchPath;
1171
- } catch {
1172
- return void 0;
1173
- }
1174
- }
1175
-
1176
- // node_modules/.pnpm/mcporter@0.13.8/node_modules/mcporter/dist/chrome-devtools-relay-handoff.js
1177
- import { spawnSync } from "node:child_process";
1178
- import { randomBytes } from "node:crypto";
1179
- import fs4 from "node:fs";
1180
- import os2 from "node:os";
1181
- import path3 from "node:path";
1182
- import { pathToFileURL as pathToFileURL2 } from "node:url";
1183
- var CHROME_RELAY_HANDOFF_ENV = "MCPORTER_CHROME_RELAY_HANDOFF_PATH";
1184
- var HANDOFF_DIR_PREFIX = "mcporter-chrome-relay-";
1185
- var HANDOFF_FILENAME = "headers.json";
1186
- var PRELOAD_FILENAME = "preload.mjs";
1187
- var WINDOWS_ACL_PATH_ENV = "MCPORTER_CHROME_RELAY_ACL_PATH";
1188
- function createChromeDevtoolsRelayHandoff(env, clientAuthorization) {
1189
- let directory;
1190
- try {
1191
- if (process.platform === "win32")
1192
- directory = createWindowsHandoffDirectory();
1193
- else {
1194
- directory = fs4.mkdtempSync(path3.join(os2.tmpdir(), HANDOFF_DIR_PREFIX));
1195
- fs4.chmodSync(directory, 448);
1196
- }
1197
- assertSecurePath(directory, "directory");
1198
- const handoffPath = path3.join(directory, HANDOFF_FILENAME);
1199
- const preloadPath = path3.join(directory, PRELOAD_FILENAME);
1200
- writeExclusiveFile(preloadPath, renderChromeDevtoolsRelayPreloadSource());
1201
- writeExclusiveFile(handoffPath, JSON.stringify({ Authorization: clientAuthorization }));
1202
- const importFlag = `--import=${pathToFileURL2(preloadPath).href}`;
1203
- const existingOptions = env.NODE_OPTIONS?.trim();
1204
- let closed = false;
1205
- return {
1206
- env: {
1207
- ...env,
1208
- NODE_OPTIONS: existingOptions ? `${existingOptions} ${importFlag}` : importFlag,
1209
- [CHROME_RELAY_HANDOFF_ENV]: handoffPath
1210
- },
1211
- handoffPath,
1212
- preloadPath,
1213
- async close() {
1214
- if (closed)
1215
- return;
1216
- closed = true;
1217
- cleanupHandoff(directory, handoffPath, preloadPath);
1218
- }
1219
- };
1220
- } catch (error) {
1221
- if (directory)
1222
- cleanupHandoff(directory, path3.join(directory, HANDOFF_FILENAME), path3.join(directory, PRELOAD_FILENAME));
1223
- const diagnostic = error instanceof Error && error.message.startsWith("Windows ACL setup failed:") ? ` ${error.message}` : "";
1224
- throw new Error(`Unable to install secure Chrome relay authorization handoff.${diagnostic}`, { cause: error });
1225
- }
1226
- }
1227
- function createWindowsHandoffDirectory() {
1228
- const directory = path3.join(os2.tmpdir(), `${HANDOFF_DIR_PREFIX}${randomBytes(16).toString("hex")}`);
1229
- const script = String.raw`
1230
- $ErrorActionPreference = 'Stop'
1231
- $stage = 'identity'
1232
- try {
1233
- $target = $env:${WINDOWS_ACL_PATH_ENV}
1234
- if ([System.IO.Directory]::Exists($target)) { throw 'handoff path already exists' }
1235
- $sid = [System.Security.Principal.WindowsIdentity]::GetCurrent().User
1236
- $stage = 'descriptor'
1237
- $security = New-Object System.Security.AccessControl.DirectorySecurity
1238
- $sidValue = $sid.Value
1239
- $security.SetSecurityDescriptorSddlForm("O:$($sidValue)G:$($sidValue)D:P(A;OICI;FA;;;$($sidValue))")
1240
- $directory = New-Object System.IO.DirectoryInfo -ArgumentList @($target)
1241
- $stage = 'create'
1242
- $directory.Create($security)
1243
- $stage = 'acl-read'
1244
- $check = $directory.GetAccessControl([System.Security.AccessControl.AccessControlSections]::All)
1245
- $rules = @($check.GetAccessRules($true, $true, [System.Security.Principal.SecurityIdentifier]))
1246
- $ownerSid = $check.GetOwner([System.Security.Principal.SecurityIdentifier]).Value
1247
- $stage = 'acl-verify'
1248
- if (-not $check.AreAccessRulesProtected -or $ownerSid -ne $sid.Value -or $rules.Count -ne 1) { throw 'unsafe ACL' }
1249
- $ruleSid = $rules[0].IdentityReference.Value
1250
- $hasFullControl = ($rules[0].FileSystemRights -band [System.Security.AccessControl.FileSystemRights]::FullControl) -eq [System.Security.AccessControl.FileSystemRights]::FullControl
1251
- if ($ruleSid -ne $sid.Value -or $rules[0].IsInherited -or -not $hasFullControl -or $rules[0].AccessControlType -ne [System.Security.AccessControl.AccessControlType]::Allow) { throw 'unsafe ACL' }
1252
- } catch {
1253
- $type = $_.Exception.GetType().FullName
1254
- $hresult = ('0x{0:X8}' -f ($_.Exception.HResult -band 0xffffffffL))
1255
- [Console]::Error.WriteLine("stage=$stage type=$type hresult=$hresult")
1256
- exit 1
1257
- }
1258
- `;
1259
- const result = spawnSync(resolveSystemPowerShellPath(), ["-NoLogo", "-NoProfile", "-NonInteractive", "-Command", script], {
1260
- encoding: "utf8",
1261
- env: { ...process.env, [WINDOWS_ACL_PATH_ENV]: directory },
1262
- stdio: ["ignore", "ignore", "pipe"],
1263
- windowsHide: true
1264
- });
1265
- if (result.status !== 0) {
1266
- try {
1267
- fs4.rmdirSync(directory);
1268
- } catch {
1269
- }
1270
- const stderr = typeof result.stderr === "string" ? result.stderr.trim() : "";
1271
- const safeDetail = /^[A-Za-z0-9_.:=\- ]{1,240}$/u.test(stderr) ? stderr : `stage=spawn type=${result.error?.code ?? "unknown"} hresult=unknown`;
1272
- throw new Error(`Windows ACL setup failed: ${safeDetail}`);
1273
- }
1274
- return directory;
1275
- }
1276
- function resolveSystemPowerShellPath() {
1277
- const systemRoot = process.env.SystemRoot?.trim() || process.env.WINDIR?.trim();
1278
- if (!systemRoot || !path3.win32.isAbsolute(systemRoot))
1279
- throw new Error("unsafe Windows system root");
1280
- const executable = path3.win32.join(systemRoot, "System32", "WindowsPowerShell", "v1.0", "powershell.exe");
1281
- const stat = fs4.lstatSync(executable);
1282
- if (!stat.isFile() || stat.isSymbolicLink())
1283
- throw new Error("unsafe Windows PowerShell path");
1284
- return executable;
1285
- }
1286
- function writeExclusiveFile(filePath, contents) {
1287
- const descriptor = fs4.openSync(filePath, fs4.constants.O_WRONLY | fs4.constants.O_CREAT | fs4.constants.O_EXCL | (fs4.constants.O_NOFOLLOW ?? 0), 384);
1288
- try {
1289
- if (process.platform !== "win32")
1290
- fs4.fchmodSync(descriptor, 384);
1291
- fs4.writeFileSync(descriptor, contents, "utf8");
1292
- } finally {
1293
- fs4.closeSync(descriptor);
1294
- }
1295
- assertSecurePath(filePath, "file");
1296
- }
1297
- function assertSecurePath(filePath, kind) {
1298
- const stat = fs4.lstatSync(filePath);
1299
- if ((kind === "directory" ? !stat.isDirectory() : !stat.isFile()) || stat.isSymbolicLink())
1300
- throw new Error("unsafe");
1301
- if (process.platform === "win32")
1302
- return;
1303
- if ((stat.mode & 63) !== 0)
1304
- throw new Error("unsafe");
1305
- if (typeof process.getuid === "function" && stat.uid !== process.getuid())
1306
- throw new Error("unsafe");
1307
- }
1308
- function cleanupHandoff(directory, handoffPath, preloadPath) {
1309
- for (const filePath of [handoffPath, preloadPath]) {
1310
- try {
1311
- fs4.unlinkSync(filePath);
1312
- } catch {
1313
- }
1314
- }
1315
- try {
1316
- fs4.rmdirSync(directory);
1317
- } catch {
1318
- }
1319
- }
1320
- function renderChromeDevtoolsRelayPreloadSource() {
1321
- return `import fs from 'node:fs';
1322
- import path from 'node:path';
1323
-
1324
- const targetPath = process.argv[1]?.replaceAll('\\\\', '/').toLowerCase();
1325
- if (targetPath?.includes('chrome-devtools-mcp')) {
1326
- const failureMessage = 'MCPorter Chrome relay authorization handoff unavailable.';
1327
- const fail = () => {
1328
- throw new Error(failureMessage);
1329
- };
1330
- const envName = ${JSON.stringify(CHROME_RELAY_HANDOFF_ENV)};
1331
- const handoffPath = process.env[envName];
1332
- delete process.env[envName];
1333
- if (!handoffPath || !path.isAbsolute(handoffPath)) fail();
1334
-
1335
- const directoryStat = (() => {
1336
- try {
1337
- return fs.lstatSync(path.dirname(handoffPath));
1338
- } catch {
1339
- return fail();
1340
- }
1341
- })();
1342
- if (!directoryStat.isDirectory() || directoryStat.isSymbolicLink()) fail();
1343
- if (process.platform !== 'win32') {
1344
- if ((directoryStat.mode & 0o077) !== 0) fail();
1345
- if (typeof process.getuid === 'function' && directoryStat.uid !== process.getuid()) fail();
1346
- }
1347
-
1348
- const descriptor = (() => {
1349
- try {
1350
- return fs.openSync(handoffPath, fs.constants.O_RDONLY | (fs.constants.O_NOFOLLOW ?? 0));
1351
- } catch {
1352
- return fail();
1353
- }
1354
- })();
1355
-
1356
- let raw = '';
1357
- let consumed = false;
1358
- try {
1359
- const stat = fs.fstatSync(descriptor);
1360
- if (!stat.isFile() || stat.size <= 0 || stat.size > 4_096) fail();
1361
- if (process.platform !== 'win32') {
1362
- if ((stat.mode & 0o077) !== 0) fail();
1363
- if (typeof process.getuid === 'function' && stat.uid !== process.getuid()) fail();
1364
- }
1365
- raw = fs.readFileSync(descriptor, 'utf8');
1366
- try {
1367
- fs.unlinkSync(handoffPath);
1368
- consumed = true;
1369
- } catch {
1370
- try {
1371
- fs.ftruncateSync(descriptor, 0);
1372
- consumed = true;
1373
- } catch {
1374
- fail();
1375
- }
1376
- }
1377
- } finally {
1378
- fs.closeSync(descriptor);
3819
+ return { env, applied: true, patchPath };
1379
3820
  }
1380
- if (!consumed) fail();
1381
-
1382
- let parsed;
3821
+ return {
3822
+ env: {
3823
+ ...env,
3824
+ NODE_OPTIONS: existingOptions ? `${existingOptions} ${importFlag}` : importFlag
3825
+ },
3826
+ applied: true,
3827
+ patchPath
3828
+ };
3829
+ }
3830
+ function shouldApplyChromeDevtoolsCompat(command, args, env = process.env) {
3831
+ if (env.MCPORTER_DISABLE_CHROME_DEVTOOLS_COMPAT === "1") {
3832
+ return false;
3833
+ }
3834
+ return resolveChromeDevtoolsAutoConnectCommand(command, args).enabled;
3835
+ }
3836
+ function resolveChromeDevtoolsCompatPatchPath(candidates = defaultChromeDevtoolsPatchCandidates(), fallbackDir = os5.tmpdir()) {
3837
+ const existing = candidates.find((candidate) => fs7.existsSync(candidate));
3838
+ if (existing) {
3839
+ return existing;
3840
+ }
3841
+ return writeFallbackPatch(fallbackDir);
3842
+ }
3843
+ function defaultChromeDevtoolsPatchCandidates() {
3844
+ const here = path8.dirname(fileURLToPath(import.meta.url));
3845
+ return [
3846
+ path8.join(here, "chrome-devtools-auto-connect-patch.js"),
3847
+ path8.resolve(here, "..", "dist", "chrome-devtools-auto-connect-patch.js")
3848
+ ];
3849
+ }
3850
+ function writeFallbackPatch(fallbackDir) {
3851
+ const patchPath = path8.join(fallbackDir, FALLBACK_PATCH_FILENAME);
1383
3852
  try {
1384
- parsed = JSON.parse(raw);
3853
+ fs7.writeFileSync(patchPath, renderChromeDevtoolsAutoConnectPatchSource(), { mode: 384 });
3854
+ return patchPath;
1385
3855
  } catch {
1386
- fail();
3856
+ return void 0;
1387
3857
  }
1388
- if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) fail();
1389
- const entries = Object.entries(parsed);
1390
- if (entries.length !== 1 || entries[0]?.[0] !== 'Authorization') fail();
1391
- const authorization = entries[0]?.[1];
1392
- if (typeof authorization !== 'string' || !/^Bearer [A-Za-z0-9_-]{43}$/u.test(authorization)) fail();
1393
-
1394
- const terminatorIndex = process.argv.indexOf('--', 2);
1395
- const insertionIndex = terminatorIndex >= 0 ? terminatorIndex : process.argv.length;
1396
- process.argv.splice(insertionIndex, 0, '--wsHeaders', JSON.stringify({ Authorization: authorization }));
1397
- }
1398
- `;
1399
3858
  }
1400
3859
 
1401
- // node_modules/.pnpm/mcporter@0.13.8/node_modules/mcporter/dist/runtime/cached-auth.js
3860
+ // node_modules/.pnpm/mcporter@0.13.10/node_modules/mcporter/dist/runtime/cached-auth.js
1402
3861
  function hasAuthorizationHeader(headers) {
1403
3862
  return Boolean(headers && Object.keys(headers).some((key) => key.toLowerCase() === "authorization"));
1404
3863
  }
@@ -1461,15 +3920,15 @@ async function applyCachedAuthIfAvailable(definition, logger, allowCachedAuth) {
1461
3920
  }
1462
3921
  }
1463
3922
 
1464
- // node_modules/.pnpm/mcporter@0.13.8/node_modules/mcporter/dist/runtime-header-utils.js
1465
- function materializeHeaders(headers, serverName) {
3923
+ // node_modules/.pnpm/mcporter@0.13.10/node_modules/mcporter/dist/runtime-header-utils.js
3924
+ function materializeHeaders(headers, serverName, env = process.env) {
1466
3925
  if (!headers) {
1467
3926
  return void 0;
1468
3927
  }
1469
3928
  const resolved = {};
1470
3929
  for (const [key, value] of Object.entries(headers)) {
1471
3930
  try {
1472
- resolved[key] = resolveEnvPlaceholders(value);
3931
+ resolved[key] = resolveEnvPlaceholders(value, env);
1473
3932
  } catch (error) {
1474
3933
  const message = error instanceof Error ? error.message : String(error);
1475
3934
  throw new Error(`Failed to resolve header '${key}' for server '${serverName}': ${message}`, { cause: error });
@@ -1478,8 +3937,8 @@ function materializeHeaders(headers, serverName) {
1478
3937
  return resolved;
1479
3938
  }
1480
3939
 
1481
- // node_modules/.pnpm/mcporter@0.13.8/node_modules/mcporter/dist/runtime/node-http-fetch.js
1482
- import http from "node:http";
3940
+ // node_modules/.pnpm/mcporter@0.13.10/node_modules/mcporter/dist/runtime/node-http-fetch.js
3941
+ import http2 from "node:http";
1483
3942
  import https from "node:https";
1484
3943
  import { Buffer as Buffer2 } from "node:buffer";
1485
3944
  import { Readable } from "node:stream";
@@ -1517,7 +3976,7 @@ async function nodeHttp1FetchWithRedirects(input, init, redirectCount) {
1517
3976
  headers["content-length"] = String(Buffer2.byteLength(body));
1518
3977
  }
1519
3978
  return new Promise((resolve, reject) => {
1520
- const client = url.protocol === "https:" ? https : http;
3979
+ const client = url.protocol === "https:" ? https : http2;
1521
3980
  const request = client.request(url, {
1522
3981
  method: init.method ?? "GET",
1523
3982
  headers
@@ -1637,7 +4096,7 @@ async function materializeRequestBody(body) {
1637
4096
  throw new TypeError("node-http1 fetch does not support streaming request bodies.");
1638
4097
  }
1639
4098
 
1640
- // node_modules/.pnpm/mcporter@0.13.8/node_modules/mcporter/dist/runtime/http-transport.js
4099
+ // node_modules/.pnpm/mcporter@0.13.10/node_modules/mcporter/dist/runtime/http-transport.js
1641
4100
  function extractTransportStatusCode(error) {
1642
4101
  if (!error || typeof error !== "object")
1643
4102
  return void 0;
@@ -1688,7 +4147,7 @@ function createHttpTransportOptions(definition, oauthSession, shouldEstablishOAu
1688
4147
  const command = definition.command;
1689
4148
  if (command.kind !== "http")
1690
4149
  throw new Error(`Server '${definition.name}' is not configured for HTTP transport.`);
1691
- const resolvedHeaders = materializeHeaders(command.headers, definition.name);
4150
+ const resolvedHeaders = materializeHeaders(command.headers, definition.name, definition.env);
1692
4151
  const effectiveHeaders = shouldEstablishOAuth ? removeAuthorizationHeader(resolvedHeaders) : resolvedHeaders;
1693
4152
  const trackedFetch = trackStandaloneSseFetch(resolveHttpFetchOverride(definition));
1694
4153
  return {
@@ -1763,8 +4222,7 @@ async function connectHttpTransport(client, transport, oauthSession, logger, con
1763
4222
  return await connectWithAuth(client, transport, oauthSession, logger, connectOptions);
1764
4223
  } catch (error) {
1765
4224
  if (!connectOptions.signal?.aborted) {
1766
- await closeTransportAndWait(logger, transport).catch(() => {
1767
- });
4225
+ await closeTransportAndWait(logger, transport, { throwOnCloseError: true, requireRetirement: true });
1768
4226
  }
1769
4227
  throw error;
1770
4228
  }
@@ -1861,213 +4319,7 @@ async function connectSseFallbackTransport(client, definition, command, transpor
1861
4319
  }
1862
4320
  }
1863
4321
 
1864
- // node_modules/.pnpm/@modelcontextprotocol+client@2.0.0/node_modules/@modelcontextprotocol/client/dist/stdio.mjs
1865
- var import_cross_spawn = __toESM(require_cross_spawn(), 1);
1866
- import process2 from "node:process";
1867
- import { PassThrough } from "node:stream";
1868
- var DEFAULT_INHERITED_ENV_VARS = process2.platform === "win32" ? [
1869
- "APPDATA",
1870
- "HOMEDRIVE",
1871
- "HOMEPATH",
1872
- "LOCALAPPDATA",
1873
- "PATH",
1874
- "PROCESSOR_ARCHITECTURE",
1875
- "SYSTEMDRIVE",
1876
- "SYSTEMROOT",
1877
- "TEMP",
1878
- "USERNAME",
1879
- "USERPROFILE",
1880
- "PROGRAMFILES"
1881
- ] : [
1882
- "HOME",
1883
- "LOGNAME",
1884
- "PATH",
1885
- "SHELL",
1886
- "TERM",
1887
- "USER"
1888
- ];
1889
- function getDefaultEnvironment() {
1890
- const env = {};
1891
- for (const key of DEFAULT_INHERITED_ENV_VARS) {
1892
- const value = process2.env[key];
1893
- if (value === void 0) continue;
1894
- if (value.startsWith("()")) continue;
1895
- env[key] = value;
1896
- }
1897
- return env;
1898
- }
1899
- var StdioClientTransport = class {
1900
- _process;
1901
- _readBuffer;
1902
- _serverParams;
1903
- _stderrStream = null;
1904
- onclose;
1905
- onerror;
1906
- onmessage;
1907
- constructor(server) {
1908
- this._serverParams = server;
1909
- this._readBuffer = new ReadBuffer({ maxBufferSize: server.maxBufferSize });
1910
- if (server.stderr === "pipe" || server.stderr === "overlapped") this._stderrStream = new PassThrough();
1911
- }
1912
- /**
1913
- * Starts the server process and prepares to communicate with it.
1914
- */
1915
- async start() {
1916
- if (this._process) throw new Error("StdioClientTransport already started! If using Client class, note that connect() calls start() automatically.");
1917
- return new Promise((resolve, reject) => {
1918
- this._process = (0, import_cross_spawn.default)(this._serverParams.command, this._serverParams.args ?? [], {
1919
- env: {
1920
- ...getDefaultEnvironment(),
1921
- ...this._serverParams.env
1922
- },
1923
- stdio: [
1924
- "pipe",
1925
- "pipe",
1926
- this._serverParams.stderr ?? "inherit"
1927
- ],
1928
- shell: false,
1929
- windowsHide: process2.platform === "win32",
1930
- cwd: this._serverParams.cwd
1931
- });
1932
- this._process.on("error", (error) => {
1933
- reject(error);
1934
- this.onerror?.(error);
1935
- });
1936
- this._process.on("spawn", () => {
1937
- resolve();
1938
- });
1939
- this._process.on("close", (_code) => {
1940
- this._process = void 0;
1941
- this.onclose?.();
1942
- });
1943
- this._process.stdin?.on("error", (error) => {
1944
- this.onerror?.(error);
1945
- });
1946
- this._process.stdout?.on("data", (chunk) => {
1947
- try {
1948
- this._readBuffer.append(chunk);
1949
- this.processReadBuffer();
1950
- } catch (error) {
1951
- this.onerror?.(error);
1952
- this.close().catch(() => {
1953
- });
1954
- }
1955
- });
1956
- this._process.stdout?.on("error", (error) => {
1957
- this.onerror?.(error);
1958
- });
1959
- if (this._stderrStream && this._process.stderr) this._process.stderr.pipe(this._stderrStream);
1960
- });
1961
- }
1962
- /**
1963
- * The `stderr` stream of the child process, if {@linkcode StdioServerParameters.stderr} was set to `"pipe"` or `"overlapped"`.
1964
- *
1965
- * If `stderr` piping was requested, a `PassThrough` stream is returned _immediately_, allowing callers to
1966
- * attach listeners before the `start` method is invoked. This prevents loss of any early
1967
- * error output emitted by the child process.
1968
- */
1969
- get stderr() {
1970
- if (this._stderrStream) return this._stderrStream;
1971
- return this._process?.stderr ?? null;
1972
- }
1973
- /**
1974
- * The child process pid spawned by this transport.
1975
- *
1976
- * This is only available after the transport has been started.
1977
- */
1978
- get pid() {
1979
- return this._process?.pid ?? null;
1980
- }
1981
- processReadBuffer() {
1982
- while (true) try {
1983
- const message = this._readBuffer.readMessage();
1984
- if (message === null) break;
1985
- this.onmessage?.(message);
1986
- } catch (error) {
1987
- this.onerror?.(error);
1988
- }
1989
- }
1990
- /**
1991
- * Reap a disposable probe sibling (see the version-negotiation sibling
1992
- * flow): signal-first teardown awaiting process `exit` — never the `close`
1993
- * event, so a helper process holding the child's stdio pipes can never
1994
- * block disposal. Not part of the public transport lifecycle.
1995
- *
1996
- * @internal
1997
- */
1998
- async _dispose() {
1999
- const proc = this._process;
2000
- this._process = void 0;
2001
- if (proc && proc.exitCode === null && proc.signalCode === null) {
2002
- const exited = new Promise((resolve) => proc.once("exit", () => resolve()));
2003
- try {
2004
- proc.stdin?.end();
2005
- } catch {
2006
- }
2007
- try {
2008
- proc.kill("SIGTERM");
2009
- } catch {
2010
- }
2011
- await Promise.race([exited, new Promise((resolve) => setTimeout(resolve, 1e3).unref())]);
2012
- if (proc.exitCode === null && proc.signalCode === null) try {
2013
- proc.kill("SIGKILL");
2014
- } catch {
2015
- }
2016
- await exited;
2017
- }
2018
- try {
2019
- proc?.stdout?.destroy();
2020
- } catch {
2021
- }
2022
- try {
2023
- proc?.stdin?.destroy();
2024
- } catch {
2025
- }
2026
- try {
2027
- proc?.stderr?.destroy();
2028
- } catch {
2029
- }
2030
- this._readBuffer.clear();
2031
- }
2032
- async close() {
2033
- if (this._process) {
2034
- const processToClose = this._process;
2035
- this._process = void 0;
2036
- const closePromise = new Promise((resolve) => {
2037
- processToClose.once("close", () => {
2038
- resolve();
2039
- });
2040
- });
2041
- try {
2042
- processToClose.stdin?.end();
2043
- } catch {
2044
- }
2045
- await Promise.race([closePromise, new Promise((resolve) => setTimeout(resolve, 2e3).unref())]);
2046
- if (processToClose.exitCode === null) {
2047
- try {
2048
- processToClose.kill("SIGTERM");
2049
- } catch {
2050
- }
2051
- await Promise.race([closePromise, new Promise((resolve) => setTimeout(resolve, 2e3).unref())]);
2052
- }
2053
- if (processToClose.exitCode === null) try {
2054
- processToClose.kill("SIGKILL");
2055
- } catch {
2056
- }
2057
- }
2058
- this._readBuffer.clear();
2059
- }
2060
- send(message) {
2061
- return new Promise((resolve) => {
2062
- if (!this._process?.stdin) throw new SdkError(SdkErrorCode.NotConnected, "Not connected");
2063
- const json = serializeMessage(message);
2064
- if (this._process.stdin.write(json)) resolve();
2065
- else this._process.stdin.once("drain", resolve);
2066
- });
2067
- }
2068
- };
2069
-
2070
- // node_modules/.pnpm/mcporter@0.13.8/node_modules/mcporter/dist/runtime/stdio-transport.js
4322
+ // node_modules/.pnpm/mcporter@0.13.10/node_modules/mcporter/dist/runtime/stdio-transport.js
2071
4323
  var McporterStdioTransport = class extends StdioClientTransport {
2072
4324
  parameters;
2073
4325
  meta;
@@ -2081,7 +4333,7 @@ var McporterStdioTransport = class extends StdioClientTransport {
2081
4333
  this.closeDelegate?.();
2082
4334
  };
2083
4335
  messageInterceptor = (message) => {
2084
- if (STDIO_TRACE_ENABLED)
4336
+ if (STDIO_TRACE_ENABLED && !this.parameters.redactDiagnostics)
2085
4337
  this.meta.stdoutChunks?.push(JSON.stringify(message));
2086
4338
  this.messageDelegate?.(message);
2087
4339
  };
@@ -2101,7 +4353,8 @@ var McporterStdioTransport = class extends StdioClientTransport {
2101
4353
  if (stderr) {
2102
4354
  stderr.setEncoding?.("utf8");
2103
4355
  const handleChunk = (chunk) => {
2104
- this.meta.stderrChunks.push(Buffer.isBuffer(chunk) ? chunk.toString("utf8") : String(chunk));
4356
+ if (!this.parameters.redactDiagnostics)
4357
+ this.meta.stderrChunks.push(Buffer.isBuffer(chunk) ? chunk.toString("utf8") : String(chunk));
2105
4358
  };
2106
4359
  stderr.on("data", handleChunk);
2107
4360
  stderr.on("error", ignoreStdioEmitterError);
@@ -2109,17 +4362,17 @@ var McporterStdioTransport = class extends StdioClientTransport {
2109
4362
  }
2110
4363
  }
2111
4364
  async start() {
2112
- if (STDIO_TRACE_ENABLED)
4365
+ if (STDIO_TRACE_ENABLED && !this.parameters.redactDiagnostics)
2113
4366
  console.log("[mcporter] STDIO trace: start() invoked for stdio transport.");
2114
4367
  this.installInterceptors();
2115
4368
  await super.start();
2116
- if (STDIO_TRACE_ENABLED) {
4369
+ if (STDIO_TRACE_ENABLED && !this.parameters.redactDiagnostics) {
2117
4370
  console.log(`[mcporter] STDIO trace: spawned ${this.meta.command ?? "stdio server"} (pid=${this.pid ?? "unknown"}).`);
2118
4371
  }
2119
4372
  }
2120
4373
  async send(message) {
2121
4374
  this.installInterceptors();
2122
- if (STDIO_TRACE_ENABLED)
4375
+ if (STDIO_TRACE_ENABLED && !this.parameters.redactDiagnostics)
2123
4376
  this.meta.stdinChunks?.push(JSON.stringify(message));
2124
4377
  await super.send(message);
2125
4378
  }
@@ -2151,7 +4404,7 @@ var McporterStdioTransport = class extends StdioClientTransport {
2151
4404
  }
2152
4405
  };
2153
4406
 
2154
- // node_modules/.pnpm/mcporter@0.13.8/node_modules/mcporter/dist/runtime/transport.js
4407
+ // node_modules/.pnpm/mcporter@0.13.10/node_modules/mcporter/dist/runtime/transport.js
2155
4408
  function shouldUseModeForServer(definition, serverFilter) {
2156
4409
  return !serverFilter || serverFilter === definition.name;
2157
4410
  }
@@ -2212,9 +4465,16 @@ async function createReplayClientContext(definition, replayPath, clientInfo, opt
2212
4465
  return { client, transport, definition, oauthSession: void 0 };
2213
4466
  }
2214
4467
  async function createStdioClientContext(client, definition, logger, options) {
2215
- const mergedEnv = resolveChromeDevtoolsRelayEnvironment(definition.env);
2216
- const command = resolveCommandArgument(definition.command.command);
2217
- const resolvedArgs = resolveCommandArguments(definition.command.args);
4468
+ const mergedEnv = {
4469
+ ...Object.fromEntries(DEFAULT_INHERITED_ENV_VARS.map((key) => [key, void 0])),
4470
+ ...definition.env
4471
+ };
4472
+ if (isBrokerDefinition(definition) && isChromeDefinition(definition) && resolveChromeDevtoolsRelayPolicy(definition.chromeDevtoolsRelay, definition.env) !== "off") {
4473
+ mergedEnv.MCPORTER_CHROME_DEVTOOLS_RELAY_POLICY = "require";
4474
+ delete mergedEnv.MCPORTER_DISABLE_CHROME_DEVTOOLS_RELAY;
4475
+ }
4476
+ const command = resolveCommandArgument(definition.command.command, mergedEnv);
4477
+ const resolvedArgs = resolveCommandArguments(definition.command.args, mergedEnv);
2218
4478
  const publishRelayDecision = (decision) => {
2219
4479
  if (decision.reason === "not-eligible")
2220
4480
  return;
@@ -2224,7 +4484,7 @@ async function createStdioClientContext(client, definition, logger, options) {
2224
4484
  let relayDecision;
2225
4485
  let relay;
2226
4486
  try {
2227
- relay = await rewriteChromeDevtoolsArgsForRelay(command, resolvedArgs, mergedEnv, { onDecision: (decision) => relayDecision = decision }, definition.chromeDevtoolsRelay);
4487
+ relay = await rewriteChromeDevtoolsArgsForRelay(command, resolvedArgs, mergedEnv, { onDecision: (decision) => relayDecision = decision }, isBrokerDefinition(definition) && isChromeDefinition(definition) && resolveChromeDevtoolsRelayPolicy(definition.chromeDevtoolsRelay, definition.env) !== "off" ? "require" : definition.chromeDevtoolsRelay);
2228
4488
  } catch (error) {
2229
4489
  if (relayDecision)
2230
4490
  publishRelayDecision(relayDecision);
@@ -2266,6 +4526,7 @@ async function createStdioClientContext(client, definition, logger, options) {
2266
4526
  args: commandArgs,
2267
4527
  cwd: definition.command.cwd,
2268
4528
  env: compat.env,
4529
+ redactDiagnostics: isBrokerDefinition(definition),
2269
4530
  cleanup: activeProxy ? async () => {
2270
4531
  await handoff?.close();
2271
4532
  await activeProxy?.close();
@@ -2282,15 +4543,13 @@ async function createStdioClientContext(client, definition, logger, options) {
2282
4543
  try {
2283
4544
  transport = wrapRecordTransport(rawTransport, definition, options);
2284
4545
  } catch (error) {
2285
- await closeTransportAndWait(logger, rawTransport).catch(() => {
2286
- });
4546
+ await closeTransportAndWait(logger, rawTransport, { throwOnCloseError: true, requireRetirement: true });
2287
4547
  throw error;
2288
4548
  }
2289
4549
  try {
2290
4550
  await client.connect(transport, { signal: options.signal });
2291
4551
  } catch (error) {
2292
- await closeTransportAndWait(logger, transport).catch(() => {
2293
- });
4552
+ await closeTransportAndWait(logger, transport, { throwOnCloseError: true, requireRetirement: true });
2294
4553
  throw error;
2295
4554
  }
2296
4555
  return { client, transport, definition, oauthSession: void 0 };
@@ -2299,8 +4558,10 @@ async function createClientContext(definition, logger, clientInfo, options = {})
2299
4558
  if (options.replayPath && shouldUseModeForServer(definition, process.env.MCPORTER_REPLAY_SERVER)) {
2300
4559
  return createReplayClientContext(definition, options.replayPath, clientInfo, options);
2301
4560
  }
2302
- const activeDefinition = await applyCachedAuthIfAvailable(definition, logger, options.allowCachedAuth);
2303
- return withEnvOverrides(activeDefinition.env, async () => {
4561
+ assertChromeBrokerAuthority(definition);
4562
+ const env = isBrokerDefinition(definition) ? definition.env : resolveChromeDevtoolsRelayEnvironment(definition.env);
4563
+ return withRuntimeEnvironment(env ?? {}, async () => {
4564
+ const activeDefinition = await applyCachedAuthIfAvailable({ ...definition, env }, logger, options.allowCachedAuth);
2304
4565
  if (activeDefinition.command.kind === "stdio") {
2305
4566
  const stdioDefinition = activeDefinition;
2306
4567
  try {
@@ -2327,7 +4588,7 @@ async function createClientContext(definition, logger, clientInfo, options = {})
2327
4588
  });
2328
4589
  }
2329
4590
 
2330
- // node_modules/.pnpm/mcporter@0.13.8/node_modules/mcporter/dist/runtime/connection-cache.js
4591
+ // node_modules/.pnpm/mcporter@0.13.10/node_modules/mcporter/dist/runtime/connection-cache.js
2331
4592
  var RuntimeConnectionCache = class {
2332
4593
  definitions;
2333
4594
  options;
@@ -2704,11 +4965,12 @@ var RuntimeConnectionCache = class {
2704
4965
  }
2705
4966
  }
2706
4967
  async closeContext(context) {
2707
- const propagateReplayCloseErrors = context.transport instanceof ReplayTransport;
4968
+ const propagateReplayCloseErrors = context.transport instanceof ReplayTransport || isBrokerDefinition(context.definition);
2708
4969
  let closeError;
2709
4970
  try {
2710
4971
  await closeTransportAndWait(this.logger, context.transport, {
2711
4972
  throwOnCloseError: propagateReplayCloseErrors,
4973
+ requireRetirement: isBrokerDefinition(context.definition),
2712
4974
  close: async () => {
2713
4975
  let firstError;
2714
4976
  const clientClose = context.client.close;
@@ -2741,7 +5003,7 @@ var RuntimeConnectionCache = class {
2741
5003
  }
2742
5004
  }
2743
5005
  async resetConnectionOnError(server, error, failedContext) {
2744
- if (!shouldResetConnection(error)) {
5006
+ if (isBrokerDefinition(this.definitions.get(server.trim())) || !shouldResetConnection(error)) {
2745
5007
  return;
2746
5008
  }
2747
5009
  const normalized = server.trim();
@@ -2880,7 +5142,7 @@ function connectionInfoFromClient(client) {
2880
5142
  };
2881
5143
  }
2882
5144
 
2883
- // node_modules/.pnpm/mcporter@0.13.8/node_modules/mcporter/dist/tool-filters.js
5145
+ // node_modules/.pnpm/mcporter@0.13.10/node_modules/mcporter/dist/tool-filters.js
2884
5146
  function validateToolFilters(name, filter) {
2885
5147
  if (filter.allowedTools !== void 0 && filter.blockedTools !== void 0) {
2886
5148
  throw new Error(`Server '${name}' cannot specify both allowedTools and blockedTools.`);
@@ -2902,7 +5164,7 @@ function filterTools(tools, filter) {
2902
5164
  return tools.filter((tool) => isToolAllowed(tool.name, filter));
2903
5165
  }
2904
5166
 
2905
- // node_modules/.pnpm/mcporter@0.13.8/node_modules/mcporter/dist/runtime.js
5167
+ // node_modules/.pnpm/mcporter@0.13.10/node_modules/mcporter/dist/runtime.js
2906
5168
  var PACKAGE_NAME = "mcporter";
2907
5169
  var OAUTH_CODE_TIMEOUT_MS = resolveOAuthTimeoutFromEnv();
2908
5170
  var MAX_RESOURCE_LIST_PAGES = 100;
@@ -2929,6 +5191,7 @@ var McpRuntime = class {
2929
5191
  definitions;
2930
5192
  connectionCache;
2931
5193
  logger;
5194
+ clientInfo;
2932
5195
  constructor(servers, options = {}) {
2933
5196
  for (const server of servers) {
2934
5197
  validateToolFilters(server.name, server);
@@ -2939,6 +5202,7 @@ var McpRuntime = class {
2939
5202
  name: PACKAGE_NAME,
2940
5203
  version: MCPORTER_VERSION
2941
5204
  };
5205
+ this.clientInfo = clientInfo;
2942
5206
  const recordSession = process.env.MCPORTER_RECORD;
2943
5207
  const replaySession = process.env.MCPORTER_REPLAY;
2944
5208
  if (recordSession && replaySession) {
@@ -2964,6 +5228,9 @@ var McpRuntime = class {
2964
5228
  elicitationHandler: options.elicitationHandler ?? defaultResponder.handler
2965
5229
  });
2966
5230
  }
5231
+ getClientInfo() {
5232
+ return { ...this.clientInfo };
5233
+ }
2967
5234
  // listServers returns configured names sorted alphabetically for stable CLI output.
2968
5235
  listServers() {
2969
5236
  return [...this.definitions.keys()].toSorted((a, b) => a.localeCompare(b));
@@ -3013,6 +5280,7 @@ var McpRuntime = class {
3013
5280
  let closeError;
3014
5281
  let tools = [];
3015
5282
  try {
5283
+ await validateBrokerRequestAuthority(this.definitions.get(server.trim()));
3016
5284
  const listPromise = context.client.listTools(void 0, timeoutMs ? { timeout: timeoutMs, resetTimeoutOnProgress: true, maxTotalTimeout: timeoutMs } : void 0);
3017
5285
  const response = timeoutMs ? await raceWithTimeout(listPromise, timeoutMs) : await listPromise;
3018
5286
  tools = (response.tools ?? []).map((tool) => ({
@@ -3057,6 +5325,7 @@ var McpRuntime = class {
3057
5325
  arguments: options.args ?? {}
3058
5326
  };
3059
5327
  const timeoutMs = normalizeTimeout(options.timeoutMs);
5328
+ await validateBrokerRequestAuthority(definition);
3060
5329
  const resultPromise = client.callTool(params, {
3061
5330
  timeout: timeoutMs,
3062
5331
  // Long runs (e.g., GPT-5 Pro) emit progress/logging; allow that to refresh the timer.
@@ -3086,8 +5355,10 @@ var McpRuntime = class {
3086
5355
  const { client } = context;
3087
5356
  const requestParams = params;
3088
5357
  if (requestParams.cursor !== void 0) {
5358
+ await validateBrokerRequestAuthority(this.definitions.get(server.trim()));
3089
5359
  return await client.listResources(requestParams);
3090
5360
  }
5361
+ await validateBrokerRequestAuthority(this.definitions.get(server.trim()));
3091
5362
  let response = await client.request({ method: "resources/list", params: requestParams }, specTypeSchemas.ListResourcesResult);
3092
5363
  const resources = [...response.resources];
3093
5364
  const seenCursors = /* @__PURE__ */ new Set();
@@ -3095,6 +5366,7 @@ var McpRuntime = class {
3095
5366
  if (seenCursors.has(response.nextCursor))
3096
5367
  break;
3097
5368
  seenCursors.add(response.nextCursor);
5369
+ await validateBrokerRequestAuthority(this.definitions.get(server.trim()));
3098
5370
  response = await client.request({ method: "resources/list", params: { ...requestParams, cursor: response.nextCursor } }, specTypeSchemas.ListResourcesResult);
3099
5371
  resources.push(...response.resources);
3100
5372
  }
@@ -3114,6 +5386,7 @@ var McpRuntime = class {
3114
5386
  disableOAuth: effectiveDisableOAuth
3115
5387
  });
3116
5388
  const { client } = context;
5389
+ await validateBrokerRequestAuthority(this.definitions.get(server.trim()));
3117
5390
  return await client.readResource({ uri });
3118
5391
  } catch (error) {
3119
5392
  await this.resetConnectionOnError(server, error, context);
@@ -3144,6 +5417,23 @@ function createConsoleLogger(level = resolveLogLevelFromEnv()) {
3144
5417
  }
3145
5418
 
3146
5419
  export {
5420
+ getChromeDevtoolsRelayDecision,
5421
+ effectiveDefinition,
5422
+ connectionIdentity,
5423
+ isChromeDefinition,
5424
+ resolveSystemPowerShellPath,
5425
+ daemonRunDir,
5426
+ secureDaemonDirectory,
5427
+ inspectLegacyDaemonDirectory,
5428
+ upgradeLegacyDaemonDirectory,
5429
+ getDaemonMetadataPath,
5430
+ getDaemonSocketPath,
5431
+ getDaemonLogPath,
5432
+ canonicalUserConfiguration,
5433
+ BrowserOwner,
5434
+ authorizeBrokerDefinition,
5435
+ isToolAllowed,
5436
+ filterTools,
3147
5437
  createRuntime,
3148
5438
  callOnce
3149
5439
  };