@refrainai/cli 0.4.1 → 0.4.2

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.
Files changed (83) hide show
  1. package/dist/{ai-model-FM6GWCID.js → ai-model-DP5PKGM6.js} +2 -2
  2. package/dist/{chunk-2BVDAJZT.js → chunk-65CTEK2K.js} +9 -6
  3. package/dist/chunk-65CTEK2K.js.map +1 -0
  4. package/dist/chunk-BGC75OVR.js +30 -0
  5. package/dist/chunk-BGC75OVR.js.map +1 -0
  6. package/dist/{chunk-H47NWH7N.js → chunk-CJM3IU5Q.js} +611 -73
  7. package/dist/chunk-CJM3IU5Q.js.map +1 -0
  8. package/dist/{chunk-CLYJHKPY.js → chunk-CMWLFQXD.js} +43 -42
  9. package/dist/chunk-CMWLFQXD.js.map +1 -0
  10. package/dist/{chunk-IGFCYKHC.js → chunk-CNJ5KCDN.js} +252 -295
  11. package/dist/chunk-CNJ5KCDN.js.map +1 -0
  12. package/dist/{chunk-DJVUITRB.js → chunk-ELQ23L4Z.js} +898 -1135
  13. package/dist/chunk-ELQ23L4Z.js.map +1 -0
  14. package/dist/chunk-EMAYENG4.js +1146 -0
  15. package/dist/chunk-EMAYENG4.js.map +1 -0
  16. package/dist/{chunk-7UCVPKD4.js → chunk-F7WTOQIQ.js} +12 -72
  17. package/dist/chunk-F7WTOQIQ.js.map +1 -0
  18. package/dist/{chunk-WEYR56ZN.js → chunk-HHRHHFSK.js} +4 -4
  19. package/dist/{chunk-UGPXCQY3.js → chunk-KFNW4XR2.js} +13 -4
  20. package/dist/chunk-KFNW4XR2.js.map +1 -0
  21. package/dist/{chunk-RT664YIO.js → chunk-LZDZGI4M.js} +3 -1
  22. package/dist/chunk-LZDZGI4M.js.map +1 -0
  23. package/dist/chunk-RBZK7T76.js +349 -0
  24. package/dist/chunk-RBZK7T76.js.map +1 -0
  25. package/dist/{chunk-HQDXLWAY.js → chunk-SDV3X5UN.js} +2 -2
  26. package/dist/{chunk-Z33FCOTZ.js → chunk-VVXNFUPL.js} +4 -2
  27. package/dist/chunk-VVXNFUPL.js.map +1 -0
  28. package/dist/chunk-XIVS7N3V.js +74 -0
  29. package/dist/chunk-XIVS7N3V.js.map +1 -0
  30. package/dist/chunk-YTVEYQGA.js +64 -0
  31. package/dist/chunk-YTVEYQGA.js.map +1 -0
  32. package/dist/{chunk-RYIJPYM3.js → chunk-YW46VP57.js} +25 -8
  33. package/dist/chunk-YW46VP57.js.map +1 -0
  34. package/dist/cli.js +5 -5
  35. package/dist/{compose-MTSIJY5D.js → compose-B2IAO7YW.js} +9 -7
  36. package/dist/{compose-MTSIJY5D.js.map → compose-B2IAO7YW.js.map} +1 -1
  37. package/dist/extraction-prompt-VDCKIFLB.js +17 -0
  38. package/dist/extraction-prompt-VDCKIFLB.js.map +1 -0
  39. package/dist/{fix-runbook-ZSBOTLC2.js → fix-runbook-JJN4HVIP.js} +12 -10
  40. package/dist/{fix-runbook-ZSBOTLC2.js.map → fix-runbook-JJN4HVIP.js.map} +1 -1
  41. package/dist/prompts-XMJXIITW.js +13 -0
  42. package/dist/runbook-builder-2ZLE2AEO.js +11 -0
  43. package/dist/{runbook-data-helpers-KRR2SH76.js → runbook-data-helpers-5UAO65TZ.js} +3 -3
  44. package/dist/{runbook-executor-K7T6RJWJ.js → runbook-executor-TVV5EG6Q.js} +41 -444
  45. package/dist/runbook-executor-TVV5EG6Q.js.map +1 -0
  46. package/dist/{runbook-generator-MPXJBQ5N.js → runbook-generator-4XKNV2B7.js} +61 -136
  47. package/dist/runbook-generator-4XKNV2B7.js.map +1 -0
  48. package/dist/{runbook-schema-3T6TP3JJ.js → runbook-schema-X7DW725O.js} +2 -2
  49. package/dist/runbook-store-S24PXIHD.js +11 -0
  50. package/dist/{schema-5G6UQSPT.js → schema-XFSD5EWN.js} +2 -2
  51. package/dist/{server-AG3LXQBI.js → server-5XARL5N7.js} +1176 -128
  52. package/dist/server-5XARL5N7.js.map +1 -0
  53. package/dist/{tenant-ai-config-QPFEJUVJ.js → tenant-ai-config-4NHKRW7O.js} +4 -4
  54. package/dist/tenant-ai-config-4NHKRW7O.js.map +1 -0
  55. package/dist/yaml-patcher-32QBPXT2.js +18 -0
  56. package/dist/yaml-patcher-32QBPXT2.js.map +1 -0
  57. package/package.json +3 -2
  58. package/dist/chunk-2BVDAJZT.js.map +0 -1
  59. package/dist/chunk-7UCVPKD4.js.map +0 -1
  60. package/dist/chunk-CLYJHKPY.js.map +0 -1
  61. package/dist/chunk-DJVUITRB.js.map +0 -1
  62. package/dist/chunk-H47NWH7N.js.map +0 -1
  63. package/dist/chunk-IGFCYKHC.js.map +0 -1
  64. package/dist/chunk-RT664YIO.js.map +0 -1
  65. package/dist/chunk-RYIJPYM3.js.map +0 -1
  66. package/dist/chunk-UGPXCQY3.js.map +0 -1
  67. package/dist/chunk-VPK2MQAZ.js +0 -589
  68. package/dist/chunk-VPK2MQAZ.js.map +0 -1
  69. package/dist/chunk-Z33FCOTZ.js.map +0 -1
  70. package/dist/runbook-executor-K7T6RJWJ.js.map +0 -1
  71. package/dist/runbook-generator-MPXJBQ5N.js.map +0 -1
  72. package/dist/runbook-store-G5GUOWRR.js +0 -11
  73. package/dist/server-AG3LXQBI.js.map +0 -1
  74. package/dist/yaml-patcher-VGUS2JGH.js +0 -15
  75. /package/dist/{ai-model-FM6GWCID.js.map → ai-model-DP5PKGM6.js.map} +0 -0
  76. /package/dist/{chunk-WEYR56ZN.js.map → chunk-HHRHHFSK.js.map} +0 -0
  77. /package/dist/{chunk-HQDXLWAY.js.map → chunk-SDV3X5UN.js.map} +0 -0
  78. /package/dist/{runbook-data-helpers-KRR2SH76.js.map → prompts-XMJXIITW.js.map} +0 -0
  79. /package/dist/{runbook-schema-3T6TP3JJ.js.map → runbook-builder-2ZLE2AEO.js.map} +0 -0
  80. /package/dist/{runbook-store-G5GUOWRR.js.map → runbook-data-helpers-5UAO65TZ.js.map} +0 -0
  81. /package/dist/{schema-5G6UQSPT.js.map → runbook-schema-X7DW725O.js.map} +0 -0
  82. /package/dist/{tenant-ai-config-QPFEJUVJ.js.map → runbook-store-S24PXIHD.js.map} +0 -0
  83. /package/dist/{yaml-patcher-VGUS2JGH.js.map → schema-XFSD5EWN.js.map} +0 -0
@@ -1,10 +1,17 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  cancel,
4
- getLocale,
5
- log,
4
+ log
5
+ } from "./chunk-XIVS7N3V.js";
6
+ import {
7
+ computeCacheRate,
8
+ computeTotalRealInput,
9
+ getModelId,
10
+ getModelProvider
11
+ } from "./chunk-KFNW4XR2.js";
12
+ import {
6
13
  t
7
- } from "./chunk-7UCVPKD4.js";
14
+ } from "./chunk-F7WTOQIQ.js";
8
15
 
9
16
  // src/cli/debug-logger.ts
10
17
  import { appendFile, writeFile } from "fs/promises";
@@ -390,6 +397,167 @@ function formatDuration(ms) {
390
397
  return ms >= 1e3 ? `${(ms / 1e3).toFixed(1)}s` : `${Math.round(ms)}ms`;
391
398
  }
392
399
 
400
+ // src/cli/options-serializer.ts
401
+ function serializeGeneratorOptions(config) {
402
+ const opts = [];
403
+ opts.push({ name: "--url", value: config.url });
404
+ opts.push({ name: "--goal", value: config.goal });
405
+ opts.push({ name: "--output", value: config.output });
406
+ opts.push({ name: "--headless", value: String(config.headless) });
407
+ opts.push({ name: "--max-iterations", value: String(config.maxIterations) });
408
+ opts.push({ name: "--step-delay", value: `${config.stepDelay}ms` });
409
+ opts.push({ name: "--stall-check-interval", value: String(config.stallCheckInterval) });
410
+ opts.push({ name: "--history-window", value: String(config.historyWindow) });
411
+ opts.push({ name: "--max-failures", value: String(config.maxConsecutiveFailures) });
412
+ opts.push({ name: "--snapshot-filter", value: String(config.snapshotFilter) });
413
+ if (config.screenshotDir) {
414
+ opts.push({ name: "--screenshots", value: config.screenshotDir });
415
+ }
416
+ if (config.contextMarkdown) {
417
+ opts.push({ name: "--context", value: `loaded (${config.contextMarkdown.split("\n").length} lines)` });
418
+ }
419
+ if (config.secrets && Object.keys(config.secrets.values).length > 0) {
420
+ opts.push({ name: "--secrets", value: `${Object.keys(config.secrets.values).length} keys` });
421
+ }
422
+ if (config.debugLogPath) {
423
+ opts.push({ name: "--debug-log", value: config.debugLogPath });
424
+ }
425
+ if (config.debugConsole) {
426
+ opts.push({ name: "--debug", value: "true" });
427
+ }
428
+ if (config.stealth) {
429
+ opts.push({ name: "--stealth", value: "true" });
430
+ }
431
+ if (config.proxy) {
432
+ opts.push({ name: "--proxy", value: config.proxy });
433
+ }
434
+ if (config.videoDir) {
435
+ opts.push({ name: "--video", value: config.videoDir });
436
+ }
437
+ if (config.skills && config.skills.length > 0) {
438
+ opts.push({ name: "--skill", value: config.skills.join(", ") });
439
+ }
440
+ serializeModelConfig(opts, config.aiModelConfig);
441
+ return opts;
442
+ }
443
+ function serializeExecutorOptions(config) {
444
+ const opts = [];
445
+ opts.push({ name: "--runbook", value: config.runbookPath });
446
+ opts.push({ name: "--headless", value: String(config.headless) });
447
+ if (config.stepDelay !== void 0) {
448
+ opts.push({ name: "--step-delay", value: `${config.stepDelay}ms` });
449
+ }
450
+ if (config.screenshotDir) {
451
+ opts.push({ name: "--screenshots", value: config.screenshotDir });
452
+ }
453
+ if (config.contextMarkdown) {
454
+ opts.push({ name: "--context", value: `loaded (${config.contextMarkdown.split("\n").length} lines)` });
455
+ }
456
+ if (config.secrets && Object.keys(config.secrets.values).length > 0) {
457
+ opts.push({ name: "--secrets", value: `${Object.keys(config.secrets.values).length} keys` });
458
+ }
459
+ if (config.skipConfirmation) {
460
+ opts.push({ name: "--yes", value: "true" });
461
+ }
462
+ if (config.dataFilePath) {
463
+ opts.push({ name: "--data", value: config.dataFilePath });
464
+ }
465
+ if (config.reuseSession === false) {
466
+ opts.push({ name: "--no-reuse-session", value: "true" });
467
+ }
468
+ if (config.debugLogPath) {
469
+ opts.push({ name: "--debug-log", value: config.debugLogPath });
470
+ }
471
+ if (config.debugConsole) {
472
+ opts.push({ name: "--debug", value: "true" });
473
+ }
474
+ if (config.approvalMode && config.approvalMode !== "web") {
475
+ opts.push({ name: "--approval-mode", value: config.approvalMode });
476
+ }
477
+ if (config.notifyMode) {
478
+ opts.push({ name: "--notify", value: config.notifyMode });
479
+ }
480
+ if (config.enableSelectorCache) {
481
+ opts.push({ name: "--enable-selector-cache", value: "true" });
482
+ }
483
+ if (config.enableAgentFallback) {
484
+ opts.push({ name: "--enable-agent-fallback", value: "true" });
485
+ }
486
+ if (config.enableVisionFallback) {
487
+ opts.push({ name: "--enable-vision-fallback", value: "true" });
488
+ }
489
+ if (config.outputDir) {
490
+ opts.push({ name: "--output-dir", value: config.outputDir });
491
+ }
492
+ if (config.mergeDownloads) {
493
+ opts.push({ name: "--merge-downloads", value: "true" });
494
+ }
495
+ if (config.selfHeal) {
496
+ opts.push({ name: "--self-heal", value: "true" });
497
+ }
498
+ if (config.maxRetries !== void 0) {
499
+ opts.push({ name: "--max-retries", value: String(config.maxRetries) });
500
+ }
501
+ if (config.retryWarningThreshold !== void 0) {
502
+ opts.push({ name: "--retry-warning-threshold", value: String(config.retryWarningThreshold) });
503
+ }
504
+ if (config.forceReport) {
505
+ opts.push({ name: "--report", value: "true" });
506
+ }
507
+ if (config.videoDir) {
508
+ opts.push({ name: "--video", value: config.videoDir });
509
+ }
510
+ if (config.callbackPort !== void 0) {
511
+ opts.push({ name: "--callback-port", value: String(config.callbackPort) });
512
+ }
513
+ if (config.approvalTimeoutMs !== void 0) {
514
+ opts.push({ name: "--approval-timeout", value: `${config.approvalTimeoutMs}ms` });
515
+ }
516
+ if (config.stealth) {
517
+ opts.push({ name: "--stealth", value: "true" });
518
+ }
519
+ if (config.proxy) {
520
+ opts.push({ name: "--proxy", value: config.proxy });
521
+ }
522
+ if (config.skills && config.skills.length > 0) {
523
+ opts.push({ name: "--skill", value: config.skills.join(", ") });
524
+ }
525
+ serializeModelConfig(opts, config.aiModelConfig);
526
+ return opts;
527
+ }
528
+ var MODEL_OVERRIDE_FLAGS = {
529
+ selector: "--model-selector",
530
+ extraction: "--model-extraction",
531
+ exploration: "--model-exploration",
532
+ review: "--model-review",
533
+ fallback: "--model-fallback",
534
+ vision: "--model-vision"
535
+ };
536
+ function serializeModelConfig(opts, aiModelConfig) {
537
+ if (!aiModelConfig) return;
538
+ opts.push({ name: "--model", value: aiModelConfig.modelId });
539
+ opts.push({ name: "--model-provider", value: aiModelConfig.provider });
540
+ if (aiModelConfig.baseURL) {
541
+ opts.push({ name: "--model-base-url", value: aiModelConfig.baseURL });
542
+ }
543
+ if (aiModelConfig.modelOverrides) {
544
+ for (const [purpose, modelId] of Object.entries(aiModelConfig.modelOverrides)) {
545
+ const flag = MODEL_OVERRIDE_FLAGS[purpose];
546
+ if (flag && modelId) {
547
+ opts.push({ name: flag, value: modelId });
548
+ }
549
+ }
550
+ }
551
+ }
552
+ function renderOptionsMarkdown(options) {
553
+ if (options.length === 0) return [];
554
+ const lines = [];
555
+ for (const opt of options) {
556
+ lines.push(`- \`${opt.name}\`: ${opt.value}`);
557
+ }
558
+ return lines;
559
+ }
560
+
393
561
  // src/cli/secrets-loader.ts
394
562
  import { readFile as readFile2 } from "fs/promises";
395
563
  function mergeVariablesIntoSecrets(secrets, variables) {
@@ -510,7 +678,8 @@ var INTERACTIVE_ROLES = /* @__PURE__ */ new Set([
510
678
  "spinbutton",
511
679
  "switch",
512
680
  "tab",
513
- "treeitem"
681
+ "treeitem",
682
+ "iframe"
514
683
  ]);
515
684
  var CONTENT_ROLES = /* @__PURE__ */ new Set([
516
685
  "heading",
@@ -652,6 +821,51 @@ async function findCursorInteractiveElements(page2, selector) {
652
821
  const fn2 = new Function("return " + scriptBody)();
653
822
  return page2.evaluate(fn2, rootSelector);
654
823
  }
824
+ async function inlineIframeSnapshots(page2, tree, refs, options) {
825
+ const mainFrame = page2.mainFrame();
826
+ const childFrames = page2.frames().filter((f) => f !== mainFrame && f.parentFrame() === mainFrame);
827
+ if (childFrames.length === 0) return tree;
828
+ const frameSnapshots = [];
829
+ for (const frame of childFrames) {
830
+ try {
831
+ const childAriaTree = await frame.locator(":root").ariaSnapshot();
832
+ if (!childAriaTree || childAriaTree.trim().length === 0) continue;
833
+ const childTree = processAriaTree(childAriaTree, refs, options);
834
+ if (childTree && childTree !== "(empty)" && childTree !== "(no interactive elements)") {
835
+ const frameUrl = frame.url();
836
+ const frameId = `frame-${frameSnapshots.length}`;
837
+ for (const [ref, data] of Object.entries(refs)) {
838
+ if (!data.frameId && childTree.includes(`[ref=${ref}]`)) {
839
+ data.frameId = frameId;
840
+ }
841
+ }
842
+ frameSnapshots.push(childTree);
843
+ }
844
+ } catch {
845
+ }
846
+ }
847
+ if (frameSnapshots.length === 0) return tree;
848
+ const lines = tree.split("\n");
849
+ const result = [];
850
+ let frameIdx = 0;
851
+ for (const line of lines) {
852
+ result.push(line);
853
+ if (frameIdx < frameSnapshots.length && /^\s*-\s*iframe\b/i.test(line)) {
854
+ const indentMatch = line.match(/^(\s*)/);
855
+ const baseIndent = (indentMatch?.[1] ?? "") + " ";
856
+ const childLines = frameSnapshots[frameIdx].split("\n");
857
+ for (const childLine of childLines) {
858
+ result.push(baseIndent + childLine);
859
+ }
860
+ frameIdx++;
861
+ }
862
+ }
863
+ for (; frameIdx < frameSnapshots.length; frameIdx++) {
864
+ result.push(`# Child frame ${frameIdx}:`);
865
+ result.push(frameSnapshots[frameIdx]);
866
+ }
867
+ return result.join("\n");
868
+ }
655
869
  async function getEnhancedSnapshot(page2, options = {}) {
656
870
  resetRefs();
657
871
  const refs = {};
@@ -663,7 +877,8 @@ async function getEnhancedSnapshot(page2, options = {}) {
663
877
  refs: {}
664
878
  };
665
879
  }
666
- const enhancedTree = processAriaTree(ariaTree, refs, options);
880
+ let enhancedTree = processAriaTree(ariaTree, refs, options);
881
+ enhancedTree = await inlineIframeSnapshots(page2, enhancedTree, refs, options);
667
882
  if (options.cursor) {
668
883
  const cursorElements = await findCursorInteractiveElements(page2, options.selector);
669
884
  const existingTexts = new Set(Object.values(refs).map((r) => r.name.toLowerCase()));
@@ -1203,6 +1418,14 @@ function parseBooleanEnvVar(name, defaultValue) {
1203
1418
  }
1204
1419
  return defaultValue;
1205
1420
  }
1421
+ function parseQueryString(url) {
1422
+ try {
1423
+ const parsed = new URL(url);
1424
+ return Array.from(parsed.searchParams.entries()).map(([name, value]) => ({ name, value }));
1425
+ } catch {
1426
+ return [];
1427
+ }
1428
+ }
1206
1429
  var BrowserManager = class _BrowserManager {
1207
1430
  constructor() {
1208
1431
  this.browser = null;
@@ -1346,6 +1569,8 @@ var BrowserManager = class _BrowserManager {
1346
1569
  });
1347
1570
  if (refData.nth !== void 0) {
1348
1571
  locator2 = locator2.nth(refData.nth);
1572
+ } else {
1573
+ locator2 = locator2.first();
1349
1574
  }
1350
1575
  return locator2;
1351
1576
  }
@@ -1577,6 +1802,20 @@ var BrowserManager = class _BrowserManager {
1577
1802
  resourceType: request.resourceType()
1578
1803
  });
1579
1804
  });
1805
+ page2.on("response", (response) => {
1806
+ const url = response.url();
1807
+ for (let i = this.trackedRequests.length - 1; i >= 0; i--) {
1808
+ if (this.trackedRequests[i].url === url && this.trackedRequests[i].status === void 0) {
1809
+ this.trackedRequests[i].status = response.status();
1810
+ this.trackedRequests[i].statusText = response.statusText();
1811
+ this.trackedRequests[i].responseHeaders = response.headers();
1812
+ this.trackedRequests[i].mimeType = response.headers()["content-type"]?.split(";")[0]?.trim() ?? "";
1813
+ const contentLength = response.headers()["content-length"];
1814
+ this.trackedRequests[i].responseBodySize = contentLength ? parseInt(contentLength, 10) : -1;
1815
+ break;
1816
+ }
1817
+ }
1818
+ });
1580
1819
  }
1581
1820
  /**
1582
1821
  * Get tracked requests
@@ -1593,6 +1832,63 @@ var BrowserManager = class _BrowserManager {
1593
1832
  clearRequests() {
1594
1833
  this.trackedRequests = [];
1595
1834
  }
1835
+ /**
1836
+ * Generate HAR 1.2 JSON from tracked requests
1837
+ */
1838
+ generateHar() {
1839
+ const page2 = this.pages[this.activePageIndex];
1840
+ const pageUrl = page2?.url() ?? "";
1841
+ const pageTitle = "";
1842
+ const entries = this.trackedRequests.map((req) => {
1843
+ const reqHeaders = Object.entries(req.headers).map(([name, value]) => ({ name, value }));
1844
+ const resHeaders = req.responseHeaders ? Object.entries(req.responseHeaders).map(([name, value]) => ({ name, value })) : [];
1845
+ return {
1846
+ startedDateTime: new Date(req.timestamp).toISOString(),
1847
+ time: 0,
1848
+ request: {
1849
+ method: req.method,
1850
+ url: req.url,
1851
+ httpVersion: "HTTP/1.1",
1852
+ cookies: [],
1853
+ headers: reqHeaders,
1854
+ queryString: parseQueryString(req.url),
1855
+ headersSize: -1,
1856
+ bodySize: -1
1857
+ },
1858
+ response: {
1859
+ status: req.status ?? 0,
1860
+ statusText: req.statusText ?? "",
1861
+ httpVersion: "HTTP/1.1",
1862
+ cookies: [],
1863
+ headers: resHeaders,
1864
+ content: {
1865
+ size: req.responseBodySize ?? -1,
1866
+ mimeType: req.mimeType ?? ""
1867
+ },
1868
+ redirectURL: "",
1869
+ headersSize: -1,
1870
+ bodySize: req.responseBodySize ?? -1
1871
+ },
1872
+ cache: {},
1873
+ timings: { send: 0, wait: 0, receive: 0 }
1874
+ };
1875
+ });
1876
+ return {
1877
+ log: {
1878
+ version: "1.2",
1879
+ creator: { name: "agent-browser", version: "0.21.0" },
1880
+ pages: [
1881
+ {
1882
+ startedDateTime: (/* @__PURE__ */ new Date()).toISOString(),
1883
+ id: "page_1",
1884
+ title: pageTitle,
1885
+ pageTimings: { onContentLoad: -1, onLoad: -1 }
1886
+ }
1887
+ ],
1888
+ entries
1889
+ }
1890
+ };
1891
+ }
1596
1892
  /**
1597
1893
  * Add a route to intercept requests
1598
1894
  */
