openpondai/agents/news-intelligence-roundup

OpenTool app

1Branch0Tags
OP
OpenPond Syncsync: merge local template master into production
typescript
import { z } from "zod"; const CONFIG_ENV = "OPENTOOL_PUBLIC_NEWS_INTELLIGENCE_ROUNDUP_CONFIG"; const TEMPLATE_CONFIG_ENV_VAR = CONFIG_ENV; const TEMPLATE_CONFIG_VERSION = 3; const MAX_WINDOW_HOURS = 24 * 90; const MAX_WINDOWS = 8; const roundupModeSchema = z.enum([ "query_search", "recent_feed", "top_events", ]); const sourceFamilySchema = z.enum([ "rss", "official", "macro", "prediction_market", "social", ]); const includePredictionMarketsSchema = z.union([ z.boolean(), z.literal("auto"), ]); const baseConfigSchema = z .object({ configVersion: z.number().int().optional(), title: z.string().min(1).max(120).optional(), mode: roundupModeSchema.optional(), query: z.string().min(1).optional(), windows: z .array(z.number().int().min(1).max(MAX_WINDOW_HOURS)) .min(1) .max(MAX_WINDOWS) .optional(), limitPerWindow: z.number().int().min(1).max(50).optional(), sourceIds: z.array(z.string().min(1)).max(50).optional(), sourceFamilies: z.array(sourceFamilySchema).max(10).optional(), includePredictionMarkets: includePredictionMarketsSchema.optional(), ingestOnRequest: z.boolean().optional(), summaryModel: z.string().min(1).optional(), summaryMaxArticles: z.number().int().min(1).max(10).optional(), asOf: z.string().datetime().optional(), }) .strict(); export const requestOverrideSchema = baseConfigSchema.partial(); export type SourceFamily = z.infer<typeof sourceFamilySchema>; export type RoundupMode = z.infer<typeof roundupModeSchema>; export type IncludePredictionMarkets = z.infer< typeof includePredictionMarketsSchema >; export type NewsIntelligenceRoundupConfig = { configVersion: number; title: string; mode: RoundupMode; query: string | null; windows: number[]; limitPerWindow: number; sourceIds?: string[]; sourceFamilies?: SourceFamily[]; includePredictionMarkets: IncludePredictionMarkets; ingestOnRequest: boolean; summaryModel?: string; summaryMaxArticles: number; asOf?: string; }; const TEMPLATE_CONFIG_DEFAULTS: NewsIntelligenceRoundupConfig = { configVersion: TEMPLATE_CONFIG_VERSION, title: "Market News Roundup", mode: "top_events", query: "global markets, macro, geopolitics, oil, rates, inflation, crypto policy", windows: [24], limitPerWindow: 8, includePredictionMarkets: false, ingestOnRequest: false, summaryModel: "gpt-4.1-mini", summaryMaxArticles: 5, }; const TEMPLATE_CONFIG_SCHEMA = { type: "object", properties: { configVersion: { type: "number", title: "Config version", description: "Internal version for roundup defaults.", readOnly: true, "x-hidden": true, }, title: { type: "string", title: "Title", description: "Display title used in the roundup payload.", }, mode: { type: "string", title: "Mode", description: "Use query search, recent feed, or top events.", enum: ["query_search", "recent_feed", "top_events"], }, query: { type: "string", title: "Query", description: "Optional search query for query_search mode, or editorial focus used by the AI summary for recent_feed and top_events.", }, windows: { type: "array", title: "Windows", description: "Lookback windows in hours, for example [1,4,24].", items: { type: "number" }, }, limitPerWindow: { type: "number", title: "Limit per window", description: "Max articles requested from gateway per lookback window.", }, sourceIds: { type: "array", title: "Source IDs", description: "Optional explicit source IDs to include.", items: { type: "string" }, }, sourceFamilies: { type: "array", title: "Source families", description: "Optional source family filters.", items: { type: "string", enum: ["rss", "official", "macro", "prediction_market", "social"], }, }, includePredictionMarkets: { type: ["boolean", "string"], title: "Include prediction markets", description: "Whether to attach bounded prediction-market context when available.", }, ingestOnRequest: { type: "boolean", title: "Ingest on request", description: "Ask gateway to ingest matching sources before resolving the roundup.", }, summaryModel: { type: "string", title: "Summary model", description: "Model used for the short AI-written roundup summary.", }, summaryMaxArticles: { type: "number", title: "Summary max articles", description: "Max number of top articles returned in the final roundup.", }, asOf: { type: "string", title: "As of", description: "Optional ISO timestamp for replaying the roundup at a prior point in time.", }, }, }; function parseJson(raw: string | null): unknown | null { if (!raw) return null; try { return JSON.parse(raw) as unknown; } catch { return null; } } function pickDefined<T extends Record<string, unknown>>(value: T): Partial<T> { return Object.fromEntries( Object.entries(value).filter(([, entry]) => entry !== undefined), ) as Partial<T>; } function uniqueSortedWindows(windows?: number[]) { const resolved = windows && windows.length > 0 ? windows : TEMPLATE_CONFIG_DEFAULTS.windows; return Array.from(new Set(resolved)).sort((left, right) => left - right); } function normalizeStringArray(value?: string[]) { if (!value || value.length === 0) return undefined; const normalized = Array.from( new Set(value.map((entry) => entry.trim()).filter(Boolean)), ); return normalized.length > 0 ? normalized : undefined; } export function resolveRuntimeConfig( overrides?: z.infer<typeof requestOverrideSchema>, ): NewsIntelligenceRoundupConfig { const envConfig = parseJson(process.env[CONFIG_ENV] ?? null); const parsed = baseConfigSchema.safeParse( envConfig ?? TEMPLATE_CONFIG_DEFAULTS, ); const base = parsed.success ? parsed.data : TEMPLATE_CONFIG_DEFAULTS; const merged = { ...base, ...pickDefined((overrides ?? {}) as Record<string, unknown>), }; const finalMode = merged.mode ?? (typeof merged.query === "string" && merged.query.trim().length > 0 ? "query_search" : TEMPLATE_CONFIG_DEFAULTS.mode); const finalQuery = typeof merged.query === "string" && merged.query.trim().length > 0 ? merged.query.trim() : null; if (finalMode === "query_search" && !finalQuery) { throw new Error("query is required for query_search mode"); } return { configVersion: TEMPLATE_CONFIG_VERSION, title: merged.title ?? TEMPLATE_CONFIG_DEFAULTS.title, mode: finalMode, query: finalQuery, windows: uniqueSortedWindows(merged.windows), limitPerWindow: merged.limitPerWindow ?? TEMPLATE_CONFIG_DEFAULTS.limitPerWindow, sourceIds: normalizeStringArray(merged.sourceIds), sourceFamilies: merged.sourceFamilies?.length ? Array.from(new Set(merged.sourceFamilies)) : undefined, includePredictionMarkets: merged.includePredictionMarkets ?? TEMPLATE_CONFIG_DEFAULTS.includePredictionMarkets, ingestOnRequest: merged.ingestOnRequest ?? TEMPLATE_CONFIG_DEFAULTS.ingestOnRequest, summaryModel: merged.summaryModel ?? TEMPLATE_CONFIG_DEFAULTS.summaryModel, summaryMaxArticles: merged.summaryMaxArticles ?? TEMPLATE_CONFIG_DEFAULTS.summaryMaxArticles, asOf: merged.asOf, }; } export const NEWS_INTELLIGENCE_ROUNDUP_TEMPLATE_CONFIG = { version: TEMPLATE_CONFIG_VERSION, schema: TEMPLATE_CONFIG_SCHEMA, defaults: TEMPLATE_CONFIG_DEFAULTS, envVar: TEMPLATE_CONFIG_ENV_VAR, };