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
@@ -1707,7 +1707,7 @@ import yaml3 from "js-yaml";
1707
1707
  import semver from "semver";
1708
1708
 
1709
1709
  // package.json
1710
- var version = "1.0.4";
1710
+ var version = "1.0.5";
1711
1711
 
1712
1712
  // src/common/task-cache.ts
1713
1713
  var debug3 = getDebug3("cache");
@@ -1735,44 +1735,70 @@ var TaskCache = class {
1735
1735
  this.cache = cacheContent;
1736
1736
  this.cacheOriginalLength = this.cache.caches.length;
1737
1737
  }
1738
- matchCache(prompt, type) {
1738
+ matchCache(prompt, type, contextData) {
1739
+ const contextHash = contextData ? this.generateContextHash(contextData) : void 0;
1739
1740
  for (let i = 0; i < this.cacheOriginalLength; i++) {
1740
1741
  const item = this.cache.caches[i];
1741
1742
  const key = `${type}:${prompt}:${i}`;
1742
- if (item.type === type && item.prompt === prompt && !this.matchedCacheIndices.has(key)) {
1743
- this.matchedCacheIndices.add(key);
1744
- debug3(
1745
- "cache found and marked as used, type: %s, prompt: %s, index: %d",
1746
- type,
1747
- prompt,
1748
- i
1749
- );
1750
- return {
1751
- cacheContent: item,
1752
- updateFn: (cb) => {
1753
- debug3(
1754
- "will call updateFn to update cache, type: %s, prompt: %s, index: %d",
1755
- type,
1756
- prompt,
1757
- i
1758
- );
1759
- cb(item);
1760
- debug3(
1761
- "cache updated, will flush to file, type: %s, prompt: %s, index: %d",
1762
- type,
1763
- prompt,
1764
- i
1765
- );
1766
- this.flushCacheToFile();
1743
+ if (item.type !== type || item.prompt !== prompt || this.matchedCacheIndices.has(key)) {
1744
+ continue;
1745
+ }
1746
+ if (type === "plan" && item.type === "plan") {
1747
+ const planItem = item;
1748
+ if (contextHash && planItem.contextHash) {
1749
+ if (contextHash !== planItem.contextHash) {
1750
+ debug3("cache context mismatch, type: %s, prompt: %s, index: %d", type, prompt, i);
1751
+ continue;
1767
1752
  }
1768
- };
1753
+ } else if (contextHash || planItem.contextHash) {
1754
+ debug3("cache context availability mismatch, type: %s, prompt: %s, index: %d", type, prompt, i);
1755
+ continue;
1756
+ }
1769
1757
  }
1758
+ this.matchedCacheIndices.add(key);
1759
+ debug3(
1760
+ "cache found and marked as used, type: %s, prompt: %s, index: %d, contextMatch: %s",
1761
+ type,
1762
+ prompt,
1763
+ i,
1764
+ contextHash ? "yes" : "no-context"
1765
+ );
1766
+ return {
1767
+ cacheContent: item,
1768
+ updateFn: (cb) => {
1769
+ debug3(
1770
+ "will call updateFn to update cache, type: %s, prompt: %s, index: %d",
1771
+ type,
1772
+ prompt,
1773
+ i
1774
+ );
1775
+ cb(item);
1776
+ debug3(
1777
+ "cache updated, will flush to file, type: %s, prompt: %s, index: %d",
1778
+ type,
1779
+ prompt,
1780
+ i
1781
+ );
1782
+ this.flushCacheToFile();
1783
+ }
1784
+ };
1770
1785
  }
1771
- debug3("no unused cache found, type: %s, prompt: %s", type, prompt);
1786
+ debug3("no unused cache found, type: %s, prompt: %s, contextHash: %s", type, prompt, contextHash);
1772
1787
  return void 0;
1773
1788
  }
1774
- matchPlanCache(prompt) {
1775
- return this.matchCache(prompt, "plan");
1789
+ generateContextHash(contextData) {
1790
+ const sortedKeys = Object.keys(contextData).sort();
1791
+ const stableString = sortedKeys.map((key) => `${key}:${JSON.stringify(contextData[key])}`).join("|");
1792
+ let hash = 0;
1793
+ for (let i = 0; i < stableString.length; i++) {
1794
+ const char = stableString.charCodeAt(i);
1795
+ hash = (hash << 5) - hash + char;
1796
+ hash = hash & hash;
1797
+ }
1798
+ return hash.toString(36);
1799
+ }
1800
+ matchPlanCache(prompt, contextData) {
1801
+ return this.matchCache(prompt, "plan", contextData);
1776
1802
  }
1777
1803
  matchLocateCache(prompt) {
1778
1804
  return this.matchCache(prompt, "locate");
@@ -1848,11 +1874,16 @@ cache file: ${cacheFile}`
1848
1874
  );
1849
1875
  }
1850
1876
  }
1851
- updateOrAppendCacheRecord(newRecord, cachedRecord) {
1877
+ updateOrAppendCacheRecord(newRecord, cachedRecord, contextData) {
1852
1878
  if (cachedRecord) {
1853
1879
  if (newRecord.type === "plan") {
1854
1880
  cachedRecord.updateFn((cache) => {
1855
- cache.yamlWorkflow = newRecord.yamlWorkflow;
1881
+ const planCache = cache;
1882
+ planCache.yamlWorkflow = newRecord.yamlWorkflow;
1883
+ if (contextData) {
1884
+ planCache.contextHash = this.generateContextHash(contextData);
1885
+ planCache.contextData = { ...contextData };
1886
+ }
1856
1887
  });
1857
1888
  } else {
1858
1889
  cachedRecord.updateFn((cache) => {
@@ -1860,6 +1891,11 @@ cache file: ${cacheFile}`
1860
1891
  });
1861
1892
  }
1862
1893
  } else {
1894
+ if (newRecord.type === "plan" && contextData) {
1895
+ const planRecord = newRecord;
1896
+ planRecord.contextHash = this.generateContextHash(contextData);
1897
+ planRecord.contextData = { ...contextData };
1898
+ }
1863
1899
  this.appendCache(newRecord);
1864
1900
  }
1865
1901
  }
