@midscene/core 0.27.0 → 0.27.1-beta-20250822094725.0
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/dist/es/agent/agent.mjs +518 -0
- package/dist/es/agent/agent.mjs.map +1 -0
- package/dist/es/agent/index.mjs +6 -0
- package/dist/es/agent/task-cache.mjs +149 -0
- package/dist/es/agent/task-cache.mjs.map +1 -0
- package/dist/es/agent/tasks.mjs +767 -0
- package/dist/es/agent/tasks.mjs.map +1 -0
- package/dist/es/agent/ui-utils.mjs +89 -0
- package/dist/es/agent/ui-utils.mjs.map +1 -0
- package/dist/es/agent/utils.mjs +337 -0
- package/dist/es/agent/utils.mjs.map +1 -0
- package/dist/es/device/index.mjs +20 -0
- package/dist/es/device/index.mjs.map +1 -0
- package/dist/es/index.mjs +2 -1
- package/dist/es/index.mjs.map +1 -1
- package/dist/es/types.mjs.map +1 -1
- package/dist/es/utils.mjs +2 -2
- package/dist/es/yaml/builder.mjs +13 -0
- package/dist/es/yaml/builder.mjs.map +1 -0
- package/dist/es/yaml/index.mjs +3 -0
- package/dist/es/yaml/player.mjs +375 -0
- package/dist/es/yaml/player.mjs.map +1 -0
- package/dist/es/yaml/utils.mjs +39 -0
- package/dist/es/yaml/utils.mjs.map +1 -0
- package/dist/lib/agent/agent.js +562 -0
- package/dist/lib/agent/agent.js.map +1 -0
- package/dist/lib/agent/index.js +90 -0
- package/dist/lib/agent/index.js.map +1 -0
- package/dist/lib/agent/task-cache.js +201 -0
- package/dist/lib/agent/task-cache.js.map +1 -0
- package/dist/lib/agent/tasks.js +804 -0
- package/dist/lib/agent/tasks.js.map +1 -0
- package/dist/lib/agent/ui-utils.js +141 -0
- package/dist/lib/agent/ui-utils.js.map +1 -0
- package/dist/lib/agent/utils.js +417 -0
- package/dist/lib/agent/utils.js.map +1 -0
- package/dist/lib/device/index.js +54 -0
- package/dist/lib/device/index.js.map +1 -0
- package/dist/lib/index.js +5 -1
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/types.js.map +1 -1
- package/dist/lib/utils.js +2 -2
- package/dist/lib/yaml/builder.js +57 -0
- package/dist/lib/yaml/builder.js.map +1 -0
- package/dist/lib/yaml/index.js +80 -0
- package/dist/lib/yaml/index.js.map +1 -0
- package/dist/lib/yaml/player.js +409 -0
- package/dist/lib/yaml/player.js.map +1 -0
- package/dist/lib/yaml/utils.js +86 -0
- package/dist/lib/yaml/utils.js.map +1 -0
- package/dist/types/agent/agent.d.ts +123 -0
- package/dist/types/agent/index.d.ts +9 -0
- package/dist/types/agent/task-cache.d.ts +38 -0
- package/dist/types/agent/tasks.d.ts +56 -0
- package/dist/types/agent/ui-utils.d.ts +11 -0
- package/dist/types/agent/utils.d.ts +54 -0
- package/dist/types/device/index.d.ts +55 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/types.d.ts +2 -0
- package/dist/types/yaml/builder.d.ts +2 -0
- package/dist/types/yaml/index.d.ts +3 -0
- package/dist/types/yaml/player.d.ts +34 -0
- package/dist/types/yaml/utils.d.ts +3 -0
- package/package.json +31 -3
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import node_assert from "node:assert";
|
|
2
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { dirname, join } from "node:path";
|
|
4
|
+
import { isDeepStrictEqual } from "node:util";
|
|
5
|
+
import { getMidsceneRunSubDir } from "@midscene/shared/common";
|
|
6
|
+
import { MIDSCENE_CACHE_MAX_FILENAME_LENGTH, getAIConfigInNumber } from "@midscene/shared/env";
|
|
7
|
+
import { getDebug } from "@midscene/shared/logger";
|
|
8
|
+
import { generateHashId, ifInBrowser, ifInWorker, replaceIllegalPathCharsAndSpace } from "@midscene/shared/utils";
|
|
9
|
+
import js_yaml from "js-yaml";
|
|
10
|
+
import semver from "semver";
|
|
11
|
+
import { getMidsceneVersion } from "./utils.mjs";
|
|
12
|
+
function _define_property(obj, key, value) {
|
|
13
|
+
if (key in obj) Object.defineProperty(obj, key, {
|
|
14
|
+
value: value,
|
|
15
|
+
enumerable: true,
|
|
16
|
+
configurable: true,
|
|
17
|
+
writable: true
|
|
18
|
+
});
|
|
19
|
+
else obj[key] = value;
|
|
20
|
+
return obj;
|
|
21
|
+
}
|
|
22
|
+
const DEFAULT_CACHE_MAX_FILENAME_LENGTH = 200;
|
|
23
|
+
const debug = getDebug('cache');
|
|
24
|
+
const lowestSupportedMidsceneVersion = '0.16.10';
|
|
25
|
+
const cacheFileExt = '.cache.yaml';
|
|
26
|
+
class TaskCache {
|
|
27
|
+
matchCache(prompt, type) {
|
|
28
|
+
for(let i = 0; i < this.cacheOriginalLength; i++){
|
|
29
|
+
const item = this.cache.caches[i];
|
|
30
|
+
const promptStr = 'string' == typeof prompt ? prompt : JSON.stringify(prompt);
|
|
31
|
+
const key = `${type}:${promptStr}:${i}`;
|
|
32
|
+
if (item.type === type && isDeepStrictEqual(item.prompt, prompt) && !this.matchedCacheIndices.has(key)) {
|
|
33
|
+
this.matchedCacheIndices.add(key);
|
|
34
|
+
debug('cache found and marked as used, type: %s, prompt: %s, index: %d', type, prompt, i);
|
|
35
|
+
return {
|
|
36
|
+
cacheContent: item,
|
|
37
|
+
updateFn: (cb)=>{
|
|
38
|
+
debug('will call updateFn to update cache, type: %s, prompt: %s, index: %d', type, prompt, i);
|
|
39
|
+
cb(item);
|
|
40
|
+
debug('cache updated, will flush to file, type: %s, prompt: %s, index: %d', type, prompt, i);
|
|
41
|
+
this.flushCacheToFile();
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
debug('no unused cache found, type: %s, prompt: %s', type, prompt);
|
|
47
|
+
}
|
|
48
|
+
matchPlanCache(prompt) {
|
|
49
|
+
return this.matchCache(prompt, 'plan');
|
|
50
|
+
}
|
|
51
|
+
matchLocateCache(prompt) {
|
|
52
|
+
return this.matchCache(prompt, 'locate');
|
|
53
|
+
}
|
|
54
|
+
appendCache(cache) {
|
|
55
|
+
debug('will append cache', cache);
|
|
56
|
+
this.cache.caches.push(cache);
|
|
57
|
+
this.flushCacheToFile();
|
|
58
|
+
}
|
|
59
|
+
loadCacheFromFile() {
|
|
60
|
+
const cacheFile = this.cacheFilePath;
|
|
61
|
+
node_assert(cacheFile, 'cache file path is required');
|
|
62
|
+
if (!existsSync(cacheFile)) return void debug('no cache file found, path: %s', cacheFile);
|
|
63
|
+
const jsonTypeCacheFile = cacheFile.replace(cacheFileExt, '.json');
|
|
64
|
+
if (existsSync(jsonTypeCacheFile) && this.isCacheResultUsed) return void console.warn(`An outdated cache file from an earlier version of Midscene has been detected. Since version 0.17, we have implemented an improved caching strategy. Please delete the old file located at: ${jsonTypeCacheFile}.`);
|
|
65
|
+
try {
|
|
66
|
+
const data = readFileSync(cacheFile, 'utf8');
|
|
67
|
+
const jsonData = js_yaml.load(data);
|
|
68
|
+
const version = getMidsceneVersion();
|
|
69
|
+
if (!version) return void debug('no midscene version info, will not read cache from file');
|
|
70
|
+
if (semver.lt(jsonData.midsceneVersion, lowestSupportedMidsceneVersion) && !jsonData.midsceneVersion.includes('beta')) return void console.warn(`You are using an old version of Midscene cache file, and we cannot match any info from it. Starting from Midscene v0.17, we changed our strategy to use xpath for cache info, providing better performance.\nPlease delete the existing cache and rebuild it. Sorry for the inconvenience.\ncache file: ${cacheFile}`);
|
|
71
|
+
debug('cache loaded from file, path: %s, cache version: %s, record length: %s', cacheFile, jsonData.midsceneVersion, jsonData.caches.length);
|
|
72
|
+
jsonData.midsceneVersion = getMidsceneVersion();
|
|
73
|
+
return jsonData;
|
|
74
|
+
} catch (err) {
|
|
75
|
+
debug('cache file exists but load failed, path: %s, error: %s', cacheFile, err);
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
flushCacheToFile() {
|
|
80
|
+
const version = getMidsceneVersion();
|
|
81
|
+
if (!version) return void debug('no midscene version info, will not write cache to file');
|
|
82
|
+
if (!this.cacheFilePath) return void debug('no cache file path, will not write cache to file');
|
|
83
|
+
try {
|
|
84
|
+
const dir = dirname(this.cacheFilePath);
|
|
85
|
+
if (!existsSync(dir)) {
|
|
86
|
+
mkdirSync(dir, {
|
|
87
|
+
recursive: true
|
|
88
|
+
});
|
|
89
|
+
debug('created cache directory: %s', dir);
|
|
90
|
+
}
|
|
91
|
+
const sortedCaches = [
|
|
92
|
+
...this.cache.caches
|
|
93
|
+
].sort((a, b)=>{
|
|
94
|
+
if ('plan' === a.type && 'locate' === b.type) return -1;
|
|
95
|
+
if ('locate' === a.type && 'plan' === b.type) return 1;
|
|
96
|
+
return 0;
|
|
97
|
+
});
|
|
98
|
+
const cacheToWrite = {
|
|
99
|
+
...this.cache,
|
|
100
|
+
caches: sortedCaches
|
|
101
|
+
};
|
|
102
|
+
const yamlData = js_yaml.dump(cacheToWrite);
|
|
103
|
+
writeFileSync(this.cacheFilePath, yamlData);
|
|
104
|
+
debug('cache flushed to file: %s', this.cacheFilePath);
|
|
105
|
+
} catch (err) {
|
|
106
|
+
debug('write cache to file failed, path: %s, error: %s', this.cacheFilePath, err);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
updateOrAppendCacheRecord(newRecord, cachedRecord) {
|
|
110
|
+
if (cachedRecord) if ('plan' === newRecord.type) cachedRecord.updateFn((cache)=>{
|
|
111
|
+
cache.yamlWorkflow = newRecord.yamlWorkflow;
|
|
112
|
+
});
|
|
113
|
+
else cachedRecord.updateFn((cache)=>{
|
|
114
|
+
cache.xpaths = newRecord.xpaths;
|
|
115
|
+
});
|
|
116
|
+
else this.appendCache(newRecord);
|
|
117
|
+
}
|
|
118
|
+
constructor(cacheId, isCacheResultUsed, cacheFilePath){
|
|
119
|
+
_define_property(this, "cacheId", void 0);
|
|
120
|
+
_define_property(this, "cacheFilePath", void 0);
|
|
121
|
+
_define_property(this, "cache", void 0);
|
|
122
|
+
_define_property(this, "isCacheResultUsed", void 0);
|
|
123
|
+
_define_property(this, "cacheOriginalLength", void 0);
|
|
124
|
+
_define_property(this, "matchedCacheIndices", new Set());
|
|
125
|
+
node_assert(cacheId, 'cacheId is required');
|
|
126
|
+
let safeCacheId = replaceIllegalPathCharsAndSpace(cacheId);
|
|
127
|
+
const cacheMaxFilenameLength = getAIConfigInNumber(MIDSCENE_CACHE_MAX_FILENAME_LENGTH) || DEFAULT_CACHE_MAX_FILENAME_LENGTH;
|
|
128
|
+
if (Buffer.byteLength(safeCacheId, 'utf8') > cacheMaxFilenameLength) {
|
|
129
|
+
const prefix = safeCacheId.slice(0, 32);
|
|
130
|
+
const hash = generateHashId(void 0, safeCacheId);
|
|
131
|
+
safeCacheId = `${prefix}-${hash}`;
|
|
132
|
+
}
|
|
133
|
+
this.cacheId = safeCacheId;
|
|
134
|
+
this.cacheFilePath = ifInBrowser || ifInWorker ? void 0 : cacheFilePath || join(getMidsceneRunSubDir('cache'), `${this.cacheId}${cacheFileExt}`);
|
|
135
|
+
this.isCacheResultUsed = isCacheResultUsed;
|
|
136
|
+
let cacheContent;
|
|
137
|
+
if (this.cacheFilePath) cacheContent = this.loadCacheFromFile();
|
|
138
|
+
if (!cacheContent) cacheContent = {
|
|
139
|
+
midsceneVersion: getMidsceneVersion(),
|
|
140
|
+
cacheId: this.cacheId,
|
|
141
|
+
caches: []
|
|
142
|
+
};
|
|
143
|
+
this.cache = cacheContent;
|
|
144
|
+
this.cacheOriginalLength = this.cache.caches.length;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
export { TaskCache, cacheFileExt, debug };
|
|
148
|
+
|
|
149
|
+
//# sourceMappingURL=task-cache.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent/task-cache.mjs","sources":["webpack://@midscene/core/./src/agent/task-cache.ts"],"sourcesContent":["import assert from 'node:assert';\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { isDeepStrictEqual } from 'node:util';\nimport type { TUserPrompt } from '@/index';\nimport { getMidsceneRunSubDir } from '@midscene/shared/common';\nimport {\n MIDSCENE_CACHE_MAX_FILENAME_LENGTH,\n getAIConfigInNumber,\n} from '@midscene/shared/env';\nimport { getDebug } from '@midscene/shared/logger';\nimport { ifInBrowser, ifInWorker } from '@midscene/shared/utils';\nimport { generateHashId } from '@midscene/shared/utils';\nimport { replaceIllegalPathCharsAndSpace } from '@midscene/shared/utils';\nimport yaml from 'js-yaml';\nimport semver from 'semver';\nimport { getMidsceneVersion } from './utils';\n\nconst DEFAULT_CACHE_MAX_FILENAME_LENGTH = 200;\n\nexport const debug = getDebug('cache');\n\nexport interface PlanningCache {\n type: 'plan';\n prompt: string;\n yamlWorkflow: string;\n}\n\nexport interface LocateCache {\n type: 'locate';\n prompt: TUserPrompt;\n xpaths: string[];\n}\n\nexport interface MatchCacheResult<T extends PlanningCache | LocateCache> {\n cacheContent: T;\n updateFn: (cb: (cache: T) => void) => void;\n}\n\nexport type CacheFileContent = {\n midsceneVersion: string;\n cacheId: string;\n caches: Array<PlanningCache | LocateCache>;\n};\n\nconst lowestSupportedMidsceneVersion = '0.16.10';\nexport const cacheFileExt = '.cache.yaml';\n\nexport class TaskCache {\n cacheId: string;\n\n cacheFilePath?: string;\n\n cache: CacheFileContent;\n\n isCacheResultUsed: boolean; // a flag to indicate if the cache result should be used\n cacheOriginalLength: number;\n\n private matchedCacheIndices: Set<string> = new Set(); // Track matched records\n\n constructor(\n cacheId: string,\n isCacheResultUsed: boolean,\n cacheFilePath?: string,\n ) {\n assert(cacheId, 'cacheId is required');\n let safeCacheId = replaceIllegalPathCharsAndSpace(cacheId);\n const cacheMaxFilenameLength =\n getAIConfigInNumber(MIDSCENE_CACHE_MAX_FILENAME_LENGTH) ||\n DEFAULT_CACHE_MAX_FILENAME_LENGTH;\n if (Buffer.byteLength(safeCacheId, 'utf8') > cacheMaxFilenameLength) {\n const prefix = safeCacheId.slice(0, 32);\n const hash = generateHashId(undefined, safeCacheId);\n safeCacheId = `${prefix}-${hash}`;\n }\n this.cacheId = safeCacheId;\n\n this.cacheFilePath =\n ifInBrowser || ifInWorker\n ? undefined\n : cacheFilePath ||\n join(getMidsceneRunSubDir('cache'), `${this.cacheId}${cacheFileExt}`);\n this.isCacheResultUsed = isCacheResultUsed;\n\n let cacheContent;\n if (this.cacheFilePath) {\n cacheContent = this.loadCacheFromFile();\n }\n if (!cacheContent) {\n cacheContent = {\n midsceneVersion: getMidsceneVersion(),\n cacheId: this.cacheId,\n caches: [],\n };\n }\n this.cache = cacheContent;\n this.cacheOriginalLength = this.cache.caches.length;\n }\n\n matchCache(\n prompt: TUserPrompt,\n type: 'plan' | 'locate',\n ): MatchCacheResult<PlanningCache | LocateCache> | undefined {\n // Find the first unused matching cache\n for (let i = 0; i < this.cacheOriginalLength; i++) {\n const item = this.cache.caches[i];\n const promptStr =\n typeof prompt === 'string' ? prompt : JSON.stringify(prompt);\n const key = `${type}:${promptStr}:${i}`;\n if (\n item.type === type &&\n isDeepStrictEqual(item.prompt, prompt) &&\n !this.matchedCacheIndices.has(key)\n ) {\n this.matchedCacheIndices.add(key);\n debug(\n 'cache found and marked as used, type: %s, prompt: %s, index: %d',\n type,\n prompt,\n i,\n );\n return {\n cacheContent: item,\n updateFn: (cb: (cache: PlanningCache | LocateCache) => void) => {\n debug(\n 'will call updateFn to update cache, type: %s, prompt: %s, index: %d',\n type,\n prompt,\n i,\n );\n cb(item);\n debug(\n 'cache updated, will flush to file, type: %s, prompt: %s, index: %d',\n type,\n prompt,\n i,\n );\n this.flushCacheToFile();\n },\n };\n }\n }\n debug('no unused cache found, type: %s, prompt: %s', type, prompt);\n return undefined;\n }\n\n matchPlanCache(prompt: string): MatchCacheResult<PlanningCache> | undefined {\n return this.matchCache(prompt, 'plan') as\n | MatchCacheResult<PlanningCache>\n | undefined;\n }\n\n matchLocateCache(\n prompt: TUserPrompt,\n ): MatchCacheResult<LocateCache> | undefined {\n return this.matchCache(prompt, 'locate') as\n | MatchCacheResult<LocateCache>\n | undefined;\n }\n\n appendCache(cache: PlanningCache | LocateCache) {\n debug('will append cache', cache);\n this.cache.caches.push(cache);\n this.flushCacheToFile();\n }\n\n loadCacheFromFile() {\n const cacheFile = this.cacheFilePath;\n assert(cacheFile, 'cache file path is required');\n\n if (!existsSync(cacheFile)) {\n debug('no cache file found, path: %s', cacheFile);\n return undefined;\n }\n\n // detect old cache file\n const jsonTypeCacheFile = cacheFile.replace(cacheFileExt, '.json');\n if (existsSync(jsonTypeCacheFile) && this.isCacheResultUsed) {\n console.warn(\n `An outdated cache file from an earlier version of Midscene has been detected. Since version 0.17, we have implemented an improved caching strategy. Please delete the old file located at: ${jsonTypeCacheFile}.`,\n );\n return undefined;\n }\n\n try {\n const data = readFileSync(cacheFile, 'utf8');\n const jsonData = yaml.load(data) as CacheFileContent;\n\n const version = getMidsceneVersion();\n if (!version) {\n debug('no midscene version info, will not read cache from file');\n return undefined;\n }\n\n if (\n semver.lt(jsonData.midsceneVersion, lowestSupportedMidsceneVersion) &&\n !jsonData.midsceneVersion.includes('beta') // for internal test\n ) {\n console.warn(\n `You are using an old version of Midscene cache file, and we cannot match any info from it. Starting from Midscene v0.17, we changed our strategy to use xpath for cache info, providing better performance.\\nPlease delete the existing cache and rebuild it. Sorry for the inconvenience.\\ncache file: ${cacheFile}`,\n );\n return undefined;\n }\n\n debug(\n 'cache loaded from file, path: %s, cache version: %s, record length: %s',\n cacheFile,\n jsonData.midsceneVersion,\n jsonData.caches.length,\n );\n jsonData.midsceneVersion = getMidsceneVersion(); // update the version\n return jsonData;\n } catch (err) {\n debug(\n 'cache file exists but load failed, path: %s, error: %s',\n cacheFile,\n err,\n );\n return undefined;\n }\n }\n\n flushCacheToFile() {\n const version = getMidsceneVersion();\n if (!version) {\n debug('no midscene version info, will not write cache to file');\n return;\n }\n\n if (!this.cacheFilePath) {\n debug('no cache file path, will not write cache to file');\n return;\n }\n\n try {\n const dir = dirname(this.cacheFilePath);\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n debug('created cache directory: %s', dir);\n }\n\n // Sort caches to ensure plan entries come before locate entries for better readability\n const sortedCaches = [...this.cache.caches].sort((a, b) => {\n if (a.type === 'plan' && b.type === 'locate') return -1;\n if (a.type === 'locate' && b.type === 'plan') return 1;\n return 0;\n });\n\n const cacheToWrite = {\n ...this.cache,\n caches: sortedCaches,\n };\n\n const yamlData = yaml.dump(cacheToWrite);\n writeFileSync(this.cacheFilePath, yamlData);\n debug('cache flushed to file: %s', this.cacheFilePath);\n } catch (err) {\n debug(\n 'write cache to file failed, path: %s, error: %s',\n this.cacheFilePath,\n err,\n );\n }\n }\n\n updateOrAppendCacheRecord(\n newRecord: PlanningCache | LocateCache,\n cachedRecord?: MatchCacheResult<PlanningCache | LocateCache>,\n ) {\n if (cachedRecord) {\n // update existing record\n if (newRecord.type === 'plan') {\n cachedRecord.updateFn((cache) => {\n (cache as PlanningCache).yamlWorkflow = newRecord.yamlWorkflow;\n });\n } else {\n cachedRecord.updateFn((cache) => {\n (cache as LocateCache).xpaths = newRecord.xpaths;\n });\n }\n } else {\n this.appendCache(newRecord);\n }\n }\n}\n"],"names":["DEFAULT_CACHE_MAX_FILENAME_LENGTH","debug","getDebug","lowestSupportedMidsceneVersion","cacheFileExt","TaskCache","prompt","type","i","item","promptStr","JSON","key","isDeepStrictEqual","cb","cache","cacheFile","assert","existsSync","jsonTypeCacheFile","console","data","readFileSync","jsonData","yaml","version","getMidsceneVersion","semver","err","dir","dirname","mkdirSync","sortedCaches","a","b","cacheToWrite","yamlData","writeFileSync","newRecord","cachedRecord","cacheId","isCacheResultUsed","cacheFilePath","Set","safeCacheId","replaceIllegalPathCharsAndSpace","cacheMaxFilenameLength","getAIConfigInNumber","MIDSCENE_CACHE_MAX_FILENAME_LENGTH","Buffer","prefix","hash","generateHashId","undefined","ifInBrowser","ifInWorker","join","getMidsceneRunSubDir","cacheContent"],"mappings":"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"}
|