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/index.js CHANGED
@@ -1688,7 +1688,7 @@ import yaml3 from "js-yaml";
1688
1688
  import semver from "semver";
1689
1689
 
1690
1690
  // package.json
1691
- var version = "1.0.4";
1691
+ var version = "1.0.5";
1692
1692
 
1693
1693
  // src/common/task-cache.ts
1694
1694
  var debug3 = getDebug3("cache");
@@ -1716,44 +1716,70 @@ var TaskCache = class {
1716
1716
  this.cache = cacheContent;
1717
1717
  this.cacheOriginalLength = this.cache.caches.length;
1718
1718
  }
1719
- matchCache(prompt, type) {
1719
+ matchCache(prompt, type, contextData) {
1720
+ const contextHash = contextData ? this.generateContextHash(contextData) : void 0;
1720
1721
  for (let i = 0; i < this.cacheOriginalLength; i++) {
1721
1722
  const item = this.cache.caches[i];
1722
1723
  const key = `${type}:${prompt}:${i}`;
1723
- if (item.type === type && item.prompt === prompt && !this.matchedCacheIndices.has(key)) {
1724
- this.matchedCacheIndices.add(key);
1725
- debug3(
1726
- "cache found and marked as used, type: %s, prompt: %s, index: %d",
1727
- type,
1728
- prompt,
1729
- i
1730
- );
1731
- return {
1732
- cacheContent: item,
1733
- updateFn: (cb) => {
1734
- debug3(
1735
- "will call updateFn to update cache, type: %s, prompt: %s, index: %d",
1736
- type,
1737
- prompt,
1738
- i
1739
- );
1740
- cb(item);
1741
- debug3(
1742
- "cache updated, will flush to file, type: %s, prompt: %s, index: %d",
1743
- type,
1744
- prompt,
1745
- i
1746
- );
1747
- this.flushCacheToFile();
1724
+ if (item.type !== type || item.prompt !== prompt || this.matchedCacheIndices.has(key)) {
1725
+ continue;
1726
+ }
1727
+ if (type === "plan" && item.type === "plan") {
1728
+ const planItem = item;
1729
+ if (contextHash && planItem.contextHash) {
1730
+ if (contextHash !== planItem.contextHash) {
1731
+ debug3("cache context mismatch, type: %s, prompt: %s, index: %d", type, prompt, i);
1732
+ continue;
1748
1733
  }
1749
- };
1734
+ } else if (contextHash || planItem.contextHash) {
1735
+ debug3("cache context availability mismatch, type: %s, prompt: %s, index: %d", type, prompt, i);
1736
+ continue;
1737
+ }
1750
1738
  }
1739
+ this.matchedCacheIndices.add(key);
1740
+ debug3(
1741
+ "cache found and marked as used, type: %s, prompt: %s, index: %d, contextMatch: %s",
1742
+ type,
1743
+ prompt,
1744
+ i,
1745
+ contextHash ? "yes" : "no-context"
1746
+ );
1747
+ return {
1748
+ cacheContent: item,
1749
+ updateFn: (cb) => {
1750
+ debug3(
1751
+ "will call updateFn to update cache, type: %s, prompt: %s, index: %d",
1752
+ type,
1753
+ prompt,
1754
+ i
1755
+ );
1756
+ cb(item);
1757
+ debug3(
1758
+ "cache updated, will flush to file, type: %s, prompt: %s, index: %d",
1759
+ type,
1760
+ prompt,
1761
+ i
1762
+ );
1763
+ this.flushCacheToFile();
1764
+ }
1765
+ };
1751
1766
  }
1752
- debug3("no unused cache found, type: %s, prompt: %s", type, prompt);
1767
+ debug3("no unused cache found, type: %s, prompt: %s, contextHash: %s", type, prompt, contextHash);
1753
1768
  return void 0;
1754
1769
  }
1755
- matchPlanCache(prompt) {
1756
- return this.matchCache(prompt, "plan");
1770
+ generateContextHash(contextData) {
1771
+ const sortedKeys = Object.keys(contextData).sort();
1772
+ const stableString = sortedKeys.map((key) => `${key}:${JSON.stringify(contextData[key])}`).join("|");
1773
+ let hash = 0;
1774
+ for (let i = 0; i < stableString.length; i++) {
1775
+ const char = stableString.charCodeAt(i);
1776
+ hash = (hash << 5) - hash + char;
1777
+ hash = hash & hash;
1778
+ }
1779
+ return hash.toString(36);
1780
+ }
1781
+ matchPlanCache(prompt, contextData) {
1782
+ return this.matchCache(prompt, "plan", contextData);
1757
1783
  }
1758
1784
  matchLocateCache(prompt) {
1759
1785
  return this.matchCache(prompt, "locate");
@@ -1829,11 +1855,16 @@ cache file: ${cacheFile}`
1829
1855
  );
1830
1856
  }
1831
1857
  }
1832
- updateOrAppendCacheRecord(newRecord, cachedRecord) {
1858
+ updateOrAppendCacheRecord(newRecord, cachedRecord, contextData) {
1833
1859
  if (cachedRecord) {
1834
1860
  if (newRecord.type === "plan") {
1835
1861
  cachedRecord.updateFn((cache) => {
1836
- cache.yamlWorkflow = newRecord.yamlWorkflow;
1862
+ const planCache = cache;
1863
+ planCache.yamlWorkflow = newRecord.yamlWorkflow;
1864
+ if (contextData) {
1865
+ planCache.contextHash = this.generateContextHash(contextData);
1866
+ planCache.contextData = { ...contextData };
1867
+ }
1837
1868
  });
1838
1869
  } else {
1839
1870
  cachedRecord.updateFn((cache) => {
@@ -1841,6 +1872,11 @@ cache file: ${cacheFile}`
1841
1872
  });
1842
1873
  }
1843
1874
  } else {
1875
+ if (newRecord.type === "plan" && contextData) {
1876
+ const planRecord = newRecord;
1877
+ planRecord.contextHash = this.generateContextHash(contextData);
1878
+ planRecord.contextData = { ...contextData };
1879
+ }
1844
1880
  this.appendCache(newRecord);
1845
1881
  }
1846
1882
  }
