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
@@ -1725,7 +1725,7 @@ var import_js_yaml3 = __toESM(require("js-yaml"));
1725
1725
  var import_semver = __toESM(require("semver"));
1726
1726
 
1727
1727
  // package.json
1728
- var version = "1.0.4";
1728
+ var version = "1.0.5";
1729
1729
 
1730
1730
  // src/common/task-cache.ts
1731
1731
  var debug3 = (0, import_logger3.getDebug)("cache");
@@ -1753,44 +1753,70 @@ var TaskCache = class {
1753
1753
  this.cache = cacheContent;
1754
1754
  this.cacheOriginalLength = this.cache.caches.length;
1755
1755
  }
1756
- matchCache(prompt, type) {
1756
+ matchCache(prompt, type, contextData) {
1757
+ const contextHash = contextData ? this.generateContextHash(contextData) : void 0;
1757
1758
  for (let i = 0; i < this.cacheOriginalLength; i++) {
1758
1759
  const item = this.cache.caches[i];
1759
1760
  const key = `${type}:${prompt}:${i}`;
1760
- if (item.type === type && item.prompt === prompt && !this.matchedCacheIndices.has(key)) {
1761
- this.matchedCacheIndices.add(key);
1762
- debug3(
1763
- "cache found and marked as used, type: %s, prompt: %s, index: %d",
1764
- type,
1765
- prompt,
1766
- i
1767
- );
1768
- return {
1769
- cacheContent: item,
1770
- updateFn: (cb) => {
1771
- debug3(
1772
- "will call updateFn to update cache, type: %s, prompt: %s, index: %d",
1773
- type,
1774
- prompt,
1775
- i
1776
- );
1777
- cb(item);
1778
- debug3(
1779
- "cache updated, will flush to file, type: %s, prompt: %s, index: %d",
1780
- type,
1781
- prompt,
1782
- i
1783
- );
1784
- this.flushCacheToFile();
1761
+ if (item.type !== type || item.prompt !== prompt || this.matchedCacheIndices.has(key)) {
1762
+ continue;
1763
+ }
1764
+ if (type === "plan" && item.type === "plan") {
1765
+ const planItem = item;
1766
+ if (contextHash && planItem.contextHash) {
1767
+ if (contextHash !== planItem.contextHash) {
1768
+ debug3("cache context mismatch, type: %s, prompt: %s, index: %d", type, prompt, i);
1769
+ continue;
1785
1770
  }
1786
- };
1771
+ } else if (contextHash || planItem.contextHash) {
1772
+ debug3("cache context availability mismatch, type: %s, prompt: %s, index: %d", type, prompt, i);
1773
+ continue;
1774
+ }
1787
1775
  }
1776
+ this.matchedCacheIndices.add(key);
1777
+ debug3(
1778
+ "cache found and marked as used, type: %s, prompt: %s, index: %d, contextMatch: %s",
1779
+ type,
1780
+ prompt,
1781
+ i,
1782
+ contextHash ? "yes" : "no-context"
1783
+ );
1784
+ return {
1785
+ cacheContent: item,
1786
+ updateFn: (cb) => {
1787
+ debug3(
1788
+ "will call updateFn to update cache, type: %s, prompt: %s, index: %d",
1789
+ type,
1790
+ prompt,
1791
+ i
1792
+ );
1793
+ cb(item);
1794
+ debug3(
1795
+ "cache updated, will flush to file, type: %s, prompt: %s, index: %d",
1796
+ type,
1797
+ prompt,
1798
+ i
1799
+ );
1800
+ this.flushCacheToFile();
1801
+ }
1802
+ };
1788
1803
  }
1789
- debug3("no unused cache found, type: %s, prompt: %s", type, prompt);
1804
+ debug3("no unused cache found, type: %s, prompt: %s, contextHash: %s", type, prompt, contextHash);
1790
1805
  return void 0;
1791
1806
  }
1792
- matchPlanCache(prompt) {
1793
- return this.matchCache(prompt, "plan");
1807
+ generateContextHash(contextData) {
1808
+ const sortedKeys = Object.keys(contextData).sort();
1809
+ const stableString = sortedKeys.map((key) => `${key}:${JSON.stringify(contextData[key])}`).join("|");
1810
+ let hash = 0;
1811
+ for (let i = 0; i < stableString.length; i++) {
1812
+ const char = stableString.charCodeAt(i);
1813
+ hash = (hash << 5) - hash + char;
1814
+ hash = hash & hash;
1815
+ }
1816
+ return hash.toString(36);
1817
+ }
1818
+ matchPlanCache(prompt, contextData) {
1819
+ return this.matchCache(prompt, "plan", contextData);
1794
1820
  }
1795
1821
  matchLocateCache(prompt) {
1796
1822
  return this.matchCache(prompt, "locate");
@@ -1866,11 +1892,16 @@ cache file: ${cacheFile}`
1866
1892
  );
1867
1893
  }
1868
1894
  }
1869
- updateOrAppendCacheRecord(newRecord, cachedRecord) {
1895
+ updateOrAppendCacheRecord(newRecord, cachedRecord, contextData) {
1870
1896
  if (cachedRecord) {
1871
1897
  if (newRecord.type === "plan") {
1872
1898
  cachedRecord.updateFn((cache) => {
1873
- cache.yamlWorkflow = newRecord.yamlWorkflow;
1899
+ const planCache = cache;
1900
+ planCache.yamlWorkflow = newRecord.yamlWorkflow;
1901
+ if (contextData) {
1902
+ planCache.contextHash = this.generateContextHash(contextData);
1903
+ planCache.contextData = { ...contextData };
1904
+ }
1874
1905
  });
1875
1906
  } else {
1876
1907
  cachedRecord.updateFn((cache) => {
@@ -1878,6 +1909,11 @@ cache file: ${cacheFile}`
1878
1909
  });
1879
1910
  }
1880
1911
  } else {
1912
+ if (newRecord.type === "plan" && contextData) {
1913
+ const planRecord = newRecord;
1914
+ planRecord.contextHash = this.generateContextHash(contextData);
1915
+ planRecord.contextData = { ...contextData };
1916
+ }
1881
1917
  this.appendCache(newRecord);
1882
1918
  }
1883
1919
  }
