feat: harden intelligence runtime and llm providers
This commit is contained in:
@@ -12,6 +12,7 @@ import { exec } from 'child_process';
|
||||
import config from '../crucix.config.mjs';
|
||||
import { createLLMProvider } from '../lib/llm/index.mjs';
|
||||
import { generateLLMIdeas } from '../lib/llm/ideas.mjs';
|
||||
import { safeFetchText } from '../apis/utils/fetch.mjs';
|
||||
|
||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||
const ROOT = join(__dirname, '..');
|
||||
@@ -146,10 +147,14 @@ function loadOpenSkyFallback(currentTimestamp) {
|
||||
}
|
||||
|
||||
// === RSS Fetching ===
|
||||
const rssHealth = {};
|
||||
|
||||
async function fetchRSS(url, source) {
|
||||
const started = Date.now();
|
||||
try {
|
||||
const res = await fetch(url, { signal: AbortSignal.timeout(8000) });
|
||||
const xml = await res.text();
|
||||
const fetched = await safeFetchText(url, { signal: AbortSignal.timeout(8000), source: `RSS:${source}`, timeout: 12000, retries: 1 });
|
||||
if (fetched.error) throw new Error(fetched.error);
|
||||
const xml = fetched.text;
|
||||
const items = [];
|
||||
const itemRegex = /<item>([\s\S]*?)<\/item>/g;
|
||||
let match;
|
||||
@@ -160,9 +165,11 @@ async function fetchRSS(url, source) {
|
||||
const pubDate = block.match(/<pubDate>(.*?)<\/pubDate>/)?.[1] || '';
|
||||
if (title && title !== source) items.push({ title, date: pubDate, source, url: link || undefined });
|
||||
}
|
||||
rssHealth[source] = { status: items.length ? 'ok' : 'degraded', items: items.length, durationMs: Date.now() - started, url };
|
||||
return items;
|
||||
} catch (e) {
|
||||
console.log(`RSS fetch failed (${source}):`, e.message);
|
||||
rssHealth[source] = { status: 'failed', items: 0, durationMs: Date.now() - started, url, error: e.message };
|
||||
return [];
|
||||
}
|
||||
}
|
||||
@@ -176,6 +183,7 @@ const RSS_SOURCE_FALLBACKS = {
|
||||
const REGIONAL_NEWS_SOURCES = ['MercoPress', 'Indian Express', 'The Hindu', 'SBS Australia'];
|
||||
|
||||
export async function fetchAllNews() {
|
||||
for (const key of Object.keys(rssHealth)) delete rssHealth[key];
|
||||
const feeds = [
|
||||
// Global
|
||||
['http://feeds.bbci.co.uk/news/world/rss.xml', 'BBC'],
|
||||
@@ -256,6 +264,10 @@ export async function fetchAllNews() {
|
||||
return selected.slice(0, 50);
|
||||
}
|
||||
|
||||
export function getRSSHealth() {
|
||||
return { ...rssHealth };
|
||||
}
|
||||
|
||||
// === Leverageable Ideas from Signals ===
|
||||
export function generateIdeas(V2) {
|
||||
const ideas = [];
|
||||
@@ -540,7 +552,12 @@ export async function synthesize(data) {
|
||||
};
|
||||
|
||||
const health = Object.entries(data.sources).map(([name, src]) => ({
|
||||
n: name, err: Boolean(src.error), stale: Boolean(src.stale)
|
||||
n: name,
|
||||
status: data.timing?.[name]?.status || (src.error ? 'degraded' : 'ok'),
|
||||
err: Boolean(src.error || data.timing?.[name]?.status === 'error'),
|
||||
stale: Boolean(src.stale),
|
||||
message: src.error || src.message || data.timing?.[name]?.error || null,
|
||||
ms: data.timing?.[name]?.ms || 0,
|
||||
}));
|
||||
|
||||
// === Yahoo Finance live market data ===
|
||||
@@ -595,6 +612,7 @@ export async function synthesize(data) {
|
||||
|
||||
// Fetch RSS
|
||||
const news = await fetchAllNews();
|
||||
const newsHealth = getRSSHealth();
|
||||
|
||||
const V2 = {
|
||||
meta: data.crucix, air, thermal, tSignals, chokepoints, nuke, nukeSignals,
|
||||
@@ -610,6 +628,11 @@ export async function synthesize(data) {
|
||||
tg: { posts: tgData.totalPosts || 0, urgent: tgUrgent, topPosts: tgTop },
|
||||
who, fred, energy, metals, bls, treasury, gscpi, defense, noaa, epa, acled, gdelt, space, health, news,
|
||||
markets, // Live Yahoo Finance market data
|
||||
newsMeta: {
|
||||
rssHealth: newsHealth,
|
||||
rssOk: Object.values(newsHealth).filter(s => s.status === 'ok').length,
|
||||
rssFailed: Object.values(newsHealth).filter(s => s.status === 'failed').length,
|
||||
},
|
||||
ideas: [], ideasSource: 'disabled',
|
||||
// newsFeed for ticker (merged RSS + GDELT + Telegram)
|
||||
newsFeed: buildNewsFeed(news, gdeltData, tgUrgent, tgTop),
|
||||
|
||||
Reference in New Issue
Block a user