feat: enhance distributor candidate research with additional fields and improved prompt for API request
This commit is contained in:
@@ -618,6 +618,9 @@ type DistributorCandidate = {
|
|||||||
website: string;
|
website: string;
|
||||||
rationale: string;
|
rationale: string;
|
||||||
confidence: number;
|
confidence: number;
|
||||||
|
reputation: string;
|
||||||
|
contactInfo: string;
|
||||||
|
outreachDraft: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
function clampDistributorConfidence(value: unknown): number {
|
function clampDistributorConfidence(value: unknown): number {
|
||||||
@@ -635,6 +638,9 @@ function normalizeDistributorCandidates(payload: unknown): DistributorCandidate[
|
|||||||
website: String(item.website ?? "").trim(),
|
website: String(item.website ?? "").trim(),
|
||||||
rationale: String(item.rationale ?? "").trim(),
|
rationale: String(item.rationale ?? "").trim(),
|
||||||
confidence: clampDistributorConfidence(item.confidence),
|
confidence: clampDistributorConfidence(item.confidence),
|
||||||
|
reputation: String(item.reputation ?? "").trim(),
|
||||||
|
contactInfo: String(item.contact_info ?? "").trim(),
|
||||||
|
outreachDraft: String(item.outreach_draft ?? "").trim(),
|
||||||
}))
|
}))
|
||||||
.filter((item) => item.name.length > 0 && item.website.length > 0)
|
.filter((item) => item.name.length > 0 && item.website.length > 0)
|
||||||
.slice(0, 10);
|
.slice(0, 10);
|
||||||
@@ -657,14 +663,32 @@ async function requestClaudeDistributorCandidates(context: Record<string, unknow
|
|||||||
throw new Error("Missing required env var: ANTHROPIC_API_KEY");
|
throw new Error("Missing required env var: ANTHROPIC_API_KEY");
|
||||||
}
|
}
|
||||||
const model = (config.anthropicModel ?? "claude-sonnet-4-6").trim() || "claude-sonnet-4-6";
|
const model = (config.anthropicModel ?? "claude-sonnet-4-6").trim() || "claude-sonnet-4-6";
|
||||||
const system = "You identify authorized wholesale distributors for products. Return only JSON.";
|
const system = [
|
||||||
|
"You are a wholesale sourcing researcher who identifies authorized U.S. distributors for Amazon products.",
|
||||||
|
"For each candidate you research their reputation, locate real point-of-contact details, and draft a concise cold-outreach message.",
|
||||||
|
"Return only raw JSON — no prose, no markdown fences.",
|
||||||
|
].join(" ");
|
||||||
const prompt = [
|
const prompt = [
|
||||||
"Given this Amazon product context, identify up to 5 likely authorized U.S. wholesale distributors.",
|
"Analyze the Amazon product context below and identify up to 5 likely authorized U.S. wholesale distributors.",
|
||||||
"Prioritize official brand channels and reputable distributors.",
|
"",
|
||||||
"Return only a raw JSON array with objects:",
|
"For each distributor:",
|
||||||
'[{"name":"...","website":"https://...","rationale":"...","confidence":0-100}]',
|
"1. Identify whether they are an official brand distributor, authorized reseller, or national wholesaler.",
|
||||||
|
"2. Investigate their reputation: check for BBB accreditation, industry tenure, any known complaints or red flags, and whether they appear on the brand's own authorized-distributor list.",
|
||||||
|
"3. Find the most direct point-of-contact for new wholesale accounts — ideally a named buyer, vendor relations team, or wholesale inquiry email/phone from their website (not a generic contact form).",
|
||||||
|
"4. Draft a short, professional cold-outreach message (3–5 sentences) I can send to open a wholesale account inquiry. The message should: mention the specific product or brand, state that I sell on Amazon as an FBA seller, ask about minimum order quantities and wholesale pricing, and invite them to share an application or terms sheet.",
|
||||||
|
"",
|
||||||
|
"Return a raw JSON array. Each object must have exactly these keys:",
|
||||||
|
' "name" — distributor company name',
|
||||||
|
' "website" — full URL (https://...)',
|
||||||
|
' "rationale" — why this distributor is a strong candidate (1–2 sentences)',
|
||||||
|
' "confidence" — integer 0–100 reflecting how confident you are this is a real authorized source',
|
||||||
|
' "reputation" — summary of reputation findings (BBB status, years in business, any red flags)',
|
||||||
|
' "contact_info" — best point-of-contact found (name/title, email or phone, or wholesale inquiry URL)',
|
||||||
|
' "outreach_draft"— ready-to-send outreach message addressed to the contact above',
|
||||||
|
"",
|
||||||
|
"Product context:",
|
||||||
JSON.stringify(context, null, 2),
|
JSON.stringify(context, null, 2),
|
||||||
].join("\n\n");
|
].join("\n");
|
||||||
const response = await fetch("https://api.anthropic.com/v1/messages", {
|
const response = await fetch("https://api.anthropic.com/v1/messages", {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
@@ -677,7 +701,7 @@ async function requestClaudeDistributorCandidates(context: Record<string, unknow
|
|||||||
system,
|
system,
|
||||||
messages: [{ role: "user", content: prompt }],
|
messages: [{ role: "user", content: prompt }],
|
||||||
temperature: 0.2,
|
temperature: 0.2,
|
||||||
max_tokens: 1800,
|
max_tokens: 4096,
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
const raw = await response.text();
|
const raw = await response.text();
|
||||||
|
|||||||
Reference in New Issue
Block a user