imperium-crawl 1.5.3 → 2.1.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 (125) hide show
  1. package/README.md +49 -34
  2. package/dist/constants.d.ts +2 -1
  3. package/dist/constants.d.ts.map +1 -1
  4. package/dist/constants.js +3 -1
  5. package/dist/constants.js.map +1 -1
  6. package/dist/network/interceptor.d.ts +19 -0
  7. package/dist/network/interceptor.d.ts.map +1 -0
  8. package/dist/network/interceptor.js +82 -0
  9. package/dist/network/interceptor.js.map +1 -0
  10. package/dist/network/types.d.ts +27 -0
  11. package/dist/network/types.d.ts.map +1 -0
  12. package/dist/network/types.js +2 -0
  13. package/dist/network/types.js.map +1 -0
  14. package/dist/recipes/index.d.ts.map +1 -1
  15. package/dist/recipes/index.js +6 -0
  16. package/dist/recipes/index.js.map +1 -1
  17. package/dist/recipes/influencer-competitor-spy.json +14 -0
  18. package/dist/recipes/influencer-hashtag-scout.json +14 -0
  19. package/dist/recipes/influencer-niche-discovery.json +14 -0
  20. package/dist/security/action-policy.d.ts +26 -0
  21. package/dist/security/action-policy.d.ts.map +1 -0
  22. package/dist/security/action-policy.js +136 -0
  23. package/dist/security/action-policy.js.map +1 -0
  24. package/dist/security/auth-vault.d.ts +49 -0
  25. package/dist/security/auth-vault.d.ts.map +1 -0
  26. package/dist/security/auth-vault.js +133 -0
  27. package/dist/security/auth-vault.js.map +1 -0
  28. package/dist/security/domain-filter.d.ts +19 -0
  29. package/dist/security/domain-filter.d.ts.map +1 -0
  30. package/dist/security/domain-filter.js +114 -0
  31. package/dist/security/domain-filter.js.map +1 -0
  32. package/dist/security/types.d.ts +19 -0
  33. package/dist/security/types.d.ts.map +1 -0
  34. package/dist/security/types.js +2 -0
  35. package/dist/security/types.js.map +1 -0
  36. package/dist/sessions/encryption.d.ts +37 -0
  37. package/dist/sessions/encryption.d.ts.map +1 -0
  38. package/dist/sessions/encryption.js +108 -0
  39. package/dist/sessions/encryption.js.map +1 -0
  40. package/dist/sessions/index.d.ts +1 -0
  41. package/dist/sessions/index.d.ts.map +1 -1
  42. package/dist/sessions/index.js +1 -0
  43. package/dist/sessions/index.js.map +1 -1
  44. package/dist/sessions/manager.d.ts +3 -0
  45. package/dist/sessions/manager.d.ts.map +1 -1
  46. package/dist/sessions/manager.js +28 -2
  47. package/dist/sessions/manager.js.map +1 -1
  48. package/dist/skills/manager.d.ts +11 -2
  49. package/dist/skills/manager.d.ts.map +1 -1
  50. package/dist/skills/manager.js.map +1 -1
  51. package/dist/snapshot/annotator.d.ts +21 -0
  52. package/dist/snapshot/annotator.d.ts.map +1 -0
  53. package/dist/snapshot/annotator.js +152 -0
  54. package/dist/snapshot/annotator.js.map +1 -0
  55. package/dist/snapshot/boundary.d.ts +7 -0
  56. package/dist/snapshot/boundary.d.ts.map +1 -0
  57. package/dist/snapshot/boundary.js +12 -0
  58. package/dist/snapshot/boundary.js.map +1 -0
  59. package/dist/snapshot/differ.d.ts +40 -0
  60. package/dist/snapshot/differ.d.ts.map +1 -0
  61. package/dist/snapshot/differ.js +194 -0
  62. package/dist/snapshot/differ.js.map +1 -0
  63. package/dist/snapshot/extractor.d.ts +27 -0
  64. package/dist/snapshot/extractor.d.ts.map +1 -0
  65. package/dist/snapshot/extractor.js +265 -0
  66. package/dist/snapshot/extractor.js.map +1 -0
  67. package/dist/snapshot/index.d.ts +8 -0
  68. package/dist/snapshot/index.d.ts.map +1 -0
  69. package/dist/snapshot/index.js +6 -0
  70. package/dist/snapshot/index.js.map +1 -0
  71. package/dist/snapshot/store.d.ts +28 -0
  72. package/dist/snapshot/store.d.ts.map +1 -0
  73. package/dist/snapshot/store.js +65 -0
  74. package/dist/snapshot/store.js.map +1 -0
  75. package/dist/snapshot/types.d.ts +42 -0
  76. package/dist/snapshot/types.d.ts.map +1 -0
  77. package/dist/snapshot/types.js +2 -0
  78. package/dist/snapshot/types.js.map +1 -0
  79. package/dist/social/ai-fallback.d.ts +22 -0
  80. package/dist/social/ai-fallback.d.ts.map +1 -0
  81. package/dist/social/ai-fallback.js +137 -0
  82. package/dist/social/ai-fallback.js.map +1 -0
  83. package/dist/social/parsers.d.ts +28 -0
  84. package/dist/social/parsers.d.ts.map +1 -0
  85. package/dist/social/parsers.js +146 -0
  86. package/dist/social/parsers.js.map +1 -0
  87. package/dist/social/types.d.ts +55 -0
  88. package/dist/social/types.d.ts.map +1 -0
  89. package/dist/social/types.js +5 -0
  90. package/dist/social/types.js.map +1 -0
  91. package/dist/social/whisper.d.ts +29 -0
  92. package/dist/social/whisper.d.ts.map +1 -0
  93. package/dist/social/whisper.js +88 -0
  94. package/dist/social/whisper.js.map +1 -0
  95. package/dist/tools/index.d.ts.map +1 -1
  96. package/dist/tools/index.js +7 -0
  97. package/dist/tools/index.js.map +1 -1
  98. package/dist/tools/interact.d.ts +194 -5
  99. package/dist/tools/interact.d.ts.map +1 -1
  100. package/dist/tools/interact.js +355 -20
  101. package/dist/tools/interact.js.map +1 -1
  102. package/dist/tools/manifest.d.ts.map +1 -1
  103. package/dist/tools/manifest.js +9 -0
  104. package/dist/tools/manifest.js.map +1 -1
  105. package/dist/tools/reddit.d.ts +36 -0
  106. package/dist/tools/reddit.d.ts.map +1 -0
  107. package/dist/tools/reddit.js +190 -0
  108. package/dist/tools/reddit.js.map +1 -0
  109. package/dist/tools/run-skill.d.ts +18 -0
  110. package/dist/tools/run-skill.d.ts.map +1 -1
  111. package/dist/tools/run-skill.js +681 -0
  112. package/dist/tools/run-skill.js.map +1 -1
  113. package/dist/tools/snapshot.d.ts +53 -0
  114. package/dist/tools/snapshot.d.ts.map +1 -0
  115. package/dist/tools/snapshot.js +160 -0
  116. package/dist/tools/snapshot.js.map +1 -0
  117. package/dist/tools/tiktok.d.ts +30 -0
  118. package/dist/tools/tiktok.d.ts.map +1 -0
  119. package/dist/tools/tiktok.js +246 -0
  120. package/dist/tools/tiktok.js.map +1 -0
  121. package/dist/tools/youtube.d.ts +33 -0
  122. package/dist/tools/youtube.d.ts.map +1 -0
  123. package/dist/tools/youtube.js +489 -0
  124. package/dist/tools/youtube.js.map +1 -0
  125. package/package.json +1 -1
