@heyamiko/amiko-cli 0.9.9-beta.6 → 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.
Files changed (3) hide show
  1. package/README.md +32 -1
  2. package/dist/index.js +74 -3
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # @heyamiko/amiko-cli (v0.9.7)
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,37 @@ 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
+
400
+ ### 0.9.9-beta.7
401
+
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.
403
+
404
+ ### 0.9.9-beta.6
405
+
406
+ - Code-review followups across `friends`, `image`, `memory`, and the friend-report payment lib: explicit allowlists for `--size`/`--quality`/`--format`/`--background` on `markets image` (rejects unknown values before charging), `auto` quality maps to `high` for billing so we never under-bill, `memory` uses `lstatSync` + `path.relative` to skip symlinks and stop relying on string `startsWith` for sandboxing, and the friends-report transfer body now sets `chain: "solana"` explicitly.
407
+
408
+ ### 0.9.9-beta.5
409
+
410
+ - `amiko friends reports request --pay` — pays the AMIKO friend-report fee from the agent's Crossmint-custodied Solana wallet (no keys held in CLI). Two-step flow: `amiko-web /transfer` signs the AMIKO charge to treasury, then `mpp-service /v1/friend-reports/generate` is called with `X-Payment-Tx`. Confirm prompt shows the exact AMIKO amount quoted from the live spot price.
411
+ - `--json` output for friends-report includes `txHash` + `amikoAmount` payment metadata.
412
+ - `did:privy:` prefix is stripped from user ids before the mpp call so amiko-web's `User` table lookup matches.
413
+ - `markets image` pricing is now dynamic: charges OpenAI pass-through × 1.30 markup per model/quality/size, quoted in AMIKO from live `AMIKO/USD`. Confirm prompt shows the exact amount before any transfer.
414
+ - Imports `Mppx` + Solana helpers from `@solana/mpp/client` subpath (root barrel only re-exports `charge`).
415
+
416
+ ### 0.9.9-beta.1 → 0.9.9-beta.4
417
+
418
+ - `amiko memory add | list | search | rm | status | sync` — manage the twin's persistent memory store from the CLI.
419
+ - `memory sync` now also walks `<workspace>/memory/` so memory written next to your project files gets picked up.
420
+ - `SKILL.md` documents the memory commands and biases agents toward calling `memory search` before falling back to other context-discovery flows.
421
+
422
+ ### 0.9.8
423
+
424
+ - `SKILL.md` defaults `platform=Amiko` and steers agents away from `sessions_*` lookups.
425
+
395
426
  ### 0.9.7
396
427
 
397
428
  - `composio connect` is now idempotent by default. Previously the CLI sent `forceReconnect: true` whenever `--force` was omitted, which caused every status probe to tear down the active Composio connection. The new default is `forceReconnect: false`: if the toolkit is already connected, the call returns `{ alreadyConnected: true }` without touching the connection. Pass `--force` explicitly to opt into a destructive reconnect.
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 user ${args.id} (signed by your agent's wallet via amiko-web)`,
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
  });
@@ -27596,12 +27659,20 @@ function registerFriendsCommand(program2) {
27596
27659
  }
27597
27660
  console.log(heading(`Friends (${items.length})`));
27598
27661
  const rows = [
27599
- [dim("ID"), dim("NAME"), dim("HANDLE"), dim("TYPE"), dim("SINCE")],
27662
+ [
27663
+ dim("USER ID"),
27664
+ dim("NAME"),
27665
+ dim("HANDLE"),
27666
+ dim("TYPE"),
27667
+ dim("FRIENDSHIP"),
27668
+ dim("SINCE")
27669
+ ],
27600
27670
  ...items.map((f) => [
27601
- f.friendship_id,
27671
+ f.friend.id,
27602
27672
  f.friend.name ?? "-",
27603
27673
  f.friend.handle ?? "-",
27604
27674
  f.friend.type,
27675
+ f.friendship_id,
27605
27676
  f.since?.slice(0, 10) ?? "-"
27606
27677
  ])
27607
27678
  ];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@heyamiko/amiko-cli",
3
- "version": "0.9.9-beta.6",
3
+ "version": "0.9.9-beta.8",
4
4
  "description": "Amiko CLI — swap tokens, manage credits, bridge cross-chain, and call marketplace agents",
5
5
  "type": "module",
6
6
  "bin": {