agentmall 0.1.6 → 0.1.8
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 +79 -18
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -303,6 +303,7 @@ function displayProduct(product, quantity = 1) {
|
|
|
303
303
|
const linePrice = product.price * quantityClamped;
|
|
304
304
|
const lineListPrice = typeof product.listPrice === "number" ? product.listPrice * quantityClamped : void 0;
|
|
305
305
|
console.log();
|
|
306
|
+
console.log(" \x1B[1m\u{1F4E6} Product\x1B[0m");
|
|
306
307
|
console.log(` \x1B[1m${product.title}\x1B[0m`);
|
|
307
308
|
console.log(` ${product.retailer} \u2014 ${product.availability}`);
|
|
308
309
|
console.log();
|
|
@@ -325,6 +326,7 @@ function displayProduct(product, quantity = 1) {
|
|
|
325
326
|
}
|
|
326
327
|
}
|
|
327
328
|
console.log();
|
|
329
|
+
console.log(" \x1B[1m\u{1F4B8} Checkout Estimate\x1B[0m");
|
|
328
330
|
console.log(
|
|
329
331
|
` Suggested budget: \x1B[1m${formatCents(suggestedBudget)}\x1B[0m (includes 15% buffer for tax and an $8 minimum shipping buffer)`
|
|
330
332
|
);
|
|
@@ -347,7 +349,7 @@ function displayProduct(product, quantity = 1) {
|
|
|
347
349
|
}
|
|
348
350
|
function displayOrderSummary(body) {
|
|
349
351
|
console.log();
|
|
350
|
-
console.log(" \x1B[
|
|
352
|
+
console.log(" \x1B[1m\u{1F9FE} Order Summary\x1B[0m");
|
|
351
353
|
for (const item of body.items) {
|
|
352
354
|
const url = item.product_url;
|
|
353
355
|
const qty = item.quantity ?? 1;
|
|
@@ -360,6 +362,7 @@ function displayOrderSummary(body) {
|
|
|
360
362
|
}
|
|
361
363
|
const addr = body.delivery_address;
|
|
362
364
|
console.log();
|
|
365
|
+
console.log(" \x1B[1m\u{1F4CD} Shipping\x1B[0m");
|
|
363
366
|
console.log(` Ship to: ${addr.first_name} ${addr.last_name}`);
|
|
364
367
|
console.log(` ${addr.address_line1}${addr.address_line2 ? `, ${addr.address_line2}` : ""}`);
|
|
365
368
|
console.log(` ${addr.city}, ${addr.state ?? ""} ${addr.postal_code} ${addr.country}`);
|
|
@@ -370,16 +373,16 @@ function displayOrderSummary(body) {
|
|
|
370
373
|
function displayOrderResult(order) {
|
|
371
374
|
console.log();
|
|
372
375
|
if (order.status === "failed") {
|
|
373
|
-
console.log(` \x1B[31m\
|
|
376
|
+
console.log(` \x1B[31m\u274C Order failed during submission.\x1B[0m`);
|
|
374
377
|
} else if (order.deduplicated) {
|
|
375
|
-
console.log(` \x1B[33m\
|
|
378
|
+
console.log(` \x1B[33m\u267B\uFE0F Reused existing order.\x1B[0m`);
|
|
376
379
|
} else {
|
|
377
|
-
console.log(` \x1B[32m\
|
|
380
|
+
console.log(` \x1B[32m\u2705 Order placed!\x1B[0m`);
|
|
378
381
|
}
|
|
379
382
|
console.log(` ID: \x1B[1m${order.id}\x1B[0m`);
|
|
380
383
|
console.log(` Status: ${order.status}`);
|
|
381
384
|
if (order.buyerToken) {
|
|
382
|
-
console.log(" Saved local access token for status and refund checks.");
|
|
385
|
+
console.log(" \u{1F510} Saved local access token for status and refund checks.");
|
|
383
386
|
}
|
|
384
387
|
console.log();
|
|
385
388
|
console.log(
|
|
@@ -390,7 +393,7 @@ function displayOrderResult(order) {
|
|
|
390
393
|
}
|
|
391
394
|
function displayStatus(purchase) {
|
|
392
395
|
console.log();
|
|
393
|
-
console.log(` \x1B[
|
|
396
|
+
console.log(` \x1B[1m\u{1F4E6} Order ${purchase.id}\x1B[0m`);
|
|
394
397
|
console.log(` Status: ${purchase.status}`);
|
|
395
398
|
if (purchase.items?.length) {
|
|
396
399
|
for (const item of purchase.items) {
|
|
@@ -414,7 +417,7 @@ function displayStatus(purchase) {
|
|
|
414
417
|
}
|
|
415
418
|
function displayRefund(refund2) {
|
|
416
419
|
console.log();
|
|
417
|
-
console.log(` \x1B[
|
|
420
|
+
console.log(` \x1B[1m\u{1F4B8} Refund ${refund2.id}\x1B[0m`);
|
|
418
421
|
console.log(` Status: ${refund2.status}`);
|
|
419
422
|
console.log(` Amount: ${formatCents(refund2.amountCents)}`);
|
|
420
423
|
console.log(` Reason: ${refund2.reason}`);
|
|
@@ -596,6 +599,13 @@ async function getBuyerToken(purchaseId) {
|
|
|
596
599
|
|
|
597
600
|
// src/cli/index.ts
|
|
598
601
|
var EMAIL_PATTERN = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
602
|
+
function parseTempoBalance(balance) {
|
|
603
|
+
const parsed = Number.parseFloat(balance ?? "0");
|
|
604
|
+
return Number.isFinite(parsed) ? parsed : 0;
|
|
605
|
+
}
|
|
606
|
+
function formatUsdcNumber(amount) {
|
|
607
|
+
return amount.toFixed(6).replace(/\.?0+$/, "");
|
|
608
|
+
}
|
|
599
609
|
async function runCommandCapture(command2, args2, envOverrides) {
|
|
600
610
|
return await new Promise((resolve, reject) => {
|
|
601
611
|
const child = spawn(command2, args2, {
|
|
@@ -672,6 +682,40 @@ async function ensureTempoReady() {
|
|
|
672
682
|
function formatUsdAmount(cents) {
|
|
673
683
|
return (cents / 100).toFixed(2);
|
|
674
684
|
}
|
|
685
|
+
async function ensureSufficientBalance(requiredCents, wallet) {
|
|
686
|
+
const required = Number.parseFloat(formatUsdAmount(requiredCents));
|
|
687
|
+
let available = parseTempoBalance(wallet.balance?.available);
|
|
688
|
+
if (available >= required) {
|
|
689
|
+
return wallet;
|
|
690
|
+
}
|
|
691
|
+
console.log();
|
|
692
|
+
console.log(" \x1B[1m\u{1F4B3} Balance Check\x1B[0m");
|
|
693
|
+
console.log(
|
|
694
|
+
` Tempo wallet balance is too low for this order: have ${formatUsdcNumber(available)} USDC, need ${formatUsdAmount(requiredCents)} USDC.`
|
|
695
|
+
);
|
|
696
|
+
console.log(` Shortfall: ${formatUsdcNumber(required - available)} USDC`);
|
|
697
|
+
const fundNow = await promptConfirm("Open Tempo funding flow now?");
|
|
698
|
+
if (!fundNow) {
|
|
699
|
+
throw new Error(
|
|
700
|
+
`Insufficient USDC balance: have ${formatUsdcNumber(available)}, need ${formatUsdAmount(requiredCents)}.`
|
|
701
|
+
);
|
|
702
|
+
}
|
|
703
|
+
const fundCode = await runInteractiveCommand("tempo", ["wallet", "fund"]);
|
|
704
|
+
if (fundCode !== 0) {
|
|
705
|
+
throw new Error("Tempo wallet funding was cancelled.");
|
|
706
|
+
}
|
|
707
|
+
const refreshed = await ensureTempoReady();
|
|
708
|
+
available = parseTempoBalance(refreshed.balance?.available);
|
|
709
|
+
if (available < required) {
|
|
710
|
+
throw new Error(
|
|
711
|
+
`Still not enough USDC after funding: have ${formatUsdcNumber(available)}, need ${formatUsdAmount(requiredCents)}.`
|
|
712
|
+
);
|
|
713
|
+
}
|
|
714
|
+
console.log(
|
|
715
|
+
` Funding complete. New balance: ${formatUsdcNumber(available)} ${refreshed.balance?.symbol ?? "USDC"}`
|
|
716
|
+
);
|
|
717
|
+
return refreshed;
|
|
718
|
+
}
|
|
675
719
|
async function createPurchaseWithTempo(body) {
|
|
676
720
|
const totalChargeCents = body.max_budget + SERVICE_FEE_CENTS;
|
|
677
721
|
const result = await runCommandCapture(
|
|
@@ -690,7 +734,15 @@ async function createPurchaseWithTempo(body) {
|
|
|
690
734
|
}
|
|
691
735
|
);
|
|
692
736
|
if (result.code !== 0) {
|
|
693
|
-
const
|
|
737
|
+
const raw = result.stderr.trim() || result.stdout.trim();
|
|
738
|
+
const payload = raw ? (() => {
|
|
739
|
+
try {
|
|
740
|
+
return JSON.parse(raw);
|
|
741
|
+
} catch {
|
|
742
|
+
return null;
|
|
743
|
+
}
|
|
744
|
+
})() : null;
|
|
745
|
+
const message = (payload?.message ?? raw) || "Tempo request failed";
|
|
694
746
|
throw new Error(message);
|
|
695
747
|
}
|
|
696
748
|
try {
|
|
@@ -702,7 +754,7 @@ async function createPurchaseWithTempo(body) {
|
|
|
702
754
|
async function buy(urlArg) {
|
|
703
755
|
try {
|
|
704
756
|
console.log();
|
|
705
|
-
console.log(" \x1B[
|
|
757
|
+
console.log(" \x1B[1m\u{1F6D2} agentmall\x1B[0m \u2014 Buy anything with a URL");
|
|
706
758
|
console.log();
|
|
707
759
|
const url = urlArg ?? await promptProductUrl();
|
|
708
760
|
const client = new AgentMall();
|
|
@@ -740,7 +792,11 @@ async function buy(urlArg) {
|
|
|
740
792
|
console.log(" Cancelled.");
|
|
741
793
|
return;
|
|
742
794
|
}
|
|
743
|
-
const
|
|
795
|
+
const totalChargeCents = maxBudget + SERVICE_FEE_CENTS;
|
|
796
|
+
const wallet = await ensureSufficientBalance(
|
|
797
|
+
totalChargeCents,
|
|
798
|
+
await ensureTempoReady()
|
|
799
|
+
);
|
|
744
800
|
if (wallet.wallet) {
|
|
745
801
|
const balance = wallet.balance?.available ? `, balance ${wallet.balance.available} ${wallet.balance?.symbol ?? "USDC"}` : "";
|
|
746
802
|
console.log(` Paying with Tempo wallet ${wallet.wallet}${balance}`);
|
|
@@ -773,6 +829,11 @@ async function buy(urlArg) {
|
|
|
773
829
|
process.exitCode = 1;
|
|
774
830
|
return;
|
|
775
831
|
}
|
|
832
|
+
if (error instanceof Error) {
|
|
833
|
+
console.error(` \x1B[31mError:\x1B[0m ${error.message}`);
|
|
834
|
+
process.exitCode = 1;
|
|
835
|
+
return;
|
|
836
|
+
}
|
|
776
837
|
throw error;
|
|
777
838
|
}
|
|
778
839
|
}
|
|
@@ -804,7 +865,7 @@ async function refund(purchaseId) {
|
|
|
804
865
|
}
|
|
805
866
|
async function onboard() {
|
|
806
867
|
console.log();
|
|
807
|
-
console.log(" \x1B[
|
|
868
|
+
console.log(" \x1B[1m\u{1F511} agentmall onboarding\x1B[0m");
|
|
808
869
|
console.log();
|
|
809
870
|
const wallet = await ensureTempoReady();
|
|
810
871
|
console.log();
|
|
@@ -870,15 +931,15 @@ async function main() {
|
|
|
870
931
|
}
|
|
871
932
|
function printHelp() {
|
|
872
933
|
console.log(`
|
|
873
|
-
\x1B[
|
|
934
|
+
\x1B[1m\u{1F6D2} agentmall\x1B[0m \u2014 Buy anything with a URL
|
|
874
935
|
|
|
875
936
|
Usage:
|
|
876
|
-
agentmall onboard
|
|
877
|
-
agentmall [url]
|
|
878
|
-
agentmall buy <url>
|
|
879
|
-
agentmall status <id>
|
|
880
|
-
agentmall refund <id>
|
|
881
|
-
agentmall help
|
|
937
|
+
\u{1F511} agentmall onboard Log in to Tempo and show wallet funding steps
|
|
938
|
+
\u{1F6CD}\uFE0F agentmall [url] Buy a product (interactive)
|
|
939
|
+
\u{1F6CD}\uFE0F agentmall buy <url> Buy a product
|
|
940
|
+
\u{1F4E6} agentmall status <id> Check order status using the saved buyer token
|
|
941
|
+
\u{1F4B8} agentmall refund <id> Check refund status using the saved buyer token
|
|
942
|
+
\u2753 agentmall help Show this help
|
|
882
943
|
`);
|
|
883
944
|
}
|
|
884
945
|
main();
|