Files

47 lines
1.5 KiB
TypeScript

import type { FastifyInstance, FastifyRequest, FastifyReply } from 'fastify';
import type { LLMAnalyst } from '../../domains/shared';
import { CatalystCache, CatalystAnalyst } from '../../domains/shared';
import { analyzeSchema } from '../../domains/shared/types/schemas';
export class AnalyzeController {
constructor(
private readonly catalystCache: CatalystCache,
private readonly llm: LLMAnalyst,
) {}
register(app: FastifyInstance): void {
app.post(
'/api/analyze',
{ schema: analyzeSchema, config: { rateLimit: { max: 10, timeWindow: '1 minute' } } },
this.analyze.bind(this),
);
}
private async analyze(req: FastifyRequest, reply: FastifyReply) {
if (!this.llm.isAvailable) {
return reply.code(400).send({ error: 'ANTHROPIC_API_KEY is not set in .env' });
}
const requestedTickers = (req.body as { tickers: string[] }).tickers.map((t) =>
t.toUpperCase(),
);
const { stories: allStories } = await this.catalystCache.get();
const stories = allStories.filter((story) =>
story.tickers.some((t) => requestedTickers.includes(t)),
);
if (!stories.length) return reply.code(200).send({ analysis: null, reason: 'no_stories' });
const { tickerFrequency } = CatalystAnalyst.rankTickers(stories);
let analysis = null;
try {
analysis = await this.llm.analyze(stories, requestedTickers, tickerFrequency);
} catch (err) {
req.log.error({ err }, 'LLM analysis failed');
}
return { analysis };
}
}