@heyamiko/amiko-cli 0.9.9-beta.7 → 0.9.9-beta.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/README.md +6 -1
- package/dist/index.js +64 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# @heyamiko/amiko-cli (v0.9.9-beta.
|
|
1
|
+
# @heyamiko/amiko-cli (v0.9.9-beta.8)
|
|
2
2
|
|
|
3
3
|
Manage wallets, credits, swaps, MPP marketplace services, and your Amiko twin (identity, documents, voice, avatar, friends, feed, Composio apps) from the terminal. Works for both human users and AI agents running on OpenClaw.
|
|
4
4
|
|
|
@@ -392,6 +392,11 @@ npm publish
|
|
|
392
392
|
|
|
393
393
|
## Changelog
|
|
394
394
|
|
|
395
|
+
### 0.9.9-beta.8
|
|
396
|
+
|
|
397
|
+
- `friends reports request --pay` now does a **free preflight** (`POST /v1/friend-reports/preflight`) before signing the on-chain AMIKO transfer. Validates User → Friendship → consent → personality profile against amiko-web. If anything's wrong (wrong id shape, missing consent, missing profile), the CLI aborts with a targeted tip — no AMIKO is transferred. Closes a hole where every retry against a bad `--id` burned ~3 AMIKO via the irreversible X-Payment-Tx flow.
|
|
398
|
+
- Confirm prompt now resolves and shows the respondent's name and User.id (e.g. `Pay X AMIKO to regenerate a friend report with Matthew Graham (cmjz...) via friendship cmnlj...`) so a human can spot a wrong-person mistake before approval.
|
|
399
|
+
|
|
395
400
|
### 0.9.9-beta.7
|
|
396
401
|
|
|
397
402
|
- `amiko friends list` table now shows the friend's `User.id` as the primary `USER ID` column (what `friends reports request`, `matches`, etc. all need) and surfaces `friendship_id` as a separate `FRIENDSHIP` column (used by `friends accept/remove`). Mirrors how amiko-web's UI separates the two ids: person actions take `actor.id`, row actions take `friendship_id`. JSON output unchanged. Fixes a 404 from `/api/internal/friend-reports/regenerate` when an agent fed the friendship row id back as `--id` for a paid report.
|
package/dist/index.js
CHANGED
|
@@ -27404,6 +27404,40 @@ async function quoteFriendReport(auth) {
|
|
|
27404
27404
|
usdAnchor: PRICE_USD
|
|
27405
27405
|
};
|
|
27406
27406
|
}
|
|
27407
|
+
async function preflightFriendReport(body) {
|
|
27408
|
+
const config2 = loadConfig();
|
|
27409
|
+
const mppBase2 = config2.apiBase.replace(/\/$/, "");
|
|
27410
|
+
const stripDidPrivy = (id) => id.startsWith("did:privy:") ? id.replace("did:privy:", "") : id;
|
|
27411
|
+
const normalizedBody = {
|
|
27412
|
+
...body,
|
|
27413
|
+
initiator_user_id: stripDidPrivy(body.initiator_user_id),
|
|
27414
|
+
respondent_user_id: stripDidPrivy(body.respondent_user_id)
|
|
27415
|
+
};
|
|
27416
|
+
try {
|
|
27417
|
+
const res = await fetch(`${mppBase2}/v1/friend-reports/preflight`, {
|
|
27418
|
+
method: "POST",
|
|
27419
|
+
headers: { "Content-Type": "application/json" },
|
|
27420
|
+
body: JSON.stringify(normalizedBody)
|
|
27421
|
+
});
|
|
27422
|
+
const data = await res.json().catch(() => ({}));
|
|
27423
|
+
if (res.ok && data.ok === true) {
|
|
27424
|
+
return data;
|
|
27425
|
+
}
|
|
27426
|
+
return {
|
|
27427
|
+
ok: false,
|
|
27428
|
+
status: res.status,
|
|
27429
|
+
error: (typeof data.error === "string" ? data.error : null) ?? `preflight returned ${res.status}`,
|
|
27430
|
+
body: data
|
|
27431
|
+
};
|
|
27432
|
+
} catch (err) {
|
|
27433
|
+
return {
|
|
27434
|
+
ok: false,
|
|
27435
|
+
status: 0,
|
|
27436
|
+
error: err instanceof Error ? err.message : "preflight fetch failed",
|
|
27437
|
+
body: {}
|
|
27438
|
+
};
|
|
27439
|
+
}
|
|
27440
|
+
}
|
|
27407
27441
|
async function mppFriendReportGenerate(auth, body, opts = {}) {
|
|
27408
27442
|
const config2 = loadConfig();
|
|
27409
27443
|
const mppBase2 = config2.apiBase.replace(/\/$/, "");
|
|
@@ -27513,10 +27547,39 @@ async function runPaidRegenerate(args) {
|
|
|
27513
27547
|
console.error(error("Paid regenerate requires your user id. Add 'amikoUserId' to your .amiko.json (alongside amikoTwinToken/amikoTwinId)."));
|
|
27514
27548
|
process.exit(1);
|
|
27515
27549
|
}
|
|
27550
|
+
const preflightSpinner = args.json ? null : ora("Validating request (no charge)...").start();
|
|
27551
|
+
const preflight = await preflightFriendReport({
|
|
27552
|
+
report_type: args.type,
|
|
27553
|
+
initiator_user_id: auth.userId,
|
|
27554
|
+
respondent_user_id: args.id
|
|
27555
|
+
});
|
|
27556
|
+
preflightSpinner?.stop();
|
|
27557
|
+
if (!preflight.ok) {
|
|
27558
|
+
if (args.json) {
|
|
27559
|
+
console.log(JSON.stringify({
|
|
27560
|
+
ok: false,
|
|
27561
|
+
stage: "preflight",
|
|
27562
|
+
status: preflight.status,
|
|
27563
|
+
error: preflight.error,
|
|
27564
|
+
body: preflight.body
|
|
27565
|
+
}, null, 2));
|
|
27566
|
+
} else {
|
|
27567
|
+
console.error(error(`Preflight failed (HTTP ${preflight.status}): ${preflight.error}`));
|
|
27568
|
+
if (preflight.status === 404) {
|
|
27569
|
+
console.error(dim("Tip: did you pass a friendship_id where a User.id was expected? " + "Run 'amiko friends list --json' and use the friend.id field, not friendship_id."));
|
|
27570
|
+
} else if (preflight.status === 403) {
|
|
27571
|
+
console.error(dim("Tip: consent must already be granted by both users for this report_type. " + "Run 'amiko friends reports request --id <user> --type <type>' (without --pay), " + "wait for accept, then retry with --pay."));
|
|
27572
|
+
} else if (preflight.status === 422) {
|
|
27573
|
+
console.error(dim("Tip: at least one user is missing a personality profile. " + "Both users must have completed onboarding."));
|
|
27574
|
+
}
|
|
27575
|
+
}
|
|
27576
|
+
process.exit(1);
|
|
27577
|
+
}
|
|
27516
27578
|
const quote = await quoteFriendReport(auth);
|
|
27517
27579
|
const priceLine = "error" in quote ? "(price oracle down — actual amount computed at server)" : `${quote.amikoAmount} AMIKO ≈ $${quote.usdAnchor} (1 AMIKO = $${quote.amikoUsd.toFixed(4)})`;
|
|
27580
|
+
const respondentLabel = preflight.respondent.name ? `${preflight.respondent.name} (${preflight.respondent.id})` : preflight.respondent.id;
|
|
27518
27581
|
await confirmDestructive({
|
|
27519
|
-
action: `Pay ${priceLine} to regenerate a ${args.type} matching report with
|
|
27582
|
+
action: `Pay ${priceLine} to regenerate a ${args.type} matching report with ${respondentLabel} via friendship ${preflight.friendship_id} (signed by your agent's wallet)`,
|
|
27520
27583
|
yes: args.yes,
|
|
27521
27584
|
commandExample: `amiko friends reports request --id ${args.id} --type ${args.type} --pay`
|
|
27522
27585
|
});
|