@heyamiko/amiko-cli 0.9.3 → 0.9.5

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 CHANGED
@@ -138,7 +138,7 @@ amiko wallets swap send 0.5 USDC AMIKO --yes
138
138
  amiko wallets swap send 100 AMIKO SOL --slippage 100
139
139
  ```
140
140
 
141
- Swaps execute via Jupiter on Solana. Supports SOL, USDC, USDT, AMIKO, PYUSD, BONK, JUP, RAY, JitoSOL, mSOL, or any mint address. `swap send` is hard-gated: in a non-interactive shell you must pass `--yes` after quoting the cost to the user (`Solana gas + 10bps platform fee`).
141
+ Swaps execute via Jupiter on Solana. Supports SOL, USDC, USDT, AMIKO, PYUSD, BONK, JUP, RAY, JitoSOL, mSOL, or any mint address. `swap send` is hard-gated: in a non-interactive shell you must pass `--yes` after quoting the cost to the user (`Solana gas + Jupiter referral fee`).
142
142
 
143
143
  ## Bridge
144
144
 
@@ -197,7 +197,7 @@ Every paid / value-moving command (`image`, `search`, `amazon search`, `service
197
197
  amiko markets image "a sunset over mountains" --yes
198
198
  ```
199
199
 
200
- This makes cost confirmation effectively mandatory regardless of which model drives the agent — weak models can no longer silently burn tokens by ignoring the skill docs. The same refusal fires for `swap send` (Solana gas + 10 bps platform fee) and `bridge send` (Across fee + gas), so an agent cannot move tokens without a round-trip through user approval.
200
+ This makes cost confirmation effectively mandatory regardless of which model drives the agent — weak models can no longer silently burn tokens by ignoring the skill docs. The same refusal fires for `swap send` (Solana gas + Jupiter referral fee) and `bridge send` (Across fee + gas), so an agent cannot move tokens without a round-trip through user approval.
201
201
 
202
202
  ## Error Output
203
203
 
package/dist/index.js CHANGED
@@ -5,25 +5,43 @@ var __getProtoOf = Object.getPrototypeOf;
5
5
  var __defProp = Object.defineProperty;
6
6
  var __getOwnPropNames = Object.getOwnPropertyNames;
7
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ function __accessProp(key) {
9
+ return this[key];
10
+ }
11
+ var __toESMCache_node;
12
+ var __toESMCache_esm;
8
13
  var __toESM = (mod, isNodeMode, target) => {
14
+ var canCache = mod != null && typeof mod === "object";
15
+ if (canCache) {
16
+ var cache = isNodeMode ? __toESMCache_node ??= new WeakMap : __toESMCache_esm ??= new WeakMap;
17
+ var cached = cache.get(mod);
18
+ if (cached)
19
+ return cached;
20
+ }
9
21
  target = mod != null ? __create(__getProtoOf(mod)) : {};
10
22
  const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
11
23
  for (let key of __getOwnPropNames(mod))
12
24
  if (!__hasOwnProp.call(to, key))
13
25
  __defProp(to, key, {
14
- get: () => mod[key],
26
+ get: __accessProp.bind(mod, key),
15
27
  enumerable: true
16
28
  });
29
+ if (canCache)
30
+ cache.set(mod, to);
17
31
  return to;
18
32
  };
19
33
  var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
34
+ var __returnValue = (v) => v;
35
+ function __exportSetter(name, newValue) {
36
+ this[name] = __returnValue.bind(null, newValue);
37
+ }
20
38
  var __export = (target, all) => {
21
39
  for (var name in all)
22
40
  __defProp(target, name, {
23
41
  get: all[name],
24
42
  enumerable: true,
25
43
  configurable: true,
26
- set: (newValue) => all[name] = () => newValue
44
+ set: __exportSetter.bind(all, name)
27
45
  });
28
46
  };
29
47
  var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
@@ -3515,11 +3533,36 @@ var require_emoji_regex = __commonJS((exports, module) => {
3515
3533
  };
3516
3534
  });
3517
3535
 
3518
- // node_modules/mppx/dist/BodyDigest.js
3519
- var init_BodyDigest = () => {};
3520
-
3521
- // node_modules/mppx/dist/PaymentRequest.js
3522
- var init_PaymentRequest = () => {};
3536
+ // node_modules/mppx/dist/Method.js
3537
+ var exports_Method = {};
3538
+ __export(exports_Method, {
3539
+ toServer: () => toServer,
3540
+ toClient: () => toClient,
3541
+ from: () => from
3542
+ });
3543
+ function from(method) {
3544
+ return method;
3545
+ }
3546
+ function toClient(method, options) {
3547
+ const { context, createCredential } = options;
3548
+ return {
3549
+ ...method,
3550
+ context,
3551
+ createCredential
3552
+ };
3553
+ }
3554
+ function toServer(method, options) {
3555
+ const { defaults, html, request, respond, transport, verify } = options;
3556
+ return {
3557
+ ...method,
3558
+ defaults,
3559
+ html,
3560
+ request,
3561
+ respond,
3562
+ transport,
3563
+ verify
3564
+ };
3565
+ }
3523
3566
 
3524
3567
  // node_modules/mppx/node_modules/zod/v4/core/core.js
3525
3568
  function $constructor(name, initializer, params) {
@@ -16604,89 +16647,8 @@ var init_zod = __esm(() => {
16604
16647
  init_mini();
16605
16648
  });
16606
16649
 
16607
- // node_modules/mppx/dist/Challenge.js
16608
- var Schema;
16609
- var init_Challenge = __esm(() => {
16610
- init_zod();
16611
- Schema = object({
16612
- description: optional(string2()),
16613
- digest: optional(string2().check(_regex(/^sha-256=/, "Invalid digest format"))),
16614
- expires: optional(datetime3()),
16615
- id: string2(),
16616
- intent: string2(),
16617
- method: string2(),
16618
- opaque: optional(record(string2(), string2())),
16619
- realm: string2(),
16620
- request: record(string2(), unknown())
16621
- });
16622
- });
16623
-
16624
- // node_modules/mppx/dist/Credential.js
16625
- var init_Credential = () => {};
16626
-
16627
- // node_modules/mppx/dist/Errors.js
16628
- var init_Errors = () => {};
16629
-
16630
- // node_modules/mppx/dist/Expires.js
16631
- var init_Expires = () => {};
16632
-
16633
- // node_modules/mppx/dist/Method.js
16634
- var exports_Method = {};
16635
- __export(exports_Method, {
16636
- toServer: () => toServer,
16637
- toClient: () => toClient,
16638
- from: () => from
16639
- });
16640
- function from(method) {
16641
- return method;
16642
- }
16643
- function toClient(method, options) {
16644
- const { context, createCredential } = options;
16645
- return {
16646
- ...method,
16647
- context,
16648
- createCredential
16649
- };
16650
- }
16651
- function toServer(method, options) {
16652
- const { defaults, html, request, respond, transport, verify } = options;
16653
- return {
16654
- ...method,
16655
- defaults,
16656
- html,
16657
- request,
16658
- respond,
16659
- transport,
16660
- verify
16661
- };
16662
- }
16663
-
16664
- // node_modules/mppx/dist/Receipt.js
16665
- var Schema2;
16666
- var init_Receipt = __esm(() => {
16667
- init_zod();
16668
- Schema2 = object({
16669
- method: string2(),
16670
- reference: string2(),
16671
- externalId: optional(string2()),
16672
- status: literal("success"),
16673
- timestamp: datetime3()
16674
- });
16675
- });
16676
-
16677
- // node_modules/mppx/dist/Store.js
16678
- var init_Store = () => {};
16679
-
16680
16650
  // node_modules/mppx/dist/index.js
16681
16651
  var init_dist = __esm(() => {
16682
- init_BodyDigest();
16683
- init_Challenge();
16684
- init_Credential();
16685
- init_Errors();
16686
- init_Expires();
16687
- init_PaymentRequest();
16688
- init_Receipt();
16689
- init_Store();
16690
16652
  init_zod();
16691
16653
  });
16692
16654
 
@@ -19536,7 +19498,7 @@ function registerSwapCommand(program2) {
19536
19498
  console.log(label("Wallet", truncAddr(wallet)));
19537
19499
  console.log("");
19538
19500
  await requireApproval({
19539
- cost: "Solana gas + 10bps platform fee",
19501
+ cost: "Solana gas + Jupiter referral fee",
19540
19502
  summary: `swap ${amountStr} ${fromToken.toUpperCase()} → ~${(Number(quote.outAmount) / 10 ** output.decimals).toFixed(6)} ${output.symbol}`,
19541
19503
  yes: opts.yes,
19542
19504
  commandExample: `amiko wallets swap send ${amountStr} ${fromToken} ${toToken}`
@@ -21609,6 +21571,77 @@ function registerPostCommand(program2) {
21609
21571
  }
21610
21572
  });
21611
21573
  }
21574
+ function registerReviewCommand(program2) {
21575
+ program2.command("list").description("List twin-drafted comments awaiting your approval").option("--json", "Output as JSON").action(async (opts) => {
21576
+ const auth = resolveAuth();
21577
+ const spinner = opts.json ? null : ora("Loading review queue...").start();
21578
+ try {
21579
+ const data = await amikoWebFetch(auth, "/api/comments/review");
21580
+ spinner?.stop();
21581
+ renderOutput(data, (d) => {
21582
+ if (!d.comments?.length) {
21583
+ console.log(dim("No comments awaiting review."));
21584
+ return;
21585
+ }
21586
+ console.log(heading(`Review queue — ${d.comments.length} comment(s)`));
21587
+ for (const c of d.comments) {
21588
+ const author = c.post?.user?.name ?? c.post?.user?.handle ?? "unknown";
21589
+ console.log("");
21590
+ console.log(label("Comment ID", c.id));
21591
+ console.log(label("Twin", c.twin?.name ?? c.twin?.id ?? "-"));
21592
+ console.log(label("On post", `${author} · ${(c.post?.content ?? "").slice(0, 80)}`));
21593
+ if (c.post?.id)
21594
+ console.log(label("Post ID", c.post.id));
21595
+ console.log(label("Draft", c.comment));
21596
+ console.log(dim(c.created_at));
21597
+ }
21598
+ }, { json: opts.json });
21599
+ } catch (e) {
21600
+ spinner?.stop();
21601
+ console.error(error(e instanceof Error ? e.message : String(e)));
21602
+ process.exit(1);
21603
+ }
21604
+ });
21605
+ program2.command("approve <commentId>").description("Approve and publish a twin-drafted comment from the review queue").option("--json", "Output as JSON").action(async (commentId, opts) => {
21606
+ const auth = resolveAuth();
21607
+ const spinner = opts.json ? null : ora("Approving comment...").start();
21608
+ try {
21609
+ const data = await amikoWebFetch(auth, `/api/comments/${encodeURIComponent(commentId)}`, { method: "PATCH", body: { action: "approve" } });
21610
+ spinner?.stop();
21611
+ renderOutput(data, () => {
21612
+ console.log(success("Comment approved and published"));
21613
+ console.log(label("Comment ID", commentId));
21614
+ }, { json: opts.json });
21615
+ } catch (e) {
21616
+ spinner?.stop();
21617
+ console.error(error(e instanceof Error ? e.message : String(e)));
21618
+ process.exit(1);
21619
+ }
21620
+ });
21621
+ program2.command("reject <commentId>").description("Reject (delete) a twin-drafted comment from the review queue").option("--yes", "Skip confirmation").option("--json", "Output as JSON").action(async (commentId, opts) => {
21622
+ await confirmDestructive({
21623
+ action: `Reject and delete comment ${commentId}`,
21624
+ yes: opts.yes,
21625
+ commandExample: `amiko review reject ${commentId}`
21626
+ });
21627
+ const auth = resolveAuth();
21628
+ const spinner = opts.json ? null : ora("Rejecting comment...").start();
21629
+ try {
21630
+ await amikoWebFetch(auth, `/api/comments/${encodeURIComponent(commentId)}`, { method: "DELETE" });
21631
+ spinner?.stop();
21632
+ if (opts.json) {
21633
+ console.log(JSON.stringify({ ok: true, id: commentId }, null, 2));
21634
+ } else {
21635
+ console.log(success("Comment rejected"));
21636
+ console.log(label("Comment ID", commentId));
21637
+ }
21638
+ } catch (e) {
21639
+ spinner?.stop();
21640
+ console.error(error(e instanceof Error ? e.message : String(e)));
21641
+ process.exit(1);
21642
+ }
21643
+ });
21644
+ }
21612
21645
 
21613
21646
  // src/commands/composio.ts
21614
21647
  function twinFromFlag3(opts) {
@@ -21903,6 +21936,7 @@ var avatar = program2.command("avatar").description("Manage twin avatar image");
21903
21936
  var friends = program2.command("friends").description("Manage friendships — list, requests, add, accept, remove, reports, matches");
21904
21937
  var users = program2.command("users").description("Search users and view public profiles");
21905
21938
  var post = program2.command("post").description("Create posts and comments on the feed");
21939
+ var review = program2.command("review").description("Review queue — list, approve, or reject twin-drafted comments");
21906
21940
  var composio = program2.command("composio").description("Manage Composio app connections");
21907
21941
  registerCreditsCommand(program2);
21908
21942
  registerSearchCommand(markets);
@@ -21927,5 +21961,6 @@ registerFriendsCommand(friends);
21927
21961
  registerUsersCommand(users);
21928
21962
  registerFeedCommand(program2);
21929
21963
  registerPostCommand(post);
21964
+ registerReviewCommand(review);
21930
21965
  registerComposioCommand(composio);
21931
21966
  program2.parse();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@heyamiko/amiko-cli",
3
- "version": "0.9.3",
3
+ "version": "0.9.5",
4
4
  "description": "Amiko CLI — swap tokens, manage credits, bridge cross-chain, and call marketplace agents",
5
5
  "type": "module",
6
6
  "bin": {
package/skills/SKILL.md CHANGED
@@ -29,6 +29,7 @@ Each row is a first-level command group or command. Start here when the user ask
29
29
  | `amiko friends <cmd>` | Social graph — list, requests, add, accept, remove, matches, reports |
30
30
  | `amiko users <cmd>` | Search users, view public profile |
31
31
  | `amiko post <cmd>` | Create posts and comments on the feed (optionally with media) |
32
+ | `amiko review <cmd>` | Review queue — list, approve, or reject twin-drafted comments |
32
33
  | `amiko feed` | Read the friends feed, for-you feed, or filter by hashtag |
33
34
  | `amiko composio <cmd>` | Connect / disconnect third-party OAuth apps (Gmail, GitHub, …) |
34
35
  | `amiko accounts` | Show the resolved identity (authenticated, userId, twinId, platform) |
@@ -51,7 +52,7 @@ Every paid / value-moving command (`markets search`, `markets image`, `markets a
51
52
 
