page-action-cache 1.0.3 → 2.0.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.
Files changed (89) hide show
  1. package/README.md +399 -0
  2. package/dist/browser-action-executor.d.ts +87 -0
  3. package/dist/browser-action-executor.d.ts.map +1 -0
  4. package/dist/browser-action-executor.js +283 -0
  5. package/dist/browser-action-executor.js.map +1 -0
  6. package/dist/cache-invalidation.d.ts +128 -0
  7. package/dist/cache-invalidation.d.ts.map +1 -0
  8. package/dist/cache-invalidation.js +262 -0
  9. package/dist/cache-invalidation.js.map +1 -0
  10. package/dist/cache-manager.d.ts +83 -0
  11. package/dist/cache-manager.d.ts.map +1 -0
  12. package/dist/cache-manager.js +184 -0
  13. package/dist/cache-manager.js.map +1 -0
  14. package/dist/index.d.ts +7 -21
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +249 -31
  17. package/dist/index.js.map +1 -1
  18. package/dist/multi-level-cache.d.ts +127 -0
  19. package/dist/multi-level-cache.d.ts.map +1 -0
  20. package/dist/multi-level-cache.js +362 -0
  21. package/dist/multi-level-cache.js.map +1 -0
  22. package/dist/scenario-recognizer.d.ts +17 -27
  23. package/dist/scenario-recognizer.d.ts.map +1 -1
  24. package/dist/scenario-recognizer.js +63 -183
  25. package/dist/scenario-recognizer.js.map +1 -1
  26. package/dist/types.d.ts +38 -312
  27. package/dist/types.d.ts.map +1 -1
  28. package/dist/types.js +2 -4
  29. package/dist/types.js.map +1 -1
  30. package/dist/variable-extractor.d.ts +56 -0
  31. package/dist/variable-extractor.d.ts.map +1 -0
  32. package/dist/variable-extractor.js +159 -0
  33. package/dist/variable-extractor.js.map +1 -0
  34. package/openclaw.plugin.json +11 -189
  35. package/package.json +28 -44
  36. package/src/browser-action-executor.ts +337 -0
  37. package/src/cache-invalidation.ts +338 -0
  38. package/src/cache-manager.ts +211 -0
  39. package/src/index.ts +306 -0
  40. package/src/multi-level-cache.ts +478 -0
  41. package/src/scenario-recognizer.ts +121 -0
  42. package/src/types-mock.d.ts +18 -0
  43. package/src/types.ts +66 -0
  44. package/src/variable-extractor.ts +204 -0
  45. package/dist/actions-executor.d.ts +0 -62
  46. package/dist/actions-executor.d.ts.map +0 -1
  47. package/dist/actions-executor.js +0 -339
  48. package/dist/actions-executor.js.map +0 -1
  49. package/dist/cache-invalidator.d.ts +0 -70
  50. package/dist/cache-invalidator.d.ts.map +0 -1
  51. package/dist/cache-invalidator.js +0 -212
  52. package/dist/cache-invalidator.js.map +0 -1
  53. package/dist/cache-store.d.ts +0 -80
  54. package/dist/cache-store.d.ts.map +0 -1
  55. package/dist/cache-store.js +0 -361
  56. package/dist/cache-store.js.map +0 -1
  57. package/dist/cache-strategy.d.ts +0 -65
  58. package/dist/cache-strategy.d.ts.map +0 -1
  59. package/dist/cache-strategy.js +0 -237
  60. package/dist/cache-strategy.js.map +0 -1
  61. package/dist/hooks-entry.d.ts +0 -18
  62. package/dist/hooks-entry.d.ts.map +0 -1
  63. package/dist/hooks-entry.js +0 -27
  64. package/dist/hooks-entry.js.map +0 -1
  65. package/dist/hooks.d.ts +0 -10
  66. package/dist/hooks.d.ts.map +0 -1
  67. package/dist/hooks.js +0 -277
  68. package/dist/hooks.js.map +0 -1
  69. package/dist/security-policy.d.ts +0 -62
  70. package/dist/security-policy.d.ts.map +0 -1
  71. package/dist/security-policy.js +0 -219
  72. package/dist/security-policy.js.map +0 -1
  73. package/dist/tools.d.ts +0 -209
  74. package/dist/tools.d.ts.map +0 -1
  75. package/dist/tools.js +0 -383
  76. package/dist/tools.js.map +0 -1
  77. package/dist/ux-enhancer.d.ts +0 -60
  78. package/dist/ux-enhancer.d.ts.map +0 -1
  79. package/dist/ux-enhancer.js +0 -218
  80. package/dist/ux-enhancer.js.map +0 -1
  81. package/dist/variable-resolver.d.ts +0 -28
  82. package/dist/variable-resolver.d.ts.map +0 -1
  83. package/dist/variable-resolver.js +0 -201
  84. package/dist/variable-resolver.js.map +0 -1
  85. package/docs/API.md +0 -555
  86. package/docs/IMPLEMENTATION.md +0 -1792
  87. package/docs/INTEGRATION.md +0 -387
  88. package/docs/README.md +0 -183
  89. package/skills/page-action-cache/SKILL.md +0 -216
