euparliamentmonitor 0.8.4
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/LICENSE +201 -0
- package/README.md +1005 -0
- package/SECURITY.md +151 -0
- package/package.json +131 -0
- package/scripts/constants/committee-indicator-map.d.ts +199 -0
- package/scripts/constants/committee-indicator-map.d.ts.map +1 -0
- package/scripts/constants/committee-indicator-map.js +1224 -0
- package/scripts/constants/committee-indicator-map.js.map +1 -0
- package/scripts/constants/config.d.ts +38 -0
- package/scripts/constants/config.d.ts.map +1 -0
- package/scripts/constants/config.js +66 -0
- package/scripts/constants/config.js.map +1 -0
- package/scripts/constants/language-articles.d.ts +84 -0
- package/scripts/constants/language-articles.d.ts.map +1 -0
- package/scripts/constants/language-articles.js +6771 -0
- package/scripts/constants/language-articles.js.map +1 -0
- package/scripts/constants/language-core.d.ts +38 -0
- package/scripts/constants/language-core.d.ts.map +1 -0
- package/scripts/constants/language-core.js +90 -0
- package/scripts/constants/language-core.js.map +1 -0
- package/scripts/constants/language-ui.d.ts +82 -0
- package/scripts/constants/language-ui.d.ts.map +1 -0
- package/scripts/constants/language-ui.js +889 -0
- package/scripts/constants/language-ui.js.map +1 -0
- package/scripts/constants/languages.d.ts +14 -0
- package/scripts/constants/languages.d.ts.map +1 -0
- package/scripts/constants/languages.js +15 -0
- package/scripts/constants/languages.js.map +1 -0
- package/scripts/generators/analysis-builders.d.ts +266 -0
- package/scripts/generators/analysis-builders.d.ts.map +1 -0
- package/scripts/generators/analysis-builders.js +2903 -0
- package/scripts/generators/analysis-builders.js.map +1 -0
- package/scripts/generators/breaking-content.d.ts +45 -0
- package/scripts/generators/breaking-content.d.ts.map +1 -0
- package/scripts/generators/breaking-content.js +530 -0
- package/scripts/generators/breaking-content.js.map +1 -0
- package/scripts/generators/committee-helpers.d.ts +54 -0
- package/scripts/generators/committee-helpers.d.ts.map +1 -0
- package/scripts/generators/committee-helpers.js +154 -0
- package/scripts/generators/committee-helpers.js.map +1 -0
- package/scripts/generators/dashboard-content.d.ts +95 -0
- package/scripts/generators/dashboard-content.d.ts.map +1 -0
- package/scripts/generators/dashboard-content.js +630 -0
- package/scripts/generators/dashboard-content.js.map +1 -0
- package/scripts/generators/deep-analysis-content.d.ts +23 -0
- package/scripts/generators/deep-analysis-content.d.ts.map +1 -0
- package/scripts/generators/deep-analysis-content.js +831 -0
- package/scripts/generators/deep-analysis-content.js.map +1 -0
- package/scripts/generators/mindmap-content.d.ts +55 -0
- package/scripts/generators/mindmap-content.d.ts.map +1 -0
- package/scripts/generators/mindmap-content.js +512 -0
- package/scripts/generators/mindmap-content.js.map +1 -0
- package/scripts/generators/motions-content.d.ts +50 -0
- package/scripts/generators/motions-content.d.ts.map +1 -0
- package/scripts/generators/motions-content.js +391 -0
- package/scripts/generators/motions-content.js.map +1 -0
- package/scripts/generators/news-enhanced.d.ts +14 -0
- package/scripts/generators/news-enhanced.d.ts.map +1 -0
- package/scripts/generators/news-enhanced.js +169 -0
- package/scripts/generators/news-enhanced.js.map +1 -0
- package/scripts/generators/news-indexes.d.ts +31 -0
- package/scripts/generators/news-indexes.d.ts.map +1 -0
- package/scripts/generators/news-indexes.js +410 -0
- package/scripts/generators/news-indexes.js.map +1 -0
- package/scripts/generators/pipeline/fetch-stage.d.ts +352 -0
- package/scripts/generators/pipeline/fetch-stage.d.ts.map +1 -0
- package/scripts/generators/pipeline/fetch-stage.js +1522 -0
- package/scripts/generators/pipeline/fetch-stage.js.map +1 -0
- package/scripts/generators/pipeline/generate-stage.d.ts +43 -0
- package/scripts/generators/pipeline/generate-stage.d.ts.map +1 -0
- package/scripts/generators/pipeline/generate-stage.js +204 -0
- package/scripts/generators/pipeline/generate-stage.js.map +1 -0
- package/scripts/generators/pipeline/output-stage.d.ts +48 -0
- package/scripts/generators/pipeline/output-stage.d.ts.map +1 -0
- package/scripts/generators/pipeline/output-stage.js +145 -0
- package/scripts/generators/pipeline/output-stage.js.map +1 -0
- package/scripts/generators/pipeline/transform-stage.d.ts +57 -0
- package/scripts/generators/pipeline/transform-stage.d.ts.map +1 -0
- package/scripts/generators/pipeline/transform-stage.js +111 -0
- package/scripts/generators/pipeline/transform-stage.js.map +1 -0
- package/scripts/generators/propositions-content.d.ts +29 -0
- package/scripts/generators/propositions-content.d.ts.map +1 -0
- package/scripts/generators/propositions-content.js +90 -0
- package/scripts/generators/propositions-content.js.map +1 -0
- package/scripts/generators/sankey-content.d.ts +45 -0
- package/scripts/generators/sankey-content.d.ts.map +1 -0
- package/scripts/generators/sankey-content.js +227 -0
- package/scripts/generators/sankey-content.js.map +1 -0
- package/scripts/generators/sitemap.d.ts +66 -0
- package/scripts/generators/sitemap.d.ts.map +1 -0
- package/scripts/generators/sitemap.js +562 -0
- package/scripts/generators/sitemap.js.map +1 -0
- package/scripts/generators/strategies/article-strategy.d.ts +146 -0
- package/scripts/generators/strategies/article-strategy.d.ts.map +1 -0
- package/scripts/generators/strategies/article-strategy.js +4 -0
- package/scripts/generators/strategies/article-strategy.js.map +1 -0
- package/scripts/generators/strategies/breaking-news-strategy.d.ts +64 -0
- package/scripts/generators/strategies/breaking-news-strategy.d.ts.map +1 -0
- package/scripts/generators/strategies/breaking-news-strategy.js +246 -0
- package/scripts/generators/strategies/breaking-news-strategy.js.map +1 -0
- package/scripts/generators/strategies/committee-reports-strategy.d.ts +93 -0
- package/scripts/generators/strategies/committee-reports-strategy.d.ts.map +1 -0
- package/scripts/generators/strategies/committee-reports-strategy.js +447 -0
- package/scripts/generators/strategies/committee-reports-strategy.js.map +1 -0
- package/scripts/generators/strategies/month-ahead-strategy.d.ts +60 -0
- package/scripts/generators/strategies/month-ahead-strategy.d.ts.map +1 -0
- package/scripts/generators/strategies/month-ahead-strategy.js +175 -0
- package/scripts/generators/strategies/month-ahead-strategy.js.map +1 -0
- package/scripts/generators/strategies/monthly-review-strategy.d.ts +66 -0
- package/scripts/generators/strategies/monthly-review-strategy.d.ts.map +1 -0
- package/scripts/generators/strategies/monthly-review-strategy.js +204 -0
- package/scripts/generators/strategies/monthly-review-strategy.js.map +1 -0
- package/scripts/generators/strategies/motions-strategy.d.ts +61 -0
- package/scripts/generators/strategies/motions-strategy.d.ts.map +1 -0
- package/scripts/generators/strategies/motions-strategy.js +215 -0
- package/scripts/generators/strategies/motions-strategy.js.map +1 -0
- package/scripts/generators/strategies/propositions-strategy.d.ts +60 -0
- package/scripts/generators/strategies/propositions-strategy.d.ts.map +1 -0
- package/scripts/generators/strategies/propositions-strategy.js +257 -0
- package/scripts/generators/strategies/propositions-strategy.js.map +1 -0
- package/scripts/generators/strategies/week-ahead-strategy.d.ts +57 -0
- package/scripts/generators/strategies/week-ahead-strategy.d.ts.map +1 -0
- package/scripts/generators/strategies/week-ahead-strategy.js +178 -0
- package/scripts/generators/strategies/week-ahead-strategy.js.map +1 -0
- package/scripts/generators/strategies/weekly-review-strategy.d.ts +63 -0
- package/scripts/generators/strategies/weekly-review-strategy.d.ts.map +1 -0
- package/scripts/generators/strategies/weekly-review-strategy.js +211 -0
- package/scripts/generators/strategies/weekly-review-strategy.js.map +1 -0
- package/scripts/generators/swot-content.d.ts +42 -0
- package/scripts/generators/swot-content.d.ts.map +1 -0
- package/scripts/generators/swot-content.js +366 -0
- package/scripts/generators/swot-content.js.map +1 -0
- package/scripts/generators/week-ahead-content.d.ts +103 -0
- package/scripts/generators/week-ahead-content.d.ts.map +1 -0
- package/scripts/generators/week-ahead-content.js +610 -0
- package/scripts/generators/week-ahead-content.js.map +1 -0
- package/scripts/index.d.ts +40 -0
- package/scripts/index.d.ts.map +1 -0
- package/scripts/index.js +53 -0
- package/scripts/index.js.map +1 -0
- package/scripts/mcp/ep-mcp-client.d.ts +471 -0
- package/scripts/mcp/ep-mcp-client.d.ts.map +1 -0
- package/scripts/mcp/ep-mcp-client.js +734 -0
- package/scripts/mcp/ep-mcp-client.js.map +1 -0
- package/scripts/mcp/mcp-connection.d.ts +264 -0
- package/scripts/mcp/mcp-connection.d.ts.map +1 -0
- package/scripts/mcp/mcp-connection.js +790 -0
- package/scripts/mcp/mcp-connection.js.map +1 -0
- package/scripts/mcp/mcp-health.d.ts +75 -0
- package/scripts/mcp/mcp-health.d.ts.map +1 -0
- package/scripts/mcp/mcp-health.js +78 -0
- package/scripts/mcp/mcp-health.js.map +1 -0
- package/scripts/mcp/mcp-retry.d.ts +94 -0
- package/scripts/mcp/mcp-retry.d.ts.map +1 -0
- package/scripts/mcp/mcp-retry.js +127 -0
- package/scripts/mcp/mcp-retry.js.map +1 -0
- package/scripts/mcp/wb-mcp-client.d.ts +38 -0
- package/scripts/mcp/wb-mcp-client.d.ts.map +1 -0
- package/scripts/mcp/wb-mcp-client.js +112 -0
- package/scripts/mcp/wb-mcp-client.js.map +1 -0
- package/scripts/templates/article-template.d.ts +9 -0
- package/scripts/templates/article-template.d.ts.map +1 -0
- package/scripts/templates/article-template.js +378 -0
- package/scripts/templates/article-template.js.map +1 -0
- package/scripts/templates/section-builders.d.ts +28 -0
- package/scripts/templates/section-builders.d.ts.map +1 -0
- package/scripts/templates/section-builders.js +142 -0
- package/scripts/templates/section-builders.js.map +1 -0
- package/scripts/types/analysis.d.ts +115 -0
- package/scripts/types/analysis.d.ts.map +1 -0
- package/scripts/types/analysis.js +4 -0
- package/scripts/types/analysis.js.map +1 -0
- package/scripts/types/common.d.ts +584 -0
- package/scripts/types/common.d.ts.map +1 -0
- package/scripts/types/common.js +96 -0
- package/scripts/types/common.js.map +1 -0
- package/scripts/types/generation.d.ts +104 -0
- package/scripts/types/generation.d.ts.map +1 -0
- package/scripts/types/generation.js +4 -0
- package/scripts/types/generation.js.map +1 -0
- package/scripts/types/index.d.ts +24 -0
- package/scripts/types/index.d.ts.map +1 -0
- package/scripts/types/index.js +16 -0
- package/scripts/types/index.js.map +1 -0
- package/scripts/types/intelligence.d.ts +129 -0
- package/scripts/types/intelligence.d.ts.map +1 -0
- package/scripts/types/intelligence.js +4 -0
- package/scripts/types/intelligence.js.map +1 -0
- package/scripts/types/mcp.d.ts +418 -0
- package/scripts/types/mcp.d.ts.map +1 -0
- package/scripts/types/mcp.js +4 -0
- package/scripts/types/mcp.js.map +1 -0
- package/scripts/types/parliament.d.ts +388 -0
- package/scripts/types/parliament.d.ts.map +1 -0
- package/scripts/types/parliament.js +4 -0
- package/scripts/types/parliament.js.map +1 -0
- package/scripts/types/quality.d.ts +114 -0
- package/scripts/types/quality.d.ts.map +1 -0
- package/scripts/types/quality.js +4 -0
- package/scripts/types/quality.js.map +1 -0
- package/scripts/types/stakeholder.d.ts +88 -0
- package/scripts/types/stakeholder.d.ts.map +1 -0
- package/scripts/types/stakeholder.js +16 -0
- package/scripts/types/stakeholder.js.map +1 -0
- package/scripts/types/visualization.d.ts +708 -0
- package/scripts/types/visualization.d.ts.map +1 -0
- package/scripts/types/visualization.js +4 -0
- package/scripts/types/visualization.js.map +1 -0
- package/scripts/types/world-bank.d.ts +85 -0
- package/scripts/types/world-bank.d.ts.map +1 -0
- package/scripts/types/world-bank.js +4 -0
- package/scripts/types/world-bank.js.map +1 -0
- package/scripts/utils/article-category.d.ts +18 -0
- package/scripts/utils/article-category.d.ts.map +1 -0
- package/scripts/utils/article-category.js +49 -0
- package/scripts/utils/article-category.js.map +1 -0
- package/scripts/utils/article-quality-scorer.d.ts +87 -0
- package/scripts/utils/article-quality-scorer.d.ts.map +1 -0
- package/scripts/utils/article-quality-scorer.js +1048 -0
- package/scripts/utils/article-quality-scorer.js.map +1 -0
- package/scripts/utils/content-metadata.d.ts +34 -0
- package/scripts/utils/content-metadata.d.ts.map +1 -0
- package/scripts/utils/content-metadata.js +249 -0
- package/scripts/utils/content-metadata.js.map +1 -0
- package/scripts/utils/content-validator.d.ts +94 -0
- package/scripts/utils/content-validator.d.ts.map +1 -0
- package/scripts/utils/content-validator.js +489 -0
- package/scripts/utils/content-validator.js.map +1 -0
- package/scripts/utils/copy-test-reports.d.ts +9 -0
- package/scripts/utils/copy-test-reports.d.ts.map +1 -0
- package/scripts/utils/copy-test-reports.js +508 -0
- package/scripts/utils/copy-test-reports.js.map +1 -0
- package/scripts/utils/file-utils.d.ts +144 -0
- package/scripts/utils/file-utils.d.ts.map +1 -0
- package/scripts/utils/file-utils.js +374 -0
- package/scripts/utils/file-utils.js.map +1 -0
- package/scripts/utils/fix-articles.d.ts +27 -0
- package/scripts/utils/fix-articles.d.ts.map +1 -0
- package/scripts/utils/fix-articles.js +510 -0
- package/scripts/utils/fix-articles.js.map +1 -0
- package/scripts/utils/generate-docs-index.d.ts +8 -0
- package/scripts/utils/generate-docs-index.d.ts.map +1 -0
- package/scripts/utils/generate-docs-index.js +275 -0
- package/scripts/utils/generate-docs-index.js.map +1 -0
- package/scripts/utils/html-sanitize.d.ts +18 -0
- package/scripts/utils/html-sanitize.d.ts.map +1 -0
- package/scripts/utils/html-sanitize.js +57 -0
- package/scripts/utils/html-sanitize.js.map +1 -0
- package/scripts/utils/intelligence-analysis.d.ts +173 -0
- package/scripts/utils/intelligence-analysis.d.ts.map +1 -0
- package/scripts/utils/intelligence-analysis.js +936 -0
- package/scripts/utils/intelligence-analysis.js.map +1 -0
- package/scripts/utils/intelligence-index.d.ts +126 -0
- package/scripts/utils/intelligence-index.d.ts.map +1 -0
- package/scripts/utils/intelligence-index.js +731 -0
- package/scripts/utils/intelligence-index.js.map +1 -0
- package/scripts/utils/metadata-utils.d.ts +14 -0
- package/scripts/utils/metadata-utils.d.ts.map +1 -0
- package/scripts/utils/metadata-utils.js +18 -0
- package/scripts/utils/metadata-utils.js.map +1 -0
- package/scripts/utils/news-metadata.d.ts +47 -0
- package/scripts/utils/news-metadata.d.ts.map +1 -0
- package/scripts/utils/news-metadata.js +259 -0
- package/scripts/utils/news-metadata.js.map +1 -0
- package/scripts/utils/validate-articles.d.ts +2 -0
- package/scripts/utils/validate-articles.d.ts.map +1 -0
- package/scripts/utils/validate-articles.js +284 -0
- package/scripts/utils/validate-articles.js.map +1 -0
- package/scripts/utils/validate-ep-api.d.ts +51 -0
- package/scripts/utils/validate-ep-api.d.ts.map +1 -0
- package/scripts/utils/validate-ep-api.js +160 -0
- package/scripts/utils/validate-ep-api.js.map +1 -0
- package/scripts/utils/world-bank-data.d.ts +84 -0
- package/scripts/utils/world-bank-data.d.ts.map +1 -0
- package/scripts/utils/world-bank-data.js +311 -0
- package/scripts/utils/world-bank-data.js.map +1 -0
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module Generators/Strategies/ArticleStrategy
|
|
3
|
+
* @description Base interface and shared types for article generation strategies.
|
|
4
|
+
* Each strategy encapsulates the fetch, build, and metadata logic for one
|
|
5
|
+
* {@link ArticleCategory}, making it trivial to add new article types without
|
|
6
|
+
* touching the orchestration layer.
|
|
7
|
+
*/
|
|
8
|
+
import type { ArticleCategory } from '../../types/index.js';
|
|
9
|
+
import type { LanguageCode } from '../../types/index.js';
|
|
10
|
+
import type { ArticleSource } from '../../types/index.js';
|
|
11
|
+
import type { EuropeanParliamentMCPClient } from '../../mcp/ep-mcp-client.js';
|
|
12
|
+
/**
|
|
13
|
+
* Minimum payload every strategy must carry: the article's publication date.
|
|
14
|
+
* Strategy-specific data interfaces extend this base.
|
|
15
|
+
*/
|
|
16
|
+
export interface ArticleData {
|
|
17
|
+
/** ISO 8601 publication date (YYYY-MM-DD) */
|
|
18
|
+
readonly date: string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Resolved title, subtitle, keywords, and optional sources for one
|
|
22
|
+
* language version of an article.
|
|
23
|
+
*/
|
|
24
|
+
export interface ArticleMetadata {
|
|
25
|
+
/** Localized article title */
|
|
26
|
+
readonly title: string;
|
|
27
|
+
/** Localized article subtitle */
|
|
28
|
+
readonly subtitle: string;
|
|
29
|
+
/** SEO keywords */
|
|
30
|
+
readonly keywords: readonly string[];
|
|
31
|
+
/** Article category */
|
|
32
|
+
readonly category: ArticleCategory;
|
|
33
|
+
/** Optional source references */
|
|
34
|
+
readonly sources?: readonly ArticleSource[] | undefined;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Non-generic base interface for {@link ArticleStrategy} used by the strategy
|
|
38
|
+
* registry. Expresses the common operations with {@link ArticleData} as the
|
|
39
|
+
* data payload type so that concrete strategies parameterised on a subtype can
|
|
40
|
+
* be stored in a single {@link StrategyRegistry} map without unsafe casts.
|
|
41
|
+
*
|
|
42
|
+
* This interface deliberately relies on TypeScript's bivariant method-parameter
|
|
43
|
+
* checking: a concrete strategy whose methods accept a narrower `TData`
|
|
44
|
+
* (extending {@link ArticleData}) still satisfies this interface structurally.
|
|
45
|
+
* That means the type is not fully sound — a caller that only sees
|
|
46
|
+
* {@link ArticleStrategyBase} could, in principle, pass an {@link ArticleData}
|
|
47
|
+
* value that does not match the concrete strategy's expected `TData` shape.
|
|
48
|
+
*
|
|
49
|
+
* To use this interface safely:
|
|
50
|
+
* - Only pass the `data` object returned by a given strategy's own
|
|
51
|
+
* {@link ArticleStrategyBase.fetchData | fetchData} to that same strategy's
|
|
52
|
+
* {@link ArticleStrategyBase.buildContent | buildContent} and
|
|
53
|
+
* {@link ArticleStrategyBase.getMetadata | getMetadata} methods.
|
|
54
|
+
* - Never mix data payloads between different strategies, even if they share
|
|
55
|
+
* the {@link ArticleData} base type.
|
|
56
|
+
*
|
|
57
|
+
* External callers that need strong typing for a specific strategy should
|
|
58
|
+
* prefer the generic {@link ArticleStrategy} interface, which preserves the
|
|
59
|
+
* concrete `TData` type and avoids this intentional unsoundness. The
|
|
60
|
+
* {@link ArticleStrategyBase} interface is intended primarily for the internal
|
|
61
|
+
* orchestration / pipeline layer that manages a heterogeneous strategy
|
|
62
|
+
* registry.
|
|
63
|
+
*/
|
|
64
|
+
export interface ArticleStrategyBase {
|
|
65
|
+
/** The article category this strategy handles */
|
|
66
|
+
readonly type: ArticleCategory;
|
|
67
|
+
/** Names of MCP tools this strategy calls */
|
|
68
|
+
readonly requiredMCPTools: readonly string[];
|
|
69
|
+
/**
|
|
70
|
+
* Fetch all domain data needed to render this article type.
|
|
71
|
+
*
|
|
72
|
+
* @param client - Connected MCP client, or null when MCP is unavailable
|
|
73
|
+
* @param date - ISO 8601 publication date (YYYY-MM-DD)
|
|
74
|
+
* @returns Populated article data payload
|
|
75
|
+
*/
|
|
76
|
+
fetchData(client: EuropeanParliamentMCPClient | null, date: string): Promise<ArticleData>;
|
|
77
|
+
/**
|
|
78
|
+
* Build the article HTML body for the given language.
|
|
79
|
+
*
|
|
80
|
+
* @param data - Data payload returned by {@link fetchData}
|
|
81
|
+
* @param lang - Target language code
|
|
82
|
+
* @returns Article body HTML string
|
|
83
|
+
*/
|
|
84
|
+
buildContent(data: ArticleData, lang: LanguageCode): string;
|
|
85
|
+
/**
|
|
86
|
+
* Return title, subtitle, keywords, and sources for the given language.
|
|
87
|
+
*
|
|
88
|
+
* @param data - Data payload returned by {@link fetchData}
|
|
89
|
+
* @param lang - Target language code
|
|
90
|
+
* @returns Article metadata
|
|
91
|
+
*/
|
|
92
|
+
getMetadata(data: ArticleData, lang: LanguageCode): ArticleMetadata;
|
|
93
|
+
/**
|
|
94
|
+
* Optional guard that lets a strategy opt out of generation when the
|
|
95
|
+
* fetched data contains only placeholder / fallback values (e.g. MCP
|
|
96
|
+
* unavailable). When `true` is returned the orchestrator skips writing
|
|
97
|
+
* all language variants and logs a notice rather than publishing empty
|
|
98
|
+
* placeholder articles.
|
|
99
|
+
*
|
|
100
|
+
* Strategies that do not implement this method are treated as always
|
|
101
|
+
* wanting to generate (i.e. the default is `false`).
|
|
102
|
+
*
|
|
103
|
+
* @param data - Data payload returned by {@link fetchData}
|
|
104
|
+
* @returns `true` when all fetched data is placeholder and generation should be skipped
|
|
105
|
+
*/
|
|
106
|
+
shouldSkip?(data: ArticleData): boolean;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Strategy interface for article generation.
|
|
110
|
+
*
|
|
111
|
+
* Each concrete implementation handles one {@link ArticleCategory}:
|
|
112
|
+
* - {@link module:Generators/Strategies/WeekAheadStrategy}
|
|
113
|
+
* - {@link module:Generators/Strategies/BreakingNewsStrategy}
|
|
114
|
+
* - {@link module:Generators/Strategies/CommitteeReportsStrategy}
|
|
115
|
+
* - {@link module:Generators/Strategies/PropositionsStrategy}
|
|
116
|
+
* - {@link module:Generators/Strategies/MotionsStrategy}
|
|
117
|
+
*
|
|
118
|
+
* @template TData - Concrete data payload type returned by {@link fetchData}
|
|
119
|
+
*/
|
|
120
|
+
export interface ArticleStrategy<TData extends ArticleData = ArticleData> extends ArticleStrategyBase {
|
|
121
|
+
/**
|
|
122
|
+
* Fetch all domain data needed to render this article type.
|
|
123
|
+
*
|
|
124
|
+
* @param client - Connected MCP client, or null when MCP is unavailable
|
|
125
|
+
* @param date - ISO 8601 publication date (YYYY-MM-DD)
|
|
126
|
+
* @returns Populated article data payload
|
|
127
|
+
*/
|
|
128
|
+
fetchData(client: EuropeanParliamentMCPClient | null, date: string): Promise<TData>;
|
|
129
|
+
/**
|
|
130
|
+
* Build the article HTML body for the given language.
|
|
131
|
+
*
|
|
132
|
+
* @param data - Data payload returned by {@link fetchData}
|
|
133
|
+
* @param lang - Target language code
|
|
134
|
+
* @returns Article body HTML string
|
|
135
|
+
*/
|
|
136
|
+
buildContent(data: TData, lang: LanguageCode): string;
|
|
137
|
+
/**
|
|
138
|
+
* Return title, subtitle, keywords, and sources for the given language.
|
|
139
|
+
*
|
|
140
|
+
* @param data - Data payload returned by {@link fetchData}
|
|
141
|
+
* @param lang - Target language code
|
|
142
|
+
* @returns Article metadata
|
|
143
|
+
*/
|
|
144
|
+
getMetadata(data: TData, lang: LanguageCode): ArticleMetadata;
|
|
145
|
+
}
|
|
146
|
+
//# sourceMappingURL=article-strategy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"article-strategy.d.ts","sourceRoot":"","sources":["../../../src/generators/strategies/article-strategy.ts"],"names":[],"mappings":"AAGA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,4BAA4B,CAAC;AAE9E;;;GAGG;AACH,MAAM,WAAW,WAAW;IAC1B,6CAA6C;IAC7C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,8BAA8B;IAC9B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,iCAAiC;IACjC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,mBAAmB;IACnB,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,uBAAuB;IACvB,QAAQ,CAAC,QAAQ,EAAE,eAAe,CAAC;IACnC,iCAAiC;IACjC,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,aAAa,EAAE,GAAG,SAAS,CAAC;CACzD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,MAAM,WAAW,mBAAmB;IAClC,iDAAiD;IACjD,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAC;IAC/B,6CAA6C;IAC7C,QAAQ,CAAC,gBAAgB,EAAE,SAAS,MAAM,EAAE,CAAC;IAC7C;;;;;;OAMG;IACH,SAAS,CAAC,MAAM,EAAE,2BAA2B,GAAG,IAAI,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IAC1F;;;;;;OAMG;IACH,YAAY,CAAC,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,YAAY,GAAG,MAAM,CAAC;IAC5D;;;;;;OAMG;IACH,WAAW,CAAC,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,YAAY,GAAG,eAAe,CAAC;IACpE;;;;;;;;;;;;OAYG;IACH,UAAU,CAAC,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC;CACzC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,eAAe,CAC9B,KAAK,SAAS,WAAW,GAAG,WAAW,CACvC,SAAQ,mBAAmB;IAC3B;;;;;;OAMG;IACH,SAAS,CAAC,MAAM,EAAE,2BAA2B,GAAG,IAAI,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;IACpF;;;;;;OAMG;IACH,YAAY,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,YAAY,GAAG,MAAM,CAAC;IACtD;;;;;;OAMG;IACH,WAAW,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,YAAY,GAAG,eAAe,CAAC;CAC/D"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"article-strategy.js","sourceRoot":"","sources":["../../../src/generators/strategies/article-strategy.ts"],"names":[],"mappings":"AAAA,8CAA8C;AAC9C,sCAAsC"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module Generators/Strategies/BreakingNewsStrategy
|
|
3
|
+
* @description Article strategy for the Breaking News article type.
|
|
4
|
+
* Uses a **feed-first** approach: EP feed endpoints (adopted texts, events,
|
|
5
|
+
* procedures, MEPs) provide the primary news content, while analytical tools
|
|
6
|
+
* (voting anomalies, coalition dynamics) supply optional context only.
|
|
7
|
+
*
|
|
8
|
+
* Precomputed statistics from `get_all_generated_stats` are **never** the
|
|
9
|
+
* primary news content and are used solely for historical comparison.
|
|
10
|
+
*/
|
|
11
|
+
import type { EuropeanParliamentMCPClient } from '../../mcp/ep-mcp-client.js';
|
|
12
|
+
import { ArticleCategory } from '../../types/index.js';
|
|
13
|
+
import type { LanguageCode, BreakingNewsFeedData } from '../../types/index.js';
|
|
14
|
+
import type { ArticleStrategy, ArticleData, ArticleMetadata } from './article-strategy.js';
|
|
15
|
+
/** Data fetched and pre-processed by {@link BreakingNewsStrategy} */
|
|
16
|
+
export interface BreakingNewsArticleData extends ArticleData {
|
|
17
|
+
/** Feed data — adopted texts, events, procedures, MEP updates (PRIMARY). Undefined when MCP unavailable. */
|
|
18
|
+
readonly feedData: BreakingNewsFeedData | undefined;
|
|
19
|
+
/** Raw voting anomaly text from MCP (CONTEXT ONLY) */
|
|
20
|
+
readonly anomalyRaw: string;
|
|
21
|
+
/** Raw coalition dynamics text from MCP (CONTEXT ONLY) */
|
|
22
|
+
readonly coalitionRaw: string;
|
|
23
|
+
/** Raw voting statistics report text from MCP (KEPT FOR BACKWARD COMPAT) */
|
|
24
|
+
readonly reportRaw: string;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Article strategy for {@link ArticleCategory.BREAKING_NEWS}.
|
|
28
|
+
*
|
|
29
|
+
* **Feed-first**: EP feed endpoints are the primary data source.
|
|
30
|
+
* Analytical tools provide supplementary context only.
|
|
31
|
+
* Stats are NEVER the news itself.
|
|
32
|
+
*/
|
|
33
|
+
export declare class BreakingNewsStrategy implements ArticleStrategy<BreakingNewsArticleData> {
|
|
34
|
+
readonly type = ArticleCategory.BREAKING_NEWS;
|
|
35
|
+
readonly requiredMCPTools: readonly ["get_adopted_texts_feed", "get_events_feed", "get_procedures_feed", "get_meps_feed", "detect_voting_anomalies", "analyze_coalition_dynamics"];
|
|
36
|
+
/**
|
|
37
|
+
* Fetch EP feed data (primary) first, then conditionally fetch analytical
|
|
38
|
+
* context (secondary) in a second phase.
|
|
39
|
+
*
|
|
40
|
+
* @param client - MCP client or null
|
|
41
|
+
* @param date - ISO 8601 publication date
|
|
42
|
+
* @returns Populated breaking news data payload
|
|
43
|
+
*/
|
|
44
|
+
fetchData(client: EuropeanParliamentMCPClient | null, date: string): Promise<BreakingNewsArticleData>;
|
|
45
|
+
/**
|
|
46
|
+
* Build the breaking news HTML body for the specified language.
|
|
47
|
+
*
|
|
48
|
+
* @param data - Breaking news data payload
|
|
49
|
+
* @param lang - Target language code used for editorial strings
|
|
50
|
+
* @returns Article HTML body
|
|
51
|
+
*/
|
|
52
|
+
buildContent(data: BreakingNewsArticleData, lang: LanguageCode): string;
|
|
53
|
+
/**
|
|
54
|
+
* Return language-specific metadata for the breaking news article.
|
|
55
|
+
*
|
|
56
|
+
* @param data - Breaking news data payload
|
|
57
|
+
* @param lang - Target language code
|
|
58
|
+
* @returns Localised metadata
|
|
59
|
+
*/
|
|
60
|
+
getMetadata(data: BreakingNewsArticleData, lang: LanguageCode): ArticleMetadata;
|
|
61
|
+
}
|
|
62
|
+
/** Singleton instance for use by the strategy registry */
|
|
63
|
+
export declare const breakingNewsStrategy: BreakingNewsStrategy;
|
|
64
|
+
//# sourceMappingURL=breaking-news-strategy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"breaking-news-strategy.d.ts","sourceRoot":"","sources":["../../../src/generators/strategies/breaking-news-strategy.ts"],"names":[],"mappings":"AAGA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,4BAA4B,CAAC;AAC9E,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,KAAK,EAAE,YAAY,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAuB/E,OAAO,KAAK,EAAE,eAAe,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAkG3F,qEAAqE;AACrE,MAAM,WAAW,uBAAwB,SAAQ,WAAW;IAC1D,4GAA4G;IAC5G,QAAQ,CAAC,QAAQ,EAAE,oBAAoB,GAAG,SAAS,CAAC;IACpD,sDAAsD;IACtD,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,0DAA0D;IAC1D,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,4EAA4E;IAC5E,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAID;;;;;;GAMG;AACH,qBAAa,oBAAqB,YAAW,eAAe,CAAC,uBAAuB,CAAC;IACnF,QAAQ,CAAC,IAAI,iCAAiC;IAE9C,QAAQ,CAAC,gBAAgB,0JAOd;IAEX;;;;;;;OAOG;IACG,SAAS,CACb,MAAM,EAAE,2BAA2B,GAAG,IAAI,EAC1C,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,uBAAuB,CAAC;IAqEnC;;;;;;OAMG;IACH,YAAY,CAAC,IAAI,EAAE,uBAAuB,EAAE,IAAI,EAAE,YAAY,GAAG,MAAM;IAuCvE;;;;;;OAMG;IACH,WAAW,CAAC,IAAI,EAAE,uBAAuB,EAAE,IAAI,EAAE,YAAY,GAAG,eAAe;CAsBhF;AAED,0DAA0D;AAC1D,eAAO,MAAM,oBAAoB,sBAA6B,CAAC"}
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: 2024-2026 Hack23 AB
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
import { ArticleCategory } from '../../types/index.js';
|
|
4
|
+
import { BREAKING_NEWS_TITLES, getLocalizedString } from '../../constants/languages.js';
|
|
5
|
+
import { fetchBreakingNewsFeedData, fetchVotingAnomalies, fetchCoalitionDynamics, loadFeedDataFromFile, } from '../pipeline/fetch-stage.js';
|
|
6
|
+
import { buildBreakingNewsContent, scoreBreakingNewsSignificance, SIGNIFICANCE_THRESHOLD, } from '../breaking-content.js';
|
|
7
|
+
import { buildDeepAnalysisSection } from '../deep-analysis-content.js';
|
|
8
|
+
import { buildBreakingAnalysis, buildBreakingSwot, buildBreakingDashboard, buildBreakingMindmap, } from '../analysis-builders.js';
|
|
9
|
+
import { buildSwotSection } from '../swot-content.js';
|
|
10
|
+
import { buildDashboardSection } from '../dashboard-content.js';
|
|
11
|
+
import { buildIntelligenceMindmapSection } from '../mindmap-content.js';
|
|
12
|
+
import { pl } from '../../utils/metadata-utils.js';
|
|
13
|
+
/** Base keywords shared by all Breaking News articles */
|
|
14
|
+
const BREAKING_NEWS_BASE_KEYWORDS = [
|
|
15
|
+
'European Parliament',
|
|
16
|
+
'breaking news',
|
|
17
|
+
'adopted texts',
|
|
18
|
+
'legislative updates',
|
|
19
|
+
'parliamentary events',
|
|
20
|
+
];
|
|
21
|
+
/**
|
|
22
|
+
* Extract content-aware keywords from breaking news feed data.
|
|
23
|
+
*
|
|
24
|
+
* Scans adopted text titles, event titles, and procedure titles for
|
|
25
|
+
* topic-relevant terms that enrich SEO keywords beyond the static base set.
|
|
26
|
+
*
|
|
27
|
+
* @param feedData - Breaking news feed data (may be undefined)
|
|
28
|
+
* @returns Deduplicated array of keywords including base + content-derived terms
|
|
29
|
+
*/
|
|
30
|
+
function buildBreakingKeywords(feedData) {
|
|
31
|
+
const keywords = [...BREAKING_NEWS_BASE_KEYWORDS];
|
|
32
|
+
if (!feedData)
|
|
33
|
+
return keywords;
|
|
34
|
+
for (const text of feedData.adoptedTexts.slice(0, 5)) {
|
|
35
|
+
if (text.title)
|
|
36
|
+
keywords.push(text.title.slice(0, 60));
|
|
37
|
+
}
|
|
38
|
+
for (const evt of feedData.events.slice(0, 3)) {
|
|
39
|
+
if (evt.title)
|
|
40
|
+
keywords.push(evt.title.slice(0, 60));
|
|
41
|
+
}
|
|
42
|
+
for (const proc of feedData.procedures.slice(0, 3)) {
|
|
43
|
+
if (proc.title)
|
|
44
|
+
keywords.push(proc.title.slice(0, 60));
|
|
45
|
+
}
|
|
46
|
+
return [...new Set(keywords)];
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Build a content-aware description from breaking news feed data.
|
|
50
|
+
* Summarises the count of adopted texts, events, procedures, and MEP updates
|
|
51
|
+
* and highlights the first adopted text title when available.
|
|
52
|
+
*
|
|
53
|
+
* @param date - Publication date
|
|
54
|
+
* @param feedData - Breaking news feed data (may be undefined)
|
|
55
|
+
* @returns SEO-friendly description string (≤ 200 chars)
|
|
56
|
+
*/
|
|
57
|
+
function buildBreakingDescription(date, feedData) {
|
|
58
|
+
if (!feedData)
|
|
59
|
+
return `European Parliament breaking developments for ${date}.`;
|
|
60
|
+
const counts = [];
|
|
61
|
+
if (feedData.adoptedTexts.length > 0)
|
|
62
|
+
counts.push(pl(feedData.adoptedTexts.length, 'adopted text', 'adopted texts'));
|
|
63
|
+
if (feedData.events.length > 0)
|
|
64
|
+
counts.push(pl(feedData.events.length, 'event', 'events'));
|
|
65
|
+
if (feedData.procedures.length > 0)
|
|
66
|
+
counts.push(pl(feedData.procedures.length, 'procedure', 'procedures'));
|
|
67
|
+
if (feedData.mepUpdates.length > 0)
|
|
68
|
+
counts.push(pl(feedData.mepUpdates.length, 'MEP update', 'MEP updates'));
|
|
69
|
+
if (counts.length === 0)
|
|
70
|
+
return `European Parliament breaking developments for ${date}.`;
|
|
71
|
+
const highlight = feedData.adoptedTexts[0]?.title ?? feedData.events[0]?.title ?? '';
|
|
72
|
+
const base = `EP breaking: ${counts.join(', ')}`;
|
|
73
|
+
if (highlight) {
|
|
74
|
+
const full = `${base}. Highlights: ${highlight}`;
|
|
75
|
+
return full.length > 200 ? full.slice(0, 197) + '...' : full;
|
|
76
|
+
}
|
|
77
|
+
return base.length > 200 ? base.slice(0, 197) + '...' : base;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Build a content-aware title suffix from feed data item counts.
|
|
81
|
+
*
|
|
82
|
+
* @param feedData - Breaking news feed data (may be undefined)
|
|
83
|
+
* @returns Short suffix string for appending to the base title, or empty string
|
|
84
|
+
*/
|
|
85
|
+
function buildBreakingTitleSuffix(feedData) {
|
|
86
|
+
if (!feedData)
|
|
87
|
+
return '';
|
|
88
|
+
const total = feedData.adoptedTexts.length +
|
|
89
|
+
feedData.events.length +
|
|
90
|
+
feedData.procedures.length +
|
|
91
|
+
feedData.mepUpdates.length;
|
|
92
|
+
if (total === 0)
|
|
93
|
+
return '';
|
|
94
|
+
const parts = [];
|
|
95
|
+
if (feedData.adoptedTexts.length > 0)
|
|
96
|
+
parts.push(pl(feedData.adoptedTexts.length, 'Text', 'Texts'));
|
|
97
|
+
if (feedData.events.length > 0)
|
|
98
|
+
parts.push(pl(feedData.events.length, 'Event', 'Events'));
|
|
99
|
+
if (feedData.procedures.length > 0)
|
|
100
|
+
parts.push(pl(feedData.procedures.length, 'Procedure', 'Procedures'));
|
|
101
|
+
return parts.join(', ');
|
|
102
|
+
}
|
|
103
|
+
// ─── Strategy implementation ──────────────────────────────────────────────────
|
|
104
|
+
/**
|
|
105
|
+
* Article strategy for {@link ArticleCategory.BREAKING_NEWS}.
|
|
106
|
+
*
|
|
107
|
+
* **Feed-first**: EP feed endpoints are the primary data source.
|
|
108
|
+
* Analytical tools provide supplementary context only.
|
|
109
|
+
* Stats are NEVER the news itself.
|
|
110
|
+
*/
|
|
111
|
+
export class BreakingNewsStrategy {
|
|
112
|
+
type = ArticleCategory.BREAKING_NEWS;
|
|
113
|
+
requiredMCPTools = [
|
|
114
|
+
'get_adopted_texts_feed',
|
|
115
|
+
'get_events_feed',
|
|
116
|
+
'get_procedures_feed',
|
|
117
|
+
'get_meps_feed',
|
|
118
|
+
'detect_voting_anomalies',
|
|
119
|
+
'analyze_coalition_dynamics',
|
|
120
|
+
];
|
|
121
|
+
/**
|
|
122
|
+
* Fetch EP feed data (primary) first, then conditionally fetch analytical
|
|
123
|
+
* context (secondary) in a second phase.
|
|
124
|
+
*
|
|
125
|
+
* @param client - MCP client or null
|
|
126
|
+
* @param date - ISO 8601 publication date
|
|
127
|
+
* @returns Populated breaking news data payload
|
|
128
|
+
*/
|
|
129
|
+
async fetchData(client, date) {
|
|
130
|
+
// Step 0: Check for pre-fetched feed data file (set by --feed-data CLI arg).
|
|
131
|
+
// This allows agentic workflows to pass MCP data fetched via framework tools
|
|
132
|
+
// into the generator without requiring a direct MCP connection.
|
|
133
|
+
const feedDataFile = process.env['EP_FEED_DATA_FILE'];
|
|
134
|
+
if (feedDataFile) {
|
|
135
|
+
console.log(` 📂 Loading pre-fetched feed data from: ${feedDataFile}`);
|
|
136
|
+
const fileFeedData = loadFeedDataFromFile(feedDataFile, { start: date, end: date });
|
|
137
|
+
if (fileFeedData) {
|
|
138
|
+
const totalItems = fileFeedData.adoptedTexts.length +
|
|
139
|
+
fileFeedData.events.length +
|
|
140
|
+
fileFeedData.procedures.length +
|
|
141
|
+
fileFeedData.mepUpdates.length;
|
|
142
|
+
console.log(` 📰 Pre-fetched feed data: ${totalItems} total items`);
|
|
143
|
+
// Fetch analytical context from MCP if client available, else skip
|
|
144
|
+
let anomalyRaw = '';
|
|
145
|
+
let coalitionRaw = '';
|
|
146
|
+
if (client && totalItems > 0) {
|
|
147
|
+
[anomalyRaw, coalitionRaw] = await Promise.all([
|
|
148
|
+
fetchVotingAnomalies(client),
|
|
149
|
+
fetchCoalitionDynamics(client),
|
|
150
|
+
]);
|
|
151
|
+
}
|
|
152
|
+
return { date, feedData: fileFeedData, anomalyRaw, coalitionRaw, reportRaw: '' };
|
|
153
|
+
}
|
|
154
|
+
console.log(' ⚠️ Pre-fetched feed data failed to load — falling through to MCP fetch');
|
|
155
|
+
}
|
|
156
|
+
if (client) {
|
|
157
|
+
console.log(' 📡 Fetching EP feed data (primary) and analytical context...');
|
|
158
|
+
}
|
|
159
|
+
// Step 1: Fetch feed data (PRIMARY news content) — 'today' for realtime breaking news
|
|
160
|
+
const feedData = await fetchBreakingNewsFeedData(client, 'today');
|
|
161
|
+
// When client is null, feedData is undefined — MCP unavailable
|
|
162
|
+
if (!feedData) {
|
|
163
|
+
console.log(' ⚠️ MCP unavailable — no feed data or analytical context');
|
|
164
|
+
return { date, feedData, anomalyRaw: '', coalitionRaw: '', reportRaw: '' };
|
|
165
|
+
}
|
|
166
|
+
const totalFeedItems = feedData.adoptedTexts.length +
|
|
167
|
+
feedData.events.length +
|
|
168
|
+
feedData.procedures.length +
|
|
169
|
+
feedData.mepUpdates.length;
|
|
170
|
+
if (totalFeedItems > 0) {
|
|
171
|
+
console.log(` 📰 Feed data: ${feedData.adoptedTexts.length} adopted texts, ` +
|
|
172
|
+
`${feedData.events.length} events, ${feedData.procedures.length} procedures, ` +
|
|
173
|
+
`${feedData.mepUpdates.length} MEP updates`);
|
|
174
|
+
}
|
|
175
|
+
else {
|
|
176
|
+
console.log(' ⚠️ No feed data available — skipping analytical context fetch');
|
|
177
|
+
return { date, feedData, anomalyRaw: '', coalitionRaw: '', reportRaw: '' };
|
|
178
|
+
}
|
|
179
|
+
// Step 2: Fetch analytical context only when at least one feed item is available
|
|
180
|
+
const [anomalyRaw, coalitionRaw] = await Promise.all([
|
|
181
|
+
fetchVotingAnomalies(client),
|
|
182
|
+
fetchCoalitionDynamics(client),
|
|
183
|
+
]);
|
|
184
|
+
return { date, feedData, anomalyRaw, coalitionRaw, reportRaw: '' };
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Build the breaking news HTML body for the specified language.
|
|
188
|
+
*
|
|
189
|
+
* @param data - Breaking news data payload
|
|
190
|
+
* @param lang - Target language code used for editorial strings
|
|
191
|
+
* @returns Article HTML body
|
|
192
|
+
*/
|
|
193
|
+
buildContent(data, lang) {
|
|
194
|
+
const base = buildBreakingNewsContent(data.date, data.anomalyRaw, data.coalitionRaw, data.reportRaw, '', lang, [], [], [], data.feedData);
|
|
195
|
+
const analysis = buildBreakingAnalysis(data.date, data.feedData, data.anomalyRaw, data.coalitionRaw, lang);
|
|
196
|
+
const deepSection = buildDeepAnalysisSection(analysis, lang);
|
|
197
|
+
const mindmapData = buildBreakingMindmap(data.feedData, lang);
|
|
198
|
+
const mindmapSection = buildIntelligenceMindmapSection(mindmapData, lang);
|
|
199
|
+
const swotData = buildBreakingSwot(data.feedData, data.anomalyRaw, data.coalitionRaw, lang);
|
|
200
|
+
const swotSection = buildSwotSection(swotData, lang);
|
|
201
|
+
const dashboardData = buildBreakingDashboard(data.feedData, lang);
|
|
202
|
+
const dashboardSection = buildDashboardSection(dashboardData, lang);
|
|
203
|
+
const injection = deepSection + mindmapSection + swotSection + dashboardSection;
|
|
204
|
+
// Inject before the closing </div> of .article-content
|
|
205
|
+
if (injection) {
|
|
206
|
+
const closingTag = '</div>';
|
|
207
|
+
const lastIdx = base.lastIndexOf(closingTag);
|
|
208
|
+
if (lastIdx !== -1) {
|
|
209
|
+
return base.slice(0, lastIdx) + injection + '\n' + base.slice(lastIdx);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
return base;
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Return language-specific metadata for the breaking news article.
|
|
216
|
+
*
|
|
217
|
+
* @param data - Breaking news data payload
|
|
218
|
+
* @param lang - Target language code
|
|
219
|
+
* @returns Localised metadata
|
|
220
|
+
*/
|
|
221
|
+
getMetadata(data, lang) {
|
|
222
|
+
const titleFn = getLocalizedString(BREAKING_NEWS_TITLES, lang);
|
|
223
|
+
const { title: baseTitle, subtitle: baseSubtitle } = titleFn(data.date);
|
|
224
|
+
const suffix = lang === 'en' ? buildBreakingTitleSuffix(data.feedData) : '';
|
|
225
|
+
const title = suffix ? `${baseTitle} — ${suffix}` : baseTitle;
|
|
226
|
+
const description = lang === 'en' ? buildBreakingDescription(data.date, data.feedData) : '';
|
|
227
|
+
const subtitle = description || baseSubtitle;
|
|
228
|
+
const keywords = buildBreakingKeywords(data.feedData);
|
|
229
|
+
if (data.feedData) {
|
|
230
|
+
const score = scoreBreakingNewsSignificance(data.feedData);
|
|
231
|
+
if (score.overallScore >= SIGNIFICANCE_THRESHOLD) {
|
|
232
|
+
keywords.push(`significance:${score.overallScore}`);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
return {
|
|
236
|
+
title,
|
|
237
|
+
subtitle,
|
|
238
|
+
keywords,
|
|
239
|
+
category: ArticleCategory.BREAKING_NEWS,
|
|
240
|
+
sources: [],
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
/** Singleton instance for use by the strategy registry */
|
|
245
|
+
export const breakingNewsStrategy = new BreakingNewsStrategy();
|
|
246
|
+
//# sourceMappingURL=breaking-news-strategy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"breaking-news-strategy.js","sourceRoot":"","sources":["../../../src/generators/strategies/breaking-news-strategy.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module Generators/Strategies/CommitteeReportsStrategy
|
|
3
|
+
* @description Article strategy for the Committee Reports article type.
|
|
4
|
+
* Fetches data for each featured committee in parallel and renders an
|
|
5
|
+
* effectiveness and activity overview article.
|
|
6
|
+
*/
|
|
7
|
+
import type { EuropeanParliamentMCPClient } from '../../mcp/ep-mcp-client.js';
|
|
8
|
+
import { ArticleCategory } from '../../types/index.js';
|
|
9
|
+
import type { LanguageCode, CommitteeData, EPFeedData } from '../../types/index.js';
|
|
10
|
+
import type { ArticleStrategy, ArticleData, ArticleMetadata } from './article-strategy.js';
|
|
11
|
+
/** Data fetched and pre-processed by {@link CommitteeReportsStrategy} */
|
|
12
|
+
export interface CommitteeReportsArticleData extends ArticleData {
|
|
13
|
+
/** Resolved data for each featured committee */
|
|
14
|
+
readonly committeeDataList: readonly CommitteeData[];
|
|
15
|
+
/** EP feed data for enrichment (when available) */
|
|
16
|
+
readonly feedData?: EPFeedData | undefined;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Narrow union type for the committee theme category keys used when
|
|
20
|
+
* grouping and displaying adopted texts.
|
|
21
|
+
*/
|
|
22
|
+
export type CommitteeTheme = 'ENVI' | 'ECON' | 'AFET' | 'LIBE' | 'AGRI' | 'OTHER';
|
|
23
|
+
/** Lowercase keywords that map an adopted-text title to the AFET theme group */
|
|
24
|
+
export declare const AFET_KEYWORDS: readonly string[];
|
|
25
|
+
/** Lowercase keywords that map an adopted-text title to the LIBE theme group */
|
|
26
|
+
export declare const LIBE_KEYWORDS: readonly string[];
|
|
27
|
+
/** Lowercase keywords that map an adopted-text title to the AGRI theme group */
|
|
28
|
+
export declare const AGRI_KEYWORDS: readonly string[];
|
|
29
|
+
/** Lowercase keywords that map an adopted-text title to the ENVI theme group */
|
|
30
|
+
export declare const ENVI_KEYWORDS: readonly string[];
|
|
31
|
+
/** Lowercase keywords that map an adopted-text title to the ECON theme group */
|
|
32
|
+
export declare const ECON_KEYWORDS: readonly string[];
|
|
33
|
+
/**
|
|
34
|
+
* Categorize an adopted-text title into a committee theme group.
|
|
35
|
+
*
|
|
36
|
+
* LIBE is tested before AFET so that human-rights and human-trafficking
|
|
37
|
+
* titles are classified under civil liberties even when they also mention
|
|
38
|
+
* an AFET country keyword (e.g. "Ukraine"). Both are tested before AGRI
|
|
39
|
+
* to avoid person-name false positives (e.g. "Bobi Wine").
|
|
40
|
+
*
|
|
41
|
+
* @param title - Adopted text title to categorize
|
|
42
|
+
* @returns Committee theme key — one of `'ENVI'` | `'ECON'` | `'AFET'` | `'LIBE'` | `'AGRI'` | `'OTHER'`
|
|
43
|
+
*/
|
|
44
|
+
export declare function categorizeAdoptedText(title: string): CommitteeTheme;
|
|
45
|
+
/**
|
|
46
|
+
* Article strategy for {@link ArticleCategory.COMMITTEE_REPORTS}.
|
|
47
|
+
* Fetches info, documents and effectiveness data for the featured committees
|
|
48
|
+
* then renders an activity overview.
|
|
49
|
+
*/
|
|
50
|
+
export declare class CommitteeReportsStrategy implements ArticleStrategy<CommitteeReportsArticleData> {
|
|
51
|
+
readonly type = ArticleCategory.COMMITTEE_REPORTS;
|
|
52
|
+
readonly requiredMCPTools: readonly ["get_committee_info", "search_documents", "analyze_legislative_effectiveness", "get_committee_documents_feed"];
|
|
53
|
+
/**
|
|
54
|
+
* Fetch committee data for all featured committees in parallel.
|
|
55
|
+
*
|
|
56
|
+
* @param client - MCP client or null
|
|
57
|
+
* @param date - ISO 8601 publication date
|
|
58
|
+
* @returns Populated committee reports data payload
|
|
59
|
+
*/
|
|
60
|
+
fetchData(client: EuropeanParliamentMCPClient | null, date: string): Promise<CommitteeReportsArticleData>;
|
|
61
|
+
/**
|
|
62
|
+
* Build the committee reports HTML body.
|
|
63
|
+
*
|
|
64
|
+
* @param data - Committee reports data payload
|
|
65
|
+
* @param lang - Language code for localized content
|
|
66
|
+
* @returns Article HTML body
|
|
67
|
+
*/
|
|
68
|
+
buildContent(data: CommitteeReportsArticleData, lang: LanguageCode): string;
|
|
69
|
+
/**
|
|
70
|
+
* Return language-specific metadata for the committee reports article.
|
|
71
|
+
*
|
|
72
|
+
* @param data - Committee reports data payload
|
|
73
|
+
* @param lang - Target language code
|
|
74
|
+
* @returns Localised metadata
|
|
75
|
+
*/
|
|
76
|
+
getMetadata(data: CommitteeReportsArticleData, lang: LanguageCode): ArticleMetadata;
|
|
77
|
+
/**
|
|
78
|
+
* Skip generation when no real data is available.
|
|
79
|
+
*
|
|
80
|
+
* Skips when:
|
|
81
|
+
* - All committee fetches failed (empty committeeDataList), or
|
|
82
|
+
* - All fetched committee data is placeholder AND no feed data is available.
|
|
83
|
+
* When EP feed data contains adopted texts or other items, the article can still
|
|
84
|
+
* provide valuable content even if individual committee metadata is sparse.
|
|
85
|
+
*
|
|
86
|
+
* @param data - Committee reports data payload
|
|
87
|
+
* @returns `true` when there is no usable data at all
|
|
88
|
+
*/
|
|
89
|
+
shouldSkip(data: CommitteeReportsArticleData): boolean;
|
|
90
|
+
}
|
|
91
|
+
/** Singleton instance for use by the strategy registry */
|
|
92
|
+
export declare const committeeReportsStrategy: CommitteeReportsStrategy;
|
|
93
|
+
//# sourceMappingURL=committee-reports-strategy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"committee-reports-strategy.d.ts","sourceRoot":"","sources":["../../../src/generators/strategies/committee-reports-strategy.ts"],"names":[],"mappings":"AAGA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,4BAA4B,CAAC;AAC9E,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AA4BpF,OAAO,KAAK,EAAE,eAAe,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAoH3F,yEAAyE;AACzE,MAAM,WAAW,2BAA4B,SAAQ,WAAW;IAC9D,gDAAgD;IAChD,QAAQ,CAAC,iBAAiB,EAAE,SAAS,aAAa,EAAE,CAAC;IACrD,mDAAmD;IACnD,QAAQ,CAAC,QAAQ,CAAC,EAAE,UAAU,GAAG,SAAS,CAAC;CAC5C;AAID;;;GAGG;AACH,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;AAclF,gFAAgF;AAChF,eAAO,MAAM,aAAa,EAAE,SAAS,MAAM,EAkB1C,CAAC;AAEF,gFAAgF;AAChF,eAAO,MAAM,aAAa,EAAE,SAAS,MAAM,EAc1C,CAAC;AAEF,gFAAgF;AAChF,eAAO,MAAM,aAAa,EAAE,SAAS,MAAM,EAQ1C,CAAC;AAEF,gFAAgF;AAChF,eAAO,MAAM,aAAa,EAAE,SAAS,MAAM,EAW1C,CAAC;AAEF,gFAAgF;AAChF,eAAO,MAAM,aAAa,EAAE,SAAS,MAAM,EAO1C,CAAC;AAEF;;;;;;;;;;GAUG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,cAAc,CAQnE;AAiJD;;;;GAIG;AACH,qBAAa,wBAAyB,YAAW,eAAe,CAAC,2BAA2B,CAAC;IAC3F,QAAQ,CAAC,IAAI,qCAAqC;IAElD,QAAQ,CAAC,gBAAgB,2HAKd;IAEX;;;;;;OAMG;IACG,SAAS,CACb,MAAM,EAAE,2BAA2B,GAAG,IAAI,EAC1C,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,2BAA2B,CAAC;IAwBvC;;;;;;OAMG;IACH,YAAY,CAAC,IAAI,EAAE,2BAA2B,EAAE,IAAI,EAAE,YAAY,GAAG,MAAM;IAuB3E;;;;;;OAMG;IACH,WAAW,CAAC,IAAI,EAAE,2BAA2B,EAAE,IAAI,EAAE,YAAY,GAAG,eAAe;IAoBnF;;;;;;;;;;;OAWG;IACH,UAAU,CAAC,IAAI,EAAE,2BAA2B,GAAG,OAAO;CAsBvD;AAED,0DAA0D;AAC1D,eAAO,MAAM,wBAAwB,0BAAiC,CAAC"}
|