@llm-newsletter-kit/core 1.3.7 → 1.3.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -2,8 +2,8 @@
2
2
 
3
3
  var runnables = require('@langchain/core/runnables');
4
4
  var esToolkit = require('es-toolkit');
5
- var ai = require('ai');
6
5
  var zod = require('zod');
6
+ var ai = require('ai');
7
7
  var jsdom = require('jsdom');
8
8
  var juice = require('juice');
9
9
  var safeMarkdown2Html = require('safe-markdown2html');
@@ -91,6 +91,25 @@ class LoggingExecutor {
91
91
  }
92
92
  }
93
93
 
94
+ async function generateObjectByLLM({ schema, ...rest }) {
95
+ const result = await ai.generateText({
96
+ ...rest,
97
+ output: ai.Output.object({ schema }),
98
+ // Anthropic truncates structured output when it contains quotation marks.
99
+ // Using 'jsonTool' mode avoids this issue.
100
+ providerOptions: {
101
+ anthropic: {
102
+ structuredOutputMode: 'jsonTool',
103
+ },
104
+ },
105
+ });
106
+ return {
107
+ output: result.output,
108
+ usage: result.usage,
109
+ finishReason: result.finishReason,
110
+ };
111
+ }
112
+
94
113
  /**
95
114
  * Replaces ASCII double quotes with Unicode smart quotes (U+201C, U+201D).
96
115
  * Prevents JSON structured output corruption when LLM reproduces quoted titles.
@@ -173,7 +192,7 @@ class AnalyzeImages extends LLMQuery {
173
192
  schema = zod.z.object({
174
193
  imageContext: zod.z
175
194
  .string()
176
- .describe('A comprehensive description of all information extracted from the images'),
195
+ .describe('A high-level overview of the general theme, mood, and context conveyed by the images (without specific names, titles, or exact figures from text within images)'),
177
196
  });
178
197
  constructor(config) {
179
198
  super(config);
@@ -186,12 +205,10 @@ class AnalyzeImages extends LLMQuery {
186
205
  if (this.imageMessages.length === 0) {
187
206
  return { result: null, usage: ZERO_USAGE };
188
207
  }
189
- const { output, usage } = await ai.generateText({
208
+ const { output, usage } = await generateObjectByLLM({
190
209
  model: this.model,
191
210
  maxRetries: this.options.llm.maxRetries,
192
- output: ai.Output.object({
193
- schema: this.schema,
194
- }),
211
+ schema: this.schema,
195
212
  system: this.systemPrompt,
196
213
  messages: [
197
214
  {
@@ -211,29 +228,36 @@ You are a specialized image analysis expert in: ${this.expertFields.join(', ')}
211
228
  ## Core Responsibilities
212
229
  1. Extract visual information unavailable from text alone
213
230
  2. Identify industry-specific elements, facilities, and stakeholders
214
- 3. Accurately read and transcribe text, charts, and data visualizations
231
+ 3. Summarize the general theme and context of charts, data visualizations, and text within images at a high level
215
232
  4. Synthesize visual information with article context
216
233
 
234
+ ## Critical Rule: NO Detailed Text Transcription
235
+ - Do NOT transcribe specific names, titles, numbers, dates, or exact phrases from text within images
236
+ - Instead, describe WHAT KIND of information is present (e.g., "a conference poster listing multiple speaker sessions" instead of transcribing each speaker's name and talk title)
237
+ - Specific text in images is prone to misreading — only describe the general nature and purpose of such text
238
+ - Focus on the overall theme, mood, and context that the images convey
239
+
217
240
  ## Analysis Framework
218
241
 
219
242
  ### Information Categories to Extract
220
243
  - Industry-relevant visual elements
221
- - Text and numerical data within images
222
- - Key subjects (people, places, objects, infrastructure)
244
+ - General theme and purpose of text/data shown in images (without exact transcription)
245
+ - Key subjects (people, places, objects, infrastructure) described at a general level
223
246
  - Contextual relationships to ${this.expertFields.join(', ')}
224
247
  - Information gaps filled by visual analysis
225
248
 
226
249
  ### Quality Standards
227
- - Accuracy and specificity in descriptions
250
+ - High-level accuracy in describing the overall context
228
251
  - Professional relevance for industry practitioners
229
252
  - Integration with accompanying text content
230
- - Completeness in covering all visual information
253
+ - Preference for general descriptions over specific details from image text
231
254
 
232
255
  ## Output Specifications
233
256
  - Language: ${this.options.content.outputLanguage}
234
257
  - Format: Single cohesive explanation (not numbered list)
235
- - Focus: Practical insights for industry professionals
236
- - Integration: Seamlessly merge all extracted information`;
258
+ - Focus: High-level context and practical insights for industry professionals
259
+ - Integration: Seamlessly merge all extracted information
260
+ - Granularity: Describe the general nature of visual content — avoid quoting specific names, titles, figures, or exact text from images`;
237
261
  }
238
262
  get imageUrls() {
239
263
  // Markdown image pattern: ![alt text](url) or ![](url)
@@ -280,9 +304,9 @@ Analyze the provided images and synthesize your findings into a single comprehen
280
304
 
281
305
  1. **Identifies Visual Content**: Extract industry-specific elements, infrastructure, and stakeholders relevant to ${this.expertFields.join(', ')}
282
306
 
283
- 2. **Captures Text & Data**: Accurately read and include all visible text, numerical data, charts, and graphs
307
+ 2. **Summarizes Visual Text & Data**: Describe the general theme and purpose of any text, numerical data, charts, or graphs shown in images — do NOT transcribe specific names, titles, exact numbers, or quoted phrases
284
308
 
285
- 3. **Describes Visual Elements**: Detail important subjects (people, places, objects) and their significance
309
+ 3. **Describes Visual Elements**: Detail important subjects (people, places, objects) and their significance at a general level
286
310
 
287
311
  4. **Establishes Connections**: Link visual information to ${this.expertFields.join(', ')} context and article content
288
312
 
@@ -290,6 +314,8 @@ Analyze the provided images and synthesize your findings into a single comprehen
290
314
 
291
315
  6. **Complements Text**: Add visual insights not covered in the article text
292
316
 
317
+ **Important**: Do NOT attempt to exactly transcribe text within images (names, titles, numbers, dates). Instead, describe what kind of information is shown. Exact text from images is unreliable and may contain errors.
318
+
293
319
  **Format**: Present all findings as one flowing narrative without enumeration.`,
294
320
  };
295
321
  }
@@ -307,12 +333,10 @@ class ClassifyTags extends LLMQuery {
307
333
  }
308
334
  async execute({ existTags }) {
309
335
  this.existTags = existTags;
310
- const { output, usage } = await ai.generateText({
336
+ const { output, usage } = await generateObjectByLLM({
311
337
  model: this.model,
312
338
  maxRetries: this.options.llm.maxRetries,
313
- output: ai.Output.object({
314
- schema: this.schema,
315
- }),
339
+ schema: this.schema,
316
340
  system: this.systemPrompt,
317
341
  prompt: this.userPrompt,
318
342
  });
@@ -389,12 +413,10 @@ class DetermineArticleImportance extends LLMQuery {
389
413
  this.dateService = config.dateService;
390
414
  }
391
415
  async execute() {
392
- const { output, usage } = await ai.generateText({
416
+ const { output, usage } = await generateObjectByLLM({
393
417
  model: this.model,
394
418
  maxRetries: this.options.llm.maxRetries,
395
- output: ai.Output.object({
396
- schema: this.schema,
397
- }),
419
+ schema: this.schema,
398
420
  system: this.systemPrompt,
399
421
  prompt: this.userPrompt,
400
422
  });
@@ -931,7 +953,7 @@ let GenerateNewsletter$1 = class GenerateNewsletter extends BaseLLMQuery {
931
953
  this.newsletterBrandName = config.newsletterBrandName;
932
954
  }
933
955
  async execute() {
934
- const { output, usage, finishReason } = await ai.generateText({
956
+ const { output, usage, finishReason } = await generateObjectByLLM({
935
957
  model: this.model,
936
958
  maxRetries: this.options.llm.maxRetries,
937
959
  maxOutputTokens: this.maxOutputTokens,
@@ -940,9 +962,7 @@ let GenerateNewsletter$1 = class GenerateNewsletter extends BaseLLMQuery {
940
962
  topK: this.topK,
941
963
  presencePenalty: this.presencePenalty,
942
964
  frequencyPenalty: this.frequencyPenalty,
943
- output: ai.Output.object({
944
- schema: this.schema,
945
- }),
965
+ schema: this.schema,
946
966
  system: this.systemPrompt,
947
967
  prompt: this.userPrompt,
948
968
  });
@@ -977,6 +997,7 @@ Important rule for displaying date ranges: When displaying date ranges, you must
977
997
  4. **Verifiable Information**: All information must be directly verifiable from the provided sources.
978
998
  5. **No Speculation**: Do not use speculative expressions like "appears to be" or "is expected to".
979
999
  6. **No Fictional Standards/Policies**: Do not mention non-existent standards/policies or systems incorrectly reported as planned for future implementation.
1000
+ 7. **Image Analysis as Supplementary Context Only**: Image analysis results are provided solely for understanding the general visual context of articles. Do NOT quote specific names, titles, numbers, or detailed facts from image analysis in the newsletter body — these may contain inaccuracies. Only use image analysis to understand the broad theme or mood of the article's visual content.
980
1001
 
981
1002
  Roles:
982
1003
  - Friendly Guide: Deliver information like a trusted colleague rather than a rigid expert. Use appropriate emoticons in titles and section headings to improve readability.
@@ -1099,7 +1120,7 @@ ${this.targetArticles
1099
1120
  **Tags:** ${[post.tag1, post.tag2, post.tag3].filter(Boolean).join(', ')}
1100
1121
  **Content Type:** ${post.contentType}
1101
1122
  **URL:** ${post.url}
1102
- ${post.imageContextByLlm ? `**Image Analysis:** ${post.imageContextByLlm}` : ''}
1123
+ ${post.imageContextByLlm ? `**Image Analysis (supplementary context only — do not cite specific details from this in the newsletter):** ${post.imageContextByLlm}` : ''}
1103
1124
  `)
1104
1125
  .join('\n\n')}
1105
1126
 
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { RunnablePassthrough, RunnableSequence } from '@langchain/core/runnables';
2
2
  import { pick, omit } from 'es-toolkit';
3
- import { generateText, Output } from 'ai';
4
3
  import { z } from 'zod';
4
+ import { generateText, Output } from 'ai';
5
5
  import { JSDOM } from 'jsdom';
6
6
  import juice from 'juice';
7
7
  import safeMarkdown2Html from 'safe-markdown2html';
@@ -89,6 +89,25 @@ class LoggingExecutor {
89
89
  }
90
90
  }
91
91
 
92
+ async function generateObjectByLLM({ schema, ...rest }) {
93
+ const result = await generateText({
94
+ ...rest,
95
+ output: Output.object({ schema }),
96
+ // Anthropic truncates structured output when it contains quotation marks.
97
+ // Using 'jsonTool' mode avoids this issue.
98
+ providerOptions: {
99
+ anthropic: {
100
+ structuredOutputMode: 'jsonTool',
101
+ },
102
+ },
103
+ });
104
+ return {
105
+ output: result.output,
106
+ usage: result.usage,
107
+ finishReason: result.finishReason,
108
+ };
109
+ }
110
+
92
111
  /**
93
112
  * Replaces ASCII double quotes with Unicode smart quotes (U+201C, U+201D).
94
113
  * Prevents JSON structured output corruption when LLM reproduces quoted titles.
@@ -171,7 +190,7 @@ class AnalyzeImages extends LLMQuery {
171
190
  schema = z.object({
172
191
  imageContext: z
173
192
  .string()
174
- .describe('A comprehensive description of all information extracted from the images'),
193
+ .describe('A high-level overview of the general theme, mood, and context conveyed by the images (without specific names, titles, or exact figures from text within images)'),
175
194
  });
176
195
  constructor(config) {
177
196
  super(config);
@@ -184,12 +203,10 @@ class AnalyzeImages extends LLMQuery {
184
203
  if (this.imageMessages.length === 0) {
185
204
  return { result: null, usage: ZERO_USAGE };
186
205
  }
187
- const { output, usage } = await generateText({
206
+ const { output, usage } = await generateObjectByLLM({
188
207
  model: this.model,
189
208
  maxRetries: this.options.llm.maxRetries,
190
- output: Output.object({
191
- schema: this.schema,
192
- }),
209
+ schema: this.schema,
193
210
  system: this.systemPrompt,
194
211
  messages: [
195
212
  {
@@ -209,29 +226,36 @@ You are a specialized image analysis expert in: ${this.expertFields.join(', ')}
209
226
  ## Core Responsibilities
210
227
  1. Extract visual information unavailable from text alone
211
228
  2. Identify industry-specific elements, facilities, and stakeholders
212
- 3. Accurately read and transcribe text, charts, and data visualizations
229
+ 3. Summarize the general theme and context of charts, data visualizations, and text within images at a high level
213
230
  4. Synthesize visual information with article context
214
231
 
232
+ ## Critical Rule: NO Detailed Text Transcription
233
+ - Do NOT transcribe specific names, titles, numbers, dates, or exact phrases from text within images
234
+ - Instead, describe WHAT KIND of information is present (e.g., "a conference poster listing multiple speaker sessions" instead of transcribing each speaker's name and talk title)
235
+ - Specific text in images is prone to misreading — only describe the general nature and purpose of such text
236
+ - Focus on the overall theme, mood, and context that the images convey
237
+
215
238
  ## Analysis Framework
216
239
 
217
240
  ### Information Categories to Extract
218
241
  - Industry-relevant visual elements
219
- - Text and numerical data within images
220
- - Key subjects (people, places, objects, infrastructure)
242
+ - General theme and purpose of text/data shown in images (without exact transcription)
243
+ - Key subjects (people, places, objects, infrastructure) described at a general level
221
244
  - Contextual relationships to ${this.expertFields.join(', ')}
222
245
  - Information gaps filled by visual analysis
223
246
 
224
247
  ### Quality Standards
225
- - Accuracy and specificity in descriptions
248
+ - High-level accuracy in describing the overall context
226
249
  - Professional relevance for industry practitioners
227
250
  - Integration with accompanying text content
228
- - Completeness in covering all visual information
251
+ - Preference for general descriptions over specific details from image text
229
252
 
230
253
  ## Output Specifications
231
254
  - Language: ${this.options.content.outputLanguage}
232
255
  - Format: Single cohesive explanation (not numbered list)
233
- - Focus: Practical insights for industry professionals
234
- - Integration: Seamlessly merge all extracted information`;
256
+ - Focus: High-level context and practical insights for industry professionals
257
+ - Integration: Seamlessly merge all extracted information
258
+ - Granularity: Describe the general nature of visual content — avoid quoting specific names, titles, figures, or exact text from images`;
235
259
  }
236
260
  get imageUrls() {
237
261
  // Markdown image pattern: ![alt text](url) or ![](url)
@@ -278,9 +302,9 @@ Analyze the provided images and synthesize your findings into a single comprehen
278
302
 
279
303
  1. **Identifies Visual Content**: Extract industry-specific elements, infrastructure, and stakeholders relevant to ${this.expertFields.join(', ')}
280
304
 
281
- 2. **Captures Text & Data**: Accurately read and include all visible text, numerical data, charts, and graphs
305
+ 2. **Summarizes Visual Text & Data**: Describe the general theme and purpose of any text, numerical data, charts, or graphs shown in images — do NOT transcribe specific names, titles, exact numbers, or quoted phrases
282
306
 
283
- 3. **Describes Visual Elements**: Detail important subjects (people, places, objects) and their significance
307
+ 3. **Describes Visual Elements**: Detail important subjects (people, places, objects) and their significance at a general level
284
308
 
285
309
  4. **Establishes Connections**: Link visual information to ${this.expertFields.join(', ')} context and article content
286
310
 
@@ -288,6 +312,8 @@ Analyze the provided images and synthesize your findings into a single comprehen
288
312
 
289
313
  6. **Complements Text**: Add visual insights not covered in the article text
290
314
 
315
+ **Important**: Do NOT attempt to exactly transcribe text within images (names, titles, numbers, dates). Instead, describe what kind of information is shown. Exact text from images is unreliable and may contain errors.
316
+
291
317
  **Format**: Present all findings as one flowing narrative without enumeration.`,
292
318
  };
293
319
  }
@@ -305,12 +331,10 @@ class ClassifyTags extends LLMQuery {
305
331
  }
306
332
  async execute({ existTags }) {
307
333
  this.existTags = existTags;
308
- const { output, usage } = await generateText({
334
+ const { output, usage } = await generateObjectByLLM({
309
335
  model: this.model,
310
336
  maxRetries: this.options.llm.maxRetries,
311
- output: Output.object({
312
- schema: this.schema,
313
- }),
337
+ schema: this.schema,
314
338
  system: this.systemPrompt,
315
339
  prompt: this.userPrompt,
316
340
  });
@@ -387,12 +411,10 @@ class DetermineArticleImportance extends LLMQuery {
387
411
  this.dateService = config.dateService;
388
412
  }
389
413
  async execute() {
390
- const { output, usage } = await generateText({
414
+ const { output, usage } = await generateObjectByLLM({
391
415
  model: this.model,
392
416
  maxRetries: this.options.llm.maxRetries,
393
- output: Output.object({
394
- schema: this.schema,
395
- }),
417
+ schema: this.schema,
396
418
  system: this.systemPrompt,
397
419
  prompt: this.userPrompt,
398
420
  });
@@ -929,7 +951,7 @@ let GenerateNewsletter$1 = class GenerateNewsletter extends BaseLLMQuery {
929
951
  this.newsletterBrandName = config.newsletterBrandName;
930
952
  }
931
953
  async execute() {
932
- const { output, usage, finishReason } = await generateText({
954
+ const { output, usage, finishReason } = await generateObjectByLLM({
933
955
  model: this.model,
934
956
  maxRetries: this.options.llm.maxRetries,
935
957
  maxOutputTokens: this.maxOutputTokens,
@@ -938,9 +960,7 @@ let GenerateNewsletter$1 = class GenerateNewsletter extends BaseLLMQuery {
938
960
  topK: this.topK,
939
961
  presencePenalty: this.presencePenalty,
940
962
  frequencyPenalty: this.frequencyPenalty,
941
- output: Output.object({
942
- schema: this.schema,
943
- }),
963
+ schema: this.schema,
944
964
  system: this.systemPrompt,
945
965
  prompt: this.userPrompt,
946
966
  });
@@ -975,6 +995,7 @@ Important rule for displaying date ranges: When displaying date ranges, you must
975
995
  4. **Verifiable Information**: All information must be directly verifiable from the provided sources.
976
996
  5. **No Speculation**: Do not use speculative expressions like "appears to be" or "is expected to".
977
997
  6. **No Fictional Standards/Policies**: Do not mention non-existent standards/policies or systems incorrectly reported as planned for future implementation.
998
+ 7. **Image Analysis as Supplementary Context Only**: Image analysis results are provided solely for understanding the general visual context of articles. Do NOT quote specific names, titles, numbers, or detailed facts from image analysis in the newsletter body — these may contain inaccuracies. Only use image analysis to understand the broad theme or mood of the article's visual content.
978
999
 
979
1000
  Roles:
980
1001
  - Friendly Guide: Deliver information like a trusted colleague rather than a rigid expert. Use appropriate emoticons in titles and section headings to improve readability.
@@ -1097,7 +1118,7 @@ ${this.targetArticles
1097
1118
  **Tags:** ${[post.tag1, post.tag2, post.tag3].filter(Boolean).join(', ')}
1098
1119
  **Content Type:** ${post.contentType}
1099
1120
  **URL:** ${post.url}
1100
- ${post.imageContextByLlm ? `**Image Analysis:** ${post.imageContextByLlm}` : ''}
1121
+ ${post.imageContextByLlm ? `**Image Analysis (supplementary context only — do not cite specific details from this in the newsletter):** ${post.imageContextByLlm}` : ''}
1101
1122
  `)
1102
1123
  .join('\n\n')}
1103
1124
 
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@llm-newsletter-kit/core",
3
3
  "private": false,
4
4
  "type": "module",
5
- "version": "1.3.7",
5
+ "version": "1.3.9",
6
6
  "description": "An extensible framework to automate your entire newsletter workflow. Handles data collection, LLM-based content analysis, and email generation, letting you focus on your unique domain logic.",
7
7
  "main": "dist/index.cjs",
8
8
  "module": "dist/index.js",
@@ -48,36 +48,36 @@
48
48
  "author": "kimhongyeon",
49
49
  "license": "Apache-2.0",
50
50
  "dependencies": {
51
- "@langchain/core": "^1.1.32",
52
- "ai": "^6.0.116",
51
+ "@langchain/core": "^1.1.39",
52
+ "ai": "^6.0.154",
53
53
  "es-toolkit": "^1.45.1",
54
- "jsdom": "^29.0.0",
54
+ "jsdom": "^29.0.2",
55
55
  "juice": "^11.1.1",
56
56
  "safe-markdown2html": "^1.0.1",
57
57
  "zod": "^4.3.6"
58
58
  },
59
59
  "devDependencies": {
60
- "@ai-sdk/anthropic": "^3.0.58",
61
- "@ai-sdk/google": "^3.0.43",
62
- "@ai-sdk/openai": "^3.0.41",
63
- "@ai-sdk/togetherai": "^2.0.39",
60
+ "@ai-sdk/anthropic": "^3.0.68",
61
+ "@ai-sdk/google": "^3.0.60",
62
+ "@ai-sdk/openai": "^3.0.52",
63
+ "@ai-sdk/togetherai": "^2.0.45",
64
64
  "@eslint/js": "^10.0.1",
65
65
  "@trivago/prettier-plugin-sort-imports": "^6.0.2",
66
- "@types/jsdom": "^28.0.0",
67
- "@types/node": "^25.5.0",
68
- "@vitest/coverage-v8": "^4.1.0",
69
- "@vitest/expect": "^4.1.0",
70
- "eslint": "^10.0.3",
66
+ "@types/jsdom": "^28.0.1",
67
+ "@types/node": "^25.5.2",
68
+ "@vitest/coverage-v8": "^4.1.4",
69
+ "@vitest/expect": "^4.1.4",
70
+ "eslint": "^10.2.0",
71
71
  "eslint-plugin-unused-imports": "^4.4.1",
72
72
  "prettier": "^3.8.1",
73
73
  "rimraf": "^6.1.3",
74
- "rollup": "^4.59.0",
75
- "rollup-plugin-dts": "^6.4.0",
76
- "rollup-plugin-typescript2": "^0.36.0",
74
+ "rollup": "^4.60.1",
75
+ "rollup-plugin-dts": "^6.4.1",
76
+ "rollup-plugin-typescript2": "^0.37.0",
77
77
  "tsx": "^4.21.0",
78
- "typescript": "^5.9.3",
79
- "typescript-eslint": "^8.57.0",
80
- "vitest": "^4.1.0"
78
+ "typescript": "^6.0.2",
79
+ "typescript-eslint": "^8.58.1",
80
+ "vitest": "^4.1.4"
81
81
  },
82
82
  "repository": {
83
83
  "type": "git",