@@ -1 +0,0 @@
1
- {"version":3,"file":"cache-invalidator.d.ts","sourceRoot":"","sources":["../src/cache-invalidator.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EACV,YAAY,EACZ,mBAAmB,EACnB,oBAAoB,EAErB,MAAM,YAAY,CAAC;AAMpB;;GAEG;AACH,qBAAa,gBAAgB;IAC3B;;OAEG;IACG,gBAAgB,CACpB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,YAAY,EACvB,WAAW,CAAC,EAAE,oBAAoB,GACjC,OAAO,CAAC,mBAAmB,CAAC;IA0D/B;;OAEG;IACH,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAKtC;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAa1B;;OAEG;IACH,OAAO,CAAC,aAAa;IAKrB;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAiB3B;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAW7B;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAU3B;;OAEG;IACH,gBAAgB,CACd,KAAK,EAAE,oBAAoB,EAC3B,YAAY,EAAE,mBAAmB,EACjC,SAAS,GAAE,MAAW,GACrB,OAAO;IAoBV;;OAEG;IACH,4BAA4B,IAAI,sBAAsB;CAGvD;AAMD;;GAEG;AACH,qBAAa,sBAAsB;IACjC,OAAO,CAAC,QAAQ,CAAoC;IAEpD;;OAEG;IACH,UAAU,CAAC,KAAK,EAAE,oBAAoB,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI;IAgBhE;;OAEG;IACH,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE;IAIlC;;OAEG;IACH,eAAe,CAAC,KAAK,EAAE,oBAAoB,GAAG,MAAM;IAOpD;;OAEG;IACH,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,WAAW,GAAE,MAAU,GAAG,IAAI;CAQ/D;AAQD,wBAAgB,mBAAmB,IAAI,gBAAgB,CAKtD"}
@@ -1,212 +0,0 @@
1
- /**
2
- * Cache Invalidator
3
- * 缓存失效检测器 - 检测页面变化并失效缓存
4
- */
5
- // ============================================================================
6
- // Cache Invalidator 类
7
- // ============================================================================
8
- /**
9
- * 缓存失效检测器
10
- */
11
- export class CacheInvalidator {
12
- /**
13
- * 检测页面是否发生变化
14
- */
15
- async detectPageChange(html, _url, _viewport, cachedEntry) {
16
- // 计算当前 DOM hash
17
- const currentHash = this.calculateDOMHash(html);
18
- if (!cachedEntry || !cachedEntry.pageChangeDetection) {
19
- return {
20
- hasChanged: true,
21
- changeType: "none",
22
- confidence: 0,
23
- domHash: currentHash,
24
- lastCheckedAt: Date.now(),
25
- };
26
- }
27
- const cachedHash = cachedEntry.pageChangeDetection.domHash;
28
- // 比较 hash
29
- if (currentHash === cachedHash) {
30
- return {
31
- hasChanged: false,
32
- changeType: "none",
33
- confidence: 100,
34
- domHash: currentHash,
35
- lastCheckedAt: Date.now(),
36
- };
37
- }
38
- // 检测变化类型
39
- const structureChanged = this.detectStructureChange(html);
40
- const contentChanged = this.detectContentChange(html, cachedEntry);
41
- if (structureChanged || contentChanged) {
42
- return {
43
- hasChanged: true,
44
- changeType: structureChanged ? "structure" : "content",
45
- confidence: Math.max(structureChanged ? 80 : 0, contentChanged ? 80 : 0),
46
- domHash: currentHash,
47
- lastCheckedAt: Date.now(),
48
- details: structureChanged
49
- ? "Form/Button count changed"
50
- : "Content hash changed",
51
- };
52
- }
53
- // hash 不同但结构未变,可能是动态内容
54
- return {
55
- hasChanged: true,
56
- changeType: "content",
57
- confidence: 50, // 低置信度,可能是动态内容
58
- domHash: currentHash,
59
- lastCheckedAt: Date.now(),
60
- details: "Hash changed but structure is similar",
61
- };
62
- }
63
- /**
64
- * 计算 DOM hash
65
- */
66
- calculateDOMHash(html) {
67
- const features = this.extractDOMFeatures(html);
68
- return this.combineFeaturesHash(features);
69
- }
70
- /**
71
- * 提取 DOM 特征
72
- */
73
- extractDOMFeatures(html) {
74
- return {
75
- formCount: this.countElements(html, "form"),
76
- buttonCount: this.countElements(html, "button"),
77
- linkCount: this.countElements(html, "a"),
78
- scriptCount: this.countElements(html, "script"),
79
- headingCount: this.countElements(html, "h1") +
80
- this.countElements(html, "h2") +
81
- this.countElements(html, "h3"),
82
- };
83
- }
84
- /**
85
- * 计算元素数量
86
- */
87
- countElements(html, tagName) {
88
- const regex = new RegExp(`<${tagName}\\b`, "gi");
89
- return (html.match(regex) || []).length;
90
- }
91
- /**
92
- * 组合特征为 hash
93
- */
94
- combineFeaturesHash(features) {
95
- const values = [
96
- features.formCount,
97
- features.buttonCount,
98
- features.linkCount,
99
- features.scriptCount,
100
- features.headingCount,
101
- ];
102
- // 简单 hash 算法
103
- let hash = 0;
104
- for (const value of values) {
105
- hash = ((hash << 5) - hash + value) | 0;
106
- }
107
- return hash.toString(16);
108
- }
109
- /**
110
- * 检测结构变化
111
- */
112
- detectStructureChange(html) {
113
- // 检查表单和按钮数量是否发生显著变化
114
- const features = this.extractDOMFeatures(html);
115
- // 如果表单数量变化,认为是结构变化
116
- // 这里简化处理,实际应该与缓存条目比较
117
- const hasForm = features.formCount > 0;
118
- return !hasForm;
119
- }
120
- /**
121
- * 检测内容变化
122
- */
123
- detectContentChange(html, cachedEntry) {
124
- // 简化处理:检查 HTML 长度变化
125
- const lengthChanged = Math.abs(html.length - (cachedEntry.actions.length * 100)) > 500;
126
- return lengthChanged;
127
- }
128
- /**
129
- * 判断是否应该失效缓存
130
- */
131
- shouldInvalidate(entry, changeResult, threshold = 80) {
132
- // 根据页面类型和置信度决定是否失效
133
- const pageType = entry.pageType || "mixed";
134
- if (pageType === "static") {
135
- // 静态页面:高置信度时失效
136
- return changeResult.hasChanged && changeResult.confidence >= threshold;
137
- }
138
- else if (pageType === "dynamic") {
139
- // 动态页面:只在结构变化时失效
140
- return (changeResult.hasChanged && changeResult.changeType === "structure");
141
- }
142
- else {
143
- // 混合页面:中等置信度时失效
144
- return (changeResult.hasChanged && changeResult.confidence >= threshold - 10);
145
- }
146
- }
147
- /**
148
- * 创建渐进式失效器
149
- */
150
- createProgressiveInvalidator() {
151
- return new ProgressiveInvalidator();
152
- }
153
- }
154
- // ============================================================================
155
- // Progressive Invalidator 类
156
- // ============================================================================
157
- /**
158
- * 渐进式失效:保留多版本
159
- */
160
- export class ProgressiveInvalidator {
161
- versions = new Map();
162
- /**
163
- * 添加版本
164
- */
165
- addVersion(entry, versionId) {
166
- const key = entry.key;
167
- if (!this.versions.has(key)) {
168
- this.versions.set(key, []);
169
- }
170
- const versions = this.versions.get(key);
171
- versions.push(versionId);
172
- // 只保留最近的 N 个版本(默认 3 个)
173
- if (versions.length > 3) {
174
- versions.shift();
175
- }
176
- }
177
- /**
178
- * 获取版本列表
179
- */
180
- getVersions(key) {
181
- return this.versions.get(key) || [];
182
- }
183
- /**
184
- * 生成版本标识
185
- */
186
- generateVersion(entry) {
187
- const time = new Date(entry.createdAt).toISOString().slice(0, 10); // YYYY-MM-DD
188
- const pageType = entry.pageType || "unknown";
189
- return `${pageType}-${entry.scenario}-${time}`;
190
- }
191
- /**
192
- * 清理旧版本
193
- */
194
- cleanupOldVersions(key, maxVersions = 3) {
195
- const versions = this.getVersions(key);
196
- if (versions.length > maxVersions) {
197
- const toKeep = versions.slice(-maxVersions);
198
- this.versions.set(key, toKeep);
199
- }
200
- }
201
- }
202
- // ============================================================================
203
- // 单例
204
- // ============================================================================
205
- let cacheInvalidatorInstance = null;
206
- export function getCacheInvalidator() {
207
- if (!cacheInvalidatorInstance) {
208
- cacheInvalidatorInstance = new CacheInvalidator();
209
- }
210
- return cacheInvalidatorInstance;
211
- }
212
- //# sourceMappingURL=cache-invalidator.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"cache-invalidator.js","sourceRoot":"","sources":["../src/cache-invalidator.ts"],"names":[],"mappings":"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"}
@@ -1,80 +0,0 @@
1
- /**
2
- * Page Action Cache Store
3
- * 管理页面操作缓存的存储
4
- */
5
- import type { PageActionCacheEntry, PageViewport, CacheStats, ScenarioMatch } from "./types.js";
6
- /**
7
- * 缓存存储管理器
8
- */
9
- export declare class CacheStore {
10
- private store;
11
- constructor();
12
- private load;
13
- private createEmptyStore;
14
- private ensureCacheDir;
15
- private save;
16
- private scheduleSave;
17
- private _saveTimeout;
18
- private generateKey;
19
- private normalizeUrl;
20
- /**
21
- * 设置缓存条目
22
- */
23
- set(url: string, viewport: PageViewport, actions: any[], metadata: {
24
- scenario: string;
25
- cacheLevel: "L3" | "L2" | "L1";
26
- variables?: Record<string, string>;
27
- description?: string;
28
- pageType?: "static" | "dynamic" | "mixed";
29
- }): string;
30
- /**
31
- * 获取缓存条目
32
- */
33
- get(url: string, viewport: PageViewport): PageActionCacheEntry | null;
34
- /**
35
- * 删除缓存条目
36
- */
37
- delete(url: string, viewport: PageViewport): boolean;
38
- /**
39
- * 按模式删除缓存条目
40
- */
41
- deleteByPattern(urlPattern: string): number;
42
- /**
43
- * 清空所有缓存
44
- */
45
- clear(): void;
46
- private updateHitRate;
47
- /**
48
- * 更新执行统计
49
- */
50
- updateExecutionStats(key: string, results: Array<{
51
- success: boolean;
52
- duration: number;
53
- }>): void;
54
- /**
55
- * 保存场景匹配
56
- */
57
- saveScenarioMatch(match: ScenarioMatch): void;
58
- /**
59
- * 获取场景匹配
60
- */
61
- getScenarioMatch(scenario: string): ScenarioMatch | undefined;
62
- /**
63
- * 获取统计信息
64
- */
65
- getStats(): CacheStats;
66
- /**
67
- * 列出所有缓存条目
68
- */
69
- listEntries(): PageActionCacheEntry[];
70
- /**
71
- * 获取热门场景
72
- */
73
- getTopScenarios(limit?: number): string;
74
- /**
75
- * 清理过期缓存
76
- */
77
- cleanupExpired(): number;
78
- }
79
- export declare function getCacheStore(): CacheStore;
80
- //# sourceMappingURL=cache-store.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"cache-store.d.ts","sourceRoot":"","sources":["../src/cache-store.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,KAAK,EACV,oBAAoB,EAEpB,YAAY,EACZ,UAAU,EACV,aAAa,EACd,MAAM,YAAY,CAAC;AA0BpB;;GAEG;AACH,qBAAa,UAAU;IACrB,OAAO,CAAC,KAAK,CAAuB;;IAUpC,OAAO,CAAC,IAAI;IAuBZ,OAAO,CAAC,gBAAgB;IA0BxB,OAAO,CAAC,cAAc;IAUtB,OAAO,CAAC,IAAI;IAgBZ,OAAO,CAAC,YAAY;IAQpB,OAAO,CAAC,YAAY,CAA+B;IAMnD,OAAO,CAAC,WAAW;IASnB,OAAO,CAAC,YAAY;IAgBpB;;OAEG;IACH,GAAG,CACD,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,YAAY,EACtB,OAAO,EAAE,GAAG,EAAE,EACd,QAAQ,EAAE;QACR,QAAQ,EAAE,MAAM,CAAC;QACjB,UAAU,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;QAC/B,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACnC,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,QAAQ,CAAC,EAAE,QAAQ,GAAG,SAAS,GAAG,OAAO,CAAC;KAC3C,GACA,MAAM;IAwCT;;OAEG;IACH,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,YAAY,GAAG,oBAAoB,GAAG,IAAI;IA4CrE;;OAEG;IACH,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,YAAY,GAAG,OAAO;IAapD;;OAEG;IACH,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM;IAkB3C;;OAEG;IACH,KAAK,IAAI,IAAI;IAWb,OAAO,CAAC,aAAa;IAMrB;;OAEG;IACH,oBAAoB,CAClB,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,KAAK,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,GACrD,IAAI;IA8BP;;OAEG;IACH,iBAAiB,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI;IAM7C;;OAEG;IACH,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS;IAQ7D;;OAEG;IACH,QAAQ,IAAI,UAAU;IAItB;;OAEG;IACH,WAAW,IAAI,oBAAoB,EAAE;IAMrC;;OAEG;IACH,eAAe,CAAC,KAAK,GAAE,MAAU,GAAG,MAAM;IAqB1C;;OAEG;IACH,cAAc,IAAI,MAAM;CAkBzB;AAQD,wBAAgB,aAAa,IAAI,UAAU,CAK1C"}
@@ -1,361 +0,0 @@
1
- /**
2
- * Page Action Cache Store
3
- * 管理页面操作缓存的存储
4
- */
5
- import fs from "node:fs";
6
- import path from "node:path";
7
- import { createHash } from "node:crypto";
8
- // ============================================================================
9
- // 配置
10
- // ============================================================================
11
- const CACHE_DIR = path.join(process.env.HOME || process.env.USERPROFILE || ".", ".openclaw", "cache", "page-actions");
12
- const CACHE_FILE = path.join(CACHE_DIR, "cache.json");
13
- const CACHE_VERSION = 1;
14
- const DEFAULT_TTL = {
15
- L3: 7 * 24 * 60 * 60 * 1000, // 7 天
16
- L2: 3 * 24 * 60 * 60 * 1000, // 3 天
17
- L1: 30 * 60 * 1000, // 30 分钟
18
- };
19
- // ============================================================================
20
- // CacheStore 类
21
- // ============================================================================
22
- /**
23
- * 缓存存储管理器
24
- */
25
- export class CacheStore {
26
- store;
27
- constructor() {
28
- this.store = this.load();
29
- }
30
- // -------------------------------------------------------------------------
31
- // 初始化和加载
32
- // -------------------------------------------------------------------------
33
- load() {
34
- try {
35
- if (fs.existsSync(CACHE_FILE)) {
36
- const data = fs.readFileSync(CACHE_FILE, "utf-8");
37
- const loaded = JSON.parse(data);
38
- // 版本检查
39
- if (loaded.version !== CACHE_VERSION) {
40
- console.warn(`[CacheStore] Cache version mismatch (expected ${CACHE_VERSION}, got ${loaded.version}), clearing cache`);
41
- return this.createEmptyStore();
42
- }
43
- return loaded;
44
- }
45
- }
46
- catch (error) {
47
- console.error(`[CacheStore] Failed to load cache:`, error);
48
- }
49
- return this.createEmptyStore();
50
- }
51
- createEmptyStore() {
52
- return {
53
- version: CACHE_VERSION,
54
- entries: {},
55
- scenarios: new Map(),
56
- stats: {
57
- totalEntries: 0,
58
- totalHits: 0,
59
- totalMisses: 0,
60
- hitRate: 0,
61
- l3Hits: 0,
62
- l2Hits: 0,
63
- l1Hits: 0,
64
- scenarioMatches: 0,
65
- llmClassifications: 0,
66
- learnedAssociations: 0,
67
- savedTokens: 0,
68
- savedTime: 0,
69
- avgExecutionTime: 0,
70
- userConfirmations: 0,
71
- userForcedRefreshes: 0,
72
- cacheErrors: 0,
73
- },
74
- };
75
- }
76
- ensureCacheDir() {
77
- if (!fs.existsSync(CACHE_DIR)) {
78
- fs.mkdirSync(CACHE_DIR, { recursive: true });
79
- }
80
- }
81
- // -------------------------------------------------------------------------
82
- // 保存
83
- // -------------------------------------------------------------------------
84
- save() {
85
- try {
86
- this.ensureCacheDir();
87
- // 序列化(处理 Map)
88
- const serialized = {
89
- ...this.store,
90
- scenarios: Array.from(this.store.scenarios.entries()),
91
- };
92
- fs.writeFileSync(CACHE_FILE, JSON.stringify(serialized, null, 2));
93
- }
94
- catch (error) {
95
- console.error(`[CacheStore] Failed to save cache:`, error);
96
- }
97
- }
98
- scheduleSave() {
99
- // 防抖保存(100ms)
100
- if (this._saveTimeout) {
101
- clearTimeout(this._saveTimeout);
102
- }
103
- this._saveTimeout = setTimeout(() => this.save(), 100);
104
- }
105
- _saveTimeout = null;
106
- // -------------------------------------------------------------------------
107
- // 缓存键生成
108
- // -------------------------------------------------------------------------
109
- generateKey(url, viewport) {
110
- const normalizedUrl = this.normalizeUrl(url);
111
- const viewportStr = `${viewport.width}x${viewport.height}`;
112
- const hash = createHash("md5")
113
- .update(`${normalizedUrl}:${viewportStr}`)
114
- .digest("hex");
115
- return hash || `fallback-${Date.now()}`; // 确保 hash 不为空
116
- }
117
- normalizeUrl(url) {
118
- try {
119
- const parsed = new URL(url);
120
- // 移除查询参数和哈希(可根据配置调整)
121
- parsed.search = "";
122
- parsed.hash = "";
123
- return parsed.toString();
124
- }
125
- catch {
126
- return url;
127
- }
128
- }
129
- // -------------------------------------------------------------------------
130
- // 基本操作
131
- // -------------------------------------------------------------------------
132
- /**
133
- * 设置缓存条目
134
- */
135
- set(url, viewport, actions, metadata) {
136
- const key = this.generateKey(url, viewport);
137
- const now = Date.now();
138
- const ttl = DEFAULT_TTL[metadata.cacheLevel];
139
- const entry = {
140
- key,
141
- url: this.normalizeUrl(url),
142
- viewport,
143
- cacheLevel: metadata.cacheLevel,
144
- scenario: metadata.scenario,
145
- description: metadata.description || `Cached ${metadata.scenario} actions`,
146
- variables: metadata.variables,
147
- actions,
148
- createdAt: now,
149
- lastAccessTime: now,
150
- accessCount: 0,
151
- expiresAt: now + ttl,
152
- pageChangeDetection: {
153
- hasChanged: false,
154
- changeType: "none",
155
- confidence: 100,
156
- domHash: "",
157
- lastCheckedAt: now,
158
- },
159
- source: "llm",
160
- version: 1,
161
- successCount: 0,
162
- failCount: 0,
163
- avgExecutionTime: 0,
164
- pageType: metadata.pageType || "mixed",
165
- };
166
- this.store.entries[key] = entry;
167
- this.store.stats.totalEntries++;
168
- this.scheduleSave();
169
- return key;
170
- }
171
- /**
172
- * 获取缓存条目
173
- */
174
- get(url, viewport) {
175
- const key = this.generateKey(url, viewport);
176
- const entry = this.store.entries[key];
177
- if (!entry) {
178
- this.store.stats.totalMisses++;
179
- this.updateHitRate();
180
- return null;
181
- }
182
- // 检查过期
183
- if (Date.now() > entry.expiresAt) {
184
- delete this.store.entries[key];
185
- this.store.stats.totalEntries--;
186
- this.store.stats.totalMisses++;
187
- this.updateHitRate();
188
- this.scheduleSave();
189
- return null;
190
- }
191
- // 更新访问统计
192
- entry.lastAccessTime = Date.now();
193
- entry.accessCount++;
194
- // 更新层级统计
195
- this.store.stats.totalHits++;
196
- switch (entry.cacheLevel) {
197
- case "L3":
198
- this.store.stats.l3Hits++;
199
- break;
200
- case "L2":
201
- this.store.stats.l2Hits++;
202
- break;
203
- case "L1":
204
- this.store.stats.l1Hits++;
205
- break;
206
- }
207
- this.updateHitRate();
208
- this.scheduleSave();
209
- return entry;
210
- }
211
- /**
212
- * 删除缓存条目
213
- */
214
- delete(url, viewport) {
215
- const key = this.generateKey(url, viewport);
216
- const existed = !!this.store.entries[key];
217
- if (existed) {
218
- delete this.store.entries[key];
219
- this.store.stats.totalEntries--;
220
- this.scheduleSave();
221
- }
222
- return existed;
223
- }
224
- /**
225
- * 按模式删除缓存条目
226
- */
227
- deleteByPattern(urlPattern) {
228
- let deleted = 0;
229
- for (const [key, entry] of Object.entries(this.store.entries)) {
230
- if (entry.url.includes(urlPattern)) {
231
- delete this.store.entries[key];
232
- this.store.stats.totalEntries--;
233
- deleted++;
234
- }
235
- }
236
- if (deleted > 0) {
237
- this.scheduleSave();
238
- }
239
- return deleted;
240
- }
241
- /**
242
- * 清空所有缓存
243
- */
244
- clear() {
245
- this.store.entries = {};
246
- this.store.scenarios.clear();
247
- this.store.stats = this.createEmptyStore().stats;
248
- this.scheduleSave();
249
- }
250
- // -------------------------------------------------------------------------
251
- // 统计更新
252
- // -------------------------------------------------------------------------
253
- updateHitRate() {
254
- const total = this.store.stats.totalHits + this.store.stats.totalMisses;
255
- this.store.stats.hitRate =
256
- total > 0 ? (this.store.stats.totalHits / total) * 100 : 0;
257
- }
258
- /**
259
- * 更新执行统计
260
- */
261
- updateExecutionStats(key, results) {
262
- const entry = this.store.entries[key];
263
- if (!entry)
264
- return;
265
- const successCount = results.filter((r) => r.success).length;
266
- const failCount = results.length - successCount;
267
- const avgDuration = results.reduce((sum, r) => sum + r.duration, 0) / results.length;
268
- // 更新统计(加权平均)
269
- const oldCount = entry.successCount + entry.failCount;
270
- const newCount = oldCount + results.length;
271
- entry.successCount += successCount;
272
- entry.failCount += failCount;
273
- entry.avgExecutionTime =
274
- (entry.avgExecutionTime * oldCount + avgDuration * results.length) /
275
- newCount;
276
- // 估算节省的 token 和时间
277
- this.store.stats.savedTokens += 5000; // 估算值
278
- this.store.stats.savedTime += 2000; // 估算值(毫秒)
279
- this.scheduleSave();
280
- }
281
- // -------------------------------------------------------------------------
282
- // 场景匹配管理
283
- // -------------------------------------------------------------------------
284
- /**
285
- * 保存场景匹配
286
- */
287
- saveScenarioMatch(match) {
288
- this.store.scenarios.set(match.scenario, match);
289
- this.store.stats.scenarioMatches++;
290
- this.scheduleSave();
291
- }
292
- /**
293
- * 获取场景匹配
294
- */
295
- getScenarioMatch(scenario) {
296
- return this.store.scenarios.get(scenario);
297
- }
298
- // -------------------------------------------------------------------------
299
- // 查询方法
300
- // -------------------------------------------------------------------------
301
- /**
302
- * 获取统计信息
303
- */
304
- getStats() {
305
- return { ...this.store.stats };
306
- }
307
- /**
308
- * 列出所有缓存条目
309
- */
310
- listEntries() {
311
- return Object.values(this.store.entries).sort((a, b) => b.lastAccessTime - a.lastAccessTime);
312
- }
313
- /**
314
- * 获取热门场景
315
- */
316
- getTopScenarios(limit = 5) {
317
- const scenarioCounts = new Map();
318
- for (const entry of Object.values(this.store.entries)) {
319
- const count = scenarioCounts.get(entry.scenario) || 0;
320
- scenarioCounts.set(entry.scenario, count + entry.accessCount);
321
- }
322
- const sorted = Array.from(scenarioCounts.entries())
323
- .sort((a, b) => b[1] - a[1])
324
- .slice(0, limit);
325
- return sorted
326
- .map(([scenario, count]) => `- ${scenario}: ${count} 次`)
327
- .join("\n");
328
- }
329
- // -------------------------------------------------------------------------
330
- // 清理
331
- // -------------------------------------------------------------------------
332
- /**
333
- * 清理过期缓存
334
- */
335
- cleanupExpired() {
336
- const now = Date.now();
337
- let cleaned = 0;
338
- for (const [key, entry] of Object.entries(this.store.entries)) {
339
- if (now > entry.expiresAt) {
340
- delete this.store.entries[key];
341
- this.store.stats.totalEntries--;
342
- cleaned++;
343
- }
344
- }
345
- if (cleaned > 0) {
346
- this.scheduleSave();
347
- }
348
- return cleaned;
349
- }
350
- }
351
- // ============================================================================
352
- // 单例
353
- // ============================================================================
354
- let cacheStoreInstance = null;
355
- export function getCacheStore() {
356
- if (!cacheStoreInstance) {
357
- cacheStoreInstance = new CacheStore();
358
- }
359
- return cacheStoreInstance;
360
- }
361
- //# sourceMappingURL=cache-store.js.map