@t2000/cli 5.24.3 → 5.26.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
CHANGED
|
@@ -32124,7 +32124,13 @@ function withoutMcpEntry(config) {
|
|
|
32124
32124
|
|
|
32125
32125
|
// src/commands/status.ts
|
|
32126
32126
|
var require2 = createRequire(import.meta.url);
|
|
32127
|
-
var { version: CLI_VERSION } =
|
|
32127
|
+
var { version: CLI_VERSION } = (() => {
|
|
32128
|
+
try {
|
|
32129
|
+
return require2("../package.json");
|
|
32130
|
+
} catch {
|
|
32131
|
+
return require2("../../package.json");
|
|
32132
|
+
}
|
|
32133
|
+
})();
|
|
32128
32134
|
var GATEWAY_URL = process.env.T2000_GATEWAY_URL ?? "https://mpp.t2000.ai";
|
|
32129
32135
|
var GATEWAY_TIMEOUT_MS = 3e3;
|
|
32130
32136
|
async function checkGateway() {
|
|
@@ -33109,7 +33115,7 @@ function registerMcpStart(parent) {
|
|
|
33109
33115
|
parent.command("start", { isDefault: true }).description("Start MCP server (stdio transport \u2014 for AI client integration)").option("--key <path>", "Custom wallet path (default ~/.t2000/wallet.key)").action(async (opts) => {
|
|
33110
33116
|
let mod3;
|
|
33111
33117
|
try {
|
|
33112
|
-
mod3 = await import("./dist-
|
|
33118
|
+
mod3 = await import("./dist-BJOELEAN.js");
|
|
33113
33119
|
} catch {
|
|
33114
33120
|
console.error("MCP server not installed. Run:\n npm install -g @t2000/mcp");
|
|
33115
33121
|
process.exit(1);
|
|
@@ -33449,7 +33455,237 @@ For MCP-aware clients (Claude Desktop, Cursor, Windsurf), prefer
|
|
|
33449
33455
|
}
|
|
33450
33456
|
|
|
33451
33457
|
// src/commands/agent/index.ts
|
|
33458
|
+
import { createHash as createHash2 } from "crypto";
|
|
33459
|
+
|
|
33460
|
+
// src/commands/agent/services.ts
|
|
33452
33461
|
import { createHash } from "crypto";
|
|
33462
|
+
import { readFileSync as readFileSync3 } from "fs";
|
|
33463
|
+
var SLUG_RE = /^[a-z0-9][a-z0-9-]{1,39}$/;
|
|
33464
|
+
async function fetchJson(url, init) {
|
|
33465
|
+
const res = await fetch(url, {
|
|
33466
|
+
method: init?.method ?? "GET",
|
|
33467
|
+
headers: init?.body ? { "Content-Type": "application/json" } : void 0,
|
|
33468
|
+
body: init?.body ? JSON.stringify(init.body) : void 0
|
|
33469
|
+
});
|
|
33470
|
+
const json = await res.json().catch(() => ({}));
|
|
33471
|
+
if (!res.ok) {
|
|
33472
|
+
const err = json.error;
|
|
33473
|
+
const msg = typeof err === "string" ? err : err?.message ?? `HTTP ${res.status}`;
|
|
33474
|
+
throw new Error(msg);
|
|
33475
|
+
}
|
|
33476
|
+
return json;
|
|
33477
|
+
}
|
|
33478
|
+
function canonicalServicesJson(services) {
|
|
33479
|
+
return JSON.stringify(
|
|
33480
|
+
services.map(
|
|
33481
|
+
(s) => Object.fromEntries(
|
|
33482
|
+
Object.entries(s).sort(([a], [b]) => a.localeCompare(b))
|
|
33483
|
+
)
|
|
33484
|
+
)
|
|
33485
|
+
);
|
|
33486
|
+
}
|
|
33487
|
+
async function getCatalog(base, address) {
|
|
33488
|
+
const res = await fetchJson(
|
|
33489
|
+
`${base}/agent/services?address=${encodeURIComponent(address)}`
|
|
33490
|
+
);
|
|
33491
|
+
return Array.isArray(res.services) ? res.services : [];
|
|
33492
|
+
}
|
|
33493
|
+
async function putCatalog(opts) {
|
|
33494
|
+
const agent = await withAgent({ keyPath: opts.keyPath });
|
|
33495
|
+
const address = agent.address();
|
|
33496
|
+
const challenge = await fetchJson(`${opts.base}/agent/challenge`, {
|
|
33497
|
+
method: "POST",
|
|
33498
|
+
body: { address }
|
|
33499
|
+
});
|
|
33500
|
+
const nonce = challenge.nonce;
|
|
33501
|
+
if (!nonce) {
|
|
33502
|
+
throw new Error("Failed to get a challenge nonce.");
|
|
33503
|
+
}
|
|
33504
|
+
const digest = createHash("sha256").update(canonicalServicesJson(opts.services)).digest("hex");
|
|
33505
|
+
const message = new TextEncoder().encode(
|
|
33506
|
+
`t2000-agent-services:${nonce}:${digest}`
|
|
33507
|
+
);
|
|
33508
|
+
const { signature } = await agent.keypair.signPersonalMessage(message);
|
|
33509
|
+
const res = await fetchJson(`${opts.base}/agent/services`, {
|
|
33510
|
+
method: "POST",
|
|
33511
|
+
body: { address, nonce, signature, services: opts.services }
|
|
33512
|
+
});
|
|
33513
|
+
return { address, count: Number(res.count ?? opts.services.length) };
|
|
33514
|
+
}
|
|
33515
|
+
function entryFromFlags(opts) {
|
|
33516
|
+
const slug = String(opts.slug ?? "").trim().toLowerCase();
|
|
33517
|
+
if (!SLUG_RE.test(slug)) {
|
|
33518
|
+
throw new Error("--slug is required: [a-z0-9-], 2-40 chars.");
|
|
33519
|
+
}
|
|
33520
|
+
const out = { slug };
|
|
33521
|
+
if (opts.title !== void 0) {
|
|
33522
|
+
out.title = opts.title;
|
|
33523
|
+
}
|
|
33524
|
+
if (opts.description !== void 0) {
|
|
33525
|
+
out.description = opts.description;
|
|
33526
|
+
}
|
|
33527
|
+
if (opts.price !== void 0) {
|
|
33528
|
+
out.priceUsdc = opts.price;
|
|
33529
|
+
}
|
|
33530
|
+
if (opts.input !== void 0) {
|
|
33531
|
+
out.input = opts.input || null;
|
|
33532
|
+
}
|
|
33533
|
+
if (opts.endpoint !== void 0) {
|
|
33534
|
+
out.endpoint = opts.endpoint || null;
|
|
33535
|
+
}
|
|
33536
|
+
if (opts.method !== void 0) {
|
|
33537
|
+
out.method = opts.method.toUpperCase() === "GET" ? "GET" : "POST";
|
|
33538
|
+
}
|
|
33539
|
+
return out;
|
|
33540
|
+
}
|
|
33541
|
+
function registerAgentServices(agentGroup, defaults) {
|
|
33542
|
+
const group = agentGroup.command("services").description(
|
|
33543
|
+
"Manage this agent's service CATALOG (one agent, many services). Buy URLs: commerce/pay/<agent>/<slug>. [Store v2]"
|
|
33544
|
+
);
|
|
33545
|
+
group.command("list").argument("[address]", "Agent address (default: your wallet)").option("--key <path>", "Custom wallet path (default ~/.t2000/wallet.key)").option("--api <url>", `API base URL (default ${defaults.apiBase})`).description("List the catalog (public read).").action(async (addressArg, opts) => {
|
|
33546
|
+
try {
|
|
33547
|
+
const base = opts.api ?? defaults.apiBase;
|
|
33548
|
+
const address = addressArg ?? (await withAgent({ keyPath: opts.key })).address();
|
|
33549
|
+
const services = await getCatalog(base, address);
|
|
33550
|
+
if (isJsonMode()) {
|
|
33551
|
+
printJson({ address, services });
|
|
33552
|
+
return;
|
|
33553
|
+
}
|
|
33554
|
+
printBlank();
|
|
33555
|
+
if (services.length === 0) {
|
|
33556
|
+
printLine("No services in the catalog. Add one: t2 agent services add --slug <slug> --title \u2026 --description \u2026 --price \u2026");
|
|
33557
|
+
printBlank();
|
|
33558
|
+
return;
|
|
33559
|
+
}
|
|
33560
|
+
for (const s of services) {
|
|
33561
|
+
printKeyValue(
|
|
33562
|
+
s.slug,
|
|
33563
|
+
`$${s.priceUsdc} \u2014 ${s.title}${s.active === false ? " (inactive)" : ""}`
|
|
33564
|
+
);
|
|
33565
|
+
}
|
|
33566
|
+
printBlank();
|
|
33567
|
+
} catch (error) {
|
|
33568
|
+
handleError(error);
|
|
33569
|
+
}
|
|
33570
|
+
});
|
|
33571
|
+
group.command("add").description("Add one service to the catalog.").requiredOption("--slug <slug>", "Service slug ([a-z0-9-], 2-40 chars)").requiredOption("--title <title>", "Service title (\u226480 chars)").requiredOption("--description <text>", "Listing copy (\u2264480 chars)").requiredOption("--price <usdc>", "Price per call in USDC (e.g. 0.02)").option("--input <hint>", 'Input hint, e.g. "Provide: 1. address 2. chain"').option("--endpoint <url>", "Self-hosted https endpoint (omit for wrap/payment-only)").option("--method <method>", "Wrap delivery method: GET or POST").option("--key <path>", "Custom wallet path (default ~/.t2000/wallet.key)").option("--api <url>", `API base URL (default ${defaults.apiBase})`).action(async (opts) => {
|
|
33572
|
+
try {
|
|
33573
|
+
const base = opts.api ?? defaults.apiBase;
|
|
33574
|
+
const agent = await withAgent({ keyPath: opts.key });
|
|
33575
|
+
const current = await getCatalog(base, agent.address());
|
|
33576
|
+
const entry = entryFromFlags(opts);
|
|
33577
|
+
if (current.some((s) => s.slug === entry.slug)) {
|
|
33578
|
+
throw new Error(
|
|
33579
|
+
`Slug "${entry.slug}" already exists \u2014 use: t2 agent services update --slug ${entry.slug}`
|
|
33580
|
+
);
|
|
33581
|
+
}
|
|
33582
|
+
const next = {
|
|
33583
|
+
title: "",
|
|
33584
|
+
description: "",
|
|
33585
|
+
priceUsdc: "0",
|
|
33586
|
+
active: true,
|
|
33587
|
+
...entry
|
|
33588
|
+
};
|
|
33589
|
+
const { count } = await putCatalog({
|
|
33590
|
+
base,
|
|
33591
|
+
keyPath: opts.key,
|
|
33592
|
+
services: [...current, next]
|
|
33593
|
+
});
|
|
33594
|
+
if (isJsonMode()) {
|
|
33595
|
+
printJson({ added: entry.slug, count });
|
|
33596
|
+
return;
|
|
33597
|
+
}
|
|
33598
|
+
printBlank();
|
|
33599
|
+
printSuccess(`Service "${entry.slug}" added \u2014 catalog now ${count} service${count === 1 ? "" : "s"}.`);
|
|
33600
|
+
printLine(`Buy URL: https://x402.t2000.ai/commerce/pay/${agent.address()}/${entry.slug}`);
|
|
33601
|
+
printBlank();
|
|
33602
|
+
} catch (error) {
|
|
33603
|
+
handleError(error);
|
|
33604
|
+
}
|
|
33605
|
+
});
|
|
33606
|
+
group.command("update").description("Update one service (only the provided fields change).").requiredOption("--slug <slug>", "Service slug to update").option("--title <title>", "Service title (\u226480 chars)").option("--description <text>", "Listing copy (\u2264480 chars)").option("--price <usdc>", "Price per call in USDC").option("--input <hint>", 'Input hint ("" to clear)').option("--endpoint <url>", 'Self-hosted https endpoint ("" to clear \u2192 wrap mode)').option("--method <method>", "Wrap delivery method: GET or POST").option("--active <bool>", "true | false \u2014 per-service kill switch").option("--key <path>", "Custom wallet path (default ~/.t2000/wallet.key)").option("--api <url>", `API base URL (default ${defaults.apiBase})`).action(async (opts) => {
|
|
33607
|
+
try {
|
|
33608
|
+
const base = opts.api ?? defaults.apiBase;
|
|
33609
|
+
const agent = await withAgent({ keyPath: opts.key });
|
|
33610
|
+
const current = await getCatalog(base, agent.address());
|
|
33611
|
+
const entry = entryFromFlags(opts);
|
|
33612
|
+
const idx = current.findIndex((s) => s.slug === entry.slug);
|
|
33613
|
+
if (idx === -1) {
|
|
33614
|
+
throw new Error(`No service "${entry.slug}" in the catalog.`);
|
|
33615
|
+
}
|
|
33616
|
+
const merged = { ...current[idx], ...entry };
|
|
33617
|
+
if (opts.active !== void 0) {
|
|
33618
|
+
merged.active = String(opts.active).toLowerCase() !== "false";
|
|
33619
|
+
}
|
|
33620
|
+
const services = [...current];
|
|
33621
|
+
services[idx] = merged;
|
|
33622
|
+
const { count } = await putCatalog({ base, keyPath: opts.key, services });
|
|
33623
|
+
if (isJsonMode()) {
|
|
33624
|
+
printJson({ updated: entry.slug, count });
|
|
33625
|
+
return;
|
|
33626
|
+
}
|
|
33627
|
+
printBlank();
|
|
33628
|
+
printSuccess(`Service "${entry.slug}" updated.`);
|
|
33629
|
+
printBlank();
|
|
33630
|
+
} catch (error) {
|
|
33631
|
+
handleError(error);
|
|
33632
|
+
}
|
|
33633
|
+
});
|
|
33634
|
+
group.command("remove").description("Remove one service from the catalog.").requiredOption("--slug <slug>", "Service slug to remove").option("--key <path>", "Custom wallet path (default ~/.t2000/wallet.key)").option("--api <url>", `API base URL (default ${defaults.apiBase})`).action(async (opts) => {
|
|
33635
|
+
try {
|
|
33636
|
+
const base = opts.api ?? defaults.apiBase;
|
|
33637
|
+
const agent = await withAgent({ keyPath: opts.key });
|
|
33638
|
+
const slug = String(opts.slug ?? "").trim().toLowerCase();
|
|
33639
|
+
const current = await getCatalog(base, agent.address());
|
|
33640
|
+
const services = current.filter((s) => s.slug !== slug);
|
|
33641
|
+
if (services.length === current.length) {
|
|
33642
|
+
throw new Error(`No service "${slug}" in the catalog.`);
|
|
33643
|
+
}
|
|
33644
|
+
const { count } = await putCatalog({ base, keyPath: opts.key, services });
|
|
33645
|
+
if (isJsonMode()) {
|
|
33646
|
+
printJson({ removed: slug, count });
|
|
33647
|
+
return;
|
|
33648
|
+
}
|
|
33649
|
+
printBlank();
|
|
33650
|
+
printSuccess(`Service "${slug}" removed \u2014 catalog now ${count} service${count === 1 ? "" : "s"}.`);
|
|
33651
|
+
printBlank();
|
|
33652
|
+
} catch (error) {
|
|
33653
|
+
handleError(error);
|
|
33654
|
+
}
|
|
33655
|
+
});
|
|
33656
|
+
group.command("sync").description(
|
|
33657
|
+
"Declarative catalog sync \u2014 the manifest file IS the catalog (adds/updates/removes to match). The catalog-scale path."
|
|
33658
|
+
).argument("<file>", "Path to a JSON manifest: [{ slug, title, description, priceUsdc, input?, endpoint?, method?, active? }]").option("--key <path>", "Custom wallet path (default ~/.t2000/wallet.key)").option("--api <url>", `API base URL (default ${defaults.apiBase})`).action(async (file, opts) => {
|
|
33659
|
+
try {
|
|
33660
|
+
const base = opts.api ?? defaults.apiBase;
|
|
33661
|
+
const raw = JSON.parse(readFileSync3(file, "utf8"));
|
|
33662
|
+
const list = Array.isArray(raw) ? raw : raw?.services ?? null;
|
|
33663
|
+
if (!Array.isArray(list)) {
|
|
33664
|
+
throw new Error(
|
|
33665
|
+
'Manifest must be a JSON array of services (or { "services": [...] }).'
|
|
33666
|
+
);
|
|
33667
|
+
}
|
|
33668
|
+
const services = list.map((s) => {
|
|
33669
|
+
const entry = s;
|
|
33670
|
+
return { ...entry, active: entry.active !== false };
|
|
33671
|
+
});
|
|
33672
|
+
const agent = await withAgent({ keyPath: opts.key });
|
|
33673
|
+
const before = await getCatalog(base, agent.address());
|
|
33674
|
+
const { count } = await putCatalog({ base, keyPath: opts.key, services });
|
|
33675
|
+
if (isJsonMode()) {
|
|
33676
|
+
printJson({ synced: count, before: before.length });
|
|
33677
|
+
return;
|
|
33678
|
+
}
|
|
33679
|
+
printBlank();
|
|
33680
|
+
printSuccess(`Catalog synced \u2014 ${before.length} \u2192 ${count} services.`);
|
|
33681
|
+
printBlank();
|
|
33682
|
+
} catch (error) {
|
|
33683
|
+
handleError(error);
|
|
33684
|
+
}
|
|
33685
|
+
});
|
|
33686
|
+
}
|
|
33687
|
+
|
|
33688
|
+
// src/commands/agent/index.ts
|
|
33453
33689
|
var DEFAULT_API_BASE3 = process.env.T2000_API_URL ?? "https://api.t2000.ai/v1";
|
|
33454
33690
|
var DEFAULT_GATEWAY = process.env.T2000_GATEWAY_URL ?? "https://mpp.t2000.ai";
|
|
33455
33691
|
var DEFAULT_RAIL = process.env.T2000_RAIL_URL ?? "https://x402.t2000.ai";
|
|
@@ -33490,19 +33726,19 @@ async function fundCredit(agent, base, amountStr, assetOpt) {
|
|
|
33490
33726
|
throw new Error(`amount must be a positive number (got "${amountStr}").`);
|
|
33491
33727
|
}
|
|
33492
33728
|
const asset = normalizeTopupAsset(assetOpt);
|
|
33493
|
-
const cfg = await
|
|
33729
|
+
const cfg = await fetchJson2(`${base}/agent/topup`, { method: "GET" });
|
|
33494
33730
|
const treasury = cfg.treasury;
|
|
33495
33731
|
if (!treasury) {
|
|
33496
33732
|
throw new Error("Could not resolve the t2000 treasury address.");
|
|
33497
33733
|
}
|
|
33498
33734
|
const sent = await agent.send({ to: treasury, amount, asset });
|
|
33499
|
-
const topup = await
|
|
33735
|
+
const topup = await fetchJson2(`${base}/agent/topup`, {
|
|
33500
33736
|
method: "POST",
|
|
33501
33737
|
body: { address: agent.address(), digest: sent.tx }
|
|
33502
33738
|
});
|
|
33503
33739
|
return { amount, asset, balanceUsd: topup.balanceUsd };
|
|
33504
33740
|
}
|
|
33505
|
-
async function
|
|
33741
|
+
async function fetchJson2(url, init) {
|
|
33506
33742
|
const res = await fetch(url, {
|
|
33507
33743
|
method: init.method,
|
|
33508
33744
|
headers: init.body ? { "Content-Type": "application/json" } : void 0,
|
|
@@ -33524,9 +33760,14 @@ Subcommands:
|
|
|
33524
33760
|
$ t2 agent onboard --fund 5 Fund 5 USDC \u2192 mint an API key (ready to call)
|
|
33525
33761
|
$ t2 agent onboard --fund 5 --asset USDsui
|
|
33526
33762
|
$ t2 agent onboard Already funded \u2192 just mint a key
|
|
33763
|
+
$ t2 agent services add --slug sui-price --title "SUI spot" --description "\u2026" --price 0.02
|
|
33764
|
+
$ t2 agent services sync ./services.json Manifest IS the catalog (catalog-scale sellers)
|
|
33527
33765
|
`
|
|
33528
33766
|
);
|
|
33529
|
-
group
|
|
33767
|
+
registerAgentServices(group, { apiBase: DEFAULT_API_BASE3 });
|
|
33768
|
+
group.command("onboard").description(
|
|
33769
|
+
"Buy-side setup: fund credit (gasless USDC/USDsui) + mint a Private API key. Registering an Agent ID is free and separate \u2014 `t2 init` / `t2 agent register`."
|
|
33770
|
+
).option("--fund <amount>", "Stablecoin amount to deposit as credit (omit if already funded)").option("--asset <asset>", "USDC (default) or USDsui", "USDC").option("--key <path>", "Custom wallet path (default ~/.t2000/wallet.key)").option("--api <url>", `API base URL (default ${DEFAULT_API_BASE3})`).action(
|
|
33530
33771
|
async (opts) => {
|
|
33531
33772
|
try {
|
|
33532
33773
|
const base = opts.api ?? DEFAULT_API_BASE3;
|
|
@@ -33540,7 +33781,7 @@ Subcommands:
|
|
|
33540
33781
|
);
|
|
33541
33782
|
}
|
|
33542
33783
|
}
|
|
33543
|
-
const challenge = await
|
|
33784
|
+
const challenge = await fetchJson2(`${base}/agent/challenge`, {
|
|
33544
33785
|
method: "POST",
|
|
33545
33786
|
body: { address }
|
|
33546
33787
|
});
|
|
@@ -33550,7 +33791,7 @@ Subcommands:
|
|
|
33550
33791
|
}
|
|
33551
33792
|
const message = new TextEncoder().encode(`t2000-agent-keys:${nonce}`);
|
|
33552
33793
|
const { signature } = await agent.keypair.signPersonalMessage(message);
|
|
33553
|
-
const minted = await
|
|
33794
|
+
const minted = await fetchJson2(`${base}/agent/keys`, {
|
|
33554
33795
|
method: "POST",
|
|
33555
33796
|
body: { address, nonce, signature }
|
|
33556
33797
|
});
|
|
@@ -33720,7 +33961,7 @@ Subcommands:
|
|
|
33720
33961
|
const base = opts.api ?? DEFAULT_API_BASE3;
|
|
33721
33962
|
const agent = await withAgent({ keyPath: opts.key });
|
|
33722
33963
|
const address = agent.address();
|
|
33723
|
-
const challenge = await
|
|
33964
|
+
const challenge = await fetchJson2(`${base}/agent/challenge`, {
|
|
33724
33965
|
method: "POST",
|
|
33725
33966
|
body: { address }
|
|
33726
33967
|
});
|
|
@@ -33730,7 +33971,7 @@ Subcommands:
|
|
|
33730
33971
|
}
|
|
33731
33972
|
const message = new TextEncoder().encode(`t2000-agent-profile:${nonce}`);
|
|
33732
33973
|
const { signature } = await agent.keypair.signPersonalMessage(message);
|
|
33733
|
-
await
|
|
33974
|
+
await fetchJson2(`${base}/agent/profile`, {
|
|
33734
33975
|
method: "POST",
|
|
33735
33976
|
body: {
|
|
33736
33977
|
address,
|
|
@@ -33837,31 +34078,37 @@ Subcommands:
|
|
|
33837
34078
|
).option("--method <method>", "Upstream method: GET or POST (default POST)").option("--price <usdc>", "Price per call in USDC (e.g. 0.02)").option(
|
|
33838
34079
|
"--category <category>",
|
|
33839
34080
|
`Storefront category: ${AGENT_CATEGORIES.join(" | ")}`
|
|
33840
|
-
).option("--remove", "Take down the deployed service").option(
|
|
34081
|
+
).option("--remove", "Take down the deployed service").option(
|
|
34082
|
+
"--service <slug>",
|
|
34083
|
+
"Catalog service slug \u2014 wrap config for ONE SKU (Store v2; omit = the default service)"
|
|
34084
|
+
).option("--gateway <url>", `Gateway base URL (default ${DEFAULT_GATEWAY})`).option("--key <path>", "Custom wallet path (default ~/.t2000/wallet.key)").option("--api <url>", `API base URL (default ${DEFAULT_API_BASE3})`).action(
|
|
33841
34085
|
async (opts) => {
|
|
33842
34086
|
try {
|
|
33843
34087
|
const base = opts.api ?? DEFAULT_API_BASE3;
|
|
33844
34088
|
const gateway = opts.gateway ?? DEFAULT_GATEWAY;
|
|
33845
34089
|
const category = normalizeCategory(opts.category);
|
|
34090
|
+
const slug = opts.service?.trim().toLowerCase() || void 0;
|
|
33846
34091
|
const agent = await withAgent({ keyPath: opts.key });
|
|
33847
34092
|
const address = agent.address();
|
|
33848
34093
|
if (opts.remove) {
|
|
33849
34094
|
const ts2 = Date.now();
|
|
33850
|
-
const msg2 = `t2000-deploy-remove:${ts2}`;
|
|
34095
|
+
const msg2 = `t2000-deploy-remove:${ts2}${slug ? `:${slug}` : ""}`;
|
|
33851
34096
|
const { signature: signature2 } = await agent.keypair.signPersonalMessage(
|
|
33852
34097
|
new TextEncoder().encode(msg2)
|
|
33853
34098
|
);
|
|
33854
|
-
await
|
|
34099
|
+
await fetchJson2(`${gateway}/deploy/config`, {
|
|
33855
34100
|
method: "DELETE",
|
|
33856
|
-
body: { address, timestamp: ts2, signature: signature2 }
|
|
34101
|
+
body: { address, timestamp: ts2, signature: signature2, ...slug ? { slug } : {} }
|
|
33857
34102
|
});
|
|
33858
|
-
|
|
33859
|
-
|
|
33860
|
-
|
|
33861
|
-
|
|
33862
|
-
|
|
33863
|
-
|
|
33864
|
-
|
|
34103
|
+
if (!slug) {
|
|
34104
|
+
await runSponsoredTx({
|
|
34105
|
+
keypair: agent.keypair,
|
|
34106
|
+
actor: address,
|
|
34107
|
+
prepareUrl: `${base}/agent/service/prepare`,
|
|
34108
|
+
prepareBody: { address, mcpEndpoint: "" },
|
|
34109
|
+
submitUrl: `${base}/agent/service/submit`
|
|
34110
|
+
}).catch(() => void 0);
|
|
34111
|
+
}
|
|
33865
34112
|
if (isJsonMode()) {
|
|
33866
34113
|
printJson({ address, removed: true });
|
|
33867
34114
|
return;
|
|
@@ -33881,12 +34128,14 @@ Subcommands:
|
|
|
33881
34128
|
const method = (opts.method ?? "POST").toUpperCase() === "GET" ? "GET" : "POST";
|
|
33882
34129
|
const headers = opts.header ?? {};
|
|
33883
34130
|
const ts = Date.now();
|
|
33884
|
-
const bodyHash =
|
|
34131
|
+
const bodyHash = createHash2("sha256").update(
|
|
34132
|
+
`${opts.upstream}|${method}|${JSON.stringify(headers)}${slug ? `|${slug}` : ""}`
|
|
34133
|
+
).digest("hex");
|
|
33885
34134
|
const msg = `t2000-deploy:${ts}:${bodyHash}`;
|
|
33886
34135
|
const { signature } = await agent.keypair.signPersonalMessage(
|
|
33887
34136
|
new TextEncoder().encode(msg)
|
|
33888
34137
|
);
|
|
33889
|
-
await
|
|
34138
|
+
await fetchJson2(`${gateway}/deploy/config`, {
|
|
33890
34139
|
method: "POST",
|
|
33891
34140
|
body: {
|
|
33892
34141
|
address,
|
|
@@ -33894,9 +34143,25 @@ Subcommands:
|
|
|
33894
34143
|
signature,
|
|
33895
34144
|
upstreamUrl: opts.upstream,
|
|
33896
34145
|
method,
|
|
33897
|
-
headers
|
|
34146
|
+
headers,
|
|
34147
|
+
...slug ? { slug } : {}
|
|
33898
34148
|
}
|
|
33899
34149
|
});
|
|
34150
|
+
if (slug) {
|
|
34151
|
+
if (isJsonMode()) {
|
|
34152
|
+
printJson({ address, slug, upstream: opts.upstream, price });
|
|
34153
|
+
return;
|
|
34154
|
+
}
|
|
34155
|
+
printBlank();
|
|
34156
|
+
printSuccess(`Wrap config stored for service "${slug}".`);
|
|
34157
|
+
printKeyValue("Wraps", opts.upstream);
|
|
34158
|
+
printKeyValue("Buy URL", `${DEFAULT_RAIL}/commerce/pay/${address}/${slug}`);
|
|
34159
|
+
printInfo(
|
|
34160
|
+
`List it in the catalog: t2 agent services add --slug ${slug} --title \u2026 --description \u2026 --price ${opts.price}`
|
|
34161
|
+
);
|
|
34162
|
+
printBlank();
|
|
34163
|
+
return;
|
|
34164
|
+
}
|
|
33900
34165
|
const { digest } = await runSponsoredTx({
|
|
33901
34166
|
keypair: agent.keypair,
|
|
33902
34167
|
actor: address,
|
|
@@ -33935,6 +34200,9 @@ Subcommands:
|
|
|
33935
34200
|
group.command("pay").argument("<seller>", "The seller agent's Sui address").description(
|
|
33936
34201
|
"Pay a seller agent for a service (gateway-mediated, USDC). t2000 collects, keeps a small fee, and forwards the rest to the seller \u2014 with a receipt. [Agent Commerce]"
|
|
33937
34202
|
).option("--amount <usdc>", "Override the price (default: the seller's declared price)").option("--data <json>", "Service input forwarded to the seller's endpoint").option("--max-price <usdc>", "Max USDC to auto-approve (default 1.00, or --amount)").option(
|
|
34203
|
+
"--service <slug>",
|
|
34204
|
+
"Catalog service slug \u2014 buys ONE SKU of the seller's catalog (Store v2)"
|
|
34205
|
+
).option(
|
|
33938
34206
|
"--gateway <url>",
|
|
33939
34207
|
`Gateway base URL (default ${DEFAULT_GATEWAY})`
|
|
33940
34208
|
).option("--force", "Override spending limits for this call (see `t2 limit`)").option("--key <path>", "Custom wallet path (default ~/.t2000/wallet.key)").action(
|
|
@@ -33950,7 +34218,8 @@ Subcommands:
|
|
|
33950
34218
|
const gateway = opts.gateway ?? DEFAULT_GATEWAY;
|
|
33951
34219
|
const agent = await withAgent({ keyPath: opts.key });
|
|
33952
34220
|
const resolvedSeller = seller.startsWith("0x") ? seller : (await agent.resolveRecipient(seller)).address;
|
|
33953
|
-
const
|
|
34221
|
+
const slugPath = opts.service ? `/${opts.service.trim().toLowerCase()}` : "";
|
|
34222
|
+
const url = opts.amount ? `${gateway}/commerce/pay/${resolvedSeller}${slugPath}?amount=${encodeURIComponent(opts.amount)}` : `${gateway}/commerce/pay/${resolvedSeller}${slugPath}`;
|
|
33954
34223
|
const result = await agent.pay({
|
|
33955
34224
|
url,
|
|
33956
34225
|
method: "POST",
|
|
@@ -34019,7 +34288,7 @@ Subcommands:
|
|
|
34019
34288
|
const gateway = opts.gateway ?? DEFAULT_GATEWAY;
|
|
34020
34289
|
const agent = await withAgent({ keyPath: opts.key });
|
|
34021
34290
|
const address = agent.address();
|
|
34022
|
-
const stats = await
|
|
34291
|
+
const stats = await fetchJson2(
|
|
34023
34292
|
`${gateway}/commerce/stats/${address}`,
|
|
34024
34293
|
{ method: "GET" }
|
|
34025
34294
|
);
|
|
@@ -34048,7 +34317,7 @@ Subcommands:
|
|
|
34048
34317
|
const base = opts.api ?? DEFAULT_API_BASE3;
|
|
34049
34318
|
const agent = await withAgent({ keyPath: opts.key });
|
|
34050
34319
|
const address = agent.address();
|
|
34051
|
-
const challenge = await
|
|
34320
|
+
const challenge = await fetchJson2(`${base}/agent/challenge`, {
|
|
34052
34321
|
method: "POST",
|
|
34053
34322
|
body: { address }
|
|
34054
34323
|
});
|
|
@@ -34060,7 +34329,7 @@ Subcommands:
|
|
|
34060
34329
|
const message = new TextEncoder().encode(`${action}:${nonce}:${label}`);
|
|
34061
34330
|
const { signature } = await agent.keypair.signPersonalMessage(message);
|
|
34062
34331
|
const path2 = opts.release ? "/agent/handle/release" : "/agent/handle";
|
|
34063
|
-
const res = await
|
|
34332
|
+
const res = await fetchJson2(`${base}${path2}`, {
|
|
34064
34333
|
method: "POST",
|
|
34065
34334
|
body: { address, label, nonce, signature }
|
|
34066
34335
|
});
|