euparliamentmonitor 0.8.19 → 0.8.21
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/package.json +7 -7
- package/scripts/constants/language-articles.d.ts +4 -0
- package/scripts/constants/language-articles.js +20 -0
- package/scripts/constants/language-ui.d.ts +8 -8
- package/scripts/constants/language-ui.js +64 -64
- package/scripts/constants/languages.d.ts +2 -2
- package/scripts/constants/languages.js +2 -2
- package/scripts/generators/news-enhanced.js +13 -3
- package/scripts/generators/pipeline/analysis-classification.d.ts +49 -0
- package/scripts/generators/pipeline/analysis-classification.js +333 -0
- package/scripts/generators/pipeline/analysis-existing.d.ts +67 -0
- package/scripts/generators/pipeline/analysis-existing.js +547 -0
- package/scripts/generators/pipeline/analysis-helpers.d.ts +140 -0
- package/scripts/generators/pipeline/analysis-helpers.js +266 -0
- package/scripts/generators/pipeline/analysis-risk.d.ts +49 -0
- package/scripts/generators/pipeline/analysis-risk.js +417 -0
- package/scripts/generators/pipeline/analysis-stage.d.ts +19 -39
- package/scripts/generators/pipeline/analysis-stage.js +219 -1704
- package/scripts/generators/pipeline/analysis-threats.d.ts +41 -0
- package/scripts/generators/pipeline/analysis-threats.js +142 -0
- package/scripts/generators/pipeline/fetch-stage.d.ts +25 -15
- package/scripts/generators/pipeline/fetch-stage.js +293 -117
- package/scripts/generators/strategies/article-strategy.d.ts +126 -7
- package/scripts/generators/strategies/article-strategy.js +491 -1
- package/scripts/generators/strategies/breaking-news-strategy.js +98 -8
- package/scripts/generators/strategies/committee-reports-strategy.js +23 -2
- package/scripts/generators/strategies/month-ahead-strategy.js +23 -2
- package/scripts/generators/strategies/monthly-review-strategy.js +13 -1
- package/scripts/generators/strategies/motions-strategy.js +15 -1
- package/scripts/generators/strategies/propositions-strategy.js +15 -1
- package/scripts/generators/strategies/week-ahead-strategy.js +19 -1
- package/scripts/generators/strategies/weekly-review-strategy.js +17 -1
- package/scripts/generators/synthesis-summary.d.ts +93 -0
- package/scripts/generators/synthesis-summary.js +364 -0
- package/scripts/index.d.ts +5 -2
- package/scripts/index.js +6 -1
- package/scripts/mcp/ep-mcp-client.d.ts +34 -1
- package/scripts/mcp/ep-mcp-client.js +110 -2
- package/scripts/mcp/mcp-connection.d.ts +3 -1
- package/scripts/mcp/mcp-connection.js +35 -4
- package/scripts/templates/article-template.js +24 -22
- package/scripts/templates/section-builders.js +2 -5
- package/scripts/types/index.d.ts +2 -1
- package/scripts/types/mcp.d.ts +7 -0
- package/scripts/types/political-classification.d.ts +1 -1
- package/scripts/types/quality.d.ts +9 -6
- package/scripts/types/significance.d.ts +130 -0
- package/scripts/types/significance.js +4 -0
- package/scripts/utils/article-quality-scorer.d.ts +13 -11
- package/scripts/utils/article-quality-scorer.js +36 -23
- package/scripts/utils/file-utils.d.ts +2 -2
- package/scripts/utils/file-utils.js +2 -2
- package/scripts/utils/html-sanitize.d.ts +10 -0
- package/scripts/utils/html-sanitize.js +32 -0
- package/scripts/utils/political-classification.d.ts +8 -7
- package/scripts/utils/political-classification.js +8 -7
- package/scripts/utils/political-risk-assessment.d.ts +1 -1
- package/scripts/utils/political-risk-assessment.js +1 -1
- package/scripts/utils/significance-scoring.d.ts +97 -0
- package/scripts/utils/significance-scoring.js +190 -0
|
@@ -1050,6 +1050,28 @@ export async function fetchProcedureStatusFromMCP(client, procedureId) {
|
|
|
1050
1050
|
}
|
|
1051
1051
|
}
|
|
1052
1052
|
// ─── EP Feed-based fetches (Breaking News) ──────────────────────────────────
|
|
1053
|
+
/**
|
|
1054
|
+
* Ordered fallback chain for feed timeframes.
|
|
1055
|
+
* When a narrow timeframe returns empty/404 (common during recess), we widen
|
|
1056
|
+
* the window to retrieve at least *some* recent data for analysis.
|
|
1057
|
+
*/
|
|
1058
|
+
const TIMEFRAME_FALLBACK_CHAIN = new Map([
|
|
1059
|
+
['today', 'one-day'],
|
|
1060
|
+
['one-day', 'one-week'],
|
|
1061
|
+
['one-week', 'one-month'],
|
|
1062
|
+
['one-month', undefined],
|
|
1063
|
+
['three-months', undefined],
|
|
1064
|
+
['one-year', undefined],
|
|
1065
|
+
]);
|
|
1066
|
+
/**
|
|
1067
|
+
* Get the next wider timeframe for fallback, or `undefined` if no fallback exists.
|
|
1068
|
+
*
|
|
1069
|
+
* @param current - Current timeframe
|
|
1070
|
+
* @returns Next wider timeframe, or undefined when at widest
|
|
1071
|
+
*/
|
|
1072
|
+
function getWiderTimeframe(current) {
|
|
1073
|
+
return TIMEFRAME_FALLBACK_CHAIN.get(current);
|
|
1074
|
+
}
|
|
1053
1075
|
/**
|
|
1054
1076
|
* Parse a feed result from MCP into a flat array of items.
|
|
1055
1077
|
* EP API v2 feeds return items under the `data` key:
|
|
@@ -1134,81 +1156,133 @@ function mapFeedItemBase(item) {
|
|
|
1134
1156
|
}
|
|
1135
1157
|
/**
|
|
1136
1158
|
* Fetch adopted texts feed from MCP.
|
|
1159
|
+
* Falls back to a wider timeframe when the initial timeframe returns no data.
|
|
1137
1160
|
*
|
|
1138
1161
|
* @param client - MCP client or null
|
|
1139
|
-
* @param timeframe - How far back to look (default: 'one-
|
|
1162
|
+
* @param timeframe - How far back to look (default: 'one-week')
|
|
1140
1163
|
* @returns Array of adopted text feed items
|
|
1141
1164
|
*/
|
|
1142
|
-
export async function fetchAdoptedTextsFeed(client, timeframe = 'one-
|
|
1165
|
+
export async function fetchAdoptedTextsFeed(client, timeframe = 'one-week') {
|
|
1143
1166
|
if (!client)
|
|
1144
1167
|
return [];
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
const
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1168
|
+
let currentTimeframe = timeframe;
|
|
1169
|
+
while (currentTimeframe) {
|
|
1170
|
+
const tf = currentTimeframe;
|
|
1171
|
+
try {
|
|
1172
|
+
console.log(`${MCP_FETCH_PREFIX} Fetching adopted texts feed (${currentTimeframe})...`);
|
|
1173
|
+
const result = await callMCP(() => client.getAdoptedTextsFeed({ timeframe: tf, limit: 20 }), undefined, 'get_adopted_texts_feed');
|
|
1174
|
+
const items = parseFeedResult(result).map((item) => mapFeedItemBase(item));
|
|
1175
|
+
if (items.length > 0 || !getWiderTimeframe(currentTimeframe))
|
|
1176
|
+
return items;
|
|
1177
|
+
console.log(`${INFO_PREFIX} adopted texts feed empty for ${currentTimeframe}, widening timeframe...`);
|
|
1178
|
+
currentTimeframe = getWiderTimeframe(currentTimeframe);
|
|
1179
|
+
}
|
|
1180
|
+
catch (error) {
|
|
1181
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1182
|
+
const wider = getWiderTimeframe(tf);
|
|
1183
|
+
if (wider && (message.includes('404') || message.includes('timed out'))) {
|
|
1184
|
+
console.warn(`${WARN_PREFIX} get_adopted_texts_feed failed (${currentTimeframe}): ${message} — retrying with ${wider}`);
|
|
1185
|
+
currentTimeframe = wider;
|
|
1186
|
+
}
|
|
1187
|
+
else {
|
|
1188
|
+
console.warn(`${WARN_PREFIX} get_adopted_texts_feed failed:`, message);
|
|
1189
|
+
return [];
|
|
1190
|
+
}
|
|
1191
|
+
}
|
|
1154
1192
|
}
|
|
1193
|
+
return [];
|
|
1155
1194
|
}
|
|
1156
1195
|
/**
|
|
1157
1196
|
* Fetch events feed from MCP.
|
|
1197
|
+
* Falls back to a wider timeframe when the initial timeframe returns no data
|
|
1198
|
+
* (common during parliamentary recess when the EP API returns 404 for narrow windows).
|
|
1158
1199
|
*
|
|
1159
1200
|
* @param client - MCP client or null
|
|
1160
|
-
* @param timeframe - How far back to look (default: 'one-
|
|
1201
|
+
* @param timeframe - How far back to look (default: 'one-week')
|
|
1161
1202
|
* @returns Array of event feed items
|
|
1162
1203
|
*/
|
|
1163
|
-
export async function fetchEventsFeed(client, timeframe = 'one-
|
|
1204
|
+
export async function fetchEventsFeed(client, timeframe = 'one-week') {
|
|
1164
1205
|
if (!client)
|
|
1165
1206
|
return [];
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
const
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1207
|
+
let currentTimeframe = timeframe;
|
|
1208
|
+
while (currentTimeframe) {
|
|
1209
|
+
const tf = currentTimeframe;
|
|
1210
|
+
try {
|
|
1211
|
+
console.log(`${MCP_FETCH_PREFIX} Fetching events feed (${currentTimeframe})...`);
|
|
1212
|
+
const result = await callMCP(() => client.getEventsFeed({ timeframe: tf, limit: 20 }), undefined, 'get_events_feed');
|
|
1213
|
+
const items = parseFeedResult(result).map((item) => ({
|
|
1214
|
+
...mapFeedItemBase(item),
|
|
1215
|
+
location: item['location'] ? String(item['location']) : undefined,
|
|
1216
|
+
}));
|
|
1217
|
+
if (items.length > 0 || !getWiderTimeframe(currentTimeframe))
|
|
1218
|
+
return items;
|
|
1219
|
+
console.log(`${INFO_PREFIX} events feed empty for ${currentTimeframe}, widening timeframe...`);
|
|
1220
|
+
currentTimeframe = getWiderTimeframe(currentTimeframe);
|
|
1221
|
+
}
|
|
1222
|
+
catch (error) {
|
|
1223
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1224
|
+
const wider = getWiderTimeframe(tf);
|
|
1225
|
+
if (wider && (message.includes('404') || message.includes('timed out'))) {
|
|
1226
|
+
console.warn(`${WARN_PREFIX} get_events_feed failed (${currentTimeframe}): ${message} — retrying with ${wider}`);
|
|
1227
|
+
currentTimeframe = wider;
|
|
1228
|
+
}
|
|
1229
|
+
else {
|
|
1230
|
+
console.warn(`${WARN_PREFIX} get_events_feed failed:`, message);
|
|
1231
|
+
return [];
|
|
1232
|
+
}
|
|
1233
|
+
}
|
|
1178
1234
|
}
|
|
1235
|
+
return [];
|
|
1179
1236
|
}
|
|
1180
1237
|
/**
|
|
1181
1238
|
* Fetch procedures feed from MCP.
|
|
1239
|
+
* Falls back to a wider timeframe when the initial timeframe returns no data.
|
|
1182
1240
|
*
|
|
1183
1241
|
* @param client - MCP client or null
|
|
1184
|
-
* @param timeframe - How far back to look (default: 'one-
|
|
1242
|
+
* @param timeframe - How far back to look (default: 'one-week')
|
|
1185
1243
|
* @returns Array of procedure feed items
|
|
1186
1244
|
*/
|
|
1187
|
-
export async function fetchProceduresFeed(client, timeframe = 'one-
|
|
1245
|
+
export async function fetchProceduresFeed(client, timeframe = 'one-week') {
|
|
1188
1246
|
if (!client)
|
|
1189
1247
|
return [];
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
const
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1248
|
+
let currentTimeframe = timeframe;
|
|
1249
|
+
while (currentTimeframe) {
|
|
1250
|
+
const tf = currentTimeframe;
|
|
1251
|
+
try {
|
|
1252
|
+
console.log(`${MCP_FETCH_PREFIX} Fetching procedures feed (${currentTimeframe})...`);
|
|
1253
|
+
const result = await callMCP(() => client.getProceduresFeed({ timeframe: tf, limit: 20 }), undefined, 'get_procedures_feed');
|
|
1254
|
+
const items = parseFeedResult(result).map((item) => ({
|
|
1255
|
+
...mapFeedItemBase(item),
|
|
1256
|
+
stage: item['stage'] ? String(item['stage']) : undefined,
|
|
1257
|
+
}));
|
|
1258
|
+
if (items.length > 0 || !getWiderTimeframe(currentTimeframe))
|
|
1259
|
+
return items;
|
|
1260
|
+
console.log(`${INFO_PREFIX} procedures feed empty for ${currentTimeframe}, widening timeframe...`);
|
|
1261
|
+
currentTimeframe = getWiderTimeframe(currentTimeframe);
|
|
1262
|
+
}
|
|
1263
|
+
catch (error) {
|
|
1264
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1265
|
+
const wider = getWiderTimeframe(tf);
|
|
1266
|
+
if (wider && (message.includes('404') || message.includes('timed out'))) {
|
|
1267
|
+
console.warn(`${WARN_PREFIX} get_procedures_feed failed (${currentTimeframe}): ${message} — retrying with ${wider}`);
|
|
1268
|
+
currentTimeframe = wider;
|
|
1269
|
+
}
|
|
1270
|
+
else {
|
|
1271
|
+
console.warn(`${WARN_PREFIX} get_procedures_feed failed:`, message);
|
|
1272
|
+
return [];
|
|
1273
|
+
}
|
|
1274
|
+
}
|
|
1202
1275
|
}
|
|
1276
|
+
return [];
|
|
1203
1277
|
}
|
|
1204
1278
|
/**
|
|
1205
1279
|
* Fetch MEPs feed from MCP.
|
|
1206
1280
|
*
|
|
1207
1281
|
* @param client - MCP client or null
|
|
1208
|
-
* @param timeframe - How far back to look (default: 'one-
|
|
1282
|
+
* @param timeframe - How far back to look (default: 'one-week')
|
|
1209
1283
|
* @returns Array of MEP feed items
|
|
1210
1284
|
*/
|
|
1211
|
-
export async function fetchMEPsFeed(client, timeframe = 'one-
|
|
1285
|
+
export async function fetchMEPsFeed(client, timeframe = 'one-week') {
|
|
1212
1286
|
return (await fetchMEPsFeedWithTotal(client, timeframe)).items;
|
|
1213
1287
|
}
|
|
1214
1288
|
/**
|
|
@@ -1222,10 +1296,10 @@ export async function fetchMEPsFeed(client, timeframe = 'one-day') {
|
|
|
1222
1296
|
* updates, the `total` field in the API response carries the true count.
|
|
1223
1297
|
*
|
|
1224
1298
|
* @param client - MCP client or null
|
|
1225
|
-
* @param timeframe - How far back to look (default: 'one-
|
|
1299
|
+
* @param timeframe - How far back to look (default: 'one-week')
|
|
1226
1300
|
* @returns Object with `items` array and `total` count from the API
|
|
1227
1301
|
*/
|
|
1228
|
-
export async function fetchMEPsFeedWithTotal(client, timeframe = 'one-
|
|
1302
|
+
export async function fetchMEPsFeedWithTotal(client, timeframe = 'one-week') {
|
|
1229
1303
|
if (!client)
|
|
1230
1304
|
return { items: [], total: 0 };
|
|
1231
1305
|
try {
|
|
@@ -1252,138 +1326,240 @@ export async function fetchMEPsFeedWithTotal(client, timeframe = 'one-day') {
|
|
|
1252
1326
|
}
|
|
1253
1327
|
/**
|
|
1254
1328
|
* Fetch documents feed from MCP.
|
|
1329
|
+
* Falls back to a wider timeframe when the initial timeframe returns no data.
|
|
1255
1330
|
*
|
|
1256
1331
|
* @param client - MCP client or null
|
|
1257
|
-
* @param timeframe - How far back to look (default: 'one-
|
|
1332
|
+
* @param timeframe - How far back to look (default: 'one-week')
|
|
1258
1333
|
* @returns Array of document feed items
|
|
1259
1334
|
*/
|
|
1260
|
-
export async function fetchDocumentsFeed(client, timeframe = 'one-
|
|
1335
|
+
export async function fetchDocumentsFeed(client, timeframe = 'one-week') {
|
|
1261
1336
|
if (!client)
|
|
1262
1337
|
return [];
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
const
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1338
|
+
let currentTimeframe = timeframe;
|
|
1339
|
+
while (currentTimeframe) {
|
|
1340
|
+
const tf = currentTimeframe;
|
|
1341
|
+
try {
|
|
1342
|
+
console.log(`${MCP_FETCH_PREFIX} Fetching documents feed (${currentTimeframe})...`);
|
|
1343
|
+
const result = await callMCP(() => client.getDocumentsFeed({ timeframe: tf, limit: 20 }), undefined, 'get_documents_feed');
|
|
1344
|
+
const items = parseFeedResult(result).map((item) => mapFeedItemBase(item));
|
|
1345
|
+
if (items.length > 0 || !getWiderTimeframe(currentTimeframe))
|
|
1346
|
+
return items;
|
|
1347
|
+
console.log(`${INFO_PREFIX} documents feed empty for ${currentTimeframe}, widening timeframe...`);
|
|
1348
|
+
currentTimeframe = getWiderTimeframe(currentTimeframe);
|
|
1349
|
+
}
|
|
1350
|
+
catch (error) {
|
|
1351
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1352
|
+
const wider = getWiderTimeframe(tf);
|
|
1353
|
+
if (wider && (message.includes('404') || message.includes('timed out'))) {
|
|
1354
|
+
console.warn(`${WARN_PREFIX} get_documents_feed failed (${currentTimeframe}): ${message} — retrying with ${wider}`);
|
|
1355
|
+
currentTimeframe = wider;
|
|
1356
|
+
}
|
|
1357
|
+
else {
|
|
1358
|
+
console.warn(`${WARN_PREFIX} get_documents_feed failed:`, message);
|
|
1359
|
+
return [];
|
|
1360
|
+
}
|
|
1361
|
+
}
|
|
1272
1362
|
}
|
|
1363
|
+
return [];
|
|
1273
1364
|
}
|
|
1274
1365
|
/**
|
|
1275
1366
|
* Fetch plenary documents feed from MCP.
|
|
1367
|
+
* Falls back to a wider timeframe when the initial timeframe returns no data.
|
|
1276
1368
|
*
|
|
1277
1369
|
* @param client - MCP client or null
|
|
1278
|
-
* @param timeframe - How far back to look (default: 'one-
|
|
1370
|
+
* @param timeframe - How far back to look (default: 'one-week')
|
|
1279
1371
|
* @returns Array of document feed items
|
|
1280
1372
|
*/
|
|
1281
|
-
export async function fetchPlenaryDocumentsFeed(client, timeframe = 'one-
|
|
1373
|
+
export async function fetchPlenaryDocumentsFeed(client, timeframe = 'one-week') {
|
|
1282
1374
|
if (!client)
|
|
1283
1375
|
return [];
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
const
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1376
|
+
let currentTimeframe = timeframe;
|
|
1377
|
+
while (currentTimeframe) {
|
|
1378
|
+
const tf = currentTimeframe;
|
|
1379
|
+
try {
|
|
1380
|
+
console.log(`${MCP_FETCH_PREFIX} Fetching plenary documents feed (${currentTimeframe})...`);
|
|
1381
|
+
const result = await callMCP(() => client.getPlenaryDocumentsFeed({ timeframe: tf, limit: 20 }), undefined, 'get_plenary_documents_feed');
|
|
1382
|
+
const items = parseFeedResult(result).map((item) => mapFeedItemBase(item));
|
|
1383
|
+
if (items.length > 0 || !getWiderTimeframe(currentTimeframe))
|
|
1384
|
+
return items;
|
|
1385
|
+
console.log(`${INFO_PREFIX} plenary documents feed empty for ${currentTimeframe}, widening timeframe...`);
|
|
1386
|
+
currentTimeframe = getWiderTimeframe(currentTimeframe);
|
|
1387
|
+
}
|
|
1388
|
+
catch (error) {
|
|
1389
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1390
|
+
const wider = getWiderTimeframe(tf);
|
|
1391
|
+
if (wider && (message.includes('404') || message.includes('timed out'))) {
|
|
1392
|
+
console.warn(`${WARN_PREFIX} get_plenary_documents_feed failed (${currentTimeframe}): ${message} — retrying with ${wider}`);
|
|
1393
|
+
currentTimeframe = wider;
|
|
1394
|
+
}
|
|
1395
|
+
else {
|
|
1396
|
+
console.warn(`${WARN_PREFIX} get_plenary_documents_feed failed:`, message);
|
|
1397
|
+
return [];
|
|
1398
|
+
}
|
|
1399
|
+
}
|
|
1293
1400
|
}
|
|
1401
|
+
return [];
|
|
1294
1402
|
}
|
|
1295
1403
|
/**
|
|
1296
1404
|
* Fetch committee documents feed from MCP.
|
|
1405
|
+
* Falls back to a wider timeframe when the initial timeframe returns no data.
|
|
1297
1406
|
*
|
|
1298
1407
|
* @param client - MCP client or null
|
|
1299
|
-
* @param timeframe - How far back to look (default: 'one-
|
|
1408
|
+
* @param timeframe - How far back to look (default: 'one-week')
|
|
1300
1409
|
* @returns Array of document feed items
|
|
1301
1410
|
*/
|
|
1302
|
-
export async function fetchCommitteeDocumentsFeed(client, timeframe = 'one-
|
|
1411
|
+
export async function fetchCommitteeDocumentsFeed(client, timeframe = 'one-week') {
|
|
1303
1412
|
if (!client)
|
|
1304
1413
|
return [];
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
const
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1414
|
+
let currentTimeframe = timeframe;
|
|
1415
|
+
while (currentTimeframe) {
|
|
1416
|
+
const tf = currentTimeframe;
|
|
1417
|
+
try {
|
|
1418
|
+
console.log(`${MCP_FETCH_PREFIX} Fetching committee documents feed (${currentTimeframe})...`);
|
|
1419
|
+
const result = await callMCP(() => client.getCommitteeDocumentsFeed({ timeframe: tf, limit: 20 }), undefined, 'get_committee_documents_feed');
|
|
1420
|
+
const items = parseFeedResult(result).map((item) => mapFeedItemBase(item));
|
|
1421
|
+
if (items.length > 0 || !getWiderTimeframe(currentTimeframe))
|
|
1422
|
+
return items;
|
|
1423
|
+
console.log(`${INFO_PREFIX} committee documents feed empty for ${currentTimeframe}, widening timeframe...`);
|
|
1424
|
+
currentTimeframe = getWiderTimeframe(currentTimeframe);
|
|
1425
|
+
}
|
|
1426
|
+
catch (error) {
|
|
1427
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1428
|
+
const wider = getWiderTimeframe(tf);
|
|
1429
|
+
if (wider && (message.includes('404') || message.includes('timed out'))) {
|
|
1430
|
+
console.warn(`${WARN_PREFIX} get_committee_documents_feed failed (${currentTimeframe}): ${message} — retrying with ${wider}`);
|
|
1431
|
+
currentTimeframe = wider;
|
|
1432
|
+
}
|
|
1433
|
+
else {
|
|
1434
|
+
console.warn(`${WARN_PREFIX} get_committee_documents_feed failed:`, message);
|
|
1435
|
+
return [];
|
|
1436
|
+
}
|
|
1437
|
+
}
|
|
1314
1438
|
}
|
|
1439
|
+
return [];
|
|
1315
1440
|
}
|
|
1316
1441
|
/**
|
|
1317
1442
|
* Fetch plenary session documents feed from MCP.
|
|
1443
|
+
* Falls back to a wider timeframe when the initial timeframe returns no data.
|
|
1318
1444
|
*
|
|
1319
1445
|
* @param client - MCP client or null
|
|
1320
|
-
* @param timeframe - How far back to look (default: 'one-
|
|
1446
|
+
* @param timeframe - How far back to look (default: 'one-week')
|
|
1321
1447
|
* @returns Array of document feed items
|
|
1322
1448
|
*/
|
|
1323
|
-
export async function fetchPlenarySessionDocumentsFeed(client, timeframe = 'one-
|
|
1449
|
+
export async function fetchPlenarySessionDocumentsFeed(client, timeframe = 'one-week') {
|
|
1324
1450
|
if (!client)
|
|
1325
1451
|
return [];
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
const
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1452
|
+
let currentTimeframe = timeframe;
|
|
1453
|
+
while (currentTimeframe) {
|
|
1454
|
+
const tf = currentTimeframe;
|
|
1455
|
+
try {
|
|
1456
|
+
console.log(`${MCP_FETCH_PREFIX} Fetching plenary session documents feed (${currentTimeframe})...`);
|
|
1457
|
+
const result = await callMCP(() => client.getPlenarySessionDocumentsFeed({ timeframe: tf, limit: 20 }), undefined, 'get_plenary_session_documents_feed');
|
|
1458
|
+
const items = parseFeedResult(result).map((item) => mapFeedItemBase(item));
|
|
1459
|
+
if (items.length > 0 || !getWiderTimeframe(currentTimeframe))
|
|
1460
|
+
return items;
|
|
1461
|
+
console.log(`${INFO_PREFIX} plenary session docs feed empty for ${currentTimeframe}, widening timeframe...`);
|
|
1462
|
+
currentTimeframe = getWiderTimeframe(currentTimeframe);
|
|
1463
|
+
}
|
|
1464
|
+
catch (error) {
|
|
1465
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1466
|
+
const wider = getWiderTimeframe(tf);
|
|
1467
|
+
if (wider && (message.includes('404') || message.includes('timed out'))) {
|
|
1468
|
+
console.warn(`${WARN_PREFIX} get_plenary_session_documents_feed failed (${currentTimeframe}): ${message} — retrying with ${wider}`);
|
|
1469
|
+
currentTimeframe = wider;
|
|
1470
|
+
}
|
|
1471
|
+
else {
|
|
1472
|
+
console.warn(`${WARN_PREFIX} get_plenary_session_documents_feed failed:`, message);
|
|
1473
|
+
return [];
|
|
1474
|
+
}
|
|
1475
|
+
}
|
|
1335
1476
|
}
|
|
1477
|
+
return [];
|
|
1336
1478
|
}
|
|
1337
1479
|
/**
|
|
1338
1480
|
* Fetch external documents feed from MCP.
|
|
1481
|
+
* Falls back to a wider timeframe when the initial timeframe returns no data.
|
|
1339
1482
|
*
|
|
1340
1483
|
* @param client - MCP client or null
|
|
1341
|
-
* @param timeframe - How far back to look (default: 'one-
|
|
1484
|
+
* @param timeframe - How far back to look (default: 'one-week')
|
|
1342
1485
|
* @returns Array of document feed items
|
|
1343
1486
|
*/
|
|
1344
|
-
export async function fetchExternalDocumentsFeed(client, timeframe = 'one-
|
|
1487
|
+
export async function fetchExternalDocumentsFeed(client, timeframe = 'one-week') {
|
|
1345
1488
|
if (!client)
|
|
1346
1489
|
return [];
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
const
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1490
|
+
let currentTimeframe = timeframe;
|
|
1491
|
+
while (currentTimeframe) {
|
|
1492
|
+
const tf = currentTimeframe;
|
|
1493
|
+
try {
|
|
1494
|
+
console.log(`${MCP_FETCH_PREFIX} Fetching external documents feed (${currentTimeframe})...`);
|
|
1495
|
+
const result = await callMCP(() => client.getExternalDocumentsFeed({ timeframe: tf, limit: 20 }), undefined, 'get_external_documents_feed');
|
|
1496
|
+
const items = parseFeedResult(result).map((item) => mapFeedItemBase(item));
|
|
1497
|
+
if (items.length > 0 || !getWiderTimeframe(currentTimeframe))
|
|
1498
|
+
return items;
|
|
1499
|
+
console.log(`${INFO_PREFIX} external documents feed empty for ${currentTimeframe}, widening timeframe...`);
|
|
1500
|
+
currentTimeframe = getWiderTimeframe(currentTimeframe);
|
|
1501
|
+
}
|
|
1502
|
+
catch (error) {
|
|
1503
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1504
|
+
const wider = getWiderTimeframe(tf);
|
|
1505
|
+
if (wider && (message.includes('404') || message.includes('timed out'))) {
|
|
1506
|
+
console.warn(`${WARN_PREFIX} get_external_documents_feed failed (${currentTimeframe}): ${message} — retrying with ${wider}`);
|
|
1507
|
+
currentTimeframe = wider;
|
|
1508
|
+
}
|
|
1509
|
+
else {
|
|
1510
|
+
console.warn(`${WARN_PREFIX} get_external_documents_feed failed:`, message);
|
|
1511
|
+
return [];
|
|
1512
|
+
}
|
|
1513
|
+
}
|
|
1356
1514
|
}
|
|
1515
|
+
return [];
|
|
1357
1516
|
}
|
|
1358
1517
|
/**
|
|
1359
1518
|
* Fetch parliamentary questions feed from MCP.
|
|
1519
|
+
* Falls back to a wider timeframe when the initial timeframe returns no data.
|
|
1360
1520
|
*
|
|
1361
1521
|
* @param client - MCP client or null
|
|
1362
|
-
* @param timeframe - How far back to look (default: 'one-
|
|
1522
|
+
* @param timeframe - How far back to look (default: 'one-week')
|
|
1363
1523
|
* @returns Array of question feed items
|
|
1364
1524
|
*/
|
|
1365
|
-
export async function fetchQuestionsFeed(client, timeframe = 'one-
|
|
1525
|
+
export async function fetchQuestionsFeed(client, timeframe = 'one-week') {
|
|
1366
1526
|
if (!client)
|
|
1367
1527
|
return [];
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
const
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1528
|
+
let currentTimeframe = timeframe;
|
|
1529
|
+
while (currentTimeframe) {
|
|
1530
|
+
const tf = currentTimeframe;
|
|
1531
|
+
try {
|
|
1532
|
+
console.log(`${MCP_FETCH_PREFIX} Fetching parliamentary questions feed (${currentTimeframe})...`);
|
|
1533
|
+
const result = await callMCP(() => client.getParliamentaryQuestionsFeed({ timeframe: tf, limit: 20 }), undefined, 'get_parliamentary_questions_feed');
|
|
1534
|
+
const items = parseFeedResult(result).map((item) => mapFeedItemBase(item));
|
|
1535
|
+
if (items.length > 0 || !getWiderTimeframe(currentTimeframe))
|
|
1536
|
+
return items;
|
|
1537
|
+
console.log(`${INFO_PREFIX} questions feed empty for ${currentTimeframe}, widening timeframe...`);
|
|
1538
|
+
currentTimeframe = getWiderTimeframe(currentTimeframe);
|
|
1539
|
+
}
|
|
1540
|
+
catch (error) {
|
|
1541
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1542
|
+
const wider = getWiderTimeframe(tf);
|
|
1543
|
+
if (wider && (message.includes('404') || message.includes('timed out'))) {
|
|
1544
|
+
console.warn(`${WARN_PREFIX} get_parliamentary_questions_feed failed (${currentTimeframe}): ${message} — retrying with ${wider}`);
|
|
1545
|
+
currentTimeframe = wider;
|
|
1546
|
+
}
|
|
1547
|
+
else {
|
|
1548
|
+
console.warn(`${WARN_PREFIX} get_parliamentary_questions_feed failed:`, message);
|
|
1549
|
+
return [];
|
|
1550
|
+
}
|
|
1551
|
+
}
|
|
1377
1552
|
}
|
|
1553
|
+
return [];
|
|
1378
1554
|
}
|
|
1379
1555
|
/**
|
|
1380
1556
|
* Fetch MEP declarations feed from MCP.
|
|
1381
1557
|
*
|
|
1382
1558
|
* @param client - MCP client or null
|
|
1383
|
-
* @param timeframe - How far back to look (default: 'one-
|
|
1559
|
+
* @param timeframe - How far back to look (default: 'one-week')
|
|
1384
1560
|
* @returns Array of declaration feed items
|
|
1385
1561
|
*/
|
|
1386
|
-
export async function fetchDeclarationsFeed(client, timeframe = 'one-
|
|
1562
|
+
export async function fetchDeclarationsFeed(client, timeframe = 'one-week') {
|
|
1387
1563
|
if (!client)
|
|
1388
1564
|
return [];
|
|
1389
1565
|
try {
|
|
@@ -1401,10 +1577,10 @@ export async function fetchDeclarationsFeed(client, timeframe = 'one-day') {
|
|
|
1401
1577
|
* Fetch corporate bodies feed from MCP.
|
|
1402
1578
|
*
|
|
1403
1579
|
* @param client - MCP client or null
|
|
1404
|
-
* @param timeframe - How far back to look (default: 'one-
|
|
1580
|
+
* @param timeframe - How far back to look (default: 'one-week')
|
|
1405
1581
|
* @returns Array of corporate body feed items
|
|
1406
1582
|
*/
|
|
1407
|
-
export async function fetchCorporateBodiesFeed(client, timeframe = 'one-
|
|
1583
|
+
export async function fetchCorporateBodiesFeed(client, timeframe = 'one-week') {
|
|
1408
1584
|
if (!client)
|
|
1409
1585
|
return [];
|
|
1410
1586
|
try {
|
|
@@ -1424,10 +1600,10 @@ export async function fetchCorporateBodiesFeed(client, timeframe = 'one-day') {
|
|
|
1424
1600
|
* Returns `undefined` when client is null (MCP unavailable).
|
|
1425
1601
|
*
|
|
1426
1602
|
* @param client - MCP client or null
|
|
1427
|
-
* @param timeframe - How far back to look (default: 'one-
|
|
1603
|
+
* @param timeframe - How far back to look (default: 'one-week')
|
|
1428
1604
|
* @returns Aggregated feed data for breaking news, or undefined when client is null
|
|
1429
1605
|
*/
|
|
1430
|
-
export async function fetchBreakingNewsFeedData(client, timeframe = 'one-
|
|
1606
|
+
export async function fetchBreakingNewsFeedData(client, timeframe = 'one-week') {
|
|
1431
1607
|
if (!client)
|
|
1432
1608
|
return undefined;
|
|
1433
1609
|
if (!mcpCircuitBreaker.canRequest()) {
|
|
@@ -1454,11 +1630,11 @@ export async function fetchBreakingNewsFeedData(client, timeframe = 'one-day') {
|
|
|
1454
1630
|
* This is the primary data source for all article strategies.
|
|
1455
1631
|
*
|
|
1456
1632
|
* @param client - MCP client or null
|
|
1457
|
-
* @param timeframe - How far back to look (default: 'one-
|
|
1633
|
+
* @param timeframe - How far back to look (default: 'one-week')
|
|
1458
1634
|
* @param dateRange - Optional inclusive UTC window for filtering feed items
|
|
1459
1635
|
* @returns Full EPFeedData or undefined when client is null
|
|
1460
1636
|
*/
|
|
1461
|
-
export async function fetchEPFeedData(client, timeframe = 'one-
|
|
1637
|
+
export async function fetchEPFeedData(client, timeframe = 'one-week', dateRange) {
|
|
1462
1638
|
// Check for pre-fetched feed data file (set by --feed-data CLI arg).
|
|
1463
1639
|
// This allows agentic workflows to pass MCP data fetched via framework tools
|
|
1464
1640
|
// into the generator without requiring a direct MCP connection.
|