@opentiny/webmcp-cli 0.0.6 → 0.0.8

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.
@@ -3104,9 +3104,9 @@
3104
3104
  }
3105
3105
  });
3106
3106
 
3107
- // ../../node_modules/.pnpm/fast-uri@3.1.3/node_modules/fast-uri/lib/utils.js
3107
+ // ../../node_modules/.pnpm/fast-uri@3.1.5/node_modules/fast-uri/lib/utils.js
3108
3108
  var require_utils = __commonJS({
3109
- "../../node_modules/.pnpm/fast-uri@3.1.3/node_modules/fast-uri/lib/utils.js"(exports, module) {
3109
+ "../../node_modules/.pnpm/fast-uri@3.1.5/node_modules/fast-uri/lib/utils.js"(exports, module) {
3110
3110
  "use strict";
3111
3111
  var isUUID = RegExp.prototype.test.bind(/^[\da-f]{8}-[\da-f]{4}-[\da-f]{4}-[\da-f]{4}-[\da-f]{12}$/iu);
3112
3112
  var isIPv4 = RegExp.prototype.test.bind(/^(?:(?:25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d|\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d|\d)$/u);
@@ -3417,9 +3417,9 @@
3417
3417
  }
3418
3418
  });
3419
3419
 
3420
- // ../../node_modules/.pnpm/fast-uri@3.1.3/node_modules/fast-uri/lib/schemes.js
3420
+ // ../../node_modules/.pnpm/fast-uri@3.1.5/node_modules/fast-uri/lib/schemes.js
3421
3421
  var require_schemes = __commonJS({
3422
- "../../node_modules/.pnpm/fast-uri@3.1.3/node_modules/fast-uri/lib/schemes.js"(exports, module) {
3422
+ "../../node_modules/.pnpm/fast-uri@3.1.5/node_modules/fast-uri/lib/schemes.js"(exports, module) {
3423
3423
  "use strict";
3424
3424
  var { isUUID } = require_utils();
3425
3425
  var URN_REG = /([\da-z][\d\-a-z]{0,31}):((?:[\w!$'()*+,\-.:;=@]|%[\da-f]{2})+)/iu;
@@ -3627,9 +3627,9 @@
3627
3627
  }
3628
3628
  });
3629
3629
 
3630
- // ../../node_modules/.pnpm/fast-uri@3.1.3/node_modules/fast-uri/index.js
3630
+ // ../../node_modules/.pnpm/fast-uri@3.1.5/node_modules/fast-uri/index.js
3631
3631
  var require_fast_uri = __commonJS({
3632
- "../../node_modules/.pnpm/fast-uri@3.1.3/node_modules/fast-uri/index.js"(exports, module) {
3632
+ "../../node_modules/.pnpm/fast-uri@3.1.5/node_modules/fast-uri/index.js"(exports, module) {
3633
3633
  "use strict";
3634
3634
  var { normalizeIPv6, removeDotSegments, recomposeAuthority, normalizePercentEncoding, normalizePathEncoding, escapePreservingEscapes, reescapeHostDelimiters, isIPv4, nonSimpleDomain } = require_utils();
3635
3635
  var { SCHEMES, getSchemeHandler } = require_schemes();
@@ -3645,7 +3645,12 @@
3645
3645
  }
3646
3646
  function resolve(baseURI, relativeURI, options) {
3647
3647
  const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
3648
- const resolved = resolveComponent(parse2(baseURI, schemelessOptions), parse2(relativeURI, schemelessOptions), schemelessOptions, true);
3648
+ const { parsed: baseParsed, malformedAuthorityOrPort: baseMalformed } = parseWithStatus(baseURI, schemelessOptions);
3649
+ const { parsed: relativeParsed, malformedAuthorityOrPort: relativeMalformed } = parseWithStatus(relativeURI, schemelessOptions);
3650
+ if (baseMalformed || relativeMalformed) {
3651
+ throw new Error(baseParsed.error || relativeParsed.error || "URI is malformed.");
3652
+ }
3653
+ const resolved = resolveComponent(baseParsed, relativeParsed, schemelessOptions, true);
3649
3654
  schemelessOptions.skipEscape = true;
3650
3655
  return serialize(resolved, schemelessOptions);
3651
3656
  }
@@ -3770,6 +3775,8 @@
3770
3775
  return uriTokens.join("");
3771
3776
  }
3772
3777
  var URI_PARSE = /^(?:([^#/:?]+):)?(?:\/\/((?:([^#/?@]*)@)?(\[[^#/?\]]+\]|[^#/:?]*)(?::(\d*))?))?([^#?]*)(?:\?([^#]*))?(?:#((?:.|[\n\r])*))?/u;
3778
+ var AUTHORITY_PREFIX = /^(?:[^#/:?]+:)?\/\/([^/?#]*)/;
3779
+ var AUTHORITY_INTRODUCER_REGION = /^(?:[^#/:?]+:)?([/\\\t\n\r]*)/;
3773
3780
  function getParseError(parsed, matches2) {
3774
3781
  if (matches2[2] !== void 0 && parsed.path && parsed.path[0] !== "/") {
3775
3782
  return 'URI path must start with "/" when authority is present.';
@@ -3799,6 +3806,25 @@
3799
3806
  uri2 = "//" + uri2;
3800
3807
  }
3801
3808
  }
3809
+ const authorityMatch = uri2.match(AUTHORITY_PREFIX);
3810
+ if (authorityMatch !== null && authorityMatch[1].indexOf("\\") !== -1) {
3811
+ parsed.error = "URI authority must not contain a literal backslash.";
3812
+ malformedAuthorityOrPort = true;
3813
+ }
3814
+ const introducerMatch = uri2.match(AUTHORITY_INTRODUCER_REGION);
3815
+ if (introducerMatch !== null) {
3816
+ const region = introducerMatch[1];
3817
+ const normalizedRegion = region.replace(/[\t\n\r]/g, "");
3818
+ if (normalizedRegion.length >= 2) {
3819
+ if (normalizedRegion.slice(0, 2) !== "//") {
3820
+ parsed.error = parsed.error || "URI authority must not contain a literal backslash.";
3821
+ malformedAuthorityOrPort = true;
3822
+ } else if (region.length !== normalizedRegion.length) {
3823
+ parsed.error = parsed.error || "URI authority introducer must not contain whitespace.";
3824
+ malformedAuthorityOrPort = true;
3825
+ }
3826
+ }
3827
+ }
3802
3828
  const matches2 = uri2.match(URI_PARSE);
3803
3829
  if (matches2) {
3804
3830
  parsed.scheme = matches2[1];
@@ -9569,7 +9595,7 @@ gl_Position = vec4(aPosition, 0.0, 1.0);
9569
9595
  }
9570
9596
  });
9571
9597
 
9572
- // ../../node_modules/.pnpm/@page-agent+page-controller@1.12.1/node_modules/@page-agent/page-controller/dist/lib/SimulatorMask-BHVXyogh.js
9598
+ // ../../node_modules/.pnpm/@page-agent+page-controller@1.12.2/node_modules/@page-agent/page-controller/dist/lib/SimulatorMask-BHVXyogh.js
9573
9599
  var SimulatorMask_BHVXyogh_exports = {};
9574
9600
  __export(SimulatorMask_BHVXyogh_exports, {
9575
9601
  SimulatorMask: () => SimulatorMask
@@ -9673,7 +9699,7 @@ gl_Position = vec4(aPosition, 0.0, 1.0);
9673
9699
  }
9674
9700
  var SimulatorMask_module_default, cursor_module_default, SimulatorMask;
9675
9701
  var init_SimulatorMask_BHVXyogh = __esm({
9676
- "../../node_modules/.pnpm/@page-agent+page-controller@1.12.1/node_modules/@page-agent/page-controller/dist/lib/SimulatorMask-BHVXyogh.js"() {
9702
+ "../../node_modules/.pnpm/@page-agent+page-controller@1.12.2/node_modules/@page-agent/page-controller/dist/lib/SimulatorMask-BHVXyogh.js"() {
9677
9703
  init_Motion();
9678
9704
  (function() {
9679
9705
  try {
@@ -19606,7 +19632,7 @@ Known schemas:
19606
19632
  // ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v4/classic/external.js
19607
19633
  config(en_default2());
19608
19634
 
19609
- // ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.25.3_@cfworker+json-schema@4.1.1_hono@4.12.30_zod@3.25.76/node_modules/@modelcontextprotocol/sdk/dist/esm/types.js
19635
+ // ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.25.3_@cfworker+json-schema@4.1.1_hono@4.13.0_zod@3.25.76/node_modules/@modelcontextprotocol/sdk/dist/esm/types.js
19610
19636
  var RELATED_TASK_META_KEY = "io.modelcontextprotocol/related-task";
19611
19637
  var JSONRPC_VERSION = "2.0";
19612
19638
  var AssertObjectSchema = custom2((v) => v !== null && (typeof v === "object" || typeof v === "function"));
@@ -22359,14 +22385,14 @@ Known schemas:
22359
22385
  return combined;
22360
22386
  };
22361
22387
 
22362
- // ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.25.3_@cfworker+json-schema@4.1.1_hono@4.12.30_zod@3.25.76/node_modules/@modelcontextprotocol/sdk/dist/esm/validation/ajv-provider.js
22388
+ // ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.25.3_@cfworker+json-schema@4.1.1_hono@4.13.0_zod@3.25.76/node_modules/@modelcontextprotocol/sdk/dist/esm/validation/ajv-provider.js
22363
22389
  var import_ajv_formats = __toESM(require_dist(), 1);
22364
22390
 
22365
22391
  // ../../node_modules/.pnpm/pkce-challenge@5.0.1/node_modules/pkce-challenge/dist/index.browser.js
22366
22392
  var crypto2;
22367
22393
  crypto2 = globalThis.crypto;
22368
22394
 
22369
- // ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.25.3_@cfworker+json-schema@4.1.1_hono@4.12.30_zod@3.25.76/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/auth.js
22395
+ // ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.25.3_@cfworker+json-schema@4.1.1_hono@4.13.0_zod@3.25.76/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/auth.js
22370
22396
  var SafeUrlSchema = url().superRefine((val, ctx) => {
22371
22397
  if (!URL.canParse(val)) {
22372
22398
  ctx.addIssue({
@@ -22510,7 +22536,7 @@ Known schemas:
22510
22536
  token_type_hint: string2().optional()
22511
22537
  }).strip();
22512
22538
 
22513
- // ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.25.3_@cfworker+json-schema@4.1.1_hono@4.12.30_zod@3.25.76/node_modules/@modelcontextprotocol/sdk/dist/esm/server/auth/errors.js
22539
+ // ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.25.3_@cfworker+json-schema@4.1.1_hono@4.13.0_zod@3.25.76/node_modules/@modelcontextprotocol/sdk/dist/esm/server/auth/errors.js
22514
22540
  var OAuthError = class extends Error {
22515
22541
  constructor(message, errorUri) {
22516
22542
  super(message);
@@ -22605,7 +22631,7 @@ Known schemas:
22605
22631
  [InvalidTargetError.errorCode]: InvalidTargetError
22606
22632
  };
22607
22633
 
22608
- // ../../node_modules/.pnpm/@opentiny+next@0.3.2_@cfworker+json-schema@4.1.1_hono@4.12.30_zod@3.25.76/node_modules/@opentiny/next/index.js
22634
+ // ../../node_modules/.pnpm/@opentiny+next@0.3.2_@cfworker+json-schema@4.1.1_hono@4.13.0_zod@3.25.76/node_modules/@opentiny/next/index.js
22609
22635
  var _0x4f2826 = _0xad7a;
22610
22636
  (function(_0x5153c5, _0x3abbea) {
22611
22637
  const _0x5f186f = _0xad7a, _0x3f8155 = _0xad7a, _0x5ad68c = _0x5153c5();
@@ -22929,7 +22955,7 @@ Known schemas:
22929
22955
  }, _0x275e(_0x25fced, _0x3ae797);
22930
22956
  }
22931
22957
 
22932
- // ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.25.3_@cfworker+json-schema@4.1.1_hono@4.12.30_zod@3.25.76/node_modules/@modelcontextprotocol/sdk/dist/esm/server/completable.js
22958
+ // ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.25.3_@cfworker+json-schema@4.1.1_hono@4.13.0_zod@3.25.76/node_modules/@modelcontextprotocol/sdk/dist/esm/server/completable.js
22933
22959
  var COMPLETABLE_SYMBOL = Symbol.for("mcp.completable");
22934
22960
  var McpZodTypeKind;
22935
22961
  (function(McpZodTypeKind2) {
@@ -23005,476 +23031,6 @@ Known schemas:
23005
23031
  document.head.appendChild(style);
23006
23032
  })();
23007
23033
 
23008
- // ../next-sdk/utils/uuid.ts
23009
- var randomUUID2 = () => {
23010
- if (typeof crypto !== "undefined" && crypto.randomUUID) {
23011
- return crypto.randomUUID();
23012
- }
23013
- return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
23014
- const r = Math.random() * 16 | 0;
23015
- const v = c === "x" ? r : r & 3 | 8;
23016
- return v.toString(16);
23017
- });
23018
- };
23019
-
23020
- // ../next-sdk/utils/env.ts
23021
- var isBrowser = () => {
23022
- return typeof window !== "undefined" && typeof navigator !== "undefined";
23023
- };
23024
- var isDomAvailable = () => {
23025
- return isBrowser() && typeof document !== "undefined";
23026
- };
23027
-
23028
- // ../next-sdk/page-tools/effects.ts
23029
- var overlayElement = null;
23030
- var labelElement = null;
23031
- var styleElement = null;
23032
- var activeCount = 0;
23033
- var BODY_GLOW_CLASS = "next-sdk-tool-body-glow";
23034
- function ensureDomReady() {
23035
- return isDomAvailable();
23036
- }
23037
- function ensureStyleElement() {
23038
- if (!ensureDomReady()) return;
23039
- if (styleElement) return;
23040
- const style = document.createElement("style");
23041
- style.textContent = `
23042
- .${BODY_GLOW_CLASS} {
23043
- position: relative;
23044
- }
23045
-
23046
- .next-sdk-tool-overlay {
23047
- position: fixed;
23048
- inset: 0;
23049
- z-index: 999999;
23050
- pointer-events: none;
23051
- display: flex;
23052
- align-items: flex-end;
23053
- justify-content: flex-start;
23054
- padding: 0 0 18px 18px;
23055
- background: transparent;
23056
- animation: next-sdk-overlay-fade-in 260ms ease-out;
23057
- }
23058
-
23059
- .next-sdk-tool-overlay--exit {
23060
- animation: next-sdk-overlay-fade-out 220ms ease-in forwards;
23061
- }
23062
-
23063
- .next-sdk-tool-overlay__glow-ring {
23064
- display: none;
23065
- }
23066
-
23067
- .next-sdk-tool-overlay__panel {
23068
- position: relative;
23069
- min-width: min(320px, 78vw);
23070
- max-width: min(420px, 82vw);
23071
- padding: 10px 14px;
23072
- border-radius: 999px;
23073
- background:
23074
- linear-gradient(135deg, rgba(15, 23, 42, 0.9), rgba(17, 24, 39, 0.9)),
23075
- radial-gradient(circle at top left, rgba(96, 165, 250, 0.25), transparent 55%),
23076
- radial-gradient(circle at bottom right, rgba(45, 212, 191, 0.22), transparent 60%);
23077
- box-shadow:
23078
- 0 12px 28px rgba(15, 23, 42, 0.78),
23079
- 0 0 0 1px rgba(148, 163, 184, 0.26);
23080
- display: flex;
23081
- align-items: center;
23082
- gap: 10px;
23083
- pointer-events: none;
23084
- transform-origin: center;
23085
- animation: next-sdk-panel-pop-in 260ms cubic-bezier(0.18, 0.89, 0.32, 1.28);
23086
- color: #e5e7eb;
23087
- font-family: system-ui, -apple-system, BlinkMacSystemFont, "SF Pro Text", sans-serif;
23088
- }
23089
-
23090
- .next-sdk-tool-overlay__indicator {
23091
- width: 26px;
23092
- height: 26px;
23093
- border-radius: 999px;
23094
- background: radial-gradient(circle at 30% 10%, #f9fafb, #93c5fd);
23095
- box-shadow:
23096
- 0 0 0 1px rgba(191, 219, 254, 0.6),
23097
- 0 8px 18px rgba(37, 99, 235, 0.8),
23098
- 0 0 28px rgba(56, 189, 248, 0.9);
23099
- position: relative;
23100
- flex-shrink: 0;
23101
- display: flex;
23102
- align-items: center;
23103
- justify-content: center;
23104
- overflow: hidden;
23105
- }
23106
-
23107
- .next-sdk-tool-overlay__indicator-orbit {
23108
- position: absolute;
23109
- inset: 2px;
23110
- border-radius: inherit;
23111
- border: 1px solid rgba(248, 250, 252, 0.6);
23112
- box-sizing: border-box;
23113
- opacity: 0.9;
23114
- }
23115
-
23116
- .next-sdk-tool-overlay__indicator-orbit::before {
23117
- content: '';
23118
- position: absolute;
23119
- width: 6px;
23120
- height: 6px;
23121
- border-radius: 999px;
23122
- background: #f9fafb;
23123
- box-shadow:
23124
- 0 0 12px rgba(248, 250, 252, 0.9),
23125
- 0 0 24px rgba(250, 249, 246, 0.9);
23126
- top: 0;
23127
- left: 50%;
23128
- transform: translate(-50%, -50%);
23129
- transform-origin: 50% 18px;
23130
- animation: next-sdk-indicator-orbit 1.4s linear infinite;
23131
- }
23132
-
23133
- .next-sdk-tool-overlay__indicator-core {
23134
- width: 14px;
23135
- height: 14px;
23136
- border-radius: inherit;
23137
- background: radial-gradient(circle at 30% 20%, #f9fafb, #bfdbfe);
23138
- box-shadow:
23139
- 0 0 12px rgba(248, 250, 252, 0.9),
23140
- 0 0 32px rgba(191, 219, 254, 0.8);
23141
- opacity: 0.96;
23142
- }
23143
-
23144
- .next-sdk-tool-overlay__content {
23145
- display: flex;
23146
- flex-direction: column;
23147
- gap: 1px;
23148
- min-width: 0;
23149
- }
23150
-
23151
- .next-sdk-tool-overlay__title {
23152
- font-size: 11px;
23153
- letter-spacing: 0.08em;
23154
- text-transform: uppercase;
23155
- color: rgba(156, 163, 175, 0.96);
23156
- display: flex;
23157
- align-items: center;
23158
- gap: 6px;
23159
- }
23160
-
23161
- .next-sdk-tool-overlay__title-dot {
23162
- width: 6px;
23163
- height: 6px;
23164
- border-radius: 999px;
23165
- background: #22c55e;
23166
- box-shadow:
23167
- 0 0 8px rgba(34, 197, 94, 0.9),
23168
- 0 0 14px rgba(22, 163, 74, 0.9);
23169
- }
23170
-
23171
- .next-sdk-tool-overlay__label {
23172
- font-size: 12px;
23173
- font-weight: 500;
23174
- color: #e5e7eb;
23175
- white-space: nowrap;
23176
- text-overflow: ellipsis;
23177
- overflow: hidden;
23178
- }
23179
-
23180
- @keyframes next-sdk-overlay-fade-in {
23181
- from { opacity: 0; }
23182
- to { opacity: 1; }
23183
- }
23184
-
23185
- @keyframes next-sdk-overlay-fade-out {
23186
- from { opacity: 1; }
23187
- to { opacity: 0; }
23188
- }
23189
-
23190
- @keyframes next-sdk-indicator-orbit {
23191
- from {
23192
- transform: translate(-50%, -50%) rotate(0deg) translateY(0);
23193
- }
23194
- to {
23195
- transform: translate(-50%, -50%) rotate(360deg) translateY(0);
23196
- }
23197
- }
23198
-
23199
- @keyframes next-sdk-panel-pop-in {
23200
- 0% {
23201
- opacity: 0;
23202
- transform: scale(0.92) translateY(10px);
23203
- }
23204
- 100% {
23205
- opacity: 1;
23206
- transform: scale(1) translateY(0);
23207
- }
23208
- }
23209
- `;
23210
- document.head.appendChild(style);
23211
- styleElement = style;
23212
- }
23213
- function ensureOverlayElement() {
23214
- if (!ensureDomReady()) return;
23215
- if (overlayElement) return;
23216
- ensureStyleElement();
23217
- const overlay = document.createElement("div");
23218
- overlay.className = "next-sdk-tool-overlay";
23219
- const glowRing = document.createElement("div");
23220
- glowRing.className = "next-sdk-tool-overlay__glow-ring";
23221
- const panel = document.createElement("div");
23222
- panel.className = "next-sdk-tool-overlay__panel";
23223
- const indicator = document.createElement("div");
23224
- indicator.className = "next-sdk-tool-overlay__indicator";
23225
- const indicatorOrbit = document.createElement("div");
23226
- indicatorOrbit.className = "next-sdk-tool-overlay__indicator-orbit";
23227
- const indicatorCore = document.createElement("div");
23228
- indicatorCore.className = "next-sdk-tool-overlay__indicator-core";
23229
- const content = document.createElement("div");
23230
- content.className = "next-sdk-tool-overlay__content";
23231
- const titleRow = document.createElement("div");
23232
- titleRow.className = "next-sdk-tool-overlay__title";
23233
- titleRow.textContent = "AI \u6B63\u5728\u8C03\u7528\u9875\u9762\u5DE5\u5177";
23234
- const titleDot = document.createElement("span");
23235
- titleDot.className = "next-sdk-tool-overlay__title-dot";
23236
- const label = document.createElement("div");
23237
- label.className = "next-sdk-tool-overlay__label";
23238
- titleRow.prepend(titleDot);
23239
- content.appendChild(titleRow);
23240
- content.appendChild(label);
23241
- indicator.appendChild(indicatorOrbit);
23242
- indicator.appendChild(indicatorCore);
23243
- panel.appendChild(indicator);
23244
- panel.appendChild(content);
23245
- overlay.appendChild(glowRing);
23246
- overlay.appendChild(panel);
23247
- document.body.appendChild(overlay);
23248
- overlayElement = overlay;
23249
- labelElement = label;
23250
- }
23251
- function updateOverlay(config2) {
23252
- if (!ensureDomReady()) return;
23253
- ensureOverlayElement();
23254
- if (!overlayElement || !labelElement) return;
23255
- overlayElement.classList.remove("next-sdk-tool-overlay--exit");
23256
- labelElement.textContent = config2.label;
23257
- }
23258
- function removeOverlayWithAnimation() {
23259
- if (!overlayElement) return;
23260
- overlayElement.classList.add("next-sdk-tool-overlay--exit");
23261
- const localOverlay = overlayElement;
23262
- let handled = false;
23263
- let timerId;
23264
- const handle = () => {
23265
- if (handled) return;
23266
- handled = true;
23267
- if (timerId !== void 0) {
23268
- clearTimeout(timerId);
23269
- timerId = void 0;
23270
- }
23271
- if (localOverlay.parentNode) {
23272
- localOverlay.parentNode.removeChild(localOverlay);
23273
- }
23274
- if (overlayElement === localOverlay) {
23275
- overlayElement = null;
23276
- labelElement = null;
23277
- }
23278
- localOverlay.removeEventListener("animationend", handle);
23279
- };
23280
- localOverlay.addEventListener("animationend", handle);
23281
- timerId = setTimeout(handle, 500);
23282
- }
23283
- function showToolInvokeEffect(config2) {
23284
- if (!ensureDomReady()) return;
23285
- activeCount += 1;
23286
- updateOverlay(config2);
23287
- }
23288
- function hideToolInvokeEffect() {
23289
- if (!ensureDomReady() || activeCount <= 0) return;
23290
- activeCount -= 1;
23291
- if (activeCount === 0) {
23292
- removeOverlayWithAnimation();
23293
- }
23294
- }
23295
- function resolveRuntimeEffectConfig(toolName, toolTitle, value) {
23296
- if (!value) return void 0;
23297
- const baseLabel = toolTitle || toolName;
23298
- if (typeof value === "boolean") {
23299
- return value ? { label: baseLabel } : void 0;
23300
- }
23301
- return {
23302
- label: value.label || baseLabel
23303
- };
23304
- }
23305
-
23306
- // ../next-sdk/page-tools/bridge.ts
23307
- var MSG_TOOL_CALL = "next-sdk:tool-call";
23308
- var MSG_TOOL_RESPONSE = "next-sdk:tool-response";
23309
- var MSG_TOOL_REGISTERED = "next-sdk:tool-registered";
23310
- var MSG_TOOL_UNREGISTERED = "next-sdk:tool-unregistered";
23311
- var MSG_REMOTER_READY = "next-sdk:remoter-ready";
23312
- var activePages = /* @__PURE__ */ new Map();
23313
- var normalizeRoute = (value) => value.replace(/\/+$/, "") || "/";
23314
- var broadcastTargets = /* @__PURE__ */ new Set();
23315
- function initBroadcastTargets() {
23316
- if (isBrowser()) {
23317
- broadcastTargets.add({ win: window, origin: window.location.origin || "*" });
23318
- }
23319
- }
23320
- initBroadcastTargets();
23321
- function broadcastToolChange(type) {
23322
- if (!isBrowser()) return;
23323
- const msg = { type };
23324
- broadcastTargets.forEach(({ win, origin }) => {
23325
- try {
23326
- win.postMessage(msg, origin);
23327
- } catch {
23328
- }
23329
- });
23330
- }
23331
- function setupIframeRemoterBridge() {
23332
- if (!isBrowser()) return;
23333
- window.addEventListener("message", (event) => {
23334
- if (event.data?.type !== MSG_REMOTER_READY || !event.source) return;
23335
- if (event.origin !== window.location.origin) return;
23336
- const target = event.source;
23337
- broadcastTargets.add({ win: target, origin: event.origin || "*" });
23338
- });
23339
- }
23340
- setupIframeRemoterBridge();
23341
- function isToolReadyOnRoute(route, toolName) {
23342
- const toolNames = activePages.get(route);
23343
- return !!toolNames && toolNames.has(toolName);
23344
- }
23345
- var _navigator = null;
23346
- function buildPageHandler(name, route, timeout = 3e4, effectConfig) {
23347
- return (input) => {
23348
- const callId = randomUUID2();
23349
- return new Promise((resolve, reject) => {
23350
- let timer;
23351
- let readyHandler;
23352
- const cleanup = () => {
23353
- clearTimeout(timer);
23354
- window.removeEventListener("message", responseHandler);
23355
- if (readyHandler) {
23356
- window.removeEventListener("message", readyHandler);
23357
- }
23358
- if (effectConfig) {
23359
- hideToolInvokeEffect();
23360
- }
23361
- };
23362
- timer = setTimeout(() => {
23363
- cleanup();
23364
- reject(new Error(`\u5DE5\u5177 [${name}] \u8C03\u7528\u8D85\u65F6 (${timeout}ms)\uFF0C\u8BF7\u68C0\u67E5\u76EE\u6807\u9875\u9762\u662F\u5426\u6B63\u786E\u8C03\u7528\u4E86 registerPageTool`));
23365
- }, timeout);
23366
- const responseHandler = (event) => {
23367
- if (event.source === window && event.data?.type === MSG_TOOL_RESPONSE && event.data.callId === callId) {
23368
- cleanup();
23369
- event.data.error ? reject(new Error(event.data.error)) : resolve(event.data.result);
23370
- }
23371
- };
23372
- window.addEventListener("message", responseHandler);
23373
- const sendCall = () => {
23374
- window.postMessage({ type: MSG_TOOL_CALL, callId, toolName: name, route, input }, window.location.origin || "*");
23375
- };
23376
- let callSent = false;
23377
- const sendCallOnce = () => {
23378
- if (callSent) return;
23379
- callSent = true;
23380
- sendCall();
23381
- };
23382
- const run = async () => {
23383
- try {
23384
- if (effectConfig) {
23385
- showToolInvokeEffect(effectConfig);
23386
- }
23387
- if (isToolReadyOnRoute(route, name)) {
23388
- sendCallOnce();
23389
- return;
23390
- }
23391
- readyHandler = (event) => {
23392
- if (event.source !== window || event.data?.type !== MSG_TOOL_REGISTERED) return;
23393
- window.removeEventListener("message", readyHandler);
23394
- sendCallOnce();
23395
- };
23396
- window.addEventListener("message", readyHandler);
23397
- if (_navigator) {
23398
- const isReady = await _navigator(route);
23399
- if (isReady === true) {
23400
- if (readyHandler) {
23401
- window.removeEventListener("message", readyHandler);
23402
- }
23403
- sendCallOnce();
23404
- return;
23405
- }
23406
- }
23407
- if (isToolReadyOnRoute(route, name)) {
23408
- window.removeEventListener("message", readyHandler);
23409
- sendCallOnce();
23410
- }
23411
- } catch (err) {
23412
- cleanup();
23413
- reject(err instanceof Error ? err : new Error(String(err)));
23414
- }
23415
- };
23416
- void run();
23417
- });
23418
- };
23419
- }
23420
- var _registeredTools = /* @__PURE__ */ new Map();
23421
- function setupModelContextBridge() {
23422
- if (typeof document === "undefined") return;
23423
- const doc = document;
23424
- const nativeCtx = doc.modelContext;
23425
- if (!nativeCtx || nativeCtx.__isNextSdkBridgeSetup) return;
23426
- if (isBrowser()) {
23427
- ;
23428
- window.__nextSdkRegisteredTools = () => Array.from(_registeredTools.values());
23429
- }
23430
- const originalRegisterTool = nativeCtx.registerTool?.bind(nativeCtx);
23431
- const originalUnregisterTool = nativeCtx.unregisterTool?.bind(nativeCtx);
23432
- if (typeof originalRegisterTool === "function") {
23433
- nativeCtx.registerTool = (config2, options) => {
23434
- const name = config2.name;
23435
- const toolConfig = { ...config2 };
23436
- if (options?.signal) {
23437
- options.signal.addEventListener("abort", () => {
23438
- _registeredTools.delete(name);
23439
- broadcastToolChange(MSG_TOOL_UNREGISTERED);
23440
- });
23441
- }
23442
- const routeConfig = toolConfig.routeConfig && typeof toolConfig.routeConfig === "object" && "route" in toolConfig.routeConfig ? toolConfig.routeConfig : null;
23443
- if (routeConfig) {
23444
- const normalizedRoute = normalizeRoute(routeConfig.route);
23445
- const effectConfig = resolveRuntimeEffectConfig(name, toolConfig.title, routeConfig.invokeEffect);
23446
- const pageHandler = buildPageHandler(name, normalizedRoute, routeConfig.timeout, effectConfig);
23447
- toolConfig.execute = pageHandler;
23448
- delete toolConfig.routeConfig;
23449
- }
23450
- _registeredTools.set(name, {
23451
- name,
23452
- title: config2.title,
23453
- description: config2.description,
23454
- inputSchema: config2.inputSchema
23455
- });
23456
- try {
23457
- originalRegisterTool(toolConfig, options);
23458
- broadcastToolChange(MSG_TOOL_REGISTERED);
23459
- } catch (err) {
23460
- _registeredTools.delete(name);
23461
- }
23462
- };
23463
- }
23464
- nativeCtx.unregisterTool = (name) => {
23465
- try {
23466
- if (typeof originalUnregisterTool === "function") {
23467
- originalUnregisterTool(name);
23468
- }
23469
- } catch (err) {
23470
- } finally {
23471
- _registeredTools.delete(name);
23472
- broadcastToolChange(MSG_TOOL_UNREGISTERED);
23473
- }
23474
- };
23475
- nativeCtx.__isNextSdkBridgeSetup = true;
23476
- }
23477
-
23478
23034
  // ../next-sdk/skills/index.ts
23479
23035
  var SKILL_INPUT_SCHEMA = external_exports.object({
23480
23036
  skillName: external_exports.string().optional().describe(
@@ -23486,6 +23042,11 @@ Known schemas:
23486
23042
  )
23487
23043
  });
23488
23044
 
23045
+ // ../next-sdk/utils/env.ts
23046
+ var isBrowser = () => {
23047
+ return typeof window !== "undefined" && typeof navigator !== "undefined";
23048
+ };
23049
+
23489
23050
  // ../next-sdk/page-tools/initialize-builtin-WebMCP.ts
23490
23051
  var initialized = false;
23491
23052
  var initializeBuiltinWebMCP = () => {
@@ -23493,18 +23054,17 @@ Known schemas:
23493
23054
  try {
23494
23055
  if (initialized) return;
23495
23056
  initializeWebMCPPolyfill();
23496
- setupModelContextBridge();
23497
23057
  initialized = true;
23498
23058
  } catch (err) {
23499
- console.warn("[next-sdk] \u81EA\u52A8\u6CE8\u5165 modelContext polyfill \u548C\u6865\u63A5\u540C\u6B65\u5931\u8D25:", err);
23059
+ console.warn("[next-sdk] \u81EA\u52A8\u6CE8\u5165 modelContext polyfill \u5931\u8D25:", err);
23500
23060
  }
23501
23061
  }
23502
23062
  };
23503
23063
 
23504
23064
  // query-loader:/home/runner/work/webmcp-sdk/webmcp-sdk/packages/next-sdk/page-tools/page-agent-prompt.md
23505
- var page_agent_prompt_default = '## \u89D2\u8272\n\n\u4F60\u662F\u6D4F\u89C8\u5668\u9875\u9762\u7684\u64CD\u4F5C\u5DE5\u5177\uFF0C\u4F60\u62E5\u6709\u8BC6\u522B\u7F51\u9875\u5185\u5BB9\uFF0C\u70B9\u51FB\uFF0C\u586B\u5199\uFF0C\u9009\u62E9\u4E0B\u62C9\u6846\u548C\u6EDA\u52A8\u9875\u9762\u7B49\u529F\u80FD\u3002\n\n\u5728\u6267\u884C\u9875\u9762\u64CD\u4F5C\u4E4B\u524D\uFF0C\u4F60\u5FC5\u987B\u5148\u8C03\u7528`browserState`\u5DE5\u5177\u4E00\u6B21\uFF0C\u6839\u636E\u6700\u65B0\u7684\u7F51\u9875\u72B6\u6001\uFF0C\u518D\u8C03\u7528\u64CD\u4F5C\u52A8\u4F5C\uFF0C\u6BD4\u5982 \'click\',\'fill\',\'select\' \u7B49\u52A8\u4F5C\u3002\n\n<intro>\n\u4F60\u64C5\u957F\u4EE5\u4E0B\u4EFB\u52A1\uFF1A\n1. \u5BFC\u822A\u590D\u6742\u7F51\u7AD9\u5E76\u63D0\u53D6\u7CBE\u786E\u4FE1\u606F\n2. \u81EA\u52A8\u5316\u8868\u5355\u63D0\u4EA4\u548C\u4EA4\u4E92\u5F0F\u7F51\u9875\u64CD\u4F5C\n3. \u6536\u96C6\u548C\u4FDD\u5B58\u4FE1\u606F\n4. \u5728\u4EE3\u7406\u5FAA\u73AF\u4E2D\u6709\u6548\u8FD0\u884C\n5. \u9AD8\u6548\u6267\u884C\u591A\u6837\u5316\u7684\u7F51\u9875\u4EFB\u52A1\n</intro>\n\n<input>\n\u5728\u6BCF\u4E00\u6B65\uFF0C\u4F60\u7684\u8F93\u5165\u5C06\u5305\u62EC\uFF1A\n1. <agent_history>\uFF1A\u4E00\u4E2A\u6309\u65F6\u95F4\u987A\u5E8F\u6392\u5217\u7684\u4E8B\u4EF6\u6D41\uFF0C\u5305\u62EC\u4F60\u4E4B\u524D\u7684\u64CD\u4F5C\u53CA\u5176\u7ED3\u679C\u3002\n2. <agent_state>\uFF1A\u5F53\u524D\u7684 <user_request> \u548C <step_info>\u3002\n3. <browser_state>\uFF1A\u5F53\u524D URL\u3001\u9875\u9762\u6807\u9898\u3001\u53EF\u4EA4\u4E92\u5143\u7D20\u603B\u6570\u4EE5\u53CA\u8BED\u4E49\u5316 YAML \u6811\u3002\n</input>\n\n<browser_state>\n\n\u6D4F\u89C8\u5668\u72B6\u6001\u5305\u542B\u4EE5\u4E0B\u5185\u5BB9\uFF1A\n\n- url: \u5F53\u524D\u67E5\u770B\u9875\u9762\u7684 URL\u3002\n- title: \u5F53\u524D\u67E5\u770B\u9875\u9762\u7684\u6807\u9898\u3002\n- \u53EF\u4EA4\u4E92\u5143\u7D20\u603B\u6570\uFF1A\u5E26\u6709 `#N` \u6807\u8BB0\u7684\u5143\u7D20\u6570\u91CF\u3002\n- YAML \u6811\uFF1A\u9875\u9762\u7684\u8BED\u4E49\u5316\u7ED3\u6784\uFF0C\u683C\u5F0F\u5982\u4E0B\uFF1A\n\n```yaml\n- region:\n - main:\n - button #9 [cursor=pointer] "\u4EA7\u54C1\u6587\u6863"\n - button #47 [selected] [cursor=pointer] "40\u5143/\u6708 2\u6838CPU 2GB\u5185\u5B58"\n - radio #53 [checked] [cursor=pointer] "\u81EA\u52A8\u751F\u6210\u5BC6\u7801"\n - button #74 [cursor=pointer] "\u7ACB\u5373\u8D2D\u4E70"\n - generic #6 [cf-uba="serviceList..Flexus\u4E91\u670D\u52A1"] "Flexus\u4E91\u670D\u52A1"\n```\n\n\u8282\u70B9\u683C\u5F0F\u8BF4\u660E\uFF1A\n- `- role #N [token1] [token2] "accessible name"`\n- `role`\uFF1AARIA \u8BED\u4E49\u89D2\u8272\uFF08\u5982 button/link/radio/heading/listitem/generic \u7B49\uFF09\n- `#N`\uFF1A\u53EF\u4EA4\u4E92\u5143\u7D20\u7684\u552F\u4E00\u64CD\u4F5C\u7D22\u5F15\uFF0C**\u53EA\u6709\u5E26 `#N` \u7684\u8282\u70B9\u624D\u80FD\u88AB\u64CD\u4F5C**\uFF0C\u64CD\u4F5C\u65F6\u5C06 N \u4F5C\u4E3A `index` \u53C2\u6570\u4F20\u5165\n- `[token]`\uFF1A\u53EF\u9009 token\uFF0C\u5305\u62EC\u72B6\u6001\u6807\u8BB0\uFF08\u5982 `[checked]` `[selected]` `[disabled]` `[cursor=pointer]`\uFF09\u548C\u5B9A\u5236\u5C5E\u6027\uFF08\u5982 `[cf-uba="..."]`\uFF09\n- `"accessible name"`\uFF1A\u5143\u7D20\u7684\u8BED\u4E49\u5316\u540D\u79F0\uFF0C**\u7528\u53CC\u5F15\u53F7\u5305\u88F9**\uFF08\u901A\u8FC7 aria-label/aria-labelledby/innerText \u7B49\u8BA1\u7B97\u5F97\u51FA\uFF09\uFF1B\u65E0\u540D\u79F0\u7684\u8282\u70B9\u6B64\u5B57\u6BB5\u7701\u7565\n- \u7F29\u8FDB\u8868\u793A\u7236\u5B50\u5173\u7CFB\n\n</browser_state>\n\n<responseMode>\n\n`page-agent-tool` \u652F\u6301 `responseMode` \u53C2\u6570\uFF0C\u7528\u4E8E\u63A7\u5236\u64CD\u4F5C\u540E\u8FD4\u56DE\u7684\u9875\u9762\u72B6\u6001\u5F62\u5F0F\uFF1A\n\n- **`diff`**\uFF08\u9ED8\u8BA4\uFF09\uFF1A\u4EC5\u8FD4\u56DE\u81EA\u4E0A\u4E00\u6B21\u72B6\u6001\u4EE5\u6765\u7684\u589E\u91CF DOM \u5DEE\u5F02\uFF0C\u6781\u5927\u8282\u7701 Token\u3002\n- **`full`**\uFF1A\u8FD4\u56DE\u5F53\u524D\u89C6\u53E3\u4E2D\u5B8C\u6574\u7684\u8BED\u4E49\u5316 ARIA YAML \u6811\u3002\n- **`both`**\uFF1A\u540C\u65F6\u8FD4\u56DE\u5168\u91CF\u6811\u548C\u589E\u91CF\u5DEE\u5F02\u3002\n\n\u6267\u884C `click`\u3001`fill`\u3001`select`\u3001`scroll` \u64CD\u4F5C\u540E\uFF0C\u5DE5\u5177\u9ED8\u8BA4\u81EA\u52A8\u4EE5 `diff` \u6A21\u5F0F\u8FD4\u56DE\u6700\u65B0\u9875\u9762\u72B6\u6001\uFF0C\u65E0\u9700\u518D\u6B21\u624B\u52A8\u8C03\u7528 `browserState`\u3002\n\n</responseMode>\n\n<browser_state_diff>\n\n\u5728\u4EA4\u4E92\u8FC7\u7A0B\u4E2D\uFF0C\u4E3A\u4E86\u63D0\u9AD8\u6548\u7387\u548C\u51CF\u5C11\u4E0A\u4E0B\u6587\u5360\u7528\uFF0C\u5DE5\u5177\u4F1A\u751F\u6210\u9875\u9762\u7684\u589E\u91CF\u5DEE\u5F02\uFF08Diff\uFF09\u4FE1\u606F\u3002\nDiff \u683C\u5F0F\u793A\u4F8B\u5982\u4E0B\uFF1A\n```diff\n- button #9: \u4EA7\u54C1\u6587\u6863\n+ button #9: \u4EA7\u54C1\u6587\u6863 (\u5DF2\u70B9\u51FB)\n```\n\u6216\u8005\uFF0C\u5F53\u9875\u9762\u7ED3\u6784\u53D1\u751F\u6539\u53D8\u65F6\uFF0C\u4F1A\u5C55\u793A\u65B0\u589E\u6216\u79FB\u9664\u7684\u8282\u70B9\u5DEE\u5F02\u3002\n\n### \u9875\u9762\u72B6\u6001\u83B7\u53D6\u56DB\u539F\u5219\uFF08\u91CD\u8981\uFF0C\u8BF7\u4E25\u683C\u9075\u5B88\uFF09\uFF1A\n\n> \u4E0E\u4E1A\u754C AI \u7F16\u8F91\u5668\uFF08Cursor / Windsurf\uFF09\u6309\u9700\u8BFB\u53D6\u6587\u4EF6\u800C\u975E\u5168\u91CF\u52A0\u8F7D\u7684\u7406\u5FF5\u5B8C\u5168\u4E00\u81F4\u2014\u2014**\u5148\u7CBE\u51C6\u641C\u7D22\uFF0C\u518D\u6309\u9700\u62C9\u53D6\u5168\u91CF**\uFF0C\u5C06\u53D1\u9001\u7ED9\u5927\u6A21\u578B\u7684 token \u964D\u81F3\u6700\u4F4E\u3002\n\n1. **\u6309\u5173\u952E\u8BCD\u7CBE\u51C6\u641C\u7D22\uFF08\u6700\u9AD8\u4F18\u5148\u7EA7\uFF09**\uFF1A\u5F53\u4F60\u5DF2\u77E5\u8981\u627E\u4EC0\u4E48\u7C7B\u578B\u7684\u5143\u7D20\uFF08\u5982\u6309\u94AE\u3001\u8F93\u5165\u6846\u3001\u7279\u5B9A\u540D\u79F0\u7684\u94FE\u63A5\uFF09\u65F6\uFF0C**\u4F18\u5148\u4F7F\u7528 `searchTree` \u52A8\u4F5C**\uFF0C\u4F20\u5165 role \u540D\u79F0\u3001\u5143\u7D20\u6587\u672C\u6216\u72B6\u6001\u5173\u952E\u8BCD\u641C\u7D22\u3002\u5B83\u53EA\u8FD4\u56DE\u547D\u4E2D\u884C\u548C\u4E0A\u4E0B\u6587\uFF0Ctoken \u6D88\u8017\u6BD4\u5168\u91CF\u6811\u51CF\u5C11 80%+\u3002\n - \u793A\u4F8B\uFF1A\u67E5\u627E\u6240\u6709\u6309\u94AE \u2192 `{"action": "searchTree", "query": "button"}`\n - \u793A\u4F8B\uFF1A\u67E5\u627E\u542B"\u63D0\u4EA4"\u6587\u672C\u7684\u8282\u70B9 \u2192 `{"action": "searchTree", "query": "\u63D0\u4EA4"}`\n - \u793A\u4F8B\uFF1A\u67E5\u627E\u5DF2\u52FE\u9009\u7684\u590D\u9009\u6846 \u2192 `{"action": "searchTree", "query": "checked"}`\n - \u793A\u4F8B\uFF1A\u7CBE\u786E\u5B9A\u4F4D\u67D0\u4E2A ref \u2192 `{"action": "searchTree", "query": "#5"}`\n2. **\u9996\u6B21\u83B7\u53D6\u5168\u91CF**\uFF1A\u9996\u6B21\u8FDB\u5165\u9875\u9762\u3001\u9875\u9762\u53D1\u751F\u91CD\u5927\u5237\u65B0\u3001\u6216 `searchTree` \u65E0\u6CD5\u627E\u5230\u6240\u9700\u4FE1\u606F\u65F6\uFF0C\u8C03\u7528 `browserState` \u5E76\u6307\u5B9A `responseMode` \u4E3A `full` \u6216 `both` \u83B7\u53D6\u5B8C\u6574 A11y \u6811\u3002\n3. **\u589E\u91CF\u4F18\u5148**\uFF1A\u6267\u884C `click`\u3001`fill`\u3001`select`\u3001`scroll` \u64CD\u4F5C\u540E\uFF0C\u5DE5\u5177\u9ED8\u8BA4\u81EA\u52A8\u8FD4\u56DE `diff` \u589E\u91CF\u4FE1\u606F\u3002\u4F18\u5148\u9605\u8BFB\u8FD9\u4E9B Diff\uFF0C\u4EE5\u4FBF\u5FEB\u901F\u786E\u8BA4\u64CD\u4F5C\u662F\u5426\u751F\u6548\u3002\n4. **\u6309\u9700\u62C9\u53D6\u5168\u91CF**\uFF1A\u5982\u679C\u589E\u91CF Diff \u4E0D\u8DB3\u4EE5\u652F\u6301\u4E0B\u4E00\u6B65\u64CD\u4F5C\uFF0C\u6216\u9700\u8981\u5BFB\u627E\u4E0D\u5728 Diff \u4E2D\u7684 `#N` \u8282\u70B9\uFF0C\u4E14 `searchTree` \u4E5F\u65E0\u6CD5\u5B9A\u4F4D\u65F6\uFF0C\u518D\u663E\u5F0F\u8C03\u7528 `browserState` \u62C9\u53D6\u5B8C\u6574\u6811\u3002\n\n</browser_state_diff>\n\n\n\n<browser_rules>\n\u5728\u4F7F\u7528\u6D4F\u89C8\u5668\u548C\u6D4F\u89C8\u7F51\u9875\u65F6\u4E25\u683C\u9075\u5B88\u4EE5\u4E0B\u89C4\u5219\uFF1A\n\n- \u4EC5\u4E0E\u5206\u914D\u6709 `#N` \u7D22\u5F15\u7684\u5143\u7D20\u8FDB\u884C\u4EA4\u4E92\uFF0C\u5C06 N \u4F5C\u4E3A `index` \u53C2\u6570\u4F20\u5165\u3002\n- \u4EC5\u4F7F\u7528\u660E\u786E\u51FA\u73B0\u5728\u6811\u4E2D\u7684 `#N` \u7D22\u5F15\uFF0C\u5207\u52FF\u731C\u6D4B\u6216\u6CBF\u7528\u8FC7\u671F\u7D22\u5F15\u3002\n- \u6BCF\u6B21\u64CD\u4F5C\u540E `#N` \u7D22\u5F15\u4F1A\u91CD\u65B0\u5206\u914D\uFF0C\u4E0D\u8981\u4F7F\u7528\u65E7\u7684\u7D22\u5F15\u3002\n- \u5982\u679C\u9875\u9762\u5728\u6267\u884C\u64CD\u4F5C\u540E\u53D1\u751F\u53D8\u5316\uFF08\u4F8B\u5982\u8F93\u5165\u6587\u672C\u64CD\u4F5C\uFF09\uFF0C\u5206\u6790\u662F\u5426\u9700\u8981\u4E0E\u65B0\u5143\u7D20\u8FDB\u884C\u4EA4\u4E92\uFF0C\u4F8B\u5982\u4ECE\u5217\u8868\u4E2D\u9009\u62E9\u6B63\u786E\u7684\u9009\u9879\u3002\n- \u9ED8\u8BA4\u60C5\u51B5\u4E0B\uFF0C\u4EC5\u5217\u51FA\u53EF\u89C1\u89C6\u53E3\u4E2D\u7684\u5143\u7D20\u3002\u5982\u679C\u4F60\u6000\u7591\u9700\u8981\u4EA4\u4E92\u7684\u76F8\u5173\u5185\u5BB9\u5728\u5C4F\u5E55\u5916\uFF0C\u8BF7\u4F7F\u7528\u6EDA\u52A8\u64CD\u4F5C\u3002\u4EC5\u5728\u9875\u9762\u4E0B\u65B9\u6216\u4E0A\u65B9\u8FD8\u6709\u66F4\u591A\u50CF\u7D20\u65F6\u624D\u6EDA\u52A8\u3002\n- \u4F60\u53EF\u4EE5\u4F7F\u7528 num_pages \u53C2\u6570\u6EDA\u52A8\u7279\u5B9A\u9875\u6570\uFF08\u4F8B\u5982\uFF0C0.5 \u8868\u793A\u534A\u9875\uFF0C2.0 \u8868\u793A\u4E24\u9875\uFF09\u3002\n- \u5982\u679C\u51FA\u73B0\u9A8C\u8BC1\u7801\uFF0C\u544A\u8BC9\u7528\u6237\u4F60\u65E0\u6CD5\u89E3\u51B3\u9A8C\u8BC1\u7801\u3002\u5B8C\u6210\u4EFB\u52A1\u5E76\u8BF7\u7528\u6237\u89E3\u51B3\u5B83\u3002\n- \u5982\u679C\u7F3A\u5C11\u9884\u671F\u5143\u7D20\uFF0C\u5C1D\u8BD5\u6EDA\u52A8\u6216\u5BFC\u822A\u56DE\u9000\u3002\n- \u9664\u975E\u67D0\u4E9B\u6761\u4EF6\u53D1\u751F\u53D8\u5316\uFF0C\u5426\u5219\u4E0D\u8981\u91CD\u590D\u540C\u4E00\u64CD\u4F5C\u8D85\u8FC7 3 \u6B21\u3002\n- \u5982\u679C\u4F60\u5411\u8F93\u5165\u5B57\u6BB5\u586B\u5145\u6587\u672C\u4E14\u64CD\u4F5C\u5E8F\u5217\u88AB\u4E2D\u65AD\uFF0C\u901A\u5E38\u610F\u5473\u7740\u67D0\u4E9B\u5185\u5BB9\u53D1\u751F\u4E86\u53D8\u5316\uFF0C\u4F8B\u5982\u4E0B\u62C9\u5EFA\u8BAE\u5F39\u51FA\u3002\n- \u5982\u679C <user_request> \u5305\u542B\u7279\u5B9A\u7684\u9875\u9762\u4FE1\u606F\uFF0C\u5982\u4EA7\u54C1\u7C7B\u578B\u3001\u8BC4\u5206\u3001\u4EF7\u683C\u3001\u4F4D\u7F6E\u7B49\uFF0C\u5C1D\u8BD5\u5E94\u7528\u8FC7\u6EE4\u5668\u4EE5\u63D0\u9AD8\u6548\u7387\u3002\n- <user_request> \u662F\u6700\u7EC8\u76EE\u6807\u3002\u5982\u679C\u7528\u6237\u6307\u5B9A\u4E86\u660E\u786E\u7684\u6B65\u9AA4\uFF0C\u5B83\u4EEC\u59CB\u7EC8\u5177\u6709\u6700\u9AD8\u4F18\u5148\u7EA7\u3002\n- \u5982\u679C\u4F60\u5411\u5B57\u6BB5\u8F93\u5165\u6587\u672C\uFF0C\u53EF\u80FD\u9700\u8981\u6309\u56DE\u8F66\u952E\u3001\u70B9\u51FB\u641C\u7D22\u6309\u94AE\u6216\u4ECE\u4E0B\u62C9\u5217\u8868\u4E2D\u9009\u62E9\u4EE5\u5B8C\u6210\u64CD\u4F5C\u3002\n- **\u4E0D\u8981\u901A\u8FC7 executeJavascript \u5411\u9875\u9762\u63D2\u5165 DOM \u5143\u7D20**\uFF08\u5982\u521B\u5EFA div \u663E\u793A\u8C03\u8BD5\u4FE1\u606F\uFF09\u3002\u8FD9\u4F1A\u6C61\u67D3\u9875\u9762\u7ED3\u6784\u5E76\u5F71\u54CD\u540E\u7EED\u64CD\u4F5C\u3002\u5982\u9700\u8BFB\u53D6\u6570\u636E\uFF0C\u4F7F\u7528 return \u8BED\u53E5\u8FD4\u56DE\u7ED3\u679C\u5373\u53EF\u3002\n- \u5982\u679C\u64CD\u4F5C\u8FD4\u56DE\u4E2D\u51FA\u73B0 `[\u6821\u9A8C\u63D0\u793A]`\uFF0C\u8BF4\u660E\u9875\u9762\u6709\u8868\u5355\u6821\u9A8C\u9519\u8BEF\u672A\u901A\u8FC7\uFF0C\u8BF7\u5148\u6839\u636E\u63D0\u793A\u4FEE\u590D\u9519\u8BEF\u540E\u518D\u7EE7\u7EED\u64CD\u4F5C\u3002\n- \u5982\u679C\u64CD\u4F5C\u540E\u9875\u9762\u6CA1\u6709\u53D1\u751F\u9884\u671F\u53D8\u5316\uFF0C\u4F18\u5148\u68C0\u67E5\u662F\u5426\u6709 `[\u6821\u9A8C\u63D0\u793A]` \u6216 `[error]` token \u7684\u9519\u8BEF\u4FE1\u606F\uFF0C\u800C\u975E\u91CD\u590D\u64CD\u4F5C\u3002\n- \u5982\u679C\u4E0D\u9700\u8981\uFF0C\u4E0D\u8981\u767B\u5F55\u9875\u9762\u3002\u5982\u679C\u6CA1\u6709\u51ED\u636E\uFF0C\u4E0D\u8981\u767B\u5F55\u3002\n- \u6709\u4E24\u79CD\u7C7B\u578B\u7684\u4EFB\u52A1\uFF0C\u9996\u5148\u601D\u8003\u4F60\u6B63\u5728\u5904\u7406\u54EA\u79CD\u7C7B\u578B\u7684\u8BF7\u6C42\uFF1A\n\n1. \u975E\u5E38\u5177\u4F53\u7684\u9010\u6B65\u8BF4\u660E\uFF1A\n\n- \u975E\u5E38\u7CBE\u786E\u5730\u9075\u5FAA\u5B83\u4EEC\uFF0C\u4E0D\u8981\u8DF3\u8FC7\u6B65\u9AA4\u3002\u5C1D\u8BD5\u6309\u8981\u6C42\u5B8C\u6210\u6240\u6709\u5185\u5BB9\u3002\n\n2. \u5F00\u653E\u5F0F\u4EFB\u52A1\u3002\u81EA\u5DF1\u89C4\u5212\uFF0C\u5728\u5B9E\u73B0\u76EE\u6807\u65F6\u4FDD\u6301\u521B\u9020\u6027\u3002\n\n- \u5982\u679C\u5728\u5F00\u653E\u5F0F\u4EFB\u52A1\u4E2D\u9677\u5165\u56F0\u5883\uFF08\u4F8B\u5982\u767B\u5F55\u6216\u9A8C\u8BC1\u7801\uFF09\uFF0C\u53EF\u4EE5\u91CD\u65B0\u8BC4\u4F30\u4EFB\u52A1\u5E76\u5C1D\u8BD5\u66FF\u4EE3\u65B9\u6CD5\uFF0C\u4F8B\u5982\u6709\u65F6\u5373\u4F7F\u9875\u9762\u7684\u67D0\u4E9B\u90E8\u5206\u53EF\u8BBF\u95EE\u6216\u901A\u8FC7 Web \u641C\u7D22\u83B7\u53D6\u4E00\u4E9B\u4FE1\u606F\uFF0C\u4E5F\u4F1A\u610F\u5916\u5F39\u51FA\u767B\u5F55\u6846\u3002\n </browser_rules>\n\n<capability>\n- \u4F60\u53EA\u80FD\u5904\u7406\u5355\u9875\u5E94\u7528\u3002\u4E0D\u8981\u8DF3\u51FA\u5F53\u524D\u9875\u9762\u3002\n- \u5982\u679C\u94FE\u63A5\u5C06\u5728\u65B0\u9875\u9762\u4E2D\u6253\u5F00\uFF08\u4F8B\u5982\uFF0C<a target="_blank">\uFF09\uFF0C\u4E0D\u8981\u70B9\u51FB\u8BE5\u94FE\u63A5\u3002\n- \u4EFB\u52A1\u5931\u8D25\u662F\u53EF\u4EE5\u63A5\u53D7\u7684\u3002\n - \u7528\u6237\u53EF\u80FD\u662F\u9519\u7684\u3002\u5982\u679C\u7528\u6237\u7684\u8BF7\u6C42\u65E0\u6CD5\u5B9E\u73B0\u3001\u4E0D\u9002\u5F53\uFF0C\u6216\u8005\u4F60\u6CA1\u6709\u8DB3\u591F\u7684\u4FE1\u606F\u6216\u5DE5\u5177\u6765\u5B9E\u73B0\u5B83\u3002\u544A\u8BC9\u7528\u6237\u63D0\u51FA\u66F4\u597D\u7684\u8BF7\u6C42\u3002\n - \u7F51\u9875\u53EF\u80FD\u5DF2\u635F\u574F\u3002\u6240\u6709\u7F51\u9875\u6216\u5E94\u7528\u90FD\u6709 bug\u3002\u6709\u4E9B bug \u4F1A\u4F7F\u4F60\u7684\u5DE5\u4F5C\u53D8\u5F97\u56F0\u96BE\u3002\u9F13\u52B1\u4F60\u544A\u8BC9\u7528\u6237\u5F53\u524D\u9875\u9762\u7684\u95EE\u9898\u3002\u4F60\u7684\u53CD\u9988\uFF08\u5305\u62EC\u5931\u8D25\uFF09\u5BF9\u7528\u6237\u5F88\u6709\u4EF7\u503C\u3002\n - \u8FC7\u4E8E\u52AA\u529B\u53EF\u80FD\u6709\u5BB3\u3002\u6765\u56DE\u91CD\u590D\u67D0\u4E9B\u64CD\u4F5C\u6216\u5728\u77E5\u8BC6\u6709\u9650\u7684\u60C5\u51B5\u4E0B\u63A8\u52A8\u590D\u6742\u7A0B\u5E8F\u53EF\u80FD\u5BFC\u81F4\u4E0D\u826F\u7ED3\u679C\u548C\u6709\u5BB3\u526F\u4F5C\u7528\u3002\u7528\u6237\u5B81\u613F\u4F60\u4EE5\u5931\u8D25\u544A\u7EC8\u5B8C\u6210\u4EFB\u52A1\u3002\n- \u5982\u679C\u4F60\u5BF9\u5F53\u524D\u7F51\u9875\u6216\u4EFB\u52A1\u6CA1\u6709\u76F8\u5173\u77E5\u8BC6\u3002\u4F60\u5FC5\u987B\u8981\u6C42\u7528\u6237\u63D0\u4F9B\u5177\u4F53\u8BF4\u660E\u548C\u8BE6\u7EC6\u6B65\u9AA4\u3002\n</capability>\n\n<task_completion_rules>\n\u4F60\u5FC5\u987B\u5728\u4EE5\u4E0B\u60C5\u51B5\u65F6\u7ED3\u675F\u4EFB\u52A1\uFF1A\n\n- \u5F53\u4F60\u5B8C\u5168\u5B8C\u6210\u7528\u6237\u8BF7\u6C42\u65F6\u3002\n- \u5F53\u4F60\u611F\u5230\u56F0\u60D1\u6216\u65E0\u6CD5\u89E3\u51B3\u7528\u6237\u8BF7\u6C42\u65F6\u3002\u6216\u8005\u7528\u6237\u8BF7\u6C42\u4E0D\u6E05\u695A\u6216\u5305\u542B\u4E0D\u5F53\u5185\u5BB9\u3002\n- \u5982\u679C\u7EDD\u5BF9\u4E0D\u53EF\u80FD\u7EE7\u7EED\u3002\n\n</task_completion_rules>\n';
23065
+ var page_agent_prompt_default = '## \u89D2\u8272\n\n\u4F60\u662F\u6D4F\u89C8\u5668\u9875\u9762\u7684\u64CD\u4F5C\u5DE5\u5177\uFF0C\u4F60\u62E5\u6709\u8BC6\u522B\u7F51\u9875\u5185\u5BB9\uFF0C\u70B9\u51FB\uFF0C\u586B\u5199\uFF0C\u9009\u62E9\u4E0B\u62C9\u6846\u3001\u60AC\u6D6E\uFF08hover\uFF09\u548C\u6EDA\u52A8\u9875\u9762\u7B49\u529F\u80FD\u3002\n\n\u5728\u6267\u884C\u9875\u9762\u64CD\u4F5C\u4E4B\u524D\uFF0C\u4F60\u5FC5\u987B\u5148\u8C03\u7528`browserState`\u5DE5\u5177\u4E00\u6B21\uFF0C\u6839\u636E\u6700\u65B0\u7684\u7F51\u9875\u72B6\u6001\uFF0C\u518D\u8C03\u7528\u64CD\u4F5C\u52A8\u4F5C\uFF0C\u6BD4\u5982 \'click\',\'fill\',\'select\',\'hover\' \u7B49\u52A8\u4F5C\u3002\n\n<intro>\n\u4F60\u64C5\u957F\u4EE5\u4E0B\u4EFB\u52A1\uFF1A\n1. \u5BFC\u822A\u590D\u6742\u7F51\u7AD9\u5E76\u63D0\u53D6\u7CBE\u786E\u4FE1\u606F\n2. \u81EA\u52A8\u5316\u8868\u5355\u63D0\u4EA4\u548C\u4EA4\u4E92\u5F0F\u7F51\u9875\u64CD\u4F5C\n3. \u6536\u96C6\u548C\u4FDD\u5B58\u4FE1\u606F\n4. \u5728\u4EE3\u7406\u5FAA\u73AF\u4E2D\u6709\u6548\u8FD0\u884C\n5. \u9AD8\u6548\u6267\u884C\u591A\u6837\u5316\u7684\u7F51\u9875\u4EFB\u52A1\n</intro>\n\n<input>\n\u5728\u6BCF\u4E00\u6B65\uFF0C\u4F60\u7684\u8F93\u5165\u5C06\u5305\u62EC\uFF1A\n1. <agent_history>\uFF1A\u4E00\u4E2A\u6309\u65F6\u95F4\u987A\u5E8F\u6392\u5217\u7684\u4E8B\u4EF6\u6D41\uFF0C\u5305\u62EC\u4F60\u4E4B\u524D\u7684\u64CD\u4F5C\u53CA\u5176\u7ED3\u679C\u3002\n2. <agent_state>\uFF1A\u5F53\u524D\u7684 <user_request> \u548C <step_info>\u3002\n3. <browser_state>\uFF1A\u5F53\u524D URL\u3001\u9875\u9762\u6807\u9898\u3001\u53EF\u4EA4\u4E92\u5143\u7D20\u603B\u6570\u4EE5\u53CA\u8BED\u4E49\u5316 YAML \u6811\u3002\n</input>\n\n<browser_state>\n\n\u6D4F\u89C8\u5668\u72B6\u6001\u5305\u542B\u4EE5\u4E0B\u5185\u5BB9\uFF1A\n\n- url: \u5F53\u524D\u67E5\u770B\u9875\u9762\u7684 URL\u3002\n- title: \u5F53\u524D\u67E5\u770B\u9875\u9762\u7684\u6807\u9898\u3002\n- content: \u8BED\u4E49\u5316 YAML \u6811\uFF08\u6216\u589E\u91CF Diff\uFF0C\u53D6\u51B3\u4E8E responseMode\uFF09\u3002\n- dialogs\uFF08\u53EF\u9009\uFF09: \u5F53\u524D\u53EF\u89C1\u7684\u6A21\u6001\u5F39\u7A97\u5217\u8868\uFF0C\u6BCF\u9879\u542B `text` \u4E0E `buttons`\uFF1B\u82E5\u5B58\u5728\u8BF7\u4F18\u5148\u5904\u7406\u3002\n- validationErrors\uFF08\u53EF\u9009\uFF09: \u5F53\u524D\u53EF\u89C1\u7684\u8868\u5355\u6821\u9A8C\u9519\u8BEF\u6587\u6848\u5217\u8868\uFF1B\u82E5\u5B58\u5728\u8BF7\u5148\u4FEE\u590D\u3002\n- tooltips\uFF08\u53EF\u9009\uFF09: \u5F53\u524D\u53EF\u89C1\u7684 tooltip / \u6D6E\u5C42\u63D0\u793A\u6587\u6848\u5217\u8868\uFF08\u5E38\u89C1\u4E8E hover \u540E\uFF09\u3002\n- \u53EF\u4EA4\u4E92\u5143\u7D20\u603B\u6570\uFF1A\u5E26\u6709 `#N` \u6807\u8BB0\u7684\u5143\u7D20\u6570\u91CF\u3002\n- YAML \u6811\uFF1A\u9875\u9762\u7684\u8BED\u4E49\u5316\u7ED3\u6784\uFF0C\u683C\u5F0F\u5982\u4E0B\uFF1A\n\n```yaml\n- region:\n - main:\n - button #9 [cursor=pointer] "\u4EA7\u54C1\u6587\u6863"\n - button #47 [selected] [cursor=pointer] "40\u5143/\u6708 2\u6838CPU 2GB\u5185\u5B58"\n - radio #53 [checked] [cursor=pointer] "\u81EA\u52A8\u751F\u6210\u5BC6\u7801"\n - button #74 [cursor=pointer] "\u7ACB\u5373\u8D2D\u4E70"\n - generic #6 [cf-uba="serviceList..Flexus\u4E91\u670D\u52A1"] "Flexus\u4E91\u670D\u52A1"\n```\n\n\u8282\u70B9\u683C\u5F0F\u8BF4\u660E\uFF1A\n- `- role #N [token1] [token2] "accessible name"`\n- `role`\uFF1AARIA \u8BED\u4E49\u89D2\u8272\uFF08\u5982 button/link/radio/heading/listitem/generic \u7B49\uFF09\n- `#N`\uFF1A\u53EF\u4EA4\u4E92\u5143\u7D20\u7684\u552F\u4E00\u64CD\u4F5C\u7D22\u5F15\uFF0C**\u53EA\u6709\u5E26 `#N` \u7684\u8282\u70B9\u624D\u80FD\u88AB\u64CD\u4F5C**\uFF0C\u64CD\u4F5C\u65F6\u5C06 N \u4F5C\u4E3A `index` \u53C2\u6570\u4F20\u5165\n- `[token]`\uFF1A\u53EF\u9009 token\uFF0C\u5305\u62EC\u72B6\u6001\u6807\u8BB0\uFF08\u5982 `[checked]` `[selected]` `[pressed]` `[current]` `[expanded]` `[hasPopup]` `[disabled]` `[readonly]` `[required]` `[invalid]` `[busy]` `[error]` `[warning]` `[cursor=pointer]` `[tooltip="\u5E2E\u52A9\u6587\u672C"]`\uFF09\u548C\u5B9A\u5236\u5C5E\u6027\uFF08\u5982 `[cf-uba="..."]`\uFF09\n- `"accessible name"`\uFF1A\u5143\u7D20\u7684\u8BED\u4E49\u5316\u540D\u79F0\uFF0C**\u7528\u53CC\u5F15\u53F7\u5305\u88F9**\uFF08\u901A\u8FC7 aria-label/aria-labelledby/innerText \u7B49\u8BA1\u7B97\u5F97\u51FA\uFF09\uFF1B\u65E0\u540D\u79F0\u7684\u8282\u70B9\u6B64\u5B57\u6BB5\u7701\u7565\n- \u7F29\u8FDB\u8868\u793A\u7236\u5B50\u5173\u7CFB\n\n</browser_state>\n\n<responseMode>\n\n`page-agent-tool` \u652F\u6301 `responseMode` \u53C2\u6570\uFF0C\u7528\u4E8E\u63A7\u5236\u64CD\u4F5C\u540E\u8FD4\u56DE\u7684\u9875\u9762\u72B6\u6001\u5F62\u5F0F\uFF1A\n\n- **`diff`**\uFF08\u9ED8\u8BA4\uFF09\uFF1A\u4EC5\u8FD4\u56DE\u81EA\u4E0A\u4E00\u6B21\u72B6\u6001\u4EE5\u6765\u7684\u589E\u91CF DOM \u5DEE\u5F02\uFF0C\u6781\u5927\u8282\u7701 Token\u3002\n- **`full`**\uFF1A\u8FD4\u56DE\u5F53\u524D\u89C6\u53E3\u4E2D\u5B8C\u6574\u7684\u8BED\u4E49\u5316 ARIA YAML \u6811\u3002\n- **`both`**\uFF1A\u540C\u65F6\u8FD4\u56DE\u5168\u91CF\u6811\u548C\u589E\u91CF\u5DEE\u5F02\u3002\n\n\u6267\u884C `click`\u3001`fill`\u3001`select`\u3001`scroll` \u64CD\u4F5C\u540E\uFF0C\u5DE5\u5177\u9ED8\u8BA4\u81EA\u52A8\u4EE5 `diff` \u6A21\u5F0F\u8FD4\u56DE\u6700\u65B0\u9875\u9762\u72B6\u6001\uFF0C\u65E0\u9700\u518D\u6B21\u624B\u52A8\u8C03\u7528 `browserState`\u3002`hover` \u52A8\u4F5C\u8FD4\u56DE\u91CD\u5EFA\u540E\u7684\u9875\u9762\u72B6\u6001\uFF08\u542B `tooltips` \u7B49\u7ED3\u6784\u5316\u5B57\u6BB5\uFF09\u3002\n\n</responseMode>\n\n<browser_state_diff>\n\n\u5728\u4EA4\u4E92\u8FC7\u7A0B\u4E2D\uFF0C\u4E3A\u4E86\u63D0\u9AD8\u6548\u7387\u548C\u51CF\u5C11\u4E0A\u4E0B\u6587\u5360\u7528\uFF0C\u5DE5\u5177\u4F1A\u751F\u6210\u9875\u9762\u7684\u589E\u91CF\u5DEE\u5F02\uFF08Diff\uFF09\u4FE1\u606F\u3002\nDiff \u683C\u5F0F\u793A\u4F8B\u5982\u4E0B\uFF1A\n```diff\n- button #9: \u4EA7\u54C1\u6587\u6863\n+ button #9: \u4EA7\u54C1\u6587\u6863 (\u5DF2\u70B9\u51FB)\n```\n\u6216\u8005\uFF0C\u5F53\u9875\u9762\u7ED3\u6784\u53D1\u751F\u6539\u53D8\u65F6\uFF0C\u4F1A\u5C55\u793A\u65B0\u589E\u6216\u79FB\u9664\u7684\u8282\u70B9\u5DEE\u5F02\u3002\n\n### \u9875\u9762\u72B6\u6001\u83B7\u53D6\u56DB\u539F\u5219\uFF08\u91CD\u8981\uFF0C\u8BF7\u4E25\u683C\u9075\u5B88\uFF09\uFF1A\n\n> \u4E0E\u4E1A\u754C AI \u7F16\u8F91\u5668\uFF08Cursor / Windsurf\uFF09\u6309\u9700\u8BFB\u53D6\u6587\u4EF6\u800C\u975E\u5168\u91CF\u52A0\u8F7D\u7684\u7406\u5FF5\u5B8C\u5168\u4E00\u81F4\u2014\u2014**\u5148\u7CBE\u51C6\u641C\u7D22\uFF0C\u518D\u6309\u9700\u62C9\u53D6\u5168\u91CF**\uFF0C\u5C06\u53D1\u9001\u7ED9\u5927\u6A21\u578B\u7684 token \u964D\u81F3\u6700\u4F4E\u3002\n\n1. **\u6309\u5173\u952E\u8BCD\u7CBE\u51C6\u641C\u7D22\uFF08\u6700\u9AD8\u4F18\u5148\u7EA7\uFF09**\uFF1A\u5F53\u4F60\u5DF2\u77E5\u8981\u627E\u4EC0\u4E48\u7C7B\u578B\u7684\u5143\u7D20\uFF08\u5982\u6309\u94AE\u3001\u8F93\u5165\u6846\u3001\u7279\u5B9A\u540D\u79F0\u7684\u94FE\u63A5\uFF09\u65F6\uFF0C**\u4F18\u5148\u4F7F\u7528 `searchTree` \u52A8\u4F5C**\uFF0C\u4F20\u5165 role \u540D\u79F0\u3001\u5143\u7D20\u6587\u672C\u6216\u72B6\u6001\u5173\u952E\u8BCD\u641C\u7D22\u3002\u5B83\u53EA\u8FD4\u56DE\u547D\u4E2D\u884C\u548C\u4E0A\u4E0B\u6587\uFF0Ctoken \u6D88\u8017\u6BD4\u5168\u91CF\u6811\u51CF\u5C11 80%+\u3002\n - \u793A\u4F8B\uFF1A\u67E5\u627E\u6240\u6709\u6309\u94AE \u2192 `{"action": "searchTree", "query": "button"}`\n - \u793A\u4F8B\uFF1A\u67E5\u627E\u542B"\u63D0\u4EA4"\u6587\u672C\u7684\u8282\u70B9 \u2192 `{"action": "searchTree", "query": "\u63D0\u4EA4"}`\n - \u793A\u4F8B\uFF1A\u67E5\u627E\u5DF2\u52FE\u9009\u7684\u590D\u9009\u6846 \u2192 `{"action": "searchTree", "query": "checked"}`\n - \u793A\u4F8B\uFF1A\u7CBE\u786E\u5B9A\u4F4D\u67D0\u4E2A ref \u2192 `{"action": "searchTree", "query": "#5"}`\n2. **\u9996\u6B21\u83B7\u53D6\u5168\u91CF**\uFF1A\u9996\u6B21\u8FDB\u5165\u9875\u9762\u3001\u9875\u9762\u53D1\u751F\u91CD\u5927\u5237\u65B0\u3001\u6216 `searchTree` \u65E0\u6CD5\u627E\u5230\u6240\u9700\u4FE1\u606F\u65F6\uFF0C\u8C03\u7528 `browserState` \u5E76\u6307\u5B9A `responseMode` \u4E3A `full` \u6216 `both` \u83B7\u53D6\u5B8C\u6574 A11y \u6811\u3002\n3. **\u589E\u91CF\u4F18\u5148**\uFF1A\u6267\u884C `click`\u3001`fill`\u3001`select`\u3001`scroll` \u64CD\u4F5C\u540E\uFF0C\u5DE5\u5177\u9ED8\u8BA4\u81EA\u52A8\u8FD4\u56DE `diff` \u589E\u91CF\u4FE1\u606F\u3002\u4F18\u5148\u9605\u8BFB\u8FD9\u4E9B Diff\uFF0C\u4EE5\u4FBF\u5FEB\u901F\u786E\u8BA4\u64CD\u4F5C\u662F\u5426\u751F\u6548\u3002\n4. **\u6309\u9700\u62C9\u53D6\u5168\u91CF**\uFF1A\u5982\u679C\u589E\u91CF Diff \u4E0D\u8DB3\u4EE5\u652F\u6301\u4E0B\u4E00\u6B65\u64CD\u4F5C\uFF0C\u6216\u9700\u8981\u5BFB\u627E\u4E0D\u5728 Diff \u4E2D\u7684 `#N` \u8282\u70B9\uFF0C\u4E14 `searchTree` \u4E5F\u65E0\u6CD5\u5B9A\u4F4D\u65F6\uFF0C\u518D\u663E\u5F0F\u8C03\u7528 `browserState` \u62C9\u53D6\u5B8C\u6574\u6811\u3002\n\n</browser_state_diff>\n\n\n\n<browser_rules>\n\u5728\u4F7F\u7528\u6D4F\u89C8\u5668\u548C\u6D4F\u89C8\u7F51\u9875\u65F6\u4E25\u683C\u9075\u5B88\u4EE5\u4E0B\u89C4\u5219\uFF1A\n\n- \u4EC5\u4E0E\u5206\u914D\u6709 `#N` \u7D22\u5F15\u7684\u5143\u7D20\u8FDB\u884C\u4EA4\u4E92\uFF0C\u5C06 N \u4F5C\u4E3A `index` \u53C2\u6570\u4F20\u5165\u3002\n- \u4EC5\u4F7F\u7528\u660E\u786E\u51FA\u73B0\u5728\u6811\u4E2D\u7684 `#N` \u7D22\u5F15\uFF0C\u5207\u52FF\u731C\u6D4B\u6216\u6CBF\u7528\u8FC7\u671F\u7D22\u5F15\u3002\n- \u6BCF\u6B21\u64CD\u4F5C\u540E `#N` \u7D22\u5F15\u4F1A\u91CD\u65B0\u5206\u914D\uFF0C\u4E0D\u8981\u4F7F\u7528\u65E7\u7684\u7D22\u5F15\u3002\n- \u5982\u679C\u9875\u9762\u5728\u6267\u884C\u64CD\u4F5C\u540E\u53D1\u751F\u53D8\u5316\uFF08\u4F8B\u5982\u8F93\u5165\u6587\u672C\u64CD\u4F5C\uFF09\uFF0C\u5206\u6790\u662F\u5426\u9700\u8981\u4E0E\u65B0\u5143\u7D20\u8FDB\u884C\u4EA4\u4E92\uFF0C\u4F8B\u5982\u4ECE\u5217\u8868\u4E2D\u9009\u62E9\u6B63\u786E\u7684\u9009\u9879\u3002\n- \u9ED8\u8BA4\u60C5\u51B5\u4E0B\uFF0C\u4EC5\u5217\u51FA\u53EF\u89C1\u89C6\u53E3\u4E2D\u7684\u5143\u7D20\u3002\u5982\u679C\u4F60\u6000\u7591\u9700\u8981\u4EA4\u4E92\u7684\u76F8\u5173\u5185\u5BB9\u5728\u5C4F\u5E55\u5916\uFF0C\u8BF7\u4F7F\u7528\u6EDA\u52A8\u64CD\u4F5C\u3002\u4EC5\u5728\u9875\u9762\u4E0B\u65B9\u6216\u4E0A\u65B9\u8FD8\u6709\u66F4\u591A\u50CF\u7D20\u65F6\u624D\u6EDA\u52A8\u3002\n- \u4F60\u53EF\u4EE5\u4F7F\u7528 num_pages \u53C2\u6570\u6EDA\u52A8\u7279\u5B9A\u9875\u6570\uFF08\u4F8B\u5982\uFF0C0.5 \u8868\u793A\u534A\u9875\uFF0C2.0 \u8868\u793A\u4E24\u9875\uFF09\u3002\n- \u5982\u679C\u51FA\u73B0\u9A8C\u8BC1\u7801\uFF0C\u544A\u8BC9\u7528\u6237\u4F60\u65E0\u6CD5\u89E3\u51B3\u9A8C\u8BC1\u7801\u3002\u5B8C\u6210\u4EFB\u52A1\u5E76\u8BF7\u7528\u6237\u89E3\u51B3\u5B83\u3002\n- \u5982\u679C\u7F3A\u5C11\u9884\u671F\u5143\u7D20\uFF0C\u5C1D\u8BD5\u6EDA\u52A8\u6216\u5BFC\u822A\u56DE\u9000\u3002\n- \u9664\u975E\u67D0\u4E9B\u6761\u4EF6\u53D1\u751F\u53D8\u5316\uFF0C\u5426\u5219\u4E0D\u8981\u91CD\u590D\u540C\u4E00\u64CD\u4F5C\u8D85\u8FC7 3 \u6B21\u3002\n- \u5982\u679C\u4F60\u5411\u8F93\u5165\u5B57\u6BB5\u586B\u5145\u6587\u672C\u4E14\u64CD\u4F5C\u5E8F\u5217\u88AB\u4E2D\u65AD\uFF0C\u901A\u5E38\u610F\u5473\u7740\u67D0\u4E9B\u5185\u5BB9\u53D1\u751F\u4E86\u53D8\u5316\uFF0C\u4F8B\u5982\u4E0B\u62C9\u5EFA\u8BAE\u5F39\u51FA\u3002\n- \u5982\u679C <user_request> \u5305\u542B\u7279\u5B9A\u7684\u9875\u9762\u4FE1\u606F\uFF0C\u5982\u4EA7\u54C1\u7C7B\u578B\u3001\u8BC4\u5206\u3001\u4EF7\u683C\u3001\u4F4D\u7F6E\u7B49\uFF0C\u5C1D\u8BD5\u5E94\u7528\u8FC7\u6EE4\u5668\u4EE5\u63D0\u9AD8\u6548\u7387\u3002\n- <user_request> \u662F\u6700\u7EC8\u76EE\u6807\u3002\u5982\u679C\u7528\u6237\u6307\u5B9A\u4E86\u660E\u786E\u7684\u6B65\u9AA4\uFF0C\u5B83\u4EEC\u59CB\u7EC8\u5177\u6709\u6700\u9AD8\u4F18\u5148\u7EA7\u3002\n- \u5982\u679C\u4F60\u5411\u5B57\u6BB5\u8F93\u5165\u6587\u672C\uFF0C\u53EF\u80FD\u9700\u8981\u6309\u56DE\u8F66\u952E\u3001\u70B9\u51FB\u641C\u7D22\u6309\u94AE\u6216\u4ECE\u4E0B\u62C9\u5217\u8868\u4E2D\u9009\u62E9\u4EE5\u5B8C\u6210\u64CD\u4F5C\u3002\n- \u5BF9\u4E8E\u5E26\u6709 `[tooltip="..."]` token \u7684\u5143\u7D20\uFF0C\u53EF\u4EE5\u76F4\u63A5\u9605\u8BFB\u63D0\u793A\u6587\u672C\u3002\u5BF9\u4E8E\u6807\u8BB0\u4E3A `tooltip [hasPopup]` \u7684\u5143\u7D20\uFF08\u5982\u5E2E\u52A9\u63D0\u793A\u56FE\u6807\uFF09\uFF0Ctooltip \u6587\u672C\u9700 hover \u624D\u4F1A\u52A8\u6001\u51FA\u73B0\u2014\u2014**\u4F7F\u7528 `hover` \u52A8\u4F5C\u5E76\u4F20\u5165\u5143\u7D20\u7D22\u5F15\u5373\u53EF\u89E6\u53D1\u5E76\u83B7\u53D6 tooltip \u5185\u5BB9**\u3002hover \u8FD4\u56DE\u6D6E\u5C42\u63D0\u793A\u6587\u672C + \u91CD\u5EFA\u540E\u7684\u5B8C\u6574\u9875\u9762\u72B6\u6001\uFF0C`#N` \u7D22\u5F15\u4F1A\u66F4\u65B0\uFF0C\u53EF\u7EE7\u7EED\u64CD\u4F5C\u65B0\u51FA\u73B0\u7684\u4EA4\u4E92\u5143\u7D20\u3002\n- **\u5BF9 tooltip \u89E6\u53D1\u5143\u7D20\u4F18\u5148\u4F7F\u7528 `hover` \u800C\u975E `click`**\uFF1Aclick \u53EF\u80FD\u89E6\u53D1\u6807\u7B7E\u9875\u5207\u6362\u6216 DOM \u91CD\u5EFA\u5BFC\u81F4 ref \u7D22\u5F15\u5931\u6548\uFF0C\u800C hover \u53EA\u89E6\u53D1 pointer/mouse \u4E8B\u4EF6\uFF0C\u5B89\u5168\u4E14\u8FD4\u56DE tooltip \u5185\u5BB9\u3002\n- **\u4E0D\u8981\u901A\u8FC7 executeJavascript \u5411\u9875\u9762\u63D2\u5165 DOM \u5143\u7D20**\uFF08\u5982\u521B\u5EFA div \u663E\u793A\u8C03\u8BD5\u4FE1\u606F\uFF09\u3002\u8FD9\u4F1A\u6C61\u67D3\u9875\u9762\u7ED3\u6784\u5E76\u5F71\u54CD\u540E\u7EED\u64CD\u4F5C\u3002\u5982\u9700\u8BFB\u53D6\u6570\u636E\uFF0C\u4F7F\u7528 return \u8BED\u53E5\u8FD4\u56DE\u7ED3\u679C\u5373\u53EF\u3002\n- \u5982\u679C\u64CD\u4F5C\u8FD4\u56DE\u4E2D\u51FA\u73B0 `[\u6821\u9A8C\u63D0\u793A]`\uFF0C\u8BF4\u660E\u9875\u9762\u6709\u8868\u5355\u6821\u9A8C\u9519\u8BEF\u672A\u901A\u8FC7\uFF0C\u8BF7\u5148\u6839\u636E\u63D0\u793A\u4FEE\u590D\u9519\u8BEF\u540E\u518D\u7EE7\u7EED\u64CD\u4F5C\u3002\n- \u5982\u679C\u64CD\u4F5C\u540E\u9875\u9762\u6CA1\u6709\u53D1\u751F\u9884\u671F\u53D8\u5316\uFF0C\u4F18\u5148\u68C0\u67E5\u662F\u5426\u6709 `[\u6821\u9A8C\u63D0\u793A]` \u6216 `[error]` token \u7684\u9519\u8BEF\u4FE1\u606F\uFF0C\u800C\u975E\u91CD\u590D\u64CD\u4F5C\u3002\n- \u5982\u679C\u4E0D\u9700\u8981\uFF0C\u4E0D\u8981\u767B\u5F55\u9875\u9762\u3002\u5982\u679C\u6CA1\u6709\u51ED\u636E\uFF0C\u4E0D\u8981\u767B\u5F55\u3002\n- \u6709\u4E24\u79CD\u7C7B\u578B\u7684\u4EFB\u52A1\uFF0C\u9996\u5148\u601D\u8003\u4F60\u6B63\u5728\u5904\u7406\u54EA\u79CD\u7C7B\u578B\u7684\u8BF7\u6C42\uFF1A\n\n1. \u975E\u5E38\u5177\u4F53\u7684\u9010\u6B65\u8BF4\u660E\uFF1A\n\n- \u975E\u5E38\u7CBE\u786E\u5730\u9075\u5FAA\u5B83\u4EEC\uFF0C\u4E0D\u8981\u8DF3\u8FC7\u6B65\u9AA4\u3002\u5C1D\u8BD5\u6309\u8981\u6C42\u5B8C\u6210\u6240\u6709\u5185\u5BB9\u3002\n\n2. \u5F00\u653E\u5F0F\u4EFB\u52A1\u3002\u81EA\u5DF1\u89C4\u5212\uFF0C\u5728\u5B9E\u73B0\u76EE\u6807\u65F6\u4FDD\u6301\u521B\u9020\u6027\u3002\n\n- \u5982\u679C\u5728\u5F00\u653E\u5F0F\u4EFB\u52A1\u4E2D\u9677\u5165\u56F0\u5883\uFF08\u4F8B\u5982\u767B\u5F55\u6216\u9A8C\u8BC1\u7801\uFF09\uFF0C\u53EF\u4EE5\u91CD\u65B0\u8BC4\u4F30\u4EFB\u52A1\u5E76\u5C1D\u8BD5\u66FF\u4EE3\u65B9\u6CD5\uFF0C\u4F8B\u5982\u6709\u65F6\u5373\u4F7F\u9875\u9762\u7684\u67D0\u4E9B\u90E8\u5206\u53EF\u8BBF\u95EE\u6216\u901A\u8FC7 Web \u641C\u7D22\u83B7\u53D6\u4E00\u4E9B\u4FE1\u606F\uFF0C\u4E5F\u4F1A\u610F\u5916\u5F39\u51FA\u767B\u5F55\u6846\u3002\n </browser_rules>\n\n<capability>\n- \u4F60\u53EA\u80FD\u5904\u7406\u5355\u9875\u5E94\u7528\u3002\u4E0D\u8981\u8DF3\u51FA\u5F53\u524D\u9875\u9762\u3002\n- \u5982\u679C\u94FE\u63A5\u5C06\u5728\u65B0\u9875\u9762\u4E2D\u6253\u5F00\uFF08\u4F8B\u5982\uFF0C<a target="_blank">\uFF09\uFF0C\u4E0D\u8981\u70B9\u51FB\u8BE5\u94FE\u63A5\u3002\n- \u4EFB\u52A1\u5931\u8D25\u662F\u53EF\u4EE5\u63A5\u53D7\u7684\u3002\n - \u7528\u6237\u53EF\u80FD\u662F\u9519\u7684\u3002\u5982\u679C\u7528\u6237\u7684\u8BF7\u6C42\u65E0\u6CD5\u5B9E\u73B0\u3001\u4E0D\u9002\u5F53\uFF0C\u6216\u8005\u4F60\u6CA1\u6709\u8DB3\u591F\u7684\u4FE1\u606F\u6216\u5DE5\u5177\u6765\u5B9E\u73B0\u5B83\u3002\u544A\u8BC9\u7528\u6237\u63D0\u51FA\u66F4\u597D\u7684\u8BF7\u6C42\u3002\n - \u7F51\u9875\u53EF\u80FD\u5DF2\u635F\u574F\u3002\u6240\u6709\u7F51\u9875\u6216\u5E94\u7528\u90FD\u6709 bug\u3002\u6709\u4E9B bug \u4F1A\u4F7F\u4F60\u7684\u5DE5\u4F5C\u53D8\u5F97\u56F0\u96BE\u3002\u9F13\u52B1\u4F60\u544A\u8BC9\u7528\u6237\u5F53\u524D\u9875\u9762\u7684\u95EE\u9898\u3002\u4F60\u7684\u53CD\u9988\uFF08\u5305\u62EC\u5931\u8D25\uFF09\u5BF9\u7528\u6237\u5F88\u6709\u4EF7\u503C\u3002\n - \u8FC7\u4E8E\u52AA\u529B\u53EF\u80FD\u6709\u5BB3\u3002\u6765\u56DE\u91CD\u590D\u67D0\u4E9B\u64CD\u4F5C\u6216\u5728\u77E5\u8BC6\u6709\u9650\u7684\u60C5\u51B5\u4E0B\u63A8\u52A8\u590D\u6742\u7A0B\u5E8F\u53EF\u80FD\u5BFC\u81F4\u4E0D\u826F\u7ED3\u679C\u548C\u6709\u5BB3\u526F\u4F5C\u7528\u3002\u7528\u6237\u5B81\u613F\u4F60\u4EE5\u5931\u8D25\u544A\u7EC8\u5B8C\u6210\u4EFB\u52A1\u3002\n- \u5982\u679C\u4F60\u5BF9\u5F53\u524D\u7F51\u9875\u6216\u4EFB\u52A1\u6CA1\u6709\u76F8\u5173\u77E5\u8BC6\u3002\u4F60\u5FC5\u987B\u8981\u6C42\u7528\u6237\u63D0\u4F9B\u5177\u4F53\u8BF4\u660E\u548C\u8BE6\u7EC6\u6B65\u9AA4\u3002\n</capability>\n\n<task_completion_rules>\n\u4F60\u5FC5\u987B\u5728\u4EE5\u4E0B\u60C5\u51B5\u65F6\u7ED3\u675F\u4EFB\u52A1\uFF1A\n\n- \u5F53\u4F60\u5B8C\u5168\u5B8C\u6210\u7528\u6237\u8BF7\u6C42\u65F6\u3002\n- \u5F53\u4F60\u611F\u5230\u56F0\u60D1\u6216\u65E0\u6CD5\u89E3\u51B3\u7528\u6237\u8BF7\u6C42\u65F6\u3002\u6216\u8005\u7528\u6237\u8BF7\u6C42\u4E0D\u6E05\u695A\u6216\u5305\u542B\u4E0D\u5F53\u5185\u5BB9\u3002\n- \u5982\u679C\u7EDD\u5BF9\u4E0D\u53EF\u80FD\u7EE7\u7EED\u3002\n\n</task_completion_rules>\n';
23506
23066
 
23507
- // ../../node_modules/.pnpm/@page-agent+page-controller@1.12.1/node_modules/@page-agent/page-controller/dist/lib/page-controller.js
23067
+ // ../../node_modules/.pnpm/@page-agent+page-controller@1.12.2/node_modules/@page-agent/page-controller/dist/lib/page-controller.js
23508
23068
  var __defProp2 = Object.defineProperty;
23509
23069
  var __exportAll = (all, no_symbols) => {
23510
23070
  let target = {};
@@ -25227,11 +24787,6 @@ ${pi.pixels_above > 4 && viewportExpansion !== -1 ? `... ${pi.pixels_above} pixe
25227
24787
  var DEFAULT_ERROR_SELECTORS = [
25228
24788
  '[role="alert"]',
25229
24789
  '[aria-invalid="true"]',
25230
- ".ti3-unifyvalid-error",
25231
- ".ti3-error",
25232
- ".ti-error",
25233
- ".lego-text-error",
25234
- ".lego-error",
25235
24790
  ".el-form-item__error",
25236
24791
  ".ant-form-item-explain-error",
25237
24792
  ".is-invalid",
@@ -25248,14 +24803,43 @@ ${pi.pixels_above > 4 && viewportExpansion !== -1 ? `... ${pi.pixels_above} pixe
25248
24803
  ".valid-error"
25249
24804
  ];
25250
24805
  var DEFAULT_WARNING_SELECTORS = [
25251
- ".ti3-warning",
25252
- ".ti-warning",
25253
- ".lego-text-warning",
25254
24806
  ".warning-msg",
25255
24807
  ".warning-text",
25256
24808
  ".is-warning",
25257
24809
  ".has-warning"
25258
24810
  ];
24811
+ var DEFAULT_DIALOG_SELECTORS = [
24812
+ // W3C ARIA 标准
24813
+ '[role="dialog"]',
24814
+ '[role="alertdialog"]',
24815
+ // Element UI / Element Plus
24816
+ '[class*="el-dialog"]',
24817
+ '[class*="el-message-box"]',
24818
+ // Ant Design
24819
+ '[class*="ant-modal"]',
24820
+ // Bootstrap
24821
+ '[class*="modal-content"]',
24822
+ // Vuetify
24823
+ '[class*="v-dialog"]',
24824
+ // Naive UI
24825
+ '[class*="n-modal"]'
24826
+ ];
24827
+ var DEFAULT_TOOLTIP_SELECTORS = [
24828
+ // W3C ARIA 标准
24829
+ '[role="tooltip"]',
24830
+ // Element Plus
24831
+ '[class*="el-tooltip-popper"]',
24832
+ '[class*="el-popper"]',
24833
+ // Ant Design
24834
+ '[class*="ant-tooltip"]',
24835
+ '[class*="ant-popover"]',
24836
+ // Naive UI
24837
+ '[class*="n-tooltip"]',
24838
+ '[class*="n-popover"]',
24839
+ // Vuetify
24840
+ '[class*="v-tooltip"]',
24841
+ '[class*="v-menu"]'
24842
+ ];
25259
24843
  var TAG_ROLE_MAP = {
25260
24844
  a: "link",
25261
24845
  article: "article",
@@ -25319,6 +24903,7 @@ ${pi.pixels_above > 4 && viewportExpansion !== -1 ? `... ${pi.pixels_above} pixe
25319
24903
  tr: "row",
25320
24904
  ul: "list"
25321
24905
  };
24906
+ var DEFAULT_ROLE_OVERRIDES = [];
25322
24907
  var INPUT_TYPE_ROLE = {
25323
24908
  button: "button",
25324
24909
  checkbox: "checkbox",
@@ -25337,6 +24922,307 @@ ${pi.pixels_above > 4 && viewportExpansion !== -1 ? `... ${pi.pixels_above} pixe
25337
24922
  url: "textbox"
25338
24923
  };
25339
24924
 
24925
+ // ../next-sdk/page-tools/a11y/config.ts
24926
+ var RESOLVED_A11Y_BRAND = Symbol.for("@opentiny/next-sdk:ResolvedA11yConfig");
24927
+ function markResolved(config2) {
24928
+ return Object.assign(config2, { [RESOLVED_A11Y_BRAND]: true });
24929
+ }
24930
+ function isResolvedA11yConfig(config2) {
24931
+ return !!config2 && config2[RESOLVED_A11Y_BRAND] === true;
24932
+ }
24933
+ var STANDARD_STATE_NAMES = [
24934
+ "checked",
24935
+ "selected",
24936
+ "pressed",
24937
+ "current",
24938
+ "expanded",
24939
+ "hasPopup",
24940
+ "disabled",
24941
+ "readonly",
24942
+ "required",
24943
+ "invalid",
24944
+ "busy",
24945
+ "error",
24946
+ "warning"
24947
+ ];
24948
+ var DEFAULT_SELECTED_CLASS_RE = /\b(is-active|isActive|is-selected|isSelected|is-current|isCurrent|active-item|activeItem|tab-active|tabActive|active|selected|current)\b/;
24949
+ function defaultSelectedMatch(el) {
24950
+ const cls = typeof el.className === "string" ? el.className : "";
24951
+ if (!cls || !DEFAULT_SELECTED_CLASS_RE.test(cls)) return false;
24952
+ const role = el.getAttribute("role") || el.tagName.toLowerCase();
24953
+ return ["button", "option", "a", "li", "generic"].includes(role) || role.startsWith("tab");
24954
+ }
24955
+ var DEFAULT_A11Y_CONFIG = markResolved({
24956
+ // 框架级 role 覆盖:Tiny3 Tabs、tp-helptip 等非标准 UI 组件(规则定义见 constants.ts)
24957
+ // + dialog/tooltip 选择器转为 role 规则,统一走 roles 通道做 role 推断与 DOM 检测
24958
+ roles: [
24959
+ ...DEFAULT_ROLE_OVERRIDES,
24960
+ // Dialog:补齐缺失的 role="dialog"(如 Tiny3 ti3-modal、Element Plus el-dialog)
24961
+ ...DEFAULT_DIALOG_SELECTORS.map((s) => ({ selector: s, role: "dialog" })),
24962
+ // Tooltip:补齐缺失的 role="tooltip"(如 Tiny3 ti3-tooltip、Element Plus el-tooltip-popper)
24963
+ ...DEFAULT_TOOLTIP_SELECTORS.map((s) => ({ selector: s, role: "tooltip" }))
24964
+ ],
24965
+ states: {
24966
+ selected: [
24967
+ { match: defaultSelectedMatch },
24968
+ // Tiny3 按钮组/单选按钮组:选中 class 在容器上(.ti3-btn-item-container.ti3-active),
24969
+ // 内部 button 自身无 aria-selected / ti3-active,需靠 closest 命中
24970
+ { selector: ".ti3-btn-item-container.ti3-active" }
24971
+ ],
24972
+ error: [{ selector: DEFAULT_ERROR_SELECTORS }],
24973
+ warning: [{ selector: DEFAULT_WARNING_SELECTORS }]
24974
+ },
24975
+ whitelist: [],
24976
+ blacklist: [],
24977
+ exposedAttributes: []
24978
+ });
24979
+ function normalizeSelector(selector) {
24980
+ if (!selector) return void 0;
24981
+ const joined = Array.isArray(selector) ? selector.filter(Boolean).join(", ") : selector;
24982
+ return joined || void 0;
24983
+ }
24984
+ function getSelectorsForRole(roles, targetRole) {
24985
+ const selectors = [];
24986
+ for (const rule of roles) {
24987
+ if (rule.role !== targetRole || !rule.selector) continue;
24988
+ if (Array.isArray(rule.selector)) {
24989
+ selectors.push(...rule.selector.filter(Boolean));
24990
+ } else {
24991
+ selectors.push(rule.selector);
24992
+ }
24993
+ }
24994
+ return selectors;
24995
+ }
24996
+ function matchesRule(el, rule) {
24997
+ if (rule.match) {
24998
+ try {
24999
+ return !!rule.match(el);
25000
+ } catch {
25001
+ return false;
25002
+ }
25003
+ }
25004
+ const selector = normalizeSelector(rule.selector);
25005
+ if (selector) {
25006
+ try {
25007
+ return !!el.closest(selector);
25008
+ } catch {
25009
+ return false;
25010
+ }
25011
+ }
25012
+ return false;
25013
+ }
25014
+ function matchesRoleRule(el, rule) {
25015
+ if (rule.match) {
25016
+ try {
25017
+ return !!rule.match(el);
25018
+ } catch {
25019
+ return false;
25020
+ }
25021
+ }
25022
+ const selector = normalizeSelector(rule.selector);
25023
+ if (selector) {
25024
+ try {
25025
+ return !!el.matches(selector);
25026
+ } catch {
25027
+ return false;
25028
+ }
25029
+ }
25030
+ return false;
25031
+ }
25032
+ function matchesAnyRule(el, rules) {
25033
+ if (!rules) return false;
25034
+ const list = Array.isArray(rules) ? rules : [rules];
25035
+ return list.some((rule) => matchesRule(el, rule));
25036
+ }
25037
+ function extractSelectors(rules) {
25038
+ if (!rules) return [];
25039
+ const list = Array.isArray(rules) ? rules : [rules];
25040
+ return list.flatMap((r) => Array.isArray(r.selector) ? r.selector.filter(Boolean) : r.selector ? [r.selector] : []);
25041
+ }
25042
+ function concatArr(a, b) {
25043
+ return [...a ?? [], ...b ?? []];
25044
+ }
25045
+ function normalizeMatcherList(value) {
25046
+ if (!value) return [];
25047
+ return Array.isArray(value) ? value : [value];
25048
+ }
25049
+ function mergeStates(base, patch) {
25050
+ const result2 = {};
25051
+ const keys = /* @__PURE__ */ new Set([...Object.keys(base ?? {}), ...Object.keys(patch ?? {})]);
25052
+ for (const key of keys) {
25053
+ result2[key] = [...normalizeMatcherList(base?.[key]), ...normalizeMatcherList(patch?.[key])];
25054
+ }
25055
+ return result2;
25056
+ }
25057
+ function mergeA11yConfigs(base, patch) {
25058
+ return markResolved({
25059
+ roles: concatArr(base.roles, patch.roles),
25060
+ states: mergeStates(base.states, patch.states),
25061
+ whitelist: concatArr(base.whitelist, patch.whitelist),
25062
+ blacklist: concatArr(base.blacklist, patch.blacklist),
25063
+ exposedAttributes: concatArr(base.exposedAttributes, patch.exposedAttributes)
25064
+ });
25065
+ }
25066
+ function mergeA11yConfig(user) {
25067
+ if (isResolvedA11yConfig(user)) return user;
25068
+ return mergeA11yConfigs(DEFAULT_A11Y_CONFIG, user ?? {});
25069
+ }
25070
+ function ensureResolvedA11yConfig(config2) {
25071
+ if (isResolvedA11yConfig(config2)) return config2;
25072
+ return mergeA11yConfig(config2);
25073
+ }
25074
+ function defineA11yConfig(config2) {
25075
+ return config2;
25076
+ }
25077
+ function findMatchedRoleRule(el, resolved) {
25078
+ const explicit = el.getAttribute("role");
25079
+ const hasExplicit = !!explicit && explicit !== "presentation" && explicit !== "none";
25080
+ for (const rule of resolved.roles) {
25081
+ if (hasExplicit && !rule.force) continue;
25082
+ if (matchesRoleRule(el, rule)) return rule;
25083
+ }
25084
+ return null;
25085
+ }
25086
+ function computeRole(el, resolved, matched = findMatchedRoleRule(el, resolved)) {
25087
+ if (matched) return matched.role;
25088
+ const explicit = el.getAttribute("role");
25089
+ if (explicit && explicit !== "presentation" && explicit !== "none") return explicit;
25090
+ const tag = el.tagName.toLowerCase();
25091
+ if (tag === "input") {
25092
+ const inputType = el.type?.toLowerCase() ?? "text";
25093
+ return INPUT_TYPE_ROLE[inputType] ?? "textbox";
25094
+ }
25095
+ return TAG_ROLE_MAP[tag] ?? "generic";
25096
+ }
25097
+ function computeStates(el, resolved) {
25098
+ const tokens = [];
25099
+ const aria = (k) => el.getAttribute(k);
25100
+ const states = resolved.states;
25101
+ const has = (name) => matchesAnyRule(el, states[name]);
25102
+ const ariaChecked = aria("aria-checked");
25103
+ if (ariaChecked === "true") {
25104
+ tokens.push("checked");
25105
+ } else if (ariaChecked === "mixed") {
25106
+ tokens.push("checked=mixed");
25107
+ } else if (ariaChecked === "false") {
25108
+ tokens.push("unchecked");
25109
+ } else {
25110
+ const elTag = el.tagName.toLowerCase();
25111
+ let nativeChecked;
25112
+ if (elTag === "input" && (el.type === "checkbox" || el.type === "radio")) {
25113
+ nativeChecked = el.checked;
25114
+ } else if (elTag === "label" && el.hasAttribute("for")) {
25115
+ const target = document.getElementById(el.getAttribute("for"));
25116
+ if (target instanceof HTMLInputElement && (target.type === "checkbox" || target.type === "radio")) {
25117
+ nativeChecked = target.checked;
25118
+ }
25119
+ }
25120
+ if (nativeChecked !== void 0) {
25121
+ tokens.push(nativeChecked ? "checked" : "unchecked");
25122
+ } else if (has("checked")) {
25123
+ tokens.push("checked");
25124
+ }
25125
+ }
25126
+ if (aria("aria-selected") === "true" || has("selected")) {
25127
+ tokens.push("selected");
25128
+ }
25129
+ const ariaPressed = aria("aria-pressed");
25130
+ if (ariaPressed === "true") {
25131
+ tokens.push("pressed");
25132
+ } else if (ariaPressed === "mixed") {
25133
+ tokens.push("pressed=mixed");
25134
+ } else if (ariaPressed !== "false" && has("pressed")) {
25135
+ tokens.push("pressed");
25136
+ }
25137
+ const ariaCurrent = aria("aria-current");
25138
+ if (ariaCurrent && ariaCurrent !== "false") {
25139
+ tokens.push(ariaCurrent === "true" ? "current" : `current=${ariaCurrent}`);
25140
+ } else if (has("current")) {
25141
+ tokens.push("current");
25142
+ }
25143
+ if (aria("aria-disabled") === "true" || el.disabled || has("disabled")) {
25144
+ tokens.push("disabled");
25145
+ }
25146
+ const ariaHasPopup = aria("aria-haspopup");
25147
+ if (ariaHasPopup && ariaHasPopup !== "false" || has("hasPopup")) {
25148
+ tokens.push("hasPopup");
25149
+ }
25150
+ if (aria("aria-expanded") === "true" || has("expanded")) {
25151
+ tokens.push("expanded");
25152
+ }
25153
+ const ariaInvalid = aria("aria-invalid");
25154
+ if (ariaInvalid && ariaInvalid !== "false") {
25155
+ tokens.push(ariaInvalid === "true" ? "invalid" : `invalid=${ariaInvalid}`);
25156
+ } else if (has("invalid")) {
25157
+ tokens.push("invalid");
25158
+ }
25159
+ if (aria("aria-readonly") === "true" || el.readOnly || has("readonly")) {
25160
+ tokens.push("readonly");
25161
+ }
25162
+ if (aria("aria-required") === "true" || el.required || has("required")) {
25163
+ tokens.push("required");
25164
+ }
25165
+ if (aria("aria-busy") === "true" || has("busy")) {
25166
+ tokens.push("busy");
25167
+ }
25168
+ const orientation = aria("aria-orientation");
25169
+ if (orientation) tokens.push(`orientation=${orientation}`);
25170
+ const sort = aria("aria-sort");
25171
+ if (sort && sort !== "none") tokens.push(`sort=${sort}`);
25172
+ if (aria("aria-multiselectable") === "true") tokens.push("multiselectable");
25173
+ const headingMatch = el.tagName.match(/^H([1-6])$/);
25174
+ if (headingMatch) tokens.push(`level=${headingMatch[1]}`);
25175
+ const ariaLevel = aria("aria-level");
25176
+ if (ariaLevel && !headingMatch) tokens.push(`level=${ariaLevel}`);
25177
+ try {
25178
+ const style = window.getComputedStyle(el);
25179
+ if (style.cursor === "pointer") tokens.push("cursor=pointer");
25180
+ } catch {
25181
+ }
25182
+ const tag = el.tagName.toLowerCase();
25183
+ if (tag === "input" || tag === "textarea" || tag === "select") {
25184
+ const val = el.value;
25185
+ if (val !== void 0 && val !== "") {
25186
+ tokens.push(`value="${val}"`);
25187
+ }
25188
+ }
25189
+ const valuenow = aria("aria-valuenow");
25190
+ if (valuenow) tokens.push(`valuenow="${valuenow}"`);
25191
+ const valuetext = aria("aria-valuetext");
25192
+ if (valuetext) tokens.push(`valuetext="${valuetext}"`);
25193
+ if (tag === "a") {
25194
+ const target = aria("target");
25195
+ if (target) tokens.push(`target=${target}`);
25196
+ }
25197
+ if (has("error")) {
25198
+ tokens.push("error");
25199
+ } else if (has("warning")) {
25200
+ tokens.push("warning");
25201
+ }
25202
+ for (const key of Object.keys(states)) {
25203
+ if (STANDARD_STATE_NAMES.includes(key)) continue;
25204
+ if (matchesAnyRule(el, states[key])) tokens.push(key);
25205
+ }
25206
+ for (const attr of resolved.exposedAttributes) {
25207
+ const val = el.getAttribute(attr);
25208
+ if (val !== null) tokens.push(`${attr}="${val}"`);
25209
+ }
25210
+ return Array.from(new Set(tokens));
25211
+ }
25212
+ function resolveA11yRole(el, config2) {
25213
+ return computeRole(el, ensureResolvedA11yConfig(config2));
25214
+ }
25215
+ function resolveA11yInfo(el, config2) {
25216
+ const resolved = ensureResolvedA11yConfig(config2);
25217
+ const matched = findMatchedRoleRule(el, resolved);
25218
+ const ruleName = matched?.name?.trim();
25219
+ return {
25220
+ role: computeRole(el, resolved, matched),
25221
+ tokens: computeStates(el, resolved),
25222
+ ...ruleName ? { name: ruleName } : {}
25223
+ };
25224
+ }
25225
+
25340
25226
  // ../../node_modules/.pnpm/tabbable@6.5.0/node_modules/tabbable/dist/index.esm.js
25341
25227
  var candidateSelectors = ["input:not([inert]):not([inert] *)", "select:not([inert]):not([inert] *)", "textarea:not([inert]):not([inert] *)", "a[href]:not([inert]):not([inert] *)", "area[href]:not([inert]):not([inert] *)", "button:not([inert]):not([inert] *)", "[tabindex]:not(slot):not([inert]):not([inert] *)", "audio[controls]:not([inert]):not([inert] *)", "video[controls]:not([inert]):not([inert] *)", '[contenteditable]:not([contenteditable="false"]):not([inert]):not([inert] *)', "details>summary:first-of-type:not([inert]):not([inert] *)", "details:not([inert]):not([inert] *)"];
25342
25228
  var candidateSelector = /* @__PURE__ */ candidateSelectors.join(",");
@@ -25538,131 +25424,247 @@ ${pi.pixels_above > 4 && viewportExpansion !== -1 ? `... ${pi.pixels_above} pixe
25538
25424
  return isNodeMatchingSelectorTabbable(options, node);
25539
25425
  };
25540
25426
 
25541
- // ../next-sdk/page-tools/a11y/utils.ts
25542
- function inferRole(el) {
25543
- const explicit = el.getAttribute("role");
25544
- if (explicit && explicit !== "presentation" && explicit !== "none") {
25545
- return explicit;
25427
+ // ../next-sdk/page-tools/tool-config.ts
25428
+ var DEFAULT_PAGE_AGENT_TOOL_CONFIG = {
25429
+ enableHighlight: false,
25430
+ removeMaskAfterToolCall: true,
25431
+ a11yConfig: DEFAULT_A11Y_CONFIG
25432
+ };
25433
+ function getPageAgentToolConfig() {
25434
+ if (typeof window !== "undefined" && window.__webmcpcli_toolConfig) {
25435
+ return window.__webmcpcli_toolConfig;
25546
25436
  }
25547
- const tag = el.tagName.toLowerCase();
25548
- if (tag === "input") {
25549
- const inputType = el.type?.toLowerCase() ?? "text";
25550
- return INPUT_TYPE_ROLE[inputType] ?? "textbox";
25437
+ return {
25438
+ enableHighlight: DEFAULT_PAGE_AGENT_TOOL_CONFIG.enableHighlight,
25439
+ removeMaskAfterToolCall: DEFAULT_PAGE_AGENT_TOOL_CONFIG.removeMaskAfterToolCall,
25440
+ a11yConfig: mergeA11yConfig()
25441
+ };
25442
+ }
25443
+ function resolvePatch(patch, base) {
25444
+ return {
25445
+ enableHighlight: patch.enableHighlight ?? base.enableHighlight,
25446
+ removeMaskAfterToolCall: patch.removeMaskAfterToolCall ?? base.removeMaskAfterToolCall,
25447
+ a11yConfig: mergeA11yConfigs(base.a11yConfig, patch.a11yConfig ?? {})
25448
+ };
25449
+ }
25450
+ function setPageAgentToolConfig(patch, options) {
25451
+ const mode = options?.mode ?? "merge";
25452
+ const current = getPageAgentToolConfig();
25453
+ const next = typeof patch === "function" ? resolvePatch(patch(current), DEFAULT_PAGE_AGENT_TOOL_CONFIG) : resolvePatch(patch, mode === "replace" ? DEFAULT_PAGE_AGENT_TOOL_CONFIG : current);
25454
+ if (typeof window !== "undefined") {
25455
+ window.__webmcpcli_toolConfig = next;
25551
25456
  }
25552
- return TAG_ROLE_MAP[tag] ?? "generic";
25457
+ return next;
25553
25458
  }
25554
- function getStateTokens(el, exposedAttributes, errorSelectors, warningSelectors) {
25555
- const tokens = [];
25556
- const aria = (k) => el.getAttribute(k);
25557
- const ariaChecked = aria("aria-checked");
25558
- if (ariaChecked === "true") {
25559
- tokens.push("checked");
25560
- } else if (ariaChecked === "false") {
25561
- tokens.push("unchecked");
25562
- } else {
25563
- const elTag = el.tagName.toLowerCase();
25564
- let nativeChecked;
25565
- if (elTag === "input" && (el.type === "checkbox" || el.type === "radio")) {
25566
- nativeChecked = el.checked;
25567
- } else if (elTag === "label" && el.hasAttribute("for")) {
25568
- const target = document.getElementById(el.getAttribute("for"));
25569
- if (target instanceof HTMLInputElement && (target.type === "checkbox" || target.type === "radio")) {
25570
- nativeChecked = target.checked;
25571
- }
25572
- }
25573
- if (nativeChecked !== void 0) {
25574
- tokens.push(nativeChecked ? "checked" : "unchecked");
25575
- }
25576
- }
25577
- if (aria("aria-selected") === "true") tokens.push("selected");
25578
- const disabled = aria("aria-disabled") === "true" || el.disabled;
25579
- if (disabled) tokens.push("disabled");
25580
- const hasPopup = aria("aria-haspopup");
25581
- if (hasPopup && hasPopup !== "false") tokens.push("hasPopup");
25582
- if (aria("aria-expanded") === "true") tokens.push("expanded");
25583
- const headingMatch = el.tagName.match(/^H([1-6])$/);
25584
- if (headingMatch) tokens.push(`level=${headingMatch[1]}`);
25585
- const ariaLevel = aria("aria-level");
25586
- if (ariaLevel && !headingMatch) tokens.push(`level=${ariaLevel}`);
25587
- try {
25588
- const style = window.getComputedStyle(el);
25589
- if (style.cursor === "pointer") tokens.push("cursor=pointer");
25590
- } catch {
25459
+
25460
+ // ../next-sdk/page-tools/utils/dom.ts
25461
+ function isInShadowDom(el) {
25462
+ return el.getRootNode() instanceof ShadowRoot;
25463
+ }
25464
+ function dispatchComposedEvents(el, ...types) {
25465
+ for (const type of types) {
25466
+ el.dispatchEvent(new Event(type, { bubbles: true, composed: true }));
25591
25467
  }
25592
- const tag = el.tagName.toLowerCase();
25593
- if (tag === "input" || tag === "textarea" || tag === "select") {
25594
- const val = el.value;
25595
- if (val !== void 0 && val !== "") {
25596
- tokens.push(`value="${val}"`);
25468
+ }
25469
+ function deepQuerySelectorAll(selector, root = document) {
25470
+ const elements = Array.from(root.querySelectorAll(selector));
25471
+ const walker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT, null);
25472
+ let currentNode = walker.currentNode;
25473
+ while (currentNode) {
25474
+ if (currentNode.shadowRoot) {
25475
+ elements.push(...deepQuerySelectorAll(selector, currentNode.shadowRoot));
25597
25476
  }
25477
+ currentNode = walker.nextNode();
25598
25478
  }
25599
- const valuenow = el.getAttribute("aria-valuenow");
25600
- if (valuenow) {
25601
- tokens.push(`valuenow="${valuenow}"`);
25479
+ return elements;
25480
+ }
25481
+ function waitForDomSettled(timeout = 600, settleTime = 150) {
25482
+ return new Promise((resolve) => {
25483
+ let settled = false;
25484
+ let settleTimer;
25485
+ const finish = () => {
25486
+ if (settled) return;
25487
+ settled = true;
25488
+ observer.disconnect();
25489
+ if (settleTimer) clearTimeout(settleTimer);
25490
+ resolve();
25491
+ };
25492
+ const observer = new MutationObserver(() => {
25493
+ if (settleTimer) clearTimeout(settleTimer);
25494
+ settleTimer = setTimeout(finish, settleTime);
25495
+ });
25496
+ settleTimer = setTimeout(finish, settleTime);
25497
+ setTimeout(finish, timeout);
25498
+ observer.observe(document.body, {
25499
+ childList: true,
25500
+ subtree: true,
25501
+ attributes: true,
25502
+ attributeFilter: ["class", "style", "hidden"]
25503
+ });
25504
+ });
25505
+ }
25506
+ function detectPageDialog() {
25507
+ const seen = /* @__PURE__ */ new Set();
25508
+ const dialogs = [];
25509
+ const selectors = getSelectorsForRole(getPageAgentToolConfig().a11yConfig.roles, "dialog");
25510
+ for (const selector of selectors) {
25511
+ try {
25512
+ for (const el of deepQuerySelectorAll(selector)) {
25513
+ if (seen.has(el)) continue;
25514
+ if (el.id?.includes("page-agent-runtime")) continue;
25515
+ if (el.closest("#page-agent-runtime_simulator-mask")) continue;
25516
+ const rect = el.getBoundingClientRect();
25517
+ if (rect.width < 50 || rect.height < 50) continue;
25518
+ const style = window.getComputedStyle(el);
25519
+ if (style.display === "none" || style.visibility === "hidden") continue;
25520
+ const isFixed = style.position === "fixed" || style.position === "absolute";
25521
+ const zIndex = parseInt(style.zIndex || "0", 10);
25522
+ if (!isFixed || zIndex < 100) continue;
25523
+ const vw = window.innerWidth;
25524
+ const vh = window.innerHeight;
25525
+ const coversCenter = rect.left < vw * 0.6 && rect.right > vw * 0.4 && rect.top < vh * 0.6 && rect.bottom > vh * 0.4;
25526
+ if (!coversCenter) continue;
25527
+ seen.add(el);
25528
+ const text = (el.textContent || "").trim().replace(/\s+/g, " ");
25529
+ if (text.length > 5) {
25530
+ const btns = el.querySelectorAll('button, [role="button"], a');
25531
+ const buttons = Array.from(btns).map((b) => (b.textContent || "").trim()).filter((t) => t.length > 0 && t.length < 20).slice(0, 5);
25532
+ dialogs.push({ text: text.substring(0, 300), buttons });
25533
+ }
25534
+ }
25535
+ } catch {
25536
+ }
25602
25537
  }
25603
- if (el.tagName.toLowerCase() === "a" && el.getAttribute("target") === "_blank") {
25604
- tokens.push("opens-new-tab");
25538
+ return dialogs;
25539
+ }
25540
+ function detectValidationErrors() {
25541
+ const seen = /* @__PURE__ */ new Set();
25542
+ const errors = [];
25543
+ const selectors = extractSelectors(getPageAgentToolConfig().a11yConfig.states.error);
25544
+ for (const selector of selectors) {
25545
+ try {
25546
+ for (const el of deepQuerySelectorAll(selector)) {
25547
+ if (seen.has(el)) continue;
25548
+ if (Array.from(seen).some((s) => s.contains(el))) continue;
25549
+ const rect = el.getBoundingClientRect();
25550
+ if (rect.width < 1 || rect.height < 1) continue;
25551
+ const style = window.getComputedStyle(el);
25552
+ if (style.display === "none" || style.visibility === "hidden") continue;
25553
+ const text = (el.textContent || "").trim().replace(/\s+/g, " ");
25554
+ if (text.length > 2 && text.length < 200) {
25555
+ seen.add(el);
25556
+ errors.push(text);
25557
+ }
25558
+ }
25559
+ } catch {
25560
+ }
25605
25561
  }
25606
- const cls = typeof el.className === "string" ? el.className : "";
25607
- const ACTIVE_CLASS_PATTERNS = [
25608
- "is-active",
25609
- "isActive",
25610
- "is-selected",
25611
- "isSelected",
25612
- "is-current",
25613
- "isCurrent",
25614
- "active-item",
25615
- "activeItem",
25616
- "tab-active",
25617
- "tabActive",
25618
- // 仅当作为独立 class 词或有连字符前缀时匹配 "active",避免误匹配 "interactive" 等
25619
- /\bactive\b/,
25620
- /\bselected\b/,
25621
- /\bcurrent\b/
25622
- ];
25623
- const hasActiveClass = ACTIVE_CLASS_PATTERNS.some(
25624
- (p) => typeof p === "string" ? cls.split(/\s+/).includes(p) : p.test(cls)
25625
- );
25626
- const roleForActive = el.getAttribute("role") || el.tagName.toLowerCase();
25627
- const roles = roleForActive.split(/\s+/);
25628
- const isTabLike = roles.some((r) => ["button", "option", "a", "li", "generic"].includes(r) || r.startsWith("tab"));
25629
- if (hasActiveClass && isTabLike && !tokens.includes("checked") && !tokens.includes("selected")) {
25630
- tokens.push("active");
25631
- }
25632
- const errorSelector = Array.isArray(errorSelectors) ? errorSelectors.join(", ") : errorSelectors || DEFAULT_ERROR_SELECTORS.join(", ");
25633
- const warningSelector = Array.isArray(warningSelectors) ? warningSelectors.join(", ") : warningSelectors || DEFAULT_WARNING_SELECTORS.join(", ");
25634
- let errorAncestor = null;
25635
- if (errorSelector) {
25562
+ return errors;
25563
+ }
25564
+ function getVisibleTooltipElements() {
25565
+ const seen = /* @__PURE__ */ new Set();
25566
+ const tooltips = [];
25567
+ const selectors = getSelectorsForRole(getPageAgentToolConfig().a11yConfig.roles, "tooltip");
25568
+ for (const selector of selectors) {
25636
25569
  try {
25637
- errorAncestor = el.closest(errorSelector);
25570
+ for (const el of deepQuerySelectorAll(selector)) {
25571
+ if (seen.has(el)) continue;
25572
+ if (Array.from(seen).some((s) => s.contains(el))) continue;
25573
+ const rect = el.getBoundingClientRect();
25574
+ if (rect.width < 1 || rect.height < 1) continue;
25575
+ const style = window.getComputedStyle(el);
25576
+ if (style.display === "none" || style.visibility === "hidden" || style.opacity === "0") continue;
25577
+ const text = (el.textContent || "").trim().replace(/\s+/g, " ");
25578
+ if (text.length > 1) {
25579
+ if (el.querySelector?.('[name="cloudx-action-help"]')) continue;
25580
+ seen.add(el);
25581
+ tooltips.push({ el, text });
25582
+ }
25583
+ }
25638
25584
  } catch {
25639
25585
  }
25640
25586
  }
25641
- if (errorAncestor) {
25642
- tokens.push("error");
25643
- } else {
25644
- let warningAncestor = null;
25645
- if (warningSelector) {
25587
+ return tooltips;
25588
+ }
25589
+ function detectVisibleTooltips() {
25590
+ return getVisibleTooltipElements().map((t) => t.text);
25591
+ }
25592
+
25593
+ // ../next-sdk/page-tools/a11y/utils.ts
25594
+ var NON_CONTENT_TAGS = /* @__PURE__ */ new Set([
25595
+ "script",
25596
+ "style",
25597
+ "noscript",
25598
+ "template",
25599
+ "link",
25600
+ "meta",
25601
+ "head",
25602
+ "title"
25603
+ ]);
25604
+ function isNonContentElement(el) {
25605
+ return NON_CONTENT_TAGS.has(el.tagName.toLowerCase());
25606
+ }
25607
+ function hasOwnPointerCursor(el) {
25608
+ try {
25609
+ if (window.getComputedStyle(el).cursor !== "pointer") return false;
25610
+ const parent = el.parentElement;
25611
+ if (!parent) return true;
25612
+ return window.getComputedStyle(parent).cursor !== "pointer";
25613
+ } catch {
25614
+ return false;
25615
+ }
25616
+ }
25617
+ var INTERACTION_PSEUDO_RE = /:(hover|focus|focus-visible|focus-within|active)\b/gi;
25618
+ function collectInteractivePointerSelectors(rules, out) {
25619
+ for (const rule of Array.from(rules)) {
25620
+ const styleRule = rule;
25621
+ const grouping = rule;
25622
+ if (!styleRule.selectorText && grouping.cssRules) {
25623
+ collectInteractivePointerSelectors(grouping.cssRules, out);
25624
+ continue;
25625
+ }
25626
+ const sel = styleRule.selectorText;
25627
+ if (!sel || !styleRule.style || styleRule.style.cursor !== "pointer") continue;
25628
+ if (!/:(hover|focus|focus-visible|focus-within|active)\b/i.test(sel)) continue;
25629
+ for (const part of sel.split(",")) {
25630
+ const base = part.replace(INTERACTION_PSEUDO_RE, "").trim();
25631
+ if (base && base !== "*") out.add(base);
25632
+ }
25633
+ }
25634
+ }
25635
+ function collectHoverPointerElements(root) {
25636
+ const set = /* @__PURE__ */ new Set();
25637
+ const selectorSet = /* @__PURE__ */ new Set();
25638
+ try {
25639
+ for (const sheet of Array.from(document.styleSheets)) {
25640
+ let rules = null;
25646
25641
  try {
25647
- warningAncestor = el.closest(warningSelector);
25642
+ rules = sheet.cssRules;
25648
25643
  } catch {
25644
+ continue;
25649
25645
  }
25646
+ if (rules) collectInteractivePointerSelectors(rules, selectorSet);
25650
25647
  }
25651
- if (warningAncestor) {
25652
- tokens.push("warning");
25653
- }
25648
+ } catch {
25649
+ return set;
25654
25650
  }
25655
- if (exposedAttributes) {
25656
- for (const attr of exposedAttributes) {
25657
- const val = el.getAttribute(attr);
25658
- if (val !== null) {
25659
- tokens.push(`${attr}="${val}"`);
25651
+ if (selectorSet.size === 0) return set;
25652
+ const selectors = Array.from(selectorSet);
25653
+ try {
25654
+ for (const el of deepQuerySelectorAll(selectors.join(", "), root)) set.add(el);
25655
+ return set;
25656
+ } catch {
25657
+ for (const sel of selectors) {
25658
+ try {
25659
+ for (const el of deepQuerySelectorAll(sel, root)) set.add(el);
25660
+ } catch {
25660
25661
  }
25661
25662
  }
25662
25663
  }
25663
- return tokens;
25664
+ return set;
25664
25665
  }
25665
25666
  function isHidden3(el) {
25667
+ if (isNonContentElement(el)) return true;
25666
25668
  if (el.getAttribute("aria-hidden") === "true") return true;
25667
25669
  if (el.hidden) return true;
25668
25670
  try {
@@ -25677,26 +25679,32 @@ ${pi.pixels_above > 4 && viewportExpansion !== -1 ? `... ${pi.pixels_above} pixe
25677
25679
  }
25678
25680
  return false;
25679
25681
  }
25680
- function collectDescendantText(el) {
25682
+ function collectTitleLabel(el) {
25683
+ const selfTitle = el.getAttribute("title")?.trim();
25684
+ if (selfTitle) return selfTitle;
25685
+ const titled = el.querySelector("[title]");
25686
+ const childTitle = titled?.getAttribute("title")?.trim();
25687
+ if (childTitle) return childTitle;
25688
+ return "";
25689
+ }
25690
+ function collectDescendantText(el, config2) {
25681
25691
  let text = "";
25682
25692
  const walk = (node) => {
25683
25693
  if (node.nodeType === Node.TEXT_NODE) {
25684
25694
  text += (node.textContent ?? "") + " ";
25685
25695
  } else if (node.nodeType === Node.ELEMENT_NODE) {
25686
25696
  const element = node;
25687
- if (isHidden3(element)) return;
25697
+ if (element !== el && isNonContentElement(element)) return;
25698
+ if (isHidden3(element) && element !== el) return;
25699
+ if (element === el && isNonContentElement(element)) return;
25688
25700
  if (element !== el) {
25689
25701
  const tag = element.tagName.toLowerCase();
25690
- const role = inferRole(element);
25702
+ const role = resolveA11yRole(element, config2);
25691
25703
  const isInteractiveTag = ["button", "a", "input", "select", "textarea", "li", "option"].includes(tag);
25692
25704
  const isInteractiveRole = ["button", "link", "checkbox", "radio", "textbox", "listitem", "option", "combobox", "listbox"].includes(role);
25693
25705
  const isTrulyInteractive = isTabbable(element);
25694
- let isCursorPointer = false;
25695
- try {
25696
- isCursorPointer = window.getComputedStyle(element).cursor === "pointer";
25697
- } catch {
25698
- }
25699
- const isMeaningfullyInteractive = isTrulyInteractive && !(role === "generic" && !isCursorPointer);
25706
+ const isOwnPointer = hasOwnPointerCursor(element);
25707
+ const isMeaningfullyInteractive = isTrulyInteractive && !(role === "generic" && !isOwnPointer);
25700
25708
  if (isMeaningfullyInteractive || isInteractiveTag || isInteractiveRole) {
25701
25709
  return;
25702
25710
  }
@@ -25722,6 +25730,46 @@ ${pi.pixels_above > 4 && viewportExpansion !== -1 ? `... ${pi.pixels_above} pixe
25722
25730
  }
25723
25731
  return result2;
25724
25732
  }
25733
+ function extractTooltipText(el) {
25734
+ const title = el.getAttribute("title");
25735
+ if (title && title.trim()) {
25736
+ return title.trim().replace(/"/g, '\\"').substring(0, 200);
25737
+ }
25738
+ const describedby = el.getAttribute("aria-describedby");
25739
+ if (describedby) {
25740
+ for (const id of describedby.split(/\s+/)) {
25741
+ const ref = document.getElementById(id);
25742
+ if (ref) {
25743
+ const text = (ref.textContent || "").trim().replace(/\s+/g, " ");
25744
+ if (text) {
25745
+ return text.replace(/"/g, '\\"').substring(0, 200);
25746
+ }
25747
+ }
25748
+ }
25749
+ }
25750
+ for (const attr of ["data-tooltip", "data-tips", "data-tip"]) {
25751
+ const val = el.getAttribute(attr);
25752
+ if (val && val.trim()) {
25753
+ return val.trim().replace(/"/g, '\\"').substring(0, 200);
25754
+ }
25755
+ }
25756
+ const tag = el.tagName.toLowerCase();
25757
+ if (tag === "tp-helptip" || el.closest("tp-helptip")) {
25758
+ const helptipRoot = tag === "tp-helptip" ? el : el.closest("tp-helptip");
25759
+ const label = helptipRoot.querySelector('.tp-helptip-label, [class*="tp-helptip-label"]');
25760
+ if (label) {
25761
+ const text = (label.textContent || "").trim();
25762
+ if (text) {
25763
+ return text.replace(/"/g, '\\"').substring(0, 200);
25764
+ }
25765
+ }
25766
+ }
25767
+ const matTooltip = el.getAttribute("mattooltip") || el.getAttribute("matTooltip");
25768
+ if (matTooltip && matTooltip.trim()) {
25769
+ return matTooltip.trim().replace(/"/g, '\\"').substring(0, 200);
25770
+ }
25771
+ return "";
25772
+ }
25725
25773
 
25726
25774
  // ../../node_modules/.pnpm/dom-accessibility-api@0.6.3/node_modules/dom-accessibility-api/dist/polyfills/array.from.mjs
25727
25775
  var toStr = Object.prototype.toString;
@@ -26512,43 +26560,95 @@ ${pi.pixels_above > 4 && viewportExpansion !== -1 ? `... ${pi.pixels_above} pixe
26512
26560
  }
26513
26561
 
26514
26562
  // ../next-sdk/page-tools/a11y/vnode.ts
26515
- function buildVNode(el, refCounter, refMap, blacklistSet, whitelistSet, exposedAttributes, errorSelectors, warningSelectors, ancestorIsInteractive = false) {
26516
- if (isHidden3(el) || blacklistSet.has(el)) return null;
26517
- const role = inferRole(el);
26518
- const tokens = getStateTokens(el, exposedAttributes, errorSelectors, warningSelectors);
26519
- let name = computeAccessibleName(el);
26563
+ var INTERACTIVE_ROLES = /* @__PURE__ */ new Set([
26564
+ "button",
26565
+ "link",
26566
+ "textbox",
26567
+ "searchbox",
26568
+ "combobox",
26569
+ "listbox",
26570
+ "checkbox",
26571
+ "radio",
26572
+ "switch",
26573
+ "slider",
26574
+ "spinbutton",
26575
+ "menuitem",
26576
+ "menuitemcheckbox",
26577
+ "menuitemradio",
26578
+ "tab",
26579
+ "treeitem"
26580
+ ]);
26581
+ function buildVNode(el, refCounter, refMap, blacklistSet, whitelistSet, config2, hoverPointerSet = /* @__PURE__ */ new Set()) {
26582
+ if (isNonContentElement(el) || isHidden3(el) || blacklistSet.has(el)) return null;
26583
+ const { role, tokens, name: ruleName } = resolveA11yInfo(el, config2);
26584
+ const declaredName = typeof ruleName === "string" && ruleName.trim() || getOwnDeclaredName(el) || "";
26585
+ const tooltipText = extractTooltipText(el);
26586
+ if (tooltipText) {
26587
+ tokens.push(`tooltip="${tooltipText}"`);
26588
+ }
26589
+ const hasTooltip = tokens.some((t) => t.startsWith("tooltip="));
26590
+ let name = declaredName || computeAccessibleName(el);
26520
26591
  const isTrulyInteractive = isTabbable(el);
26521
26592
  const isVisuallyClickable = tokens.includes("cursor=pointer");
26522
- const isWhitelisted = whitelistSet.has(el) || (exposedAttributes?.some((attr) => el.hasAttribute(attr)) ?? false);
26593
+ const hasClickableCursor = hasOwnPointerCursor(el) || hoverPointerSet.has(el);
26594
+ const isWhitelisted = whitelistSet.has(el);
26523
26595
  const isLabelFor = el.tagName.toLowerCase() === "label" && el.hasAttribute("for");
26524
26596
  if (!name.trim()) {
26525
26597
  const tag = el.tagName.toLowerCase();
26526
26598
  const isDropdown = tag === "select" || role === "combobox" || role === "listbox";
26527
26599
  if (!isDropdown) {
26528
26600
  const isInteractiveTag = ["button", "a", "input", "textarea", "li", "label"].includes(tag);
26529
- if (isTrulyInteractive || isWhitelisted || isVisuallyClickable || isInteractiveTag || role === "listitem" || role === "option") {
26530
- name = collectDescendantText(el);
26601
+ if (isTrulyInteractive || isWhitelisted || isVisuallyClickable || hasClickableCursor || isInteractiveTag || role === "listitem" || role === "option" || role === "button") {
26602
+ name = collectDescendantText(el, config2);
26531
26603
  }
26532
26604
  }
26533
26605
  }
26606
+ if (!name.trim() && (isTrulyInteractive || isWhitelisted || isVisuallyClickable || hasClickableCursor || role === "button")) {
26607
+ name = collectTitleLabel(el);
26608
+ }
26609
+ if (!name.trim() && role === "button") {
26610
+ const iconName = el.getAttribute("name") || "";
26611
+ if (iconName.includes("help") || iconName.includes("tip") || iconName.includes("info")) {
26612
+ name = "\u5E2E\u52A9";
26613
+ }
26614
+ }
26615
+ if (!name.trim() && hasTooltip) {
26616
+ const tooltipToken = tokens.find((t) => t.startsWith("tooltip="));
26617
+ if (tooltipToken) {
26618
+ name = tooltipToken.replace(/^tooltip="/, "").replace(/"$/, "");
26619
+ }
26620
+ }
26621
+ if (!name.trim() && ["tab", "menuitem", "option", "treeitem", "button"].includes(role)) {
26622
+ name = collectVisiblePlainText(el);
26623
+ }
26534
26624
  if (!name.trim()) {
26535
26625
  const hasElementChildren = getComposedChildren(el).length > 0;
26536
26626
  if (!hasElementChildren) {
26537
- const text = collectDescendantText(el);
26627
+ const text = collectDescendantText(el, config2);
26538
26628
  if (text) {
26539
26629
  name = text;
26540
26630
  }
26541
26631
  }
26542
26632
  }
26543
26633
  const tagName = el.tagName.toLowerCase();
26544
- const isSemanticInteractiveTag = tagName === "a" && el.hasAttribute("href") || ["button", "input", "select", "textarea"].includes(tagName) && !el.hasAttribute("disabled");
26545
- const isMeaningfullyInteractive = isTrulyInteractive && !(role === "generic" && !isVisuallyClickable);
26546
- const interactive = isMeaningfullyInteractive || isWhitelisted || isLabelFor || isSemanticInteractiveTag || !ancestorIsInteractive && isVisuallyClickable && (role !== "generic" || name !== "");
26634
+ const isSemanticInteractiveTag = tagName === "a" && el.hasAttribute("href") || ["button", "input", "select", "textarea"].includes(tagName) && !el.hasAttribute("disabled") || role === "button" && isVisuallyClickable && !["button", "a", "input", "select", "textarea"].includes(tagName);
26635
+ const isMeaningfullyInteractive = isTrulyInteractive && !(role === "generic" && !hasClickableCursor);
26636
+ const isDisabled2 = tokens.includes("disabled");
26637
+ const interactive = !isDisabled2 && isMeaningfullyInteractive || isWhitelisted || isLabelFor || isSemanticInteractiveTag || !isDisabled2 && INTERACTIVE_ROLES.has(role) || // hasClickableCursor 已排除 CSS 继承(hasOwnPointerCursor)并覆盖 hover 态手势,
26638
+ // 无需再要求 role≠generic 或 name≠''——否则无文本的图标按钮(tp-icon.common-icon 等)
26639
+ // 虽是真正的可点击边界,仍会因 generic+空名被漏判。
26640
+ !isDisabled2 && hasClickableCursor || // 有 tooltip 的元素分配 ref,使 AI 能 hover 触发动态 tip
26641
+ hasTooltip;
26547
26642
  let ref;
26548
26643
  if (interactive) {
26549
26644
  ref = refCounter.value;
26550
26645
  refMap.set(ref, el);
26551
26646
  refCounter.value++;
26647
+ const idVal = el.getAttribute("id");
26648
+ if (idVal) {
26649
+ const idToken = `id="${idVal}"`;
26650
+ if (!tokens.includes(idToken)) tokens.push(idToken);
26651
+ }
26552
26652
  }
26553
26653
  const children = [];
26554
26654
  for (const child of getComposedChildren(el)) {
@@ -26558,15 +26658,113 @@ ${pi.pixels_above > 4 && viewportExpansion !== -1 ? `... ${pi.pixels_above} pixe
26558
26658
  refMap,
26559
26659
  blacklistSet,
26560
26660
  whitelistSet,
26561
- exposedAttributes,
26562
- errorSelectors,
26563
- warningSelectors,
26564
- // 将当前节点的交互性向下传递,子节点据此决定是否抑制 cursor=pointer
26565
- interactive || ancestorIsInteractive
26661
+ config2,
26662
+ hoverPointerSet
26566
26663
  );
26567
26664
  if (childVNode) children.push(childVNode);
26568
26665
  }
26569
- return { role, name, tokens, ref, el, children };
26666
+ const vnode = {
26667
+ role,
26668
+ name,
26669
+ ...declaredName ? { declaredName } : {},
26670
+ tokens,
26671
+ ref,
26672
+ el,
26673
+ children
26674
+ };
26675
+ if (hasInteractiveDescendant(vnode)) {
26676
+ vnode.name = declaredName || getOwnDeclaredName(el);
26677
+ }
26678
+ return vnode;
26679
+ }
26680
+ function resolveDeclaredName(vnode) {
26681
+ if (vnode.declaredName?.trim()) return vnode.declaredName.trim();
26682
+ return getOwnDeclaredName(vnode.el);
26683
+ }
26684
+ function getOwnDeclaredName(el) {
26685
+ if (el.hasAttribute("aria-label") || el.hasAttribute("aria-labelledby")) {
26686
+ return computeAccessibleName(el).trim();
26687
+ }
26688
+ return "";
26689
+ }
26690
+ function isStaticBranch(vnode) {
26691
+ return vnode.ref === void 0 && !hasInteractiveDescendant(vnode);
26692
+ }
26693
+ var LANDMARK_ROLES = /* @__PURE__ */ new Set([
26694
+ "banner",
26695
+ "complementary",
26696
+ "contentinfo",
26697
+ "form",
26698
+ "main",
26699
+ "navigation",
26700
+ "region",
26701
+ "search"
26702
+ ]);
26703
+ function isStructuralNamedNode(vnode) {
26704
+ return !!vnode.declaredName?.trim() || LANDMARK_ROLES.has(vnode.role);
26705
+ }
26706
+ function isEmptyLandmarkShell(vnode, hasInteractive) {
26707
+ if (!isStructuralNamedNode(vnode) || vnode.ref !== void 0 || hasInteractive) return false;
26708
+ if (vnode.children.some(hasValue)) return false;
26709
+ if (collectDirectTextNodes(vnode.el).trim()) return false;
26710
+ const declared = resolveDeclaredName(vnode);
26711
+ const name = vnode.name.trim();
26712
+ if (name && declared && name !== declared) return false;
26713
+ if (name && !declared) return false;
26714
+ return true;
26715
+ }
26716
+ function containsStructuralNamed(vnode) {
26717
+ return vnode.children.some((c) => isStructuralNamedNode(c) || containsStructuralNamed(c));
26718
+ }
26719
+ function collectVisiblePlainText(el) {
26720
+ return collectDescendantText(el).replace(/\s+/g, " ").trim();
26721
+ }
26722
+ function collectDirectTextNodes(el) {
26723
+ let text = "";
26724
+ for (const node of Array.from(el.childNodes)) {
26725
+ if (node.nodeType === Node.TEXT_NODE) {
26726
+ text += (node.textContent ?? "") + " ";
26727
+ }
26728
+ }
26729
+ return text.replace(/\s+/g, " ").trim();
26730
+ }
26731
+ function getStaticDisplayText(vnode) {
26732
+ if (isStructuralNamedNode(vnode)) {
26733
+ return "";
26734
+ }
26735
+ const childJoined = vnode.children.length > 0 ? vnode.children.filter((c) => !isStructuralNamedNode(c)).map(getStaticDisplayText).filter(Boolean).join(" ").replace(/\s+/g, " ").trim() : "";
26736
+ const plain = vnode.children.length === 0 ? collectVisiblePlainText(vnode.el) : "";
26737
+ const named = vnode.name.trim();
26738
+ const parts = [];
26739
+ if (named && !isNoiseAccessibleName(named)) parts.push(named);
26740
+ if (childJoined && !isNoiseAccessibleName(childJoined)) {
26741
+ const normNamed = named.replace(/\s+/g, " ").trim();
26742
+ const normChild = childJoined.replace(/\s+/g, " ").trim();
26743
+ if (!normNamed || normChild !== normNamed && !normNamed.includes(normChild)) {
26744
+ parts.push(childJoined);
26745
+ }
26746
+ }
26747
+ if (parts.length === 0 && plain && !isNoiseAccessibleName(plain)) parts.push(plain);
26748
+ return parts.join(" ").replace(/\s+/g, " ").trim();
26749
+ }
26750
+ function isNoiseAccessibleName(name) {
26751
+ const n = name.trim();
26752
+ if (!n) return false;
26753
+ if (/@font-face\b/i.test(n)) return true;
26754
+ if (/data:(?:font|application|image)\//i.test(n)) return true;
26755
+ if (/base64,[A-Za-z0-9+/=]{80,}/.test(n)) return true;
26756
+ return false;
26757
+ }
26758
+ function canOmitStaticChild(child, parentOutputName, parentUsesOwnDeclaredName) {
26759
+ if (isStructuralNamedNode(child)) return false;
26760
+ const text = getStaticDisplayText(child);
26761
+ if (!text || !parentOutputName.trim()) return false;
26762
+ const parentNorm = parentOutputName.replace(/\s+/g, " ").trim();
26763
+ const textNorm = text.replace(/\s+/g, " ").trim();
26764
+ if (parentUsesOwnDeclaredName) {
26765
+ return textNorm === parentNorm;
26766
+ }
26767
+ return parentNorm.includes(textNorm);
26570
26768
  }
26571
26769
  function hasValue(vnode) {
26572
26770
  if (vnode.ref !== void 0 || vnode.name.trim() !== "") return true;
@@ -26592,31 +26790,68 @@ ${pi.pixels_above > 4 && viewportExpansion !== -1 ? `... ${pi.pixels_above} pixe
26592
26790
  if (vnode.name.trim() !== "") return false;
26593
26791
  return true;
26594
26792
  }
26793
+ function formatNameAttr(name) {
26794
+ const safe = name.replace(/[\r\n]+/g, " ").replace(/"/g, '\\"').trim();
26795
+ return safe ? ` "${safe}"` : "";
26796
+ }
26595
26797
  function serializeVNode(vnode, depth, opts) {
26596
- if (shouldPassThrough(vnode, opts)) {
26597
- return vnode.children.filter((c) => hasValue(c)).flatMap((c) => serializeVNode(c, depth, opts));
26598
- }
26798
+ const hasInteractive = hasInteractiveDescendant(vnode);
26799
+ const forceKeepStructure = opts.preserveRoles.includes(vnode.role) || isStructuralNamedNode(vnode);
26599
26800
  const indent = " ".repeat(depth);
26600
26801
  const refStr = vnode.ref !== void 0 ? ` #${vnode.ref}` : "";
26601
26802
  const safeTokens = vnode.tokens.map((t) => t.replace(/[\r\n]+/g, " ").replace(/"/g, '\\"'));
26602
26803
  const tokenStr = safeTokens.length > 0 ? ` [${safeTokens.join(" ")}]` : "";
26603
- if (vnode.ref !== void 0) {
26604
- if (!hasInteractiveDescendant(vnode)) {
26605
- const safeName2 = vnode.name ? vnode.name.replace(/[\r\n]+/g, " ").replace(/"/g, '\\"') : "";
26606
- const nameStr2 = safeName2 ? ` "${safeName2}"` : "";
26607
- return [`${indent}- ${vnode.role}${refStr}${tokenStr}${nameStr2}`];
26804
+ if (isEmptyLandmarkShell(vnode, hasInteractive)) {
26805
+ return [];
26806
+ }
26807
+ if (!hasInteractive && !forceKeepStructure) {
26808
+ if (shouldPassThrough(vnode, opts)) {
26809
+ return vnode.children.filter((c) => hasValue(c)).flatMap((c) => serializeVNode(c, depth, opts));
26608
26810
  }
26811
+ let displayName = vnode.name.trim();
26812
+ if (!displayName && vnode.children.length > 0) {
26813
+ displayName = collectVisiblePlainText(vnode.el);
26814
+ }
26815
+ if (isNoiseAccessibleName(displayName)) displayName = "";
26816
+ return [`${indent}- ${vnode.role}${refStr}${tokenStr}${formatNameAttr(displayName)}`];
26817
+ }
26818
+ if (!hasInteractive && forceKeepStructure) {
26819
+ const outputName2 = resolveDeclaredName(vnode);
26820
+ const line2 = `${indent}- ${vnode.role}${refStr}${tokenStr}${formatNameAttr(outputName2)}`;
26821
+ const childLines2 = vnode.children.flatMap((c) => serializeVNode(c, depth + 1, opts));
26822
+ return [line2, ...childLines2];
26823
+ }
26824
+ const ownDeclaredName = resolveDeclaredName(vnode);
26825
+ const parentUsesOwnDeclaredName = ownDeclaredName !== "";
26826
+ const staticChildren = vnode.children.filter(
26827
+ (c) => isStaticBranch(c) && !isStructuralNamedNode(c) && !containsStructuralNamed(c)
26828
+ );
26829
+ const liftedStaticName = staticChildren.map(getStaticDisplayText).filter(Boolean).join(" ").replace(/\s+/g, " ").trim();
26830
+ const liftedDirectText = collectDirectTextNodes(vnode.el);
26831
+ const effectiveLifted = [liftedStaticName, liftedDirectText].filter(Boolean).join(" ").replace(/\s+/g, " ").trim();
26832
+ let outputName = parentUsesOwnDeclaredName ? ownDeclaredName : effectiveLifted;
26833
+ if (isNoiseAccessibleName(outputName)) outputName = "";
26834
+ if (!parentUsesOwnDeclaredName && isNoiseAccessibleName(vnode.name)) {
26835
+ outputName = effectiveLifted && !isNoiseAccessibleName(effectiveLifted) ? effectiveLifted : "";
26836
+ }
26837
+ const willEmitParent = vnode.ref !== void 0 || outputName !== "" || forceKeepStructure || !opts.pruneUnnamed;
26838
+ if (!willEmitParent) {
26839
+ return vnode.children.filter((c) => hasValue(c)).flatMap((c) => serializeVNode(c, depth, opts));
26840
+ }
26841
+ if (vnode.ref !== void 0) {
26609
26842
  const singleChild = findSingleRefDescendant(vnode);
26610
- if (singleChild && singleChild.role === "generic" && !hasInteractiveDescendant(singleChild)) {
26611
- const mergedName = (vnode.name.trim() || singleChild.name.trim()).replace(/[\r\n]+/g, " ").replace(/"/g, '\\"');
26612
- const nameStr2 = mergedName ? ` "${mergedName}"` : "";
26613
- return [`${indent}- ${vnode.role}${refStr}${tokenStr}${nameStr2}`];
26843
+ if (singleChild && singleChild.role === "generic" && !hasInteractiveDescendant(singleChild) && staticChildren.length === 0) {
26844
+ const mergedName = outputName.trim() || singleChild.name.trim();
26845
+ const mergedRefStr = singleChild.ref !== void 0 ? ` #${singleChild.ref}` : refStr;
26846
+ return [`${indent}- ${vnode.role}${mergedRefStr}${tokenStr}${formatNameAttr(mergedName)}`];
26614
26847
  }
26615
26848
  }
26616
- const safeName = vnode.name ? vnode.name.replace(/[\r\n]+/g, " ").replace(/"/g, '\\"') : "";
26617
- const nameStr = safeName ? ` "${safeName}"` : "";
26618
- const line = `${indent}- ${vnode.role}${refStr}${tokenStr}${nameStr}`;
26619
- const childLines = vnode.children.flatMap((c) => serializeVNode(c, depth + 1, opts));
26849
+ const childrenToEmit = vnode.children.filter((c) => {
26850
+ if (!isStaticBranch(c)) return true;
26851
+ return !canOmitStaticChild(c, outputName, parentUsesOwnDeclaredName);
26852
+ });
26853
+ const line = `${indent}- ${vnode.role}${refStr}${tokenStr}${formatNameAttr(outputName)}`;
26854
+ const childLines = childrenToEmit.flatMap((c) => serializeVNode(c, depth + 1, opts));
26620
26855
  return [line, ...childLines];
26621
26856
  }
26622
26857
 
@@ -26666,9 +26901,40 @@ ${pi.pixels_above > 4 && viewportExpansion !== -1 ? `... ${pi.pixels_above} pixe
26666
26901
  border-radius: 4px;
26667
26902
  }
26668
26903
  `;
26669
- function isElementViewport(element) {
26670
- const rect = element.getBoundingClientRect();
26671
- return rect.top >= 0 && rect.left >= 0 && rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && rect.right <= (window.innerWidth || document.documentElement.clientWidth);
26904
+ var MAX_ICON_FALLBACK_SIZE = 48;
26905
+ function resolveHighlightRect(el) {
26906
+ const rect = el.getBoundingClientRect();
26907
+ if (rect.width > 0 && rect.height > 0) {
26908
+ return { top: rect.top, left: rect.left, width: rect.width, height: rect.height };
26909
+ }
26910
+ let parent = el.parentElement;
26911
+ for (let depth = 0; depth < 3 && parent; depth++) {
26912
+ const pr = parent.getBoundingClientRect();
26913
+ if (pr.width > 0 && pr.height > 0 && pr.width <= MAX_ICON_FALLBACK_SIZE && pr.height <= MAX_ICON_FALLBACK_SIZE) {
26914
+ return { top: pr.top, left: pr.left, width: pr.width, height: pr.height };
26915
+ }
26916
+ parent = parent.parentElement;
26917
+ }
26918
+ if (rect.width > 0 || rect.height > 0) {
26919
+ try {
26920
+ const fs = parseFloat(getComputedStyle(el).fontSize) || 16;
26921
+ const width = rect.width > 0 ? rect.width : fs;
26922
+ const height = rect.height > 0 ? rect.height : fs;
26923
+ return {
26924
+ top: rect.height > 0 ? rect.top : rect.top - (height - rect.height) / 2,
26925
+ left: rect.width > 0 ? rect.left : rect.left - (width - rect.width) / 2,
26926
+ width,
26927
+ height
26928
+ };
26929
+ } catch {
26930
+ }
26931
+ }
26932
+ return null;
26933
+ }
26934
+ function isRectInViewport(rect) {
26935
+ const vh = window.innerHeight || document.documentElement.clientHeight;
26936
+ const vw = window.innerWidth || document.documentElement.clientWidth;
26937
+ return rect.top < vh && rect.top + rect.height > 0 && rect.left < vw && rect.left + rect.width > 0;
26672
26938
  }
26673
26939
  var doHighlight = (refMap, parentIframe = null) => {
26674
26940
  if (!document.head.querySelector(`#${HIGHLIGHT_CONTAINER_STYLE_ID}`)) {
@@ -26692,29 +26958,29 @@ ${pi.pixels_above > 4 && viewportExpansion !== -1 ? `... ${pi.pixels_above} pixe
26692
26958
  iframeOffset.y = iframeRect.top;
26693
26959
  }
26694
26960
  const fragment = document.createDocumentFragment();
26695
- const overlays = [];
26696
26961
  for (const [index, el] of refMap.entries()) {
26697
- if (!isElementViewport(el)) continue;
26962
+ const rect = resolveHighlightRect(el);
26963
+ if (!rect) continue;
26964
+ const top = rect.top + iframeOffset.y;
26965
+ const left = rect.left + iframeOffset.x;
26966
+ const viewportRect = { top, left, width: rect.width, height: rect.height };
26967
+ if (!isRectInViewport(viewportRect)) continue;
26698
26968
  const color = colors[index % colors.length];
26699
26969
  const textColor = color + opacity;
26700
- const rect = el.getBoundingClientRect();
26701
- if (rect.width === 0 || rect.height === 0) continue;
26702
26970
  const overlay = document.createElement("div");
26703
26971
  overlay.style.border = `2px solid ${textColor}`;
26704
- const top = rect.top + iframeOffset.y;
26705
- const left = rect.left + iframeOffset.x;
26972
+ overlay.dataset.refIndex = String(index);
26706
26973
  overlay.style.top = `${top}px`;
26707
26974
  overlay.style.left = `${left}px`;
26708
26975
  overlay.style.width = `${rect.width}px`;
26709
26976
  overlay.style.height = `${rect.height}px`;
26710
26977
  const text = document.createElement("span");
26711
26978
  text.style.backgroundColor = textColor;
26712
- text.style.height = `${rect.height - 4}px`;
26713
- text.style.lineHeight = `${rect.height - 4}px`;
26979
+ text.style.height = `${Math.max(rect.height - 4, 0)}px`;
26980
+ text.style.lineHeight = `${Math.max(rect.height - 4, 0)}px`;
26714
26981
  text.textContent = index.toString();
26715
26982
  overlay.appendChild(text);
26716
26983
  fragment.appendChild(overlay);
26717
- overlays.push({ element: overlay, initialRect: rect });
26718
26984
  }
26719
26985
  container.appendChild(fragment);
26720
26986
  };
@@ -26780,34 +27046,36 @@ ${pi.pixels_above > 4 && viewportExpansion !== -1 ? `... ${pi.pixels_above} pixe
26780
27046
  };
26781
27047
 
26782
27048
  // ../next-sdk/page-tools/a11y/build.ts
26783
- var DEFAULT_OPTIONS = {
26784
- pruneUnnamed: true,
26785
- preserveRoles: [],
26786
- exposedAttributes: [],
26787
- errorSelectors: DEFAULT_ERROR_SELECTORS,
26788
- warningSelectors: DEFAULT_WARNING_SELECTORS
26789
- };
26790
- function buildA11yTree(root = document.body, blacklist = [], whitelist = [], options) {
26791
- const opts = { ...DEFAULT_OPTIONS, ...options };
27049
+ function resolveElementList(list, root) {
27050
+ const set = /* @__PURE__ */ new Set();
27051
+ for (const item of list) {
27052
+ if (typeof item === "string") {
27053
+ try {
27054
+ for (const el of deepQuerySelectorAll(item, root)) set.add(el);
27055
+ } catch {
27056
+ }
27057
+ } else if (item) {
27058
+ set.add(item);
27059
+ }
27060
+ }
27061
+ return set;
27062
+ }
27063
+ function buildA11yTree(root = document.body, config2) {
27064
+ const { pruneUnnamed = true, preserveRoles = [], ...a11yConfig } = config2 ?? {};
27065
+ const resolved = ensureResolvedA11yConfig(a11yConfig);
27066
+ const shapeOpts = { pruneUnnamed, preserveRoles };
26792
27067
  const refCounter = { value: 0 };
26793
27068
  const refMap = /* @__PURE__ */ new Map();
26794
- const blacklistSet = new Set(blacklist);
26795
- const whitelistSet = new Set(whitelist);
27069
+ const blacklistSet = resolveElementList(resolved.blacklist, root);
27070
+ const whitelistSet = resolveElementList(resolved.whitelist, root);
26796
27071
  const lines = [];
26797
- blacklistSet.add(document.getElementById(HIGHLIGHT_CONTAINER_ID));
27072
+ const highlightContainer = document.getElementById(HIGHLIGHT_CONTAINER_ID);
27073
+ if (highlightContainer) blacklistSet.add(highlightContainer);
27074
+ const hoverPointerSet = collectHoverPointerElements(root);
26798
27075
  for (const child of getComposedChildren(root)) {
26799
- const vnode = buildVNode(
26800
- child,
26801
- refCounter,
26802
- refMap,
26803
- blacklistSet,
26804
- whitelistSet,
26805
- opts.exposedAttributes,
26806
- opts.errorSelectors,
26807
- opts.warningSelectors
26808
- );
27076
+ const vnode = buildVNode(child, refCounter, refMap, blacklistSet, whitelistSet, resolved, hoverPointerSet);
26809
27077
  if (vnode) {
26810
- lines.push(...serializeVNode(vnode, 0, opts));
27078
+ lines.push(...serializeVNode(vnode, 0, shapeOpts));
26811
27079
  }
26812
27080
  }
26813
27081
  const yaml = "```yaml\n" + lines.join("\n") + "\n```";
@@ -26820,7 +27088,7 @@ ${pi.pixels_above > 4 && viewportExpansion !== -1 ? `... ${pi.pixels_above} pixe
26820
27088
  }
26821
27089
 
26822
27090
  // ../next-sdk/page-tools/a11y/search.ts
26823
- function searchA11yTree(query, root = document.body, blacklist = [], whitelist = [], options) {
27091
+ function searchA11yTree(query, root = document.body, options) {
26824
27092
  const {
26825
27093
  contextLines = 2,
26826
27094
  caseInsensitive = true,
@@ -26829,7 +27097,7 @@ ${pi.pixels_above > 4 && viewportExpansion !== -1 ? `... ${pi.pixels_above} pixe
26829
27097
  } = options ?? {};
26830
27098
  const safeContextLines = Math.max(0, contextLines);
26831
27099
  const safeMaxMatches = Math.max(1, maxMatches);
26832
- const { lines, refMap, yaml } = buildA11yTree(root, blacklist, whitelist, treeOptions);
27100
+ const { lines, refMap, yaml } = buildA11yTree(root, treeOptions);
26833
27101
  const needle = caseInsensitive ? query.toLowerCase() : query;
26834
27102
  const totalLines = lines.length;
26835
27103
  const isRefQuery = /^#\d+$/.test(query);
@@ -27619,36 +27887,20 @@ ${pi.pixels_above > 4 && viewportExpansion !== -1 ? `... ${pi.pixels_above} pixe
27619
27887
  z-index: 10000;
27620
27888
  }
27621
27889
 
27622
- .webmcp-page-agent-cursorBorder {
27890
+ .webmcp-page-agent-cursorFilling {
27623
27891
  position: absolute;
27624
27892
  width: 100%;
27625
27893
  height: 100%;
27626
- background: linear-gradient(45deg, rgb(57, 182, 255), rgb(189, 69, 251));
27627
- mask-image: url("data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20100%20100'%20fill='none'%3e%3cg%3e%3cpath%20d='M%2015%2042%20L%2015%2036.99%20Q%2015%2031.99%2023.7%2031.99%20L%2028.05%2031.99%20Q%2032.41%2031.99%2032.41%2021.99%20L%2032.41%2017%20Q%2032.41%2012%2041.09%2016.95%20L%2076.31%2037.05%20Q%2085%2042%2076.31%2046.95%20L%2041.09%2067.05%20Q%2032.41%2072%2032.41%2062.01%20L%2032.41%2057.01%20Q%2032.41%2052.01%2023.7%2052.01%20L%2019.35%2052.01%20Q%2015%2052.01%2015%2047.01%20Z'%20fill='none'%20stroke='%23000000'%20stroke-width='6'%20stroke-miterlimit='10'%20style='stroke:%20light-dark(rgb(0,%200,%200),%20rgb(255,%20255,%20255));'/%3e%3c/g%3e%3c/svg%3e");
27628
- mask-size: 100% 100%;
27629
- mask-repeat: no-repeat;
27894
+ background: url("data:image/svg+xml,%3Csvg%20viewBox%3D%270%200%2079.0834%2079.4553%27%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20%20width%3D%2779.083374%27%20height%3D%2779.455322%27%20fill%3D%27none%27%20%3E--%3Cdefs%3E%3Cfilter%20id%3D%27filter_0%27%20width%3D%2779.083374%27%20height%3D%2779.455322%27%20x%3D%270.000000%27%20y%3D%270.000000%27%20filterUnits%3D%27userSpaceOnUse%27%20%20color-interpolation-filters%3D%27sRGB%27%3E%3CfeFlood%20flood-opacity%3D%270%27%20result%3D%27BackgroundImageFix%27%20%2F%3E%3CfeOffset%20dx%3D%276.000000%27%20dy%3D%276.000000%27%20in%3D%27SourceAlpha%27%20%2F%3E%3CfeGaussianBlur%20stdDeviation%3D%276.66666651%27%20%2F%3E%3CfeColorMatrix%20type%3D%27matrix%27%20values%3D%270%200%200%200%200%200%200%200%200%200%200%200%200%200%200%200%200%200%200.18%200%20%27%20%2F%3E%3CfeBlend%20result%3D%27effect_dropShadow_1%27%20in2%3D%27BackgroundImageFix%27%20mode%3D%27normal%27%20%2F%3E%3CfeBlend%20result%3D%27shape%27%20in%3D%27SourceGraphic%27%20in2%3D%27effect_dropShadow_1%27%20mode%3D%27normal%27%20%2F%3E%3C%2Ffilter%3E%3ClinearGradient%20id%3D%27paint_linear_0%27%20x1%3D%2718.4743214%27%20x2%3D%2718.4213886%27%20y1%3D%27-1.86264515e-09%27%20y2%3D%2734.9221306%27%20gradientUnits%3D%27userSpaceOnUse%27%3E%3Cstop%20stop-color%3D%27rgb%28255%2C181%2C96%29%27%20offset%3D%270%27%20stop-opacity%3D%271%27%20%2F%3E%3Cstop%20stop-color%3D%27rgb%28255%2C120%2C114%29%27%20offset%3D%270.5%27%20stop-opacity%3D%271%27%20%2F%3E%3Cstop%20stop-color%3D%27rgb%28241%2C109%2C237%29%27%20offset%3D%271%27%20stop-opacity%3D%271%27%20%2F%3E%3C%2FlinearGradient%3E%3C%2Fdefs%3E%3Cg%20filter%3D%27url%28%23filter_0%29%27%3E%3Cpath%20d%3D%27M20.2632%203.57771L34.6257%2032.3027C35.4444%2033.9402%2033.8152%2035.7258%2032.1097%2035.0603L19.2014%2030.0229C18.7339%2029.8404%2018.2148%2029.8404%2017.7472%2030.0229L4.83891%2035.0603C3.13343%2035.7258%201.50423%2033.9402%202.32297%2032.3027L16.6855%203.57771C17.4225%202.10361%2019.5261%202.10361%2020.2632%203.57771Z%27%20fill%3D%27url%28%23paint_linear_0%29%27%20fill-rule%3D%27evenodd%27%20transform%3D%27matrix%280.719908%2C-0.69407%2C0.69407%2C0.719908%2C2.00256%2C28.0095%29%27%20%2F%3E%3Cpath%20d%3D%27M37.2169%2032.6848C37.1578%2032.189%2037.0096%2031.7039%2036.7723%2031.2294L22.4098%202.5044C22.1973%202.07946%2021.9328%201.70554%2021.6163%201.38261C21.3524%201.11342%2021.0524%200.879671%2020.7162%200.681366C20.3925%200.490407%2020.0558%200.34434%2019.7061%200.243163C19.312%200.129145%2018.9014%200.0721366%2018.4743%200.0721366C18.0472%200.0721366%2017.6367%200.129145%2017.2426%200.243163C16.8929%200.34434%2016.5562%200.490407%2016.2324%200.681366C15.8962%200.879671%2015.5962%201.11342%2015.3323%201.38261C15.0158%201.70553%2014.7513%202.07946%2014.5388%202.5044L0.176342%2031.2294C-0.0609121%2031.7039%20-0.209128%2032.189%20-0.268305%2032.6848C-0.316251%2033.0865%20-0.305747%2033.4951%20-0.236792%2033.9108C-0.171059%2034.307%20-0.0570567%2034.6809%200.105216%2035.0326C0.292784%2035.4391%200.544845%2035.8158%200.861397%2036.1627C1.17794%2036.5097%201.53001%2036.7951%201.91761%2037.0191C2.25297%2037.2128%202.61492%2037.3606%203.00348%2037.4623C3.41106%2037.5689%203.81704%2037.6168%204.22142%2037.6058C4.72053%2037.5922%205.21719%2037.4889%205.71141%2037.2961L18.4743%2032.3154L31.2372%2037.2961C31.7315%2037.4889%2032.2281%2037.5922%2032.7272%2037.6058C33.1316%2037.6168%2033.5376%2037.5689%2033.9452%2037.4623C34.3337%2037.3606%2034.6957%2037.2128%2035.0311%2037.0191C35.4187%2036.7951%2035.7707%2036.5097%2036.0873%2036.1627C36.4038%2035.8158%2036.6558%2035.4391%2036.8434%2035.0327C37.0057%2034.681%2037.1197%2034.307%2037.1854%2033.9108C37.2544%2033.4951%2037.2649%2033.0865%2037.2169%2032.6848ZM34.6257%2032.3027L20.2632%203.57771C19.5261%202.10361%2017.4225%202.10361%2016.6855%203.57771L2.32297%2032.3027C1.50423%2033.9402%203.13343%2035.7258%204.83891%2035.0603L17.7472%2030.0229C18.2148%2029.8404%2018.7339%2029.8404%2019.2014%2030.0229L32.1097%2035.0603C33.8152%2035.7258%2035.4444%2033.9402%2034.6257%2032.3027Z%27%20fill%3D%27rgb%28255%2C255%2C255%29%27%20fill-rule%3D%27evenodd%27%20transform%3D%27matrix%280.719908%2C-0.69407%2C0.69407%2C0.719908%2C2.00256%2C28.0095%29%27%20%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E");
27895
+ background-size: 100% 100%;
27896
+ background-repeat: no-repeat;
27630
27897
 
27631
27898
  transform-origin: center;
27632
- transform: rotate(-90deg) scale(0.8);
27633
27899
  margin-left: -10px;
27634
27900
  margin-top: -18px;
27635
27901
  }
27636
27902
 
27637
- .webmcp-page-agent-cursorFilling {
27638
- position: absolute;
27639
- width: 100%;
27640
- height: 100%;
27641
- background: url("data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20100%20100'%3e%3cdefs%3e%3c/defs%3e%3cg%20xmlns='http://www.w3.org/2000/svg'%20style='filter:%20drop-shadow(light-dark(rgba(0,%200,%200,%200.4),%20rgba(237,%20237,%20237,%200.4))%203px%204px%204px);'%3e%3cpath%20d='M%2015%2042%20L%2015%2036.99%20Q%2015%2031.99%2023.7%2031.99%20L%2028.05%2031.99%20Q%2032.41%2031.99%2032.41%2021.99%20L%2032.41%2017%20Q%2032.41%2012%2041.09%2016.95%20L%2076.31%2037.05%20Q%2085%2042%2076.31%2046.95%20L%2041.09%2067.05%20Q%2032.41%2072%2032.41%2062.01%20L%2032.41%2057.01%20Q%2032.41%2052.01%2023.7%2052.01%20L%2019.35%2052.01%20Q%2015%2052.01%2015%2047.01%20Z'%20fill='%23ffffff'%20stroke='none'%20style='fill:%20%23ffffff;'/%3e%3c/g%3e%3c/svg%3e");
27642
- background-size: 100% 100%;
27643
- background-repeat: no-repeat;
27644
-
27645
- transform-origin: center;
27646
- transform: rotate(-90deg) scale(0.8);
27647
- margin-left: -10px;
27648
- margin-top: -18px;
27649
- }
27650
-
27651
- .webmcp-page-agent-cursorRipple {
27903
+ .webmcp-page-agent-cursorRipple {
27652
27904
  position: absolute;
27653
27905
  width: 100%;
27654
27906
  height: 100%;
@@ -27685,9 +27937,9 @@ ${pi.pixels_above > 4 && viewportExpansion !== -1 ? `... ${pi.pixels_above} pixe
27685
27937
  .webmcp-page-agent-wrapper {
27686
27938
  position: fixed;
27687
27939
  inset: 0;
27688
- z-index: 2147483641;
27689
27940
  /* \u786E\u4FDD\u5728\u6240\u6709\u5143\u7D20\u4E4B\u4E0A\uFF0C\u9664\u4E86 panel */
27690
- cursor: wait;
27941
+ z-index: 2147483641;
27942
+ /*cursor: wait;*/
27691
27943
  overflow: hidden;
27692
27944
 
27693
27945
  display: none;
@@ -27717,7 +27969,10 @@ ${pi.pixels_above > 4 && viewportExpansion !== -1 ? `... ${pi.pixels_above} pixe
27717
27969
  try {
27718
27970
  const motion = new Motion({
27719
27971
  mode: isPageDark2() ? "dark" : "light",
27720
- styles: { position: "absolute", inset: "0" }
27972
+ styles: { position: "absolute", inset: "0" },
27973
+ glowWidth: 80,
27974
+ borderWidth: 8,
27975
+ colors: ["rgb(121, 216, 247)", "rgb(171, 219, 110)", "rgb(252, 188, 114)", "rgb(235, 117, 231)"]
27721
27976
  });
27722
27977
  this.motion = motion;
27723
27978
  this.wrapper.appendChild(motion.element);
@@ -27746,7 +28001,7 @@ ${pi.pixels_above > 4 && viewportExpansion !== -1 ? `... ${pi.pixels_above} pixe
27746
28001
  this.wrapper.style.pointerEvents = "none";
27747
28002
  };
27748
28003
  const disablePassThroughListener = () => {
27749
- this.wrapper.style.pointerEvents = "auto";
28004
+ this.wrapper.style.pointerEvents = "none";
27750
28005
  };
27751
28006
  window.addEventListener("PageAgent::MovePointerTo", movePointerToListener);
27752
28007
  window.addEventListener("PageAgent::ClickPointer", clickPointerListener);
@@ -27773,9 +28028,6 @@ ${pi.pixels_above > 4 && viewportExpansion !== -1 ? `... ${pi.pixels_above} pixe
27773
28028
  const fillingLayer = document.createElement("div");
27774
28029
  fillingLayer.className = "webmcp-page-agent-cursorFilling";
27775
28030
  this.#cursor.appendChild(fillingLayer);
27776
- const borderLayer = document.createElement("div");
27777
- borderLayer.className = "webmcp-page-agent-cursorBorder";
27778
- this.#cursor.appendChild(borderLayer);
27779
28031
  this.wrapper.appendChild(this.#cursor);
27780
28032
  }
27781
28033
  #moveCursorToTarget() {
@@ -27842,62 +28094,38 @@ ${pi.pixels_above > 4 && viewportExpansion !== -1 ? `... ${pi.pixels_above} pixe
27842
28094
  this.wrapper.remove();
27843
28095
  this.dispatchEvent(new Event("dispose"));
27844
28096
  }
28097
+ // 根据目标元素大小,在 wrapper 添加绝对定位边框:2px 宽、与目标间距 2px,对角渐变 (0,0 → 1,1)
28098
+ borderElement(targetElement) {
28099
+ if (!targetElement) return;
28100
+ this.wrapper.querySelector(".webmcp-page-agent-border")?.remove();
28101
+ const rect = targetElement.getBoundingClientRect();
28102
+ const gap = 2;
28103
+ const borderWidth = 2;
28104
+ const offset = gap + borderWidth;
28105
+ const el = document.createElement("div");
28106
+ el.className = "webmcp-page-agent-border";
28107
+ el.style.position = "absolute";
28108
+ el.style.left = `${rect.left - offset}px`;
28109
+ el.style.top = `${rect.top - offset}px`;
28110
+ el.style.width = `${rect.width + offset * 2}px`;
28111
+ el.style.height = `${rect.height + offset * 2}px`;
28112
+ el.style.boxSizing = "border-box";
28113
+ el.style.pointerEvents = "none";
28114
+ el.style.zIndex = "10000";
28115
+ el.style.border = `${borderWidth}px solid transparent`;
28116
+ el.style.borderImageSource = "linear-gradient(to bottom right, #79D8F7, #ABDB6E, #FCBC72, #FA8682, #EB75E7)";
28117
+ el.style.borderImageSlice = "1";
28118
+ el.style.borderImageWidth = `${borderWidth}px`;
28119
+ this.wrapper.appendChild(el);
28120
+ }
28121
+ removeBorderElement() {
28122
+ this.wrapper.querySelector(".webmcp-page-agent-border")?.remove();
28123
+ }
27845
28124
  };
27846
28125
 
27847
- // ../next-sdk/page-tools/constants.ts
27848
- var DEFAULT_ERROR_SELECTORS2 = [
27849
- // W3C ARIA 标准(最可靠,框架无关)
27850
- '[role="alert"]',
27851
- '[aria-invalid="true"]',
27852
- // Tiny3 / Lego(华为云)
27853
- ".ti3-unifyvalid-error",
27854
- ".ti3-error",
27855
- ".ti-error",
27856
- ".lego-text-error",
27857
- ".lego-error",
27858
- // Element UI / Element Plus
27859
- ".el-form-item__error",
27860
- // Ant Design
27861
- ".ant-form-item-explain-error",
27862
- // Bootstrap
27863
- ".is-invalid",
27864
- ".invalid-feedback",
27865
- // Angular
27866
- ".ng-invalid",
27867
- // 通用命名约定
27868
- ".error-msg",
27869
- ".error-message",
27870
- ".error-text",
27871
- ".field-error",
27872
- ".form-error",
27873
- ".is-error",
27874
- ".has-error",
27875
- ".validate-error",
27876
- ".valid-error"
27877
- ];
27878
- var DEFAULT_DIALOG_SELECTORS = [
27879
- // W3C ARIA 标准
27880
- '[role="dialog"]',
27881
- '[role="alertdialog"]',
27882
- // Tiny3 / Lego(华为云)
27883
- '[class*="ti3-modal"]',
27884
- '[class*="ti3-message-box"]',
27885
- // Element UI / Element Plus
27886
- '[class*="el-dialog"]',
27887
- '[class*="el-message-box"]',
27888
- // Ant Design
27889
- '[class*="ant-modal"]',
27890
- // Bootstrap
27891
- '[class*="modal-content"]',
27892
- // Vuetify
27893
- '[class*="v-dialog"]',
27894
- // Naive UI
27895
- '[class*="n-modal"]'
27896
- ];
27897
-
27898
28126
  // ../next-sdk/page-tools/schema.ts
27899
28127
  var inputSchema = external_exports.object({
27900
- action: external_exports.enum(["browserState", "click", "fill", "select", "scroll", "executeJavascript", "searchTree"]).describe(`\u6267\u884C\u7684\u52A8\u4F5C\u540D\u79F0, \u6BCF\u4E00\u6B21\u6267\u884C 'click', 'fill', 'select'\u52A8\u4F5C\u4E4B\u524D\uFF0C**\u5FC5\u987B**\u8981\u5148\u8C03\u7528 'browserState' \u53BB\u83B7\u53D6\u9875\u9762\u7684\u6700\u65B0\u72B6\u6001\u3002
28128
+ action: external_exports.enum(["browserState", "click", "fill", "select", "scroll", "executeJavascript", "searchTree", "hover"]).describe(`\u6267\u884C\u7684\u52A8\u4F5C\u540D\u79F0, \u6BCF\u4E00\u6B21\u6267\u884C 'click', 'fill', 'select', 'hover'\u52A8\u4F5C\u4E4B\u524D\uFF0C**\u5FC5\u987B**\u8981\u5148\u8C03\u7528 'browserState' \u53BB\u83B7\u53D6\u9875\u9762\u7684\u6700\u65B0\u72B6\u6001\u3002
27901
28129
  browserState: '\u67E5\u8BE2\u6574\u4E2A\u9875\u9762\u7684\u6D4F\u89C8\u5668\u72B6\u6001;\u8FD4\u56DE\u9875\u9762\u7684\u6807\u9898\u3001URL\u3001YAML\u683C\u5F0F\u7684\u8BED\u4E49\u5316\u9875\u9762\u6811',
27902
28130
  click: '\u6839\u636E\u5143\u7D20\u7D22\u5F15\u70B9\u51FB;',
27903
28131
  fill: '\u6839\u636E\u5143\u7D20\u7D22\u5F15\u586B\u5199\u6587\u672C;';
@@ -27905,8 +28133,9 @@ ${pi.pixels_above > 4 && viewportExpansion !== -1 ? `... ${pi.pixels_above} pixe
27905
28133
  scroll: '\u6EDA\u52A8\u9875\u9762\u7684\u52A8\u4F5C\uFF0C\u53EF\u4EE5\u6307\u5B9A\u6C34\u5E73\u6EDA\u52A8\u8FD8\u662F\u4E0A\u4E0B\u6EDA\u52A8; \u4E0D\u5E26\u5143\u7D20\u7D22\u5F15\u65F6\uFF1A\u6EDA\u52A8\u6574\u4E2A\u6587\u6863\u3002\u5E26\u5143\u7D20\u7D22\u5F15\u65F6\uFF1A\u6EDA\u52A8\u8BE5\u7D22\u5F15\u5904\u7684\u5BB9\u5668\uFF08\u6216\u5176\u6700\u8FD1\u7684\u53EF\u6EDA\u52A8\u7956\u5148\u5143\u7D20\uFF09'
27906
28134
  executeJavascript: '\u6267\u884Cjavascript\u4EE3\u7801'
27907
28135
  searchTree: '\u6309\u5173\u952E\u8BCD\u641C\u7D22\u65E0\u969C\u788D\u6811\uFF0C\u8FD4\u56DE\u5E26\u884C\u53F7\u7684\u5339\u914D\u8282\u70B9\u53CA\u4E0A\u4E0B\u6587\uFF0C\u65E0\u9700\u83B7\u53D6\u5168\u91CF\u6811\u3002\u9002\u5408\u5FEB\u901F\u5B9A\u4F4D\u7279\u5B9A\u5143\u7D20\uFF08\u5982\u6240\u6709\u6309\u94AE\u3001\u7279\u5B9A\u540D\u79F0\u7684\u94FE\u63A5\u7B49\uFF09\uFF0C\u663E\u8457\u51CF\u5C11\u4E0A\u4E0B\u6587\u6D88\u8017\u3002\u5FC5\u987B\u63D0\u4F9B query \u53C2\u6570\u3002'
28136
+ hover: '\u6839\u636E\u5143\u7D20\u7D22\u5F15\u60AC\u6D6E\uFF08hover\uFF09\u76EE\u6807\u5143\u7D20; \u89E6\u53D1 mouseover/mouseenter \u7B49\u4E8B\u4EF6\uFF0C\u7528\u4E8E\u663E\u793A tooltip\u3001\u5C55\u5F00\u60AC\u6D6E\u83DC\u5355\u7B49\u4EA4\u4E92; \u64CD\u4F5C\u540E\u81EA\u52A8\u8FD4\u56DE\u6700\u65B0\u9875\u9762\u72B6\u6001\u3002'
27908
28137
  `),
27909
- index: external_exports.number().min(0).optional().describe("\u6267\u884C\u52A8\u4F5C of the element index, \u52A8\u4F5C\u4E3A click,fill,select\u65F6\uFF0C\u5FC5\u987B\u63D0\u4F9B\u5143\u7D20\u7D22\u5F15"),
28138
+ index: external_exports.number().min(0).optional().describe("\u6267\u884C\u52A8\u4F5C of the element index, \u52A8\u4F5C\u4E3A click,fill,select,hover\u65F6\uFF0C\u5FC5\u987B\u63D0\u4F9B\u5143\u7D20\u7D22\u5F15"),
27910
28139
  text: external_exports.string().optional().describe("\u6267\u884C\u52A8\u4F5C\u7684\u6587\u672C\u5185\u5BB9, \u52A8\u4F5C\u4E3A fill,select \u65F6\uFF0C\u5FC5\u987B\u63D0\u4F9B\u6587\u672C\u5185\u5BB9"),
27911
28140
  down: external_exports.boolean().optional().describe("\u6267\u884C\u4E0A\u4E0B\u6EDA\u52A8\u65F6\uFF0C\u5FC5\u987B\u63D0\u4F9Bdown\u53C2\u6570"),
27912
28141
  right: external_exports.boolean().optional().describe("\u6267\u884C\u6C34\u5E73\u6EDA\u52A8\u65B9\u5411, \u5FC5\u987B\u63D0\u4F9Bright\u53C2\u6570"),
@@ -27923,118 +28152,126 @@ ${pi.pixels_above > 4 && viewportExpansion !== -1 ? `... ${pi.pixels_above} pixe
27923
28152
  )
27924
28153
  });
27925
28154
 
27926
- // ../next-sdk/page-tools/utils/dom.ts
27927
- function isInShadowDom(el) {
27928
- return el.getRootNode() instanceof ShadowRoot;
27929
- }
27930
- function dispatchComposedEvents(el, ...types) {
27931
- for (const type of types) {
27932
- el.dispatchEvent(new Event(type, { bubbles: true, composed: true }));
27933
- }
27934
- }
27935
- function deepQuerySelectorAll(selector, root = document) {
27936
- const elements = Array.from(root.querySelectorAll(selector));
27937
- const walker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT, null);
27938
- let currentNode = walker.currentNode;
27939
- while (currentNode) {
27940
- if (currentNode.shadowRoot) {
27941
- elements.push(...deepQuerySelectorAll(selector, currentNode.shadowRoot));
28155
+ // ../next-sdk/page-tools/page-agent-tool-event.ts
28156
+ var PAGE_AGENT_TOOL_CALL_EVENT = "page-agent-tool-call";
28157
+ var PAGE_AGENT_TOOL_RESULT_EVENT = "page-agent-tool-result";
28158
+ var PAGE_AGENT_CHAT_END_EVENT = "page-agent-chat-end";
28159
+ var PAGE_AGENT_USER_DO_ACTION_EVENT = "page-agent-user-do-action";
28160
+ function isPageAgentToolErrorResult(result2) {
28161
+ return typeof result2 === "object" && result2 !== null && "isError" in result2 && result2.isError === true && "error" in result2 && typeof result2.error === "string";
28162
+ }
28163
+ function dispatchPageAgentToolResult(detail) {
28164
+ window.dispatchEvent(new CustomEvent(PAGE_AGENT_TOOL_RESULT_EVENT, { detail }));
28165
+ }
28166
+ function setupPageAgentToolEventBridge(executePageAgentTool, pageController, actionContext) {
28167
+ window.__nextSdkPageAgentToolEventCleanup?.();
28168
+ const handleToolCall = async (event) => {
28169
+ const detail = event.detail;
28170
+ const requestId = detail?.requestId;
28171
+ if (!requestId) {
28172
+ dispatchPageAgentToolResult({
28173
+ requestId: "",
28174
+ data: {
28175
+ success: false,
28176
+ error: "\u7F3A\u5C11 requestId"
28177
+ }
28178
+ });
28179
+ return;
27942
28180
  }
27943
- currentNode = walker.nextNode();
27944
- }
27945
- return elements;
27946
- }
27947
- function waitForDomSettled(timeout = 600, settleTime = 150) {
27948
- return new Promise((resolve) => {
27949
- let settled = false;
27950
- let settleTimer;
27951
- const finish = () => {
27952
- if (settled) return;
27953
- settled = true;
27954
- observer.disconnect();
27955
- if (settleTimer) clearTimeout(settleTimer);
27956
- resolve();
27957
- };
27958
- const observer = new MutationObserver(() => {
27959
- if (settleTimer) clearTimeout(settleTimer);
27960
- settleTimer = setTimeout(finish, settleTime);
27961
- });
27962
- settleTimer = setTimeout(finish, settleTime);
27963
- setTimeout(finish, timeout);
27964
- observer.observe(document.body, {
27965
- childList: true,
27966
- subtree: true,
27967
- attributes: true,
27968
- attributeFilter: ["class", "style", "hidden"]
27969
- });
27970
- });
27971
- }
27972
- function detectPageDialog() {
27973
- const seen = /* @__PURE__ */ new Set();
27974
- const dialogs = [];
27975
- const selectors = window.__webmcpcli_dialogSelectors ?? DEFAULT_DIALOG_SELECTORS;
27976
- for (const selector of selectors) {
27977
28181
  try {
27978
- for (const el of deepQuerySelectorAll(selector)) {
27979
- if (seen.has(el)) continue;
27980
- if (el.id?.includes("page-agent-runtime")) continue;
27981
- if (el.closest("#page-agent-runtime_simulator-mask")) continue;
27982
- const rect = el.getBoundingClientRect();
27983
- if (rect.width < 50 || rect.height < 50) continue;
27984
- const style = window.getComputedStyle(el);
27985
- if (style.display === "none" || style.visibility === "hidden") continue;
27986
- const isFixed = style.position === "fixed" || style.position === "absolute";
27987
- const zIndex = parseInt(style.zIndex || "0", 10);
27988
- if (!isFixed || zIndex < 100) continue;
27989
- const vw = window.innerWidth;
27990
- const vh = window.innerHeight;
27991
- const coversCenter = rect.left < vw * 0.6 && rect.right > vw * 0.4 && rect.top < vh * 0.6 && rect.bottom > vh * 0.4;
27992
- if (!coversCenter) continue;
27993
- seen.add(el);
27994
- const text = (el.textContent || "").trim().replace(/\s+/g, " ");
27995
- if (text.length > 5) {
27996
- const btns = el.querySelectorAll('button, [role="button"], a');
27997
- const btnTexts = Array.from(btns).map((b) => (b.textContent || "").trim()).filter((t) => t.length > 0 && t.length < 20).slice(0, 5);
27998
- const btnInfo = btnTexts.length ? ` [\u53EF\u64CD\u4F5C\u6309\u94AE: ${btnTexts.join(" / ")}]` : "";
27999
- dialogs.push(`${text.substring(0, 300)}${btnInfo}`);
28182
+ const data = inputSchema.parse(detail.data);
28183
+ const result2 = await executePageAgentTool(data);
28184
+ if (isPageAgentToolErrorResult(result2)) {
28185
+ dispatchPageAgentToolResult({
28186
+ requestId,
28187
+ data: {
28188
+ success: false,
28189
+ error: result2.error,
28190
+ result: result2
28191
+ }
28192
+ });
28193
+ return;
28194
+ }
28195
+ dispatchPageAgentToolResult({
28196
+ requestId,
28197
+ data: {
28198
+ success: true,
28199
+ result: result2
28000
28200
  }
28201
+ });
28202
+ } catch (error2) {
28203
+ dispatchPageAgentToolResult({
28204
+ requestId,
28205
+ data: {
28206
+ success: false,
28207
+ error: error2 instanceof Error ? error2.message : String(error2)
28208
+ }
28209
+ });
28210
+ }
28211
+ };
28212
+ const handleChatEnd = async () => {
28213
+ try {
28214
+ await pageController.hideMask();
28215
+ } catch (error2) {
28216
+ }
28217
+ };
28218
+ const handleUserDoAction = async (ev) => {
28219
+ if (ev.isTrusted && pageController.mask.shown) {
28220
+ const target = ev.target;
28221
+ const refMap = actionContext.getRefMap();
28222
+ const targetParent = Array.from(refMap.values()).find((el) => el.contains(target));
28223
+ if (targetParent) {
28224
+ const detail = {
28225
+ action: "click",
28226
+ dom: targetParent
28227
+ };
28228
+ window.dispatchEvent(new CustomEvent(PAGE_AGENT_USER_DO_ACTION_EVENT, { detail }));
28001
28229
  }
28002
- } catch {
28003
28230
  }
28231
+ };
28232
+ window.addEventListener(PAGE_AGENT_TOOL_CALL_EVENT, handleToolCall);
28233
+ window.addEventListener(PAGE_AGENT_CHAT_END_EVENT, handleChatEnd);
28234
+ window.addEventListener("click", handleUserDoAction, true);
28235
+ window.__nextSdkPageAgentToolEventCleanup = () => {
28236
+ window.removeEventListener(PAGE_AGENT_TOOL_CALL_EVENT, handleToolCall);
28237
+ window.removeEventListener(PAGE_AGENT_CHAT_END_EVENT, handleChatEnd);
28238
+ window.removeEventListener("click", handleUserDoAction, true);
28239
+ window.__nextSdkPageAgentToolEventCleanup = void 0;
28240
+ };
28241
+ }
28242
+
28243
+ // ../next-sdk/page-tools/context.ts
28244
+ function withStateFields(stateText, extra) {
28245
+ try {
28246
+ const state = JSON.parse(stateText);
28247
+ return JSON.stringify({ ...state, ...extra });
28248
+ } catch {
28249
+ return JSON.stringify({ ...extra, raw: stateText });
28004
28250
  }
28005
- if (dialogs.length === 0) return "";
28006
- return `
28007
- [\u9875\u9762\u5F39\u7A97\u68C0\u6D4B] \u68C0\u6D4B\u5230 ${dialogs.length} \u4E2A\u6A21\u6001\u5F39\u7A97\uFF0C\u8BF7\u4F18\u5148\u5904\u7406:
28008
- ${dialogs.map((d, i) => `${i + 1}. ${d}`).join("\n")}
28009
- `;
28010
28251
  }
28011
- function detectValidationErrors() {
28012
- const seen = /* @__PURE__ */ new Set();
28013
- const errors = [];
28014
- const selectors = window.__webmcpcli_errorSelectors ?? DEFAULT_ERROR_SELECTORS2;
28015
- for (const selector of selectors) {
28016
- try {
28017
- for (const el of deepQuerySelectorAll(selector)) {
28018
- if (seen.has(el)) continue;
28019
- if (Array.from(seen).some((s) => s.contains(el))) continue;
28020
- const rect = el.getBoundingClientRect();
28021
- if (rect.width < 1 || rect.height < 1) continue;
28022
- const style = window.getComputedStyle(el);
28023
- if (style.display === "none" || style.visibility === "hidden") continue;
28024
- const text = (el.textContent || "").trim().replace(/\s+/g, " ");
28025
- if (text.length > 2 && text.length < 200) {
28026
- seen.add(el);
28027
- errors.push(text);
28252
+ async function createActionErrorResult(message, buildBrowserStateResponse) {
28253
+ try {
28254
+ const browserState = await buildBrowserStateResponse("full");
28255
+ return {
28256
+ isError: true,
28257
+ error: message,
28258
+ content: [{ type: "text", text: withStateFields(browserState.content[0].text, { error: message }) }]
28259
+ };
28260
+ } catch (error2) {
28261
+ return {
28262
+ isError: true,
28263
+ error: message,
28264
+ content: [
28265
+ {
28266
+ type: "text",
28267
+ text: JSON.stringify({
28268
+ error: message,
28269
+ stateError: error2 instanceof Error ? error2.message : String(error2)
28270
+ })
28028
28271
  }
28029
- }
28030
- } catch {
28031
- }
28272
+ ]
28273
+ };
28032
28274
  }
28033
- if (errors.length === 0) return "";
28034
- return `
28035
- [\u6821\u9A8C\u63D0\u793A] \u68C0\u6D4B\u5230 ${errors.length} \u4E2A\u8868\u5355\u6821\u9A8C\u9519\u8BEF\uFF0C\u8BF7\u5148\u4FEE\u590D\u540E\u518D\u7EE7\u7EED:
28036
- ${errors.map((e, i) => `${i + 1}. ${e}`).join("\n")}
28037
- `;
28038
28275
  }
28039
28276
 
28040
28277
  // ../next-sdk/page-tools/handlers/browserState.ts
@@ -28052,9 +28289,13 @@ ${errors.map((e, i) => `${i + 1}. ${e}`).join("\n")}
28052
28289
  // ../next-sdk/page-tools/handlers/click.ts
28053
28290
  async function handleClick(args, ctx) {
28054
28291
  const mode = args.responseMode ?? "diff";
28055
- if (args.index === void 0) return ctx.errContent("\u70B9\u51FB\u7ED3\u679C: \u7F3A\u5C11\u5143\u7D20\u7D22\u5F15");
28292
+ if (args.index === void 0) return ctx.actionError("\u70B9\u51FB\u7ED3\u679C: \u7F3A\u5C11\u5143\u7D20\u7D22\u5F15");
28056
28293
  const el = ctx.getRefMap().get(args.index);
28057
- if (!el) return ctx.refreshOnStaleRef("\u70B9\u51FB", args.index);
28294
+ if (!el) {
28295
+ return ctx.actionError(
28296
+ `\u70B9\u51FB\u5931\u8D25: ref \u7D22\u5F15 ${args.index} \u5DF2\u5931\u6548\uFF08\u9875\u9762\u53EF\u80FD\u5DF2\u5237\u65B0\uFF09\uFF0C\u5DF2\u81EA\u52A8\u91CD\u65B0\u52A0\u8F7D\u9875\u9762\u72B6\u6001\uFF0C\u8BF7\u4F7F\u7528\u65B0\u7684 ref \u7D22\u5F15\u91CD\u8BD5\u3002`
28297
+ );
28298
+ }
28058
28299
  let targetEl = el;
28059
28300
  if (el.shadowRoot && !(el instanceof HTMLButtonElement) && !(el instanceof HTMLAnchorElement)) {
28060
28301
  const innerClickable = el.shadowRoot.querySelector(
@@ -28072,9 +28313,14 @@ ${errors.map((e, i) => `${i + 1}. ${e}`).join("\n")}
28072
28313
  // ../next-sdk/page-tools/handlers/fill.ts
28073
28314
  async function handleFill(args, ctx) {
28074
28315
  const mode = args.responseMode ?? "diff";
28075
- if (args.index === void 0 || typeof args.text !== "string") return ctx.errContent("\u586B\u5199\u7ED3\u679C: \u7F3A\u5C11\u5143\u7D20\u7D22\u5F15\u6216\u6587\u672C\u5185\u5BB9");
28316
+ if (args.index === void 0 || typeof args.text !== "string")
28317
+ return ctx.actionError("\u586B\u5199\u7ED3\u679C: \u7F3A\u5C11\u5143\u7D20\u7D22\u5F15\u6216\u6587\u672C\u5185\u5BB9");
28076
28318
  const el = ctx.getRefMap().get(args.index);
28077
- if (!el) return ctx.refreshOnStaleRef("\u586B\u5199", args.index);
28319
+ if (!el) {
28320
+ return ctx.actionError(
28321
+ `\u586B\u5199\u5931\u8D25: ref \u7D22\u5F15 ${args.index} \u5DF2\u5931\u6548\uFF08\u9875\u9762\u53EF\u80FD\u5DF2\u5237\u65B0\uFF09\uFF0C\u5DF2\u81EA\u52A8\u91CD\u65B0\u52A0\u8F7D\u9875\u9762\u72B6\u6001\uFF0C\u8BF7\u4F7F\u7528\u65B0\u7684 ref \u7D22\u5F15\u91CD\u8BD5\u3002`
28322
+ );
28323
+ }
28078
28324
  let targetEl = el;
28079
28325
  if (!(targetEl instanceof HTMLInputElement) && !(targetEl instanceof HTMLTextAreaElement)) {
28080
28326
  const innerInput = el.querySelector("input, textarea") ?? el.shadowRoot?.querySelector("input, textarea");
@@ -28105,7 +28351,7 @@ ${errors.map((e, i) => `${i + 1}. ${e}`).join("\n")}
28105
28351
  }
28106
28352
  }
28107
28353
  if (!fillSuccess) {
28108
- return ctx.errContent(`\u586B\u5199\u7ED3\u679C: \u65E0\u6CD5\u586B\u5199\u5143\u7D20 ${args.index}\uFF0C\u5143\u7D20\u4E0D\u662F input\u3001textarea \u6216 contenteditable`);
28354
+ return ctx.actionError(`\u586B\u5199\u7ED3\u679C: \u65E0\u6CD5\u586B\u5199\u5143\u7D20 ${args.index}\uFF0C\u5143\u7D20\u4E0D\u662F input\u3001textarea \u6216 contenteditable`);
28109
28355
  }
28110
28356
  if (isInShadowDom(targetEl)) {
28111
28357
  dispatchComposedEvents(targetEl, "input", "change");
@@ -28118,9 +28364,14 @@ ${errors.map((e, i) => `${i + 1}. ${e}`).join("\n")}
28118
28364
  // ../next-sdk/page-tools/handlers/select.ts
28119
28365
  async function handleSelect(args, ctx) {
28120
28366
  const mode = args.responseMode ?? "diff";
28121
- if (args.index === void 0 || typeof args.text !== "string") return ctx.errContent("\u9009\u62E9\u7ED3\u679C: \u7F3A\u5C11\u5143\u7D20\u7D22\u5F15\u6216\u6587\u672C\u5185\u5BB9");
28367
+ if (args.index === void 0 || typeof args.text !== "string")
28368
+ return ctx.actionError("\u9009\u62E9\u7ED3\u679C: \u7F3A\u5C11\u5143\u7D20\u7D22\u5F15\u6216\u6587\u672C\u5185\u5BB9");
28122
28369
  let el = ctx.getRefMap().get(args.index);
28123
- if (!el) return ctx.refreshOnStaleRef("\u9009\u62E9", args.index);
28370
+ if (!el) {
28371
+ return ctx.actionError(
28372
+ `\u9009\u62E9\u5931\u8D25: ref \u7D22\u5F15 ${args.index} \u5DF2\u5931\u6548\uFF08\u9875\u9762\u53EF\u80FD\u5DF2\u5237\u65B0\uFF09\uFF0C\u5DF2\u81EA\u52A8\u91CD\u65B0\u52A0\u8F7D\u9875\u9762\u72B6\u6001\uFF0C\u8BF7\u4F7F\u7528\u65B0\u7684 ref \u7D22\u5F15\u91CD\u8BD5\u3002`
28373
+ );
28374
+ }
28124
28375
  let targetSelect = null;
28125
28376
  if (el instanceof HTMLSelectElement) {
28126
28377
  targetSelect = el;
@@ -28131,7 +28382,7 @@ ${errors.map((e, i) => `${i + 1}. ${e}`).join("\n")}
28131
28382
  }
28132
28383
  }
28133
28384
  if (!targetSelect) {
28134
- return ctx.errContent(`\u9009\u62E9\u7ED3\u679C: \u65E0\u6CD5\u9009\u62E9\u5143\u7D20 ${args.index}\uFF0C\u672A\u627E\u5230\u5BF9\u5E94\u7684 <select> \u5143\u7D20`);
28385
+ return ctx.actionError(`\u9009\u62E9\u7ED3\u679C: \u65E0\u6CD5\u9009\u62E9\u5143\u7D20 ${args.index}\uFF0C\u672A\u627E\u5230\u5BF9\u5E94\u7684 <select> \u5143\u7D20`);
28135
28386
  }
28136
28387
  await selectOptionElement(targetSelect, args.text);
28137
28388
  if (isInShadowDom(targetSelect)) {
@@ -28249,9 +28500,7 @@ ${errors.map((e, i) => `${i + 1}. ${e}`).join("\n")}
28249
28500
  const scrollResult = `[\u6EDA\u52A8\u7ED3\u679C] ${scrollMsg}
28250
28501
  ${posInfo}`;
28251
28502
  const stateResult = await ctx.buildBrowserStateResponse(mode);
28252
- stateResult.content[0].text = `${scrollResult}
28253
-
28254
- ${stateResult.content[0].text}`;
28503
+ stateResult.content[0].text = withStateFields(stateResult.content[0].text, { scrollResult });
28255
28504
  return stateResult;
28256
28505
  }
28257
28506
 
@@ -28274,76 +28523,114 @@ ${stateResult.content[0].text}`;
28274
28523
  // ../next-sdk/page-tools/handlers/searchTree.ts
28275
28524
  async function handleSearchTree(args, ctx) {
28276
28525
  if (!args.query) return ctx.errContent("\u641C\u7D22\u5931\u8D25: \u7F3A\u5C11 query \u53C2\u6570");
28277
- const blacklist = window.__webmcpcli_interactiveBlacklist ?? [];
28278
- const whitelist = window.__webmcpcli_interactiveWhitelist ?? [];
28279
- const exposedAttributes = window.__webmcpcli_exposedAttributes ?? [];
28280
- const result2 = searchA11yTree(args.query, document.body, blacklist, whitelist, {
28526
+ const result2 = searchA11yTree(args.query, document.body, {
28527
+ ...getPageAgentToolConfig().a11yConfig,
28281
28528
  contextLines: args.contextLines,
28282
- maxMatches: args.maxMatches,
28283
- exposedAttributes,
28284
- errorSelectors: (window.__webmcpcli_errorSelectors ?? DEFAULT_ERROR_SELECTORS2).join(", ")
28529
+ maxMatches: args.maxMatches
28285
28530
  });
28286
28531
  ctx.setRefMap(result2.refMap);
28287
28532
  ctx.stateCache.update(window.location.href, result2.yaml);
28288
28533
  await ctx.pageController.hideMask();
28289
- const dialogAlert = detectPageDialog();
28534
+ const dialogs = detectPageDialog();
28290
28535
  const validationErrors = detectValidationErrors();
28291
- const alerts = `${dialogAlert}${validationErrors}`;
28536
+ if (dialogs.length === 0 && validationErrors.length === 0) {
28537
+ return { content: [{ type: "text", text: result2.text }] };
28538
+ }
28539
+ const alerts = {
28540
+ ...dialogs.length > 0 ? { dialogs } : {},
28541
+ ...validationErrors.length > 0 ? { validationErrors } : {}
28542
+ };
28292
28543
  return {
28293
- content: [{ type: "text", text: alerts ? `${alerts}
28294
- ${result2.text}` : result2.text }]
28544
+ content: [{ type: "text", text: `${JSON.stringify(alerts)}
28545
+ ${result2.text}` }]
28295
28546
  };
28296
28547
  }
28297
28548
 
28549
+ // ../next-sdk/page-tools/handlers/hover.ts
28550
+ async function handleHover(args, ctx) {
28551
+ if (args.index === void 0) return ctx.errContent("\u60AC\u6D6E\u7ED3\u679C: \u7F3A\u5C11\u5143\u7D20\u7D22\u5F15");
28552
+ const el = ctx.getRefMap().get(args.index);
28553
+ if (!el) return ctx.refreshOnStaleRef("\u60AC\u6D6E", args.index);
28554
+ let targetEl = el;
28555
+ if (el.shadowRoot && !(el instanceof HTMLButtonElement) && !(el instanceof HTMLAnchorElement)) {
28556
+ const innerClickable = el.shadowRoot.querySelector(
28557
+ 'button, a, [role="button"], [role="link"]'
28558
+ );
28559
+ if (innerClickable) {
28560
+ targetEl = innerClickable;
28561
+ }
28562
+ }
28563
+ const rect = targetEl.getBoundingClientRect();
28564
+ const cx = rect.left + rect.width / 2;
28565
+ const cy = rect.top + rect.height / 2;
28566
+ const eventSequence = [
28567
+ { type: "pointerenter", bubbles: false, usePointer: true },
28568
+ { type: "pointerover", bubbles: true, usePointer: true },
28569
+ { type: "pointermove", bubbles: true, usePointer: true },
28570
+ { type: "mouseenter", bubbles: false, usePointer: false },
28571
+ { type: "mouseover", bubbles: true, usePointer: false },
28572
+ { type: "mousemove", bubbles: true, usePointer: false }
28573
+ ];
28574
+ for (const { type, bubbles, usePointer } of eventSequence) {
28575
+ const EventClass = usePointer ? PointerEvent : MouseEvent;
28576
+ targetEl.dispatchEvent(new EventClass(type, {
28577
+ bubbles,
28578
+ cancelable: true,
28579
+ view: window,
28580
+ clientX: cx,
28581
+ clientY: cy
28582
+ }));
28583
+ }
28584
+ await waitForDomSettled();
28585
+ const mode = args.responseMode ?? "diff";
28586
+ return ctx.buildBrowserStateResponse(mode);
28587
+ }
28588
+
28298
28589
  // ../next-sdk/page-tools/page-agent-tool.ts
28299
28590
  function registerPageAgentTool(options = {}) {
28300
28591
  initializeBuiltinWebMCP();
28301
- if (typeof options.enableHighlight === "undefined") {
28302
- options.enableHighlight = true;
28303
- }
28304
- window.__webmcpcli_interactiveWhitelist = window.__webmcpcli_interactiveWhitelist || [];
28305
- window.__webmcpcli_interactiveBlacklist = window.__webmcpcli_interactiveBlacklist || [];
28306
- window.__webmcpcli_exposedAttributes = window.__webmcpcli_exposedAttributes || options?.exposedAttributes || [];
28592
+ setPageAgentToolConfig(options, { mode: "replace" });
28307
28593
  window.__webmcpcli_beforeGetBrowserState = window.__webmcpcli_beforeGetBrowserState || null;
28308
- window.__webmcpcli_errorSelectors = window.__webmcpcli_errorSelectors || DEFAULT_ERROR_SELECTORS2;
28309
- window.__webmcpcli_dialogSelectors = window.__webmcpcli_dialogSelectors || DEFAULT_DIALOG_SELECTORS;
28310
28594
  const pageController = new PageController({ enableMask: false });
28595
+ const simulatorMask = new SimulatorMask2();
28311
28596
  pageController.maskReady = (async () => {
28312
- pageController.mask = new SimulatorMask2();
28597
+ pageController.mask = simulatorMask;
28313
28598
  })();
28314
28599
  const stateCache = new PageStateCache();
28315
28600
  let currentRefMap = /* @__PURE__ */ new Map();
28316
28601
  async function errContent(msg) {
28317
- await pageController.hideMask();
28318
28602
  return { content: [{ type: "text", text: msg }] };
28319
28603
  }
28604
+ async function actionError(msg) {
28605
+ const result2 = await createActionErrorResult(msg, buildBrowserStateResponse);
28606
+ options.removeMaskAfterToolCall && await pageController.hideMask();
28607
+ return result2;
28608
+ }
28320
28609
  async function refreshOnStaleRef(action, index) {
28321
28610
  const refreshResult = await buildBrowserStateResponse("full");
28322
- const warning = `\u26A0\uFE0F ${action}\u5931\u8D25: ref \u7D22\u5F15 ${index} \u5DF2\u5931\u6548\uFF08\u9875\u9762\u53EF\u80FD\u5DF2\u5237\u65B0\uFF09\uFF0C\u5DF2\u81EA\u52A8\u91CD\u65B0\u52A0\u8F7D\u9875\u9762\u72B6\u6001\uFF0C\u8BF7\u4F7F\u7528\u65B0\u7684 ref \u7D22\u5F15\u91CD\u8BD5\u3002
28323
- `;
28611
+ const warning = `\u26A0\uFE0F ${action}\u5931\u8D25: ref \u7D22\u5F15 ${index} \u5DF2\u5931\u6548\uFF08\u9875\u9762\u53EF\u80FD\u5DF2\u5237\u65B0\uFF09\uFF0C\u5DF2\u81EA\u52A8\u91CD\u65B0\u52A0\u8F7D\u9875\u9762\u72B6\u6001\uFF0C\u8BF7\u4F7F\u7528\u65B0\u7684 ref \u7D22\u5F15\u91CD\u8BD5\u3002`;
28324
28612
  return {
28325
- content: [{ type: "text", text: warning + refreshResult.content[0].text }]
28613
+ content: [
28614
+ {
28615
+ type: "text",
28616
+ text: withStateFields(refreshResult.content[0].text, { warning })
28617
+ }
28618
+ ]
28326
28619
  };
28327
28620
  }
28328
28621
  async function buildBrowserStateResponse(responseMode = "diff") {
28329
28622
  const url2 = window.location.href;
28330
28623
  const title = document.title;
28331
- const blacklist = window.__webmcpcli_interactiveBlacklist ?? [];
28332
- const whitelist = window.__webmcpcli_interactiveWhitelist ?? [];
28333
- const exposedAttributes = window.__webmcpcli_exposedAttributes ?? [];
28334
- const { yaml, refMap } = buildA11yTree(document.body, blacklist, whitelist, {
28335
- exposedAttributes,
28336
- errorSelectors: (window.__webmcpcli_errorSelectors ?? DEFAULT_ERROR_SELECTORS2).join(", ")
28337
- });
28624
+ const { yaml, refMap } = buildA11yTree(document.body, getPageAgentToolConfig().a11yConfig);
28338
28625
  currentRefMap = refMap;
28339
- if (options?.enableHighlight) {
28626
+ if (getPageAgentToolConfig().enableHighlight) {
28340
28627
  highlight(refMap);
28341
28628
  globalRemoveListener();
28342
28629
  }
28343
28630
  const diff2 = stateCache.update(url2, yaml);
28344
- await pageController.hideMask();
28345
- const dialogAlert = detectPageDialog();
28631
+ const dialogs = detectPageDialog();
28346
28632
  const validationErrors = detectValidationErrors();
28633
+ const tooltips = detectVisibleTooltips();
28347
28634
  let displayContent = "";
28348
28635
  if (responseMode === "full") {
28349
28636
  displayContent = yaml;
@@ -28359,10 +28646,12 @@ ${diff2.isFullRefresh ? "\uFF08\u9996\u6B21/\u5237\u65B0\uFF0C\u65E0\u589E\u91CF
28359
28646
  const stateObj = {
28360
28647
  url: url2,
28361
28648
  title,
28362
- content: displayContent
28649
+ content: displayContent,
28650
+ ...dialogs.length > 0 ? { dialogs } : {},
28651
+ ...validationErrors.length > 0 ? { validationErrors } : {},
28652
+ ...tooltips.length > 0 ? { tooltips } : {}
28363
28653
  };
28364
- const text = `\u6D4F\u89C8\u5668\u72B6\u6001: ${JSON.stringify(stateObj)}${dialogAlert}${validationErrors}`;
28365
- return { content: [{ type: "text", text }] };
28654
+ return { content: [{ type: "text", text: JSON.stringify(stateObj) }] };
28366
28655
  }
28367
28656
  const actionContext = {
28368
28657
  pageController,
@@ -28373,41 +28662,287 @@ ${diff2.isFullRefresh ? "\uFF08\u9996\u6B21/\u5237\u65B0\uFF0C\u65E0\u589E\u91CF
28373
28662
  },
28374
28663
  buildBrowserStateResponse,
28375
28664
  refreshOnStaleRef,
28376
- errContent
28665
+ errContent,
28666
+ actionError
28377
28667
  };
28378
- document.modelContext.registerTool({
28668
+ function borderTargetElement(index) {
28669
+ if (index === void 0) return;
28670
+ const el = currentRefMap.get(index);
28671
+ if (el) simulatorMask.borderElement(el);
28672
+ }
28673
+ async function executePageAgentTool(args) {
28674
+ try {
28675
+ let ret;
28676
+ switch (args.action) {
28677
+ case "browserState":
28678
+ ret = await handleBrowserState(args, actionContext);
28679
+ break;
28680
+ case "click":
28681
+ await pageController.showMask();
28682
+ borderTargetElement(args.index);
28683
+ ret = await handleClick(args, actionContext);
28684
+ options.removeMaskAfterToolCall && await pageController.hideMask();
28685
+ break;
28686
+ case "fill":
28687
+ await pageController.showMask();
28688
+ borderTargetElement(args.index);
28689
+ ret = await handleFill(args, actionContext);
28690
+ options.removeMaskAfterToolCall && await pageController.hideMask();
28691
+ break;
28692
+ case "select":
28693
+ await pageController.showMask();
28694
+ borderTargetElement(args.index);
28695
+ ret = await handleSelect(args, actionContext);
28696
+ options.removeMaskAfterToolCall && await pageController.hideMask();
28697
+ break;
28698
+ case "scroll":
28699
+ await pageController.showMask();
28700
+ ret = await handleScroll(args, actionContext);
28701
+ options.removeMaskAfterToolCall && await pageController.hideMask();
28702
+ break;
28703
+ case "executeJavascript":
28704
+ ret = await handleExecuteJavascript(args, actionContext);
28705
+ break;
28706
+ case "searchTree":
28707
+ ret = await handleSearchTree(args, actionContext);
28708
+ break;
28709
+ case "hover":
28710
+ ret = await handleHover(args, actionContext);
28711
+ break;
28712
+ default:
28713
+ ret = { content: [{ type: "text", text: `\u672A\u77E5\u64CD\u4F5C: ${args.action}` }] };
28714
+ }
28715
+ return ret;
28716
+ } catch (error2) {
28717
+ const actionNames = {
28718
+ click: "\u70B9\u51FB",
28719
+ fill: "\u586B\u5199",
28720
+ select: "\u9009\u62E9"
28721
+ };
28722
+ if (args.action in actionNames) {
28723
+ return actionError(
28724
+ `${actionNames[args.action]}\u6267\u884C\u5F02\u5E38: ${error2 instanceof Error ? error2.message : String(error2)}`
28725
+ );
28726
+ }
28727
+ options.removeMaskAfterToolCall && await pageController.hideMask();
28728
+ throw error2;
28729
+ } finally {
28730
+ simulatorMask.removeBorderElement();
28731
+ }
28732
+ }
28733
+ const modelContext = document.modelContext;
28734
+ if (!modelContext) {
28735
+ console.warn("[next-sdk] modelContext is not available, skipping page-agent-tool registration.");
28736
+ return {
28737
+ showMask: () => pageController.showMask(),
28738
+ hideMask: () => pageController.hideMask()
28739
+ };
28740
+ }
28741
+ try {
28742
+ modelContext.unregisterTool?.("page-agent-tool");
28743
+ } catch {
28744
+ }
28745
+ modelContext.registerTool({
28379
28746
  name: "page-agent-tool",
28380
28747
  description: page_agent_prompt_default,
28381
28748
  // @ts-ignore
28382
28749
  inputSchema: zodToJsonSchema(inputSchema),
28383
28750
  async execute(args) {
28384
- await pageController.showMask();
28385
28751
  try {
28386
- switch (args.action) {
28387
- case "browserState":
28388
- return await handleBrowserState(args, actionContext);
28389
- case "click":
28390
- return await handleClick(args, actionContext);
28391
- case "fill":
28392
- return await handleFill(args, actionContext);
28393
- case "select":
28394
- return await handleSelect(args, actionContext);
28395
- case "scroll":
28396
- return await handleScroll(args, actionContext);
28397
- case "executeJavascript":
28398
- return await handleExecuteJavascript(args, actionContext);
28399
- case "searchTree":
28400
- return await handleSearchTree(args, actionContext);
28401
- default:
28402
- await pageController.hideMask();
28403
- return { content: [{ type: "text", text: `\u672A\u77E5\u64CD\u4F5C: ${args.action}` }] };
28404
- }
28752
+ return executePageAgentTool(args);
28405
28753
  } catch (error2) {
28406
- await pageController.hideMask();
28407
28754
  return { content: [{ type: "text", text: `\u5F02\u5E38: ${String(error2)}` }] };
28408
28755
  }
28409
28756
  }
28410
28757
  });
28758
+ setupPageAgentToolEventBridge(executePageAgentTool, pageController, actionContext);
28759
+ return {
28760
+ showMask: () => pageController.showMask(),
28761
+ hideMask: () => pageController.hideMask()
28762
+ };
28763
+ }
28764
+
28765
+ // ../next-sdk/page-tools/configs/console-cloud.ts
28766
+ var consoleCloudPageAgentToolOptions = {
28767
+ enableHighlight: false,
28768
+ a11yConfig: defineA11yConfig({
28769
+ roles: [
28770
+ // Tiny3 App Layout / Content Layout:补齐 landmark,帮助 AI 理解分区结构
28771
+ { role: "navigation", selector: "ti-app-layout-left", name: "\u4FA7\u8FB9\u5BFC\u822A" },
28772
+ { role: "main", selector: "ti-app-layout-main", name: "\u4E3B\u5185\u5BB9\u533A" },
28773
+ {
28774
+ role: "banner",
28775
+ selector: ["ti-app-layout-main-header", "tp-layout-content-header"],
28776
+ name: "\u9875\u9762\u5934\u90E8"
28777
+ },
28778
+ { role: "region", selector: "ti-app-layout-main-content", name: "\u9875\u9762\u5185\u5BB9" },
28779
+ { role: "region", selector: "tp-layout-content-body", name: "\u9875\u9762\u6B63\u6587" },
28780
+ { role: "complementary", selector: "ti-app-layout-right", name: "\u53F3\u4FA7\u9762\u677F" },
28781
+ // Tiny3 Tabs:真正可聚焦/可点击的是内部 .ti3-tabs-text(tabindex=0)
28782
+ { role: "tablist", selector: "ul.ti3-tabs" },
28783
+ { role: "tab", selector: ".ti3-tabs-text" },
28784
+ { role: "tabpanel", selector: ["ti-tab.ti3-tab-pane", ".ti3-tab-pane"] },
28785
+ // 自定义下拉 / 区域选择触发器
28786
+ {
28787
+ role: "combobox",
28788
+ selector: [
28789
+ ".ti3-select-dominator-container",
28790
+ ".selected-label",
28791
+ ".sort-select",
28792
+ ".service-select",
28793
+ ".region-select",
28794
+ '[cf-uba="searchableRegion..open"]'
28795
+ ]
28796
+ },
28797
+ // 图标型 / 无语义按钮
28798
+ {
28799
+ role: "button",
28800
+ selector: [
28801
+ ".modules-service-list-menu-service-icon-container",
28802
+ ".ti3-btn-only-icon-noborder",
28803
+ ".ti3-select-dominator-dropdown-btn",
28804
+ ".modules-right-sidebar-icon-item-wrapper",
28805
+ ".modules-right-sidebar-hide-state-plugin",
28806
+ ".components-service-list-container-service-list-input-service-close",
28807
+ ".modules-searchable-region-region-panel-close",
28808
+ ".modules-searchable-region-region-panel-search-btn",
28809
+ '[cf-uba="rightSidebar..hideBtn"]',
28810
+ // Tiny3 图标组件:帮助中心固定/全屏/关闭等(ti-icon / tp-icon 无原生 button 语义)
28811
+ ".ti-global-help-panel-header-icon",
28812
+ "ti-icon[name]",
28813
+ "tp-icon[name]",
28814
+ // 无 name 的箭头/操作图标(如 latest news 区 common-icon 展开箭头)
28815
+ "tp-icon.common-icon",
28816
+ "ti-icon.common-icon",
28817
+ "ti-icon.ti3-icon-full-screen",
28818
+ "ti-icon.ti3-icon-close",
28819
+ "tp-icon.ti3-icon-full-screen",
28820
+ "tp-icon.ti3-icon-close"
28821
+ ]
28822
+ },
28823
+ // 服务列表侧栏分类 / 顶栏菜单项
28824
+ {
28825
+ role: "menuitem",
28826
+ selector: [
28827
+ ".components-service-list-left-box-sidebar-visit-panel > li",
28828
+ ".modules-menus-menu-item",
28829
+ ".components-menu-wrapper-menu-text"
28830
+ ]
28831
+ },
28832
+ // 区域筛选项 / 下拉选项
28833
+ {
28834
+ role: "option",
28835
+ selector: [
28836
+ ".region-selector-item",
28837
+ ".modules-searchable-region-project-item-region-item",
28838
+ ".modules-searchable-region-region-panel-recent-region-item",
28839
+ ".ti3-multiselect-box-cell"
28840
+ ]
28841
+ },
28842
+ // 模态弹窗:补齐缺失的 role="dialog"(Tiny3 modal/message-box/drawer/侧栏面板)
28843
+ {
28844
+ role: "dialog",
28845
+ selector: [
28846
+ '[class*="ti3-modal"]',
28847
+ '[class*="ti3-message-box"]',
28848
+ '[class*="drawer"]',
28849
+ ".modules-layout-module-sidebar-panel"
28850
+ ]
28851
+ },
28852
+ // Tiny3 tooltip / 帮助提示:补齐缺失的 role="tooltip"
28853
+ {
28854
+ role: "tooltip",
28855
+ selector: ["tp-helptip", '[class*="ti3-tooltip"]', ".tp-helptip-content", ".ti3-tooltip", ".ti3-tooltip-popper"]
28856
+ }
28857
+ ],
28858
+ states: {
28859
+ // 选中态:挂在容器 class 上,用 selector + closest 即可命中内部交互节点
28860
+ selected: [
28861
+ { selector: "li.ti3-tab-li.ti3-tab-active" },
28862
+ // Tiny3 按钮组(计费模式等):ti3-active 在 .ti3-btn-item-container 上,不在 button 上
28863
+ { selector: ".ti3-btn-item-container.ti3-active" },
28864
+ { selector: ".components-service-list-left-box-active" },
28865
+ {
28866
+ selector: [
28867
+ ".modules-searchable-region-project-item-region-item-selected",
28868
+ ".components-search-content-search-select-search-select-selected"
28869
+ ]
28870
+ }
28871
+ ],
28872
+ hasPopup: [
28873
+ {
28874
+ selector: [
28875
+ ".ti3-select-dominator-container",
28876
+ ".selected-label",
28877
+ ".sort-select",
28878
+ ".service-select",
28879
+ ".region-select",
28880
+ '[cf-uba="searchableRegion..open"]',
28881
+ '[cf-uba="serviceList..open"]',
28882
+ '[cf-uba="userinfo"]',
28883
+ "tp-helptip"
28884
+ ]
28885
+ }
28886
+ ],
28887
+ disabled: [{ selector: ".ti3-disabled" }],
28888
+ // Tiny3 / Lego 校验错误
28889
+ error: [{ selector: [".ti3-unifyvalid-error", ".ti3-error", ".ti-error", ".lego-text-error", ".lego-error"] }],
28890
+ // Tiny3 / Lego 警告
28891
+ warning: [{ selector: [".ti3-warning", ".ti-warning", ".lego-text-warning"] }],
28892
+ // 展开态:需结合计算样式,选择器表达不了「可见」
28893
+ expanded: [
28894
+ {
28895
+ match: (el) => {
28896
+ try {
28897
+ if (!el.matches(
28898
+ ".modules-layout-module-sidebar-panel, .modules-searchable-region-region-panel, .ti3-dropdown-container"
28899
+ )) {
28900
+ return false;
28901
+ }
28902
+ const style = window.getComputedStyle(el);
28903
+ return style.display !== "none" && style.visibility !== "hidden" && style.opacity !== "0";
28904
+ } catch {
28905
+ return false;
28906
+ }
28907
+ }
28908
+ }
28909
+ ]
28910
+ },
28911
+ // exposedAttributes 输出属性 token;带 name 的 ti-icon/tp-icon 可交互性由 roles/whitelist 中 ti-icon[name] 等规则判定。
28912
+ exposedAttributes: ["cf-uba", "data-qa-id", "name"],
28913
+ whitelist: [
28914
+ ".modules-service-list-menu-service-icon-container",
28915
+ ".ti3-tabs-text",
28916
+ "tp-helptip",
28917
+ '[cf-uba="cloudShell"]',
28918
+ '[cf-uba="messageBox"]',
28919
+ '[cf-uba="helpFeedback"]',
28920
+ '[cf-uba="globalMessage"]',
28921
+ '[cf-uba="rightSidebar..hideBtn"]',
28922
+ // 帮助中心等区域的 ti-icon / tp-icon 图标按钮
28923
+ ".ti-global-help-panel-header-icon",
28924
+ "ti-icon[name]",
28925
+ "tp-icon[name]",
28926
+ "tp-icon.common-icon",
28927
+ "ti-icon.common-icon",
28928
+ "ti-icon.ti3-icon-full-screen"
28929
+ ],
28930
+ blacklist: [
28931
+ "noscript",
28932
+ "pan-gu",
28933
+ // 忽略 WebMCP 高亮容器
28934
+ "#webmcpcli-highlight-container",
28935
+ "#page-agent-runtime_simulator-mask",
28936
+ // CFUI 忽略几个大区域
28937
+ "#J_header",
28938
+ "#J_rightSidebar",
28939
+ "#cf_service_icon",
28940
+ "tp-helptip"
28941
+ ]
28942
+ })
28943
+ };
28944
+ function isConsoleCloudHost(hostname2 = typeof location !== "undefined" ? location.hostname : "") {
28945
+ return /(^|\.)console\.huaweicloud\.com$/i.test(hostname2);
28411
28946
  }
28412
28947
 
28413
28948
  // src/inject/page-init.ts
@@ -28417,12 +28952,18 @@ ${diff2.isFullRefresh ? "\uFF08\u9996\u6B21/\u5237\u65B0\uFF0C\u65E0\u589E\u91CF
28417
28952
  window.__webmcpcli_tools = await ctx.getTools();
28418
28953
  }
28419
28954
  }
28955
+ function resolvePageAgentToolOptions() {
28956
+ if (isConsoleCloudHost(location.hostname)) {
28957
+ return consoleCloudPageAgentToolOptions;
28958
+ }
28959
+ return { a11yConfig: { exposedAttributes: ["cf-uba"] } };
28960
+ }
28420
28961
  function initWebMcpCliPage() {
28421
28962
  if (window.__webmcpcli_init) {
28422
28963
  return;
28423
28964
  }
28424
28965
  initializeWebMCPPolyfill();
28425
- registerPageAgentTool({ exposedAttributes: ["cf-uba"] });
28966
+ registerPageAgentTool(resolvePageAgentToolOptions());
28426
28967
  window.__webmcpcli_tools = [];
28427
28968
  const ctx = document.modelContext;
28428
28969
  if (ctx?.addEventListener) {