import { z } from "zod";
import { searchTweets } from "../lib/twitter.js";
import { checkBatchQuality } from "../lib/llm.js";
import type { FetchPostsResult, Post } from "../types.js";
export const fetchPostsSchema = z.object({
query: z.string().describe("Single search query"),
loop_limit: z
.number()
.min(1)
.max(10)
.default(5)
.describe("Max fetch iterations (default: 5)"),
count: z
.number()
.min(10)
.max(100)
.default(10)
.describe("Posts per fetch (default: 10)"),
target: z
.string()
.optional()
.describe("Target name for quality evaluation (optional, improves results)"),
});
export type FetchPostsInput = z.infer<typeof fetchPostsSchema>;
export async function fetchPosts(input: FetchPostsInput): Promise<FetchPostsResult> {
const loopLimit = input.loop_limit ?? 5;
const count = input.count ?? 10;
const target = input.target ?? input.query;
const allPosts: Post[] = [];
let iterations = 0;
let nextToken: string | undefined;
let stoppedReason: "quality_threshold" | "loop_limit" = "loop_limit";
while (iterations < loopLimit) {
iterations++;
try {
const result = await searchTweets(input.query, count, nextToken);
allPosts.push(...result.posts);
nextToken = result.nextToken;
// Check batch quality via LLM
const isQualityMet = await checkBatchQuality(target, allPosts);
if (isQualityMet) {
stoppedReason = "quality_threshold";
break;
}
// If no more pages, stop
if (!nextToken) {
break;
}
} catch (error) {
// If we have some posts, return them; otherwise, throw
if (allPosts.length > 0) {
break;
}
throw error;
}
}
return {
posts: allPosts,
iterations,
stopped_reason: stoppedReason,
};
}
export const fetchPostsTool = {
name: "fetch_posts",
description:
"Fetch posts from Twitter for a given query, looping until quality threshold is met. Uses AI to evaluate batch quality and stops early when sufficient roast content is found. Returns posts with engagement metrics.",
inputSchema: {
type: "object" as const,
properties: {
query: {
type: "string",
description: "Single search query to find posts",
},
loop_limit: {
type: "number",
description: "Max fetch iterations (default: 5, max: 10)",
},
count: {
type: "number",
description: "Posts per fetch (default: 10, max: 100)",
},
target: {
type: "string",
description:
"Target name for quality evaluation (optional, improves quality checking)",
},
},
required: ["query"],
},
};