ai-browser 0.2.4 → 0.3.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 (107) hide show
  1. package/README.md +40 -1
  2. package/dist/agent/agent-loop.d.ts +26 -2
  3. package/dist/agent/agent-loop.d.ts.map +1 -1
  4. package/dist/agent/agent-loop.js +371 -89
  5. package/dist/agent/agent-loop.js.map +1 -1
  6. package/dist/agent/config.d.ts +5 -0
  7. package/dist/agent/config.d.ts.map +1 -1
  8. package/dist/agent/config.js +5 -0
  9. package/dist/agent/config.js.map +1 -1
  10. package/dist/agent/content-budget.d.ts +11 -0
  11. package/dist/agent/content-budget.d.ts.map +1 -0
  12. package/dist/agent/content-budget.js +133 -0
  13. package/dist/agent/content-budget.js.map +1 -0
  14. package/dist/agent/conversation-manager.d.ts +48 -0
  15. package/dist/agent/conversation-manager.d.ts.map +1 -0
  16. package/dist/agent/conversation-manager.js +171 -0
  17. package/dist/agent/conversation-manager.js.map +1 -0
  18. package/dist/agent/error-recovery.d.ts +29 -0
  19. package/dist/agent/error-recovery.d.ts.map +1 -0
  20. package/dist/agent/error-recovery.js +72 -0
  21. package/dist/agent/error-recovery.js.map +1 -0
  22. package/dist/agent/index.js +7 -2
  23. package/dist/agent/index.js.map +1 -1
  24. package/dist/agent/page-state-cache.d.ts +22 -0
  25. package/dist/agent/page-state-cache.d.ts.map +1 -0
  26. package/dist/agent/page-state-cache.js +71 -0
  27. package/dist/agent/page-state-cache.js.map +1 -0
  28. package/dist/agent/progress-estimator.d.ts +17 -0
  29. package/dist/agent/progress-estimator.d.ts.map +1 -0
  30. package/dist/agent/progress-estimator.js +67 -0
  31. package/dist/agent/progress-estimator.js.map +1 -0
  32. package/dist/agent/prompt.d.ts +1 -1
  33. package/dist/agent/prompt.d.ts.map +1 -1
  34. package/dist/agent/prompt.js +91 -48
  35. package/dist/agent/prompt.js.map +1 -1
  36. package/dist/agent/token-tracker.d.ts +22 -0
  37. package/dist/agent/token-tracker.d.ts.map +1 -0
  38. package/dist/agent/token-tracker.js +29 -0
  39. package/dist/agent/token-tracker.js.map +1 -0
  40. package/dist/agent/tool-usage-tracker.d.ts +45 -0
  41. package/dist/agent/tool-usage-tracker.d.ts.map +1 -0
  42. package/dist/agent/tool-usage-tracker.js +149 -0
  43. package/dist/agent/tool-usage-tracker.js.map +1 -0
  44. package/dist/agent/types.d.ts +30 -0
  45. package/dist/agent/types.d.ts.map +1 -1
  46. package/dist/api/mcp-sse.d.ts +2 -1
  47. package/dist/api/mcp-sse.d.ts.map +1 -1
  48. package/dist/api/mcp-sse.js +2 -1
  49. package/dist/api/mcp-sse.js.map +1 -1
  50. package/dist/api/routes.d.ts +2 -1
  51. package/dist/api/routes.d.ts.map +1 -1
  52. package/dist/api/routes.js +355 -7
  53. package/dist/api/routes.js.map +1 -1
  54. package/dist/browser/BrowserManager.d.ts.map +1 -1
  55. package/dist/browser/BrowserManager.js +5 -2
  56. package/dist/browser/BrowserManager.js.map +1 -1
  57. package/dist/cli/mcp-stdio.js +3 -0
  58. package/dist/cli/mcp-stdio.js.map +1 -1
  59. package/dist/cli/server.js +15 -3
  60. package/dist/cli/server.js.map +1 -1
  61. package/dist/mcp/ai-markdown.d.ts +2 -0
  62. package/dist/mcp/ai-markdown.d.ts.map +1 -0
  63. package/dist/mcp/ai-markdown.js +1807 -0
  64. package/dist/mcp/ai-markdown.js.map +1 -0
  65. package/dist/mcp/browser-mcp-server.d.ts +2 -0
  66. package/dist/mcp/browser-mcp-server.d.ts.map +1 -1
  67. package/dist/mcp/browser-mcp-server.js +340 -49
  68. package/dist/mcp/browser-mcp-server.js.map +1 -1
  69. package/dist/mcp/task-tools.d.ts.map +1 -1
  70. package/dist/mcp/task-tools.js +108 -13
  71. package/dist/mcp/task-tools.js.map +1 -1
  72. package/dist/memory/KnowledgeCardStore.d.ts +35 -0
  73. package/dist/memory/KnowledgeCardStore.d.ts.map +1 -0
  74. package/dist/memory/KnowledgeCardStore.js +304 -0
  75. package/dist/memory/KnowledgeCardStore.js.map +1 -0
  76. package/dist/memory/MemoryCapturer.d.ts +14 -0
  77. package/dist/memory/MemoryCapturer.d.ts.map +1 -0
  78. package/dist/memory/MemoryCapturer.js +183 -0
  79. package/dist/memory/MemoryCapturer.js.map +1 -0
  80. package/dist/memory/MemoryInjector.d.ts +23 -0
  81. package/dist/memory/MemoryInjector.d.ts.map +1 -0
  82. package/dist/memory/MemoryInjector.js +180 -0
  83. package/dist/memory/MemoryInjector.js.map +1 -0
  84. package/dist/memory/RecordingConverter.d.ts +16 -0
  85. package/dist/memory/RecordingConverter.d.ts.map +1 -0
  86. package/dist/memory/RecordingConverter.js +108 -0
  87. package/dist/memory/RecordingConverter.js.map +1 -0
  88. package/dist/memory/SessionRecorder.d.ts +39 -0
  89. package/dist/memory/SessionRecorder.d.ts.map +1 -0
  90. package/dist/memory/SessionRecorder.js +198 -0
  91. package/dist/memory/SessionRecorder.js.map +1 -0
  92. package/dist/memory/index.d.ts +8 -0
  93. package/dist/memory/index.d.ts.map +1 -0
  94. package/dist/memory/index.js +6 -0
  95. package/dist/memory/index.js.map +1 -0
  96. package/dist/memory/types.d.ts +39 -0
  97. package/dist/memory/types.d.ts.map +1 -0
  98. package/dist/memory/types.js +2 -0
  99. package/dist/memory/types.js.map +1 -0
  100. package/dist/task/tool-actions.d.ts +4 -0
  101. package/dist/task/tool-actions.d.ts.map +1 -1
  102. package/dist/task/tool-actions.js +72 -0
  103. package/dist/task/tool-actions.js.map +1 -1
  104. package/package.json +5 -2
  105. package/public/index.html +2296 -226
  106. package/public/task-result.html +107 -12
  107. package/public/tasks.html +83 -10
