feat: add support for Claude LLM integration across multiple modules

- Introduced `useClaude` option in `AnalysisPipelineOptions` to toggle Claude LLM usage.
- Updated `processProductChunk` and `analyzeProducts` functions to accept and handle `useClaude` parameter.
- Modified argument parsing in various scripts (`bestsellers-by-category`, `mid-range-sellers-by-category`, `top-monthly-sold-by-category`, etc.) to include `--claude` flag.
- Enhanced `analyzeProductsInternal` to differentiate between LLM providers and handle requests to Claude API.
- Added error handling for Claude API responses and ensured proper configuration for using Claude.
- Updated documentation and usage messages to reflect the new `--claude` flag.
This commit is contained in:
Victor Noguera
2026-05-21 19:57:46 -04:00
parent 0f256be2be
commit 95cebaa27c
12 changed files with 423 additions and 144 deletions

View File

@@ -28,6 +28,7 @@ type ParsedArgs = {
categoryCandidatePool: number;
minMonthlySold: number;
blacklistFile: string;
useClaude: boolean;
};
type CategoryRunSummary = {
@@ -76,6 +77,7 @@ function log(
function parseArgs(): ParsedArgs {
const args = process.argv.slice(2);
const useClaude = hasFlag(args, "--claude");
const outputDir =
readFlagValue(args, "--out-dir") ?? path.join(process.cwd(), "output");
const blacklistFile =
@@ -131,9 +133,14 @@ function parseArgs(): ParsedArgs {
categoryCandidatePool,
minMonthlySold,
blacklistFile,
useClaude,
};
}
function hasFlag(args: string[], flag: string): boolean {
return args.includes(flag);
}
function readFlagValue(args: string[], flag: string): string | undefined {
const idx = args.indexOf(flag);
if (idx === -1) return undefined;
@@ -149,7 +156,7 @@ function printUsageAndExit(message: string): never {
"error",
[
"Usage:",
" bun run src/top-monthly-sold-by-category.ts [--category-limit 32] [--per-category-top 100] [--category-candidate-pool 500] [--min-monthly-sold 300] [--out-dir output] [--blacklist-file category-blacklist.csv]",
" bun run src/top-monthly-sold-by-category.ts [--category-limit 32] [--per-category-top 100] [--category-candidate-pool 500] [--min-monthly-sold 300] [--out-dir output] [--blacklist-file category-blacklist.csv] [--claude]",
"",
"Flow:",
" 1) Discover categories and round-robin selection.",
@@ -1066,6 +1073,7 @@ export async function processCategory(
perCategoryTop: number,
categoryCandidatePool: number,
minMonthlySold: number,
useClaude = false,
): Promise<CategoryRunSummary> {
log("info", `\nCategory ${category.label} (${category.id})`);
@@ -1200,7 +1208,7 @@ export async function processCategory(
let batchVerdicts: LlmVerdict[];
try {
batchVerdicts = await analyzeProducts(batch);
batchVerdicts = await analyzeProducts(batch, { useClaude });
} catch (err) {
const message = err instanceof Error ? err.message : String(err);
log("warn", ` LLM batch failed: ${message}`);
@@ -1286,7 +1294,7 @@ export async function main(): Promise<void> {
mkdirSync(args.outputDir, { recursive: true });
const DB_PATH =
process.env.RESULTS_DB_PATH || path.join(process.cwd(), "db", "results.db");
process.env.RESULTS_DB_PATH || path.join(process.cwd(), "db", "results.db");
initDb(DB_PATH);
const db = getDb(DB_PATH);
@@ -1348,6 +1356,7 @@ export async function main(): Promise<void> {
args.perCategoryTop,
args.categoryCandidatePool,
args.minMonthlySold,
args.useClaude,
);
totalInsertedAsins += categorySummary.results?.length ?? 0;