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/es/agent.js CHANGED
@@ -1660,7 +1660,7 @@ import yaml3 from "js-yaml";
1660
1660
  import semver from "semver";
1661
1661
 
1662
1662
  // package.json
1663
- var version = "1.0.4";
1663
+ var version = "1.0.5";
1664
1664
 
1665
1665
  // src/common/task-cache.ts
1666
1666
  var debug3 = getDebug3("cache");
@@ -1688,44 +1688,70 @@ var TaskCache = class {
1688
1688
  this.cache = cacheContent;
1689
1689
  this.cacheOriginalLength = this.cache.caches.length;
1690
1690
  }
1691
- matchCache(prompt, type) {
1691
+ matchCache(prompt, type, contextData) {
1692
+ const contextHash = contextData ? this.generateContextHash(contextData) : void 0;
1692
1693
  for (let i = 0; i < this.cacheOriginalLength; i++) {
1693
1694
  const item = this.cache.caches[i];
1694
1695
  const key = `${type}:${prompt}:${i}`;
1695
- if (item.type === type && item.prompt === prompt && !this.matchedCacheIndices.has(key)) {
1696
- this.matchedCacheIndices.add(key);
1697
- debug3(
1698
- "cache found and marked as used, type: %s, prompt: %s, index: %d",
1699
- type,
1700
- prompt,
1701
- i
1702
- );
1703
- return {
1704
- cacheContent: item,
1705
- updateFn: (cb) => {
1706
- debug3(
1707
- "will call updateFn to update cache, type: %s, prompt: %s, index: %d",
1708
- type,
1709
- prompt,
1710
- i
1711
- );
1712
- cb(item);
1713
- debug3(
1714
- "cache updated, will flush to file, type: %s, prompt: %s, index: %d",
1715
- type,
1716
- prompt,
1717
- i
1718
- );
1719
- this.flushCacheToFile();
1696
+ if (item.type !== type || item.prompt !== prompt || this.matchedCacheIndices.has(key)) {
1697
+ continue;
1698
+ }
1699
+ if (type === "plan" && item.type === "plan") {
1700
+ const planItem = item;
1701
+ if (contextHash && planItem.contextHash) {
1702
+ if (contextHash !== planItem.contextHash) {
1703
+ debug3("cache context mismatch, type: %s, prompt: %s, index: %d", type, prompt, i);
1704
+ continue;
1720
1705
  }
1721
- };
1706
+ } else if (contextHash || planItem.contextHash) {
1707
+ debug3("cache context availability mismatch, type: %s, prompt: %s, index: %d", type, prompt, i);
1708
+ continue;
1709
+ }
1722
1710
  }
1711
+ this.matchedCacheIndices.add(key);
1712
+ debug3(
1713
+ "cache found and marked as used, type: %s, prompt: %s, index: %d, contextMatch: %s",
1714
+ type,
1715
+ prompt,
1716
+ i,
1717
+ contextHash ? "yes" : "no-context"
1718
+ );
1719
+ return {
1720
+ cacheContent: item,
1721
+ updateFn: (cb) => {
1722
+ debug3(
1723
+ "will call updateFn to update cache, type: %s, prompt: %s, index: %d",
1724
+ type,
1725
+ prompt,
1726
+ i
1727
+ );
1728
+ cb(item);
1729
+ debug3(
1730
+ "cache updated, will flush to file, type: %s, prompt: %s, index: %d",
1731
+ type,
1732
+ prompt,
1733
+ i
1734
+ );
1735
+ this.flushCacheToFile();
1736
+ }
1737
+ };
1723
1738
  }
1724
- debug3("no unused cache found, type: %s, prompt: %s", type, prompt);
1739
+ debug3("no unused cache found, type: %s, prompt: %s, contextHash: %s", type, prompt, contextHash);
1725
1740
  return void 0;
1726
1741
  }
1727
- matchPlanCache(prompt) {
1728
- return this.matchCache(prompt, "plan");
1742
+ generateContextHash(contextData) {
1743
+ const sortedKeys = Object.keys(contextData).sort();
1744
+ const stableString = sortedKeys.map((key) => `${key}:${JSON.stringify(contextData[key])}`).join("|");
1745
+ let hash = 0;
1746
+ for (let i = 0; i < stableString.length; i++) {
1747
+ const char = stableString.charCodeAt(i);
1748
+ hash = (hash << 5) - hash + char;
1749
+ hash = hash & hash;
1750
+ }
1751
+ return hash.toString(36);
1752
+ }
1753
+ matchPlanCache(prompt, contextData) {
1754
+ return this.matchCache(prompt, "plan", contextData);
1729
1755
  }
1730
1756
  matchLocateCache(prompt) {
1731
1757
  return this.matchCache(prompt, "locate");
@@ -1801,11 +1827,16 @@ cache file: ${cacheFile}`
1801
1827
  );
1802
1828
  }
1803
1829
  }
1804
- updateOrAppendCacheRecord(newRecord, cachedRecord) {
1830
+ updateOrAppendCacheRecord(newRecord, cachedRecord, contextData) {
1805
1831
  if (cachedRecord) {
1806
1832
  if (newRecord.type === "plan") {
1807
1833
  cachedRecord.updateFn((cache) => {
1808
- cache.yamlWorkflow = newRecord.yamlWorkflow;
1834
+ const planCache = cache;
1835
+ planCache.yamlWorkflow = newRecord.yamlWorkflow;
1836
+ if (contextData) {
1837
+ planCache.contextHash = this.generateContextHash(contextData);
1838
+ planCache.contextData = { ...contextData };
1839
+ }
1809
1840
  });
1810
1841
  } else {
1811
1842
  cachedRecord.updateFn((cache) => {
@@ -1813,6 +1844,11 @@ cache file: ${cacheFile}`
1813
1844
  });
1814
1845
  }
1815
1846
  } else {
1847
+ if (newRecord.type === "plan" && contextData) {
1848
+ const planRecord = newRecord;
1849
+ planRecord.contextHash = this.generateContextHash(contextData);
1850
+ planRecord.contextData = { ...contextData };
1851
+ }
1816
1852
  this.appendCache(newRecord);
1817
1853
  }
1818
1854
  }
