@llm-newsletter-kit/core 1.3.11 → 2.0.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.
package/README.md CHANGED
@@ -87,8 +87,8 @@ const config: GenerateNewsletterConfig<string> = {
87
87
  // titleContext: 'AI Weekly', // Optional: keyword to include in title
88
88
  },
89
89
  dateService: {
90
- getCurrentISODateString: () => new Date().toISOString().split('T')[0],
91
- getDisplayDateString: () => new Date().toLocaleDateString('en-US'),
90
+ getPublicationISODateString: () => new Date().toISOString().split('T')[0],
91
+ getPublicationDisplayDateString: () => new Date().toLocaleDateString('en-US'),
92
92
  },
93
93
  taskService: {
94
94
  start: async () => `task-${Date.now()}`,
package/dist/index.cjs CHANGED
@@ -444,15 +444,23 @@ Importance Score Criteria (${this.minPoint}-10):
444
444
  5-6: General important information limited to specific fields or regions (e.g., small project permits, general event notices, small-scale bids)
445
445
  4-5: General industry news or small/medium-scale event information
446
446
  2-3: Simple information sharing or repetitive daily news
447
- ${this.hasHigherMinimumScore ? '' : `1: Information without current significance - Expired support programs, past events, invalid bid notices or recruitment information, notices that have lost practical value, or administrative/simple notices like "membership fee status", "meeting minutes", "internal schedule notices"`}
447
+ ${this.hasHigherMinimumScore ? '' : `1: **Information without current practical value** - Expired support programs, past events, invalid bid notices or recruitment information, notices that have lost practical value, or administrative/simple notices like "membership fee status", "meeting minutes", "internal schedule notices"`}
448
448
 
449
449
  Evaluation Criteria:
450
450
  - Academic Value: Journal publications, research reports, academic seminars/symposiums, research output presentations etc. minimum 7 points (knowledge base expansion and long-term reference value)
451
451
  - Practical Impact: Information requiring immediate response like policies, regulations, bids, recruitment
452
452
  - Impact Range: How many stakeholders are affected
453
453
  - Scarcity: How rare and exclusive the information is
454
- - Temporal Context: Practical value at current time considering deadlines, event schedules${this.hasHigherMinimumScore ? '' : ' (However, recent academic achievements maintain high scores)'}
455
-
454
+ - Temporal Context: Practical value as of the Newsletter Publication Date considering deadlines, event schedules${this.hasHigherMinimumScore ? '' : ' (However, recent academic achievements maintain high scores)'}
455
+ ${this.hasHigherMinimumScore
456
+ ? ''
457
+ : `
458
+ **HARD RULE — Temporal Expiration (MUST):**
459
+ - Compare the Newsletter Publication Date (given in the user prompt) against any deadline, application period, event date, bid closing date, recruitment period, or validity period mentioned in the article (and the Article Published Date when provided).
460
+ - If the article's deadline/event has already passed relative to the Newsletter Publication Date, you MUST score it 1, regardless of other criteria. This overrides all other considerations.
461
+ - Exception: Academic outputs (journal publications, published research, completed conference proceedings) retain their score based on reference value; do not downgrade these under this rule.
462
+ - If no deadline/event is mentioned and no temporal cue is available, this rule does not apply.
463
+ `}
456
464
  Important Notes:
457
465
  - Evaluate considering characteristics and context of ${this.expertFields.join(', ')} fields.
458
466
  - Be sensitive to core keywords, events, policies considered important in the field.`;
@@ -460,7 +468,10 @@ Important Notes:
460
468
  get userPrompt() {
461
469
  return `Please rate the importance of this article from ${this.minPoint} to 10.
462
470
 
463
- **Current Date:** ${this.dateService.getCurrentISODateString()}
471
+ **Newsletter Publication Date:** ${this.dateService.getPublicationISODateString()}${this.targetArticle.publishedDate
472
+ ? `
473
+ **Article Published Date:** ${this.targetArticle.publishedDate}`
474
+ : ''}
464
475
 
465
476
  **Title:** ${this.targetArticle.title || 'No Title'}
466
477
 
@@ -470,7 +481,11 @@ Important Notes:
470
481
  ${this.targetArticle.imageContextByLlm
471
482
  ? `
472
483
  **Image Analysis:** ${this.targetArticle.imageContextByLlm}`
473
- : ''}`;
484
+ : ''}${this.hasHigherMinimumScore
485
+ ? ''
486
+ : `
487
+
488
+ Before assigning a score, explicitly check whether any deadline, application period, event date, bid closing date, or recruitment period in the article has already passed relative to the Newsletter Publication Date above. If so and the HARD RULE applies, assign 1.`}`;
474
489
  }
