misoai-web 1.0.4 → 1.0.6

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 (68) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +353 -9
  3. package/bin/midscene-playground +2 -2
  4. package/dist/es/agent.js +378 -92
  5. package/dist/es/agent.js.map +1 -1
  6. package/dist/es/bridge-mode-browser.js +3 -3
  7. package/dist/es/bridge-mode-browser.js.map +1 -1
  8. package/dist/es/bridge-mode.js +380 -94
  9. package/dist/es/bridge-mode.js.map +1 -1
  10. package/dist/es/chrome-extension.js +379 -93
  11. package/dist/es/chrome-extension.js.map +1 -1
  12. package/dist/es/index.js +378 -92
  13. package/dist/es/index.js.map +1 -1
  14. package/dist/es/midscene-playground.js +378 -92
  15. package/dist/es/midscene-playground.js.map +1 -1
  16. package/dist/es/midscene-server.js.map +1 -1
  17. package/dist/es/playground.js +378 -92
  18. package/dist/es/playground.js.map +1 -1
  19. package/dist/es/playwright-report.js.map +1 -1
  20. package/dist/es/playwright.js +378 -92
  21. package/dist/es/playwright.js.map +1 -1
  22. package/dist/es/puppeteer-agent-launcher.js +378 -92
  23. package/dist/es/puppeteer-agent-launcher.js.map +1 -1
  24. package/dist/es/puppeteer.js +378 -92
  25. package/dist/es/puppeteer.js.map +1 -1
  26. package/dist/es/ui-utils.js.map +1 -1
  27. package/dist/es/utils.js.map +1 -1
  28. package/dist/es/yaml.js.map +1 -1
  29. package/dist/lib/agent.js +378 -92
  30. package/dist/lib/agent.js.map +1 -1
  31. package/dist/lib/bridge-mode-browser.js +3 -3
  32. package/dist/lib/bridge-mode-browser.js.map +1 -1
  33. package/dist/lib/bridge-mode.js +380 -94
  34. package/dist/lib/bridge-mode.js.map +1 -1
  35. package/dist/lib/chrome-extension.js +379 -93
  36. package/dist/lib/chrome-extension.js.map +1 -1
  37. package/dist/lib/index.js +378 -92
  38. package/dist/lib/index.js.map +1 -1
  39. package/dist/lib/midscene-playground.js +378 -92
  40. package/dist/lib/midscene-playground.js.map +1 -1
  41. package/dist/lib/midscene-server.js.map +1 -1
  42. package/dist/lib/playground.js +378 -92
  43. package/dist/lib/playground.js.map +1 -1
  44. package/dist/lib/playwright-report.js.map +1 -1
  45. package/dist/lib/playwright.js +378 -92
  46. package/dist/lib/playwright.js.map +1 -1
  47. package/dist/lib/puppeteer-agent-launcher.js +378 -92
  48. package/dist/lib/puppeteer-agent-launcher.js.map +1 -1
  49. package/dist/lib/puppeteer.js +378 -92
  50. package/dist/lib/puppeteer.js.map +1 -1
  51. package/dist/lib/ui-utils.js.map +1 -1
  52. package/dist/lib/utils.js.map +1 -1
  53. package/dist/lib/yaml.js.map +1 -1
  54. package/dist/types/agent.d.ts +45 -4
  55. package/dist/types/bridge-mode-browser.d.ts +2 -2
  56. package/dist/types/bridge-mode.d.ts +2 -2
  57. package/dist/types/{browser-a1877d18.d.ts → browser-aec1055d.d.ts} +1 -1
  58. package/dist/types/chrome-extension.d.ts +2 -2
  59. package/dist/types/index.d.ts +1 -1
  60. package/dist/types/midscene-server.d.ts +1 -1
  61. package/dist/types/{page-663ece08.d.ts → page-86ab0fe1.d.ts} +34 -34
  62. package/dist/types/playground.d.ts +2 -2
  63. package/dist/types/playwright.d.ts +1 -1
  64. package/dist/types/puppeteer-agent-launcher.d.ts +1 -1
  65. package/dist/types/puppeteer.d.ts +1 -1
  66. package/dist/types/utils.d.ts +1 -1
  67. package/dist/types/yaml.d.ts +1 -1
  68. package/package.json +3 -3
