page-action-cache 2.0.4 → 2.0.8
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/index.d.ts.map +1 -1
- package/dist/index.js +19 -212
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/index.ts +23 -236
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAMzD;;GAEG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,iBAAiB,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAMzD;;GAEG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,iBAAiB,GAAG,IAAI,CA2CC"}
|
package/dist/index.js
CHANGED
|
@@ -2,25 +2,31 @@
|
|
|
2
2
|
* Page Action Cache - OpenClaw Extension
|
|
3
3
|
* 页面操作缓存扩展 - OpenClaw 扩展
|
|
4
4
|
*/
|
|
5
|
-
import { scenarioRecognizer } from './scenario-recognizer.js';
|
|
6
|
-
import { multiLevelCache } from './multi-level-cache.js';
|
|
7
|
-
import { cacheInvalidation } from './cache-invalidation.js';
|
|
8
|
-
import { browserActionExecutor } from './browser-action-executor.js';
|
|
9
5
|
/**
|
|
10
6
|
* 主扩展入口
|
|
11
7
|
*/
|
|
12
8
|
export function register(api) {
|
|
13
9
|
console.log('[PageActionCache] Initializing extension...');
|
|
14
|
-
// 获取插件配置
|
|
15
|
-
const
|
|
16
|
-
|
|
10
|
+
// 获取插件配置 - 详细日志
|
|
11
|
+
const rawConfig = api.getConfig?.();
|
|
12
|
+
console.log('[PageActionCache] Raw config object:', JSON.stringify(rawConfig, null, 2));
|
|
13
|
+
// 检查配置对象是否有效
|
|
14
|
+
if (!rawConfig || typeof rawConfig !== 'object') {
|
|
15
|
+
console.log('[PageActionCache] Invalid config object type:', typeof rawConfig);
|
|
16
|
+
// 配置无效,使用空对象继续
|
|
17
|
+
rawConfig = {};
|
|
18
|
+
}
|
|
19
|
+
const pluginConfig = rawConfig?.plugins?.entries?.['page-action-cache'] ?? {};
|
|
20
|
+
console.log('[PageActionCache] Plugin config for page-action-cache:', JSON.stringify(pluginConfig, null, 2));
|
|
21
|
+
const pageActionCacheConfig = pluginConfig ?? {};
|
|
22
|
+
console.log('[PageActionCache] Parsed pageActionCacheConfig:', JSON.stringify(pageActionCacheConfig, null, 2));
|
|
17
23
|
const enabled = pageActionCacheConfig.enabled !== false;
|
|
24
|
+
console.log('[PageActionCache] Enabled status:', enabled);
|
|
18
25
|
if (!enabled) {
|
|
19
26
|
console.log('[PageActionCache] Extension disabled by configuration');
|
|
20
27
|
return;
|
|
21
28
|
}
|
|
22
|
-
|
|
23
|
-
// 如果需要更多配置选项,可以在 configSchema 中添加更多属性
|
|
29
|
+
console.log('[PageActionCache] Extension enabled, proceeding with tool registration...');
|
|
24
30
|
// 注册缓存执行工具
|
|
25
31
|
api.registerTool({
|
|
26
32
|
name: 'browser_cache_execute',
|
|
@@ -28,214 +34,15 @@ export function register(api) {
|
|
|
28
34
|
async execute(ctx) {
|
|
29
35
|
try {
|
|
30
36
|
console.log('[PageActionCache] browser_cache_execute called');
|
|
37
|
+
console.log('[PageActionCache] Context type:', typeof ctx);
|
|
38
|
+
console.log('[PageActionCache] Context config:', ctx.config ? JSON.stringify(ctx.config, null, 2) : 'null');
|
|
39
|
+
console.log('[PageActionCache] Context params:', ctx.params ? JSON.stringify(ctx.params, null, 2) : 'null');
|
|
31
40
|
// 从插件配置中读取 enabled 状态
|
|
32
41
|
const pluginConfig = ctx.config?.plugins?.entries?.['page-action-cache'] ?? {};
|
|
33
42
|
const enabled = pluginConfig.enabled !== false;
|
|
34
|
-
if (!enabled) {
|
|
35
|
-
return {
|
|
36
|
-
type: 'text',
|
|
37
|
-
content: 'Page Action Cache 功能已禁用'
|
|
38
|
-
};
|
|
39
|
-
}
|
|
40
|
-
const request = ctx.params;
|
|
41
|
-
const url = request?.url;
|
|
42
|
-
if (!url) {
|
|
43
|
-
return {
|
|
44
|
-
type: 'text',
|
|
45
|
-
content: 'Missing required parameter: url'
|
|
46
|
-
};
|
|
47
|
-
}
|
|
48
|
-
// 尝试从缓存中查找
|
|
49
|
-
const cachedEntry = multiLevelCache.queryCache(url, request.viewport || '1920x1080');
|
|
50
|
-
if (cachedEntry && !request.forceRefresh) {
|
|
51
|
-
console.log('[PageActionCache] Cache hit found');
|
|
52
|
-
return await executeFromCache(cachedEntry);
|
|
53
|
-
}
|
|
54
|
-
// 缓存未命中或强制刷新,创建新缓存并执行
|
|
55
|
-
console.log('[PageActionCache] Cache miss or forced refresh, creating new entry');
|
|
56
|
-
// 识别场景
|
|
57
|
-
let scenario = request.scenario;
|
|
58
|
-
if (!scenario) {
|
|
59
|
-
scenario = scenarioRecognizer.recognizeByUrl(url);
|
|
60
|
-
}
|
|
61
|
-
// 创建缓存条目
|
|
62
|
-
const actions = request.actions || [];
|
|
63
|
-
const cacheActions = actions.map((action) => ({
|
|
64
|
-
type: action.type,
|
|
65
|
-
params: action.params,
|
|
66
|
-
successCount: 0,
|
|
67
|
-
failCount: 0
|
|
68
|
-
}));
|
|
69
|
-
const cacheId = multiLevelCache.addCache(url, request.viewport || '1920x1080', cacheActions, scenario, request.llmClassificationScore);
|
|
70
|
-
// 执行操作
|
|
71
|
-
const entry = {
|
|
72
|
-
id: cacheId,
|
|
73
|
-
url,
|
|
74
|
-
viewport: request.viewport || '1920x1080',
|
|
75
|
-
actions: cacheActions,
|
|
76
|
-
scenario,
|
|
77
|
-
timestamp: Date.now(),
|
|
78
|
-
hitRate: 0,
|
|
79
|
-
savedActions: 0,
|
|
80
|
-
savedTime: 0,
|
|
81
|
-
level: 'L1',
|
|
82
|
-
createdAt: Date.now(),
|
|
83
|
-
lastAccessed: Date.now(),
|
|
84
|
-
accessCount: 0,
|
|
85
|
-
expiresAt: Date.now() + 86400000 // 24小时
|
|
86
|
-
};
|
|
87
|
-
const result = await browserActionExecutor.executeCacheEntry(entry);
|
|
88
|
-
return {
|
|
89
|
-
type: 'text',
|
|
90
|
-
content: `## Cache Execution Result
|
|
91
|
-
|
|
92
|
-
${result.message}
|
|
93
|
-
|
|
94
|
-
- Executed Actions: ${result.executedActions}
|
|
95
|
-
- Skipped Actions: ${result.skippedActions}
|
|
96
|
-
- Failed Actions: ${result.failedActions}
|
|
97
|
-
- Saved Time: ${result.savedTime}ms
|
|
98
|
-
|
|
99
|
-
Cache ID: ${cacheId}
|
|
100
|
-
URL: ${url}
|
|
101
|
-
Scenario: ${scenario}
|
|
102
|
-
LLM Classification Score: ${request.llmClassificationScore || 'N/A'}`
|
|
103
|
-
};
|
|
104
|
-
}
|
|
105
|
-
catch (error) {
|
|
106
|
-
console.error('[PageActionCache] Error:', error);
|
|
107
|
-
return {
|
|
108
|
-
type: 'text',
|
|
109
|
-
content: `执行失败: ${error.message}`
|
|
110
|
-
};
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
});
|
|
114
|
-
// 注册缓存统计工具
|
|
115
|
-
api.registerTool({
|
|
116
|
-
name: 'browser_cache_stats',
|
|
117
|
-
description: '查看页面操作缓存的统计信息',
|
|
118
|
-
async execute(_ctx) {
|
|
119
|
-
try {
|
|
120
|
-
const stats = multiLevelCache.getStats();
|
|
121
|
-
const invalidationStats = cacheInvalidation.getInvalidationStats();
|
|
122
|
-
return {
|
|
123
|
-
type: 'text',
|
|
124
|
-
content: `## Page Action Cache Statistics
|
|
125
|
-
|
|
126
|
-
### Overall Performance
|
|
127
|
-
- Total Cache Entries: ${stats.totalEntries}
|
|
128
|
-
- Total Cache Hits: ${stats.totalHits}
|
|
129
|
-
- Cache Hit Rate: ${stats.hitRate.toFixed(2)}%
|
|
130
|
-
|
|
131
|
-
### Multi-Level Cache Distribution
|
|
132
|
-
${Object.entries(stats.levelStats).map(([level, data]) => `
|
|
133
|
-
#### ${level} Cache
|
|
134
|
-
- Size: ${data.size}/${data.maxCapacity} (${(data.usageRate * 100).toFixed(1)}% full)
|
|
135
|
-
- Average Access Count: ${data.avgAccessCount.toFixed(1)}
|
|
136
|
-
`).join('')}
|
|
137
|
-
|
|
138
|
-
### Cache Invalidation
|
|
139
|
-
- Total Snapshots: ${invalidationStats.totalSnapshots}
|
|
140
|
-
- Active Snapshots: ${invalidationStats.activeSnapshots}
|
|
141
|
-
- Invalidation Rate: ${(invalidationStats.invalidationRate * 100).toFixed(2)}%`
|
|
142
|
-
};
|
|
143
|
-
}
|
|
144
|
-
catch (error) {
|
|
145
|
-
return {
|
|
146
|
-
type: 'text',
|
|
147
|
-
content: `统计功能错误: ${error.message}`
|
|
148
|
-
};
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
});
|
|
152
|
-
// 注册缓存清除工具
|
|
153
|
-
api.registerTool({
|
|
154
|
-
name: 'browser_cache_clear',
|
|
155
|
-
description: '清空页面操作缓存',
|
|
156
|
-
async execute(ctx) {
|
|
157
|
-
try {
|
|
158
|
-
const request = ctx.params;
|
|
159
|
-
if (request.url && request.viewport) {
|
|
160
|
-
// 删除特定缓存条目
|
|
161
|
-
const deleted = multiLevelCache.deleteCache(request.url, request.viewport || '1920x1080');
|
|
162
|
-
cacheInvalidation.invalidate(request.url, request.viewport || '1920x1080');
|
|
163
|
-
return {
|
|
164
|
-
type: 'text',
|
|
165
|
-
content: deleted
|
|
166
|
-
? `Cache entry deleted for ${request.url}:${request.viewport || '1920x1080'}`
|
|
167
|
-
: `No cache entry found for ${request.url}:${request.viewport || '1920x1080'}`
|
|
168
|
-
};
|
|
169
|
-
}
|
|
170
|
-
else if (request.url) {
|
|
171
|
-
// 删除 URL 相关的所有缓存
|
|
172
|
-
multiLevelCache.deleteCacheByUrl(request.url);
|
|
173
|
-
cacheInvalidation.invalidateByUrl(request.url);
|
|
174
|
-
return {
|
|
175
|
-
type: 'text',
|
|
176
|
-
content: `All cache entries for ${request.url} have been deleted`
|
|
177
|
-
};
|
|
178
|
-
}
|
|
179
|
-
else if (request.level) {
|
|
180
|
-
// 按级别删除
|
|
181
|
-
if (request.level === 'all') {
|
|
182
|
-
multiLevelCache.clearAll();
|
|
183
|
-
cacheInvalidation.reset();
|
|
184
|
-
}
|
|
185
|
-
else {
|
|
186
|
-
multiLevelCache.clearLevel(request.level);
|
|
187
|
-
}
|
|
188
|
-
return {
|
|
189
|
-
type: 'text',
|
|
190
|
-
content: `Cache cleared for level: ${request.level}`
|
|
191
|
-
};
|
|
192
|
-
}
|
|
193
|
-
else {
|
|
194
|
-
// 默认清空所有缓存
|
|
195
|
-
multiLevelCache.clearAll();
|
|
196
|
-
cacheInvalidation.reset();
|
|
197
|
-
return {
|
|
198
|
-
type: 'text',
|
|
199
|
-
content: 'All page action cache has been cleared'
|
|
200
|
-
};
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
catch (error) {
|
|
204
|
-
return {
|
|
205
|
-
type: 'text',
|
|
206
|
-
content: `清除功能错误: ${error.message}`
|
|
207
|
-
};
|
|
208
43
|
}
|
|
44
|
+
finally { }
|
|
209
45
|
}
|
|
210
46
|
});
|
|
211
|
-
console.log('[PageActionCache] Tools registered successfully');
|
|
212
|
-
// 定期清理过期缓存
|
|
213
|
-
setInterval(() => {
|
|
214
|
-
multiLevelCache.cleanupExpired();
|
|
215
|
-
cacheInvalidation.cleanup();
|
|
216
|
-
}, 60 * 60 * 1000); // 每小时清理一次
|
|
217
|
-
}
|
|
218
|
-
/**
|
|
219
|
-
* 从缓存执行
|
|
220
|
-
*/
|
|
221
|
-
async function executeFromCache(cachedEntry) {
|
|
222
|
-
const result = await browserActionExecutor.executeCacheEntry(cachedEntry);
|
|
223
|
-
return {
|
|
224
|
-
type: 'text',
|
|
225
|
-
content: `## Cached Execution
|
|
226
|
-
|
|
227
|
-
${result.message}
|
|
228
|
-
|
|
229
|
-
- Executed Actions: ${result.executedActions}
|
|
230
|
-
- Skipped Actions: ${result.skippedActions}
|
|
231
|
-
- Failed Actions: ${result.failedActions}
|
|
232
|
-
- Saved Time: ${result.savedTime}ms
|
|
233
|
-
|
|
234
|
-
Cache ID: ${cachedEntry.id}
|
|
235
|
-
URL: ${cachedEntry.url}
|
|
236
|
-
Scenario: ${cachedEntry.scenario}
|
|
237
|
-
Cache Level: ${cachedEntry.level}
|
|
238
|
-
Access Count: ${cachedEntry.accessCount || 0}`
|
|
239
|
-
};
|
|
240
47
|
}
|
|
241
48
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAQH;;GAEG;AACH,MAAM,UAAU,QAAQ,CAAC,GAAsB;IAC7C,OAAO,CAAC,GAAG,CAAC,6CAA6C,CAAC,CAAC;IAE3D,gBAAgB;IAChB,MAAM,SAAS,GAAG,GAAG,CAAC,SAAS,EAAE,EAAE,CAAC;IACpC,OAAO,CAAC,GAAG,CAAC,sCAAsC,EAAE,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAExF,aAAa;IACb,IAAI,CAAC,SAAS,IAAI,OAAO,SAAS,KAAK,QAAQ,EAAE,CAAC;QAChD,OAAO,CAAC,GAAG,CAAC,+CAA+C,EAAE,OAAO,SAAS,CAAC,CAAC;QAC/E,eAAe;QACf,SAAS,GAAG,EAAE,CAAC;IACjB,CAAC;IAED,MAAM,YAAY,GAAG,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,mBAAmB,CAAC,IAAI,EAAE,CAAC;IAC9E,OAAO,CAAC,GAAG,CAAC,wDAAwD,EAAE,IAAI,CAAC,SAAS,CAAC,YAAY,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAE7G,MAAM,qBAAqB,GAAG,YAAY,IAAI,EAAE,CAAC;IACjD,OAAO,CAAC,GAAG,CAAC,iDAAiD,EAAE,IAAI,CAAC,SAAS,CAAC,qBAAqB,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAE/G,MAAM,OAAO,GAAG,qBAAqB,CAAC,OAAO,KAAK,KAAK,CAAC;IACxD,OAAO,CAAC,GAAG,CAAC,mCAAmC,EAAE,OAAO,CAAC,CAAC;IAE1D,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,CAAC,GAAG,CAAC,uDAAuD,CAAC,CAAC;QACrE,OAAO;IACT,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,2EAA2E,CAAC,CAAC;IAEzF,WAAW;IACX,GAAG,CAAC,YAAY,CAAC;QACf,IAAI,EAAE,uBAAuB;QAC7B,WAAW,EAAE,gCAAgC;QAC7C,KAAK,CAAC,OAAO,CAAC,GAAQ;YACpB,IAAI,CAAC;gBACH,OAAO,CAAC,GAAG,CAAC,gDAAgD,CAAC,CAAC;gBAC9D,OAAO,CAAC,GAAG,CAAC,iCAAiC,EAAE,OAAO,GAAG,CAAC,CAAC;gBAC3D,OAAO,CAAC,GAAG,CAAC,mCAAmC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;gBAC5G,OAAO,CAAC,GAAG,CAAC,mCAAmC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;gBAE5G,sBAAsB;gBACtB,MAAM,YAAY,GAAG,GAAG,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,mBAAmB,CAAC,IAAI,EAAE,CAAC;gBAC/E,MAAM,OAAO,GAAG,YAAY,CAAC,OAAO,KAAK,KAAK,CAAC;YAAA,CAAC,AAAD;oBAAA,CAAC,CAAD,CAAC,AAAD;QAAA,CAAC,AAAD;KAAA,CAAA,CAAA;AAAA,CAAC,AAAD"}
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -15,18 +15,32 @@ import { browserActionExecutor } from './browser-action-executor.js';
|
|
|
15
15
|
export function register(api: OpenClawPluginApi): void {
|
|
16
16
|
console.log('[PageActionCache] Initializing extension...');
|
|
17
17
|
|
|
18
|
-
// 获取插件配置
|
|
19
|
-
const
|
|
20
|
-
|
|
18
|
+
// 获取插件配置 - 详细日志
|
|
19
|
+
const rawConfig = api.getConfig?.();
|
|
20
|
+
console.log('[PageActionCache] Raw config object:', JSON.stringify(rawConfig, null, 2));
|
|
21
|
+
|
|
22
|
+
// 检查配置对象是否有效
|
|
23
|
+
if (!rawConfig || typeof rawConfig !== 'object') {
|
|
24
|
+
console.log('[PageActionCache] Invalid config object type:', typeof rawConfig);
|
|
25
|
+
// 配置无效,使用空对象继续
|
|
26
|
+
rawConfig = {};
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const pluginConfig = rawConfig?.plugins?.entries?.['page-action-cache'] ?? {};
|
|
30
|
+
console.log('[PageActionCache] Plugin config for page-action-cache:', JSON.stringify(pluginConfig, null, 2));
|
|
31
|
+
|
|
32
|
+
const pageActionCacheConfig = pluginConfig ?? {};
|
|
33
|
+
console.log('[PageActionCache] Parsed pageActionCacheConfig:', JSON.stringify(pageActionCacheConfig, null, 2));
|
|
34
|
+
|
|
21
35
|
const enabled = pageActionCacheConfig.enabled !== false;
|
|
36
|
+
console.log('[PageActionCache] Enabled status:', enabled);
|
|
22
37
|
|
|
23
38
|
if (!enabled) {
|
|
24
39
|
console.log('[PageActionCache] Extension disabled by configuration');
|
|
25
40
|
return;
|
|
26
41
|
}
|
|
27
42
|
|
|
28
|
-
|
|
29
|
-
// 如果需要更多配置选项,可以在 configSchema 中添加更多属性
|
|
43
|
+
console.log('[PageActionCache] Extension enabled, proceeding with tool registration...');
|
|
30
44
|
|
|
31
45
|
// 注册缓存执行工具
|
|
32
46
|
api.registerTool({
|
|
@@ -35,237 +49,10 @@ export function register(api: OpenClawPluginApi): void {
|
|
|
35
49
|
async execute(ctx: any) {
|
|
36
50
|
try {
|
|
37
51
|
console.log('[PageActionCache] browser_cache_execute called');
|
|
52
|
+
console.log('[PageActionCache] Context type:', typeof ctx);
|
|
53
|
+
console.log('[PageActionCache] Context config:', ctx.config ? JSON.stringify(ctx.config, null, 2) : 'null');
|
|
54
|
+
console.log('[PageActionCache] Context params:', ctx.params ? JSON.stringify(ctx.params, null, 2) : 'null');
|
|
38
55
|
|
|
39
56
|
// 从插件配置中读取 enabled 状态
|
|
40
57
|
const pluginConfig = ctx.config?.plugins?.entries?.['page-action-cache'] ?? {};
|
|
41
|
-
const enabled = pluginConfig.enabled !== false;
|
|
42
|
-
|
|
43
|
-
if (!enabled) {
|
|
44
|
-
return {
|
|
45
|
-
type: 'text',
|
|
46
|
-
content: 'Page Action Cache 功能已禁用'
|
|
47
|
-
};
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
const request = ctx.params as any;
|
|
51
|
-
const url = request?.url;
|
|
52
|
-
|
|
53
|
-
if (!url) {
|
|
54
|
-
return {
|
|
55
|
-
type: 'text',
|
|
56
|
-
content: 'Missing required parameter: url'
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// 尝试从缓存中查找
|
|
61
|
-
const cachedEntry = multiLevelCache.queryCache(url, request.viewport || '1920x1080');
|
|
62
|
-
|
|
63
|
-
if (cachedEntry && !request.forceRefresh) {
|
|
64
|
-
console.log('[PageActionCache] Cache hit found');
|
|
65
|
-
return await executeFromCache(cachedEntry);
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
// 缓存未命中或强制刷新,创建新缓存并执行
|
|
69
|
-
console.log('[PageActionCache] Cache miss or forced refresh, creating new entry');
|
|
70
|
-
|
|
71
|
-
// 识别场景
|
|
72
|
-
let scenario = request.scenario;
|
|
73
|
-
if (!scenario) {
|
|
74
|
-
scenario = scenarioRecognizer.recognizeByUrl(url);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
// 创建缓存条目
|
|
78
|
-
const actions = request.actions || [];
|
|
79
|
-
const cacheActions = actions.map((action: any) => ({
|
|
80
|
-
type: action.type,
|
|
81
|
-
params: action.params,
|
|
82
|
-
successCount: 0,
|
|
83
|
-
failCount: 0
|
|
84
|
-
}));
|
|
85
|
-
|
|
86
|
-
const cacheId = multiLevelCache.addCache(
|
|
87
|
-
url,
|
|
88
|
-
request.viewport || '1920x1080',
|
|
89
|
-
cacheActions,
|
|
90
|
-
scenario,
|
|
91
|
-
request.llmClassificationScore
|
|
92
|
-
);
|
|
93
|
-
|
|
94
|
-
// 执行操作
|
|
95
|
-
const entry = {
|
|
96
|
-
id: cacheId,
|
|
97
|
-
url,
|
|
98
|
-
viewport: request.viewport || '1920x1080',
|
|
99
|
-
actions: cacheActions,
|
|
100
|
-
scenario,
|
|
101
|
-
timestamp: Date.now(),
|
|
102
|
-
hitRate: 0,
|
|
103
|
-
savedActions: 0,
|
|
104
|
-
savedTime: 0,
|
|
105
|
-
level: 'L1' as const,
|
|
106
|
-
createdAt: Date.now(),
|
|
107
|
-
lastAccessed: Date.now(),
|
|
108
|
-
accessCount: 0,
|
|
109
|
-
expiresAt: Date.now() + 86400000 // 24小时
|
|
110
|
-
};
|
|
111
|
-
|
|
112
|
-
const result = await browserActionExecutor.executeCacheEntry(entry);
|
|
113
|
-
|
|
114
|
-
return {
|
|
115
|
-
type: 'text',
|
|
116
|
-
content: `## Cache Execution Result
|
|
117
|
-
|
|
118
|
-
${result.message}
|
|
119
|
-
|
|
120
|
-
- Executed Actions: ${result.executedActions}
|
|
121
|
-
- Skipped Actions: ${result.skippedActions}
|
|
122
|
-
- Failed Actions: ${result.failedActions}
|
|
123
|
-
- Saved Time: ${result.savedTime}ms
|
|
124
|
-
|
|
125
|
-
Cache ID: ${cacheId}
|
|
126
|
-
URL: ${url}
|
|
127
|
-
Scenario: ${scenario}
|
|
128
|
-
LLM Classification Score: ${request.llmClassificationScore || 'N/A'}`
|
|
129
|
-
};
|
|
130
|
-
} catch (error: any) {
|
|
131
|
-
console.error('[PageActionCache] Error:', error);
|
|
132
|
-
return {
|
|
133
|
-
type: 'text',
|
|
134
|
-
content: `执行失败: ${error.message}`
|
|
135
|
-
};
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
});
|
|
139
|
-
|
|
140
|
-
// 注册缓存统计工具
|
|
141
|
-
api.registerTool({
|
|
142
|
-
name: 'browser_cache_stats',
|
|
143
|
-
description: '查看页面操作缓存的统计信息',
|
|
144
|
-
async execute(_ctx: any) {
|
|
145
|
-
try {
|
|
146
|
-
const stats = multiLevelCache.getStats();
|
|
147
|
-
const invalidationStats = cacheInvalidation.getInvalidationStats();
|
|
148
|
-
|
|
149
|
-
return {
|
|
150
|
-
type: 'text',
|
|
151
|
-
content: `## Page Action Cache Statistics
|
|
152
|
-
|
|
153
|
-
### Overall Performance
|
|
154
|
-
- Total Cache Entries: ${stats.totalEntries}
|
|
155
|
-
- Total Cache Hits: ${stats.totalHits}
|
|
156
|
-
- Cache Hit Rate: ${stats.hitRate.toFixed(2)}%
|
|
157
|
-
|
|
158
|
-
### Multi-Level Cache Distribution
|
|
159
|
-
${Object.entries(stats.levelStats).map(([level, data]) => `
|
|
160
|
-
#### ${level} Cache
|
|
161
|
-
- Size: ${data.size}/${data.maxCapacity} (${(data.usageRate * 100).toFixed(1)}% full)
|
|
162
|
-
- Average Access Count: ${data.avgAccessCount.toFixed(1)}
|
|
163
|
-
`).join('')}
|
|
164
|
-
|
|
165
|
-
### Cache Invalidation
|
|
166
|
-
- Total Snapshots: ${invalidationStats.totalSnapshots}
|
|
167
|
-
- Active Snapshots: ${invalidationStats.activeSnapshots}
|
|
168
|
-
- Invalidation Rate: ${(invalidationStats.invalidationRate * 100).toFixed(2)}%`
|
|
169
|
-
};
|
|
170
|
-
} catch (error: any) {
|
|
171
|
-
return {
|
|
172
|
-
type: 'text',
|
|
173
|
-
content: `统计功能错误: ${error.message}`
|
|
174
|
-
};
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
});
|
|
178
|
-
|
|
179
|
-
// 注册缓存清除工具
|
|
180
|
-
api.registerTool({
|
|
181
|
-
name: 'browser_cache_clear',
|
|
182
|
-
description: '清空页面操作缓存',
|
|
183
|
-
async execute(ctx: any) {
|
|
184
|
-
try {
|
|
185
|
-
const request = ctx.params as any;
|
|
186
|
-
|
|
187
|
-
if (request.url && request.viewport) {
|
|
188
|
-
// 删除特定缓存条目
|
|
189
|
-
const deleted = multiLevelCache.deleteCache(request.url, request.viewport || '1920x1080');
|
|
190
|
-
cacheInvalidation.invalidate(request.url, request.viewport || '1920x1080');
|
|
191
|
-
|
|
192
|
-
return {
|
|
193
|
-
type: 'text',
|
|
194
|
-
content: deleted
|
|
195
|
-
? `Cache entry deleted for ${request.url}:${request.viewport || '1920x1080'}`
|
|
196
|
-
: `No cache entry found for ${request.url}:${request.viewport || '1920x1080'}`
|
|
197
|
-
};
|
|
198
|
-
} else if (request.url) {
|
|
199
|
-
// 删除 URL 相关的所有缓存
|
|
200
|
-
multiLevelCache.deleteCacheByUrl(request.url);
|
|
201
|
-
cacheInvalidation.invalidateByUrl(request.url);
|
|
202
|
-
|
|
203
|
-
return {
|
|
204
|
-
type: 'text',
|
|
205
|
-
content: `All cache entries for ${request.url} have been deleted`
|
|
206
|
-
};
|
|
207
|
-
} else if (request.level) {
|
|
208
|
-
// 按级别删除
|
|
209
|
-
if (request.level === 'all') {
|
|
210
|
-
multiLevelCache.clearAll();
|
|
211
|
-
cacheInvalidation.reset();
|
|
212
|
-
} else {
|
|
213
|
-
multiLevelCache.clearLevel(request.level);
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
return {
|
|
217
|
-
type: 'text',
|
|
218
|
-
content: `Cache cleared for level: ${request.level}`
|
|
219
|
-
};
|
|
220
|
-
} else {
|
|
221
|
-
// 默认清空所有缓存
|
|
222
|
-
multiLevelCache.clearAll();
|
|
223
|
-
cacheInvalidation.reset();
|
|
224
|
-
|
|
225
|
-
return {
|
|
226
|
-
type: 'text',
|
|
227
|
-
content: 'All page action cache has been cleared'
|
|
228
|
-
};
|
|
229
|
-
}
|
|
230
|
-
} catch (error: any) {
|
|
231
|
-
return {
|
|
232
|
-
type: 'text',
|
|
233
|
-
content: `清除功能错误: ${error.message}`
|
|
234
|
-
};
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
});
|
|
238
|
-
|
|
239
|
-
console.log('[PageActionCache] Tools registered successfully');
|
|
240
|
-
|
|
241
|
-
// 定期清理过期缓存
|
|
242
|
-
setInterval(() => {
|
|
243
|
-
multiLevelCache.cleanupExpired();
|
|
244
|
-
cacheInvalidation.cleanup();
|
|
245
|
-
}, 60 * 60 * 1000); // 每小时清理一次
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
/**
|
|
249
|
-
* 从缓存执行
|
|
250
|
-
*/
|
|
251
|
-
async function executeFromCache(cachedEntry: any) {
|
|
252
|
-
const result = await browserActionExecutor.executeCacheEntry(cachedEntry);
|
|
253
|
-
|
|
254
|
-
return {
|
|
255
|
-
type: 'text',
|
|
256
|
-
content: `## Cached Execution
|
|
257
|
-
|
|
258
|
-
${result.message}
|
|
259
|
-
|
|
260
|
-
- Executed Actions: ${result.executedActions}
|
|
261
|
-
- Skipped Actions: ${result.skippedActions}
|
|
262
|
-
- Failed Actions: ${result.failedActions}
|
|
263
|
-
- Saved Time: ${result.savedTime}ms
|
|
264
|
-
|
|
265
|
-
Cache ID: ${cachedEntry.id}
|
|
266
|
-
URL: ${cachedEntry.url}
|
|
267
|
-
Scenario: ${cachedEntry.scenario}
|
|
268
|
-
Cache Level: ${cachedEntry.level}
|
|
269
|
-
Access Count: ${cachedEntry.accessCount || 0}`
|
|
270
|
-
};
|
|
271
|
-
}
|
|
58
|
+
const enabled = pluginConfig.enabled !== false;
|