@nathanvale/chatline 0.0.1 → 0.0.2-next.1

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 (213) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/bin/index.js +1 -1
  3. package/dist/index.js +1 -1
  4. package/package.json +1 -1
  5. package/dist/cli/commands/clean.d.ts +0 -17
  6. package/dist/cli/commands/clean.d.ts.map +0 -1
  7. package/dist/cli/commands/clean.js +0 -142
  8. package/dist/cli/commands/clean.js.map +0 -1
  9. package/dist/cli/commands/doctor.d.ts +0 -17
  10. package/dist/cli/commands/doctor.d.ts.map +0 -1
  11. package/dist/cli/commands/doctor.js +0 -202
  12. package/dist/cli/commands/doctor.js.map +0 -1
  13. package/dist/cli/commands/enrich-ai.d.ts +0 -17
  14. package/dist/cli/commands/enrich-ai.d.ts.map +0 -1
  15. package/dist/cli/commands/enrich-ai.js +0 -371
  16. package/dist/cli/commands/enrich-ai.js.map +0 -1
  17. package/dist/cli/commands/index.d.ts +0 -16
  18. package/dist/cli/commands/index.d.ts.map +0 -1
  19. package/dist/cli/commands/index.js +0 -16
  20. package/dist/cli/commands/index.js.map +0 -1
  21. package/dist/cli/commands/ingest-csv.d.ts +0 -17
  22. package/dist/cli/commands/ingest-csv.d.ts.map +0 -1
  23. package/dist/cli/commands/ingest-csv.js +0 -138
  24. package/dist/cli/commands/ingest-csv.js.map +0 -1
  25. package/dist/cli/commands/ingest-db.d.ts +0 -17
  26. package/dist/cli/commands/ingest-db.d.ts.map +0 -1
  27. package/dist/cli/commands/ingest-db.js +0 -159
  28. package/dist/cli/commands/ingest-db.js.map +0 -1
  29. package/dist/cli/commands/init.d.ts +0 -17
  30. package/dist/cli/commands/init.d.ts.map +0 -1
  31. package/dist/cli/commands/init.js +0 -110
  32. package/dist/cli/commands/init.js.map +0 -1
  33. package/dist/cli/commands/normalize-link.d.ts +0 -16
  34. package/dist/cli/commands/normalize-link.d.ts.map +0 -1
  35. package/dist/cli/commands/normalize-link.js +0 -144
  36. package/dist/cli/commands/normalize-link.js.map +0 -1
  37. package/dist/cli/commands/render-markdown.d.ts +0 -17
  38. package/dist/cli/commands/render-markdown.d.ts.map +0 -1
  39. package/dist/cli/commands/render-markdown.js +0 -218
  40. package/dist/cli/commands/render-markdown.js.map +0 -1
  41. package/dist/cli/commands/stats.d.ts +0 -17
  42. package/dist/cli/commands/stats.d.ts.map +0 -1
  43. package/dist/cli/commands/stats.js +0 -175
  44. package/dist/cli/commands/stats.js.map +0 -1
  45. package/dist/cli/commands/validate.d.ts +0 -17
  46. package/dist/cli/commands/validate.d.ts.map +0 -1
  47. package/dist/cli/commands/validate.js +0 -152
  48. package/dist/cli/commands/validate.js.map +0 -1
  49. package/dist/cli/index.d.ts +0 -13
  50. package/dist/cli/index.d.ts.map +0 -1
  51. package/dist/cli/index.js +0 -121
  52. package/dist/cli/index.js.map +0 -1
  53. package/dist/cli/types.d.ts +0 -93
  54. package/dist/cli/types.d.ts.map +0 -1
  55. package/dist/cli/types.js +0 -7
  56. package/dist/cli/types.js.map +0 -1
  57. package/dist/cli/utils.d.ts +0 -29
  58. package/dist/cli/utils.d.ts.map +0 -1
  59. package/dist/cli/utils.js +0 -53
  60. package/dist/cli/utils.js.map +0 -1
  61. package/dist/cli.d.ts +0 -9
  62. package/dist/cli.d.ts.map +0 -1
  63. package/dist/cli.js +0 -1805
  64. package/dist/config/generator.d.ts +0 -90
  65. package/dist/config/generator.d.ts.map +0 -1
  66. package/dist/config/generator.js +0 -320
  67. package/dist/config/generator.js.map +0 -1
  68. package/dist/config/loader.d.ts +0 -107
  69. package/dist/config/loader.d.ts.map +0 -1
  70. package/dist/config/loader.js +0 -251
  71. package/dist/config/loader.js.map +0 -1
  72. package/dist/config/schema.d.ts +0 -107
  73. package/dist/config/schema.d.ts.map +0 -1
  74. package/dist/config/schema.js +0 -169
  75. package/dist/config/schema.js.map +0 -1
  76. package/dist/enrich/audio-transcription.d.ts +0 -77
  77. package/dist/enrich/audio-transcription.d.ts.map +0 -1
  78. package/dist/enrich/audio-transcription.js +0 -370
  79. package/dist/enrich/audio-transcription.js.map +0 -1
  80. package/dist/enrich/checkpoint.d.ts +0 -137
  81. package/dist/enrich/checkpoint.d.ts.map +0 -1
  82. package/dist/enrich/checkpoint.js +0 -205
  83. package/dist/enrich/checkpoint.js.map +0 -1
  84. package/dist/enrich/idempotency.d.ts +0 -90
  85. package/dist/enrich/idempotency.d.ts.map +0 -1
  86. package/dist/enrich/idempotency.js +0 -188
  87. package/dist/enrich/idempotency.js.map +0 -1
  88. package/dist/enrich/image-analysis.d.ts +0 -62
  89. package/dist/enrich/image-analysis.d.ts.map +0 -1
  90. package/dist/enrich/image-analysis.js +0 -264
  91. package/dist/enrich/image-analysis.js.map +0 -1
  92. package/dist/enrich/index.d.ts +0 -60
  93. package/dist/enrich/index.d.ts.map +0 -1
  94. package/dist/enrich/index.js +0 -74
  95. package/dist/enrich/index.js.map +0 -1
  96. package/dist/enrich/link-enrichment.d.ts +0 -37
  97. package/dist/enrich/link-enrichment.d.ts.map +0 -1
  98. package/dist/enrich/link-enrichment.js +0 -202
  99. package/dist/enrich/link-enrichment.js.map +0 -1
  100. package/dist/enrich/pdf-video-handling.d.ts +0 -49
  101. package/dist/enrich/pdf-video-handling.d.ts.map +0 -1
  102. package/dist/enrich/pdf-video-handling.js +0 -325
  103. package/dist/enrich/pdf-video-handling.js.map +0 -1
  104. package/dist/enrich/progress-tracker.d.ts +0 -120
  105. package/dist/enrich/progress-tracker.d.ts.map +0 -1
  106. package/dist/enrich/progress-tracker.js +0 -220
  107. package/dist/enrich/progress-tracker.js.map +0 -1
  108. package/dist/enrich/providers/firecrawl.d.ts +0 -18
  109. package/dist/enrich/providers/firecrawl.d.ts.map +0 -1
  110. package/dist/enrich/providers/firecrawl.js +0 -48
  111. package/dist/enrich/providers/firecrawl.js.map +0 -1
  112. package/dist/enrich/providers/generic.d.ts +0 -16
  113. package/dist/enrich/providers/generic.d.ts.map +0 -1
  114. package/dist/enrich/providers/generic.js +0 -36
  115. package/dist/enrich/providers/generic.js.map +0 -1
  116. package/dist/enrich/providers/index.d.ts +0 -14
  117. package/dist/enrich/providers/index.d.ts.map +0 -1
  118. package/dist/enrich/providers/index.js +0 -13
  119. package/dist/enrich/providers/index.js.map +0 -1
  120. package/dist/enrich/providers/instagram.d.ts +0 -16
  121. package/dist/enrich/providers/instagram.d.ts.map +0 -1
  122. package/dist/enrich/providers/instagram.js +0 -43
  123. package/dist/enrich/providers/instagram.js.map +0 -1
  124. package/dist/enrich/providers/spotify.d.ts +0 -16
  125. package/dist/enrich/providers/spotify.d.ts.map +0 -1
  126. package/dist/enrich/providers/spotify.js +0 -45
  127. package/dist/enrich/providers/spotify.js.map +0 -1
  128. package/dist/enrich/providers/twitter.d.ts +0 -16
  129. package/dist/enrich/providers/twitter.d.ts.map +0 -1
  130. package/dist/enrich/providers/twitter.js +0 -43
  131. package/dist/enrich/providers/twitter.js.map +0 -1
  132. package/dist/enrich/providers/types.d.ts +0 -47
  133. package/dist/enrich/providers/types.d.ts.map +0 -1
  134. package/dist/enrich/providers/types.js +0 -15
  135. package/dist/enrich/providers/types.js.map +0 -1
  136. package/dist/enrich/providers/youtube.d.ts +0 -16
  137. package/dist/enrich/providers/youtube.d.ts.map +0 -1
  138. package/dist/enrich/providers/youtube.js +0 -43
  139. package/dist/enrich/providers/youtube.js.map +0 -1
  140. package/dist/enrich/rate-limiting.d.ts +0 -118
  141. package/dist/enrich/rate-limiting.d.ts.map +0 -1
  142. package/dist/enrich/rate-limiting.js +0 -258
  143. package/dist/enrich/rate-limiting.js.map +0 -1
  144. package/dist/index.d.ts.map +0 -1
  145. package/dist/index.js.map +0 -1
  146. package/dist/ingest/dedup-merge.d.ts +0 -82
  147. package/dist/ingest/dedup-merge.d.ts.map +0 -1
  148. package/dist/ingest/dedup-merge.js +0 -262
  149. package/dist/ingest/dedup-merge.js.map +0 -1
  150. package/dist/ingest/ingest-csv.d.ts +0 -62
  151. package/dist/ingest/ingest-csv.d.ts.map +0 -1
  152. package/dist/ingest/ingest-csv.js +0 -300
  153. package/dist/ingest/ingest-csv.js.map +0 -1
  154. package/dist/ingest/ingest-db.d.ts +0 -64
  155. package/dist/ingest/ingest-db.d.ts.map +0 -1
  156. package/dist/ingest/ingest-db.js +0 -172
  157. package/dist/ingest/ingest-db.js.map +0 -1
  158. package/dist/ingest/link-replies-and-tapbacks.d.ts +0 -53
  159. package/dist/ingest/link-replies-and-tapbacks.d.ts.map +0 -1
  160. package/dist/ingest/link-replies-and-tapbacks.js +0 -381
  161. package/dist/ingest/link-replies-and-tapbacks.js.map +0 -1
  162. package/dist/normalize/date-converters.d.ts +0 -45
  163. package/dist/normalize/date-converters.d.ts.map +0 -1
  164. package/dist/normalize/date-converters.js +0 -166
  165. package/dist/normalize/date-converters.js.map +0 -1
  166. package/dist/normalize/path-validator.d.ts +0 -65
  167. package/dist/normalize/path-validator.d.ts.map +0 -1
  168. package/dist/normalize/path-validator.js +0 -221
  169. package/dist/normalize/path-validator.js.map +0 -1
  170. package/dist/normalize/validate-normalized.d.ts +0 -45
  171. package/dist/normalize/validate-normalized.d.ts.map +0 -1
  172. package/dist/normalize/validate-normalized.js +0 -144
  173. package/dist/normalize/validate-normalized.js.map +0 -1
  174. package/dist/render/embeds-blockquotes.d.ts +0 -84
  175. package/dist/render/embeds-blockquotes.d.ts.map +0 -1
  176. package/dist/render/embeds-blockquotes.js +0 -204
  177. package/dist/render/embeds-blockquotes.js.map +0 -1
  178. package/dist/render/grouping.d.ts +0 -78
  179. package/dist/render/grouping.d.ts.map +0 -1
  180. package/dist/render/grouping.js +0 -134
  181. package/dist/render/grouping.js.map +0 -1
  182. package/dist/render/index.d.ts +0 -47
  183. package/dist/render/index.d.ts.map +0 -1
  184. package/dist/render/index.js +0 -245
  185. package/dist/render/index.js.map +0 -1
  186. package/dist/render/reply-rendering.d.ts +0 -88
  187. package/dist/render/reply-rendering.d.ts.map +0 -1
  188. package/dist/render/reply-rendering.js +0 -196
  189. package/dist/render/reply-rendering.js.map +0 -1
  190. package/dist/schema/message.d.ts +0 -125
  191. package/dist/schema/message.d.ts.map +0 -1
  192. package/dist/schema/message.js +0 -331
  193. package/dist/schema/message.js.map +0 -1
  194. package/dist/utils/delta-detection.d.ts +0 -107
  195. package/dist/utils/delta-detection.d.ts.map +0 -1
  196. package/dist/utils/delta-detection.js +0 -199
  197. package/dist/utils/delta-detection.js.map +0 -1
  198. package/dist/utils/enrichment-merge.d.ts +0 -135
  199. package/dist/utils/enrichment-merge.d.ts.map +0 -1
  200. package/dist/utils/enrichment-merge.js +0 -280
  201. package/dist/utils/enrichment-merge.js.map +0 -1
  202. package/dist/utils/human.d.ts +0 -15
  203. package/dist/utils/human.d.ts.map +0 -1
  204. package/dist/utils/human.js +0 -27
  205. package/dist/utils/human.js.map +0 -1
  206. package/dist/utils/incremental-state.d.ts +0 -133
  207. package/dist/utils/incremental-state.d.ts.map +0 -1
  208. package/dist/utils/incremental-state.js +0 -237
  209. package/dist/utils/incremental-state.js.map +0 -1
  210. package/dist/utils/logger.d.ts +0 -40
  211. package/dist/utils/logger.d.ts.map +0 -1
  212. package/dist/utils/logger.js +0 -176
  213. package/dist/utils/logger.js.map +0 -1
