import { z } from 'zod'; import { getRouter } from '../router.js'; import type { CostContext, ModelProvider } from '../types.js'; export interface NewsInput { url: string; title: string; text: string; publishedAt?: string | null; } export const NewsSummarySchema = z.object({ items: z.array( z.object({ url: z.string(), summary: z.string().describe('2–3 factual sentences, no speculation, figures only if present in the source'), newsType: z.enum(['auction_results', 'record_sales', 'grading', 'releases', 'trends', 'discoveries', 'events', 'other']), categorySlugs: z.array(z.string()).max(4), mentionedPrices: z.array(z.object({ amount: z.number(), currency: z.string(), what: z.string() })).max(5), }), ), }); /** Summarise market news items with source links (§156). Facts only; the UI links each summary to its source. */ export async function summarizeNews(items: NewsInput[], opts: { provider?: ModelProvider; cost?: CostContext } = {}) { const provider = opts.provider ?? getRouter(); const input = items.map((i, n) => `### Item ${n + 1}\nURL: ${i.url}\nTitle: ${i.title}\nPublished: ${i.publishedAt ?? 'unknown'}\n${i.text.slice(0, 6000)}`).join('\n\n'); return provider.extract('summarize', { schema: NewsSummarySchema, system: 'You summarise collectibles-market news for a data terminal. Neutral tone, no investment advice, keep every figure exactly as stated in the source, return one entry per item with the same URL.', prompt: 'Summarise each item.', input, maxTokens: 4096, effort: 'low', cost: { endpoint: 'summarize_news', ...(opts.cost ?? {}) }, }); }