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.
- package/LICENSE +21 -21
- package/README.md +353 -9
- package/bin/midscene-playground +2 -2
- package/dist/es/agent.js +378 -92
- package/dist/es/agent.js.map +1 -1
- package/dist/es/bridge-mode-browser.js +3 -3
- package/dist/es/bridge-mode-browser.js.map +1 -1
- package/dist/es/bridge-mode.js +380 -94
- package/dist/es/bridge-mode.js.map +1 -1
- package/dist/es/chrome-extension.js +379 -93
- package/dist/es/chrome-extension.js.map +1 -1
- package/dist/es/index.js +378 -92
- package/dist/es/index.js.map +1 -1
- package/dist/es/midscene-playground.js +378 -92
- package/dist/es/midscene-playground.js.map +1 -1
- package/dist/es/midscene-server.js.map +1 -1
- package/dist/es/playground.js +378 -92
- package/dist/es/playground.js.map +1 -1
- package/dist/es/playwright-report.js.map +1 -1
- package/dist/es/playwright.js +378 -92
- package/dist/es/playwright.js.map +1 -1
- package/dist/es/puppeteer-agent-launcher.js +378 -92
- package/dist/es/puppeteer-agent-launcher.js.map +1 -1
- package/dist/es/puppeteer.js +378 -92
- package/dist/es/puppeteer.js.map +1 -1
- package/dist/es/ui-utils.js.map +1 -1
- package/dist/es/utils.js.map +1 -1
- package/dist/es/yaml.js.map +1 -1
- package/dist/lib/agent.js +378 -92
- package/dist/lib/agent.js.map +1 -1
- package/dist/lib/bridge-mode-browser.js +3 -3
- package/dist/lib/bridge-mode-browser.js.map +1 -1
- package/dist/lib/bridge-mode.js +380 -94
- package/dist/lib/bridge-mode.js.map +1 -1
- package/dist/lib/chrome-extension.js +379 -93
- package/dist/lib/chrome-extension.js.map +1 -1
- package/dist/lib/index.js +378 -92
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/midscene-playground.js +378 -92
- package/dist/lib/midscene-playground.js.map +1 -1
- package/dist/lib/midscene-server.js.map +1 -1
- package/dist/lib/playground.js +378 -92
- package/dist/lib/playground.js.map +1 -1
- package/dist/lib/playwright-report.js.map +1 -1
- package/dist/lib/playwright.js +378 -92
- package/dist/lib/playwright.js.map +1 -1
- package/dist/lib/puppeteer-agent-launcher.js +378 -92
- package/dist/lib/puppeteer-agent-launcher.js.map +1 -1
- package/dist/lib/puppeteer.js +378 -92
- package/dist/lib/puppeteer.js.map +1 -1
- package/dist/lib/ui-utils.js.map +1 -1
- package/dist/lib/utils.js.map +1 -1
- package/dist/lib/yaml.js.map +1 -1
- package/dist/types/agent.d.ts +45 -4
- package/dist/types/bridge-mode-browser.d.ts +2 -2
- package/dist/types/bridge-mode.d.ts +2 -2
- package/dist/types/{browser-a1877d18.d.ts → browser-aec1055d.d.ts} +1 -1
- package/dist/types/chrome-extension.d.ts +2 -2
- package/dist/types/index.d.ts +1 -1
- package/dist/types/midscene-server.d.ts +1 -1
- package/dist/types/{page-663ece08.d.ts → page-86ab0fe1.d.ts} +34 -34
- package/dist/types/playground.d.ts +2 -2
- package/dist/types/playwright.d.ts +1 -1
- package/dist/types/puppeteer-agent-launcher.d.ts +1 -1
- package/dist/types/puppeteer.d.ts +1 -1
- package/dist/types/utils.d.ts +1 -1
- package/dist/types/yaml.d.ts +1 -1
- package/package.json +3 -3
@@ -1661,7 +1661,7 @@ import yaml3 from "js-yaml";
|
|
1661
1661
|
import semver from "semver";
|
1662
1662
|
|
1663
1663
|
// package.json
|
1664
|
-
var version = "1.0.
|
1664
|
+
var version = "1.0.5";
|
1665
1665
|
|
1666
1666
|
// src/common/task-cache.ts
|
1667
1667
|
var debug3 = getDebug3("cache");
|
@@ -1689,44 +1689,70 @@ var TaskCache = class {
|
|
1689
1689
|
this.cache = cacheContent;
|
1690
1690
|
this.cacheOriginalLength = this.cache.caches.length;
|
1691
1691
|
}
|
1692
|
-
matchCache(prompt, type) {
|
1692
|
+
matchCache(prompt, type, contextData) {
|
1693
|
+
const contextHash = contextData ? this.generateContextHash(contextData) : void 0;
|
1693
1694
|
for (let i = 0; i < this.cacheOriginalLength; i++) {
|
1694
1695
|
const item = this.cache.caches[i];
|
1695
1696
|
const key = `${type}:${prompt}:${i}`;
|
1696
|
-
if (item.type
|
1697
|
-
|
1698
|
-
|
1699
|
-
|
1700
|
-
|
1701
|
-
|
1702
|
-
|
1703
|
-
|
1704
|
-
|
1705
|
-
cacheContent: item,
|
1706
|
-
updateFn: (cb) => {
|
1707
|
-
debug3(
|
1708
|
-
"will call updateFn to update cache, type: %s, prompt: %s, index: %d",
|
1709
|
-
type,
|
1710
|
-
prompt,
|
1711
|
-
i
|
1712
|
-
);
|
1713
|
-
cb(item);
|
1714
|
-
debug3(
|
1715
|
-
"cache updated, will flush to file, type: %s, prompt: %s, index: %d",
|
1716
|
-
type,
|
1717
|
-
prompt,
|
1718
|
-
i
|
1719
|
-
);
|
1720
|
-
this.flushCacheToFile();
|
1697
|
+
if (item.type !== type || item.prompt !== prompt || this.matchedCacheIndices.has(key)) {
|
1698
|
+
continue;
|
1699
|
+
}
|
1700
|
+
if (type === "plan" && item.type === "plan") {
|
1701
|
+
const planItem = item;
|
1702
|
+
if (contextHash && planItem.contextHash) {
|
1703
|
+
if (contextHash !== planItem.contextHash) {
|
1704
|
+
debug3("cache context mismatch, type: %s, prompt: %s, index: %d", type, prompt, i);
|
1705
|
+
continue;
|
1721
1706
|
}
|
1722
|
-
}
|
1707
|
+
} else if (contextHash || planItem.contextHash) {
|
1708
|
+
debug3("cache context availability mismatch, type: %s, prompt: %s, index: %d", type, prompt, i);
|
1709
|
+
continue;
|
1710
|
+
}
|
1723
1711
|
}
|
1712
|
+
this.matchedCacheIndices.add(key);
|
1713
|
+
debug3(
|
1714
|
+
"cache found and marked as used, type: %s, prompt: %s, index: %d, contextMatch: %s",
|
1715
|
+
type,
|
1716
|
+
prompt,
|
1717
|
+
i,
|
1718
|
+
contextHash ? "yes" : "no-context"
|
1719
|
+
);
|
1720
|
+
return {
|
1721
|
+
cacheContent: item,
|
1722
|
+
updateFn: (cb) => {
|
1723
|
+
debug3(
|
1724
|
+
"will call updateFn to update cache, type: %s, prompt: %s, index: %d",
|
1725
|
+
type,
|
1726
|
+
prompt,
|
1727
|
+
i
|
1728
|
+
);
|
1729
|
+
cb(item);
|
1730
|
+
debug3(
|
1731
|
+
"cache updated, will flush to file, type: %s, prompt: %s, index: %d",
|
1732
|
+
type,
|
1733
|
+
prompt,
|
1734
|
+
i
|
1735
|
+
);
|
1736
|
+
this.flushCacheToFile();
|
1737
|
+
}
|
1738
|
+
};
|
1724
1739
|
}
|
1725
|
-
debug3("no unused cache found, type: %s, prompt: %s", type, prompt);
|
1740
|
+
debug3("no unused cache found, type: %s, prompt: %s, contextHash: %s", type, prompt, contextHash);
|
1726
1741
|
return void 0;
|
1727
1742
|
}
|
1728
|
-
|
1729
|
-
|
1743
|
+
generateContextHash(contextData) {
|
1744
|
+
const sortedKeys = Object.keys(contextData).sort();
|
1745
|
+
const stableString = sortedKeys.map((key) => `${key}:${JSON.stringify(contextData[key])}`).join("|");
|
1746
|
+
let hash = 0;
|
1747
|
+
for (let i = 0; i < stableString.length; i++) {
|
1748
|
+
const char = stableString.charCodeAt(i);
|
1749
|
+
hash = (hash << 5) - hash + char;
|
1750
|
+
hash = hash & hash;
|
1751
|
+
}
|
1752
|
+
return hash.toString(36);
|
1753
|
+
}
|
1754
|
+
matchPlanCache(prompt, contextData) {
|
1755
|
+
return this.matchCache(prompt, "plan", contextData);
|
1730
1756
|
}
|
1731
1757
|
matchLocateCache(prompt) {
|
1732
1758
|
return this.matchCache(prompt, "locate");
|
@@ -1802,11 +1828,16 @@ cache file: ${cacheFile}`
|
|
1802
1828
|
);
|
1803
1829
|
}
|
1804
1830
|
}
|
1805
|
-
updateOrAppendCacheRecord(newRecord, cachedRecord) {
|
1831
|
+
updateOrAppendCacheRecord(newRecord, cachedRecord, contextData) {
|
1806
1832
|
if (cachedRecord) {
|
1807
1833
|
if (newRecord.type === "plan") {
|
1808
1834
|
cachedRecord.updateFn((cache) => {
|
1809
|
-
|
1835
|
+
const planCache = cache;
|
1836
|
+
planCache.yamlWorkflow = newRecord.yamlWorkflow;
|
1837
|
+
if (contextData) {
|
1838
|
+
planCache.contextHash = this.generateContextHash(contextData);
|
1839
|
+
planCache.contextData = { ...contextData };
|
1840
|
+
}
|
1810
1841
|
});
|
1811
1842
|
} else {
|
1812
1843
|
cachedRecord.updateFn((cache) => {
|
@@ -1814,6 +1845,11 @@ cache file: ${cacheFile}`
|
|
1814
1845
|
});
|
1815
1846
|
}
|
1816
1847
|
} else {
|
1848
|
+
if (newRecord.type === "plan" && contextData) {
|
1849
|
+
const planRecord = newRecord;
|
1850
|
+
planRecord.contextHash = this.generateContextHash(contextData);
|
1851
|
+
planRecord.contextData = { ...contextData };
|
1852
|
+
}
|
1817
1853
|
this.appendCache(newRecord);
|
1818
1854
|
}
|
1819
1855
|
}
|
@@ -1843,10 +1879,13 @@ var PageAgent = class {
|
|
1843
1879
|
generateReport: true,
|
1844
1880
|
autoPrintReportMsg: true,
|
1845
1881
|
groupName: "Midscene Report",
|
1846
|
-
groupDescription: ""
|
1882
|
+
groupDescription: "",
|
1883
|
+
enableCumulativeContext: true,
|
1884
|
+
autoClearContext: false
|
1847
1885
|
},
|
1848
1886
|
opts || {}
|
1849
1887
|
);
|
1888
|
+
this.initializeContextStore();
|
1850
1889
|
if (this.page.pageType === "puppeteer" || this.page.pageType === "playwright") {
|
1851
1890
|
this.page.waitForNavigationTimeout = this.opts.waitForNavigationTimeout || DEFAULT_WAIT_FOR_NAVIGATION_TIMEOUT;
|
1852
1891
|
this.page.waitForNetworkIdleTimeout = this.opts.waitForNetworkIdleTimeout || DEFAULT_WAIT_FOR_NETWORK_IDLE_TIMEOUT;
|
@@ -1873,6 +1912,69 @@ var PageAgent = class {
|
|
1873
1912
|
opts?.testId || this.page.pageType || "web"
|
1874
1913
|
);
|
1875
1914
|
}
|
1915
|
+
/**
|
1916
|
+
* Initialize context store for cumulative context functionality
|
1917
|
+
*/
|
1918
|
+
async initializeContextStore() {
|
1919
|
+
if (!this.opts.enableCumulativeContext) {
|
1920
|
+
debug4("Cumulative context disabled via options");
|
1921
|
+
return;
|
1922
|
+
}
|
1923
|
+
try {
|
1924
|
+
const aiModel = await import("misoai-core/ai-model");
|
1925
|
+
this.contextStore = aiModel.getContextStore();
|
1926
|
+
debug4("Context store initialized successfully", {
|
1927
|
+
autoClearContext: this.opts.autoClearContext,
|
1928
|
+
testId: this.opts.testId
|
1929
|
+
});
|
1930
|
+
if (this.opts.autoClearContext) {
|
1931
|
+
this.contextStore.clear();
|
1932
|
+
debug4("Context store cleared due to autoClearContext option");
|
1933
|
+
} else {
|
1934
|
+
const existingData = this.contextStore.getAllData();
|
1935
|
+
const existingSteps = this.contextStore.getRecentSteps(100).length;
|
1936
|
+
debug4("Context store preserving existing data", {
|
1937
|
+
existingDataKeys: Object.keys(existingData),
|
1938
|
+
existingStepsCount: existingSteps
|
1939
|
+
});
|
1940
|
+
}
|
1941
|
+
} catch (error) {
|
1942
|
+
debug4("Failed to initialize context store:", error);
|
1943
|
+
console.warn("⚠️ Could not initialize context store:", error);
|
1944
|
+
}
|
1945
|
+
}
|
1946
|
+
/**
|
1947
|
+
* Get the context store instance
|
1948
|
+
*/
|
1949
|
+
getContextStore() {
|
1950
|
+
return this.contextStore;
|
1951
|
+
}
|
1952
|
+
/**
|
1953
|
+
* Clear the context store
|
1954
|
+
*/
|
1955
|
+
clearContext() {
|
1956
|
+
if (this.contextStore) {
|
1957
|
+
this.contextStore.clear();
|
1958
|
+
}
|
1959
|
+
}
|
1960
|
+
/**
|
1961
|
+
* Get all stored data from context store
|
1962
|
+
*/
|
1963
|
+
getStoredData() {
|
1964
|
+
if (this.contextStore) {
|
1965
|
+
return this.contextStore.getAllData();
|
1966
|
+
}
|
1967
|
+
return {};
|
1968
|
+
}
|
1969
|
+
/**
|
1970
|
+
* Get step summary from context store
|
1971
|
+
*/
|
1972
|
+
getStepSummary() {
|
1973
|
+
if (this.contextStore) {
|
1974
|
+
return this.contextStore.getStepSummary();
|
1975
|
+
}
|
1976
|
+
return "";
|
1977
|
+
}
|
1876
1978
|
async getUIContext(action) {
|
1877
1979
|
if (action && (action === "extract" || action === "assert" || action === "captcha")) {
|
1878
1980
|
return await parseContextFromWebPage(this.page, {
|
@@ -2108,22 +2210,35 @@ var PageAgent = class {
|
|
2108
2210
|
};
|
2109
2211
|
}
|
2110
2212
|
async aiAction(taskPrompt, opt) {
|
2111
|
-
|
2112
|
-
|
2113
|
-
|
2114
|
-
|
2115
|
-
|
2116
|
-
|
2117
|
-
|
2118
|
-
|
2119
|
-
|
2120
|
-
|
2121
|
-
|
2122
|
-
|
2213
|
+
const originalPrompt = taskPrompt;
|
2214
|
+
let processedPrompt = taskPrompt;
|
2215
|
+
if (this.opts.enableCumulativeContext && this.contextStore) {
|
2216
|
+
try {
|
2217
|
+
const storedData = this.contextStore.getAllData();
|
2218
|
+
if (Object.keys(storedData).length > 0) {
|
2219
|
+
debug4("Available data for aiAction:", {
|
2220
|
+
prompt: taskPrompt,
|
2221
|
+
availableData: storedData
|
2222
|
+
});
|
2223
|
+
}
|
2224
|
+
} catch (error) {
|
2225
|
+
debug4("Context store operation failed:", error);
|
2226
|
+
}
|
2123
2227
|
}
|
2124
2228
|
const cacheable = opt?.cacheable;
|
2125
2229
|
const isVlmUiTars = vlLocateMode() === "vlm-ui-tars";
|
2126
|
-
|
2230
|
+
let contextData;
|
2231
|
+
if (this.opts.enableCumulativeContext && this.contextStore) {
|
2232
|
+
try {
|
2233
|
+
contextData = this.contextStore.getAllData();
|
2234
|
+
if (contextData && Object.keys(contextData).length === 0) {
|
2235
|
+
contextData = void 0;
|
2236
|
+
}
|
2237
|
+
} catch (error) {
|
2238
|
+
debug4("Failed to get context data for cache:", error);
|
2239
|
+
}
|
2240
|
+
}
|
2241
|
+
const matchedCache = isVlmUiTars || cacheable === false ? void 0 : this.taskCache?.matchPlanCache(taskPrompt, contextData);
|
2127
2242
|
if (matchedCache && this.taskCache?.isCacheResultUsed) {
|
2128
2243
|
const { executor: executor2 } = await this.taskExecutor.loadYamlFlowAsPlanning(
|
2129
2244
|
taskPrompt,
|
@@ -2133,6 +2248,28 @@ var PageAgent = class {
|
|
2133
2248
|
debug4("matched cache, will call .runYaml to run the action");
|
2134
2249
|
const yaml5 = matchedCache.cacheContent?.yamlWorkflow;
|
2135
2250
|
const result = await this.runYaml(yaml5);
|
2251
|
+
if (this.opts.enableCumulativeContext && this.contextStore) {
|
2252
|
+
try {
|
2253
|
+
const executionResult = {
|
2254
|
+
success: true,
|
2255
|
+
actionType: "cached",
|
2256
|
+
description: `Executed cached action: ${processedPrompt}`,
|
2257
|
+
timing: result.metadata?.totalTime
|
2258
|
+
};
|
2259
|
+
this.contextStore.addStep({
|
2260
|
+
type: "action",
|
2261
|
+
summary: `Action: ${processedPrompt} (cached)`,
|
2262
|
+
prompt: processedPrompt,
|
2263
|
+
executionResult
|
2264
|
+
});
|
2265
|
+
debug4("Added cached action step to context store:", {
|
2266
|
+
stepNumber: this.contextStore.getRecentSteps(1)[0]?.stepNumber,
|
2267
|
+
totalSteps: this.contextStore.getRecentSteps(100).length
|
2268
|
+
});
|
2269
|
+
} catch (error) {
|
2270
|
+
debug4("Failed to add cached action step:", error);
|
2271
|
+
}
|
2272
|
+
}
|
2136
2273
|
return {
|
2137
2274
|
result: result.result,
|
2138
2275
|
metadata: metadata2
|
@@ -2157,10 +2294,39 @@ var PageAgent = class {
|
|
2157
2294
|
prompt: taskPrompt,
|
2158
2295
|
yamlWorkflow: yamlFlowStr
|
2159
2296
|
},
|
2160
|
-
matchedCache
|
2297
|
+
matchedCache,
|
2298
|
+
contextData
|
2299
|
+
// Pass context data for cache creation
|
2161
2300
|
);
|
2162
2301
|
}
|
2163
2302
|
const metadata = this.afterTaskRunning(executor);
|
2303
|
+
if (this.opts.enableCumulativeContext && this.contextStore) {
|
2304
|
+
try {
|
2305
|
+
const executionResult = this.analyzeExecutionResults(executor, originalPrompt);
|
2306
|
+
this.contextStore.addStep({
|
2307
|
+
type: "action",
|
2308
|
+
summary: `Action: ${processedPrompt}`,
|
2309
|
+
prompt: processedPrompt,
|
2310
|
+
executionResult
|
2311
|
+
});
|
2312
|
+
debug4("Added action step with execution result to context store:", {
|
2313
|
+
stepNumber: this.contextStore.getRecentSteps(1)[0]?.stepNumber,
|
2314
|
+
totalSteps: this.contextStore.getRecentSteps(100).length,
|
2315
|
+
executionResult
|
2316
|
+
});
|
2317
|
+
} catch (error) {
|
2318
|
+
debug4("Failed to analyze execution results, adding step without execution result:", error);
|
2319
|
+
try {
|
2320
|
+
this.contextStore.addStep({
|
2321
|
+
type: "action",
|
2322
|
+
summary: `Action: ${processedPrompt}`,
|
2323
|
+
prompt: processedPrompt
|
2324
|
+
});
|
2325
|
+
} catch (stepError) {
|
2326
|
+
debug4("Failed to add action step:", stepError);
|
2327
|
+
}
|
2328
|
+
}
|
2329
|
+
}
|
2164
2330
|
return {
|
2165
2331
|
result: output,
|
2166
2332
|
metadata
|
@@ -2190,38 +2356,50 @@ var PageAgent = class {
|
|
2190
2356
|
debug4("Context store not available:", error);
|
2191
2357
|
}
|
2192
2358
|
const { output, executor } = await this.taskExecutor.query(processedDemand);
|
2193
|
-
if (
|
2194
|
-
|
2195
|
-
|
2196
|
-
|
2197
|
-
|
2198
|
-
|
2199
|
-
|
2200
|
-
|
2201
|
-
|
2202
|
-
|
2359
|
+
if (this.opts.enableCumulativeContext && this.contextStore) {
|
2360
|
+
if (storageKey && output) {
|
2361
|
+
try {
|
2362
|
+
const pendingAliases = this.contextStore._pendingAliases;
|
2363
|
+
if (pendingAliases) {
|
2364
|
+
this.contextStore.storeDataWithAliases(storageKey, output, pendingAliases, typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand));
|
2365
|
+
delete this.contextStore._pendingAliases;
|
2366
|
+
debug4("Stored query result with aliases:", {
|
2367
|
+
key: storageKey,
|
2368
|
+
value: output,
|
2369
|
+
aliases: pendingAliases
|
2370
|
+
});
|
2371
|
+
} else {
|
2372
|
+
this.contextStore.storeData(storageKey, output);
|
2373
|
+
debug4("Stored query result:", {
|
2374
|
+
key: storageKey,
|
2375
|
+
value: output
|
2376
|
+
});
|
2377
|
+
}
|
2378
|
+
this.contextStore.addStep({
|
2379
|
+
type: "query",
|
2380
|
+
summary: `Query: ${typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand)} (stored as ${storageKey})`,
|
2381
|
+
data: output,
|
2382
|
+
prompt: typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand)
|
2383
|
+
});
|
2384
|
+
debug4("Added query step to context store:", {
|
2385
|
+
storageKey,
|
2386
|
+
totalStoredItems: Object.keys(this.contextStore.getAllData()).length,
|
2387
|
+
totalSteps: this.contextStore.getRecentSteps(100).length
|
2388
|
+
});
|
2389
|
+
} catch (error) {
|
2390
|
+
debug4("Failed to store query result:", error);
|
2391
|
+
}
|
2392
|
+
} else {
|
2393
|
+
try {
|
2394
|
+
this.contextStore.addStep({
|
2395
|
+
type: "query",
|
2396
|
+
summary: `Query: ${typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand)}`,
|
2397
|
+
data: output,
|
2398
|
+
prompt: typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand)
|
2399
|
+
});
|
2400
|
+
} catch (error) {
|
2401
|
+
debug4("Failed to add query step:", error);
|
2203
2402
|
}
|
2204
|
-
contextStore.addStep({
|
2205
|
-
type: "query",
|
2206
|
-
summary: `Query: ${typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand)} (stored as ${storageKey})`,
|
2207
|
-
data: output,
|
2208
|
-
prompt: typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand)
|
2209
|
-
});
|
2210
|
-
} catch (error) {
|
2211
|
-
debug4("Failed to store query result:", error);
|
2212
|
-
}
|
2213
|
-
} else {
|
2214
|
-
try {
|
2215
|
-
const aiModel = await import("misoai-core/ai-model");
|
2216
|
-
const contextStore = aiModel.getContextStore();
|
2217
|
-
contextStore.addStep({
|
2218
|
-
type: "query",
|
2219
|
-
summary: `Query: ${typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand)}`,
|
2220
|
-
data: output,
|
2221
|
-
prompt: typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand)
|
2222
|
-
});
|
2223
|
-
} catch (error) {
|
2224
|
-
debug4("Failed to add query step:", error);
|
2225
2403
|
}
|
2226
2404
|
}
|
2227
2405
|
const metadata = this.afterTaskRunning(executor);
|
@@ -2333,18 +2511,47 @@ var PageAgent = class {
|
|
2333
2511
|
};
|
2334
2512
|
}
|
2335
2513
|
async aiAssert(assertion, msg, opt) {
|
2336
|
-
let
|
2337
|
-
|
2338
|
-
|
2339
|
-
|
2340
|
-
|
2341
|
-
|
2342
|
-
|
2343
|
-
|
2344
|
-
|
2345
|
-
|
2346
|
-
|
2347
|
-
|
2514
|
+
let executionContext = "";
|
2515
|
+
if (this.opts.enableCumulativeContext && this.contextStore) {
|
2516
|
+
try {
|
2517
|
+
const recentSteps = this.contextStore.getRecentSteps(3);
|
2518
|
+
const stepsWithExecutionResults = recentSteps.filter((step) => step.executionResult);
|
2519
|
+
const storedData = this.contextStore.getAllData();
|
2520
|
+
if (stepsWithExecutionResults.length > 0) {
|
2521
|
+
const recentActions = stepsWithExecutionResults.map((step) => {
|
2522
|
+
const result = step.executionResult;
|
2523
|
+
return `- ${result.description}${result.success ? "" : " (FAILED)"}`;
|
2524
|
+
}).join("\n");
|
2525
|
+
executionContext = `
|
2526
|
+
|
2527
|
+
Recent actions performed:
|
2528
|
+
${recentActions}
|
2529
|
+
|
2530
|
+
This context may help verify the assertion.`;
|
2531
|
+
}
|
2532
|
+
if (storedData && Object.keys(storedData).length > 0) {
|
2533
|
+
executionContext += `
|
2534
|
+
|
2535
|
+
Available data for reference:
|
2536
|
+
${JSON.stringify(storedData, null, 2)}
|
2537
|
+
|
2538
|
+
Note: If the assertion references any data keys or natural language equivalents, consider the stored values when verifying.`;
|
2539
|
+
debug4("Available data for aiAssert:", {
|
2540
|
+
assertion,
|
2541
|
+
availableData: storedData
|
2542
|
+
});
|
2543
|
+
}
|
2544
|
+
this.contextStore.addStep({
|
2545
|
+
type: "assertion",
|
2546
|
+
summary: `Assertion: ${assertion}`,
|
2547
|
+
prompt: assertion
|
2548
|
+
});
|
2549
|
+
debug4("Added assertion step to context store:", {
|
2550
|
+
totalSteps: this.contextStore.getRecentSteps(100).length
|
2551
|
+
});
|
2552
|
+
} catch (error) {
|
2553
|
+
debug4("Context store operation failed:", error);
|
2554
|
+
}
|
2348
2555
|
}
|
2349
2556
|
let currentUrl = "";
|
2350
2557
|
if (this.page.url) {
|
@@ -2353,7 +2560,13 @@ var PageAgent = class {
|
|
2353
2560
|
} catch (e) {
|
2354
2561
|
}
|
2355
2562
|
}
|
2356
|
-
|
2563
|
+
let assertionWithContext = assertion;
|
2564
|
+
if (currentUrl) {
|
2565
|
+
assertionWithContext = `For the page at URL "${currentUrl}", ${assertion}`;
|
2566
|
+
}
|
2567
|
+
if (executionContext) {
|
2568
|
+
assertionWithContext += executionContext;
|
2569
|
+
}
|
2357
2570
|
const { output, executor } = await this.taskExecutor.assert(assertionWithContext);
|
2358
2571
|
const metadata = this.afterTaskRunning(executor, true);
|
2359
2572
|
if (output && opt?.keepRawResponse) {
|
@@ -2567,6 +2780,79 @@ ${errors}`);
|
|
2567
2780
|
async destroy() {
|
2568
2781
|
await this.page.destroy();
|
2569
2782
|
}
|
2783
|
+
/**
|
2784
|
+
* Analyze execution results from executor to generate meaningful descriptions
|
2785
|
+
*/
|
2786
|
+
analyzeExecutionResults(executor, originalPrompt) {
|
2787
|
+
const tasks = executor.tasks;
|
2788
|
+
const success = !executor.isInErrorState();
|
2789
|
+
if (!success) {
|
2790
|
+
const errorTask = executor.latestErrorTask();
|
2791
|
+
return {
|
2792
|
+
success: false,
|
2793
|
+
actionType: "error",
|
2794
|
+
description: `Failed to execute: ${originalPrompt}`,
|
2795
|
+
error: errorTask?.error
|
2796
|
+
};
|
2797
|
+
}
|
2798
|
+
const actionTasks = tasks.filter((t) => t.type === "Action" && t.status === "finished");
|
2799
|
+
const locateTasks = tasks.filter((t) => t.type === "Insight" && t.subType === "Locate");
|
2800
|
+
const lastAction = actionTasks[actionTasks.length - 1];
|
2801
|
+
const lastLocate = locateTasks[locateTasks.length - 1];
|
2802
|
+
if (!lastAction) {
|
2803
|
+
return {
|
2804
|
+
success: true,
|
2805
|
+
actionType: "unknown",
|
2806
|
+
description: `Completed: ${originalPrompt}`
|
2807
|
+
};
|
2808
|
+
}
|
2809
|
+
const actionType = lastAction.subType || "unknown";
|
2810
|
+
const elementInfo = this.extractElementInfo(lastLocate, lastAction);
|
2811
|
+
const description = this.generateActionDescription(actionType, lastAction.param, elementInfo);
|
2812
|
+
return {
|
2813
|
+
success: true,
|
2814
|
+
actionType,
|
2815
|
+
description,
|
2816
|
+
elementInfo,
|
2817
|
+
timing: lastAction.timing?.cost
|
2818
|
+
};
|
2819
|
+
}
|
2820
|
+
/**
|
2821
|
+
* Extract element information from locate task
|
2822
|
+
*/
|
2823
|
+
extractElementInfo(locateTask, _actionTask) {
|
2824
|
+
if (!locateTask?.output?.element)
|
2825
|
+
return void 0;
|
2826
|
+
const element = locateTask.output.element;
|
2827
|
+
return {
|
2828
|
+
type: element.attributes?.nodeType || "unknown",
|
2829
|
+
text: element.content || element.attributes?.placeholder || element.attributes?.title || "",
|
2830
|
+
location: `(${element.center[0]}, ${element.center[1]})`
|
2831
|
+
};
|
2832
|
+
}
|
2833
|
+
/**
|
2834
|
+
* Generate natural language description for actions
|
2835
|
+
*/
|
2836
|
+
generateActionDescription(actionType, param, elementInfo) {
|
2837
|
+
const elementDesc = elementInfo ? `'${elementInfo.text || elementInfo.type}' element` : "element";
|
2838
|
+
switch (actionType) {
|
2839
|
+
case "Tap":
|
2840
|
+
return `Clicked on ${elementDesc}`;
|
2841
|
+
case "Input":
|
2842
|
+
const inputValue = param?.value || "";
|
2843
|
+
return `Entered "${inputValue}" into ${elementDesc}`;
|
2844
|
+
case "KeyboardPress":
|
2845
|
+
return `Pressed ${param?.value || "key"}`;
|
2846
|
+
case "Scroll":
|
2847
|
+
return `Scrolled ${param?.direction || "on page"}`;
|
2848
|
+
case "Hover":
|
2849
|
+
return `Hovered over ${elementDesc}`;
|
2850
|
+
case "Drag":
|
2851
|
+
return `Dragged ${elementDesc}`;
|
2852
|
+
default:
|
2853
|
+
return `Performed ${actionType} action on ${elementDesc}`;
|
2854
|
+
}
|
2855
|
+
}
|
2570
2856
|
};
|
2571
2857
|
|
2572
2858
|
// src/playground/agent.ts
|