agentmall 0.1.4 → 0.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +75 -22
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -285,17 +285,37 @@ var FAILURE_MESSAGES = {
|
|
|
285
285
|
function formatCents(cents) {
|
|
286
286
|
return `$${(cents / 100).toFixed(2)}`;
|
|
287
287
|
}
|
|
288
|
-
function
|
|
288
|
+
function getBudgetBasePrice(product) {
|
|
289
|
+
return product.listPrice ?? product.price;
|
|
290
|
+
}
|
|
291
|
+
function calculateSuggestedBudget(product, quantity = 1) {
|
|
292
|
+
const quantityClamped = Math.max(1, quantity);
|
|
293
|
+
const basePriceCents = getBudgetBasePrice(product) * quantityClamped;
|
|
294
|
+
const variableBufferCents = Math.round(basePriceCents * 0.15);
|
|
295
|
+
return basePriceCents + Math.max(variableBufferCents, 800);
|
|
296
|
+
}
|
|
297
|
+
function calculateMinimumBudget(product, quantity = 1) {
|
|
298
|
+
return product.price * Math.max(1, quantity);
|
|
299
|
+
}
|
|
300
|
+
function displayProduct(product, quantity = 1) {
|
|
301
|
+
const quantityClamped = Math.max(1, quantity);
|
|
302
|
+
const suggestedBudget = calculateSuggestedBudget(product, quantityClamped);
|
|
303
|
+
const linePrice = product.price * quantityClamped;
|
|
304
|
+
const lineListPrice = typeof product.listPrice === "number" ? product.listPrice * quantityClamped : void 0;
|
|
289
305
|
console.log();
|
|
290
306
|
console.log(` \x1B[1m${product.title}\x1B[0m`);
|
|
291
307
|
console.log(` ${product.retailer} \u2014 ${product.availability}`);
|
|
292
308
|
console.log();
|
|
293
|
-
if (
|
|
309
|
+
if (lineListPrice && product.discountPercent) {
|
|
294
310
|
console.log(
|
|
295
|
-
` Price: \x1B[32m${formatCents(
|
|
311
|
+
` Price: \x1B[32m${formatCents(linePrice)}\x1B[0m \x1B[2m\x1B[9m${formatCents(lineListPrice)}\x1B[0m \x1B[33m-${product.discountPercent}%\x1B[0m`
|
|
296
312
|
);
|
|
297
313
|
} else {
|
|
298
|
-
console.log(` Price: \x1B[32m${formatCents(
|
|
314
|
+
console.log(` Price: \x1B[32m${formatCents(linePrice)}\x1B[0m`);
|
|
315
|
+
}
|
|
316
|
+
if (quantityClamped > 1) {
|
|
317
|
+
console.log(` Quantity: ${quantityClamped}`);
|
|
318
|
+
console.log(` Unit price: ${formatCents(product.price)}`);
|
|
299
319
|
}
|
|
300
320
|
if (product.variants?.length) {
|
|
301
321
|
console.log();
|
|
@@ -306,13 +326,19 @@ function displayProduct(product) {
|
|
|
306
326
|
}
|
|
307
327
|
console.log();
|
|
308
328
|
console.log(
|
|
309
|
-
` Suggested budget: \x1B[1m${formatCents(
|
|
329
|
+
` Suggested budget: \x1B[1m${formatCents(suggestedBudget)}\x1B[0m (includes 15% buffer for tax and an $8 minimum shipping buffer)`
|
|
310
330
|
);
|
|
311
331
|
console.log(
|
|
312
332
|
` Service fee: ${formatCents(SERVICE_FEE_CENTS)}`
|
|
313
333
|
);
|
|
314
334
|
console.log(
|
|
315
|
-
` Total charge: \x1B[1m${formatCents(
|
|
335
|
+
` Total charge: \x1B[1m${formatCents(suggestedBudget + SERVICE_FEE_CENTS)}\x1B[0m USDC`
|
|
336
|
+
);
|
|
337
|
+
console.log(
|
|
338
|
+
` Any unused amount from your max budget is refunded automatically after checkout.`
|
|
339
|
+
);
|
|
340
|
+
console.log(
|
|
341
|
+
` The buffer covers unforeseen tax, shipping, and retailer price changes at final checkout.`
|
|
316
342
|
);
|
|
317
343
|
if (product.cached) {
|
|
318
344
|
console.log(` \x1B[33m\u26A0 Price from cache \u2014 may not reflect current listing\x1B[0m`);
|
|
@@ -471,6 +497,20 @@ async function promptAddress() {
|
|
|
471
497
|
country: "US"
|
|
472
498
|
};
|
|
473
499
|
}
|
|
500
|
+
async function promptQuantity() {
|
|
501
|
+
const value = await input({
|
|
502
|
+
message: "Quantity",
|
|
503
|
+
default: "1",
|
|
504
|
+
validate: (v) => {
|
|
505
|
+
const n = parseInt(v.trim(), 10);
|
|
506
|
+
if (!Number.isInteger(n) || n <= 0) {
|
|
507
|
+
return "Enter a whole number greater than 0";
|
|
508
|
+
}
|
|
509
|
+
return true;
|
|
510
|
+
}
|
|
511
|
+
});
|
|
512
|
+
return parseInt(value.trim(), 10);
|
|
513
|
+
}
|
|
474
514
|
async function promptConfirm(message) {
|
|
475
515
|
return confirm({ message });
|
|
476
516
|
}
|
|
@@ -556,11 +596,15 @@ async function getBuyerToken(purchaseId) {
|
|
|
556
596
|
|
|
557
597
|
// src/cli/index.ts
|
|
558
598
|
var EMAIL_PATTERN = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
559
|
-
async function runCommandCapture(command2, args2) {
|
|
599
|
+
async function runCommandCapture(command2, args2, envOverrides) {
|
|
560
600
|
return await new Promise((resolve, reject) => {
|
|
561
601
|
const child = spawn(command2, args2, {
|
|
562
602
|
stdio: ["ignore", "pipe", "pipe"],
|
|
563
|
-
shell: process.platform === "win32"
|
|
603
|
+
shell: process.platform === "win32",
|
|
604
|
+
env: {
|
|
605
|
+
...process.env,
|
|
606
|
+
...envOverrides
|
|
607
|
+
}
|
|
564
608
|
});
|
|
565
609
|
let stdout = "";
|
|
566
610
|
let stderr = "";
|
|
@@ -630,17 +674,21 @@ function formatUsdAmount(cents) {
|
|
|
630
674
|
}
|
|
631
675
|
async function createPurchaseWithTempo(body) {
|
|
632
676
|
const totalChargeCents = body.max_budget + SERVICE_FEE_CENTS;
|
|
633
|
-
const result = await runCommandCapture(
|
|
634
|
-
"
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
677
|
+
const result = await runCommandCapture(
|
|
678
|
+
"tempo",
|
|
679
|
+
[
|
|
680
|
+
"request",
|
|
681
|
+
"-s",
|
|
682
|
+
"-X",
|
|
683
|
+
"POST",
|
|
684
|
+
"--json",
|
|
685
|
+
JSON.stringify(body),
|
|
686
|
+
`${BASE_URL}/api/purchases`
|
|
687
|
+
],
|
|
688
|
+
{
|
|
689
|
+
TEMPO_MAX_SPEND: formatUsdAmount(totalChargeCents)
|
|
690
|
+
}
|
|
691
|
+
);
|
|
644
692
|
if (result.code !== 0) {
|
|
645
693
|
const message = result.stderr.trim() || result.stdout.trim() || "Tempo request failed";
|
|
646
694
|
throw new Error(message);
|
|
@@ -660,10 +708,13 @@ async function buy(urlArg) {
|
|
|
660
708
|
const client = new AgentMall();
|
|
661
709
|
console.log(" Looking up product...");
|
|
662
710
|
const product = await client.products.lookup(url);
|
|
663
|
-
|
|
711
|
+
const quantity = await promptQuantity();
|
|
712
|
+
const suggestedMaxBudget = calculateSuggestedBudget(product, quantity);
|
|
713
|
+
const minimumBudget = calculateMinimumBudget(product, quantity);
|
|
714
|
+
displayProduct(product, quantity);
|
|
664
715
|
const variantSelections = product.variants?.length ? await promptVariants(product.variants) : void 0;
|
|
665
716
|
const address = await promptAddress();
|
|
666
|
-
const maxBudget = await promptBudget(
|
|
717
|
+
const maxBudget = await promptBudget(suggestedMaxBudget, minimumBudget);
|
|
667
718
|
const { input: input2 } = await import("@inquirer/prompts");
|
|
668
719
|
const buyerEmail = await input2({
|
|
669
720
|
message: "Email for order updates",
|
|
@@ -672,7 +723,7 @@ async function buy(urlArg) {
|
|
|
672
723
|
const body = {
|
|
673
724
|
items: [{
|
|
674
725
|
product_url: url,
|
|
675
|
-
quantity
|
|
726
|
+
quantity,
|
|
676
727
|
...variantSelections?.length ? { variant: variantSelections } : {}
|
|
677
728
|
}],
|
|
678
729
|
delivery_address: address,
|
|
@@ -681,6 +732,8 @@ async function buy(urlArg) {
|
|
|
681
732
|
};
|
|
682
733
|
displayOrderSummary(body);
|
|
683
734
|
console.log(` Total charge: \x1B[1m${formatCents(maxBudget + SERVICE_FEE_CENTS)}\x1B[0m USDC on Tempo`);
|
|
735
|
+
console.log(" Any unused amount from your max budget is refunded automatically after checkout.");
|
|
736
|
+
console.log(" The buffer covers unforeseen tax, shipping, and retailer price changes at final checkout.");
|
|
684
737
|
console.log();
|
|
685
738
|
const proceed = await promptConfirm("Place order?");
|
|
686
739
|
if (!proceed) {
|