@t2000/cli 6.0.0 → 8.0.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
@@ -33122,7 +33122,7 @@ function registerMcpStart(parent) {
33122
33122
  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) => {
33123
33123
  let mod3;
33124
33124
  try {
33125
- mod3 = await import("./dist-DYYYQUW7.js");
33125
+ mod3 = await import("./dist-BOOS6EPV.js");
33126
33126
  } catch {
33127
33127
  console.error("MCP server not installed. Run:\n npm install -g @t2000/mcp");
33128
33128
  process.exit(1);
@@ -33594,9 +33594,6 @@ For MCP-aware clients (Claude Desktop, Cursor, Windsurf), prefer
33594
33594
  registerSkillsUninstall(group);
33595
33595
  }
33596
33596
 
33597
- // src/commands/agent/index.ts
33598
- import { createHash as createHash2 } from "crypto";
33599
-
33600
33597
  // src/commands/agent/create.ts
33601
33598
  var DEFAULT_API_BASE3 = process.env.T2000_API_URL ?? "https://api.t2000.ai/v1";
33602
33599
  var STORE_BASE = "https://agents.t2000.ai";
@@ -33630,7 +33627,7 @@ function registerAgentCreate(group) {
33630
33627
  "Create an agent in one pass \u2014 wallet + on-chain Agent ID + profile (+ optional owner link). Sponsored, gasless."
33631
33628
  ).requiredOption("--name <name>", "Display name (shown in the store)").option("--description <text>", "Short description (what it does, for whom)").option(
33632
33629
  "--category <category>",
33633
- `Storefront category: ${AGENT_CATEGORIES.join(" | ")}`
33630
+ `Directory category: ${AGENT_CATEGORIES.join(" | ")}`
33634
33631
  ).option(
33635
33632
  "--owner <address>",
33636
33633
  "Propose a Passport owner (confirm at agents.t2000.ai \u2192 My agents)"
@@ -33745,236 +33742,7 @@ function registerAgentCreate(group) {
33745
33742
  printBlank();
33746
33743
  printLine("Next:");
33747
33744
  printLine(" t2 fund # add USDC (QR / card link)");
33748
- printLine(" t2 agent services add ... # list something to sell");
33749
- printLine(" t2 agent deploy ... # wrap an API behind x402");
33750
- printBlank();
33751
- } catch (error) {
33752
- handleError(error);
33753
- }
33754
- });
33755
- }
33756
-
33757
- // src/commands/agent/services.ts
33758
- import { createHash } from "crypto";
33759
- import { readFileSync as readFileSync3 } from "fs";
33760
- var SLUG_RE = /^[a-z0-9][a-z0-9-]{1,39}$/;
33761
- async function fetchJson2(url, init) {
33762
- const res = await fetch(url, {
33763
- method: init?.method ?? "GET",
33764
- headers: init?.body ? { "Content-Type": "application/json" } : void 0,
33765
- body: init?.body ? JSON.stringify(init.body) : void 0
33766
- });
33767
- const json = await res.json().catch(() => ({}));
33768
- if (!res.ok) {
33769
- const err = json.error;
33770
- const msg = typeof err === "string" ? err : err?.message ?? `HTTP ${res.status}`;
33771
- throw new Error(msg);
33772
- }
33773
- return json;
33774
- }
33775
- function canonicalServicesJson(services) {
33776
- return JSON.stringify(
33777
- services.map(
33778
- (s) => Object.fromEntries(
33779
- Object.entries(s).sort(([a], [b]) => a.localeCompare(b))
33780
- )
33781
- )
33782
- );
33783
- }
33784
- async function getCatalog(base, address) {
33785
- const res = await fetchJson2(
33786
- `${base}/agent/services?address=${encodeURIComponent(address)}`
33787
- );
33788
- return Array.isArray(res.services) ? res.services : [];
33789
- }
33790
- async function putCatalog(opts) {
33791
- const agent = await withAgent({ keyPath: opts.keyPath });
33792
- const address = agent.address();
33793
- const challenge = await fetchJson2(`${opts.base}/agent/challenge`, {
33794
- method: "POST",
33795
- body: { address }
33796
- });
33797
- const nonce = challenge.nonce;
33798
- if (!nonce) {
33799
- throw new Error("Failed to get a challenge nonce.");
33800
- }
33801
- const digest = createHash("sha256").update(canonicalServicesJson(opts.services)).digest("hex");
33802
- const message = new TextEncoder().encode(
33803
- `t2000-agent-services:${nonce}:${digest}`
33804
- );
33805
- const { signature } = await agent.keypair.signPersonalMessage(message);
33806
- const res = await fetchJson2(`${opts.base}/agent/services`, {
33807
- method: "POST",
33808
- body: { address, nonce, signature, services: opts.services }
33809
- });
33810
- return { address, count: Number(res.count ?? opts.services.length) };
33811
- }
33812
- function entryFromFlags(opts) {
33813
- const slug = String(opts.slug ?? "").trim().toLowerCase();
33814
- if (!SLUG_RE.test(slug)) {
33815
- throw new Error("--slug is required: [a-z0-9-], 2-40 chars.");
33816
- }
33817
- const out = { slug };
33818
- if (opts.title !== void 0) {
33819
- out.title = opts.title;
33820
- }
33821
- if (opts.description !== void 0) {
33822
- out.description = opts.description;
33823
- }
33824
- if (opts.price !== void 0) {
33825
- out.priceUsdc = opts.price;
33826
- }
33827
- if (opts.input !== void 0) {
33828
- out.input = opts.input || null;
33829
- }
33830
- if (opts.endpoint !== void 0) {
33831
- out.endpoint = opts.endpoint || null;
33832
- }
33833
- if (opts.method !== void 0) {
33834
- out.method = opts.method.toUpperCase() === "GET" ? "GET" : "POST";
33835
- }
33836
- return out;
33837
- }
33838
- function registerAgentServices(agentGroup, defaults) {
33839
- const group = agentGroup.command("services").description(
33840
- "Manage this agent's service CATALOG (one agent, many services). Buy URLs: commerce/pay/<agent>/<slug>. [Store v2]"
33841
- );
33842
- 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) => {
33843
- try {
33844
- const base = opts.api ?? defaults.apiBase;
33845
- const address = addressArg ?? (await withAgent({ keyPath: opts.key })).address();
33846
- const services = await getCatalog(base, address);
33847
- if (isJsonMode()) {
33848
- printJson({ address, services });
33849
- return;
33850
- }
33851
- printBlank();
33852
- if (services.length === 0) {
33853
- printLine("No services in the catalog. Add one: t2 agent services add --slug <slug> --title \u2026 --description \u2026 --price \u2026");
33854
- printBlank();
33855
- return;
33856
- }
33857
- for (const s of services) {
33858
- printKeyValue(
33859
- s.slug,
33860
- `$${s.priceUsdc} \u2014 ${s.title}${s.active === false ? " (inactive)" : ""}`
33861
- );
33862
- }
33863
- printBlank();
33864
- } catch (error) {
33865
- handleError(error);
33866
- }
33867
- });
33868
- 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) => {
33869
- try {
33870
- const base = opts.api ?? defaults.apiBase;
33871
- const agent = await withAgent({ keyPath: opts.key });
33872
- const current = await getCatalog(base, agent.address());
33873
- const entry = entryFromFlags(opts);
33874
- if (current.some((s) => s.slug === entry.slug)) {
33875
- throw new Error(
33876
- `Slug "${entry.slug}" already exists \u2014 use: t2 agent services update --slug ${entry.slug}`
33877
- );
33878
- }
33879
- const next = {
33880
- title: "",
33881
- description: "",
33882
- priceUsdc: "0",
33883
- active: true,
33884
- ...entry
33885
- };
33886
- const { count } = await putCatalog({
33887
- base,
33888
- keyPath: opts.key,
33889
- services: [...current, next]
33890
- });
33891
- if (isJsonMode()) {
33892
- printJson({ added: entry.slug, count });
33893
- return;
33894
- }
33895
- printBlank();
33896
- printSuccess(`Service "${entry.slug}" added \u2014 catalog now ${count} service${count === 1 ? "" : "s"}.`);
33897
- printLine(`Buy URL: https://x402.t2000.ai/commerce/pay/${agent.address()}/${entry.slug}`);
33898
- printBlank();
33899
- } catch (error) {
33900
- handleError(error);
33901
- }
33902
- });
33903
- 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) => {
33904
- try {
33905
- const base = opts.api ?? defaults.apiBase;
33906
- const agent = await withAgent({ keyPath: opts.key });
33907
- const current = await getCatalog(base, agent.address());
33908
- const entry = entryFromFlags(opts);
33909
- const idx = current.findIndex((s) => s.slug === entry.slug);
33910
- if (idx === -1) {
33911
- throw new Error(`No service "${entry.slug}" in the catalog.`);
33912
- }
33913
- const merged = { ...current[idx], ...entry };
33914
- if (opts.active !== void 0) {
33915
- merged.active = String(opts.active).toLowerCase() !== "false";
33916
- }
33917
- const services = [...current];
33918
- services[idx] = merged;
33919
- const { count } = await putCatalog({ base, keyPath: opts.key, services });
33920
- if (isJsonMode()) {
33921
- printJson({ updated: entry.slug, count });
33922
- return;
33923
- }
33924
- printBlank();
33925
- printSuccess(`Service "${entry.slug}" updated.`);
33926
- printBlank();
33927
- } catch (error) {
33928
- handleError(error);
33929
- }
33930
- });
33931
- 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) => {
33932
- try {
33933
- const base = opts.api ?? defaults.apiBase;
33934
- const agent = await withAgent({ keyPath: opts.key });
33935
- const slug = String(opts.slug ?? "").trim().toLowerCase();
33936
- const current = await getCatalog(base, agent.address());
33937
- const services = current.filter((s) => s.slug !== slug);
33938
- if (services.length === current.length) {
33939
- throw new Error(`No service "${slug}" in the catalog.`);
33940
- }
33941
- const { count } = await putCatalog({ base, keyPath: opts.key, services });
33942
- if (isJsonMode()) {
33943
- printJson({ removed: slug, count });
33944
- return;
33945
- }
33946
- printBlank();
33947
- printSuccess(`Service "${slug}" removed \u2014 catalog now ${count} service${count === 1 ? "" : "s"}.`);
33948
- printBlank();
33949
- } catch (error) {
33950
- handleError(error);
33951
- }
33952
- });
33953
- group.command("sync").description(
33954
- "Declarative catalog sync \u2014 the manifest file IS the catalog (adds/updates/removes to match). The catalog-scale path."
33955
- ).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) => {
33956
- try {
33957
- const base = opts.api ?? defaults.apiBase;
33958
- const raw = JSON.parse(readFileSync3(file, "utf8"));
33959
- const list = Array.isArray(raw) ? raw : raw?.services ?? null;
33960
- if (!Array.isArray(list)) {
33961
- throw new Error(
33962
- 'Manifest must be a JSON array of services (or { "services": [...] }).'
33963
- );
33964
- }
33965
- const services = list.map((s) => {
33966
- const entry = s;
33967
- return { ...entry, active: entry.active !== false };
33968
- });
33969
- const agent = await withAgent({ keyPath: opts.key });
33970
- const before = await getCatalog(base, agent.address());
33971
- const { count } = await putCatalog({ base, keyPath: opts.key, services });
33972
- if (isJsonMode()) {
33973
- printJson({ synced: count, before: before.length });
33974
- return;
33975
- }
33976
- printBlank();
33977
- printSuccess(`Catalog synced \u2014 ${before.length} \u2192 ${count} services.`);
33745
+ printLine(" agents.t2000.ai/skills # give it skills to act on Sui");
33978
33746
  printBlank();
33979
33747
  } catch (error) {
33980
33748
  handleError(error);
@@ -33984,36 +33752,6 @@ function registerAgentServices(agentGroup, defaults) {
33984
33752
 
33985
33753
  // src/commands/agent/index.ts
33986
33754
  var DEFAULT_API_BASE4 = process.env.T2000_API_URL ?? "https://api.t2000.ai/v1";
33987
- var DEFAULT_GATEWAY = process.env.T2000_GATEWAY_URL ?? "https://mpp.t2000.ai";
33988
- var DEFAULT_RAIL = process.env.T2000_RAIL_URL ?? "https://x402.t2000.ai";
33989
- var AGENT_CATEGORIES2 = [
33990
- "ai-models",
33991
- "data-feeds",
33992
- "finance",
33993
- "research",
33994
- "dev-tools",
33995
- "creative",
33996
- "other"
33997
- ];
33998
- function normalizeCategory(input) {
33999
- if (input === void 0) {
34000
- return;
34001
- }
34002
- const c = input.trim().toLowerCase();
34003
- if (!AGENT_CATEGORIES2.includes(c)) {
34004
- throw new Error(
34005
- `--category must be one of: ${AGENT_CATEGORIES2.join(", ")} (got "${input}").`
34006
- );
34007
- }
34008
- return c;
34009
- }
34010
- function collectHeader(value, previous) {
34011
- const [key, ...rest] = value.split("=");
34012
- if (key && rest.length > 0) {
34013
- previous[key.trim()] = rest.join("=").trim();
34014
- }
34015
- return previous;
34016
- }
34017
33755
  function normalizeTopupAsset(input) {
34018
33756
  return input?.toLowerCase() === "usdsui" ? "USDsui" : "USDC";
34019
33757
  }
@@ -34023,19 +33761,19 @@ async function fundCredit(agent, base, amountStr, assetOpt) {
34023
33761
  throw new Error(`amount must be a positive number (got "${amountStr}").`);
34024
33762
  }
34025
33763
  const asset = normalizeTopupAsset(assetOpt);
34026
- const cfg = await fetchJson3(`${base}/agent/topup`, { method: "GET" });
33764
+ const cfg = await fetchJson2(`${base}/agent/topup`, { method: "GET" });
34027
33765
  const treasury = cfg.treasury;
34028
33766
  if (!treasury) {
34029
33767
  throw new Error("Could not resolve the t2000 treasury address.");
34030
33768
  }
34031
33769
  const sent = await agent.send({ to: treasury, amount, asset });
34032
- const topup = await fetchJson3(`${base}/agent/topup`, {
33770
+ const topup = await fetchJson2(`${base}/agent/topup`, {
34033
33771
  method: "POST",
34034
33772
  body: { address: agent.address(), digest: sent.tx }
34035
33773
  });
34036
33774
  return { amount, asset, balanceUsd: topup.balanceUsd };
34037
33775
  }
34038
- async function fetchJson3(url, init) {
33776
+ async function fetchJson2(url, init) {
34039
33777
  const res = await fetch(url, {
34040
33778
  method: init.method,
34041
33779
  headers: init.body ? { "Content-Type": "application/json" } : void 0,
@@ -34058,12 +33796,9 @@ Subcommands:
34058
33796
  $ t2 agent onboard --fund 5 Fund 5 USDC \u2192 mint an API key (ready to call)
34059
33797
  $ t2 agent onboard --fund 5 --asset USDsui
34060
33798
  $ t2 agent onboard Already funded \u2192 just mint a key
34061
- $ t2 agent services add --slug sui-price --title "SUI spot" --description "\u2026" --price 0.02
34062
- $ t2 agent services sync ./services.json Manifest IS the catalog (catalog-scale sellers)
34063
33799
  `
34064
33800
  );
34065
33801
  registerAgentCreate(group);
34066
- registerAgentServices(group, { apiBase: DEFAULT_API_BASE4 });
34067
33802
  group.command("onboard").description(
34068
33803
  "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`."
34069
33804
  ).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_BASE4})`).action(
@@ -34080,7 +33815,7 @@ Subcommands:
34080
33815
  );
34081
33816
  }
34082
33817
  }
34083
- const challenge = await fetchJson3(`${base}/agent/challenge`, {
33818
+ const challenge = await fetchJson2(`${base}/agent/challenge`, {
34084
33819
  method: "POST",
34085
33820
  body: { address }
34086
33821
  });
@@ -34090,7 +33825,7 @@ Subcommands:
34090
33825
  }
34091
33826
  const message = new TextEncoder().encode(`t2000-agent-keys:${nonce}`);
34092
33827
  const { signature } = await agent.keypair.signPersonalMessage(message);
34093
- const minted = await fetchJson3(`${base}/agent/keys`, {
33828
+ const minted = await fetchJson2(`${base}/agent/keys`, {
34094
33829
  method: "POST",
34095
33830
  body: { address, nonce, signature }
34096
33831
  });
@@ -34287,7 +34022,7 @@ Subcommands:
34287
34022
  const base = opts.api ?? DEFAULT_API_BASE4;
34288
34023
  const agent = await withAgent({ keyPath: opts.key });
34289
34024
  const address = agent.address();
34290
- const challenge = await fetchJson3(`${base}/agent/challenge`, {
34025
+ const challenge = await fetchJson2(`${base}/agent/challenge`, {
34291
34026
  method: "POST",
34292
34027
  body: { address }
34293
34028
  });
@@ -34297,7 +34032,7 @@ Subcommands:
34297
34032
  }
34298
34033
  const message = new TextEncoder().encode(`t2000-agent-profile:${nonce}`);
34299
34034
  const { signature } = await agent.keypair.signPersonalMessage(message);
34300
- await fetchJson3(`${base}/agent/profile`, {
34035
+ await fetchJson2(`${base}/agent/profile`, {
34301
34036
  method: "POST",
34302
34037
  body: {
34303
34038
  address,
@@ -34323,318 +34058,6 @@ Subcommands:
34323
34058
  }
34324
34059
  }
34325
34060
  );
34326
- group.command("service").description(
34327
- "Declare this agent's paid service \u2014 an MCP endpoint + accepted payment methods (e.g. x402). Sponsored, gasless. Lights up Service / x402 in the directory."
34328
- ).option("--mcp-endpoint <url>", "Your agent service endpoint (https)").option(
34329
- "--payment-methods <list>",
34330
- 'Comma-separated methods you accept, e.g. "x402"'
34331
- ).option("--price <usdc>", "Price per call in USDC (e.g. 0.02) \u2014 buyers pay this").option(
34332
- "--category <category>",
34333
- `Storefront category: ${AGENT_CATEGORIES2.join(" | ")}`
34334
- ).option("--key <path>", "Custom wallet path (default ~/.t2000/wallet.key)").option("--api <url>", `API base URL (default ${DEFAULT_API_BASE4})`).action(
34335
- async (opts) => {
34336
- try {
34337
- if (opts.mcpEndpoint === void 0 && opts.paymentMethods === void 0 && opts.price === void 0 && opts.category === void 0) {
34338
- throw new Error(
34339
- 'Provide at least one of --mcp-endpoint, --payment-methods, --price, --category. (Pass --mcp-endpoint "" to clear your endpoint.)'
34340
- );
34341
- }
34342
- if (opts.price !== void 0) {
34343
- const p = Number.parseFloat(opts.price);
34344
- if (Number.isNaN(p) || p <= 0) {
34345
- throw new Error(`--price must be a positive number (got "${opts.price}").`);
34346
- }
34347
- }
34348
- const category = normalizeCategory(opts.category);
34349
- const base = opts.api ?? DEFAULT_API_BASE4;
34350
- const agent = await withAgent({ keyPath: opts.key });
34351
- const address = agent.address();
34352
- const prepareBody = { address };
34353
- if (opts.mcpEndpoint !== void 0) {
34354
- prepareBody.mcpEndpoint = opts.mcpEndpoint;
34355
- }
34356
- if (opts.paymentMethods !== void 0) {
34357
- prepareBody.paymentMethods = opts.paymentMethods.split(",").map((s) => s.trim()).filter(Boolean);
34358
- }
34359
- if (opts.price !== void 0) {
34360
- prepareBody.priceUsdc = opts.price;
34361
- }
34362
- if (category !== void 0) {
34363
- prepareBody.category = category;
34364
- }
34365
- const { digest } = await runSponsoredTx({
34366
- keypair: agent.keypair,
34367
- actor: address,
34368
- prepareUrl: `${base}/agent/service/prepare`,
34369
- prepareBody,
34370
- submitUrl: `${base}/agent/service/submit`
34371
- });
34372
- if (isJsonMode()) {
34373
- printJson({ address, updated: true, digest });
34374
- return;
34375
- }
34376
- printBlank();
34377
- printSuccess("Service declared \u2014 showing in the directory.");
34378
- if (opts.mcpEndpoint) {
34379
- printKeyValue("MCP endpoint", opts.mcpEndpoint);
34380
- }
34381
- if (opts.paymentMethods) {
34382
- printKeyValue("Payment methods", opts.paymentMethods);
34383
- }
34384
- if (opts.price) {
34385
- printKeyValue("Price", `$${opts.price} USDC`);
34386
- }
34387
- if (category) {
34388
- printKeyValue("Category", category);
34389
- }
34390
- printKeyValue("Tx", String(digest));
34391
- printBlank();
34392
- } catch (error) {
34393
- handleError(error);
34394
- }
34395
- }
34396
- );
34397
- group.command("deploy").description(
34398
- "Deploy a paid service by wrapping any HTTP API \u2014 t2000 hosts the proxy (your key stays server-side, encrypted), lists it, and settles payments. No server needed. Use --remove to take it down. [Agent Commerce]"
34399
- ).option("--upstream <url>", "The upstream API URL to wrap (https)").option(
34400
- "--header <k=v>",
34401
- "Header to inject into upstream calls (repeatable; e.g. your API key)",
34402
- collectHeader,
34403
- {}
34404
- ).option("--method <method>", "Upstream method: GET or POST (default POST)").option("--price <usdc>", "Price per call in USDC (e.g. 0.02)").option(
34405
- "--category <category>",
34406
- `Storefront category: ${AGENT_CATEGORIES2.join(" | ")}`
34407
- ).option("--remove", "Take down the deployed service").option(
34408
- "--service <slug>",
34409
- "Catalog service slug \u2014 wrap config for ONE SKU (Store v2; omit = the default service)"
34410
- ).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_BASE4})`).action(
34411
- async (opts) => {
34412
- try {
34413
- const base = opts.api ?? DEFAULT_API_BASE4;
34414
- const gateway = opts.gateway ?? DEFAULT_GATEWAY;
34415
- const category = normalizeCategory(opts.category);
34416
- const slug = opts.service?.trim().toLowerCase() || void 0;
34417
- const agent = await withAgent({ keyPath: opts.key });
34418
- const address = agent.address();
34419
- if (opts.remove) {
34420
- const ts2 = Date.now();
34421
- const msg2 = `t2000-deploy-remove:${ts2}${slug ? `:${slug}` : ""}`;
34422
- const { signature: signature2 } = await agent.keypair.signPersonalMessage(
34423
- new TextEncoder().encode(msg2)
34424
- );
34425
- await fetchJson3(`${gateway}/deploy/config`, {
34426
- method: "DELETE",
34427
- body: { address, timestamp: ts2, signature: signature2, ...slug ? { slug } : {} }
34428
- });
34429
- if (!slug) {
34430
- await runSponsoredTx({
34431
- keypair: agent.keypair,
34432
- actor: address,
34433
- prepareUrl: `${base}/agent/service/prepare`,
34434
- prepareBody: { address, mcpEndpoint: "" },
34435
- submitUrl: `${base}/agent/service/submit`
34436
- }).catch(() => void 0);
34437
- }
34438
- if (isJsonMode()) {
34439
- printJson({ address, removed: true });
34440
- return;
34441
- }
34442
- printBlank();
34443
- printSuccess("Service taken down.");
34444
- printBlank();
34445
- return;
34446
- }
34447
- if (!(opts.upstream && opts.price)) {
34448
- throw new Error("Both --upstream and --price are required (or use --remove).");
34449
- }
34450
- const price = Number.parseFloat(opts.price);
34451
- if (Number.isNaN(price) || price <= 0) {
34452
- throw new Error(`--price must be a positive number (got "${opts.price}").`);
34453
- }
34454
- const method = (opts.method ?? "POST").toUpperCase() === "GET" ? "GET" : "POST";
34455
- const headers = opts.header ?? {};
34456
- const ts = Date.now();
34457
- const bodyHash = createHash2("sha256").update(
34458
- `${opts.upstream}|${method}|${JSON.stringify(headers)}${slug ? `|${slug}` : ""}`
34459
- ).digest("hex");
34460
- const msg = `t2000-deploy:${ts}:${bodyHash}`;
34461
- const { signature } = await agent.keypair.signPersonalMessage(
34462
- new TextEncoder().encode(msg)
34463
- );
34464
- await fetchJson3(`${gateway}/deploy/config`, {
34465
- method: "POST",
34466
- body: {
34467
- address,
34468
- timestamp: ts,
34469
- signature,
34470
- upstreamUrl: opts.upstream,
34471
- method,
34472
- headers,
34473
- ...slug ? { slug } : {}
34474
- }
34475
- });
34476
- if (slug) {
34477
- if (isJsonMode()) {
34478
- printJson({ address, slug, upstream: opts.upstream, price });
34479
- return;
34480
- }
34481
- printBlank();
34482
- printSuccess(`Wrap config stored for service "${slug}".`);
34483
- printKeyValue("Wraps", opts.upstream);
34484
- printKeyValue("Buy URL", `${DEFAULT_RAIL}/commerce/pay/${address}/${slug}`);
34485
- printInfo(
34486
- `List it in the catalog: t2 agent services add --slug ${slug} --title \u2026 --description \u2026 --price ${opts.price}`
34487
- );
34488
- printBlank();
34489
- return;
34490
- }
34491
- const { digest } = await runSponsoredTx({
34492
- keypair: agent.keypair,
34493
- actor: address,
34494
- prepareUrl: `${base}/agent/service/prepare`,
34495
- prepareBody: {
34496
- address,
34497
- // The real, x402-callable buy endpoint (GET → 402 + requirements,
34498
- // pay → collect/deliver/forward). `/deploy/<addr>` was a phantom
34499
- // (no route → 404). Any x402 client can hit this URL.
34500
- mcpEndpoint: `${DEFAULT_RAIL}/commerce/pay/${address}`,
34501
- paymentMethods: ["x402"],
34502
- priceUsdc: opts.price,
34503
- ...category ? { category } : {}
34504
- },
34505
- submitUrl: `${base}/agent/service/submit`
34506
- });
34507
- if (isJsonMode()) {
34508
- printJson({ address, upstream: opts.upstream, price, digest });
34509
- return;
34510
- }
34511
- printBlank();
34512
- printSuccess("Service deployed \u2014 live + listed in the directory.");
34513
- printKeyValue("Wraps", opts.upstream);
34514
- printKeyValue("Price", `$${opts.price} USDC`);
34515
- if (category) {
34516
- printKeyValue("Category", category);
34517
- }
34518
- printKeyValue("Tx", String(digest));
34519
- printInfo(`Buyers: t2 agent pay ${truncateAddress(address)}`);
34520
- printBlank();
34521
- } catch (error) {
34522
- handleError(error);
34523
- }
34524
- }
34525
- );
34526
- group.command("pay").argument("<seller>", "The seller agent's Sui address").description(
34527
- "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]"
34528
- ).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(
34529
- "--service <slug>",
34530
- "Catalog service slug \u2014 buys ONE SKU of the seller's catalog (Store v2)"
34531
- ).option(
34532
- "--gateway <url>",
34533
- `Gateway base URL (default ${DEFAULT_GATEWAY})`
34534
- ).option("--force", "Override spending limits for this call (see `t2 limit`)").option("--key <path>", "Custom wallet path (default ~/.t2000/wallet.key)").action(
34535
- async (seller, opts) => {
34536
- try {
34537
- if (opts.amount !== void 0) {
34538
- const a = Number.parseFloat(opts.amount);
34539
- if (Number.isNaN(a) || a <= 0) {
34540
- throw new Error(`--amount must be a positive number (got "${opts.amount}").`);
34541
- }
34542
- }
34543
- const maxPrice = opts.maxPrice ? Number.parseFloat(opts.maxPrice) : opts.amount ? Number.parseFloat(opts.amount) : 1;
34544
- const gateway = opts.gateway ?? DEFAULT_GATEWAY;
34545
- const agent = await withAgent({ keyPath: opts.key });
34546
- const resolvedSeller = seller.startsWith("0x") ? seller : (await agent.resolveRecipient(seller)).address;
34547
- const slugPath = opts.service ? `/${opts.service.trim().toLowerCase()}` : "";
34548
- const url = opts.amount ? `${gateway}/commerce/pay/${resolvedSeller}${slugPath}?amount=${encodeURIComponent(opts.amount)}` : `${gateway}/commerce/pay/${resolvedSeller}${slugPath}`;
34549
- const result = await agent.pay({
34550
- url,
34551
- method: "POST",
34552
- body: opts.data,
34553
- maxPrice,
34554
- force: opts.force
34555
- });
34556
- const body2 = result.body;
34557
- if (result.status >= 400) {
34558
- throw new Error(
34559
- `${body2?.error ?? `Request failed (HTTP ${result.status})`}${result.paid ? "" : " \u2014 nothing was paid."}`
34560
- );
34561
- }
34562
- const receipt = body2?.receipt;
34563
- const chargedMicros = receipt?.chargedMicros ?? receipt?.grossMicros;
34564
- const paidUsd = typeof chargedMicros === "number" ? chargedMicros / 1e6 : opts.amount ? Number.parseFloat(opts.amount) : result.cost ?? 0;
34565
- if (isJsonMode()) {
34566
- printJson({
34567
- seller: resolvedSeller,
34568
- amount: paidUsd,
34569
- paid: result.paid,
34570
- cost: result.cost,
34571
- receipt,
34572
- response: body2?.response
34573
- });
34574
- return;
34575
- }
34576
- printBlank();
34577
- printSuccess(
34578
- `Paid ${formatUsd(paidUsd)} to ${seller.startsWith("0x") ? truncateAddress(seller) : `${seller} (${truncateAddress(resolvedSeller)})`}`
34579
- );
34580
- if (receipt) {
34581
- if (typeof receipt.refundMicros === "number" && receipt.refundMicros > 0 && typeof receipt.authorizedMicros === "number") {
34582
- printKeyValue(
34583
- "Authorized",
34584
- `$${(receipt.authorizedMicros / 1e6).toFixed(6)}`
34585
- );
34586
- printKeyValue("Charged", `$${paidUsd.toFixed(6)}`);
34587
- printKeyValue("Refunded", `$${(receipt.refundMicros / 1e6).toFixed(6)}`);
34588
- }
34589
- if (typeof receipt.netMicros === "number") {
34590
- printKeyValue("Seller received", `$${(receipt.netMicros / 1e6).toFixed(6)}`);
34591
- }
34592
- if (typeof receipt.feeMicros === "number") {
34593
- printKeyValue("Facilitator fee", `$${(receipt.feeMicros / 1e6).toFixed(6)}`);
34594
- }
34595
- if (receipt.forwardDigest) {
34596
- printKeyValue("Settlement tx", receipt.forwardDigest);
34597
- }
34598
- }
34599
- if (body2?.response !== void 0) {
34600
- printBlank();
34601
- printInfo("Service response:");
34602
- printLine(JSON.stringify(body2.response, null, 2));
34603
- }
34604
- printBlank();
34605
- } catch (error) {
34606
- handleError(error);
34607
- }
34608
- }
34609
- );
34610
- group.command("earnings").description(
34611
- "Your sales as a seller \u2014 count, USDC earned (net), and unique buyers, from the on-chain settlement ledger. [Agent Commerce]"
34612
- ).option("--gateway <url>", `Gateway base URL (default ${DEFAULT_GATEWAY})`).option("--key <path>", "Custom wallet path (default ~/.t2000/wallet.key)").action(async (opts) => {
34613
- try {
34614
- const gateway = opts.gateway ?? DEFAULT_GATEWAY;
34615
- const agent = await withAgent({ keyPath: opts.key });
34616
- const address = agent.address();
34617
- const stats = await fetchJson3(
34618
- `${gateway}/commerce/stats/${address}`,
34619
- { method: "GET" }
34620
- );
34621
- if (isJsonMode()) {
34622
- printJson({ address, ...stats });
34623
- return;
34624
- }
34625
- printBlank();
34626
- printSuccess(`Earnings for ${truncateAddress(address)}`);
34627
- printKeyValue("Sales", String(stats.sales ?? 0));
34628
- printKeyValue("Earned (net)", `$${(stats.volumeUsd ?? 0).toFixed(6)} USDC`);
34629
- printKeyValue("Unique buyers", String(stats.buyers ?? 0));
34630
- if (stats.lastSaleAt) {
34631
- printKeyValue("Last sale", new Date(stats.lastSaleAt).toISOString());
34632
- }
34633
- printBlank();
34634
- } catch (error) {
34635
- handleError(error);
34636
- }
34637
- });
34638
34061
  group.command("handle").argument("<label>", "Handle label (3\u201320 chars: lowercase a\u2013z, 0\u20139, hyphens)").description(
34639
34062
  "Claim <label>.agent-id.sui \u2192 this wallet (custody-minted, gasless). Use --release to give it up."
34640
34063
  ).option("--release", "Release (revoke) this handle instead of claiming it").option("--key <path>", "Custom wallet path (default ~/.t2000/wallet.key)").option("--api <url>", `API base URL (default ${DEFAULT_API_BASE4})`).action(
@@ -34643,7 +34066,7 @@ Subcommands:
34643
34066
  const base = opts.api ?? DEFAULT_API_BASE4;
34644
34067
  const agent = await withAgent({ keyPath: opts.key });
34645
34068
  const address = agent.address();
34646
- const challenge = await fetchJson3(`${base}/agent/challenge`, {
34069
+ const challenge = await fetchJson2(`${base}/agent/challenge`, {
34647
34070
  method: "POST",
34648
34071
  body: { address }
34649
34072
  });
@@ -34655,7 +34078,7 @@ Subcommands:
34655
34078
  const message = new TextEncoder().encode(`${action}:${nonce}:${label}`);
34656
34079
  const { signature } = await agent.keypair.signPersonalMessage(message);
34657
34080
  const path2 = opts.release ? "/agent/handle/release" : "/agent/handle";
34658
- const res = await fetchJson3(`${base}${path2}`, {
34081
+ const res = await fetchJson2(`${base}${path2}`, {
34659
34082
  method: "POST",
34660
34083
  body: { address, label, nonce, signature }
34661
34084
  });
@@ -34694,9 +34117,9 @@ function firstLine(text, max = 76) {
34694
34117
  return line.length > max ? `${line.slice(0, max - 1)}\u2026` : line;
34695
34118
  }
34696
34119
  function registerAgents(program3) {
34697
- program3.command("agents").argument("[address]", "Show one agent\u2019s full listing (profile + reputation)").description(
34698
- "Browse the agent store (agents.t2000.ai): priced services from the live directory, or one agent\u2019s full listing. Buy with `t2 agent pay <address>`. [Agent Commerce]"
34699
- ).option("--category <category>", "Filter the list by store category").option("--all", "Include agents without a priced service").option("--limit <n>", "Max rows (default: all)").option("--api <url>", `API base URL (default ${DEFAULT_API_BASE5})`).action(
34120
+ program3.command("agents").argument("[address]", "Show one agent\u2019s identity profile").description(
34121
+ "Look up the agent directory (agents.t2000.ai): registered on-chain Agent IDs. Read-only. [Agent ID]"
34122
+ ).option("--category <category>", "Filter the list by category").option("--limit <n>", "Max rows (default: all)").option("--api <url>", `API base URL (default ${DEFAULT_API_BASE5})`).action(
34700
34123
  async (address, opts) => {
34701
34124
  try {
34702
34125
  const base = opts.api ?? DEFAULT_API_BASE5;
@@ -34706,30 +34129,20 @@ function registerAgents(program3) {
34706
34129
  printJson(profile);
34707
34130
  return;
34708
34131
  }
34709
- const rep = profile.reputation;
34710
34132
  printBlank();
34711
34133
  printHeader(profile.name ?? truncateAddress(profile.address));
34712
34134
  printKeyValue("Address", profile.address);
34713
- if (profile.priceUsdc) {
34714
- printKeyValue(
34715
- "Price",
34716
- `${formatUsd(Number.parseFloat(profile.priceUsdc))} / call${profile.category ? ` \xB7 ${profile.category}` : ""}`
34717
- );
34135
+ if (profile.numericId != null) {
34136
+ printKeyValue("Agent ID", `#${profile.numericId}`);
34718
34137
  }
34719
34138
  if (profile.description) {
34720
34139
  printKeyValue("About", firstLine(profile.description, 90));
34721
34140
  }
34722
- if (rep) {
34723
- printKeyValue(
34724
- "Verified on the rail",
34725
- `${rep.sales ?? 0} sold \xB7 ${rep.buyers ?? 0} buyer${(rep.buyers ?? 0) === 1 ? "" : "s"} \xB7 ${formatUsd(rep.volumeUsd ?? 0)} settled${typeof rep.deliveredRate === "number" ? ` \xB7 ${Math.round(rep.deliveredRate * 100)}% delivered` : ""}`
34726
- );
34141
+ if (profile.owner) {
34142
+ printKeyValue("Owner", truncateAddress(profile.owner));
34727
34143
  }
34728
34144
  printBlank();
34729
- if (profile.priceUsdc) {
34730
- printInfo(`Buy it: t2 agent pay ${profile.address}`);
34731
- }
34732
- printInfo(`Listing: https://agents.t2000.ai/${profile.address}`);
34145
+ printInfo(`Profile: https://agents.t2000.ai/${profile.numericId ?? profile.address}`);
34733
34146
  printBlank();
34734
34147
  return;
34735
34148
  }
@@ -34738,9 +34151,6 @@ function registerAgents(program3) {
34738
34151
  `${base}/agents?limit=100`
34739
34152
  );
34740
34153
  let agents = (data.agents ?? []).filter((a) => a.active !== false);
34741
- if (!opts.all) {
34742
- agents = agents.filter((a) => a.service && a.priceUsdc);
34743
- }
34744
34154
  if (opts.category) {
34745
34155
  const cat = opts.category.trim().toLowerCase();
34746
34156
  agents = agents.filter((a) => a.category?.toLowerCase() === cat);
@@ -34752,17 +34162,16 @@ function registerAgents(program3) {
34752
34162
  }
34753
34163
  printBlank();
34754
34164
  printHeader(
34755
- `Agent store \u2014 ${agents.length} ${opts.all ? "agents" : "priced services"}${opts.category ? ` in ${opts.category}` : ""}`
34165
+ `Agent directory \u2014 ${agents.length} agents${opts.category ? ` in ${opts.category}` : ""}`
34756
34166
  );
34757
34167
  for (const a of agents) {
34758
- const price = a.priceUsdc ? formatUsd(Number.parseFloat(a.priceUsdc)).padStart(6) : " \u2014";
34759
34168
  printLine(
34760
- ` ${price} ${(a.name ?? truncateAddress(a.address)).padEnd(24).slice(0, 24)} ${a.category ?? ""}`
34169
+ ` #${String(a.numericId ?? "\u2014").padEnd(4)} ${(a.name ?? truncateAddress(a.address)).padEnd(24).slice(0, 24)} ${firstLine(a.description, 40)}`
34761
34170
  );
34762
- printLine(` ${a.address}`);
34171
+ printLine(` ${a.address}`);
34763
34172
  }
34764
34173
  printBlank();
34765
- printInfo("Detail: t2 agents <address> \xB7 Buy: t2 agent pay <address> (addresses above are complete)");
34174
+ printInfo("Detail: t2 agents <address>");
34766
34175
  printBlank();
34767
34176
  } catch (error) {
34768
34177
  handleError(error);
@@ -34792,8 +34201,7 @@ Examples:
34792
34201
  $ t2 models List the Private API model catalog
34793
34202
  $ t2 pay <url> --estimate Preview an x402 service's price + input schema (no payment)
34794
34203
  $ t2 services search "image" Discover x402 services in the gateway catalog
34795
- $ t2 agents Browse the agent store (agents.t2000.ai)
34796
- $ t2 agent pay <address> Buy an agent's service (escrowed, auto-refund on failure)
34204
+ $ t2 agents Look up the agent directory (agents.t2000.ai)
34797
34205
  $ t2 limit set --daily 100 Change the daily spend cap (default $100/day)
34798
34206
  $ t2 mcp install Connect Claude / Cursor / Windsurf
34799
34207
  $ t2 skills install Install skills as local SKILL.md files`);