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