@@ -1889,10 +1925,13 @@ var PageAgent = class {
1889
1925
  generateReport: true,
1890
1926
  autoPrintReportMsg: true,
1891
1927
  groupName: "Midscene Report",
1892
- groupDescription: ""
1928
+ groupDescription: "",
1929
+ enableCumulativeContext: true,
1930
+ autoClearContext: false
1893
1931
  },
1894
1932
  opts || {}
1895
1933
  );
1934
+ this.initializeContextStore();
1896
1935
  if (this.page.pageType === "puppeteer" || this.page.pageType === "playwright") {
1897
1936
  this.page.waitForNavigationTimeout = this.opts.waitForNavigationTimeout || DEFAULT_WAIT_FOR_NAVIGATION_TIMEOUT;
1898
1937
  this.page.waitForNetworkIdleTimeout = this.opts.waitForNetworkIdleTimeout || DEFAULT_WAIT_FOR_NETWORK_IDLE_TIMEOUT;
@@ -1919,6 +1958,69 @@ var PageAgent = class {
1919
1958
  opts?.testId || this.page.pageType || "web"
1920
1959
  );
1921
1960
  }
1961
+ /**
1962
+ * Initialize context store for cumulative context functionality
1963
+ */
1964
+ async initializeContextStore() {
1965
+ if (!this.opts.enableCumulativeContext) {
1966
+ debug4("Cumulative context disabled via options");
1967
+ return;
1968
+ }
1969
+ try {
1970
+ const aiModel = await import("misoai-core/ai-model");
1971
+ this.contextStore = aiModel.getContextStore();
1972
+ debug4("Context store initialized successfully", {
1973
+ autoClearContext: this.opts.autoClearContext,
1974
+ testId: this.opts.testId
1975
+ });
1976
+ if (this.opts.autoClearContext) {
1977
+ this.contextStore.clear();
1978
+ debug4("Context store cleared due to autoClearContext option");
1979
+ } else {
1980
+ const existingData = this.contextStore.getAllData();
1981
+ const existingSteps = this.contextStore.getRecentSteps(100).length;
1982
+ debug4("Context store preserving existing data", {
1983
+ existingDataKeys: Object.keys(existingData),
1984
+ existingStepsCount: existingSteps
1985
+ });
1986
+ }
1987
+ } catch (error) {
1988
+ debug4("Failed to initialize context store:", error);
1989
+ console.warn("⚠️ Could not initialize context store:", error);
1990
+ }
1991
+ }
1992
+ /**
1993
+ * Get the context store instance
1994
+ */
1995
+ getContextStore() {
1996
+ return this.contextStore;
1997
+ }
1998
+ /**
1999
+ * Clear the context store
2000
+ */
2001
+ clearContext() {
2002
+ if (this.contextStore) {
2003
+ this.contextStore.clear();
2004
+ }
2005
+ }
2006
+ /**
2007
+ * Get all stored data from context store
2008
+ */
2009
+ getStoredData() {
2010
+ if (this.contextStore) {
2011
+ return this.contextStore.getAllData();
2012
+ }
2013
+ return {};
2014
+ }
2015
+ /**
2016
+ * Get step summary from context store
2017
+ */
2018
+ getStepSummary() {
2019
+ if (this.contextStore) {
2020
+ return this.contextStore.getStepSummary();
2021
+ }
2022
+ return "";
2023
+ }
1922
2024
  async getUIContext(action) {
1923
2025
  if (action && (action === "extract" || action === "assert" || action === "captcha")) {
1924
2026
  return await parseContextFromWebPage(this.page, {
@@ -2154,22 +2256,35 @@ var PageAgent = class {
2154
2256
  };
2155
2257
  }
2156
2258
  async aiAction(taskPrompt, opt) {
2157
- try {
2158
- const aiModel = await import("misoai-core/ai-model");
2159
- const contextStore = aiModel.getContextStore();
2160
- const processedPrompt = contextStore.replaceAllReferences(taskPrompt, "action");
2161
- contextStore.addStep({
2162
- type: "action",
2163
- summary: `Action: ${processedPrompt}`,
2164
- prompt: processedPrompt
2165
- });
2166
- taskPrompt = processedPrompt;
2167
- } catch (error) {
2168
- debug4("Context store not available:", error);
2259
+ const originalPrompt = taskPrompt;
2260
+ let processedPrompt = taskPrompt;
2261
+ if (this.opts.enableCumulativeContext && this.contextStore) {
2262
+ try {
2263
+ const storedData = this.contextStore.getAllData();
2264
+ if (Object.keys(storedData).length > 0) {
2265
+ debug4("Available data for aiAction:", {
2266
+ prompt: taskPrompt,
2267
+ availableData: storedData
2268
+ });
2269
+ }
2270
+ } catch (error) {
2271
+ debug4("Context store operation failed:", error);
2272
+ }
2169
2273
  }
2170
2274
  const cacheable = opt?.cacheable;
2171
2275
  const isVlmUiTars = vlLocateMode() === "vlm-ui-tars";
2172
- const matchedCache = isVlmUiTars || cacheable === false ? void 0 : this.taskCache?.matchPlanCache(taskPrompt);
2276
+ let contextData;
2277
+ if (this.opts.enableCumulativeContext && this.contextStore) {
2278
+ try {
2279
+ contextData = this.contextStore.getAllData();
2280
+ if (contextData && Object.keys(contextData).length === 0) {
2281
+ contextData = void 0;
2282
+ }
2283
+ } catch (error) {
2284
+ debug4("Failed to get context data for cache:", error);
2285
+ }
2286
+ }
2287
+ const matchedCache = isVlmUiTars || cacheable === false ? void 0 : this.taskCache?.matchPlanCache(taskPrompt, contextData);
2173
2288
  if (matchedCache && this.taskCache?.isCacheResultUsed) {
2174
2289
  const { executor: executor2 } = await this.taskExecutor.loadYamlFlowAsPlanning(
2175
2290
  taskPrompt,
@@ -2179,6 +2294,28 @@ var PageAgent = class {
2179
2294
  debug4("matched cache, will call .runYaml to run the action");
2180
2295
  const yaml5 = matchedCache.cacheContent?.yamlWorkflow;
2181
2296
  const result = await this.runYaml(yaml5);
2297
+ if (this.opts.enableCumulativeContext && this.contextStore) {
2298
+ try {
2299
+ const executionResult = {
2300
+ success: true,
2301
+ actionType: "cached",
2302
+ description: `Executed cached action: ${processedPrompt}`,
2303
+ timing: result.metadata?.totalTime
2304
+ };
2305
+ this.contextStore.addStep({
2306
+ type: "action",
2307
+ summary: `Action: ${processedPrompt} (cached)`,
2308
+ prompt: processedPrompt,
2309
+ executionResult
2310
+ });
2311
+ debug4("Added cached action step to context store:", {
2312
+ stepNumber: this.contextStore.getRecentSteps(1)[0]?.stepNumber,
2313
+ totalSteps: this.contextStore.getRecentSteps(100).length
2314
+ });
2315
+ } catch (error) {
2316
+ debug4("Failed to add cached action step:", error);
2317
+ }
2318
+ }
2182
2319
  return {
2183
2320
  result: result.result,
2184
2321
  metadata: metadata2
@@ -2203,10 +2340,39 @@ var PageAgent = class {
2203
2340
  prompt: taskPrompt,
2204
2341
  yamlWorkflow: yamlFlowStr
2205
2342
  },
2206
- matchedCache
2343
+ matchedCache,
2344
+ contextData
2345
+ // Pass context data for cache creation
2207
2346
  );
2208
2347
  }
2209
2348
  const metadata = this.afterTaskRunning(executor);
2349
+ if (this.opts.enableCumulativeContext && this.contextStore) {
2350
+ try {
2351
+ const executionResult = this.analyzeExecutionResults(executor, originalPrompt);
2352
+ this.contextStore.addStep({
2353
+ type: "action",
2354
+ summary: `Action: ${processedPrompt}`,
2355
+ prompt: processedPrompt,
2356
+ executionResult
2357
+ });
2358
+ debug4("Added action step with execution result to context store:", {
2359
+ stepNumber: this.contextStore.getRecentSteps(1)[0]?.stepNumber,
2360
+ totalSteps: this.contextStore.getRecentSteps(100).length,
2361
+ executionResult
2362
+ });
2363
+ } catch (error) {
2364
+ debug4("Failed to analyze execution results, adding step without execution result:", error);
2365
+ try {
2366
+ this.contextStore.addStep({
2367
+ type: "action",
2368
+ summary: `Action: ${processedPrompt}`,
2369
+ prompt: processedPrompt
2370
+ });
2371
+ } catch (stepError) {
2372
+ debug4("Failed to add action step:", stepError);
2373
+ }
2374
+ }
2375
+ }
2210
2376
  return {
2211
2377
  result: output,
2212
2378
  metadata
@@ -2236,38 +2402,50 @@ var PageAgent = class {
2236
2402
  debug4("Context store not available:", error);
2237
2403
  }
2238
2404
  const { output, executor } = await this.taskExecutor.query(processedDemand);
2239
- if (storageKey && output) {
2240
- try {
2241
- const aiModel = await import("misoai-core/ai-model");
2242
- const contextStore = aiModel.getContextStore();
2243
- const pendingAliases = contextStore._pendingAliases;
2244
- if (pendingAliases) {
2245
- contextStore.storeDataWithAliases(storageKey, output, pendingAliases, typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand));
2246
- delete contextStore._pendingAliases;
2247
- } else {
2248
- contextStore.storeData(storageKey, output);
2405
+ if (this.opts.enableCumulativeContext && this.contextStore) {
2406
+ if (storageKey && output) {
2407
+ try {
2408
+ const pendingAliases = this.contextStore._pendingAliases;
2409
+ if (pendingAliases) {
2410
+ this.contextStore.storeDataWithAliases(storageKey, output, pendingAliases, typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand));
2411
+ delete this.contextStore._pendingAliases;
2412
+ debug4("Stored query result with aliases:", {
2413
+ key: storageKey,
2414
+ value: output,
2415
+ aliases: pendingAliases
2416
+ });
2417
+ } else {
2418
+ this.contextStore.storeData(storageKey, output);
2419
+ debug4("Stored query result:", {
2420
+ key: storageKey,
2421
+ value: output
2422
+ });
2423
+ }
2424
+ this.contextStore.addStep({
2425
+ type: "query",
2426
+ summary: `Query: ${typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand)} (stored as ${storageKey})`,
2427
+ data: output,
2428
+ prompt: typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand)
2429
+ });
2430
+ debug4("Added query step to context store:", {
2431
+ storageKey,
2432
+ totalStoredItems: Object.keys(this.contextStore.getAllData()).length,
2433
+ totalSteps: this.contextStore.getRecentSteps(100).length
2434
+ });
2435
+ } catch (error) {
2436
+ debug4("Failed to store query result:", error);
2437
+ }
2438
+ } else {
2439
+ try {
2440
+ this.contextStore.addStep({
2441
+ type: "query",
2442
+ summary: `Query: ${typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand)}`,
2443
+ data: output,
2444
+ prompt: typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand)
2445
+ });
2446
+ } catch (error) {
2447
+ debug4("Failed to add query step:", error);
2249
2448
  }
2250
- contextStore.addStep({
2251
- type: "query",
2252
- summary: `Query: ${typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand)} (stored as ${storageKey})`,
2253
- data: output,
2254
- prompt: typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand)
2255
- });
2256
- } catch (error) {
2257
- debug4("Failed to store query result:", error);
2258
- }
2259
- } else {
2260
- try {
2261
- const aiModel = await import("misoai-core/ai-model");
2262
- const contextStore = aiModel.getContextStore();
2263
- contextStore.addStep({
2264
- type: "query",
2265
- summary: `Query: ${typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand)}`,
2266
- data: output,
2267
- prompt: typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand)
2268
- });
2269
- } catch (error) {
2270
- debug4("Failed to add query step:", error);
2271
2449
  }
2272
2450
  }
2273
2451
  const metadata = this.afterTaskRunning(executor);
@@ -2379,18 +2557,47 @@ var PageAgent = class {
2379
2557
  };
2380
2558
  }
2381
2559
  async aiAssert(assertion, msg, opt) {
2382
- let processedAssertion = assertion;
2383
- try {
2384
- const aiModel = await import("misoai-core/ai-model");
2385
- const contextStore = aiModel.getContextStore();
2386
- processedAssertion = contextStore.replaceAllReferences(assertion, "assertion");
2387
- contextStore.addStep({
2388
- type: "assertion",
2389
- summary: `Assertion: ${processedAssertion}`,
2390
- prompt: processedAssertion
2391
- });
2392
- } catch (error) {
2393
- debug4("Context store not available:", error);
2560
+ let executionContext = "";
2561
+ if (this.opts.enableCumulativeContext && this.contextStore) {
2562
+ try {
2563
+ const recentSteps = this.contextStore.getRecentSteps(3);
2564
+ const stepsWithExecutionResults = recentSteps.filter((step) => step.executionResult);
2565
+ const storedData = this.contextStore.getAllData();
2566
+ if (stepsWithExecutionResults.length > 0) {
2567
+ const recentActions = stepsWithExecutionResults.map((step) => {
2568
+ const result = step.executionResult;
2569
+ return `- ${result.description}${result.success ? "" : " (FAILED)"}`;
2570
+ }).join("\n");
2571
+ executionContext = `
2572
+
2573
+ Recent actions performed:
2574
+ ${recentActions}
2575
+
2576
+ This context may help verify the assertion.`;
2577
+ }
2578
+ if (storedData && Object.keys(storedData).length > 0) {
2579
+ executionContext += `
2580
+
2581
+ Available data for reference:
2582
+ ${JSON.stringify(storedData, null, 2)}
2583
+
2584
+ Note: If the assertion references any data keys or natural language equivalents, consider the stored values when verifying.`;
2585
+ debug4("Available data for aiAssert:", {
2586
+ assertion,
2587
+ availableData: storedData
2588
+ });
2589
+ }
2590
+ this.contextStore.addStep({
2591
+ type: "assertion",
2592
+ summary: `Assertion: ${assertion}`,
2593
+ prompt: assertion
2594
+ });
2595
+ debug4("Added assertion step to context store:", {
2596
+ totalSteps: this.contextStore.getRecentSteps(100).length
2597
+ });
2598
+ } catch (error) {
2599
+ debug4("Context store operation failed:", error);
2600
+ }
2394
2601
  }
2395
2602
  let currentUrl = "";
2396
2603
  if (this.page.url) {
@@ -2399,7 +2606,13 @@ var PageAgent = class {
2399
2606
  } catch (e) {
2400
2607
  }
2401
2608
  }
2402
- const assertionWithContext = currentUrl ? `For the page at URL "${currentUrl}", ${processedAssertion}` : processedAssertion;
2609
+ let assertionWithContext = assertion;
2610
+ if (currentUrl) {
2611
+ assertionWithContext = `For the page at URL "${currentUrl}", ${assertion}`;
2612
+ }
2613
+ if (executionContext) {
2614
+ assertionWithContext += executionContext;
2615
+ }
2403
2616
  const { output, executor } = await this.taskExecutor.assert(assertionWithContext);
2404
2617
  const metadata = this.afterTaskRunning(executor, true);
2405
2618
  if (output && opt?.keepRawResponse) {
@@ -2613,6 +2826,79 @@ ${errors}`);
2613
2826
  async destroy() {
2614
2827
  await this.page.destroy();
2615
2828
  }
2829
+ /**
2830
+ * Analyze execution results from executor to generate meaningful descriptions
2831
+ */
2832
+ analyzeExecutionResults(executor, originalPrompt) {
2833
+ const tasks = executor.tasks;
2834
+ const success = !executor.isInErrorState();
2835
+ if (!success) {
2836
+ const errorTask = executor.latestErrorTask();
2837
+ return {
2838
+ success: false,
2839
+ actionType: "error",
2840
+ description: `Failed to execute: ${originalPrompt}`,
2841
+ error: errorTask?.error
2842
+ };
2843
+ }
2844
+ const actionTasks = tasks.filter((t) => t.type === "Action" && t.status === "finished");
2845
+ const locateTasks = tasks.filter((t) => t.type === "Insight" && t.subType === "Locate");
2846
+ const lastAction = actionTasks[actionTasks.length - 1];
2847
+ const lastLocate = locateTasks[locateTasks.length - 1];
2848
+ if (!lastAction) {
2849
+ return {
2850
+ success: true,
2851
+ actionType: "unknown",
2852
+ description: `Completed: ${originalPrompt}`
2853
+ };
2854
+ }
2855
+ const actionType = lastAction.subType || "unknown";
2856
+ const elementInfo = this.extractElementInfo(lastLocate, lastAction);
2857
+ const description = this.generateActionDescription(actionType, lastAction.param, elementInfo);
2858
+ return {
2859
+ success: true,
2860
+ actionType,
2861
+ description,
2862
+ elementInfo,
2863
+ timing: lastAction.timing?.cost
2864
+ };
2865
+ }
2866
+ /**
2867
+ * Extract element information from locate task
2868
+ */
2869
+ extractElementInfo(locateTask, _actionTask) {
2870
+ if (!locateTask?.output?.element)
2871
+ return void 0;
2872
+ const element = locateTask.output.element;
2873
+ return {
2874
+ type: element.attributes?.nodeType || "unknown",
2875
+ text: element.content || element.attributes?.placeholder || element.attributes?.title || "",
2876
+ location: `(${element.center[0]}, ${element.center[1]})`
2877
+ };
2878
+ }
2879
+ /**
2880
+ * Generate natural language description for actions
2881
+ */
2882
+ generateActionDescription(actionType, param, elementInfo) {
2883
+ const elementDesc = elementInfo ? `'${elementInfo.text || elementInfo.type}' element` : "element";
2884
+ switch (actionType) {
2885
+ case "Tap":
2886
+ return `Clicked on ${elementDesc}`;
2887
+ case "Input":
2888
+ const inputValue = param?.value || "";
2889
+ return `Entered "${inputValue}" into ${elementDesc}`;
2890
+ case "KeyboardPress":
2891
+ return `Pressed ${param?.value || "key"}`;
2892
+ case "Scroll":
2893
+ return `Scrolled ${param?.direction || "on page"}`;
2894
+ case "Hover":
2895
+ return `Hovered over ${elementDesc}`;
2896
+ case "Drag":
2897
+ return `Dragged ${elementDesc}`;
2898
+ default:
2899
+ return `Performed ${actionType} action on ${elementDesc}`;
2900
+ }
2901
+ }
2616
2902
  };
2617
2903
 
2618
2904
  // src/chrome-extension/agent.ts
@@ -2832,7 +3118,7 @@ function sleep2(ms) {
2832
3118
  var ChromeExtensionProxyPage = class {
2833
3119
  constructor(forceSameTabNavigation) {
2834
3120
  this.pageType = "chrome-extension-proxy";
2835
- this.version = "1.0.4";
3121
+ this.version = "1.0.5";
2836
3122
  this.activeTabId = null;
2837
3123
  this.tabIdOfDebuggerAttached = null;
2838
3124
  this.attachingDebugger = null;