TypeScript 61.9%
HTML 37.2%
SQL 0.7%
1import { z } from 'zod';2import { getRouter } from '../router.js';3import type { CostContext, ModelProvider } from '../types.js';45export interface NewsInput {6 url: string;7 title: string;8 text: string;9 publishedAt?: string | null;10}1112export const NewsSummarySchema = z.object({13 items: z.array(14 z.object({15 url: z.string(),16 summary: z.string().describe('2–3 factual sentences, no speculation, figures only if present in the source'),17 newsType: z.enum(['auction_results', 'record_sales', 'grading', 'releases', 'trends', 'discoveries', 'events', 'other']),18 categorySlugs: z.array(z.string()).max(4),19 mentionedPrices: z.array(z.object({ amount: z.number(), currency: z.string(), what: z.string() })).max(5),20 }),21 ),22});2324/** Summarise market news items with source links (§156). Facts only; the UI links each summary to its source. */25export async function summarizeNews(items: NewsInput[], opts: { provider?: ModelProvider; cost?: CostContext } = {}) {26 const provider = opts.provider ?? getRouter();27 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');28 return provider.extract('summarize', {29 schema: NewsSummarySchema,30 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.',31 prompt: 'Summarise each item.',32 input,33 maxTokens: 4096,34 effort: 'low',35 cost: { endpoint: 'summarize_news', ...(opts.cost ?? {}) },36 });37}38