package/dist/lib/agent.js CHANGED
@@ -1674,7 +1674,7 @@ var import_js_yaml3 = __toESM(require("js-yaml"));
1674
1674
  var import_semver = __toESM(require("semver"));
1675
1675
 
1676
1676
  // package.json
1677
- var version = "1.0.4";
1677
+ var version = "1.0.5";
1678
1678
 
1679
1679
  // src/common/task-cache.ts
1680
1680
  var debug3 = (0, import_logger3.getDebug)("cache");
@@ -1702,44 +1702,70 @@ var TaskCache = class {
1702
1702
  this.cache = cacheContent;
1703
1703
  this.cacheOriginalLength = this.cache.caches.length;
1704
1704
  }
1705
- matchCache(prompt, type) {
1705
+ matchCache(prompt, type, contextData) {
1706
+ const contextHash = contextData ? this.generateContextHash(contextData) : void 0;
1706
1707
  for (let i = 0; i < this.cacheOriginalLength; i++) {
1707
1708
  const item = this.cache.caches[i];
1708
1709
  const key = `${type}:${prompt}:${i}`;
1709
- if (item.type === type && item.prompt === prompt && !this.matchedCacheIndices.has(key)) {
1710
- this.matchedCacheIndices.add(key);
1711
- debug3(
1712
- "cache found and marked as used, type: %s, prompt: %s, index: %d",
1713
- type,
1714
- prompt,
1715
- i
1716
- );
1717
- return {
1718
- cacheContent: item,
1719
- updateFn: (cb) => {
1720
- debug3(
1721
- "will call updateFn to update cache, type: %s, prompt: %s, index: %d",
1722
- type,
1723
- prompt,
1724
- i
1725
- );
1726
- cb(item);
1727
- debug3(
1728
- "cache updated, will flush to file, type: %s, prompt: %s, index: %d",
1729
- type,
1730
- prompt,
1731
- i
1732
- );
1733
- this.flushCacheToFile();
1710
+ if (item.type !== type || item.prompt !== prompt || this.matchedCacheIndices.has(key)) {
1711
+ continue;
1712
+ }
1713
+ if (type === "plan" && item.type === "plan") {
1714
+ const planItem = item;
1715
+ if (contextHash && planItem.contextHash) {
1716
+ if (contextHash !== planItem.contextHash) {
1717
+ debug3("cache context mismatch, type: %s, prompt: %s, index: %d", type, prompt, i);
1718
+ continue;
1734
1719
  }
1735
- };
1720
+ } else if (contextHash || planItem.contextHash) {
1721
+ debug3("cache context availability mismatch, type: %s, prompt: %s, index: %d", type, prompt, i);
1722
+ continue;
1723
+ }
1736
1724
  }
1725
+ this.matchedCacheIndices.add(key);
1726
+ debug3(
1727
+ "cache found and marked as used, type: %s, prompt: %s, index: %d, contextMatch: %s",
1728
+ type,
1729
+ prompt,
1730
+ i,
1731
+ contextHash ? "yes" : "no-context"
1732
+ );
1733
+ return {
1734
+ cacheContent: item,
1735
+ updateFn: (cb) => {
1736
+ debug3(
1737
+ "will call updateFn to update cache, type: %s, prompt: %s, index: %d",
1738
+ type,
1739
+ prompt,
1740
+ i
1741
+ );
1742
+ cb(item);
1743
+ debug3(
1744
+ "cache updated, will flush to file, type: %s, prompt: %s, index: %d",
1745
+ type,
1746
+ prompt,
1747
+ i
1748
+ );
1749
+ this.flushCacheToFile();
1750
+ }
1751
+ };
1737
1752
  }
1738
- debug3("no unused cache found, type: %s, prompt: %s", type, prompt);
1753
+ debug3("no unused cache found, type: %s, prompt: %s, contextHash: %s", type, prompt, contextHash);
1739
1754
  return void 0;
1740
1755
  }
1741
- matchPlanCache(prompt) {
1742
- return this.matchCache(prompt, "plan");
1756
+ generateContextHash(contextData) {
1757
+ const sortedKeys = Object.keys(contextData).sort();
1758
+ const stableString = sortedKeys.map((key) => `${key}:${JSON.stringify(contextData[key])}`).join("|");
1759
+ let hash = 0;
1760
+ for (let i = 0; i < stableString.length; i++) {
1761
+ const char = stableString.charCodeAt(i);
1762
+ hash = (hash << 5) - hash + char;
1763
+ hash = hash & hash;
1764
+ }
1765
+ return hash.toString(36);
1766
+ }
1767
+ matchPlanCache(prompt, contextData) {
1768
+ return this.matchCache(prompt, "plan", contextData);
1743
1769
  }
1744
1770
  matchLocateCache(prompt) {
1745
1771
  return this.matchCache(prompt, "locate");
@@ -1815,11 +1841,16 @@ cache file: ${cacheFile}`
1815
1841
  );
1816
1842
  }
1817
1843
  }
1818
- updateOrAppendCacheRecord(newRecord, cachedRecord) {
1844
+ updateOrAppendCacheRecord(newRecord, cachedRecord, contextData) {
1819
1845
  if (cachedRecord) {
1820
1846
  if (newRecord.type === "plan") {
1821
1847
  cachedRecord.updateFn((cache) => {
1822
- cache.yamlWorkflow = newRecord.yamlWorkflow;
1848
+ const planCache = cache;
1849
+ planCache.yamlWorkflow = newRecord.yamlWorkflow;
1850
+ if (contextData) {
1851
+ planCache.contextHash = this.generateContextHash(contextData);
1852
+ planCache.contextData = { ...contextData };
1853
+ }
1823
1854
  });
1824
1855
  } else {
1825
1856
  cachedRecord.updateFn((cache) => {
@@ -1827,6 +1858,11 @@ cache file: ${cacheFile}`
1827
1858
  });
1828
1859
  }
1829
1860
  } else {
1861
+ if (newRecord.type === "plan" && contextData) {
1862
+ const planRecord = newRecord;
1863
+ planRecord.contextHash = this.generateContextHash(contextData);
1864
+ planRecord.contextData = { ...contextData };
1865
+ }
1830
1866
  this.appendCache(newRecord);
1831
1867
  }
1832
1868
  }