@@ -1907,10 +1943,13 @@ var PageAgent = class {
1907
1943
  generateReport: true,
1908
1944
  autoPrintReportMsg: true,
1909
1945
  groupName: "Midscene Report",
1910
- groupDescription: ""
1946
+ groupDescription: "",
1947
+ enableCumulativeContext: true,
1948
+ autoClearContext: false
1911
1949
  },
1912
1950
  opts || {}
1913
1951
  );
1952
+ this.initializeContextStore();
1914
1953
  if (this.page.pageType === "puppeteer" || this.page.pageType === "playwright") {
1915
1954
  this.page.waitForNavigationTimeout = this.opts.waitForNavigationTimeout || import_constants2.DEFAULT_WAIT_FOR_NAVIGATION_TIMEOUT;
1916
1955
  this.page.waitForNetworkIdleTimeout = this.opts.waitForNetworkIdleTimeout || import_constants2.DEFAULT_WAIT_FOR_NETWORK_IDLE_TIMEOUT;
@@ -1937,6 +1976,69 @@ var PageAgent = class {
1937
1976
  opts?.testId || this.page.pageType || "web"
1938
1977
  );
1939
1978
  }
1979
+ /**
1980
+ * Initialize context store for cumulative context functionality
1981
+ */
1982
+ async initializeContextStore() {
1983
+ if (!this.opts.enableCumulativeContext) {
1984
+ debug4("Cumulative context disabled via options");
1985
+ return;
1986
+ }
1987
+ try {
1988
+ const aiModel = await import("misoai-core/ai-model");
1989
+ this.contextStore = aiModel.getContextStore();
1990
+ debug4("Context store initialized successfully", {
1991
+ autoClearContext: this.opts.autoClearContext,
1992
+ testId: this.opts.testId
1993
+ });
1994
+ if (this.opts.autoClearContext) {
1995
+ this.contextStore.clear();
1996
+ debug4("Context store cleared due to autoClearContext option");
1997
+ } else {
1998
+ const existingData = this.contextStore.getAllData();
1999
+ const existingSteps = this.contextStore.getRecentSteps(100).length;
2000
+ debug4("Context store preserving existing data", {
2001
+ existingDataKeys: Object.keys(existingData),
2002
+ existingStepsCount: existingSteps
2003
+ });
2004
+ }
2005
+ } catch (error) {
2006
+ debug4("Failed to initialize context store:", error);
2007
+ console.warn("⚠️ Could not initialize context store:", error);
2008
+ }
2009
+ }
2010
+ /**
2011
+ * Get the context store instance
2012
+ */
2013
+ getContextStore() {
2014
+ return this.contextStore;
2015
+ }
2016
+ /**
2017
+ * Clear the context store
2018
+ */
2019
+ clearContext() {
2020
+ if (this.contextStore) {
2021
+ this.contextStore.clear();
2022
+ }
2023
+ }
2024
+ /**
2025
+ * Get all stored data from context store
2026
+ */
2027
+ getStoredData() {
2028
+ if (this.contextStore) {
2029
+ return this.contextStore.getAllData();
2030
+ }
2031
+ return {};
2032
+ }
2033
+ /**
2034
+ * Get step summary from context store
2035
+ */
2036
+ getStepSummary() {
2037
+ if (this.contextStore) {
2038
+ return this.contextStore.getStepSummary();
2039
+ }
2040
+ return "";
2041
+ }
1940
2042
  async getUIContext(action) {
1941
2043
  if (action && (action === "extract" || action === "assert" || action === "captcha")) {
1942
2044
  return await parseContextFromWebPage(this.page, {
@@ -2172,22 +2274,35 @@ var PageAgent = class {
2172
2274
  };
2173
2275
  }
2174
2276
  async aiAction(taskPrompt, opt) {
2175
- try {
2176
- const aiModel = await import("misoai-core/ai-model");
2177
- const contextStore = aiModel.getContextStore();
2178
- const processedPrompt = contextStore.replaceAllReferences(taskPrompt, "action");
2179
- contextStore.addStep({
2180
- type: "action",
2181
- summary: `Action: ${processedPrompt}`,
2182
- prompt: processedPrompt
2183
- });
2184
- taskPrompt = processedPrompt;
2185
- } catch (error) {
2186
- debug4("Context store not available:", error);
2277
+ const originalPrompt = taskPrompt;
2278
+ let processedPrompt = taskPrompt;
2279
+ if (this.opts.enableCumulativeContext && this.contextStore) {
2280
+ try {
2281
+ const storedData = this.contextStore.getAllData();
2282
+ if (Object.keys(storedData).length > 0) {
2283
+ debug4("Available data for aiAction:", {
2284
+ prompt: taskPrompt,
2285
+ availableData: storedData
2286
+ });
2287
+ }
2288
+ } catch (error) {
2289
+ debug4("Context store operation failed:", error);
2290
+ }
2187
2291
  }
2188
2292
  const cacheable = opt?.cacheable;
2189
2293
  const isVlmUiTars = (0, import_env2.vlLocateMode)() === "vlm-ui-tars";
2190
- const matchedCache = isVlmUiTars || cacheable === false ? void 0 : this.taskCache?.matchPlanCache(taskPrompt);
2294
+ let contextData;
2295
+ if (this.opts.enableCumulativeContext && this.contextStore) {
2296
+ try {
2297
+ contextData = this.contextStore.getAllData();
2298
+ if (contextData && Object.keys(contextData).length === 0) {
2299
+ contextData = void 0;
2300
+ }
2301
+ } catch (error) {
2302
+ debug4("Failed to get context data for cache:", error);
2303
+ }
2304
+ }
2305
+ const matchedCache = isVlmUiTars || cacheable === false ? void 0 : this.taskCache?.matchPlanCache(taskPrompt, contextData);
2191
2306
  if (matchedCache && this.taskCache?.isCacheResultUsed) {
2192
2307
  const { executor: executor2 } = await this.taskExecutor.loadYamlFlowAsPlanning(
2193
2308
  taskPrompt,
@@ -2197,6 +2312,28 @@ var PageAgent = class {
2197
2312
  debug4("matched cache, will call .runYaml to run the action");
2198
2313
  const yaml5 = matchedCache.cacheContent?.yamlWorkflow;
2199
2314
  const result = await this.runYaml(yaml5);
2315
+ if (this.opts.enableCumulativeContext && this.contextStore) {
2316
+ try {
2317
+ const executionResult = {
2318
+ success: true,
2319
+ actionType: "cached",
2320
+ description: `Executed cached action: ${processedPrompt}`,
2321
+ timing: result.metadata?.totalTime
2322
+ };
2323
+ this.contextStore.addStep({
2324
+ type: "action",
2325
+ summary: `Action: ${processedPrompt} (cached)`,
2326
+ prompt: processedPrompt,
2327
+ executionResult
2328
+ });
2329
+ debug4("Added cached action step to context store:", {
2330
+ stepNumber: this.contextStore.getRecentSteps(1)[0]?.stepNumber,
2331
+ totalSteps: this.contextStore.getRecentSteps(100).length
2332
+ });
2333
+ } catch (error) {
2334
+ debug4("Failed to add cached action step:", error);
2335
+ }
2336
+ }
2200
2337
  return {
2201
2338
  result: result.result,
2202
2339
  metadata: metadata2
@@ -2221,10 +2358,39 @@ var PageAgent = class {
2221
2358
  prompt: taskPrompt,
2222
2359
  yamlWorkflow: yamlFlowStr
2223
2360
  },
2224
- matchedCache
2361
+ matchedCache,
2362
+ contextData
2363
+ // Pass context data for cache creation
2225
2364
  );
2226
2365
  }
2227
2366
  const metadata = this.afterTaskRunning(executor);
2367
+ if (this.opts.enableCumulativeContext && this.contextStore) {
2368
+ try {
2369
+ const executionResult = this.analyzeExecutionResults(executor, originalPrompt);
2370
+ this.contextStore.addStep({
2371
+ type: "action",
2372
+ summary: `Action: ${processedPrompt}`,
2373
+ prompt: processedPrompt,
2374
+ executionResult
2375
+ });
2376
+ debug4("Added action step with execution result to context store:", {
2377
+ stepNumber: this.contextStore.getRecentSteps(1)[0]?.stepNumber,
2378
+ totalSteps: this.contextStore.getRecentSteps(100).length,
2379
+ executionResult
2380
+ });
2381
+ } catch (error) {
2382
+ debug4("Failed to analyze execution results, adding step without execution result:", error);
2383
+ try {
2384
+ this.contextStore.addStep({
2385
+ type: "action",
2386
+ summary: `Action: ${processedPrompt}`,
2387
+ prompt: processedPrompt
2388
+ });
2389
+ } catch (stepError) {
2390
+ debug4("Failed to add action step:", stepError);
2391
+ }
2392
+ }
2393
+ }
2228
2394
  return {
2229
2395
  result: output,
2230
2396
  metadata
@@ -2254,38 +2420,50 @@ var PageAgent = class {
2254
2420
  debug4("Context store not available:", error);
2255
2421
  }
2256
2422
  const { output, executor } = await this.taskExecutor.query(processedDemand);
2257
- if (storageKey && output) {
2258
- try {
2259
- const aiModel = await import("misoai-core/ai-model");
2260
- const contextStore = aiModel.getContextStore();
2261
- const pendingAliases = contextStore._pendingAliases;
2262
- if (pendingAliases) {
2263
- contextStore.storeDataWithAliases(storageKey, output, pendingAliases, typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand));
2264
- delete contextStore._pendingAliases;
2265
- } else {
2266
- contextStore.storeData(storageKey, output);
2423
+ if (this.opts.enableCumulativeContext && this.contextStore) {
2424
+ if (storageKey && output) {
2425
+ try {
2426
+ const pendingAliases = this.contextStore._pendingAliases;
2427
+ if (pendingAliases) {
2428
+ this.contextStore.storeDataWithAliases(storageKey, output, pendingAliases, typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand));
2429
+ delete this.contextStore._pendingAliases;
2430
+ debug4("Stored query result with aliases:", {
2431
+ key: storageKey,
2432
+ value: output,
2433
+ aliases: pendingAliases
2434
+ });
2435
+ } else {
2436
+ this.contextStore.storeData(storageKey, output);
2437
+ debug4("Stored query result:", {
2438
+ key: storageKey,
2439
+ value: output
2440
+ });
2441
+ }
2442
+ this.contextStore.addStep({
2443
+ type: "query",
2444
+ summary: `Query: ${typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand)} (stored as ${storageKey})`,
2445
+ data: output,
2446
+ prompt: typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand)
2447
+ });
2448
+ debug4("Added query step to context store:", {
2449
+ storageKey,
2450
+ totalStoredItems: Object.keys(this.contextStore.getAllData()).length,
2451
+ totalSteps: this.contextStore.getRecentSteps(100).length
2452
+ });
2453
+ } catch (error) {
2454
+ debug4("Failed to store query result:", error);
2455
+ }
2456
+ } else {
2457
+ try {
2458
+ this.contextStore.addStep({
2459
+ type: "query",
2460
+ summary: `Query: ${typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand)}`,
2461
+ data: output,
2462
+ prompt: typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand)
2463
+ });
2464
+ } catch (error) {
2465
+ debug4("Failed to add query step:", error);
2267
2466
  }
2268
- contextStore.addStep({
2269
- type: "query",
2270
- summary: `Query: ${typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand)} (stored as ${storageKey})`,
2271
- data: output,
2272
- prompt: typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand)
2273
- });
2274
- } catch (error) {
2275
- debug4("Failed to store query result:", error);
2276
- }
2277
- } else {
2278
- try {
2279
- const aiModel = await import("misoai-core/ai-model");
2280
- const contextStore = aiModel.getContextStore();
2281
- contextStore.addStep({
2282
- type: "query",
2283
- summary: `Query: ${typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand)}`,
2284
- data: output,
2285
- prompt: typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand)
2286
- });
2287
- } catch (error) {
2288
- debug4("Failed to add query step:", error);
2289
2467
  }
2290
2468
  }
2291
2469
  const metadata = this.afterTaskRunning(executor);
@@ -2397,18 +2575,47 @@ var PageAgent = class {
2397
2575
  };
2398
2576
  }
2399
2577
  async aiAssert(assertion, msg, opt) {
2400
- let processedAssertion = assertion;
2401
- try {
2402
- const aiModel = await import("misoai-core/ai-model");
2403
- const contextStore = aiModel.getContextStore();
2404
- processedAssertion = contextStore.replaceAllReferences(assertion, "assertion");
2405
- contextStore.addStep({
2406
- type: "assertion",
2407
- summary: `Assertion: ${processedAssertion}`,
2408
- prompt: processedAssertion
2409
- });
2410
- } catch (error) {
2411
- debug4("Context store not available:", error);
2578
+ let executionContext = "";
2579
+ if (this.opts.enableCumulativeContext && this.contextStore) {
2580
+ try {
2581
+ const recentSteps = this.contextStore.getRecentSteps(3);
2582
+ const stepsWithExecutionResults = recentSteps.filter((step) => step.executionResult);
2583
+ const storedData = this.contextStore.getAllData();
2584
+ if (stepsWithExecutionResults.length > 0) {
2585
+ const recentActions = stepsWithExecutionResults.map((step) => {
2586
+ const result = step.executionResult;
2587
+ return `- ${result.description}${result.success ? "" : " (FAILED)"}`;
2588
+ }).join("\n");
2589
+ executionContext = `
2590
+
2591
+ Recent actions performed:
2592
+ ${recentActions}
2593
+
2594
+ This context may help verify the assertion.`;
2595
+ }
2596
+ if (storedData && Object.keys(storedData).length > 0) {
2597
+ executionContext += `
2598
+
2599
+ Available data for reference:
2600
+ ${JSON.stringify(storedData, null, 2)}
2601
+
2602
+ Note: If the assertion references any data keys or natural language equivalents, consider the stored values when verifying.`;
2603
+ debug4("Available data for aiAssert:", {
2604
+ assertion,
2605
+ availableData: storedData
2606
+ });
2607
+ }
2608
+ this.contextStore.addStep({
2609
+ type: "assertion",
2610
+ summary: `Assertion: ${assertion}`,
2611
+ prompt: assertion
2612
+ });
2613
+ debug4("Added assertion step to context store:", {
2614
+ totalSteps: this.contextStore.getRecentSteps(100).length
2615
+ });
2616
+ } catch (error) {
2617
+ debug4("Context store operation failed:", error);
2618
+ }
2412
2619
  }
2413
2620
  let currentUrl = "";
2414
2621
  if (this.page.url) {
@@ -2417,7 +2624,13 @@ var PageAgent = class {
2417
2624
  } catch (e) {
2418
2625
  }
2419
2626
  }
2420
- const assertionWithContext = currentUrl ? `For the page at URL "${currentUrl}", ${processedAssertion}` : processedAssertion;
2627
+ let assertionWithContext = assertion;
2628
+ if (currentUrl) {
2629
+ assertionWithContext = `For the page at URL "${currentUrl}", ${assertion}`;
2630
+ }
2631
+ if (executionContext) {
2632
+ assertionWithContext += executionContext;
2633
+ }
2421
2634
  const { output, executor } = await this.taskExecutor.assert(assertionWithContext);
2422
2635
  const metadata = this.afterTaskRunning(executor, true);
2423
2636
  if (output && opt?.keepRawResponse) {
@@ -2631,6 +2844,79 @@ ${errors}`);
2631
2844
  async destroy() {
2632
2845
  await this.page.destroy();
2633
2846
  }
2847
+ /**
2848
+ * Analyze execution results from executor to generate meaningful descriptions
2849
+ */
2850
+ analyzeExecutionResults(executor, originalPrompt) {
2851
+ const tasks = executor.tasks;
2852
+ const success = !executor.isInErrorState();
2853
+ if (!success) {
2854
+ const errorTask = executor.latestErrorTask();
2855
+ return {
2856
+ success: false,
2857
+ actionType: "error",
2858
+ description: `Failed to execute: ${originalPrompt}`,
2859
+ error: errorTask?.error
2860
+ };
2861
+ }
2862
+ const actionTasks = tasks.filter((t) => t.type === "Action" && t.status === "finished");
2863
+ const locateTasks = tasks.filter((t) => t.type === "Insight" && t.subType === "Locate");
2864
+ const lastAction = actionTasks[actionTasks.length - 1];
2865
+ const lastLocate = locateTasks[locateTasks.length - 1];
2866
+ if (!lastAction) {
2867
+ return {
2868
+ success: true,
2869
+ actionType: "unknown",
2870
+ description: `Completed: ${originalPrompt}`
2871
+ };
2872
+ }
2873
+ const actionType = lastAction.subType || "unknown";
2874
+ const elementInfo = this.extractElementInfo(lastLocate, lastAction);
2875
+ const description = this.generateActionDescription(actionType, lastAction.param, elementInfo);
2876
+ return {
2877
+ success: true,
2878
+ actionType,
2879
+ description,
2880
+ elementInfo,
2881
+ timing: lastAction.timing?.cost
2882
+ };
2883
+ }
2884
+ /**
2885
+ * Extract element information from locate task
2886
+ */
2887
+ extractElementInfo(locateTask, _actionTask) {
2888
+ if (!locateTask?.output?.element)
2889
+ return void 0;
2890
+ const element = locateTask.output.element;
2891
+ return {
2892
+ type: element.attributes?.nodeType || "unknown",
2893
+ text: element.content || element.attributes?.placeholder || element.attributes?.title || "",
2894
+ location: `(${element.center[0]}, ${element.center[1]})`
2895
+ };
2896
+ }
2897
+ /**
2898
+ * Generate natural language description for actions
2899
+ */
2900
+ generateActionDescription(actionType, param, elementInfo) {
2901
+ const elementDesc = elementInfo ? `'${elementInfo.text || elementInfo.type}' element` : "element";
2902
+ switch (actionType) {
2903
+ case "Tap":
2904
+ return `Clicked on ${elementDesc}`;
2905
+ case "Input":
2906
+ const inputValue = param?.value || "";
2907
+ return `Entered "${inputValue}" into ${elementDesc}`;
2908
+ case "KeyboardPress":
2909
+ return `Pressed ${param?.value || "key"}`;
2910
+ case "Scroll":
2911
+ return `Scrolled ${param?.direction || "on page"}`;
2912
+ case "Hover":
2913
+ return `Hovered over ${elementDesc}`;
2914
+ case "Drag":
2915
+ return `Dragged ${elementDesc}`;
2916
+ default:
2917
+ return `Performed ${actionType} action on ${elementDesc}`;
2918
+ }
2919
+ }
2634
2920
  };
2635
2921
 
2636
2922
  // src/chrome-extension/agent.ts
@@ -2848,7 +3134,7 @@ function sleep2(ms) {
2848
3134
  var ChromeExtensionProxyPage = class {
2849
3135
  constructor(forceSameTabNavigation) {
2850
3136
  this.pageType = "chrome-extension-proxy";
2851
- this.version = "1.0.4";
3137
+ this.version = "1.0.5";
2852
3138
  this.activeTabId = null;
2853
3139
  this.tabIdOfDebuggerAttached = null;
2854
3140
  this.attachingDebugger = null;