@xbrowser/cli 1.26.0 → 1.28.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.
@@ -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,
@@ -1305,9 +1305,12 @@ var visionTaskCommand = registerCommand({
1305
1305
  } catch {
1306
1306
  }
1307
1307
  }
1308
- const buffer = await page.screenshot({ type: "png" });
1308
+ const shotQuality = Math.max(30, Math.min(95, parseInt(process.env.XBROWSER_VLM_SHOT_QUALITY ?? "75", 10) || 75));
1309
+ const buffer = await page.screenshot({ type: "jpeg", quality: shotQuality });
1309
1310
  const b64 = buffer.toString("base64");
1310
- const { w, h } = pngDims(b64);
1311
+ const vp = typeof page.viewportSize === "function" ? page.viewportSize() : null;
1312
+ const w = vp?.width ?? pngDims(b64).w;
1313
+ const h = vp?.height ?? pngDims(b64).h;
1311
1314
  const obsText = [
1312
1315
  `\u4EFB\u52A1\uFF1A${p.task}`,
1313
1316
  `\u622A\u56FE\u5C3A\u5BF8\uFF1A${w}x${h}\uFF08\u5750\u6807\u539F\u70B9\uFF1A\u5DE6\u4E0A\u89D2\uFF09`,
@@ -1316,7 +1319,7 @@ var visionTaskCommand = registerCommand({
1316
1319
  ${history.slice(-6).join("\n")}` : "\u5C1A\u65E0\u52A8\u4F5C\u3002"
1317
1320
  ].join("\n");
1318
1321
  const reply = await vlmAskRetry(creds, [
1319
- { type: "image", source: { type: "base64", media_type: "image/png", data: b64 } },
1322
+ { type: "image", source: { type: "base64", media_type: shotQuality >= 100 ? "image/png" : "image/jpeg", data: b64 } },
1320
1323
  { type: "text", text: `${SYSTEM_PROMPT}
1321
1324
 
1322
1325
  ${obsText}` }
@@ -4760,6 +4763,25 @@ function getRefTarget(sessionKey2, ref) {
4760
4763
  if (!session || !target) return null;
4761
4764
  return { screenHash: session.screenHash, target };
4762
4765
  }
4766
+ function inheritStableRefs(key, rawTargets) {
4767
+ const prev = sessions.get(key);
4768
+ if (!prev || prev.targets.size === 0) {
4769
+ return rawTargets.map((target, index) => ({ ...target, ref: `e${index + 1}` }));
4770
+ }
4771
+ const bySelector = /* @__PURE__ */ new Map();
4772
+ let maxId = 0;
4773
+ for (const [ref, target] of prev.targets) {
4774
+ bySelector.set(target.selector, ref);
4775
+ const id = Number(ref.slice(1));
4776
+ if (Number.isFinite(id) && id > maxId) maxId = id;
4777
+ }
4778
+ let next = maxId + 1;
4779
+ return rawTargets.map((target) => {
4780
+ const inherited = bySelector.get(target.selector);
4781
+ if (inherited) return { ...target, ref: inherited };
4782
+ return { ...target, ref: `e${next++}` };
4783
+ });
4784
+ }
4763
4785
 
4764
4786
  // src/utils/resolve-selector.ts
4765
4787
  function buildElementSelector(el) {
@@ -5384,10 +5406,7 @@ async function observePage(page, sessionId, options = {}) {
5384
5406
  { includeHidden: !!options.includeHidden, limit: options.limit ?? 80 }
5385
5407
  )
5386
5408
  ]);
5387
- const targets = raw.targets.map((target, index) => ({
5388
- ref: `e${index + 1}`,
5389
- ...target
5390
- }));
5409
+ const targets = inheritStableRefs(sessionKey(sessionId), raw.targets);
5391
5410
  replaceRefs(sessionKey(sessionId), raw.screenHash, targets);
5392
5411
  return {
5393
5412
  url: page.url(),
@@ -5879,26 +5898,193 @@ var waitForCommand = registerCommand({
5879
5898
  }
5880
5899
  });
5881
5900
 
5882
- // src/commands/tab.ts
5901
+ // src/commands/task.ts
5883
5902
  import { z as z27 } from "zod";
5884
- import { ok as ok26, fail as fail12 } from "@dyyz1993/xcli-core";
5885
- var TabParams = z27.object({
5886
- subcommand: z27.enum(["list", "new", "close", "switch"]),
5887
- url: z27.string().optional(),
5888
- index: z27.number().int().min(0).optional()
5903
+ import { ok as ok26, fail as fail12, normalizeTips as normalizeTips5 } from "@dyyz1993/xcli-core";
5904
+ 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
5905
+
5906
+ \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
5907
+ {"action":"click","ref":"@eN","thought":"\u4E3A\u4EC0\u4E48"}
5908
+ {"action":"fill","ref":"@eN","value":"\u6587\u672C","thought":"\u4E3A\u4EC0\u4E48"}
5909
+ {"action":"select","ref":"@eN","value":"\u9009\u9879\u503C","thought":"\u4E3A\u4EC0\u4E48"}
5910
+ {"action":"press","value":"Enter","thought":"\u4E3A\u4EC0\u4E48"}
5911
+ {"action":"scroll","value":"down \u6216 up","thought":"\u4E3A\u4EC0\u4E48"}
5912
+ {"action":"done","value":"\u5B8C\u6210\u6458\u8981","thought":"\u4E3A\u4EC0\u4E48"}
5913
+ {"action":"blocked","value":"\u5361\u4F4F\u539F\u56E0","thought":"\u4E3A\u4EC0\u4E48"}
5914
+
5915
+ \u89C4\u5219\uFF1A
5916
+ 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
5917
+ 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
5918
+ 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`;
5919
+ function extractDecision(raw) {
5920
+ let s = raw.trim().replace(/^```(?:json)?\s*/i, "").replace(/\s*```$/, "");
5921
+ const start = s.indexOf("{");
5922
+ if (start < 0) return null;
5923
+ let depth = 0;
5924
+ for (let i = start; i < s.length; i++) {
5925
+ if (s[i] === "{") depth++;
5926
+ else if (s[i] === "}") {
5927
+ depth--;
5928
+ if (depth === 0) {
5929
+ try {
5930
+ return JSON.parse(s.slice(start, i + 1));
5931
+ } catch {
5932
+ return null;
5933
+ }
5934
+ }
5935
+ }
5936
+ }
5937
+ return null;
5938
+ }
5939
+ var taskCommand = registerCommand({
5940
+ name: "task",
5941
+ description: "Autonomous goal loop: observe refs \u2192 LLM decides \u2192 act, until done/blocked (budget-capped)",
5942
+ scope: "page",
5943
+ parameters: z27.object({
5944
+ goal: z27.string().describe("Natural-language goal"),
5945
+ maxSteps: z27.number().int().positive().max(50).optional().default(15).describe("Hard action budget"),
5946
+ timeout: z27.number().optional().default(18e4).describe("Wall clock budget in ms"),
5947
+ limit: z27.number().int().positive().max(300).optional().default(80).describe("Max targets per observe")
5948
+ }),
5949
+ result: z27.object({
5950
+ status: z27.enum(["done", "blocked", "max_steps", "error"]),
5951
+ summary: z27.string().optional(),
5952
+ steps: z27.array(z27.record(z27.unknown())),
5953
+ finalUrl: z27.string().optional(),
5954
+ usage: z27.object({ llmCalls: z27.number(), steps: z27.number() }).passthrough().optional()
5955
+ }).passthrough(),
5956
+ handler: async (p, ctx) => {
5957
+ const creds = loadVLMCredentials2();
5958
+ if (!creds) {
5959
+ return fail12("task \u9700\u8981\u51B3\u7B56\u6A21\u578B\u51ED\u8BC1\uFF1A\u8BBE\u7F6E XBROWSER_VLM_CONFIG \u6216 ~/.zcode/v2/config.json");
5960
+ }
5961
+ const model = process.env.XBROWSER_TASK_MODEL || creds.model;
5962
+ const started = Date.now();
5963
+ const steps = [];
5964
+ const history = [];
5965
+ let llmCalls = 0;
5966
+ let status = "max_steps";
5967
+ let summary = "";
5968
+ let lastError = "";
5969
+ for (let step = 1; step <= p.maxSteps; step++) {
5970
+ if (Date.now() - started > p.timeout) {
5971
+ status = "blocked";
5972
+ summary = `timeout after ${step - 1} steps`;
5973
+ break;
5974
+ }
5975
+ const obs = await observePage(ctx.page, ctx.sessionId, { limit: p.limit, includeHidden: false });
5976
+ const compact = obs.compact ?? obs.targets.map((t, i) => `@e${i + 1} [${t.tag ?? ""}] ${t.name ?? ""}`).join("\n");
5977
+ const screenHash = obs.screenHash;
5978
+ const userPayload = [
5979
+ `\u76EE\u6807\uFF1A${p.goal}`,
5980
+ `\u5F53\u524D\u9875\u9762\uFF08URL: ${obs.url ?? ""}\uFF09\uFF1A`,
5981
+ compact,
5982
+ history.length ? `
5983
+ \u5DF2\u6267\u884C\uFF08\u52FF\u91CD\u590D\u5931\u8D25\u52A8\u4F5C\uFF09\uFF1A
5984
+ ${history.slice(-6).join("\n")}` : ""
5985
+ ].filter(Boolean).join("\n");
5986
+ let raw = "";
5987
+ try {
5988
+ raw = await vlmAsk({ ...creds, model }, [{ type: "text", text: `${DECISION_SYSTEM}
5989
+
5990
+ ---
5991
+
5992
+ ${userPayload}` }], 900);
5993
+ llmCalls++;
5994
+ } catch (e) {
5995
+ lastError = e instanceof Error ? e.message : String(e);
5996
+ status = "error";
5997
+ summary = `LLM call failed: ${lastError}`;
5998
+ break;
5999
+ }
6000
+ const decision = extractDecision(raw);
6001
+ if (!decision || typeof decision.action !== "string") {
6002
+ status = "blocked";
6003
+ summary = `LLM returned unparsable decision: ${raw.slice(0, 120)}`;
6004
+ break;
6005
+ }
6006
+ const action = decision.action;
6007
+ const ref = typeof decision.ref === "string" ? decision.ref : void 0;
6008
+ const value = typeof decision.value === "string" ? decision.value : void 0;
6009
+ const thought = typeof decision.thought === "string" ? decision.thought : void 0;
6010
+ if (action === "done") {
6011
+ status = "done";
6012
+ summary = value || thought || "task done";
6013
+ steps.push({ step, thought, action: "done", ok: true, screenHash });
6014
+ break;
6015
+ }
6016
+ if (action === "blocked") {
6017
+ status = "blocked";
6018
+ summary = value || thought || "LLM judged blocked";
6019
+ steps.push({ step, thought, action: "blocked", ok: true, screenHash });
6020
+ break;
6021
+ }
6022
+ const legalRefs = new Set(obs.targets.map((t, i) => t.ref ?? `e${i + 1}`));
6023
+ const normalizedRef = ref ? legalRefs.has(ref.replace("@", "")) || legalRefs.has(ref) ? ref : void 0 : void 0;
6024
+ if (ref && !normalizedRef && action !== "scroll" && action !== "press") {
6025
+ history.push(`step${step}: ${action} ${ref} REJECTED (ref not in current list)`);
6026
+ steps.push({ step, thought, action, ref, ok: false, error: "ref not in current list", screenHash });
6027
+ continue;
6028
+ }
6029
+ const res = await actOnPage(ctx.page, ctx.sessionId, {
6030
+ action,
6031
+ ref: normalizedRef,
6032
+ value,
6033
+ selector: void 0,
6034
+ force: false,
6035
+ timeout: 1e4
6036
+ });
6037
+ const record = {
6038
+ step,
6039
+ thought,
6040
+ action,
6041
+ ref: normalizedRef,
6042
+ value,
6043
+ ok: res.success === true,
6044
+ stale: res.stale,
6045
+ error: res.success ? void 0 : res.message || res.reason,
6046
+ screenHash
6047
+ };
6048
+ steps.push(record);
6049
+ history.push(`step${step}: ${action} ${normalizedRef ?? ""} ${value ?? ""} -> ${res.success ? "ok" : `failed(${res.reason || res.message})`}`);
6050
+ const sig = (s) => `${s.action}|${s.ref ?? ""}|${s.value ?? ""}`;
6051
+ const last3 = steps.slice(-3);
6052
+ if (last3.length === 3 && new Set(last3.map(sig)).size === 1) {
6053
+ status = "blocked";
6054
+ summary = "dead loop: identical action repeated 3 times";
6055
+ break;
6056
+ }
6057
+ }
6058
+ if (status === "max_steps") summary = summary || `hit maxSteps=${p.maxSteps}`;
6059
+ const finalUrl = ctx.page ? ctx.page.url() : void 0;
6060
+ const data = { status, summary, steps, finalUrl, usage: { llmCalls, steps: steps.length } };
6061
+ if (status === "error") return fail12(summary || lastError, normalizeTips5([`completed steps: ${steps.length}`]));
6062
+ return ok26(data, normalizeTips5([
6063
+ status === "done" ? `\u2705 task done (${steps.length} steps, ${llmCalls} LLM calls)` : `\u26A0\uFE0F task ${status}: ${summary.slice(0, 80)}`
6064
+ ]));
6065
+ }
6066
+ });
6067
+
6068
+ // src/commands/tab.ts
6069
+ import { z as z28 } from "zod";
6070
+ import { ok as ok27, fail as fail13 } from "@dyyz1993/xcli-core";
6071
+ var TabParams = z28.object({
6072
+ subcommand: z28.enum(["list", "new", "close", "switch"]),
6073
+ url: z28.string().optional(),
6074
+ index: z28.number().int().min(0).optional()
5889
6075
  });
5890
6076
  var tabCommand = registerCommand({
5891
6077
  name: "tab",
5892
6078
  description: "Manage browser tabs: list, new, close, switch",
5893
6079
  scope: "page",
5894
6080
  parameters: TabParams,
5895
- result: z27.object({
5896
- success: z27.boolean(),
5897
- data: z27.unknown()
6081
+ result: z28.object({
6082
+ success: z28.boolean(),
6083
+ data: z28.unknown()
5898
6084
  }),
5899
6085
  handler: async (p, ctx) => {
5900
6086
  if (!ctx.browserContext) {
5901
- return fail12("No browser context available. Use --cdp to connect to a browser first.");
6087
+ return fail13("No browser context available. Use --cdp to connect to a browser first.");
5902
6088
  }
5903
6089
  const pages = ctx.browserContext.pages();
5904
6090
  switch (p.subcommand) {
@@ -5911,7 +6097,7 @@ var tabCommand = registerCommand({
5911
6097
  case "switch":
5912
6098
  return handleSwitch(p, pages, ctx);
5913
6099
  default:
5914
- return fail12(`Unknown subcommand: ${p.subcommand}`);
6100
+ return fail13(`Unknown subcommand: ${p.subcommand}`);
5915
6101
  }
5916
6102
  }
5917
6103
  });
@@ -5926,7 +6112,7 @@ async function handleList(pages, ctx) {
5926
6112
  if (isActive) activeIndex = i;
5927
6113
  tabs.push({ index: i, url, title, active: isActive });
5928
6114
  }
5929
- return ok26({ tabs, total: tabs.length, activeIndex });
6115
+ return ok27({ tabs, total: tabs.length, activeIndex });
5930
6116
  }
5931
6117
  async function handleNew(p, _pages, ctx) {
5932
6118
  const newPage = await ctx.browserContext.newPage();
@@ -5954,7 +6140,7 @@ async function handleNew(p, _pages, ctx) {
5954
6140
  const title = await newPage.title().catch(() => "");
5955
6141
  const allPages = ctx.browserContext.pages();
5956
6142
  const newIndex = allPages.indexOf(newPage);
5957
- return ok26({
6143
+ return ok27({
5958
6144
  index: newIndex >= 0 ? newIndex : allPages.length - 1,
5959
6145
  url: newPage.url(),
5960
6146
  title,
@@ -5965,11 +6151,11 @@ async function handleNew(p, _pages, ctx) {
5965
6151
  async function handleClose(p, ctx) {
5966
6152
  const currentPages = ctx.browserContext.pages();
5967
6153
  if (currentPages.length <= 1) {
5968
- return fail12("Cannot close the last remaining tab");
6154
+ return fail13("Cannot close the last remaining tab");
5969
6155
  }
5970
6156
  const closeIndex = p.index ?? currentPages.findIndex((pg) => pg === ctx.page);
5971
6157
  if (closeIndex < 0 || closeIndex >= currentPages.length) {
5972
- return fail12(`Invalid tab index: ${closeIndex}. Valid range: 0-${currentPages.length - 1}`);
6158
+ return fail13(`Invalid tab index: ${closeIndex}. Valid range: 0-${currentPages.length - 1}`);
5973
6159
  }
5974
6160
  const pageToClose = currentPages[closeIndex];
5975
6161
  const isActivePage = pageToClose === ctx.page;
@@ -5984,7 +6170,7 @@ async function handleClose(p, ctx) {
5984
6170
  }
5985
6171
  ctx.page = newActivePage;
5986
6172
  }
5987
- return ok26({
6173
+ return ok27({
5988
6174
  closedIndex: closeIndex,
5989
6175
  total: remainingPages.length,
5990
6176
  activeIndex: isActivePage ? closeIndex < remainingPages.length ? closeIndex : remainingPages.length - 1 : remainingPages.findIndex((pg) => pg === ctx.page)
@@ -5992,10 +6178,10 @@ async function handleClose(p, ctx) {
5992
6178
  }
5993
6179
  async function handleSwitch(p, pages, ctx) {
5994
6180
  if (p.index === void 0) {
5995
- return fail12("Parameter --index is required for switch subcommand");
6181
+ return fail13("Parameter --index is required for switch subcommand");
5996
6182
  }
5997
6183
  if (p.index < 0 || p.index >= pages.length) {
5998
- return fail12(`Invalid tab index: ${p.index}. Valid range: 0-${pages.length - 1}`);
6184
+ return fail13(`Invalid tab index: ${p.index}. Valid range: 0-${pages.length - 1}`);
5999
6185
  }
6000
6186
  const targetPage = pages[p.index];
6001
6187
  await targetPage.bringToFront().catch(() => {
@@ -6017,7 +6203,7 @@ async function handleSwitch(p, pages, ctx) {
6017
6203
  }
6018
6204
  ctx.page = targetPage;
6019
6205
  const title = await targetPage.title().catch(() => "");
6020
- return ok26({
6206
+ return ok27({
6021
6207
  index: p.index,
6022
6208
  url: targetPage.url(),
6023
6209
  title,
@@ -6026,8 +6212,8 @@ async function handleSwitch(p, pages, ctx) {
6026
6212
  }
6027
6213
 
6028
6214
  // src/commands/addinitscript.ts
6029
- import { z as z28 } from "zod";
6030
- import { ok as ok27 } from "@dyyz1993/xcli-core";
6215
+ import { z as z29 } from "zod";
6216
+ import { ok as ok28 } from "@dyyz1993/xcli-core";
6031
6217
  import { readFileSync as readFileSync4 } from "fs";
6032
6218
 
6033
6219
  // src/chain-parser.ts
@@ -6168,14 +6354,14 @@ registerCommandDefinition("tab", ["subcommand"]);
6168
6354
  registerCommandDefinition("mouse", ["action", "x", "y"]);
6169
6355
 
6170
6356
  // src/commands/addinitscript.ts
6171
- var InitScriptParams = z28.object({
6172
- script: z28.string().optional(),
6173
- file: z28.string().optional(),
6174
- stdin: z28.boolean().optional(),
6175
- name: z28.string().optional(),
6176
- list: z28.boolean().optional(),
6177
- remove: z28.union([z28.string(), z28.boolean()]).optional(),
6178
- base64: z28.string().optional()
6357
+ var InitScriptParams = z29.object({
6358
+ script: z29.string().optional(),
6359
+ file: z29.string().optional(),
6360
+ stdin: z29.boolean().optional(),
6361
+ name: z29.string().optional(),
6362
+ list: z29.boolean().optional(),
6363
+ remove: z29.union([z29.string(), z29.boolean()]).optional(),
6364
+ base64: z29.string().optional()
6179
6365
  });
6180
6366
  var registeredScripts = /* @__PURE__ */ new Map();
6181
6367
  function resolveScriptContent(params) {
@@ -6209,14 +6395,14 @@ var addInitScriptCommand = registerCommand({
6209
6395
  description: "Add an initialization script that runs on every page load",
6210
6396
  scope: "page",
6211
6397
  parameters: InitScriptParams,
6212
- result: z28.object({
6213
- scripts: z28.array(z28.object({ name: z28.string(), size: z28.number(), preview: z28.string() })).optional(),
6214
- removed: z28.string().optional(),
6215
- existed: z28.boolean().optional(),
6216
- error: z28.string().optional(),
6217
- registered: z28.string().optional(),
6218
- hint: z28.string().optional(),
6219
- executedImmediately: z28.boolean().optional()
6398
+ result: z29.object({
6399
+ scripts: z29.array(z29.object({ name: z29.string(), size: z29.number(), preview: z29.string() })).optional(),
6400
+ removed: z29.string().optional(),
6401
+ existed: z29.boolean().optional(),
6402
+ error: z29.string().optional(),
6403
+ registered: z29.string().optional(),
6404
+ hint: z29.string().optional(),
6405
+ executedImmediately: z29.boolean().optional()
6220
6406
  }).passthrough(),
6221
6407
  handler: async (params, ctx) => {
6222
6408
  if (params.list) {
@@ -6225,20 +6411,20 @@ var addInitScriptCommand = registerCommand({
6225
6411
  size: content2.length,
6226
6412
  preview: content2.slice(0, 80)
6227
6413
  }));
6228
- return ok27({ scripts });
6414
+ return ok28({ scripts });
6229
6415
  }
6230
6416
  if (params.remove && typeof params.remove === "string") {
6231
6417
  const existed = registeredScripts.delete(params.remove);
6232
- return ok27({ removed: params.remove, existed });
6418
+ return ok28({ removed: params.remove, existed });
6233
6419
  }
6234
6420
  const removeTarget = (typeof params.remove === "string" ? params.remove : null) || (params.name && !resolveScriptContent(params) ? params.name : null);
6235
6421
  if (removeTarget && !resolveScriptContent(params)) {
6236
6422
  const existed = registeredScripts.delete(removeTarget);
6237
- return ok27({ removed: removeTarget, existed });
6423
+ return ok28({ removed: removeTarget, existed });
6238
6424
  }
6239
6425
  let content = params.stdin ? await readStdin() : resolveScriptContent(params);
6240
6426
  if (!content) {
6241
- return ok27({ error: "No script content provided. Use --script, --file, --stdin, or --base64" });
6427
+ return ok28({ error: "No script content provided. Use --script, --file, --stdin, or --base64" });
6242
6428
  }
6243
6429
  const scriptName = params.name ?? `script-${Date.now()}`;
6244
6430
  registeredScripts.set(scriptName, content);
@@ -6246,45 +6432,45 @@ var addInitScriptCommand = registerCommand({
6246
6432
  try {
6247
6433
  await ctx.page.evaluate(content);
6248
6434
  } catch {
6249
- return ok27({
6435
+ return ok28({
6250
6436
  registered: scriptName,
6251
6437
  hint: "Script registered for future page loads; immediate execution skipped (page may not be ready)"
6252
6438
  });
6253
6439
  }
6254
- return ok27({ registered: scriptName, executedImmediately: true });
6440
+ return ok28({ registered: scriptName, executedImmediately: true });
6255
6441
  }
6256
6442
  });
6257
6443
  registerCommandDefinition("addinitscript", ["script"]);
6258
6444
 
6259
6445
  // src/commands/find.ts
6260
- import { z as z29 } from "zod";
6261
- import { ok as ok28, fail as fail13, normalizeTips as normalizeTips5 } from "@dyyz1993/xcli-core";
6262
- var actionSchema2 = z29.enum(["click", "fill", "type", "select", "hover", "check"]);
6446
+ import { z as z30 } from "zod";
6447
+ import { ok as ok29, fail as fail14, normalizeTips as normalizeTips6 } from "@dyyz1993/xcli-core";
6448
+ var actionSchema2 = z30.enum(["click", "fill", "type", "select", "hover", "check"]);
6263
6449
  var findCommand = registerCommand({
6264
6450
  name: "find",
6265
6451
  description: "Find elements by semantic strategy (text/role/label/placeholder/testid) and optionally perform an action",
6266
6452
  scope: "page",
6267
- parameters: z29.object({
6268
- strategy: z29.enum(["text", "role", "label", "placeholder", "testid", "alt", "title", "first", "last", "nth"]),
6269
- value: z29.string(),
6270
- name: z29.string().optional(),
6271
- exact: z29.boolean().optional().default(false),
6272
- operation: z29.string().optional().describe('Trailing operation syntax, e.g. click, fill "text", type "text"'),
6453
+ parameters: z30.object({
6454
+ strategy: z30.enum(["text", "role", "label", "placeholder", "testid", "alt", "title", "first", "last", "nth"]),
6455
+ value: z30.string(),
6456
+ name: z30.string().optional(),
6457
+ exact: z30.boolean().optional().default(false),
6458
+ operation: z30.string().optional().describe('Trailing operation syntax, e.g. click, fill "text", type "text"'),
6273
6459
  action: actionSchema2.optional().describe("Action to perform when not using trailing operation syntax"),
6274
- actionValue: z29.string().optional().describe("Value for fill/type/select when using action"),
6275
- index: z29.number().int().optional().describe("Index for nth strategy"),
6276
- click: z29.boolean().optional().default(false),
6277
- fill: z29.string().optional(),
6278
- type: z29.string().optional(),
6279
- select: z29.string().optional(),
6280
- hover: z29.boolean().optional().default(false),
6281
- check: z29.boolean().optional().default(false),
6282
- timeout: z29.number().optional().default(1e4)
6460
+ actionValue: z30.string().optional().describe("Value for fill/type/select when using action"),
6461
+ index: z30.number().int().optional().describe("Index for nth strategy"),
6462
+ click: z30.boolean().optional().default(false),
6463
+ fill: z30.string().optional(),
6464
+ type: z30.string().optional(),
6465
+ select: z30.string().optional(),
6466
+ hover: z30.boolean().optional().default(false),
6467
+ check: z30.boolean().optional().default(false),
6468
+ timeout: z30.number().optional().default(1e4)
6283
6469
  }),
6284
- result: z29.object({
6285
- matched: z29.number(),
6286
- selector: z29.string(),
6287
- action: z29.string().optional()
6470
+ result: z30.object({
6471
+ matched: z30.number(),
6472
+ selector: z30.string(),
6473
+ action: z30.string().optional()
6288
6474
  }),
6289
6475
  handler: async (p, ctx) => {
6290
6476
  const page = ctx.page;
@@ -6299,7 +6485,7 @@ var findCommand = registerCommand({
6299
6485
  });
6300
6486
  const count = await locator.count();
6301
6487
  if (count === 0) {
6302
- return fail13(`No element found with ${p.strategy}="${p.value}"`);
6488
+ return fail14(`No element found with ${p.strategy}="${p.value}"`);
6303
6489
  }
6304
6490
  const tips = [];
6305
6491
  const target = selectTarget(locator, p.strategy);
@@ -6311,15 +6497,15 @@ var findCommand = registerCommand({
6311
6497
  await target.click({ timeout: p.timeout, force: true });
6312
6498
  return okWithTips({ matched: count, selector, action: "click" }, tips);
6313
6499
  } else if (actionName === "fill") {
6314
- if (actionValue === void 0) return fail13("find fill requires a value");
6500
+ if (actionValue === void 0) return fail14("find fill requires a value");
6315
6501
  await target.fill(actionValue, { timeout: p.timeout, force: true });
6316
6502
  return okWithTips({ matched: count, selector, action: `fill("${actionValue}")` }, tips);
6317
6503
  } else if (actionName === "type") {
6318
- if (actionValue === void 0) return fail13("find type requires a value");
6504
+ if (actionValue === void 0) return fail14("find type requires a value");
6319
6505
  await target.type(actionValue, { delay: 10, timeout: p.timeout });
6320
6506
  return okWithTips({ matched: count, selector, action: `type("${actionValue}")` }, tips);
6321
6507
  } else if (actionName === "select") {
6322
- if (actionValue === void 0) return fail13("find select requires a value");
6508
+ if (actionValue === void 0) return fail14("find select requires a value");
6323
6509
  await target.selectOption(actionValue);
6324
6510
  return okWithTips({ matched: count, selector, action: `select("${actionValue}")` }, tips);
6325
6511
  } else if (actionName === "hover") {
@@ -6333,8 +6519,8 @@ var findCommand = registerCommand({
6333
6519
  }
6334
6520
  });
6335
6521
  function okWithTips(data, tips) {
6336
- const result = ok28(data);
6337
- if (tips.length > 0) result.tips = normalizeTips5(tips);
6522
+ const result = ok29(data);
6523
+ if (tips.length > 0) result.tips = normalizeTips6(tips);
6338
6524
  return result;
6339
6525
  }
6340
6526
  function parseOperation(operation) {
@@ -6432,8 +6618,8 @@ function describeSelector(strategy, value, name) {
6432
6618
  }
6433
6619
 
6434
6620
  // src/commands/visual-tag.ts
6435
- import { z as z30 } from "zod";
6436
- import { ok as ok29, fail as fail14 } from "@dyyz1993/xcli-core";
6621
+ import { z as z31 } from "zod";
6622
+ import { ok as ok30, fail as fail15 } from "@dyyz1993/xcli-core";
6437
6623
  var SAFE_SET = "ahjkmnprtw3479".split("");
6438
6624
  var TAG_SCRIPT = `
6439
6625
  (function() {
@@ -6524,49 +6710,49 @@ var visualTagCommand = registerCommand({
6524
6710
  name: "visual-tag",
6525
6711
  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",
6526
6712
  scope: "page",
6527
- parameters: z30.object({
6528
- action: z30.enum(["tag", "lookup", "clear", "list"]),
6529
- id: z30.string().optional().describe("lookup \u65F6\u6307\u5B9A\u8981\u67E5\u7684 ID")
6713
+ parameters: z31.object({
6714
+ action: z31.enum(["tag", "lookup", "clear", "list"]),
6715
+ id: z31.string().optional().describe("lookup \u65F6\u6307\u5B9A\u8981\u67E5\u7684 ID")
6530
6716
  }),
6531
- result: z30.object({
6532
- action: z30.string(),
6533
- tagged: z30.number().optional(),
6534
- id: z30.string().optional(),
6535
- element: z30.record(z30.unknown()).optional()
6717
+ result: z31.object({
6718
+ action: z31.string(),
6719
+ tagged: z31.number().optional(),
6720
+ id: z31.string().optional(),
6721
+ element: z31.record(z31.unknown()).optional()
6536
6722
  }),
6537
6723
  handler: async (p, ctx) => {
6538
6724
  switch (p.action) {
6539
6725
  case "tag": {
6540
6726
  const result = await ctx.page.evaluate(TAG_SCRIPT);
6541
6727
  const parsed = JSON.parse(result);
6542
- return ok29({ action: "tag", tagged: parsed.tagged });
6728
+ return ok30({ action: "tag", tagged: parsed.tagged });
6543
6729
  }
6544
6730
  case "lookup": {
6545
- if (!p.id) return fail14("lookup \u9700\u8981 --id \u53C2\u6570");
6731
+ if (!p.id) return fail15("lookup \u9700\u8981 --id \u53C2\u6570");
6546
6732
  const result = await ctx.page.evaluate(
6547
6733
  `(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'}); })()`
6548
6734
  );
6549
6735
  const parsed = JSON.parse(result);
6550
- if (parsed.err) return fail14(`ID ${p.id}: ${parsed.err}`);
6551
- return ok29({ action: "lookup", id: p.id, element: parsed });
6736
+ if (parsed.err) return fail15(`ID ${p.id}: ${parsed.err}`);
6737
+ return ok30({ action: "lookup", id: p.id, element: parsed });
6552
6738
  }
6553
6739
  case "list": {
6554
6740
  const result = await ctx.page.evaluate(
6555
6741
  `(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); })()`
6556
6742
  );
6557
- return ok29({ action: "list", element: JSON.parse(result) });
6743
+ return ok30({ action: "list", element: JSON.parse(result) });
6558
6744
  }
6559
6745
  case "clear": {
6560
6746
  await ctx.page.evaluate(`(function(){var o=document.getElementById('__xb-tag-overlay');if(o)o.remove();window.__xbTagMap=null;return 'cleared'})()`);
6561
- return ok29({ action: "clear" });
6747
+ return ok30({ action: "clear" });
6562
6748
  }
6563
6749
  }
6564
6750
  }
6565
6751
  });
6566
6752
 
6567
6753
  // src/commands/visual-tag-v2.ts
6568
- import { z as z31 } from "zod";
6569
- import { ok as ok30, fail as fail15 } from "@dyyz1993/xcli-core";
6754
+ import { z as z32 } from "zod";
6755
+ import { ok as ok31, fail as fail16 } from "@dyyz1993/xcli-core";
6570
6756
  var SAFE_SET2 = "ahjkmnprtw3479".split("");
6571
6757
  var TAG_V2_SCRIPT = `
6572
6758
  (function() {
@@ -6913,45 +7099,45 @@ var visualTagV2Command = registerCommand({
6913
7099
  name: "visual-tag-v2",
6914
7100
  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",
6915
7101
  scope: "page",
6916
- parameters: z31.object({
6917
- action: z31.enum(["tag", "lookup", "clear", "stats", "by-type", "find", "export", "interact"]),
6918
- id: z31.string().optional().describe("lookup \u65F6\u6307\u5B9A\u8981\u67E5\u7684 ID"),
6919
- query: z31.string().optional().describe('find \u65F6\u6307\u5B9A\u641C\u7D22\u8BCD\uFF08\u5982 "\u627E\u6709AI\u7F16\u7A0B\u6807\u7B7E\u7684\u5361\u7247"\uFF09'),
6920
- type: z31.string().optional().describe("by-type \u65F6\u8FC7\u6EE4\u7C7B\u578B\uFF1Aclick/input/img/list/count/text"),
6921
- "interact-action": z31.enum(["click", "fill", "read"]).optional().describe("interact \u52A8\u4F5C\u7C7B\u578B"),
6922
- value: z31.string().optional().describe("fill \u65F6\u7684\u586B\u5145\u503C")
7102
+ parameters: z32.object({
7103
+ action: z32.enum(["tag", "lookup", "clear", "stats", "by-type", "find", "export", "interact"]),
7104
+ id: z32.string().optional().describe("lookup \u65F6\u6307\u5B9A\u8981\u67E5\u7684 ID"),
7105
+ query: z32.string().optional().describe('find \u65F6\u6307\u5B9A\u641C\u7D22\u8BCD\uFF08\u5982 "\u627E\u6709AI\u7F16\u7A0B\u6807\u7B7E\u7684\u5361\u7247"\uFF09'),
7106
+ type: z32.string().optional().describe("by-type \u65F6\u8FC7\u6EE4\u7C7B\u578B\uFF1Aclick/input/img/list/count/text"),
7107
+ "interact-action": z32.enum(["click", "fill", "read"]).optional().describe("interact \u52A8\u4F5C\u7C7B\u578B"),
7108
+ value: z32.string().optional().describe("fill \u65F6\u7684\u586B\u5145\u503C")
6923
7109
  }),
6924
- result: z31.object({
6925
- action: z31.string(),
6926
- total: z31.number().optional(),
6927
- byType: z31.record(z31.number()).optional(),
6928
- element: z31.record(z31.unknown()).optional()
7110
+ result: z32.object({
7111
+ action: z32.string(),
7112
+ total: z32.number().optional(),
7113
+ byType: z32.record(z32.number()).optional(),
7114
+ element: z32.record(z32.unknown()).optional()
6929
7115
  }),
6930
7116
  handler: async (p, ctx) => {
6931
7117
  switch (p.action) {
6932
7118
  case "tag": {
6933
7119
  const result = await ctx.page.evaluate(TAG_V2_SCRIPT);
6934
7120
  const parsed = JSON.parse(result);
6935
- return ok30({ action: "tag", total: parsed.total, byType: parsed.byType });
7121
+ return ok31({ action: "tag", total: parsed.total, byType: parsed.byType });
6936
7122
  }
6937
7123
  case "lookup": {
6938
- if (!p.id) return fail15("lookup \u9700\u8981 --id");
7124
+ if (!p.id) return fail16("lookup \u9700\u8981 --id");
6939
7125
  const result = await ctx.page.evaluate(
6940
7126
  `(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'})})()`
6941
7127
  );
6942
7128
  const parsed = JSON.parse(result);
6943
- if (parsed.err) return fail15(`ID ${p.id}: ${parsed.err}`);
6944
- return ok30({ action: "lookup", id: p.id, element: parsed });
7129
+ if (parsed.err) return fail16(`ID ${p.id}: ${parsed.err}`);
7130
+ return ok31({ action: "lookup", id: p.id, element: parsed });
6945
7131
  }
6946
7132
  case "by-type": {
6947
7133
  const result = await ctx.page.evaluate(
6948
7134
  `(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)})()`
6949
7135
  );
6950
- return ok30({ action: "by-type", element: JSON.parse(result) });
7136
+ return ok31({ action: "by-type", element: JSON.parse(result) });
6951
7137
  }
6952
7138
  case "find": {
6953
7139
  const query = p.query;
6954
- if (!query) return fail15('find \u9700\u8981 --query \u53C2\u6570\uFF08\u5982 "\u627E\u6709AI\u7F16\u7A0B\u6807\u7B7E\u7684\u5361\u7247"\uFF09');
7140
+ if (!query) return fail16('find \u9700\u8981 --query \u53C2\u6570\uFF08\u5982 "\u627E\u6709AI\u7F16\u7A0B\u6807\u7B7E\u7684\u5361\u7247"\uFF09');
6955
7141
  const result = await ctx.page.evaluate(
6956
7142
  `(function(){
6957
7143
  var map = window.__xbTagSerializable;
@@ -6993,21 +7179,21 @@ var visualTagV2Command = registerCommand({
6993
7179
  return JSON.stringify({total:results.length, results:results.slice(0,20)});
6994
7180
  })()`
6995
7181
  );
6996
- return ok30({ action: "find", query, element: JSON.parse(result) });
7182
+ return ok31({ action: "find", query, element: JSON.parse(result) });
6997
7183
  }
6998
7184
  case "stats": {
6999
7185
  const result = await ctx.page.evaluate(
7000
7186
  `(function(){return JSON.stringify(window.__xbTagStats||{})})()`
7001
7187
  );
7002
- return ok30({ action: "stats", element: JSON.parse(result) });
7188
+ return ok31({ action: "stats", element: JSON.parse(result) });
7003
7189
  }
7004
7190
  case "interact": {
7005
7191
  const query = p.query;
7006
7192
  const pAny = p;
7007
7193
  const action = pAny["interact-action"] || pAny.interactAction || pAny.interact_action;
7008
7194
  const value = pAny.value;
7009
- if (!query) return fail15("interact \u9700\u8981 --query \u53C2\u6570");
7010
- if (!action) return fail15("interact \u9700\u8981 --interact-action \u53C2\u6570\uFF08click/fill/read\uFF09");
7195
+ if (!query) return fail16("interact \u9700\u8981 --query \u53C2\u6570");
7196
+ if (!action) return fail16("interact \u9700\u8981 --interact-action \u53C2\u6570\uFF08click/fill/read\uFF09");
7011
7197
  const findResult = await ctx.page.evaluate(
7012
7198
  `(function(){
7013
7199
  var map = window.__xbTagSerializable;
@@ -7037,11 +7223,11 @@ var visualTagV2Command = registerCommand({
7037
7223
  })()`
7038
7224
  );
7039
7225
  const parsed = JSON.parse(findResult);
7040
- if (parsed.err) return fail15(parsed.err);
7041
- if (!parsed.total || !parsed.results?.length) return fail15(`\u672A\u627E\u5230\u5339\u914D "${query}" \u7684\u5143\u7D20`);
7226
+ if (parsed.err) return fail16(parsed.err);
7227
+ if (!parsed.total || !parsed.results?.length) return fail16(`\u672A\u627E\u5230\u5339\u914D "${query}" \u7684\u5143\u7D20`);
7042
7228
  const target = parsed.results[0];
7043
7229
  if (action === "read") {
7044
- return ok30({ action: "interact", query, target, result: { read: target.text || target.label } });
7230
+ return ok31({ action: "interact", query, target, result: { read: target.text || target.label } });
7045
7231
  }
7046
7232
  if (action === "click") {
7047
7233
  const el = await ctx.page.evaluate(
@@ -7054,12 +7240,12 @@ var visualTagV2Command = registerCommand({
7054
7240
  return {x: Math.round(r.x + r.width/2), y: Math.round(r.y + r.height/2)};
7055
7241
  })()`
7056
7242
  );
7057
- if (!el) return fail15(`\u5143\u7D20 ${target.id} \u4E0D\u53EF\u4EA4\u4E92`);
7243
+ if (!el) return fail16(`\u5143\u7D20 ${target.id} \u4E0D\u53EF\u4EA4\u4E92`);
7058
7244
  await ctx.page.mouse.click(el.x, el.y, { stealth: true });
7059
- return ok30({ action: "interact", query, target, result: { clicked: true, x: el.x, y: el.y } });
7245
+ return ok31({ action: "interact", query, target, result: { clicked: true, x: el.x, y: el.y } });
7060
7246
  }
7061
7247
  if (action === "fill") {
7062
- if (!value) return fail15("fill \u9700\u8981 --value \u53C2\u6570");
7248
+ if (!value) return fail16("fill \u9700\u8981 --value \u53C2\u6570");
7063
7249
  const el = await ctx.page.evaluate(
7064
7250
  `(function(){
7065
7251
  var map = window.__xbTagMap;
@@ -7070,12 +7256,12 @@ var visualTagV2Command = registerCommand({
7070
7256
  return {x: Math.round(r.x + r.width/2), y: Math.round(r.y + r.height/2)};
7071
7257
  })()`
7072
7258
  );
7073
- if (!el) return fail15(`\u5143\u7D20 ${target.id} \u4E0D\u53EF\u4EA4\u4E92`);
7259
+ if (!el) return fail16(`\u5143\u7D20 ${target.id} \u4E0D\u53EF\u4EA4\u4E92`);
7074
7260
  await ctx.page.mouse.click(el.x, el.y, { stealth: true });
7075
7261
  await ctx.page.keyboard.type(value, { stealth: true });
7076
- return ok30({ action: "interact", query, target, result: { filled: true, value } });
7262
+ return ok31({ action: "interact", query, target, result: { filled: true, value } });
7077
7263
  }
7078
- return fail15(`\u672A\u77E5 action: ${action}`);
7264
+ return fail16(`\u672A\u77E5 action: ${action}`);
7079
7265
  }
7080
7266
  case "export": {
7081
7267
  const result = await ctx.page.evaluate(
@@ -7123,12 +7309,12 @@ var visualTagV2Command = registerCommand({
7123
7309
  })()`
7124
7310
  );
7125
7311
  const parsed = JSON.parse(result);
7126
- if (parsed.err) return fail15(String(parsed.err));
7127
- return ok30({ action: "export", element: parsed });
7312
+ if (parsed.err) return fail16(String(parsed.err));
7313
+ return ok31({ action: "export", element: parsed });
7128
7314
  }
7129
7315
  case "clear": {
7130
7316
  await ctx.page.evaluate(`(function(){var o=document.getElementById('__xb-tag-overlay');if(o)o.remove();window.__xbTagMap=null;window.__xbTagStats=null;return 'ok'})()`);
7131
- return ok30({ action: "clear" });
7317
+ return ok31({ action: "clear" });
7132
7318
  }
7133
7319
  }
7134
7320
  }
@@ -7803,7 +7989,7 @@ async function guardCheck(commandName) {
7803
7989
  }
7804
7990
  }
7805
7991
  function errorResult(message) {
7806
- return { ...fail16(message), duration: 0 };
7992
+ return { ...fail17(message), duration: 0 };
7807
7993
  }
7808
7994
  function tipsToMessages(tips) {
7809
7995
  if (!tips || tips.length === 0) return [];
@@ -7992,7 +8178,7 @@ async function executeCommand(commandName, params, sessionName = "default", extr
7992
8178
  const cache = /* @__PURE__ */ new Map();
7993
8179
  const resolved = await resolveRefParams(session.page, params, command.selectorParams, cache, session.id);
7994
8180
  if (resolved.tips.length > 0) {
7995
- refTips = normalizeTips6(resolved.tips);
8181
+ refTips = normalizeTips7(resolved.tips);
7996
8182
  params = resolved.params;
7997
8183
  }
7998
8184
  }
@@ -8060,8 +8246,8 @@ async function executeCommand(commandName, params, sessionName = "default", extr
8060
8246
  }
8061
8247
  const merged = [
8062
8248
  ...raw.tips || [],
8063
- ...normalizeTips6(smartTips),
8064
- ...snapshotHint ? normalizeTips6([snapshotHint]) : [],
8249
+ ...normalizeTips7(smartTips),
8250
+ ...snapshotHint ? normalizeTips7([snapshotHint]) : [],
8065
8251
  ...refTips
8066
8252
  ];
8067
8253
  const isSuccess = raw.success !== false;
@@ -8076,7 +8262,7 @@ async function executeCommand(commandName, params, sessionName = "default", extr
8076
8262
  timestamp: start
8077
8263
  });
8078
8264
  if (isSuccess) {
8079
- return { ...ok31(raw.data, merged.length > 0 ? merged : raw.tips), duration, ...hookOutputs ? { hookOutputs } : {} };
8265
+ return { ...ok32(raw.data, merged.length > 0 ? merged : raw.tips), duration, ...hookOutputs ? { hookOutputs } : {} };
8080
8266
  }
8081
8267
  const fc = classifyFailure(raw.message);
8082
8268
  return {
@@ -8089,7 +8275,7 @@ async function executeCommand(commandName, params, sessionName = "default", extr
8089
8275
  ...hookOutputs ? { hookOutputs } : {}
8090
8276
  };
8091
8277
  }
8092
- const smartTipNormalized = normalizeTips6(smartTips);
8278
+ const smartTipNormalized = normalizeTips7(smartTips);
8093
8279
  recordArchive(session?.id, sessionName, {
8094
8280
  step: 0,
8095
8281
  command: commandName,
@@ -8099,7 +8285,7 @@ async function executeCommand(commandName, params, sessionName = "default", extr
8099
8285
  duration,
8100
8286
  timestamp: start
8101
8287
  });
8102
- return { ...ok31(raw, smartTipNormalized), duration, ...hookOutputs ? { hookOutputs } : {} };
8288
+ return { ...ok32(raw, smartTipNormalized), duration, ...hookOutputs ? { hookOutputs } : {} };
8103
8289
  } catch (err) {
8104
8290
  const end = Date.now();
8105
8291
  const duration = end - start;
@@ -8144,7 +8330,7 @@ async function executeCommand(commandName, params, sessionName = "default", extr
8144
8330
  duration,
8145
8331
  timestamp: start
8146
8332
  });
8147
- return { ...fail16(errorMessage), duration };
8333
+ return { ...fail17(errorMessage), duration };
8148
8334
  } finally {
8149
8335
  }
8150
8336
  }
@@ -8189,7 +8375,7 @@ async function executeChain(input, options) {
8189
8375
  results.push({
8190
8376
  command: cmdName,
8191
8377
  raw: cmdStr,
8192
- ...fail16(`Plugin "${cmdName}" requires a sub-command`),
8378
+ ...fail17(`Plugin "${cmdName}" requires a sub-command`),
8193
8379
  duration: 0
8194
8380
  });
8195
8381
  if (type === "and") {
@@ -8208,7 +8394,7 @@ async function executeChain(input, options) {
8208
8394
  results.push({
8209
8395
  command: cmdName,
8210
8396
  raw: cmdStr,
8211
- ...fail16(`Unknown command "${subCommand}" for plugin "${cmdName}"`),
8397
+ ...fail17(`Unknown command "${subCommand}" for plugin "${cmdName}"`),
8212
8398
  duration: 0
8213
8399
  });
8214
8400
  if (type === "and") {
@@ -8278,7 +8464,7 @@ async function executeChain(input, options) {
8278
8464
  success: false,
8279
8465
  data: data2,
8280
8466
  message: loginGuard.message,
8281
- tips: normalizeTips6(loginGuard.tips),
8467
+ tips: normalizeTips7(loginGuard.tips),
8282
8468
  duration: duration3
8283
8469
  });
8284
8470
  if (type === "and") {
@@ -8320,7 +8506,7 @@ async function executeChain(input, options) {
8320
8506
  results.push({
8321
8507
  command: `${cmdName} ${subCommand}`,
8322
8508
  raw: cmdStr,
8323
- ...ok31(data),
8509
+ ...ok32(data),
8324
8510
  duration: duration2,
8325
8511
  ...hookOutputs ? { hookOutputs } : {}
8326
8512
  });
@@ -8348,7 +8534,7 @@ async function executeChain(input, options) {
8348
8534
  results.push({
8349
8535
  command: `${cmdName} ${subCommand}`,
8350
8536
  raw: cmdStr,
8351
- ...fail16(errorMessage),
8537
+ ...fail17(errorMessage),
8352
8538
  duration: duration2
8353
8539
  });
8354
8540
  if (type === "and") {
@@ -9772,10 +9958,10 @@ function createRPCHandler() {
9772
9958
  const errors = Array.isArray(input.errors) ? input.errors : [];
9773
9959
  const eventsPlayed = typeof input.eventsPlayed === "number" ? input.eventsPlayed : 0;
9774
9960
  const totalEvents = typeof input.totalEvents === "number" ? input.totalEvents : eventsPlayed + errors.length;
9775
- const ok32 = input.ok ?? errors.length === 0;
9961
+ const ok33 = input.ok ?? errors.length === 0;
9776
9962
  return {
9777
- ok: ok32,
9778
- success: ok32,
9963
+ ok: ok33,
9964
+ success: ok33,
9779
9965
  duration: typeof input.duration === "number" ? input.duration : 0,
9780
9966
  eventsPlayed,
9781
9967
  totalEvents,