@llm-newsletter-kit/core 3.0.5 → 3.0.6

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
@@ -71,7 +71,7 @@ See the quality for yourself—an actual newsletter generated by this kit: https
71
71
  npm i @llm-newsletter-kit/core
72
72
  ```
73
73
 
74
- - Node.js **>= 24** (CI uses 24.x)
74
+ - Node.js **24.15.0 or newer within 24.x, or >= 26.0.0** (Node.js 25 is not supported; CI verifies 24.15.0, the latest 24.x, and the latest 26.x)
75
75
  - ESM-only distribution: `dist/index.js` and `dist/index.d.ts`; use named imports.
76
76
  - The core uses AI SDK 7 and Zod 4. Install an AI SDK-compatible model provider separately; provider adapters are development dependencies in this repository, not runtime dependencies of the published package.
77
77
 
@@ -562,7 +562,7 @@ Results are saved to `playground/output/` (git-ignored):
562
562
 
563
563
  ## Development / Build / Test / CI
564
564
 
565
- Use Node.js 24 or newer and npm:
565
+ Use Node.js 24.15.0 or newer within 24.x, or Node.js 26.0.0 or newer, with npm. Node.js 25 is not supported:
566
566
 
567
567
  ```bash
568
568
  npm ci
@@ -573,7 +573,7 @@ npm run build
573
573
  npm run test:ci
574
574
  ```
575
575
 
576
- The [CI workflow](./.github/workflows/ci.yml) runs these checks on pull requests to any branch and manual dispatches, using Node.js 24.x. Rollup emits ESM JavaScript, a source map, and bundled declarations in `dist/`. Vitest uses the Node environment and V8 coverage with 100% thresholds for lines, branches, functions, and statements; the entry point and model/type files are excluded from coverage.
576
+ The [CI workflow](./.github/workflows/ci.yml) runs these checks on pull requests to any branch and manual dispatches, using the minimum supported Node.js version (24.15.0), the latest 24.x, and the latest 26.x. Rollup emits ESM JavaScript, a source map, and bundled declarations in `dist/`. Vitest uses the Node environment and V8 coverage with 100% thresholds for lines, branches, functions, and statements; the entry point and model/type files are excluded from coverage.
577
577
 
578
578
  For local iteration, use `npm run test:watch`, `npm run test:coverage`, `npm run lint:fix`, and `npm run format`. For the contribution workflow and release scripts, see [CONTRIBUTING.md](./CONTRIBUTING.md); [package.json](./package.json) defines the current runtime requirement and commands.
579
579
 
package/dist/index.js CHANGED
@@ -1496,6 +1496,27 @@ function parseRetryAfter(header) {
1496
1496
  return clamp(diff, 0, 60_000);
1497
1497
  return null;
1498
1498
  }
1499
+ /**
1500
+ * Describes a rejection value for retry matching.
1501
+ *
1502
+ * A rejected fetch does not have to reject with an `Error`. `controller.abort()`
1503
+ * takes an arbitrary reason and the request rejects with that value as-is, so
1504
+ * the timeout below — which aborts with a string — rejects with a string. A
1505
+ * `customFetch` may reject with anything at all. Matching only `Error`
1506
+ * instances silently made those rejections non-retryable, which is the opposite
1507
+ * of what a timeout should be.
1508
+ */
1509
+ function describeRejection(error) {
1510
+ if (typeof error === 'string')
1511
+ return error;
1512
+ if (typeof error === 'object' && error !== null) {
1513
+ const { name, message } = error;
1514
+ const parts = [name, message].filter((part) => typeof part === 'string');
1515
+ if (parts.length > 0)
1516
+ return parts.join(' ');
1517
+ }
1518
+ return String(error);
1519
+ }
1499
1520
  function shouldRetry(status, error) {
1500
1521
  if (status === 429)
1501
1522
  return true; // Too Many Requests (429)
@@ -1504,16 +1525,11 @@ function shouldRetry(status, error) {
1504
1525
  if (status && status >= 400 && status < 500)
1505
1526
  return false; // Fatal client error
1506
1527
  // Network error or aborted
1507
- if (error instanceof Error) {
1508
- const msg = error.message.toLowerCase();
1509
- if (msg.includes('aborted') ||
1510
- msg.includes('timeout') ||
1511
- msg.includes('network') ||
1512
- msg.includes('fetch')) {
1513
- return true;
1514
- }
1515
- }
1516
- return false;
1528
+ const description = describeRejection(error).toLowerCase();
1529
+ return (description.includes('abort') ||
1530
+ description.includes('timeout') ||
1531
+ description.includes('network') ||
1532
+ description.includes('fetch'));
1517
1533
  }
1518
1534
  async function getHtmlFromUrl(logger, url, referer = 'https://www.google.com/', customFetch) {
1519
1535
  const maxRetries = 5;
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",
5
+ "version": "3.0.6",
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",
@@ -51,36 +51,36 @@
51
51
  "author": "kimhongyeon",
52
52
  "license": "Apache-2.0",
53
53
  "dependencies": {
54
- "@langchain/core": "^1.2.9",
55
- "ai": "^7.0.92",
54
+ "@langchain/core": "^1.2.11",
55
+ "ai": "^7.0.107",
56
56
  "es-toolkit": "^1.52.0",
57
- "jsdom": "^30.0.1",
58
- "juice": "^12.1.2",
59
- "safe-markdown2html": "^1.0.12",
60
- "zod": "^4.5.4"
57
+ "jsdom": "^30.1.0",
58
+ "juice": "^12.1.3",
59
+ "safe-markdown2html": "^1.0.13",
60
+ "zod": "^4.6.5"
61
61
  },
62
62
  "devDependencies": {
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
+ "@ai-sdk/anthropic": "^4.0.58",
64
+ "@ai-sdk/google": "^4.0.76",
65
+ "@ai-sdk/openai": "^4.0.71",
66
+ "@ai-sdk/togetherai": "^3.0.54",
67
67
  "@eslint/js": "^10.0.1",
68
68
  "@trivago/prettier-plugin-sort-imports": "^6.0.2",
69
69
  "@types/jsdom": "^30.0.0",
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
+ "@types/node": "^26.6.2",
71
+ "@vitest/coverage-v8": "^5.0.1",
72
+ "@vitest/expect": "^5.0.1",
73
+ "eslint": "^10.11.0",
74
74
  "eslint-plugin-unused-imports": "^4.4.1",
75
- "prettier": "^3.9.6",
75
+ "prettier": "^3.9.8",
76
76
  "rimraf": "^6.1.3",
77
- "rollup": "^4.63.1",
77
+ "rollup": "^4.63.4",
78
78
  "rollup-plugin-dts": "^6.5.1",
79
79
  "rollup-plugin-typescript2": "^0.37.0",
80
80
  "tsx": "^4.23.13",
81
81
  "typescript": "^6.0.3",
82
- "typescript-eslint": "^8.69.0",
83
- "vitest": "^5.0.0"
82
+ "typescript-eslint": "^8.70.0",
83
+ "vitest": "^5.0.1"
84
84
  },
85
85
  "repository": {
86
86
  "type": "git",
@@ -112,7 +112,7 @@
112
112
  "nodejs"
113
113
  ],
114
114
  "engines": {
115
- "node": ">=24"
115
+ "node": "^24.15.0 || >=26.0.0"
116
116
  },
117
117
  "publishConfig": {
118
118
  "access": "public"