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