52
53
  ## Critical Rules
53
54
 
54
- 1. **Every paid / value-moving command is hard-gated on `--yes` in a non-interactive shell.** The CLI *refuses* to run `markets image`, `markets search`, `markets amazon search`, `markets service call`, `markets service tts`, `markets service stt`, `markets service chat`, `credits topup`, `wallets swap send`, `wallets bridge send`, or `wallets transfer` unless `--yes` is passed. The refusal is loud: it prints the cost and the command you should re-run. **Quote the cost to the user, get explicit approval, THEN append `--yes`**. Same for destructive non-paid commands (`twin update --public`, `docs delete`, `friends remove`, `friends reports request`, `avatar update`, `voice reset`, `composio disconnect`).
55
+ 1. **Every paid / value-moving command is hard-gated on `--yes` in a non-interactive shell.** The CLI *refuses* to run `markets image`, `markets search`, `markets amazon search`, `markets service call`, `markets service tts`, `markets service stt`, `markets service chat`, `credits topup`, `wallets swap send`, `wallets bridge send`, or `wallets transfer` unless `--yes` is passed. The refusal is loud: it prints the cost and the command you should re-run. **Quote the cost to the user, get explicit approval, THEN append `--yes`**. Same for destructive non-paid commands (`twin update --public`, `docs delete`, `friends remove`, `friends reports request`, `avatar update`, `voice reset`, `composio disconnect`, `review reject`).
55
56
  2. **After every paid command, report the remaining balance.** The CLI prints a `Balance: N credits` line at the end of every paid command — include that figure in your reply.