475
490
  }
476
491
 
@@ -1001,6 +1016,13 @@ Roles:
1001
1016
  - Credibility Builder: All information must be provided with sources. Whenever specific content or titles are mentioned in the body, links must be provided in [original title](URL) format. Understand that source citation is not just formal but a key element in enhancing newsletter credibility and accessibility.
1002
1017
  - Fact Checker: Use only facts from provided source materials. Do not make unsubstantiated claims or speculate beyond the materials.
1003
1018
 
1019
+ **Temporal Validity (HARD RULE):**
1020
+ The current issue's Newsletter Publication Date is provided in the user prompt. For every article you consider including:
1021
+ - If the article's deadline, application period, event date, bid closing date, or recruitment period has already passed relative to the Newsletter Publication Date, you MUST EXCLUDE the article from the newsletter body entirely, regardless of its importance score.
1022
+ - Exception: Academic outputs (published journal articles, research outputs, past conference proceedings with reference value) may be retained.
1023
+ - If the article provides an Article Published Date and it is older than 30 days relative to the Newsletter Publication Date, treat it as suspicious for freshness and include only if it still has clear forward-looking relevance (e.g., an ongoing program whose deadline has not passed).
1024
+ - Do not list or mention excluded articles even as "also notable" or in tables.
1025
+
1004
1026
  **Important Prohibitions:**
1005
1027
  - Do not bundle or omit structured list items (permits/reports/notices etc.) with "... and n more" etc. (tables must list all items in individual rows).
1006
1028
  - Do not describe policies or plans of governments/organizations/companies not explicitly mentioned in sources as facts.
@@ -1034,9 +1056,9 @@ Copyright Protection & Fact-Checking Principles:
1034
1056
  Output Format & Requirements:
1035
1057
  1. Language: ${this.options.content.outputLanguage}
1036
1058
 
1037
- 2. Start: ${this.options.content.freeFormIntro ? 'Begin directly with the Overall Briefing section (no separate opening heading or greeting).' : `Specify date (${this.dateService.getDisplayDateString()}) and begin with neutral, objective greeting. Briefly introduce key factual information to be covered in today's newsletter.`}
1059
+ 2. Start: ${this.options.content.freeFormIntro ? 'Begin directly with the Overall Briefing section (no separate opening heading or greeting).' : `Specify date (${this.dateService.getPublicationDisplayDateString()}) and begin with neutral, objective greeting. Briefly introduce key factual information to be covered in today's newsletter.`}
1038
1060
 
