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/lib/agent.js
CHANGED
@@ -1674,7 +1674,7 @@ var import_js_yaml3 = __toESM(require("js-yaml"));
|
|
1674
1674
|
var import_semver = __toESM(require("semver"));
|
1675
1675
|
|
1676
1676
|
// package.json
|
1677
|
-
var version = "1.0.
|
1677
|
+
var version = "1.0.5";
|
1678
1678
|
|
1679
1679
|
// src/common/task-cache.ts
|
1680
1680
|
var debug3 = (0, import_logger3.getDebug)("cache");
|
@@ -1702,44 +1702,70 @@ var TaskCache = class {
|
|
1702
1702
|
this.cache = cacheContent;
|
1703
1703
|
this.cacheOriginalLength = this.cache.caches.length;
|
1704
1704
|
}
|
1705
|
-
matchCache(prompt, type) {
|
1705
|
+
matchCache(prompt, type, contextData) {
|
1706
|
+
const contextHash = contextData ? this.generateContextHash(contextData) : void 0;
|
1706
1707
|
for (let i = 0; i < this.cacheOriginalLength; i++) {
|
1707
1708
|
const item = this.cache.caches[i];
|
1708
1709
|
const key = `${type}:${prompt}:${i}`;
|
1709
|
-
if (item.type
|
1710
|
-
|
1711
|
-
|
1712
|
-
|
1713
|
-
|
1714
|
-
|
1715
|
-
|
1716
|
-
|
1717
|
-
|
1718
|
-
cacheContent: item,
|
1719
|
-
updateFn: (cb) => {
|
1720
|
-
debug3(
|
1721
|
-
"will call updateFn to update cache, type: %s, prompt: %s, index: %d",
|
1722
|
-
type,
|
1723
|
-
prompt,
|
1724
|
-
i
|
1725
|
-
);
|
1726
|
-
cb(item);
|
1727
|
-
debug3(
|
1728
|
-
"cache updated, will flush to file, type: %s, prompt: %s, index: %d",
|
1729
|
-
type,
|
1730
|
-
prompt,
|
1731
|
-
i
|
1732
|
-
);
|
1733
|
-
this.flushCacheToFile();
|
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;
|
1734
1719
|
}
|
1735
|
-
}
|
1720
|
+
} else if (contextHash || planItem.contextHash) {
|
1721
|
+
debug3("cache context availability mismatch, type: %s, prompt: %s, index: %d", type, prompt, i);
|
1722
|
+
continue;
|
1723
|
+
}
|
1736
1724
|
}
|
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
|
+
};
|
1737
1752
|
}
|
1738
|
-
debug3("no unused cache found, type: %s, prompt: %s", type, prompt);
|
1753
|
+
debug3("no unused cache found, type: %s, prompt: %s, contextHash: %s", type, prompt, contextHash);
|
1739
1754
|
return void 0;
|
1740
1755
|
}
|
1741
|
-
|
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
1769
|
}
|
1744
1770
|
matchLocateCache(prompt) {
|
1745
1771
|
return this.matchCache(prompt, "locate");
|
@@ -1815,11 +1841,16 @@ cache file: ${cacheFile}`
|
|
1815
1841
|
);
|
1816
1842
|
}
|
1817
1843
|
}
|
1818
|
-
updateOrAppendCacheRecord(newRecord, cachedRecord) {
|
1844
|
+
updateOrAppendCacheRecord(newRecord, cachedRecord, contextData) {
|
1819
1845
|
if (cachedRecord) {
|
1820
1846
|
if (newRecord.type === "plan") {
|
1821
1847
|
cachedRecord.updateFn((cache) => {
|
1822
|
-
|
1848
|
+
const planCache = cache;
|
1849
|
+
planCache.yamlWorkflow = newRecord.yamlWorkflow;
|
1850
|
+
if (contextData) {
|
1851
|
+
planCache.contextHash = this.generateContextHash(contextData);
|
1852
|
+
planCache.contextData = { ...contextData };
|
1853
|
+
}
|
1823
1854
|
});
|
1824
1855
|
} else {
|
1825
1856
|
cachedRecord.updateFn((cache) => {
|
@@ -1827,6 +1858,11 @@ cache file: ${cacheFile}`
|
|
1827
1858
|
});
|
1828
1859
|
}
|
1829
1860
|
} else {
|
1861
|
+
if (newRecord.type === "plan" && contextData) {
|
1862
|
+
const planRecord = newRecord;
|
1863
|
+
planRecord.contextHash = this.generateContextHash(contextData);
|
1864
|
+
planRecord.contextData = { ...contextData };
|
1865
|
+
}
|
1830
1866
|
this.appendCache(newRecord);
|
1831
1867
|
}
|
1832
1868
|
}
|
@@ -1856,10 +1892,13 @@ var PageAgent = class {
|
|
1856
1892
|
generateReport: true,
|
1857
1893
|
autoPrintReportMsg: true,
|
1858
1894
|
groupName: "Midscene Report",
|
1859
|
-
groupDescription: ""
|
1895
|
+
groupDescription: "",
|
1896
|
+
enableCumulativeContext: true,
|
1897
|
+
autoClearContext: false
|
1860
1898
|
},
|
1861
1899
|
opts || {}
|
1862
1900
|
);
|
1901
|
+
this.initializeContextStore();
|
1863
1902
|
if (this.page.pageType === "puppeteer" || this.page.pageType === "playwright") {
|
1864
1903
|
this.page.waitForNavigationTimeout = this.opts.waitForNavigationTimeout || import_constants2.DEFAULT_WAIT_FOR_NAVIGATION_TIMEOUT;
|
1865
1904
|
this.page.waitForNetworkIdleTimeout = this.opts.waitForNetworkIdleTimeout || import_constants2.DEFAULT_WAIT_FOR_NETWORK_IDLE_TIMEOUT;
|
@@ -1886,6 +1925,69 @@ var PageAgent = class {
|
|
1886
1925
|
opts?.testId || this.page.pageType || "web"
|
1887
1926
|
);
|
1888
1927
|
}
|
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
|
+
}
|
1889
1991
|
async getUIContext(action) {
|
1890
1992
|
if (action && (action === "extract" || action === "assert" || action === "captcha")) {
|
1891
1993
|
return await parseContextFromWebPage(this.page, {
|
@@ -2121,22 +2223,35 @@ var PageAgent = class {
|
|
2121
2223
|
};
|
2122
2224
|
}
|
2123
2225
|
async aiAction(taskPrompt, opt) {
|
2124
|
-
|
2125
|
-
|
2126
|
-
|
2127
|
-
|
2128
|
-
|
2129
|
-
|
2130
|
-
|
2131
|
-
|
2132
|
-
|
2133
|
-
|
2134
|
-
|
2135
|
-
|
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
|
+
}
|
2136
2240
|
}
|
2137
2241
|
const cacheable = opt?.cacheable;
|
2138
2242
|
const isVlmUiTars = (0, import_env2.vlLocateMode)() === "vlm-ui-tars";
|
2139
|
-
|
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);
|
2140
2255
|
if (matchedCache && this.taskCache?.isCacheResultUsed) {
|
2141
2256
|
const { executor: executor2 } = await this.taskExecutor.loadYamlFlowAsPlanning(
|
2142
2257
|
taskPrompt,
|
@@ -2146,6 +2261,28 @@ var PageAgent = class {
|
|
2146
2261
|
debug4("matched cache, will call .runYaml to run the action");
|
2147
2262
|
const yaml5 = matchedCache.cacheContent?.yamlWorkflow;
|
2148
2263
|
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
|
+
}
|
2149
2286
|
return {
|
2150
2287
|
result: result.result,
|
2151
2288
|
metadata: metadata2
|
@@ -2170,10 +2307,39 @@ var PageAgent = class {
|
|
2170
2307
|
prompt: taskPrompt,
|
2171
2308
|
yamlWorkflow: yamlFlowStr
|
2172
2309
|
},
|
2173
|
-
matchedCache
|
2310
|
+
matchedCache,
|
2311
|
+
contextData
|
2312
|
+
// Pass context data for cache creation
|
2174
2313
|
);
|
2175
2314
|
}
|
2176
2315
|
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
|
+
}
|
2177
2343
|
return {
|
2178
2344
|
result: output,
|
2179
2345
|
metadata
|
@@ -2203,38 +2369,50 @@ var PageAgent = class {
|
|
2203
2369
|
debug4("Context store not available:", error);
|
2204
2370
|
}
|
2205
2371
|
const { output, executor } = await this.taskExecutor.query(processedDemand);
|
2206
|
-
if (
|
2207
|
-
|
2208
|
-
|
2209
|
-
|
2210
|
-
|
2211
|
-
|
2212
|
-
|
2213
|
-
|
2214
|
-
|
2215
|
-
|
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);
|
2216
2415
|
}
|
2217
|
-
contextStore.addStep({
|
2218
|
-
type: "query",
|
2219
|
-
summary: `Query: ${typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand)} (stored as ${storageKey})`,
|
2220
|
-
data: output,
|
2221
|
-
prompt: typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand)
|
2222
|
-
});
|
2223
|
-
} catch (error) {
|
2224
|
-
debug4("Failed to store query result:", error);
|
2225
|
-
}
|
2226
|
-
} else {
|
2227
|
-
try {
|
2228
|
-
const aiModel = await import("misoai-core/ai-model");
|
2229
|
-
const contextStore = aiModel.getContextStore();
|
2230
|
-
contextStore.addStep({
|
2231
|
-
type: "query",
|
2232
|
-
summary: `Query: ${typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand)}`,
|
2233
|
-
data: output,
|
2234
|
-
prompt: typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand)
|
2235
|
-
});
|
2236
|
-
} catch (error) {
|
2237
|
-
debug4("Failed to add query step:", error);
|
2238
2416
|
}
|
2239
2417
|
}
|
2240
2418
|
const metadata = this.afterTaskRunning(executor);
|
@@ -2346,18 +2524,47 @@ var PageAgent = class {
|
|
2346
2524
|
};
|
2347
2525
|
}
|
2348
2526
|
async aiAssert(assertion, msg, opt) {
|
2349
|
-
let
|
2350
|
-
|
2351
|
-
|
2352
|
-
|
2353
|
-
|
2354
|
-
|
2355
|
-
|
2356
|
-
|
2357
|
-
|
2358
|
-
|
2359
|
-
|
2360
|
-
|
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
|
+
}
|
2361
2568
|
}
|
2362
2569
|
let currentUrl = "";
|
2363
2570
|
if (this.page.url) {
|
@@ -2366,7 +2573,13 @@ var PageAgent = class {
|
|
2366
2573
|
} catch (e) {
|
2367
2574
|
}
|
2368
2575
|
}
|
2369
|
-
|
2576
|
+
let assertionWithContext = assertion;
|
2577
|
+
if (currentUrl) {
|
2578
|
+
assertionWithContext = `For the page at URL "${currentUrl}", ${assertion}`;
|
2579
|
+
}
|
2580
|
+
if (executionContext) {
|
2581
|
+
assertionWithContext += executionContext;
|
2582
|
+
}
|
2370
2583
|
const { output, executor } = await this.taskExecutor.assert(assertionWithContext);
|
2371
2584
|
const metadata = this.afterTaskRunning(executor, true);
|
2372
2585
|
if (output && opt?.keepRawResponse) {
|
@@ -2580,6 +2793,79 @@ ${errors}`);
|
|
2580
2793
|
async destroy() {
|
2581
2794
|
await this.page.destroy();
|
2582
2795
|
}
|
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
|
+
}
|
2583
2869
|
};
|
2584
2870
|
// Annotate the CommonJS export names for ESM import in node:
|
2585
2871
|
0 && (module.exports = {
|