misoai-web 1.0.6 → 1.5.7

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 (76) hide show
  1. package/README.md +5 -349
  2. package/dist/es/agent.js +165 -428
  3. package/dist/es/agent.js.map +1 -1
  4. package/dist/es/bridge-mode-browser.js +10 -9
  5. package/dist/es/bridge-mode-browser.js.map +1 -1
  6. package/dist/es/bridge-mode.js +167 -430
  7. package/dist/es/bridge-mode.js.map +1 -1
  8. package/dist/es/chrome-extension.js +173 -435
  9. package/dist/es/chrome-extension.js.map +1 -1
  10. package/dist/es/index.js +185 -432
  11. package/dist/es/index.js.map +1 -1
  12. package/dist/es/midscene-playground.js +165 -428
  13. package/dist/es/midscene-playground.js.map +1 -1
  14. package/dist/es/midscene-server.js.map +1 -1
  15. package/dist/es/playground.js +165 -428
  16. package/dist/es/playground.js.map +1 -1
  17. package/dist/es/playwright-report.js +1 -1
  18. package/dist/es/playwright-report.js.map +1 -1
  19. package/dist/es/playwright.js +182 -429
  20. package/dist/es/playwright.js.map +1 -1
  21. package/dist/es/puppeteer-agent-launcher.js +169 -432
  22. package/dist/es/puppeteer-agent-launcher.js.map +1 -1
  23. package/dist/es/puppeteer.js +169 -432
  24. package/dist/es/puppeteer.js.map +1 -1
  25. package/dist/es/ui-utils.js.map +1 -1
  26. package/dist/es/utils.js +7 -4
  27. package/dist/es/utils.js.map +1 -1
  28. package/dist/es/yaml.js +29 -3
  29. package/dist/es/yaml.js.map +1 -1
  30. package/dist/lib/agent.js +163 -426
  31. package/dist/lib/agent.js.map +1 -1
  32. package/dist/lib/bridge-mode-browser.js +10 -9
  33. package/dist/lib/bridge-mode-browser.js.map +1 -1
  34. package/dist/lib/bridge-mode.js +165 -428
  35. package/dist/lib/bridge-mode.js.map +1 -1
  36. package/dist/lib/chrome-extension.js +171 -433
  37. package/dist/lib/chrome-extension.js.map +1 -1
  38. package/dist/lib/index.js +183 -430
  39. package/dist/lib/index.js.map +1 -1
  40. package/dist/lib/midscene-playground.js +163 -426
  41. package/dist/lib/midscene-playground.js.map +1 -1
  42. package/dist/lib/midscene-server.js.map +1 -1
  43. package/dist/lib/playground.js +163 -426
  44. package/dist/lib/playground.js.map +1 -1
  45. package/dist/lib/playwright-report.js +1 -1
  46. package/dist/lib/playwright-report.js.map +1 -1
  47. package/dist/lib/playwright.js +180 -427
  48. package/dist/lib/playwright.js.map +1 -1
  49. package/dist/lib/puppeteer-agent-launcher.js +167 -430
  50. package/dist/lib/puppeteer-agent-launcher.js.map +1 -1
  51. package/dist/lib/puppeteer.js +167 -430
  52. package/dist/lib/puppeteer.js.map +1 -1
  53. package/dist/lib/ui-utils.js.map +1 -1
  54. package/dist/lib/utils.js +7 -4
  55. package/dist/lib/utils.js.map +1 -1
  56. package/dist/lib/yaml.js +29 -3
  57. package/dist/lib/yaml.js.map +1 -1
  58. package/dist/types/agent.d.ts +13 -51
  59. package/dist/types/bridge-mode-browser.d.ts +2 -3
  60. package/dist/types/bridge-mode.d.ts +2 -3
  61. package/dist/types/{browser-aec1055d.d.ts → browser-9b472ffb.d.ts} +1 -1
  62. package/dist/types/chrome-extension.d.ts +2 -3
  63. package/dist/types/index.d.ts +1 -2
  64. package/dist/types/midscene-server.d.ts +1 -2
  65. package/dist/types/{page-86ab0fe1.d.ts → page-ed0ecb44.d.ts} +19 -9
  66. package/dist/types/playground.d.ts +2 -3
  67. package/dist/types/playwright.d.ts +9 -2
  68. package/dist/types/puppeteer-agent-launcher.d.ts +1 -2
  69. package/dist/types/puppeteer.d.ts +6 -5
  70. package/dist/types/ui-utils.d.ts +1 -1
  71. package/dist/types/utils.d.ts +1 -2
  72. package/dist/types/yaml.d.ts +1 -2
  73. package/iife-script/htmlElement.js +53 -75
  74. package/iife-script/htmlElementDebug.js +35 -56
  75. package/package.json +24 -24
  76. package/LICENSE +0 -21
