feat: implement reanalyze and distributor discovery endpoints for Stalker products by ASIN

This commit is contained in:
Victor Noguera
2026-05-25 15:57:24 -04:00
parent 313677692b
commit 506e2344b7
3 changed files with 74 additions and 15 deletions

View File

@@ -531,6 +531,36 @@ async function getProduct(asin: string) {
return { product, observations, analyses, distributorResearch };
}
async function findLatestStalkerRunItemIdByAsin(asin: string): Promise<number | null> {
const row = await pgGet<{ id: number }>(
`SELECT ri.id
FROM run_items ri
JOIN runs run ON run.id = ri.run_id
WHERE ri.product_asin = ?
AND run.type = 'stalker'
ORDER BY ri.id DESC
LIMIT 1`,
[asin],
);
return row?.id == null ? null : Number(row.id);
}
async function reanalyzeStalkerProductByAsin(asin: string, useClaude = USE_CLAUDE) {
const runItemId = await findLatestStalkerRunItemIdByAsin(asin);
if (runItemId == null) {
throw new Error("Stalker product item not found");
}
return reanalyzeRunItem(runItemId, useClaude);
}
async function findDistributorsForStalkerProductByAsin(asin: string) {
const runItemId = await findLatestStalkerRunItemIdByAsin(asin);
if (runItemId == null) {
throw new Error("Stalker product item not found");
}
return findDistributorsForStalkerProduct(runItemId);
}
async function reanalyzeRunItem(itemId: number, useClaude = USE_CLAUDE) {
const row = await pgGet<Record<string, any>>(
`SELECT ri.id, ri.run_id, ri.product_asin AS asin, r.type,
@@ -1159,6 +1189,30 @@ const server = Bun.serve({
return json({ error: message }, message === "Stalker product item not found" ? 404 : 500);
}
},
"/api/stalker/products/by-asin/:asin/reanalyze": async (req) => {
if (req.method !== "POST") return json({ error: "Method not allowed" }, 405);
const asin = normalizeAsin(req.params.asin);
if (!asin) return json({ error: "Invalid ASIN" }, 400);
const provider = new URL(req.url).searchParams.get("provider")?.trim().toLowerCase();
const useClaude = provider === "claude";
try {
return json(await reanalyzeStalkerProductByAsin(asin, useClaude || USE_CLAUDE));
} catch (error) {
const message = error instanceof Error ? error.message : String(error);
return json({ error: message }, message === "Stalker product item not found" ? 404 : 500);
}
},
"/api/stalker/products/by-asin/:asin/distributors": async (req) => {
if (req.method !== "POST") return json({ error: "Method not allowed" }, 405);
const asin = normalizeAsin(req.params.asin);
if (!asin) return json({ error: "Invalid ASIN" }, 400);
try {
return json(await findDistributorsForStalkerProductByAsin(asin));
} catch (error) {
const message = error instanceof Error ? error.message : String(error);
return json({ error: message }, message === "Stalker product item not found" ? 404 : 500);
}
},
"/api/stalker/purge": async (req) =>
req.method === "DELETE" || req.method === "POST"
? json(await purgeStalkerData())