@@ -2591,20 +2887,23 @@ var BrowserManager = class _BrowserManager {
2591
2887
  return [
2592
2888
  path2.join(home, "Library", "Application Support", "Google", "Chrome"),
2593
2889
  path2.join(home, "Library", "Application Support", "Google", "Chrome Canary"),
2594
- path2.join(home, "Library", "Application Support", "Chromium")
2890
+ path2.join(home, "Library", "Application Support", "Chromium"),
2891
+ path2.join(home, "Library", "Application Support", "BraveSoftware", "Brave-Browser")
2595
2892
  ];
2596
2893
  } else if (platform === "win32") {
2597
2894
  const localAppData = process.env.LOCALAPPDATA ?? path2.join(home, "AppData", "Local");
2598
2895
  return [
2599
2896
  path2.join(localAppData, "Google", "Chrome", "User Data"),
2600
2897
  path2.join(localAppData, "Google", "Chrome SxS", "User Data"),
2601
- path2.join(localAppData, "Chromium", "User Data")
2898
+ path2.join(localAppData, "Chromium", "User Data"),
2899
+ path2.join(localAppData, "BraveSoftware", "Brave-Browser", "User Data")
2602
2900
  ];
2603
2901
  } else {
2604
2902
  return [
2605
2903
  path2.join(home, ".config", "google-chrome"),
2606
2904
  path2.join(home, ".config", "google-chrome-unstable"),
2607
- path2.join(home, ".config", "chromium")
2905
+ path2.join(home, ".config", "chromium"),
2906
+ path2.join(home, ".config", "BraveSoftware", "Brave-Browser")
2608
2907
  ];
2609
2908
  }
2610
2909
  }
@@ -4007,7 +4306,7 @@ var harStartSchema = baseCommandSchema.extend({
4007
4306
  });
4008
4307
  var harStopSchema = baseCommandSchema.extend({
4009
4308
  action: z.literal("har_stop"),
4010
- path: z.string().min(1)
4309
+ path: z.string().min(1).optional()
4011
4310
  });
