chrome-relay 0.5.11 → 0.5.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +750 -1
- package/dist/index.js +1 -1
- package/dist/native-host.js +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -9,6 +9,714 @@ var __export = (target, all) => {
|
|
|
9
9
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
10
|
};
|
|
11
11
|
|
|
12
|
+
// ../protocol/dist/args/shared.js
|
|
13
|
+
function asObject(input, tool) {
|
|
14
|
+
if (!input || typeof input !== "object" || Array.isArray(input)) {
|
|
15
|
+
throw new RelayError({
|
|
16
|
+
code: "invalid_arguments",
|
|
17
|
+
message: `${tool}: arguments must be a JSON object.`,
|
|
18
|
+
tool,
|
|
19
|
+
phase: "parse_arguments",
|
|
20
|
+
details: { received: input },
|
|
21
|
+
retryable: false
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
return input;
|
|
25
|
+
}
|
|
26
|
+
function requireString(obj, key, tool) {
|
|
27
|
+
const v = obj[key];
|
|
28
|
+
if (typeof v !== "string" || !v) {
|
|
29
|
+
throw new RelayError({
|
|
30
|
+
code: "invalid_arguments",
|
|
31
|
+
message: `${tool}: \`${key}\` is required and must be a non-empty string.`,
|
|
32
|
+
tool,
|
|
33
|
+
phase: "parse_arguments",
|
|
34
|
+
details: { field: key, received: v },
|
|
35
|
+
retryable: false
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
return v;
|
|
39
|
+
}
|
|
40
|
+
function optString(obj, key) {
|
|
41
|
+
const v = obj[key];
|
|
42
|
+
return typeof v === "string" && v ? v : void 0;
|
|
43
|
+
}
|
|
44
|
+
function optNumber(obj, key) {
|
|
45
|
+
const v = obj[key];
|
|
46
|
+
return typeof v === "number" && Number.isFinite(v) ? v : void 0;
|
|
47
|
+
}
|
|
48
|
+
function optBool(obj, key) {
|
|
49
|
+
const v = obj[key];
|
|
50
|
+
return typeof v === "boolean" ? v : void 0;
|
|
51
|
+
}
|
|
52
|
+
function parseTargetArgs(obj) {
|
|
53
|
+
const out = {};
|
|
54
|
+
if (typeof obj.tabId === "number")
|
|
55
|
+
out.tabId = obj.tabId;
|
|
56
|
+
if (typeof obj.workspaceName === "string" && obj.workspaceName)
|
|
57
|
+
out.workspaceName = obj.workspaceName;
|
|
58
|
+
if (typeof obj.groupName === "string" && obj.groupName)
|
|
59
|
+
out.groupName = obj.groupName;
|
|
60
|
+
return out;
|
|
61
|
+
}
|
|
62
|
+
var init_shared = __esm({
|
|
63
|
+
"../protocol/dist/args/shared.js"() {
|
|
64
|
+
"use strict";
|
|
65
|
+
init_dist();
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
// ../protocol/dist/args/navigate.js
|
|
70
|
+
function parseChromeNavigateArgs(input) {
|
|
71
|
+
const obj = asObject(input, TOOL_NAMES.NAVIGATE);
|
|
72
|
+
const out = {
|
|
73
|
+
url: requireString(obj, "url", TOOL_NAMES.NAVIGATE),
|
|
74
|
+
...parseTargetArgs(obj)
|
|
75
|
+
};
|
|
76
|
+
if (typeof obj.tabId === "string" && obj.tabId) {
|
|
77
|
+
const n = Number(obj.tabId);
|
|
78
|
+
if (!Number.isFinite(n)) {
|
|
79
|
+
throw new RelayError({
|
|
80
|
+
code: "invalid_arguments",
|
|
81
|
+
message: `chrome_navigate: invalid tabId ${JSON.stringify(obj.tabId)}. Expected a number.`,
|
|
82
|
+
tool: TOOL_NAMES.NAVIGATE,
|
|
83
|
+
phase: "parse_arguments",
|
|
84
|
+
details: { field: "tabId", received: obj.tabId },
|
|
85
|
+
retryable: false
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
out.tabId = n;
|
|
89
|
+
} else {
|
|
90
|
+
const n = optNumber(obj, "tabId");
|
|
91
|
+
if (n !== void 0)
|
|
92
|
+
out.tabId = n;
|
|
93
|
+
}
|
|
94
|
+
const newTab = optBool(obj, "newTab");
|
|
95
|
+
if (newTab !== void 0)
|
|
96
|
+
out.newTab = newTab;
|
|
97
|
+
const active = optBool(obj, "active");
|
|
98
|
+
if (active !== void 0)
|
|
99
|
+
out.active = active;
|
|
100
|
+
const allowPartial = optBool(obj, "allowPartial");
|
|
101
|
+
if (allowPartial !== void 0)
|
|
102
|
+
out.allowPartial = allowPartial;
|
|
103
|
+
void optString;
|
|
104
|
+
return out;
|
|
105
|
+
}
|
|
106
|
+
var init_navigate = __esm({
|
|
107
|
+
"../protocol/dist/args/navigate.js"() {
|
|
108
|
+
"use strict";
|
|
109
|
+
init_dist();
|
|
110
|
+
init_shared();
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
// ../protocol/dist/args/hover.js
|
|
115
|
+
function parseChromeHoverArgs(input) {
|
|
116
|
+
const obj = asObject(input, TOOL_NAMES.HOVER);
|
|
117
|
+
const target = parseTargetArgs(obj);
|
|
118
|
+
const x = optNumber(obj, "x");
|
|
119
|
+
const y = optNumber(obj, "y");
|
|
120
|
+
if (x !== void 0 && y !== void 0) {
|
|
121
|
+
return { ...target, kind: "coords", x, y };
|
|
122
|
+
}
|
|
123
|
+
const selector = optString(obj, "selector");
|
|
124
|
+
if (selector) {
|
|
125
|
+
return { ...target, kind: "selector", selector };
|
|
126
|
+
}
|
|
127
|
+
throw new RelayError({
|
|
128
|
+
code: "invalid_arguments",
|
|
129
|
+
message: "chrome_hover requires either a selector or x AND y.",
|
|
130
|
+
tool: TOOL_NAMES.HOVER,
|
|
131
|
+
phase: "parse_arguments",
|
|
132
|
+
details: { received: { selector: obj.selector, x: obj.x, y: obj.y } },
|
|
133
|
+
retryable: false
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
var init_hover = __esm({
|
|
137
|
+
"../protocol/dist/args/hover.js"() {
|
|
138
|
+
"use strict";
|
|
139
|
+
init_dist();
|
|
140
|
+
init_shared();
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
// ../protocol/dist/args/network.js
|
|
145
|
+
function parseFilter(obj) {
|
|
146
|
+
const out = {};
|
|
147
|
+
const filter = optString(obj, "filter");
|
|
148
|
+
if (filter)
|
|
149
|
+
out.filter = filter;
|
|
150
|
+
const method = optString(obj, "method");
|
|
151
|
+
if (method)
|
|
152
|
+
out.method = method;
|
|
153
|
+
const limit = optNumber(obj, "limit");
|
|
154
|
+
if (limit !== void 0)
|
|
155
|
+
out.limit = limit;
|
|
156
|
+
const status = obj.status;
|
|
157
|
+
if (status !== void 0 && status !== null) {
|
|
158
|
+
if (typeof status !== "string" || !VALID_STATUSES.includes(status)) {
|
|
159
|
+
throw new RelayError({
|
|
160
|
+
code: "invalid_arguments",
|
|
161
|
+
message: `chrome_network: invalid status ${JSON.stringify(status)}. Expected one of: ${VALID_STATUSES.join(", ")}.`,
|
|
162
|
+
tool: TOOL_NAMES.NETWORK,
|
|
163
|
+
phase: "parse_status",
|
|
164
|
+
details: { received: status, validChoices: VALID_STATUSES },
|
|
165
|
+
retryable: false
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
out.status = status;
|
|
169
|
+
}
|
|
170
|
+
return out;
|
|
171
|
+
}
|
|
172
|
+
function parseChromeNetworkArgs(input) {
|
|
173
|
+
const obj = asObject(input, TOOL_NAMES.NETWORK);
|
|
174
|
+
const target = parseTargetArgs(obj);
|
|
175
|
+
const rawAction = obj.action;
|
|
176
|
+
const action = typeof rawAction === "string" ? rawAction : "read";
|
|
177
|
+
if (action === "clear") {
|
|
178
|
+
return { ...target, action: "clear" };
|
|
179
|
+
}
|
|
180
|
+
if (action === "body") {
|
|
181
|
+
const requestId = optString(obj, "requestId");
|
|
182
|
+
if (!requestId) {
|
|
183
|
+
throw new RelayError({
|
|
184
|
+
code: "invalid_arguments",
|
|
185
|
+
message: "chrome_network body requires `requestId` (a non-empty string).",
|
|
186
|
+
tool: TOOL_NAMES.NETWORK,
|
|
187
|
+
phase: "parse_arguments",
|
|
188
|
+
details: { field: "requestId", received: obj.requestId },
|
|
189
|
+
retryable: false
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
const out = {
|
|
193
|
+
...target,
|
|
194
|
+
action: "body",
|
|
195
|
+
requestId
|
|
196
|
+
};
|
|
197
|
+
const full = optBool(obj, "full");
|
|
198
|
+
if (full !== void 0)
|
|
199
|
+
out.full = full;
|
|
200
|
+
const head = optNumber(obj, "head");
|
|
201
|
+
if (head !== void 0)
|
|
202
|
+
out.head = head;
|
|
203
|
+
return out;
|
|
204
|
+
}
|
|
205
|
+
if (action === "har") {
|
|
206
|
+
const withBodies = optBool(obj, "withBodies");
|
|
207
|
+
const bestEffortBodies = optBool(obj, "bestEffortBodies");
|
|
208
|
+
return {
|
|
209
|
+
...target,
|
|
210
|
+
action: "har",
|
|
211
|
+
...withBodies !== void 0 ? { withBodies } : {},
|
|
212
|
+
...bestEffortBodies !== void 0 ? { bestEffortBodies } : {},
|
|
213
|
+
...parseFilter(obj)
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
if (action === "read") {
|
|
217
|
+
return { ...target, action: "read", ...parseFilter(obj) };
|
|
218
|
+
}
|
|
219
|
+
throw new RelayError({
|
|
220
|
+
code: "invalid_arguments",
|
|
221
|
+
message: `chrome_network: unknown action "${action}". Expected read | clear | har | body.`,
|
|
222
|
+
tool: TOOL_NAMES.NETWORK,
|
|
223
|
+
phase: "parse_action",
|
|
224
|
+
details: { received: action, validChoices: ["read", "clear", "har", "body"] },
|
|
225
|
+
retryable: false
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
var VALID_STATUSES;
|
|
229
|
+
var init_network = __esm({
|
|
230
|
+
"../protocol/dist/args/network.js"() {
|
|
231
|
+
"use strict";
|
|
232
|
+
init_dist();
|
|
233
|
+
init_shared();
|
|
234
|
+
VALID_STATUSES = ["ok", "redirect", "client_error", "server_error", "failed"];
|
|
235
|
+
}
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
// ../protocol/dist/args/simple.js
|
|
239
|
+
function parseGetWindowsAndTabsArgs(_input) {
|
|
240
|
+
return {};
|
|
241
|
+
}
|
|
242
|
+
function parseChromeSelfReloadArgs(_input) {
|
|
243
|
+
return {};
|
|
244
|
+
}
|
|
245
|
+
function parseChromeReadPageArgs(input) {
|
|
246
|
+
const obj = asObject(input, TOOL_NAMES.READ_PAGE);
|
|
247
|
+
const out = { ...parseTargetArgs(obj) };
|
|
248
|
+
const io = optBool(obj, "interactiveOnly");
|
|
249
|
+
if (io !== void 0)
|
|
250
|
+
out.interactiveOnly = io;
|
|
251
|
+
return out;
|
|
252
|
+
}
|
|
253
|
+
function parseChromeClickArgs(input) {
|
|
254
|
+
const obj = asObject(input, TOOL_NAMES.CLICK);
|
|
255
|
+
return {
|
|
256
|
+
selector: requireString(obj, "selector", TOOL_NAMES.CLICK),
|
|
257
|
+
...parseTargetArgs(obj)
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
function parseChromeFillArgs(input) {
|
|
261
|
+
const obj = asObject(input, TOOL_NAMES.FILL);
|
|
262
|
+
if (typeof obj.value !== "string") {
|
|
263
|
+
throw new RelayError({
|
|
264
|
+
code: "invalid_arguments",
|
|
265
|
+
message: `${TOOL_NAMES.FILL}: \`value\` is required and must be a string (empty string allowed).`,
|
|
266
|
+
tool: TOOL_NAMES.FILL,
|
|
267
|
+
phase: "parse_arguments",
|
|
268
|
+
details: { field: "value", received: obj.value },
|
|
269
|
+
retryable: false
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
return {
|
|
273
|
+
selector: requireString(obj, "selector", TOOL_NAMES.FILL),
|
|
274
|
+
value: obj.value,
|
|
275
|
+
...parseTargetArgs(obj)
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
function parseChromeKeyboardArgs(input) {
|
|
279
|
+
const obj = asObject(input, TOOL_NAMES.KEYBOARD);
|
|
280
|
+
return {
|
|
281
|
+
keys: requireString(obj, "keys", TOOL_NAMES.KEYBOARD),
|
|
282
|
+
...parseTargetArgs(obj)
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
function parseChromeTypeArgs(input) {
|
|
286
|
+
const obj = asObject(input, TOOL_NAMES.TYPE);
|
|
287
|
+
const out = {
|
|
288
|
+
text: requireString(obj, "text", TOOL_NAMES.TYPE),
|
|
289
|
+
...parseTargetArgs(obj)
|
|
290
|
+
};
|
|
291
|
+
const selector = optString(obj, "selector");
|
|
292
|
+
if (selector)
|
|
293
|
+
out.selector = selector;
|
|
294
|
+
return out;
|
|
295
|
+
}
|
|
296
|
+
function parseChromeEvaluateArgs(input) {
|
|
297
|
+
const obj = asObject(input, TOOL_NAMES.EVALUATE);
|
|
298
|
+
const out = {
|
|
299
|
+
code: requireString(obj, "code", TOOL_NAMES.EVALUATE),
|
|
300
|
+
...parseTargetArgs(obj)
|
|
301
|
+
};
|
|
302
|
+
const t = optNumber(obj, "timeoutMs");
|
|
303
|
+
if (t !== void 0)
|
|
304
|
+
out.timeoutMs = t;
|
|
305
|
+
return out;
|
|
306
|
+
}
|
|
307
|
+
function parseChromeSwitchTabArgs(input) {
|
|
308
|
+
const obj = asObject(input, TOOL_NAMES.SWITCH_TAB);
|
|
309
|
+
const tabId = Number(obj.tabId);
|
|
310
|
+
if (!Number.isFinite(tabId)) {
|
|
311
|
+
throw new RelayError({
|
|
312
|
+
code: "invalid_arguments",
|
|
313
|
+
message: `${TOOL_NAMES.SWITCH_TAB} requires a numeric tabId.`,
|
|
314
|
+
tool: TOOL_NAMES.SWITCH_TAB,
|
|
315
|
+
phase: "parse_arguments",
|
|
316
|
+
details: { received: obj.tabId },
|
|
317
|
+
retryable: false
|
|
318
|
+
});
|
|
319
|
+
}
|
|
320
|
+
return { tabId };
|
|
321
|
+
}
|
|
322
|
+
function parseChromeCloseTabsArgs(input) {
|
|
323
|
+
const obj = asObject(input, TOOL_NAMES.CLOSE_TABS);
|
|
324
|
+
if (!Array.isArray(obj.tabIds)) {
|
|
325
|
+
throw new RelayError({
|
|
326
|
+
code: "invalid_arguments",
|
|
327
|
+
message: `${TOOL_NAMES.CLOSE_TABS} requires a numeric tabIds array.`,
|
|
328
|
+
tool: TOOL_NAMES.CLOSE_TABS,
|
|
329
|
+
phase: "parse_arguments",
|
|
330
|
+
details: { field: "tabIds", received: obj.tabIds },
|
|
331
|
+
retryable: false
|
|
332
|
+
});
|
|
333
|
+
}
|
|
334
|
+
const tabIds = obj.tabIds.map((v) => Number(v));
|
|
335
|
+
if (tabIds.length === 0 || tabIds.some((n) => !Number.isFinite(n))) {
|
|
336
|
+
throw new RelayError({
|
|
337
|
+
code: "invalid_arguments",
|
|
338
|
+
message: `${TOOL_NAMES.CLOSE_TABS} requires a non-empty array of numeric tab IDs.`,
|
|
339
|
+
tool: TOOL_NAMES.CLOSE_TABS,
|
|
340
|
+
phase: "parse_arguments",
|
|
341
|
+
details: { received: obj.tabIds },
|
|
342
|
+
retryable: false
|
|
343
|
+
});
|
|
344
|
+
}
|
|
345
|
+
return { tabIds };
|
|
346
|
+
}
|
|
347
|
+
function parseChromeAxArgs(input) {
|
|
348
|
+
const obj = asObject(input, TOOL_NAMES.AX);
|
|
349
|
+
const out = { ...parseTargetArgs(obj) };
|
|
350
|
+
const io = optBool(obj, "interactiveOnly");
|
|
351
|
+
if (io !== void 0)
|
|
352
|
+
out.interactiveOnly = io;
|
|
353
|
+
const root = optString(obj, "rootRole");
|
|
354
|
+
if (root)
|
|
355
|
+
out.rootRole = root;
|
|
356
|
+
const is = optBool(obj, "includeSubframes");
|
|
357
|
+
if (is !== void 0)
|
|
358
|
+
out.includeSubframes = is;
|
|
359
|
+
return out;
|
|
360
|
+
}
|
|
361
|
+
function parseChromeClickAxArgs(input) {
|
|
362
|
+
const obj = asObject(input, TOOL_NAMES.CLICK_AX);
|
|
363
|
+
const node = Number(obj.node ?? obj.id);
|
|
364
|
+
if (!Number.isFinite(node) || node <= 0) {
|
|
365
|
+
throw new RelayError({
|
|
366
|
+
code: "invalid_arguments",
|
|
367
|
+
message: `${TOOL_NAMES.CLICK_AX} requires \`node\` (a positive backendDOMNodeId from chrome_ax).`,
|
|
368
|
+
tool: TOOL_NAMES.CLICK_AX,
|
|
369
|
+
phase: "parse_arguments",
|
|
370
|
+
details: { received: obj.node ?? obj.id },
|
|
371
|
+
retryable: false
|
|
372
|
+
});
|
|
373
|
+
}
|
|
374
|
+
return { node, ...parseTargetArgs(obj) };
|
|
375
|
+
}
|
|
376
|
+
function parseChromeScreenshotArgs(input) {
|
|
377
|
+
const obj = asObject(input, TOOL_NAMES.SCREENSHOT);
|
|
378
|
+
const out = { ...parseTargetArgs(obj) };
|
|
379
|
+
const fp = optBool(obj, "fullPage");
|
|
380
|
+
if (fp !== void 0)
|
|
381
|
+
out.fullPage = fp;
|
|
382
|
+
const bbox = optString(obj, "bbox");
|
|
383
|
+
if (bbox)
|
|
384
|
+
out.bbox = bbox;
|
|
385
|
+
const sel = optString(obj, "selector");
|
|
386
|
+
if (sel)
|
|
387
|
+
out.selector = sel;
|
|
388
|
+
const pad = optNumber(obj, "padding");
|
|
389
|
+
if (pad !== void 0)
|
|
390
|
+
out.padding = pad;
|
|
391
|
+
const me = optNumber(obj, "maxEdge");
|
|
392
|
+
if (me !== void 0 && me > 0)
|
|
393
|
+
out.maxEdge = me;
|
|
394
|
+
return out;
|
|
395
|
+
}
|
|
396
|
+
var init_simple = __esm({
|
|
397
|
+
"../protocol/dist/args/simple.js"() {
|
|
398
|
+
"use strict";
|
|
399
|
+
init_dist();
|
|
400
|
+
init_shared();
|
|
401
|
+
}
|
|
402
|
+
});
|
|
403
|
+
|
|
404
|
+
// ../protocol/dist/args/multi.js
|
|
405
|
+
function invalidAction(tool, received, expected) {
|
|
406
|
+
throw new RelayError({
|
|
407
|
+
code: "invalid_arguments",
|
|
408
|
+
message: `${tool}: unknown action ${JSON.stringify(received)}. Expected ${expected.join(" | ")}.`,
|
|
409
|
+
tool,
|
|
410
|
+
phase: "parse_action",
|
|
411
|
+
details: { received, validChoices: expected },
|
|
412
|
+
retryable: false
|
|
413
|
+
});
|
|
414
|
+
}
|
|
415
|
+
function parseChromeViewportArgs(input) {
|
|
416
|
+
const obj = asObject(input, TOOL_NAMES.VIEWPORT);
|
|
417
|
+
const action = typeof obj.action === "string" ? obj.action : "set";
|
|
418
|
+
if (!VALID_VIEWPORT_ACTIONS.includes(action)) {
|
|
419
|
+
invalidAction(TOOL_NAMES.VIEWPORT, action, VALID_VIEWPORT_ACTIONS);
|
|
420
|
+
}
|
|
421
|
+
const target = parseTargetArgs(obj);
|
|
422
|
+
if (action === "list")
|
|
423
|
+
return { action: "list" };
|
|
424
|
+
if (action === "clear")
|
|
425
|
+
return { ...target, action: "clear" };
|
|
426
|
+
if (action === "preset") {
|
|
427
|
+
return { ...target, action: "preset", name: requireString(obj, "name", TOOL_NAMES.VIEWPORT) };
|
|
428
|
+
}
|
|
429
|
+
const width = Number(obj.width);
|
|
430
|
+
const height = Number(obj.height);
|
|
431
|
+
if (!Number.isFinite(width) || !Number.isFinite(height) || width <= 0 || height <= 0) {
|
|
432
|
+
throw new RelayError({
|
|
433
|
+
code: "invalid_arguments",
|
|
434
|
+
message: `${TOOL_NAMES.VIEWPORT} set requires positive numeric width and height.`,
|
|
435
|
+
tool: TOOL_NAMES.VIEWPORT,
|
|
436
|
+
phase: "parse_dimensions",
|
|
437
|
+
details: { received: { width: obj.width, height: obj.height } },
|
|
438
|
+
retryable: false
|
|
439
|
+
});
|
|
440
|
+
}
|
|
441
|
+
const out = {
|
|
442
|
+
...target,
|
|
443
|
+
action: "set",
|
|
444
|
+
width,
|
|
445
|
+
height
|
|
446
|
+
};
|
|
447
|
+
const dpr = optNumber(obj, "dpr");
|
|
448
|
+
if (dpr !== void 0)
|
|
449
|
+
out.dpr = dpr;
|
|
450
|
+
const mobile = optBool(obj, "mobile");
|
|
451
|
+
if (mobile !== void 0)
|
|
452
|
+
out.mobile = mobile;
|
|
453
|
+
const hasTouch = optBool(obj, "hasTouch");
|
|
454
|
+
if (hasTouch !== void 0)
|
|
455
|
+
out.hasTouch = hasTouch;
|
|
456
|
+
const userAgent = optString(obj, "userAgent");
|
|
457
|
+
if (userAgent)
|
|
458
|
+
out.userAgent = userAgent;
|
|
459
|
+
return out;
|
|
460
|
+
}
|
|
461
|
+
function parseLevels(input) {
|
|
462
|
+
if (input === void 0 || input === null)
|
|
463
|
+
return void 0;
|
|
464
|
+
const valid = new Set(VALID_CONSOLE_LEVELS);
|
|
465
|
+
const verify = (s) => {
|
|
466
|
+
if (typeof s !== "string" || !valid.has(s)) {
|
|
467
|
+
throw new RelayError({
|
|
468
|
+
code: "invalid_arguments",
|
|
469
|
+
message: `${TOOL_NAMES.CONSOLE}: invalid level ${JSON.stringify(s)}. Expected one of: ${VALID_CONSOLE_LEVELS.join(", ")}.`,
|
|
470
|
+
tool: TOOL_NAMES.CONSOLE,
|
|
471
|
+
phase: "parse_levels",
|
|
472
|
+
details: { received: s, validChoices: VALID_CONSOLE_LEVELS },
|
|
473
|
+
retryable: false
|
|
474
|
+
});
|
|
475
|
+
}
|
|
476
|
+
return s;
|
|
477
|
+
};
|
|
478
|
+
if (typeof input === "string")
|
|
479
|
+
return input.split(",").map((s) => verify(s.trim()));
|
|
480
|
+
if (Array.isArray(input))
|
|
481
|
+
return input.map(verify);
|
|
482
|
+
throw new RelayError({
|
|
483
|
+
code: "invalid_arguments",
|
|
484
|
+
message: `${TOOL_NAMES.CONSOLE}: invalid levels argument ${JSON.stringify(input)}. Expected a comma-separated string or an array of strings.`,
|
|
485
|
+
tool: TOOL_NAMES.CONSOLE,
|
|
486
|
+
phase: "parse_levels",
|
|
487
|
+
details: { received: input },
|
|
488
|
+
retryable: false
|
|
489
|
+
});
|
|
490
|
+
}
|
|
491
|
+
function parseChromeConsoleArgs(input) {
|
|
492
|
+
const obj = asObject(input, TOOL_NAMES.CONSOLE);
|
|
493
|
+
const target = parseTargetArgs(obj);
|
|
494
|
+
const action = typeof obj.action === "string" ? obj.action : "read";
|
|
495
|
+
if (!VALID_CONSOLE_ACTIONS.includes(action)) {
|
|
496
|
+
invalidAction(TOOL_NAMES.CONSOLE, action, VALID_CONSOLE_ACTIONS);
|
|
497
|
+
}
|
|
498
|
+
if (action === "clear")
|
|
499
|
+
return { ...target, action: "clear" };
|
|
500
|
+
const out = { ...target, action: "read" };
|
|
501
|
+
const levels = parseLevels(obj.levels);
|
|
502
|
+
if (levels)
|
|
503
|
+
out.levels = levels;
|
|
504
|
+
const since = optNumber(obj, "since");
|
|
505
|
+
if (since !== void 0)
|
|
506
|
+
out.since = since;
|
|
507
|
+
const limit = optNumber(obj, "limit");
|
|
508
|
+
if (limit !== void 0)
|
|
509
|
+
out.limit = limit;
|
|
510
|
+
return out;
|
|
511
|
+
}
|
|
512
|
+
function parseChromeWorkspaceArgs(input) {
|
|
513
|
+
const obj = asObject(input, TOOL_NAMES.WORKSPACE);
|
|
514
|
+
const action = typeof obj.action === "string" ? obj.action : "list";
|
|
515
|
+
if (!VALID_WORKSPACE_ACTIONS.includes(action)) {
|
|
516
|
+
invalidAction(TOOL_NAMES.WORKSPACE, action, VALID_WORKSPACE_ACTIONS);
|
|
517
|
+
}
|
|
518
|
+
if (action === "list")
|
|
519
|
+
return { action: "list" };
|
|
520
|
+
if (action === "close")
|
|
521
|
+
return { action: "close", name: requireString(obj, "name", TOOL_NAMES.WORKSPACE) };
|
|
522
|
+
const out = {
|
|
523
|
+
action: "create",
|
|
524
|
+
name: requireString(obj, "name", TOOL_NAMES.WORKSPACE)
|
|
525
|
+
};
|
|
526
|
+
const url = optString(obj, "url");
|
|
527
|
+
if (url)
|
|
528
|
+
out.url = url;
|
|
529
|
+
const label = optString(obj, "label");
|
|
530
|
+
if (label)
|
|
531
|
+
out.label = label;
|
|
532
|
+
return out;
|
|
533
|
+
}
|
|
534
|
+
function parseTabIds(raw) {
|
|
535
|
+
const reject = (bad) => {
|
|
536
|
+
throw new RelayError({
|
|
537
|
+
code: "invalid_arguments",
|
|
538
|
+
message: `${TOOL_NAMES.GROUP}: invalid tabId ${JSON.stringify(bad)}. Expected a number or a comma-separated list of numbers.`,
|
|
539
|
+
tool: TOOL_NAMES.GROUP,
|
|
540
|
+
phase: "parse_tab_ids",
|
|
541
|
+
details: { received: bad },
|
|
542
|
+
retryable: false
|
|
543
|
+
});
|
|
544
|
+
};
|
|
545
|
+
const coerce = (v) => {
|
|
546
|
+
const n = Number(typeof v === "string" ? v.trim() : v);
|
|
547
|
+
if (!Number.isFinite(n))
|
|
548
|
+
reject(v);
|
|
549
|
+
return n;
|
|
550
|
+
};
|
|
551
|
+
if (Array.isArray(raw))
|
|
552
|
+
return raw.map(coerce);
|
|
553
|
+
if (typeof raw === "string")
|
|
554
|
+
return raw.split(",").map(coerce);
|
|
555
|
+
if (typeof raw === "number")
|
|
556
|
+
return [raw];
|
|
557
|
+
return [];
|
|
558
|
+
}
|
|
559
|
+
function parseColor(raw) {
|
|
560
|
+
if (raw === void 0 || raw === null)
|
|
561
|
+
return void 0;
|
|
562
|
+
if (typeof raw !== "string") {
|
|
563
|
+
throw new RelayError({
|
|
564
|
+
code: "invalid_arguments",
|
|
565
|
+
message: `${TOOL_NAMES.GROUP}: invalid color ${JSON.stringify(raw)}. Expected one of: ${VALID_GROUP_COLORS.join(", ")}.`,
|
|
566
|
+
tool: TOOL_NAMES.GROUP,
|
|
567
|
+
phase: "parse_color",
|
|
568
|
+
details: { received: raw, validChoices: VALID_GROUP_COLORS },
|
|
569
|
+
retryable: false
|
|
570
|
+
});
|
|
571
|
+
}
|
|
572
|
+
const c = raw.toLowerCase();
|
|
573
|
+
if (!VALID_GROUP_COLORS.includes(c)) {
|
|
574
|
+
throw new RelayError({
|
|
575
|
+
code: "invalid_arguments",
|
|
576
|
+
message: `${TOOL_NAMES.GROUP}: invalid color "${raw}". Expected one of: ${VALID_GROUP_COLORS.join(", ")}.`,
|
|
577
|
+
tool: TOOL_NAMES.GROUP,
|
|
578
|
+
phase: "parse_color",
|
|
579
|
+
details: { received: raw, validChoices: VALID_GROUP_COLORS },
|
|
580
|
+
retryable: false
|
|
581
|
+
});
|
|
582
|
+
}
|
|
583
|
+
return c;
|
|
584
|
+
}
|
|
585
|
+
function parseChromeGroupArgs(input) {
|
|
586
|
+
const obj = asObject(input, TOOL_NAMES.GROUP);
|
|
587
|
+
const action = typeof obj.action === "string" ? obj.action : "list";
|
|
588
|
+
if (!VALID_GROUP_ACTIONS.includes(action)) {
|
|
589
|
+
invalidAction(TOOL_NAMES.GROUP, action, VALID_GROUP_ACTIONS);
|
|
590
|
+
}
|
|
591
|
+
if (action === "list")
|
|
592
|
+
return { action: "list" };
|
|
593
|
+
if (action === "close")
|
|
594
|
+
return { action: "close", name: requireString(obj, "name", TOOL_NAMES.GROUP) };
|
|
595
|
+
if (action === "remove") {
|
|
596
|
+
const tabIds2 = parseTabIds(obj.tabIds);
|
|
597
|
+
if (tabIds2.length === 0) {
|
|
598
|
+
throw new RelayError({
|
|
599
|
+
code: "invalid_arguments",
|
|
600
|
+
message: `${TOOL_NAMES.GROUP} remove requires tabIds.`,
|
|
601
|
+
tool: TOOL_NAMES.GROUP,
|
|
602
|
+
phase: "parse_arguments",
|
|
603
|
+
details: { field: "tabIds" },
|
|
604
|
+
retryable: false
|
|
605
|
+
});
|
|
606
|
+
}
|
|
607
|
+
return { action: "remove", tabIds: tabIds2 };
|
|
608
|
+
}
|
|
609
|
+
if (action === "add") {
|
|
610
|
+
const tabIds2 = parseTabIds(obj.tabIds);
|
|
611
|
+
if (tabIds2.length === 0) {
|
|
612
|
+
throw new RelayError({
|
|
613
|
+
code: "invalid_arguments",
|
|
614
|
+
message: `${TOOL_NAMES.GROUP} add requires tabIds.`,
|
|
615
|
+
tool: TOOL_NAMES.GROUP,
|
|
616
|
+
phase: "parse_arguments",
|
|
617
|
+
details: { field: "tabIds" },
|
|
618
|
+
retryable: false
|
|
619
|
+
});
|
|
620
|
+
}
|
|
621
|
+
return { action: "add", name: requireString(obj, "name", TOOL_NAMES.GROUP), tabIds: tabIds2 };
|
|
622
|
+
}
|
|
623
|
+
const tabIds = parseTabIds(obj.tabIds);
|
|
624
|
+
if (tabIds.length === 0) {
|
|
625
|
+
throw new RelayError({
|
|
626
|
+
code: "invalid_arguments",
|
|
627
|
+
message: `${TOOL_NAMES.GROUP} create requires at least one tabId.`,
|
|
628
|
+
tool: TOOL_NAMES.GROUP,
|
|
629
|
+
phase: "parse_arguments",
|
|
630
|
+
details: { field: "tabIds" },
|
|
631
|
+
retryable: false
|
|
632
|
+
});
|
|
633
|
+
}
|
|
634
|
+
const out = {
|
|
635
|
+
action: "create",
|
|
636
|
+
name: requireString(obj, "name", TOOL_NAMES.GROUP),
|
|
637
|
+
tabIds
|
|
638
|
+
};
|
|
639
|
+
const color = parseColor(obj.color);
|
|
640
|
+
if (color)
|
|
641
|
+
out.color = color;
|
|
642
|
+
const collapsed = optBool(obj, "collapsed");
|
|
643
|
+
if (collapsed !== void 0)
|
|
644
|
+
out.collapsed = collapsed;
|
|
645
|
+
const windowId = optNumber(obj, "windowId");
|
|
646
|
+
if (windowId !== void 0)
|
|
647
|
+
out.windowId = windowId;
|
|
648
|
+
return out;
|
|
649
|
+
}
|
|
650
|
+
function parseChromeScreencastArgs(input) {
|
|
651
|
+
const obj = asObject(input, TOOL_NAMES.SCREENCAST);
|
|
652
|
+
const target = parseTargetArgs(obj);
|
|
653
|
+
const action = typeof obj.action === "string" ? obj.action : "start";
|
|
654
|
+
if (!VALID_SCREENCAST_ACTIONS.includes(action)) {
|
|
655
|
+
invalidAction(TOOL_NAMES.SCREENCAST, action, VALID_SCREENCAST_ACTIONS);
|
|
656
|
+
}
|
|
657
|
+
if (action === "stop")
|
|
658
|
+
return { ...target, action: "stop" };
|
|
659
|
+
const out = {
|
|
660
|
+
...target,
|
|
661
|
+
action: "start"
|
|
662
|
+
};
|
|
663
|
+
if (obj.format !== void 0 && obj.format !== null) {
|
|
664
|
+
if (obj.format !== "jpeg" && obj.format !== "png") {
|
|
665
|
+
throw new RelayError({
|
|
666
|
+
code: "invalid_arguments",
|
|
667
|
+
message: `${TOOL_NAMES.SCREENCAST}: invalid format ${JSON.stringify(obj.format)}. Expected "jpeg" or "png".`,
|
|
668
|
+
tool: TOOL_NAMES.SCREENCAST,
|
|
669
|
+
phase: "parse_format",
|
|
670
|
+
details: { received: obj.format, validChoices: VALID_SCREENCAST_FORMATS },
|
|
671
|
+
retryable: false
|
|
672
|
+
});
|
|
673
|
+
}
|
|
674
|
+
out.format = obj.format;
|
|
675
|
+
}
|
|
676
|
+
const q = optNumber(obj, "quality");
|
|
677
|
+
if (q !== void 0)
|
|
678
|
+
out.quality = q;
|
|
679
|
+
const mw = optNumber(obj, "maxWidth");
|
|
680
|
+
if (mw !== void 0)
|
|
681
|
+
out.maxWidth = mw;
|
|
682
|
+
const mh = optNumber(obj, "maxHeight");
|
|
683
|
+
if (mh !== void 0)
|
|
684
|
+
out.maxHeight = mh;
|
|
685
|
+
const en = optNumber(obj, "everyNthFrame");
|
|
686
|
+
if (en !== void 0)
|
|
687
|
+
out.everyNthFrame = en;
|
|
688
|
+
return out;
|
|
689
|
+
}
|
|
690
|
+
var VALID_VIEWPORT_ACTIONS, VALID_CONSOLE_ACTIONS, VALID_CONSOLE_LEVELS, VALID_WORKSPACE_ACTIONS, VALID_GROUP_ACTIONS, VALID_GROUP_COLORS, VALID_SCREENCAST_ACTIONS, VALID_SCREENCAST_FORMATS;
|
|
691
|
+
var init_multi = __esm({
|
|
692
|
+
"../protocol/dist/args/multi.js"() {
|
|
693
|
+
"use strict";
|
|
694
|
+
init_dist();
|
|
695
|
+
init_shared();
|
|
696
|
+
VALID_VIEWPORT_ACTIONS = ["set", "preset", "clear", "list"];
|
|
697
|
+
VALID_CONSOLE_ACTIONS = ["read", "clear"];
|
|
698
|
+
VALID_CONSOLE_LEVELS = ["log", "info", "warn", "error", "debug", "exception"];
|
|
699
|
+
VALID_WORKSPACE_ACTIONS = ["create", "list", "close"];
|
|
700
|
+
VALID_GROUP_ACTIONS = ["create", "list", "close", "add", "remove"];
|
|
701
|
+
VALID_GROUP_COLORS = ["grey", "blue", "red", "yellow", "green", "pink", "purple", "cyan", "orange"];
|
|
702
|
+
VALID_SCREENCAST_ACTIONS = ["start", "stop"];
|
|
703
|
+
VALID_SCREENCAST_FORMATS = ["jpeg", "png"];
|
|
704
|
+
}
|
|
705
|
+
});
|
|
706
|
+
|
|
707
|
+
// ../protocol/dist/args/index.js
|
|
708
|
+
var init_args = __esm({
|
|
709
|
+
"../protocol/dist/args/index.js"() {
|
|
710
|
+
"use strict";
|
|
711
|
+
init_shared();
|
|
712
|
+
init_navigate();
|
|
713
|
+
init_hover();
|
|
714
|
+
init_network();
|
|
715
|
+
init_simple();
|
|
716
|
+
init_multi();
|
|
717
|
+
}
|
|
718
|
+
});
|
|
719
|
+
|
|
12
720
|
// ../protocol/dist/index.js
|
|
13
721
|
var dist_exports = {};
|
|
14
722
|
__export(dist_exports, {
|
|
@@ -21,6 +729,33 @@ __export(dist_exports, {
|
|
|
21
729
|
NATIVE_HOST_NAME: () => NATIVE_HOST_NAME,
|
|
22
730
|
RelayError: () => RelayError,
|
|
23
731
|
TOOL_NAMES: () => TOOL_NAMES,
|
|
732
|
+
asObject: () => asObject,
|
|
733
|
+
optBool: () => optBool,
|
|
734
|
+
optNumber: () => optNumber,
|
|
735
|
+
optString: () => optString,
|
|
736
|
+
parseChromeAxArgs: () => parseChromeAxArgs,
|
|
737
|
+
parseChromeClickArgs: () => parseChromeClickArgs,
|
|
738
|
+
parseChromeClickAxArgs: () => parseChromeClickAxArgs,
|
|
739
|
+
parseChromeCloseTabsArgs: () => parseChromeCloseTabsArgs,
|
|
740
|
+
parseChromeConsoleArgs: () => parseChromeConsoleArgs,
|
|
741
|
+
parseChromeEvaluateArgs: () => parseChromeEvaluateArgs,
|
|
742
|
+
parseChromeFillArgs: () => parseChromeFillArgs,
|
|
743
|
+
parseChromeGroupArgs: () => parseChromeGroupArgs,
|
|
744
|
+
parseChromeHoverArgs: () => parseChromeHoverArgs,
|
|
745
|
+
parseChromeKeyboardArgs: () => parseChromeKeyboardArgs,
|
|
746
|
+
parseChromeNavigateArgs: () => parseChromeNavigateArgs,
|
|
747
|
+
parseChromeNetworkArgs: () => parseChromeNetworkArgs,
|
|
748
|
+
parseChromeReadPageArgs: () => parseChromeReadPageArgs,
|
|
749
|
+
parseChromeScreencastArgs: () => parseChromeScreencastArgs,
|
|
750
|
+
parseChromeScreenshotArgs: () => parseChromeScreenshotArgs,
|
|
751
|
+
parseChromeSelfReloadArgs: () => parseChromeSelfReloadArgs,
|
|
752
|
+
parseChromeSwitchTabArgs: () => parseChromeSwitchTabArgs,
|
|
753
|
+
parseChromeTypeArgs: () => parseChromeTypeArgs,
|
|
754
|
+
parseChromeViewportArgs: () => parseChromeViewportArgs,
|
|
755
|
+
parseChromeWorkspaceArgs: () => parseChromeWorkspaceArgs,
|
|
756
|
+
parseGetWindowsAndTabsArgs: () => parseGetWindowsAndTabsArgs,
|
|
757
|
+
parseTargetArgs: () => parseTargetArgs,
|
|
758
|
+
requireString: () => requireString,
|
|
24
759
|
toBridgeError: () => toBridgeError
|
|
25
760
|
});
|
|
26
761
|
function toBridgeError(unknownErr, fallbackTool) {
|
|
@@ -39,6 +774,7 @@ var NATIVE_HOST_NAME, DEFAULT_HTTP_PORT, CHROME_WEB_STORE_EXTENSION_ID, LEGACY_D
|
|
|
39
774
|
var init_dist = __esm({
|
|
40
775
|
"../protocol/dist/index.js"() {
|
|
41
776
|
"use strict";
|
|
777
|
+
init_args();
|
|
42
778
|
NATIVE_HOST_NAME = "dev.chrome_relay.native_host";
|
|
43
779
|
DEFAULT_HTTP_PORT = 12122;
|
|
44
780
|
CHROME_WEB_STORE_EXTENSION_ID = "cpdiapbifblhlcpnmlmfpgfjlacebokb";
|
|
@@ -130,7 +866,7 @@ var init_dist = __esm({
|
|
|
130
866
|
import { Command } from "commander";
|
|
131
867
|
|
|
132
868
|
// src/index.ts
|
|
133
|
-
var CHROME_RELAY_VERSION = true ? "0.5.
|
|
869
|
+
var CHROME_RELAY_VERSION = true ? "0.5.13" : "0.0.0-dev";
|
|
134
870
|
|
|
135
871
|
// src/commands/shared.ts
|
|
136
872
|
init_dist();
|
|
@@ -364,6 +1100,19 @@ async function runDoctor() {
|
|
|
364
1100
|
|
|
365
1101
|
// src/release-notes.ts
|
|
366
1102
|
var RELEASE_NOTES = {
|
|
1103
|
+
"0.5.13": [
|
|
1104
|
+
"Protocol arg-parser coverage complete (code-quality-hardening Risk 1 \u2014 finished). Every one of the 22 tools now has an executable parser in @chrome-relay/protocol that returns a typed args object with `code:'invalid_arguments'` errors on malformed input.",
|
|
1105
|
+
"New parsers in this release: parseChrome{ReadPage,Click,Fill,Keyboard,Type,Evaluate,SwitchTab,CloseTabs,Ax,ClickAx,Screenshot,Viewport,Console,Workspace,Group,Screencast}Args, plus parseGetWindowsAndTabsArgs and parseChromeSelfReloadArgs.",
|
|
1106
|
+
"All extension handlers now consume their parser at the top of the handler body \u2014 silent shape drift between CLI and extension is structurally impossible.",
|
|
1107
|
+
"Multi-action tools (viewport, console, network, workspace, group, screencast) return discriminated unions so the handler branches with TypeScript narrowing instead of `typeof args.action === 'string'` boilerplate.",
|
|
1108
|
+
"36 new tests in packages/protocol/test/args-all.test.ts. Total now 433 (was 397)."
|
|
1109
|
+
],
|
|
1110
|
+
"0.5.12": [
|
|
1111
|
+
"Protocol-owned tool arg parsers (code-quality-hardening Risk 1). New @chrome-relay/protocol exports: `parseChromeNavigateArgs`, `parseChromeHoverArgs`, `parseChromeNetworkArgs`. Each is the single source of truth for what its tool accepts \u2014 CLI and extension consume the same parser so silent shape drift can't happen.",
|
|
1112
|
+
"Pattern established with 3 representative tools (navigate, hover, network \u2014 the doc-followup explicitly named these). Remaining 19 tools are mechanical follow-up (~20 lines + tests each). Each parser throws `RelayError(invalid_arguments)` with field/received/validChoices in details.",
|
|
1113
|
+
"chrome_hover handler refactored to use the new parser end-to-end. Hover args now collapse into a discriminated union (`{kind:'selector', selector}` | `{kind:'coords', x, y}`) so the handler branches without re-doing the typeof dance.",
|
|
1114
|
+
"19 new tests in packages/protocol/test/args.test.ts. Total now 397."
|
|
1115
|
+
],
|
|
367
1116
|
"0.5.11": [
|
|
368
1117
|
"Tests-only: 6 new edge-case tests for `chrome-relay update`. Covers --dry-run, install failure, install-success-but-binary-version-unchanged (PATH mismatch / stale shim), install-success-but-which-fails, install-success-but-release-notes-parse-fails, and the happy path. Locks in the structured-metadata contract from 0.5.7.",
|
|
369
1118
|
"Total tests now 378 (was 372)."
|
package/dist/index.js
CHANGED
package/dist/native-host.js
CHANGED
|
@@ -48,7 +48,7 @@ function toBridgeError(unknownErr, fallbackTool) {
|
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
// src/index.ts
|
|
51
|
-
var CHROME_RELAY_VERSION = true ? "0.5.
|
|
51
|
+
var CHROME_RELAY_VERSION = true ? "0.5.13" : "0.0.0-dev";
|
|
52
52
|
|
|
53
53
|
// src/release-notes.ts
|
|
54
54
|
function compareSemver(a, b) {
|