@heyamiko/amiko-cli 0.5.18 → 0.6.0

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 (2) hide show
  1. package/dist/index.js +183 -3
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -75833,8 +75833,8 @@ function registerUpdateCommand(program2) {
75833
75833
  // src/commands/search.ts
75834
75834
  var TREASURY = "FPiZAf3jEnNfCwfvbv46jdPfHbmSepD4Q6iHiLJDQXvb";
75835
75835
  function registerSearchCommand(program2) {
75836
- program2.command("search <query>").description("Search X/Twitter — pays 1 AMIKO token per search").option("--raw", "Output raw JSON").action(async (query, opts) => {
75837
- const spinner = ora("Searching X...").start();
75836
+ program2.command("search <query>").description("X Search — pays 1 AMIKO token per search").option("--raw", "Output raw JSON").action(async (query, opts) => {
75837
+ const spinner = ora("X Search...").start();
75838
75838
  try {
75839
75839
  const config2 = loadConfig();
75840
75840
  const auth = resolveAuth(config2);
@@ -75902,7 +75902,7 @@ function registerSearchCommand(program2) {
75902
75902
  console.log(JSON.stringify(data, null, 2));
75903
75903
  return;
75904
75904
  }
75905
- console.log(heading(`X Search: "${query}"
75905
+ console.log(heading(`X Search — "${query}"
75906
75906
  `));
75907
75907
  const tweets = data.data || [];
75908
75908
  if (tweets.length === 0) {
@@ -75929,6 +75929,185 @@ function registerSearchCommand(program2) {
75929
75929
  });
75930
75930
  }
75931
75931
 
75932
+ // src/commands/services.ts
75933
+ var TREASURY2 = "FPiZAf3jEnNfCwfvbv46jdPfHbmSepD4Q6iHiLJDQXvb";
75934
+ async function payAndCall(mppBase2, method, path, billingBase2, billingToken, solanaWallet, amikoAmount, body) {
75935
+ const transferRes = await fetch(`${billingBase2}/api/crossmint/wallets/${encodeURIComponent(solanaWallet)}/transfer`, {
75936
+ method: "POST",
75937
+ headers: {
75938
+ "Content-Type": "application/json",
75939
+ Authorization: `Bearer ${billingToken}`
75940
+ },
75941
+ body: JSON.stringify({
75942
+ to: TREASURY2,
75943
+ amount: amikoAmount,
75944
+ token: "AMIKO",
75945
+ chain: "solana"
75946
+ })
75947
+ });
75948
+ if (!transferRes.ok) {
75949
+ const err = await transferRes.json().catch(() => ({ error: "Transfer failed" }));
75950
+ throw new Error(err.error || `AMIKO payment failed: ${transferRes.status}`);
75951
+ }
75952
+ const transferData = await transferRes.json();
75953
+ const txHash = transferData.txHash;
75954
+ if (!txHash)
75955
+ throw new Error("Payment sent but no tx hash returned.");
75956
+ const headers = {
75957
+ "Content-Type": "application/json",
75958
+ "X-Payment-Tx": txHash
75959
+ };
75960
+ const fetchOpts = { method, headers };
75961
+ if (body && method !== "GET") {
75962
+ fetchOpts.body = JSON.stringify(body);
75963
+ }
75964
+ const url2 = path.startsWith("http") ? path : `${mppBase2}${path}`;
75965
+ const res = await fetch(url2, fetchOpts);
75966
+ return { res, txHash };
75967
+ }
75968
+ function registerServicesCommand(program2) {
75969
+ const svc = program2.command("service").alias("svc").description("Call any MPP service — pays with AMIKO tokens");
75970
+ svc.command("tts <voiceId> <text>").description("Text-to-speech — 1 AMIKO").option("--raw", "Output raw response").action(async (voiceId, text, opts) => {
75971
+ await callService({
75972
+ name: "Text-to-Speech",
75973
+ method: "POST",
75974
+ path: `/v1/tts/${encodeURIComponent(voiceId)}`,
75975
+ body: { text },
75976
+ amiko: "1",
75977
+ opts
75978
+ });
75979
+ });
75980
+ svc.command("stt <audioUrl>").description("Speech-to-text — 1 AMIKO").option("--raw", "Output raw response").action(async (audioUrl, opts) => {
75981
+ await callService({
75982
+ name: "Speech-to-Text",
75983
+ method: "POST",
75984
+ path: "/v1/stt",
75985
+ body: { audioUrl },
75986
+ amiko: "1",
75987
+ opts
75988
+ });
75989
+ });
75990
+ svc.command("voices").description("List available voices — free").action(async () => {
75991
+ const config2 = loadConfig();
75992
+ const mppBase2 = (config2.apiBase || "https://mpp.amikomarkets.com").replace(/\/$/, "");
75993
+ const res = await fetch(`${mppBase2}/v1/voices`);
75994
+ const data = await res.json();
75995
+ console.log(heading(`Available Voices
75996
+ `));
75997
+ const voices = data.voices || data;
75998
+ if (Array.isArray(voices)) {
75999
+ for (const v8 of voices) {
76000
+ console.log(` ${source_default.cyan(v8.voice_id || v8.id)} ${v8.name || ""}`);
76001
+ if (v8.description)
76002
+ console.log(dim(` ${v8.description}`));
76003
+ }
76004
+ } else {
76005
+ console.log(JSON.stringify(data, null, 2));
76006
+ }
76007
+ });
76008
+ svc.command("chat <message>").description("AI chat — 1 AMIKO").option("--model <model>", "Model to use").option("--raw", "Output raw response").action(async (message, opts) => {
76009
+ const body = { message };
76010
+ if (opts.model)
76011
+ body.model = opts.model;
76012
+ await callService({
76013
+ name: "AI Chat",
76014
+ method: "POST",
76015
+ path: "/v1/ai/chat",
76016
+ body,
76017
+ amiko: "1",
76018
+ opts
76019
+ });
76020
+ });
76021
+ svc.command("call <method> <path> [body]").description("Call any MPP endpoint — 1 AMIKO").option("--amiko <amount>", "AMIKO tokens to pay", "1").option("--raw", "Output raw response").action(async (method, path, bodyStr, opts) => {
76022
+ let body;
76023
+ if (bodyStr) {
76024
+ try {
76025
+ body = JSON.parse(bodyStr);
76026
+ } catch {
76027
+ body = { text: bodyStr };
76028
+ }
76029
+ }
76030
+ await callService({
76031
+ name: `${method.toUpperCase()} ${path}`,
76032
+ method: method.toUpperCase(),
76033
+ path,
76034
+ body,
76035
+ amiko: opts.amiko || "1",
76036
+ opts
76037
+ });
76038
+ });
76039
+ svc.command("list").alias("ls").description("List available MPP services and prices").action(async () => {
76040
+ const config2 = loadConfig();
76041
+ const mppBase2 = (config2.apiBase || "https://mpp.amikomarkets.com").replace(/\/$/, "");
76042
+ const spinner = ora("Fetching services...").start();
76043
+ try {
76044
+ const res = await fetch(`${mppBase2}/openapi.json`);
76045
+ const spec = await res.json();
76046
+ spinner.stop();
76047
+ console.log(heading(`MPP Services
76048
+ `));
76049
+ const paths = spec.paths || {};
76050
+ for (const [path, methods] of Object.entries(paths)) {
76051
+ for (const [method, op] of Object.entries(methods)) {
76052
+ const price = op["x-payment-info"]?.price;
76053
+ const priceLabel = price === "0" || !price ? source_default.green("FREE") : source_default.yellow(`$${parseFloat(price).toFixed(2)}`);
76054
+ console.log(` ${source_default.bold(method.toUpperCase().padEnd(6))} ${path.padEnd(40)} ${priceLabel}`);
76055
+ if (op.summary)
76056
+ console.log(dim(` ${op.summary}`));
76057
+ }
76058
+ }
76059
+ } catch (err) {
76060
+ spinner.stop();
76061
+ console.error(error("Failed to fetch service list"));
76062
+ }
76063
+ });
76064
+ }
76065
+ async function callService(params) {
76066
+ const spinner = ora(`${params.name}...`).start();
76067
+ try {
76068
+ const config2 = loadConfig();
76069
+ const auth = resolveAuth(config2);
76070
+ const mppBase2 = (config2.apiBase || "https://mpp.amikomarkets.com").replace(/\/$/, "");
76071
+ const billingBase2 = auth.billingBase || "https://billing.heyamiko.com";
76072
+ const billingToken = auth.platformKey || auth.twinToken || auth.privyToken;
76073
+ if (!billingToken) {
76074
+ spinner.stop();
76075
+ console.error(error("No auth token."));
76076
+ process.exit(1);
76077
+ }
76078
+ const allWallets = auth.agentWallets || config2.agentWallets || [];
76079
+ const solanaWallet = allWallets.find((w5) => w5.chain === "solana")?.address;
76080
+ if (!solanaWallet) {
76081
+ spinner.stop();
76082
+ console.error(error("No Solana wallet for AMIKO payment."));
76083
+ process.exit(1);
76084
+ }
76085
+ spinner.text = `Paying ${params.amiko} AMIKO...`;
76086
+ const { res, txHash } = await payAndCall(mppBase2, params.method, params.path, billingBase2, billingToken, solanaWallet, params.amiko, params.body);
76087
+ spinner.stop();
76088
+ if (!res.ok) {
76089
+ const text = await res.text().catch(() => "");
76090
+ console.error(error(`${params.name} failed: ${res.status} ${text.slice(0, 300)}`));
76091
+ console.log(dim(`Payment tx: https://solscan.io/tx/${txHash}`));
76092
+ process.exit(1);
76093
+ }
76094
+ const contentType = res.headers.get("content-type") || "";
76095
+ if (params.opts.raw || !contentType.includes("json")) {
76096
+ const text = await res.text();
76097
+ console.log(text);
76098
+ } else {
76099
+ const data = await res.json();
76100
+ console.log(JSON.stringify(data, null, 2));
76101
+ }
76102
+ console.log("");
76103
+ console.log(success(`Paid ${params.amiko} AMIKO`) + dim(` tx: ${txHash.slice(0, 16)}...`));
76104
+ } catch (err) {
76105
+ spinner.stop();
76106
+ console.error(error(err instanceof Error ? err.message : "Service call failed"));
76107
+ process.exit(1);
76108
+ }
76109
+ }
76110
+
75932
76111
  // src/index.ts
75933
76112
  var require2 = createRequire2(import.meta.url);
75934
76113
  var { version: PKG_VERSION } = require2("../package.json");
@@ -75950,6 +76129,7 @@ registerWalletCommand(program2);
75950
76129
  registerLoginCommand(program2);
75951
76130
  registerReputationCommand(program2);
75952
76131
  registerConfigCommand(program2);
76132
+ registerServicesCommand(program2);
75953
76133
  registerDiscoveryCommand(program2);
75954
76134
  registerUpdateCommand(program2);
75955
76135
  program2.parse();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@heyamiko/amiko-cli",
3
- "version": "0.5.18",
3
+ "version": "0.6.0",
4
4
  "description": "Amiko CLI — swap tokens, manage credits, bridge cross-chain, and call marketplace agents",
5
5
  "type": "module",
6
6
  "bin": {