4012
4311
  var stateSaveSchema = baseCommandSchema.extend({
4013
4312
  action: z.literal("state_save"),
@@ -6132,9 +6431,21 @@ async function handleHarStart(command2, browser2) {
6132
6431
  return successResponse(command2.id, { started: true });
6133
6432
  }
6134
6433
  async function handleHarStop(command2, browser2) {
6434
+ const har = browser2.generateHar();
6435
+ const harJson = JSON.stringify(har, null, 2);
6436
+ let outputPath = command2.path;
6437
+ if (!outputPath) {
6438
+ const harDir = path5.join(getAppDir(), "tmp", "har");
6439
+ mkdirSync5(harDir, { recursive: true });
6440
+ outputPath = path5.join(harDir, `har-${Date.now()}.har`);
6441
+ } else {
6442
+ const dir = path5.dirname(outputPath);
6443
+ mkdirSync5(dir, { recursive: true });
6444
+ }
6445
+ fs2.writeFileSync(outputPath, harJson, "utf-8");
6135
6446
  const requests = browser2.getRequests();
6136
6447
  return successResponse(command2.id, {
6137
- path: command2.path,
6448
+ path: outputPath,
6138
6449
  requestCount: requests.length
6139
6450
  });
6140
6451
  }
@@ -7355,7 +7666,7 @@ var AgentBrowser = class {
7355
7666
  }
7356
7667
  }
7357
7668
  async evaluate(script2) {
7358
- const wrappedScript = /\bawait\b/.test(script2) ? `(async () => { ${script2} })()` : script2;
7669
+ const wrappedScript = normalizeEvalScript(script2);
7359
7670
  const response = await this.exec({
7360
7671
  id: nextId(),
7361
7672
  action: "evaluate",
@@ -7767,65 +8078,80 @@ var AgentBrowser = class {
7767
8078
  }
7768
8079
  }
7769
8080
  };
7770
-
7771
- // src/browser/snapshot-parser.ts
7772
- function parseSnapshotLine(line) {
7773
- const refMatch = line.match(/\[ref=(e\d+)\]/);
7774
- if (!refMatch) return null;
7775
- const ref = refMatch[1];
7776
- const refIndex = line.indexOf(refMatch[0]);
7777
- const beforeRef = line.slice(0, refIndex).trim();
7778
- const afterRef = line.slice(refIndex + refMatch[0].length).trim();
7779
- const cleanBefore = beforeRef.replace(/^-\s+/, "");
7780
- let role;
7781
- let name;
7782
- const roleNameMatch = cleanBefore.match(/^(\S+)\s+"([^"]*)"$/);
7783
- const roleOnlyMatch = cleanBefore.match(/^(\S+)$/);
7784
- if (roleNameMatch) {
7785
- role = roleNameMatch[1];
7786
- name = roleNameMatch[2];
7787
- } else if (roleOnlyMatch && !roleOnlyMatch[1].startsWith("[")) {
7788
- role = roleOnlyMatch[1];
7789
- name = "";
8081
+ function normalizeEvalScript(script2) {
8082
+ let s = script2.trim();
8083
+ if (!s) return s;
8084
+ s = closeBrackets(s);
8085
+ const isIIFE = /^\((?:\(\)|function\s*\()/.test(s) || // (()=>... or (function(...
8086
+ /^\(\s*(?:async\s+)?(?:\(\)|function)/.test(s);
8087
+ if (!isIIFE) {
8088
+ if (/\bawait\b/.test(s)) {
8089
+ s = `(async () => { ${s} })()`;
8090
+ } else if (/\breturn\b/.test(s)) {
8091
+ s = `(() => { ${s} })()`;
8092
+ }
7790
8093
  } else {
7791
- return null;
7792
- }
7793
- const attrSource = afterRef.replace(/:$/, "").trim();
7794
- const attributes = {};
7795
- const attrRegex = /\[(\w+)(?:=([^\]]*))?\]/g;
7796
- let attrMatch;
7797
- while ((attrMatch = attrRegex.exec(attrSource)) !== null) {
7798
- const key = attrMatch[1];
7799
- if (key === "ref") continue;
7800
- const value = attrMatch[2] ?? "true";
7801
- attributes[key] = value;
7802
- }
7803
- return { ref, role, name, attributes };
7804
- }
7805
- function findElementInSnapshot(snapshot, ref) {
7806
- const lines = snapshot.split("\n");
7807
- for (const line of lines) {
7808
- if (!line.includes(`[ref=${ref}]`)) continue;
7809
- const parsed = parseSnapshotLine(line);
7810
- if (parsed && parsed.ref === ref) return parsed;
7811
- }
7812
- return null;
7813
- }
7814
- function parseAllElements(snapshot) {
7815
- const lines = snapshot.split("\n");
7816
- const elements2 = [];
7817
- for (const line of lines) {
7818
- const parsed = parseSnapshotLine(line);
7819
- if (parsed) elements2.push(parsed);
8094
+ if (/\bawait\b/.test(s) && !/\basync\b/.test(s)) {
8095
+ s = `(async () => { ${s} })()`;
8096
+ }
8097
+ }
8098
+ return s;
8099
+ }
8100
+ function closeBrackets(script2) {
8101
+ const stack = [];
8102
+ const pairs = { "(": ")", "[": "]", "{": "}" };
8103
+ const closers = /* @__PURE__ */ new Set([")", "]", "}"]);
8104
+ let inString = null;
8105
+ let escaped = false;
8106
+ for (let i = 0; i < script2.length; i++) {
8107
+ const ch = script2[i];
8108
+ if (escaped) {
8109
+ escaped = false;
8110
+ continue;
8111
+ }
8112
+ if (ch === "\\") {
8113
+ escaped = true;
8114
+ continue;
8115
+ }
8116
+ if (inString) {
8117
+ if (ch === inString) inString = null;
8118
+ continue;
8119
+ }
8120
+ if (ch === "'" || ch === '"' || ch === "`") {
8121
+ inString = ch;
8122
+ continue;
8123
+ }
8124
+ if (ch === "/" && i + 1 < script2.length) {
8125
+ const next = script2[i + 1];
8126
+ if (next === "/") {
8127
+ const nl = script2.indexOf("\n", i + 2);
8128
+ i = nl === -1 ? script2.length - 1 : nl;
8129
+ continue;
8130
+ }
8131
+ if (next === "*") {
8132
+ const end = script2.indexOf("*/", i + 2);
8133
+ i = end === -1 ? script2.length - 1 : end + 1;
8134
+ continue;
8135
+ }
8136
+ }
8137
+ if (pairs[ch]) {
8138
+ stack.push(pairs[ch]);
8139
+ } else if (closers.has(ch)) {
8140
+ if (stack.length > 0 && stack[stack.length - 1] === ch) {
8141
+ stack.pop();
8142
+ }
8143
+ }
7820
8144
  }
7821
- return elements2;
7822
- }
7823
- function countElements(snapshot) {
7824
- return parseAllElements(snapshot).length;
8145
+ if (stack.length === 0) return script2;
8146
+ const suffix = stack.reverse().join("");
8147
+ return script2 + suffix;
7825
8148
  }
7826
8149
 
7827
8150
  // src/harness/error-classifier.ts
7828
8151
  function classifyFailure(ctx) {
8152
+ if (ctx.error.includes("SyntaxError")) {
8153
+ return "script_syntax_error";
8154
+ }
7829
8155
  if (ctx.actionExecuted) {
7830
8156
  return "action_failed";
7831
8157
  }
@@ -7855,6 +8181,7 @@ function getRecoveryHint(category) {
7855
8181
  page_structure_changed: "errors.pageStructureChanged",
7856
8182
  navigation_timeout: "errors.navigationTimeout",
7857
8183
  action_failed: "errors.actionFailed",
8184
+ script_syntax_error: "errors.scriptSyntaxError",
7858
8185
  unknown: "errors.unknownError"
7859
8186
  };
7860
8187
  return t(keyMap[category]);
@@ -7906,12 +8233,37 @@ function parseAndAppendToMemory(rawValue, ctx) {
7906
8233
  }
7907
8234
  const parsed = JSON.parse(dataToParse);
7908
8235
  if (Array.isArray(parsed)) {
7909
- const items = parsed.map((item2, i) => {
8236
+ let items = parsed.map((item2, i) => {
7910
8237
  if (typeof item2 === "object" && item2 !== null && !Array.isArray(item2)) {
7911
8238
  return item2;
7912
8239
  }
7913
8240
  return { index: i, value: item2 };
7914
8241
  });
8242
+ if (items.length > 1) {
8243
+ const maxFilledCount = Math.max(
8244
+ ...items.map(
8245
+ (item2) => Object.values(item2).filter((v) => v != null && v !== "").length
8246
+ )
8247
+ );
8248
+ if (maxFilledCount >= 3) {
8249
+ const threshold = Math.floor(maxFilledCount / 2) + 1;
8250
+ const before = items.length;
8251
+ items = items.filter((item2) => {
8252
+ const filled = Object.values(item2).filter((v) => v != null && v !== "").length;
8253
+ return filled >= threshold;
8254
+ });
8255
+ const dropped = before - items.length;
8256
+ if (dropped > 0) {
8257
+ debugLogger.log({
8258
+ phase,
8259
+ event: "memory_append_filtered",
8260
+ step,
8261
+ data: { droppedCount: dropped, threshold, maxFilledCount }
8262
+ });
8263
+ log.warn(`Memory: filtered ${dropped} item(s) with mostly empty fields`);
8264
+ }
8265
+ }
8266
+ }
7915
8267
  const firstKeys = items.length > 0 ? JSON.stringify(Object.keys(items[0])) : "N/A";
7916
8268
  debugLogger.log({
7917
8269
  phase,
@@ -7967,1087 +8319,494 @@ function sleep(ms) {
7967
8319
  return new Promise((resolve2) => setTimeout(resolve2, ms));
7968
8320
  }
7969
8321
 
7970
- // src/i18n/prompts/en/exploration.ts
7971
- var COMMAND_SCHEMA = `### Basic Operations
7972
- - \`click\`: Click element by selector
7973
- - \`fill\`: Fill value in selector (clears existing value)
7974
- - \`type\`: Type value into selector character by character
7975
- - \`select\`: Select value from dropdown by selector
7976
- - \`check\` / \`uncheck\`: Toggle checkbox by selector
7977
-
7978
- ### Navigation
7979
- - \`navigate\`: Navigate to URL in value (only URLs explicitly stated in goal/context; use click for page links)
7980
- - \`wait\`: Wait for value ms
7981
- - \`scroll\`: value: "up"|"down"|"left"|"right"
7982
-
7983
- ### Data Extraction
7984
- - \`extract\`: Extract data via script (JS) or extractPrompt (AI). Result in extractedData
7985
- - **script must return a flat array of objects. No JSON.stringify() needed**
7986
- - When extracting tables, dynamically get column names from header row
7987
- - \`download\`: Download by clicking selector (specify save path with downloadPath)
7988
- - \`export\`: Export memory data to file (exportCollection, exportFormat: csv|json, exportPath)
7989
-
7990
- ### Memory Operations
7991
- - \`memory_append\`: Accumulate data in memoryCollection (value or previous extract result)
7992
- - **extract and memory_append must be in the same actions array**
7993
- - \`memory_aggregate\`: aggregation: {collection, field, operation: sum|count|concat|min|max|avg|unique_count, outputVariable}
7994
-
7995
- **Use only the actions listed above.**`;
7996
- function getAgentInstructions(goal, contextMarkdown, secrets) {
7997
- const contextSection = contextMarkdown ? `
7998
- ## Supplementary Information
7999
- ${contextMarkdown}
8000
- ` : "";
8001
- let secretsSection = "";
8002
- if (secrets && Object.keys(secrets.values).length > 0) {
8003
- const entries = Object.entries(secrets.values).map(([key, value]) => `- ${key}: ${value}`).join("\n");
8004
- secretsSection = `
8005
- ## Input Values (secrets)
8006
- Use the following values when filling forms:
8007
- ${entries}
8008
-
8009
- **Important**: Use these values verbatim. Do not replace them with sample data, test data, or guessed alternatives. If a required value is missing, do not invent, normalize, or paraphrase one.
8010
-
8011
- **Important**: When using these values, set the corresponding \`variableName\` and choose the appropriate \`inputCategory\` (\`credential\` or \`user_data\`).
8012
- `;
8013
- }
8014
- return `You are an AI explorer that navigates web pages to achieve goals.
8015
- Use the browser tool to operate the browser and achieve the goal.
8016
-
8017
- ## How to use the browser tool
8018
-
8019
- ### Getting a Snapshot
8020
- Call the browser tool with \`actions: []\` (empty array) to get the current page's snapshot (accessibility tree) and URL.
8021
-
8022
- ### Executing Actions
8023
- Pass operations as an array in the browser tool's \`actions\`. Keep to 1-3 actions per call.
8024
-
8025
- ### Selector Format
8026
- Use \`@eN\` format corresponding to \`[ref=eN]\` in the snapshot (e.g., \`@e1\`, \`@e10\`)
8027
-
8028
- ### Available Commands
8029
- ${COMMAND_SCHEMA}
8030
-
8031
- ### Input Category (inputCategory)
8032
- When entering values with fill/type, always include inputCategory:
8033
- - \`credential\`: Authentication info (username, email, password, etc.)
8034
- - \`user_data\`: User-specific data (name, address, phone number, etc.)
8035
- - \`fixed\`: Fixed values (test values, constants, etc.)
8036
- - \`navigation\`: URLs, search keywords, etc.
8037
-
8038
- ### Variable Name (variableName)
8039
- When entering values with fill/type, assign a short English camelCase variable name to \`variableName\`.
8040
- Example: \`email\`, \`password\`, \`searchQuery\`, \`companyName\`, \`firstName\`
8041
- Always use the same name for the same concept (e.g., if email input appears in 2 places, use \`email\` for both).
8042
-
8043
- ### Data Capture (suggestedCaptures)
8044
- When important data appears on the page as a result of operations (IDs, order numbers, URL changes, amounts, etc.),
8045
- record them with \`suggestedCaptures\`. Prioritize values needed in subsequent steps.
8046
- Available strategies:
8047
- - \`snapshot\`: Regex match on snapshot (pattern required)
8048
- - \`url\`: Regex match on URL (pattern required)
8049
- - \`ai\`: AI extraction with natural language (prompt required)
8050
- - \`expression\`: Template from existing variables (expression required)
8051
- - \`evaluate\`: Execute JavaScript on page and capture result (expression contains JS code)
8052
-
8053
- Example:
8054
- \`\`\`json
8055
- {
8056
- "suggestedCaptures": [
8057
- { "name": "orderId", "strategy": "snapshot", "pattern": "Order[:\uFF1A]\\\\s*([A-Z]+-\\\\d+)", "description": "Order confirmation number" },
8058
- { "name": "resourceId", "strategy": "url", "pattern": "/orders/(\\\\d+)" }
8059
- ]
8060
- }
8061
- \`\`\`
8062
-
8063
- ## Critical Rules
8064
- - **Only interact with elements visible in the snapshot.** Never guess about elements or URLs that may not exist
8065
- - **Never guess input values.** Do not fabricate email addresses, passwords, names, phone numbers, or any other user data that is not present in Input Values (secrets), context, or the page itself
8066
- - Navigate pages by clicking links/buttons on screen. Do not guess/construct URLs with \`navigate\` (except URLs explicitly stated in goal or context)
8067
- - Only use \`@eN\` refs that exist as \`[ref=eN]\` in the most recent snapshot
8068
- - If context (supplementary info) is provided, prioritize the procedures, paths, and hints described there
8069
- - If the snapshot shows \`[... N items omitted]\`, the target element may be in the omitted section. Try \`scroll\` to move the view and re-fetch
8070
-
8071
- ## Exploration Strategy
8072
- 1. First check page state with \`actions: []\`
8073
- 2. **Carefully read** the snapshot and identify elements related to the goal using keyword matching:
8074
- - Break down the goal into keywords (e.g., "Log in to the dashboard" \u2192 "login", "sign in", "dashboard") and scan link/button names
8075
- - Prioritize exact keyword matches over vague labels (e.g., prefer "Login" over "Click here")
8076
- 3. Execute operations using the identified \`@eN\` refs
8077
- 4. Check results and decide next operation (observe \u2192 decide \u2192 act cycle)
8078
- 5. If target element is not found, \`scroll\` to move the view and check the snapshot again
8079
- 6. Use \`select\` command for SELECT elements, not \`click\`
8080
- 7. Use \`check\` / \`uncheck\` commands for checkboxes
8081
- 8. Use \`click\` command for radio buttons \u2014 just click the desired option directly
8082
- 9. Never use \`extract\` to investigate form elements. If radio buttons, checkboxes, or dropdowns are visible in the snapshot, interact with them directly using the appropriate command
8083
-
8084
- ## Link Selection and Navigation Recovery
8085
- When a page has many links:
8086
- 1. **Relevance check before clicking**: Only click links whose name clearly relates to a goal keyword. Links with generic names are a last resort
8087
- 2. **Avoid exploratory clicking**: Do not click links just to "see what happens." Each click must have a clear rationale tied to the goal
8088
- 3. **Recovery from wrong navigation**: If a clicked page is unrelated to the goal, \`navigate\` back to the starting URL and look for alternative links
8089
-
8090
- ## Form Input Efficiency
8091
- When filling large forms, strictly follow these rules:
8092
- 1. **Enter each field only once** \u2014 Do not re-operate on fields that already have values
8093
- 2. **Check filled fields in snapshot** \u2014 After fill/type, the field value appears in the snapshot. Skip fields showing values
8094
- 3. **Progress systematically top to bottom** \u2014 Process fieldsets/sections in order. Don't go back to previous sections
8095
- 4. **Track filled field count** \u2014 Reference operation history to know what you've already entered. Duplicate operations on the same selector are forbidden
8096
- 5. **Submit after all fields are filled** \u2014 Once all required fields are complete, promptly click the submit button
8097
- 6. **Check filledFields** \u2014 The browser tool result includes filledFields listing filled fields. Never re-enter fields in this list
8098
-
8099
- ## Form Completion Verification
8100
- Before returning your final report when filling forms:
8101
- 1. Scan the ENTIRE current snapshot for remaining unfilled fields \u2014 check every fieldset/section
8102
- 2. Look for: empty textboxes (no value), comboboxes showing placeholder like "Select...", unchecked checkboxes
8103
- 3. The LAST section of a form is commonly missed \u2014 always verify the bottom of the form
8104
- 4. After all fields are filled, click the submit/register button
8105
- 5. Verify the success confirmation appears before declaring goalAchieved: true
8106
- Do NOT declare goalAchieved without first confirming all form sections are complete and the form is submitted.
8107
-
8108
- ## Data Collection Pattern (Pagination Traversal)
8109
- Procedure: extract \u2192 memory_append \u2192 click "Next" \u2192 repeat \u2192 memory_aggregate for aggregation
8110
-
8111
- Example (table extract \u2192 accumulate \u2192 next page \u2192 aggregate \u2192 CSV export):
8112
- \`\`\`json
8113
- [
8114
- {"action":"extract","description":"Extract table","script":"(()=>{const h=[...document.querySelectorAll('table thead th')].map(t=>t.textContent.trim());return[...document.querySelectorAll('table tbody tr')].map(r=>{const c=r.querySelectorAll('td');return Object.fromEntries([...c].map((c,i)=>[h[i]||'col'+i,c.textContent.trim()]));});})()"},
8115
- {"action":"memory_append","description":"Accumulate","memoryCollection":"data"},
8116
- {"action":"click","description":"Next page","selector":"@e15"}
8117
- ]
8118
- \`\`\`
8119
- Aggregate: \`[{"action":"memory_aggregate","description":"Sum total","aggregation":{"collection":"data","field":"amount","operation":"sum","outputVariable":"total"}}]\`
8120
- CSV export: \`[{"action":"export","description":"CSV export","exportCollection":"data","exportFormat":"csv","exportPath":"/tmp/data.csv"}]\`
8121
-
8122
- Note: No JSON.stringify() needed in script. Each row is a flat object. Check collection item count via memoryStatus.
8123
-
8124
- **Important**: When paginating, you MUST continue until the LAST page. Check the page indicator (e.g., "Page X of Y") and keep clicking "Next" until you reach the final page. Do NOT stop after a few pages \u2014 process every single page. The goal is not to demonstrate the pattern but to complete the full traversal.
8125
-
8126
- ## Using filledFields
8127
- If the browser tool result includes \`filledFields\`, this is a list of already-filled form fields.
8128
- Do not re-enter fields in this list. Only operate on unfilled fields.
8129
-
8130
- ## Diff Snapshots
8131
- After text input (fill/type), if page structure hasn't changed, you'll receive a compact snapshot listing all refs.
8132
- - \`Unfilled:\` shows elements you still need to interact with
8133
- - \`Filled:\` shows elements already filled
8134
- - All refs from the compact snapshot are valid and usable
8135
- - If you need full page context, call the browser tool with \`actions: []\`
8136
-
8137
- ## Responding to nudgeMessage
8138
- If the browser tool result includes \`nudgeMessage\`, it contains important guidance:
8139
- - **Pagination progress**: Shows current page and remaining pages. You MUST continue until ALL pages are processed.
8140
- - **Loop warning**: Indicates you are repeating the same actions without progress. Try a different approach.
8141
- - **Form hints**: Lists remaining unfilled form fields.
8142
- Always follow the instructions in the message.
8143
-
8144
- ## Compound Goal Verification
8145
- When the goal contains multiple steps (e.g., "Do A, then navigate to B, then execute C"):
8146
- 1. Break down the goal into individual sub-tasks
8147
- 2. Verify each sub-task is completed by checking the current page state
8148
- 3. **Do NOT declare goalAchieved until ALL sub-tasks are completed**
8149
- 4. Even if login or page navigation succeeds, the goal is NOT achieved if subsequent tasks remain
8150
- 5. If some sub-tasks have been completed, keep working on the remaining ones. Only declare goalAchieved: false when you encounter an unrecoverable error or have exhausted all reasonable approaches
8151
-
8152
- Example: If the goal is "Log in and then execute X in the action list":
8153
- - Login succeeds \u2192 NOT goalAchieved yet (executing X remains)
8154
- - X executed in action list \u2192 goalAchieved: true
8155
-
8156
- ## When Goal is Achieved
8157
- **CRITICAL: Your goal achievement claim will be independently verified against the final page state. False claims will be overridden.**
8158
-
8159
- Before declaring goalAchieved: true, you MUST complete this mandatory checklist:
8160
- 1. **Re-read the original goal** and break it into every sub-task
8161
- 2. **Check the current page state** \u2014 does the snapshot show clear evidence of completion?
8162
- 3. **For form tasks**: Is a success/confirmation message visible? (NOT just "fields are filled" \u2014 the form must be SUBMITTED and confirmed)
8163
- 4. **For navigation tasks**: Is the target page actually displayed?
8164
- 5. **For compound goals** (A then B then C): Verify evidence for EACH part, not just the first
8165
- 6. **Look for failure signals**: Error messages, validation warnings, login forms still visible, "try again" prompts
8166
- 7. **Include specific evidence** in your summary: quote the confirmation message, success banner, or page title that proves completion
8167
-
8168
- Common false positive patterns to AVOID:
8169
- - Declaring success after login when the goal includes post-login tasks
8170
- - Declaring success after filling a form but before submitting it
8171
- - Declaring success based on clicking a button without waiting for confirmation
8172
- - Declaring success when the page shows an error or is still loading
8173
-
8174
- When you have verified ALL checklist items, stop calling the browser tool and return:
8175
- \`\`\`json
8176
- { "goalAchieved": true, "summary": "Evidence: [specific confirmation message or page state]. Completed: [list of sub-tasks done]" }
8177
- \`\`\`
8178
-
8179
- If the goal cannot be achieved:
8180
- \`\`\`json
8181
- { "goalAchieved": false, "summary": "Summary of the situation and reasons" }
8182
- \`\`\`
8183
-
8184
- ---
8185
- The following is task-specific information.
8186
-
8187
- ## Goal
8188
- ${goal}
8189
- ${contextSection}${secretsSection}
8190
- Respond in English.`;
8191
- }
8192
- function getInitialUserMessage() {
8193
- return "Call the browser tool with actions:[] (empty array) to check the current page state. Then begin exploring toward the goal.";
8194
- }
8195
-
8196
- // src/i18n/prompts/ja/exploration.ts
8197
- var COMMAND_SCHEMA2 = `### \u57FA\u672C\u64CD\u4F5C
8198
- - \`click\`: selector \u3067\u8981\u7D20\u30AF\u30EA\u30C3\u30AF
8199
- - \`fill\`: selector \u306B value \u3092\u5165\u529B\uFF08\u65E2\u5B58\u5024\u30AF\u30EA\u30A2\uFF09
8200
- - \`type\`: selector \u306B value \u30921\u6587\u5B57\u305A\u3064\u5165\u529B
8201
- - \`select\`: selector \u306E\u30C9\u30ED\u30C3\u30D7\u30C0\u30A6\u30F3\u3067 value \u3092\u9078\u629E
8202
- - \`check\` / \`uncheck\`: selector \u306E\u30C1\u30A7\u30C3\u30AF\u30DC\u30C3\u30AF\u30B9\u64CD\u4F5C
8203
-
8204
- ### \u30CA\u30D3\u30B2\u30FC\u30B7\u30E7\u30F3
8205
- - \`navigate\`: value \u306EURL\u306B\u79FB\u52D5\uFF08\u30B4\u30FC\u30EB/\u30B3\u30F3\u30C6\u30AD\u30B9\u30C8\u3067\u660E\u793A\u3055\u308C\u305FURL\u306E\u307F\u3002\u30DA\u30FC\u30B8\u5185\u30EA\u30F3\u30AF\u306F click\uFF09
8206
- - \`wait\`: value ms\u5F85\u6A5F
8207
- - \`scroll\`: value: "up"|"down"|"left"|"right"
8208
-
8209
- ### \u30C7\u30FC\u30BF\u62BD\u51FA
8210
- - \`extract\`: script(JS) \u307E\u305F\u306F extractPrompt(AI) \u3067\u30C7\u30FC\u30BF\u62BD\u51FA\u3002\u7D50\u679C\u306F extractedData
8211
- - **script \u306F\u30D5\u30E9\u30C3\u30C8\u306A\u30AA\u30D6\u30B8\u30A7\u30AF\u30C8\u914D\u5217\u3092\u8FD4\u3059\u3053\u3068\u3002JSON.stringify()\u4E0D\u8981**
8212
- - \u30C6\u30FC\u30D6\u30EB\u62BD\u51FA\u6642\u306F\u30D8\u30C3\u30C0\u30FC\u884C\u304B\u3089\u30AB\u30E9\u30E0\u540D\u3092\u52D5\u7684\u53D6\u5F97
8213
- - \`download\`: selector \u30AF\u30EA\u30C3\u30AF\u3067\u30C0\u30A6\u30F3\u30ED\u30FC\u30C9\uFF08downloadPath \u3067\u4FDD\u5B58\u5148\u6307\u5B9A\u53EF\uFF09
8214
- - \`export\`: \u30E1\u30E2\u30EA\u30C7\u30FC\u30BF\u3092\u30D5\u30A1\u30A4\u30EB\u51FA\u529B\uFF08exportCollection, exportFormat: csv|json, exportPath\uFF09
8215
-
8216
- ### \u30E1\u30E2\u30EA\u64CD\u4F5C
8217
- - \`memory_append\`: memoryCollection \u306B\u30C7\u30FC\u30BF\u84C4\u7A4D\uFF08value \u307E\u305F\u306F\u76F4\u524D extract \u7D50\u679C\uFF09
8218
- - **extract \u3068 memory_append \u306F\u5FC5\u305A\u540C\u3058 actions \u914D\u5217\u306B\u542B\u3081\u308B\u3053\u3068**
8219
- - \`memory_aggregate\`: aggregation: {collection, field, operation: sum|count|concat|min|max|avg|unique_count, outputVariable}
8220
-
8221
- **\u4E0A\u8A18\u306E\u30A2\u30AF\u30B7\u30E7\u30F3\u306E\u307F\u4F7F\u7528\u3002**`;
8222
- function getAgentInstructions2(goal, contextMarkdown, secrets) {
8223
- const contextSection = contextMarkdown ? `
8224
- ## \u88DC\u8DB3\u60C5\u5831
8225
- ${contextMarkdown}
8226
- ` : "";
8227
- let secretsSection = "";
8228
- if (secrets && Object.keys(secrets.values).length > 0) {
8229
- const entries = Object.entries(secrets.values).map(([key, value]) => `- ${key}: ${value}`).join("\n");
8230
- secretsSection = `
8231
- ## \u5165\u529B\u5024\uFF08secrets\uFF09
8232
- \u30D5\u30A9\u30FC\u30E0\u5165\u529B\u6642\u306B\u4EE5\u4E0B\u306E\u5024\u3092\u4F7F\u7528\u3057\u3066\u304F\u3060\u3055\u3044:
8233
- ${entries}
8234
-
8235
- **\u91CD\u8981**: \u3053\u308C\u3089\u306E\u5024\u306F\u305D\u306E\u307E\u307E\u53B3\u5BC6\u306B\u4F7F\u7528\u3057\u3066\u304F\u3060\u3055\u3044\u3002\u5225\u306E\u30C6\u30B9\u30C8\u5024\u30FB\u30B5\u30F3\u30D7\u30EB\u5024\u30FB\u63A8\u6E2C\u5024\u306B\u7F6E\u304D\u63DB\u3048\u3066\u306F\u3044\u3051\u307E\u305B\u3093\u3002\u5FC5\u8981\u306A\u5024\u304C\u4E0D\u8DB3\u3057\u3066\u3044\u308B\u5834\u5408\u3082\u3001\u88DC\u5B8C\u30FB\u6B63\u898F\u5316\u30FB\u8A00\u3044\u63DB\u3048\u3067\u57CB\u3081\u305A\u3001\u672A\u63D0\u4F9B\u3068\u3057\u3066\u6271\u3063\u3066\u304F\u3060\u3055\u3044\u3002
8236
-
8237
- **\u91CD\u8981**: \u3053\u308C\u3089\u306E\u5024\u3092\u4F7F\u7528\u3059\u308B\u969B\u306F\u3001\u5BFE\u5FDC\u3059\u308B \`variableName\` \u3092\u8A2D\u5B9A\u3057\u3001\`inputCategory\` \u306F \`credential\` \u307E\u305F\u306F \`user_data\` \u3092\u9069\u5207\u306B\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044\u3002
8238
- `;
8322
+ // src/harness/report-sections.ts
8323
+ import { readFile as readFile4 } from "fs/promises";
8324
+ async function readDebugLog(filePath) {
8325
+ try {
8326
+ const content = await readFile4(filePath, "utf-8");
8327
+ return content.trim().split("\n").filter((line) => line.trim()).map((line) => {
8328
+ try {
8329
+ return JSON.parse(line);
8330
+ } catch {
8331
+ return {};
8332
+ }
8333
+ });
8334
+ } catch {
8335
+ return [];
8239
8336
  }
8240
- return `\u3042\u306A\u305F\u306FWeb\u30DA\u30FC\u30B8\u3092\u63A2\u7D22\u3057\u3066\u30B4\u30FC\u30EB\u3092\u9054\u6210\u3059\u308BAI\u30A8\u30AF\u30B9\u30D7\u30ED\u30FC\u30E9\u30FC\u3067\u3059\u3002
8241
- browser\u30C4\u30FC\u30EB\u3092\u4F7F\u3063\u3066\u30D6\u30E9\u30A6\u30B6\u3092\u64CD\u4F5C\u3057\u3001\u30B4\u30FC\u30EB\u3092\u9054\u6210\u3057\u3066\u304F\u3060\u3055\u3044\u3002
8242
-
8243
- ## browser\u30C4\u30FC\u30EB\u306E\u4F7F\u3044\u65B9
8244
-
8245
- ### \u30B9\u30CA\u30C3\u30D7\u30B7\u30E7\u30C3\u30C8\u53D6\u5F97
8246
- browser\u30C4\u30FC\u30EB\u3092 \`actions: []\`\uFF08\u7A7A\u914D\u5217\uFF09\u3067\u547C\u3076\u3068\u3001\u73FE\u5728\u306E\u30DA\u30FC\u30B8\u306E\u30B9\u30CA\u30C3\u30D7\u30B7\u30E7\u30C3\u30C8\uFF08\u30A2\u30AF\u30BB\u30B7\u30D3\u30EA\u30C6\u30A3\u30C4\u30EA\u30FC\uFF09\u3068URL\u304C\u8FD4\u308A\u307E\u3059\u3002
8247
-
8248
- ### \u30A2\u30AF\u30B7\u30E7\u30F3\u5B9F\u884C
8249
- browser\u30C4\u30FC\u30EB\u306E \`actions\` \u306B\u64CD\u4F5C\u3092\u914D\u5217\u3067\u6E21\u3059\u3068\u9806\u6B21\u5B9F\u884C\u3055\u308C\u307E\u3059\u30021\u56DE\u306E\u547C\u3073\u51FA\u3057\u30671\u301C3\u30A2\u30AF\u30B7\u30E7\u30F3\u7A0B\u5EA6\u306B\u6291\u3048\u3066\u304F\u3060\u3055\u3044\u3002
8250
-
8251
- ### \u30BB\u30EC\u30AF\u30BF\u5F62\u5F0F
8252
- \u30B9\u30CA\u30C3\u30D7\u30B7\u30E7\u30C3\u30C8\u306E \`[ref=eN]\` \u306B\u5BFE\u5FDC\u3059\u308B \`@eN\` \u5F62\u5F0F\u3067\u6307\u5B9A\uFF08\u4F8B: \`@e1\`, \`@e10\`\uFF09
8253
-
8254
- ### \u5229\u7528\u53EF\u80FD\u306A\u30B3\u30DE\u30F3\u30C9
8255
- ${COMMAND_SCHEMA2}
8256
-
8257
- ### \u5165\u529B\u5024\u306E\u30AB\u30C6\u30B4\u30EA\uFF08inputCategory\uFF09
8258
- fill/type \u3067\u5024\u3092\u5165\u529B\u3059\u308B\u5834\u5408\u3001\u5FC5\u305A inputCategory \u3092\u4ED8\u4E0E:
8259
- - \`credential\`: \u30E6\u30FC\u30B6\u30FC\u540D\u3001\u30E1\u30FC\u30EB\u30A2\u30C9\u30EC\u30B9\u3001\u30D1\u30B9\u30EF\u30FC\u30C9\u7B49\u306E\u8A8D\u8A3C\u60C5\u5831
8260
- - \`user_data\`: \u30E6\u30FC\u30B6\u30FC\u56FA\u6709\u306E\u30C7\u30FC\u30BF\uFF08\u540D\u524D\u3001\u4F4F\u6240\u3001\u96FB\u8A71\u756A\u53F7\u7B49\uFF09
8261
- - \`fixed\`: \u56FA\u5B9A\u5024\uFF08\u30C6\u30B9\u30C8\u5024\u3001\u5B9A\u6570\u7B49\uFF09
8262
- - \`navigation\`: URL\u3001\u691C\u7D22\u30AD\u30FC\u30EF\u30FC\u30C9\u7B49
8263
-
8264
- ### \u5909\u6570\u540D\uFF08variableName\uFF09
8265
- fill/type \u3067\u5024\u3092\u5165\u529B\u3059\u308B\u5834\u5408\u3001\u77ED\u3044\u82F1\u8A9E camelCase \u306E\u5909\u6570\u540D\u3092 \`variableName\` \u306B\u4ED8\u4E0E\u3057\u3066\u304F\u3060\u3055\u3044\u3002
8266
- \u4F8B: \`email\`, \`password\`, \`searchQuery\`, \`companyName\`, \`firstName\`
8267
- \u540C\u3058\u6982\u5FF5\u306E\u5024\u306B\u306F\u5FC5\u305A\u540C\u3058\u540D\u524D\u3092\u4F7F\u7528\u3057\u3066\u304F\u3060\u3055\u3044\uFF08\u4F8B: \u30E1\u30FC\u30EB\u30A2\u30C9\u30EC\u30B9\u5165\u529B\u304C2\u7B87\u6240\u3042\u308C\u3070\u4E21\u65B9 \`email\`\uFF09\u3002
8268
-
8269
- ### \u30C7\u30FC\u30BF\u30AD\u30E3\u30D7\u30C1\u30E3\uFF08suggestedCaptures\uFF09
8270
- \u64CD\u4F5C\u7D50\u679C\u3068\u3057\u3066\u91CD\u8981\u306A\u30C7\u30FC\u30BF\uFF08ID\u3001\u6CE8\u6587\u756A\u53F7\u3001URL\u5909\u5316\u3001\u91D1\u984D\u7B49\uFF09\u304C\u30DA\u30FC\u30B8\u306B\u73FE\u308C\u305F\u5834\u5408\u3001
8271
- \`suggestedCaptures\` \u3067\u8A18\u9332\u3057\u3066\u304F\u3060\u3055\u3044\u3002\u5F8C\u7D9A\u30B9\u30C6\u30C3\u30D7\u3067\u53C2\u7167\u304C\u5FC5\u8981\u306B\u306A\u308B\u5024\u3092\u512A\u5148\u3002
8272
- \u5229\u7528\u53EF\u80FD\u306A strategy:
8273
- - \`snapshot\`: \u30B9\u30CA\u30C3\u30D7\u30B7\u30E7\u30C3\u30C8\u306B\u6B63\u898F\u8868\u73FE\u30DE\u30C3\u30C1\uFF08pattern \u5FC5\u9808\uFF09
8274
- - \`url\`: URL\u306B\u6B63\u898F\u8868\u73FE\u30DE\u30C3\u30C1\uFF08pattern \u5FC5\u9808\uFF09
8275
- - \`ai\`: AI\u306B\u81EA\u7136\u8A00\u8A9E\u3067\u62BD\u51FA\u3055\u305B\u308B\uFF08prompt \u5FC5\u9808\uFF09
8276
- - \`expression\`: \u65E2\u5B58\u5909\u6570\u304B\u3089\u30C6\u30F3\u30D7\u30EC\u30FC\u30C8\u7D44\u307F\u7ACB\u3066\uFF08expression \u5FC5\u9808\uFF09
8277
- - \`evaluate\`: \u30DA\u30FC\u30B8\u5185\u3067JavaScript\u3092\u5B9F\u884C\u3057\u3066\u7D50\u679C\u3092\u30AD\u30E3\u30D7\u30C1\u30E3\uFF08expression \u306BJS\u30B3\u30FC\u30C9\u3092\u6307\u5B9A\uFF09
8278
-
8279
- \u4F8B:
8280
- \`\`\`json
8281
- {
8282
- "suggestedCaptures": [
8283
- { "name": "orderId", "strategy": "snapshot", "pattern": "\u6CE8\u6587\u756A\u53F7[:\uFF1A]\\\\s*([A-Z]+-\\\\d+)", "description": "\u6CE8\u6587\u78BA\u8A8D\u756A\u53F7" },
8284
- { "name": "resourceId", "strategy": "url", "pattern": "/orders/(\\\\d+)" }
8285
- ]
8286
- }
8287
- \`\`\`
8288
-
8289
- ## \u6700\u91CD\u8981\u30EB\u30FC\u30EB
8290
- - **\u30B9\u30CA\u30C3\u30D7\u30B7\u30E7\u30C3\u30C8\u306B\u898B\u3048\u3066\u3044\u308B\u8981\u7D20\u3060\u3051\u3092\u64CD\u4F5C\u3059\u308B\u3053\u3068\u3002** \u5B58\u5728\u3059\u308B\u304B\u5206\u304B\u3089\u306A\u3044\u8981\u7D20\u3084URL\u3092\u63A8\u6E2C\u3057\u3066\u306F\u3044\u3051\u306A\u3044
8291
- - **\u5165\u529B\u5024\u3092\u63A8\u6E2C\u3057\u3066\u306F\u3044\u3051\u306A\u3044\u3002** \u5165\u529B\u5024\uFF08secrets\uFF09\u30FB\u30B3\u30F3\u30C6\u30AD\u30B9\u30C8\u30FB\u30DA\u30FC\u30B8\u4E0A\u306B\u5B58\u5728\u3057\u306A\u3044\u30E1\u30FC\u30EB\u30A2\u30C9\u30EC\u30B9\u3001\u30D1\u30B9\u30EF\u30FC\u30C9\u3001\u6C0F\u540D\u3001\u96FB\u8A71\u756A\u53F7\u306A\u3069\u3092\u52DD\u624B\u306B\u4F5C\u3089\u306A\u3044
8292
- - \u30DA\u30FC\u30B8\u9077\u79FB\u306F\u753B\u9762\u4E0A\u306E\u30EA\u30F3\u30AF\u3084\u30DC\u30BF\u30F3\u3092 \`click\` \u3067\u884C\u3046\u3002\`navigate\` \u3067URL\u3092\u63A8\u6E2C\u30FB\u7D44\u307F\u7ACB\u3066\u308B\u3053\u3068\u306F\u7981\u6B62\uFF08\u30B4\u30FC\u30EB\u3084\u30B3\u30F3\u30C6\u30AD\u30B9\u30C8\u3067\u660E\u793A\u3055\u308C\u305FURL\u306F\u9664\u304F\uFF09
8293
- - \u64CD\u4F5C\u5BFE\u8C61\u306E \`@eN\` \u306F\u3001\u76F4\u524D\u306E\u30B9\u30CA\u30C3\u30D7\u30B7\u30E7\u30C3\u30C8\u306B \`[ref=eN]\` \u3068\u3057\u3066\u5B58\u5728\u3059\u308B\u3082\u306E\u3060\u3051\u3092\u4F7F\u7528\u3059\u308B
8294
- - \u30B3\u30F3\u30C6\u30AD\u30B9\u30C8\uFF08\u88DC\u8DB3\u60C5\u5831\uFF09\u304C\u63D0\u4F9B\u3055\u308C\u3066\u3044\u308B\u5834\u5408\u3001\u305D\u3053\u306B\u8A18\u8F09\u3055\u308C\u305F\u624B\u9806\u30FB\u5C0E\u7DDA\u30FB\u30D2\u30F3\u30C8\u3092\u512A\u5148\u7684\u306B\u53C2\u7167\u3059\u308B
8295
- - \u30B9\u30CA\u30C3\u30D7\u30B7\u30E7\u30C3\u30C8\u306B \`[... N\u4EF6\u7701\u7565]\` \u3068\u3042\u308B\u5834\u5408\u3001\u76EE\u7684\u306E\u8981\u7D20\u304C\u7701\u7565\u90E8\u5206\u306B\u3042\u308B\u53EF\u80FD\u6027\u304C\u3042\u308B\u3002\`scroll\` \u3067\u753B\u9762\u3092\u52D5\u304B\u3057\u3066\u518D\u53D6\u5F97\u3092\u8A66\u307F\u308B\u3053\u3068
8296
-
8297
- ## \u63A2\u7D22\u6226\u7565
8298
- 1. \u307E\u305A \`actions: []\` \u3067\u30DA\u30FC\u30B8\u72B6\u614B\u3092\u78BA\u8A8D
8299
- 2. \u30B9\u30CA\u30C3\u30D7\u30B7\u30E7\u30C3\u30C8\u3092**\u6CE8\u610F\u6DF1\u304F\u8AAD\u307F**\u3001\u30B4\u30FC\u30EB\u306E\u30AD\u30FC\u30EF\u30FC\u30C9\u3092\u4F7F\u3063\u3066\u95A2\u9023\u8981\u7D20\u3092\u7279\u5B9A:
8300
- - \u30B4\u30FC\u30EB\u3092\u30AD\u30FC\u30EF\u30FC\u30C9\u306B\u5206\u89E3\u3057\uFF08\u4F8B: \u300C\u30ED\u30B0\u30A4\u30F3\u3057\u3066\u30C0\u30C3\u30B7\u30E5\u30DC\u30FC\u30C9\u8868\u793A\u300D\u2192 \u300C\u30ED\u30B0\u30A4\u30F3\u300D\u300C\u30B5\u30A4\u30F3\u30A4\u30F3\u300D\u300C\u30C0\u30C3\u30B7\u30E5\u30DC\u30FC\u30C9\u300D\uFF09\u3001\u30EA\u30F3\u30AF\u30FB\u30DC\u30BF\u30F3\u540D\u304B\u3089\u691C\u7D22\u3059\u308B
8301
- - \u66D6\u6627\u306A\u30E9\u30D9\u30EB\uFF08\u300C\u8A73\u7D30\u300D\u300C\u3053\u3061\u3089\u300D\uFF09\u3088\u308A\u3001\u30AD\u30FC\u30EF\u30FC\u30C9\u306B\u4E00\u81F4\u3059\u308B\u30EA\u30F3\u30AF\u3092\u512A\u5148\u3059\u308B
8302
- 3. \u7279\u5B9A\u3057\u305F\u8981\u7D20\u306E \`@eN\` \u3092\u4F7F\u3063\u3066\u64CD\u4F5C\u3092\u5B9F\u884C
8303
- 4. \u7D50\u679C\u3092\u78BA\u8A8D\u3057\u3001\u6B21\u306E\u64CD\u4F5C\u3092\u6C7A\u5B9A\uFF08\u89B3\u5BDF\u2192\u5224\u65AD\u2192\u884C\u52D5\u306E\u7E70\u308A\u8FD4\u3057\uFF09
8304
- 5. \u76EE\u7684\u306E\u8981\u7D20\u304C\u898B\u3064\u304B\u3089\u306A\u3044\u5834\u5408\u306F \`scroll\` \u3067\u753B\u9762\u3092\u79FB\u52D5\u3057\u3001\u518D\u5EA6\u30B9\u30CA\u30C3\u30D7\u30B7\u30E7\u30C3\u30C8\u3092\u78BA\u8A8D\u3059\u308B
8305
- 6. SELECT\u8981\u7D20\u306B\u306F \`click\` \u3067\u306F\u306A\u304F \`select\` \u30B3\u30DE\u30F3\u30C9\u3092\u4F7F\u7528
8306
- 7. \u30C1\u30A7\u30C3\u30AF\u30DC\u30C3\u30AF\u30B9\u306B\u306F \`check\` / \`uncheck\` \u30B3\u30DE\u30F3\u30C9\u3092\u4F7F\u7528
8307
- 8. \u30E9\u30B8\u30AA\u30DC\u30BF\u30F3\u306B\u306F \`click\` \u30B3\u30DE\u30F3\u30C9\u3092\u4F7F\u7528 \u2014 \u9078\u629E\u3057\u305F\u3044\u30AA\u30D7\u30B7\u30E7\u30F3\u3092\u76F4\u63A5\u30AF\u30EA\u30C3\u30AF\u3059\u308B
8308
- 9. \u30D5\u30A9\u30FC\u30E0\u8981\u7D20\u306E\u8ABF\u67FB\u306B \`extract\` \u3092\u4F7F\u308F\u306A\u3044\u3053\u3068\u3002\u30B9\u30CA\u30C3\u30D7\u30B7\u30E7\u30C3\u30C8\u306B\u30E9\u30B8\u30AA\u30DC\u30BF\u30F3\u30FB\u30C1\u30A7\u30C3\u30AF\u30DC\u30C3\u30AF\u30B9\u30FB\u30C9\u30ED\u30C3\u30D7\u30C0\u30A6\u30F3\u304C\u898B\u3048\u3066\u3044\u308C\u3070\u3001\u9069\u5207\u306A\u30B3\u30DE\u30F3\u30C9\u3067\u76F4\u63A5\u64CD\u4F5C\u3059\u308B
8309
-
8310
- ## \u30EA\u30F3\u30AF\u9078\u629E\u3068\u30CA\u30D3\u30B2\u30FC\u30B7\u30E7\u30F3\u56DE\u5FA9
8311
- \u30DA\u30FC\u30B8\u306B\u591A\u6570\u306E\u30EA\u30F3\u30AF\u304C\u3042\u308B\u5834\u5408:
8312
- 1. **\u30AF\u30EA\u30C3\u30AF\u524D\u306E\u95A2\u9023\u6027\u30C1\u30A7\u30C3\u30AF**: \u30EA\u30F3\u30AF\u306E\u540D\u524D\u304C\u30B4\u30FC\u30EB\u306E\u30AD\u30FC\u30EF\u30FC\u30C9\u306B\u95A2\u9023\u3059\u308B\u5834\u5408\u306E\u307F\u30AF\u30EA\u30C3\u30AF\u3059\u308B\u3002\u6C4E\u7528\u7684\u306A\u540D\u524D\u306E\u30EA\u30F3\u30AF\u306F\u6700\u5F8C\u306E\u624B\u6BB5
8313
- 2. **\u63A2\u7D22\u7684\u30AF\u30EA\u30C3\u30AF\u306E\u56DE\u907F**: \u300C\u3069\u3046\u306A\u308B\u304B\u898B\u3066\u307F\u3088\u3046\u300D\u3067\u30EA\u30F3\u30AF\u3092\u30AF\u30EA\u30C3\u30AF\u3057\u306A\u3044\u3002\u5404\u30AF\u30EA\u30C3\u30AF\u306B\u306F\u30B4\u30FC\u30EB\u306B\u7D10\u3065\u3044\u305F\u6839\u62E0\u304C\u5FC5\u8981
8314
- 3. **\u8AA4\u9077\u79FB\u304B\u3089\u306E\u56DE\u5FA9**: \u30AF\u30EA\u30C3\u30AF\u5F8C\u306E\u30DA\u30FC\u30B8\u304C\u30B4\u30FC\u30EB\u306B\u7121\u95A2\u4FC2\u306A\u5834\u5408\u3001\u958B\u59CBURL\u306B \`navigate\` \u3067\u623B\u308A\u3001\u5225\u306E\u30EA\u30F3\u30AF\u3092\u63A2\u3059
8315
-
8316
- ## \u30D5\u30A9\u30FC\u30E0\u5165\u529B\u306E\u52B9\u7387\u5316
8317
- \u5927\u304D\u306A\u30D5\u30A9\u30FC\u30E0\u3092\u5165\u529B\u3059\u308B\u969B\u306F\u3001\u4EE5\u4E0B\u306E\u30EB\u30FC\u30EB\u3092\u53B3\u5B88\u3057\u3066\u304F\u3060\u3055\u3044:
8318
- 1. **\u5404\u30D5\u30A3\u30FC\u30EB\u30C9\u306F1\u56DE\u3060\u3051\u5165\u529B\u3059\u308B** \u2014 \u65E2\u306B\u5024\u304C\u5165\u529B\u3055\u308C\u305F\u30D5\u30A3\u30FC\u30EB\u30C9\u3092\u518D\u5EA6\u64CD\u4F5C\u3057\u306A\u3044\u3053\u3068
8319
- 2. **\u30B9\u30CA\u30C3\u30D7\u30B7\u30E7\u30C3\u30C8\u3067\u5165\u529B\u6E08\u307F\u30D5\u30A3\u30FC\u30EB\u30C9\u3092\u78BA\u8A8D\u3059\u308B** \u2014 fill/type \u5F8C\u306E\u30D5\u30A3\u30FC\u30EB\u30C9\u306F\u30B9\u30CA\u30C3\u30D7\u30B7\u30E7\u30C3\u30C8\u306B\u5165\u529B\u5024\u304C\u8868\u793A\u3055\u308C\u308B\u3002\u5024\u304C\u8868\u793A\u3055\u308C\u3066\u3044\u308B\u30D5\u30A3\u30FC\u30EB\u30C9\u306F\u30B9\u30AD\u30C3\u30D7\u3059\u308B
8320
- 3. **\u4E0A\u304B\u3089\u4E0B\u3078\u4F53\u7CFB\u7684\u306B\u9032\u3080** \u2014 \u30D5\u30A9\u30FC\u30E0\u5185\u306E\u30D5\u30A3\u30FC\u30EB\u30C9\u30BB\u30C3\u30C8/\u30BB\u30AF\u30B7\u30E7\u30F3\u3092\u4E0A\u304B\u3089\u9806\u306B\u51E6\u7406\u3059\u308B\u3002\u524D\u306E\u30BB\u30AF\u30B7\u30E7\u30F3\u306B\u623B\u3089\u306A\u3044
8321
- 4. **\u5165\u529B\u6E08\u307F\u30D5\u30A3\u30FC\u30EB\u30C9\u6570\u3092\u610F\u8B58\u3059\u308B** \u2014 \u64CD\u4F5C\u5C65\u6B74\u3092\u53C2\u7167\u3057\u3001\u65E2\u306B\u4F55\u3092\u5165\u529B\u3057\u305F\u304B\u3092\u628A\u63E1\u3059\u308B\u3002\u540C\u3058\u30BB\u30EC\u30AF\u30BF\u3078\u306E\u91CD\u8907\u64CD\u4F5C\u306F\u7981\u6B62
8322
- 5. **\u5168\u30D5\u30A3\u30FC\u30EB\u30C9\u5165\u529B\u5F8C\u306B\u9001\u4FE1\u3059\u308B** \u2014 \u30D5\u30A9\u30FC\u30E0\u5185\u306E\u5168\u5FC5\u9808\u30D5\u30A3\u30FC\u30EB\u30C9\u304C\u57CB\u307E\u3063\u305F\u3089\u3001\u901F\u3084\u304B\u306B\u9001\u4FE1\u30DC\u30BF\u30F3\u3092\u30AF\u30EA\u30C3\u30AF\u3059\u308B
8323
- 6. **filledFields \u3092\u78BA\u8A8D\u3059\u308B** \u2014 browser\u30C4\u30FC\u30EB\u306E\u7D50\u679C\u306B\u542B\u307E\u308C\u308B filledFields \u306F\u5165\u529B\u6E08\u307F\u30D5\u30A3\u30FC\u30EB\u30C9\u306E\u4E00\u89A7\u3002\u3053\u306E\u4E00\u89A7\u306B\u3042\u308B\u30D5\u30A3\u30FC\u30EB\u30C9\u306F\u7D76\u5BFE\u306B\u518D\u5165\u529B\u3057\u306A\u3044\u3053\u3068
8324
-
8325
- ## \u30D5\u30A9\u30FC\u30E0\u5B8C\u4E86\u306E\u691C\u8A3C
8326
- \u30D5\u30A9\u30FC\u30E0\u5165\u529B\u306E\u30B4\u30FC\u30EB\u3067\u6700\u7D42\u5831\u544A\u3092\u8FD4\u3059\u524D\u306B:
8327
- 1. \u73FE\u5728\u306E\u30B9\u30CA\u30C3\u30D7\u30B7\u30E7\u30C3\u30C8\u5168\u4F53\u3092\u30B9\u30AD\u30E3\u30F3\u3057\u3001\u672A\u5165\u529B\u30D5\u30A3\u30FC\u30EB\u30C9\u304C\u306A\u3044\u304B\u78BA\u8A8D \u2014 \u5168\u30D5\u30A3\u30FC\u30EB\u30C9\u30BB\u30C3\u30C8/\u30BB\u30AF\u30B7\u30E7\u30F3\u3092\u30C1\u30A7\u30C3\u30AF
8328
- 2. \u4EE5\u4E0B\u3092\u63A2\u3059: \u5024\u306E\u306A\u3044\u30C6\u30AD\u30B9\u30C8\u30DC\u30C3\u30AF\u30B9\u3001\u300CSelect...\u300D\u30D7\u30EC\u30FC\u30B9\u30DB\u30EB\u30C0\u30FC\u8868\u793A\u306E\u30C9\u30ED\u30C3\u30D7\u30C0\u30A6\u30F3\u3001\u672A\u30C1\u30A7\u30C3\u30AF\u306E\u30C1\u30A7\u30C3\u30AF\u30DC\u30C3\u30AF\u30B9
8329
- 3. \u30D5\u30A9\u30FC\u30E0\u306E\u6700\u5F8C\u306E\u30BB\u30AF\u30B7\u30E7\u30F3\u306F\u898B\u843D\u3068\u3057\u3084\u3059\u3044 \u2014 \u30D5\u30A9\u30FC\u30E0\u6700\u4E0B\u90E8\u3092\u5FC5\u305A\u78BA\u8A8D
8330
- 4. \u5168\u30D5\u30A3\u30FC\u30EB\u30C9\u5165\u529B\u5F8C\u3001\u9001\u4FE1/\u767B\u9332\u30DC\u30BF\u30F3\u3092\u30AF\u30EA\u30C3\u30AF
8331
- 5. goalAchieved: true \u3092\u5BA3\u8A00\u3059\u308B\u524D\u306B\u6210\u529F\u78BA\u8A8D\u30E1\u30C3\u30BB\u30FC\u30B8\u306E\u8868\u793A\u3092\u78BA\u8A8D
8332
- \u5168\u30BB\u30AF\u30B7\u30E7\u30F3\u5B8C\u4E86\u30FB\u30D5\u30A9\u30FC\u30E0\u9001\u4FE1\u3092\u78BA\u8A8D\u3059\u308B\u307E\u3067 goalAchieved \u3092\u5BA3\u8A00\u3057\u306A\u3044\u3053\u3068\u3002
8333
-
8334
- ## \u30C7\u30FC\u30BF\u53CE\u96C6\u30D1\u30BF\u30FC\u30F3\uFF08\u30DA\u30FC\u30B8\u30CD\u30FC\u30B7\u30E7\u30F3\u8D70\u67FB\uFF09
8335
- \u624B\u9806: extract \u2192 memory_append \u2192 click\u300C\u6B21\u3078\u300D\u2192 \u7E70\u308A\u8FD4\u3057 \u2192 memory_aggregate \u3067\u96C6\u8A08
8336
-
8337
- \u4F8B\uFF08\u30C6\u30FC\u30D6\u30EB\u62BD\u51FA \u2192 \u84C4\u7A4D \u2192 \u6B21\u30DA\u30FC\u30B8 \u2192 \u96C6\u8A08 \u2192 CSV\u51FA\u529B\uFF09:
8338
- \`\`\`json
8339
- [
8340
- {"action":"extract","description":"\u30C6\u30FC\u30D6\u30EB\u62BD\u51FA","script":"(()=>{const h=[...document.querySelectorAll('table thead th')].map(t=>t.textContent.trim());return[...document.querySelectorAll('table tbody tr')].map(r=>{const c=r.querySelectorAll('td');return Object.fromEntries([...c].map((c,i)=>[h[i]||'col'+i,c.textContent.trim()]));});})()"},
8341
- {"action":"memory_append","description":"\u84C4\u7A4D","memoryCollection":"data"},
8342
- {"action":"click","description":"\u6B21\u30DA\u30FC\u30B8","selector":"@e15"}
8343
- ]
8344
- \`\`\`
8345
- \u96C6\u8A08: \`[{"action":"memory_aggregate","description":"\u5408\u8A08","aggregation":{"collection":"data","field":"amount","operation":"sum","outputVariable":"total"}}]\`
8346
- CSV\u51FA\u529B: \`[{"action":"export","description":"CSV\u51FA\u529B","exportCollection":"data","exportFormat":"csv","exportPath":"/tmp/data.csv"}]\`
8347
-
8348
- \u6CE8\u610F: script \u3067 JSON.stringify() \u4E0D\u8981\u3002\u5404\u884C\u306F\u30D5\u30E9\u30C3\u30C8\u306A\u30AA\u30D6\u30B8\u30A7\u30AF\u30C8\u3002memoryStatus \u3067\u30B3\u30EC\u30AF\u30B7\u30E7\u30F3\u306E\u30A2\u30A4\u30C6\u30E0\u6570\u3092\u78BA\u8A8D\u53EF\u80FD\u3002
8349
-
8350
- **\u91CD\u8981**: \u30DA\u30FC\u30B8\u30CD\u30FC\u30B7\u30E7\u30F3\u8D70\u67FB\u6642\u306F\u6700\u5F8C\u306E\u30DA\u30FC\u30B8\u307E\u3067\u5FC5\u305A\u7D99\u7D9A\u3057\u3066\u304F\u3060\u3055\u3044\u3002\u30DA\u30FC\u30B8\u8868\u793A\uFF08\u4F8B: "Page X of Y"\uFF09\u3092\u78BA\u8A8D\u3057\u3001\u6700\u7D42\u30DA\u30FC\u30B8\u306B\u5230\u9054\u3059\u308B\u307E\u3067\u300C\u6B21\u3078\u300D\u3092\u30AF\u30EA\u30C3\u30AF\u3057\u7D9A\u3051\u3066\u304F\u3060\u3055\u3044\u3002\u6570\u30DA\u30FC\u30B8\u3067\u6B62\u3081\u305A\u3001\u5168\u30DA\u30FC\u30B8\u3092\u51E6\u7406\u3057\u3066\u304F\u3060\u3055\u3044\u3002\u30D1\u30BF\u30FC\u30F3\u3092\u793A\u3059\u3053\u3068\u304C\u76EE\u7684\u3067\u306F\u306A\u304F\u3001\u5168\u30C7\u30FC\u30BF\u306E\u8D70\u67FB\u3092\u5B8C\u4E86\u3059\u308B\u3053\u3068\u304C\u76EE\u7684\u3067\u3059\u3002
8351
-
8352
- ## filledFields \u306E\u6D3B\u7528
8353
- browser\u30C4\u30FC\u30EB\u306E\u7D50\u679C\u306B \`filledFields\` \u304C\u542B\u307E\u308C\u3066\u3044\u308B\u5834\u5408\u3001\u3053\u308C\u306F\u65E2\u306B\u5165\u529B\u6E08\u307F\u306E\u30D5\u30A9\u30FC\u30E0\u30D5\u30A3\u30FC\u30EB\u30C9\u306E\u4E00\u89A7\u3067\u3059\u3002
8354
- \u30EA\u30B9\u30C8\u306B\u542B\u307E\u308C\u308B\u30D5\u30A3\u30FC\u30EB\u30C9\u306B\u306F\u518D\u5EA6\u5165\u529B\u3057\u306A\u3044\u3067\u304F\u3060\u3055\u3044\u3002\u672A\u5165\u529B\u306E\u30D5\u30A3\u30FC\u30EB\u30C9\u306E\u307F\u3092\u64CD\u4F5C\u3057\u3066\u304F\u3060\u3055\u3044\u3002
8355
-
8356
- ## \u5DEE\u5206\u30B9\u30CA\u30C3\u30D7\u30B7\u30E7\u30C3\u30C8
8357
- \u30C6\u30AD\u30B9\u30C8\u5165\u529B\uFF08fill/type\uFF09\u5F8C\u306B\u30DA\u30FC\u30B8\u69CB\u9020\u304C\u5909\u308F\u3063\u3066\u3044\u306A\u3044\u5834\u5408\u3001\u5168ref\u3092\u4E00\u89A7\u306B\u3057\u305F\u30B3\u30F3\u30D1\u30AF\u30C8\u306A\u30B9\u30CA\u30C3\u30D7\u30B7\u30E7\u30C3\u30C8\u304C\u8FD4\u3055\u308C\u307E\u3059\u3002
8358
- - \`Unfilled:\` \u306F\u307E\u3060\u64CD\u4F5C\u304C\u5FC5\u8981\u306A\u8981\u7D20\u3092\u793A\u3057\u307E\u3059
8359
- - \`Filled:\` \u306F\u5165\u529B\u6E08\u307F\u306E\u8981\u7D20\u3092\u793A\u3057\u307E\u3059
8360
- - \u30B3\u30F3\u30D1\u30AF\u30C8\u30B9\u30CA\u30C3\u30D7\u30B7\u30E7\u30C3\u30C8\u5185\u306E\u5168ref\u306F\u6709\u52B9\u3067\u4F7F\u7528\u53EF\u80FD\u3067\u3059
8361
- - \u5B8C\u5168\u306A\u30DA\u30FC\u30B8\u30B3\u30F3\u30C6\u30AD\u30B9\u30C8\u304C\u5FC5\u8981\u306A\u5834\u5408\u306F \`actions: []\` \u3067\u30D6\u30E9\u30A6\u30B6\u30C4\u30FC\u30EB\u3092\u547C\u3073\u51FA\u3057\u3066\u304F\u3060\u3055\u3044
8362
-
8363
- ## nudgeMessage \u3078\u306E\u5BFE\u5FDC
8364
- browser\u30C4\u30FC\u30EB\u306E\u7D50\u679C\u306B \`nudgeMessage\` \u304C\u542B\u307E\u308C\u3066\u3044\u308B\u5834\u5408\u3001\u91CD\u8981\u306A\u30AC\u30A4\u30C0\u30F3\u30B9\u304C\u8A18\u8F09\u3055\u308C\u3066\u3044\u307E\u3059:
8365
- - **\u30DA\u30FC\u30B8\u30CD\u30FC\u30B7\u30E7\u30F3\u9032\u6357**: \u73FE\u5728\u306E\u30DA\u30FC\u30B8\u3068\u6B8B\u308A\u30DA\u30FC\u30B8\u6570\u3092\u793A\u3057\u307E\u3059\u3002\u5168\u30DA\u30FC\u30B8\u306E\u51E6\u7406\u304C\u5B8C\u4E86\u3059\u308B\u307E\u3067\u7D9A\u884C\u3057\u3066\u304F\u3060\u3055\u3044\u3002
8366
- - **\u30EB\u30FC\u30D7\u8B66\u544A**: \u540C\u3058\u64CD\u4F5C\u3092\u7E70\u308A\u8FD4\u3057\u3066\u3044\u308B\u53EF\u80FD\u6027\u304C\u3042\u308A\u307E\u3059\u3002\u5225\u306E\u30A2\u30D7\u30ED\u30FC\u30C1\u3092\u8A66\u3057\u3066\u304F\u3060\u3055\u3044\u3002
8367
- - **\u30D5\u30A9\u30FC\u30E0\u30D2\u30F3\u30C8**: \u672A\u5165\u529B\u306E\u30D5\u30A9\u30FC\u30E0\u30D5\u30A3\u30FC\u30EB\u30C9\u4E00\u89A7\u3067\u3059\u3002
8368
- \u30E1\u30C3\u30BB\u30FC\u30B8\u306E\u6307\u793A\u306B\u5FC5\u305A\u5F93\u3063\u3066\u304F\u3060\u3055\u3044\u3002
8369
-
8370
- ## \u8907\u5408\u30B4\u30FC\u30EB\u306E\u691C\u8A3C
8371
- \u30B4\u30FC\u30EB\u306B\u8907\u6570\u306E\u30B9\u30C6\u30C3\u30D7\u304C\u542B\u307E\u308C\u3066\u3044\u308B\u5834\u5408\uFF08\u4F8B: \u300CA\u3057\u3066\u3001B\u306B\u9077\u79FB\u3057\u3001C\u3092\u5B9F\u884C\u3059\u308B\u300D\uFF09\uFF1A
8372
- 1. \u30B4\u30FC\u30EB\u3092\u500B\u5225\u306E\u30B5\u30D6\u30BF\u30B9\u30AF\u306B\u5206\u89E3\u3059\u308B
8373
- 2. \u5404\u30B5\u30D6\u30BF\u30B9\u30AF\u304C\u5B8C\u4E86\u3057\u305F\u304B\u3069\u3046\u304B\u3092\u73FE\u5728\u306E\u30DA\u30FC\u30B8\u72B6\u614B\u304B\u3089\u78BA\u8A8D\u3059\u308B
8374
- 3. **\u5168\u3066\u306E\u30B5\u30D6\u30BF\u30B9\u30AF\u304C\u5B8C\u4E86\u3059\u308B\u307E\u3067 goalAchieved \u3092\u5BA3\u8A00\u3057\u306A\u3044\u3053\u3068**
8375
- 4. \u30ED\u30B0\u30A4\u30F3\u3084\u30DA\u30FC\u30B8\u9077\u79FB\u304C\u6210\u529F\u3057\u3066\u3082\u3001\u5F8C\u7D9A\u306E\u30BF\u30B9\u30AF\u304C\u3042\u308C\u3070\u307E\u3060\u30B4\u30FC\u30EB\u306F\u672A\u9054\u6210
8376
- 5. \u4E00\u90E8\u306E\u30B5\u30D6\u30BF\u30B9\u30AF\u304C\u5B8C\u4E86\u3057\u3066\u3044\u308B\u5834\u5408\u306F\u3001\u6B8B\u308A\u306E\u30B5\u30D6\u30BF\u30B9\u30AF\u306B\u53D6\u308A\u7D44\u307F\u7D9A\u3051\u308B\u3053\u3068\u3002\u56DE\u5FA9\u4E0D\u80FD\u306A\u30A8\u30E9\u30FC\u3084\u5168\u3066\u306E\u30A2\u30D7\u30ED\u30FC\u30C1\u3092\u8A66\u3057\u305F\u5834\u5408\u306B\u306E\u307F goalAchieved: false \u3092\u5BA3\u8A00\u3059\u308B
8377
-
8378
- \u4F8B: \u30B4\u30FC\u30EB\u304C\u300C\u30ED\u30B0\u30A4\u30F3\u3057\u3066\u30A2\u30AF\u30B7\u30E7\u30F3\u4E00\u89A7\u3067X\u3092\u5B9F\u884C\u3059\u308B\u300D\u306E\u5834\u5408\uFF1A
8379
- - \u30ED\u30B0\u30A4\u30F3\u6210\u529F \u2192 \u307E\u3060 goalAchieved \u3067\u306F\u306A\u3044\uFF08\u30A2\u30AF\u30B7\u30E7\u30F3\u5B9F\u884C\u304C\u6B8B\u3063\u3066\u3044\u308B\uFF09
8380
- - \u30A2\u30AF\u30B7\u30E7\u30F3\u4E00\u89A7\u3067X\u3092\u5B9F\u884C\u5B8C\u4E86 \u2192 goalAchieved: true
8381
-
8382
- ## \u30B4\u30FC\u30EB\u9054\u6210\u6642
8383
- **\u91CD\u8981: goalAchieved \u306E\u7533\u544A\u306F\u6700\u7D42\u30DA\u30FC\u30B8\u72B6\u614B\u304B\u3089\u72EC\u7ACB\u691C\u8A3C\u3055\u308C\u307E\u3059\u3002\u865A\u507D\u306E\u7533\u544A\u306F\u4E0A\u66F8\u304D\u3055\u308C\u307E\u3059\u3002**
8384
-
8385
- goalAchieved: true \u3092\u5BA3\u8A00\u3059\u308B\u524D\u306B\u3001\u4EE5\u4E0B\u306E\u30C1\u30A7\u30C3\u30AF\u30EA\u30B9\u30C8\u3092\u5FC5\u305A\u5B8C\u4E86\u3057\u3066\u304F\u3060\u3055\u3044:
8386
- 1. **\u5143\u306E\u30B4\u30FC\u30EB\u3092\u518D\u78BA\u8A8D** \u2014 \u5168\u3066\u306E\u30B5\u30D6\u30BF\u30B9\u30AF\u306B\u5206\u89E3\u3059\u308B
8387
- 2. **\u73FE\u5728\u306E\u30DA\u30FC\u30B8\u72B6\u614B\u3092\u78BA\u8A8D** \u2014 \u30B9\u30CA\u30C3\u30D7\u30B7\u30E7\u30C3\u30C8\u306B\u9054\u6210\u306E\u660E\u78BA\u306A\u8A3C\u62E0\u304C\u3042\u308B\u304B\uFF1F
8388
- 3. **\u30D5\u30A9\u30FC\u30E0\u30BF\u30B9\u30AF**: \u6210\u529F/\u78BA\u8A8D\u30E1\u30C3\u30BB\u30FC\u30B8\u304C\u8868\u793A\u3055\u308C\u3066\u3044\u308B\u304B\uFF1F\uFF08\u300C\u30D5\u30A3\u30FC\u30EB\u30C9\u3092\u5165\u529B\u3057\u305F\u300D\u3060\u3051\u3067\u306F\u4E0D\u5341\u5206 \u2014 \u30D5\u30A9\u30FC\u30E0\u304C\u9001\u4FE1\u3055\u308C\u3001\u78BA\u8A8D\u304C\u8868\u793A\u3055\u308C\u3066\u3044\u308B\u3053\u3068\uFF09
8389
- 4. **\u30CA\u30D3\u30B2\u30FC\u30B7\u30E7\u30F3\u30BF\u30B9\u30AF**: \u76EE\u7684\u306E\u30DA\u30FC\u30B8\u304C\u5B9F\u969B\u306B\u8868\u793A\u3055\u308C\u3066\u3044\u308B\u304B\uFF1F
8390
- 5. **\u8907\u5408\u30B4\u30FC\u30EB**\uFF08A \u2192 B \u2192 C\uFF09: \u6700\u521D\u306E\u90E8\u5206\u3060\u3051\u3067\u306A\u304F\u3001\u5168\u30D1\u30FC\u30C8\u306E\u8A3C\u62E0\u3092\u78BA\u8A8D
8391
- 6. **\u5931\u6557\u30B7\u30B0\u30CA\u30EB\u306E\u78BA\u8A8D**: \u30A8\u30E9\u30FC\u30E1\u30C3\u30BB\u30FC\u30B8\u3001\u30D0\u30EA\u30C7\u30FC\u30B7\u30E7\u30F3\u8B66\u544A\u3001\u30ED\u30B0\u30A4\u30F3\u30D5\u30A9\u30FC\u30E0\u304C\u307E\u3060\u8868\u793A\u3055\u308C\u3066\u3044\u306A\u3044\u304B\u3001\u300C\u518D\u8A66\u884C\u300D\u30D7\u30ED\u30F3\u30D7\u30C8\u304C\u306A\u3044\u304B
8392
- 7. **summary \u306B\u5177\u4F53\u7684\u306A\u8A3C\u62E0\u3092\u542B\u3081\u308B**: \u5B8C\u4E86\u3092\u8A3C\u660E\u3059\u308B\u78BA\u8A8D\u30E1\u30C3\u30BB\u30FC\u30B8\u3001\u6210\u529F\u30D0\u30CA\u30FC\u3001\u30DA\u30FC\u30B8\u30BF\u30A4\u30C8\u30EB\u3092\u5F15\u7528\u3059\u308B
8393
-
8394
- \u3088\u304F\u3042\u308B\u507D\u967D\u6027\u30D1\u30BF\u30FC\u30F3\uFF08\u907F\u3051\u308B\u3079\u304D\uFF09:
8395
- - \u30ED\u30B0\u30A4\u30F3\u5F8C\u306E\u30BF\u30B9\u30AF\u304C\u3042\u308B\u306E\u306B\u3001\u30ED\u30B0\u30A4\u30F3\u6210\u529F\u3060\u3051\u3067\u9054\u6210\u3068\u5BA3\u8A00\u3059\u308B
8396
- - \u30D5\u30A9\u30FC\u30E0\u5165\u529B\u5F8C\u3001\u9001\u4FE1\u524D\u306B\u9054\u6210\u3068\u5BA3\u8A00\u3059\u308B
8397
- - \u30DC\u30BF\u30F3\u30AF\u30EA\u30C3\u30AF\u5F8C\u3001\u78BA\u8A8D\u3092\u5F85\u305F\u305A\u306B\u9054\u6210\u3068\u5BA3\u8A00\u3059\u308B
8398
- - \u30DA\u30FC\u30B8\u304C\u30A8\u30E9\u30FC\u3092\u8868\u793A\u3057\u3066\u3044\u308B\u3001\u307E\u305F\u306F\u30ED\u30FC\u30C9\u4E2D\u306A\u306E\u306B\u9054\u6210\u3068\u5BA3\u8A00\u3059\u308B
8399
-
8400
- \u5168\u30C1\u30A7\u30C3\u30AF\u9805\u76EE\u3092\u78BA\u8A8D\u3057\u305F\u4E0A\u3067\u3001browser\u30C4\u30FC\u30EB\u306E\u547C\u3073\u51FA\u3057\u3092\u505C\u6B62\u3057\u3001\u4EE5\u4E0B\u306EJSON\u5F62\u5F0F\u3067\u6700\u7D42\u5831\u544A\u3092\u8FD4\u3057\u3066\u304F\u3060\u3055\u3044:
8401
- \`\`\`json
8402
- { "goalAchieved": true, "summary": "\u8A3C\u62E0: [\u5177\u4F53\u7684\u306A\u78BA\u8A8D\u30E1\u30C3\u30BB\u30FC\u30B8\u3084\u30DA\u30FC\u30B8\u72B6\u614B]\u3002\u5B8C\u4E86: [\u5B9F\u884C\u3057\u305F\u30B5\u30D6\u30BF\u30B9\u30AF\u4E00\u89A7]" }
8403
- \`\`\`
8404
-
8405
- \u30B4\u30FC\u30EB\u304C\u9054\u6210\u3067\u304D\u306A\u3044\u3068\u5224\u65AD\u3057\u305F\u5834\u5408:
8406
- \`\`\`json
8407
- { "goalAchieved": false, "summary": "\u72B6\u6CC1\u306E\u8981\u7D04\u3068\u7406\u7531" }
8408
- \`\`\`
8409
-
8410
- ---
8411
- \u4EE5\u4E0B\u306F\u3053\u306E\u30BF\u30B9\u30AF\u56FA\u6709\u306E\u60C5\u5831\u3067\u3059\u3002
8412
-
8413
- ## \u30B4\u30FC\u30EB
8414
- ${goal}
8415
- ${contextSection}${secretsSection}
8416
- \u65E5\u672C\u8A9E\u3067\u5FDC\u7B54\u3057\u3066\u304F\u3060\u3055\u3044\u3002`;
8417
- }
8418
- function getInitialUserMessage2() {
8419
- return "browser\u30C4\u30FC\u30EB\u3092actions:[]\uFF08\u7A7A\u914D\u5217\uFF09\u3067\u547C\u3073\u51FA\u3057\u3001\u73FE\u5728\u306E\u30DA\u30FC\u30B8\u72B6\u614B\u3092\u78BA\u8A8D\u3057\u3066\u304F\u3060\u3055\u3044\u3002\u305D\u306E\u5F8C\u3001\u30B4\u30FC\u30EB\u9054\u6210\u306B\u5411\u3051\u3066\u63A2\u7D22\u3092\u958B\u59CB\u3057\u3066\u304F\u3060\u3055\u3044\u3002";
8420
8337
  }
8421
-
8422
- // src/i18n/prompts/en/review.ts
8423
- function getReviewSystemPrompt() {
8424
- return `You are an expert reviewer of web browser automation procedures.
8425
-
8426
- ## Task
8427
- Analyze the recorded steps and determine the following:
8428
-
8429
- 1. **Remove unnecessary steps**: Identify and exclude trial-and-error during exploration, dead ends, unnecessary navigation, and duplicate operations
8430
- 2. **Risk level assessment**: Assess the risk of each step
8431
- - \`low\`: Low side-effect operations like input, scrolling, navigation
8432
- - \`medium\`: Login, form submission, settings changes, etc.
8433
- - \`high\`: Irreversible operations like deletion, payment, data modification
8434
- 3. **Approval requirement**: Whether user approval is needed before execution
8435
-
8436
- ## Capture Candidate Identification
8437
- If you detect important data used in subsequent steps (IDs, order numbers, URL changes, amounts, etc.),
8438
- include them as suggestedCaptures in each step's response.
8439
- Available strategies: snapshot (regex), url (URL regex), ai (AI extraction), expression (template)
8440
-
8441
- ## Notes
8442
- - Failed steps (success=false) should generally be excluded
8443
- - Keep only the shortest path steps needed to achieve the goal
8444
- - riskLevel is used in the Chrome extension approval flow (medium/high requires approval)
8445
- - Respond in English`;
8446
- }
8447
- function createReviewUserPrompt(goal, recordedSteps, goalAchieved, interventions) {
8448
- const stepsList = recordedSteps.map(
8449
- (s) => `${s.ordinal}. [${s.success ? "OK" : "FAIL"}] ${s.action.description} (action: ${s.action.action}, url: ${s.url})${s.error ? ` Error: ${s.error}` : ""}`
8450
- ).join("\n");
8451
- const interventionsSection = interventions && interventions.length > 0 ? `
8452
- ## User Interventions During Exploration
8453
- The user modified the exploration direction at the following points.
8454
- Steps before the intervention likely contain trial-and-error, while steps after are more accurate.
8455
-
8456
- ${interventions.map(
8457
- (iv, i) => `${i + 1}. Around step #${iv.stepIndex}: "${iv.userInstruction}" (URL: ${iv.url})`
8458
- ).join("\n")}
8459
-
8460
- **Review note**: Actively exclude unnecessary steps before intervention points.
8461
- ` : "";
8462
- return `## Goal
8463
- ${goal}
8464
-
8465
- ## Goal Achievement Status
8466
- ${goalAchieved ? "Achieved" : "Not achieved"}
8467
- ${interventionsSection}
8468
- ## All Recorded Steps
8469
- ${stepsList}`;
8470
- }
8471
-
8472
- // src/i18n/prompts/ja/review.ts
8473
- function getReviewSystemPrompt2() {
8474
- return `\u3042\u306A\u305F\u306FWeb\u30D6\u30E9\u30A6\u30B6\u81EA\u52D5\u64CD\u4F5C\u306E\u624B\u9806\u66F8\u3092\u30EC\u30D3\u30E5\u30FC\u3059\u308B\u30A8\u30AD\u30B9\u30D1\u30FC\u30C8\u3067\u3059\u3002
8475
-
8476
- ## \u30BF\u30B9\u30AF
8477
- \u8A18\u9332\u3055\u308C\u305F\u30B9\u30C6\u30C3\u30D7\u3092\u5206\u6790\u3057\u3001\u4EE5\u4E0B\u3092\u5224\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044:
8478
-
8479
- 1. **\u4E0D\u8981\u30B9\u30C6\u30C3\u30D7\u306E\u9664\u5916**: \u63A2\u7D22\u4E2D\u306E\u8A66\u884C\u932F\u8AA4\u3001\u884C\u304D\u6B62\u307E\u308A\u3001\u4E0D\u8981\u306A\u30CA\u30D3\u30B2\u30FC\u30B7\u30E7\u30F3\u3001\u91CD\u8907\u64CD\u4F5C\u3092\u7279\u5B9A\u3057\u9664\u5916
8480
- 2. **\u30EA\u30B9\u30AF\u30EC\u30D9\u30EB\u5224\u5B9A**: \u5404\u30B9\u30C6\u30C3\u30D7\u306E\u30EA\u30B9\u30AF\u3092\u5224\u5B9A
8481
- - \`low\`: \u5165\u529B\u3001\u30B9\u30AF\u30ED\u30FC\u30EB\u3001\u30CA\u30D3\u30B2\u30FC\u30B7\u30E7\u30F3\u306A\u3069\u526F\u4F5C\u7528\u306E\u5C11\u306A\u3044\u64CD\u4F5C
8482
- - \`medium\`: \u30ED\u30B0\u30A4\u30F3\u3001\u30D5\u30A9\u30FC\u30E0\u9001\u4FE1\u3001\u8A2D\u5B9A\u5909\u66F4\u306A\u3069
8483
- - \`high\`: \u524A\u9664\u3001\u6C7A\u6E08\u3001\u30C7\u30FC\u30BF\u5909\u66F4\u306A\u3069\u4E0D\u53EF\u9006\u306A\u64CD\u4F5C
8484
- 3. **\u627F\u8A8D\u8981\u5426\u5224\u5B9A**: \u5B9F\u884C\u524D\u306B\u30E6\u30FC\u30B6\u30FC\u627F\u8A8D\u304C\u5FC5\u8981\u304B\u3069\u3046\u304B
8485
-
8486
- ## \u30AD\u30E3\u30D7\u30C1\u30E3\u5019\u88DC\u306E\u8B58\u5225
8487
- \u64CD\u4F5C\u7D50\u679C\u3068\u3057\u3066\u5F8C\u7D9A\u30B9\u30C6\u30C3\u30D7\u3067\u4F7F\u7528\u3055\u308C\u308B\u91CD\u8981\u306A\u30C7\u30FC\u30BF\uFF08ID\u3001\u6CE8\u6587\u756A\u53F7\u3001URL\u5909\u5316\u3001\u91D1\u984D\u306A\u3069\uFF09\u3092\u691C\u51FA\u3057\u305F\u5834\u5408\u3001
8488
- suggestedCaptures \u3068\u3057\u3066\u30EC\u30B9\u30DD\u30F3\u30B9\u306E\u5404\u30B9\u30C6\u30C3\u30D7\u306B\u542B\u3081\u3066\u304F\u3060\u3055\u3044\u3002
8489
- \u5229\u7528\u53EF\u80FD\u306A strategy: snapshot\uFF08\u6B63\u898F\u8868\u73FE\uFF09, url\uFF08URL\u6B63\u898F\u8868\u73FE\uFF09, ai\uFF08AI\u62BD\u51FA\uFF09, expression\uFF08\u30C6\u30F3\u30D7\u30EC\u30FC\u30C8\uFF09
8490
-
8491
- ## \u6CE8\u610F\u4E8B\u9805
8492
- - \u5931\u6557\u30B9\u30C6\u30C3\u30D7\uFF08success=false\uFF09\u306F\u57FA\u672C\u7684\u306B\u9664\u5916\u3057\u3066\u304F\u3060\u3055\u3044
8493
- - \u30B4\u30FC\u30EB\u9054\u6210\u306B\u5FC5\u8981\u306A\u6700\u77ED\u7D4C\u8DEF\u306E\u30B9\u30C6\u30C3\u30D7\u306E\u307F\u6B8B\u3057\u3066\u304F\u3060\u3055\u3044
8494
- - riskLevel \u306F Chrome\u62E1\u5F35\u306E\u627F\u8A8D\u30D5\u30ED\u30FC\u3067\u4F7F\u7528\u3055\u308C\u307E\u3059\uFF08medium/high \u306F\u627F\u8A8D\u304C\u5FC5\u8981\uFF09
8495
- - \u65E5\u672C\u8A9E\u3067\u5FDC\u7B54\u3057\u3066\u304F\u3060\u3055\u3044`;
8496
- }
8497
- function createReviewUserPrompt2(goal, recordedSteps, goalAchieved, interventions) {
8498
- const stepsList = recordedSteps.map(
8499
- (s) => `${s.ordinal}. [${s.success ? "\u6210\u529F" : "\u5931\u6557"}] ${s.action.description} (action: ${s.action.action}, url: ${s.url})${s.error ? ` \u30A8\u30E9\u30FC: ${s.error}` : ""}`
8500
- ).join("\n");
8501
- const interventionsSection = interventions && interventions.length > 0 ? `
8502
- ## \u63A2\u7D22\u4E2D\u306E\u30E6\u30FC\u30B6\u30FC\u4ECB\u5165
8503
- \u4EE5\u4E0B\u306E\u30BF\u30A4\u30DF\u30F3\u30B0\u3067\u30E6\u30FC\u30B6\u30FC\u304C\u63A2\u7D22\u65B9\u91DD\u3092\u4FEE\u6B63\u3057\u307E\u3057\u305F\u3002
8504
- \u4ECB\u5165\u524D\u306E\u30B9\u30C6\u30C3\u30D7\u306B\u306F\u63A2\u7D22\u306E\u8A66\u884C\u932F\u8AA4\u304C\u542B\u307E\u308C\u3066\u3044\u308B\u53EF\u80FD\u6027\u304C\u9AD8\u304F\u3001\u4ECB\u5165\u5F8C\u306E\u30B9\u30C6\u30C3\u30D7\u304C\u3088\u308A\u6B63\u78BA\u306A\u624B\u9806\u3067\u3059\u3002
8505
-
8506
- ${interventions.map(
8507
- (iv, i) => `${i + 1}. \u30B9\u30C6\u30C3\u30D7#${iv.stepIndex}\u4ED8\u8FD1: "${iv.userInstruction}" (URL: ${iv.url})`
8508
- ).join("\n")}
8509
-
8510
- **\u30EC\u30D3\u30E5\u30FC\u6642\u306E\u6CE8\u610F**: \u4ECB\u5165\u30DD\u30A4\u30F3\u30C8\u3088\u308A\u524D\u306E\u4E0D\u8981\u306A\u30B9\u30C6\u30C3\u30D7\u306F\u7A4D\u6975\u7684\u306B\u9664\u5916\u3057\u3066\u304F\u3060\u3055\u3044\u3002
8511
- ` : "";
8512
- return `## \u30B4\u30FC\u30EB
8513
- ${goal}
8514
-
8515
- ## \u30B4\u30FC\u30EB\u9054\u6210\u72B6\u6CC1
8516
- ${goalAchieved ? "\u9054\u6210\u6E08\u307F" : "\u672A\u9054\u6210"}
8517
- ${interventionsSection}
8518
- ## \u8A18\u9332\u3055\u308C\u305F\u5168\u30B9\u30C6\u30C3\u30D7
8519
- ${stepsList}`;
8520
- }
8521
-
8522
- // src/i18n/prompts/en/selector.ts
8523
- function buildSelectorMessages(snapshot, selector, stepDescription, url, contextMarkdown, retryContext, workingMemorySummary) {
8524
- const system = [
8525
- "You are a selector resolver for browser automation.",
8526
- "Based on the step description, identify the target element in the accessibility snapshot.",
8527
- "",
8528
- "## Matching Guidelines",
8529
- "1. Infer the type of target element (button, input field, link, etc.) from the step description",
8530
- "2. Find the element in the snapshot that semantically best matches the step description",
8531
- "3. Use surrounding text, labels, placeholders, and roles as clues",
8532
- "4. Even without an exact match, return the ref of the most likely element",
8533
- "5. Return an empty string only if the target element truly does not exist in the snapshot"
8534
- ].join("\n");
8535
- const parts = [
8536
- "## Step Description (Most Important)",
8537
- stepDescription,
8538
- "",
8539
- "## Selector Hints (Reference)",
8540
- "The following is reference information for identifying the element. Even without an exact match, choose the element semantically closest to the step description.",
8541
- JSON.stringify(pruneSelectorHints(selector)),
8542
- "",
8543
- "Notes:",
8544
- '- If tagName is "unknown" or ":", there is no tag name information',
8545
- "- ariaLabel is auto-generated from the step description and may not match the actual aria-label attribute",
8546
- "- Prioritize semantic match with the step description over exact selector match",
8547
- "",
8548
- "## Current URL",
8549
- url
8550
- ];
8551
- if (workingMemorySummary) {
8552
- parts.push("", "## Execution Context", workingMemorySummary);
8553
- }
8554
- parts.push(
8555
- "",
8556
- "## Accessibility Snapshot",
8557
- snapshot
8558
- );
8559
- const includeContext = contextMarkdown && !(retryContext && retryContext.attempt > 0);
8560
- if (includeContext) {
8561
- parts.push("", "## Supplementary Context", contextMarkdown);
8562
- }
8563
- if (retryContext && retryContext.attempt > 0) {
8564
- parts.push(
8565
- "",
8566
- "## Recovery Context (Attempt " + (retryContext.attempt + 1) + ")"
8567
- );
8568
- if (retryContext.failureHints) {
8569
- parts.push(`Pattern: ${retryContext.failureHints}`);
8338
+ function formatAiMetricsSection(aiMetrics) {
8339
+ const lines = [];
8340
+ if (aiMetrics.totalCalls <= 0) return lines;
8341
+ const m = aiMetrics;
8342
+ const totalRealInput = computeTotalRealInput(m);
8343
+ const cacheRate = (computeCacheRate(m) * 100).toFixed(1);
8344
+ lines.push("### AI Metrics");
8345
+ lines.push("");
8346
+ lines.push("| \u30E1\u30C8\u30EA\u30AF\u30B9 | \u5024 |");
8347
+ lines.push("|-----------|-----|");
8348
+ lines.push(`| Total calls | ${m.totalCalls} |`);
8349
+ lines.push(`| Total input tokens | ${totalRealInput.toLocaleString()} |`);
8350
+ lines.push(`| Output tokens | ${m.totalOutputTokens.toLocaleString()} |`);
8351
+ lines.push(`| Cache read tokens | ${m.totalCachedInputTokens.toLocaleString()} |`);
8352
+ lines.push(`| Cache write tokens | ${m.totalCacheCreationTokens.toLocaleString()} |`);
8353
+ lines.push(`| Cache hit rate | ${cacheRate}% |`);
8354
+ lines.push(`| Estimated cost | $${m.estimatedCostUsd.toFixed(4)} |`);
8355
+ lines.push(`| Total AI duration | ${(m.totalDurationMs / 1e3).toFixed(1)}s |`);
8356
+ lines.push("");
8357
+ const cacheHitRate = computeCacheRate(m);
8358
+ if (cacheHitRate < 0.3 && m.totalCalls >= 3) {
8359
+ lines.push(`> **:warning: \u30AD\u30E3\u30C3\u30B7\u30E5\u30D2\u30C3\u30C8\u7387\u304C\u4F4E\u3044 (${cacheRate}%)**`);
8360
+ lines.push("> AI \u30D7\u30ED\u30F3\u30D7\u30C8\u30AD\u30E3\u30C3\u30B7\u30E5\u306E\u6D3B\u7528\u304C\u5C11\u306A\u304F\u3001\u30B3\u30B9\u30C8\u52B9\u7387\u304C\u60AA\u3044\u53EF\u80FD\u6027\u304C\u3042\u308A\u307E\u3059\u3002");
8361
+ lines.push("> \u8003\u3048\u3089\u308C\u308B\u539F\u56E0: \u30D7\u30ED\u30F3\u30D7\u30C8\u306E\u5148\u982D\u90E8\u5206\u304C\u6BCE\u56DE\u7570\u306A\u308B\u3001\u30B9\u30CA\u30C3\u30D7\u30B7\u30E7\u30C3\u30C8\u304C\u5927\u304D\u304F\u5909\u52D5\u3059\u308B\u3001\u540C\u4E00\u30BB\u30EC\u30AF\u30BF\u306E\u518D\u89E3\u6C7A\u304C\u767A\u751F\u3057\u3066\u3044\u306A\u3044\u3002");
8362
+ lines.push("");
8363
+ }
8364
+ if (Object.keys(m.byPurpose).length > 0) {
8365
+ lines.push("**By purpose:**");
8366
+ lines.push("");
8367
+ lines.push("| Purpose | Calls | Input | Output | Cache Read | Cache Write | Duration |");
8368
+ lines.push("|---------|-------|-------|--------|------------|-------------|----------|");
8369
+ for (const [purpose, b] of Object.entries(m.byPurpose)) {
8370
+ const purposeRealInput = computeTotalRealInput(b);
8371
+ lines.push(
8372
+ `| ${purpose} | ${b.calls} | ${purposeRealInput.toLocaleString()} | ${b.outputTokens.toLocaleString()} | ${b.cachedInputTokens.toLocaleString()} | ${b.cacheCreationTokens.toLocaleString()} | ${(b.durationMs / 1e3).toFixed(1)}s |`
8373
+ );
8570
8374
  }
8571
- if (retryContext.failureHistory.length > 0) {
8572
- const recent = retryContext.failureHistory.slice(-2);
8573
- parts.push(`Previous: ${recent.join("; ")}`);
8375
+ lines.push("");
8376
+ }
8377
+ if (m.byModel && Object.keys(m.byModel).length > 0) {
8378
+ lines.push("**By model:**");
8379
+ lines.push("");
8380
+ lines.push("| Model | Calls | Input | Output | Cache Read | Cache Write | Cost | Duration |");
8381
+ lines.push("|-------|-------|-------|--------|------------|-------------|------|----------|");
8382
+ for (const [modelId, b] of Object.entries(m.byModel)) {
8383
+ const modelRealInput = computeTotalRealInput(b);
8384
+ lines.push(
8385
+ `| ${modelId} | ${b.calls} | ${modelRealInput.toLocaleString()} | ${b.outputTokens.toLocaleString()} | ${b.cachedInputTokens.toLocaleString()} | ${b.cacheCreationTokens.toLocaleString()} | $${b.estimatedCostUsd.toFixed(4)} | ${(b.durationMs / 1e3).toFixed(1)}s |`
8386
+ );
8574
8387
  }
8575
- if (retryContext.previousAiResponse) {
8576
- try {
8577
- const parsed = JSON.parse(retryContext.previousAiResponse);
8578
- if (parsed.reasoning) {
8579
- parts.push(`Last reasoning: "${parsed.reasoning}"`);
8580
- }
8581
- } catch {
8582
- parts.push(`Last response: ${retryContext.previousAiResponse.slice(0, 200)}`);
8388
+ lines.push("");
8389
+ }
8390
+ return lines;
8391
+ }
8392
+ function formatRuntimeEnvironment() {
8393
+ const lines = [];
8394
+ lines.push("### Runtime Environment");
8395
+ lines.push("");
8396
+ lines.push(`- **AI Model**: ${getModelId()} (${getModelProvider()})`);
8397
+ lines.push(`- **Node.js**: ${process.version}`);
8398
+ lines.push(`- **Platform**: ${process.platform} ${process.arch}`);
8399
+ lines.push("");
8400
+ return lines;
8401
+ }
8402
+ function formatSelectorResolutionStats(debugEntries, allSteps) {
8403
+ const lines = [];
8404
+ lines.push("### Selector Resolution Statistics");
8405
+ lines.push("");
8406
+ const stepsWithSelector = allSteps.filter(
8407
+ (s) => s.diagnostics?.stepAction?.selector || s.diagnostics?.deterministicResolveResult
8408
+ );
8409
+ const deterministicHits = debugEntries.filter((e) => e.event === "deterministic_resolve").length;
8410
+ const deterministicMisses = debugEntries.filter((e) => e.event === "deterministic_resolve_miss").length;
8411
+ const aiResolves = debugEntries.filter((e) => e.event === "selector_resolve").length;
8412
+ const cacheHits = debugEntries.filter((e) => e.event === "selector_cache_hit").length;
8413
+ const cacheStales = debugEntries.filter((e) => e.event === "selector_cache_stale").length;
8414
+ const retryEvents = debugEntries.filter((e) => e.event === "selector_retry").length;
8415
+ const recoveryAttempts = debugEntries.filter((e) => e.event === "recovery_attempt").length;
8416
+ const agentFallbackStarts = debugEntries.filter((e) => e.event === "agent_fallback_start").length;
8417
+ const agentFallbackResults = debugEntries.filter((e) => e.event === "agent_fallback_result");
8418
+ const agentFallbackSuccesses = agentFallbackResults.filter(
8419
+ (e) => e.data && e.data.success === true
8420
+ ).length;
8421
+ const totalResolveAttempts = deterministicHits + deterministicMisses + cacheHits;
8422
+ if (totalResolveAttempts > 0 || stepsWithSelector.length > 0) {
8423
+ lines.push("| \u30E1\u30C8\u30EA\u30AF\u30B9 | \u4EF6\u6570 |");
8424
+ lines.push("|-----------|------|");
8425
+ if (totalResolveAttempts > 0) {
8426
+ lines.push(`| \u6C7A\u5B9A\u8AD6\u7684\u89E3\u6C7A \u6210\u529F | ${deterministicHits} |`);
8427
+ lines.push(`| \u6C7A\u5B9A\u8AD6\u7684\u89E3\u6C7A \u5931\u6557\u2192AI\u59D4\u8B72 | ${deterministicMisses} |`);
8428
+ lines.push(`| AI \u30BB\u30EC\u30AF\u30BF\u89E3\u6C7A | ${aiResolves} |`);
8429
+ if (cacheHits > 0 || cacheStales > 0) {
8430
+ lines.push(`| \u30AD\u30E3\u30C3\u30B7\u30E5\u30D2\u30C3\u30C8 | ${cacheHits} |`);
8431
+ lines.push(`| \u30AD\u30E3\u30C3\u30B7\u30E5 stale\uFF08\u81EA\u52D5\u7121\u52B9\u5316\uFF09 | ${cacheStales} |`);
8583
8432
  }
8584
- }
8585
- if (!retryContext.snapshotChanged) {
8586
- parts.push(
8587
- "Snapshot unchanged \u2014 try partial matching, role-based matching, or inference from nearby elements."
8433
+ lines.push(`| \u30BB\u30EC\u30AF\u30BF\u30EA\u30C8\u30E9\u30A4 | ${retryEvents} |`);
8434
+ if (recoveryAttempts > 0) {
8435
+ lines.push(`| \u30B9\u30AF\u30ED\u30FC\u30EB\u56DE\u5FA9 | ${recoveryAttempts} |`);
8436
+ }
8437
+ const visionFbStarts = debugEntries.filter((e) => e.event === "vision_fallback_start").length;
8438
+ if (visionFbStarts > 0) {
8439
+ const visionFbSuccesses = debugEntries.filter(
8440
+ (e) => e.event === "vision_fallback_result" && e.data && e.data.ref
8441
+ ).length;
8442
+ lines.push(`| Vision Fallback \u767A\u52D5 | ${visionFbStarts} |`);
8443
+ lines.push(`| Vision Fallback \u6210\u529F | ${visionFbSuccesses} |`);
8444
+ }
8445
+ if (agentFallbackStarts > 0) {
8446
+ lines.push(`| Agent Fallback \u767A\u52D5 | ${agentFallbackStarts} |`);
8447
+ lines.push(`| Agent Fallback \u6210\u529F | ${agentFallbackSuccesses} |`);
8448
+ }
8449
+ } else {
8450
+ const totalRetries = allSteps.reduce((sum, s) => sum + (s.retryCount ?? 0), 0);
8451
+ const stepsWithRetry = allSteps.filter((s) => s.retryCount && s.retryCount > 0);
8452
+ lines.push(`| \u30BB\u30EC\u30AF\u30BF\u89E3\u6C7A\u5BFE\u8C61\u30B9\u30C6\u30C3\u30D7 | ${stepsWithSelector.length} |`);
8453
+ lines.push(`| \u30EA\u30C8\u30E9\u30A4\u767A\u751F\u30B9\u30C6\u30C3\u30D7 | ${stepsWithRetry.length} |`);
8454
+ lines.push(`| \u5408\u8A08\u30EA\u30C8\u30E9\u30A4\u56DE\u6570 | ${totalRetries} |`);
8455
+ }
8456
+ lines.push("");
8457
+ if (totalResolveAttempts > 0) {
8458
+ const deterministicRate = deterministicHits + deterministicMisses > 0 ? Math.round(deterministicHits / (deterministicHits + deterministicMisses) * 100) : 0;
8459
+ lines.push(`**\u6C7A\u5B9A\u8AD6\u7684\u89E3\u6C7A\u7387**: ${deterministicRate}% \u2014 `);
8460
+ if (deterministicRate < 50) {
8461
+ lines.push("\u4F4E\u3044\u3002`deterministic-resolver.ts` \u306E\u30D1\u30BF\u30FC\u30F3\u30DE\u30C3\u30C1\u30F3\u30B0\u7CBE\u5EA6\u6539\u5584\u306E\u4F59\u5730\u3042\u308A\u3002");
8462
+ } else if (deterministicRate < 80) {
8463
+ lines.push("\u4E2D\u7A0B\u5EA6\u3002\u983B\u51FA\u306E\u30DE\u30C3\u30C1\u5931\u6557\u30D1\u30BF\u30FC\u30F3\u3092\u5206\u6790\u3057\u8FFD\u52A0\u3059\u308B\u3068 AI \u547C\u3073\u51FA\u3057\u3092\u524A\u6E1B\u3067\u304D\u308B\u3002");
8464
+ } else {
8465
+ lines.push("\u9AD8\u3044\u3002\u6C7A\u5B9A\u8AD6\u7684\u89E3\u6C7A\u304C\u6709\u52B9\u306B\u6A5F\u80FD\u3057\u3066\u3044\u308B\u3002");
8466
+ }
8467
+ lines.push("");
8468
+ }
8469
+ }
8470
+ return lines;
8471
+ }
8472
+ function formatRetryDistribution(allSteps) {
8473
+ const lines = [];
8474
+ lines.push("### Retry Distribution");
8475
+ lines.push("");
8476
+ const retryDistribution = /* @__PURE__ */ new Map();
8477
+ for (const step of allSteps) {
8478
+ const count = step.retryCount ?? 0;
8479
+ retryDistribution.set(count, (retryDistribution.get(count) ?? 0) + 1);
8480
+ }
8481
+ if (retryDistribution.size > 0) {
8482
+ lines.push("| \u30EA\u30C8\u30E9\u30A4\u56DE\u6570 | \u30B9\u30C6\u30C3\u30D7\u6570 |");
8483
+ lines.push("|-------------|-----------|");
8484
+ for (const [count, steps] of [...retryDistribution.entries()].sort((a, b) => a[0] - b[0])) {
8485
+ lines.push(`| ${count} | ${steps} |`);
8486
+ }
8487
+ lines.push("");
8488
+ }
8489
+ return lines;
8490
+ }
8491
+ function getSystemImprovementHint(category) {
8492
+ switch (category) {
8493
+ case "element_not_found":
8494
+ return "\u6C7A\u5B9A\u8AD6\u7684\u89E3\u6C7A\u306E\u30D1\u30BF\u30FC\u30F3\u8FFD\u52A0\u3001\u30B9\u30CA\u30C3\u30D7\u30B7\u30E7\u30C3\u30C8\u30D5\u30A3\u30EB\u30BF\u306E\u898B\u76F4\u3057";
8495
+ case "element_stale":
8496
+ return "\u30AD\u30E3\u30C3\u30B7\u30E5\u7121\u52B9\u5316\u30ED\u30B8\u30C3\u30AF\u306E\u6539\u5584\u3001DOM\u5B89\u5B9A\u5316\u5F85\u6A5F\u306E\u8ABF\u6574";
8497
+ case "page_structure_changed":
8498
+ return "\u30B9\u30CA\u30C3\u30D7\u30B7\u30E7\u30C3\u30C8\u5DEE\u5206\u691C\u77E5\u306E\u611F\u5EA6\u8ABF\u6574\u3001\u52D5\u7684\u30B3\u30F3\u30C6\u30F3\u30C4\u5BFE\u5FDC";
8499
+ case "navigation_timeout":
8500
+ return "\u30CA\u30D3\u30B2\u30FC\u30B7\u30E7\u30F3\u5F85\u6A5F\u306E\u6BB5\u968E\u7684\u30BF\u30A4\u30E0\u30A2\u30A6\u30C8\u8ABF\u6574\u3001SPA\u691C\u77E5\u306E\u6539\u5584";
8501
+ case "action_failed":
8502
+ return "\u30A2\u30AF\u30B7\u30E7\u30F3\u30D0\u30EA\u30C7\u30FC\u30B7\u30E7\u30F3\u306E\u7DB2\u7F85\u6027\u5411\u4E0A\u3001role\u4E92\u63DB\u30DE\u30C3\u30D4\u30F3\u30B0\u306E\u62E1\u5145";
8503
+ case "script_syntax_error":
8504
+ return "AI \u751F\u6210\u30B9\u30AF\u30EA\u30D7\u30C8\u306E\u69CB\u6587\u4FEE\u5FA9\u30ED\u30B8\u30C3\u30AF (normalizeEvalScript) \u306E\u6539\u5584";
8505
+ case "unknown":
8506
+ return "\u30A8\u30E9\u30FC\u5206\u985E\u30ED\u30B8\u30C3\u30AF\u3078\u306E\u65B0\u30AB\u30C6\u30B4\u30EA\u8FFD\u52A0\u3092\u691C\u8A0E";
8507
+ default:
8508
+ return "\u65B0\u3057\u3044\u30AB\u30C6\u30B4\u30EA \u2014 error-classifier.ts \u306B\u8FFD\u52A0\u3092\u691C\u8A0E";
8509
+ }
8510
+ }
8511
+ function formatFailureCategoryDistribution(failedSteps) {
8512
+ const lines = [];
8513
+ if (failedSteps.length === 0) return lines;
8514
+ lines.push("### Failure Category Distribution");
8515
+ lines.push("");
8516
+ const categoryCount = /* @__PURE__ */ new Map();
8517
+ for (const step of failedSteps) {
8518
+ const cat = step.failureCategory ?? "unclassified";
8519
+ categoryCount.set(cat, (categoryCount.get(cat) ?? 0) + 1);
8520
+ }
8521
+ lines.push("| \u30AB\u30C6\u30B4\u30EA | \u4EF6\u6570 | \u6539\u5584\u30D2\u30F3\u30C8 |");
8522
+ lines.push("|---------|------|-----------|");
8523
+ for (const [cat, count] of [...categoryCount.entries()].sort((a, b) => b[1] - a[1])) {
8524
+ const hint = getSystemImprovementHint(cat);
8525
+ lines.push(`| \`${cat}\` | ${count} | ${hint} |`);
8526
+ }
8527
+ lines.push("");
8528
+ return lines;
8529
+ }
8530
+ function analyzeRecoveryEffectiveness(entries, allSteps) {
8531
+ const results = [];
8532
+ const retrySteps = allSteps.filter((s) => s.retryCount && s.retryCount > 0);
8533
+ if (retrySteps.length > 0) {
8534
+ const retrySuccesses = retrySteps.filter((s) => s.status === "success").length;
8535
+ results.push({ name: "\u30B9\u30DE\u30FC\u30C8\u30EA\u30C8\u30E9\u30A4", total: retrySteps.length, success: retrySuccesses });
8536
+ }
8537
+ const scrollRecoveries = entries.filter((e) => e.event === "recovery_attempt");
8538
+ if (scrollRecoveries.length > 0) {
8539
+ const scrollStepOrdinals = new Set(scrollRecoveries.map((e) => e.step).filter((s) => s !== void 0));
8540
+ const scrollSuccesses = allSteps.filter(
8541
+ (s) => scrollStepOrdinals.has(s.ordinal) && s.status === "success"
8542
+ ).length;
8543
+ results.push({ name: "\u30B9\u30AF\u30ED\u30FC\u30EB\u56DE\u5FA9", total: scrollRecoveries.length, success: scrollSuccesses });
8544
+ }
8545
+ const visionFallbackStarts = entries.filter((e) => e.event === "vision_fallback_start").length;
8546
+ if (visionFallbackStarts > 0) {
8547
+ const visionSuccesses = entries.filter(
8548
+ (e) => e.event === "vision_fallback_result" && e.data && e.data.ref
8549
+ ).length;
8550
+ results.push({ name: "Vision Fallback", total: visionFallbackStarts, success: visionSuccesses });
8551
+ }
8552
+ const fbStarts = entries.filter((e) => e.event === "agent_fallback_start").length;
8553
+ if (fbStarts > 0) {
8554
+ const fbSuccesses = entries.filter(
8555
+ (e) => e.event === "agent_fallback_result" && e.data && e.data.success === true
8556
+ ).length;
8557
+ results.push({ name: "Agent Fallback", total: fbStarts, success: fbSuccesses });
8558
+ }
8559
+ const deterministicMisses = entries.filter((e) => e.event === "deterministic_resolve_miss");
8560
+ if (deterministicMisses.length > 0) {
8561
+ const missStepOrdinals = new Set(deterministicMisses.map((e) => e.step).filter((s) => s !== void 0));
8562
+ const aiRecoveries = allSteps.filter(
8563
+ (s) => missStepOrdinals.has(s.ordinal) && s.status === "success"
8564
+ ).length;
8565
+ results.push({ name: "AI \u30D5\u30A9\u30FC\u30EB\u30D0\u30C3\u30AF\uFF08\u6C7A\u5B9A\u8AD6\u7684\u5931\u6557\u5F8C\uFF09", total: deterministicMisses.length, success: aiRecoveries });
8566
+ }
8567
+ return results;
8568
+ }
8569
+ function formatRecoveryEffectiveness(entries, allSteps) {
8570
+ const lines = [];
8571
+ if (entries.length === 0) return lines;
8572
+ const recoveryResults = analyzeRecoveryEffectiveness(entries, allSteps);
8573
+ if (recoveryResults.length === 0) return lines;
8574
+ lines.push("### Recovery Mechanism Effectiveness");
8575
+ lines.push("");
8576
+ lines.push("| \u56DE\u5FA9\u6A5F\u69CB | \u767A\u52D5\u56DE\u6570 | \u6210\u529F | \u5931\u6557 | \u6210\u529F\u7387 |");
8577
+ lines.push("|---------|---------|------|------|--------|");
8578
+ for (const r of recoveryResults) {
8579
+ const rate = r.total > 0 ? Math.round(r.success / r.total * 100) : 0;
8580
+ lines.push(`| ${r.name} | ${r.total} | ${r.success} | ${r.total - r.success} | ${rate}% |`);
8581
+ }
8582
+ lines.push("");
8583
+ return lines;
8584
+ }
8585
+ function formatPerformanceBottlenecks(allSteps) {
8586
+ const lines = [];
8587
+ const slowSteps = [...allSteps].filter((s) => s.durationMs > 0).sort((a, b) => b.durationMs - a.durationMs).slice(0, 5);
8588
+ if (slowSteps.length > 0 && slowSteps[0].durationMs > 3e3) {
8589
+ lines.push("### Performance Bottlenecks");
8590
+ lines.push("");
8591
+ lines.push("| Step | \u6240\u8981\u6642\u9593 | \u30EA\u30C8\u30E9\u30A4 | \u72B6\u614B | \u8AAC\u660E |");
8592
+ lines.push("|------|---------|---------|------|------|");
8593
+ for (const step of slowSteps) {
8594
+ if (step.durationMs <= 3e3) break;
8595
+ const status = step.status === "failed" ? ":x:" : ":white_check_mark:";
8596
+ lines.push(
8597
+ `| #${step.ordinal} | ${(step.durationMs / 1e3).toFixed(1)}s | ${step.retryCount ?? 0} | ${status} | ${step.description} |`
8588
8598
  );
8589
8599
  }
8600
+ lines.push("");
8590
8601
  }
8591
- return { system, userPrompt: parts.join("\n") };
8602
+ return lines;
8592
8603
  }
8593
- function pruneSelectorHints(selector) {
8594
- const pruned = {};
8595
- for (const [key, value] of Object.entries(selector)) {
8596
- if (value === null || value === void 0 || value === "" || value === "unknown" || value === ":") continue;
8597
- pruned[key] = value;
8604
+ function analyzeAiSelectorQuality(entries) {
8605
+ const issues = [];
8606
+ const aiResponses = entries.filter((e) => e.event === "ai_selector_response");
8607
+ const stepAiCounts = /* @__PURE__ */ new Map();
8608
+ for (const e of aiResponses) {
8609
+ if (e.step !== void 0) {
8610
+ stepAiCounts.set(e.step, (stepAiCounts.get(e.step) ?? 0) + 1);
8611
+ }
8598
8612
  }
8599
- return pruned;
8600
- }
8601
-
8602
- // src/i18n/prompts/ja/selector.ts
8603
- function buildSelectorMessages2(snapshot, selector, stepDescription, url, contextMarkdown, retryContext, workingMemorySummary) {
8604
- const system = [
8605
- "\u3042\u306A\u305F\u306F\u30D6\u30E9\u30A6\u30B6\u81EA\u52D5\u64CD\u4F5C\u306E\u30BB\u30EC\u30AF\u30BF\u30EA\u30BE\u30EB\u30D0\u30FC\u3067\u3059\u3002",
8606
- "\u30B9\u30C6\u30C3\u30D7\u306E\u8AAC\u660E\u306B\u57FA\u3065\u3044\u3066\u3001\u30A2\u30AF\u30BB\u30B7\u30D3\u30EA\u30C6\u30A3\u30B9\u30CA\u30C3\u30D7\u30B7\u30E7\u30C3\u30C8\u5185\u306E\u64CD\u4F5C\u5BFE\u8C61\u8981\u7D20\u3092\u7279\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\u3002",
8607
- "",
8608
- "## \u30DE\u30C3\u30C1\u30F3\u30B0\u306E\u6307\u91DD",
8609
- "1. \u30B9\u30C6\u30C3\u30D7\u306E\u8AAC\u660E\u304B\u3089\u64CD\u4F5C\u5BFE\u8C61\u306E\u8981\u7D20\u306E\u7A2E\u985E\uFF08\u30DC\u30BF\u30F3\u3001\u5165\u529B\u30D5\u30A3\u30FC\u30EB\u30C9\u3001\u30EA\u30F3\u30AF\u7B49\uFF09\u3092\u63A8\u5B9A\u3059\u308B",
8610
- "2. \u30B9\u30CA\u30C3\u30D7\u30B7\u30E7\u30C3\u30C8\u5185\u3067\u3001\u30B9\u30C6\u30C3\u30D7\u306E\u8AAC\u660E\u3068\u610F\u5473\u7684\u306B\u6700\u3082\u4E00\u81F4\u3059\u308B\u8981\u7D20\u3092\u63A2\u3059",
8611
- "3. \u5468\u8FBA\u306E\u30C6\u30AD\u30B9\u30C8\u3001\u30E9\u30D9\u30EB\u3001\u30D7\u30EC\u30FC\u30B9\u30DB\u30EB\u30C0\u30FC\u3001role \u3082\u624B\u304C\u304B\u308A\u306B\u3059\u308B",
8612
- "4. \u5B8C\u5168\u4E00\u81F4\u304C\u306A\u304F\u3066\u3082\u6700\u3082\u53EF\u80FD\u6027\u306E\u9AD8\u3044\u8981\u7D20\u306E ref \u3092\u8FD4\u3059",
8613
- "5. \u8A72\u5F53\u3059\u308B\u8981\u7D20\u304C\u30B9\u30CA\u30C3\u30D7\u30B7\u30E7\u30C3\u30C8\u5185\u306B\u672C\u5F53\u306B\u5B58\u5728\u3057\u306A\u3044\u5834\u5408\u306E\u307F\u7A7A\u6587\u5B57\u3092\u8FD4\u3059"
8614
- ].join("\n");
8615
- const parts = [
8616
- "## \u30B9\u30C6\u30C3\u30D7\u306E\u8AAC\u660E\uFF08\u6700\u91CD\u8981\uFF09",
8617
- stepDescription,
8618
- "",
8619
- "## \u30BB\u30EC\u30AF\u30BF\u306E\u30D2\u30F3\u30C8\uFF08\u53C2\u8003\u60C5\u5831\uFF09",
8620
- "\u4EE5\u4E0B\u306F\u8981\u7D20\u3092\u7279\u5B9A\u3059\u308B\u305F\u3081\u306E\u53C2\u8003\u60C5\u5831\u3067\u3059\u3002\u5B8C\u5168\u4E00\u81F4\u3057\u306A\u3044\u5834\u5408\u3067\u3082\u3001\u30B9\u30C6\u30C3\u30D7\u306E\u8AAC\u660E\u304B\u3089\u610F\u5473\u7684\u306B\u6700\u3082\u8FD1\u3044\u8981\u7D20\u3092\u9078\u3093\u3067\u304F\u3060\u3055\u3044\u3002",
8621
- JSON.stringify(pruneSelectorHints2(selector)),
8622
- "",
8623
- "\u6CE8\u610F:",
8624
- '- tagName \u304C "unknown" \u3084 ":" \u306E\u5834\u5408\u306F\u30BF\u30B0\u540D\u60C5\u5831\u304C\u3042\u308A\u307E\u305B\u3093',
8625
- "- ariaLabel \u306F\u30B9\u30C6\u30C3\u30D7\u8AAC\u660E\u304B\u3089\u81EA\u52D5\u751F\u6210\u3055\u308C\u305F\u3082\u306E\u3067\u3042\u308A\u3001\u5B9F\u969B\u306E aria-label \u5C5E\u6027\u3068\u4E00\u81F4\u3057\u306A\u3044\u3053\u3068\u304C\u3042\u308A\u307E\u3059",
8626
- "- \u30BB\u30EC\u30AF\u30BF\u306E\u5B8C\u5168\u4E00\u81F4\u3088\u308A\u3082\u30B9\u30C6\u30C3\u30D7\u306E\u8AAC\u660E\u3068\u306E\u610F\u5473\u7684\u4E00\u81F4\u3092\u512A\u5148\u3057\u3066\u304F\u3060\u3055\u3044",
8627
- "",
8628
- "## \u73FE\u5728\u306EURL",
8629
- url
8630
- ];
8631
- if (workingMemorySummary) {
8632
- parts.push("", "## \u5B9F\u884C\u30B3\u30F3\u30C6\u30AD\u30B9\u30C8", workingMemorySummary);
8613
+ for (const [step, count] of stepAiCounts) {
8614
+ if (count > 1) {
8615
+ issues.push({
8616
+ step,
8617
+ description: `AI \u304C ${count} \u56DE\u547C\u3073\u51FA\u3055\u308C\u305F\uFF08\u524D\u56DE\u5FDC\u7B54\u304C\u4E0D\u6B63\u78BA\uFF09\u3002\u30D7\u30ED\u30F3\u30D7\u30C8\u306E\u6539\u5584\u4F59\u5730\u3042\u308A`
8618
+ });
8619
+ }
8633
8620
  }
8634
- parts.push(
8635
- "",
8636
- "## \u30A2\u30AF\u30BB\u30B7\u30D3\u30EA\u30C6\u30A3\u30B9\u30CA\u30C3\u30D7\u30B7\u30E7\u30C3\u30C8",
8637
- snapshot
8621
+ const unchangedRetries = entries.filter(
8622
+ (e) => e.event === "snapshot_unchanged" && e.data && !e.data.skippingAI
8638
8623
  );
8639
- const includeContext = contextMarkdown && !(retryContext && retryContext.attempt > 0);
8640
- if (includeContext) {
8641
- parts.push("", "## \u88DC\u8DB3\u30B3\u30F3\u30C6\u30AD\u30B9\u30C8", contextMarkdown);
8642
- }
8643
- if (retryContext && retryContext.attempt > 0) {
8644
- parts.push(
8645
- "",
8646
- "## \u56DE\u5FA9\u30B3\u30F3\u30C6\u30AD\u30B9\u30C8\uFF08\u8A66\u884C" + (retryContext.attempt + 1) + "\u56DE\u76EE\uFF09"
8647
- );
8648
- if (retryContext.failureHints) {
8649
- parts.push(`\u30D1\u30BF\u30FC\u30F3: ${retryContext.failureHints}`);
8650
- }
8651
- if (retryContext.failureHistory.length > 0) {
8652
- const recent = retryContext.failureHistory.slice(-2);
8653
- parts.push(`\u76F4\u8FD1\u306E\u5931\u6557: ${recent.join("; ")}`);
8654
- }
8655
- if (retryContext.previousAiResponse) {
8656
- try {
8657
- const parsed = JSON.parse(retryContext.previousAiResponse);
8658
- if (parsed.reasoning) {
8659
- parts.push(`\u524D\u56DE\u306E\u63A8\u8AD6: "${parsed.reasoning}"`);
8660
- }
8661
- } catch {
8662
- parts.push(`\u524D\u56DE\u306E\u5FDC\u7B54: ${retryContext.previousAiResponse.slice(0, 200)}`);
8624
+ if (unchangedRetries.length > 0) {
8625
+ for (const e of unchangedRetries) {
8626
+ if (e.step !== void 0) {
8627
+ issues.push({
8628
+ step: e.step,
8629
+ description: "\u30B9\u30CA\u30C3\u30D7\u30B7\u30E7\u30C3\u30C8\u672A\u5909\u5316\u306A\u306E\u306B AI \u304C\u518D\u547C\u3073\u51FA\u3057\u3055\u308C\u305F\u3002\u30B9\u30AD\u30C3\u30D7\u30ED\u30B8\u30C3\u30AF\u306E\u78BA\u8A8D\u304C\u5FC5\u8981"
8630
+ });
8663
8631
  }
8664
8632
  }
8665
- if (!retryContext.snapshotChanged) {
8666
- parts.push(
8667
- "\u30B9\u30CA\u30C3\u30D7\u30B7\u30E7\u30C3\u30C8\u672A\u5909\u5316 \u2014 \u90E8\u5206\u4E00\u81F4\u3001role\u30D9\u30FC\u30B9\u306E\u30DE\u30C3\u30C1\u30F3\u30B0\u3001\u8FD1\u63A5\u8981\u7D20\u304B\u3089\u306E\u63A8\u5B9A\u3092\u8A66\u307F\u3066\u304F\u3060\u3055\u3044\u3002"
8668
- );
8669
- }
8670
8633
  }
8671
- return { system, userPrompt: parts.join("\n") };
8672
- }
8673
- function pruneSelectorHints2(selector) {
8674
- const pruned = {};
8675
- for (const [key, value] of Object.entries(selector)) {
8676
- if (value === null || value === void 0 || value === "" || value === "unknown" || value === ":") continue;
8677
- pruned[key] = value;
8634
+ const emptyRefResponses = entries.filter(
8635
+ (e) => e.event === "ai_selector_response" && e.data && typeof e.data.parsedResult === "object" && e.data.parsedResult !== null && e.data.parsedResult.ref === ""
8636
+ );
8637
+ if (emptyRefResponses.length > 0) {
8638
+ const steps = [...new Set(emptyRefResponses.map((e) => e.step).filter((s) => s !== void 0))];
8639
+ for (const step of steps) {
8640
+ issues.push({
8641
+ step,
8642
+ description: "AI \u304C\u7A7A ref \u3092\u8FD4\u3057\u305F\uFF08\u8981\u7D20\u4E0D\u5728\u5224\u5B9A\uFF09\u3002\u30B9\u30CA\u30C3\u30D7\u30B7\u30E7\u30C3\u30C8\u30D5\u30A3\u30EB\u30BF\u304C\u8981\u7D20\u3092\u9664\u53BB\u3057\u3066\u3044\u306A\u3044\u304B\u78BA\u8A8D"
8643
+ });
8644
+ }
8678
8645
  }
8679
- return pruned;
8680
- }
8681
-
8682
- // src/i18n/prompts/en/goal-agent.ts
8683
- function buildFallbackMessages(snapshot, step, failureHistory, url, contextMarkdown) {
8684
- const system = [
8685
- "You are a problem-solving agent for browser automation.",
8686
- "Normal selector resolution has failed at all phases. Analyze the entire page and find an alternative operation path.",
8687
- "",
8688
- "## Alternative Path Search Guidelines",
8689
- "1. Check if the target element is hidden inside a hamburger menu, dropdown, or accordion",
8690
- "2. Check if a modal or overlay is covering the target element",
8691
- "3. Check if the page is in an unexpected state (not logged in, error state, loading)",
8692
- "4. Check if the target element is above the current scroll position",
8693
- "5. Check if a semantically equivalent alternative element exists (e.g., a button instead of a link)",
8694
- "",
8695
- "## Alternative Strategy Selection Criteria",
8696
- "- direct_ref: Try a different ref directly (when a semantically equivalent element is found)",
8697
- "- scroll_up_and_retry: When the target element might be above the current view",
8698
- "- expand_collapsed: When a collapsed section/menu needs to be expanded (prerequisiteRef required)",
8699
- "- dismiss_overlay: When a modal/overlay needs to be closed (prerequisiteRef required)",
8700
- "- tab_navigation: When the element can be reached via Tab key focus navigation",
8701
- "- not_found: When the target element truly does not exist on the page"
8702
- ].join("\n");
8703
- const parts = [
8704
- "## Step Being Attempted",
8705
- `Description: ${step.description}`,
8706
- `Action: ${step.action.type}`,
8707
- `Selector hints: ${JSON.stringify(step.action.selector, null, 2)}`,
8708
- `URL: ${url}`,
8709
- "",
8710
- "## Failure History",
8711
- ...failureHistory.map((f, i) => ` ${i + 1}. ${f}`),
8712
- "",
8713
- "## Current Page Snapshot (Filtered)",
8714
- snapshot
8715
- ];
8716
- if (contextMarkdown) {
8717
- parts.push("", "## Supplementary Context", contextMarkdown);
8646
+ return issues;
8647
+ }
8648
+ function formatAiSelectorQualityIssues(entries) {
8649
+ const lines = [];
8650
+ const aiQualityIssues = analyzeAiSelectorQuality(entries);
8651
+ if (aiQualityIssues.length === 0) return lines;
8652
+ lines.push("### AI Selector Resolution Issues");
8653
+ lines.push("");
8654
+ lines.push("> AI \u30BB\u30EC\u30AF\u30BF\u89E3\u6C7A\u3067\u554F\u984C\u304C\u691C\u51FA\u3055\u308C\u305F\u30B1\u30FC\u30B9\u3002\u30D7\u30ED\u30F3\u30D7\u30C8\u6539\u5584\u306E\u6750\u6599\u3002");
8655
+ lines.push("");
8656
+ for (const issue of aiQualityIssues.slice(0, 5)) {
8657
+ lines.push(`- **Step #${issue.step}**: ${issue.description}`);
8658
+ }
8659
+ lines.push("");
8660
+ return lines;
8661
+ }
8662
+ function formatSelectorResolutionStatsFromTelemetry(stats, allSteps) {
8663
+ const lines = [];
8664
+ const counts = stats.resolveMethodCounts;
8665
+ const totalResolutions = Object.values(counts).reduce((sum, n) => sum + n, 0);
8666
+ if (totalResolutions === 0 && stats.stepsWithRetries === 0) return lines;
8667
+ lines.push("### Selector Resolution Statistics");
8668
+ lines.push("");
8669
+ lines.push("| \u89E3\u6C7A\u65B9\u6CD5 | \u4EF6\u6570 | \u5272\u5408 |");
8670
+ lines.push("|---------|------|------|");
8671
+ for (const [method, n] of Object.entries(counts).sort((a, b) => b[1] - a[1])) {
8672
+ const pct = totalResolutions > 0 ? Math.round(n / totalResolutions * 100) : 0;
8673
+ lines.push(`| ${method} | ${n} | ${pct}% |`);
8674
+ }
8675
+ lines.push("");
8676
+ if (stats.stepsWithRetries > 0) {
8677
+ lines.push(`**\u30EA\u30C8\u30E9\u30A4\u767A\u751F\u30B9\u30C6\u30C3\u30D7**: ${stats.stepsWithRetries} / ${allSteps.length} (\u5408\u8A08\u30EA\u30C8\u30E9\u30A4: ${stats.totalRetryCount})`);
8678
+ lines.push("");
8679
+ }
8680
+ const deterministicCount = counts["deterministic"] ?? 0;
8681
+ const aiCount = counts["ai"] ?? 0;
8682
+ if (deterministicCount + aiCount > 0) {
8683
+ const rate = Math.round(deterministicCount / (deterministicCount + aiCount) * 100);
8684
+ lines.push(`**\u6C7A\u5B9A\u8AD6\u7684\u89E3\u6C7A\u7387**: ${rate}% \u2014 `);
8685
+ if (rate < 50) {
8686
+ lines.push("\u4F4E\u3044\u3002`deterministic-resolver.ts` \u306E\u30D1\u30BF\u30FC\u30F3\u30DE\u30C3\u30C1\u30F3\u30B0\u7CBE\u5EA6\u6539\u5584\u306E\u4F59\u5730\u3042\u308A\u3002");
8687
+ } else if (rate < 80) {
8688
+ lines.push("\u4E2D\u7A0B\u5EA6\u3002\u983B\u51FA\u306E\u30DE\u30C3\u30C1\u5931\u6557\u30D1\u30BF\u30FC\u30F3\u3092\u5206\u6790\u3057\u8FFD\u52A0\u3059\u308B\u3068 AI \u547C\u3073\u51FA\u3057\u3092\u524A\u6E1B\u3067\u304D\u308B\u3002");
8689
+ } else {
8690
+ lines.push("\u9AD8\u3044\u3002\u6C7A\u5B9A\u8AD6\u7684\u89E3\u6C7A\u304C\u6709\u52B9\u306B\u6A5F\u80FD\u3057\u3066\u3044\u308B\u3002");
8691
+ }
8692
+ lines.push("");
8718
8693
  }
8719
- return { system, userPrompt: parts.join("\n") };
8694
+ return lines;
8720
8695
  }
8721
-
8722
- // src/i18n/prompts/ja/goal-agent.ts
8723
- function buildFallbackMessages2(snapshot, step, failureHistory, url, contextMarkdown) {
8724
- const system = [
8725
- "\u3042\u306A\u305F\u306F\u30D6\u30E9\u30A6\u30B6\u81EA\u52D5\u64CD\u4F5C\u306E\u554F\u984C\u89E3\u6C7A\u30A8\u30FC\u30B8\u30A7\u30F3\u30C8\u3067\u3059\u3002",
8726
- "\u901A\u5E38\u306E\u30BB\u30EC\u30AF\u30BF\u89E3\u6C7A\u304C\u5168\u30D5\u30A7\u30FC\u30BA\u5931\u6557\u3057\u307E\u3057\u305F\u3002\u30DA\u30FC\u30B8\u5168\u4F53\u3092\u5206\u6790\u3057\u3066\u4EE3\u66FF\u64CD\u4F5C\u30D1\u30B9\u3092\u898B\u3064\u3051\u3066\u304F\u3060\u3055\u3044\u3002",
8727
- "",
8728
- "## \u4EE3\u66FF\u30D1\u30B9\u63A2\u7D22\u306E\u6307\u91DD",
8729
- "1. \u30CF\u30F3\u30D0\u30FC\u30AC\u30FC\u30E1\u30CB\u30E5\u30FC\u3001\u30C9\u30ED\u30C3\u30D7\u30C0\u30A6\u30F3\u3001\u30A2\u30B3\u30FC\u30C7\u30A3\u30AA\u30F3\u306E\u4E2D\u306B\u5BFE\u8C61\u8981\u7D20\u304C\u96A0\u308C\u3066\u3044\u306A\u3044\u304B\u78BA\u8A8D",
8730
- "2. \u30E2\u30FC\u30C0\u30EB\u3084\u30AA\u30FC\u30D0\u30FC\u30EC\u30A4\u304C\u524D\u9762\u306B\u3042\u3063\u3066\u5BFE\u8C61\u8981\u7D20\u3092\u96A0\u3057\u3066\u3044\u306A\u3044\u304B\u78BA\u8A8D",
8731
- "3. \u30DA\u30FC\u30B8\u304C\u60F3\u5B9A\u3068\u7570\u306A\u308B\u72B6\u614B\uFF08\u672A\u30ED\u30B0\u30A4\u30F3\u3001\u30A8\u30E9\u30FC\u72B6\u614B\u3001\u30ED\u30FC\u30C7\u30A3\u30F3\u30B0\u4E2D\uFF09\u3067\u306A\u3044\u304B\u78BA\u8A8D",
8732
- "4. \u5BFE\u8C61\u8981\u7D20\u304C\u4E0A\u65B9\u306B\u3042\u3063\u3066\u30B9\u30AF\u30ED\u30FC\u30EB\u3067\u96A0\u308C\u3066\u3044\u306A\u3044\u304B\u78BA\u8A8D",
8733
- "5. \u610F\u5473\u7684\u306B\u540C\u7B49\u306A\u5225\u306E\u8981\u7D20\uFF08\u30EA\u30F3\u30AF\u3067\u306F\u306A\u304F\u30DC\u30BF\u30F3\u3001\u7B49\uFF09\u304C\u5B58\u5728\u3057\u306A\u3044\u304B\u78BA\u8A8D",
8734
- "",
8735
- "## \u4EE3\u66FF\u6226\u7565\u306E\u9078\u629E\u57FA\u6E96",
8736
- "- direct_ref: \u5225\u306E ref \u3092\u76F4\u63A5\u8A66\u3059\uFF08\u610F\u5473\u7684\u306B\u540C\u7B49\u306A\u8981\u7D20\u304C\u898B\u3064\u304B\u3063\u305F\u5834\u5408\uFF09",
8737
- "- scroll_up_and_retry: \u5BFE\u8C61\u8981\u7D20\u304C\u4E0A\u65B9\u306B\u3042\u308B\u53EF\u80FD\u6027\u304C\u3042\u308B\u5834\u5408",
8738
- "- expand_collapsed: \u6298\u308A\u7573\u307E\u308C\u305F\u30BB\u30AF\u30B7\u30E7\u30F3/\u30E1\u30CB\u30E5\u30FC\u3092\u5C55\u958B\u3059\u308B\u5FC5\u8981\u304C\u3042\u308B\u5834\u5408\uFF08prerequisiteRef \u5FC5\u9808\uFF09",
8739
- "- dismiss_overlay: \u30E2\u30FC\u30C0\u30EB/\u30AA\u30FC\u30D0\u30FC\u30EC\u30A4\u3092\u9589\u3058\u308B\u5FC5\u8981\u304C\u3042\u308B\u5834\u5408\uFF08prerequisiteRef \u5FC5\u9808\uFF09",
8740
- "- tab_navigation: Tab \u30AD\u30FC\u3067\u30D5\u30A9\u30FC\u30AB\u30B9\u79FB\u52D5\u3057\u3066\u5230\u9054\u3067\u304D\u308B\u5834\u5408",
8741
- "- not_found: \u672C\u5F53\u306B\u30DA\u30FC\u30B8\u4E0A\u306B\u5BFE\u8C61\u8981\u7D20\u304C\u5B58\u5728\u3057\u306A\u3044\u5834\u5408"
8742
- ].join("\n");
8743
- const parts = [
8744
- "## \u9054\u6210\u3057\u3088\u3046\u3068\u3057\u3066\u3044\u305F\u30B9\u30C6\u30C3\u30D7",
8745
- `\u8AAC\u660E: ${step.description}`,
8746
- `\u30A2\u30AF\u30B7\u30E7\u30F3: ${step.action.type}`,
8747
- `\u30BB\u30EC\u30AF\u30BF\u30D2\u30F3\u30C8: ${JSON.stringify(step.action.selector, null, 2)}`,
8748
- `URL: ${url}`,
8749
- "",
8750
- "## \u3053\u308C\u307E\u3067\u306E\u5931\u6557\u5C65\u6B74",
8751
- ...failureHistory.map((f, i) => ` ${i + 1}. ${f}`),
8752
- "",
8753
- "## \u73FE\u5728\u306E\u30DA\u30FC\u30B8\u30B9\u30CA\u30C3\u30D7\u30B7\u30E7\u30C3\u30C8\uFF08\u30D5\u30A3\u30EB\u30BF\u6E08\u307F\uFF09",
8754
- snapshot
8755
- ];
8756
- if (contextMarkdown) {
8757
- parts.push("", "## \u88DC\u8DB3\u30B3\u30F3\u30C6\u30AD\u30B9\u30C8", contextMarkdown);
8696
+ function formatRecoveryEffectivenessFromTelemetry(stats, allSteps) {
8697
+ const lines = [];
8698
+ const rows = [];
8699
+ const retrySteps = allSteps.filter((s) => s.retryCount && s.retryCount > 0);
8700
+ if (retrySteps.length > 0) {
8701
+ const retrySuccesses = retrySteps.filter((s) => s.status === "success").length;
8702
+ rows.push({ name: "\u30B9\u30DE\u30FC\u30C8\u30EA\u30C8\u30E9\u30A4", total: retrySteps.length, success: retrySuccesses });
8758
8703
  }
8759
- return { system, userPrompt: parts.join("\n") };
8760
- }
8761
-
8762
- // src/i18n/prompts/en/vision.ts
8763
- function buildVisionMessages(annotations, selector, stepDescription, url, failureHistory) {
8764
- const system = [
8765
- "You are a visual selector resolver for browser automation.",
8766
- "The text-based accessibility tree could not find the element.",
8767
- "Analyze the screenshot visually to identify the target element.",
8768
- "",
8769
- "## How to Read the Screenshot",
8770
- "- Each interactive element has a red border and number label",
8771
- "- Number labels are displayed at the top-left of each element",
8772
- "- Each number corresponds to the number field in the annotation list below",
8773
- "",
8774
- "## Matching Guidelines",
8775
- "1. Infer the type of target element (button, input field, link, etc.) from the step description",
8776
- "2. Find the element in the screenshot that visually best matches",
8777
- "3. Use element text, position, and appearance as clues",
8778
- "4. Also reference the role and name from the annotation list",
8779
- "5. Target elements not in the A11y tree (canvas, Shadow DOM, iframe, etc.) are also in scope",
8780
- "6. Return empty string if confidence is low (below 0.5)"
8781
- ].join("\n");
8782
- const annotationList = annotations.map((a) => {
8783
- const nameStr = a.name ? ` "${a.name}"` : "";
8784
- return ` #${a.number} ref=${a.ref} ${a.role}${nameStr} @(${a.box.x},${a.box.y})`;
8785
- }).join("\n");
8786
- const selectorHints = pruneSelectorHints3(selector);
8787
- const parts = [
8788
- "## Step Description (Most Important)",
8789
- stepDescription,
8790
- "",
8791
- "## Selector Hints (Reference)",
8792
- JSON.stringify(selectorHints),
8793
- "",
8794
- "## Current URL",
8795
- url,
8796
- "",
8797
- "## Annotation List (Corresponds to Numbers on Screenshot)",
8798
- annotationList
8799
- ];
8800
- if (failureHistory.length > 0) {
8801
- const recent = failureHistory.slice(-3);
8802
- parts.push(
8803
- "",
8804
- "## Text-based Resolution Failure History (Recent 3)",
8805
- ...recent.map((f, i) => ` ${i + 1}. ${f}`)
8806
- );
8704
+ if (stats.visionFallbackAttempts > 0) {
8705
+ rows.push({
8706
+ name: "Vision Fallback",
8707
+ total: stats.visionFallbackAttempts,
8708
+ success: stats.visionFallbackSuccesses
8709
+ });
8807
8710
  }
8808
- return { system, userTextContent: parts.join("\n") };
8809
- }
8810
- function pruneSelectorHints3(selector) {
8811
- const pruned = {};
8812
- for (const [key, value] of Object.entries(selector)) {
8813
- if (value === null || value === void 0 || value === "" || value === "unknown" || value === ":") continue;
8814
- pruned[key] = value;
8711
+ if (stats.agentFallbackAttempts > 0) {
8712
+ rows.push({
8713
+ name: "Agent Fallback",
8714
+ total: stats.agentFallbackAttempts,
8715
+ success: stats.agentFallbackSuccesses
8716
+ });
8815
8717
  }
8816
- return pruned;
8817
- }
8818
-
8819
- // src/i18n/prompts/ja/vision.ts
8820
- function buildVisionMessages2(annotations, selector, stepDescription, url, failureHistory) {
8821
- const system = [
8822
- "\u3042\u306A\u305F\u306F\u30D6\u30E9\u30A6\u30B6\u81EA\u52D5\u64CD\u4F5C\u306E\u30D3\u30B8\u30E5\u30A2\u30EB\u30BB\u30EC\u30AF\u30BF\u30EA\u30BE\u30EB\u30D0\u30FC\u3067\u3059\u3002",
8823
- "\u30C6\u30AD\u30B9\u30C8\u30D9\u30FC\u30B9\u306E\u30A2\u30AF\u30BB\u30B7\u30D3\u30EA\u30C6\u30A3\u30C4\u30EA\u30FC\u3067\u306F\u8981\u7D20\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3067\u3057\u305F\u3002",
8824
- "\u30B9\u30AF\u30EA\u30FC\u30F3\u30B7\u30E7\u30C3\u30C8\u3092\u8996\u899A\u7684\u306B\u5206\u6790\u3057\u3066\u3001\u64CD\u4F5C\u5BFE\u8C61\u306E\u8981\u7D20\u3092\u7279\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\u3002",
8825
- "",
8826
- "## \u30B9\u30AF\u30EA\u30FC\u30F3\u30B7\u30E7\u30C3\u30C8\u306E\u898B\u65B9",
8827
- "- \u5404\u30A4\u30F3\u30BF\u30E9\u30AF\u30C6\u30A3\u30D6\u8981\u7D20\u306B\u8D64\u3044\u67A0\u7DDA\u3068\u756A\u53F7\u30E9\u30D9\u30EB\u304C\u8868\u793A\u3055\u308C\u3066\u3044\u307E\u3059",
8828
- "- \u756A\u53F7\u30E9\u30D9\u30EB\u306F\u5404\u8981\u7D20\u306E\u5DE6\u4E0A\u306B\u8868\u793A\u3055\u308C\u307E\u3059",
8829
- "- \u5404\u756A\u53F7\u306F\u4E0B\u8A18\u306E\u30A2\u30CE\u30C6\u30FC\u30B7\u30E7\u30F3\u4E00\u89A7\u306E number \u30D5\u30A3\u30FC\u30EB\u30C9\u306B\u5BFE\u5FDC\u3057\u307E\u3059",
8830
- "",
8831
- "## \u30DE\u30C3\u30C1\u30F3\u30B0\u306E\u6307\u91DD",
8832
- "1. \u30B9\u30C6\u30C3\u30D7\u306E\u8AAC\u660E\u304B\u3089\u64CD\u4F5C\u5BFE\u8C61\u306E\u8981\u7D20\u306E\u7A2E\u985E\uFF08\u30DC\u30BF\u30F3\u3001\u5165\u529B\u30D5\u30A3\u30FC\u30EB\u30C9\u3001\u30EA\u30F3\u30AF\u7B49\uFF09\u3092\u63A8\u5B9A",
8833
- "2. \u30B9\u30AF\u30EA\u30FC\u30F3\u30B7\u30E7\u30C3\u30C8\u5185\u3067\u8996\u899A\u7684\u306B\u6700\u3082\u4E00\u81F4\u3059\u308B\u8981\u7D20\u3092\u63A2\u3059",
8834
- "3. \u8981\u7D20\u306E\u30C6\u30AD\u30B9\u30C8\u3001\u4F4D\u7F6E\u3001\u5916\u89B3\u3092\u624B\u304C\u304B\u308A\u306B\u3059\u308B",
8835
- "4. \u30A2\u30CE\u30C6\u30FC\u30B7\u30E7\u30F3\u4E00\u89A7\u306E role \u3068 name \u3082\u53C2\u8003\u306B\u3059\u308B",
8836
- "5. A11y \u30C4\u30EA\u30FC\u306B\u8868\u308C\u306A\u3044\u8981\u7D20\uFF08canvas\u3001Shadow DOM\u3001iframe \u5185\u7B49\uFF09\u3082\u5BFE\u8C61",
8837
- "6. \u78BA\u4FE1\u5EA6\u304C\u4F4E\u3044\u5834\u5408\uFF080.5\u672A\u6E80\uFF09\u306F\u7A7A\u6587\u5B57\u3092\u8FD4\u3059"
8838
- ].join("\n");
8839
- const annotationList = annotations.map((a) => {
8840
- const nameStr = a.name ? ` "${a.name}"` : "";
8841
- return ` #${a.number} ref=${a.ref} ${a.role}${nameStr} @(${a.box.x},${a.box.y})`;
8842
- }).join("\n");
8843
- const selectorHints = pruneSelectorHints4(selector);
8844
- const parts = [
8845
- "## \u30B9\u30C6\u30C3\u30D7\u306E\u8AAC\u660E\uFF08\u6700\u91CD\u8981\uFF09",
8846
- stepDescription,
8847
- "",
8848
- "## \u30BB\u30EC\u30AF\u30BF\u306E\u30D2\u30F3\u30C8\uFF08\u53C2\u8003\u60C5\u5831\uFF09",
8849
- JSON.stringify(selectorHints),
8850
- "",
8851
- "## \u73FE\u5728\u306EURL",
8852
- url,
8853
- "",
8854
- "## \u30A2\u30CE\u30C6\u30FC\u30B7\u30E7\u30F3\u4E00\u89A7\uFF08\u30B9\u30AF\u30EA\u30FC\u30F3\u30B7\u30E7\u30C3\u30C8\u4E0A\u306E\u756A\u53F7\u3068\u5BFE\u5FDC\uFF09",
8855
- annotationList
8856
- ];
8857
- if (failureHistory.length > 0) {
8858
- const recent = failureHistory.slice(-3);
8859
- parts.push(
8860
- "",
8861
- "## \u30C6\u30AD\u30B9\u30C8\u30D9\u30FC\u30B9\u89E3\u6C7A\u306E\u5931\u6557\u5C65\u6B74\uFF08\u76F4\u8FD13\u4EF6\uFF09",
8862
- ...recent.map((f, i) => ` ${i + 1}. ${f}`)
8718
+ if (rows.length === 0) return lines;
8719
+ lines.push("### Recovery Mechanism Effectiveness");
8720
+ lines.push("");
8721
+ lines.push("| \u56DE\u5FA9\u6A5F\u69CB | \u767A\u52D5\u56DE\u6570 | \u6210\u529F | \u5931\u6557 | \u6210\u529F\u7387 |");
8722
+ lines.push("|---------|---------|------|------|--------|");
8723
+ for (const r of rows) {
8724
+ const rate = r.total > 0 ? Math.round(r.success / r.total * 100) : 0;
8725
+ lines.push(`| ${r.name} | ${r.total} | ${r.success} | ${r.total - r.success} | ${rate}% |`);
8726
+ }
8727
+ lines.push("");
8728
+ return lines;
8729
+ }
8730
+ function formatAiSelectorQualityFromSteps(allSteps) {
8731
+ const lines = [];
8732
+ const issues = allSteps.filter(
8733
+ (s) => s.resolveMethod === "ai" && s.retryCount !== void 0 && s.retryCount > 1
8734
+ );
8735
+ if (issues.length === 0) return lines;
8736
+ lines.push("### AI Selector Resolution Issues");
8737
+ lines.push("");
8738
+ lines.push("> AI \u30BB\u30EC\u30AF\u30BF\u89E3\u6C7A\u3067\u30EA\u30C8\u30E9\u30A4\u304C\u8907\u6570\u56DE\u767A\u751F\u3057\u305F\u30B9\u30C6\u30C3\u30D7\u3002\u30D7\u30ED\u30F3\u30D7\u30C8\u6539\u5584\u306E\u6750\u6599\u3002");
8739
+ lines.push("");
8740
+ for (const step of issues.slice(0, 5)) {
8741
+ lines.push(`- **Step #${step.ordinal}**: ${step.description} \u2014 ${step.retryCount} retries`);
8742
+ }
8743
+ lines.push("");
8744
+ return lines;
8745
+ }
8746
+ var DEFAULT_RECENT_EVENT_TYPES = [
8747
+ "action",
8748
+ "snapshot",
8749
+ "selector_resolve",
8750
+ "selector_retry",
8751
+ "selector_cache_hit",
8752
+ "selector_cache_stale",
8753
+ "deterministic_resolve",
8754
+ "deterministic_resolve_miss",
8755
+ "vision_fallback_start",
8756
+ "vision_fallback_result",
8757
+ "agent_fallback_start",
8758
+ "agent_fallback_result",
8759
+ "recovery_attempt",
8760
+ "extract",
8761
+ "extract_result",
8762
+ "memory_operation"
8763
+ ];
8764
+ function formatDebugLogSections(entries, options = {}) {
8765
+ const lines = [];
8766
+ if (entries.length === 0) return lines;
8767
+ const maxErrors = options.maxErrors ?? 20;
8768
+ const maxRecent = options.maxRecent ?? 15;
8769
+ const recentEventTypes = options.recentEventTypes ?? DEFAULT_RECENT_EVENT_TYPES;
8770
+ if (options.showFailedStepEvents && options.failedOrdinals && options.failedOrdinals.size > 0) {
8771
+ const failedStepEntries = entries.filter(
8772
+ (e) => e.step !== void 0 && options.failedOrdinals.has(e.step)
8863
8773
  );
8774
+ if (failedStepEntries.length > 0) {
8775
+ lines.push("## Debug Log (Failed Step Events)");
8776
+ lines.push("```json");
8777
+ for (const entry of failedStepEntries.slice(-30)) {
8778
+ lines.push(JSON.stringify(entry));
8779
+ }
8780
+ lines.push("```");
8781
+ lines.push("");
8782
+ }
8864
8783
  }
8865
- return { system, userTextContent: parts.join("\n") };
8866
- }
8867
- function pruneSelectorHints4(selector) {
8868
- const pruned = {};
8869
- for (const [key, value] of Object.entries(selector)) {
8870
- if (value === null || value === void 0 || value === "" || value === "unknown" || value === ":") continue;
8871
- pruned[key] = value;
8872
- }
8873
- return pruned;
8874
- }
8875
-
8876
- // src/i18n/prompts/en/self-heal.ts
8877
- function getSuggestionSystemPrompt() {
8878
- return [
8879
- "You are an runbook debugger for browser automation.",
8880
- "Analyze the failed steps from the debug execution and generate fix suggestions for the runbook and context.",
8881
- "",
8882
- "## Fix Suggestion Guidelines",
8883
- "",
8884
- "For each failed step, provide suggestions from these two perspectives:",
8885
- "",
8886
- "### 1. runbookFix (Runbook YAML Fix)",
8887
- "- Selector changes (when element has moved/been renamed)",
8888
- "- Step addition/removal (when the navigation flow has changed)",
8889
- "- Action value updates (text or URL changes)",
8890
- "- riskLevel or requiresConfirmation adjustments",
8891
- `Example: "Step 3: Change selector ariaLabel from 'Submit' to 'Confirm and Submit'"`,
8892
- "",
8893
- "### 2. contextFix (Context Markdown Fix)",
8894
- "- Document page structure changes (new modals, menu structure changes, etc.)",
8895
- "- Add prerequisites (login state, permissions, environment conditions, etc.)",
8896
- "- Add selector resolution hints (dynamic ID naming patterns, etc.)",
8897
- `Example: "Add to context: 'Settings page has changed from tab UI to accordion UI'"`,
8898
- "",
8899
- "If context markdown is not provided, return empty string for contextFix.",
8900
- "",
8901
- "### severity Criteria",
8902
- "- error: Selector completely not found, fundamental page structure change",
8903
- "- warning: Succeeded with retry but unstable, element position or label slightly changed",
8904
- "",
8905
- "### Template Variable Protection",
8906
- "- If step values contain {{varName}} template variables, preserve them as-is in fix suggestions",
8907
- "- Template variables are dynamic references resolved at runtime. Do not suggest replacing them with literal values",
8908
- "",
8909
- "### failureCategory and suggestedStrategy",
8910
- "If a failure category is provided, describe a specific fix strategy in suggestedStrategy:",
8911
- "- element_not_found: Update selector ariaLabel/role/text to match current page structure",
8912
- "- element_stale: Delete selector cache and re-execute",
8913
- "- page_structure_changed: Document page structure changes in context.md and update all selectors",
8914
- "- navigation_timeout: Add wait step or increase step-delay",
8915
- "- action_failed: Consider changing action type (e.g., click \u2192 hover)",
8916
- "- unknown: Analyze error details and propose specific remediation"
8917
- ].join("\n");
8918
- }
8919
- function buildSuggestionUserPrompt(failedInfo, stepsInfo, runbook, contextMarkdown) {
8920
- const parts = [
8921
- "## Instruction Information",
8922
- `Title: ${runbook.title}`,
8923
- `Goal: ${runbook.metadata.goal}`,
8924
- `Start URL: ${runbook.metadata.startUrl}`,
8925
- "",
8926
- "## Instruction Steps",
8927
- stepsInfo.join("\n\n"),
8928
- "",
8929
- "## Failed Step Details",
8930
- failedInfo.join("\n\n")
8931
- ];
8932
- if (contextMarkdown) {
8933
- parts.push(
8934
- "",
8935
- "## Current Context (markdown)",
8936
- contextMarkdown
8937
- );
8938
- } else {
8939
- parts.push(
8940
- "",
8941
- "## Context",
8942
- "Context markdown is not provided. Return empty string for contextFix."
8943
- );
8784
+ const errorEntries = entries.filter(
8785
+ (e) => e.event === "error" || e.event === "step_error" || e.event === "validation_failed" || e.data && typeof e.data === "object" && "result" in e.data && typeof e.data.result === "object" && e.data.result !== null && "success" in e.data.result && e.data.result.success === false
8786
+ );
8787
+ if (errorEntries.length > 0) {
8788
+ lines.push("## Debug Log (Error Events)");
8789
+ lines.push("```json");
8790
+ for (const entry of errorEntries.slice(-maxErrors)) {
8791
+ lines.push(JSON.stringify(entry));
8792
+ }
8793
+ lines.push("```");
8794
+ lines.push("");
8944
8795
  }
8945
- return parts.join("\n");
8946
- }
8947
-
8948
- // src/i18n/prompts/ja/self-heal.ts
8949
- function getSuggestionSystemPrompt2() {
8950
- return [
8951
- "\u3042\u306A\u305F\u306F\u30D6\u30E9\u30A6\u30B6\u81EA\u52D5\u64CD\u4F5C\u306E\u624B\u9806\u66F8\u30C7\u30D0\u30C3\u30AC\u30FC\u3067\u3059\u3002",
8952
- "\u30C7\u30D0\u30C3\u30B0\u5B9F\u884C\u3067\u5931\u6557\u3057\u305F\u30B9\u30C6\u30C3\u30D7\u3092\u5206\u6790\u3057\u3001\u624B\u9806\u66F8\u3068\u30B3\u30F3\u30C6\u30AD\u30B9\u30C8\u306E\u4FEE\u6B63\u63D0\u6848\u3092\u751F\u6210\u3057\u3066\u304F\u3060\u3055\u3044\u3002",
8953
- "",
8954
- "## \u4FEE\u6B63\u63D0\u6848\u306E\u6307\u91DD",
8955
- "",
8956
- "\u5404\u5931\u6557\u30B9\u30C6\u30C3\u30D7\u306B\u3064\u3044\u3066\u3001\u4EE5\u4E0B\u306E2\u3064\u306E\u89B3\u70B9\u3067\u4FEE\u6B63\u63D0\u6848\u3092\u51FA\u3057\u3066\u304F\u3060\u3055\u3044:",
8957
- "",
8958
- "### 1. runbookFix\uFF08\u624B\u9806\u66F8 YAML \u306E\u4FEE\u6B63\uFF09",
8959
- "- \u30BB\u30EC\u30AF\u30BF\u306E\u5909\u66F4\uFF08\u8981\u7D20\u304C\u79FB\u52D5/\u30EA\u30CD\u30FC\u30E0\u3055\u308C\u305F\u5834\u5408\uFF09",
8960
- "- \u30B9\u30C6\u30C3\u30D7\u306E\u8FFD\u52A0/\u524A\u9664\uFF08\u5C0E\u7DDA\u304C\u5909\u308F\u3063\u305F\u5834\u5408\uFF09",
8961
- "- \u30A2\u30AF\u30B7\u30E7\u30F3\u5024\u306E\u66F4\u65B0\uFF08\u30C6\u30AD\u30B9\u30C8\u3084URL\u306E\u5909\u66F4\uFF09",
8962
- "- riskLevel \u3084 requiresConfirmation \u306E\u8ABF\u6574",
8963
- "\u4F8B: \u300CStep 3: selector \u306E ariaLabel \u3092 '\u9001\u4FE1' \u2192 '\u78BA\u8A8D\u3057\u3066\u9001\u4FE1' \u306B\u5909\u66F4\u300D",
8964
- "",
8965
- "### 2. contextFix\uFF08context markdown \u306E\u4FEE\u6B63\uFF09",
8966
- "- \u30DA\u30FC\u30B8\u69CB\u9020\u5909\u66F4\u306E\u8A18\u8F09\uFF08\u65B0\u3057\u3044\u30E2\u30FC\u30C0\u30EB\u3001\u30E1\u30CB\u30E5\u30FC\u69CB\u9020\u306E\u5909\u66F4\u306A\u3069\uFF09",
8967
- "- \u524D\u63D0\u6761\u4EF6\u306E\u8FFD\u52A0\uFF08\u30ED\u30B0\u30A4\u30F3\u72B6\u614B\u3001\u6A29\u9650\u3001\u74B0\u5883\u6761\u4EF6\u306A\u3069\uFF09",
8968
- "- \u30BB\u30EC\u30AF\u30BF\u89E3\u6C7A\u306E\u30D2\u30F3\u30C8\u8FFD\u52A0\uFF08\u52D5\u7684ID\u306E\u547D\u540D\u898F\u5247\u306A\u3069\uFF09",
8969
- "\u4F8B: \u300Ccontext \u306B'\u8A2D\u5B9A\u753B\u9762\u304C\u30BF\u30D6UI\u304B\u3089\u30A2\u30B3\u30FC\u30C7\u30A3\u30AA\u30F3UI\u306B\u5909\u66F4\u3055\u308C\u305F'\u65E8\u3092\u8FFD\u8A18\u300D",
8970
- "",
8971
- "context markdown \u304C\u672A\u63D0\u4F9B\u306E\u5834\u5408\u3001contextFix \u306F\u7A7A\u6587\u5B57\u3067\u8FD4\u3057\u3066\u304F\u3060\u3055\u3044\u3002",
8972
- "",
8973
- "### severity \u306E\u5224\u5B9A\u57FA\u6E96",
8974
- "- error: \u30BB\u30EC\u30AF\u30BF\u304C\u5B8C\u5168\u306B\u898B\u3064\u304B\u3089\u306A\u3044\u3001\u30DA\u30FC\u30B8\u69CB\u9020\u304C\u6839\u672C\u7684\u306B\u5909\u308F\u3063\u3066\u3044\u308B",
8975
- "- warning: \u30EA\u30C8\u30E9\u30A4\u3067\u6210\u529F\u3057\u305F\u304C\u4E0D\u5B89\u5B9A\u3001\u8981\u7D20\u306E\u4F4D\u7F6E\u3084\u30E9\u30D9\u30EB\u304C\u5FAE\u5999\u306B\u5909\u308F\u3063\u3066\u3044\u308B",
8976
- "",
8977
- "### \u30C6\u30F3\u30D7\u30EC\u30FC\u30C8\u5909\u6570\u306E\u4FDD\u8B77",
8978
- "- \u30B9\u30C6\u30C3\u30D7\u306E\u5024\u306B {{varName}} \u5F62\u5F0F\u306E\u30C6\u30F3\u30D7\u30EC\u30FC\u30C8\u5909\u6570\u304C\u542B\u307E\u308C\u3066\u3044\u308B\u5834\u5408\u3001\u4FEE\u6B63\u63D0\u6848\u3067\u3082\u305D\u306E\u307E\u307E\u7DAD\u6301\u3057\u3066\u304F\u3060\u3055\u3044",
8979
- "- \u30C6\u30F3\u30D7\u30EC\u30FC\u30C8\u5909\u6570\u306F\u5B9F\u884C\u6642\u306B\u52D5\u7684\u306B\u5C55\u958B\u3055\u308C\u308B\u5909\u6570\u53C2\u7167\u3067\u3059\u3002\u30EA\u30C6\u30E9\u30EB\u5024\u3078\u306E\u7F6E\u63DB\u3092\u63D0\u6848\u3057\u306A\u3044\u3067\u304F\u3060\u3055\u3044",
8980
- "",
8981
- "### failureCategory \u3068 suggestedStrategy",
8982
- "\u30A8\u30E9\u30FC\u5206\u985E\u30AB\u30C6\u30B4\u30EA\u304C\u63D0\u4F9B\u3055\u308C\u3066\u3044\u308B\u5834\u5408\u3001\u305D\u308C\u306B\u57FA\u3065\u3044\u3066\u5177\u4F53\u7684\u306A\u4FEE\u6B63\u6226\u7565\u3092 suggestedStrategy \u306B\u8A18\u8F09\u3057\u3066\u304F\u3060\u3055\u3044:",
8983
- "- element_not_found: \u30BB\u30EC\u30AF\u30BF\u306E ariaLabel/role/text \u3092\u73FE\u5728\u306E\u30DA\u30FC\u30B8\u69CB\u9020\u306B\u5408\u308F\u305B\u3066\u66F4\u65B0",
8984
- "- element_stale: \u30BB\u30EC\u30AF\u30BF\u30AD\u30E3\u30C3\u30B7\u30E5\u306E\u524A\u9664\u3068\u518D\u5B9F\u884C",
8985
- "- page_structure_changed: context.md \u306B\u30DA\u30FC\u30B8\u69CB\u9020\u5909\u66F4\u3092\u8A18\u9332\u3057\u3001\u30BB\u30EC\u30AF\u30BF\u3092\u5168\u9762\u66F4\u65B0",
8986
- "- navigation_timeout: wait \u30B9\u30C6\u30C3\u30D7\u306E\u8FFD\u52A0\u307E\u305F\u306F step-delay \u306E\u5897\u52A0",
8987
- "- action_failed: \u30A2\u30AF\u30B7\u30E7\u30F3\u7A2E\u5225\u306E\u5909\u66F4\uFF08\u4F8B: click \u2192 hover\uFF09\u3092\u691C\u8A0E",
8988
- "- unknown: \u30A8\u30E9\u30FC\u5185\u5BB9\u3092\u8A73\u7D30\u306B\u5206\u6790\u3057\u3001\u5177\u4F53\u7684\u306A\u5BFE\u51E6\u3092\u63D0\u6848"
8989
- ].join("\n");
8990
- }
8991
- function buildSuggestionUserPrompt2(failedInfo, stepsInfo, runbook, contextMarkdown) {
8992
- const parts = [
8993
- "## \u624B\u9806\u66F8\u60C5\u5831",
8994
- `\u30BF\u30A4\u30C8\u30EB: ${runbook.title}`,
8995
- `\u76EE\u7684: ${runbook.metadata.goal}`,
8996
- `\u958B\u59CBURL: ${runbook.metadata.startUrl}`,
8997
- "",
8998
- "## \u624B\u9806\u66F8\u306E\u30B9\u30C6\u30C3\u30D7\u4E00\u89A7",
8999
- stepsInfo.join("\n\n"),
9000
- "",
9001
- "## \u5931\u6557\u30B9\u30C6\u30C3\u30D7\u306E\u8A73\u7D30",
9002
- failedInfo.join("\n\n")
9003
- ];
9004
- if (contextMarkdown) {
9005
- parts.push(
9006
- "",
9007
- "## \u73FE\u5728\u306E\u30B3\u30F3\u30C6\u30AD\u30B9\u30C8\uFF08markdown\uFF09",
9008
- contextMarkdown
9009
- );
9010
- } else {
9011
- parts.push(
9012
- "",
9013
- "## \u30B3\u30F3\u30C6\u30AD\u30B9\u30C8",
9014
- "context markdown \u306F\u672A\u63D0\u4F9B\u3067\u3059\u3002contextFix \u306F\u7A7A\u6587\u5B57\u3067\u8FD4\u3057\u3066\u304F\u3060\u3055\u3044\u3002"
9015
- );
8796
+ const actionEntries = entries.filter(
8797
+ (e) => e.event !== void 0 && recentEventTypes.includes(e.event)
8798
+ );
8799
+ const recentActions = actionEntries.slice(-maxRecent);
8800
+ if (recentActions.length > 0) {
8801
+ lines.push("## Debug Log (Recent Events)");
8802
+ lines.push("```json");
8803
+ for (const entry of recentActions) {
8804
+ lines.push(JSON.stringify(entry));
8805
+ }
8806
+ lines.push("```");
8807
+ lines.push("");
9016
8808
  }
9017
- return parts.join("\n");
9018
- }
9019
-
9020
- // src/i18n/prompts/index.ts
9021
- function getAgentInstructions3(goal, contextMarkdown, secrets, locale) {
9022
- const effectiveLocale = locale ?? getLocale();
9023
- return effectiveLocale === "ja" ? getAgentInstructions2(goal, contextMarkdown, secrets) : getAgentInstructions(goal, contextMarkdown, secrets);
9024
- }
9025
- function getInitialUserMessage3(locale) {
9026
- const effectiveLocale = locale ?? getLocale();
9027
- return effectiveLocale === "ja" ? getInitialUserMessage2() : getInitialUserMessage();
9028
- }
9029
- function getReviewSystemPrompt3(locale) {
9030
- const effectiveLocale = locale ?? getLocale();
9031
- return effectiveLocale === "ja" ? getReviewSystemPrompt2() : getReviewSystemPrompt();
9032
- }
9033
- function createReviewUserPrompt3(goal, recordedSteps, goalAchieved, interventions, locale) {
9034
- const effectiveLocale = locale ?? getLocale();
9035
- return effectiveLocale === "ja" ? createReviewUserPrompt2(goal, recordedSteps, goalAchieved, interventions) : createReviewUserPrompt(goal, recordedSteps, goalAchieved, interventions);
9036
- }
9037
- function buildSelectorMessages3(snapshot, selector, stepDescription, url, contextMarkdown, retryContext, workingMemorySummary) {
9038
- return getLocale() === "ja" ? buildSelectorMessages2(snapshot, selector, stepDescription, url, contextMarkdown, retryContext, workingMemorySummary) : buildSelectorMessages(snapshot, selector, stepDescription, url, contextMarkdown, retryContext, workingMemorySummary);
9039
- }
9040
- function buildFallbackMessages3(snapshot, step, failureHistory, url, contextMarkdown) {
9041
- return getLocale() === "ja" ? buildFallbackMessages2(snapshot, step, failureHistory, url, contextMarkdown) : buildFallbackMessages(snapshot, step, failureHistory, url, contextMarkdown);
9042
- }
9043
- function buildVisionMessages3(annotations, selector, stepDescription, url, failureHistory) {
9044
- return getLocale() === "ja" ? buildVisionMessages2(annotations, selector, stepDescription, url, failureHistory) : buildVisionMessages(annotations, selector, stepDescription, url, failureHistory);
9045
- }
9046
- function getSuggestionSystemPrompt3() {
9047
- return getLocale() === "ja" ? getSuggestionSystemPrompt2() : getSuggestionSystemPrompt();
9048
- }
9049
- function buildSuggestionUserPrompt3(failedInfo, stepsInfo, runbook, contextMarkdown) {
9050
- return getLocale() === "ja" ? buildSuggestionUserPrompt2(failedInfo, stepsInfo, runbook, contextMarkdown) : buildSuggestionUserPrompt(failedInfo, stepsInfo, runbook, contextMarkdown);
8809
+ return lines;
9051
8810
  }
9052
8811
 
9053
8812
  export {
@@ -9058,9 +8817,6 @@ export {
9058
8817
  NoopLogger,
9059
8818
  NoopSpinner,
9060
8819
  AgentBrowser,
9061
- findElementInSnapshot,
9062
- parseAllElements,
9063
- countElements,
9064
8820
  classifyFailure,
9065
8821
  getRecoveryHint,
9066
8822
  sanitizeBrowserError,
@@ -9068,17 +8824,24 @@ export {
9068
8824
  createDebugLogger,
9069
8825
  parseAndAppendToMemory,
9070
8826
  sleep,
9071
- getAgentInstructions3 as getAgentInstructions,
9072
- getInitialUserMessage3 as getInitialUserMessage,
9073
- getReviewSystemPrompt3 as getReviewSystemPrompt,
9074
- createReviewUserPrompt3 as createReviewUserPrompt,
9075
- buildSelectorMessages3 as buildSelectorMessages,
9076
- buildFallbackMessages3 as buildFallbackMessages,
9077
- buildVisionMessages3 as buildVisionMessages,
9078
- getSuggestionSystemPrompt3 as getSuggestionSystemPrompt,
9079
- buildSuggestionUserPrompt3 as buildSuggestionUserPrompt,
9080
8827
  InMemoryDataStore,
9081
8828
  DownloadManager,
9082
- formatDuration
8829
+ formatDuration,
8830
+ serializeGeneratorOptions,
8831
+ serializeExecutorOptions,
8832
+ renderOptionsMarkdown,
8833
+ readDebugLog,
8834
+ formatAiMetricsSection,
8835
+ formatRuntimeEnvironment,
8836
+ formatSelectorResolutionStats,
8837
+ formatRetryDistribution,
8838
+ formatFailureCategoryDistribution,
8839
+ formatRecoveryEffectiveness,
8840
+ formatPerformanceBottlenecks,
8841
+ formatAiSelectorQualityIssues,
8842
+ formatSelectorResolutionStatsFromTelemetry,
8843
+ formatRecoveryEffectivenessFromTelemetry,
8844
+ formatAiSelectorQualityFromSteps,
8845
+ formatDebugLogSections
9083
8846
  };
9084
- //# sourceMappingURL=chunk-DJVUITRB.js.map
8847
+ //# sourceMappingURL=chunk-ELQ23L4Z.js.map