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