1039
- 3. Overall Briefing: Before the main listing, create a briefing section conveying objective facts about today's news${this.options.content.freeFormIntro ? `. Structure: Start with a Heading 2 (##) briefing section heading in the format "## 📮 ${this.dateService.getDisplayDateString()} [Briefing/Summary word in output language]" (e.g., "## 📮 2월 6일 브리핑" for Korean, "## 📮 Feb 6 Briefing" for English) — do NOT include domain or field names in the heading. Immediately follow with a brief paragraph introducing key factual information to be covered in today's newsletter, then include the following bullet points:` : ' in these aspects:'}
1061
+ 3. Overall Briefing: Before the main listing, create a briefing section conveying objective facts about today's news${this.options.content.freeFormIntro ? `. Structure: Start with a Heading 2 (##) briefing section heading in the format "## 📮 ${this.dateService.getPublicationDisplayDateString()} [Briefing/Summary word in output language]" (e.g., "## 📮 2월 6일 브리핑" for Korean, "## 📮 Feb 6 Briefing" for English) — do NOT include domain or field names in the heading. Immediately follow with a brief paragraph introducing key factual information to be covered in today's newsletter, then include the following bullet points:` : ' in these aspects:'}
1040
1062
  - Key Trends: Explain major patterns or trends found in this news based on data. Ex: 'Over 00% of today's news relates to 00'.
1041
1063
  - Immediate Impact: Emphasize most important changes or decisions affecting industry immediately, specifically mentioning which fields will be most impacted.
1042
1064
 
@@ -1096,7 +1118,7 @@ Output Format & Requirements:
1096
1118
 
1097
1119
  8. Additional Requirements:
1098
1120
  - Comprehensively analyze posts to create email containing most important information for ${this.expertFields.join(', ')} field experts.
1099
- ${this.options.content.freeFormIntro ? '' : `- Naturally include date at beginning in the format: "${this.dateService.getDisplayDateString()} ${this.expertFields.join(', ')} [News Term]". Replace [News Term] with the word for "News" appropriate for the output language (e.g., "News" for English, "소식" for Korean). Declare this part as \`Heading 1\`(#).\n `}- Write body in markdown format, effectively using headings(#, ##, ###), bold(**), italics(_), bullet points(-, *) etc. to improve readability.
1121
+ ${this.options.content.freeFormIntro ? '' : `- Naturally include date at beginning in the format: "${this.dateService.getPublicationDisplayDateString()} ${this.expertFields.join(', ')} [News Term]". Replace [News Term] with the word for "News" appropriate for the output language (e.g., "News" for English, "소식" for Korean). Declare this part as \`Heading 1\`(#).\n `}- Write body in markdown format, effectively using headings(#, ##, ###), bold(**), italics(_), bullet points(-, *) etc. to improve readability.
1100
1122
  - Group related news to provide broader context, and mention development status if there's continuity with content covered in previous issues.
1101
1123
  - **Source citation is most important for ensuring credibility.** Must provide links in [original title](URL) format using source's title. Do not write as "View", "Article", "[Post3](URL)" format.
1102
1124
  - Specify source whenever article titles or content are quoted in newsletter, ensure all information is provided with links.
@@ -1115,7 +1137,7 @@ ${this.targetArticles
1115
1137
  **Importance:** ${post.importanceScore}/10
1116
1138
  **Tags:** ${[post.tag1, post.tag2, post.tag3].filter(Boolean).join(', ')}
1117
1139
  **Content Type:** ${post.contentType}
1118
- **URL:** ${post.url}
1140
+ **URL:** ${post.url}${post.publishedDate ? `\n**Published Date:** ${post.publishedDate}` : ''}
1119
1141
  ${post.imageContextByLlm ? `**Image Analysis (supplementary context only — do not cite specific details from this in the newsletter):** ${post.imageContextByLlm}` : ''}
1120
1142
  `)
1121
1143
  .join('\n\n')}
@@ -1123,7 +1145,11 @@ ${post.imageContextByLlm ? `**Image Analysis (supplementary context only — do
1123
1145
 
1124
1146
  ---
1125
1147
  **Comprehensive Analysis and Daily Newsletter Generation Request:**
1126
- Based on all post information provided above, please generate a ${this.expertFields.join(', ')} trends newsletter for ${this.dateService.getDisplayDateString()}. Please note the following:
1148
+ **Newsletter Publication Date:** ${this.dateService.getPublicationISODateString()} (${this.dateService.getPublicationDisplayDateString()})
1149
+
1150
+ Based on all post information provided above, please generate a ${this.expertFields.join(', ')} trends newsletter for ${this.dateService.getPublicationDisplayDateString()}. Please note the following:
1151
+
1152
+ 0. **TEMPORAL VALIDITY (HIGHEST PRIORITY):** Before anything else, apply the Temporal Validity HARD RULE from the system prompt. Any post whose deadline/event has passed relative to the Newsletter Publication Date above MUST be excluded from the newsletter body. Do not reference excluded posts anywhere.
1127
1153
 
1128
1154
  1. **STRICT LENGTH CONTROL BY IMPORTANCE SCORE:**
1129
1155
  - 9-10 points: Full detailed coverage allowed (Key Facts + Targets + Dates + Related Facts)
@@ -1300,7 +1326,7 @@ class ContentGenerateChain extends Chain {
1300
1326
  ...coreContent,
1301
1327
  htmlBody: juice(html),
1302
1328
  issueOrder: this.provider.issueOrder,
1303
- date: this.dateService.getCurrentISODateString(),
1329
+ date: this.dateService.getPublicationISODateString(),
1304
1330
  },
1305
1331
  usedArticles: candidateArticles,
1306
1332
  });
@@ -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.d.ts CHANGED
@@ -98,6 +98,14 @@ type UnscoredArticle = {
98
98
  * @example "https://example.com/board/notice"
99
99
  */
100
100
  targetUrl: UrlString;
101
+ /**
102
+ * (Optional) Original posting/publication date of the article in ISO format (YYYY-MM-DD).
103
+ * When provided, this is used by LLM queries to judge temporal validity — for example,
104
+ * whether deadlines or event dates have passed relative to the newsletter publication date.
105
+ * Implementations that cannot reliably extract this value may omit it.
106
+ * @example "2024-10-12"
107
+ */
108
+ publishedDate?: IsoDateString;
101
109
  };
102
110
  /**
103
111
  * Article type used after the analysis phase (image/tagging/score) for updates.
@@ -456,19 +464,28 @@ interface EmailService {
456
464
  }
457
465
  /**
458
466
  * Service that provides dates for internal use or insertion into the newsletter.
459
- * Clients can consider locale/language/timezone themselves.
467
+ *
468
+ * Semantics: every method on this interface represents the **newsletter publication
469
+ * date** — i.e. the date the issue is (or will be) published. This may not be
470
+ * "today" in wall-clock terms: if a caller builds an issue the night before its
471
+ * scheduled release, they should inject tomorrow's date here.
472
+ *
473
+ * Clients are responsible for locale/language/timezone handling in their
474
+ * implementation.
460
475
  */
461
476
  interface DateService {
462
477
  /**
463
- * Return current date in ISO format (YYYY-MM-DD).
478
+ * Return the newsletter publication date in ISO format (YYYY-MM-DD).
464
479
  * @returns ISO date string
465
480
  * @example "2024-10-15"
466
481
  */
467
- getCurrentISODateString: () => IsoDateString;
482
+ getPublicationISODateString: () => IsoDateString;
468
483
  /**
469
- * Return a localized display date string for use in newsletter content.
484
+ * Return a localized display string of the newsletter publication date
485
+ * for use in newsletter content.
486
+ * @example "10월 15일"
470
487
  */
471
- getDisplayDateString: () => string;
488
+ getPublicationDisplayDateString: () => string;
472
489
  }
473
490
 
474
491
  /**
package/dist/index.js CHANGED
@@ -442,15 +442,23 @@ Importance Score Criteria (${this.minPoint}-10):
442
442
  5-6: General important information limited to specific fields or regions (e.g., small project permits, general event notices, small-scale bids)
443
443
  4-5: General industry news or small/medium-scale event information
444
444
  2-3: Simple information sharing or repetitive daily news
445
- ${this.hasHigherMinimumScore ? '' : `1: Information without current significance - Expired support programs, past events, invalid bid notices or recruitment information, notices that have lost practical value, or administrative/simple notices like "membership fee status", "meeting minutes", "internal schedule notices"`}
445
+ ${this.hasHigherMinimumScore ? '' : `1: **Information without current practical value** - Expired support programs, past events, invalid bid notices or recruitment information, notices that have lost practical value, or administrative/simple notices like "membership fee status", "meeting minutes", "internal schedule notices"`}
446
446
 
447
447
  Evaluation Criteria:
448
448
  - Academic Value: Journal publications, research reports, academic seminars/symposiums, research output presentations etc. minimum 7 points (knowledge base expansion and long-term reference value)
449
449
  - Practical Impact: Information requiring immediate response like policies, regulations, bids, recruitment
450
450
  - Impact Range: How many stakeholders are affected
451
451
  - Scarcity: How rare and exclusive the information is
452
- - Temporal Context: Practical value at current time considering deadlines, event schedules${this.hasHigherMinimumScore ? '' : ' (However, recent academic achievements maintain high scores)'}
453
-
452
+ - Temporal Context: Practical value as of the Newsletter Publication Date considering deadlines, event schedules${this.hasHigherMinimumScore ? '' : ' (However, recent academic achievements maintain high scores)'}
453
+ ${this.hasHigherMinimumScore
454
+ ? ''
455
+ : `
456
+ **HARD RULE — Temporal Expiration (MUST):**
457
+ - Compare the Newsletter Publication Date (given in the user prompt) against any deadline, application period, event date, bid closing date, recruitment period, or validity period mentioned in the article (and the Article Published Date when provided).
458
+ - If the article's deadline/event has already passed relative to the Newsletter Publication Date, you MUST score it 1, regardless of other criteria. This overrides all other considerations.
459
+ - Exception: Academic outputs (journal publications, published research, completed conference proceedings) retain their score based on reference value; do not downgrade these under this rule.
460
+ - If no deadline/event is mentioned and no temporal cue is available, this rule does not apply.
461
+ `}
454
462
  Important Notes:
455
463
  - Evaluate considering characteristics and context of ${this.expertFields.join(', ')} fields.
456
464
  - Be sensitive to core keywords, events, policies considered important in the field.`;
@@ -458,7 +466,10 @@ Important Notes:
458
466
  get userPrompt() {
459
467
  return `Please rate the importance of this article from ${this.minPoint} to 10.
460
468
 
461
- **Current Date:** ${this.dateService.getCurrentISODateString()}
469
+ **Newsletter Publication Date:** ${this.dateService.getPublicationISODateString()}${this.targetArticle.publishedDate
470
+ ? `
471
+ **Article Published Date:** ${this.targetArticle.publishedDate}`
472
+ : ''}
462
473
 
463
474
  **Title:** ${this.targetArticle.title || 'No Title'}
464
475
 
@@ -468,7 +479,11 @@ Important Notes:
468
479
  ${this.targetArticle.imageContextByLlm
469
480
  ? `
470
481
  **Image Analysis:** ${this.targetArticle.imageContextByLlm}`
471
- : ''}`;
482
+ : ''}${this.hasHigherMinimumScore
483
+ ? ''
484
+ : `
485
+
486
+ Before assigning a score, explicitly check whether any deadline, application period, event date, bid closing date, or recruitment period in the article has already passed relative to the Newsletter Publication Date above. If so and the HARD RULE applies, assign 1.`}`;
472
487
  }
473
488
  }
474
489
 
@@ -999,6 +1014,13 @@ Roles:
999
1014
  - Credibility Builder: All information must be provided with sources. Whenever specific content or titles are mentioned in the body, links must be provided in [original title](URL) format. Understand that source citation is not just formal but a key element in enhancing newsletter credibility and accessibility.
1000
1015
  - Fact Checker: Use only facts from provided source materials. Do not make unsubstantiated claims or speculate beyond the materials.
1001
1016
 
1017
+ **Temporal Validity (HARD RULE):**
1018
+ The current issue's Newsletter Publication Date is provided in the user prompt. For every article you consider including:
1019
+ - If the article's deadline, application period, event date, bid closing date, or recruitment period has already passed relative to the Newsletter Publication Date, you MUST EXCLUDE the article from the newsletter body entirely, regardless of its importance score.
1020
+ - Exception: Academic outputs (published journal articles, research outputs, past conference proceedings with reference value) may be retained.
1021
+ - If the article provides an Article Published Date and it is older than 30 days relative to the Newsletter Publication Date, treat it as suspicious for freshness and include only if it still has clear forward-looking relevance (e.g., an ongoing program whose deadline has not passed).
1022
+ - Do not list or mention excluded articles even as "also notable" or in tables.
1023
+
1002
1024
  **Important Prohibitions:**
1003
1025
  - Do not bundle or omit structured list items (permits/reports/notices etc.) with "... and n more" etc. (tables must list all items in individual rows).
1004
1026
  - Do not describe policies or plans of governments/organizations/companies not explicitly mentioned in sources as facts.
@@ -1032,9 +1054,9 @@ Copyright Protection & Fact-Checking Principles:
1032
1054
  Output Format & Requirements:
1033
1055
  1. Language: ${this.options.content.outputLanguage}
1034
1056
 
1035
- 2. Start: ${this.options.content.freeFormIntro ? 'Begin directly with the Overall Briefing section (no separate opening heading or greeting).' : `Specify date (${this.dateService.getDisplayDateString()}) and begin with neutral, objective greeting. Briefly introduce key factual information to be covered in today's newsletter.`}
1057
+ 2. Start: ${this.options.content.freeFormIntro ? 'Begin directly with the Overall Briefing section (no separate opening heading or greeting).' : `Specify date (${this.dateService.getPublicationDisplayDateString()}) and begin with neutral, objective greeting. Briefly introduce key factual information to be covered in today's newsletter.`}
1036
1058
 
1037
- 3. Overall Briefing: Before the main listing, create a briefing section conveying objective facts about today's news${this.options.content.freeFormIntro ? `. Structure: Start with a Heading 2 (##) briefing section heading in the format "## 📮 ${this.dateService.getDisplayDateString()} [Briefing/Summary word in output language]" (e.g., "## 📮 2월 6일 브리핑" for Korean, "## 📮 Feb 6 Briefing" for English) — do NOT include domain or field names in the heading. Immediately follow with a brief paragraph introducing key factual information to be covered in today's newsletter, then include the following bullet points:` : ' in these aspects:'}
1059
+ 3. Overall Briefing: Before the main listing, create a briefing section conveying objective facts about today's news${this.options.content.freeFormIntro ? `. Structure: Start with a Heading 2 (##) briefing section heading in the format "## 📮 ${this.dateService.getPublicationDisplayDateString()} [Briefing/Summary word in output language]" (e.g., "## 📮 2월 6일 브리핑" for Korean, "## 📮 Feb 6 Briefing" for English) — do NOT include domain or field names in the heading. Immediately follow with a brief paragraph introducing key factual information to be covered in today's newsletter, then include the following bullet points:` : ' in these aspects:'}
1038
1060
  - Key Trends: Explain major patterns or trends found in this news based on data. Ex: 'Over 00% of today's news relates to 00'.
1039
1061
  - Immediate Impact: Emphasize most important changes or decisions affecting industry immediately, specifically mentioning which fields will be most impacted.
1040
1062
 
@@ -1094,7 +1116,7 @@ Output Format & Requirements:
1094
1116
 
1095
1117
  8. Additional Requirements:
1096
1118
  - Comprehensively analyze posts to create email containing most important information for ${this.expertFields.join(', ')} field experts.
1097
- ${this.options.content.freeFormIntro ? '' : `- Naturally include date at beginning in the format: "${this.dateService.getDisplayDateString()} ${this.expertFields.join(', ')} [News Term]". Replace [News Term] with the word for "News" appropriate for the output language (e.g., "News" for English, "소식" for Korean). Declare this part as \`Heading 1\`(#).\n `}- Write body in markdown format, effectively using headings(#, ##, ###), bold(**), italics(_), bullet points(-, *) etc. to improve readability.
1119
+ ${this.options.content.freeFormIntro ? '' : `- Naturally include date at beginning in the format: "${this.dateService.getPublicationDisplayDateString()} ${this.expertFields.join(', ')} [News Term]". Replace [News Term] with the word for "News" appropriate for the output language (e.g., "News" for English, "소식" for Korean). Declare this part as \`Heading 1\`(#).\n `}- Write body in markdown format, effectively using headings(#, ##, ###), bold(**), italics(_), bullet points(-, *) etc. to improve readability.
1098
1120
  - Group related news to provide broader context, and mention development status if there's continuity with content covered in previous issues.
1099
1121
  - **Source citation is most important for ensuring credibility.** Must provide links in [original title](URL) format using source's title. Do not write as "View", "Article", "[Post3](URL)" format.
1100
1122
  - Specify source whenever article titles or content are quoted in newsletter, ensure all information is provided with links.
@@ -1113,7 +1135,7 @@ ${this.targetArticles
1113
1135
  **Importance:** ${post.importanceScore}/10
1114
1136
  **Tags:** ${[post.tag1, post.tag2, post.tag3].filter(Boolean).join(', ')}
1115
1137
  **Content Type:** ${post.contentType}
1116
- **URL:** ${post.url}
1138
+ **URL:** ${post.url}${post.publishedDate ? `\n**Published Date:** ${post.publishedDate}` : ''}
1117
1139
  ${post.imageContextByLlm ? `**Image Analysis (supplementary context only — do not cite specific details from this in the newsletter):** ${post.imageContextByLlm}` : ''}
1118
1140
  `)
1119
1141
  .join('\n\n')}
@@ -1121,7 +1143,11 @@ ${post.imageContextByLlm ? `**Image Analysis (supplementary context only — do
1121
1143
 
1122
1144
  ---
1123
1145
  **Comprehensive Analysis and Daily Newsletter Generation Request:**
1124
- Based on all post information provided above, please generate a ${this.expertFields.join(', ')} trends newsletter for ${this.dateService.getDisplayDateString()}. Please note the following:
1146
+ **Newsletter Publication Date:** ${this.dateService.getPublicationISODateString()} (${this.dateService.getPublicationDisplayDateString()})
1147
+
1148
+ Based on all post information provided above, please generate a ${this.expertFields.join(', ')} trends newsletter for ${this.dateService.getPublicationDisplayDateString()}. Please note the following:
1149
+
1150
+ 0. **TEMPORAL VALIDITY (HIGHEST PRIORITY):** Before anything else, apply the Temporal Validity HARD RULE from the system prompt. Any post whose deadline/event has passed relative to the Newsletter Publication Date above MUST be excluded from the newsletter body. Do not reference excluded posts anywhere.
1125
1151
 
1126
1152
  1. **STRICT LENGTH CONTROL BY IMPORTANCE SCORE:**
1127
1153
  - 9-10 points: Full detailed coverage allowed (Key Facts + Targets + Dates + Related Facts)
@@ -1298,7 +1324,7 @@ class ContentGenerateChain extends Chain {
1298
1324
  ...coreContent,
1299
1325
  htmlBody: juice(html),
1300
1326
  issueOrder: this.provider.issueOrder,
1301
- date: this.dateService.getCurrentISODateString(),
1327
+ date: this.dateService.getPublicationISODateString(),
1302
1328
  },
1303
1329
  usedArticles: candidateArticles,
1304
1330
  });
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.11",
5
+ "version": "2.0.1",
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.39",
52
- "ai": "^6.0.158",
53
- "es-toolkit": "^1.45.1",
54
- "jsdom": "^29.0.2",
51
+ "@langchain/core": "^1.1.45",
52
+ "ai": "^6.0.177",
53
+ "es-toolkit": "^1.46.1",
54
+ "jsdom": "^29.1.1",
55
55
  "juice": "^11.1.1",
56
- "safe-markdown2html": "^1.0.2",
57
- "zod": "^4.3.6"
56
+ "safe-markdown2html": "^1.0.3",
57
+ "zod": "^4.4.3"
58
58
  },
59
59
  "devDependencies": {
60
- "@ai-sdk/anthropic": "^3.0.69",
61
- "@ai-sdk/google": "^3.0.62",
62
- "@ai-sdk/openai": "^3.0.52",
63
- "@ai-sdk/togetherai": "^2.0.45",
60
+ "@ai-sdk/anthropic": "^3.0.76",
61
+ "@ai-sdk/google": "^3.0.71",
62
+ "@ai-sdk/openai": "^3.0.63",
63
+ "@ai-sdk/togetherai": "^2.0.51",
64
64
  "@eslint/js": "^10.0.1",
65
65
  "@trivago/prettier-plugin-sort-imports": "^6.0.2",
66
66
  "@types/jsdom": "^28.0.1",
67
- "@types/node": "^25.6.0",
68
- "@vitest/coverage-v8": "^4.1.4",
69
- "@vitest/expect": "^4.1.4",
70
- "eslint": "^10.2.0",
67
+ "@types/node": "^25.6.2",
68
+ "@vitest/coverage-v8": "^4.1.5",
69
+ "@vitest/expect": "^4.1.5",
70
+ "eslint": "^10.3.0",
71
71
  "eslint-plugin-unused-imports": "^4.4.1",
72
- "prettier": "^3.8.2",
72
+ "prettier": "^3.8.3",
73
73
  "rimraf": "^6.1.3",
74
- "rollup": "^4.60.1",
74
+ "rollup": "^4.60.3",
75
75
  "rollup-plugin-dts": "^6.4.1",
76
76
  "rollup-plugin-typescript2": "^0.37.0",
77
77
  "tsx": "^4.21.0",
78
- "typescript": "^6.0.2",
79
- "typescript-eslint": "^8.58.1",
80
- "vitest": "^4.1.4"
78
+ "typescript": "^6.0.3",
79
+ "typescript-eslint": "^8.59.2",
80
+ "vitest": "^4.1.5"
81
81
  },
82
82
  "repository": {
83
83
  "type": "git",