@heyamiko/amiko-cli 0.5.19 → 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.
- package/dist/index.js +180 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -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();
|