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,215 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: 2024-2026 Hack23 AB
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
import { ArticleCategory } from '../../types/index.js';
|
|
4
|
+
import { MOTIONS_TITLES, getLocalizedString } from '../../constants/languages.js';
|
|
5
|
+
import { fetchMotionsData, fetchEPFeedData } from '../pipeline/fetch-stage.js';
|
|
6
|
+
import { generateMotionsContent, buildPoliticalAlignmentSection, buildAdoptedTextsSection, PLACEHOLDER_MARKER, } from '../motions-content.js';
|
|
7
|
+
import { buildDeepAnalysisSection } from '../deep-analysis-content.js';
|
|
8
|
+
import { buildVotingAnalysis, buildVotingSwot, buildVotingDashboard, buildVotingMindmap, } 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 Motions articles */
|
|
14
|
+
const MOTIONS_BASE_KEYWORDS = [
|
|
15
|
+
'European Parliament',
|
|
16
|
+
'motions',
|
|
17
|
+
'voting records',
|
|
18
|
+
'party cohesion',
|
|
19
|
+
'parliamentary questions',
|
|
20
|
+
];
|
|
21
|
+
/**
|
|
22
|
+
* Extract content-aware keywords from motions data.
|
|
23
|
+
*
|
|
24
|
+
* Adds voting record titles, anomaly descriptions, question topics,
|
|
25
|
+
* and adopted text titles to the base keyword set.
|
|
26
|
+
*
|
|
27
|
+
* @param data - Motions article data payload
|
|
28
|
+
* @returns Deduplicated keyword array
|
|
29
|
+
*/
|
|
30
|
+
function buildMotionsKeywords(data) {
|
|
31
|
+
const keywords = [...MOTIONS_BASE_KEYWORDS];
|
|
32
|
+
for (const r of data.votingRecords.slice(0, 5)) {
|
|
33
|
+
if (r.title)
|
|
34
|
+
keywords.push(r.title.slice(0, 60));
|
|
35
|
+
}
|
|
36
|
+
for (const a of data.anomalies.slice(0, 3)) {
|
|
37
|
+
if (a.type)
|
|
38
|
+
keywords.push(a.type);
|
|
39
|
+
}
|
|
40
|
+
for (const q of data.questions.slice(0, 3)) {
|
|
41
|
+
if (q.topic)
|
|
42
|
+
keywords.push(q.topic);
|
|
43
|
+
}
|
|
44
|
+
if (data.feedData?.adoptedTexts) {
|
|
45
|
+
for (const text of data.feedData.adoptedTexts.slice(0, 3)) {
|
|
46
|
+
if (text.title)
|
|
47
|
+
keywords.push(text.title.slice(0, 60));
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return [...new Set(keywords)];
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Build a content-aware description from motions data.
|
|
54
|
+
* Summarises voting record count, anomaly count, and key vote highlights.
|
|
55
|
+
*
|
|
56
|
+
* @param data - Motions article data payload
|
|
57
|
+
* @returns SEO-friendly description (≤ 200 chars)
|
|
58
|
+
*/
|
|
59
|
+
function buildMotionsDescription(data) {
|
|
60
|
+
const parts = [];
|
|
61
|
+
if (data.votingRecords.length > 0)
|
|
62
|
+
parts.push(`${pl(data.votingRecords.length, 'vote', 'votes')} analysed`);
|
|
63
|
+
if (data.anomalies.length > 0)
|
|
64
|
+
parts.push(`${pl(data.anomalies.length, 'anomaly', 'anomalies')} detected`);
|
|
65
|
+
if (data.questions.length > 0)
|
|
66
|
+
parts.push(pl(data.questions.length, 'parliamentary question', 'parliamentary questions'));
|
|
67
|
+
const adoptedCount = data.feedData?.adoptedTexts?.length ?? 0;
|
|
68
|
+
if (adoptedCount > 0)
|
|
69
|
+
parts.push(pl(adoptedCount, 'adopted text', 'adopted texts'));
|
|
70
|
+
if (parts.length === 0) {
|
|
71
|
+
return `European Parliament plenary votes and resolutions from ${data.dateFromStr} to ${data.date}.`;
|
|
72
|
+
}
|
|
73
|
+
const highlight = data.votingRecords[0]?.title ?? '';
|
|
74
|
+
const base = `EP voting analysis: ${parts.join(', ')}`;
|
|
75
|
+
if (highlight) {
|
|
76
|
+
const full = `${base}. Key vote: ${highlight}`;
|
|
77
|
+
return full.length > 200 ? full.slice(0, 197) + '...' : full;
|
|
78
|
+
}
|
|
79
|
+
return base.length > 200 ? base.slice(0, 197) + '...' : base;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Build a content-aware title suffix from motions data counts.
|
|
83
|
+
*
|
|
84
|
+
* @param data - Motions article data payload
|
|
85
|
+
* @returns Short suffix for the title, or empty string
|
|
86
|
+
*/
|
|
87
|
+
function buildMotionsTitleSuffix(data) {
|
|
88
|
+
const parts = [];
|
|
89
|
+
if (data.votingRecords.length > 0) {
|
|
90
|
+
parts.push(pl(data.votingRecords.length, 'Vote', 'Votes'));
|
|
91
|
+
}
|
|
92
|
+
if (data.anomalies.length > 0) {
|
|
93
|
+
parts.push(pl(data.anomalies.length, 'Anomaly', 'Anomalies'));
|
|
94
|
+
}
|
|
95
|
+
const adoptedCount = data.feedData?.adoptedTexts?.length ?? 0;
|
|
96
|
+
if (adoptedCount > 0) {
|
|
97
|
+
parts.push(pl(adoptedCount, 'Adopted Text', 'Adopted Texts'));
|
|
98
|
+
}
|
|
99
|
+
return parts.join(', ');
|
|
100
|
+
}
|
|
101
|
+
/** Number of days to look back when fetching motions data */
|
|
102
|
+
const MOTIONS_LOOKBACK_DAYS = 30;
|
|
103
|
+
// ─── Strategy implementation ──────────────────────────────────────────────────
|
|
104
|
+
/**
|
|
105
|
+
* Article strategy for {@link ArticleCategory.MOTIONS}.
|
|
106
|
+
* Aggregates voting data over a rolling 30-day window and surfaces
|
|
107
|
+
* patterns, anomalies and parliamentary questions.
|
|
108
|
+
*/
|
|
109
|
+
export class MotionsStrategy {
|
|
110
|
+
type = ArticleCategory.MOTIONS;
|
|
111
|
+
requiredMCPTools = [
|
|
112
|
+
'get_voting_records',
|
|
113
|
+
'analyze_voting_patterns',
|
|
114
|
+
'detect_voting_anomalies',
|
|
115
|
+
'get_parliamentary_questions',
|
|
116
|
+
'get_adopted_texts_feed',
|
|
117
|
+
'get_parliamentary_questions_feed',
|
|
118
|
+
];
|
|
119
|
+
/**
|
|
120
|
+
* Fetch all motions data for the last 30 days.
|
|
121
|
+
*
|
|
122
|
+
* @param client - MCP client or null
|
|
123
|
+
* @param date - ISO 8601 publication date (end of the look-back window)
|
|
124
|
+
* @returns Populated motions data payload
|
|
125
|
+
*/
|
|
126
|
+
async fetchData(client, date) {
|
|
127
|
+
const dateFrom = new Date(`${date}T00:00:00Z`);
|
|
128
|
+
dateFrom.setUTCDate(dateFrom.getUTCDate() - MOTIONS_LOOKBACK_DAYS);
|
|
129
|
+
const dateFromParts = dateFrom.toISOString().split('T');
|
|
130
|
+
if (!dateFromParts[0]) {
|
|
131
|
+
throw new Error('Invalid date format generated for motions look-back window');
|
|
132
|
+
}
|
|
133
|
+
const dateFromStr = dateFromParts[0];
|
|
134
|
+
// Fetch voting data and EP feed data in parallel
|
|
135
|
+
const feedDateRange = { start: dateFromStr, end: date };
|
|
136
|
+
const [motionsDataResult, feedData] = await Promise.all([
|
|
137
|
+
fetchMotionsData(client, dateFromStr, date),
|
|
138
|
+
fetchEPFeedData(client, 'one-month', feedDateRange),
|
|
139
|
+
]);
|
|
140
|
+
const { votingRecords, votingPatterns, anomalies, questions } = motionsDataResult;
|
|
141
|
+
return {
|
|
142
|
+
date,
|
|
143
|
+
dateFromStr,
|
|
144
|
+
votingRecords,
|
|
145
|
+
votingPatterns,
|
|
146
|
+
anomalies,
|
|
147
|
+
questions,
|
|
148
|
+
feedData,
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Build the motions HTML body for the specified language.
|
|
153
|
+
*
|
|
154
|
+
* @param data - Motions data payload
|
|
155
|
+
* @param lang - Target language code used for editorial strings
|
|
156
|
+
* @returns Article HTML body
|
|
157
|
+
*/
|
|
158
|
+
buildContent(data, lang) {
|
|
159
|
+
const base = generateMotionsContent(data.dateFromStr, data.date, [...data.votingRecords], [...data.votingPatterns], [...data.anomalies], [...data.questions], lang);
|
|
160
|
+
const adoptedTextsSection = data.feedData?.adoptedTexts
|
|
161
|
+
? buildAdoptedTextsSection(data.feedData.adoptedTexts, lang)
|
|
162
|
+
: '';
|
|
163
|
+
const alignmentSection = buildPoliticalAlignmentSection([...data.votingRecords], [], lang);
|
|
164
|
+
const analysis = buildVotingAnalysis(data.dateFromStr, data.date, data.votingRecords, data.votingPatterns, data.anomalies, data.questions);
|
|
165
|
+
const deepSection = buildDeepAnalysisSection(analysis, lang, 'en');
|
|
166
|
+
const mindmapData = buildVotingMindmap(data.votingRecords, data.votingPatterns, data.anomalies, lang);
|
|
167
|
+
const mindmapSection = buildIntelligenceMindmapSection(mindmapData, lang);
|
|
168
|
+
const swotData = buildVotingSwot(data.votingRecords, data.votingPatterns, data.anomalies, lang);
|
|
169
|
+
const swotSection = buildSwotSection(swotData, lang);
|
|
170
|
+
const hasRealVotingData = data.votingRecords.some((r) => r.result !== PLACEHOLDER_MARKER);
|
|
171
|
+
const dashboardData = hasRealVotingData
|
|
172
|
+
? buildVotingDashboard(data.votingRecords, data.votingPatterns, data.anomalies, lang)
|
|
173
|
+
: null;
|
|
174
|
+
const dashboardSection = buildDashboardSection(dashboardData, lang);
|
|
175
|
+
// Inject at the explicit <!-- /article-content --> marker so the section
|
|
176
|
+
// stays inside the .article-content styling scope. The marker is always
|
|
177
|
+
// emitted by generateMotionsContent as the last child of that wrapper and
|
|
178
|
+
// is removed from the final HTML during this replacement.
|
|
179
|
+
const injection = adoptedTextsSection +
|
|
180
|
+
(alignmentSection || '') +
|
|
181
|
+
deepSection +
|
|
182
|
+
mindmapSection +
|
|
183
|
+
swotSection +
|
|
184
|
+
dashboardSection;
|
|
185
|
+
if (injection) {
|
|
186
|
+
return base.replace('<!-- /article-content -->', `${injection}\n`);
|
|
187
|
+
}
|
|
188
|
+
return base.replace('<!-- /article-content -->', '');
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Return language-specific metadata for the motions article.
|
|
192
|
+
*
|
|
193
|
+
* @param data - Motions data payload
|
|
194
|
+
* @param lang - Target language code
|
|
195
|
+
* @returns Localised metadata
|
|
196
|
+
*/
|
|
197
|
+
getMetadata(data, lang) {
|
|
198
|
+
const titleFn = getLocalizedString(MOTIONS_TITLES, lang);
|
|
199
|
+
const { title: baseTitle, subtitle: baseSubtitle } = titleFn(data.date);
|
|
200
|
+
const suffix = lang === 'en' ? buildMotionsTitleSuffix(data) : '';
|
|
201
|
+
const title = suffix ? `${baseTitle} — ${suffix}` : baseTitle;
|
|
202
|
+
const description = lang === 'en' ? buildMotionsDescription(data) : '';
|
|
203
|
+
const subtitle = description || baseSubtitle;
|
|
204
|
+
return {
|
|
205
|
+
title,
|
|
206
|
+
subtitle,
|
|
207
|
+
keywords: buildMotionsKeywords(data),
|
|
208
|
+
category: ArticleCategory.MOTIONS,
|
|
209
|
+
sources: [],
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
/** Singleton instance for use by the strategy registry */
|
|
214
|
+
export const motionsStrategy = new MotionsStrategy();
|
|
215
|
+
//# sourceMappingURL=motions-strategy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"motions-strategy.js","sourceRoot":"","sources":["../../../src/generators/strategies/motions-strategy.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module Generators/Strategies/PropositionsStrategy
|
|
3
|
+
* @description Article strategy for the Propositions article type.
|
|
4
|
+
* Fetches legislative proposals and active pipeline data from MCP, then
|
|
5
|
+
* renders a language-specific legislative overview article.
|
|
6
|
+
*/
|
|
7
|
+
import type { EuropeanParliamentMCPClient } from '../../mcp/ep-mcp-client.js';
|
|
8
|
+
import { ArticleCategory } from '../../types/index.js';
|
|
9
|
+
import type { LanguageCode, EPFeedData } from '../../types/index.js';
|
|
10
|
+
import type { PipelineData } from '../propositions-content.js';
|
|
11
|
+
import type { ArticleStrategy, ArticleData, ArticleMetadata } from './article-strategy.js';
|
|
12
|
+
/** Data fetched and pre-processed by {@link PropositionsStrategy} */
|
|
13
|
+
export interface PropositionsArticleData extends ArticleData {
|
|
14
|
+
/** Pre-sanitised HTML for the legislative procedures list section */
|
|
15
|
+
readonly proposalsHtml: string;
|
|
16
|
+
/** Pre-sanitised HTML for the recently adopted texts section */
|
|
17
|
+
readonly adoptedTextsHtml: string;
|
|
18
|
+
/** Active legislative pipeline data (null when MCP unavailable) */
|
|
19
|
+
readonly pipelineData: PipelineData | null;
|
|
20
|
+
/** Pre-sanitised HTML for the tracked procedure section */
|
|
21
|
+
readonly procedureHtml: string;
|
|
22
|
+
/** EP feed data for enrichment (when available) */
|
|
23
|
+
readonly feedData?: EPFeedData | undefined;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Article strategy for {@link ArticleCategory.PROPOSITIONS}.
|
|
27
|
+
* Fetches legislative proposals, active pipeline status, and procedure detail
|
|
28
|
+
* then renders a language-specific article.
|
|
29
|
+
*/
|
|
30
|
+
export declare class PropositionsStrategy implements ArticleStrategy<PropositionsArticleData> {
|
|
31
|
+
readonly type = ArticleCategory.PROPOSITIONS;
|
|
32
|
+
readonly requiredMCPTools: readonly ["search_documents", "monitor_legislative_pipeline", "track_legislation", "get_procedures_feed", "get_adopted_texts_feed"];
|
|
33
|
+
/**
|
|
34
|
+
* Fetch legislative proposals and pipeline data in parallel.
|
|
35
|
+
*
|
|
36
|
+
* @param client - MCP client or null
|
|
37
|
+
* @param date - ISO 8601 publication date
|
|
38
|
+
* @returns Populated propositions data payload
|
|
39
|
+
*/
|
|
40
|
+
fetchData(client: EuropeanParliamentMCPClient | null, date: string): Promise<PropositionsArticleData>;
|
|
41
|
+
/**
|
|
42
|
+
* Build the propositions HTML body using language-specific strings.
|
|
43
|
+
*
|
|
44
|
+
* @param data - Propositions data payload
|
|
45
|
+
* @param lang - Target language code
|
|
46
|
+
* @returns Article HTML body
|
|
47
|
+
*/
|
|
48
|
+
buildContent(data: PropositionsArticleData, lang: LanguageCode): string;
|
|
49
|
+
/**
|
|
50
|
+
* Return language-specific metadata for the propositions article.
|
|
51
|
+
*
|
|
52
|
+
* @param data - Propositions data payload
|
|
53
|
+
* @param lang - Target language code
|
|
54
|
+
* @returns Localised metadata
|
|
55
|
+
*/
|
|
56
|
+
getMetadata(data: PropositionsArticleData, lang: LanguageCode): ArticleMetadata;
|
|
57
|
+
}
|
|
58
|
+
/** Singleton instance for use by the strategy registry */
|
|
59
|
+
export declare const propositionsStrategy: PropositionsStrategy;
|
|
60
|
+
//# sourceMappingURL=propositions-strategy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"propositions-strategy.d.ts","sourceRoot":"","sources":["../../../src/generators/strategies/propositions-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,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAyBrE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC/D,OAAO,KAAK,EAAE,eAAe,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AA2I3F,qEAAqE;AACrE,MAAM,WAAW,uBAAwB,SAAQ,WAAW;IAC1D,qEAAqE;IACrE,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,gEAAgE;IAChE,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,mEAAmE;IACnE,QAAQ,CAAC,YAAY,EAAE,YAAY,GAAG,IAAI,CAAC;IAC3C,2DAA2D;IAC3D,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,mDAAmD;IACnD,QAAQ,CAAC,QAAQ,CAAC,EAAE,UAAU,GAAG,SAAS,CAAC;CAC5C;AAID;;;;GAIG;AACH,qBAAa,oBAAqB,YAAW,eAAe,CAAC,uBAAuB,CAAC;IACnF,QAAQ,CAAC,IAAI,gCAAgC;IAE7C,QAAQ,CAAC,gBAAgB,sIAMd;IAEX;;;;;;OAMG;IACG,SAAS,CACb,MAAM,EAAE,2BAA2B,GAAG,IAAI,EAC1C,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,uBAAuB,CAAC;IAsDnC;;;;;;OAMG;IACH,YAAY,CAAC,IAAI,EAAE,uBAAuB,EAAE,IAAI,EAAE,YAAY,GAAG,MAAM;IAoCvE;;;;;;OAMG;IACH,WAAW,CAAC,IAAI,EAAE,uBAAuB,EAAE,IAAI,EAAE,YAAY,GAAG,eAAe;CAehF;AAED,0DAA0D;AAC1D,eAAO,MAAM,oBAAoB,sBAA6B,CAAC"}
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: 2024-2026 Hack23 AB
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
import { ArticleCategory } from '../../types/index.js';
|
|
4
|
+
import { escapeHTML } from '../../utils/file-utils.js';
|
|
5
|
+
import { PROPOSITIONS_TITLES, PROPOSITIONS_STRINGS, getLocalizedString, } from '../../constants/languages.js';
|
|
6
|
+
import { computeRollingDateRange, fetchProposalsFromMCP, fetchPipelineFromMCP, fetchProcedureStatusFromMCP, fetchEPFeedData, } from '../pipeline/fetch-stage.js';
|
|
7
|
+
import { buildPropositionsContent } from '../propositions-content.js';
|
|
8
|
+
import { buildDeepAnalysisSection } from '../deep-analysis-content.js';
|
|
9
|
+
import { buildPropositionsAnalysis, buildPropositionsSwot, buildPropositionsDashboard, buildPropositionsMindmap, } from '../analysis-builders.js';
|
|
10
|
+
import { buildSwotSection } from '../swot-content.js';
|
|
11
|
+
import { buildDashboardSection } from '../dashboard-content.js';
|
|
12
|
+
import { buildIntelligenceMindmapSection } from '../mindmap-content.js';
|
|
13
|
+
import { pl } from '../../utils/metadata-utils.js';
|
|
14
|
+
/** Base keywords shared by all Propositions articles */
|
|
15
|
+
const PROPOSITIONS_BASE_KEYWORDS = [
|
|
16
|
+
'European Parliament',
|
|
17
|
+
'legislation',
|
|
18
|
+
'proposals',
|
|
19
|
+
'procedure',
|
|
20
|
+
'OLP',
|
|
21
|
+
];
|
|
22
|
+
/**
|
|
23
|
+
* Extract content-aware keywords from propositions data and feed.
|
|
24
|
+
*
|
|
25
|
+
* Adds procedure titles, adopted text titles, and pipeline health
|
|
26
|
+
* indicators to the base keyword set.
|
|
27
|
+
*
|
|
28
|
+
* @param data - Propositions article data payload
|
|
29
|
+
* @returns Deduplicated keyword array
|
|
30
|
+
*/
|
|
31
|
+
function buildPropositionsKeywords(data) {
|
|
32
|
+
const keywords = [...PROPOSITIONS_BASE_KEYWORDS];
|
|
33
|
+
if (data.feedData?.procedures) {
|
|
34
|
+
for (const proc of data.feedData.procedures.slice(0, 5)) {
|
|
35
|
+
if (proc.title)
|
|
36
|
+
keywords.push(proc.title.slice(0, 60));
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
if (data.feedData?.adoptedTexts) {
|
|
40
|
+
for (const text of data.feedData.adoptedTexts.slice(0, 3)) {
|
|
41
|
+
if (text.title)
|
|
42
|
+
keywords.push(text.title.slice(0, 60));
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
if (data.pipelineData) {
|
|
46
|
+
keywords.push('legislative pipeline');
|
|
47
|
+
if (data.pipelineData.healthScore >= 0.8)
|
|
48
|
+
keywords.push('healthy pipeline');
|
|
49
|
+
}
|
|
50
|
+
return [...new Set(keywords)];
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Build a content-aware description from propositions data.
|
|
54
|
+
* Summarises pipeline health, procedure counts, and adopted text counts.
|
|
55
|
+
*
|
|
56
|
+
* @param data - Propositions article data payload
|
|
57
|
+
* @returns SEO-friendly description (≤ 200 chars)
|
|
58
|
+
*/
|
|
59
|
+
function buildPropositionsDescription(data) {
|
|
60
|
+
const parts = [];
|
|
61
|
+
const procCount = data.feedData?.procedures?.length ?? 0;
|
|
62
|
+
const adoptedCount = data.feedData?.adoptedTexts?.length ?? 0;
|
|
63
|
+
// Count proposals by the number of proposal-card divs in the HTML
|
|
64
|
+
const proposalMatches = data.proposalsHtml.match(/proposal-card/gu);
|
|
65
|
+
const proposalCount = proposalMatches ? proposalMatches.length : 0;
|
|
66
|
+
if (proposalCount > 0)
|
|
67
|
+
parts.push(`${proposalCount} active proposals`);
|
|
68
|
+
if (procCount > 0)
|
|
69
|
+
parts.push(`${procCount} procedures tracked`);
|
|
70
|
+
if (adoptedCount > 0)
|
|
71
|
+
parts.push(`${adoptedCount} recently adopted texts`);
|
|
72
|
+
if (data.pipelineData) {
|
|
73
|
+
const healthPct = Math.round(data.pipelineData.healthScore * 100);
|
|
74
|
+
parts.push(`pipeline health ${healthPct}%`);
|
|
75
|
+
}
|
|
76
|
+
if (parts.length === 0) {
|
|
77
|
+
return 'Recent legislative proposals, procedure tracking, and pipeline status in the European Parliament';
|
|
78
|
+
}
|
|
79
|
+
const desc = `EP legislative tracker: ${parts.join(', ')}.`;
|
|
80
|
+
return desc.length > 200 ? desc.slice(0, 197) + '...' : desc;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Build a content-aware title suffix from propositions data.
|
|
84
|
+
*
|
|
85
|
+
* @param data - Propositions article data payload
|
|
86
|
+
* @returns Short suffix for the title, or empty string
|
|
87
|
+
*/
|
|
88
|
+
function buildPropositionsTitleSuffix(data) {
|
|
89
|
+
const parts = [];
|
|
90
|
+
const procCount = data.feedData?.procedures?.length ?? 0;
|
|
91
|
+
const adoptedCount = data.feedData?.adoptedTexts?.length ?? 0;
|
|
92
|
+
if (procCount > 0)
|
|
93
|
+
parts.push(pl(procCount, 'Procedure', 'Procedures'));
|
|
94
|
+
if (adoptedCount > 0)
|
|
95
|
+
parts.push(pl(adoptedCount, 'Adopted Text', 'Adopted Texts'));
|
|
96
|
+
if (data.pipelineData && parts.length === 0) {
|
|
97
|
+
const healthPct = Math.round(data.pipelineData.healthScore * 100);
|
|
98
|
+
parts.push(`Pipeline ${healthPct}%`);
|
|
99
|
+
}
|
|
100
|
+
return parts.join(', ');
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Build procedures and adopted-texts HTML separately from EP feed data when
|
|
104
|
+
* search_documents returns empty. Uses procedures and adopted texts from the
|
|
105
|
+
* feed as fallback content, rendering each as a distinct section.
|
|
106
|
+
*
|
|
107
|
+
* @param feedData - EP feed data containing procedures and adopted texts
|
|
108
|
+
* @returns Pre-sanitized HTML for procedures and adopted texts sections separately
|
|
109
|
+
*/
|
|
110
|
+
function buildProceduresAndAdoptedTextsFromFeed(feedData) {
|
|
111
|
+
const procedureItems = [];
|
|
112
|
+
const adoptedTextItems = [];
|
|
113
|
+
for (const proc of feedData.procedures.slice(0, 8)) {
|
|
114
|
+
procedureItems.push(`
|
|
115
|
+
<div class="proposal-card">
|
|
116
|
+
<h3>${escapeHTML(proc.title || proc.id)}</h3>
|
|
117
|
+
<div class="proposal-meta">
|
|
118
|
+
<span class="proposal-id">${escapeHTML(proc.identifier ?? proc.id)}</span>
|
|
119
|
+
${proc.date ? `<span class="proposal-date">${escapeHTML(proc.date)}</span>` : ''}
|
|
120
|
+
${proc.stage ? `<span class="proposal-status">${escapeHTML(proc.stage)}</span>` : ''}
|
|
121
|
+
</div>
|
|
122
|
+
</div>`);
|
|
123
|
+
}
|
|
124
|
+
for (const text of feedData.adoptedTexts.slice(0, 8)) {
|
|
125
|
+
adoptedTextItems.push(`
|
|
126
|
+
<div class="proposal-card">
|
|
127
|
+
<h3>${escapeHTML(text.title || text.id)}</h3>
|
|
128
|
+
<div class="proposal-meta">
|
|
129
|
+
<span class="proposal-id">${escapeHTML(text.identifier ?? text.id)}</span>
|
|
130
|
+
${text.date ? `<span class="proposal-date">${escapeHTML(text.date)}</span>` : ''}
|
|
131
|
+
</div>
|
|
132
|
+
</div>`);
|
|
133
|
+
}
|
|
134
|
+
return {
|
|
135
|
+
proceduresHtml: procedureItems.join('\n'),
|
|
136
|
+
adoptedTextsHtml: adoptedTextItems.join('\n'),
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
// ─── Strategy implementation ──────────────────────────────────────────────────
|
|
140
|
+
/**
|
|
141
|
+
* Article strategy for {@link ArticleCategory.PROPOSITIONS}.
|
|
142
|
+
* Fetches legislative proposals, active pipeline status, and procedure detail
|
|
143
|
+
* then renders a language-specific article.
|
|
144
|
+
*/
|
|
145
|
+
export class PropositionsStrategy {
|
|
146
|
+
type = ArticleCategory.PROPOSITIONS;
|
|
147
|
+
requiredMCPTools = [
|
|
148
|
+
'search_documents',
|
|
149
|
+
'monitor_legislative_pipeline',
|
|
150
|
+
'track_legislation',
|
|
151
|
+
'get_procedures_feed',
|
|
152
|
+
'get_adopted_texts_feed',
|
|
153
|
+
];
|
|
154
|
+
/**
|
|
155
|
+
* Fetch legislative proposals and pipeline data in parallel.
|
|
156
|
+
*
|
|
157
|
+
* @param client - MCP client or null
|
|
158
|
+
* @param date - ISO 8601 publication date
|
|
159
|
+
* @returns Populated propositions data payload
|
|
160
|
+
*/
|
|
161
|
+
async fetchData(client, date) {
|
|
162
|
+
const feedDateRange = computeRollingDateRange(date, 7, 'propositions feed window');
|
|
163
|
+
if (client) {
|
|
164
|
+
console.log(' 📡 Fetching legislative data from MCP server...');
|
|
165
|
+
}
|
|
166
|
+
// Fetch proposals, pipeline, and EP feed data in parallel
|
|
167
|
+
const [proposalsResult, pipelineResult, feedData] = await Promise.allSettled([
|
|
168
|
+
fetchProposalsFromMCP(client),
|
|
169
|
+
fetchPipelineFromMCP(client),
|
|
170
|
+
fetchEPFeedData(client, 'one-week', feedDateRange),
|
|
171
|
+
]);
|
|
172
|
+
const { html: proposalsHtml, firstProcedureId } = proposalsResult.status === 'fulfilled'
|
|
173
|
+
? proposalsResult.value
|
|
174
|
+
: { html: '', firstProcedureId: '' };
|
|
175
|
+
const pipelineData = pipelineResult.status === 'fulfilled' ? pipelineResult.value : null;
|
|
176
|
+
const feedResult = feedData.status === 'fulfilled' ? feedData.value : undefined;
|
|
177
|
+
const procedureHtml = await fetchProcedureStatusFromMCP(client, firstProcedureId);
|
|
178
|
+
// When search_documents returns empty but feed data has procedures/adopted texts,
|
|
179
|
+
// build proposals HTML from the feed data as fallback
|
|
180
|
+
let finalProposalsHtml = proposalsHtml;
|
|
181
|
+
let finalAdoptedTextsHtml = '';
|
|
182
|
+
if (!finalProposalsHtml && feedResult) {
|
|
183
|
+
const hasFeedItems = feedResult.procedures.length > 0 || feedResult.adoptedTexts.length > 0;
|
|
184
|
+
if (hasFeedItems) {
|
|
185
|
+
console.log(` 📰 Building procedures/adopted-texts from feed data: ${feedResult.procedures.length} procedures, ${feedResult.adoptedTexts.length} adopted texts`);
|
|
186
|
+
const feedHtml = buildProceduresAndAdoptedTextsFromFeed(feedResult);
|
|
187
|
+
finalProposalsHtml = feedHtml.proceduresHtml;
|
|
188
|
+
finalAdoptedTextsHtml = feedHtml.adoptedTextsHtml;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
if (!finalProposalsHtml && !finalAdoptedTextsHtml) {
|
|
192
|
+
console.log(' ℹ️ No proposals from MCP — pipeline article will be data-free');
|
|
193
|
+
}
|
|
194
|
+
return {
|
|
195
|
+
date,
|
|
196
|
+
proposalsHtml: finalProposalsHtml,
|
|
197
|
+
adoptedTextsHtml: finalAdoptedTextsHtml,
|
|
198
|
+
pipelineData,
|
|
199
|
+
procedureHtml,
|
|
200
|
+
feedData: feedResult,
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Build the propositions HTML body using language-specific strings.
|
|
205
|
+
*
|
|
206
|
+
* @param data - Propositions data payload
|
|
207
|
+
* @param lang - Target language code
|
|
208
|
+
* @returns Article HTML body
|
|
209
|
+
*/
|
|
210
|
+
buildContent(data, lang) {
|
|
211
|
+
const strings = getLocalizedString(PROPOSITIONS_STRINGS, lang);
|
|
212
|
+
const base = buildPropositionsContent(data.proposalsHtml, data.adoptedTextsHtml, data.pipelineData, data.procedureHtml, strings, lang);
|
|
213
|
+
const analysis = buildPropositionsAnalysis(data.proposalsHtml, data.pipelineData, data.date, lang, data.adoptedTextsHtml);
|
|
214
|
+
const deepSection = buildDeepAnalysisSection(analysis, lang, 'en');
|
|
215
|
+
const mindmapData = buildPropositionsMindmap(data.pipelineData, lang);
|
|
216
|
+
const mindmapSection = buildIntelligenceMindmapSection(mindmapData, lang);
|
|
217
|
+
const swotData = buildPropositionsSwot(data.pipelineData, lang);
|
|
218
|
+
const swotSection = buildSwotSection(swotData, lang);
|
|
219
|
+
const dashboardData = buildPropositionsDashboard(data.pipelineData, lang);
|
|
220
|
+
const dashboardSection = buildDashboardSection(dashboardData, lang);
|
|
221
|
+
const injection = deepSection + mindmapSection + swotSection + dashboardSection;
|
|
222
|
+
// Inject before the closing </div> of .article-content
|
|
223
|
+
if (injection) {
|
|
224
|
+
const closingTag = '</div>';
|
|
225
|
+
const lastIdx = base.lastIndexOf(closingTag);
|
|
226
|
+
if (lastIdx !== -1) {
|
|
227
|
+
return base.slice(0, lastIdx) + injection + '\n' + base.slice(lastIdx);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
return base;
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Return language-specific metadata for the propositions article.
|
|
234
|
+
*
|
|
235
|
+
* @param data - Propositions data payload
|
|
236
|
+
* @param lang - Target language code
|
|
237
|
+
* @returns Localised metadata
|
|
238
|
+
*/
|
|
239
|
+
getMetadata(data, lang) {
|
|
240
|
+
const titleFn = getLocalizedString(PROPOSITIONS_TITLES, lang);
|
|
241
|
+
const { title: baseTitle, subtitle: baseSubtitle } = titleFn();
|
|
242
|
+
const suffix = lang === 'en' ? buildPropositionsTitleSuffix(data) : '';
|
|
243
|
+
const title = suffix ? `${baseTitle} — ${suffix}` : baseTitle;
|
|
244
|
+
const helperSubtitle = lang === 'en' ? buildPropositionsDescription(data) : '';
|
|
245
|
+
const subtitle = helperSubtitle || baseSubtitle;
|
|
246
|
+
return {
|
|
247
|
+
title,
|
|
248
|
+
subtitle,
|
|
249
|
+
keywords: buildPropositionsKeywords(data),
|
|
250
|
+
category: ArticleCategory.PROPOSITIONS,
|
|
251
|
+
sources: [],
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
/** Singleton instance for use by the strategy registry */
|
|
256
|
+
export const propositionsStrategy = new PropositionsStrategy();
|
|
257
|
+
//# sourceMappingURL=propositions-strategy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"propositions-strategy.js","sourceRoot":"","sources":["../../../src/generators/strategies/propositions-strategy.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module Generators/Strategies/WeekAheadStrategy
|
|
3
|
+
* @description Article strategy for the Week Ahead article type.
|
|
4
|
+
* Fetches plenary sessions, committee meetings, documents, pipeline and
|
|
5
|
+
* parliamentary questions then renders a forward-looking HTML article.
|
|
6
|
+
*/
|
|
7
|
+
import type { EuropeanParliamentMCPClient } from '../../mcp/ep-mcp-client.js';
|
|
8
|
+
import { ArticleCategory } from '../../types/index.js';
|
|
9
|
+
import type { LanguageCode, DateRange, WeekAheadData, EPFeedData } from '../../types/index.js';
|
|
10
|
+
import type { ArticleStrategy, ArticleData, ArticleMetadata } from './article-strategy.js';
|
|
11
|
+
/** Data fetched and pre-processed by {@link WeekAheadStrategy} */
|
|
12
|
+
export interface WeekAheadArticleData extends ArticleData {
|
|
13
|
+
/** Week-ahead date range */
|
|
14
|
+
readonly dateRange: DateRange;
|
|
15
|
+
/** Aggregated week-ahead domain data */
|
|
16
|
+
readonly weekData: WeekAheadData;
|
|
17
|
+
/** SEO keywords derived from the week-ahead data */
|
|
18
|
+
readonly keywords: readonly string[];
|
|
19
|
+
/** EP feed data for enrichment (when available) */
|
|
20
|
+
readonly feedData?: EPFeedData | undefined;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Article strategy for {@link ArticleCategory.WEEK_AHEAD}.
|
|
24
|
+
* Fetches plenary, committee, document, pipeline and question data then builds
|
|
25
|
+
* a forward-looking preview of the upcoming parliamentary week.
|
|
26
|
+
*/
|
|
27
|
+
export declare class WeekAheadStrategy implements ArticleStrategy<WeekAheadArticleData> {
|
|
28
|
+
readonly type = ArticleCategory.WEEK_AHEAD;
|
|
29
|
+
readonly requiredMCPTools: readonly ["get_plenary_sessions", "get_committee_info", "search_documents", "monitor_legislative_pipeline", "get_parliamentary_questions", "get_events", "get_events_feed", "get_plenary_documents_feed", "get_adopted_texts_feed"];
|
|
30
|
+
/**
|
|
31
|
+
* Fetch week-ahead data from MCP.
|
|
32
|
+
*
|
|
33
|
+
* @param client - MCP client or null
|
|
34
|
+
* @param date - ISO 8601 publication date
|
|
35
|
+
* @returns Populated week-ahead data payload
|
|
36
|
+
*/
|
|
37
|
+
fetchData(client: EuropeanParliamentMCPClient | null, date: string): Promise<WeekAheadArticleData>;
|
|
38
|
+
/**
|
|
39
|
+
* Build the week-ahead HTML body for the specified language.
|
|
40
|
+
*
|
|
41
|
+
* @param data - Week-ahead data payload
|
|
42
|
+
* @param lang - Target language code used for editorial strings
|
|
43
|
+
* @returns Article HTML body
|
|
44
|
+
*/
|
|
45
|
+
buildContent(data: WeekAheadArticleData, lang: LanguageCode): string;
|
|
46
|
+
/**
|
|
47
|
+
* Return language-specific metadata for the week-ahead article.
|
|
48
|
+
*
|
|
49
|
+
* @param data - Week-ahead data payload
|
|
50
|
+
* @param lang - Target language code
|
|
51
|
+
* @returns Localised metadata
|
|
52
|
+
*/
|
|
53
|
+
getMetadata(data: WeekAheadArticleData, lang: LanguageCode): ArticleMetadata;
|
|
54
|
+
}
|
|
55
|
+
/** Singleton instance for use by the strategy registry */
|
|
56
|
+
export declare const weekAheadStrategy: WeekAheadStrategy;
|
|
57
|
+
//# sourceMappingURL=week-ahead-strategy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"week-ahead-strategy.d.ts","sourceRoot":"","sources":["../../../src/generators/strategies/week-ahead-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,SAAS,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAkB/F,OAAO,KAAK,EAAE,eAAe,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAK3F,kEAAkE;AAClE,MAAM,WAAW,oBAAqB,SAAQ,WAAW;IACvD,4BAA4B;IAC5B,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC;IAC9B,wCAAwC;IACxC,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAC;IACjC,oDAAoD;IACpD,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,mDAAmD;IACnD,QAAQ,CAAC,QAAQ,CAAC,EAAE,UAAU,GAAG,SAAS,CAAC;CAC5C;AAuFD;;;;GAIG;AACH,qBAAa,iBAAkB,YAAW,eAAe,CAAC,oBAAoB,CAAC;IAC7E,QAAQ,CAAC,IAAI,8BAA8B;IAE3C,QAAQ,CAAC,gBAAgB,sOAUd;IAEX;;;;;;OAMG;IACG,SAAS,CACb,MAAM,EAAE,2BAA2B,GAAG,IAAI,EAC1C,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,oBAAoB,CAAC;IAoBhC;;;;;;OAMG;IACH,YAAY,CAAC,IAAI,EAAE,oBAAoB,EAAE,IAAI,EAAE,YAAY,GAAG,MAAM;IAsBpE;;;;;;OAMG;IACH,WAAW,CAAC,IAAI,EAAE,oBAAoB,EAAE,IAAI,EAAE,YAAY,GAAG,eAAe;CAoB7E;AAED,0DAA0D;AAC1D,eAAO,MAAM,iBAAiB,mBAA0B,CAAC"}
|