@@ -1870,10 +1906,13 @@ var PageAgent = class {
1870
1906
  generateReport: true,
1871
1907
  autoPrintReportMsg: true,
1872
1908
  groupName: "Midscene Report",
1873
- groupDescription: ""
1909
+ groupDescription: "",
1910
+ enableCumulativeContext: true,
1911
+ autoClearContext: false
1874
1912
  },
1875
1913
  opts || {}
1876
1914
  );
1915
+ this.initializeContextStore();
1877
1916
  if (this.page.pageType === "puppeteer" || this.page.pageType === "playwright") {
1878
1917
  this.page.waitForNavigationTimeout = this.opts.waitForNavigationTimeout || DEFAULT_WAIT_FOR_NAVIGATION_TIMEOUT;
1879
1918
  this.page.waitForNetworkIdleTimeout = this.opts.waitForNetworkIdleTimeout || DEFAULT_WAIT_FOR_NETWORK_IDLE_TIMEOUT;
@@ -1900,6 +1939,69 @@ var PageAgent = class {
1900
1939
  opts?.testId || this.page.pageType || "web"
1901
1940
  );
1902
1941
  }
1942
+ /**
1943
+ * Initialize context store for cumulative context functionality
1944
+ */
1945
+ async initializeContextStore() {
1946
+ if (!this.opts.enableCumulativeContext) {
1947
+ debug4("Cumulative context disabled via options");
1948
+ return;
1949
+ }
1950
+ try {
1951
+ const aiModel = await import("misoai-core/ai-model");
1952
+ this.contextStore = aiModel.getContextStore();
1953
+ debug4("Context store initialized successfully", {
1954
+ autoClearContext: this.opts.autoClearContext,
1955
+ testId: this.opts.testId
1956
+ });
1957
+ if (this.opts.autoClearContext) {
1958
+ this.contextStore.clear();
1959
+ debug4("Context store cleared due to autoClearContext option");
1960
+ } else {
1961
+ const existingData = this.contextStore.getAllData();
1962
+ const existingSteps = this.contextStore.getRecentSteps(100).length;
1963
+ debug4("Context store preserving existing data", {
1964
+ existingDataKeys: Object.keys(existingData),
1965
+ existingStepsCount: existingSteps
1966
+ });
1967
+ }
1968
+ } catch (error) {
1969
+ debug4("Failed to initialize context store:", error);
1970
+ console.warn("⚠️ Could not initialize context store:", error);
1971
+ }
1972
+ }
1973
+ /**
1974
+ * Get the context store instance
1975
+ */
1976
+ getContextStore() {
1977
+ return this.contextStore;
1978
+ }
1979
+ /**
1980
+ * Clear the context store
1981
+ */
1982
+ clearContext() {
1983
+ if (this.contextStore) {
1984
+ this.contextStore.clear();
1985
+ }
1986
+ }
1987
+ /**
1988
+ * Get all stored data from context store
1989
+ */
1990
+ getStoredData() {
1991
+ if (this.contextStore) {
1992
+ return this.contextStore.getAllData();
1993
+ }
1994
+ return {};
1995
+ }
1996
+ /**
1997
+ * Get step summary from context store
1998
+ */
1999
+ getStepSummary() {
2000
+ if (this.contextStore) {
2001
+ return this.contextStore.getStepSummary();
2002
+ }
2003
+ return "";
2004
+ }
1903
2005
  async getUIContext(action) {
1904
2006
  if (action && (action === "extract" || action === "assert" || action === "captcha")) {
1905
2007
  return await parseContextFromWebPage(this.page, {
@@ -2135,22 +2237,35 @@ var PageAgent = class {
2135
2237
  };
2136
2238
  }
2137
2239
  async aiAction(taskPrompt, opt) {
2138
- try {
2139
- const aiModel = await import("misoai-core/ai-model");
2140
- const contextStore = aiModel.getContextStore();
2141
- const processedPrompt = contextStore.replaceAllReferences(taskPrompt, "action");
2142
- contextStore.addStep({
2143
- type: "action",
2144
- summary: `Action: ${processedPrompt}`,
2145
- prompt: processedPrompt
2146
- });
2147
- taskPrompt = processedPrompt;
2148
- } catch (error) {
2149
- debug4("Context store not available:", error);
2240
+ const originalPrompt = taskPrompt;
2241
+ let processedPrompt = taskPrompt;
2242
+ if (this.opts.enableCumulativeContext && this.contextStore) {
2243
+ try {
2244
+ const storedData = this.contextStore.getAllData();
2245
+ if (Object.keys(storedData).length > 0) {
2246
+ debug4("Available data for aiAction:", {
2247
+ prompt: taskPrompt,
2248
+ availableData: storedData
2249
+ });
2250
+ }
2251
+ } catch (error) {
2252
+ debug4("Context store operation failed:", error);
2253
+ }
2150
2254
  }
2151
2255
  const cacheable = opt?.cacheable;
2152
2256
  const isVlmUiTars = vlLocateMode() === "vlm-ui-tars";
2153
- const matchedCache = isVlmUiTars || cacheable === false ? void 0 : this.taskCache?.matchPlanCache(taskPrompt);
2257
+ let contextData;
2258
+ if (this.opts.enableCumulativeContext && this.contextStore) {
2259
+ try {
2260
+ contextData = this.contextStore.getAllData();
2261
+ if (contextData && Object.keys(contextData).length === 0) {
2262
+ contextData = void 0;
2263
+ }
2264
+ } catch (error) {
2265
+ debug4("Failed to get context data for cache:", error);
2266
+ }
2267
+ }
2268
+ const matchedCache = isVlmUiTars || cacheable === false ? void 0 : this.taskCache?.matchPlanCache(taskPrompt, contextData);
2154
2269
  if (matchedCache && this.taskCache?.isCacheResultUsed) {
2155
2270
  const { executor: executor2 } = await this.taskExecutor.loadYamlFlowAsPlanning(
2156
2271
  taskPrompt,
@@ -2160,6 +2275,28 @@ var PageAgent = class {
2160
2275
  debug4("matched cache, will call .runYaml to run the action");
2161
2276
  const yaml5 = matchedCache.cacheContent?.yamlWorkflow;
2162
2277
  const result = await this.runYaml(yaml5);
2278
+ if (this.opts.enableCumulativeContext && this.contextStore) {
2279
+ try {
2280
+ const executionResult = {
2281
+ success: true,
2282
+ actionType: "cached",
2283
+ description: `Executed cached action: ${processedPrompt}`,
2284
+ timing: result.metadata?.totalTime
2285
+ };
2286
+ this.contextStore.addStep({
2287
+ type: "action",
2288
+ summary: `Action: ${processedPrompt} (cached)`,
2289
+ prompt: processedPrompt,
2290
+ executionResult
2291
+ });
2292
+ debug4("Added cached action step to context store:", {
2293
+ stepNumber: this.contextStore.getRecentSteps(1)[0]?.stepNumber,
2294
+ totalSteps: this.contextStore.getRecentSteps(100).length
2295
+ });
2296
+ } catch (error) {
2297
+ debug4("Failed to add cached action step:", error);
2298
+ }
2299
+ }
2163
2300
  return {
2164
2301
  result: result.result,
2165
2302
  metadata: metadata2
@@ -2184,10 +2321,39 @@ var PageAgent = class {
2184
2321
  prompt: taskPrompt,
2185
2322
  yamlWorkflow: yamlFlowStr
2186
2323
  },
2187
- matchedCache
2324
+ matchedCache,
2325
+ contextData
2326
+ // Pass context data for cache creation
2188
2327
  );
2189
2328
  }
2190
2329
  const metadata = this.afterTaskRunning(executor);
2330
+ if (this.opts.enableCumulativeContext && this.contextStore) {
2331
+ try {
2332
+ const executionResult = this.analyzeExecutionResults(executor, originalPrompt);
2333
+ this.contextStore.addStep({
2334
+ type: "action",
2335
+ summary: `Action: ${processedPrompt}`,
2336
+ prompt: processedPrompt,
2337
+ executionResult
2338
+ });
2339
+ debug4("Added action step with execution result to context store:", {
2340
+ stepNumber: this.contextStore.getRecentSteps(1)[0]?.stepNumber,
2341
+ totalSteps: this.contextStore.getRecentSteps(100).length,
2342
+ executionResult
2343
+ });
2344
+ } catch (error) {
2345
+ debug4("Failed to analyze execution results, adding step without execution result:", error);
2346
+ try {
2347
+ this.contextStore.addStep({
2348
+ type: "action",
2349
+ summary: `Action: ${processedPrompt}`,
2350
+ prompt: processedPrompt
2351
+ });
2352
+ } catch (stepError) {
2353
+ debug4("Failed to add action step:", stepError);
2354
+ }
2355
+ }
2356
+ }
2191
2357
  return {
2192
2358
  result: output,
2193
2359
  metadata
@@ -2217,38 +2383,50 @@ var PageAgent = class {
2217
2383
  debug4("Context store not available:", error);
2218
2384
  }
2219
2385
  const { output, executor } = await this.taskExecutor.query(processedDemand);
2220
- if (storageKey && output) {
2221
- try {
2222
- const aiModel = await import("misoai-core/ai-model");
2223
- const contextStore = aiModel.getContextStore();
2224
- const pendingAliases = contextStore._pendingAliases;
2225
- if (pendingAliases) {
2226
- contextStore.storeDataWithAliases(storageKey, output, pendingAliases, typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand));
2227
- delete contextStore._pendingAliases;
2228
- } else {
2229
- contextStore.storeData(storageKey, output);
2386
+ if (this.opts.enableCumulativeContext && this.contextStore) {
2387
+ if (storageKey && output) {
2388
+ try {
2389
+ const pendingAliases = this.contextStore._pendingAliases;
2390
+ if (pendingAliases) {
2391
+ this.contextStore.storeDataWithAliases(storageKey, output, pendingAliases, typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand));
2392
+ delete this.contextStore._pendingAliases;
2393
+ debug4("Stored query result with aliases:", {
2394
+ key: storageKey,
2395
+ value: output,
2396
+ aliases: pendingAliases
2397
+ });
2398
+ } else {
2399
+ this.contextStore.storeData(storageKey, output);
2400
+ debug4("Stored query result:", {
2401
+ key: storageKey,
2402
+ value: output
2403
+ });
2404
+ }
2405
+ this.contextStore.addStep({
2406
+ type: "query",
2407
+ summary: `Query: ${typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand)} (stored as ${storageKey})`,
2408
+ data: output,
2409
+ prompt: typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand)
2410
+ });
2411
+ debug4("Added query step to context store:", {
2412
+ storageKey,
2413
+ totalStoredItems: Object.keys(this.contextStore.getAllData()).length,
2414
+ totalSteps: this.contextStore.getRecentSteps(100).length
2415
+ });
2416
+ } catch (error) {
2417
+ debug4("Failed to store query result:", error);
2418
+ }
2419
+ } else {
2420
+ try {
2421
+ this.contextStore.addStep({
2422
+ type: "query",
2423
+ summary: `Query: ${typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand)}`,
2424
+ data: output,
2425
+ prompt: typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand)
2426
+ });
2427
+ } catch (error) {
2428
+ debug4("Failed to add query step:", error);
2230
2429
  }
2231
- contextStore.addStep({
2232
- type: "query",
2233
- summary: `Query: ${typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand)} (stored as ${storageKey})`,
2234
- data: output,
2235
- prompt: typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand)
2236
- });
2237
- } catch (error) {
2238
- debug4("Failed to store query result:", error);
2239
- }
2240
- } else {
2241
- try {
2242
- const aiModel = await import("misoai-core/ai-model");
2243
- const contextStore = aiModel.getContextStore();
2244
- contextStore.addStep({
2245
- type: "query",
2246
- summary: `Query: ${typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand)}`,
2247
- data: output,
2248
- prompt: typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand)
2249
- });
2250
- } catch (error) {
2251
- debug4("Failed to add query step:", error);
2252
2430
  }
2253
2431
  }
2254
2432
  const metadata = this.afterTaskRunning(executor);
@@ -2360,18 +2538,47 @@ var PageAgent = class {
2360
2538
  };
2361
2539
  }
2362
2540
  async aiAssert(assertion, msg, opt) {
2363
- let processedAssertion = assertion;
2364
- try {
2365
- const aiModel = await import("misoai-core/ai-model");
2366
- const contextStore = aiModel.getContextStore();
2367
- processedAssertion = contextStore.replaceAllReferences(assertion, "assertion");
2368
- contextStore.addStep({
2369
- type: "assertion",
2370
- summary: `Assertion: ${processedAssertion}`,
2371
- prompt: processedAssertion
2372
- });
2373
- } catch (error) {
2374
- debug4("Context store not available:", error);
2541
+ let executionContext = "";
2542
+ if (this.opts.enableCumulativeContext && this.contextStore) {
2543
+ try {
2544
+ const recentSteps = this.contextStore.getRecentSteps(3);
2545
+ const stepsWithExecutionResults = recentSteps.filter((step) => step.executionResult);
2546
+ const storedData = this.contextStore.getAllData();
2547
+ if (stepsWithExecutionResults.length > 0) {
2548
+ const recentActions = stepsWithExecutionResults.map((step) => {
2549
+ const result = step.executionResult;
2550
+ return `- ${result.description}${result.success ? "" : " (FAILED)"}`;
2551
+ }).join("\n");
2552
+ executionContext = `
2553
+
2554
+ Recent actions performed:
2555
+ ${recentActions}
2556
+
2557
+ This context may help verify the assertion.`;
2558
+ }
2559
+ if (storedData && Object.keys(storedData).length > 0) {
2560
+ executionContext += `
2561
+
2562
+ Available data for reference:
2563
+ ${JSON.stringify(storedData, null, 2)}
2564
+
2565
+ Note: If the assertion references any data keys or natural language equivalents, consider the stored values when verifying.`;
2566
+ debug4("Available data for aiAssert:", {
2567
+ assertion,
2568
+ availableData: storedData
2569
+ });
2570
+ }
2571
+ this.contextStore.addStep({
2572
+ type: "assertion",
2573
+ summary: `Assertion: ${assertion}`,
2574
+ prompt: assertion
2575
+ });
2576
+ debug4("Added assertion step to context store:", {
2577
+ totalSteps: this.contextStore.getRecentSteps(100).length
2578
+ });
2579
+ } catch (error) {
2580
+ debug4("Context store operation failed:", error);
2581
+ }
2375
2582
  }
2376
2583
  let currentUrl = "";
2377
2584
  if (this.page.url) {
@@ -2380,7 +2587,13 @@ var PageAgent = class {
2380
2587
  } catch (e) {
2381
2588
  }
2382
2589
  }
2383
- const assertionWithContext = currentUrl ? `For the page at URL "${currentUrl}", ${processedAssertion}` : processedAssertion;
2590
+ let assertionWithContext = assertion;
2591
+ if (currentUrl) {
2592
+ assertionWithContext = `For the page at URL "${currentUrl}", ${assertion}`;
2593
+ }
2594
+ if (executionContext) {
2595
+ assertionWithContext += executionContext;
2596
+ }
2384
2597
  const { output, executor } = await this.taskExecutor.assert(assertionWithContext);
2385
2598
  const metadata = this.afterTaskRunning(executor, true);
2386
2599
  if (output && opt?.keepRawResponse) {
@@ -2594,6 +2807,79 @@ ${errors}`);
2594
2807
  async destroy() {
2595
2808
  await this.page.destroy();
2596
2809
  }
2810
+ /**
2811
+ * Analyze execution results from executor to generate meaningful descriptions
2812
+ */
2813
+ analyzeExecutionResults(executor, originalPrompt) {
2814
+ const tasks = executor.tasks;
2815
+ const success = !executor.isInErrorState();
2816
+ if (!success) {
2817
+ const errorTask = executor.latestErrorTask();
2818
+ return {
2819
+ success: false,
2820
+ actionType: "error",
2821
+ description: `Failed to execute: ${originalPrompt}`,
2822
+ error: errorTask?.error
2823
+ };
2824
+ }
2825
+ const actionTasks = tasks.filter((t) => t.type === "Action" && t.status === "finished");
2826
+ const locateTasks = tasks.filter((t) => t.type === "Insight" && t.subType === "Locate");
2827
+ const lastAction = actionTasks[actionTasks.length - 1];
2828
+ const lastLocate = locateTasks[locateTasks.length - 1];
2829
+ if (!lastAction) {
2830
+ return {
2831
+ success: true,
2832
+ actionType: "unknown",
2833
+ description: `Completed: ${originalPrompt}`
2834
+ };
2835
+ }
2836
+ const actionType = lastAction.subType || "unknown";
2837
+ const elementInfo = this.extractElementInfo(lastLocate, lastAction);
2838
+ const description = this.generateActionDescription(actionType, lastAction.param, elementInfo);
2839
+ return {
2840
+ success: true,
2841
+ actionType,
2842
+ description,
2843
+ elementInfo,
2844
+ timing: lastAction.timing?.cost
2845
+ };
2846
+ }
2847
+ /**
2848
+ * Extract element information from locate task
2849
+ */
2850
+ extractElementInfo(locateTask, _actionTask) {
2851
+ if (!locateTask?.output?.element)
2852
+ return void 0;
2853
+ const element = locateTask.output.element;
2854
+ return {
2855
+ type: element.attributes?.nodeType || "unknown",
2856
+ text: element.content || element.attributes?.placeholder || element.attributes?.title || "",
2857
+ location: `(${element.center[0]}, ${element.center[1]})`
2858
+ };
2859
+ }
2860
+ /**
2861
+ * Generate natural language description for actions
2862
+ */
2863
+ generateActionDescription(actionType, param, elementInfo) {
2864
+ const elementDesc = elementInfo ? `'${elementInfo.text || elementInfo.type}' element` : "element";
2865
+ switch (actionType) {
2866
+ case "Tap":
2867
+ return `Clicked on ${elementDesc}`;
2868
+ case "Input":
2869
+ const inputValue = param?.value || "";
2870
+ return `Entered "${inputValue}" into ${elementDesc}`;
2871
+ case "KeyboardPress":
2872
+ return `Pressed ${param?.value || "key"}`;
2873
+ case "Scroll":
2874
+ return `Scrolled ${param?.direction || "on page"}`;
2875
+ case "Hover":
2876
+ return `Hovered over ${elementDesc}`;
2877
+ case "Drag":
2878
+ return `Dragged ${elementDesc}`;
2879
+ default:
2880
+ return `Performed ${actionType} action on ${elementDesc}`;
2881
+ }
2882
+ }
2597
2883
  };
2598
2884
 
2599
2885
  // src/puppeteer/base-page.ts