@llm-newsletter-kit/core 1.3.5 → 1.3.7
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 +22 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +22 -1
- package/dist/index.js.map +1 -1
- package/package.json +10 -10
package/dist/index.cjs
CHANGED
|
@@ -91,6 +91,18 @@ class LoggingExecutor {
|
|
|
91
91
|
}
|
|
92
92
|
}
|
|
93
93
|
|
|
94
|
+
/**
|
|
95
|
+
* Replaces ASCII double quotes with Unicode smart quotes (U+201C, U+201D).
|
|
96
|
+
* Prevents JSON structured output corruption when LLM reproduces quoted titles.
|
|
97
|
+
*/
|
|
98
|
+
const replaceAsciiQuotes = (str) => {
|
|
99
|
+
let isOpen = true;
|
|
100
|
+
return str.replace(/"/g, () => {
|
|
101
|
+
const q = isOpen ? '\u201c' : '\u201d';
|
|
102
|
+
isOpen = !isOpen;
|
|
103
|
+
return q;
|
|
104
|
+
});
|
|
105
|
+
};
|
|
94
106
|
const ensureStringArray = (value) => {
|
|
95
107
|
return typeof value === 'string' ? [value] : value;
|
|
96
108
|
};
|
|
@@ -919,7 +931,7 @@ let GenerateNewsletter$1 = class GenerateNewsletter extends BaseLLMQuery {
|
|
|
919
931
|
this.newsletterBrandName = config.newsletterBrandName;
|
|
920
932
|
}
|
|
921
933
|
async execute() {
|
|
922
|
-
const { output, usage } = await ai.generateText({
|
|
934
|
+
const { output, usage, finishReason } = await ai.generateText({
|
|
923
935
|
model: this.model,
|
|
924
936
|
maxRetries: this.options.llm.maxRetries,
|
|
925
937
|
maxOutputTokens: this.maxOutputTokens,
|
|
@@ -934,6 +946,11 @@ let GenerateNewsletter$1 = class GenerateNewsletter extends BaseLLMQuery {
|
|
|
934
946
|
system: this.systemPrompt,
|
|
935
947
|
prompt: this.userPrompt,
|
|
936
948
|
});
|
|
949
|
+
if (finishReason === 'length') {
|
|
950
|
+
throw new Error(`[GenerateNewsletter] Output truncated: LLM reached the token limit (finishReason: "length"). ` +
|
|
951
|
+
`Increase "maxOutputTokens" in ContentGenerateProvider or reduce the number of input articles. ` +
|
|
952
|
+
`Current maxOutputTokens: ${this.maxOutputTokens ?? 'not set (model default)'}`);
|
|
953
|
+
}
|
|
937
954
|
const needsRetry = !output.isWrittenInOutputLanguage ||
|
|
938
955
|
!output.copyrightVerified ||
|
|
939
956
|
!output.factAccuracy ||
|
|
@@ -1665,6 +1682,10 @@ class CrawlingChain extends Chain {
|
|
|
1665
1682
|
return {
|
|
1666
1683
|
...esToolkit.omit(listItem, ['pipelineId']),
|
|
1667
1684
|
...esToolkit.omit(detail, ['pipelineId']),
|
|
1685
|
+
title: replaceAsciiQuotes(listItem.title),
|
|
1686
|
+
...(detail.detailContent != null && {
|
|
1687
|
+
detailContent: replaceAsciiQuotes(detail.detailContent),
|
|
1688
|
+
}),
|
|
1668
1689
|
};
|
|
1669
1690
|
});
|
|
1670
1691
|
return merged;
|
package/dist/index.cjs.map
CHANGED
|
@@ -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
|
@@ -89,6 +89,18 @@ class LoggingExecutor {
|
|
|
89
89
|
}
|
|
90
90
|
}
|
|
91
91
|
|
|
92
|
+
/**
|
|
93
|
+
* Replaces ASCII double quotes with Unicode smart quotes (U+201C, U+201D).
|
|
94
|
+
* Prevents JSON structured output corruption when LLM reproduces quoted titles.
|
|
95
|
+
*/
|
|
96
|
+
const replaceAsciiQuotes = (str) => {
|
|
97
|
+
let isOpen = true;
|
|
98
|
+
return str.replace(/"/g, () => {
|
|
99
|
+
const q = isOpen ? '\u201c' : '\u201d';
|
|
100
|
+
isOpen = !isOpen;
|
|
101
|
+
return q;
|
|
102
|
+
});
|
|
103
|
+
};
|
|
92
104
|
const ensureStringArray = (value) => {
|
|
93
105
|
return typeof value === 'string' ? [value] : value;
|
|
94
106
|
};
|
|
@@ -917,7 +929,7 @@ let GenerateNewsletter$1 = class GenerateNewsletter extends BaseLLMQuery {
|
|
|
917
929
|
this.newsletterBrandName = config.newsletterBrandName;
|
|
918
930
|
}
|
|
919
931
|
async execute() {
|
|
920
|
-
const { output, usage } = await generateText({
|
|
932
|
+
const { output, usage, finishReason } = await generateText({
|
|
921
933
|
model: this.model,
|
|
922
934
|
maxRetries: this.options.llm.maxRetries,
|
|
923
935
|
maxOutputTokens: this.maxOutputTokens,
|
|
@@ -932,6 +944,11 @@ let GenerateNewsletter$1 = class GenerateNewsletter extends BaseLLMQuery {
|
|
|
932
944
|
system: this.systemPrompt,
|
|
933
945
|
prompt: this.userPrompt,
|
|
934
946
|
});
|
|
947
|
+
if (finishReason === 'length') {
|
|
948
|
+
throw new Error(`[GenerateNewsletter] Output truncated: LLM reached the token limit (finishReason: "length"). ` +
|
|
949
|
+
`Increase "maxOutputTokens" in ContentGenerateProvider or reduce the number of input articles. ` +
|
|
950
|
+
`Current maxOutputTokens: ${this.maxOutputTokens ?? 'not set (model default)'}`);
|
|
951
|
+
}
|
|
935
952
|
const needsRetry = !output.isWrittenInOutputLanguage ||
|
|
936
953
|
!output.copyrightVerified ||
|
|
937
954
|
!output.factAccuracy ||
|
|
@@ -1663,6 +1680,10 @@ class CrawlingChain extends Chain {
|
|
|
1663
1680
|
return {
|
|
1664
1681
|
...omit(listItem, ['pipelineId']),
|
|
1665
1682
|
...omit(detail, ['pipelineId']),
|
|
1683
|
+
title: replaceAsciiQuotes(listItem.title),
|
|
1684
|
+
...(detail.detailContent != null && {
|
|
1685
|
+
detailContent: replaceAsciiQuotes(detail.detailContent),
|
|
1686
|
+
}),
|
|
1666
1687
|
};
|
|
1667
1688
|
});
|
|
1668
1689
|
return merged;
|
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.
|
|
5
|
+
"version": "1.3.7",
|
|
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,10 +48,10 @@
|
|
|
48
48
|
"author": "kimhongyeon",
|
|
49
49
|
"license": "Apache-2.0",
|
|
50
50
|
"dependencies": {
|
|
51
|
-
"@langchain/core": "^1.1.
|
|
51
|
+
"@langchain/core": "^1.1.32",
|
|
52
52
|
"ai": "^6.0.116",
|
|
53
53
|
"es-toolkit": "^1.45.1",
|
|
54
|
-
"jsdom": "^
|
|
54
|
+
"jsdom": "^29.0.0",
|
|
55
55
|
"juice": "^11.1.1",
|
|
56
56
|
"safe-markdown2html": "^1.0.1",
|
|
57
57
|
"zod": "^4.3.6"
|
|
@@ -64,20 +64,20 @@
|
|
|
64
64
|
"@eslint/js": "^10.0.1",
|
|
65
65
|
"@trivago/prettier-plugin-sort-imports": "^6.0.2",
|
|
66
66
|
"@types/jsdom": "^28.0.0",
|
|
67
|
-
"@types/node": "^25.
|
|
68
|
-
"@vitest/coverage-v8": "^4.0
|
|
69
|
-
"@vitest/expect": "^4.0
|
|
70
|
-
"eslint": "^10.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",
|
|
71
71
|
"eslint-plugin-unused-imports": "^4.4.1",
|
|
72
72
|
"prettier": "^3.8.1",
|
|
73
73
|
"rimraf": "^6.1.3",
|
|
74
74
|
"rollup": "^4.59.0",
|
|
75
|
-
"rollup-plugin-dts": "^6.
|
|
75
|
+
"rollup-plugin-dts": "^6.4.0",
|
|
76
76
|
"rollup-plugin-typescript2": "^0.36.0",
|
|
77
77
|
"tsx": "^4.21.0",
|
|
78
78
|
"typescript": "^5.9.3",
|
|
79
|
-
"typescript-eslint": "^8.
|
|
80
|
-
"vitest": "^4.0
|
|
79
|
+
"typescript-eslint": "^8.57.0",
|
|
80
|
+
"vitest": "^4.1.0"
|
|
81
81
|
},
|
|
82
82
|
"repository": {
|
|
83
83
|
"type": "git",
|