@@ -0,0 +1,180 @@
1
+ import { MemoryCapturer } from './MemoryCapturer.js';
2
+ const DEFAULT_MAX_CHARS = 2000;
3
+ /**
4
+ * Compute substring-based relevance score between an intent value and a hint.
5
+ * CJK-compatible: uses sliding window substring matching instead of word splitting.
6
+ * Returns the length of the longest matching substring (≥2 chars), or 0.
7
+ */
8
+ export function relevanceScore(intentValue, hint) {
9
+ if (hint.length < 2)
10
+ return 0;
11
+ const lowerIntent = intentValue.toLowerCase();
12
+ const lowerHint = hint.toLowerCase();
13
+ // From longest to shortest, find the first match
14
+ for (let len = lowerHint.length; len >= 2; len--) {
15
+ for (let i = 0; i <= lowerHint.length - len; i++) {
16
+ if (lowerIntent.includes(lowerHint.slice(i, i + len))) {
17
+ return len;
18
+ }
19
+ }
20
+ }
21
+ return 0;
22
+ }
23
+ export class MemoryInjector {
24
+ /**
25
+ * Extract target domain from task text.
26
+ * Looks for URLs or well-known domain names.
27
+ */
28
+ static extractDomain(task) {
29
+ // Try to find a URL in the task
30
+ const urlMatch = task.match(/https?:\/\/[^\s,,。、))]+/);
31
+ if (urlMatch) {
32
+ const domain = MemoryCapturer.extractDomain(urlMatch[0]);
33
+ if (domain)
34
+ return domain;
35
+ }
36
+ // Try to find domain-like patterns (e.g., bilibili.com, jd.com)
37
+ const domainMatch = task.match(/\b([a-zA-Z0-9][-a-zA-Z0-9]*\.(?:com|cn|org|net|io|co|tv|cc|me)(?:\.[a-z]{2})?)\b/);
38
+ if (domainMatch) {
39
+ return domainMatch[1].replace(/^www\./, '');
40
+ }
41
+ // Try well-known site names (Chinese context)
42
+ const siteMap = {
43
+ 'B站': 'bilibili.com',
44
+ 'b站': 'bilibili.com',
45
+ '哔哩哔哩': 'bilibili.com',
46
+ 'bilibili': 'bilibili.com',
47
+ '京东': 'jd.com',
48
+ '淘宝': 'taobao.com',
49
+ '天猫': 'tmall.com',
50
+ '微博': 'weibo.com',
51
+ '知乎': 'zhihu.com',
52
+ '百度': 'baidu.com',
53
+ '豆瓣': 'douban.com',
54
+ '36氪': '36kr.com',
55
+ '新浪': 'sina.com.cn',
56
+ '网易': '163.com',
57
+ '腾讯': 'qq.com',
58
+ '抖音': 'douyin.com',
59
+ '小红书': 'xiaohongshu.com',
60
+ 'github': 'github.com',
61
+ 'Google': 'google.com',
62
+ 'google': 'google.com',
63
+ 'bing': 'bing.com',
64
+ 'Bing': 'bing.com',
65
+ '必应': 'bing.com',
66
+ };
67
+ const lowerTask = task.toLowerCase();
68
+ for (const [name, domain] of Object.entries(siteMap)) {
69
+ if (lowerTask.includes(name.toLowerCase()))
70
+ return domain;
71
+ }
72
+ return null;
73
+ }
74
+ /**
75
+ * Build a compact prompt fragment from a knowledge card.
76
+ * Sorted by effective confidence, hard-limited to maxChars.
77
+ * When taskHint is provided, task_intent patterns are sorted by substring relevance.
78
+ */
79
+ static buildContext(card, maxChars = DEFAULT_MAX_CHARS, taskHint) {
80
+ const now = Date.now();
81
+ const lines = [];
82
+ // Header
83
+ const siteTag = card.siteType === 'spa' ? ' [SPA]' : card.siteType === 'ssr' ? ' [SSR]' : '';
84
+ lines.push(`## 站点记忆: ${card.domain}${siteTag}`);
85
+ if (card.requiresLogin) {
86
+ lines.push('- 需要登录: 是');
87
+ }
88
+ // Task intents first (most valuable context for the agent), cap at 3
89
+ let intents = card.patterns.filter(p => p.type === 'task_intent');
90
+ if (taskHint && intents.length > 0) {
91
+ // Sort by substring relevance (CJK-compatible), then by recency
92
+ intents.sort((a, b) => {
93
+ const scoreA = relevanceScore(a.value, taskHint);
94
+ const scoreB = relevanceScore(b.value, taskHint);
95
+ if (scoreA !== scoreB)
96
+ return scoreB - scoreA;
97
+ return b.lastUsedAt - a.lastUsedAt;
98
+ });
99
+ }
100
+ else {
101
+ intents.sort((a, b) => b.lastUsedAt - a.lastUsedAt);
102
+ }
103
+ intents = intents.slice(0, 3);
104
+ if (intents.length > 0) {
105
+ lines.push('');
106
+ lines.push('### 已知任务经验(请优先按此步骤操作)');
107
+ for (const intent of intents) {
108
+ // Structured prefix to reduce prompt injection surface
109
+ const truncated = intent.value.slice(0, 800);
110
+ const line = `- 任务: ${truncated}`;
111
+ lines.push(line);
112
+ }
113
+ lines.push('');
114
+ }
115
+ let currentLength = lines.reduce((sum, l) => sum + l.length + 1, 0);
116
+ // If intents already consumed most of the budget, warn and limit
117
+ if (currentLength > maxChars - 200) {
118
+ lines.push('⚠️ 以上为历史经验,如页面结构已变化请忽略并重新探索。');
119
+ return lines.join('\n').slice(0, maxChars);
120
+ }
121
+ // Sort patterns by effective confidence
122
+ const sorted = [...card.patterns].sort((a, b) => {
123
+ const confA = a.confidence * Math.pow(0.95, (now - a.lastUsedAt) / 86400000);
124
+ const confB = b.confidence * Math.pow(0.95, (now - b.lastUsedAt) / 86400000);
125
+ return confB - confA;
126
+ });
127
+ // Global types are always included; selector/navigation_path are filtered by taskHint
128
+ const globalTypes = new Set(['login_required', 'spa_hint', 'page_structure']);
129
+ for (const p of sorted) {
130
+ if (p.type === 'task_intent')
131
+ continue; // already rendered above
132
+ // When taskHint is provided, skip non-global patterns that don't match
133
+ if (taskHint && !globalTypes.has(p.type)) {
134
+ const matchText = `${p.description} ${p.value}`;
135
+ if (relevanceScore(matchText, taskHint) === 0)
136
+ continue;
137
+ }
138
+ const effConf = p.confidence * Math.pow(0.95, (now - p.lastUsedAt) / 86400000);
139
+ const confStr = effConf.toFixed(2);
140
+ const useStr = p.useCount > 1 ? `, 用过${p.useCount}次` : '';
141
+ let line;
142
+ switch (p.type) {
143
+ case 'selector':
144
+ line = `- 选择器 \`${p.value}\` → ${p.description},可用 execute_javascript querySelector 操作 (置信度:${confStr}${useStr})`;
145
+ break;
146
+ case 'navigation_path':
147
+ line = `- 路径: ${p.value} (置信度:${confStr}${useStr})`;
148
+ break;
149
+ case 'login_required':
150
+ line = `- 需要登录 (置信度:${confStr})`;
151
+ break;
152
+ case 'spa_hint':
153
+ line = `- SPA提示: ${p.description} (置信度:${confStr}${useStr})`;
154
+ break;
155
+ case 'page_structure':
156
+ line = `- 结构: ${p.description} (置信度:${confStr}${useStr})`;
157
+ break;
158
+ default:
159
+ line = `- ${p.description} (置信度:${confStr}${useStr})`;
160
+ }
161
+ // Check char budget before adding
162
+ if (currentLength + line.length + 1 > maxChars - 80)
163
+ break; // reserve space for footer
164
+ lines.push(line);
165
+ currentLength += line.length + 1;
166
+ }
167
+ lines.push('');
168
+ lines.push('⚠️ 以上为历史经验,如页面结构已变化请忽略并重新探索。');
169
+ return lines.join('\n');
170
+ }
171
+ /** Count patterns by type for the tool response */
172
+ static countPatternTypes(patterns) {
173
+ const counts = {};
174
+ for (const p of patterns) {
175
+ counts[p.type] = (counts[p.type] || 0) + 1;
176
+ }
177
+ return counts;
178
+ }
179
+ }
180
+ //# sourceMappingURL=MemoryInjector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MemoryInjector.js","sourceRoot":"","sources":["../../src/memory/MemoryInjector.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import type { SessionRecording } from './SessionRecorder.js';
2
+ import type { SitePattern } from './types.js';
3
+ /**
4
+ * Converts human session recordings into reusable SitePattern[].
5
+ * Human-recorded patterns get higher initial confidence than agent-auto.
6
+ */
7
+ export declare class RecordingConverter {
8
+ static convert(recording: SessionRecording): SitePattern[];
9
+ /**
10
+ * Convert recording and save as knowledge card patterns.
11
+ * Returns the domain extracted from the recording.
12
+ */
13
+ static extractDomain(recording: SessionRecording): string;
14
+ private static extractPath;
15
+ }
16
+ //# sourceMappingURL=RecordingConverter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RecordingConverter.d.ts","sourceRoot":"","sources":["../../src/memory/RecordingConverter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAkB,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC7E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAG9C;;;GAGG;AACH,qBAAa,kBAAkB;IAC7B,MAAM,CAAC,OAAO,CAAC,SAAS,EAAE,gBAAgB,GAAG,WAAW,EAAE;IA+E1D;;;OAGG;IACH,MAAM,CAAC,aAAa,CAAC,SAAS,EAAE,gBAAgB,GAAG,MAAM;IAYzD,OAAO,CAAC,MAAM,CAAC,WAAW;CAO3B"}
@@ -0,0 +1,108 @@
1
+ import { MemoryCapturer } from './MemoryCapturer.js';
2
+ /**
3
+ * Converts human session recordings into reusable SitePattern[].
4
+ * Human-recorded patterns get higher initial confidence than agent-auto.
5
+ */
6
+ export class RecordingConverter {
7
+ static convert(recording) {
8
+ const patterns = [];
9
+ const now = Date.now();
10
+ const seen = new Set();
11
+ // Extract navigation path from navigate events (deduplicate consecutive identical paths)
12
+ const navEvents = recording.events.filter(e => e.type === 'navigate' && e.url);
13
+ if (navEvents.length >= 2) {
14
+ const paths = [];
15
+ for (const e of navEvents) {
16
+ try {
17
+ const p = new URL(e.url).pathname;
18
+ if (paths.length === 0 || paths[paths.length - 1] !== p)
19
+ paths.push(p);
20
+ }
21
+ catch {
22
+ const v = e.url;
23
+ if (paths.length === 0 || paths[paths.length - 1] !== v)
24
+ paths.push(v);
25
+ }
26
+ }
27
+ if (paths.length >= 2) {
28
+ const pathValue = paths.join(' → ');
29
+ if (!seen.has(pathValue)) {
30
+ seen.add(pathValue);
31
+ patterns.push({
32
+ type: 'navigation_path',
33
+ description: `人类浏览路径: ${pathValue}`,
34
+ value: pathValue,
35
+ confidence: 0.8,
36
+ useCount: 1,
37
+ lastUsedAt: now,
38
+ createdAt: now,
39
+ source: 'human_recording',
40
+ });
41
+ }
42
+ }
43
+ }
44
+ // Extract click targets as selector patterns
45
+ const clickEvents = recording.events.filter(e => e.type === 'click' && e.target);
46
+ for (const event of clickEvents) {
47
+ const key = `click:${event.target}`;
48
+ if (seen.has(key))
49
+ continue;
50
+ seen.add(key);
51
+ patterns.push({
52
+ type: 'selector',
53
+ description: `点击目标: ${event.targetLabel || event.target}`,
54
+ value: event.target,
55
+ urlPattern: this.extractPath(event.url),
56
+ confidence: 0.8,
57
+ useCount: 1,
58
+ lastUsedAt: now,
59
+ createdAt: now,
60
+ source: 'human_recording',
61
+ });
62
+ }
63
+ // Extract form inputs as page_structure patterns
64
+ const inputEvents = recording.events.filter(e => (e.type === 'type' || e.type === 'select') && e.target);
65
+ for (const event of inputEvents) {
66
+ const key = `input:${event.target}`;
67
+ if (seen.has(key))
68
+ continue;
69
+ seen.add(key);
70
+ patterns.push({
71
+ type: 'page_structure',
72
+ description: event.targetLabel ? `表单字段: ${event.targetLabel}` : `输入字段 (${event.target})`,
73
+ value: event.target,
74
+ urlPattern: this.extractPath(event.url),
75
+ confidence: 0.8,
76
+ useCount: 1,
77
+ lastUsedAt: now,
78
+ createdAt: now,
79
+ source: 'human_recording',
80
+ });
81
+ }
82
+ return patterns;
83
+ }
84
+ /**
85
+ * Convert recording and save as knowledge card patterns.
86
+ * Returns the domain extracted from the recording.
87
+ */
88
+ static extractDomain(recording) {
89
+ if (recording.domain) {
90
+ return MemoryCapturer.extractDomain(`https://${recording.domain}`);
91
+ }
92
+ // Try to extract from first navigate event
93
+ const nav = recording.events.find(e => e.type === 'navigate' && e.url);
94
+ if (nav) {
95
+ return MemoryCapturer.extractDomain(nav.url);
96
+ }
97
+ return '';
98
+ }
99
+ static extractPath(url) {
100
+ try {
101
+ return new URL(url).pathname;
102
+ }
103
+ catch {
104
+ return undefined;
105
+ }
106
+ }
107
+ }
108
+ //# sourceMappingURL=RecordingConverter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RecordingConverter.js","sourceRoot":"","sources":["../../src/memory/RecordingConverter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ import type { Page } from 'puppeteer-core';
2
+ export interface RecordingEvent {
3
+ type: 'navigate' | 'click' | 'type' | 'select' | 'scroll';
4
+ timestamp: number;
5
+ url: string;
6
+ target?: string;
7
+ targetLabel?: string;
8
+ value?: string;
9
+ }
10
+ export interface SessionRecording {
11
+ id: string;
12
+ sessionId: string;
13
+ domain: string;
14
+ events: RecordingEvent[];
15
+ startedAt: number;
16
+ endedAt?: number;
17
+ }
18
+ /**
19
+ * Records human browsing interactions via CDP event injection.
20
+ * Captures click, input, select, and scroll events.
21
+ * Password field values are never recorded.
22
+ */
23
+ export declare class SessionRecorder {
24
+ private sessionId;
25
+ private recording;
26
+ private consoleHandler;
27
+ private frameHandler;
28
+ private page;
29
+ constructor(sessionId: string);
30
+ startRecording(page: Page, recordingId: string): Promise<void>;
31
+ stopRecording(): SessionRecording | null;
32
+ isRecording(): boolean;
33
+ getStatus(): {
34
+ recording: boolean;
35
+ eventCount: number;
36
+ domain: string;
37
+ };
38
+ }
39
+ //# sourceMappingURL=SessionRecorder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SessionRecorder.d.ts","sourceRoot":"","sources":["../../src/memory/SessionRecorder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAE3C,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,UAAU,GAAG,OAAO,GAAG,MAAM,GAAG,QAAQ,GAAG,QAAQ,CAAC;IAC1D,SAAS,EAAE,MAAM,CAAC;IAClB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,cAAc,EAAE,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AA2FD;;;;GAIG;AACH,qBAAa,eAAe;IAMd,OAAO,CAAC,SAAS;IAL7B,OAAO,CAAC,SAAS,CAAiC;IAClD,OAAO,CAAC,cAAc,CAAqC;IAC3D,OAAO,CAAC,YAAY,CAAuC;IAC3D,OAAO,CAAC,IAAI,CAAqB;gBAEb,SAAS,EAAE,MAAM;IAE/B,cAAc,CAAC,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA6DpE,aAAa,IAAI,gBAAgB,GAAG,IAAI;IA2BxC,WAAW,IAAI,OAAO;IAItB,SAAS,IAAI;QAAE,SAAS,EAAE,OAAO,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE;CAOxE"}
@@ -0,0 +1,198 @@
1
+ const MAX_EVENTS = 500;
2
+ const RECORD_PREFIX = '__RECORD__:';
3
+ /** Shared JS injection script — used for both evaluateOnNewDocument and page.evaluate */
4
+ const RECORDER_SCRIPT = `(function() {
5
+ if (window.__aiRecorderInjected) return;
6
+ window.__aiRecorderInjected = true;
7
+
8
+ function getSelector(el) {
9
+ if (!el || el === document.body || el === document.documentElement) return 'body';
10
+ if (el.id) return '#' + CSS.escape(el.id);
11
+ var parts = [];
12
+ var current = el;
13
+ for (var i = 0; i < 5 && current && current !== document.body; i++) {
14
+ var tag = current.tagName.toLowerCase();
15
+ if (current.id) { parts.unshift('#' + CSS.escape(current.id)); break; }
16
+ var cls = current.className && typeof current.className === 'string'
17
+ ? '.' + current.className.trim().split(/\\s+/).slice(0, 2).map(function(c) { return CSS.escape(c); }).join('.')
18
+ : '';
19
+ parts.unshift(tag + cls);
20
+ current = current.parentElement;
21
+ }
22
+ return parts.join(' > ');
23
+ }
24
+
25
+ function getLabel(el) {
26
+ var text = (el.textContent || '').trim().slice(0, 50);
27
+ var aria = el.getAttribute('aria-label') || '';
28
+ var placeholder = el.getAttribute('placeholder') || '';
29
+ return aria || placeholder || text;
30
+ }
31
+
32
+ function isPassword(el) {
33
+ return el.tagName === 'INPUT' && el.type === 'password';
34
+ }
35
+
36
+ function send(data) {
37
+ if (!window.__aiRecorderActive) return;
38
+ console.log('${RECORD_PREFIX}' + JSON.stringify(data));
39
+ }
40
+
41
+ document.addEventListener('click', function(e) {
42
+ send({
43
+ type: 'click',
44
+ timestamp: Date.now(),
45
+ url: location.href,
46
+ target: getSelector(e.target),
47
+ targetLabel: getLabel(e.target)
48
+ });
49
+ }, true);
50
+
51
+ document.addEventListener('change', function(e) {
52
+ var el = e.target;
53
+ if (el.tagName === 'SELECT') {
54
+ send({
55
+ type: 'select',
56
+ timestamp: Date.now(),
57
+ url: location.href,
58
+ target: getSelector(el),
59
+ targetLabel: getLabel(el),
60
+ value: el.value
61
+ });
62
+ } else if (el.tagName === 'INPUT' || el.tagName === 'TEXTAREA') {
63
+ send({
64
+ type: 'type',
65
+ timestamp: Date.now(),
66
+ url: location.href,
67
+ target: getSelector(el),
68
+ targetLabel: getLabel(el),
69
+ value: isPassword(el) ? undefined : el.value
70
+ });
71
+ }
72
+ }, true);
73
+
74
+ var scrollTimer = null;
75
+ document.addEventListener('scroll', function() {
76
+ if (scrollTimer) return;
77
+ scrollTimer = setTimeout(function() {
78
+ scrollTimer = null;
79
+ send({
80
+ type: 'scroll',
81
+ timestamp: Date.now(),
82
+ url: location.href,
83
+ value: window.scrollY + ''
84
+ });
85
+ }, 500);
86
+ }, true);
87
+ })();`;
88
+ /**
89
+ * Records human browsing interactions via CDP event injection.
90
+ * Captures click, input, select, and scroll events.
91
+ * Password field values are never recorded.
92
+ */
93
+ export class SessionRecorder {
94
+ sessionId;
95
+ recording = null;
96
+ consoleHandler = null;
97
+ frameHandler = null;
98
+ page = null;
99
+ constructor(sessionId) {
100
+ this.sessionId = sessionId;
101
+ }
102
+ async startRecording(page, recordingId) {
103
+ if (this.recording) {
104
+ throw new Error('Already recording');
105
+ }
106
+ this.page = page;
107
+ let domain = '';
108
+ try {
109
+ domain = new URL(page.url()).hostname.replace(/^www\./, '');
110
+ }
111
+ catch { /* ok */ }
112
+ this.recording = {
113
+ id: recordingId,
114
+ sessionId: this.sessionId,
115
+ domain,
116
+ events: [],
117
+ startedAt: Date.now(),
118
+ };
119
+ // Inject for future navigations
120
+ await page.evaluateOnNewDocument(RECORDER_SCRIPT);
121
+ // Inject into current page + activate
122
+ await page.evaluate(RECORDER_SCRIPT).catch(() => { });
123
+ await page.evaluate('window.__aiRecorderActive = true').catch(() => { });
124
+ // Listen for console messages with our prefix
125
+ this.consoleHandler = (msg) => {
126
+ if (!this.recording)
127
+ return;
128
+ const text = typeof msg.text === 'function' ? msg.text() : String(msg);
129
+ if (!text.startsWith(RECORD_PREFIX))
130
+ return;
131
+ if (this.recording.events.length >= MAX_EVENTS)
132
+ return;
133
+ try {
134
+ const event = JSON.parse(text.slice(RECORD_PREFIX.length));
135
+ this.recording.events.push(event);
136
+ // Update domain from navigation events
137
+ if (event.type === 'navigate' || (event.url && !this.recording.domain)) {
138
+ try {
139
+ this.recording.domain = new URL(event.url).hostname.replace(/^www\./, '');
140
+ }
141
+ catch { /* ok */ }
142
+ }
143
+ }
144
+ catch { /* malformed event, skip */ }
145
+ };
146
+ page.on('console', this.consoleHandler);
147
+ // Track navigations as events
148
+ this.frameHandler = (frame) => {
149
+ if (!this.recording)
150
+ return;
151
+ if (frame === page.mainFrame()) {
152
+ if (this.recording.events.length < MAX_EVENTS) {
153
+ this.recording.events.push({
154
+ type: 'navigate',
155
+ timestamp: Date.now(),
156
+ url: frame.url(),
157
+ });
158
+ }
159
+ }
160
+ };
161
+ page.on('framenavigated', this.frameHandler);
162
+ }
163
+ stopRecording() {
164
+ if (!this.recording)
165
+ return null;
166
+ this.recording.endedAt = Date.now();
167
+ const result = this.recording;
168
+ this.recording = null;
169
+ // Deactivate injected script (it stays injected but stops sending)
170
+ if (this.page) {
171
+ this.page.evaluate('window.__aiRecorderActive = false').catch(() => { });
172
+ }
173
+ // Clean up listeners
174
+ if (this.page) {
175
+ if (this.consoleHandler) {
176
+ this.page.removeListener('console', this.consoleHandler);
177
+ }
178
+ if (this.frameHandler) {
179
+ this.page.removeListener('framenavigated', this.frameHandler);
180
+ }
181
+ }
182
+ this.consoleHandler = null;
183
+ this.frameHandler = null;
184
+ this.page = null;
185
+ return result;
186
+ }
187
+ isRecording() {
188
+ return this.recording !== null;
189
+ }
190
+ getStatus() {
191
+ return {
192
+ recording: this.recording !== null,
193
+ eventCount: this.recording?.events.length || 0,
194
+ domain: this.recording?.domain || '',
195
+ };
196
+ }
197
+ }
198
+ //# sourceMappingURL=SessionRecorder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SessionRecorder.js","sourceRoot":"","sources":["../../src/memory/SessionRecorder.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ export { KnowledgeCardStore, isSafeDomain } from './KnowledgeCardStore.js';
2
+ export { MemoryCapturer, mergePatterns } from './MemoryCapturer.js';
3
+ export { MemoryInjector } from './MemoryInjector.js';
4
+ export { SessionRecorder } from './SessionRecorder.js';
5
+ export { RecordingConverter } from './RecordingConverter.js';
6
+ export type { SitePattern, KnowledgeCard, CardIndexEntry, CardIndex } from './types.js';
7
+ export type { RecordingEvent, SessionRecording } from './SessionRecorder.js';
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/memory/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAC3E,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpE,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACxF,YAAY,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC"}
@@ -0,0 +1,6 @@
1
+ export { KnowledgeCardStore, isSafeDomain } from './KnowledgeCardStore.js';
2
+ export { MemoryCapturer, mergePatterns } from './MemoryCapturer.js';
3
+ export { MemoryInjector } from './MemoryInjector.js';
4
+ export { SessionRecorder } from './SessionRecorder.js';
5
+ export { RecordingConverter } from './RecordingConverter.js';
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/memory/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAC3E,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpE,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC"}
@@ -0,0 +1,39 @@
1
+ /** Single site pattern learned from browsing */
2
+ export interface SitePattern {
3
+ type: 'selector' | 'navigation_path' | 'login_required' | 'spa_hint' | 'page_structure' | 'task_intent';
4
+ description: string;
5
+ value: string;
6
+ urlPattern?: string;
7
+ confidence: number;
8
+ useCount: number;
9
+ lastUsedAt: number;
10
+ createdAt: number;
11
+ source: 'agent_auto' | 'human_recording' | 'manual';
12
+ }
13
+ /** Knowledge card — all memory for a single domain */
14
+ export interface KnowledgeCard {
15
+ domain: string;
16
+ version: number;
17
+ patterns: SitePattern[];
18
+ siteType?: 'spa' | 'ssr' | 'unknown';
19
+ requiresLogin?: boolean;
20
+ createdAt: number;
21
+ updatedAt: number;
22
+ }
23
+ /** Lightweight index entry, kept in memory */
24
+ export interface CardIndexEntry {
25
+ domain: string;
26
+ version: number;
27
+ patternCount: number;
28
+ siteType?: string;
29
+ requiresLogin?: boolean;
30
+ topPatterns: string[];
31
+ lastUsedAt: number;
32
+ updatedAt: number;
33
+ }
34
+ /** Full index structure — index.json */
35
+ export interface CardIndex {
36
+ entries: Record<string, CardIndexEntry>;
37
+ updatedAt: number;
38
+ }
39
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/memory/types.ts"],"names":[],"mappings":"AAAA,gDAAgD;AAChD,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,UAAU,GAAG,iBAAiB,GAAG,gBAAgB,GAAG,UAAU,GAAG,gBAAgB,GAAG,aAAa,CAAC;IACxG,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,YAAY,GAAG,iBAAiB,GAAG,QAAQ,CAAC;CACrD;AAED,sDAAsD;AACtD,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,QAAQ,CAAC,EAAE,KAAK,GAAG,KAAK,GAAG,SAAS,CAAC;IACrC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,8CAA8C;AAC9C,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,wCAAwC;AACxC,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IACxC,SAAS,EAAE,MAAM,CAAC;CACnB"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/memory/types.ts"],"names":[],"mappings":""}