@@ -0,0 +1,265 @@
1
+ /**
2
+ * Snapshot Extractor — Core engine for ARIA-based page snapshots.
3
+ *
4
+ * Uses Playwright's locator.ariaSnapshot() for the ARIA tree,
5
+ * then post-processes to add [ref=eN] tags for interactive elements.
6
+ * Optionally detects cursor-interactive elements without ARIA roles.
7
+ *
8
+ * Inspired by agent-browser's approach but with:
9
+ * - Per-snapshot ref counter (thread-safe, no global state)
10
+ * - Hybrid cursor detection
11
+ * - Semantic locators (getByRole) for robust element targeting
12
+ */
13
+ // ── Role classification ──
14
+ const INTERACTIVE_ROLES = new Set([
15
+ "button", "link", "textbox", "checkbox", "radio",
16
+ "combobox", "listbox", "menuitem", "option", "searchbox",
17
+ "slider", "spinbutton", "switch", "tab", "treeitem",
18
+ ]);
19
+ const CONTENT_ROLES = new Set([
20
+ "heading", "cell", "article", "region", "navigation",
21
+ "img", "figure", "blockquote", "code",
22
+ ]);
23
+ const STRUCTURAL_ROLES = new Set([
24
+ "generic", "group", "list", "table", "row", "rowgroup",
25
+ "columnheader", "rowheader", "presentation", "none",
26
+ "separator", "toolbar", "banner", "contentinfo", "main",
27
+ "complementary", "form",
28
+ ]);
29
+ /**
30
+ * Parse a single line from Playwright's ariaSnapshot output.
31
+ * Format: " - role \"name\" [attributes]" or " - role \"name\":"
32
+ * Also handles: " - text: content here"
33
+ */
34
+ function parseLine(line) {
35
+ // Count leading spaces for indentation
36
+ const stripped = line.replace(/^\s*/, "");
37
+ const indent = line.length - stripped.length;
38
+ // Must start with "- "
39
+ if (!stripped.startsWith("- "))
40
+ return null;
41
+ const content = stripped.slice(2);
42
+ // Match: role "name" or role "name": or just role:
43
+ const roleNameMatch = content.match(/^(\w+)\s+"([^"]*)"(.*)$/);
44
+ if (roleNameMatch) {
45
+ return {
46
+ indent,
47
+ role: roleNameMatch[1],
48
+ name: roleNameMatch[2],
49
+ rawLine: line,
50
+ attributes: roleNameMatch[3].trim(),
51
+ };
52
+ }
53
+ // Match: role (no name) — e.g. "- list:" or "- generic"
54
+ const roleOnlyMatch = content.match(/^(\w+):?\s*$/);
55
+ if (roleOnlyMatch) {
56
+ return {
57
+ indent,
58
+ role: roleOnlyMatch[1],
59
+ name: "",
60
+ rawLine: line,
61
+ attributes: "",
62
+ };
63
+ }
64
+ // Text node: "- text: some content"
65
+ if (content.startsWith("text:")) {
66
+ return {
67
+ indent,
68
+ role: "text",
69
+ name: content.slice(5).trim(),
70
+ rawLine: line,
71
+ attributes: "",
72
+ };
73
+ }
74
+ // Plain text line (e.g. "- Some text content")
75
+ return {
76
+ indent,
77
+ role: "text",
78
+ name: content.replace(/:$/, "").trim(),
79
+ rawLine: line,
80
+ attributes: "",
81
+ };
82
+ }
83
+ // ── Role+Name dedup tracker ──
84
+ class RoleNameTracker {
85
+ counts = new Map();
86
+ assigned = new Map();
87
+ /** First pass: count occurrences */
88
+ count(role, name) {
89
+ const key = `${role}:::${name}`;
90
+ this.counts.set(key, (this.counts.get(key) ?? 0) + 1);
91
+ }
92
+ /** Second pass: get nth index (only if duplicates exist) */
93
+ getNth(role, name) {
94
+ const key = `${role}:::${name}`;
95
+ const total = this.counts.get(key) ?? 1;
96
+ if (total <= 1)
97
+ return undefined;
98
+ const idx = this.assigned.get(key) ?? 0;
99
+ this.assigned.set(key, idx + 1);
100
+ return idx;
101
+ }
102
+ }
103
+ // ── Selector builder ──
104
+ function buildSelector(role, name, nth) {
105
+ const nameOpt = name ? `, { name: '${name.replace(/'/g, "\\'")}', exact: true }` : "";
106
+ const base = `getByRole('${role}'${nameOpt})`;
107
+ return nth !== undefined ? `${base}.nth(${nth})` : base;
108
+ }
109
+ async function findCursorInteractiveElements(page, scopeSelector) {
110
+ return page.evaluate((scope) => {
111
+ const root = scope
112
+ ? document.querySelector(scope) ?? document.body
113
+ : document.body;
114
+ const results = [];
115
+ const seen = new Set();
116
+ const walker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT);
117
+ let node = walker.nextNode();
118
+ while (node) {
119
+ if (!seen.has(node)) {
120
+ const style = getComputedStyle(node);
121
+ const hasClick = node.hasAttribute("onclick") ||
122
+ node.hasAttribute("tabindex") ||
123
+ style.cursor === "pointer";
124
+ const role = node.getAttribute("role");
125
+ const tag = node.tagName.toLowerCase();
126
+ // Only capture elements that LOOK interactive but have no ARIA role
127
+ if (hasClick && !role && !["a", "button", "input", "select", "textarea"].includes(tag)) {
128
+ results.push({
129
+ role: "generic",
130
+ name: node.getAttribute("aria-label") ||
131
+ (node.textContent ?? "").trim().slice(0, 80) || "",
132
+ tagName: tag,
133
+ ariaLabel: node.getAttribute("aria-label") ?? "",
134
+ });
135
+ seen.add(node);
136
+ }
137
+ }
138
+ node = walker.nextNode();
139
+ }
140
+ return results;
141
+ }, scopeSelector);
142
+ }
143
+ // ── Main export ──
144
+ /**
145
+ * Generate an enhanced ARIA snapshot with ref annotations.
146
+ *
147
+ * Flow:
148
+ * 1. Get ARIA tree from Playwright's ariaSnapshot()
149
+ * 2. Parse each line, identify roles
150
+ * 3. Two-pass ref assignment (count first for dedup, then assign)
151
+ * 4. Optionally detect cursor-interactive elements
152
+ * 5. Build RefMap and annotated tree string
153
+ */
154
+ export async function getEnhancedSnapshot(page, options = {}) {
155
+ const { interactive = true, cursor = false, compact = true, selector, } = options;
156
+ // Get the ARIA tree from Playwright
157
+ const locator = selector
158
+ ? page.locator(selector)
159
+ : page.locator("body");
160
+ // ariaSnapshot() exists in playwright-core 1.49+ but types may not be in rebrowser-playwright
161
+ const ariaTree = await locator.ariaSnapshot();
162
+ const lines = ariaTree.split("\n");
163
+ const parsed = lines.map(parseLine);
164
+ // ── First pass: count role+name for dedup ──
165
+ const tracker = new RoleNameTracker();
166
+ for (const p of parsed) {
167
+ if (!p)
168
+ continue;
169
+ if (p.role === "text")
170
+ continue;
171
+ if (INTERACTIVE_ROLES.has(p.role) || CONTENT_ROLES.has(p.role)) {
172
+ tracker.count(p.role, p.name);
173
+ }
174
+ }
175
+ // ── Second pass: assign refs ──
176
+ let refCounter = 0;
177
+ const refs = {};
178
+ const annotatedLines = [];
179
+ let totalElements = 0;
180
+ let interactiveCount = 0;
181
+ let contentCount = 0;
182
+ for (let i = 0; i < lines.length; i++) {
183
+ const p = parsed[i];
184
+ if (!p) {
185
+ // Keep raw lines that didn't parse (empty lines, etc.)
186
+ if (lines[i].trim())
187
+ annotatedLines.push(lines[i]);
188
+ continue;
189
+ }
190
+ totalElements++;
191
+ const isInteractive = INTERACTIVE_ROLES.has(p.role);
192
+ const isContent = CONTENT_ROLES.has(p.role);
193
+ const isStructural = STRUCTURAL_ROLES.has(p.role);
194
+ const isText = p.role === "text";
195
+ // Decide whether to assign a ref
196
+ let ref;
197
+ if (isInteractive) {
198
+ interactiveCount++;
199
+ ref = `e${++refCounter}`;
200
+ const nth = tracker.getNth(p.role, p.name);
201
+ refs[ref] = {
202
+ selector: buildSelector(p.role, p.name, nth),
203
+ role: p.role,
204
+ name: p.name,
205
+ ...(nth !== undefined && { nth }),
206
+ };
207
+ }
208
+ else if (isContent && !interactive) {
209
+ contentCount++;
210
+ ref = `e${++refCounter}`;
211
+ const nth = tracker.getNth(p.role, p.name);
212
+ refs[ref] = {
213
+ selector: buildSelector(p.role, p.name, nth),
214
+ role: p.role,
215
+ name: p.name,
216
+ ...(nth !== undefined && { nth }),
217
+ };
218
+ }
219
+ // Build annotated line
220
+ if (compact && isStructural && !ref) {
221
+ // In compact mode, skip structural elements without refs
222
+ // BUT keep them if they have children (indicated by trailing ":")
223
+ if (!p.rawLine.trimEnd().endsWith(":"))
224
+ continue;
225
+ }
226
+ if (ref) {
227
+ // Insert [ref=eN] after the role
228
+ const indent = " ".repeat(p.indent);
229
+ const nameStr = p.name ? ` "${p.name}"` : "";
230
+ const attrStr = p.attributes ? ` ${p.attributes}` : "";
231
+ annotatedLines.push(`${indent}- ${p.role}${nameStr} [ref=${ref}]${attrStr}`);
232
+ }
233
+ else if (isText || !compact || !isStructural) {
234
+ annotatedLines.push(p.rawLine);
235
+ }
236
+ }
237
+ // ── Cursor-interactive elements (optional) ──
238
+ if (cursor) {
239
+ const cursorElements = await findCursorInteractiveElements(page, selector);
240
+ for (const el of cursorElements) {
241
+ const ref = `e${++refCounter}`;
242
+ interactiveCount++;
243
+ // For cursor elements, build a CSS-based selector as fallback
244
+ const nameStr = el.ariaLabel || el.name;
245
+ refs[ref] = {
246
+ selector: nameStr
247
+ ? `getByRole('${el.role}', { name: '${nameStr.replace(/'/g, "\\'")}', exact: true })`
248
+ : `locator('${el.tagName}')`,
249
+ role: el.role || "generic",
250
+ name: nameStr,
251
+ };
252
+ annotatedLines.push(`- ${el.role || "generic"} "${nameStr}" [ref=${ref}] (cursor-interactive)`);
253
+ }
254
+ }
255
+ return {
256
+ tree: annotatedLines.join("\n"),
257
+ refs,
258
+ stats: {
259
+ totalElements,
260
+ interactiveElements: interactiveCount,
261
+ contentElements: contentCount,
262
+ },
263
+ };
264
+ }
265
+ //# sourceMappingURL=extractor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extractor.js","sourceRoot":"","sources":["../../src/snapshot/extractor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ export type { RefMap, RefEntry, EnhancedSnapshot, SnapshotOptions } from "./types.js";
2
+ export { getEnhancedSnapshot } from "./extractor.js";
3
+ export { getSnapshotStore, resetSnapshotStore } from "./store.js";
4
+ export { annotateScreenshot } from "./annotator.js";
5
+ export { generateBoundary, wrapContent } from "./boundary.js";
6
+ export { diffSnapshots, diffScreenshots } from "./differ.js";
7
+ export type { TextDiffResult, ImageDiffResult, ImageDiffOptions } from "./differ.js";
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/snapshot/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,MAAM,EAAE,QAAQ,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AACtF,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAClE,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC9D,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC7D,YAAY,EAAE,cAAc,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,6 @@
1
+ export { getEnhancedSnapshot } from "./extractor.js";
2
+ export { getSnapshotStore, resetSnapshotStore } from "./store.js";
3
+ export { annotateScreenshot } from "./annotator.js";
4
+ export { generateBoundary, wrapContent } from "./boundary.js";
5
+ export { diffSnapshots, diffScreenshots } from "./differ.js";
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/snapshot/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAClE,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC9D,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * SnapshotStore — In-memory ref storage with LRU eviction.
3
+ *
4
+ * Stores RefMaps keyed by session_id (or auto-generated snapshot IDs).
5
+ * Refs are ephemeral — they exist only in memory and are invalidated
6
+ * when a new snapshot is taken for the same session.
7
+ */
8
+ import type { RefMap, RefEntry } from "./types.js";
9
+ declare class SnapshotStore {
10
+ private store;
11
+ /** Save a snapshot's refs, evicting oldest if at capacity */
12
+ save(id: string, refs: RefMap, url: string): void;
13
+ /** Resolve a ref string (e.g. "e5" or "@e5") to its locator info */
14
+ resolveRef(id: string, refString: string): RefEntry | null;
15
+ /** Get all refs for a snapshot */
16
+ getRefs(id: string): RefMap | null;
17
+ /** Invalidate a specific snapshot */
18
+ invalidate(id: string): void;
19
+ /** Clear all stored snapshots */
20
+ clear(): void;
21
+ /** Number of stored snapshots */
22
+ get size(): number;
23
+ }
24
+ export declare function getSnapshotStore(): SnapshotStore;
25
+ /** Reset singleton (for testing) */
26
+ export declare function resetSnapshotStore(): void;
27
+ export {};
28
+ //# sourceMappingURL=store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/snapshot/store.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AASnD,cAAM,aAAa;IACjB,OAAO,CAAC,KAAK,CAAqC;IAElD,6DAA6D;IAC7D,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI;IAiBjD,oEAAoE;IACpE,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI;IAS1D,kCAAkC;IAClC,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAIlC,qCAAqC;IACrC,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAI5B,iCAAiC;IACjC,KAAK,IAAI,IAAI;IAIb,iCAAiC;IACjC,IAAI,IAAI,IAAI,MAAM,CAEjB;CACF;AAMD,wBAAgB,gBAAgB,IAAI,aAAa,CAGhD;AAED,oCAAoC;AACpC,wBAAgB,kBAAkB,IAAI,IAAI,CAEzC"}
@@ -0,0 +1,65 @@
1
+ /**
2
+ * SnapshotStore — In-memory ref storage with LRU eviction.
3
+ *
4
+ * Stores RefMaps keyed by session_id (or auto-generated snapshot IDs).
5
+ * Refs are ephemeral — they exist only in memory and are invalidated
6
+ * when a new snapshot is taken for the same session.
7
+ */
8
+ import { MAX_STORED_SNAPSHOTS } from "../constants.js";
9
+ class SnapshotStore {
10
+ store = new Map();
11
+ /** Save a snapshot's refs, evicting oldest if at capacity */
12
+ save(id, refs, url) {
13
+ // Evict oldest if at capacity (LRU)
14
+ if (this.store.size >= MAX_STORED_SNAPSHOTS && !this.store.has(id)) {
15
+ let oldestKey;
16
+ let oldestTime = Infinity;
17
+ for (const [key, val] of this.store) {
18
+ if (val.timestamp < oldestTime) {
19
+ oldestTime = val.timestamp;
20
+ oldestKey = key;
21
+ }
22
+ }
23
+ if (oldestKey)
24
+ this.store.delete(oldestKey);
25
+ }
26
+ this.store.set(id, { refs, timestamp: Date.now(), url });
27
+ }
28
+ /** Resolve a ref string (e.g. "e5" or "@e5") to its locator info */
29
+ resolveRef(id, refString) {
30
+ const snapshot = this.store.get(id);
31
+ if (!snapshot)
32
+ return null;
33
+ // Strip leading @ if present
34
+ const ref = refString.startsWith("@") ? refString.slice(1) : refString;
35
+ return snapshot.refs[ref] ?? null;
36
+ }
37
+ /** Get all refs for a snapshot */
38
+ getRefs(id) {
39
+ return this.store.get(id)?.refs ?? null;
40
+ }
41
+ /** Invalidate a specific snapshot */
42
+ invalidate(id) {
43
+ this.store.delete(id);
44
+ }
45
+ /** Clear all stored snapshots */
46
+ clear() {
47
+ this.store.clear();
48
+ }
49
+ /** Number of stored snapshots */
50
+ get size() {
51
+ return this.store.size;
52
+ }
53
+ }
54
+ // ── Singleton ──
55
+ let instance = null;
56
+ export function getSnapshotStore() {
57
+ if (!instance)
58
+ instance = new SnapshotStore();
59
+ return instance;
60
+ }
61
+ /** Reset singleton (for testing) */
62
+ export function resetSnapshotStore() {
63
+ instance = null;
64
+ }
65
+ //# sourceMappingURL=store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/snapshot/store.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAQvD,MAAM,aAAa;IACT,KAAK,GAAG,IAAI,GAAG,EAA0B,CAAC;IAElD,6DAA6D;IAC7D,IAAI,CAAC,EAAU,EAAE,IAAY,EAAE,GAAW;QACxC,oCAAoC;QACpC,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,IAAI,oBAAoB,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;YACnE,IAAI,SAA6B,CAAC;YAClC,IAAI,UAAU,GAAG,QAAQ,CAAC;YAC1B,KAAK,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;gBACpC,IAAI,GAAG,CAAC,SAAS,GAAG,UAAU,EAAE,CAAC;oBAC/B,UAAU,GAAG,GAAG,CAAC,SAAS,CAAC;oBAC3B,SAAS,GAAG,GAAG,CAAC;gBAClB,CAAC;YACH,CAAC;YACD,IAAI,SAAS;gBAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAC9C,CAAC;QAED,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC;IAC3D,CAAC;IAED,oEAAoE;IACpE,UAAU,CAAC,EAAU,EAAE,SAAiB;QACtC,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACpC,IAAI,CAAC,QAAQ;YAAE,OAAO,IAAI,CAAC;QAE3B,6BAA6B;QAC7B,MAAM,GAAG,GAAG,SAAS,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QACvE,OAAO,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC;IACpC,CAAC;IAED,kCAAkC;IAClC,OAAO,CAAC,EAAU;QAChB,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,IAAI,IAAI,IAAI,CAAC;IAC1C,CAAC;IAED,qCAAqC;IACrC,UAAU,CAAC,EAAU;QACnB,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IACxB,CAAC;IAED,iCAAiC;IACjC,KAAK;QACH,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;IACrB,CAAC;IAED,iCAAiC;IACjC,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;IACzB,CAAC;CACF;AAED,kBAAkB;AAElB,IAAI,QAAQ,GAAyB,IAAI,CAAC;AAE1C,MAAM,UAAU,gBAAgB;IAC9B,IAAI,CAAC,QAAQ;QAAE,QAAQ,GAAG,IAAI,aAAa,EAAE,CAAC;IAC9C,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,oCAAoC;AACpC,MAAM,UAAU,kBAAkB;IAChC,QAAQ,GAAG,IAAI,CAAC;AAClB,CAAC"}
@@ -0,0 +1,42 @@
1
+ /** Semantic locator info resolved from a ref */
2
+ export interface RefEntry {
3
+ /** Playwright semantic locator string, e.g. getByRole('button', { name: 'Submit', exact: true }) */
4
+ selector: string;
5
+ /** ARIA role */
6
+ role: string;
7
+ /** Accessible name */
8
+ name: string;
9
+ /** nth index when multiple elements share same role+name */
10
+ nth?: number;
11
+ }
12
+ /** Map of ref IDs (e.g. "e1", "e2") to their locator info */
13
+ export interface RefMap {
14
+ [ref: string]: RefEntry;
15
+ }
16
+ /** Result from getEnhancedSnapshot */
17
+ export interface EnhancedSnapshot {
18
+ /** ARIA tree with [ref=eN] annotations */
19
+ tree: string;
20
+ /** Ref-to-locator mapping */
21
+ refs: RefMap;
22
+ /** Stats about the snapshot */
23
+ stats: {
24
+ totalElements: number;
25
+ interactiveElements: number;
26
+ contentElements: number;
27
+ };
28
+ }
29
+ /** Options for snapshot extraction */
30
+ export interface SnapshotOptions {
31
+ /** Only include interactive elements (default: true) */
32
+ interactive?: boolean;
33
+ /** Also detect cursor:pointer/onclick elements without ARIA roles (default: false) */
34
+ cursor?: boolean;
35
+ /** Maximum depth of ARIA tree to include */
36
+ maxDepth?: number;
37
+ /** Filter out structural elements without refs (default: true) */
38
+ compact?: boolean;
39
+ /** CSS selector to scope the snapshot to a subtree */
40
+ selector?: string;
41
+ }
42
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/snapshot/types.ts"],"names":[],"mappings":"AAAA,gDAAgD;AAChD,MAAM,WAAW,QAAQ;IACvB,oGAAoG;IACpG,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,sBAAsB;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,4DAA4D;IAC5D,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,6DAA6D;AAC7D,MAAM,WAAW,MAAM;IACrB,CAAC,GAAG,EAAE,MAAM,GAAG,QAAQ,CAAC;CACzB;AAED,sCAAsC;AACtC,MAAM,WAAW,gBAAgB;IAC/B,0CAA0C;IAC1C,IAAI,EAAE,MAAM,CAAC;IACb,6BAA6B;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,+BAA+B;IAC/B,KAAK,EAAE;QACL,aAAa,EAAE,MAAM,CAAC;QACtB,mBAAmB,EAAE,MAAM,CAAC;QAC5B,eAAe,EAAE,MAAM,CAAC;KACzB,CAAC;CACH;AAED,sCAAsC;AACtC,MAAM,WAAW,eAAe;IAC9B,wDAAwD;IACxD,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,sFAAsF;IACtF,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,4CAA4C;IAC5C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kEAAkE;IAClE,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,sDAAsD;IACtD,QAAQ,CAAC,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/snapshot/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * AI fallback for social media tools.
3
+ *
4
+ * When structured parsers fail (ytInitialData, .json API, rehydration data),
5
+ * this uses the existing LLM infrastructure to extract data from ARIA trees
6
+ * or raw HTML markdown.
7
+ *
8
+ * Structured extraction = primary (free, fast).
9
+ * AI fallback = backup (costs tokens, slower, but always works).
10
+ */
11
+ import type { Page } from "rebrowser-playwright";
12
+ export type SocialAction = "youtube:search" | "youtube:video" | "youtube:comments" | "youtube:transcript" | "youtube:channel" | "reddit:search" | "reddit:posts" | "reddit:comments" | "reddit:subreddit";
13
+ export declare function socialAiFallback<T>(opts: {
14
+ action: SocialAction;
15
+ page?: Page;
16
+ url?: string;
17
+ maxTokens?: number;
18
+ }): Promise<{
19
+ data: T;
20
+ model: string;
21
+ } | null>;
22
+ //# sourceMappingURL=ai-fallback.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai-fallback.d.ts","sourceRoot":"","sources":["../../src/social/ai-fallback.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC;AAWjD,MAAM,MAAM,YAAY,GACpB,gBAAgB,GAAG,eAAe,GAAG,kBAAkB,GACvD,oBAAoB,GAAG,iBAAiB,GACxC,eAAe,GAAG,cAAc,GAAG,iBAAiB,GAAG,kBAAkB,CAAC;AAkB9E,wBAAsB,gBAAgB,CAAC,CAAC,EAAE,IAAI,EAAE;IAC9C,MAAM,EAAE,YAAY,CAAC;IACrB,IAAI,CAAC,EAAE,IAAI,CAAC;IACZ,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,GAAG,OAAO,CAAC;IAAE,IAAI,EAAE,CAAC,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAC,CA6B7C"}
@@ -0,0 +1,137 @@
1
+ /**
2
+ * AI fallback for social media tools.
3
+ *
4
+ * When structured parsers fail (ytInitialData, .json API, rehydration data),
5
+ * this uses the existing LLM infrastructure to extract data from ARIA trees
6
+ * or raw HTML markdown.
7
+ *
8
+ * Structured extraction = primary (free, fast).
9
+ * AI fallback = backup (costs tokens, slower, but always works).
10
+ */
11
+ import { hasLLMConfigured, createLLMClient } from "../llm/index.js";
12
+ import { extractWithLLM } from "../llm/extractor.js";
13
+ import { getEnhancedSnapshot } from "../snapshot/extractor.js";
14
+ import { smartFetch } from "../stealth/index.js";
15
+ import { htmlToMarkdown } from "../utils/markdown.js";
16
+ import { parseCompactNumber } from "./parsers.js";
17
+ // ── Schemas for LLM extraction ──
18
+ const SOCIAL_SCHEMAS = {
19
+ "youtube:search": `{ "videos": [{ "id": "video ID", "title": "string", "url": "full URL", "duration": "M:SS", "views": "view count text", "author": "channel name", "author_url": "channel URL", "published": "relative time" }] }`,
20
+ "youtube:video": `{ "id": "video ID", "title": "string", "url": "full URL", "views": "view count text", "likes": "like count text", "author": "channel name", "author_url": "channel URL", "published": "date text", "description": "first 2000 chars" }`,
21
+ "youtube:comments": `{ "comments": [{ "author": "string", "text": "comment text", "likes": "like count", "published": "relative time" }] }`,
22
+ "youtube:transcript": `{ "segments": [{ "start": "timestamp M:SS", "text": "string" }] }`,
23
+ "youtube:channel": `{ "name": "channel name", "url": "channel URL", "description": "about text", "subscribers": "subscriber count text", "verified": true/false }`,
24
+ "reddit:search": `{ "posts": [{ "title": "string", "url": "permalink", "author": "string", "score": "number or text", "comments_count": "number", "subreddit": "string", "published": "relative time" }] }`,
25
+ "reddit:posts": `{ "posts": [{ "title": "string", "url": "permalink", "author": "string", "score": "number or text", "comments_count": "number", "published": "relative time", "flair": "flair text or null" }] }`,
26
+ "reddit:comments": `{ "post": { "title": "string", "author": "string", "score": "number" }, "comments": [{ "author": "string", "text": "comment body", "score": "number", "published": "relative time" }] }`,
27
+ "reddit:subreddit": `{ "name": "subreddit name", "description": "description text", "subscribers": "subscriber count text", "created": "creation date" }`,
28
+ };
29
+ // ── Main fallback function ──
30
+ export async function socialAiFallback(opts) {
31
+ if (!hasLLMConfigured())
32
+ return null;
33
+ const schema = SOCIAL_SCHEMAS[opts.action];
34
+ if (!schema)
35
+ return null;
36
+ let content;
37
+ if (opts.page) {
38
+ // Playwright mode: ARIA tree from already-open page
39
+ const snapshot = await getEnhancedSnapshot(opts.page, { compact: true });
40
+ content = snapshot.tree;
41
+ }
42
+ else if (opts.url) {
43
+ // HTTP mode: fetch + convert to markdown
44
+ const result = await smartFetch(opts.url, { maxLevel: 2 });
45
+ content = htmlToMarkdown(result.html);
46
+ }
47
+ else {
48
+ return null;
49
+ }
50
+ if (!content || content.length < 50)
51
+ return null;
52
+ const client = await createLLMClient();
53
+ const extraction = await extractWithLLM(client, content, schema, opts.maxTokens ?? 4000);
54
+ const raw = extraction.data;
55
+ const normalized = normalizeResult(opts.action, raw);
56
+ return { data: normalized, model: extraction.model };
57
+ }
58
+ // ── Normalizers ──
59
+ function normalizeResult(action, raw) {
60
+ const platform = action.split(":")[0];
61
+ const type = action.split(":")[1];
62
+ if (type === "search" || type === "posts") {
63
+ const items = (raw.videos || raw.posts || []);
64
+ const normalized = items.map((item) => platform === "reddit" ? normalizePost(item) : normalizeVideo(item));
65
+ return platform === "reddit"
66
+ ? { platform: "reddit", results: normalized }
67
+ : { platform, results: normalized };
68
+ }
69
+ if (type === "video")
70
+ return normalizeVideo(raw);
71
+ if (type === "user" || type === "channel" || type === "subreddit")
72
+ return normalizeProfile(raw);
73
+ if (type === "comments") {
74
+ const comments = (raw.comments || []).map(normalizeComment);
75
+ return { ...raw, comments };
76
+ }
77
+ return raw;
78
+ }
79
+ function normalizeVideo(raw) {
80
+ return {
81
+ id: raw.id || "",
82
+ title: raw.title || "",
83
+ url: raw.url || "",
84
+ thumbnail: raw.thumbnail,
85
+ duration: raw.duration,
86
+ views: typeof raw.views === "number" ? raw.views : parseNum(raw.views),
87
+ likes: typeof raw.likes === "number" ? raw.likes : parseNum(raw.likes),
88
+ author: raw.author || "",
89
+ author_url: raw.author_url,
90
+ published: raw.published,
91
+ description: raw.description?.substring(0, 2000),
92
+ };
93
+ }
94
+ function normalizePost(raw) {
95
+ return {
96
+ id: raw.id || "",
97
+ title: raw.title || "",
98
+ url: raw.url || "",
99
+ author: raw.author || "",
100
+ score: typeof raw.score === "number" ? raw.score : parseNum(raw.score),
101
+ comments_count: typeof raw.comments_count === "number" ? raw.comments_count : parseNum(raw.comments_count),
102
+ published: raw.published,
103
+ subreddit: raw.subreddit,
104
+ text: raw.text,
105
+ flair: raw.flair,
106
+ };
107
+ }
108
+ function normalizeComment(raw) {
109
+ return {
110
+ id: raw.id || `comment-${Math.random().toString(36).slice(2, 8)}`,
111
+ author: raw.author || "",
112
+ text: raw.text || "",
113
+ score: typeof raw.score === "number" ? raw.score : (typeof raw.likes === "number" ? raw.likes : parseNum(raw.score || raw.likes)),
114
+ published: raw.published,
115
+ };
116
+ }
117
+ function normalizeProfile(raw) {
118
+ const subs = raw.subscribers || raw.followers;
119
+ return {
120
+ name: raw.name || raw.username || "",
121
+ url: raw.url || "",
122
+ description: raw.description?.substring(0, 1000),
123
+ subscribers: typeof subs === "number" ? subs : parseNum(subs),
124
+ avatar: raw.avatar,
125
+ verified: raw.verified ?? false,
126
+ video_count: typeof raw.video_count === "number" ? raw.video_count : parseNum(raw.video_count),
127
+ created: raw.created,
128
+ };
129
+ }
130
+ /** Parse a number string, returning undefined for NaN. */
131
+ function parseNum(val) {
132
+ if (val == null)
133
+ return undefined;
134
+ const n = parseCompactNumber(String(val));
135
+ return isNaN(n) ? undefined : n;
136
+ }
137
+ //# sourceMappingURL=ai-fallback.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai-fallback.js","sourceRoot":"","sources":["../../src/social/ai-fallback.ts"],"names":[],"mappings":"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"}