@xbrowser/cli 1.25.2 → 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.
@@ -38,10 +38,10 @@ import {
38
38
  resolveLaunchOpts,
39
39
  saveSessionDiskMeta,
40
40
  setActivePage
41
- } from "./chunk-ZOYM7QMS.js";
41
+ } from "./chunk-3PUOISKE.js";
42
42
  import {
43
43
  createRuleEngine
44
- } from "./chunk-CGNHGAIJ.js";
44
+ } from "./chunk-ME5FO5YV.js";
45
45
  import {
46
46
  queryJS
47
47
  } from "./chunk-A7NEA4PA.js";
@@ -50,7 +50,7 @@ import {
50
50
  sleep,
51
51
  wheelDelta
52
52
  } from "./chunk-R3F4K2SB.js";
53
- import "./chunk-MYH6FIBZ.js";
53
+ import "./chunk-SEEWE5SJ.js";
54
54
  import {
55
55
  errMsg
56
56
  } from "./chunk-GDKLH7ZY.js";
@@ -102,12 +102,12 @@ function classifyFailure(message) {
102
102
 
103
103
  // src/executor.ts
104
104
  import {
105
- ok as ok31,
106
- fail as fail16,
105
+ ok as ok32,
106
+ fail as fail17,
107
107
  isCommandResult,
108
108
  CompositeStorage as CompositeStorage2,
109
109
  TipCollector as TipCollector2,
110
- normalizeTips as normalizeTips6,
110
+ normalizeTips as normalizeTips7,
111
111
  configureArchiveStore,
112
112
  appendCommandToArchive,
113
113
  checkGuard,
@@ -535,10 +535,14 @@ var clickCommand = registerCommand({
535
535
  targetIdsBefore = /* @__PURE__ */ new Set();
536
536
  }
537
537
  const pagePromise = new Promise((resolve) => {
538
+ const waitMs = (() => {
539
+ const v = parseInt(process.env.XBROWSER_NEW_TAB_WAIT ?? "250", 10);
540
+ return Number.isFinite(v) && v > 0 ? v : 250;
541
+ })();
538
542
  const timer = setTimeout(() => {
539
543
  ctx.browserContext.off("page", handler);
540
544
  resolve(void 0);
541
- }, 3e3);
545
+ }, waitMs);
542
546
  const handler = (page2) => {
543
547
  if (targetIdsBefore.has(targetIdOf(page2))) return;
544
548
  try {
@@ -5875,26 +5879,193 @@ var waitForCommand = registerCommand({
5875
5879
  }
5876
5880
  });
5877
5881
 
5878
- // src/commands/tab.ts
5882
+ // src/commands/task.ts
5879
5883
  import { z as z27 } from "zod";
5880
- import { ok as ok26, fail as fail12 } from "@dyyz1993/xcli-core";
5881
- var TabParams = z27.object({
5882
- subcommand: z27.enum(["list", "new", "close", "switch"]),
5883
- url: z27.string().optional(),
5884
- index: z27.number().int().min(0).optional()
5884
+ import { ok as ok26, fail as fail12, normalizeTips as normalizeTips5 } from "@dyyz1993/xcli-core";
5885
+ 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
5886
+
5887
+ \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
5888
+ {"action":"click","ref":"@eN","thought":"\u4E3A\u4EC0\u4E48"}
5889
+ {"action":"fill","ref":"@eN","value":"\u6587\u672C","thought":"\u4E3A\u4EC0\u4E48"}
5890
+ {"action":"select","ref":"@eN","value":"\u9009\u9879\u503C","thought":"\u4E3A\u4EC0\u4E48"}
5891
+ {"action":"press","value":"Enter","thought":"\u4E3A\u4EC0\u4E48"}
5892
+ {"action":"scroll","value":"down \u6216 up","thought":"\u4E3A\u4EC0\u4E48"}
5893
+ {"action":"done","value":"\u5B8C\u6210\u6458\u8981","thought":"\u4E3A\u4EC0\u4E48"}
5894
+ {"action":"blocked","value":"\u5361\u4F4F\u539F\u56E0","thought":"\u4E3A\u4EC0\u4E48"}
5895
+
5896
+ \u89C4\u5219\uFF1A
5897
+ 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
5898
+ 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
5899
+ 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`;
5900
+ function extractDecision(raw) {
5901
+ let s = raw.trim().replace(/^```(?:json)?\s*/i, "").replace(/\s*```$/, "");
5902
+ const start = s.indexOf("{");
5903
+ if (start < 0) return null;
5904
+ let depth = 0;
5905
+ for (let i = start; i < s.length; i++) {
5906
+ if (s[i] === "{") depth++;
5907
+ else if (s[i] === "}") {
5908
+ depth--;
5909
+ if (depth === 0) {
5910
+ try {
5911
+ return JSON.parse(s.slice(start, i + 1));
5912
+ } catch {
5913
+ return null;
5914
+ }
5915
+ }
5916
+ }
5917
+ }
5918
+ return null;
5919
+ }
5920
+ var taskCommand = registerCommand({
5921
+ name: "task",
5922
+ description: "Autonomous goal loop: observe refs \u2192 LLM decides \u2192 act, until done/blocked (budget-capped)",
5923
+ scope: "page",
5924
+ parameters: z27.object({
5925
+ goal: z27.string().describe("Natural-language goal"),
5926
+ maxSteps: z27.number().int().positive().max(50).optional().default(15).describe("Hard action budget"),
5927
+ timeout: z27.number().optional().default(18e4).describe("Wall clock budget in ms"),
5928
+ limit: z27.number().int().positive().max(300).optional().default(80).describe("Max targets per observe")
5929
+ }),
5930
+ result: z27.object({
5931
+ status: z27.enum(["done", "blocked", "max_steps", "error"]),
5932
+ summary: z27.string().optional(),
5933
+ steps: z27.array(z27.record(z27.unknown())),
5934
+ finalUrl: z27.string().optional(),
5935
+ usage: z27.object({ llmCalls: z27.number(), steps: z27.number() }).passthrough().optional()
5936
+ }).passthrough(),
5937
+ handler: async (p, ctx) => {
5938
+ const creds = loadVLMCredentials2();
5939
+ if (!creds) {
5940
+ return fail12("task \u9700\u8981\u51B3\u7B56\u6A21\u578B\u51ED\u8BC1\uFF1A\u8BBE\u7F6E XBROWSER_VLM_CONFIG \u6216 ~/.zcode/v2/config.json");
5941
+ }
5942
+ const model = process.env.XBROWSER_TASK_MODEL || creds.model;
5943
+ const started = Date.now();
5944
+ const steps = [];
5945
+ const history = [];
5946
+ let llmCalls = 0;
5947
+ let status = "max_steps";
5948
+ let summary = "";
5949
+ let lastError = "";
5950
+ for (let step = 1; step <= p.maxSteps; step++) {
5951
+ if (Date.now() - started > p.timeout) {
5952
+ status = "blocked";
5953
+ summary = `timeout after ${step - 1} steps`;
5954
+ break;
5955
+ }
5956
+ const obs = await observePage(ctx.page, ctx.sessionId, { limit: p.limit, includeHidden: false });
5957
+ const compact = obs.compact ?? obs.targets.map((t, i) => `@e${i + 1} [${t.tag ?? ""}] ${t.name ?? ""}`).join("\n");
5958
+ const screenHash = obs.screenHash;
5959
+ const userPayload = [
5960
+ `\u76EE\u6807\uFF1A${p.goal}`,
5961
+ `\u5F53\u524D\u9875\u9762\uFF08URL: ${obs.url ?? ""}\uFF09\uFF1A`,
5962
+ compact,
5963
+ history.length ? `
5964
+ \u5DF2\u6267\u884C\uFF08\u52FF\u91CD\u590D\u5931\u8D25\u52A8\u4F5C\uFF09\uFF1A
5965
+ ${history.slice(-6).join("\n")}` : ""
5966
+ ].filter(Boolean).join("\n");
5967
+ let raw = "";
5968
+ try {
5969
+ raw = await vlmAsk({ ...creds, model }, [{ type: "text", text: `${DECISION_SYSTEM}
5970
+
5971
+ ---
5972
+
5973
+ ${userPayload}` }], 900);
5974
+ llmCalls++;
5975
+ } catch (e) {
5976
+ lastError = e instanceof Error ? e.message : String(e);
5977
+ status = "error";
5978
+ summary = `LLM call failed: ${lastError}`;
5979
+ break;
5980
+ }
5981
+ const decision = extractDecision(raw);
5982
+ if (!decision || typeof decision.action !== "string") {
5983
+ status = "blocked";
5984
+ summary = `LLM returned unparsable decision: ${raw.slice(0, 120)}`;
5985
+ break;
5986
+ }
5987
+ const action = decision.action;
5988
+ const ref = typeof decision.ref === "string" ? decision.ref : void 0;
5989
+ const value = typeof decision.value === "string" ? decision.value : void 0;
5990
+ const thought = typeof decision.thought === "string" ? decision.thought : void 0;
5991
+ if (action === "done") {
5992
+ status = "done";
5993
+ summary = value || thought || "task done";
5994
+ steps.push({ step, thought, action: "done", ok: true, screenHash });
5995
+ break;
5996
+ }
5997
+ if (action === "blocked") {
5998
+ status = "blocked";
5999
+ summary = value || thought || "LLM judged blocked";
6000
+ steps.push({ step, thought, action: "blocked", ok: true, screenHash });
6001
+ break;
6002
+ }
6003
+ const legalRefs = new Set(obs.targets.map((t, i) => t.ref ?? `e${i + 1}`));
6004
+ const normalizedRef = ref ? legalRefs.has(ref.replace("@", "")) || legalRefs.has(ref) ? ref : void 0 : void 0;
6005
+ if (ref && !normalizedRef && action !== "scroll" && action !== "press") {
6006
+ history.push(`step${step}: ${action} ${ref} REJECTED (ref not in current list)`);
6007
+ steps.push({ step, thought, action, ref, ok: false, error: "ref not in current list", screenHash });
6008
+ continue;
6009
+ }
6010
+ const res = await actOnPage(ctx.page, ctx.sessionId, {
6011
+ action,
6012
+ ref: normalizedRef,
6013
+ value,
6014
+ selector: void 0,
6015
+ force: false,
6016
+ timeout: 1e4
6017
+ });
6018
+ const record = {
6019
+ step,
6020
+ thought,
6021
+ action,
6022
+ ref: normalizedRef,
6023
+ value,
6024
+ ok: res.success === true,
6025
+ stale: res.stale,
6026
+ error: res.success ? void 0 : res.message || res.reason,
6027
+ screenHash
6028
+ };
6029
+ steps.push(record);
6030
+ history.push(`step${step}: ${action} ${normalizedRef ?? ""} ${value ?? ""} -> ${res.success ? "ok" : `failed(${res.reason || res.message})`}`);
6031
+ const sig = (s) => `${s.action}|${s.ref ?? ""}|${s.value ?? ""}`;
6032
+ const last3 = steps.slice(-3);
6033
+ if (last3.length === 3 && new Set(last3.map(sig)).size === 1) {
6034
+ status = "blocked";
6035
+ summary = "dead loop: identical action repeated 3 times";
6036
+ break;
6037
+ }
6038
+ }
6039
+ if (status === "max_steps") summary = summary || `hit maxSteps=${p.maxSteps}`;
6040
+ const finalUrl = ctx.page ? ctx.page.url() : void 0;
6041
+ const data = { status, summary, steps, finalUrl, usage: { llmCalls, steps: steps.length } };
6042
+ if (status === "error") return fail12(summary || lastError, normalizeTips5([`completed steps: ${steps.length}`]));
6043
+ return ok26(data, normalizeTips5([
6044
+ status === "done" ? `\u2705 task done (${steps.length} steps, ${llmCalls} LLM calls)` : `\u26A0\uFE0F task ${status}: ${summary.slice(0, 80)}`
6045
+ ]));
6046
+ }
6047
+ });
6048
+
6049
+ // src/commands/tab.ts
6050
+ import { z as z28 } from "zod";
6051
+ import { ok as ok27, fail as fail13 } from "@dyyz1993/xcli-core";
6052
+ var TabParams = z28.object({
6053
+ subcommand: z28.enum(["list", "new", "close", "switch"]),
6054
+ url: z28.string().optional(),
6055
+ index: z28.number().int().min(0).optional()
5885
6056
  });
5886
6057
  var tabCommand = registerCommand({
5887
6058
  name: "tab",
5888
6059
  description: "Manage browser tabs: list, new, close, switch",
5889
6060
  scope: "page",
5890
6061
  parameters: TabParams,
5891
- result: z27.object({
5892
- success: z27.boolean(),
5893
- data: z27.unknown()
6062
+ result: z28.object({
6063
+ success: z28.boolean(),
6064
+ data: z28.unknown()
5894
6065
  }),
5895
6066
  handler: async (p, ctx) => {
5896
6067
  if (!ctx.browserContext) {
5897
- return fail12("No browser context available. Use --cdp to connect to a browser first.");
6068
+ return fail13("No browser context available. Use --cdp to connect to a browser first.");
5898
6069
  }
5899
6070
  const pages = ctx.browserContext.pages();
5900
6071
  switch (p.subcommand) {
@@ -5907,7 +6078,7 @@ var tabCommand = registerCommand({
5907
6078
  case "switch":
5908
6079
  return handleSwitch(p, pages, ctx);
5909
6080
  default:
5910
- return fail12(`Unknown subcommand: ${p.subcommand}`);
6081
+ return fail13(`Unknown subcommand: ${p.subcommand}`);
5911
6082
  }
5912
6083
  }
5913
6084
  });
@@ -5922,7 +6093,7 @@ async function handleList(pages, ctx) {
5922
6093
  if (isActive) activeIndex = i;
5923
6094
  tabs.push({ index: i, url, title, active: isActive });
5924
6095
  }
5925
- return ok26({ tabs, total: tabs.length, activeIndex });
6096
+ return ok27({ tabs, total: tabs.length, activeIndex });
5926
6097
  }
5927
6098
  async function handleNew(p, _pages, ctx) {
5928
6099
  const newPage = await ctx.browserContext.newPage();
@@ -5950,7 +6121,7 @@ async function handleNew(p, _pages, ctx) {
5950
6121
  const title = await newPage.title().catch(() => "");
5951
6122
  const allPages = ctx.browserContext.pages();
5952
6123
  const newIndex = allPages.indexOf(newPage);
5953
- return ok26({
6124
+ return ok27({
5954
6125
  index: newIndex >= 0 ? newIndex : allPages.length - 1,
5955
6126
  url: newPage.url(),
5956
6127
  title,
@@ -5961,11 +6132,11 @@ async function handleNew(p, _pages, ctx) {
5961
6132
  async function handleClose(p, ctx) {
5962
6133
  const currentPages = ctx.browserContext.pages();
5963
6134
  if (currentPages.length <= 1) {
5964
- return fail12("Cannot close the last remaining tab");
6135
+ return fail13("Cannot close the last remaining tab");
5965
6136
  }
5966
6137
  const closeIndex = p.index ?? currentPages.findIndex((pg) => pg === ctx.page);
5967
6138
  if (closeIndex < 0 || closeIndex >= currentPages.length) {
5968
- return fail12(`Invalid tab index: ${closeIndex}. Valid range: 0-${currentPages.length - 1}`);
6139
+ return fail13(`Invalid tab index: ${closeIndex}. Valid range: 0-${currentPages.length - 1}`);
5969
6140
  }
5970
6141
  const pageToClose = currentPages[closeIndex];
5971
6142
  const isActivePage = pageToClose === ctx.page;
@@ -5980,7 +6151,7 @@ async function handleClose(p, ctx) {
5980
6151
  }
5981
6152
  ctx.page = newActivePage;
5982
6153
  }
5983
- return ok26({
6154
+ return ok27({
5984
6155
  closedIndex: closeIndex,
5985
6156
  total: remainingPages.length,
5986
6157
  activeIndex: isActivePage ? closeIndex < remainingPages.length ? closeIndex : remainingPages.length - 1 : remainingPages.findIndex((pg) => pg === ctx.page)
@@ -5988,10 +6159,10 @@ async function handleClose(p, ctx) {
5988
6159
  }
5989
6160
  async function handleSwitch(p, pages, ctx) {
5990
6161
  if (p.index === void 0) {
5991
- return fail12("Parameter --index is required for switch subcommand");
6162
+ return fail13("Parameter --index is required for switch subcommand");
5992
6163
  }
5993
6164
  if (p.index < 0 || p.index >= pages.length) {
5994
- return fail12(`Invalid tab index: ${p.index}. Valid range: 0-${pages.length - 1}`);
6165
+ return fail13(`Invalid tab index: ${p.index}. Valid range: 0-${pages.length - 1}`);
5995
6166
  }
5996
6167
  const targetPage = pages[p.index];
5997
6168
  await targetPage.bringToFront().catch(() => {
@@ -6013,7 +6184,7 @@ async function handleSwitch(p, pages, ctx) {
6013
6184
  }
6014
6185
  ctx.page = targetPage;
6015
6186
  const title = await targetPage.title().catch(() => "");
6016
- return ok26({
6187
+ return ok27({
6017
6188
  index: p.index,
6018
6189
  url: targetPage.url(),
6019
6190
  title,
@@ -6022,8 +6193,8 @@ async function handleSwitch(p, pages, ctx) {
6022
6193
  }
6023
6194
 
6024
6195
  // src/commands/addinitscript.ts
6025
- import { z as z28 } from "zod";
6026
- import { ok as ok27 } from "@dyyz1993/xcli-core";
6196
+ import { z as z29 } from "zod";
6197
+ import { ok as ok28 } from "@dyyz1993/xcli-core";
6027
6198
  import { readFileSync as readFileSync4 } from "fs";
6028
6199
 
6029
6200
  // src/chain-parser.ts
@@ -6164,14 +6335,14 @@ registerCommandDefinition("tab", ["subcommand"]);
6164
6335
  registerCommandDefinition("mouse", ["action", "x", "y"]);
6165
6336
 
6166
6337
  // src/commands/addinitscript.ts
6167
- var InitScriptParams = z28.object({
6168
- script: z28.string().optional(),
6169
- file: z28.string().optional(),
6170
- stdin: z28.boolean().optional(),
6171
- name: z28.string().optional(),
6172
- list: z28.boolean().optional(),
6173
- remove: z28.union([z28.string(), z28.boolean()]).optional(),
6174
- base64: z28.string().optional()
6338
+ var InitScriptParams = z29.object({
6339
+ script: z29.string().optional(),
6340
+ file: z29.string().optional(),
6341
+ stdin: z29.boolean().optional(),
6342
+ name: z29.string().optional(),
6343
+ list: z29.boolean().optional(),
6344
+ remove: z29.union([z29.string(), z29.boolean()]).optional(),
6345
+ base64: z29.string().optional()
6175
6346
  });
6176
6347
  var registeredScripts = /* @__PURE__ */ new Map();
6177
6348
  function resolveScriptContent(params) {
@@ -6205,14 +6376,14 @@ var addInitScriptCommand = registerCommand({
6205
6376
  description: "Add an initialization script that runs on every page load",
6206
6377
  scope: "page",
6207
6378
  parameters: InitScriptParams,
6208
- result: z28.object({
6209
- scripts: z28.array(z28.object({ name: z28.string(), size: z28.number(), preview: z28.string() })).optional(),
6210
- removed: z28.string().optional(),
6211
- existed: z28.boolean().optional(),
6212
- error: z28.string().optional(),
6213
- registered: z28.string().optional(),
6214
- hint: z28.string().optional(),
6215
- executedImmediately: z28.boolean().optional()
6379
+ result: z29.object({
6380
+ scripts: z29.array(z29.object({ name: z29.string(), size: z29.number(), preview: z29.string() })).optional(),
6381
+ removed: z29.string().optional(),
6382
+ existed: z29.boolean().optional(),
6383
+ error: z29.string().optional(),
6384
+ registered: z29.string().optional(),
6385
+ hint: z29.string().optional(),
6386
+ executedImmediately: z29.boolean().optional()
6216
6387
  }).passthrough(),
6217
6388
  handler: async (params, ctx) => {
6218
6389
  if (params.list) {
@@ -6221,20 +6392,20 @@ var addInitScriptCommand = registerCommand({
6221
6392
  size: content2.length,
6222
6393
  preview: content2.slice(0, 80)
6223
6394
  }));
6224
- return ok27({ scripts });
6395
+ return ok28({ scripts });
6225
6396
  }
6226
6397
  if (params.remove && typeof params.remove === "string") {
6227
6398
  const existed = registeredScripts.delete(params.remove);
6228
- return ok27({ removed: params.remove, existed });
6399
+ return ok28({ removed: params.remove, existed });
6229
6400
  }
6230
6401
  const removeTarget = (typeof params.remove === "string" ? params.remove : null) || (params.name && !resolveScriptContent(params) ? params.name : null);
6231
6402
  if (removeTarget && !resolveScriptContent(params)) {
6232
6403
  const existed = registeredScripts.delete(removeTarget);
6233
- return ok27({ removed: removeTarget, existed });
6404
+ return ok28({ removed: removeTarget, existed });
6234
6405
  }
6235
6406
  let content = params.stdin ? await readStdin() : resolveScriptContent(params);
6236
6407
  if (!content) {
6237
- return ok27({ error: "No script content provided. Use --script, --file, --stdin, or --base64" });
6408
+ return ok28({ error: "No script content provided. Use --script, --file, --stdin, or --base64" });
6238
6409
  }
6239
6410
  const scriptName = params.name ?? `script-${Date.now()}`;
6240
6411
  registeredScripts.set(scriptName, content);
@@ -6242,45 +6413,45 @@ var addInitScriptCommand = registerCommand({
6242
6413
  try {
6243
6414
  await ctx.page.evaluate(content);
6244
6415
  } catch {
6245
- return ok27({
6416
+ return ok28({
6246
6417
  registered: scriptName,
6247
6418
  hint: "Script registered for future page loads; immediate execution skipped (page may not be ready)"
6248
6419
  });
6249
6420
  }
6250
- return ok27({ registered: scriptName, executedImmediately: true });
6421
+ return ok28({ registered: scriptName, executedImmediately: true });
6251
6422
  }
6252
6423
  });
6253
6424
  registerCommandDefinition("addinitscript", ["script"]);
6254
6425
 
6255
6426
  // src/commands/find.ts
6256
- import { z as z29 } from "zod";
6257
- import { ok as ok28, fail as fail13, normalizeTips as normalizeTips5 } from "@dyyz1993/xcli-core";
6258
- var actionSchema2 = z29.enum(["click", "fill", "type", "select", "hover", "check"]);
6427
+ import { z as z30 } from "zod";
6428
+ import { ok as ok29, fail as fail14, normalizeTips as normalizeTips6 } from "@dyyz1993/xcli-core";
6429
+ var actionSchema2 = z30.enum(["click", "fill", "type", "select", "hover", "check"]);
6259
6430
  var findCommand = registerCommand({
6260
6431
  name: "find",
6261
6432
  description: "Find elements by semantic strategy (text/role/label/placeholder/testid) and optionally perform an action",
6262
6433
  scope: "page",
6263
- parameters: z29.object({
6264
- strategy: z29.enum(["text", "role", "label", "placeholder", "testid", "alt", "title", "first", "last", "nth"]),
6265
- value: z29.string(),
6266
- name: z29.string().optional(),
6267
- exact: z29.boolean().optional().default(false),
6268
- operation: z29.string().optional().describe('Trailing operation syntax, e.g. click, fill "text", type "text"'),
6434
+ parameters: z30.object({
6435
+ strategy: z30.enum(["text", "role", "label", "placeholder", "testid", "alt", "title", "first", "last", "nth"]),
6436
+ value: z30.string(),
6437
+ name: z30.string().optional(),
6438
+ exact: z30.boolean().optional().default(false),
6439
+ operation: z30.string().optional().describe('Trailing operation syntax, e.g. click, fill "text", type "text"'),
6269
6440
  action: actionSchema2.optional().describe("Action to perform when not using trailing operation syntax"),
6270
- actionValue: z29.string().optional().describe("Value for fill/type/select when using action"),
6271
- index: z29.number().int().optional().describe("Index for nth strategy"),
6272
- click: z29.boolean().optional().default(false),
6273
- fill: z29.string().optional(),
6274
- type: z29.string().optional(),
6275
- select: z29.string().optional(),
6276
- hover: z29.boolean().optional().default(false),
6277
- check: z29.boolean().optional().default(false),
6278
- timeout: z29.number().optional().default(1e4)
6441
+ actionValue: z30.string().optional().describe("Value for fill/type/select when using action"),
6442
+ index: z30.number().int().optional().describe("Index for nth strategy"),
6443
+ click: z30.boolean().optional().default(false),
6444
+ fill: z30.string().optional(),
6445
+ type: z30.string().optional(),
6446
+ select: z30.string().optional(),
6447
+ hover: z30.boolean().optional().default(false),
6448
+ check: z30.boolean().optional().default(false),
6449
+ timeout: z30.number().optional().default(1e4)
6279
6450
  }),
6280
- result: z29.object({
6281
- matched: z29.number(),
6282
- selector: z29.string(),
6283
- action: z29.string().optional()
6451
+ result: z30.object({
6452
+ matched: z30.number(),
6453
+ selector: z30.string(),
6454
+ action: z30.string().optional()
6284
6455
  }),
6285
6456
  handler: async (p, ctx) => {
6286
6457
  const page = ctx.page;
@@ -6295,7 +6466,7 @@ var findCommand = registerCommand({
6295
6466
  });
6296
6467
  const count = await locator.count();
6297
6468
  if (count === 0) {
6298
- return fail13(`No element found with ${p.strategy}="${p.value}"`);
6469
+ return fail14(`No element found with ${p.strategy}="${p.value}"`);
6299
6470
  }
6300
6471
  const tips = [];
6301
6472
  const target = selectTarget(locator, p.strategy);
@@ -6307,15 +6478,15 @@ var findCommand = registerCommand({
6307
6478
  await target.click({ timeout: p.timeout, force: true });
6308
6479
  return okWithTips({ matched: count, selector, action: "click" }, tips);
6309
6480
  } else if (actionName === "fill") {
6310
- if (actionValue === void 0) return fail13("find fill requires a value");
6481
+ if (actionValue === void 0) return fail14("find fill requires a value");
6311
6482
  await target.fill(actionValue, { timeout: p.timeout, force: true });
6312
6483
  return okWithTips({ matched: count, selector, action: `fill("${actionValue}")` }, tips);
6313
6484
  } else if (actionName === "type") {
6314
- if (actionValue === void 0) return fail13("find type requires a value");
6485
+ if (actionValue === void 0) return fail14("find type requires a value");
6315
6486
  await target.type(actionValue, { delay: 10, timeout: p.timeout });
6316
6487
  return okWithTips({ matched: count, selector, action: `type("${actionValue}")` }, tips);
6317
6488
  } else if (actionName === "select") {
6318
- if (actionValue === void 0) return fail13("find select requires a value");
6489
+ if (actionValue === void 0) return fail14("find select requires a value");
6319
6490
  await target.selectOption(actionValue);
6320
6491
  return okWithTips({ matched: count, selector, action: `select("${actionValue}")` }, tips);
6321
6492
  } else if (actionName === "hover") {
@@ -6329,8 +6500,8 @@ var findCommand = registerCommand({
6329
6500
  }
6330
6501
  });
6331
6502
  function okWithTips(data, tips) {
6332
- const result = ok28(data);
6333
- if (tips.length > 0) result.tips = normalizeTips5(tips);
6503
+ const result = ok29(data);
6504
+ if (tips.length > 0) result.tips = normalizeTips6(tips);
6334
6505
  return result;
6335
6506
  }
6336
6507
  function parseOperation(operation) {
@@ -6428,8 +6599,8 @@ function describeSelector(strategy, value, name) {
6428
6599
  }
6429
6600
 
6430
6601
  // src/commands/visual-tag.ts
6431
- import { z as z30 } from "zod";
6432
- import { ok as ok29, fail as fail14 } from "@dyyz1993/xcli-core";
6602
+ import { z as z31 } from "zod";
6603
+ import { ok as ok30, fail as fail15 } from "@dyyz1993/xcli-core";
6433
6604
  var SAFE_SET = "ahjkmnprtw3479".split("");
6434
6605
  var TAG_SCRIPT = `
6435
6606
  (function() {
@@ -6520,49 +6691,49 @@ var visualTagCommand = registerCommand({
6520
6691
  name: "visual-tag",
6521
6692
  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",
6522
6693
  scope: "page",
6523
- parameters: z30.object({
6524
- action: z30.enum(["tag", "lookup", "clear", "list"]),
6525
- id: z30.string().optional().describe("lookup \u65F6\u6307\u5B9A\u8981\u67E5\u7684 ID")
6694
+ parameters: z31.object({
6695
+ action: z31.enum(["tag", "lookup", "clear", "list"]),
6696
+ id: z31.string().optional().describe("lookup \u65F6\u6307\u5B9A\u8981\u67E5\u7684 ID")
6526
6697
  }),
6527
- result: z30.object({
6528
- action: z30.string(),
6529
- tagged: z30.number().optional(),
6530
- id: z30.string().optional(),
6531
- element: z30.record(z30.unknown()).optional()
6698
+ result: z31.object({
6699
+ action: z31.string(),
6700
+ tagged: z31.number().optional(),
6701
+ id: z31.string().optional(),
6702
+ element: z31.record(z31.unknown()).optional()
6532
6703
  }),
6533
6704
  handler: async (p, ctx) => {
6534
6705
  switch (p.action) {
6535
6706
  case "tag": {
6536
6707
  const result = await ctx.page.evaluate(TAG_SCRIPT);
6537
6708
  const parsed = JSON.parse(result);
6538
- return ok29({ action: "tag", tagged: parsed.tagged });
6709
+ return ok30({ action: "tag", tagged: parsed.tagged });
6539
6710
  }
6540
6711
  case "lookup": {
6541
- if (!p.id) return fail14("lookup \u9700\u8981 --id \u53C2\u6570");
6712
+ if (!p.id) return fail15("lookup \u9700\u8981 --id \u53C2\u6570");
6542
6713
  const result = await ctx.page.evaluate(
6543
6714
  `(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'}); })()`
6544
6715
  );
6545
6716
  const parsed = JSON.parse(result);
6546
- if (parsed.err) return fail14(`ID ${p.id}: ${parsed.err}`);
6547
- return ok29({ action: "lookup", id: p.id, element: parsed });
6717
+ if (parsed.err) return fail15(`ID ${p.id}: ${parsed.err}`);
6718
+ return ok30({ action: "lookup", id: p.id, element: parsed });
6548
6719
  }
6549
6720
  case "list": {
6550
6721
  const result = await ctx.page.evaluate(
6551
6722
  `(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); })()`
6552
6723
  );
6553
- return ok29({ action: "list", element: JSON.parse(result) });
6724
+ return ok30({ action: "list", element: JSON.parse(result) });
6554
6725
  }
6555
6726
  case "clear": {
6556
6727
  await ctx.page.evaluate(`(function(){var o=document.getElementById('__xb-tag-overlay');if(o)o.remove();window.__xbTagMap=null;return 'cleared'})()`);
6557
- return ok29({ action: "clear" });
6728
+ return ok30({ action: "clear" });
6558
6729
  }
6559
6730
  }
6560
6731
  }
6561
6732
  });
6562
6733
 
6563
6734
  // src/commands/visual-tag-v2.ts
6564
- import { z as z31 } from "zod";
6565
- import { ok as ok30, fail as fail15 } from "@dyyz1993/xcli-core";
6735
+ import { z as z32 } from "zod";
6736
+ import { ok as ok31, fail as fail16 } from "@dyyz1993/xcli-core";
6566
6737
  var SAFE_SET2 = "ahjkmnprtw3479".split("");
6567
6738
  var TAG_V2_SCRIPT = `
6568
6739
  (function() {
@@ -6909,45 +7080,45 @@ var visualTagV2Command = registerCommand({
6909
7080
  name: "visual-tag-v2",
6910
7081
  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",
6911
7082
  scope: "page",
6912
- parameters: z31.object({
6913
- action: z31.enum(["tag", "lookup", "clear", "stats", "by-type", "find", "export", "interact"]),
6914
- id: z31.string().optional().describe("lookup \u65F6\u6307\u5B9A\u8981\u67E5\u7684 ID"),
6915
- query: z31.string().optional().describe('find \u65F6\u6307\u5B9A\u641C\u7D22\u8BCD\uFF08\u5982 "\u627E\u6709AI\u7F16\u7A0B\u6807\u7B7E\u7684\u5361\u7247"\uFF09'),
6916
- type: z31.string().optional().describe("by-type \u65F6\u8FC7\u6EE4\u7C7B\u578B\uFF1Aclick/input/img/list/count/text"),
6917
- "interact-action": z31.enum(["click", "fill", "read"]).optional().describe("interact \u52A8\u4F5C\u7C7B\u578B"),
6918
- value: z31.string().optional().describe("fill \u65F6\u7684\u586B\u5145\u503C")
7083
+ parameters: z32.object({
7084
+ action: z32.enum(["tag", "lookup", "clear", "stats", "by-type", "find", "export", "interact"]),
7085
+ id: z32.string().optional().describe("lookup \u65F6\u6307\u5B9A\u8981\u67E5\u7684 ID"),
7086
+ query: z32.string().optional().describe('find \u65F6\u6307\u5B9A\u641C\u7D22\u8BCD\uFF08\u5982 "\u627E\u6709AI\u7F16\u7A0B\u6807\u7B7E\u7684\u5361\u7247"\uFF09'),
7087
+ type: z32.string().optional().describe("by-type \u65F6\u8FC7\u6EE4\u7C7B\u578B\uFF1Aclick/input/img/list/count/text"),
7088
+ "interact-action": z32.enum(["click", "fill", "read"]).optional().describe("interact \u52A8\u4F5C\u7C7B\u578B"),
7089
+ value: z32.string().optional().describe("fill \u65F6\u7684\u586B\u5145\u503C")
6919
7090
  }),
6920
- result: z31.object({
6921
- action: z31.string(),
6922
- total: z31.number().optional(),
6923
- byType: z31.record(z31.number()).optional(),
6924
- element: z31.record(z31.unknown()).optional()
7091
+ result: z32.object({
7092
+ action: z32.string(),
7093
+ total: z32.number().optional(),
7094
+ byType: z32.record(z32.number()).optional(),
7095
+ element: z32.record(z32.unknown()).optional()
6925
7096
  }),
6926
7097
  handler: async (p, ctx) => {
6927
7098
  switch (p.action) {
6928
7099
  case "tag": {
6929
7100
  const result = await ctx.page.evaluate(TAG_V2_SCRIPT);
6930
7101
  const parsed = JSON.parse(result);
6931
- return ok30({ action: "tag", total: parsed.total, byType: parsed.byType });
7102
+ return ok31({ action: "tag", total: parsed.total, byType: parsed.byType });
6932
7103
  }
6933
7104
  case "lookup": {
6934
- if (!p.id) return fail15("lookup \u9700\u8981 --id");
7105
+ if (!p.id) return fail16("lookup \u9700\u8981 --id");
6935
7106
  const result = await ctx.page.evaluate(
6936
7107
  `(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'})})()`
6937
7108
  );
6938
7109
  const parsed = JSON.parse(result);
6939
- if (parsed.err) return fail15(`ID ${p.id}: ${parsed.err}`);
6940
- return ok30({ action: "lookup", id: p.id, element: parsed });
7110
+ if (parsed.err) return fail16(`ID ${p.id}: ${parsed.err}`);
7111
+ return ok31({ action: "lookup", id: p.id, element: parsed });
6941
7112
  }
6942
7113
  case "by-type": {
6943
7114
  const result = await ctx.page.evaluate(
6944
7115
  `(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)})()`
6945
7116
  );
6946
- return ok30({ action: "by-type", element: JSON.parse(result) });
7117
+ return ok31({ action: "by-type", element: JSON.parse(result) });
6947
7118
  }
6948
7119
  case "find": {
6949
7120
  const query = p.query;
6950
- if (!query) return fail15('find \u9700\u8981 --query \u53C2\u6570\uFF08\u5982 "\u627E\u6709AI\u7F16\u7A0B\u6807\u7B7E\u7684\u5361\u7247"\uFF09');
7121
+ if (!query) return fail16('find \u9700\u8981 --query \u53C2\u6570\uFF08\u5982 "\u627E\u6709AI\u7F16\u7A0B\u6807\u7B7E\u7684\u5361\u7247"\uFF09');
6951
7122
  const result = await ctx.page.evaluate(
6952
7123
  `(function(){
6953
7124
  var map = window.__xbTagSerializable;
@@ -6989,21 +7160,21 @@ var visualTagV2Command = registerCommand({
6989
7160
  return JSON.stringify({total:results.length, results:results.slice(0,20)});
6990
7161
  })()`
6991
7162
  );
6992
- return ok30({ action: "find", query, element: JSON.parse(result) });
7163
+ return ok31({ action: "find", query, element: JSON.parse(result) });
6993
7164
  }
6994
7165
  case "stats": {
6995
7166
  const result = await ctx.page.evaluate(
6996
7167
  `(function(){return JSON.stringify(window.__xbTagStats||{})})()`
6997
7168
  );
6998
- return ok30({ action: "stats", element: JSON.parse(result) });
7169
+ return ok31({ action: "stats", element: JSON.parse(result) });
6999
7170
  }
7000
7171
  case "interact": {
7001
7172
  const query = p.query;
7002
7173
  const pAny = p;
7003
7174
  const action = pAny["interact-action"] || pAny.interactAction || pAny.interact_action;
7004
7175
  const value = pAny.value;
7005
- if (!query) return fail15("interact \u9700\u8981 --query \u53C2\u6570");
7006
- if (!action) return fail15("interact \u9700\u8981 --interact-action \u53C2\u6570\uFF08click/fill/read\uFF09");
7176
+ if (!query) return fail16("interact \u9700\u8981 --query \u53C2\u6570");
7177
+ if (!action) return fail16("interact \u9700\u8981 --interact-action \u53C2\u6570\uFF08click/fill/read\uFF09");
7007
7178
  const findResult = await ctx.page.evaluate(
7008
7179
  `(function(){
7009
7180
  var map = window.__xbTagSerializable;
@@ -7033,11 +7204,11 @@ var visualTagV2Command = registerCommand({
7033
7204
  })()`
7034
7205
  );
7035
7206
  const parsed = JSON.parse(findResult);
7036
- if (parsed.err) return fail15(parsed.err);
7037
- if (!parsed.total || !parsed.results?.length) return fail15(`\u672A\u627E\u5230\u5339\u914D "${query}" \u7684\u5143\u7D20`);
7207
+ if (parsed.err) return fail16(parsed.err);
7208
+ if (!parsed.total || !parsed.results?.length) return fail16(`\u672A\u627E\u5230\u5339\u914D "${query}" \u7684\u5143\u7D20`);
7038
7209
  const target = parsed.results[0];
7039
7210
  if (action === "read") {
7040
- return ok30({ action: "interact", query, target, result: { read: target.text || target.label } });
7211
+ return ok31({ action: "interact", query, target, result: { read: target.text || target.label } });
7041
7212
  }
7042
7213
  if (action === "click") {
7043
7214
  const el = await ctx.page.evaluate(
@@ -7050,12 +7221,12 @@ var visualTagV2Command = registerCommand({
7050
7221
  return {x: Math.round(r.x + r.width/2), y: Math.round(r.y + r.height/2)};
7051
7222
  })()`
7052
7223
  );
7053
- if (!el) return fail15(`\u5143\u7D20 ${target.id} \u4E0D\u53EF\u4EA4\u4E92`);
7224
+ if (!el) return fail16(`\u5143\u7D20 ${target.id} \u4E0D\u53EF\u4EA4\u4E92`);
7054
7225
  await ctx.page.mouse.click(el.x, el.y, { stealth: true });
7055
- return ok30({ action: "interact", query, target, result: { clicked: true, x: el.x, y: el.y } });
7226
+ return ok31({ action: "interact", query, target, result: { clicked: true, x: el.x, y: el.y } });
7056
7227
  }
7057
7228
  if (action === "fill") {
7058
- if (!value) return fail15("fill \u9700\u8981 --value \u53C2\u6570");
7229
+ if (!value) return fail16("fill \u9700\u8981 --value \u53C2\u6570");
7059
7230
  const el = await ctx.page.evaluate(
7060
7231
  `(function(){
7061
7232
  var map = window.__xbTagMap;
@@ -7066,12 +7237,12 @@ var visualTagV2Command = registerCommand({
7066
7237
  return {x: Math.round(r.x + r.width/2), y: Math.round(r.y + r.height/2)};
7067
7238
  })()`
7068
7239
  );
7069
- if (!el) return fail15(`\u5143\u7D20 ${target.id} \u4E0D\u53EF\u4EA4\u4E92`);
7240
+ if (!el) return fail16(`\u5143\u7D20 ${target.id} \u4E0D\u53EF\u4EA4\u4E92`);
7070
7241
  await ctx.page.mouse.click(el.x, el.y, { stealth: true });
7071
7242
  await ctx.page.keyboard.type(value, { stealth: true });
7072
- return ok30({ action: "interact", query, target, result: { filled: true, value } });
7243
+ return ok31({ action: "interact", query, target, result: { filled: true, value } });
7073
7244
  }
7074
- return fail15(`\u672A\u77E5 action: ${action}`);
7245
+ return fail16(`\u672A\u77E5 action: ${action}`);
7075
7246
  }
7076
7247
  case "export": {
7077
7248
  const result = await ctx.page.evaluate(
@@ -7119,12 +7290,12 @@ var visualTagV2Command = registerCommand({
7119
7290
  })()`
7120
7291
  );
7121
7292
  const parsed = JSON.parse(result);
7122
- if (parsed.err) return fail15(String(parsed.err));
7123
- return ok30({ action: "export", element: parsed });
7293
+ if (parsed.err) return fail16(String(parsed.err));
7294
+ return ok31({ action: "export", element: parsed });
7124
7295
  }
7125
7296
  case "clear": {
7126
7297
  await ctx.page.evaluate(`(function(){var o=document.getElementById('__xb-tag-overlay');if(o)o.remove();window.__xbTagMap=null;window.__xbTagStats=null;return 'ok'})()`);
7127
- return ok30({ action: "clear" });
7298
+ return ok31({ action: "clear" });
7128
7299
  }
7129
7300
  }
7130
7301
  }
@@ -7533,7 +7704,10 @@ function buildSnapshot(elements) {
7533
7704
  }
7534
7705
 
7535
7706
  // src/tips/index.ts
7536
- var DEBOUNCE_MS = 500;
7707
+ function tipsDebounceMs() {
7708
+ const v = parseInt(process.env.XBROWSER_TIPS_DEBOUNCE ?? "120", 10);
7709
+ return Number.isFinite(v) && v > 0 ? v : 0;
7710
+ }
7537
7711
  var SKIP_DETECT_COMMANDS = /* @__PURE__ */ new Set([
7538
7712
  "goto",
7539
7713
  // 导航命令不需要检测
@@ -7625,7 +7799,9 @@ var TipsManager = class {
7625
7799
  }
7626
7800
  }
7627
7801
  debounce() {
7628
- return new Promise((resolve) => setTimeout(resolve, DEBOUNCE_MS));
7802
+ const ms = tipsDebounceMs();
7803
+ if (ms <= 0) return Promise.resolve();
7804
+ return new Promise((resolve) => setTimeout(resolve, ms));
7629
7805
  }
7630
7806
  formatTips(tips) {
7631
7807
  return tips.map((tip) => {
@@ -7794,7 +7970,7 @@ async function guardCheck(commandName) {
7794
7970
  }
7795
7971
  }
7796
7972
  function errorResult(message) {
7797
- return { ...fail16(message), duration: 0 };
7973
+ return { ...fail17(message), duration: 0 };
7798
7974
  }
7799
7975
  function tipsToMessages(tips) {
7800
7976
  if (!tips || tips.length === 0) return [];
@@ -7871,7 +8047,7 @@ async function executeCommand(commandName, params, sessionName = "default", extr
7871
8047
  }
7872
8048
  let targetPageOverride = null;
7873
8049
  if (_target && extraOpts?.cdpEndpoint) {
7874
- const { findTargetPage } = await import("./browser-4LOJSMWV.js");
8050
+ const { findTargetPage } = await import("./browser-ZD53IMUJ.js");
7875
8051
  targetPageOverride = await findTargetPage(extraOpts.cdpEndpoint, _target);
7876
8052
  if (!targetPageOverride) {
7877
8053
  return errorResult(`Target "${_target}" not found. Use 'xbrowser targets --cdp ${extraOpts.cdpEndpoint}' to list available pages.`);
@@ -7983,7 +8159,7 @@ async function executeCommand(commandName, params, sessionName = "default", extr
7983
8159
  const cache = /* @__PURE__ */ new Map();
7984
8160
  const resolved = await resolveRefParams(session.page, params, command.selectorParams, cache, session.id);
7985
8161
  if (resolved.tips.length > 0) {
7986
- refTips = normalizeTips6(resolved.tips);
8162
+ refTips = normalizeTips7(resolved.tips);
7987
8163
  params = resolved.params;
7988
8164
  }
7989
8165
  }
@@ -8051,8 +8227,8 @@ async function executeCommand(commandName, params, sessionName = "default", extr
8051
8227
  }
8052
8228
  const merged = [
8053
8229
  ...raw.tips || [],
8054
- ...normalizeTips6(smartTips),
8055
- ...snapshotHint ? normalizeTips6([snapshotHint]) : [],
8230
+ ...normalizeTips7(smartTips),
8231
+ ...snapshotHint ? normalizeTips7([snapshotHint]) : [],
8056
8232
  ...refTips
8057
8233
  ];
8058
8234
  const isSuccess = raw.success !== false;
@@ -8067,7 +8243,7 @@ async function executeCommand(commandName, params, sessionName = "default", extr
8067
8243
  timestamp: start
8068
8244
  });
8069
8245
  if (isSuccess) {
8070
- return { ...ok31(raw.data, merged.length > 0 ? merged : raw.tips), duration, ...hookOutputs ? { hookOutputs } : {} };
8246
+ return { ...ok32(raw.data, merged.length > 0 ? merged : raw.tips), duration, ...hookOutputs ? { hookOutputs } : {} };
8071
8247
  }
8072
8248
  const fc = classifyFailure(raw.message);
8073
8249
  return {
@@ -8080,7 +8256,7 @@ async function executeCommand(commandName, params, sessionName = "default", extr
8080
8256
  ...hookOutputs ? { hookOutputs } : {}
8081
8257
  };
8082
8258
  }
8083
- const smartTipNormalized = normalizeTips6(smartTips);
8259
+ const smartTipNormalized = normalizeTips7(smartTips);
8084
8260
  recordArchive(session?.id, sessionName, {
8085
8261
  step: 0,
8086
8262
  command: commandName,
@@ -8090,7 +8266,7 @@ async function executeCommand(commandName, params, sessionName = "default", extr
8090
8266
  duration,
8091
8267
  timestamp: start
8092
8268
  });
8093
- return { ...ok31(raw, smartTipNormalized), duration, ...hookOutputs ? { hookOutputs } : {} };
8269
+ return { ...ok32(raw, smartTipNormalized), duration, ...hookOutputs ? { hookOutputs } : {} };
8094
8270
  } catch (err) {
8095
8271
  const end = Date.now();
8096
8272
  const duration = end - start;
@@ -8135,7 +8311,7 @@ async function executeCommand(commandName, params, sessionName = "default", extr
8135
8311
  duration,
8136
8312
  timestamp: start
8137
8313
  });
8138
- return { ...fail16(errorMessage), duration };
8314
+ return { ...fail17(errorMessage), duration };
8139
8315
  } finally {
8140
8316
  }
8141
8317
  }
@@ -8180,7 +8356,7 @@ async function executeChain(input, options) {
8180
8356
  results.push({
8181
8357
  command: cmdName,
8182
8358
  raw: cmdStr,
8183
- ...fail16(`Plugin "${cmdName}" requires a sub-command`),
8359
+ ...fail17(`Plugin "${cmdName}" requires a sub-command`),
8184
8360
  duration: 0
8185
8361
  });
8186
8362
  if (type === "and") {
@@ -8199,7 +8375,7 @@ async function executeChain(input, options) {
8199
8375
  results.push({
8200
8376
  command: cmdName,
8201
8377
  raw: cmdStr,
8202
- ...fail16(`Unknown command "${subCommand}" for plugin "${cmdName}"`),
8378
+ ...fail17(`Unknown command "${subCommand}" for plugin "${cmdName}"`),
8203
8379
  duration: 0
8204
8380
  });
8205
8381
  if (type === "and") {
@@ -8269,7 +8445,7 @@ async function executeChain(input, options) {
8269
8445
  success: false,
8270
8446
  data: data2,
8271
8447
  message: loginGuard.message,
8272
- tips: normalizeTips6(loginGuard.tips),
8448
+ tips: normalizeTips7(loginGuard.tips),
8273
8449
  duration: duration3
8274
8450
  });
8275
8451
  if (type === "and") {
@@ -8311,7 +8487,7 @@ async function executeChain(input, options) {
8311
8487
  results.push({
8312
8488
  command: `${cmdName} ${subCommand}`,
8313
8489
  raw: cmdStr,
8314
- ...ok31(data),
8490
+ ...ok32(data),
8315
8491
  duration: duration2,
8316
8492
  ...hookOutputs ? { hookOutputs } : {}
8317
8493
  });
@@ -8339,7 +8515,7 @@ async function executeChain(input, options) {
8339
8515
  results.push({
8340
8516
  command: `${cmdName} ${subCommand}`,
8341
8517
  raw: cmdStr,
8342
- ...fail16(errorMessage),
8518
+ ...fail17(errorMessage),
8343
8519
  duration: duration2
8344
8520
  });
8345
8521
  if (type === "and") {
@@ -9711,7 +9887,7 @@ function createRPCHandler() {
9711
9887
  if (isNewFormat) {
9712
9888
  try {
9713
9889
  const replayErrors = [];
9714
- const { SessionReplayer } = await import("./session-replayer-PJIUH7KI.js");
9890
+ const { SessionReplayer } = await import("./session-replayer-TXTNTG33.js");
9715
9891
  const replayer = new SessionReplayer({
9716
9892
  page: session.page,
9717
9893
  stepDelay: slowMo * 500,
@@ -9763,10 +9939,10 @@ function createRPCHandler() {
9763
9939
  const errors = Array.isArray(input.errors) ? input.errors : [];
9764
9940
  const eventsPlayed = typeof input.eventsPlayed === "number" ? input.eventsPlayed : 0;
9765
9941
  const totalEvents = typeof input.totalEvents === "number" ? input.totalEvents : eventsPlayed + errors.length;
9766
- const ok32 = input.ok ?? errors.length === 0;
9942
+ const ok33 = input.ok ?? errors.length === 0;
9767
9943
  return {
9768
- ok: ok32,
9769
- success: ok32,
9944
+ ok: ok33,
9945
+ success: ok33,
9770
9946
  duration: typeof input.duration === "number" ? input.duration : 0,
9771
9947
  eventsPlayed,
9772
9948
  totalEvents,