@heripo/research-radar 5.2.4 → 5.3.0

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
@@ -24,7 +24,7 @@ Previously reported service metrics were $0.2–1 per issue and 15% CTR. These a
24
24
  - Type-safe TypeScript with strict interfaces
25
25
  - Provider pattern for swapping components (Crawling/Analysis/Content/Email)
26
26
  - 74 active crawling targets across heritage agencies, museums, academic societies, filtered at runtime by robots.txt
27
- - Multi LLM providers: OpenAI GPT-5 (analysis) + selectable content generation (OpenAI / Anthropic / Google)
27
+ - OpenAI GPT-6 defaults for every LLM task, with per-task model overrides
28
28
  - Built-in retries, chain options, preview emails
29
29
 
30
30
  **Links**: [Live service](https://heripo.app/research-radar/subscribe) • [Newsletter example](https://heripo.app/research-radar-newsletter-example.html) • [Core engine](https://github.com/heripo-lab/llm-newsletter-kit-core)
@@ -72,7 +72,7 @@ npm install @heripo/research-radar '@llm-newsletter-kit/core@~3.0.6'
72
72
 
73
73
  **Requirements**: Node.js 24.15.0 or newer within 24.x, or >= 26.0.0, and an ESM application. Node.js 25 is not supported. The package exports `dist/index.js` and TypeScript declarations (`dist/index.d.ts`), with a JavaScript sourcemap. The core engine is a peer dependency; the current supported range is `~3.0.6`. The floor moved to 3.0.6 because the 나라장터 target runs its triage inside a crawl fetch that core times out, and before 3.0.6 core classified a timeout as non-retryable, so that target failed on the first attempt every run. 3.0.5 remains required for the self-verification retry cap the generation prompt relies on.
74
74
 
75
- Article analysis requires an OpenAI API key. Content generation requires a key for the selected provider (OpenAI / Anthropic / Google); OpenAI can use the same key for both. Keys are passed explicitly to the library; load environment variables in your application.
75
+ An OpenAI API key is always required and supplies all default models. The optional compatibility path for Anthropic or Google newsletter generation additionally requires that provider's key. Keys are passed explicitly to the library; load environment variables in your application.
76
76
 
77
77
  ## Quick Start
78
78
 
@@ -99,7 +99,6 @@ export async function runNewsletter(repositories: {
99
99
  const newsletterId = await generateNewsletter({
100
100
  ...repositories,
101
101
  openAIApiKey: apiKey,
102
- contentGeneration: { provider: 'openai', apiKey },
103
102
  logger: console,
104
103
  });
105
104
 
@@ -163,18 +162,33 @@ Uses the **Provider-Service pattern** from `@llm-newsletter-kit/core`. See [core
163
162
 
164
163
  ## Configuration and models
165
164
 
166
- Defaults below describe the checked-in code, not provider recommendations. This package uses AI SDK 7 and the OpenAI, Anthropic, and Google SDK adapters.
165
+ Defaults below describe the checked-in code, not provider recommendations. `openAIApiKey` is required and supplies every default model.
167
166
 
168
- | Stage | Provider | Default model |
169
- | ------------------ | --------- | ------------------------ |
170
- | Tag classification | OpenAI | `gpt-5.6-luna` |
171
- | Image analysis | OpenAI | `gpt-5.6-terra` |
172
- | Importance scoring | OpenAI | `gpt-5.6-terra` |
173
- | Content generation | OpenAI | `gpt-5.6-sol` |
174
- | Content generation | Anthropic | `claude-sonnet-4-6` |
175
- | Content generation | Google | `gemini-3.1-pro-preview` |
167
+ | Stage | Provider | Default model |
168
+ | --------------------- | -------- | ------------- |
169
+ | Heritage bid triage | OpenAI | `gpt-6-luna` |
170
+ | Tag classification | OpenAI | `gpt-6-luna` |
171
+ | Image analysis | OpenAI | `gpt-6-sol` |
172
+ | Importance scoring | OpenAI | `gpt-6-sol` |
173
+ | Newsletter generation | OpenAI | `gpt-6-sol` |
176
174
 
177
- Select content generation with `contentGeneration: { provider, apiKey, model? }`. `model` overrides that provider's default. Analysis models are configured in [analysis.provider.ts](./src/providers/analysis.provider.ts).
175
+ Override any task independently with `models`. Every value is an OpenAI model ID:
176
+
177
+ ```typescript
178
+ await generateNewsletter({
179
+ ...repositories,
180
+ openAIApiKey,
181
+ models: {
182
+ heritageBidTriage: 'gpt-6-luna',
183
+ classifyTags: 'gpt-6-luna',
184
+ analyzeImages: 'gpt-6-sol',
185
+ determineImportance: 'gpt-6-sol',
186
+ generateNewsletter: 'gpt-6-sol',
187
+ },
188
+ });
189
+ ```
190
+
191
+ The optional `contentGeneration: { provider, apiKey, model? }` compatibility path still supports Anthropic and Google for newsletter generation. `models.generateNewsletter` takes precedence when both are supplied.
178
192
 
179
193
  [src/config/index.ts](./src/config/index.ts) defines Korean output (`outputLanguage: '한국어'`), the cultural heritage domain (`expertField: ['문화유산']`), brand name, `subscribePageUrl`, LLM `maxRetries: 5`, chain `stopAfterAttempt: 3`, and generation `temperature: 0.3`. Publication settings are `minimumArticleCountForIssue: 5` and `priorityArticleScoreThreshold: 8`; the core engine evaluates them. In the locked core 3.0.6 implementation, the count check skips **5 or fewer** candidates unless at least one has importance score >= 8. An empty candidate list is always skipped.
180
194
 
@@ -379,7 +393,7 @@ export const newsletterConfig: NewsletterConfig = {
379
393
  - Replace Korean heritage sites with your domain sources
380
394
  - Implement parsers in `src/parsers/`
381
395
 
382
- **4. Switch content generation LLM provider** (optional):
396
+ **4. Switch content generation LLM provider** (legacy compatibility):
383
397
 
384
398
  Content generation supports **3 built-in providers** — just change `contentGeneration.provider`:
385
399
 
@@ -396,7 +410,7 @@ const contentGeneration: ContentGenerationConfig = {
396
410
  };
397
411
  ```
398
412
 
399
- Default models: openai=`gpt-5.6-sol`, anthropic=`claude-sonnet-4-6`, google=`gemini-3.1-pro-preview`
413
+ Compatibility defaults: openai=`gpt-6-sol`, anthropic=`claude-sonnet-4-6`, google=`gemini-3.1-pro-preview`
400
414
 
401
415
  To change analysis providers, update both `src/providers/analysis.provider.ts` (provider type and models) and `src/newsletter-generator.ts` (provider construction), using a compatible AI SDK provider. Also adapt domain-specific minimum-score rules in the analysis provider, output language and expert fields in config, package metadata, and the GitHub Actions runner/Slack settings for your fork.
402
416
 
package/dist/index.d.ts CHANGED
@@ -203,9 +203,11 @@ interface NewsletterRepository {
203
203
  }
204
204
 
205
205
  /**
206
- * Uses OpenAI for article analysis and a configurable provider (OpenAI / Anthropic / Google) for content generation.
206
+ * Uses the required OpenAI key for every default model. Each task accepts an
207
+ * OpenAI model-ID override, while the compatibility content-generation option
208
+ * can still select Anthropic or Google.
207
209
  *
208
- * Content generation provider is selected via `contentGeneration.provider` in dependencies.
210
+ * `models.generateNewsletter` takes precedence over `contentGeneration`.
209
211
  */
210
212
 
211
213
  /**
@@ -225,7 +227,7 @@ interface PreviewNewsletterOptions {
225
227
  * Each provider uses a sensible default model that can be overridden.
226
228
  *
227
229
  * Default models:
228
- * - openai: `gpt-5.6-sol`
230
+ * - openai: `gpt-6-sol`
229
231
  * - anthropic: `claude-sonnet-4-6`
230
232
  * - google: `gemini-3.1-pro-preview`
231
233
  */
@@ -242,14 +244,35 @@ type ContentGenerationConfig = {
242
244
  apiKey: string;
243
245
  model?: string;
244
246
  };
247
+ /**
248
+ * OpenAI model IDs used by each LLM task.
249
+ *
250
+ * Omitted values use the defaults from `llmConfig.models`. Content generation
251
+ * can still use a non-OpenAI provider through the legacy `contentGeneration`
252
+ * option; `models.generateNewsletter` takes precedence when both are supplied.
253
+ */
254
+ interface NewsletterModelConfig {
255
+ heritageBidTriage?: string;
256
+ classifyTags?: string;
257
+ analyzeImages?: string;
258
+ determineImportance?: string;
259
+ generateNewsletter?: string;
260
+ }
245
261
  /**
246
262
  * Newsletter generator dependencies interface
247
263
  */
248
264
  interface NewsletterGeneratorDependencies {
249
- /** OpenAI API key (used for article analysis: tag classification, image analysis, importance scoring) */
265
+ /** OpenAI API key used by every default model. */
250
266
  openAIApiKey: string;
251
- /** Content generation LLM configuration (provider + API key + optional model) */
252
- contentGeneration: ContentGenerationConfig;
267
+ /** OpenAI model overrides for every LLM task (optional). */
268
+ models?: NewsletterModelConfig;
269
+ /**
270
+ * Non-OpenAI content generation configuration (optional).
271
+ *
272
+ * Prefer `models.generateNewsletter`, which uses the required `openAIApiKey`.
273
+ * This remains available for Anthropic/Google compatibility.
274
+ */
275
+ contentGeneration?: ContentGenerationConfig;
253
276
  /** Task management repository */
254
277
  taskRepository: TaskRepository;
255
278
  /** Article management repository */
@@ -398,13 +421,17 @@ declare class TaskService implements TaskService$1<number> {
398
421
  end(): Promise<void>;
399
422
  }
400
423
 
424
+ interface AnalysisModels {
425
+ classifyTags: ReturnType<OpenAIProvider>;
426
+ analyzeImages: ReturnType<OpenAIProvider>;
427
+ determineImportance: ReturnType<OpenAIProvider>;
428
+ }
401
429
  /**
402
430
  * Analysis provider implementation
403
431
  * - LLM-based article analysis
404
432
  * - Tag classification, image analysis, importance scoring
405
433
  */
406
434
  declare class AnalysisProvider implements AnalysisProvider$1 {
407
- private readonly openai;
408
435
  private readonly articleRepository;
409
436
  private readonly tagRepository;
410
437
  classifyTagOptions: {
@@ -421,6 +448,7 @@ declare class AnalysisProvider implements AnalysisProvider$1 {
421
448
  }>;
422
449
  };
423
450
  constructor(openai: OpenAIProvider, articleRepository: ArticleRepository, tagRepository: TagRepository);
451
+ constructor(models: AnalysisModels, articleRepository: ArticleRepository, tagRepository: TagRepository);
424
452
  /**
425
453
  * Fetch articles that haven't been scored yet
426
454
  * @returns Unscored articles awaiting analysis
@@ -612,6 +640,13 @@ declare const robotsExemptOrigins: readonly string[];
612
640
  * LLM configuration
613
641
  */
614
642
  declare const llmConfig: {
643
+ models: {
644
+ heritageBidTriage: string;
645
+ classifyTags: string;
646
+ analyzeImages: string;
647
+ determineImportance: string;
648
+ generateNewsletter: string;
649
+ };
615
650
  maxRetries: number;
616
651
  chainStopAfterAttempt: number;
617
652
  generation: {
@@ -650,4 +685,4 @@ declare const llmConfig: {
650
685
  declare const researchRadarPromptProvider: PromptProvider;
651
686
 
652
687
  export { AnalysisProvider, ContentGenerateProvider, CrawlingProvider, DateService, TaskService, contentOptions, createCrawlingTargetGroups, generateNewsletter, generateWelcomeHTML, getSourceList, llmConfig, maximumImportanceScoreByDomain, newsletterConfig, researchRadarPromptProvider, robotsExemptOrigins };
653
- export type { ArticleRepository, ContentGenerationConfig, ContentOptions, ExcavationReport, ExcavationReportSource, NewsletterConfig, NewsletterGeneratorDependencies, NewsletterRepository, NewsletterTemplateOptions, PreviewNewsletterOptions, SourceGroup, SourceItem, TagRepository, TaskRepository, WelcomeTemplateOptions };
688
+ export type { ArticleRepository, ContentGenerationConfig, ContentOptions, ExcavationReport, ExcavationReportSource, NewsletterConfig, NewsletterGeneratorDependencies, NewsletterModelConfig, NewsletterRepository, NewsletterTemplateOptions, PreviewNewsletterOptions, SourceGroup, SourceItem, TagRepository, TaskRepository, WelcomeTemplateOptions };
package/dist/index.js CHANGED
@@ -3200,6 +3200,13 @@ const robotsExemptOrigins = [
3200
3200
  * LLM configuration
3201
3201
  */
3202
3202
  const llmConfig = {
3203
+ models: {
3204
+ heritageBidTriage: 'gpt-6-luna',
3205
+ classifyTags: 'gpt-6-luna',
3206
+ analyzeImages: 'gpt-6-sol',
3207
+ determineImportance: 'gpt-6-sol',
3208
+ generateNewsletter: 'gpt-6-sol',
3209
+ },
3203
3210
  maxRetries: 5,
3204
3211
  chainStopAfterAttempt: 3,
3205
3212
  generation: {
@@ -3789,24 +3796,29 @@ const researchRadarPromptProvider = {
3789
3796
  * - Tag classification, image analysis, importance scoring
3790
3797
  */
3791
3798
  class AnalysisProvider {
3792
- openai;
3793
3799
  articleRepository;
3794
3800
  tagRepository;
3795
3801
  classifyTagOptions;
3796
3802
  analyzeImagesOptions;
3797
3803
  determineScoreOptions;
3798
- constructor(openai, articleRepository, tagRepository) {
3799
- this.openai = openai;
3804
+ constructor(modelsOrOpenAI, articleRepository, tagRepository) {
3800
3805
  this.articleRepository = articleRepository;
3801
3806
  this.tagRepository = tagRepository;
3807
+ const models = typeof modelsOrOpenAI === 'function'
3808
+ ? {
3809
+ classifyTags: modelsOrOpenAI(llmConfig.models.classifyTags),
3810
+ analyzeImages: modelsOrOpenAI(llmConfig.models.analyzeImages),
3811
+ determineImportance: modelsOrOpenAI(llmConfig.models.determineImportance),
3812
+ }
3813
+ : modelsOrOpenAI;
3802
3814
  this.classifyTagOptions = {
3803
- model: this.openai('gpt-5.6-luna'),
3815
+ model: models.classifyTags,
3804
3816
  };
3805
3817
  this.analyzeImagesOptions = {
3806
- model: this.openai('gpt-5.6-terra'),
3818
+ model: models.analyzeImages,
3807
3819
  };
3808
3820
  this.determineScoreOptions = {
3809
- model: this.openai('gpt-5.6-terra'),
3821
+ model: models.determineImportance,
3810
3822
  minimumImportanceScoreRules: [
3811
3823
  // Korean Archaeological Society news: minimum score 6
3812
3824
  {
@@ -5054,7 +5066,7 @@ function createContentGenerationModel(config) {
5054
5066
  switch (config.provider) {
5055
5067
  case 'openai': {
5056
5068
  const provider = createOpenAI({ apiKey: config.apiKey });
5057
- return provider(config.model ?? 'gpt-5.6-sol');
5069
+ return provider(config.model ?? 'gpt-6-sol');
5058
5070
  }
5059
5071
  case 'anthropic': {
5060
5072
  const provider = createAnthropic({ apiKey: config.apiKey });
@@ -5070,6 +5082,10 @@ function createNewsletterGenerator(dependencies) {
5070
5082
  const openai = createOpenAI({
5071
5083
  apiKey: dependencies.openAIApiKey,
5072
5084
  });
5085
+ const modelIds = {
5086
+ ...llmConfig.models,
5087
+ ...dependencies.models,
5088
+ };
5073
5089
  const dateService = new DateService(dependencies.publishDate);
5074
5090
  const taskService = new TaskService(dependencies.taskRepository);
5075
5091
  const crawlingProvider = new CrawlingProvider(dependencies.articleRepository, dependencies.customFetch, dependencies.excavationReportSource, dependencies.logger, dependencies.publicDataApiKey,
@@ -5077,7 +5093,7 @@ function createNewsletterGenerator(dependencies) {
5077
5093
  // reach per-article scoring is decided here, 100 titles per request. The
5078
5094
  // deterministic filter stays behind it as the fallback.
5079
5095
  createHeritageBidTriage({
5080
- model: openai('gpt-5.6-luna'),
5096
+ model: openai(modelIds.heritageBidTriage),
5081
5097
  onFallback: (reason, batchSize) => {
5082
5098
  dependencies.logger?.info({
5083
5099
  event: 'crawl.g2b.triage.fallback',
@@ -5085,7 +5101,11 @@ function createNewsletterGenerator(dependencies) {
5085
5101
  });
5086
5102
  },
5087
5103
  }));
5088
- const analysisProvider = new AnalysisProvider(openai, dependencies.articleRepository, dependencies.tagRepository);
5104
+ const analysisProvider = new AnalysisProvider({
5105
+ classifyTags: openai(modelIds.classifyTags),
5106
+ analyzeImages: openai(modelIds.analyzeImages),
5107
+ determineImportance: openai(modelIds.determineImportance),
5108
+ }, dependencies.articleRepository, dependencies.tagRepository);
5089
5109
  // Inject display date from DateService into template options
5090
5110
  const templateOptions = dependencies.templateOptions
5091
5111
  ? {
@@ -5104,7 +5124,11 @@ function createNewsletterGenerator(dependencies) {
5104
5124
  };
5105
5125
  resolvedBrandName = '한국고고학회 뉴스레터';
5106
5126
  }
5107
- const contentModel = createContentGenerationModel(dependencies.contentGeneration);
5127
+ const contentModel = dependencies.models?.generateNewsletter
5128
+ ? openai(modelIds.generateNewsletter)
5129
+ : dependencies.contentGeneration
5130
+ ? createContentGenerationModel(dependencies.contentGeneration)
5131
+ : openai(modelIds.generateNewsletter);
5108
5132
  const contentGenerateProvider = new ContentGenerateProvider(contentModel, dependencies.articleRepository, dependencies.newsletterRepository, templateOptions, resolvedBrandName);
5109
5133
  return new GenerateNewsletter({
5110
5134
  contentOptions: resolvedContentOptions,
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": "@heripo/research-radar",
3
3
  "private": false,
4
4
  "type": "module",
5
- "version": "5.2.4",
5
+ "version": "5.3.0",
6
6
  "description": "AI-driven intelligence for Korean cultural heritage. This package serves as both a ready-to-use newsletter service and a practical implementation example for the LLM-Newsletter-Kit.",
7
7
  "main": "dist/index.js",
8
8
  "types": "dist/index.d.ts",