@llm-newsletter-kit/core 3.0.2 → 3.0.3
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 +62 -6
- package/dist/index.d.ts +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +22 -18
package/README.md
CHANGED
|
@@ -107,16 +107,16 @@ const config: GenerateNewsletterConfig<string> = {
|
|
|
107
107
|
},
|
|
108
108
|
analysisProvider: {
|
|
109
109
|
// Configure LLM models for analysis
|
|
110
|
-
classifyTagOptions: { model: openai('gpt-5-
|
|
111
|
-
analyzeImagesOptions: { model: openai('gpt-5.
|
|
112
|
-
determineScoreOptions: { model: openai('gpt-5.
|
|
110
|
+
classifyTagOptions: { model: openai('gpt-5.4-nano') },
|
|
111
|
+
analyzeImagesOptions: { model: openai('gpt-5.4-nano') },
|
|
112
|
+
determineScoreOptions: { model: openai('gpt-5.4-nano') },
|
|
113
113
|
fetchUnscoredArticles: async () => [/* ... */],
|
|
114
114
|
fetchTags: async () => [/* ... */],
|
|
115
115
|
update: async (article) => {},
|
|
116
116
|
},
|
|
117
117
|
contentGenerateProvider: {
|
|
118
118
|
// Configure content generation
|
|
119
|
-
model: openai('gpt-5.
|
|
119
|
+
model: openai('gpt-5.4-nano'),
|
|
120
120
|
issueOrder: 1,
|
|
121
121
|
newsletterBrandName: 'Tech Insight Weekly',
|
|
122
122
|
publicationCriteria: { minimumArticleCountForIssue: 5 },
|
|
@@ -281,21 +281,77 @@ Playground scripts let you run individual LLM query classes in isolation — no
|
|
|
281
281
|
```
|
|
282
282
|
|
|
283
283
|
3. Edit `playground/data/config.json` with your OpenAI API key and options.
|
|
284
|
-
4. Edit `playground/data/articles.json` with your target articles.
|
|
284
|
+
4. Edit `playground/data/articles.json` with your target articles. Both camelCase field names (`detailContent`, `targetUrl`, …) and snake_case DB dumps (`detail_content`, `target_url`, …) are accepted — snake_case records are normalized automatically.
|
|
285
285
|
5. (Optional) Replace `playground/data/template.html` with your actual email template.
|
|
286
286
|
|
|
287
|
+
### Custom Prompts (optional)
|
|
288
|
+
|
|
289
|
+
To test custom LLM prompts per pipeline stage (the `PromptProvider` interface), copy the example prompt module and edit it:
|
|
290
|
+
|
|
291
|
+
```bash
|
|
292
|
+
cp playground/data-examples/prompts.example.ts playground/data/prompts.ts
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
Every builder in `prompts.ts` is optional — delete the ones you don't want to override and those stages fall back to the built-in default prompts. Each playground script logs whether it is running with custom or default prompts.
|
|
296
|
+
|
|
297
|
+
Prompt builders receive their values (`expertFields`, `outputLanguage`, `targetArticle`, `dateService`, …) as arguments rather than reading config directly, so a prompt module written this way works unchanged across different configurations. Those argument values come from `config.json` and `articles.json`.
|
|
298
|
+
|
|
299
|
+
### Per-stage models (optional)
|
|
300
|
+
|
|
301
|
+
Production pipelines often mix providers — a cheap model for tagging, a multimodal one for images, a stronger one for the final newsletter. Add a `models` block to override any stage; omitted fields fall back to the top-level `provider` / `apiKey` / `model`:
|
|
302
|
+
|
|
303
|
+
```json
|
|
304
|
+
{
|
|
305
|
+
"provider": "openai",
|
|
306
|
+
"apiKey": "sk-...",
|
|
307
|
+
"model": "gpt-5.4-nano",
|
|
308
|
+
"models": {
|
|
309
|
+
"analyzeImages": { "model": "gpt-5.4-nano" },
|
|
310
|
+
"generateNewsletter": {
|
|
311
|
+
"provider": "anthropic",
|
|
312
|
+
"apiKey": "sk-ant-...",
|
|
313
|
+
"model": "claude-sonnet-4-6"
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
### Generation options (optional)
|
|
320
|
+
|
|
321
|
+
Sampling and output limits for the newsletter generation stage. Omitted values use the core defaults (`temperature: 0.3`, everything else unset):
|
|
322
|
+
|
|
323
|
+
```json
|
|
324
|
+
{
|
|
325
|
+
"generation": {
|
|
326
|
+
"temperature": 0.3,
|
|
327
|
+
"maxOutputTokens": 32000
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
Set `maxOutputTokens` when generating long newsletters — the generation query throws if the model stops on the token limit (`finishReason: "length"`).
|
|
333
|
+
|
|
287
334
|
### Run
|
|
288
335
|
|
|
336
|
+
Each pipeline stage can be run in isolation:
|
|
337
|
+
|
|
289
338
|
```bash
|
|
290
|
-
npm run playground:
|
|
339
|
+
npm run playground:classify-tags # ❶ Tag classification
|
|
340
|
+
npm run playground:analyze-images # ❷ Image analysis (multimodal model required)
|
|
341
|
+
npm run playground:determine-importance # ❸ Importance scoring
|
|
342
|
+
npm run playground:generate-newsletter # ❹ Newsletter generation
|
|
291
343
|
```
|
|
292
344
|
|
|
293
345
|
### Output
|
|
294
346
|
|
|
295
347
|
Results are saved to `playground/output/` (git-ignored):
|
|
296
348
|
|
|
349
|
+
- `classify-tags.md` — Assigned tags per article
|
|
350
|
+
- `analyze-images.md` — Image analysis context per article
|
|
351
|
+
- `determine-importance.md` — Importance score table
|
|
297
352
|
- `newsletter.md` — Generated markdown with title in frontmatter
|
|
298
353
|
- `newsletter.html` — Rendered HTML with CSS inlined (juice)
|
|
354
|
+
- `usage.md` — Token usage report (newsletter generation)
|
|
299
355
|
|
|
300
356
|
### Data Management
|
|
301
357
|
|
package/dist/index.d.ts
CHANGED
|
@@ -445,7 +445,7 @@ interface DateService {
|
|
|
445
445
|
/**
|
|
446
446
|
* Return a localized display string of the newsletter publication date
|
|
447
447
|
* for use in newsletter content.
|
|
448
|
-
* @example "
|
|
448
|
+
* @example "October 15"
|
|
449
449
|
*/
|
|
450
450
|
getPublicationDisplayDateString: () => string;
|
|
451
451
|
}
|
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": "3.0.
|
|
5
|
+
"version": "3.0.3",
|
|
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.js",
|
|
8
8
|
"types": "dist/index.d.ts",
|
|
@@ -42,41 +42,45 @@
|
|
|
42
42
|
"format": "prettier --write \"**/*.{ts,tsx,js,jsx,mjs,json,md,mdx}\"",
|
|
43
43
|
"format:check": "prettier --check \"**/*.{ts,tsx,js,jsx,mjs,json,md,mdx}\"",
|
|
44
44
|
"playground": "tsx",
|
|
45
|
+
"playground:verify-prompts": "tsx playground/verify-prompts.ts",
|
|
46
|
+
"playground:classify-tags": "tsx playground/classify-tags.ts",
|
|
47
|
+
"playground:analyze-images": "tsx playground/analyze-images.ts",
|
|
48
|
+
"playground:determine-importance": "tsx playground/determine-importance.ts",
|
|
45
49
|
"playground:generate-newsletter": "tsx playground/generate-newsletter.ts"
|
|
46
50
|
},
|
|
47
51
|
"author": "kimhongyeon",
|
|
48
52
|
"license": "Apache-2.0",
|
|
49
53
|
"dependencies": {
|
|
50
|
-
"@langchain/core": "^1.2.
|
|
51
|
-
"ai": "^7.0.
|
|
52
|
-
"es-toolkit": "^1.
|
|
54
|
+
"@langchain/core": "^1.2.9",
|
|
55
|
+
"ai": "^7.0.92",
|
|
56
|
+
"es-toolkit": "^1.52.0",
|
|
53
57
|
"jsdom": "^30.0.1",
|
|
54
58
|
"juice": "^12.1.2",
|
|
55
|
-
"safe-markdown2html": "^1.0.
|
|
56
|
-
"zod": "^4.4
|
|
59
|
+
"safe-markdown2html": "^1.0.12",
|
|
60
|
+
"zod": "^4.5.4"
|
|
57
61
|
},
|
|
58
62
|
"devDependencies": {
|
|
59
|
-
"@ai-sdk/anthropic": "^4.0.
|
|
60
|
-
"@ai-sdk/google": "^4.0.
|
|
61
|
-
"@ai-sdk/openai": "^4.0.
|
|
62
|
-
"@ai-sdk/togetherai": "^3.0.
|
|
63
|
+
"@ai-sdk/anthropic": "^4.0.49",
|
|
64
|
+
"@ai-sdk/google": "^4.0.63",
|
|
65
|
+
"@ai-sdk/openai": "^4.0.58",
|
|
66
|
+
"@ai-sdk/togetherai": "^3.0.44",
|
|
63
67
|
"@eslint/js": "^10.0.1",
|
|
64
68
|
"@trivago/prettier-plugin-sort-imports": "^6.0.2",
|
|
65
69
|
"@types/jsdom": "^30.0.0",
|
|
66
|
-
"@types/node": "^26.
|
|
67
|
-
"@vitest/coverage-v8": "^
|
|
68
|
-
"@vitest/expect": "^
|
|
69
|
-
"eslint": "^10.
|
|
70
|
+
"@types/node": "^26.4.1",
|
|
71
|
+
"@vitest/coverage-v8": "^5.0.0",
|
|
72
|
+
"@vitest/expect": "^5.0.0",
|
|
73
|
+
"eslint": "^10.9.1",
|
|
70
74
|
"eslint-plugin-unused-imports": "^4.4.1",
|
|
71
75
|
"prettier": "^3.9.6",
|
|
72
76
|
"rimraf": "^6.1.3",
|
|
73
|
-
"rollup": "^4.
|
|
77
|
+
"rollup": "^4.63.1",
|
|
74
78
|
"rollup-plugin-dts": "^6.5.1",
|
|
75
79
|
"rollup-plugin-typescript2": "^0.37.0",
|
|
76
|
-
"tsx": "^4.23.
|
|
80
|
+
"tsx": "^4.23.13",
|
|
77
81
|
"typescript": "^6.0.3",
|
|
78
|
-
"typescript-eslint": "^8.
|
|
79
|
-
"vitest": "^
|
|
82
|
+
"typescript-eslint": "^8.69.0",
|
|
83
|
+
"vitest": "^5.0.0"
|
|
80
84
|
},
|
|
81
85
|
"repository": {
|
|
82
86
|
"type": "git",
|