@t2000/cli 10.11.1 → 10.12.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.
@@ -147219,7 +147219,7 @@ CRITICAL: When the user asks to use any external or paid API, names a provider (
147219
147219
  The wallet also trades on the t2 AGENT ECONOMY (agents.t2000.ai). It can HIRE other agents: browse structured fixed-price agent services with t2000_browse, fund an on-chain USDC escrow job with t2000_job_create, track it with t2000_jobs, settle with t2000_job_settle, and rate the seller with t2000_job_review (escrow protects both sides \u2014 no delivery means an automatic refund path). It can EARN too: list what THIS agent sells with t2000_service_create (no server or endpoint needed), watch incoming jobs with t2000_jobs (role: seller), and deliver with t2000_job_deliver \u2014 the escrow pays this wallet on release.
147220
147220
 
147221
147221
  Spending is the user's own USDC and every t2000_pay call is bounded by maxPrice; t2000_job_create locks the listed service price in escrow. For larger or multi-step spends, state the estimated cost first and proceed once the user is happy. Use t2000_balance to check funds. The v4 wallet is payments-only \u2014 there is no savings / lending surface.`;
147222
- var PKG_VERSION = "10.11.1";
147222
+ var PKG_VERSION = "10.12.0";
147223
147223
  console.log = (...args) => console.error("[log]", ...args);
147224
147224
  console.warn = (...args) => console.error("[warn]", ...args);
147225
147225
  async function startMcpServer(opts) {
@@ -147305,4 +147305,4 @@ mime-types/index.js:
147305
147305
  @scure/bip39/index.js:
147306
147306
  (*! scure-bip39 - MIT License (c) 2022 Patricio Palladino, Paul Miller (paulmillr.com) *)
147307
147307
  */
147308
- //# sourceMappingURL=dist-3SIZORGI.js.map
147308
+ //# sourceMappingURL=dist-MUMCWXCF.js.map
package/dist/index.js CHANGED
@@ -23390,7 +23390,7 @@ function registerMcpStart(parent) {
23390
23390
  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) => {
23391
23391
  let mod;
23392
23392
  try {
23393
- mod = await import("./dist-3SIZORGI.js");
23393
+ mod = await import("./dist-MUMCWXCF.js");
23394
23394
  } catch {
23395
23395
  console.error("MCP server not installed. Run:\n npm install -g @t2000/mcp");
23396
23396
  process.exit(1);
@@ -23862,9 +23862,7 @@ For MCP-aware clients (Claude Desktop, Cursor, Windsurf), prefer
23862
23862
  registerSkillsUninstall(group);
23863
23863
  }
23864
23864
 
23865
- // src/commands/agent/create.ts
23866
- var DEFAULT_API_BASE2 = process.env.T2000_API_URL ?? "https://api.t2000.ai/v1";
23867
- var STORE_BASE = "https://agents.t2000.ai";
23865
+ // src/lib/agent-category.ts
23868
23866
  var AGENT_CATEGORIES = [
23869
23867
  "ai-models",
23870
23868
  "data-feeds",
@@ -23872,8 +23870,71 @@ var AGENT_CATEGORIES = [
23872
23870
  "research",
23873
23871
  "dev-tools",
23874
23872
  "creative",
23873
+ "travel",
23874
+ "comms",
23875
23875
  "other"
23876
23876
  ];
23877
+ function parseCategory(raw) {
23878
+ const c = raw.trim().toLowerCase();
23879
+ if (!AGENT_CATEGORIES.includes(c)) {
23880
+ throw new Error(
23881
+ `--category must be one of: ${AGENT_CATEGORIES.join(", ")} (got "${raw}").`
23882
+ );
23883
+ }
23884
+ return c;
23885
+ }
23886
+ async function getJson(url, init) {
23887
+ const res = await fetch(url, {
23888
+ method: init?.method ?? "GET",
23889
+ headers: init?.body ? { "Content-Type": "application/json" } : void 0,
23890
+ body: init?.body ? JSON.stringify(init.body) : void 0
23891
+ });
23892
+ const json = await res.json().catch(() => ({}));
23893
+ if (!res.ok) {
23894
+ const err = json.error;
23895
+ const msg = typeof err === "string" ? err : err?.message ?? `HTTP ${res.status}`;
23896
+ throw new Error(msg);
23897
+ }
23898
+ return json;
23899
+ }
23900
+ async function ensureSellerCategory(opts) {
23901
+ const address = opts.agent.address();
23902
+ if (opts.category !== void 0) {
23903
+ const category = parseCategory(opts.category);
23904
+ const challenge = await getJson(`${opts.base}/agent/challenge`, {
23905
+ method: "POST",
23906
+ body: { address }
23907
+ });
23908
+ const nonce = challenge.nonce;
23909
+ if (!nonce) {
23910
+ throw new Error("Failed to get a challenge nonce.");
23911
+ }
23912
+ const message = new TextEncoder().encode(`t2000-agent-profile:${nonce}`);
23913
+ const { signature } = await opts.agent.keypair.signPersonalMessage(message);
23914
+ await getJson(`${opts.base}/agent/profile`, {
23915
+ method: "POST",
23916
+ body: { address, nonce, signature, category }
23917
+ });
23918
+ return;
23919
+ }
23920
+ let existing = null;
23921
+ try {
23922
+ const profile = await getJson(`${opts.base}/agents/${address}`);
23923
+ existing = typeof profile.category === "string" ? profile.category : null;
23924
+ } catch {
23925
+ }
23926
+ if (!existing) {
23927
+ throw new Error(
23928
+ `Pick a directory category first \u2014 buyers browse listings by category.
23929
+ Re-run with --category <${AGENT_CATEGORIES.join(" | ")}>
23930
+ (or set it once: t2 agent profile --category <category>).`
23931
+ );
23932
+ }
23933
+ }
23934
+
23935
+ // src/commands/agent/create.ts
23936
+ var DEFAULT_API_BASE2 = process.env.T2000_API_URL ?? "https://api.t2000.ai/v1";
23937
+ var STORE_BASE = "https://agents.t2000.ai";
23877
23938
  var DEFAULT_PER_TX_USD2 = 25;
23878
23939
  var DEFAULT_DAILY_USD2 = 100;
23879
23940
  async function fetchJson(url, init) {
@@ -23911,13 +23972,7 @@ function registerAgentCreate(group) {
23911
23972
  }
23912
23973
  let category;
23913
23974
  if (opts.category !== void 0) {
23914
- const c = opts.category.trim().toLowerCase();
23915
- if (!AGENT_CATEGORIES.includes(c)) {
23916
- throw new Error(
23917
- `--category must be one of: ${AGENT_CATEGORIES.join(", ")} (got "${opts.category}").`
23918
- );
23919
- }
23920
- category = c;
23975
+ category = parseCategory(opts.category);
23921
23976
  }
23922
23977
  let owner;
23923
23978
  if (opts.owner !== void 0) {
@@ -24372,14 +24427,18 @@ Subcommands:
24372
24427
  });
24373
24428
  group.command("profile").description(
24374
24429
  "Set this agent's public profile (name \xB7 image \xB7 description \xB7 links). Signed, no gas \u2014 shows in the directory."
24375
- ).option("--name <name>", "Display name").option("--image <url>", "Image URL (https)").option("--description <text>", "Short description").option("--website <url>", "Website link (https)").option("--twitter <url>", "X / Twitter link (https)").option("--github <url>", "GitHub link (https)").option("--key <path>", "Custom wallet path (default ~/.t2000/wallet.key)").option("--api <url>", `API base URL (default ${DEFAULT_API_BASE3})`).action(
24430
+ ).option("--name <name>", "Display name").option("--image <url>", "Image URL (https)").option("--description <text>", "Short description").option(
24431
+ "--category <category>",
24432
+ `Directory category: ${AGENT_CATEGORIES.join(" | ")}`
24433
+ ).option("--website <url>", "Website link (https)").option("--twitter <url>", "X / Twitter link (https)").option("--github <url>", "GitHub link (https)").option("--key <path>", "Custom wallet path (default ~/.t2000/wallet.key)").option("--api <url>", `API base URL (default ${DEFAULT_API_BASE3})`).action(
24376
24434
  async (opts) => {
24377
24435
  try {
24378
- if (!(opts.name || opts.image || opts.description || opts.website || opts.twitter || opts.github)) {
24436
+ if (!(opts.name || opts.image || opts.description || opts.category || opts.website || opts.twitter || opts.github)) {
24379
24437
  throw new Error(
24380
- "Provide at least one of --name, --image, --description, --website, --twitter, --github."
24438
+ "Provide at least one of --name, --image, --description, --category, --website, --twitter, --github."
24381
24439
  );
24382
24440
  }
24441
+ const category = opts.category === void 0 ? void 0 : parseCategory(opts.category);
24383
24442
  const base = opts.api ?? DEFAULT_API_BASE3;
24384
24443
  const agent = await withAgent({ keyPath: opts.key });
24385
24444
  const address = agent.address();
@@ -24402,6 +24461,7 @@ Subcommands:
24402
24461
  displayName: opts.name,
24403
24462
  imageUrl: opts.image,
24404
24463
  description: opts.description,
24464
+ category,
24405
24465
  website: opts.website,
24406
24466
  twitter: opts.twitter,
24407
24467
  github: opts.github
@@ -24424,7 +24484,10 @@ Subcommands:
24424
24484
  "Your x402 endpoint URL (https). Omit with --remove to clear the listing."
24425
24485
  ).description(
24426
24486
  'List your x402 endpoint on your public Agent ID profile. The endpoint is live-probed (must answer 402 with a Sui payment challenge), then set on-chain \u2014 sponsored, gasless. Same flow as the console\u2019s "Sell your API".'
24427
- ).option("--remove", "Remove the listing instead").option("--key <path>", "Custom wallet path (default ~/.t2000/wallet.key)").option("--api <url>", `API base URL (default ${DEFAULT_API_BASE3})`).action(
24487
+ ).option("--remove", "Remove the listing instead").option(
24488
+ "--category <category>",
24489
+ `Directory category for your listing: ${AGENT_CATEGORIES.join(" | ")} (required unless already set on your profile)`
24490
+ ).option("--key <path>", "Custom wallet path (default ~/.t2000/wallet.key)").option("--api <url>", `API base URL (default ${DEFAULT_API_BASE3})`).action(
24428
24491
  async (endpoint, opts) => {
24429
24492
  try {
24430
24493
  if (!(opts.remove || endpoint)) {
@@ -24432,10 +24495,14 @@ Subcommands:
24432
24495
  "Provide your x402 endpoint URL (or --remove to clear the listing)."
24433
24496
  );
24434
24497
  }
24498
+ const category = opts.category === void 0 ? void 0 : parseCategory(opts.category);
24435
24499
  const base = opts.api ?? DEFAULT_API_BASE3;
24436
24500
  const agent = await withAgent({ keyPath: opts.key });
24437
24501
  const address = agent.address();
24438
24502
  const target = opts.remove ? "" : endpoint;
24503
+ if (!opts.remove) {
24504
+ await ensureSellerCategory({ base, agent, category });
24505
+ }
24439
24506
  const prepRes = await fetch(`${base}/agent/endpoint/prepare`, {
24440
24507
  method: "POST",
24441
24508
  headers: { "Content-Type": "application/json" },
@@ -24589,7 +24656,7 @@ ${detail}` : msg);
24589
24656
 
24590
24657
  // src/commands/agents.ts
24591
24658
  var DEFAULT_API_BASE4 = process.env.T2000_API_URL ?? "https://api.t2000.ai/v1";
24592
- async function getJson(url) {
24659
+ async function getJson2(url) {
24593
24660
  const res = await fetch(url, { headers: { accept: "application/json" } });
24594
24661
  if (!res.ok) {
24595
24662
  throw new Error(`Directory request failed (${res.status}).`);
@@ -24608,7 +24675,7 @@ function registerAgents(program3) {
24608
24675
  try {
24609
24676
  const base = opts.api ?? DEFAULT_API_BASE4;
24610
24677
  if (address) {
24611
- const profile = await getJson(`${base}/agents/${address}`);
24678
+ const profile = await getJson2(`${base}/agents/${address}`);
24612
24679
  if (isJsonMode()) {
24613
24680
  printJson(profile);
24614
24681
  return;
@@ -24631,7 +24698,7 @@ function registerAgents(program3) {
24631
24698
  return;
24632
24699
  }
24633
24700
  const limit = Math.min(Number.parseInt(opts.limit ?? "100", 10) || 100, 100);
24634
- const data = await getJson(
24701
+ const data = await getJson2(
24635
24702
  `${base}/agents?limit=100`
24636
24703
  );
24637
24704
  let agents = (data.agents ?? []).filter((a) => a.active !== false);
@@ -25330,7 +25397,10 @@ Examples:
25330
25397
  group.command("create").description("List a service under your Agent ID (re-run to update it)").requiredOption("--name <name>", "Service name (max 80 chars)").requiredOption("--price <usdc>", "Fixed price in USDC (0.01\u201350)").requiredOption("--sla <duration>", "Delivery SLA \u2014 e.g. 30m, 24h, 7d").requiredOption("--description <text>", "What this service is (max 2000 chars)").requiredOption("--deliverable <text>", "What the buyer receives (max 1000 chars)").option("--slug <slug>", "Machine name (default: derived from --name)").option(
25331
25398
  "--requirements <file-or-json-or-text>",
25332
25399
  "What the buyer must provide \u2014 free text or a JSON schema (file path ok)"
25333
- ).option("--review <duration>", "Buyer's accept/reject window after delivery", "24h").option("--split <bps>", "Buyer's share in bps if they reject (0\u201310000)", "8000").option("--key <path>", "Custom wallet path (default ~/.t2000/wallet.key)").option("--api <url>", `API base URL (default ${DEFAULT_API_BASE6})`).action(
25400
+ ).option("--review <duration>", "Buyer's accept/reject window after delivery", "24h").option("--split <bps>", "Buyer's share in bps if they reject (0\u201310000)", "8000").option(
25401
+ "--category <category>",
25402
+ `Directory category for your listing: ${AGENT_CATEGORIES.join(" | ")} (required unless already set on your profile)`
25403
+ ).option("--key <path>", "Custom wallet path (default ~/.t2000/wallet.key)").option("--api <url>", `API base URL (default ${DEFAULT_API_BASE6})`).action(
25334
25404
  async (opts) => {
25335
25405
  try {
25336
25406
  const priceUsdc = Number.parseFloat(opts.price);
@@ -25341,7 +25411,13 @@ Examples:
25341
25411
  const reviewWindowMinutes = Math.round(parseDuration(opts.review) / 6e4);
25342
25412
  const rejectSplitBps = Number.parseInt(opts.split, 10);
25343
25413
  const slug = (opts.slug ?? slugify(opts.name)).trim().toLowerCase();
25414
+ const category = opts.category === void 0 ? void 0 : parseCategory(opts.category);
25344
25415
  const requirements = opts.requirements ? await resolveRequirements(opts.requirements) : null;
25416
+ await ensureSellerCategory({
25417
+ base: opts.api ?? DEFAULT_API_BASE6,
25418
+ agent: await withAgent({ keyPath: opts.key }),
25419
+ category
25420
+ });
25345
25421
  const payload = {
25346
25422
  slug,
25347
25423
  name: opts.name.trim(),