@@ -1856,10 +1892,13 @@ var PageAgent = class {
1856
1892
  generateReport: true,
1857
1893
  autoPrintReportMsg: true,
1858
1894
  groupName: "Midscene Report",
1859
- groupDescription: ""
1895
+ groupDescription: "",
1896
+ enableCumulativeContext: true,
1897
+ autoClearContext: false
1860
1898
  },
1861
1899
  opts || {}
1862
1900
  );
1901
+ this.initializeContextStore();
1863
1902
  if (this.page.pageType === "puppeteer" || this.page.pageType === "playwright") {
1864
1903
  this.page.waitForNavigationTimeout = this.opts.waitForNavigationTimeout || import_constants2.DEFAULT_WAIT_FOR_NAVIGATION_TIMEOUT;
1865
1904
  this.page.waitForNetworkIdleTimeout = this.opts.waitForNetworkIdleTimeout || import_constants2.DEFAULT_WAIT_FOR_NETWORK_IDLE_TIMEOUT;
@@ -1886,6 +1925,69 @@ var PageAgent = class {
1886
1925
  opts?.testId || this.page.pageType || "web"
1887
1926
  );
1888
1927
  }
1928
+ /**
1929
+ * Initialize context store for cumulative context functionality
1930
+ */
1931
+ async initializeContextStore() {
1932
+ if (!this.opts.enableCumulativeContext) {
1933
+ debug4("Cumulative context disabled via options");
1934
+ return;
1935
+ }
1936
+ try {
1937
+ const aiModel = await import("misoai-core/ai-model");
1938
+ this.contextStore = aiModel.getContextStore();
1939
+ debug4("Context store initialized successfully", {
1940
+ autoClearContext: this.opts.autoClearContext,
1941
+ testId: this.opts.testId
1942
+ });
1943
+ if (this.opts.autoClearContext) {
1944
+ this.contextStore.clear();
1945
+ debug4("Context store cleared due to autoClearContext option");
1946
+ } else {
1947
+ const existingData = this.contextStore.getAllData();
1948
+ const existingSteps = this.contextStore.getRecentSteps(100).length;
1949
+ debug4("Context store preserving existing data", {
1950
+ existingDataKeys: Object.keys(existingData),
1951
+ existingStepsCount: existingSteps
1952
+ });
1953
+ }
1954
+ } catch (error) {
1955
+ debug4("Failed to initialize context store:", error);
1956
+ console.warn("⚠️ Could not initialize context store:", error);
1957
+ }
1958
+ }
1959
+ /**
1960
+ * Get the context store instance
1961
+ */
1962
+ getContextStore() {
1963
+ return this.contextStore;
1964
+ }
1965
+ /**
1966
+ * Clear the context store
1967
+ */
1968
+ clearContext() {
1969
+ if (this.contextStore) {
1970
+ this.contextStore.clear();
1971
+ }
1972
+ }
1973
+ /**
1974
+ * Get all stored data from context store
1975
+ */
1976
+ getStoredData() {
1977
+ if (this.contextStore) {
1978
+ return this.contextStore.getAllData();
1979
+ }
1980
+ return {};
1981
+ }
1982
+ /**
1983
+ * Get step summary from context store
1984
+ */
1985
+ getStepSummary() {
1986
+ if (this.contextStore) {
1987
+ return this.contextStore.getStepSummary();
1988
+ }
1989
+ return "";
1990
+ }
1889
1991
  async getUIContext(action) {
1890
1992
  if (action && (action === "extract" || action === "assert" || action === "captcha")) {
1891
1993
  return await parseContextFromWebPage(this.page, {
@@ -2121,22 +2223,35 @@ var PageAgent = class {
2121
2223
  };
2122
2224
  }
2123
2225
  async aiAction(taskPrompt, opt) {
2124
- try {
2125
- const aiModel = await import("misoai-core/ai-model");
2126
- const contextStore = aiModel.getContextStore();
2127
- const processedPrompt = contextStore.replaceAllReferences(taskPrompt, "action");
2128
- contextStore.addStep({
2129
- type: "action",
2130
- summary: `Action: ${processedPrompt}`,
2131
- prompt: processedPrompt
2132
- });
2133
- taskPrompt = processedPrompt;
2134
- } catch (error) {
2135
- debug4("Context store not available:", error);
2226
+ const originalPrompt = taskPrompt;
2227
+ let processedPrompt = taskPrompt;
2228
+ if (this.opts.enableCumulativeContext && this.contextStore) {
2229
+ try {
2230
+ const storedData = this.contextStore.getAllData();
2231
+ if (Object.keys(storedData).length > 0) {
2232
+ debug4("Available data for aiAction:", {
2233
+ prompt: taskPrompt,
2234
+ availableData: storedData
2235
+ });
2236
+ }
2237
+ } catch (error) {
2238
+ debug4("Context store operation failed:", error);
2239
+ }
2136
2240
  }
2137
2241
  const cacheable = opt?.cacheable;
2138
2242
  const isVlmUiTars = (0, import_env2.vlLocateMode)() === "vlm-ui-tars";
2139
- const matchedCache = isVlmUiTars || cacheable === false ? void 0 : this.taskCache?.matchPlanCache(taskPrompt);
2243
+ let contextData;
2244
+ if (this.opts.enableCumulativeContext && this.contextStore) {
2245
+ try {
2246
+ contextData = this.contextStore.getAllData();
2247
+ if (contextData && Object.keys(contextData).length === 0) {
2248
+ contextData = void 0;
2249
+ }
2250
+ } catch (error) {
2251
+ debug4("Failed to get context data for cache:", error);
2252
+ }
2253
+ }
2254
+ const matchedCache = isVlmUiTars || cacheable === false ? void 0 : this.taskCache?.matchPlanCache(taskPrompt, contextData);
2140
2255
  if (matchedCache && this.taskCache?.isCacheResultUsed) {
2141
2256
  const { executor: executor2 } = await this.taskExecutor.loadYamlFlowAsPlanning(
2142
2257
  taskPrompt,
@@ -2146,6 +2261,28 @@ var PageAgent = class {
2146
2261
  debug4("matched cache, will call .runYaml to run the action");
2147
2262
  const yaml5 = matchedCache.cacheContent?.yamlWorkflow;
2148
2263
  const result = await this.runYaml(yaml5);
2264
+ if (this.opts.enableCumulativeContext && this.contextStore) {
2265
+ try {
2266
+ const executionResult = {
2267
+ success: true,
2268
+ actionType: "cached",
2269
+ description: `Executed cached action: ${processedPrompt}`,
2270
+ timing: result.metadata?.totalTime
2271
+ };
2272
+ this.contextStore.addStep({
2273
+ type: "action",
2274
+ summary: `Action: ${processedPrompt} (cached)`,
2275
+ prompt: processedPrompt,
2276
+ executionResult
2277
+ });
2278
+ debug4("Added cached action step to context store:", {
2279
+ stepNumber: this.contextStore.getRecentSteps(1)[0]?.stepNumber,
2280
+ totalSteps: this.contextStore.getRecentSteps(100).length
2281
+ });
2282
+ } catch (error) {
2283
+ debug4("Failed to add cached action step:", error);
2284
+ }
2285
+ }
2149
2286
  return {
2150
2287
  result: result.result,
2151
2288
  metadata: metadata2
@@ -2170,10 +2307,39 @@ var PageAgent = class {
2170
2307
  prompt: taskPrompt,
2171
2308
  yamlWorkflow: yamlFlowStr
2172
2309
  },
2173
- matchedCache
2310
+ matchedCache,
2311
+ contextData
2312
+ // Pass context data for cache creation
2174
2313
  );
2175
2314
  }
2176
2315
  const metadata = this.afterTaskRunning(executor);
2316
+ if (this.opts.enableCumulativeContext && this.contextStore) {
2317
+ try {
2318
+ const executionResult = this.analyzeExecutionResults(executor, originalPrompt);
2319
+ this.contextStore.addStep({
2320
+ type: "action",
2321
+ summary: `Action: ${processedPrompt}`,
2322
+ prompt: processedPrompt,
2323
+ executionResult
2324
+ });
2325
+ debug4("Added action step with execution result to context store:", {
2326
+ stepNumber: this.contextStore.getRecentSteps(1)[0]?.stepNumber,
2327
+ totalSteps: this.contextStore.getRecentSteps(100).length,
2328
+ executionResult
2329
+ });
2330
+ } catch (error) {
2331
+ debug4("Failed to analyze execution results, adding step without execution result:", error);
2332
+ try {
2333
+ this.contextStore.addStep({
2334
+ type: "action",
2335
+ summary: `Action: ${processedPrompt}`,
2336
+ prompt: processedPrompt
2337
+ });
2338
+ } catch (stepError) {
2339
+ debug4("Failed to add action step:", stepError);
2340
+ }
2341
+ }
2342
+ }
2177
2343
  return {
2178
2344
  result: output,
2179
2345
  metadata
@@ -2203,38 +2369,50 @@ var PageAgent = class {
2203
2369
  debug4("Context store not available:", error);
2204
2370
  }
2205
2371
  const { output, executor } = await this.taskExecutor.query(processedDemand);
2206
- if (storageKey && output) {
2207
- try {
2208
- const aiModel = await import("misoai-core/ai-model");
2209
- const contextStore = aiModel.getContextStore();
2210
- const pendingAliases = contextStore._pendingAliases;
2211
- if (pendingAliases) {
2212
- contextStore.storeDataWithAliases(storageKey, output, pendingAliases, typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand));
2213
- delete contextStore._pendingAliases;
2214
- } else {
2215
- contextStore.storeData(storageKey, output);
2372
+ if (this.opts.enableCumulativeContext && this.contextStore) {
2373
+ if (storageKey && output) {
2374
+ try {
2375
+ const pendingAliases = this.contextStore._pendingAliases;
2376
+ if (pendingAliases) {
2377
+ this.contextStore.storeDataWithAliases(storageKey, output, pendingAliases, typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand));
2378
+ delete this.contextStore._pendingAliases;
2379
+ debug4("Stored query result with aliases:", {
2380
+ key: storageKey,
2381
+ value: output,
2382
+ aliases: pendingAliases
2383
+ });
2384
+ } else {
2385
+ this.contextStore.storeData(storageKey, output);
2386
+ debug4("Stored query result:", {
2387
+ key: storageKey,
2388
+ value: output
2389
+ });
2390
+ }
2391
+ this.contextStore.addStep({
2392
+ type: "query",
2393
+ summary: `Query: ${typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand)} (stored as ${storageKey})`,
2394
+ data: output,
2395
+ prompt: typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand)
2396
+ });
2397
+ debug4("Added query step to context store:", {
2398
+ storageKey,
2399
+ totalStoredItems: Object.keys(this.contextStore.getAllData()).length,
2400
+ totalSteps: this.contextStore.getRecentSteps(100).length
2401
+ });
2402
+ } catch (error) {
2403
+ debug4("Failed to store query result:", error);
2404
+ }
2405
+ } else {
2406
+ try {
2407
+ this.contextStore.addStep({
2408
+ type: "query",
2409
+ summary: `Query: ${typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand)}`,
2410
+ data: output,
2411
+ prompt: typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand)
2412
+ });
2413
+ } catch (error) {
2414
+ debug4("Failed to add query step:", error);
2216
2415
  }
2217
- contextStore.addStep({
2218
- type: "query",
2219
- summary: `Query: ${typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand)} (stored as ${storageKey})`,
2220
- data: output,
2221
- prompt: typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand)
2222
- });
2223
- } catch (error) {
2224
- debug4("Failed to store query result:", error);
2225
- }
2226
- } else {
2227
- try {
2228
- const aiModel = await import("misoai-core/ai-model");
2229
- const contextStore = aiModel.getContextStore();
2230
- contextStore.addStep({
2231
- type: "query",
2232
- summary: `Query: ${typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand)}`,
2233
- data: output,
2234
- prompt: typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand)
2235
- });
2236
- } catch (error) {
2237
- debug4("Failed to add query step:", error);
2238
2416
  }
2239
2417
  }
2240
2418
  const metadata = this.afterTaskRunning(executor);
@@ -2346,18 +2524,47 @@ var PageAgent = class {
2346
2524
  };
2347
2525
  }
2348
2526
  async aiAssert(assertion, msg, opt) {
2349
- let processedAssertion = assertion;
2350
- try {
2351
- const aiModel = await import("misoai-core/ai-model");
2352
- const contextStore = aiModel.getContextStore();
2353
- processedAssertion = contextStore.replaceAllReferences(assertion, "assertion");
2354
- contextStore.addStep({
2355
- type: "assertion",
2356
- summary: `Assertion: ${processedAssertion}`,
2357
- prompt: processedAssertion
2358
- });
2359
- } catch (error) {
2360
- debug4("Context store not available:", error);
2527
+ let executionContext = "";
2528
+ if (this.opts.enableCumulativeContext && this.contextStore) {
2529
+ try {
2530
+ const recentSteps = this.contextStore.getRecentSteps(3);
2531
+ const stepsWithExecutionResults = recentSteps.filter((step) => step.executionResult);
2532
+ const storedData = this.contextStore.getAllData();
2533
+ if (stepsWithExecutionResults.length > 0) {
2534
+ const recentActions = stepsWithExecutionResults.map((step) => {
2535
+ const result = step.executionResult;
2536
+ return `- ${result.description}${result.success ? "" : " (FAILED)"}`;
2537
+ }).join("\n");
2538
+ executionContext = `
2539
+
2540
+ Recent actions performed:
2541
+ ${recentActions}
2542
+
2543
+ This context may help verify the assertion.`;
2544
+ }
2545
+ if (storedData && Object.keys(storedData).length > 0) {
2546
+ executionContext += `
2547
+
2548
+ Available data for reference:
2549
+ ${JSON.stringify(storedData, null, 2)}
2550
+
2551
+ Note: If the assertion references any data keys or natural language equivalents, consider the stored values when verifying.`;
2552
+ debug4("Available data for aiAssert:", {
2553
+ assertion,
2554
+ availableData: storedData
2555
+ });
2556
+ }
2557
+ this.contextStore.addStep({
2558
+ type: "assertion",
2559
+ summary: `Assertion: ${assertion}`,
2560
+ prompt: assertion
2561
+ });
2562
+ debug4("Added assertion step to context store:", {
2563
+ totalSteps: this.contextStore.getRecentSteps(100).length
2564
+ });
2565
+ } catch (error) {
2566
+ debug4("Context store operation failed:", error);
2567
+ }
2361
2568
  }
2362
2569
  let currentUrl = "";
2363
2570
  if (this.page.url) {
@@ -2366,7 +2573,13 @@ var PageAgent = class {
2366
2573
  } catch (e) {
2367
2574
  }
2368
2575
  }
2369
- const assertionWithContext = currentUrl ? `For the page at URL "${currentUrl}", ${processedAssertion}` : processedAssertion;
2576
+ let assertionWithContext = assertion;
2577
+ if (currentUrl) {
2578
+ assertionWithContext = `For the page at URL "${currentUrl}", ${assertion}`;
2579
+ }
2580
+ if (executionContext) {
2581
+ assertionWithContext += executionContext;
2582
+ }
2370
2583
  const { output, executor } = await this.taskExecutor.assert(assertionWithContext);
2371
2584
  const metadata = this.afterTaskRunning(executor, true);
2372
2585
  if (output && opt?.keepRawResponse) {
@@ -2580,6 +2793,79 @@ ${errors}`);
2580
2793
  async destroy() {
2581
2794
  await this.page.destroy();
2582
2795
  }
2796
+ /**
2797
+ * Analyze execution results from executor to generate meaningful descriptions
2798
+ */
2799
+ analyzeExecutionResults(executor, originalPrompt) {
2800
+ const tasks = executor.tasks;
2801
+ const success = !executor.isInErrorState();
2802
+ if (!success) {
2803
+ const errorTask = executor.latestErrorTask();
2804
+ return {
2805
+ success: false,
2806
+ actionType: "error",
2807
+ description: `Failed to execute: ${originalPrompt}`,
2808
+ error: errorTask?.error
2809
+ };
2810
+ }
2811
+ const actionTasks = tasks.filter((t) => t.type === "Action" && t.status === "finished");
2812
+ const locateTasks = tasks.filter((t) => t.type === "Insight" && t.subType === "Locate");
2813
+ const lastAction = actionTasks[actionTasks.length - 1];
2814
+ const lastLocate = locateTasks[locateTasks.length - 1];
2815
+ if (!lastAction) {
2816
+ return {
2817
+ success: true,
2818
+ actionType: "unknown",
2819
+ description: `Completed: ${originalPrompt}`
2820
+ };
2821
+ }
2822
+ const actionType = lastAction.subType || "unknown";
2823
+ const elementInfo = this.extractElementInfo(lastLocate, lastAction);
2824
+ const description = this.generateActionDescription(actionType, lastAction.param, elementInfo);
2825
+ return {
2826
+ success: true,
2827
+ actionType,
2828
+ description,
2829
+ elementInfo,
2830
+ timing: lastAction.timing?.cost
2831
+ };
2832
+ }
2833
+ /**
2834
+ * Extract element information from locate task
2835
+ */
2836
+ extractElementInfo(locateTask, _actionTask) {
2837
+ if (!locateTask?.output?.element)
2838
+ return void 0;
2839
+ const element = locateTask.output.element;
2840
+ return {
2841
+ type: element.attributes?.nodeType || "unknown",
2842
+ text: element.content || element.attributes?.placeholder || element.attributes?.title || "",
2843
+ location: `(${element.center[0]}, ${element.center[1]})`
2844
+ };
2845
+ }
2846
+ /**
2847
+ * Generate natural language description for actions
2848
+ */
2849
+ generateActionDescription(actionType, param, elementInfo) {
2850
+ const elementDesc = elementInfo ? `'${elementInfo.text || elementInfo.type}' element` : "element";
2851
+ switch (actionType) {
2852
+ case "Tap":
2853
+ return `Clicked on ${elementDesc}`;
2854
+ case "Input":
2855
+ const inputValue = param?.value || "";
2856
+ return `Entered "${inputValue}" into ${elementDesc}`;
2857
+ case "KeyboardPress":
2858
+ return `Pressed ${param?.value || "key"}`;
2859
+ case "Scroll":
2860
+ return `Scrolled ${param?.direction || "on page"}`;
2861
+ case "Hover":
2862
+ return `Hovered over ${elementDesc}`;
2863
+ case "Drag":
2864
+ return `Dragged ${elementDesc}`;
2865
+ default:
2866
+ return `Performed ${actionType} action on ${elementDesc}`;
2867
+ }
2868
+ }
2583
2869
  };
2584
2870
  // Annotate the CommonJS export names for ESM import in node:
2585
2871
  0 && (module.exports = {