56
57
  3. **Never retry a failed command.** Report the error and stop. Every paid call costs tokens even on failure.
57
58
  4. **Never suggest `amiko login` or `amiko connect`.** These don't exist. Auth is automatic when you run from your workspace folder.
@@ -252,8 +253,13 @@ amiko post create --content "look" --media https://...jpg
252
253
  amiko post comment --id <postId> --comment "great post"
253
254
  amiko post comment --id <postId> --comment "look" --media https://...jpg
254
255
  amiko post comment --id <postId> --comment "..." --twin <id>
256
+ amiko review list # list twin-drafted comments awaiting your approval
257
+ amiko review approve <commentId> # publish a draft comment from the review queue
258
+ amiko review reject <commentId> --yes # destructive — delete a draft comment
255
259
  ```
256
260
 
261
+ **Comments authored by a twin always go through review.** Any comment created with `amiko post comment ... --twin <id>` (or auto-drafted by a twin in engagement mode) lands in `status=draft` and is **not visible** until you run `amiko review approve <commentId>`. Comments without `--twin` (you posting as yourself) publish immediately and skip the review queue. Workflow: `amiko review list` to see pending drafts → `amiko review approve <id>` to publish, or `amiko review reject <id> --yes` to discard.
262
+
257
263
  ## Composio
258
264
 
259
265
  ```bash