misoai-web 1.0.6 → 1.5.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 (47) hide show
  1. package/README.md +5 -349
  2. package/dist/es/agent.js +43 -409
  3. package/dist/es/agent.js.map +1 -1
  4. package/dist/es/bridge-mode-browser.js +3 -3
  5. package/dist/es/bridge-mode.js +45 -411
  6. package/dist/es/bridge-mode.js.map +1 -1
  7. package/dist/es/chrome-extension.js +44 -410
  8. package/dist/es/chrome-extension.js.map +1 -1
  9. package/dist/es/index.js +47 -413
  10. package/dist/es/index.js.map +1 -1
  11. package/dist/es/midscene-playground.js +43 -409
  12. package/dist/es/midscene-playground.js.map +1 -1
  13. package/dist/es/playground.js +43 -409
  14. package/dist/es/playground.js.map +1 -1
  15. package/dist/es/playwright.js +44 -410
  16. package/dist/es/playwright.js.map +1 -1
  17. package/dist/es/puppeteer-agent-launcher.js +47 -413
  18. package/dist/es/puppeteer-agent-launcher.js.map +1 -1
  19. package/dist/es/puppeteer.js +47 -413
  20. package/dist/es/puppeteer.js.map +1 -1
  21. package/dist/es/yaml.js +5 -3
  22. package/dist/es/yaml.js.map +1 -1
  23. package/dist/lib/agent.js +43 -409
  24. package/dist/lib/agent.js.map +1 -1
  25. package/dist/lib/bridge-mode-browser.js +3 -3
  26. package/dist/lib/bridge-mode.js +45 -411
  27. package/dist/lib/bridge-mode.js.map +1 -1
  28. package/dist/lib/chrome-extension.js +44 -410
  29. package/dist/lib/chrome-extension.js.map +1 -1
  30. package/dist/lib/index.js +47 -413
  31. package/dist/lib/index.js.map +1 -1
  32. package/dist/lib/midscene-playground.js +43 -409
  33. package/dist/lib/midscene-playground.js.map +1 -1
  34. package/dist/lib/playground.js +43 -409
  35. package/dist/lib/playground.js.map +1 -1
  36. package/dist/lib/playwright.js +44 -410
  37. package/dist/lib/playwright.js.map +1 -1
  38. package/dist/lib/puppeteer-agent-launcher.js +47 -413
  39. package/dist/lib/puppeteer-agent-launcher.js.map +1 -1
  40. package/dist/lib/puppeteer.js +47 -413
  41. package/dist/lib/puppeteer.js.map +1 -1
  42. package/dist/lib/yaml.js +5 -3
  43. package/dist/lib/yaml.js.map +1 -1
  44. package/dist/types/agent.d.ts +3 -44
  45. package/iife-script/htmlElement.js +2 -2
  46. package/iife-script/htmlElementDebug.js +2 -2
  47. package/package.json +4 -4
