import { getRpcBaseUrl } from '@/services/rpc-client'; import type { ArxivPaper, GithubRepo, HackernewsItem } from '@/generated/client/worldmonitor/research/v1/service_client'; import { createCircuitBreaker } from '@/utils'; import { ResearchServiceClient } from '@/services/generated-rpc-clients'; // Re-export proto types (no legacy mapping needed -- proto types are clean) export type { ArxivPaper, GithubRepo, HackernewsItem }; const client = new ResearchServiceClient(getRpcBaseUrl(), { fetch: (...args) => globalThis.fetch(...args) }); const arxivBreaker = createCircuitBreaker({ name: 'ArXiv Papers', cacheTtlMs: 10 * 60 * 1000, persistCache: true }); const trendingBreaker = createCircuitBreaker({ name: 'GitHub Trending', cacheTtlMs: 10 * 60 * 1000, persistCache: true }); const hnBreaker = createCircuitBreaker({ name: 'Hacker News', cacheTtlMs: 10 * 60 * 1000, persistCache: true }); export async function fetchArxivPapers( category = 'cs.AI', query = '', pageSize = 50, ): Promise { return arxivBreaker.execute(async () => { const resp = await client.listArxivPapers({ category, query, pageSize, cursor: '', }); return resp.papers; }, [], { cacheKey: `${category}:${query}:${pageSize}` }); } export async function fetchTrendingRepos( language = 'python', period = 'daily', pageSize = 50, ): Promise { return trendingBreaker.execute(async () => { const resp = await client.listTrendingRepos({ language, period, pageSize, cursor: '', }); return resp.repos; }, [], { cacheKey: `${language}:${period}:${pageSize}` }); } export async function fetchHackernewsItems( feedType = 'top', pageSize = 30, ): Promise { return hnBreaker.execute(async () => { const resp = await client.listHackernewsItems({ feedType, pageSize, cursor: '', }); return resp.items; }, [], { cacheKey: `${feedType}:${pageSize}` }); }