@@ -1,264 +0,0 @@
1
- /**
2
- * Image Analysis Module (ENRICH--T01)
3
- *
4
- * Implements image analysis with preview generation:
5
- * - AC01: HEIC → JPG conversion with ≥90% quality
6
- * - AC02: TIFF → JPG conversion
7
- * - AC03: Preview caching by filename (generate once, skip if exists)
8
- * - AC04: Gemini Vision API with structured prompt
9
- * - AC05: Parse response into enrichment array with kind='image_analysis'
10
- * - AC06: Store provenance (provider, model, version, timestamp)
11
- *
12
- * Architecture:
13
- * - convertToJpgPreview: Handles format conversion with caching
14
- * - analyzeImageWithGemini: Calls Gemini Vision API with structured prompt
15
- * - analyzeImage: Main entry point, handles single message enrichment
16
- * - analyzeImages: Batch processing wrapper
17
- *
18
- * Error Handling:
19
- * - Non-fatal errors are logged and original message is returned
20
- * - Preview generation failures don't block Gemini analysis
21
- * - Pipeline never crashes on enrichment errors
22
- */
23
- import { access, writeFile } from 'node:fs/promises';
24
- import path from 'node:path';
25
- import { GoogleGenerativeAI } from '@google/generative-ai';
26
- import sharp from 'sharp';
27
- import { createLogger } from '#utils/logger';
28
- const logger = createLogger('enrich:image-analysis');
29
- /**
30
- * Structured prompt for Gemini Vision analysis
31
- * First classifies image type, then provides detailed + short descriptions
32
- */
33
- const GEMINI_VISION_PROMPT = `You are an expert at analyzing images. First, classify the image type:
34
- - photo (real-world scene, landscape, portrait, food, outdoor, indoor, etc.)
35
- - screenshot (UI, application, website, text content)
36
- - diagram (chart, graph, whiteboard, flowchart)
37
- - artwork (drawing, illustration, design, painting)
38
- - other (specify what it is)
39
-
40
- Then provide:
41
- 1. visionSummary: A detailed 2-3 sentence description of the image content, context, and notable details
42
- 2. shortDescription: A concise 1-sentence summary for quick scanning
43
-
44
- Format your response exactly as:
45
- IMAGE_TYPE: [classification]
46
- visionSummary: [detailed description here]
47
- shortDescription: [one sentence summary]`;
48
- /**
49
- * AC03: Convert image to JPG preview
50
- * - Input: path to HEIC, TIFF, or other format
51
- * - Output: path to cached JPG preview
52
- * - Behavior: Generate once, cache by filename, skip if exists
53
- */
54
- export async function convertToJpgPreview(inputPath, cacheDir, quality = 90) {
55
- if (!inputPath || !cacheDir) {
56
- throw new Error('inputPath and cacheDir are required');
57
- }
58
- const filename = path.parse(path.basename(inputPath)).name;
59
- const previewFilename = `preview-${filename}.jpg`;
60
- const previewPath = path.join(cacheDir, previewFilename);
61
- try {
62
- // AC03: Check if preview already exists
63
- await access(previewPath);
64
- // If we get here, file exists - return cached path
65
- logger.debug(`Preview cache hit: ${previewPath}`);
66
- return previewPath;
67
- }
68
- catch {
69
- // File doesn't exist, proceed with conversion
70
- }
71
- // AC01/AC02: Convert to JPG with quality preservation
72
- try {
73
- const imageBuffer = await sharp(inputPath)
74
- .toFormat('jpeg')
75
- .jpeg({ quality, progressive: true })
76
- .toBuffer();
77
- // Write to cache
78
- await writeFile(previewPath, imageBuffer);
79
- logger.info(`Generated preview: ${previewPath}`, { inputPath, quality });
80
- return previewPath;
81
- }
82
- catch (error) {
83
- logger.error(`Failed to convert image: ${inputPath}`, { error });
84
- throw new Error(`Failed to convert image to JPG: ${inputPath}`);
85
- }
86
- }
87
- /**
88
- * AC04: Call Gemini Vision with structured prompt
89
- * AC05: Parse response into enrichment array
90
- * AC06: Store provenance
91
- */
92
- export async function analyzeImageWithGemini(imagePath, config) {
93
- const apiKey = config.geminiApiKey;
94
- const modelName = config.geminiModel || 'gemini-1.5-pro';
95
- if (!apiKey) {
96
- throw new Error('GEMINI_API_KEY is required for image analysis');
97
- }
98
- try {
99
- // AC04: Create Gemini client and call with structured prompt
100
- const genAI = new GoogleGenerativeAI(apiKey);
101
- const model = genAI.getGenerativeModel({ model: modelName });
102
- // Read image file
103
- const imageData = await sharp(imagePath).toFormat('jpeg').toBuffer();
104
- const base64Image = imageData.toString('base64');
105
- // AC04: Call Gemini with structured prompt
106
- // Call Gemini with image
107
- const response = await model.generateContent([
108
- {
109
- inlineData: {
110
- mimeType: 'image/jpeg',
111
- data: base64Image,
112
- },
113
- },
114
- GEMINI_VISION_PROMPT,
115
- ]);
116
- const responseText = response.response.text();
117
- logger.debug(`Gemini response received: ${responseText.substring(0, 150)}...`);
118
- // AC05: Parse response
119
- const visionSummaryMatch = responseText.match(/visionSummary:\s*(.+?)(?=\n(?:shortDescription|$))/is);
120
- const shortDescriptionMatch = responseText.match(/shortDescription:\s*(.+?)(?=\n|$)/is);
121
- if (!visionSummaryMatch || !shortDescriptionMatch) {
122
- logger.warn(`Failed to parse Gemini response for ${imagePath}`);
123
- }
124
- const visionSummary = visionSummaryMatch?.[1]?.trim() || 'Image analysis unavailable';
125
- const shortDescription = shortDescriptionMatch?.[1]?.trim() || 'Image';
126
- // AC06: Create enrichment entry with full provenance
127
- const version = new Date().toISOString().split('T')[0] || 'unknown';
128
- const enrichment = {
129
- kind: 'image_analysis',
130
- provider: 'gemini',
131
- model: modelName,
132
- version, // YYYY-MM-DD
133
- createdAt: new Date().toISOString(),
134
- visionSummary,
135
- shortDescription,
136
- };
137
- logger.info(`Image analysis complete for ${imagePath}`, {
138
- kind: enrichment.kind,
139
- });
140
- return enrichment;
141
- }
142
- catch (error) {
143
- logger.error(`Gemini API error for ${imagePath}`, { error });
144
- throw error;
145
- }
146
- }
147
- /**
148
- * Main entry point - analyze image media message and enrich it
149
- * Handles all ACs (AC01-AC06) through helper functions
150
- *
151
- * Responsibilities:
152
- * 1. Check if media is image type (skip non-images)
153
- * 2. Convert HEIC/TIFF to JPG preview (AC01-AC03)
154
- * 3. Call Gemini Vision API (AC04)
155
- * 4. Parse response (AC05)
156
- * 5. Add enrichment with provenance (AC06)
157
- */
158
- export async function analyzeImage(message, config) {
159
- // Skip if not enabled
160
- if (!config.enableVisionAnalysis) {
161
- logger.debug('Vision analysis disabled in config');
162
- return message;
163
- }
164
- // Skip if not a media message
165
- if (message.messageKind !== 'media' || !message.media) {
166
- return message;
167
- }
168
- // Skip if media is not an image
169
- if (message.media.mediaKind !== 'image') {
170
- logger.debug('Skipping non-image media', {
171
- mediaKind: message.media.mediaKind,
172
- });
173
- return message;
174
- }
175
- // Skip if path is missing
176
- if (!message.media.path) {
177
- logger.warn('Skipping image with missing path', {
178
- filename: message.media.filename,
179
- });
180
- return message;
181
- }
182
- try {
183
- const imageCacheDir = config.imageCacheDir || '/tmp/image-cache';
184
- // AC01-AC03: Generate preview (cached)
185
- let _previewPath;
186
- try {
187
- _previewPath = await convertToJpgPreview(message.media.path, imageCacheDir, 90);
188
- }
189
- catch (err) {
190
- logger.warn('Failed to create preview - continuing with Gemini analysis', {
191
- filename: message.media.filename,
192
- error: err instanceof Error ? err.message : String(err),
193
- });
194
- // Continue with Gemini analysis even if preview fails
195
- }
196
- // AC04-AC06: Analyze with Gemini
197
- const enrichment = await analyzeImageWithGemini(message.media.path, config);
198
- // Update message with enrichment
199
- const updatedMedia = {
200
- ...message.media,
201
- enrichment: [...(message.media.enrichment || []), enrichment],
202
- };
203
- logger.info('Image enriched', {
204
- filename: message.media.filename,
205
- guid: message.guid,
206
- });
207
- return {
208
- ...message,
209
- media: updatedMedia,
210
- };
211
- }
212
- catch (error) {
213
- logger.error('Error analyzing image', {
214
- filename: message.media?.filename,
215
- guid: message.guid,
216
- error: error instanceof Error ? error.message : String(error),
217
- });
218
- // Don't crash pipeline - return original message
219
- return message;
220
- }
221
- }
222
- /**
223
- * Batch analyze multiple messages
224
- * Useful for enrichment stage that processes arrays of messages
225
- * Each message is processed independently; errors don't stop the batch
226
- */
227
- export async function analyzeImages(messages, config) {
228
- const results = [];
229
- let successCount = 0;
230
- let skipCount = 0;
231
- let errorCount = 0;
232
- for (const message of messages) {
233
- try {
234
- const analyzed = await analyzeImage(message, config);
235
- // Track if enrichment was added
236
- if (analyzed.media?.enrichment &&
237
- analyzed.media.enrichment.length >
238
- (message.media?.enrichment?.length || 0)) {
239
- successCount++;
240
- }
241
- else {
242
- skipCount++;
243
- }
244
- results.push(analyzed);
245
- }
246
- catch (err) {
247
- errorCount++;
248
- logger.error('Failed to analyze message', {
249
- guid: message.guid,
250
- error: err instanceof Error ? err.message : String(err),
251
- });
252
- // Keep original message if analysis fails
253
- results.push(message);
254
- }
255
- }
256
- logger.info('Batch image analysis complete', {
257
- successCount,
258
- skipCount,
259
- errorCount,
260
- total: messages.length,
261
- });
262
- return results;
263
- }
264
- //# sourceMappingURL=image-analysis.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"image-analysis.js","sourceRoot":"","sources":["../../src/enrich/image-analysis.ts"],"names":[],"mappings":"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"}
@@ -1,60 +0,0 @@
1
- /**
2
- * Enrich Module - Main Entry Point
3
- *
4
- * Provides consolidated access to all enrichment operations with idempotency
5
- * support built-in.
6
- *
7
- * Implements:
8
- * - ENRICH--T01: Image analysis with preview generation
9
- * - ENRICH--T02: Audio transcription
10
- * - ENRICH--T03: PDF/video handling
11
- * - ENRICH--T04: Link enrichment (pending)
12
- * - ENRICH--T05: Enrichment idempotency
13
- */
14
- export * from './audio-transcription';
15
- export * from './idempotency';
16
- export * from './image-analysis';
17
- export * from './link-enrichment';
18
- export * from './pdf-video-handling';
19
- import type { MediaEnrichment, Message } from '#schema/message';
20
- type EnrichmentConfig = {
21
- enableVisionAnalysis?: boolean;
22
- enableLinkAnalysis?: boolean;
23
- geminiApiKey?: string;
24
- geminiModel?: string;
25
- imageCacheDir?: string;
26
- firecrawlApiKey?: string;
27
- rateLimitDelay?: number;
28
- forceRefresh?: boolean;
29
- };
30
- /**
31
- * Apply enrichment to a message with idempotency checks
32
- *
33
- * This is the main entry point for enrichment operations that ensures
34
- * idempotency: re-running enrichment won't create duplicate entries.
35
- *
36
- * @param message - Message to enrich
37
- * @param enrichment - New enrichment to add
38
- * @param config - Enrichment configuration including forceRefresh flag
39
- * @returns Updated message with enrichment applied idempotently
40
- */
41
- export declare function applyEnrichmentIdempotent(message: Message, enrichment: MediaEnrichment, config?: EnrichmentConfig): Message;
42
- /**
43
- * Check if a message should skip enrichment of a specific kind
44
- *
45
- * @param message - Message to check
46
- * @param kind - Enrichment kind to check
47
- * @param forceRefresh - If true, always proceed (don't skip)
48
- * @returns true if should skip, false if should proceed
49
- */
50
- export declare function shouldSkipEnrichmentForKind(message: Message, kind: MediaEnrichment['kind'], forceRefresh?: boolean): boolean;
51
- /**
52
- * Ensure message enrichment is deduplicated
53
- *
54
- * Useful for cleanup after multiple enrichment operations.
55
- *
56
- * @param message - Message to deduplicate
57
- * @returns Message with deduplicated enrichment
58
- */
59
- export declare function ensureDeduplicatedEnrichment(message: Message): Message;
60
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/enrich/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,cAAc,uBAAuB,CAAA;AACrC,cAAc,eAAe,CAAA;AAC7B,cAAc,kBAAkB,CAAA;AAChC,cAAc,mBAAmB,CAAA;AACjC,cAAc,sBAAsB,CAAA;AAEpC,OAAO,KAAK,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAA;AAO/D,KAAK,gBAAgB,GAAG;IACvB,oBAAoB,CAAC,EAAE,OAAO,CAAA;IAC9B,kBAAkB,CAAC,EAAE,OAAO,CAAA;IAC5B,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,YAAY,CAAC,EAAE,OAAO,CAAA;CACtB,CAAA;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,yBAAyB,CACxC,OAAO,EAAE,OAAO,EAChB,UAAU,EAAE,eAAe,EAC3B,MAAM,GAAE,gBAAqB,GAC3B,OAAO,CAIT;AAED;;;;;;;GAOG;AACH,wBAAgB,2BAA2B,CAC1C,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,eAAe,CAAC,MAAM,CAAC,EAC7B,YAAY,UAAQ,GAClB,OAAO,CAMT;AAED;;;;;;;GAOG;AACH,wBAAgB,4BAA4B,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAmBtE"}
@@ -1,74 +0,0 @@
1
- /**
2
- * Enrich Module - Main Entry Point
3
- *
4
- * Provides consolidated access to all enrichment operations with idempotency
5
- * support built-in.
6
- *
7
- * Implements:
8
- * - ENRICH--T01: Image analysis with preview generation
9
- * - ENRICH--T02: Audio transcription
10
- * - ENRICH--T03: PDF/video handling
11
- * - ENRICH--T04: Link enrichment (pending)
12
- * - ENRICH--T05: Enrichment idempotency
13
- */
14
- export * from './audio-transcription';
15
- export * from './idempotency';
16
- export * from './image-analysis';
17
- export * from './link-enrichment';
18
- export * from './pdf-video-handling';
19
- import { addEnrichmentIdempotent, deduplicateEnrichmentByKind, shouldSkipEnrichment, } from './idempotency';
20
- /**
21
- * Apply enrichment to a message with idempotency checks
22
- *
23
- * This is the main entry point for enrichment operations that ensures
24
- * idempotency: re-running enrichment won't create duplicate entries.
25
- *
26
- * @param message - Message to enrich
27
- * @param enrichment - New enrichment to add
28
- * @param config - Enrichment configuration including forceRefresh flag
29
- * @returns Updated message with enrichment applied idempotently
30
- */
31
- export function applyEnrichmentIdempotent(message, enrichment, config = {}) {
32
- const { forceRefresh = false } = config;
33
- return addEnrichmentIdempotent(message, enrichment, { forceRefresh });
34
- }
35
- /**
36
- * Check if a message should skip enrichment of a specific kind
37
- *
38
- * @param message - Message to check
39
- * @param kind - Enrichment kind to check
40
- * @param forceRefresh - If true, always proceed (don't skip)
41
- * @returns true if should skip, false if should proceed
42
- */
43
- export function shouldSkipEnrichmentForKind(message, kind, forceRefresh = false) {
44
- if (forceRefresh) {
45
- return false;
46
- }
47
- return shouldSkipEnrichment(message, kind);
48
- }
49
- /**
50
- * Ensure message enrichment is deduplicated
51
- *
52
- * Useful for cleanup after multiple enrichment operations.
53
- *
54
- * @param message - Message to deduplicate
55
- * @returns Message with deduplicated enrichment
56
- */
57
- export function ensureDeduplicatedEnrichment(message) {
58
- if (!message.media?.enrichment) {
59
- return message;
60
- }
61
- const deduped = deduplicateEnrichmentByKind(message.media.enrichment);
62
- if (deduped.length === message.media.enrichment.length) {
63
- // No change needed
64
- return message;
65
- }
66
- return {
67
- ...message,
68
- media: {
69
- ...message.media,
70
- enrichment: deduped,
71
- },
72
- };
73
- }
74
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/enrich/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,cAAc,uBAAuB,CAAA;AACrC,cAAc,eAAe,CAAA;AAC7B,cAAc,kBAAkB,CAAA;AAChC,cAAc,mBAAmB,CAAA;AACjC,cAAc,sBAAsB,CAAA;AAGpC,OAAO,EACN,uBAAuB,EACvB,2BAA2B,EAC3B,oBAAoB,GACpB,MAAM,eAAe,CAAA;AAatB;;;;;;;;;;GAUG;AACH,MAAM,UAAU,yBAAyB,CACxC,OAAgB,EAChB,UAA2B,EAC3B,SAA2B,EAAE;IAE7B,MAAM,EAAE,YAAY,GAAG,KAAK,EAAE,GAAG,MAAM,CAAA;IAEvC,OAAO,uBAAuB,CAAC,OAAO,EAAE,UAAU,EAAE,EAAE,YAAY,EAAE,CAAC,CAAA;AACtE,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,2BAA2B,CAC1C,OAAgB,EAChB,IAA6B,EAC7B,YAAY,GAAG,KAAK;IAEpB,IAAI,YAAY,EAAE,CAAC;QAClB,OAAO,KAAK,CAAA;IACb,CAAC;IAED,OAAO,oBAAoB,CAAC,OAAO,EAAE,IAAI,CAAC,CAAA;AAC3C,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,4BAA4B,CAAC,OAAgB;IAC5D,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,UAAU,EAAE,CAAC;QAChC,OAAO,OAAO,CAAA;IACf,CAAC;IAED,MAAM,OAAO,GAAG,2BAA2B,CAAC,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,CAAA;IAErE,IAAI,OAAO,CAAC,MAAM,KAAK,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,MAAM,EAAE,CAAC;QACxD,mBAAmB;QACnB,OAAO,OAAO,CAAA;IACf,CAAC;IAED,OAAO;QACN,GAAG,OAAO;QACV,KAAK,EAAE;YACN,GAAG,OAAO,CAAC,KAAK;YAChB,UAAU,EAAE,OAAO;SACnB;KACD,CAAA;AACF,CAAC"}
@@ -1,37 +0,0 @@
1
- /**
2
- * Link Enrichment Module (ENRICH--T04)
3
- *
4
- * Implements link context extraction with cascading fallbacks:
5
- * - AC01: Firecrawl as primary provider for generic link context
6
- * - AC02: YouTube fallback with title/channel extraction
7
- * - AC03: Spotify fallback with track/artist extraction
8
- * - AC04: Social media fallbacks (Twitter/Instagram) using meta tags
9
- * - AC05: Never crash - comprehensive error handling with fallbacks
10
- * - AC06: Store enrichment with kind='link_context' and provenance
11
- *
12
- * Architecture:
13
- * - Provider factory pattern with priority-based cascading
14
- * - Firecrawl (priority 0) → Provider-specific (1-4) → Generic fallback (5)
15
- * - URL detection regex for each provider type
16
- * - Meta tag extraction for social media
17
- * - Comprehensive error logging and statistics
18
- *
19
- * Error Handling:
20
- * - Non-fatal errors logged and fall through to next provider
21
- * - Pipeline never crashes - always return message
22
- * - Rate limit detection with fallback triggering
23
- */
24
- import type { Message } from '#schema/message';
25
- import { type LinkEnrichmentConfig } from './providers/index.js';
26
- export type { LinkContext, LinkEnrichmentConfig } from './providers/index.js';
27
- /**
28
- * Main entry point - enrich text message with link context
29
- * AC01-AC06: Full implementation
30
- */
31
- export declare function enrichLinkContext(message: Message, config: Partial<LinkEnrichmentConfig>): Promise<Message>;
32
- /**
33
- * Batch analyze multiple messages
34
- * Tracks statistics and handles errors per message
35
- */
36
- export declare function enrichLinksContext(messages: Message[], config: Partial<LinkEnrichmentConfig>): Promise<Message[]>;
37
- //# sourceMappingURL=link-enrichment.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"link-enrichment.d.ts","sourceRoot":"","sources":["../../src/enrich/link-enrichment.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,KAAK,EAAmB,OAAO,EAAE,MAAM,iBAAiB,CAAA;AAG/D,OAAO,EAKN,KAAK,oBAAoB,EAKzB,MAAM,sBAAsB,CAAA;AAG7B,YAAY,EAAE,WAAW,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAA;AAkF7E;;;GAGG;AACH,wBAAsB,iBAAiB,CACtC,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,OAAO,CAAC,oBAAoB,CAAC,GACnC,OAAO,CAAC,OAAO,CAAC,CA4ElB;AAED;;;GAGG;AACH,wBAAsB,kBAAkB,CACvC,QAAQ,EAAE,OAAO,EAAE,EACnB,MAAM,EAAE,OAAO,CAAC,oBAAoB,CAAC,GACnC,OAAO,CAAC,OAAO,EAAE,CAAC,CAmCpB"}
@@ -1,202 +0,0 @@
1
- /**
2
- * Link Enrichment Module (ENRICH--T04)
3
- *
4
- * Implements link context extraction with cascading fallbacks:
5
- * - AC01: Firecrawl as primary provider for generic link context
6
- * - AC02: YouTube fallback with title/channel extraction
7
- * - AC03: Spotify fallback with track/artist extraction
8
- * - AC04: Social media fallbacks (Twitter/Instagram) using meta tags
9
- * - AC05: Never crash - comprehensive error handling with fallbacks
10
- * - AC06: Store enrichment with kind='link_context' and provenance
11
- *
12
- * Architecture:
13
- * - Provider factory pattern with priority-based cascading
14
- * - Firecrawl (priority 0) → Provider-specific (1-4) → Generic fallback (5)
15
- * - URL detection regex for each provider type
16
- * - Meta tag extraction for social media
17
- * - Comprehensive error logging and statistics
18
- *
19
- * Error Handling:
20
- * - Non-fatal errors logged and fall through to next provider
21
- * - Pipeline never crashes - always return message
22
- * - Rate limit detection with fallback triggering
23
- */
24
- import { createLogger } from '#utils/logger';
25
- import { FirecrawlProvider, GenericProvider, InstagramProvider, SpotifyProvider, TwitterProvider, YouTubeProvider, } from './providers/index.js';
26
- /**
27
- * Logger for structured output
28
- */
29
- const logger = createLogger('enrich:link-enrichment');
30
- /**
31
- * AC01-AC04: Provider factory with cascading fallback strategy
32
- */
33
- function createProviders(config) {
34
- const providers = [];
35
- // AC01: Firecrawl primary
36
- if (config.firecrawlApiKey) {
37
- providers.push(new FirecrawlProvider(config.firecrawlApiKey));
38
- }
39
- // AC02-AC04: Add provider-specific handlers
40
- providers.push(new YouTubeProvider());
41
- providers.push(new SpotifyProvider());
42
- providers.push(new TwitterProvider());
43
- providers.push(new InstagramProvider());
44
- // Generic fallback (always last)
45
- providers.push(new GenericProvider());
46
- // Sort by priority
47
- return providers.sort((a, b) => a.priority - b.priority);
48
- }
49
- /**
50
- * Extract URLs from message text
51
- */
52
- function extractUrls(text) {
53
- const urlRegex = /https?:\/\/[^\s)]+/g;
54
- const matches = text.match(urlRegex) || [];
55
- return matches;
56
- }
57
- /**
58
- * AC05: Cascading fallback with error handling
59
- * Never crashes - always returns result or original message
60
- */
61
- async function enrichUrl(url, config) {
62
- const providers = createProviders(config);
63
- const failedProviders = [];
64
- // AC05: Try each provider in order until one succeeds
65
- for (const provider of providers) {
66
- try {
67
- if (!provider.detect(url)) {
68
- logger.debug(`Provider ${provider.name} skipped (not applicable for URL)`);
69
- continue;
70
- }
71
- const context = await provider.extract(url);
72
- logger.info(`Link enrichment succeeded with ${provider.name}`, { url });
73
- const result = { ...context };
74
- if (failedProviders.length > 0) {
75
- result.failedProviders = failedProviders;
76
- }
77
- return result;
78
- }
79
- catch (error) {
80
- failedProviders.push(provider.name);
81
- logger.warn(`Provider ${provider.name} failed for ${url}`, {
82
- error: error instanceof Error ? error.message : String(error),
83
- });
84
- // Continue to next provider
85
- }
86
- }
87
- // AC05: All providers failed - return null but don't crash
88
- logger.warn(`All providers failed for URL ${url}`, { failedProviders });
89
- return null;
90
- }
91
- /**
92
- * Main entry point - enrich text message with link context
93
- * AC01-AC06: Full implementation
94
- */
95
- export async function enrichLinkContext(message, config) {
96
- // Skip if not enabled
97
- if (!config.enableLinkAnalysis) {
98
- logger.debug('Link analysis disabled in config');
99
- return message;
100
- }
101
- // Skip if not a text message
102
- if (message.messageKind !== 'text' || !message.text) {
103
- return message;
104
- }
105
- try {
106
- // Extract URLs from message text
107
- const urls = extractUrls(message.text);
108
- if (urls.length === 0) {
109
- logger.debug('No URLs found in message', { guid: message.guid });
110
- return message;
111
- }
112
- // Process first URL found (could extend to handle multiple)
113
- const url = urls[0];
114
- if (!url) {
115
- logger.debug('URL array is empty', { guid: message.guid });
116
- return message;
117
- }
118
- const context = await enrichUrl(url, config);
119
- if (!context) {
120
- logger.debug(`Failed to enrich link for ${url}`, { guid: message.guid });
121
- return message;
122
- }
123
- // AC06: Create enrichment entry with full provenance
124
- const version = new Date().toISOString().split('T')[0];
125
- if (!version) {
126
- throw new Error('Failed to generate version string');
127
- }
128
- const enrichment = {
129
- kind: 'link_context',
130
- provider: context.provider,
131
- model: 'link-extractor',
132
- version,
133
- createdAt: new Date().toISOString(),
134
- url: context.url,
135
- };
136
- if (context.title)
137
- enrichment.title = context.title;
138
- if (context.description)
139
- enrichment.summary = context.description;
140
- if (context.usedFallback)
141
- enrichment.usedFallback = context.usedFallback;
142
- logger.info('Link enriched', {
143
- url,
144
- provider: context.provider,
145
- guid: message.guid,
146
- });
147
- // For text messages, store enrichment in a linkEnrichments array on the message
148
- // This preserves the original message structure while adding the enrichment data
149
- const existingEnrichments = message
150
- .linkEnrichments || [];
151
- return {
152
- ...message,
153
- linkEnrichments: [...existingEnrichments, enrichment],
154
- };
155
- }
156
- catch (error) {
157
- logger.error('Error enriching link', {
158
- guid: message.guid,
159
- error: error instanceof Error ? error.message : String(error),
160
- });
161
- // AC05: Never crash - return original message
162
- return message;
163
- }
164
- }
165
- /**
166
- * Batch analyze multiple messages
167
- * Tracks statistics and handles errors per message
168
- */
169
- export async function enrichLinksContext(messages, config) {
170
- const results = [];
171
- let enrichedCount = 0;
172
- const skippedCount = 0;
173
- let failedCount = 0;
174
- const providerStats = {};
175
- for (const message of messages) {
176
- try {
177
- const enriched = await enrichLinkContext(message, config);
178
- // Check if enrichment was added (would need to check media.enrichment in production)
179
- // For now, count as processed
180
- enrichedCount++;
181
- results.push(enriched);
182
- }
183
- catch (error) {
184
- failedCount++;
185
- logger.error('Failed to analyze message', {
186
- guid: message.guid,
187
- error: error instanceof Error ? error.message : String(error),
188
- });
189
- // Keep original message if enrichment fails
190
- results.push(message);
191
- }
192
- }
193
- logger.info('Batch link enrichment complete', {
194
- enrichedCount,
195
- skippedCount,
196
- failedCount,
197
- total: messages.length,
198
- providerStats,
199
- });
200
- return results;
201
- }
202
- //# sourceMappingURL=link-enrichment.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"link-enrichment.js","sourceRoot":"","sources":["../../src/enrich/link-enrichment.ts"],"names":[],"mappings":"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"}