package/dist/lib/index.js CHANGED
@@ -60,10 +60,11 @@ var ScriptPlayer = class {
60
60
  this.unnamedResultIndex = 0;
61
61
  this.pageAgent = null;
62
62
  this.result = {};
63
+ const target = script.target || script.web || script.android;
63
64
  if (import_utils.ifInBrowser) {
64
65
  this.output = void 0;
65
- } else if (script.target?.output) {
66
- this.output = (0, import_node_path.resolve)(process.cwd(), script.target.output);
66
+ } else if (target?.output) {
67
+ this.output = (0, import_node_path.resolve)(process.cwd(), target.output);
67
68
  } else {
68
69
  this.output = (0, import_node_path.join)((0, import_common.getMidsceneRunSubDir)("output"), `${process.pid}.json`);
69
70
  }
@@ -137,15 +138,20 @@ var ScriptPlayer = class {
137
138
  } else if ("aiAssert" in flowItem) {
138
139
  const assertTask = flowItem;
139
140
  const prompt = assertTask.aiAssert;
141
+ const msg = assertTask.errorMessage;
140
142
  (0, import_utils.assert)(prompt, "missing prompt for aiAssert");
141
143
  (0, import_utils.assert)(
142
144
  typeof prompt === "string",
143
145
  "prompt for aiAssert must be a string"
144
146
  );
145
- await agent.aiAssert(prompt);
147
+ await agent.aiAssert(prompt, msg);
146
148
  } else if ("aiQuery" in flowItem) {
147
149
  const queryTask = flowItem;
148
150
  const prompt = queryTask.aiQuery;
151
+ const options = {
152
+ domIncluded: queryTask.domIncluded,
153
+ screenshotIncluded: queryTask.screenshotIncluded
154
+ };
149
155
  (0, import_utils.assert)(prompt, "missing prompt for aiQuery");
150
156
  (0, import_utils.assert)(
151
157
  typeof prompt === "string",
@@ -156,6 +162,10 @@ var ScriptPlayer = class {
156
162
  } else if ("aiNumber" in flowItem) {
157
163
  const numberTask = flowItem;
158
164
  const prompt = numberTask.aiNumber;
165
+ const options = {
166
+ domIncluded: numberTask.domIncluded,
167
+ screenshotIncluded: numberTask.screenshotIncluded
168
+ };
159
169
  (0, import_utils.assert)(prompt, "missing prompt for number");
160
170
  (0, import_utils.assert)(
161
171
  typeof prompt === "string",
@@ -166,6 +176,10 @@ var ScriptPlayer = class {
166
176
  } else if ("aiString" in flowItem) {
167
177
  const stringTask = flowItem;
168
178
  const prompt = stringTask.aiString;
179
+ const options = {
180
+ domIncluded: stringTask.domIncluded,
181
+ screenshotIncluded: stringTask.screenshotIncluded
182
+ };
169
183
  (0, import_utils.assert)(prompt, "missing prompt for string");
170
184
  (0, import_utils.assert)(
171
185
  typeof prompt === "string",
@@ -176,6 +190,10 @@ var ScriptPlayer = class {
176
190
  } else if ("aiBoolean" in flowItem) {
177
191
  const booleanTask = flowItem;
178
192
  const prompt = booleanTask.aiBoolean;
193
+ const options = {
194
+ domIncluded: booleanTask.domIncluded,
195
+ screenshotIncluded: booleanTask.screenshotIncluded
196
+ };
179
197
  (0, import_utils.assert)(prompt, "missing prompt for boolean");
180
198
  (0, import_utils.assert)(
181
199
  typeof prompt === "string",
@@ -218,6 +236,9 @@ var ScriptPlayer = class {
218
236
  } else if ("aiTap" in flowItem) {
219
237
  const tapTask = flowItem;
220
238
  await agent.aiTap(tapTask.aiTap, tapTask);
239
+ } else if ("aiRightClick" in flowItem) {
240
+ const rightClickTask = flowItem;
241
+ await agent.aiRightClick(rightClickTask.aiRightClick, rightClickTask);
221
242
  } else if ("aiHover" in flowItem) {
222
243
  const hoverTask = flowItem;
223
244
  await agent.aiHover(hoverTask.aiHover, hoverTask);
@@ -240,6 +261,11 @@ var ScriptPlayer = class {
240
261
  evaluateJavaScriptTask.javascript
241
262
  );
242
263
  this.setResult(evaluateJavaScriptTask.name, result);
264
+ } else if ("logScreenshot" in flowItem) {
265
+ const logScreenshotTask = flowItem;
266
+ await agent.logScreenshot(logScreenshotTask.logScreenshot, {
267
+ content: logScreenshotTask.content || ""
268
+ });
243
269
  } else {
244
270
  throw new Error(`unknown flowItem: ${JSON.stringify(flowItem)}`);
245
271
  }
@@ -488,7 +514,8 @@ var WebElementInfo = class {
488
514
  id,
489
515
  attributes,
490
516
  indexId,
491
- xpaths
517
+ xpaths,
518
+ isVisible
492
519
  }) {
493
520
  this.content = content;
494
521
  this.rect = rect;
@@ -501,6 +528,7 @@ var WebElementInfo = class {
501
528
  this.attributes = attributes;
502
529
  this.indexId = indexId;
503
530
  this.xpaths = xpaths;
531
+ this.isVisible = isVisible;
504
532
  }
505
533
  };
506
534
 
@@ -523,14 +551,15 @@ async function parseContextFromWebPage(page, _opt) {
523
551
  })
524
552
  ]);
525
553
  const webTree = (0, import_extractor.traverseTree)(tree, (elementInfo) => {
526
- const { rect, id, content, attributes, locator, indexId } = elementInfo;
554
+ const { rect, id, content, attributes, locator, indexId, isVisible } = elementInfo;
527
555
  return new WebElementInfo({
528
556
  rect,
529
557
  locator,
530
558
  id,
531
559
  content,
532
560
  attributes,
533
- indexId
561
+ indexId,
562
+ isVisible
534
563
  });
535
564
  });
536
565
  (0, import_utils4.assert)(screenshotBase64, "screenshotBase64 is required");
@@ -560,7 +589,7 @@ function printReportMsg(filepath) {
560
589
  (0, import_utils4.logMsg)(`Midscene - report file updated: ${filepath}`);
561
590
  }
562
591
  function replaceIllegalPathCharsAndSpace(str) {
563
- return str.replace(/[/\\:*?"<>| ]/g, "-");
592
+ return str.replace(/[:*?"<>| ]/g, "-");
564
593
  }
565
594
  function forceClosePopup(page, debug7) {
566
595
  page.on("popup", async (popup) => {
@@ -874,10 +903,10 @@ var PageTaskExecutor = class {
874
903
  if (!taskParam || !taskParam.value) {
875
904
  return;
876
905
  }
877
- await this.page.keyboard.type(taskParam.value);
878
- } else {
879
- await this.page.keyboard.type(taskParam.value);
880
906
  }
907
+ await this.page.keyboard.type(taskParam.value, {
908
+ autoDismissKeyboard: taskParam.autoDismissKeyboard
909
+ });
881
910
  }
882
911
  };
883
912
  tasks.push(taskActionInput);
@@ -906,6 +935,22 @@ var PageTaskExecutor = class {
906
935
  }
907
936
  };
908
937
  tasks.push(taskActionTap);
938
+ } else if (plan2.type === "RightClick") {
939
+ const taskActionRightClick = {
940
+ type: "Action",
941
+ subType: "RightClick",
942
+ thought: plan2.thought,
943
+ locate: plan2.locate,
944
+ executor: async (param, { element }) => {
945
+ (0, import_utils6.assert)(element, "Element not found, cannot right click");
946
+ await this.page.mouse.click(
947
+ element.center[0],
948
+ element.center[1],
949
+ { button: "right" }
950
+ );
951
+ }
952
+ };
953
+ tasks.push(taskActionRightClick);
909
954
  } else if (plan2.type === "Drag") {
910
955
  const taskActionDrag = {
911
956
  type: "Action",
@@ -1434,7 +1479,7 @@ var PageTaskExecutor = class {
1434
1479
  executor: taskExecutor
1435
1480
  };
1436
1481
  }
1437
- async createTypeQueryTask(type, demand) {
1482
+ async createTypeQueryTask(type, demand, opt) {
1438
1483
  const taskExecutor = new import_misoai_core.Executor(
1439
1484
  taskTitleStr(
1440
1485
  type,
@@ -1465,7 +1510,10 @@ var PageTaskExecutor = class {
1465
1510
  result: `${type}, ${demand}`
1466
1511
  };
1467
1512
  }
1468
- const { data, usage } = await this.insight.extract(demandInput);
1513
+ const { data, usage } = await this.insight.extract(
1514
+ demandInput,
1515
+ opt
1516
+ );
1469
1517
  let outputResult = data;
1470
1518
  if (ifTypeRestricted) {
1471
1519
  (0, import_utils6.assert)(data?.result !== void 0, "No result in query data");
@@ -1485,17 +1533,17 @@ var PageTaskExecutor = class {
1485
1533
  executor: taskExecutor
1486
1534
  };
1487
1535
  }
1488
- async query(demand) {
1489
- return this.createTypeQueryTask("Query", demand);
1536
+ async query(demand, opt) {
1537
+ return this.createTypeQueryTask("Query", demand, opt);
1490
1538
  }
1491
- async boolean(prompt) {
1492
- return this.createTypeQueryTask("Boolean", prompt);
1539
+ async boolean(prompt, opt) {
1540
+ return this.createTypeQueryTask("Boolean", prompt, opt);
1493
1541
  }
1494
- async number(prompt) {
1495
- return this.createTypeQueryTask("Number", prompt);
1542
+ async number(prompt, opt) {
1543
+ return this.createTypeQueryTask("Number", prompt, opt);
1496
1544
  }
1497
- async string(prompt) {
1498
- return this.createTypeQueryTask("String", prompt);
1545
+ async string(prompt, opt) {
1546
+ return this.createTypeQueryTask("String", prompt, opt);
1499
1547
  }
1500
1548
  async assert(assertion) {
1501
1549
  const description = `assert: ${assertion}`;
@@ -1631,7 +1679,7 @@ function buildPlans(type, locateParam, param) {
1631
1679
  param: locateParam,
1632
1680
  thought: ""
1633
1681
  } : null;
1634
- if (type === "Tap" || type === "Hover") {
1682
+ if (type === "Tap" || type === "Hover" || type === "RightClick") {
1635
1683
  (0, import_utils8.assert)(locateParam, `missing locate info for action "${type}"`);
1636
1684
  (0, import_utils8.assert)(locatePlan, `missing locate info for action "${type}"`);
1637
1685
  const tapPlan = {
@@ -1711,7 +1759,7 @@ var import_js_yaml3 = __toESM(require("js-yaml"));
1711
1759
  var import_semver = __toESM(require("semver"));
1712
1760
 
1713
1761
  // package.json
1714
- var version = "1.0.5";
1762
+ var version = "1.0.3";
1715
1763
 
1716
1764
  // src/common/task-cache.ts
1717
1765
  var debug3 = (0, import_logger3.getDebug)("cache");
@@ -1739,70 +1787,44 @@ var TaskCache = class {
1739
1787
  this.cache = cacheContent;
1740
1788
  this.cacheOriginalLength = this.cache.caches.length;
1741
1789
  }
1742
- matchCache(prompt, type, contextData) {
1743
- const contextHash = contextData ? this.generateContextHash(contextData) : void 0;
1790
+ matchCache(prompt, type) {
1744
1791
  for (let i = 0; i < this.cacheOriginalLength; i++) {
1745
1792
  const item = this.cache.caches[i];
1746
1793
  const key = `${type}:${prompt}:${i}`;
1747
- if (item.type !== type || item.prompt !== prompt || this.matchedCacheIndices.has(key)) {
1748
- continue;
1749
- }
1750
- if (type === "plan" && item.type === "plan") {
1751
- const planItem = item;
1752
- if (contextHash && planItem.contextHash) {
1753
- if (contextHash !== planItem.contextHash) {
1754
- debug3("cache context mismatch, type: %s, prompt: %s, index: %d", type, prompt, i);
1755
- continue;
1794
+ if (item.type === type && item.prompt === prompt && !this.matchedCacheIndices.has(key)) {
1795
+ this.matchedCacheIndices.add(key);
1796
+ debug3(
1797
+ "cache found and marked as used, type: %s, prompt: %s, index: %d",
1798
+ type,
1799
+ prompt,
1800
+ i
1801
+ );
1802
+ return {
1803
+ cacheContent: item,
1804
+ updateFn: (cb) => {
1805
+ debug3(
1806
+ "will call updateFn to update cache, type: %s, prompt: %s, index: %d",
1807
+ type,
1808
+ prompt,
1809
+ i
1810
+ );
1811
+ cb(item);
1812
+ debug3(
1813
+ "cache updated, will flush to file, type: %s, prompt: %s, index: %d",
1814
+ type,
1815
+ prompt,
1816
+ i
1817
+ );
1818
+ this.flushCacheToFile();
1756
1819
  }
1757
- } else if (contextHash || planItem.contextHash) {
1758
- debug3("cache context availability mismatch, type: %s, prompt: %s, index: %d", type, prompt, i);
1759
- continue;
1760
- }
1820
+ };
1761
1821
  }
1762
- this.matchedCacheIndices.add(key);
1763
- debug3(
1764
- "cache found and marked as used, type: %s, prompt: %s, index: %d, contextMatch: %s",
1765
- type,
1766
- prompt,
1767
- i,
1768
- contextHash ? "yes" : "no-context"
1769
- );
1770
- return {
1771
- cacheContent: item,
1772
- updateFn: (cb) => {
1773
- debug3(
1774
- "will call updateFn to update cache, type: %s, prompt: %s, index: %d",
1775
- type,
1776
- prompt,
1777
- i
1778
- );
1779
- cb(item);
1780
- debug3(
1781
- "cache updated, will flush to file, type: %s, prompt: %s, index: %d",
1782
- type,
1783
- prompt,
1784
- i
1785
- );
1786
- this.flushCacheToFile();
1787
- }
1788
- };
1789
1822
  }
1790
- debug3("no unused cache found, type: %s, prompt: %s, contextHash: %s", type, prompt, contextHash);
1823
+ debug3("no unused cache found, type: %s, prompt: %s", type, prompt);
1791
1824
  return void 0;
1792
1825
  }
1793
- generateContextHash(contextData) {
1794
- const sortedKeys = Object.keys(contextData).sort();
1795
- const stableString = sortedKeys.map((key) => `${key}:${JSON.stringify(contextData[key])}`).join("|");
1796
- let hash = 0;
1797
- for (let i = 0; i < stableString.length; i++) {
1798
- const char = stableString.charCodeAt(i);
1799
- hash = (hash << 5) - hash + char;
1800
- hash = hash & hash;
1801
- }
1802
- return hash.toString(36);
1803
- }
1804
- matchPlanCache(prompt, contextData) {
1805
- return this.matchCache(prompt, "plan", contextData);
1826
+ matchPlanCache(prompt) {
1827
+ return this.matchCache(prompt, "plan");
1806
1828
  }
1807
1829
  matchLocateCache(prompt) {
1808
1830
  return this.matchCache(prompt, "locate");
@@ -1868,8 +1890,14 @@ cache file: ${cacheFile}`
1868
1890
  return;
1869
1891
  }
1870
1892
  try {
1893
+ const dir = (0, import_node_path2.dirname)(this.cacheFilePath);
1894
+ if (!(0, import_node_fs2.existsSync)(dir)) {
1895
+ (0, import_node_fs2.mkdirSync)(dir, { recursive: true });
1896
+ debug3("created cache directory: %s", dir);
1897
+ }
1871
1898
  const yamlData = import_js_yaml3.default.dump(this.cache);
1872
1899
  (0, import_node_fs2.writeFileSync)(this.cacheFilePath, yamlData);
1900
+ debug3("cache flushed to file: %s", this.cacheFilePath);
1873
1901
  } catch (err) {
1874
1902
  debug3(
1875
1903
  "write cache to file failed, path: %s, error: %s",
@@ -1878,16 +1906,11 @@ cache file: ${cacheFile}`
1878
1906
  );
1879
1907
  }
1880
1908
  }
1881
- updateOrAppendCacheRecord(newRecord, cachedRecord, contextData) {
1909
+ updateOrAppendCacheRecord(newRecord, cachedRecord) {
1882
1910
  if (cachedRecord) {
1883
1911
  if (newRecord.type === "plan") {
1884
1912
  cachedRecord.updateFn((cache) => {
1885
- const planCache = cache;
1886
- planCache.yamlWorkflow = newRecord.yamlWorkflow;
1887
- if (contextData) {
1888
- planCache.contextHash = this.generateContextHash(contextData);
1889
- planCache.contextData = { ...contextData };
1890
- }
1913
+ cache.yamlWorkflow = newRecord.yamlWorkflow;
1891
1914
  });
1892
1915
  } else {
1893
1916
  cachedRecord.updateFn((cache) => {
@@ -1895,11 +1918,6 @@ cache file: ${cacheFile}`
1895
1918
  });
1896
1919
  }
1897
1920
  } else {
1898
- if (newRecord.type === "plan" && contextData) {
1899
- const planRecord = newRecord;
1900
- planRecord.contextHash = this.generateContextHash(contextData);
1901
- planRecord.contextData = { ...contextData };
1902
- }
1903
1921
  this.appendCache(newRecord);
1904
1922
  }
1905
1923
  }
@@ -1929,13 +1947,10 @@ var PageAgent = class {
1929
1947
  generateReport: true,
1930
1948
  autoPrintReportMsg: true,
1931
1949
  groupName: "Midscene Report",
1932
- groupDescription: "",
1933
- enableCumulativeContext: true,
1934
- autoClearContext: false
1950
+ groupDescription: ""
1935
1951
  },
1936
1952
  opts || {}
1937
1953
  );
1938
- this.initializeContextStore();
1939
1954
  if (this.page.pageType === "puppeteer" || this.page.pageType === "playwright") {
1940
1955
  this.page.waitForNavigationTimeout = this.opts.waitForNavigationTimeout || import_constants2.DEFAULT_WAIT_FOR_NAVIGATION_TIMEOUT;
1941
1956
  this.page.waitForNetworkIdleTimeout = this.opts.waitForNetworkIdleTimeout || import_constants2.DEFAULT_WAIT_FOR_NETWORK_IDLE_TIMEOUT;
@@ -1962,69 +1977,6 @@ var PageAgent = class {
1962
1977
  opts?.testId || this.page.pageType || "web"
1963
1978
  );
1964
1979
  }
1965
- /**
1966
- * Initialize context store for cumulative context functionality
1967
- */
1968
- async initializeContextStore() {
1969
- if (!this.opts.enableCumulativeContext) {
1970
- debug4("Cumulative context disabled via options");
1971
- return;
1972
- }
1973
- try {
1974
- const aiModel = await import("misoai-core/ai-model");
1975
- this.contextStore = aiModel.getContextStore();
1976
- debug4("Context store initialized successfully", {
1977
- autoClearContext: this.opts.autoClearContext,
1978
- testId: this.opts.testId
1979
- });
1980
- if (this.opts.autoClearContext) {
1981
- this.contextStore.clear();
1982
- debug4("Context store cleared due to autoClearContext option");
1983
- } else {
1984
- const existingData = this.contextStore.getAllData();
1985
- const existingSteps = this.contextStore.getRecentSteps(100).length;
1986
- debug4("Context store preserving existing data", {
1987
- existingDataKeys: Object.keys(existingData),
1988
- existingStepsCount: existingSteps
1989
- });
1990
- }
1991
- } catch (error) {
1992
- debug4("Failed to initialize context store:", error);
1993
- console.warn("⚠️ Could not initialize context store:", error);
1994
- }
1995
- }
1996
- /**
1997
- * Get the context store instance
1998
- */
1999
- getContextStore() {
2000
- return this.contextStore;
2001
- }
2002
- /**
2003
- * Clear the context store
2004
- */
2005
- clearContext() {
2006
- if (this.contextStore) {
2007
- this.contextStore.clear();
2008
- }
2009
- }
2010
- /**
2011
- * Get all stored data from context store
2012
- */
2013
- getStoredData() {
2014
- if (this.contextStore) {
2015
- return this.contextStore.getAllData();
2016
- }
2017
- return {};
2018
- }
2019
- /**
2020
- * Get step summary from context store
2021
- */
2022
- getStepSummary() {
2023
- if (this.contextStore) {
2024
- return this.contextStore.getStepSummary();
2025
- }
2026
- return "";
2027
- }
2028
1980
  async getUIContext(action) {
2029
1981
  if (action && (action === "extract" || action === "assert" || action === "captcha")) {
2030
1982
  return await parseContextFromWebPage(this.page, {
@@ -2203,6 +2155,23 @@ var PageAgent = class {
2203
2155
  metadata
2204
2156
  };
2205
2157
  }
2158
+ async aiRightClick(locatePrompt, opt) {
2159
+ const detailedLocateParam = this.buildDetailedLocateParam(
2160
+ locatePrompt,
2161
+ opt
2162
+ );
2163
+ const plans = buildPlans("RightClick", detailedLocateParam);
2164
+ const { executor, output } = await this.taskExecutor.runPlans(
2165
+ taskTitleStr("RightClick", locateParamStr(detailedLocateParam)),
2166
+ plans,
2167
+ { cacheable: opt?.cacheable }
2168
+ );
2169
+ const metadata = this.afterTaskRunning(executor);
2170
+ return {
2171
+ result: output,
2172
+ metadata
2173
+ };
2174
+ }
2206
2175
  async aiInput(value, locatePrompt, opt) {
2207
2176
  (0, import_utils12.assert)(
2208
2177
  typeof value === "string",
@@ -2260,35 +2229,9 @@ var PageAgent = class {
2260
2229
  };
2261
2230
  }
2262
2231
  async aiAction(taskPrompt, opt) {
2263
- const originalPrompt = taskPrompt;
2264
- let processedPrompt = taskPrompt;
2265
- if (this.opts.enableCumulativeContext && this.contextStore) {
2266
- try {
2267
- const storedData = this.contextStore.getAllData();
2268
- if (Object.keys(storedData).length > 0) {
2269
- debug4("Available data for aiAction:", {
2270
- prompt: taskPrompt,
2271
- availableData: storedData
2272
- });
2273
- }
2274
- } catch (error) {
2275
- debug4("Context store operation failed:", error);
2276
- }
2277
- }
2278
2232
  const cacheable = opt?.cacheable;
2279
2233
  const isVlmUiTars = (0, import_env2.vlLocateMode)() === "vlm-ui-tars";
2280
- let contextData;
2281
- if (this.opts.enableCumulativeContext && this.contextStore) {
2282
- try {
2283
- contextData = this.contextStore.getAllData();
2284
- if (contextData && Object.keys(contextData).length === 0) {
2285
- contextData = void 0;
2286
- }
2287
- } catch (error) {
2288
- debug4("Failed to get context data for cache:", error);
2289
- }
2290
- }
2291
- const matchedCache = isVlmUiTars || cacheable === false ? void 0 : this.taskCache?.matchPlanCache(taskPrompt, contextData);
2234
+ const matchedCache = isVlmUiTars || cacheable === false ? void 0 : this.taskCache?.matchPlanCache(taskPrompt);
2292
2235
  if (matchedCache && this.taskCache?.isCacheResultUsed) {
2293
2236
  const { executor: executor2 } = await this.taskExecutor.loadYamlFlowAsPlanning(
2294
2237
  taskPrompt,
@@ -2298,28 +2241,6 @@ var PageAgent = class {
2298
2241
  debug4("matched cache, will call .runYaml to run the action");
2299
2242
  const yaml5 = matchedCache.cacheContent?.yamlWorkflow;
2300
2243
  const result = await this.runYaml(yaml5);
2301
- if (this.opts.enableCumulativeContext && this.contextStore) {
2302
- try {
2303
- const executionResult = {
2304
- success: true,
2305
- actionType: "cached",
2306
- description: `Executed cached action: ${processedPrompt}`,
2307
- timing: result.metadata?.totalTime
2308
- };
2309
- this.contextStore.addStep({
2310
- type: "action",
2311
- summary: `Action: ${processedPrompt} (cached)`,
2312
- prompt: processedPrompt,
2313
- executionResult
2314
- });
2315
- debug4("Added cached action step to context store:", {
2316
- stepNumber: this.contextStore.getRecentSteps(1)[0]?.stepNumber,
2317
- totalSteps: this.contextStore.getRecentSteps(100).length
2318
- });
2319
- } catch (error) {
2320
- debug4("Failed to add cached action step:", error);
2321
- }
2322
- }
2323
2244
  return {
2324
2245
  result: result.result,
2325
2246
  metadata: metadata2
@@ -2344,114 +2265,17 @@ var PageAgent = class {
2344
2265
  prompt: taskPrompt,
2345
2266
  yamlWorkflow: yamlFlowStr
2346
2267
  },
2347
- matchedCache,
2348
- contextData
2349
- // Pass context data for cache creation
2268
+ matchedCache
2350
2269
  );
2351
2270
  }
2352
2271
  const metadata = this.afterTaskRunning(executor);
2353
- if (this.opts.enableCumulativeContext && this.contextStore) {
2354
- try {
2355
- const executionResult = this.analyzeExecutionResults(executor, originalPrompt);
2356
- this.contextStore.addStep({
2357
- type: "action",
2358
- summary: `Action: ${processedPrompt}`,
2359
- prompt: processedPrompt,
2360
- executionResult
2361
- });
2362
- debug4("Added action step with execution result to context store:", {
2363
- stepNumber: this.contextStore.getRecentSteps(1)[0]?.stepNumber,
2364
- totalSteps: this.contextStore.getRecentSteps(100).length,
2365
- executionResult
2366
- });
2367
- } catch (error) {
2368
- debug4("Failed to analyze execution results, adding step without execution result:", error);
2369
- try {
2370
- this.contextStore.addStep({
2371
- type: "action",
2372
- summary: `Action: ${processedPrompt}`,
2373
- prompt: processedPrompt
2374
- });
2375
- } catch (stepError) {
2376
- debug4("Failed to add action step:", stepError);
2377
- }
2378
- }
2379
- }
2380
2272
  return {
2381
2273
  result: output,
2382
2274
  metadata
2383
2275
  };
2384
2276
  }
2385
2277
  async aiQuery(demand) {
2386
- let processedDemand = demand;
2387
- let storageKey;
2388
- try {
2389
- const aiModel = await import("misoai-core/ai-model");
2390
- const contextStore = aiModel.getContextStore();
2391
- if (typeof demand === "string") {
2392
- const storageInstruction = contextStore.parseStorageInstruction(demand);
2393
- if (storageInstruction) {
2394
- storageKey = storageInstruction.key;
2395
- processedDemand = storageInstruction.cleanText;
2396
- contextStore._pendingAliases = storageInstruction.aliases;
2397
- } else {
2398
- const storageMatch = demand.match(/store\s+(?:as\s+)?(\w+)/i);
2399
- if (storageMatch) {
2400
- storageKey = storageMatch[1];
2401
- processedDemand = demand.replace(/,?\s*store\s+(?:as\s+)?\w+/i, "").trim();
2402
- }
2403
- }
2404
- }
2405
- } catch (error) {
2406
- debug4("Context store not available:", error);
2407
- }
2408
- const { output, executor } = await this.taskExecutor.query(processedDemand);
2409
- if (this.opts.enableCumulativeContext && this.contextStore) {
2410
- if (storageKey && output) {
2411
- try {
2412
- const pendingAliases = this.contextStore._pendingAliases;
2413
- if (pendingAliases) {
2414
- this.contextStore.storeDataWithAliases(storageKey, output, pendingAliases, typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand));
2415
- delete this.contextStore._pendingAliases;
2416
- debug4("Stored query result with aliases:", {
2417
- key: storageKey,
2418
- value: output,
2419
- aliases: pendingAliases
2420
- });
2421
- } else {
2422
- this.contextStore.storeData(storageKey, output);
2423
- debug4("Stored query result:", {
2424
- key: storageKey,
2425
- value: output
2426
- });
2427
- }
2428
- this.contextStore.addStep({
2429
- type: "query",
2430
- summary: `Query: ${typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand)} (stored as ${storageKey})`,
2431
- data: output,
2432
- prompt: typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand)
2433
- });
2434
- debug4("Added query step to context store:", {
2435
- storageKey,
2436
- totalStoredItems: Object.keys(this.contextStore.getAllData()).length,
2437
- totalSteps: this.contextStore.getRecentSteps(100).length
2438
- });
2439
- } catch (error) {
2440
- debug4("Failed to store query result:", error);
2441
- }
2442
- } else {
2443
- try {
2444
- this.contextStore.addStep({
2445
- type: "query",
2446
- summary: `Query: ${typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand)}`,
2447
- data: output,
2448
- prompt: typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand)
2449
- });
2450
- } catch (error) {
2451
- debug4("Failed to add query step:", error);
2452
- }
2453
- }
2454
- }
2278
+ const { output, executor } = await this.taskExecutor.query(demand);
2455
2279
  const metadata = this.afterTaskRunning(executor);
2456
2280
  return {
2457
2281
  result: output,
@@ -2561,48 +2385,6 @@ var PageAgent = class {
2561
2385
  };
2562
2386
  }
2563
2387
  async aiAssert(assertion, msg, opt) {
2564
- let executionContext = "";
2565
- if (this.opts.enableCumulativeContext && this.contextStore) {
2566
- try {
2567
- const recentSteps = this.contextStore.getRecentSteps(3);
2568
- const stepsWithExecutionResults = recentSteps.filter((step) => step.executionResult);
2569
- const storedData = this.contextStore.getAllData();
2570
- if (stepsWithExecutionResults.length > 0) {
2571
- const recentActions = stepsWithExecutionResults.map((step) => {
2572
- const result = step.executionResult;
2573
- return `- ${result.description}${result.success ? "" : " (FAILED)"}`;
2574
- }).join("\n");
2575
- executionContext = `
2576
-
2577
- Recent actions performed:
2578
- ${recentActions}
2579
-
2580
- This context may help verify the assertion.`;
2581
- }
2582
- if (storedData && Object.keys(storedData).length > 0) {
2583
- executionContext += `
2584
-
2585
- Available data for reference:
2586
- ${JSON.stringify(storedData, null, 2)}
2587
-
2588
- Note: If the assertion references any data keys or natural language equivalents, consider the stored values when verifying.`;
2589
- debug4("Available data for aiAssert:", {
2590
- assertion,
2591
- availableData: storedData
2592
- });
2593
- }
2594
- this.contextStore.addStep({
2595
- type: "assertion",
2596
- summary: `Assertion: ${assertion}`,
2597
- prompt: assertion
2598
- });
2599
- debug4("Added assertion step to context store:", {
2600
- totalSteps: this.contextStore.getRecentSteps(100).length
2601
- });
2602
- } catch (error) {
2603
- debug4("Context store operation failed:", error);
2604
- }
2605
- }
2606
2388
  let currentUrl = "";
2607
2389
  if (this.page.url) {
2608
2390
  try {
@@ -2610,13 +2392,7 @@ Note: If the assertion references any data keys or natural language equivalents,
2610
2392
  } catch (e) {
2611
2393
  }
2612
2394
  }
2613
- let assertionWithContext = assertion;
2614
- if (currentUrl) {
2615
- assertionWithContext = `For the page at URL "${currentUrl}", ${assertion}`;
2616
- }
2617
- if (executionContext) {
2618
- assertionWithContext += executionContext;
2619
- }
2395
+ const assertionWithContext = currentUrl ? `For the page at URL "${currentUrl}", ${assertion}` : assertion;
2620
2396
  const { output, executor } = await this.taskExecutor.assert(assertionWithContext);
2621
2397
  const metadata = this.afterTaskRunning(executor, true);
2622
2398
  if (output && opt?.keepRawResponse) {
@@ -2827,81 +2603,42 @@ ${errors}`);
2827
2603
  }
2828
2604
  throw new Error("evaluateJavaScript is not supported in current agent");
2829
2605
  }
2830
- async destroy() {
2831
- await this.page.destroy();
2832
- }
2833
- /**
2834
- * Analyze execution results from executor to generate meaningful descriptions
2835
- */
2836
- analyzeExecutionResults(executor, originalPrompt) {
2837
- const tasks = executor.tasks;
2838
- const success = !executor.isInErrorState();
2839
- if (!success) {
2840
- const errorTask = executor.latestErrorTask();
2841
- return {
2842
- success: false,
2843
- actionType: "error",
2844
- description: `Failed to execute: ${originalPrompt}`,
2845
- error: errorTask?.error
2846
- };
2847
- }
2848
- const actionTasks = tasks.filter((t) => t.type === "Action" && t.status === "finished");
2849
- const locateTasks = tasks.filter((t) => t.type === "Insight" && t.subType === "Locate");
2850
- const lastAction = actionTasks[actionTasks.length - 1];
2851
- const lastLocate = locateTasks[locateTasks.length - 1];
2852
- if (!lastAction) {
2853
- return {
2854
- success: true,
2855
- actionType: "unknown",
2856
- description: `Completed: ${originalPrompt}`
2606
+ async logScreenshot(title, options) {
2607
+ const screenshotTitle = title || "untitled";
2608
+ const content = options?.content || "";
2609
+ const screenshot = await this.page.screenshotBase64?.();
2610
+ if (screenshot) {
2611
+ const executionDump = {
2612
+ name: screenshotTitle,
2613
+ description: content,
2614
+ tasks: [{
2615
+ type: "Screenshot",
2616
+ subType: "log",
2617
+ status: "finished",
2618
+ executor: null,
2619
+ param: {
2620
+ title: screenshotTitle,
2621
+ content
2622
+ },
2623
+ output: {
2624
+ screenshot
2625
+ },
2626
+ thought: `Logged screenshot: ${screenshotTitle}`,
2627
+ timing: {
2628
+ start: Date.now(),
2629
+ end: Date.now(),
2630
+ cost: 0
2631
+ }
2632
+ }],
2633
+ sdkVersion: "1.0.0",
2634
+ logTime: Date.now(),
2635
+ model_name: "screenshot"
2857
2636
  };
2637
+ this.appendExecutionDump(executionDump);
2858
2638
  }
2859
- const actionType = lastAction.subType || "unknown";
2860
- const elementInfo = this.extractElementInfo(lastLocate, lastAction);
2861
- const description = this.generateActionDescription(actionType, lastAction.param, elementInfo);
2862
- return {
2863
- success: true,
2864
- actionType,
2865
- description,
2866
- elementInfo,
2867
- timing: lastAction.timing?.cost
2868
- };
2869
2639
  }
2870
- /**
2871
- * Extract element information from locate task
2872
- */
2873
- extractElementInfo(locateTask, _actionTask) {
2874
- if (!locateTask?.output?.element)
2875
- return void 0;
2876
- const element = locateTask.output.element;
2877
- return {
2878
- type: element.attributes?.nodeType || "unknown",
2879
- text: element.content || element.attributes?.placeholder || element.attributes?.title || "",
2880
- location: `(${element.center[0]}, ${element.center[1]})`
2881
- };
2882
- }
2883
- /**
2884
- * Generate natural language description for actions
2885
- */
2886
- generateActionDescription(actionType, param, elementInfo) {
2887
- const elementDesc = elementInfo ? `'${elementInfo.text || elementInfo.type}' element` : "element";
2888
- switch (actionType) {
2889
- case "Tap":
2890
- return `Clicked on ${elementDesc}`;
2891
- case "Input":
2892
- const inputValue = param?.value || "";
2893
- return `Entered "${inputValue}" into ${elementDesc}`;
2894
- case "KeyboardPress":
2895
- return `Pressed ${param?.value || "key"}`;
2896
- case "Scroll":
2897
- return `Scrolled ${param?.direction || "on page"}`;
2898
- case "Hover":
2899
- return `Hovered over ${elementDesc}`;
2900
- case "Drag":
2901
- return `Dragged ${elementDesc}`;
2902
- default:
2903
- return `Performed ${actionType} action on ${elementDesc}`;
2904
- }
2640
+ async destroy() {
2641
+ await this.page.destroy();
2905
2642
  }
2906
2643
  };
2907
2644
 
@@ -2918,7 +2655,7 @@ var Page = class {
2918
2655
  this.everMoved = false;
2919
2656
  this.underlyingPage = underlyingPage;
2920
2657
  this.pageType = pageType;
2921
- this.waitForNavigationTimeout = opts?.waitForNavigationTimeout || import_constants3.DEFAULT_WAIT_FOR_NAVIGATION_TIMEOUT;
2658
+ this.waitForNavigationTimeout = opts?.waitForNavigationTimeout ?? import_constants3.DEFAULT_WAIT_FOR_NAVIGATION_TIMEOUT;
2922
2659
  }
2923
2660
  async evaluate(pageFunction, arg) {
2924
2661
  let result;
@@ -3323,6 +3060,14 @@ var PlaywrightAiFixture = (options) => {
3323
3060
  aiActionType: "aiTap"
3324
3061
  });
3325
3062
  },
3063
+ aiRightClick: async ({ page }, use, testInfo) => {
3064
+ await generateAiFunction({
3065
+ page,
3066
+ testInfo,
3067
+ use,
3068
+ aiActionType: "aiRightClick"
3069
+ });
3070
+ },
3326
3071
  aiHover: async ({ page }, use, testInfo) => {
3327
3072
  await generateAiFunction({
3328
3073
  page,
@@ -3410,6 +3155,14 @@ var PlaywrightAiFixture = (options) => {
3410
3155
  use,
3411
3156
  aiActionType: "aiBoolean"
3412
3157
  });
3158
+ },
3159
+ logScreenshot: async ({ page }, use, testInfo) => {
3160
+ await generateAiFunction({
3161
+ page,
3162
+ testInfo,
3163
+ use,
3164
+ aiActionType: "logScreenshot"
3165
+ });
3413
3166
  }
3414
3167
  };
3415
3168
  };
@@ -3449,9 +3202,9 @@ var WebPage2 = class extends Page {
3449
3202
  }
3450
3203
  async waitUntilNetworkIdle(options) {
3451
3204
  await this.underlyingPage.waitForNetworkIdle({
3452
- idleTime: options?.idleTime || import_constants4.DEFAULT_WAIT_FOR_NETWORK_IDLE_TIME,
3453
- concurrency: options?.concurrency || import_constants4.DEFAULT_WAIT_FOR_NETWORK_IDLE_CONCURRENCY,
3454
- timeout: options?.timeout || this.waitForNetworkIdleTimeout
3205
+ idleTime: options?.idleTime ?? import_constants4.DEFAULT_WAIT_FOR_NETWORK_IDLE_TIME,
3206
+ concurrency: options?.concurrency ?? import_constants4.DEFAULT_WAIT_FOR_NETWORK_IDLE_CONCURRENCY,
3207
+ timeout: options?.timeout ?? this.waitForNetworkIdleTimeout
3455
3208
  });
3456
3209
  }
3457
3210
  };