package/dist/lib/agent.js CHANGED
@@ -51,10 +51,11 @@ var ScriptPlayer = class {
51
51
  this.unnamedResultIndex = 0;
52
52
  this.pageAgent = null;
53
53
  this.result = {};
54
+ const target = script.target || script.web || script.android;
54
55
  if (import_utils.ifInBrowser) {
55
56
  this.output = void 0;
56
- } else if (script.target?.output) {
57
- this.output = (0, import_node_path.resolve)(process.cwd(), script.target.output);
57
+ } else if (target?.output) {
58
+ this.output = (0, import_node_path.resolve)(process.cwd(), target.output);
58
59
  } else {
59
60
  this.output = (0, import_node_path.join)((0, import_common.getMidsceneRunSubDir)("output"), `${process.pid}.json`);
60
61
  }
@@ -128,12 +129,13 @@ var ScriptPlayer = class {
128
129
  } else if ("aiAssert" in flowItem) {
129
130
  const assertTask = flowItem;
130
131
  const prompt = assertTask.aiAssert;
132
+ const msg = assertTask.errorMessage;
131
133
  (0, import_utils.assert)(prompt, "missing prompt for aiAssert");
132
134
  (0, import_utils.assert)(
133
135
  typeof prompt === "string",
134
136
  "prompt for aiAssert must be a string"
135
137
  );
136
- await agent.aiAssert(prompt);
138
+ await agent.aiAssert(prompt, msg);
137
139
  } else if ("aiQuery" in flowItem) {
138
140
  const queryTask = flowItem;
139
141
  const prompt = queryTask.aiQuery;
@@ -1674,7 +1676,7 @@ var import_js_yaml3 = __toESM(require("js-yaml"));
1674
1676
  var import_semver = __toESM(require("semver"));
1675
1677
 
1676
1678
  // package.json
1677
- var version = "1.0.5";
1679
+ var version = "1.5.6";
1678
1680
 
1679
1681
  // src/common/task-cache.ts
1680
1682
  var debug3 = (0, import_logger3.getDebug)("cache");
@@ -1702,70 +1704,44 @@ var TaskCache = class {
1702
1704
  this.cache = cacheContent;
1703
1705
  this.cacheOriginalLength = this.cache.caches.length;
1704
1706
  }
1705
- matchCache(prompt, type, contextData) {
1706
- const contextHash = contextData ? this.generateContextHash(contextData) : void 0;
1707
+ matchCache(prompt, type) {
1707
1708
  for (let i = 0; i < this.cacheOriginalLength; i++) {
1708
1709
  const item = this.cache.caches[i];
1709
1710
  const key = `${type}:${prompt}:${i}`;
1710
- if (item.type !== type || item.prompt !== prompt || this.matchedCacheIndices.has(key)) {
1711
- continue;
1712
- }
1713
- if (type === "plan" && item.type === "plan") {
1714
- const planItem = item;
1715
- if (contextHash && planItem.contextHash) {
1716
- if (contextHash !== planItem.contextHash) {
1717
- debug3("cache context mismatch, type: %s, prompt: %s, index: %d", type, prompt, i);
1718
- continue;
1711
+ if (item.type === type && item.prompt === prompt && !this.matchedCacheIndices.has(key)) {
1712
+ this.matchedCacheIndices.add(key);
1713
+ debug3(
1714
+ "cache found and marked as used, type: %s, prompt: %s, index: %d",
1715
+ type,
1716
+ prompt,
1717
+ i
1718
+ );
1719
+ return {
1720
+ cacheContent: item,
1721
+ updateFn: (cb) => {
1722
+ debug3(
1723
+ "will call updateFn to update cache, type: %s, prompt: %s, index: %d",
1724
+ type,
1725
+ prompt,
1726
+ i
1727
+ );
1728
+ cb(item);
1729
+ debug3(
1730
+ "cache updated, will flush to file, type: %s, prompt: %s, index: %d",
1731
+ type,
1732
+ prompt,
1733
+ i
1734
+ );
1735
+ this.flushCacheToFile();
1719
1736
  }
1720
- } else if (contextHash || planItem.contextHash) {
1721
- debug3("cache context availability mismatch, type: %s, prompt: %s, index: %d", type, prompt, i);
1722
- continue;
1723
- }
1737
+ };
1724
1738
  }
1725
- this.matchedCacheIndices.add(key);
1726
- debug3(
1727
- "cache found and marked as used, type: %s, prompt: %s, index: %d, contextMatch: %s",
1728
- type,
1729
- prompt,
1730
- i,
1731
- contextHash ? "yes" : "no-context"
1732
- );
1733
- return {
1734
- cacheContent: item,
1735
- updateFn: (cb) => {
1736
- debug3(
1737
- "will call updateFn to update cache, type: %s, prompt: %s, index: %d",
1738
- type,
1739
- prompt,
1740
- i
1741
- );
1742
- cb(item);
1743
- debug3(
1744
- "cache updated, will flush to file, type: %s, prompt: %s, index: %d",
1745
- type,
1746
- prompt,
1747
- i
1748
- );
1749
- this.flushCacheToFile();
1750
- }
1751
- };
1752
1739
  }
1753
- debug3("no unused cache found, type: %s, prompt: %s, contextHash: %s", type, prompt, contextHash);
1740
+ debug3("no unused cache found, type: %s, prompt: %s", type, prompt);
1754
1741
  return void 0;
1755
1742
  }
1756
- generateContextHash(contextData) {
1757
- const sortedKeys = Object.keys(contextData).sort();
1758
- const stableString = sortedKeys.map((key) => `${key}:${JSON.stringify(contextData[key])}`).join("|");
1759
- let hash = 0;
1760
- for (let i = 0; i < stableString.length; i++) {
1761
- const char = stableString.charCodeAt(i);
1762
- hash = (hash << 5) - hash + char;
1763
- hash = hash & hash;
1764
- }
1765
- return hash.toString(36);
1766
- }
1767
- matchPlanCache(prompt, contextData) {
1768
- return this.matchCache(prompt, "plan", contextData);
1743
+ matchPlanCache(prompt) {
1744
+ return this.matchCache(prompt, "plan");
1769
1745
  }
1770
1746
  matchLocateCache(prompt) {
1771
1747
  return this.matchCache(prompt, "locate");
@@ -1841,16 +1817,11 @@ cache file: ${cacheFile}`
1841
1817
  );
1842
1818
  }
1843
1819
  }
1844
- updateOrAppendCacheRecord(newRecord, cachedRecord, contextData) {
1820
+ updateOrAppendCacheRecord(newRecord, cachedRecord) {
1845
1821
  if (cachedRecord) {
1846
1822
  if (newRecord.type === "plan") {
1847
1823
  cachedRecord.updateFn((cache) => {
1848
- const planCache = cache;
1849
- planCache.yamlWorkflow = newRecord.yamlWorkflow;
1850
- if (contextData) {
1851
- planCache.contextHash = this.generateContextHash(contextData);
1852
- planCache.contextData = { ...contextData };
1853
- }
1824
+ cache.yamlWorkflow = newRecord.yamlWorkflow;
1854
1825
  });
1855
1826
  } else {
1856
1827
  cachedRecord.updateFn((cache) => {
@@ -1858,11 +1829,6 @@ cache file: ${cacheFile}`
1858
1829
  });
1859
1830
  }
1860
1831
  } else {
1861
- if (newRecord.type === "plan" && contextData) {
1862
- const planRecord = newRecord;
1863
- planRecord.contextHash = this.generateContextHash(contextData);
1864
- planRecord.contextData = { ...contextData };
1865
- }
1866
1832
  this.appendCache(newRecord);
1867
1833
  }
1868
1834
  }
@@ -1892,13 +1858,10 @@ var PageAgent = class {
1892
1858
  generateReport: true,
1893
1859
  autoPrintReportMsg: true,
1894
1860
  groupName: "Midscene Report",
1895
- groupDescription: "",
1896
- enableCumulativeContext: true,
1897
- autoClearContext: false
1861
+ groupDescription: ""
1898
1862
  },
1899
1863
  opts || {}
1900
1864
  );
1901
- this.initializeContextStore();
1902
1865
  if (this.page.pageType === "puppeteer" || this.page.pageType === "playwright") {
1903
1866
  this.page.waitForNavigationTimeout = this.opts.waitForNavigationTimeout || import_constants2.DEFAULT_WAIT_FOR_NAVIGATION_TIMEOUT;
1904
1867
  this.page.waitForNetworkIdleTimeout = this.opts.waitForNetworkIdleTimeout || import_constants2.DEFAULT_WAIT_FOR_NETWORK_IDLE_TIMEOUT;
@@ -1925,69 +1888,6 @@ var PageAgent = class {
1925
1888
  opts?.testId || this.page.pageType || "web"
1926
1889
  );
1927
1890
  }
1928
- /**
1929
- * Initialize context store for cumulative context functionality
1930
- */
1931
- async initializeContextStore() {
1932
- if (!this.opts.enableCumulativeContext) {
1933
- debug4("Cumulative context disabled via options");
1934
- return;
1935
- }
1936
- try {
1937
- const aiModel = await import("misoai-core/ai-model");
1938
- this.contextStore = aiModel.getContextStore();
1939
- debug4("Context store initialized successfully", {
1940
- autoClearContext: this.opts.autoClearContext,
1941
- testId: this.opts.testId
1942
- });
1943
- if (this.opts.autoClearContext) {
1944
- this.contextStore.clear();
1945
- debug4("Context store cleared due to autoClearContext option");
1946
- } else {
1947
- const existingData = this.contextStore.getAllData();
1948
- const existingSteps = this.contextStore.getRecentSteps(100).length;
1949
- debug4("Context store preserving existing data", {
1950
- existingDataKeys: Object.keys(existingData),
1951
- existingStepsCount: existingSteps
1952
- });
1953
- }
1954
- } catch (error) {
1955
- debug4("Failed to initialize context store:", error);
1956
- console.warn("⚠️ Could not initialize context store:", error);
1957
- }
1958
- }
1959
- /**
1960
- * Get the context store instance
1961
- */
1962
- getContextStore() {
1963
- return this.contextStore;
1964
- }
1965
- /**
1966
- * Clear the context store
1967
- */
1968
- clearContext() {
1969
- if (this.contextStore) {
1970
- this.contextStore.clear();
1971
- }
1972
- }
1973
- /**
1974
- * Get all stored data from context store
1975
- */
1976
- getStoredData() {
1977
- if (this.contextStore) {
1978
- return this.contextStore.getAllData();
1979
- }
1980
- return {};
1981
- }
1982
- /**
1983
- * Get step summary from context store
1984
- */
1985
- getStepSummary() {
1986
- if (this.contextStore) {
1987
- return this.contextStore.getStepSummary();
1988
- }
1989
- return "";
1990
- }
1991
1891
  async getUIContext(action) {
1992
1892
  if (action && (action === "extract" || action === "assert" || action === "captcha")) {
1993
1893
  return await parseContextFromWebPage(this.page, {
@@ -2223,35 +2123,9 @@ var PageAgent = class {
2223
2123
  };
2224
2124
  }
2225
2125
  async aiAction(taskPrompt, opt) {
2226
- const originalPrompt = taskPrompt;
2227
- let processedPrompt = taskPrompt;
2228
- if (this.opts.enableCumulativeContext && this.contextStore) {
2229
- try {
2230
- const storedData = this.contextStore.getAllData();
2231
- if (Object.keys(storedData).length > 0) {
2232
- debug4("Available data for aiAction:", {
2233
- prompt: taskPrompt,
2234
- availableData: storedData
2235
- });
2236
- }
2237
- } catch (error) {
2238
- debug4("Context store operation failed:", error);
2239
- }
2240
- }
2241
2126
  const cacheable = opt?.cacheable;
2242
2127
  const isVlmUiTars = (0, import_env2.vlLocateMode)() === "vlm-ui-tars";
2243
- let contextData;
2244
- if (this.opts.enableCumulativeContext && this.contextStore) {
2245
- try {
2246
- contextData = this.contextStore.getAllData();
2247
- if (contextData && Object.keys(contextData).length === 0) {
2248
- contextData = void 0;
2249
- }
2250
- } catch (error) {
2251
- debug4("Failed to get context data for cache:", error);
2252
- }
2253
- }
2254
- const matchedCache = isVlmUiTars || cacheable === false ? void 0 : this.taskCache?.matchPlanCache(taskPrompt, contextData);
2128
+ const matchedCache = isVlmUiTars || cacheable === false ? void 0 : this.taskCache?.matchPlanCache(taskPrompt);
2255
2129
  if (matchedCache && this.taskCache?.isCacheResultUsed) {
2256
2130
  const { executor: executor2 } = await this.taskExecutor.loadYamlFlowAsPlanning(
2257
2131
  taskPrompt,
@@ -2261,28 +2135,6 @@ var PageAgent = class {
2261
2135
  debug4("matched cache, will call .runYaml to run the action");
2262
2136
  const yaml5 = matchedCache.cacheContent?.yamlWorkflow;
2263
2137
  const result = await this.runYaml(yaml5);
2264
- if (this.opts.enableCumulativeContext && this.contextStore) {
2265
- try {
2266
- const executionResult = {
2267
- success: true,
2268
- actionType: "cached",
2269
- description: `Executed cached action: ${processedPrompt}`,
2270
- timing: result.metadata?.totalTime
2271
- };
2272
- this.contextStore.addStep({
2273
- type: "action",
2274
- summary: `Action: ${processedPrompt} (cached)`,
2275
- prompt: processedPrompt,
2276
- executionResult
2277
- });
2278
- debug4("Added cached action step to context store:", {
2279
- stepNumber: this.contextStore.getRecentSteps(1)[0]?.stepNumber,
2280
- totalSteps: this.contextStore.getRecentSteps(100).length
2281
- });
2282
- } catch (error) {
2283
- debug4("Failed to add cached action step:", error);
2284
- }
2285
- }
2286
2138
  return {
2287
2139
  result: result.result,
2288
2140
  metadata: metadata2
@@ -2307,114 +2159,17 @@ var PageAgent = class {
2307
2159
  prompt: taskPrompt,
2308
2160
  yamlWorkflow: yamlFlowStr
2309
2161
  },
2310
- matchedCache,
2311
- contextData
2312
- // Pass context data for cache creation
2162
+ matchedCache
2313
2163
  );
2314
2164
  }
2315
2165
  const metadata = this.afterTaskRunning(executor);
2316
- if (this.opts.enableCumulativeContext && this.contextStore) {
2317
- try {
2318
- const executionResult = this.analyzeExecutionResults(executor, originalPrompt);
2319
- this.contextStore.addStep({
2320
- type: "action",
2321
- summary: `Action: ${processedPrompt}`,
2322
- prompt: processedPrompt,
2323
- executionResult
2324
- });
2325
- debug4("Added action step with execution result to context store:", {
2326
- stepNumber: this.contextStore.getRecentSteps(1)[0]?.stepNumber,
2327
- totalSteps: this.contextStore.getRecentSteps(100).length,
2328
- executionResult
2329
- });
2330
- } catch (error) {
2331
- debug4("Failed to analyze execution results, adding step without execution result:", error);
2332
- try {
2333
- this.contextStore.addStep({
2334
- type: "action",
2335
- summary: `Action: ${processedPrompt}`,
2336
- prompt: processedPrompt
2337
- });
2338
- } catch (stepError) {
2339
- debug4("Failed to add action step:", stepError);
2340
- }
2341
- }
2342
- }
2343
2166
  return {
2344
2167
  result: output,
2345
2168
  metadata
2346
2169
  };
2347
2170
  }
2348
2171
  async aiQuery(demand) {
2349
- let processedDemand = demand;
2350
- let storageKey;
2351
- try {
2352
- const aiModel = await import("misoai-core/ai-model");
2353
- const contextStore = aiModel.getContextStore();
2354
- if (typeof demand === "string") {
2355
- const storageInstruction = contextStore.parseStorageInstruction(demand);
2356
- if (storageInstruction) {
2357
- storageKey = storageInstruction.key;
2358
- processedDemand = storageInstruction.cleanText;
2359
- contextStore._pendingAliases = storageInstruction.aliases;
2360
- } else {
2361
- const storageMatch = demand.match(/store\s+(?:as\s+)?(\w+)/i);
2362
- if (storageMatch) {
2363
- storageKey = storageMatch[1];
2364
- processedDemand = demand.replace(/,?\s*store\s+(?:as\s+)?\w+/i, "").trim();
2365
- }
2366
- }
2367
- }
2368
- } catch (error) {
2369
- debug4("Context store not available:", error);
2370
- }
2371
- const { output, executor } = await this.taskExecutor.query(processedDemand);
2372
- if (this.opts.enableCumulativeContext && this.contextStore) {
2373
- if (storageKey && output) {
2374
- try {
2375
- const pendingAliases = this.contextStore._pendingAliases;
2376
- if (pendingAliases) {
2377
- this.contextStore.storeDataWithAliases(storageKey, output, pendingAliases, typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand));
2378
- delete this.contextStore._pendingAliases;
2379
- debug4("Stored query result with aliases:", {
2380
- key: storageKey,
2381
- value: output,
2382
- aliases: pendingAliases
2383
- });
2384
- } else {
2385
- this.contextStore.storeData(storageKey, output);
2386
- debug4("Stored query result:", {
2387
- key: storageKey,
2388
- value: output
2389
- });
2390
- }
2391
- this.contextStore.addStep({
2392
- type: "query",
2393
- summary: `Query: ${typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand)} (stored as ${storageKey})`,
2394
- data: output,
2395
- prompt: typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand)
2396
- });
2397
- debug4("Added query step to context store:", {
2398
- storageKey,
2399
- totalStoredItems: Object.keys(this.contextStore.getAllData()).length,
2400
- totalSteps: this.contextStore.getRecentSteps(100).length
2401
- });
2402
- } catch (error) {
2403
- debug4("Failed to store query result:", error);
2404
- }
2405
- } else {
2406
- try {
2407
- this.contextStore.addStep({
2408
- type: "query",
2409
- summary: `Query: ${typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand)}`,
2410
- data: output,
2411
- prompt: typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand)
2412
- });
2413
- } catch (error) {
2414
- debug4("Failed to add query step:", error);
2415
- }
2416
- }
2417
- }
2172
+ const { output, executor } = await this.taskExecutor.query(demand);
2418
2173
  const metadata = this.afterTaskRunning(executor);
2419
2174
  return {
2420
2175
  result: output,
@@ -2524,48 +2279,6 @@ var PageAgent = class {
2524
2279
  };
2525
2280
  }
2526
2281
  async aiAssert(assertion, msg, opt) {
2527
- let executionContext = "";
2528
- if (this.opts.enableCumulativeContext && this.contextStore) {
2529
- try {
2530
- const recentSteps = this.contextStore.getRecentSteps(3);
2531
- const stepsWithExecutionResults = recentSteps.filter((step) => step.executionResult);
2532
- const storedData = this.contextStore.getAllData();
2533
- if (stepsWithExecutionResults.length > 0) {
2534
- const recentActions = stepsWithExecutionResults.map((step) => {
2535
- const result = step.executionResult;
2536
- return `- ${result.description}${result.success ? "" : " (FAILED)"}`;
2537
- }).join("\n");
2538
- executionContext = `
2539
-
2540
- Recent actions performed:
2541
- ${recentActions}
2542
-
2543
- This context may help verify the assertion.`;
2544
- }
2545
- if (storedData && Object.keys(storedData).length > 0) {
2546
- executionContext += `
2547
-
2548
- Available data for reference:
2549
- ${JSON.stringify(storedData, null, 2)}
2550
-
2551
- Note: If the assertion references any data keys or natural language equivalents, consider the stored values when verifying.`;
2552
- debug4("Available data for aiAssert:", {
2553
- assertion,
2554
- availableData: storedData
2555
- });
2556
- }
2557
- this.contextStore.addStep({
2558
- type: "assertion",
2559
- summary: `Assertion: ${assertion}`,
2560
- prompt: assertion
2561
- });
2562
- debug4("Added assertion step to context store:", {
2563
- totalSteps: this.contextStore.getRecentSteps(100).length
2564
- });
2565
- } catch (error) {
2566
- debug4("Context store operation failed:", error);
2567
- }
2568
- }
2569
2282
  let currentUrl = "";
2570
2283
  if (this.page.url) {
2571
2284
  try {
@@ -2573,13 +2286,7 @@ Note: If the assertion references any data keys or natural language equivalents,
2573
2286
  } catch (e) {
2574
2287
  }
2575
2288
  }
2576
- let assertionWithContext = assertion;
2577
- if (currentUrl) {
2578
- assertionWithContext = `For the page at URL "${currentUrl}", ${assertion}`;
2579
- }
2580
- if (executionContext) {
2581
- assertionWithContext += executionContext;
2582
- }
2289
+ const assertionWithContext = currentUrl ? `For the page at URL "${currentUrl}", ${assertion}` : assertion;
2583
2290
  const { output, executor } = await this.taskExecutor.assert(assertionWithContext);
2584
2291
  const metadata = this.afterTaskRunning(executor, true);
2585
2292
  if (output && opt?.keepRawResponse) {
@@ -2793,79 +2500,6 @@ ${errors}`);
2793
2500
  async destroy() {
2794
2501
  await this.page.destroy();
2795
2502
  }
2796
- /**
2797
- * Analyze execution results from executor to generate meaningful descriptions
2798
- */
2799
- analyzeExecutionResults(executor, originalPrompt) {
2800
- const tasks = executor.tasks;
2801
- const success = !executor.isInErrorState();
2802
- if (!success) {
2803
- const errorTask = executor.latestErrorTask();
2804
- return {
2805
- success: false,
2806
- actionType: "error",
2807
- description: `Failed to execute: ${originalPrompt}`,
2808
- error: errorTask?.error
2809
- };
2810
- }
2811
- const actionTasks = tasks.filter((t) => t.type === "Action" && t.status === "finished");
2812
- const locateTasks = tasks.filter((t) => t.type === "Insight" && t.subType === "Locate");
2813
- const lastAction = actionTasks[actionTasks.length - 1];
2814
- const lastLocate = locateTasks[locateTasks.length - 1];
2815
- if (!lastAction) {
2816
- return {
2817
- success: true,
2818
- actionType: "unknown",
2819
- description: `Completed: ${originalPrompt}`
2820
- };
2821
- }
2822
- const actionType = lastAction.subType || "unknown";
2823
- const elementInfo = this.extractElementInfo(lastLocate, lastAction);
2824
- const description = this.generateActionDescription(actionType, lastAction.param, elementInfo);
2825
- return {
2826
- success: true,
2827
- actionType,
2828
- description,
2829
- elementInfo,
2830
- timing: lastAction.timing?.cost
2831
- };
2832
- }
2833
- /**
2834
- * Extract element information from locate task
2835
- */
2836
- extractElementInfo(locateTask, _actionTask) {
2837
- if (!locateTask?.output?.element)
2838
- return void 0;
2839
- const element = locateTask.output.element;
2840
- return {
2841
- type: element.attributes?.nodeType || "unknown",
2842
- text: element.content || element.attributes?.placeholder || element.attributes?.title || "",
2843
- location: `(${element.center[0]}, ${element.center[1]})`
2844
- };
2845
- }
2846
- /**
2847
- * Generate natural language description for actions
2848
- */
2849
- generateActionDescription(actionType, param, elementInfo) {
2850
- const elementDesc = elementInfo ? `'${elementInfo.text || elementInfo.type}' element` : "element";
2851
- switch (actionType) {
2852
- case "Tap":
2853
- return `Clicked on ${elementDesc}`;
2854
- case "Input":
2855
- const inputValue = param?.value || "";
2856
- return `Entered "${inputValue}" into ${elementDesc}`;
2857
- case "KeyboardPress":
2858
- return `Pressed ${param?.value || "key"}`;
2859
- case "Scroll":
2860
- return `Scrolled ${param?.direction || "on page"}`;
2861
- case "Hover":
2862
- return `Hovered over ${elementDesc}`;
2863
- case "Drag":
2864
- return `Dragged ${elementDesc}`;
2865
- default:
2866
- return `Performed ${actionType} action on ${elementDesc}`;
2867
- }
2868
- }
2869
2503
  };
2870
2504
  // Annotate the CommonJS export names for ESM import in node:
2871
2505
  0 && (module.exports = {