Prince9868's picture
Hackathon submission: Guardian OpenEnv
5743bc2
Raw
History Blame Contribute Delete
8.44 kB
type ScanReport = Record<string, any>;
type FeeEstimate = Record<string, any>;
type MissionPayload = Record<string, any>;
function cleanText(value: unknown, fallback = ""): string {
if (typeof value !== "string") return fallback;
const trimmed = value.trim();
return trimmed || fallback;
}
function asNumber(value: unknown): number | null {
return typeof value === "number" && Number.isFinite(value) ? value : null;
}
function formatMoney(value: unknown): string {
const numeric = asNumber(value);
if (numeric == null) return "--";
return `$${numeric.toFixed(2)}`;
}
export function buildScanCopilot(input: {
domain: string;
url?: string;
pageText?: string;
darkPatternReport: ScanReport;
trustRating?: { score?: number; tier?: string } | null;
}) {
const report = input.darkPatternReport ?? {};
const detected: Array<{ label: string; explanation: string }> = [];
if (report.falseUrgency?.detected) {
detected.push({
label: "False urgency",
explanation: cleanText(report.falseUrgency?.evidence, "The page uses time pressure to rush the decision."),
});
}
if (report.falseScarcity?.detected) {
detected.push({
label: "False scarcity",
explanation: cleanText(report.falseScarcity?.evidence, "The page suggests stock pressure or crowd pressure."),
});
}
if (report.confirmShaming?.detected) {
detected.push({
label: "Confirm shaming",
explanation: cleanText(report.confirmShaming?.shamingText, "The decline path uses guilt-inducing copy."),
});
}
if (report.hiddenFees?.detected) {
const fees = Array.isArray(report.hiddenFees?.feeItems)
? report.hiddenFees.feeItems.map((fee: any) => `${fee.label} ${formatMoney(fee.amount)}`).join(", ")
: "";
detected.push({
label: "Hidden fees",
explanation: fees || "The page appears to hold back mandatory price information until later in checkout.",
});
}
if (report.preCheckedAddOns?.detected) {
detected.push({
label: "Pre-checked add-ons",
explanation: cleanText(
Array.isArray(report.preCheckedAddOns?.addOnLabels) ? report.preCheckedAddOns.addOnLabels.join(", ") : "",
"Optional extras are already selected for the shopper.",
),
});
}
if (report.misdirection?.detected) {
detected.push({
label: "Misdirection",
explanation: cleanText(report.misdirection?.hiddenDeclineText, "The safer or cheaper path is visually deprioritized."),
});
}
const trustScore = report.trustScore ?? input.trustRating?.score ?? 50;
const headline =
detected.length === 0
? `Guardian thinks ${input.domain} looks relatively clean from the submitted checkout content.`
: `Guardian thinks ${input.domain} is using ${detected.length} manipulation signal${detected.length === 1 ? "" : "s"}.`;
const recommendation =
detected.length === 0
? "Proceed, but keep Guardian active through the final confirmation step."
: detected.length >= 3
? "Slow down, verify the total, and look for a cleaner alternative before buying."
: "Proceed cautiously and remove optional extras before continuing.";
return {
mode: "scan",
headline,
confidence:
detected.length === 0 ? "medium" : detected.length >= 3 ? "high" : "medium",
inputSummary: `Input reviewed for ${input.domain}${input.url ? ` at ${input.url}` : ""}.`,
reasoning: detected.length
? detected.map((item) => `${item.label}: ${item.explanation}`)
: ["No major dark-pattern signature was triggered in the submitted checkout content."],
recommendation,
trustScore,
followUps:
detected.length === 0
? ["Keep watching for last-second fees at the payment step."]
: [
"Check whether the final payable amount matches the first quoted price.",
"Look for a neutral decline path and remove any default-on add-ons.",
],
};
}
export function buildFeeCopilot(input: {
domain: string;
merchantType: string;
listedPrice: number;
result: FeeEstimate;
}) {
const estimatedTotal = asNumber(input.result?.estimatedTotal) ?? input.listedPrice;
const savingsOpportunity = asNumber(input.result?.savingsOpportunity) ?? Math.max(0, estimatedTotal - input.listedPrice);
const breakdown = Array.isArray(input.result?.feeBreakdown)
? input.result.feeBreakdown.map((fee: any) => `${fee.label} ${formatMoney(fee.amount)}`)
: [];
return {
mode: "fee_estimate",
headline: `Guardian thinks the advertised ${formatMoney(input.listedPrice)} on ${input.domain} is likely to end closer to ${formatMoney(estimatedTotal)}.`,
confidence: cleanText(input.result?.confidence, "medium"),
inputSummary: `Input reviewed for ${input.domain} in the ${input.merchantType} category.`,
reasoning: [
breakdown.length
? `Likely hidden cost layers: ${breakdown.join(", ")}.`
: "Guardian expects taxes, surcharges, or service fees beyond the headline price.",
`Modeled uplift over headline price: ${formatMoney(savingsOpportunity)}.`,
],
recommendation:
savingsOpportunity <= 0
? "The listed price looks close to the real total."
: savingsOpportunity / Math.max(input.listedPrice, 1) > 0.2
? "Treat this as a high-risk price gap and compare alternatives before checkout."
: "Proceed with caution and verify the fee breakdown before paying.",
trustScore: null,
followUps: [
"Try a full mission run on the merchant to verify the true payable amount.",
"Look for the same product or booking on a cleaner alternative site.",
],
};
}
export function buildMissionCopilot(input: {
domain: string;
purchaseGoal: string;
mission: MissionPayload;
}) {
const recommendation = cleanText(input.mission?.recommendation, "proceed");
const trustScore = asNumber(input.mission?.trust?.score);
const signals = Array.isArray(input.mission?.manipulativeSignals) ? input.mission.manipulativeSignals : [];
const alternatives = Array.isArray(input.mission?.alternatives) ? input.mission.alternatives : [];
const dealItems = Array.isArray(input.mission?.dealIntelligence?.items) ? input.mission.dealIntelligence.items : [];
const misleadingDeals = dealItems.filter((item: any) => item?.status === "likely_misleading");
const isShoppingPage = input.mission?.commerceIntent?.isShoppingPage !== false;
return {
mode: "mission",
headline: isShoppingPage
? `Guardian thinks the best next move for ${input.domain} is to ${recommendation.replaceAll("_", " ")}.`
: `Guardian thinks ${input.domain} is not a shopping flow, so it should not run checkout automation here.`,
confidence: isShoppingPage ? "high" : "high",
inputSummary: `Goal understood: ${input.purchaseGoal}`,
reasoning: isShoppingPage
? [
cleanText(input.mission?.trust?.verdict, "Guardian evaluated the trust posture of the current merchant."),
signals.length
? `Main manipulation signals: ${signals.slice(0, 3).map((signal: any) => signal.label).join(", ")}.`
: "No major manipulation signature was triggered for the current merchant profile.",
alternatives.length
? `Guardian found ${alternatives.length} alternative site option${alternatives.length === 1 ? "" : "s"} for comparison.`
: "No alternative sites were returned for this mission.",
dealItems.length
? misleadingDeals.length
? `Deal-authenticity check flagged ${misleadingDeals.length} likely misleading limited-deal claim${misleadingDeals.length === 1 ? "" : "s"}.`
: "Deal-authenticity check did not find high-confidence misleading claim patterns."
: "No product-level deal cards were available for authenticity scoring.",
]
: [cleanText(input.mission?.commerceIntent?.reason, "No checkout signals were detected on the current page.")],
recommendation: cleanText(input.mission?.nextBestAction, "Keep Guardian active through checkout."),
trustScore,
followUps: isShoppingPage
? [
"Approve account creation only if the site remains the best option after comparison.",
"Keep Guardian active until the final payment step to catch late fees.",
]
: ["Open a product, cart, booking, or checkout page before rerunning the mission."],
};
}