@@ -1842,10 +1878,13 @@ var PageAgent = class {
1842
1878
  generateReport: true,
1843
1879
  autoPrintReportMsg: true,
1844
1880
  groupName: "Midscene Report",
1845
- groupDescription: ""
1881
+ groupDescription: "",
1882
+ enableCumulativeContext: true,
1883
+ autoClearContext: false
1846
1884
  },
1847
1885
  opts || {}
1848
1886
  );
1887
+ this.initializeContextStore();
1849
1888
  if (this.page.pageType === "puppeteer" || this.page.pageType === "playwright") {
1850
1889
  this.page.waitForNavigationTimeout = this.opts.waitForNavigationTimeout || DEFAULT_WAIT_FOR_NAVIGATION_TIMEOUT;
1851
1890
  this.page.waitForNetworkIdleTimeout = this.opts.waitForNetworkIdleTimeout || DEFAULT_WAIT_FOR_NETWORK_IDLE_TIMEOUT;
@@ -1872,6 +1911,69 @@ var PageAgent = class {
1872
1911
  opts?.testId || this.page.pageType || "web"
1873
1912
  );
1874
1913
  }
1914
+ /**
1915
+ * Initialize context store for cumulative context functionality
1916
+ */
1917
+ async initializeContextStore() {
1918
+ if (!this.opts.enableCumulativeContext) {
1919
+ debug4("Cumulative context disabled via options");
1920
+ return;
1921
+ }
1922
+ try {
1923
+ const aiModel = await import("misoai-core/ai-model");
1924
+ this.contextStore = aiModel.getContextStore();
1925
+ debug4("Context store initialized successfully", {
1926
+ autoClearContext: this.opts.autoClearContext,
1927
+ testId: this.opts.testId
1928
+ });
1929
+ if (this.opts.autoClearContext) {
1930
+ this.contextStore.clear();
1931
+ debug4("Context store cleared due to autoClearContext option");
1932
+ } else {
1933
+ const existingData = this.contextStore.getAllData();
1934
+ const existingSteps = this.contextStore.getRecentSteps(100).length;
1935
+ debug4("Context store preserving existing data", {
1936
+ existingDataKeys: Object.keys(existingData),
1937
+ existingStepsCount: existingSteps
1938
+ });
1939
+ }
1940
+ } catch (error) {
1941
+ debug4("Failed to initialize context store:", error);
1942
+ console.warn("⚠️ Could not initialize context store:", error);
1943
+ }
1944
+ }
1945
+ /**
1946
+ * Get the context store instance
1947
+ */
1948
+ getContextStore() {
1949
+ return this.contextStore;
1950
+ }
1951
+ /**
1952
+ * Clear the context store
1953
+ */
1954
+ clearContext() {
1955
+ if (this.contextStore) {
1956
+ this.contextStore.clear();
1957
+ }
1958
+ }
1959
+ /**
1960
+ * Get all stored data from context store
1961
+ */
1962
+ getStoredData() {
1963
+ if (this.contextStore) {
1964
+ return this.contextStore.getAllData();
1965
+ }
1966
+ return {};
1967
+ }
1968
+ /**
1969
+ * Get step summary from context store
1970
+ */
1971
+ getStepSummary() {
1972
+ if (this.contextStore) {
1973
+ return this.contextStore.getStepSummary();
1974
+ }
1975
+ return "";
1976
+ }
1875
1977
  async getUIContext(action) {
1876
1978
  if (action && (action === "extract" || action === "assert" || action === "captcha")) {
1877
1979
  return await parseContextFromWebPage(this.page, {
@@ -2107,22 +2209,35 @@ var PageAgent = class {
2107
2209
  };
2108
2210
  }
2109
2211
  async aiAction(taskPrompt, opt) {
2110
- try {
2111
- const aiModel = await import("misoai-core/ai-model");
2112
- const contextStore = aiModel.getContextStore();
2113
- const processedPrompt = contextStore.replaceAllReferences(taskPrompt, "action");
2114
- contextStore.addStep({
2115
- type: "action",
2116
- summary: `Action: ${processedPrompt}`,
2117
- prompt: processedPrompt
2118
- });
2119
- taskPrompt = processedPrompt;
2120
- } catch (error) {
2121
- debug4("Context store not available:", error);
2212
+ const originalPrompt = taskPrompt;
2213
+ let processedPrompt = taskPrompt;
2214
+ if (this.opts.enableCumulativeContext && this.contextStore) {
2215
+ try {
2216
+ const storedData = this.contextStore.getAllData();
2217
+ if (Object.keys(storedData).length > 0) {
2218
+ debug4("Available data for aiAction:", {
2219
+ prompt: taskPrompt,
2220
+ availableData: storedData
2221
+ });
2222
+ }
2223
+ } catch (error) {
2224
+ debug4("Context store operation failed:", error);
2225
+ }
2122
2226
  }
2123
2227
  const cacheable = opt?.cacheable;
2124
2228
  const isVlmUiTars = vlLocateMode() === "vlm-ui-tars";
2125
- const matchedCache = isVlmUiTars || cacheable === false ? void 0 : this.taskCache?.matchPlanCache(taskPrompt);
2229
+ let contextData;
2230
+ if (this.opts.enableCumulativeContext && this.contextStore) {
2231
+ try {
2232
+ contextData = this.contextStore.getAllData();
2233
+ if (contextData && Object.keys(contextData).length === 0) {
2234
+ contextData = void 0;
2235
+ }
2236
+ } catch (error) {
2237
+ debug4("Failed to get context data for cache:", error);
2238
+ }
2239
+ }
2240
+ const matchedCache = isVlmUiTars || cacheable === false ? void 0 : this.taskCache?.matchPlanCache(taskPrompt, contextData);
2126
2241
  if (matchedCache && this.taskCache?.isCacheResultUsed) {
2127
2242
  const { executor: executor2 } = await this.taskExecutor.loadYamlFlowAsPlanning(
2128
2243
  taskPrompt,
@@ -2132,6 +2247,28 @@ var PageAgent = class {
2132
2247
  debug4("matched cache, will call .runYaml to run the action");
2133
2248
  const yaml5 = matchedCache.cacheContent?.yamlWorkflow;
2134
2249
  const result = await this.runYaml(yaml5);
2250
+ if (this.opts.enableCumulativeContext && this.contextStore) {
2251
+ try {
2252
+ const executionResult = {
2253
+ success: true,
2254
+ actionType: "cached",
2255
+ description: `Executed cached action: ${processedPrompt}`,
2256
+ timing: result.metadata?.totalTime
2257
+ };
2258
+ this.contextStore.addStep({
2259
+ type: "action",
2260
+ summary: `Action: ${processedPrompt} (cached)`,
2261
+ prompt: processedPrompt,
2262
+ executionResult
2263
+ });
2264
+ debug4("Added cached action step to context store:", {
2265
+ stepNumber: this.contextStore.getRecentSteps(1)[0]?.stepNumber,
2266
+ totalSteps: this.contextStore.getRecentSteps(100).length
2267
+ });
2268
+ } catch (error) {
2269
+ debug4("Failed to add cached action step:", error);
2270
+ }
2271
+ }
2135
2272
  return {
2136
2273
  result: result.result,
2137
2274
  metadata: metadata2
@@ -2156,10 +2293,39 @@ var PageAgent = class {
2156
2293
  prompt: taskPrompt,
2157
2294
  yamlWorkflow: yamlFlowStr
2158
2295
  },
2159
- matchedCache
2296
+ matchedCache,
2297
+ contextData
2298
+ // Pass context data for cache creation
2160
2299
  );
2161
2300
  }
2162
2301
  const metadata = this.afterTaskRunning(executor);
2302
+ if (this.opts.enableCumulativeContext && this.contextStore) {
2303
+ try {
2304
+ const executionResult = this.analyzeExecutionResults(executor, originalPrompt);
2305
+ this.contextStore.addStep({
2306
+ type: "action",
2307
+ summary: `Action: ${processedPrompt}`,
2308
+ prompt: processedPrompt,
2309
+ executionResult
2310
+ });
2311
+ debug4("Added action step with execution result to context store:", {
2312
+ stepNumber: this.contextStore.getRecentSteps(1)[0]?.stepNumber,
2313
+ totalSteps: this.contextStore.getRecentSteps(100).length,
2314
+ executionResult
2315
+ });
2316
+ } catch (error) {
2317
+ debug4("Failed to analyze execution results, adding step without execution result:", error);
2318
+ try {
2319
+ this.contextStore.addStep({
2320
+ type: "action",
2321
+ summary: `Action: ${processedPrompt}`,
2322
+ prompt: processedPrompt
2323
+ });
2324
+ } catch (stepError) {
2325
+ debug4("Failed to add action step:", stepError);
2326
+ }
2327
+ }
2328
+ }
2163
2329
  return {
2164
2330
  result: output,
2165
2331
  metadata
@@ -2189,38 +2355,50 @@ var PageAgent = class {
2189
2355
  debug4("Context store not available:", error);
2190
2356
  }
2191
2357
  const { output, executor } = await this.taskExecutor.query(processedDemand);
2192
- if (storageKey && output) {
2193
- try {
2194
- const aiModel = await import("misoai-core/ai-model");
2195
- const contextStore = aiModel.getContextStore();
2196
- const pendingAliases = contextStore._pendingAliases;
2197
- if (pendingAliases) {
2198
- contextStore.storeDataWithAliases(storageKey, output, pendingAliases, typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand));
2199
- delete contextStore._pendingAliases;
2200
- } else {
2201
- contextStore.storeData(storageKey, output);
2358
+ if (this.opts.enableCumulativeContext && this.contextStore) {
2359
+ if (storageKey && output) {
2360
+ try {
2361
+ const pendingAliases = this.contextStore._pendingAliases;
2362
+ if (pendingAliases) {
2363
+ this.contextStore.storeDataWithAliases(storageKey, output, pendingAliases, typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand));
2364
+ delete this.contextStore._pendingAliases;
2365
+ debug4("Stored query result with aliases:", {
2366
+ key: storageKey,
2367
+ value: output,
2368
+ aliases: pendingAliases
2369
+ });
2370
+ } else {
2371
+ this.contextStore.storeData(storageKey, output);
2372
+ debug4("Stored query result:", {
2373
+ key: storageKey,
2374
+ value: output
2375
+ });
2376
+ }
2377
+ this.contextStore.addStep({
2378
+ type: "query",
2379
+ summary: `Query: ${typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand)} (stored as ${storageKey})`,
2380
+ data: output,
2381
+ prompt: typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand)
2382
+ });
2383
+ debug4("Added query step to context store:", {
2384
+ storageKey,
2385
+ totalStoredItems: Object.keys(this.contextStore.getAllData()).length,
2386
+ totalSteps: this.contextStore.getRecentSteps(100).length
2387
+ });
2388
+ } catch (error) {
2389
+ debug4("Failed to store query result:", error);
2390
+ }
2391
+ } else {
2392
+ try {
2393
+ this.contextStore.addStep({
2394
+ type: "query",
2395
+ summary: `Query: ${typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand)}`,
2396
+ data: output,
2397
+ prompt: typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand)
2398
+ });
2399
+ } catch (error) {
2400
+ debug4("Failed to add query step:", error);
2202
2401
  }
2203
- contextStore.addStep({
2204
- type: "query",
2205
- summary: `Query: ${typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand)} (stored as ${storageKey})`,
2206
- data: output,
2207
- prompt: typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand)
2208
- });
2209
- } catch (error) {
2210
- debug4("Failed to store query result:", error);
2211
- }
2212
- } else {
2213
- try {
2214
- const aiModel = await import("misoai-core/ai-model");
2215
- const contextStore = aiModel.getContextStore();
2216
- contextStore.addStep({
2217
- type: "query",
2218
- summary: `Query: ${typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand)}`,
2219
- data: output,
2220
- prompt: typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand)
2221
- });
2222
- } catch (error) {
2223
- debug4("Failed to add query step:", error);
2224
2402
  }
2225
2403
  }
2226
2404
  const metadata = this.afterTaskRunning(executor);
@@ -2332,18 +2510,47 @@ var PageAgent = class {
2332
2510
  };
2333
2511
  }
2334
2512
  async aiAssert(assertion, msg, opt) {
2335
- let processedAssertion = assertion;
2336
- try {
2337
- const aiModel = await import("misoai-core/ai-model");
2338
- const contextStore = aiModel.getContextStore();
2339
- processedAssertion = contextStore.replaceAllReferences(assertion, "assertion");
2340
- contextStore.addStep({
2341
- type: "assertion",
2342
- summary: `Assertion: ${processedAssertion}`,
2343
- prompt: processedAssertion
2344
- });
2345
- } catch (error) {
2346
- debug4("Context store not available:", error);
2513
+ let executionContext = "";
2514
+ if (this.opts.enableCumulativeContext && this.contextStore) {
2515
+ try {
2516
+ const recentSteps = this.contextStore.getRecentSteps(3);
2517
+ const stepsWithExecutionResults = recentSteps.filter((step) => step.executionResult);
2518
+ const storedData = this.contextStore.getAllData();
2519
+ if (stepsWithExecutionResults.length > 0) {
2520
+ const recentActions = stepsWithExecutionResults.map((step) => {
2521
+ const result = step.executionResult;
2522
+ return `- ${result.description}${result.success ? "" : " (FAILED)"}`;
2523
+ }).join("\n");
2524
+ executionContext = `
2525
+
2526
+ Recent actions performed:
2527
+ ${recentActions}
2528
+
2529
+ This context may help verify the assertion.`;
2530
+ }
2531
+ if (storedData && Object.keys(storedData).length > 0) {
2532
+ executionContext += `
2533
+
2534
+ Available data for reference:
2535
+ ${JSON.stringify(storedData, null, 2)}
2536
+
2537
+ Note: If the assertion references any data keys or natural language equivalents, consider the stored values when verifying.`;
2538
+ debug4("Available data for aiAssert:", {
2539
+ assertion,
2540
+ availableData: storedData
2541
+ });
2542
+ }
2543
+ this.contextStore.addStep({
2544
+ type: "assertion",
2545
+ summary: `Assertion: ${assertion}`,
2546
+ prompt: assertion
2547
+ });
2548
+ debug4("Added assertion step to context store:", {
2549
+ totalSteps: this.contextStore.getRecentSteps(100).length
2550
+ });
2551
+ } catch (error) {
2552
+ debug4("Context store operation failed:", error);
2553
+ }
2347
2554
  }
2348
2555
  let currentUrl = "";
2349
2556
  if (this.page.url) {
@@ -2352,7 +2559,13 @@ var PageAgent = class {
2352
2559
  } catch (e) {
2353
2560
  }
2354
2561
  }
2355
- const assertionWithContext = currentUrl ? `For the page at URL "${currentUrl}", ${processedAssertion}` : processedAssertion;
2562
+ let assertionWithContext = assertion;
2563
+ if (currentUrl) {
2564
+ assertionWithContext = `For the page at URL "${currentUrl}", ${assertion}`;
2565
+ }
2566
+ if (executionContext) {
2567
+ assertionWithContext += executionContext;
2568
+ }
2356
2569
  const { output, executor } = await this.taskExecutor.assert(assertionWithContext);
2357
2570
  const metadata = this.afterTaskRunning(executor, true);
2358
2571
  if (output && opt?.keepRawResponse) {
@@ -2566,6 +2779,79 @@ ${errors}`);
2566
2779
  async destroy() {
2567
2780
  await this.page.destroy();
2568
2781
  }
2782
+ /**
2783
+ * Analyze execution results from executor to generate meaningful descriptions
2784
+ */
2785
+ analyzeExecutionResults(executor, originalPrompt) {
2786
+ const tasks = executor.tasks;
2787
+ const success = !executor.isInErrorState();
2788
+ if (!success) {
2789
+ const errorTask = executor.latestErrorTask();
2790
+ return {
2791
+ success: false,
2792
+ actionType: "error",
2793
+ description: `Failed to execute: ${originalPrompt}`,
2794
+ error: errorTask?.error
2795
+ };
2796
+ }
2797
+ const actionTasks = tasks.filter((t) => t.type === "Action" && t.status === "finished");
2798
+ const locateTasks = tasks.filter((t) => t.type === "Insight" && t.subType === "Locate");
2799
+ const lastAction = actionTasks[actionTasks.length - 1];
2800
+ const lastLocate = locateTasks[locateTasks.length - 1];
2801
+ if (!lastAction) {
2802
+ return {
2803
+ success: true,
2804
+ actionType: "unknown",
2805
+ description: `Completed: ${originalPrompt}`
2806
+ };
2807
+ }
2808
+ const actionType = lastAction.subType || "unknown";
2809
+ const elementInfo = this.extractElementInfo(lastLocate, lastAction);
2810
+ const description = this.generateActionDescription(actionType, lastAction.param, elementInfo);
2811
+ return {
2812
+ success: true,
2813
+ actionType,
2814
+ description,
2815
+ elementInfo,
2816
+ timing: lastAction.timing?.cost
2817
+ };
2818
+ }
2819
+ /**
2820
+ * Extract element information from locate task
2821
+ */
2822
+ extractElementInfo(locateTask, _actionTask) {
2823
+ if (!locateTask?.output?.element)
2824
+ return void 0;
2825
+ const element = locateTask.output.element;
2826
+ return {
2827
+ type: element.attributes?.nodeType || "unknown",
2828
+ text: element.content || element.attributes?.placeholder || element.attributes?.title || "",
2829
+ location: `(${element.center[0]}, ${element.center[1]})`
2830
+ };
2831
+ }
2832
+ /**
2833
+ * Generate natural language description for actions
2834
+ */
2835
+ generateActionDescription(actionType, param, elementInfo) {
2836
+ const elementDesc = elementInfo ? `'${elementInfo.text || elementInfo.type}' element` : "element";
2837
+ switch (actionType) {
2838
+ case "Tap":
2839
+ return `Clicked on ${elementDesc}`;
2840
+ case "Input":
2841
+ const inputValue = param?.value || "";
2842
+ return `Entered "${inputValue}" into ${elementDesc}`;
2843
+ case "KeyboardPress":
2844
+ return `Pressed ${param?.value || "key"}`;
2845
+ case "Scroll":
2846
+ return `Scrolled ${param?.direction || "on page"}`;
2847
+ case "Hover":
2848
+ return `Hovered over ${elementDesc}`;
2849
+ case "Drag":
2850
+ return `Dragged ${elementDesc}`;
2851
+ default:
2852
+ return `Performed ${actionType} action on ${elementDesc}`;
2853
+ }
2854
+ }
2569
2855
  };
2570
2856
  export {
2571
2857
  PageAgent