@xbrowser/cli 1.26.0 → 1.27.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.
@@ -63,12 +63,12 @@ function classifyFailure(message) {
63
63
 
64
64
  // src/executor.ts
65
65
  import {
66
- ok as ok31,
67
- fail as fail16,
66
+ ok as ok32,
67
+ fail as fail17,
68
68
  isCommandResult,
69
69
  CompositeStorage as CompositeStorage2,
70
70
  TipCollector as TipCollector2,
71
- normalizeTips as normalizeTips6,
71
+ normalizeTips as normalizeTips7,
72
72
  configureArchiveStore,
73
73
  appendCommandToArchive,
74
74
  checkGuard,
@@ -5859,26 +5859,193 @@ var waitForCommand = registerCommand({
5859
5859
  }
5860
5860
  });
5861
5861
 
5862
- // src/commands/tab.ts
5862
+ // src/commands/task.ts
5863
5863
  import { z as z27 } from "zod";
5864
- import { ok as ok26, fail as fail12 } from "@dyyz1993/xcli-core";
5865
- var TabParams = z27.object({
5866
- subcommand: z27.enum(["list", "new", "close", "switch"]),
5867
- url: z27.string().optional(),
5868
- index: z27.number().int().min(0).optional()
5864
+ import { ok as ok26, fail as fail12, normalizeTips as normalizeTips5 } from "@dyyz1993/xcli-core";
5865
+ var DECISION_SYSTEM = `\u4F60\u662F\u6D4F\u89C8\u5668\u4EFB\u52A1\u51B3\u7B56\u5668\u3002\u6839\u636E\u76EE\u6807\u3001\u5F53\u524D\u9875\u9762\u5143\u7D20\u6E05\u5355\uFF08\u6BCF\u9879\u5E26 @eN \u7F16\u53F7\uFF09\u548C\u5DF2\u6267\u884C\u5386\u53F2\uFF0C\u8F93\u51FA\u4E0B\u4E00\u6B65\u52A8\u4F5C\u3002
5866
+
5867
+ \u53EF\u7528\u52A8\u4F5C\uFF08\u53EA\u80FD\u8F93\u51FA\u4E00\u4E2A JSON \u5BF9\u8C61\uFF0C\u4E0D\u8981\u8F93\u51FA\u4EFB\u4F55\u5176\u4ED6\u6587\u5B57\uFF09\uFF1A
5868
+ {"action":"click","ref":"@eN","thought":"\u4E3A\u4EC0\u4E48"}
5869
+ {"action":"fill","ref":"@eN","value":"\u6587\u672C","thought":"\u4E3A\u4EC0\u4E48"}
5870
+ {"action":"select","ref":"@eN","value":"\u9009\u9879\u503C","thought":"\u4E3A\u4EC0\u4E48"}
5871
+ {"action":"press","value":"Enter","thought":"\u4E3A\u4EC0\u4E48"}
5872
+ {"action":"scroll","value":"down \u6216 up","thought":"\u4E3A\u4EC0\u4E48"}
5873
+ {"action":"done","value":"\u5B8C\u6210\u6458\u8981","thought":"\u4E3A\u4EC0\u4E48"}
5874
+ {"action":"blocked","value":"\u5361\u4F4F\u539F\u56E0","thought":"\u4E3A\u4EC0\u4E48"}
5875
+
5876
+ \u89C4\u5219\uFF1A
5877
+ 1. ref \u5FC5\u987B\u539F\u6837\u6765\u81EA\u672C\u6B21\u5143\u7D20\u6E05\u5355\uFF1B\u6E05\u5355\u91CC\u6CA1\u6709\u80FD\u63A8\u8FDB\u76EE\u6807\u7684\u5143\u7D20\u5C31\u8F93\u51FA blocked\u3002
5878
+ 2. \u76EE\u6807\u5DF2\u5B8C\u6210\uFF08\u9875\u9762\u4E0A\u80FD\u786E\u8BA4\u7ED3\u679C\uFF09\u5C31\u8F93\u51FA done\uFF0Cvalue \u5199\u5B8C\u6210\u6458\u8981\u3002
5879
+ 3. \u4E0D\u8981\u91CD\u590D\u521A\u5931\u8D25\u8FC7\u7684\u540C\u4E00\u52A8\u4F5C\uFF1B\u8FDE\u7EED\u5931\u8D25\u6362\u601D\u8DEF\u6216 blocked\u3002`;
5880
+ function extractDecision(raw) {
5881
+ let s = raw.trim().replace(/^```(?:json)?\s*/i, "").replace(/\s*```$/, "");
5882
+ const start = s.indexOf("{");
5883
+ if (start < 0) return null;
5884
+ let depth = 0;
5885
+ for (let i = start; i < s.length; i++) {
5886
+ if (s[i] === "{") depth++;
5887
+ else if (s[i] === "}") {
5888
+ depth--;
5889
+ if (depth === 0) {
5890
+ try {
5891
+ return JSON.parse(s.slice(start, i + 1));
5892
+ } catch {
5893
+ return null;
5894
+ }
5895
+ }
5896
+ }
5897
+ }
5898
+ return null;
5899
+ }
5900
+ var taskCommand = registerCommand({
5901
+ name: "task",
5902
+ description: "Autonomous goal loop: observe refs \u2192 LLM decides \u2192 act, until done/blocked (budget-capped)",
5903
+ scope: "page",
5904
+ parameters: z27.object({
5905
+ goal: z27.string().describe("Natural-language goal"),
5906
+ maxSteps: z27.number().int().positive().max(50).optional().default(15).describe("Hard action budget"),
5907
+ timeout: z27.number().optional().default(18e4).describe("Wall clock budget in ms"),
5908
+ limit: z27.number().int().positive().max(300).optional().default(80).describe("Max targets per observe")
5909
+ }),
5910
+ result: z27.object({
5911
+ status: z27.enum(["done", "blocked", "max_steps", "error"]),
5912
+ summary: z27.string().optional(),
5913
+ steps: z27.array(z27.record(z27.unknown())),
5914
+ finalUrl: z27.string().optional(),
5915
+ usage: z27.object({ llmCalls: z27.number(), steps: z27.number() }).passthrough().optional()
5916
+ }).passthrough(),
5917
+ handler: async (p, ctx) => {
5918
+ const creds = loadVLMCredentials2();
5919
+ if (!creds) {
5920
+ return fail12("task \u9700\u8981\u51B3\u7B56\u6A21\u578B\u51ED\u8BC1\uFF1A\u8BBE\u7F6E XBROWSER_VLM_CONFIG \u6216 ~/.zcode/v2/config.json");
5921
+ }
5922
+ const model = process.env.XBROWSER_TASK_MODEL || creds.model;
5923
+ const started = Date.now();
5924
+ const steps = [];
5925
+ const history = [];
5926
+ let llmCalls = 0;
5927
+ let status = "max_steps";
5928
+ let summary = "";
5929
+ let lastError = "";
5930
+ for (let step = 1; step <= p.maxSteps; step++) {
5931
+ if (Date.now() - started > p.timeout) {
5932
+ status = "blocked";
5933
+ summary = `timeout after ${step - 1} steps`;
5934
+ break;
5935
+ }
5936
+ const obs = await observePage(ctx.page, ctx.sessionId, { limit: p.limit, includeHidden: false });
5937
+ const compact = obs.compact ?? obs.targets.map((t, i) => `@e${i + 1} [${t.tag ?? ""}] ${t.name ?? ""}`).join("\n");
5938
+ const screenHash = obs.screenHash;
5939
+ const userPayload = [
5940
+ `\u76EE\u6807\uFF1A${p.goal}`,
5941
+ `\u5F53\u524D\u9875\u9762\uFF08URL: ${obs.url ?? ""}\uFF09\uFF1A`,
5942
+ compact,
5943
+ history.length ? `
5944
+ \u5DF2\u6267\u884C\uFF08\u52FF\u91CD\u590D\u5931\u8D25\u52A8\u4F5C\uFF09\uFF1A
5945
+ ${history.slice(-6).join("\n")}` : ""
5946
+ ].filter(Boolean).join("\n");
5947
+ let raw = "";
5948
+ try {
5949
+ raw = await vlmAsk({ ...creds, model }, [{ type: "text", text: `${DECISION_SYSTEM}
5950
+
5951
+ ---
5952
+
5953
+ ${userPayload}` }], 900);
5954
+ llmCalls++;
5955
+ } catch (e) {
5956
+ lastError = e instanceof Error ? e.message : String(e);
5957
+ status = "error";
5958
+ summary = `LLM call failed: ${lastError}`;
5959
+ break;
5960
+ }
5961
+ const decision = extractDecision(raw);
5962
+ if (!decision || typeof decision.action !== "string") {
5963
+ status = "blocked";
5964
+ summary = `LLM returned unparsable decision: ${raw.slice(0, 120)}`;
5965
+ break;
5966
+ }
5967
+ const action = decision.action;
5968
+ const ref = typeof decision.ref === "string" ? decision.ref : void 0;
5969
+ const value = typeof decision.value === "string" ? decision.value : void 0;
5970
+ const thought = typeof decision.thought === "string" ? decision.thought : void 0;
5971
+ if (action === "done") {
5972
+ status = "done";
5973
+ summary = value || thought || "task done";
5974
+ steps.push({ step, thought, action: "done", ok: true, screenHash });
5975
+ break;
5976
+ }
5977
+ if (action === "blocked") {
5978
+ status = "blocked";
5979
+ summary = value || thought || "LLM judged blocked";
5980
+ steps.push({ step, thought, action: "blocked", ok: true, screenHash });
5981
+ break;
5982
+ }
5983
+ const legalRefs = new Set(obs.targets.map((t, i) => t.ref ?? `e${i + 1}`));
5984
+ const normalizedRef = ref ? legalRefs.has(ref.replace("@", "")) || legalRefs.has(ref) ? ref : void 0 : void 0;
5985
+ if (ref && !normalizedRef && action !== "scroll" && action !== "press") {
5986
+ history.push(`step${step}: ${action} ${ref} REJECTED (ref not in current list)`);
5987
+ steps.push({ step, thought, action, ref, ok: false, error: "ref not in current list", screenHash });
5988
+ continue;
5989
+ }
5990
+ const res = await actOnPage(ctx.page, ctx.sessionId, {
5991
+ action,
5992
+ ref: normalizedRef,
5993
+ value,
5994
+ selector: void 0,
5995
+ force: false,
5996
+ timeout: 1e4
5997
+ });
5998
+ const record = {
5999
+ step,
6000
+ thought,
6001
+ action,
6002
+ ref: normalizedRef,
6003
+ value,
6004
+ ok: res.success === true,
6005
+ stale: res.stale,
6006
+ error: res.success ? void 0 : res.message || res.reason,
6007
+ screenHash
6008
+ };
6009
+ steps.push(record);
6010
+ history.push(`step${step}: ${action} ${normalizedRef ?? ""} ${value ?? ""} -> ${res.success ? "ok" : `failed(${res.reason || res.message})`}`);
6011
+ const sig = (s) => `${s.action}|${s.ref ?? ""}|${s.value ?? ""}`;
6012
+ const last3 = steps.slice(-3);
6013
+ if (last3.length === 3 && new Set(last3.map(sig)).size === 1) {
6014
+ status = "blocked";
6015
+ summary = "dead loop: identical action repeated 3 times";
6016
+ break;
6017
+ }
6018
+ }
6019
+ if (status === "max_steps") summary = summary || `hit maxSteps=${p.maxSteps}`;
6020
+ const finalUrl = ctx.page ? ctx.page.url() : void 0;
6021
+ const data = { status, summary, steps, finalUrl, usage: { llmCalls, steps: steps.length } };
6022
+ if (status === "error") return fail12(summary || lastError, normalizeTips5([`completed steps: ${steps.length}`]));
6023
+ return ok26(data, normalizeTips5([
6024
+ status === "done" ? `\u2705 task done (${steps.length} steps, ${llmCalls} LLM calls)` : `\u26A0\uFE0F task ${status}: ${summary.slice(0, 80)}`
6025
+ ]));
6026
+ }
6027
+ });
6028
+
6029
+ // src/commands/tab.ts
6030
+ import { z as z28 } from "zod";
6031
+ import { ok as ok27, fail as fail13 } from "@dyyz1993/xcli-core";
6032
+ var TabParams = z28.object({
6033
+ subcommand: z28.enum(["list", "new", "close", "switch"]),
6034
+ url: z28.string().optional(),
6035
+ index: z28.number().int().min(0).optional()
5869
6036
  });
5870
6037
  var tabCommand = registerCommand({
5871
6038
  name: "tab",
5872
6039
  description: "Manage browser tabs: list, new, close, switch",
5873
6040
  scope: "page",
5874
6041
  parameters: TabParams,
5875
- result: z27.object({
5876
- success: z27.boolean(),
5877
- data: z27.unknown()
6042
+ result: z28.object({
6043
+ success: z28.boolean(),
6044
+ data: z28.unknown()
5878
6045
  }),
5879
6046
  handler: async (p, ctx) => {
5880
6047
  if (!ctx.browserContext) {
5881
- return fail12("No browser context available. Use --cdp to connect to a browser first.");
6048
+ return fail13("No browser context available. Use --cdp to connect to a browser first.");
5882
6049
  }
5883
6050
  const pages = ctx.browserContext.pages();
5884
6051
  switch (p.subcommand) {
@@ -5891,7 +6058,7 @@ var tabCommand = registerCommand({
5891
6058
  case "switch":
5892
6059
  return handleSwitch(p, pages, ctx);
5893
6060
  default:
5894
- return fail12(`Unknown subcommand: ${p.subcommand}`);
6061
+ return fail13(`Unknown subcommand: ${p.subcommand}`);
5895
6062
  }
5896
6063
  }
5897
6064
  });
@@ -5906,7 +6073,7 @@ async function handleList(pages, ctx) {
5906
6073
  if (isActive) activeIndex = i;
5907
6074
  tabs.push({ index: i, url, title, active: isActive });
5908
6075
  }
5909
- return ok26({ tabs, total: tabs.length, activeIndex });
6076
+ return ok27({ tabs, total: tabs.length, activeIndex });
5910
6077
  }
5911
6078
  async function handleNew(p, _pages, ctx) {
5912
6079
  const newPage = await ctx.browserContext.newPage();
@@ -5934,7 +6101,7 @@ async function handleNew(p, _pages, ctx) {
5934
6101
  const title = await newPage.title().catch(() => "");
5935
6102
  const allPages = ctx.browserContext.pages();
5936
6103
  const newIndex = allPages.indexOf(newPage);
5937
- return ok26({
6104
+ return ok27({
5938
6105
  index: newIndex >= 0 ? newIndex : allPages.length - 1,
5939
6106
  url: newPage.url(),
5940
6107
  title,
@@ -5945,11 +6112,11 @@ async function handleNew(p, _pages, ctx) {
5945
6112
  async function handleClose(p, ctx) {
5946
6113
  const currentPages = ctx.browserContext.pages();
5947
6114
  if (currentPages.length <= 1) {
5948
- return fail12("Cannot close the last remaining tab");
6115
+ return fail13("Cannot close the last remaining tab");
5949
6116
  }
5950
6117
  const closeIndex = p.index ?? currentPages.findIndex((pg) => pg === ctx.page);
5951
6118
  if (closeIndex < 0 || closeIndex >= currentPages.length) {
5952
- return fail12(`Invalid tab index: ${closeIndex}. Valid range: 0-${currentPages.length - 1}`);
6119
+ return fail13(`Invalid tab index: ${closeIndex}. Valid range: 0-${currentPages.length - 1}`);
5953
6120
  }
5954
6121
  const pageToClose = currentPages[closeIndex];
5955
6122
  const isActivePage = pageToClose === ctx.page;
@@ -5964,7 +6131,7 @@ async function handleClose(p, ctx) {
5964
6131
  }
5965
6132
  ctx.page = newActivePage;
5966
6133
  }
5967
- return ok26({
6134
+ return ok27({
5968
6135
  closedIndex: closeIndex,
5969
6136
  total: remainingPages.length,
5970
6137
  activeIndex: isActivePage ? closeIndex < remainingPages.length ? closeIndex : remainingPages.length - 1 : remainingPages.findIndex((pg) => pg === ctx.page)
@@ -5972,10 +6139,10 @@ async function handleClose(p, ctx) {
5972
6139
  }
5973
6140
  async function handleSwitch(p, pages, ctx) {
5974
6141
  if (p.index === void 0) {
5975
- return fail12("Parameter --index is required for switch subcommand");
6142
+ return fail13("Parameter --index is required for switch subcommand");
5976
6143
  }
5977
6144
  if (p.index < 0 || p.index >= pages.length) {
5978
- return fail12(`Invalid tab index: ${p.index}. Valid range: 0-${pages.length - 1}`);
6145
+ return fail13(`Invalid tab index: ${p.index}. Valid range: 0-${pages.length - 1}`);
5979
6146
  }
5980
6147
  const targetPage = pages[p.index];
5981
6148
  await targetPage.bringToFront().catch(() => {
@@ -5997,7 +6164,7 @@ async function handleSwitch(p, pages, ctx) {
5997
6164
  }
5998
6165
  ctx.page = targetPage;
5999
6166
  const title = await targetPage.title().catch(() => "");
6000
- return ok26({
6167
+ return ok27({
6001
6168
  index: p.index,
6002
6169
  url: targetPage.url(),
6003
6170
  title,
@@ -6006,8 +6173,8 @@ async function handleSwitch(p, pages, ctx) {
6006
6173
  }
6007
6174
 
6008
6175
  // src/commands/addinitscript.ts
6009
- import { z as z28 } from "zod";
6010
- import { ok as ok27 } from "@dyyz1993/xcli-core";
6176
+ import { z as z29 } from "zod";
6177
+ import { ok as ok28 } from "@dyyz1993/xcli-core";
6011
6178
  import { readFileSync as readFileSync4 } from "fs";
6012
6179
 
6013
6180
  // src/chain-parser.ts
@@ -6148,14 +6315,14 @@ registerCommandDefinition("tab", ["subcommand"]);
6148
6315
  registerCommandDefinition("mouse", ["action", "x", "y"]);
6149
6316
 
6150
6317
  // src/commands/addinitscript.ts
6151
- var InitScriptParams = z28.object({
6152
- script: z28.string().optional(),
6153
- file: z28.string().optional(),
6154
- stdin: z28.boolean().optional(),
6155
- name: z28.string().optional(),
6156
- list: z28.boolean().optional(),
6157
- remove: z28.union([z28.string(), z28.boolean()]).optional(),
6158
- base64: z28.string().optional()
6318
+ var InitScriptParams = z29.object({
6319
+ script: z29.string().optional(),
6320
+ file: z29.string().optional(),
6321
+ stdin: z29.boolean().optional(),
6322
+ name: z29.string().optional(),
6323
+ list: z29.boolean().optional(),
6324
+ remove: z29.union([z29.string(), z29.boolean()]).optional(),
6325
+ base64: z29.string().optional()
6159
6326
  });
6160
6327
  var registeredScripts = /* @__PURE__ */ new Map();
6161
6328
  function resolveScriptContent(params) {
@@ -6189,14 +6356,14 @@ var addInitScriptCommand = registerCommand({
6189
6356
  description: "Add an initialization script that runs on every page load",
6190
6357
  scope: "page",
6191
6358
  parameters: InitScriptParams,
6192
- result: z28.object({
6193
- scripts: z28.array(z28.object({ name: z28.string(), size: z28.number(), preview: z28.string() })).optional(),
6194
- removed: z28.string().optional(),
6195
- existed: z28.boolean().optional(),
6196
- error: z28.string().optional(),
6197
- registered: z28.string().optional(),
6198
- hint: z28.string().optional(),
6199
- executedImmediately: z28.boolean().optional()
6359
+ result: z29.object({
6360
+ scripts: z29.array(z29.object({ name: z29.string(), size: z29.number(), preview: z29.string() })).optional(),
6361
+ removed: z29.string().optional(),
6362
+ existed: z29.boolean().optional(),
6363
+ error: z29.string().optional(),
6364
+ registered: z29.string().optional(),
6365
+ hint: z29.string().optional(),
6366
+ executedImmediately: z29.boolean().optional()
6200
6367
  }).passthrough(),
6201
6368
  handler: async (params, ctx) => {
6202
6369
  if (params.list) {
@@ -6205,20 +6372,20 @@ var addInitScriptCommand = registerCommand({
6205
6372
  size: content2.length,
6206
6373
  preview: content2.slice(0, 80)
6207
6374
  }));
6208
- return ok27({ scripts });
6375
+ return ok28({ scripts });
6209
6376
  }
6210
6377
  if (params.remove && typeof params.remove === "string") {
6211
6378
  const existed = registeredScripts.delete(params.remove);
6212
- return ok27({ removed: params.remove, existed });
6379
+ return ok28({ removed: params.remove, existed });
6213
6380
  }
6214
6381
  const removeTarget = (typeof params.remove === "string" ? params.remove : null) || (params.name && !resolveScriptContent(params) ? params.name : null);
6215
6382
  if (removeTarget && !resolveScriptContent(params)) {
6216
6383
  const existed = registeredScripts.delete(removeTarget);
6217
- return ok27({ removed: removeTarget, existed });
6384
+ return ok28({ removed: removeTarget, existed });
6218
6385
  }
6219
6386
  let content = params.stdin ? await readStdin() : resolveScriptContent(params);
6220
6387
  if (!content) {
6221
- return ok27({ error: "No script content provided. Use --script, --file, --stdin, or --base64" });
6388
+ return ok28({ error: "No script content provided. Use --script, --file, --stdin, or --base64" });
6222
6389
  }
6223
6390
  const scriptName = params.name ?? `script-${Date.now()}`;
6224
6391
  registeredScripts.set(scriptName, content);
@@ -6226,45 +6393,45 @@ var addInitScriptCommand = registerCommand({
6226
6393
  try {
6227
6394
  await ctx.page.evaluate(content);
6228
6395
  } catch {
6229
- return ok27({
6396
+ return ok28({
6230
6397
  registered: scriptName,
6231
6398
  hint: "Script registered for future page loads; immediate execution skipped (page may not be ready)"
6232
6399
  });
6233
6400
  }
6234
- return ok27({ registered: scriptName, executedImmediately: true });
6401
+ return ok28({ registered: scriptName, executedImmediately: true });
6235
6402
  }
6236
6403
  });
6237
6404
  registerCommandDefinition("addinitscript", ["script"]);
6238
6405
 
6239
6406
  // src/commands/find.ts
6240
- import { z as z29 } from "zod";
6241
- import { ok as ok28, fail as fail13, normalizeTips as normalizeTips5 } from "@dyyz1993/xcli-core";
6242
- var actionSchema2 = z29.enum(["click", "fill", "type", "select", "hover", "check"]);
6407
+ import { z as z30 } from "zod";
6408
+ import { ok as ok29, fail as fail14, normalizeTips as normalizeTips6 } from "@dyyz1993/xcli-core";
6409
+ var actionSchema2 = z30.enum(["click", "fill", "type", "select", "hover", "check"]);
6243
6410
  var findCommand = registerCommand({
6244
6411
  name: "find",
6245
6412
  description: "Find elements by semantic strategy (text/role/label/placeholder/testid) and optionally perform an action",
6246
6413
  scope: "page",
6247
- parameters: z29.object({
6248
- strategy: z29.enum(["text", "role", "label", "placeholder", "testid", "alt", "title", "first", "last", "nth"]),
6249
- value: z29.string(),
6250
- name: z29.string().optional(),
6251
- exact: z29.boolean().optional().default(false),
6252
- operation: z29.string().optional().describe('Trailing operation syntax, e.g. click, fill "text", type "text"'),
6414
+ parameters: z30.object({
6415
+ strategy: z30.enum(["text", "role", "label", "placeholder", "testid", "alt", "title", "first", "last", "nth"]),
6416
+ value: z30.string(),
6417
+ name: z30.string().optional(),
6418
+ exact: z30.boolean().optional().default(false),
6419
+ operation: z30.string().optional().describe('Trailing operation syntax, e.g. click, fill "text", type "text"'),
6253
6420
  action: actionSchema2.optional().describe("Action to perform when not using trailing operation syntax"),
6254
- actionValue: z29.string().optional().describe("Value for fill/type/select when using action"),
6255
- index: z29.number().int().optional().describe("Index for nth strategy"),
6256
- click: z29.boolean().optional().default(false),
6257
- fill: z29.string().optional(),
6258
- type: z29.string().optional(),
6259
- select: z29.string().optional(),
6260
- hover: z29.boolean().optional().default(false),
6261
- check: z29.boolean().optional().default(false),
6262
- timeout: z29.number().optional().default(1e4)
6421
+ actionValue: z30.string().optional().describe("Value for fill/type/select when using action"),
6422
+ index: z30.number().int().optional().describe("Index for nth strategy"),
6423
+ click: z30.boolean().optional().default(false),
6424
+ fill: z30.string().optional(),
6425
+ type: z30.string().optional(),
6426
+ select: z30.string().optional(),
6427
+ hover: z30.boolean().optional().default(false),
6428
+ check: z30.boolean().optional().default(false),
6429
+ timeout: z30.number().optional().default(1e4)
6263
6430
  }),
6264
- result: z29.object({
6265
- matched: z29.number(),
6266
- selector: z29.string(),
6267
- action: z29.string().optional()
6431
+ result: z30.object({
6432
+ matched: z30.number(),
6433
+ selector: z30.string(),
6434
+ action: z30.string().optional()
6268
6435
  }),
6269
6436
  handler: async (p, ctx) => {
6270
6437
  const page = ctx.page;
@@ -6279,7 +6446,7 @@ var findCommand = registerCommand({
6279
6446
  });
6280
6447
  const count = await locator.count();
6281
6448
  if (count === 0) {
6282
- return fail13(`No element found with ${p.strategy}="${p.value}"`);
6449
+ return fail14(`No element found with ${p.strategy}="${p.value}"`);
6283
6450
  }
6284
6451
  const tips = [];
6285
6452
  const target = selectTarget(locator, p.strategy);
@@ -6291,15 +6458,15 @@ var findCommand = registerCommand({
6291
6458
  await target.click({ timeout: p.timeout, force: true });
6292
6459
  return okWithTips({ matched: count, selector, action: "click" }, tips);
6293
6460
  } else if (actionName === "fill") {
6294
- if (actionValue === void 0) return fail13("find fill requires a value");
6461
+ if (actionValue === void 0) return fail14("find fill requires a value");
6295
6462
  await target.fill(actionValue, { timeout: p.timeout, force: true });
6296
6463
  return okWithTips({ matched: count, selector, action: `fill("${actionValue}")` }, tips);
6297
6464
  } else if (actionName === "type") {
6298
- if (actionValue === void 0) return fail13("find type requires a value");
6465
+ if (actionValue === void 0) return fail14("find type requires a value");
6299
6466
  await target.type(actionValue, { delay: 10, timeout: p.timeout });
6300
6467
  return okWithTips({ matched: count, selector, action: `type("${actionValue}")` }, tips);
6301
6468
  } else if (actionName === "select") {
6302
- if (actionValue === void 0) return fail13("find select requires a value");
6469
+ if (actionValue === void 0) return fail14("find select requires a value");
6303
6470
  await target.selectOption(actionValue);
6304
6471
  return okWithTips({ matched: count, selector, action: `select("${actionValue}")` }, tips);
6305
6472
  } else if (actionName === "hover") {
@@ -6313,8 +6480,8 @@ var findCommand = registerCommand({
6313
6480
  }
6314
6481
  });
6315
6482
  function okWithTips(data, tips) {
6316
- const result = ok28(data);
6317
- if (tips.length > 0) result.tips = normalizeTips5(tips);
6483
+ const result = ok29(data);
6484
+ if (tips.length > 0) result.tips = normalizeTips6(tips);
6318
6485
  return result;
6319
6486
  }
6320
6487
  function parseOperation(operation) {
@@ -6412,8 +6579,8 @@ function describeSelector(strategy, value, name) {
6412
6579
  }
6413
6580
 
6414
6581
  // src/commands/visual-tag.ts
6415
- import { z as z30 } from "zod";
6416
- import { ok as ok29, fail as fail14 } from "@dyyz1993/xcli-core";
6582
+ import { z as z31 } from "zod";
6583
+ import { ok as ok30, fail as fail15 } from "@dyyz1993/xcli-core";
6417
6584
  var SAFE_SET = "ahjkmnprtw3479".split("");
6418
6585
  var TAG_SCRIPT = `
6419
6586
  (function() {
@@ -6504,49 +6671,49 @@ var visualTagCommand = registerCommand({
6504
6671
  name: "visual-tag",
6505
6672
  description: "\u5728\u9875\u9762\u4E0A\u7ED9\u53EF\u4EA4\u4E92\u5143\u7D20\u53E0\u52A0\u9632\u6DF7\u6DC6\u77ED ID \u6807\u7B7E\uFF08\u89C6\u89C9\u5B9A\u4F4D\u7528\uFF09",
6506
6673
  scope: "page",
6507
- parameters: z30.object({
6508
- action: z30.enum(["tag", "lookup", "clear", "list"]),
6509
- id: z30.string().optional().describe("lookup \u65F6\u6307\u5B9A\u8981\u67E5\u7684 ID")
6674
+ parameters: z31.object({
6675
+ action: z31.enum(["tag", "lookup", "clear", "list"]),
6676
+ id: z31.string().optional().describe("lookup \u65F6\u6307\u5B9A\u8981\u67E5\u7684 ID")
6510
6677
  }),
6511
- result: z30.object({
6512
- action: z30.string(),
6513
- tagged: z30.number().optional(),
6514
- id: z30.string().optional(),
6515
- element: z30.record(z30.unknown()).optional()
6678
+ result: z31.object({
6679
+ action: z31.string(),
6680
+ tagged: z31.number().optional(),
6681
+ id: z31.string().optional(),
6682
+ element: z31.record(z31.unknown()).optional()
6516
6683
  }),
6517
6684
  handler: async (p, ctx) => {
6518
6685
  switch (p.action) {
6519
6686
  case "tag": {
6520
6687
  const result = await ctx.page.evaluate(TAG_SCRIPT);
6521
6688
  const parsed = JSON.parse(result);
6522
- return ok29({ action: "tag", tagged: parsed.tagged });
6689
+ return ok30({ action: "tag", tagged: parsed.tagged });
6523
6690
  }
6524
6691
  case "lookup": {
6525
- if (!p.id) return fail14("lookup \u9700\u8981 --id \u53C2\u6570");
6692
+ if (!p.id) return fail15("lookup \u9700\u8981 --id \u53C2\u6570");
6526
6693
  const result = await ctx.page.evaluate(
6527
6694
  `(function() { var m = window.__xbTagMap; if (!m) return JSON.stringify({err:'no-map'}); var e = m[${JSON.stringify(p.id)}]; return e ? JSON.stringify(e) : JSON.stringify({err:'not-found'}); })()`
6528
6695
  );
6529
6696
  const parsed = JSON.parse(result);
6530
- if (parsed.err) return fail14(`ID ${p.id}: ${parsed.err}`);
6531
- return ok29({ action: "lookup", id: p.id, element: parsed });
6697
+ if (parsed.err) return fail15(`ID ${p.id}: ${parsed.err}`);
6698
+ return ok30({ action: "lookup", id: p.id, element: parsed });
6532
6699
  }
6533
6700
  case "list": {
6534
6701
  const result = await ctx.page.evaluate(
6535
6702
  `(function() { var m = window.__xbTagMap; if (!m) return '{}'; var out = {}; for (var k in m) { out[k] = m[k].text || m[k].tagName; } return JSON.stringify(out); })()`
6536
6703
  );
6537
- return ok29({ action: "list", element: JSON.parse(result) });
6704
+ return ok30({ action: "list", element: JSON.parse(result) });
6538
6705
  }
6539
6706
  case "clear": {
6540
6707
  await ctx.page.evaluate(`(function(){var o=document.getElementById('__xb-tag-overlay');if(o)o.remove();window.__xbTagMap=null;return 'cleared'})()`);
6541
- return ok29({ action: "clear" });
6708
+ return ok30({ action: "clear" });
6542
6709
  }
6543
6710
  }
6544
6711
  }
6545
6712
  });
6546
6713
 
6547
6714
  // src/commands/visual-tag-v2.ts
6548
- import { z as z31 } from "zod";
6549
- import { ok as ok30, fail as fail15 } from "@dyyz1993/xcli-core";
6715
+ import { z as z32 } from "zod";
6716
+ import { ok as ok31, fail as fail16 } from "@dyyz1993/xcli-core";
6550
6717
  var SAFE_SET2 = "ahjkmnprtw3479".split("");
6551
6718
  var TAG_V2_SCRIPT = `
6552
6719
  (function() {
@@ -6893,45 +7060,45 @@ var visualTagV2Command = registerCommand({
6893
7060
  name: "visual-tag-v2",
6894
7061
  description: "\u5206\u8272\u6807\u6CE8\u9875\u9762\u5143\u7D20\uFF08\u7EA2=\u53EF\u70B9\u51FB \u84DD=\u8F93\u5165 \u7EFF=\u56FE\u7247 \u9EC4=\u5217\u8868 \u7D2B=\u6570\u5B57 \u6A59=\u6587\u672C\uFF09",
6895
7062
  scope: "page",
6896
- parameters: z31.object({
6897
- action: z31.enum(["tag", "lookup", "clear", "stats", "by-type", "find", "export", "interact"]),
6898
- id: z31.string().optional().describe("lookup \u65F6\u6307\u5B9A\u8981\u67E5\u7684 ID"),
6899
- query: z31.string().optional().describe('find \u65F6\u6307\u5B9A\u641C\u7D22\u8BCD\uFF08\u5982 "\u627E\u6709AI\u7F16\u7A0B\u6807\u7B7E\u7684\u5361\u7247"\uFF09'),
6900
- type: z31.string().optional().describe("by-type \u65F6\u8FC7\u6EE4\u7C7B\u578B\uFF1Aclick/input/img/list/count/text"),
6901
- "interact-action": z31.enum(["click", "fill", "read"]).optional().describe("interact \u52A8\u4F5C\u7C7B\u578B"),
6902
- value: z31.string().optional().describe("fill \u65F6\u7684\u586B\u5145\u503C")
7063
+ parameters: z32.object({
7064
+ action: z32.enum(["tag", "lookup", "clear", "stats", "by-type", "find", "export", "interact"]),
7065
+ id: z32.string().optional().describe("lookup \u65F6\u6307\u5B9A\u8981\u67E5\u7684 ID"),
7066
+ query: z32.string().optional().describe('find \u65F6\u6307\u5B9A\u641C\u7D22\u8BCD\uFF08\u5982 "\u627E\u6709AI\u7F16\u7A0B\u6807\u7B7E\u7684\u5361\u7247"\uFF09'),
7067
+ type: z32.string().optional().describe("by-type \u65F6\u8FC7\u6EE4\u7C7B\u578B\uFF1Aclick/input/img/list/count/text"),
7068
+ "interact-action": z32.enum(["click", "fill", "read"]).optional().describe("interact \u52A8\u4F5C\u7C7B\u578B"),
7069
+ value: z32.string().optional().describe("fill \u65F6\u7684\u586B\u5145\u503C")
6903
7070
  }),
6904
- result: z31.object({
6905
- action: z31.string(),
6906
- total: z31.number().optional(),
6907
- byType: z31.record(z31.number()).optional(),
6908
- element: z31.record(z31.unknown()).optional()
7071
+ result: z32.object({
7072
+ action: z32.string(),
7073
+ total: z32.number().optional(),
7074
+ byType: z32.record(z32.number()).optional(),
7075
+ element: z32.record(z32.unknown()).optional()
6909
7076
  }),
6910
7077
  handler: async (p, ctx) => {
6911
7078
  switch (p.action) {
6912
7079
  case "tag": {
6913
7080
  const result = await ctx.page.evaluate(TAG_V2_SCRIPT);
6914
7081
  const parsed = JSON.parse(result);
6915
- return ok30({ action: "tag", total: parsed.total, byType: parsed.byType });
7082
+ return ok31({ action: "tag", total: parsed.total, byType: parsed.byType });
6916
7083
  }
6917
7084
  case "lookup": {
6918
- if (!p.id) return fail15("lookup \u9700\u8981 --id");
7085
+ if (!p.id) return fail16("lookup \u9700\u8981 --id");
6919
7086
  const result = await ctx.page.evaluate(
6920
7087
  `(function(){var m=window.__xbTagMap;if(!m)return JSON.stringify({err:'no-map'});var e=m[${JSON.stringify(p.id)}];return e?JSON.stringify(e):JSON.stringify({err:'not-found'})})()`
6921
7088
  );
6922
7089
  const parsed = JSON.parse(result);
6923
- if (parsed.err) return fail15(`ID ${p.id}: ${parsed.err}`);
6924
- return ok30({ action: "lookup", id: p.id, element: parsed });
7090
+ if (parsed.err) return fail16(`ID ${p.id}: ${parsed.err}`);
7091
+ return ok31({ action: "lookup", id: p.id, element: parsed });
6925
7092
  }
6926
7093
  case "by-type": {
6927
7094
  const result = await ctx.page.evaluate(
6928
7095
  `(function(){var m=window.__xbTagMap;if(!m)return'{}';var out={};for(var k in m){if(!${JSON.stringify(p.type || "")}||m[k].type===${JSON.stringify(p.type || "")}){out[k]={type:m[k].type,text:m[k].text,num:m[k].num,label:m[k].formLabel}}}return JSON.stringify(out)})()`
6929
7096
  );
6930
- return ok30({ action: "by-type", element: JSON.parse(result) });
7097
+ return ok31({ action: "by-type", element: JSON.parse(result) });
6931
7098
  }
6932
7099
  case "find": {
6933
7100
  const query = p.query;
6934
- if (!query) return fail15('find \u9700\u8981 --query \u53C2\u6570\uFF08\u5982 "\u627E\u6709AI\u7F16\u7A0B\u6807\u7B7E\u7684\u5361\u7247"\uFF09');
7101
+ if (!query) return fail16('find \u9700\u8981 --query \u53C2\u6570\uFF08\u5982 "\u627E\u6709AI\u7F16\u7A0B\u6807\u7B7E\u7684\u5361\u7247"\uFF09');
6935
7102
  const result = await ctx.page.evaluate(
6936
7103
  `(function(){
6937
7104
  var map = window.__xbTagSerializable;
@@ -6973,21 +7140,21 @@ var visualTagV2Command = registerCommand({
6973
7140
  return JSON.stringify({total:results.length, results:results.slice(0,20)});
6974
7141
  })()`
6975
7142
  );
6976
- return ok30({ action: "find", query, element: JSON.parse(result) });
7143
+ return ok31({ action: "find", query, element: JSON.parse(result) });
6977
7144
  }
6978
7145
  case "stats": {
6979
7146
  const result = await ctx.page.evaluate(
6980
7147
  `(function(){return JSON.stringify(window.__xbTagStats||{})})()`
6981
7148
  );
6982
- return ok30({ action: "stats", element: JSON.parse(result) });
7149
+ return ok31({ action: "stats", element: JSON.parse(result) });
6983
7150
  }
6984
7151
  case "interact": {
6985
7152
  const query = p.query;
6986
7153
  const pAny = p;
6987
7154
  const action = pAny["interact-action"] || pAny.interactAction || pAny.interact_action;
6988
7155
  const value = pAny.value;
6989
- if (!query) return fail15("interact \u9700\u8981 --query \u53C2\u6570");
6990
- if (!action) return fail15("interact \u9700\u8981 --interact-action \u53C2\u6570\uFF08click/fill/read\uFF09");
7156
+ if (!query) return fail16("interact \u9700\u8981 --query \u53C2\u6570");
7157
+ if (!action) return fail16("interact \u9700\u8981 --interact-action \u53C2\u6570\uFF08click/fill/read\uFF09");
6991
7158
  const findResult = await ctx.page.evaluate(
6992
7159
  `(function(){
6993
7160
  var map = window.__xbTagSerializable;
@@ -7017,11 +7184,11 @@ var visualTagV2Command = registerCommand({
7017
7184
  })()`
7018
7185
  );
7019
7186
  const parsed = JSON.parse(findResult);
7020
- if (parsed.err) return fail15(parsed.err);
7021
- if (!parsed.total || !parsed.results?.length) return fail15(`\u672A\u627E\u5230\u5339\u914D "${query}" \u7684\u5143\u7D20`);
7187
+ if (parsed.err) return fail16(parsed.err);
7188
+ if (!parsed.total || !parsed.results?.length) return fail16(`\u672A\u627E\u5230\u5339\u914D "${query}" \u7684\u5143\u7D20`);
7022
7189
  const target = parsed.results[0];
7023
7190
  if (action === "read") {
7024
- return ok30({ action: "interact", query, target, result: { read: target.text || target.label } });
7191
+ return ok31({ action: "interact", query, target, result: { read: target.text || target.label } });
7025
7192
  }
7026
7193
  if (action === "click") {
7027
7194
  const el = await ctx.page.evaluate(
@@ -7034,12 +7201,12 @@ var visualTagV2Command = registerCommand({
7034
7201
  return {x: Math.round(r.x + r.width/2), y: Math.round(r.y + r.height/2)};
7035
7202
  })()`
7036
7203
  );
7037
- if (!el) return fail15(`\u5143\u7D20 ${target.id} \u4E0D\u53EF\u4EA4\u4E92`);
7204
+ if (!el) return fail16(`\u5143\u7D20 ${target.id} \u4E0D\u53EF\u4EA4\u4E92`);
7038
7205
  await ctx.page.mouse.click(el.x, el.y, { stealth: true });
7039
- return ok30({ action: "interact", query, target, result: { clicked: true, x: el.x, y: el.y } });
7206
+ return ok31({ action: "interact", query, target, result: { clicked: true, x: el.x, y: el.y } });
7040
7207
  }
7041
7208
  if (action === "fill") {
7042
- if (!value) return fail15("fill \u9700\u8981 --value \u53C2\u6570");
7209
+ if (!value) return fail16("fill \u9700\u8981 --value \u53C2\u6570");
7043
7210
  const el = await ctx.page.evaluate(
7044
7211
  `(function(){
7045
7212
  var map = window.__xbTagMap;
@@ -7050,12 +7217,12 @@ var visualTagV2Command = registerCommand({
7050
7217
  return {x: Math.round(r.x + r.width/2), y: Math.round(r.y + r.height/2)};
7051
7218
  })()`
7052
7219
  );
7053
- if (!el) return fail15(`\u5143\u7D20 ${target.id} \u4E0D\u53EF\u4EA4\u4E92`);
7220
+ if (!el) return fail16(`\u5143\u7D20 ${target.id} \u4E0D\u53EF\u4EA4\u4E92`);
7054
7221
  await ctx.page.mouse.click(el.x, el.y, { stealth: true });
7055
7222
  await ctx.page.keyboard.type(value, { stealth: true });
7056
- return ok30({ action: "interact", query, target, result: { filled: true, value } });
7223
+ return ok31({ action: "interact", query, target, result: { filled: true, value } });
7057
7224
  }
7058
- return fail15(`\u672A\u77E5 action: ${action}`);
7225
+ return fail16(`\u672A\u77E5 action: ${action}`);
7059
7226
  }
7060
7227
  case "export": {
7061
7228
  const result = await ctx.page.evaluate(
@@ -7103,12 +7270,12 @@ var visualTagV2Command = registerCommand({
7103
7270
  })()`
7104
7271
  );
7105
7272
  const parsed = JSON.parse(result);
7106
- if (parsed.err) return fail15(String(parsed.err));
7107
- return ok30({ action: "export", element: parsed });
7273
+ if (parsed.err) return fail16(String(parsed.err));
7274
+ return ok31({ action: "export", element: parsed });
7108
7275
  }
7109
7276
  case "clear": {
7110
7277
  await ctx.page.evaluate(`(function(){var o=document.getElementById('__xb-tag-overlay');if(o)o.remove();window.__xbTagMap=null;window.__xbTagStats=null;return 'ok'})()`);
7111
- return ok30({ action: "clear" });
7278
+ return ok31({ action: "clear" });
7112
7279
  }
7113
7280
  }
7114
7281
  }
@@ -8251,7 +8418,7 @@ async function guardCheck(commandName) {
8251
8418
  }
8252
8419
  }
8253
8420
  function errorResult(message) {
8254
- return { ...fail16(message), duration: 0 };
8421
+ return { ...fail17(message), duration: 0 };
8255
8422
  }
8256
8423
  function tipsToMessages(tips) {
8257
8424
  if (!tips || tips.length === 0) return [];
@@ -8440,7 +8607,7 @@ async function executeCommand(commandName, params, sessionName = "default", extr
8440
8607
  const cache = /* @__PURE__ */ new Map();
8441
8608
  const resolved = await resolveRefParams(session.page, params, command.selectorParams, cache, session.id);
8442
8609
  if (resolved.tips.length > 0) {
8443
- refTips = normalizeTips6(resolved.tips);
8610
+ refTips = normalizeTips7(resolved.tips);
8444
8611
  params = resolved.params;
8445
8612
  }
8446
8613
  }
@@ -8508,8 +8675,8 @@ async function executeCommand(commandName, params, sessionName = "default", extr
8508
8675
  }
8509
8676
  const merged = [
8510
8677
  ...raw.tips || [],
8511
- ...normalizeTips6(smartTips),
8512
- ...snapshotHint ? normalizeTips6([snapshotHint]) : [],
8678
+ ...normalizeTips7(smartTips),
8679
+ ...snapshotHint ? normalizeTips7([snapshotHint]) : [],
8513
8680
  ...refTips
8514
8681
  ];
8515
8682
  const isSuccess = raw.success !== false;
@@ -8524,7 +8691,7 @@ async function executeCommand(commandName, params, sessionName = "default", extr
8524
8691
  timestamp: start
8525
8692
  });
8526
8693
  if (isSuccess) {
8527
- return { ...ok31(raw.data, merged.length > 0 ? merged : raw.tips), duration, ...hookOutputs ? { hookOutputs } : {} };
8694
+ return { ...ok32(raw.data, merged.length > 0 ? merged : raw.tips), duration, ...hookOutputs ? { hookOutputs } : {} };
8528
8695
  }
8529
8696
  const fc = classifyFailure(raw.message);
8530
8697
  return {
@@ -8537,7 +8704,7 @@ async function executeCommand(commandName, params, sessionName = "default", extr
8537
8704
  ...hookOutputs ? { hookOutputs } : {}
8538
8705
  };
8539
8706
  }
8540
- const smartTipNormalized = normalizeTips6(smartTips);
8707
+ const smartTipNormalized = normalizeTips7(smartTips);
8541
8708
  recordArchive(session?.id, sessionName, {
8542
8709
  step: 0,
8543
8710
  command: commandName,
@@ -8547,7 +8714,7 @@ async function executeCommand(commandName, params, sessionName = "default", extr
8547
8714
  duration,
8548
8715
  timestamp: start
8549
8716
  });
8550
- return { ...ok31(raw, smartTipNormalized), duration, ...hookOutputs ? { hookOutputs } : {} };
8717
+ return { ...ok32(raw, smartTipNormalized), duration, ...hookOutputs ? { hookOutputs } : {} };
8551
8718
  } catch (err) {
8552
8719
  const end = Date.now();
8553
8720
  const duration = end - start;
@@ -8592,7 +8759,7 @@ async function executeCommand(commandName, params, sessionName = "default", extr
8592
8759
  duration,
8593
8760
  timestamp: start
8594
8761
  });
8595
- return { ...fail16(errorMessage), duration };
8762
+ return { ...fail17(errorMessage), duration };
8596
8763
  } finally {
8597
8764
  }
8598
8765
  }
@@ -8637,7 +8804,7 @@ async function executeChain(input, options) {
8637
8804
  results.push({
8638
8805
  command: cmdName,
8639
8806
  raw: cmdStr,
8640
- ...fail16(`Plugin "${cmdName}" requires a sub-command`),
8807
+ ...fail17(`Plugin "${cmdName}" requires a sub-command`),
8641
8808
  duration: 0
8642
8809
  });
8643
8810
  if (type === "and") {
@@ -8656,7 +8823,7 @@ async function executeChain(input, options) {
8656
8823
  results.push({
8657
8824
  command: cmdName,
8658
8825
  raw: cmdStr,
8659
- ...fail16(`Unknown command "${subCommand}" for plugin "${cmdName}"`),
8826
+ ...fail17(`Unknown command "${subCommand}" for plugin "${cmdName}"`),
8660
8827
  duration: 0
8661
8828
  });
8662
8829
  if (type === "and") {
@@ -8726,7 +8893,7 @@ async function executeChain(input, options) {
8726
8893
  success: false,
8727
8894
  data: data2,
8728
8895
  message: loginGuard.message,
8729
- tips: normalizeTips6(loginGuard.tips),
8896
+ tips: normalizeTips7(loginGuard.tips),
8730
8897
  duration: duration3
8731
8898
  });
8732
8899
  if (type === "and") {
@@ -8768,7 +8935,7 @@ async function executeChain(input, options) {
8768
8935
  results.push({
8769
8936
  command: `${cmdName} ${subCommand}`,
8770
8937
  raw: cmdStr,
8771
- ...ok31(data),
8938
+ ...ok32(data),
8772
8939
  duration: duration2,
8773
8940
  ...hookOutputs ? { hookOutputs } : {}
8774
8941
  });
@@ -8796,7 +8963,7 @@ async function executeChain(input, options) {
8796
8963
  results.push({
8797
8964
  command: `${cmdName} ${subCommand}`,
8798
8965
  raw: cmdStr,
8799
- ...fail16(errorMessage),
8966
+ ...fail17(errorMessage),
8800
8967
  duration: duration2
8801
8968
  });
8802
8969
  if (type === "and") {