@heyamiko/amiko-cli 0.9.9-beta.5 → 0.9.9-beta.7
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 +27 -1
- package/dist/index.js +67 -12
- 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.7)
|
|
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,32 @@ npm publish
|
|
|
392
392
|
|
|
393
393
|
## Changelog
|
|
394
394
|
|
|
395
|
+
### 0.9.9-beta.7
|
|
396
|
+
|
|
397
|
+
- `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.
|
|
398
|
+
|
|
399
|
+
### 0.9.9-beta.6
|
|
400
|
+
|
|
401
|
+
- 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.
|
|
402
|
+
|
|
403
|
+
### 0.9.9-beta.5
|
|
404
|
+
|
|
405
|
+
- `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.
|
|
406
|
+
- `--json` output for friends-report includes `txHash` + `amikoAmount` payment metadata.
|
|
407
|
+
- `did:privy:` prefix is stripped from user ids before the mpp call so amiko-web's `User` table lookup matches.
|
|
408
|
+
- `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.
|
|
409
|
+
- Imports `Mppx` + Solana helpers from `@solana/mpp/client` subpath (root barrel only re-exports `charge`).
|
|
410
|
+
|
|
411
|
+
### 0.9.9-beta.1 → 0.9.9-beta.4
|
|
412
|
+
|
|
413
|
+
- `amiko memory add | list | search | rm | status | sync` — manage the twin's persistent memory store from the CLI.
|
|
414
|
+
- `memory sync` now also walks `<workspace>/memory/` so memory written next to your project files gets picked up.
|
|
415
|
+
- `SKILL.md` documents the memory commands and biases agents toward calling `memory search` before falling back to other context-discovery flows.
|
|
416
|
+
|
|
417
|
+
### 0.9.8
|
|
418
|
+
|
|
419
|
+
- `SKILL.md` defaults `platform=Amiko` and steers agents away from `sessions_*` lookups.
|
|
420
|
+
|
|
395
421
|
### 0.9.7
|
|
396
422
|
|
|
397
423
|
- `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
|
@@ -26283,8 +26283,29 @@ function registerImageCommand(program2) {
|
|
|
26283
26283
|
console.error(error(`Unknown model "${opts.model}". Supported: ${SUPPORTED_MODELS.join(", ")}.`));
|
|
26284
26284
|
process.exit(1);
|
|
26285
26285
|
}
|
|
26286
|
+
const ALLOWED_SIZES = ["1024x1024", "1024x1536", "1536x1024"];
|
|
26287
|
+
const ALLOWED_QUALITIES = ["low", "medium", "high", "auto"];
|
|
26288
|
+
const ALLOWED_FORMATS = ["png", "webp", "jpeg"];
|
|
26289
|
+
const ALLOWED_BACKGROUNDS = ["transparent", "opaque", "auto"];
|
|
26290
|
+
if (!ALLOWED_SIZES.includes(opts.size)) {
|
|
26291
|
+
console.error(error(`Unknown --size "${opts.size}". Allowed: ${ALLOWED_SIZES.join(", ")}.`));
|
|
26292
|
+
process.exit(1);
|
|
26293
|
+
}
|
|
26294
|
+
if (!ALLOWED_QUALITIES.includes(opts.quality)) {
|
|
26295
|
+
console.error(error(`Unknown --quality "${opts.quality}". Allowed: ${ALLOWED_QUALITIES.join(", ")}.`));
|
|
26296
|
+
process.exit(1);
|
|
26297
|
+
}
|
|
26298
|
+
if (opts.format && !ALLOWED_FORMATS.includes(opts.format)) {
|
|
26299
|
+
console.error(error(`Unknown --format "${opts.format}". Allowed: ${ALLOWED_FORMATS.join(", ")}.`));
|
|
26300
|
+
process.exit(1);
|
|
26301
|
+
}
|
|
26302
|
+
if (opts.background && !ALLOWED_BACKGROUNDS.includes(opts.background)) {
|
|
26303
|
+
console.error(error(`Unknown --background "${opts.background}". Allowed: ${ALLOWED_BACKGROUNDS.join(", ")}.`));
|
|
26304
|
+
process.exit(1);
|
|
26305
|
+
}
|
|
26306
|
+
const billedQuality = opts.quality === "auto" ? "high" : opts.quality;
|
|
26286
26307
|
const n = Math.max(1, Math.min(Math.floor(Number(opts.n) || 1), 4));
|
|
26287
|
-
const usdCost = computeImageUsd(opts.model,
|
|
26308
|
+
const usdCost = computeImageUsd(opts.model, billedQuality, opts.size, n);
|
|
26288
26309
|
let auth;
|
|
26289
26310
|
try {
|
|
26290
26311
|
auth = requireAuth();
|
|
@@ -27372,6 +27393,17 @@ function registerAvatarCommand(program2) {
|
|
|
27372
27393
|
// src/lib/mpp-friend-report.ts
|
|
27373
27394
|
var AMIKO_TREASURY = "FPiZAf3jEnNfCwfvbv46jdPfHbmSepD4Q6iHiLJDQXvb";
|
|
27374
27395
|
var PRICE_USD = "0.10";
|
|
27396
|
+
async function quoteFriendReport(auth) {
|
|
27397
|
+
const amikoUsd = await getTokenUsdPrice(auth, "AMIKO");
|
|
27398
|
+
if (!amikoUsd || amikoUsd <= 0) {
|
|
27399
|
+
return { error: "Failed to fetch AMIKO/USD price" };
|
|
27400
|
+
}
|
|
27401
|
+
return {
|
|
27402
|
+
amikoAmount: (Number(PRICE_USD) / amikoUsd).toFixed(6),
|
|
27403
|
+
amikoUsd,
|
|
27404
|
+
usdAnchor: PRICE_USD
|
|
27405
|
+
};
|
|
27406
|
+
}
|
|
27375
27407
|
async function mppFriendReportGenerate(auth, body, opts = {}) {
|
|
27376
27408
|
const config2 = loadConfig();
|
|
27377
27409
|
const mppBase2 = config2.apiBase.replace(/\/$/, "");
|
|
@@ -27407,7 +27439,8 @@ async function mppFriendReportGenerate(auth, body, opts = {}) {
|
|
|
27407
27439
|
body: {
|
|
27408
27440
|
to: AMIKO_TREASURY,
|
|
27409
27441
|
amount: amikoAmount,
|
|
27410
|
-
token: "AMIKO"
|
|
27442
|
+
token: "AMIKO",
|
|
27443
|
+
chain: "solana"
|
|
27411
27444
|
}
|
|
27412
27445
|
});
|
|
27413
27446
|
const candidate = transferData.txHash ?? transferData.tx_hash ?? transferData.signature;
|
|
@@ -27480,8 +27513,10 @@ async function runPaidRegenerate(args) {
|
|
|
27480
27513
|
console.error(error("Paid regenerate requires your user id. Add 'amikoUserId' to your .amiko.json (alongside amikoTwinToken/amikoTwinId)."));
|
|
27481
27514
|
process.exit(1);
|
|
27482
27515
|
}
|
|
27516
|
+
const quote = await quoteFriendReport(auth);
|
|
27517
|
+
const priceLine = "error" in quote ? "(price oracle down — actual amount computed at server)" : `${quote.amikoAmount} AMIKO ≈ $${quote.usdAnchor} (1 AMIKO = $${quote.amikoUsd.toFixed(4)})`;
|
|
27483
27518
|
await confirmDestructive({
|
|
27484
|
-
action: `Pay
|
|
27519
|
+
action: `Pay ${priceLine} to regenerate a ${args.type} matching report with user ${args.id} (signed by your agent's wallet via amiko-web)`,
|
|
27485
27520
|
yes: args.yes,
|
|
27486
27521
|
commandExample: `amiko friends reports request --id ${args.id} --type ${args.type} --pay`
|
|
27487
27522
|
});
|
|
@@ -27561,12 +27596,20 @@ function registerFriendsCommand(program2) {
|
|
|
27561
27596
|
}
|
|
27562
27597
|
console.log(heading(`Friends (${items.length})`));
|
|
27563
27598
|
const rows = [
|
|
27564
|
-
[
|
|
27599
|
+
[
|
|
27600
|
+
dim("USER ID"),
|
|
27601
|
+
dim("NAME"),
|
|
27602
|
+
dim("HANDLE"),
|
|
27603
|
+
dim("TYPE"),
|
|
27604
|
+
dim("FRIENDSHIP"),
|
|
27605
|
+
dim("SINCE")
|
|
27606
|
+
],
|
|
27565
27607
|
...items.map((f) => [
|
|
27566
|
-
f.
|
|
27608
|
+
f.friend.id,
|
|
27567
27609
|
f.friend.name ?? "-",
|
|
27568
27610
|
f.friend.handle ?? "-",
|
|
27569
27611
|
f.friend.type,
|
|
27612
|
+
f.friendship_id,
|
|
27570
27613
|
f.since?.slice(0, 10) ?? "-"
|
|
27571
27614
|
])
|
|
27572
27615
|
];
|
|
@@ -27671,6 +27714,7 @@ Accept with: amiko friends accept <friendshipId>`));
|
|
|
27671
27714
|
const reports = program2.command("reports").description("Friend matching reports");
|
|
27672
27715
|
reports.command("list").description("List friend matching reports").option("--page <n>", "Page number", "1").option("--limit <n>", "Page size (1-50)", "20").option("--json", "Output as JSON").action(async (opts) => {
|
|
27673
27716
|
const auth = resolveAuth();
|
|
27717
|
+
const meId = (auth.userId ?? "").replace(/^did:privy:/, "");
|
|
27674
27718
|
const spinner = opts.json ? null : ora("Loading reports...").start();
|
|
27675
27719
|
try {
|
|
27676
27720
|
const data = await amikoWebFetch(auth, "/api/friends/reports", {
|
|
@@ -27694,7 +27738,7 @@ Accept with: amiko friends accept <friendshipId>`));
|
|
|
27694
27738
|
dim("CREATED")
|
|
27695
27739
|
],
|
|
27696
27740
|
...items.map((r) => {
|
|
27697
|
-
const other = r.respondent ?? r.initiator;
|
|
27741
|
+
const other = r.initiator?.id === meId ? r.respondent : r.respondent?.id === meId ? r.initiator : r.respondent ?? r.initiator;
|
|
27698
27742
|
return [
|
|
27699
27743
|
r.id,
|
|
27700
27744
|
r.report_type ?? "-",
|
|
@@ -27715,6 +27759,7 @@ Accept with: amiko friends accept <friendshipId>`));
|
|
|
27715
27759
|
});
|
|
27716
27760
|
reports.command("view <id>").description("View a friend matching report").option("--json", "Output as JSON").action(async (id, opts) => {
|
|
27717
27761
|
const auth = resolveAuth();
|
|
27762
|
+
const meId = (auth.userId ?? "").replace(/^did:privy:/, "");
|
|
27718
27763
|
const spinner = opts.json ? null : ora("Loading report...").start();
|
|
27719
27764
|
try {
|
|
27720
27765
|
const data = await amikoWebFetch(auth, `/api/friends/reports/${encodeURIComponent(id)}`);
|
|
@@ -27726,7 +27771,7 @@ Accept with: amiko friends accept <friendshipId>`));
|
|
|
27726
27771
|
console.log(label("Type", r.report_type));
|
|
27727
27772
|
if (r.status)
|
|
27728
27773
|
console.log(label("Status", r.status));
|
|
27729
|
-
const other = r.respondent ?? r.initiator;
|
|
27774
|
+
const other = r.initiator?.id === meId ? r.respondent : r.respondent?.id === meId ? r.initiator : r.respondent ?? r.initiator;
|
|
27730
27775
|
if (other)
|
|
27731
27776
|
console.log(label("With", other.name ?? other.handle ?? other.id));
|
|
27732
27777
|
if (r.created_at)
|
|
@@ -28599,8 +28644,12 @@ function registerNotificationsCommand(program2) {
|
|
|
28599
28644
|
}
|
|
28600
28645
|
|
|
28601
28646
|
// src/commands/memory.ts
|
|
28602
|
-
import { existsSync as existsSync3, readdirSync, readFileSync as readFileSync2, statSync } from "node:fs";
|
|
28603
|
-
import { dirname, isAbsolute, normalize, resolve as resolve2 } from "node:path";
|
|
28647
|
+
import { existsSync as existsSync3, lstatSync, readdirSync, readFileSync as readFileSync2, statSync } from "node:fs";
|
|
28648
|
+
import { dirname, isAbsolute, normalize, relative, resolve as resolve2 } from "node:path";
|
|
28649
|
+
function isInsideRoot(abs, root) {
|
|
28650
|
+
const rel = relative(root, abs);
|
|
28651
|
+
return rel !== "" && !rel.startsWith("..") && !isAbsolute(rel);
|
|
28652
|
+
}
|
|
28604
28653
|
var VALID_CATEGORIES = ["fact", "preference", "pattern", "decision", "context"];
|
|
28605
28654
|
var VALID_SOURCES = ["chat", "file", "manual"];
|
|
28606
28655
|
var DEFAULT_WORKSPACE = "/data/.openclaw/workspace";
|
|
@@ -28878,7 +28927,7 @@ function collectMemoryFiles(root, indexPaths, memoryDir) {
|
|
|
28878
28927
|
if (isExternal(ref))
|
|
28879
28928
|
continue;
|
|
28880
28929
|
const abs = normalize(isAbsolute(ref) ? ref : resolve2(indexDir, ref));
|
|
28881
|
-
if (!abs
|
|
28930
|
+
if (!isInsideRoot(abs, root)) {
|
|
28882
28931
|
errors3.push(`Skipping ${ref}: outside workspace ${root}`);
|
|
28883
28932
|
continue;
|
|
28884
28933
|
}
|
|
@@ -28886,7 +28935,11 @@ function collectMemoryFiles(root, indexPaths, memoryDir) {
|
|
|
28886
28935
|
errors3.push(`Referenced file missing: ${ref}`);
|
|
28887
28936
|
continue;
|
|
28888
28937
|
}
|
|
28889
|
-
const st =
|
|
28938
|
+
const st = lstatSync(abs);
|
|
28939
|
+
if (st.isSymbolicLink()) {
|
|
28940
|
+
errors3.push(`Skipping ${ref}: symlinks not followed`);
|
|
28941
|
+
continue;
|
|
28942
|
+
}
|
|
28890
28943
|
if (!st.isFile())
|
|
28891
28944
|
continue;
|
|
28892
28945
|
const content = safeRead(abs, errors3);
|
|
@@ -28918,10 +28971,12 @@ function walkMarkdown(dir, errors3) {
|
|
|
28918
28971
|
const abs = resolve2(dir, name);
|
|
28919
28972
|
let st;
|
|
28920
28973
|
try {
|
|
28921
|
-
st =
|
|
28974
|
+
st = lstatSync(abs);
|
|
28922
28975
|
} catch {
|
|
28923
28976
|
continue;
|
|
28924
28977
|
}
|
|
28978
|
+
if (st.isSymbolicLink())
|
|
28979
|
+
continue;
|
|
28925
28980
|
if (st.isDirectory()) {
|
|
28926
28981
|
out.push(...walkMarkdown(abs, errors3));
|
|
28927
28982
|
} else if (st.isFile() && name.toLowerCase().endsWith(".md")) {
|