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/puppeteer.js
CHANGED
@@ -1688,7 +1688,7 @@ import yaml3 from "js-yaml";
|
|
1688
1688
|
import semver from "semver";
|
1689
1689
|
|
1690
1690
|
// package.json
|
1691
|
-
var version = "1.0.
|
1691
|
+
var version = "1.0.5";
|
1692
1692
|
|
1693
1693
|
// src/common/task-cache.ts
|
1694
1694
|
var debug3 = getDebug3("cache");
|
@@ -1716,44 +1716,70 @@ var TaskCache = class {
|
|
1716
1716
|
this.cache = cacheContent;
|
1717
1717
|
this.cacheOriginalLength = this.cache.caches.length;
|
1718
1718
|
}
|
1719
|
-
matchCache(prompt, type) {
|
1719
|
+
matchCache(prompt, type, contextData) {
|
1720
|
+
const contextHash = contextData ? this.generateContextHash(contextData) : void 0;
|
1720
1721
|
for (let i = 0; i < this.cacheOriginalLength; i++) {
|
1721
1722
|
const item = this.cache.caches[i];
|
1722
1723
|
const key = `${type}:${prompt}:${i}`;
|
1723
|
-
if (item.type
|
1724
|
-
|
1725
|
-
|
1726
|
-
|
1727
|
-
|
1728
|
-
|
1729
|
-
|
1730
|
-
|
1731
|
-
|
1732
|
-
cacheContent: item,
|
1733
|
-
updateFn: (cb) => {
|
1734
|
-
debug3(
|
1735
|
-
"will call updateFn to update cache, type: %s, prompt: %s, index: %d",
|
1736
|
-
type,
|
1737
|
-
prompt,
|
1738
|
-
i
|
1739
|
-
);
|
1740
|
-
cb(item);
|
1741
|
-
debug3(
|
1742
|
-
"cache updated, will flush to file, type: %s, prompt: %s, index: %d",
|
1743
|
-
type,
|
1744
|
-
prompt,
|
1745
|
-
i
|
1746
|
-
);
|
1747
|
-
this.flushCacheToFile();
|
1724
|
+
if (item.type !== type || item.prompt !== prompt || this.matchedCacheIndices.has(key)) {
|
1725
|
+
continue;
|
1726
|
+
}
|
1727
|
+
if (type === "plan" && item.type === "plan") {
|
1728
|
+
const planItem = item;
|
1729
|
+
if (contextHash && planItem.contextHash) {
|
1730
|
+
if (contextHash !== planItem.contextHash) {
|
1731
|
+
debug3("cache context mismatch, type: %s, prompt: %s, index: %d", type, prompt, i);
|
1732
|
+
continue;
|
1748
1733
|
}
|
1749
|
-
}
|
1734
|
+
} else if (contextHash || planItem.contextHash) {
|
1735
|
+
debug3("cache context availability mismatch, type: %s, prompt: %s, index: %d", type, prompt, i);
|
1736
|
+
continue;
|
1737
|
+
}
|
1750
1738
|
}
|
1739
|
+
this.matchedCacheIndices.add(key);
|
1740
|
+
debug3(
|
1741
|
+
"cache found and marked as used, type: %s, prompt: %s, index: %d, contextMatch: %s",
|
1742
|
+
type,
|
1743
|
+
prompt,
|
1744
|
+
i,
|
1745
|
+
contextHash ? "yes" : "no-context"
|
1746
|
+
);
|
1747
|
+
return {
|
1748
|
+
cacheContent: item,
|
1749
|
+
updateFn: (cb) => {
|
1750
|
+
debug3(
|
1751
|
+
"will call updateFn to update cache, type: %s, prompt: %s, index: %d",
|
1752
|
+
type,
|
1753
|
+
prompt,
|
1754
|
+
i
|
1755
|
+
);
|
1756
|
+
cb(item);
|
1757
|
+
debug3(
|
1758
|
+
"cache updated, will flush to file, type: %s, prompt: %s, index: %d",
|
1759
|
+
type,
|
1760
|
+
prompt,
|
1761
|
+
i
|
1762
|
+
);
|
1763
|
+
this.flushCacheToFile();
|
1764
|
+
}
|
1765
|
+
};
|
1751
1766
|
}
|
1752
|
-
debug3("no unused cache found, type: %s, prompt: %s", type, prompt);
|
1767
|
+
debug3("no unused cache found, type: %s, prompt: %s, contextHash: %s", type, prompt, contextHash);
|
1753
1768
|
return void 0;
|
1754
1769
|
}
|
1755
|
-
|
1756
|
-
|
1770
|
+
generateContextHash(contextData) {
|
1771
|
+
const sortedKeys = Object.keys(contextData).sort();
|
1772
|
+
const stableString = sortedKeys.map((key) => `${key}:${JSON.stringify(contextData[key])}`).join("|");
|
1773
|
+
let hash = 0;
|
1774
|
+
for (let i = 0; i < stableString.length; i++) {
|
1775
|
+
const char = stableString.charCodeAt(i);
|
1776
|
+
hash = (hash << 5) - hash + char;
|
1777
|
+
hash = hash & hash;
|
1778
|
+
}
|
1779
|
+
return hash.toString(36);
|
1780
|
+
}
|
1781
|
+
matchPlanCache(prompt, contextData) {
|
1782
|
+
return this.matchCache(prompt, "plan", contextData);
|
1757
1783
|
}
|
1758
1784
|
matchLocateCache(prompt) {
|
1759
1785
|
return this.matchCache(prompt, "locate");
|
@@ -1829,11 +1855,16 @@ cache file: ${cacheFile}`
|
|
1829
1855
|
);
|
1830
1856
|
}
|
1831
1857
|
}
|
1832
|
-
updateOrAppendCacheRecord(newRecord, cachedRecord) {
|
1858
|
+
updateOrAppendCacheRecord(newRecord, cachedRecord, contextData) {
|
1833
1859
|
if (cachedRecord) {
|
1834
1860
|
if (newRecord.type === "plan") {
|
1835
1861
|
cachedRecord.updateFn((cache) => {
|
1836
|
-
|
1862
|
+
const planCache = cache;
|
1863
|
+
planCache.yamlWorkflow = newRecord.yamlWorkflow;
|
1864
|
+
if (contextData) {
|
1865
|
+
planCache.contextHash = this.generateContextHash(contextData);
|
1866
|
+
planCache.contextData = { ...contextData };
|
1867
|
+
}
|
1837
1868
|
});
|
1838
1869
|
} else {
|
1839
1870
|
cachedRecord.updateFn((cache) => {
|
@@ -1841,6 +1872,11 @@ cache file: ${cacheFile}`
|
|
1841
1872
|
});
|
1842
1873
|
}
|
1843
1874
|
} else {
|
1875
|
+
if (newRecord.type === "plan" && contextData) {
|
1876
|
+
const planRecord = newRecord;
|
1877
|
+
planRecord.contextHash = this.generateContextHash(contextData);
|
1878
|
+
planRecord.contextData = { ...contextData };
|
1879
|
+
}
|
1844
1880
|
this.appendCache(newRecord);
|
1845
1881
|
}
|
1846
1882
|
}
|
@@ -1870,10 +1906,13 @@ var PageAgent = class {
|
|
1870
1906
|
generateReport: true,
|
1871
1907
|
autoPrintReportMsg: true,
|
1872
1908
|
groupName: "Midscene Report",
|
1873
|
-
groupDescription: ""
|
1909
|
+
groupDescription: "",
|
1910
|
+
enableCumulativeContext: true,
|
1911
|
+
autoClearContext: false
|
1874
1912
|
},
|
1875
1913
|
opts || {}
|
1876
1914
|
);
|
1915
|
+
this.initializeContextStore();
|
1877
1916
|
if (this.page.pageType === "puppeteer" || this.page.pageType === "playwright") {
|
1878
1917
|
this.page.waitForNavigationTimeout = this.opts.waitForNavigationTimeout || DEFAULT_WAIT_FOR_NAVIGATION_TIMEOUT;
|
1879
1918
|
this.page.waitForNetworkIdleTimeout = this.opts.waitForNetworkIdleTimeout || DEFAULT_WAIT_FOR_NETWORK_IDLE_TIMEOUT;
|
@@ -1900,6 +1939,69 @@ var PageAgent = class {
|
|
1900
1939
|
opts?.testId || this.page.pageType || "web"
|
1901
1940
|
);
|
1902
1941
|
}
|
1942
|
+
/**
|
1943
|
+
* Initialize context store for cumulative context functionality
|
1944
|
+
*/
|
1945
|
+
async initializeContextStore() {
|
1946
|
+
if (!this.opts.enableCumulativeContext) {
|
1947
|
+
debug4("Cumulative context disabled via options");
|
1948
|
+
return;
|
1949
|
+
}
|
1950
|
+
try {
|
1951
|
+
const aiModel = await import("misoai-core/ai-model");
|
1952
|
+
this.contextStore = aiModel.getContextStore();
|
1953
|
+
debug4("Context store initialized successfully", {
|
1954
|
+
autoClearContext: this.opts.autoClearContext,
|
1955
|
+
testId: this.opts.testId
|
1956
|
+
});
|
1957
|
+
if (this.opts.autoClearContext) {
|
1958
|
+
this.contextStore.clear();
|
1959
|
+
debug4("Context store cleared due to autoClearContext option");
|
1960
|
+
} else {
|
1961
|
+
const existingData = this.contextStore.getAllData();
|
1962
|
+
const existingSteps = this.contextStore.getRecentSteps(100).length;
|
1963
|
+
debug4("Context store preserving existing data", {
|
1964
|
+
existingDataKeys: Object.keys(existingData),
|
1965
|
+
existingStepsCount: existingSteps
|
1966
|
+
});
|
1967
|
+
}
|
1968
|
+
} catch (error) {
|
1969
|
+
debug4("Failed to initialize context store:", error);
|
1970
|
+
console.warn("⚠️ Could not initialize context store:", error);
|
1971
|
+
}
|
1972
|
+
}
|
1973
|
+
/**
|
1974
|
+
* Get the context store instance
|
1975
|
+
*/
|
1976
|
+
getContextStore() {
|
1977
|
+
return this.contextStore;
|
1978
|
+
}
|
1979
|
+
/**
|
1980
|
+
* Clear the context store
|
1981
|
+
*/
|
1982
|
+
clearContext() {
|
1983
|
+
if (this.contextStore) {
|
1984
|
+
this.contextStore.clear();
|
1985
|
+
}
|
1986
|
+
}
|
1987
|
+
/**
|
1988
|
+
* Get all stored data from context store
|
1989
|
+
*/
|
1990
|
+
getStoredData() {
|
1991
|
+
if (this.contextStore) {
|
1992
|
+
return this.contextStore.getAllData();
|
1993
|
+
}
|
1994
|
+
return {};
|
1995
|
+
}
|
1996
|
+
/**
|
1997
|
+
* Get step summary from context store
|
1998
|
+
*/
|
1999
|
+
getStepSummary() {
|
2000
|
+
if (this.contextStore) {
|
2001
|
+
return this.contextStore.getStepSummary();
|
2002
|
+
}
|
2003
|
+
return "";
|
2004
|
+
}
|
1903
2005
|
async getUIContext(action) {
|
1904
2006
|
if (action && (action === "extract" || action === "assert" || action === "captcha")) {
|
1905
2007
|
return await parseContextFromWebPage(this.page, {
|
@@ -2135,22 +2237,35 @@ var PageAgent = class {
|
|
2135
2237
|
};
|
2136
2238
|
}
|
2137
2239
|
async aiAction(taskPrompt, opt) {
|
2138
|
-
|
2139
|
-
|
2140
|
-
|
2141
|
-
|
2142
|
-
|
2143
|
-
|
2144
|
-
|
2145
|
-
|
2146
|
-
|
2147
|
-
|
2148
|
-
|
2149
|
-
|
2240
|
+
const originalPrompt = taskPrompt;
|
2241
|
+
let processedPrompt = taskPrompt;
|
2242
|
+
if (this.opts.enableCumulativeContext && this.contextStore) {
|
2243
|
+
try {
|
2244
|
+
const storedData = this.contextStore.getAllData();
|
2245
|
+
if (Object.keys(storedData).length > 0) {
|
2246
|
+
debug4("Available data for aiAction:", {
|
2247
|
+
prompt: taskPrompt,
|
2248
|
+
availableData: storedData
|
2249
|
+
});
|
2250
|
+
}
|
2251
|
+
} catch (error) {
|
2252
|
+
debug4("Context store operation failed:", error);
|
2253
|
+
}
|
2150
2254
|
}
|
2151
2255
|
const cacheable = opt?.cacheable;
|
2152
2256
|
const isVlmUiTars = vlLocateMode() === "vlm-ui-tars";
|
2153
|
-
|
2257
|
+
let contextData;
|
2258
|
+
if (this.opts.enableCumulativeContext && this.contextStore) {
|
2259
|
+
try {
|
2260
|
+
contextData = this.contextStore.getAllData();
|
2261
|
+
if (contextData && Object.keys(contextData).length === 0) {
|
2262
|
+
contextData = void 0;
|
2263
|
+
}
|
2264
|
+
} catch (error) {
|
2265
|
+
debug4("Failed to get context data for cache:", error);
|
2266
|
+
}
|
2267
|
+
}
|
2268
|
+
const matchedCache = isVlmUiTars || cacheable === false ? void 0 : this.taskCache?.matchPlanCache(taskPrompt, contextData);
|
2154
2269
|
if (matchedCache && this.taskCache?.isCacheResultUsed) {
|
2155
2270
|
const { executor: executor2 } = await this.taskExecutor.loadYamlFlowAsPlanning(
|
2156
2271
|
taskPrompt,
|
@@ -2160,6 +2275,28 @@ var PageAgent = class {
|
|
2160
2275
|
debug4("matched cache, will call .runYaml to run the action");
|
2161
2276
|
const yaml5 = matchedCache.cacheContent?.yamlWorkflow;
|
2162
2277
|
const result = await this.runYaml(yaml5);
|
2278
|
+
if (this.opts.enableCumulativeContext && this.contextStore) {
|
2279
|
+
try {
|
2280
|
+
const executionResult = {
|
2281
|
+
success: true,
|
2282
|
+
actionType: "cached",
|
2283
|
+
description: `Executed cached action: ${processedPrompt}`,
|
2284
|
+
timing: result.metadata?.totalTime
|
2285
|
+
};
|
2286
|
+
this.contextStore.addStep({
|
2287
|
+
type: "action",
|
2288
|
+
summary: `Action: ${processedPrompt} (cached)`,
|
2289
|
+
prompt: processedPrompt,
|
2290
|
+
executionResult
|
2291
|
+
});
|
2292
|
+
debug4("Added cached action step to context store:", {
|
2293
|
+
stepNumber: this.contextStore.getRecentSteps(1)[0]?.stepNumber,
|
2294
|
+
totalSteps: this.contextStore.getRecentSteps(100).length
|
2295
|
+
});
|
2296
|
+
} catch (error) {
|
2297
|
+
debug4("Failed to add cached action step:", error);
|
2298
|
+
}
|
2299
|
+
}
|
2163
2300
|
return {
|
2164
2301
|
result: result.result,
|
2165
2302
|
metadata: metadata2
|
@@ -2184,10 +2321,39 @@ var PageAgent = class {
|
|
2184
2321
|
prompt: taskPrompt,
|
2185
2322
|
yamlWorkflow: yamlFlowStr
|
2186
2323
|
},
|
2187
|
-
matchedCache
|
2324
|
+
matchedCache,
|
2325
|
+
contextData
|
2326
|
+
// Pass context data for cache creation
|
2188
2327
|
);
|
2189
2328
|
}
|
2190
2329
|
const metadata = this.afterTaskRunning(executor);
|
2330
|
+
if (this.opts.enableCumulativeContext && this.contextStore) {
|
2331
|
+
try {
|
2332
|
+
const executionResult = this.analyzeExecutionResults(executor, originalPrompt);
|
2333
|
+
this.contextStore.addStep({
|
2334
|
+
type: "action",
|
2335
|
+
summary: `Action: ${processedPrompt}`,
|
2336
|
+
prompt: processedPrompt,
|
2337
|
+
executionResult
|
2338
|
+
});
|
2339
|
+
debug4("Added action step with execution result to context store:", {
|
2340
|
+
stepNumber: this.contextStore.getRecentSteps(1)[0]?.stepNumber,
|
2341
|
+
totalSteps: this.contextStore.getRecentSteps(100).length,
|
2342
|
+
executionResult
|
2343
|
+
});
|
2344
|
+
} catch (error) {
|
2345
|
+
debug4("Failed to analyze execution results, adding step without execution result:", error);
|
2346
|
+
try {
|
2347
|
+
this.contextStore.addStep({
|
2348
|
+
type: "action",
|
2349
|
+
summary: `Action: ${processedPrompt}`,
|
2350
|
+
prompt: processedPrompt
|
2351
|
+
});
|
2352
|
+
} catch (stepError) {
|
2353
|
+
debug4("Failed to add action step:", stepError);
|
2354
|
+
}
|
2355
|
+
}
|
2356
|
+
}
|
2191
2357
|
return {
|
2192
2358
|
result: output,
|
2193
2359
|
metadata
|
@@ -2217,38 +2383,50 @@ var PageAgent = class {
|
|
2217
2383
|
debug4("Context store not available:", error);
|
2218
2384
|
}
|
2219
2385
|
const { output, executor } = await this.taskExecutor.query(processedDemand);
|
2220
|
-
if (
|
2221
|
-
|
2222
|
-
|
2223
|
-
|
2224
|
-
|
2225
|
-
|
2226
|
-
|
2227
|
-
|
2228
|
-
|
2229
|
-
|
2386
|
+
if (this.opts.enableCumulativeContext && this.contextStore) {
|
2387
|
+
if (storageKey && output) {
|
2388
|
+
try {
|
2389
|
+
const pendingAliases = this.contextStore._pendingAliases;
|
2390
|
+
if (pendingAliases) {
|
2391
|
+
this.contextStore.storeDataWithAliases(storageKey, output, pendingAliases, typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand));
|
2392
|
+
delete this.contextStore._pendingAliases;
|
2393
|
+
debug4("Stored query result with aliases:", {
|
2394
|
+
key: storageKey,
|
2395
|
+
value: output,
|
2396
|
+
aliases: pendingAliases
|
2397
|
+
});
|
2398
|
+
} else {
|
2399
|
+
this.contextStore.storeData(storageKey, output);
|
2400
|
+
debug4("Stored query result:", {
|
2401
|
+
key: storageKey,
|
2402
|
+
value: output
|
2403
|
+
});
|
2404
|
+
}
|
2405
|
+
this.contextStore.addStep({
|
2406
|
+
type: "query",
|
2407
|
+
summary: `Query: ${typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand)} (stored as ${storageKey})`,
|
2408
|
+
data: output,
|
2409
|
+
prompt: typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand)
|
2410
|
+
});
|
2411
|
+
debug4("Added query step to context store:", {
|
2412
|
+
storageKey,
|
2413
|
+
totalStoredItems: Object.keys(this.contextStore.getAllData()).length,
|
2414
|
+
totalSteps: this.contextStore.getRecentSteps(100).length
|
2415
|
+
});
|
2416
|
+
} catch (error) {
|
2417
|
+
debug4("Failed to store query result:", error);
|
2418
|
+
}
|
2419
|
+
} else {
|
2420
|
+
try {
|
2421
|
+
this.contextStore.addStep({
|
2422
|
+
type: "query",
|
2423
|
+
summary: `Query: ${typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand)}`,
|
2424
|
+
data: output,
|
2425
|
+
prompt: typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand)
|
2426
|
+
});
|
2427
|
+
} catch (error) {
|
2428
|
+
debug4("Failed to add query step:", error);
|
2230
2429
|
}
|
2231
|
-
contextStore.addStep({
|
2232
|
-
type: "query",
|
2233
|
-
summary: `Query: ${typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand)} (stored as ${storageKey})`,
|
2234
|
-
data: output,
|
2235
|
-
prompt: typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand)
|
2236
|
-
});
|
2237
|
-
} catch (error) {
|
2238
|
-
debug4("Failed to store query result:", error);
|
2239
|
-
}
|
2240
|
-
} else {
|
2241
|
-
try {
|
2242
|
-
const aiModel = await import("misoai-core/ai-model");
|
2243
|
-
const contextStore = aiModel.getContextStore();
|
2244
|
-
contextStore.addStep({
|
2245
|
-
type: "query",
|
2246
|
-
summary: `Query: ${typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand)}`,
|
2247
|
-
data: output,
|
2248
|
-
prompt: typeof processedDemand === "string" ? processedDemand : JSON.stringify(processedDemand)
|
2249
|
-
});
|
2250
|
-
} catch (error) {
|
2251
|
-
debug4("Failed to add query step:", error);
|
2252
2430
|
}
|
2253
2431
|
}
|
2254
2432
|
const metadata = this.afterTaskRunning(executor);
|
@@ -2360,18 +2538,47 @@ var PageAgent = class {
|
|
2360
2538
|
};
|
2361
2539
|
}
|
2362
2540
|
async aiAssert(assertion, msg, opt) {
|
2363
|
-
let
|
2364
|
-
|
2365
|
-
|
2366
|
-
|
2367
|
-
|
2368
|
-
|
2369
|
-
|
2370
|
-
|
2371
|
-
|
2372
|
-
|
2373
|
-
|
2374
|
-
|
2541
|
+
let executionContext = "";
|
2542
|
+
if (this.opts.enableCumulativeContext && this.contextStore) {
|
2543
|
+
try {
|
2544
|
+
const recentSteps = this.contextStore.getRecentSteps(3);
|
2545
|
+
const stepsWithExecutionResults = recentSteps.filter((step) => step.executionResult);
|
2546
|
+
const storedData = this.contextStore.getAllData();
|
2547
|
+
if (stepsWithExecutionResults.length > 0) {
|
2548
|
+
const recentActions = stepsWithExecutionResults.map((step) => {
|
2549
|
+
const result = step.executionResult;
|
2550
|
+
return `- ${result.description}${result.success ? "" : " (FAILED)"}`;
|
2551
|
+
}).join("\n");
|
2552
|
+
executionContext = `
|
2553
|
+
|
2554
|
+
Recent actions performed:
|
2555
|
+
${recentActions}
|
2556
|
+
|
2557
|
+
This context may help verify the assertion.`;
|
2558
|
+
}
|
2559
|
+
if (storedData && Object.keys(storedData).length > 0) {
|
2560
|
+
executionContext += `
|
2561
|
+
|
2562
|
+
Available data for reference:
|
2563
|
+
${JSON.stringify(storedData, null, 2)}
|
2564
|
+
|
2565
|
+
Note: If the assertion references any data keys or natural language equivalents, consider the stored values when verifying.`;
|
2566
|
+
debug4("Available data for aiAssert:", {
|
2567
|
+
assertion,
|
2568
|
+
availableData: storedData
|
2569
|
+
});
|
2570
|
+
}
|
2571
|
+
this.contextStore.addStep({
|
2572
|
+
type: "assertion",
|
2573
|
+
summary: `Assertion: ${assertion}`,
|
2574
|
+
prompt: assertion
|
2575
|
+
});
|
2576
|
+
debug4("Added assertion step to context store:", {
|
2577
|
+
totalSteps: this.contextStore.getRecentSteps(100).length
|
2578
|
+
});
|
2579
|
+
} catch (error) {
|
2580
|
+
debug4("Context store operation failed:", error);
|
2581
|
+
}
|
2375
2582
|
}
|
2376
2583
|
let currentUrl = "";
|
2377
2584
|
if (this.page.url) {
|
@@ -2380,7 +2587,13 @@ var PageAgent = class {
|
|
2380
2587
|
} catch (e) {
|
2381
2588
|
}
|
2382
2589
|
}
|
2383
|
-
|
2590
|
+
let assertionWithContext = assertion;
|
2591
|
+
if (currentUrl) {
|
2592
|
+
assertionWithContext = `For the page at URL "${currentUrl}", ${assertion}`;
|
2593
|
+
}
|
2594
|
+
if (executionContext) {
|
2595
|
+
assertionWithContext += executionContext;
|
2596
|
+
}
|
2384
2597
|
const { output, executor } = await this.taskExecutor.assert(assertionWithContext);
|
2385
2598
|
const metadata = this.afterTaskRunning(executor, true);
|
2386
2599
|
if (output && opt?.keepRawResponse) {
|
@@ -2594,6 +2807,79 @@ ${errors}`);
|
|
2594
2807
|
async destroy() {
|
2595
2808
|
await this.page.destroy();
|
2596
2809
|
}
|
2810
|
+
/**
|
2811
|
+
* Analyze execution results from executor to generate meaningful descriptions
|
2812
|
+
*/
|
2813
|
+
analyzeExecutionResults(executor, originalPrompt) {
|
2814
|
+
const tasks = executor.tasks;
|
2815
|
+
const success = !executor.isInErrorState();
|
2816
|
+
if (!success) {
|
2817
|
+
const errorTask = executor.latestErrorTask();
|
2818
|
+
return {
|
2819
|
+
success: false,
|
2820
|
+
actionType: "error",
|
2821
|
+
description: `Failed to execute: ${originalPrompt}`,
|
2822
|
+
error: errorTask?.error
|
2823
|
+
};
|
2824
|
+
}
|
2825
|
+
const actionTasks = tasks.filter((t) => t.type === "Action" && t.status === "finished");
|
2826
|
+
const locateTasks = tasks.filter((t) => t.type === "Insight" && t.subType === "Locate");
|
2827
|
+
const lastAction = actionTasks[actionTasks.length - 1];
|
2828
|
+
const lastLocate = locateTasks[locateTasks.length - 1];
|
2829
|
+
if (!lastAction) {
|
2830
|
+
return {
|
2831
|
+
success: true,
|
2832
|
+
actionType: "unknown",
|
2833
|
+
description: `Completed: ${originalPrompt}`
|
2834
|
+
};
|
2835
|
+
}
|
2836
|
+
const actionType = lastAction.subType || "unknown";
|
2837
|
+
const elementInfo = this.extractElementInfo(lastLocate, lastAction);
|
2838
|
+
const description = this.generateActionDescription(actionType, lastAction.param, elementInfo);
|
2839
|
+
return {
|
2840
|
+
success: true,
|
2841
|
+
actionType,
|
2842
|
+
description,
|
2843
|
+
elementInfo,
|
2844
|
+
timing: lastAction.timing?.cost
|
2845
|
+
};
|
2846
|
+
}
|
2847
|
+
/**
|
2848
|
+
* Extract element information from locate task
|
2849
|
+
*/
|
2850
|
+
extractElementInfo(locateTask, _actionTask) {
|
2851
|
+
if (!locateTask?.output?.element)
|
2852
|
+
return void 0;
|
2853
|
+
const element = locateTask.output.element;
|
2854
|
+
return {
|
2855
|
+
type: element.attributes?.nodeType || "unknown",
|
2856
|
+
text: element.content || element.attributes?.placeholder || element.attributes?.title || "",
|
2857
|
+
location: `(${element.center[0]}, ${element.center[1]})`
|
2858
|
+
};
|
2859
|
+
}
|
2860
|
+
/**
|
2861
|
+
* Generate natural language description for actions
|
2862
|
+
*/
|
2863
|
+
generateActionDescription(actionType, param, elementInfo) {
|
2864
|
+
const elementDesc = elementInfo ? `'${elementInfo.text || elementInfo.type}' element` : "element";
|
2865
|
+
switch (actionType) {
|
2866
|
+
case "Tap":
|
2867
|
+
return `Clicked on ${elementDesc}`;
|
2868
|
+
case "Input":
|
2869
|
+
const inputValue = param?.value || "";
|
2870
|
+
return `Entered "${inputValue}" into ${elementDesc}`;
|
2871
|
+
case "KeyboardPress":
|
2872
|
+
return `Pressed ${param?.value || "key"}`;
|
2873
|
+
case "Scroll":
|
2874
|
+
return `Scrolled ${param?.direction || "on page"}`;
|
2875
|
+
case "Hover":
|
2876
|
+
return `Hovered over ${elementDesc}`;
|
2877
|
+
case "Drag":
|
2878
|
+
return `Dragged ${elementDesc}`;
|
2879
|
+
default:
|
2880
|
+
return `Performed ${actionType} action on ${elementDesc}`;
|
2881
|
+
}
|
2882
|
+
}
|
2597
2883
|
};
|
2598
2884
|
|
2599
2885
|
// src/puppeteer/index.ts
|