| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667 |
- import { tool } from "ai";
- import { z } from "zod";
- /**
- * Get top stories from Hacker News.
- * Uses the official HN Firebase API. Free, no auth required.
- * https://github.com/HackerNewsAPI/API
- */
- export const getHackerNewsTop = tool({
- description:
- "Get the current top stories from Hacker News, including title, score, author, URL, and comment count.",
- inputSchema: z.object({
- count: z
- .number()
- .min(1)
- .max(30)
- .describe("Number of top stories to fetch (1-30)"),
- }),
- execute: async ({ count }) => {
- const topUrl =
- "https://hacker-news.firebaseio.com/v0/topstories.json?print=pretty";
- const topRes = await fetch(topUrl);
- if (!topRes.ok) {
- return { error: "Failed to fetch Hacker News top stories" };
- }
- const topIds = (await topRes.json()) as number[];
- const storyIds = topIds.slice(0, count);
- const stories = await Promise.all(
- storyIds.map(async (id) => {
- const storyRes = await fetch(
- `https://hacker-news.firebaseio.com/v0/item/${id}.json?print=pretty`,
- );
- if (!storyRes.ok) return null;
- const story = (await storyRes.json()) as {
- id: number;
- title: string;
- url?: string;
- score: number;
- by: string;
- time: number;
- descendants?: number;
- type: string;
- };
- return {
- id: story.id,
- title: story.title,
- url: story.url ?? `https://news.ycombinator.com/item?id=${story.id}`,
- score: story.score,
- author: story.by,
- comments: story.descendants ?? 0,
- postedAt: new Date(story.time * 1000).toISOString(),
- hnUrl: `https://news.ycombinator.com/item?id=${story.id}`,
- };
- }),
- );
- return {
- stories: stories.filter(Boolean),
- fetchedAt: new Date().toISOString(),
- };
- },
- });
|