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
@@ -170,10 +170,11 @@ var ScriptPlayer = class {
170
170
  this.unnamedResultIndex = 0;
171
171
  this.pageAgent = null;
172
172
  this.result = {};
173
+ const target = script.target || script.web || script.android;
173
174
  if (import_utils3.ifInBrowser) {
174
175
  this.output = void 0;
175
- } else if (script.target?.output) {
176
- this.output = (0, import_node_path.resolve)(process.cwd(), script.target.output);
176
+ } else if (target?.output) {
177
+ this.output = (0, import_node_path.resolve)(process.cwd(), target.output);
177
178
  } else {
178
179
  this.output = (0, import_node_path.join)((0, import_common.getMidsceneRunSubDir)("output"), `${process.pid}.json`);
179
180
  }
@@ -247,12 +248,13 @@ var ScriptPlayer = class {
247
248
  } else if ("aiAssert" in flowItem) {
248
249
  const assertTask = flowItem;
249
250
  const prompt = assertTask.aiAssert;
251
+ const msg = assertTask.errorMessage;
250
252
  (0, import_utils3.assert)(prompt, "missing prompt for aiAssert");
251
253
  (0, import_utils3.assert)(
252
254
  typeof prompt === "string",
253
255
  "prompt for aiAssert must be a string"
254
256
  );
255
- await agent.aiAssert(prompt);
257
+ await agent.aiAssert(prompt, msg);
256
258
  } else if ("aiQuery" in flowItem) {
257
259
  const queryTask = flowItem;
258
260
  const prompt = queryTask.aiQuery;
@@ -1679,7 +1681,7 @@ var import_js_yaml3 = __toESM(require("js-yaml"));
1679
1681
  var import_semver = __toESM(require("semver"));
1680
1682
 
1681
1683
  // package.json
1682
- var version = "1.0.5";
1684
+ var version = "1.5.6";
1683
1685
 
1684
1686
  // src/common/task-cache.ts
1685
1687
  var debug3 = (0, import_logger3.getDebug)("cache");
@@ -1707,70 +1709,44 @@ var TaskCache = class {
1707
1709
  this.cache = cacheContent;
1708
1710
  this.cacheOriginalLength = this.cache.caches.length;
1709
1711
  }
1710
- matchCache(prompt, type, contextData) {
1711
- const contextHash = contextData ? this.generateContextHash(contextData) : void 0;
1712
+ matchCache(prompt, type) {
1712
1713
  for (let i = 0; i < this.cacheOriginalLength; i++) {
1713
1714
  const item = this.cache.caches[i];
1714
1715
  const key = `${type}:${prompt}:${i}`;
1715
- if (item.type !== type || item.prompt !== prompt || this.matchedCacheIndices.has(key)) {
1716
- continue;
1717
- }
1718
- if (type === "plan" && item.type === "plan") {
1719
- const planItem = item;
1720
- if (contextHash && planItem.contextHash) {
1721
- if (contextHash !== planItem.contextHash) {
1722
- debug3("cache context mismatch, type: %s, prompt: %s, index: %d", type, prompt, i);
1723
- continue;
1716
+ if (item.type === type && item.prompt === prompt && !this.matchedCacheIndices.has(key)) {
1717
+ this.matchedCacheIndices.add(key);
1718
+ debug3(
1719
+ "cache found and marked as used, type: %s, prompt: %s, index: %d",
1720
+ type,
1721
+ prompt,
1722
+ i
1723
+ );
1724
+ return {
1725
+ cacheContent: item,
1726
+ updateFn: (cb) => {
1727
+ debug3(
1728
+ "will call updateFn to update cache, type: %s, prompt: %s, index: %d",
1729
+ type,
1730
+ prompt,
1731
+ i
1732
+ );
1733
+ cb(item);
1734
+ debug3(
1735
+ "cache updated, will flush to file, type: %s, prompt: %s, index: %d",
1736
+ type,
1737
+ prompt,
1738
+ i
1739
+ );
1740
+ this.flushCacheToFile();
1724
1741
  }
1725
- } else if (contextHash || planItem.contextHash) {
1726
- debug3("cache context availability mismatch, type: %s, prompt: %s, index: %d", type, prompt, i);
1727
- continue;
1728
- }
1742
+ };
1729
1743
  }
1730
- this.matchedCacheIndices.add(key);
1731
- debug3(
1732
- "cache found and marked as used, type: %s, prompt: %s, index: %d, contextMatch: %s",
1733
- type,
1734
- prompt,
1735
- i,
1736
- contextHash ? "yes" : "no-context"
1737
- );
1738
- return {
1739
- cacheContent: item,
1740
- updateFn: (cb) => {
1741
- debug3(
1742
- "will call updateFn to update cache, type: %s, prompt: %s, index: %d",
1743
- type,
1744
- prompt,
1745
- i
1746
- );
1747
- cb(item);
1748
- debug3(
1749
- "cache updated, will flush to file, type: %s, prompt: %s, index: %d",
1750
- type,
1751
- prompt,
1752
- i
1753
- );
1754
- this.flushCacheToFile();
1755
- }
1756
- };
1757
1744
  }
1758
- debug3("no unused cache found, type: %s, prompt: %s, contextHash: %s", type, prompt, contextHash);
1745
+ debug3("no unused cache found, type: %s, prompt: %s", type, prompt);
1759
1746
  return void 0;
1760
1747
  }
1761
- generateContextHash(contextData) {
1762
- const sortedKeys = Object.keys(contextData).sort();
1763
- const stableString = sortedKeys.map((key) => `${key}:${JSON.stringify(contextData[key])}`).join("|");
1764
- let hash = 0;
1765
- for (let i = 0; i < stableString.length; i++) {
1766
- const char = stableString.charCodeAt(i);
1767
- hash = (hash << 5) - hash + char;
1768
- hash = hash & hash;
1769
- }
1770
- return hash.toString(36);
1771
- }
1772
- matchPlanCache(prompt, contextData) {
1773
- return this.matchCache(prompt, "plan", contextData);
1748
+ matchPlanCache(prompt) {
1749
+ return this.matchCache(prompt, "plan");
1774
1750
  }
1775
1751
  matchLocateCache(prompt) {
1776
1752
  return this.matchCache(prompt, "locate");
@@ -1846,16 +1822,11 @@ cache file: ${cacheFile}`
1846
1822
  );
1847
1823
  }
1848
1824
  }
1849
- updateOrAppendCacheRecord(newRecord, cachedRecord, contextData) {
1825
+ updateOrAppendCacheRecord(newRecord, cachedRecord) {
1850
1826
  if (cachedRecord) {
1851
1827
  if (newRecord.type === "plan") {
1852
1828
  cachedRecord.updateFn((cache) => {
1853
- const planCache = cache;
1854
- planCache.yamlWorkflow = newRecord.yamlWorkflow;
1855
- if (contextData) {
1856
- planCache.contextHash = this.generateContextHash(contextData);
1857
- planCache.contextData = { ...contextData };
1858
- }
1829
+ cache.yamlWorkflow = newRecord.yamlWorkflow;
1859
1830
  });
1860
1831
  } else {
1861
1832
  cachedRecord.updateFn((cache) => {
@@ -1863,11 +1834,6 @@ cache file: ${cacheFile}`
1863
1834
  });
1864
1835
  }
1865
1836
  } else {
1866
- if (newRecord.type === "plan" && contextData) {
1867
- const planRecord = newRecord;
1868
- planRecord.contextHash = this.generateContextHash(contextData);
1869
- planRecord.contextData = { ...contextData };
1870
- }
1871
1837
  this.appendCache(newRecord);
1872
1838
  }
1873
1839
  }
@@ -1897,13 +1863,10 @@ var PageAgent = class {
1897
1863
  generateReport: true,
1898
1864
  autoPrintReportMsg: true,
1899
1865
  groupName: "Midscene Report",
1900
- groupDescription: "",
1901
- enableCumulativeContext: true,
1902
- autoClearContext: false
1866
+ groupDescription: ""
1903
1867
  },
1904
1868
  opts || {}
1905
1869
  );
1906
- this.initializeContextStore();
1907
1870
  if (this.page.pageType === "puppeteer" || this.page.pageType === "playwright") {
1908
1871
  this.page.waitForNavigationTimeout = this.opts.waitForNavigationTimeout || import_constants2.DEFAULT_WAIT_FOR_NAVIGATION_TIMEOUT;
1909
1872
  this.page.waitForNetworkIdleTimeout = this.opts.waitForNetworkIdleTimeout || import_constants2.DEFAULT_WAIT_FOR_NETWORK_IDLE_TIMEOUT;
@@ -1930,69 +1893,6 @@ var PageAgent = class {
1930
1893
  opts?.testId || this.page.pageType || "web"
1931
1894
  );
1932
1895
  }
1933
- /**
1934
- * Initialize context store for cumulative context functionality
1935
- */
1936
- async initializeContextStore() {
1937
- if (!this.opts.enableCumulativeContext) {
1938
- debug4("Cumulative context disabled via options");
1939
- return;
1940
- }
1941
- try {
1942
- const aiModel = await import("misoai-core/ai-model");
1943
- this.contextStore = aiModel.getContextStore();
1944
- debug4("Context store initialized successfully", {
1945
- autoClearContext: this.opts.autoClearContext,
1946
- testId: this.opts.testId
1947
- });
1948
- if (this.opts.autoClearContext) {
1949
- this.contextStore.clear();
1950
- debug4("Context store cleared due to autoClearContext option");
1951
- } else {
1952
- const existingData = this.contextStore.getAllData();
1953
- const existingSteps = this.contextStore.getRecentSteps(100).length;
1954
- debug4("Context store preserving existing data", {
1955
- existingDataKeys: Object.keys(existingData),
1956
- existingStepsCount: existingSteps
1957
- });
1958
- }
1959
- } catch (error) {
1960
- debug4("Failed to initialize context store:", error);
1961
- console.warn("⚠️ Could not initialize context store:", error);
1962
- }
1963
- }
1964
- /**
1965
- * Get the context store instance
1966
- */
1967
- getContextStore() {
1968
- return this.contextStore;
1969
- }
1970
- /**
1971
- * Clear the context store
1972
- */
1973
- clearContext() {
1974
- if (this.contextStore) {
1975
- this.contextStore.clear();
1976
- }
1977
- }
1978
- /**
1979
- * Get all stored data from context store
1980
- */
1981
- getStoredData() {
1982
- if (this.contextStore) {
1983
- return this.contextStore.getAllData();
1984
- }
1985
- return {};
1986
- }
1987
- /**
1988
- * Get step summary from context store
1989
- */
1990
- getStepSummary() {
1991
- if (this.contextStore) {
1992
- return this.contextStore.getStepSummary();
1993
- }
1994
- return "";
1995
- }
1996
1896
  async getUIContext(action) {
1997
1897
  if (action && (action === "extract" || action === "assert" || action === "captcha")) {
1998
1898
  return await parseContextFromWebPage(this.page, {
@@ -2228,35 +2128,9 @@ var PageAgent = class {
2228
2128
  };
2229
2129
  }
2230
2130
  async aiAction(taskPrompt, opt) {
2231
- const originalPrompt = taskPrompt;
2232
- let processedPrompt = taskPrompt;
2233
- if (this.opts.enableCumulativeContext && this.contextStore) {
2234
- try {
2235
- const storedData = this.contextStore.getAllData();
2236
- if (Object.keys(storedData).length > 0) {
2237
- debug4("Available data for aiAction:", {
2238
- prompt: taskPrompt,
2239
- availableData: storedData
2240
- });
2241
- }
2242
- } catch (error) {
2243
- debug4("Context store operation failed:", error);
2244
- }
2245
- }
2246
2131
  const cacheable = opt?.cacheable;
2247
2132
  const isVlmUiTars = (0, import_env2.vlLocateMode)() === "vlm-ui-tars";
2248
- let contextData;
2249
- if (this.opts.enableCumulativeContext && this.contextStore) {
2250
- try {
2251
- contextData = this.contextStore.getAllData();
2252
- if (contextData && Object.keys(contextData).length === 0) {
2253
- contextData = void 0;
2254
- }
2255
- } catch (error) {
2256
- debug4("Failed to get context data for cache:", error);
2257
- }
2258
- }
2259
- const matchedCache = isVlmUiTars || cacheable === false ? void 0 : this.taskCache?.matchPlanCache(taskPrompt, contextData);
2133
+ const matchedCache = isVlmUiTars || cacheable === false ? void 0 : this.taskCache?.matchPlanCache(taskPrompt);
2260
2134
  if (matchedCache && this.taskCache?.isCacheResultUsed) {
2261
2135
  const { executor: executor2 } = await this.taskExecutor.loadYamlFlowAsPlanning(
2262
2136
  taskPrompt,
@@ -2266,28 +2140,6 @@ var PageAgent = class {
2266
2140
  debug4("matched cache, will call .runYaml to run the action");
2267
2141
  const yaml5 = matchedCache.cacheContent?.yamlWorkflow;
2268
2142
  const result = await this.runYaml(yaml5);
2269
- if (this.opts.enableCumulativeContext && this.contextStore) {
2270
- try {
2271
- const executionResult = {
2272
- success: true,
2273
- actionType: "cached",
2274
- description: `Executed cached action: ${processedPrompt}`,
2275
- timing: result.metadata?.totalTime
2276
- };
2277
- this.contextStore.addStep({
2278
- type: "action",
2279
- summary: `Action: ${processedPrompt} (cached)`,
2280
- prompt: processedPrompt,
2281
- executionResult
2282
- });
2283
- debug4("Added cached action step to context store:", {
2284
- stepNumber: this.contextStore.getRecentSteps(1)[0]?.stepNumber,
2285
- totalSteps: this.contextStore.getRecentSteps(100).length
2286
- });
2287
- } catch (error) {
2288
- debug4("Failed to add cached action step:", error);
2289
- }
2290
- }
2291
2143
  return {
2292
2144
  result: result.result,
2293
2145
  metadata: metadata2
@@ -2312,114 +2164,17 @@ var PageAgent = class {
2312
2164
  prompt: taskPrompt,
2313
2165
  yamlWorkflow: yamlFlowStr
2314
2166
  },
2315
- matchedCache,
2316
- contextData
2317
- // Pass context data for cache creation
2167
+ matchedCache
2318
2168
  );
2319
2169
  }
2320
2170
  const metadata = this.afterTaskRunning(executor);
2321
- if (this.opts.enableCumulativeContext && this.contextStore) {
2322
- try {
2323
- const executionResult = this.analyzeExecutionResults(executor, originalPrompt);
2324
- this.contextStore.addStep({
2325
- type: "action",
2326
- summary: `Action: ${processedPrompt}`,
2327
- prompt: processedPrompt,
2328
- executionResult
2329
- });
2330
- debug4("Added action step with execution result to context store:", {
2331
- stepNumber: this.contextStore.getRecentSteps(1)[0]?.stepNumber,
2332
- totalSteps: this.contextStore.getRecentSteps(100).length,
2333
- executionResult
2334
- });
2335
- } catch (error) {
2336
- debug4("Failed to analyze execution results, adding step without execution result:", error);
2337
- try {
2338
- this.contextStore.addStep({
2339
- type: "action",
2340
- summary: `Action: ${processedPrompt}`,
2341
- prompt: processedPrompt
2342
- });
2343
- } catch (stepError) {
2344
- debug4("Failed to add action step:", stepError);
2345
- }
2346
- }
2347
- }
2348
2171
  return {
2349
2172
  result: output,
2350
2173
  metadata
2351
2174
  };
2352
2175
  }
2353
2176
  async aiQuery(demand) {
2354
- let processedDemand = demand;
2355
- let storageKey;
2356
- try {
2357
- const aiModel = await import("misoai-core/ai-model");
2358
- const contextStore = aiModel.getContextStore();
2359
- if (typeof demand === "string") {
2360
- const storageInstruction = contextStore.parseStorageInstruction(demand);
2361
- if (storageInstruction) {
2362
- storageKey = storageInstruction.key;
2363
- processedDemand = storageInstruction.cleanText;
2364
- contextStore._pendingAliases = storageInstruction.aliases;
2365
- } else {
2366
- const storageMatch = demand.match(/store\s+(?:as\s+)?(\w+)/i);
2367
- if (storageMatch) {
2368
- storageKey = storageMatch[1];
2369
- processedDemand = demand.replace(/,?\s*store\s+(?:as\s+)?\w+/i, "").trim();
2370
- }
2371
- }
2372
- }
2373
- } catch (error) {
2374
- debug4("Context store not available:", error);
2375
- }
2376
- const { output, executor } = await this.taskExecutor.query(processedDemand);
2377
- if (this.opts.enableCumulativeContext && this.contextStore) {
2378
- if (storageKey && output) {
2379
- try {
2380
- const pendingAliases = this.contextStore._pendingAliases;
2381
- if (pendingAliases) {
2382
- this.contextStore.storeDataWithAliases(storageKey, output, pendingAliases, typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand));
2383
- delete this.contextStore._pendingAliases;
2384
- debug4("Stored query result with aliases:", {
2385
- key: storageKey,
2386
- value: output,
2387
- aliases: pendingAliases
2388
- });
2389
- } else {
2390
- this.contextStore.storeData(storageKey, output);
2391
- debug4("Stored query result:", {
2392
- key: storageKey,
2393
- value: output
2394
- });
2395
- }
2396
- this.contextStore.addStep({
2397
- type: "query",
2398
- summary: `Query: ${typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand)} (stored as ${storageKey})`,
2399
- data: output,
2400
- prompt: typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand)
2401
- });
2402
- debug4("Added query step to context store:", {
2403
- storageKey,
2404
- totalStoredItems: Object.keys(this.contextStore.getAllData()).length,
2405
- totalSteps: this.contextStore.getRecentSteps(100).length
2406
- });
2407
- } catch (error) {
2408
- debug4("Failed to store query result:", error);
2409
- }
2410
- } else {
2411
- try {
2412
- this.contextStore.addStep({
2413
- type: "query",
2414
- summary: `Query: ${typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand)}`,
2415
- data: output,
2416
- prompt: typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand)
2417
- });
2418
- } catch (error) {
2419
- debug4("Failed to add query step:", error);
2420
- }
2421
- }
2422
- }
2177
+ const { output, executor } = await this.taskExecutor.query(demand);
2423
2178
  const metadata = this.afterTaskRunning(executor);
2424
2179
  return {
2425
2180
  result: output,
@@ -2529,48 +2284,6 @@ var PageAgent = class {
2529
2284
  };
2530
2285
  }
2531
2286
  async aiAssert(assertion, msg, opt) {
2532
- let executionContext = "";
2533
- if (this.opts.enableCumulativeContext && this.contextStore) {
2534
- try {
2535
- const recentSteps = this.contextStore.getRecentSteps(3);
2536
- const stepsWithExecutionResults = recentSteps.filter((step) => step.executionResult);
2537
- const storedData = this.contextStore.getAllData();
2538
- if (stepsWithExecutionResults.length > 0) {
2539
- const recentActions = stepsWithExecutionResults.map((step) => {
2540
- const result = step.executionResult;
2541
- return `- ${result.description}${result.success ? "" : " (FAILED)"}`;
2542
- }).join("\n");
2543
- executionContext = `
2544
-
2545
- Recent actions performed:
2546
- ${recentActions}
2547
-
2548
- This context may help verify the assertion.`;
2549
- }
2550
- if (storedData && Object.keys(storedData).length > 0) {
2551
- executionContext += `
2552
-
2553
- Available data for reference:
2554
- ${JSON.stringify(storedData, null, 2)}
2555
-
2556
- Note: If the assertion references any data keys or natural language equivalents, consider the stored values when verifying.`;
2557
- debug4("Available data for aiAssert:", {
2558
- assertion,
2559
- availableData: storedData
2560
- });
2561
- }
2562
- this.contextStore.addStep({
2563
- type: "assertion",
2564
- summary: `Assertion: ${assertion}`,
2565
- prompt: assertion
2566
- });
2567
- debug4("Added assertion step to context store:", {
2568
- totalSteps: this.contextStore.getRecentSteps(100).length
2569
- });
2570
- } catch (error) {
2571
- debug4("Context store operation failed:", error);
2572
- }
2573
- }
2574
2287
  let currentUrl = "";
2575
2288
  if (this.page.url) {
2576
2289
  try {
@@ -2578,13 +2291,7 @@ Note: If the assertion references any data keys or natural language equivalents,
2578
2291
  } catch (e) {
2579
2292
  }
2580
2293
  }
2581
- let assertionWithContext = assertion;
2582
- if (currentUrl) {
2583
- assertionWithContext = `For the page at URL "${currentUrl}", ${assertion}`;
2584
- }
2585
- if (executionContext) {
2586
- assertionWithContext += executionContext;
2587
- }
2294
+ const assertionWithContext = currentUrl ? `For the page at URL "${currentUrl}", ${assertion}` : assertion;
2588
2295
  const { output, executor } = await this.taskExecutor.assert(assertionWithContext);
2589
2296
  const metadata = this.afterTaskRunning(executor, true);
2590
2297
  if (output && opt?.keepRawResponse) {
@@ -2798,79 +2505,6 @@ ${errors}`);
2798
2505
  async destroy() {
2799
2506
  await this.page.destroy();
2800
2507
  }
2801
- /**
2802
- * Analyze execution results from executor to generate meaningful descriptions
2803
- */
2804
- analyzeExecutionResults(executor, originalPrompt) {
2805
- const tasks = executor.tasks;
2806
- const success = !executor.isInErrorState();
2807
- if (!success) {
2808
- const errorTask = executor.latestErrorTask();
2809
- return {
2810
- success: false,
2811
- actionType: "error",
2812
- description: `Failed to execute: ${originalPrompt}`,
2813
- error: errorTask?.error
2814
- };
2815
- }
2816
- const actionTasks = tasks.filter((t) => t.type === "Action" && t.status === "finished");
2817
- const locateTasks = tasks.filter((t) => t.type === "Insight" && t.subType === "Locate");
2818
- const lastAction = actionTasks[actionTasks.length - 1];
2819
- const lastLocate = locateTasks[locateTasks.length - 1];
2820
- if (!lastAction) {
2821
- return {
2822
- success: true,
2823
- actionType: "unknown",
2824
- description: `Completed: ${originalPrompt}`
2825
- };
2826
- }
2827
- const actionType = lastAction.subType || "unknown";
2828
- const elementInfo = this.extractElementInfo(lastLocate, lastAction);
2829
- const description = this.generateActionDescription(actionType, lastAction.param, elementInfo);
2830
- return {
2831
- success: true,
2832
- actionType,
2833
- description,
2834
- elementInfo,
2835
- timing: lastAction.timing?.cost
2836
- };
2837
- }
2838
- /**
2839
- * Extract element information from locate task
2840
- */
2841
- extractElementInfo(locateTask, _actionTask) {
2842
- if (!locateTask?.output?.element)
2843
- return void 0;
2844
- const element = locateTask.output.element;
2845
- return {
2846
- type: element.attributes?.nodeType || "unknown",
2847
- text: element.content || element.attributes?.placeholder || element.attributes?.title || "",
2848
- location: `(${element.center[0]}, ${element.center[1]})`
2849
- };
2850
- }
2851
- /**
2852
- * Generate natural language description for actions
2853
- */
2854
- generateActionDescription(actionType, param, elementInfo) {
2855
- const elementDesc = elementInfo ? `'${elementInfo.text || elementInfo.type}' element` : "element";
2856
- switch (actionType) {
2857
- case "Tap":
2858
- return `Clicked on ${elementDesc}`;
2859
- case "Input":
2860
- const inputValue = param?.value || "";
2861
- return `Entered "${inputValue}" into ${elementDesc}`;
2862
- case "KeyboardPress":
2863
- return `Pressed ${param?.value || "key"}`;
2864
- case "Scroll":
2865
- return `Scrolled ${param?.direction || "on page"}`;
2866
- case "Hover":
2867
- return `Hovered over ${elementDesc}`;
2868
- case "Drag":
2869
- return `Dragged ${elementDesc}`;
2870
- default:
2871
- return `Performed ${actionType} action on ${elementDesc}`;
2872
- }
2873
- }
2874
2508
  };
2875
2509
 
2876
2510
  // src/playground/agent.ts