@t2000/cli 5.32.0 → 7.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
@@ -10784,7 +10784,7 @@ var require_lib2 = __commonJS({
10784
10784
  return matches;
10785
10785
  };
10786
10786
  exports.analyse = analyse;
10787
- var detectFile = (filepath, opts = {}) => new Promise((resolve3, reject) => {
10787
+ var detectFile = (filepath, opts = {}) => new Promise((resolve2, reject) => {
10788
10788
  let fd;
10789
10789
  const fs = (0, node_1.default)();
10790
10790
  const handler = (err, buffer) => {
@@ -10794,7 +10794,7 @@ var require_lib2 = __commonJS({
10794
10794
  if (err) {
10795
10795
  reject(err);
10796
10796
  } else if (buffer) {
10797
- resolve3((0, exports.detect)(buffer));
10797
+ resolve2((0, exports.detect)(buffer));
10798
10798
  } else {
10799
10799
  reject(new Error("No error and no buffer received"));
10800
10800
  }
@@ -18970,10 +18970,10 @@ var require_browser = __commonJS({
18970
18970
  text = canvas;
18971
18971
  canvas = void 0;
18972
18972
  }
18973
- return new Promise(function(resolve3, reject) {
18973
+ return new Promise(function(resolve2, reject) {
18974
18974
  try {
18975
18975
  const data = QRCode.create(text, opts);
18976
- resolve3(renderFunc(data, canvas, opts));
18976
+ resolve2(renderFunc(data, canvas, opts));
18977
18977
  } catch (e) {
18978
18978
  reject(e);
18979
18979
  }
@@ -19055,11 +19055,11 @@ var require_server = __commonJS({
19055
19055
  }
19056
19056
  function render(renderFunc, text, params) {
19057
19057
  if (!params.cb) {
19058
- return new Promise(function(resolve3, reject) {
19058
+ return new Promise(function(resolve2, reject) {
19059
19059
  try {
19060
19060
  const data = QRCode.create(text, params.opts);
19061
19061
  return renderFunc(data, params.opts, function(err, data2) {
19062
- return err ? reject(err) : resolve3(data2);
19062
+ return err ? reject(err) : resolve2(data2);
19063
19063
  });
19064
19064
  } catch (e) {
19065
19065
  reject(e);
@@ -30298,13 +30298,13 @@ var PromisePolyfill = class extends Promise {
30298
30298
  // Available starting from Node 22
30299
30299
  // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/withResolvers
30300
30300
  static withResolver() {
30301
- let resolve3;
30301
+ let resolve2;
30302
30302
  let reject;
30303
30303
  const promise = new Promise((res, rej) => {
30304
- resolve3 = res;
30304
+ resolve2 = res;
30305
30305
  reject = rej;
30306
30306
  });
30307
- return { promise, resolve: resolve3, reject };
30307
+ return { promise, resolve: resolve2, reject };
30308
30308
  }
30309
30309
  };
30310
30310
 
@@ -30338,7 +30338,7 @@ function createPrompt(view) {
30338
30338
  output
30339
30339
  });
30340
30340
  const screen = new ScreenManager(rl);
30341
- const { promise, resolve: resolve3, reject } = PromisePolyfill.withResolver();
30341
+ const { promise, resolve: resolve2, reject } = PromisePolyfill.withResolver();
30342
30342
  const cancel = () => reject(new CancelPromptError());
30343
30343
  if (signal) {
30344
30344
  const abort = () => reject(new AbortPromptError({ cause: signal.reason }));
@@ -30365,7 +30365,7 @@ function createPrompt(view) {
30365
30365
  cycle(() => {
30366
30366
  try {
30367
30367
  const nextView = view(config, (value) => {
30368
- setImmediate(() => resolve3(value));
30368
+ setImmediate(() => resolve2(value));
30369
30369
  });
30370
30370
  if (nextView === void 0) {
30371
30371
  const callerFilename = callSites[1]?.getFileName();
@@ -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-VB42REWC.js");
33125
+ mod3 = await import("./dist-Q2GGV3W4.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 createHash4 } 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";
@@ -33715,868 +33712,47 @@ function registerAgentCreate(group) {
33715
33712
  }
33716
33713
  const storeUrl = `${STORE_BASE}/${address}`;
33717
33714
  if (isJsonMode()) {
33718
- printJson({
33719
- address,
33720
- walletCreated: created,
33721
- registered: true,
33722
- alreadyRegistered: reg.alreadyRegistered,
33723
- name,
33724
- ...category ? { category } : {},
33725
- ...ownerProposed ? { ownerProposed: owner } : {},
33726
- storeUrl,
33727
- keyPath: opts.key ?? "~/.t2000/wallet.key"
33728
- });
33729
- return;
33730
- }
33731
- printBlank();
33732
- printSuccess(`${name} is live`);
33733
- printKeyValue("Address", address);
33734
- printKeyValue("Store", storeUrl);
33735
- printKeyValue(
33736
- "Wallet",
33737
- created ? `created at ${opts.key ?? "~/.t2000/wallet.key"}` : `reused ${opts.key ?? "~/.t2000/wallet.key"}`
33738
- );
33739
- if (ownerProposed) {
33740
- printKeyValue(
33741
- "Owner",
33742
- `proposed ${owner} \u2014 confirm at ${STORE_BASE}/manage/agents`
33743
- );
33744
- }
33745
- printBlank();
33746
- printLine("Next:");
33747
- 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/review.ts
33758
- import { createHash } from "crypto";
33759
- var DEFAULT_GATEWAY = "https://x402.t2000.ai";
33760
- async function fetchJson2(url, init) {
33761
- const res = await fetch(url, {
33762
- method: init?.method ?? "GET",
33763
- headers: init?.body ? { "Content-Type": "application/json" } : void 0,
33764
- body: init?.body ? JSON.stringify(init.body) : void 0
33765
- });
33766
- const json = await res.json().catch(() => ({}));
33767
- if (!res.ok) {
33768
- const err = json.error;
33769
- throw new Error(typeof err === "string" ? err : `HTTP ${res.status}`);
33770
- }
33771
- return json;
33772
- }
33773
- function reviewMessage(digest, stars, text, timestamp) {
33774
- const hash = createHash("sha256").update(text, "utf8").digest("hex");
33775
- return `t2000-review:${digest}:${stars}:${hash}:${timestamp}`;
33776
- }
33777
- function registerAgentReview(agent) {
33778
- agent.command("review").description(
33779
- "Review a purchase (1-5 stars + optional text). Binds to your latest settled receipt with the seller, or --digest for a specific one. Re-run to edit. [Store v2]"
33780
- ).argument("<seller>", "Seller address (0x\u2026)").requiredOption("--stars <n>", "Rating 1-5").option("--text <text>", "Review text (\u2264400 chars)").option("--digest <digest>", "Collect digest of the specific purchase").option("--gateway <url>", `Gateway base URL (default ${DEFAULT_GATEWAY})`).option("--key <path>", "Custom wallet path (default ~/.t2000/wallet.key)").action(
33781
- async (seller, opts) => {
33782
- try {
33783
- const stars = Number(opts.stars);
33784
- if (!Number.isInteger(stars) || stars < 1 || stars > 5) {
33785
- throw new Error("--stars must be an integer 1-5.");
33786
- }
33787
- const text = (opts.text ?? "").trim();
33788
- if (text.length > 400) {
33789
- throw new Error("--text must be \u2264 400 chars.");
33790
- }
33791
- const gateway = opts.gateway ?? DEFAULT_GATEWAY;
33792
- const agentW = await withAgent({ keyPath: opts.key });
33793
- const buyer = agentW.address();
33794
- let digest = (opts.digest ?? "").trim();
33795
- if (!digest) {
33796
- const res = await fetchJson2(
33797
- `${gateway}/commerce/review?buyer=${buyer}&seller=${encodeURIComponent(seller)}`
33798
- );
33799
- const reviewable = res.reviewable ?? [];
33800
- if (reviewable.length === 0) {
33801
- throw new Error(
33802
- "No settled purchase from this wallet to that seller \u2014 buy first (`t2 agent pay`), then review."
33803
- );
33804
- }
33805
- digest = reviewable[0].digest;
33806
- }
33807
- const timestamp = Date.now();
33808
- const message = new TextEncoder().encode(
33809
- reviewMessage(digest, stars, text, timestamp)
33810
- );
33811
- const { signature } = await agentW.keypair.signPersonalMessage(message);
33812
- await fetchJson2(`${gateway}/commerce/review`, {
33813
- method: "POST",
33814
- body: { digest, stars, text, timestamp, signature }
33815
- });
33816
- if (isJsonMode()) {
33817
- printJson({ ok: true, digest, stars, text: text || null });
33818
- return;
33819
- }
33820
- printBlank();
33821
- printSuccess(
33822
- `Review posted \u2014 ${"\u2605".repeat(stars)}${"\u2606".repeat(5 - stars)}${text ? ` "${text}"` : ""}`
33823
- );
33824
- printKeyValue("Receipt", digest);
33825
- printKeyValue(
33826
- "Listing",
33827
- `https://agents.t2000.ai/${seller.startsWith("0x") ? seller : ""}`
33828
- );
33829
- printBlank();
33830
- } catch (e) {
33831
- handleError(e);
33832
- }
33833
- }
33834
- );
33835
- }
33836
-
33837
- // src/commands/agent/serve.ts
33838
- import { createHash as createHash3 } from "crypto";
33839
- import { existsSync as existsSync4, mkdirSync as mkdirSync2, readFileSync as readFileSync4, writeFileSync as writeFileSync3 } from "fs";
33840
- import { createServer } from "http";
33841
- import { join as join8, resolve as resolve2 } from "path";
33842
- import { pathToFileURL } from "url";
33843
-
33844
- // src/commands/agent/services.ts
33845
- import { createHash as createHash2 } from "crypto";
33846
- import { readFileSync as readFileSync3 } from "fs";
33847
- var SLUG_RE = /^[a-z0-9][a-z0-9-]{1,39}$/;
33848
- async function fetchJson3(url, init) {
33849
- const res = await fetch(url, {
33850
- method: init?.method ?? "GET",
33851
- headers: init?.body ? { "Content-Type": "application/json" } : void 0,
33852
- body: init?.body ? JSON.stringify(init.body) : void 0
33853
- });
33854
- const json = await res.json().catch(() => ({}));
33855
- if (!res.ok) {
33856
- const err = json.error;
33857
- const msg = typeof err === "string" ? err : err?.message ?? `HTTP ${res.status}`;
33858
- throw new Error(msg);
33859
- }
33860
- return json;
33861
- }
33862
- function canonicalServicesJson(services) {
33863
- return JSON.stringify(
33864
- services.map(
33865
- (s) => Object.fromEntries(
33866
- Object.entries(s).sort(([a], [b]) => a.localeCompare(b))
33867
- )
33868
- )
33869
- );
33870
- }
33871
- async function getCatalog(base, address) {
33872
- const res = await fetchJson3(
33873
- `${base}/agent/services?address=${encodeURIComponent(address)}`
33874
- );
33875
- return Array.isArray(res.services) ? res.services : [];
33876
- }
33877
- async function putCatalog(opts) {
33878
- const agent = await withAgent({ keyPath: opts.keyPath });
33879
- const address = agent.address();
33880
- const challenge = await fetchJson3(`${opts.base}/agent/challenge`, {
33881
- method: "POST",
33882
- body: { address }
33883
- });
33884
- const nonce = challenge.nonce;
33885
- if (!nonce) {
33886
- throw new Error("Failed to get a challenge nonce.");
33887
- }
33888
- const digest = createHash2("sha256").update(canonicalServicesJson(opts.services)).digest("hex");
33889
- const message = new TextEncoder().encode(
33890
- `t2000-agent-services:${nonce}:${digest}`
33891
- );
33892
- const { signature } = await agent.keypair.signPersonalMessage(message);
33893
- const res = await fetchJson3(`${opts.base}/agent/services`, {
33894
- method: "POST",
33895
- body: { address, nonce, signature, services: opts.services }
33896
- });
33897
- return { address, count: Number(res.count ?? opts.services.length) };
33898
- }
33899
- function entryFromFlags(opts) {
33900
- const slug = String(opts.slug ?? "").trim().toLowerCase();
33901
- if (!SLUG_RE.test(slug)) {
33902
- throw new Error("--slug is required: [a-z0-9-], 2-40 chars.");
33903
- }
33904
- const out = { slug };
33905
- if (opts.title !== void 0) {
33906
- out.title = opts.title;
33907
- }
33908
- if (opts.description !== void 0) {
33909
- out.description = opts.description;
33910
- }
33911
- if (opts.price !== void 0) {
33912
- out.priceUsdc = opts.price;
33913
- }
33914
- if (opts.input !== void 0) {
33915
- out.input = opts.input || null;
33916
- }
33917
- if (opts.endpoint !== void 0) {
33918
- out.endpoint = opts.endpoint || null;
33919
- }
33920
- if (opts.method !== void 0) {
33921
- out.method = opts.method.toUpperCase() === "GET" ? "GET" : "POST";
33922
- }
33923
- return out;
33924
- }
33925
- function registerAgentServices(agentGroup, defaults) {
33926
- const group = agentGroup.command("services").description(
33927
- "Manage this agent's service CATALOG (one agent, many services). Buy URLs: commerce/pay/<agent>/<slug>. [Store v2]"
33928
- );
33929
- 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) => {
33930
- try {
33931
- const base = opts.api ?? defaults.apiBase;
33932
- const address = addressArg ?? (await withAgent({ keyPath: opts.key })).address();
33933
- const services = await getCatalog(base, address);
33934
- if (isJsonMode()) {
33935
- printJson({ address, services });
33936
- return;
33937
- }
33938
- printBlank();
33939
- if (services.length === 0) {
33940
- printLine("No services in the catalog. Add one: t2 agent services add --slug <slug> --title \u2026 --description \u2026 --price \u2026");
33941
- printBlank();
33942
- return;
33943
- }
33944
- for (const s of services) {
33945
- printKeyValue(
33946
- s.slug,
33947
- `$${s.priceUsdc} \u2014 ${s.title}${s.active === false ? " (inactive)" : ""}`
33948
- );
33949
- }
33950
- printBlank();
33951
- } catch (error) {
33952
- handleError(error);
33953
- }
33954
- });
33955
- 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) => {
33956
- try {
33957
- const base = opts.api ?? defaults.apiBase;
33958
- const agent = await withAgent({ keyPath: opts.key });
33959
- const current = await getCatalog(base, agent.address());
33960
- const entry = entryFromFlags(opts);
33961
- if (current.some((s) => s.slug === entry.slug)) {
33962
- throw new Error(
33963
- `Slug "${entry.slug}" already exists \u2014 use: t2 agent services update --slug ${entry.slug}`
33964
- );
33965
- }
33966
- const next = {
33967
- title: "",
33968
- description: "",
33969
- priceUsdc: "0",
33970
- active: true,
33971
- ...entry
33972
- };
33973
- const { count } = await putCatalog({
33974
- base,
33975
- keyPath: opts.key,
33976
- services: [...current, next]
33977
- });
33978
- if (isJsonMode()) {
33979
- printJson({ added: entry.slug, count });
33980
- return;
33981
- }
33982
- printBlank();
33983
- printSuccess(`Service "${entry.slug}" added \u2014 catalog now ${count} service${count === 1 ? "" : "s"}.`);
33984
- printLine(`Buy URL: https://x402.t2000.ai/commerce/pay/${agent.address()}/${entry.slug}`);
33985
- printBlank();
33986
- } catch (error) {
33987
- handleError(error);
33988
- }
33989
- });
33990
- 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) => {
33991
- try {
33992
- const base = opts.api ?? defaults.apiBase;
33993
- const agent = await withAgent({ keyPath: opts.key });
33994
- const current = await getCatalog(base, agent.address());
33995
- const entry = entryFromFlags(opts);
33996
- const idx = current.findIndex((s) => s.slug === entry.slug);
33997
- if (idx === -1) {
33998
- throw new Error(`No service "${entry.slug}" in the catalog.`);
33999
- }
34000
- const merged = { ...current[idx], ...entry };
34001
- if (opts.active !== void 0) {
34002
- merged.active = String(opts.active).toLowerCase() !== "false";
34003
- }
34004
- const services = [...current];
34005
- services[idx] = merged;
34006
- const { count } = await putCatalog({ base, keyPath: opts.key, services });
34007
- if (isJsonMode()) {
34008
- printJson({ updated: entry.slug, count });
34009
- return;
34010
- }
34011
- printBlank();
34012
- printSuccess(`Service "${entry.slug}" updated.`);
34013
- printBlank();
34014
- } catch (error) {
34015
- handleError(error);
34016
- }
34017
- });
34018
- 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) => {
34019
- try {
34020
- const base = opts.api ?? defaults.apiBase;
34021
- const agent = await withAgent({ keyPath: opts.key });
34022
- const slug = String(opts.slug ?? "").trim().toLowerCase();
34023
- const current = await getCatalog(base, agent.address());
34024
- const services = current.filter((s) => s.slug !== slug);
34025
- if (services.length === current.length) {
34026
- throw new Error(`No service "${slug}" in the catalog.`);
34027
- }
34028
- const { count } = await putCatalog({ base, keyPath: opts.key, services });
34029
- if (isJsonMode()) {
34030
- printJson({ removed: slug, count });
34031
- return;
34032
- }
34033
- printBlank();
34034
- printSuccess(`Service "${slug}" removed \u2014 catalog now ${count} service${count === 1 ? "" : "s"}.`);
34035
- printBlank();
34036
- } catch (error) {
34037
- handleError(error);
34038
- }
34039
- });
34040
- group.command("sync").description(
34041
- "Declarative catalog sync \u2014 the manifest file IS the catalog (adds/updates/removes to match). The catalog-scale path."
34042
- ).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) => {
34043
- try {
34044
- const base = opts.api ?? defaults.apiBase;
34045
- const raw = JSON.parse(readFileSync3(file, "utf8"));
34046
- const list = Array.isArray(raw) ? raw : raw?.services ?? null;
34047
- if (!Array.isArray(list)) {
34048
- throw new Error(
34049
- 'Manifest must be a JSON array of services (or { "services": [...] }).'
34050
- );
34051
- }
34052
- const services = list.map((s) => {
34053
- const entry = s;
34054
- return { ...entry, active: entry.active !== false };
34055
- });
34056
- const agent = await withAgent({ keyPath: opts.key });
34057
- const before = await getCatalog(base, agent.address());
34058
- const { count } = await putCatalog({ base, keyPath: opts.key, services });
34059
- if (isJsonMode()) {
34060
- printJson({ synced: count, before: before.length });
34061
- return;
34062
- }
34063
- printBlank();
34064
- printSuccess(`Catalog synced \u2014 ${before.length} \u2192 ${count} services.`);
34065
- printBlank();
34066
- } catch (error) {
34067
- handleError(error);
34068
- }
34069
- });
34070
- }
34071
-
34072
- // src/commands/agent/serve.ts
34073
- var DEFAULT_API_BASE4 = process.env.T2000_API_URL ?? "https://api.t2000.ai/v1";
34074
- var DEFAULT_GATEWAY2 = process.env.T2000_GATEWAY_URL ?? "https://mpp.t2000.ai";
34075
- var SLUG_RE2 = /^[a-z0-9][a-z0-9-]{1,39}$/;
34076
- var MANIFEST = "t2serve.json";
34077
- var HANDLER = "handler.mjs";
34078
- var HANDLER_TEMPLATE = `// t2000 hosted handler (R1). Deploys with: t2 agent serve deploy
34079
- //
34080
- // Contract: one self-contained ES module (no imports \u2014 fetch/crypto/URL are
34081
- // available as Workers globals). The gateway calls this ONLY for paid,
34082
- // escrowed deliveries; on a 2xx your wallet is paid, on failure the buyer is
34083
- // auto-refunded. Keep it fast (15s delivery timeout, 5s CPU cap).
34084
- //
34085
- // input \u2014 the buyer's request body (parsed JSON, or a raw string)
34086
- // ctx \u2014 { agent, slug, buyer, secrets }
34087
- // secrets = your vault (t2 agent serve secrets set KEY=value)
34088
- export default async function handle(input, ctx) {
34089
- // Example: compose public data and return a result.
34090
- // const res = await fetch('https://api.example.com/data');
34091
- // const data = await res.json();
34092
- return {
34093
- echo: input,
34094
- from: ctx.slug,
34095
- note: 'Replace this with your service logic.',
34096
- };
34097
- }
34098
- `;
34099
- var PROXY_TEMPLATE = `// t2000 hosted handler \u2014 "Proxy an API" template. You hold a key to an
34100
- // API; this resells calls to it per-call, with your key never leaving the
34101
- // t2000 vault. Setup:
34102
- // 1. Edit UPSTREAM below.
34103
- // 2. t2 agent serve secrets set UPSTREAM_KEY=<your api key>
34104
- // 3. t2 agent serve deploy
34105
- const UPSTREAM = 'https://api.example.com/v1/endpoint';
34106
-
34107
- export default async function handle(input, ctx) {
34108
- const res = await fetch(UPSTREAM, {
34109
- method: 'POST',
34110
- headers: {
34111
- 'content-type': 'application/json',
34112
- // Adjust the auth scheme to your upstream (x-api-key, basic, \u2026).
34113
- ...(ctx.secrets?.UPSTREAM_KEY
34114
- ? { authorization: \`Bearer \${ctx.secrets.UPSTREAM_KEY}\` }
34115
- : {}),
34116
- },
34117
- body: JSON.stringify(input ?? {}),
34118
- });
34119
- if (!res.ok) {
34120
- // Throwing fails the delivery \u2192 the buyer is auto-refunded.
34121
- throw new Error(\`Upstream error \${res.status}\`);
34122
- }
34123
- return await res.json();
34124
- }
34125
- `;
34126
- var TEMPLATES = {
34127
- default: HANDLER_TEMPLATE,
34128
- proxy: PROXY_TEMPLATE
34129
- };
34130
- function readManifest(dir) {
34131
- const p = join8(dir, MANIFEST);
34132
- if (!existsSync4(p)) {
34133
- throw new Error(
34134
- `No ${MANIFEST} here \u2014 run \`t2 agent serve init\` first (or --dir <path>).`
34135
- );
34136
- }
34137
- const m = JSON.parse(readFileSync4(p, "utf8"));
34138
- const slug = String(m.slug ?? "").trim().toLowerCase();
34139
- if (!SLUG_RE2.test(slug)) {
34140
- throw new Error(`${MANIFEST}: slug must match [a-z0-9-], 2-40 chars.`);
34141
- }
34142
- if (!m.title?.trim() || !m.description?.trim()) {
34143
- throw new Error(`${MANIFEST}: title and description are required.`);
34144
- }
34145
- const price = Number(m.price);
34146
- if (!Number.isFinite(price) || price <= 0) {
34147
- throw new Error(`${MANIFEST}: price must be a positive USDC amount.`);
34148
- }
34149
- return { ...m, slug };
34150
- }
34151
- function readHandler(dir) {
34152
- const p = join8(dir, HANDLER);
34153
- if (!existsSync4(p)) {
34154
- throw new Error(`No ${HANDLER} here \u2014 run \`t2 agent serve init\` first.`);
34155
- }
34156
- const src = readFileSync4(p, "utf8");
34157
- if (!src.trim()) {
34158
- throw new Error(`${HANDLER} is empty.`);
34159
- }
34160
- if (/^\s*import\s.+from\s/m.test(src)) {
34161
- throw new Error(
34162
- `${HANDLER} must be self-contained (no imports) \u2014 fetch, crypto, and URL are available as globals.`
34163
- );
34164
- }
34165
- return src;
34166
- }
34167
- async function fetchJson4(url, init) {
34168
- const res = await fetch(url, {
34169
- method: init?.method ?? "GET",
34170
- headers: init?.body ? { "Content-Type": "application/json" } : void 0,
34171
- body: init?.body ? JSON.stringify(init.body) : void 0
34172
- });
34173
- const json = await res.json().catch(() => ({}));
34174
- if (!res.ok) {
34175
- const err = json.error;
34176
- const msg = typeof err === "string" ? err : err?.message ?? `HTTP ${res.status}`;
34177
- throw new Error(msg);
34178
- }
34179
- return json;
34180
- }
34181
- function registerAgentServe(agentGroup) {
34182
- const group = agentGroup.command("serve").description(
34183
- "Hosted handlers \u2014 deploy a function to t2000 compute and sell it per call. No server, no wrap. [R1]"
34184
- );
34185
- group.command("init").description(`Scaffold ${HANDLER} + ${MANIFEST} in the current directory.`).option("--slug <slug>", "Service slug (in the buy URL)", "my-service").option(
34186
- "--template <name>",
34187
- `Handler template: ${Object.keys(TEMPLATES).join(" | ")} (proxy = resell a keyed API)`,
34188
- "default"
34189
- ).option("--dir <path>", "Target directory (default: cwd)").action((opts) => {
34190
- try {
34191
- const dir = resolve2(opts.dir ?? ".");
34192
- mkdirSync2(dir, { recursive: true });
34193
- const slug = opts.slug.trim().toLowerCase();
34194
- if (!SLUG_RE2.test(slug)) {
34195
- throw new Error("--slug must match [a-z0-9-], 2-40 chars.");
34196
- }
34197
- const template = TEMPLATES[opts.template];
34198
- if (!template) {
34199
- throw new Error(
34200
- `Unknown --template "${opts.template}" \u2014 use: ${Object.keys(TEMPLATES).join(", ")}.`
34201
- );
34202
- }
34203
- const manifestPath = join8(dir, MANIFEST);
34204
- const handlerPath = join8(dir, HANDLER);
34205
- if (existsSync4(manifestPath) || existsSync4(handlerPath)) {
34206
- throw new Error(`${MANIFEST} or ${HANDLER} already exists here.`);
34207
- }
34208
- writeFileSync3(
34209
- manifestPath,
34210
- `${JSON.stringify(
34211
- {
34212
- slug,
34213
- title: "My service",
34214
- description: "What the buyer gets, in one or two sentences. Provide: 1. \u2026",
34215
- price: "0.02",
34216
- input: "JSON body with your parameters"
34217
- },
34218
- null,
34219
- 2
34220
- )}
34221
- `
34222
- );
34223
- writeFileSync3(handlerPath, template);
34224
- if (isJsonMode()) {
34225
- printJson({ dir, files: [MANIFEST, HANDLER] });
34226
- return;
34227
- }
34228
- printBlank();
34229
- printSuccess("Scaffolded a hosted handler");
34230
- printKeyValue("Handler", handlerPath);
34231
- printKeyValue("Manifest", manifestPath);
34232
- printBlank();
34233
- printLine("Next:");
34234
- printLine(" t2 agent serve dev # try it locally");
34235
- printLine(" t2 agent serve deploy # deploy + list it for sale");
34236
- printBlank();
34237
- } catch (error) {
34238
- handleError(error);
34239
- }
34240
- });
34241
- group.command("dev").description(
34242
- "Run the handler locally against the delivery contract (POST {input} to :8787)."
34243
- ).option("--dir <path>", "Handler directory (default: cwd)").option("--port <port>", "Port (default 8787)", "8787").option("--input <json>", "One-shot: invoke once with this input and exit").action(async (opts) => {
34244
- try {
34245
- const dir = resolve2(opts.dir ?? ".");
34246
- const manifest = readManifest(dir);
34247
- readHandler(dir);
34248
- const mod3 = await import(pathToFileURL(join8(dir, HANDLER)).href);
34249
- const fn = mod3.default;
34250
- if (typeof fn !== "function") {
34251
- throw new Error(`${HANDLER} must default-export a function.`);
34252
- }
34253
- const ctx = {
34254
- agent: "0xLOCAL",
34255
- slug: manifest.slug,
34256
- buyer: "0xBUYER"
34257
- };
34258
- if (opts.input !== void 0) {
34259
- let input = opts.input;
34260
- try {
34261
- input = JSON.parse(opts.input);
34262
- } catch {
34263
- }
34264
- const out = await fn(input, ctx);
34265
- printJson({ ok: true, output: out });
34266
- return;
34267
- }
34268
- const port = Number(opts.port) || 8787;
34269
- const server = createServer(async (req, res) => {
34270
- const chunks = [];
34271
- for await (const c of req) {
34272
- chunks.push(c);
34273
- }
34274
- const raw = Buffer.concat(chunks).toString("utf8");
34275
- let input = raw;
34276
- try {
34277
- input = raw ? JSON.parse(raw) : {};
34278
- } catch {
34279
- }
34280
- try {
34281
- const out = await fn(input, ctx);
34282
- res.writeHead(200, { "content-type": "application/json" });
34283
- res.end(JSON.stringify(out));
34284
- } catch (e) {
34285
- res.writeHead(500, { "content-type": "application/json" });
34286
- res.end(
34287
- JSON.stringify({ error: e instanceof Error ? e.message : String(e) })
34288
- );
34289
- }
34290
- });
34291
- server.listen(port, () => {
34292
- printBlank();
34293
- printSuccess(`Local handler running \u2014 slug "${manifest.slug}"`);
34294
- printLine(` curl -X POST http://localhost:${port} -d '{"hello":"world"}'`);
34295
- printLine(" Ctrl-C to stop.");
34296
- printBlank();
34297
- });
34298
- } catch (error) {
34299
- handleError(error);
34300
- }
34301
- });
34302
- group.command("deploy").description(
34303
- "Deploy the handler to t2000 compute + list the SKU in your catalog. Sponsored listing, per-call earnings to your wallet."
34304
- ).option("--dir <path>", "Handler directory (default: cwd)").option("--key <path>", "Custom wallet path (default ~/.t2000/wallet.key)").option("--api <url>", `API base URL (default ${DEFAULT_API_BASE4})`).option("--gateway <url>", `Gateway URL (default ${DEFAULT_GATEWAY2})`).action(
34305
- async (opts) => {
34306
- try {
34307
- const dir = resolve2(opts.dir ?? ".");
34308
- const base = opts.api ?? DEFAULT_API_BASE4;
34309
- const gateway = opts.gateway ?? DEFAULT_GATEWAY2;
34310
- const manifest = readManifest(dir);
34311
- const script = readHandler(dir);
34312
- const scriptB64 = Buffer.from(script, "utf8").toString("base64");
34313
- const agent = await withAgent({ keyPath: opts.key });
34314
- const address = agent.address();
34315
- const ts = Date.now();
34316
- const bodyHash = createHash3("sha256").update(`${manifest.slug}|${scriptB64}`).digest("hex");
34317
- const message = new TextEncoder().encode(
34318
- `t2000-serve:${ts}:${bodyHash}`
34319
- );
34320
- const { signature } = await agent.keypair.signPersonalMessage(message);
34321
- const deployed = await fetchJson4(`${gateway}/serve/deploy`, {
34322
- method: "POST",
34323
- body: {
34324
- address,
34325
- slug: manifest.slug,
34326
- script: scriptB64,
34327
- timestamp: ts,
34328
- signature
34329
- }
34330
- });
34331
- const catalog = await getCatalog(base, address);
34332
- const entry = {
34333
- slug: manifest.slug,
34334
- title: manifest.title,
34335
- description: manifest.description,
34336
- priceUsdc: String(manifest.price),
34337
- input: manifest.input ?? null,
34338
- endpoint: null,
34339
- method: "POST",
34340
- active: true
34341
- };
34342
- const next = [
34343
- ...catalog.filter((s) => s.slug !== manifest.slug),
34344
- entry
34345
- ];
34346
- await putCatalog({ base, keyPath: opts.key, services: next });
34347
- const buyUrl = String(
34348
- deployed.buyUrl ?? `https://x402.t2000.ai/commerce/pay/${address}/${manifest.slug}`
34349
- );
34350
- if (isJsonMode()) {
34351
- printJson({
34352
- address,
34353
- slug: manifest.slug,
34354
- sizeBytes: deployed.sizeBytes,
34355
- listed: true,
34356
- buyUrl
34357
- });
34358
- return;
34359
- }
34360
- printBlank();
34361
- printSuccess(`Deployed "${manifest.slug}" to t2000 compute`);
34362
- printKeyValue("Buy URL", buyUrl);
34363
- printKeyValue("Price", `$${manifest.price} per call`);
34364
- printKeyValue("Store", `https://agents.t2000.ai/${address}`);
34365
- printBlank();
34366
- printLine(" t2 agent serve logs # invocations");
34367
- printLine(" t2 agent serve undeploy --slug " + manifest.slug);
34368
- printBlank();
34369
- } catch (error) {
34370
- handleError(error);
34371
- }
34372
- }
34373
- );
34374
- const secrets = group.command("secrets").description(
34375
- "This agent's handler secrets vault \u2014 encrypted at t2000, injected as ctx.secrets on paid deliveries only. Values are write-only."
34376
- );
34377
- secrets.command("set").argument("<pairs...>", "NAME=value pairs (e.g. UPSTREAM_KEY=sk-\u2026)").description("Set (or overwrite) vault secrets. NAME: A-Z, 0-9, _.").option("--key <path>", "Custom wallet path (default ~/.t2000/wallet.key)").option("--gateway <url>", `Gateway URL (default ${DEFAULT_GATEWAY2})`).action(
34378
- async (pairs, opts) => {
34379
- try {
34380
- const updates = {};
34381
- for (const pair of pairs) {
34382
- const eq = pair.indexOf("=");
34383
- if (eq <= 0) {
34384
- throw new Error(`"${pair}" is not NAME=value.`);
34385
- }
34386
- updates[pair.slice(0, eq).trim()] = pair.slice(eq + 1);
34387
- }
34388
- const res = await postSecrets(opts, "set", updates);
34389
- if (isJsonMode()) {
34390
- printJson({ names: res.names });
34391
- return;
34392
- }
34393
- printBlank();
34394
- printSuccess("Vault updated");
34395
- printKeyValue("Secrets", res.names.join(", ") || "(none)");
34396
- printInfo("Handlers read them as ctx.secrets.NAME on paid deliveries.");
34397
- printBlank();
34398
- } catch (error) {
34399
- handleError(error);
34400
- }
34401
- }
34402
- );
34403
- secrets.command("unset").argument("<names...>", "Secret names to delete").description("Delete vault secrets.").option("--key <path>", "Custom wallet path (default ~/.t2000/wallet.key)").option("--gateway <url>", `Gateway URL (default ${DEFAULT_GATEWAY2})`).action(
34404
- async (names, opts) => {
34405
- try {
34406
- const updates = {};
34407
- for (const n of names) {
34408
- updates[n.trim()] = "";
34409
- }
34410
- const res = await postSecrets(opts, "set", updates);
34411
- if (isJsonMode()) {
34412
- printJson({ names: res.names });
34413
- return;
34414
- }
34415
- printBlank();
34416
- printSuccess("Vault updated");
34417
- printKeyValue("Secrets", res.names.join(", ") || "(none)");
34418
- printBlank();
34419
- } catch (error) {
34420
- handleError(error);
34421
- }
34422
- }
34423
- );
34424
- secrets.command("list").description("List vault secret NAMES (values never leave the gateway).").option("--key <path>", "Custom wallet path (default ~/.t2000/wallet.key)").option("--gateway <url>", `Gateway URL (default ${DEFAULT_GATEWAY2})`).action(async (opts) => {
34425
- try {
34426
- const res = await postSecrets(opts, "list");
34427
- if (isJsonMode()) {
34428
- printJson({ names: res.names });
34429
- return;
34430
- }
34431
- const names = res.names;
34432
- printBlank();
34433
- if (names.length === 0) {
34434
- printLine("Vault is empty. Set one: t2 agent serve secrets set NAME=value");
34435
- } else {
34436
- for (const n of names) {
34437
- printLine(` ${n}`);
34438
- }
34439
- }
34440
- printBlank();
34441
- } catch (error) {
34442
- handleError(error);
34443
- }
34444
- });
34445
- async function postSecrets(opts, op, updates) {
34446
- const gateway = opts.gateway ?? DEFAULT_GATEWAY2;
34447
- const agent = await withAgent({ keyPath: opts.key });
34448
- const address = agent.address();
34449
- const ts = Date.now();
34450
- const payload = op === "list" ? "list" : JSON.stringify(
34451
- Object.fromEntries(
34452
- Object.entries(updates ?? {}).sort(
34453
- ([a], [b]) => a.localeCompare(b)
34454
- )
34455
- )
34456
- );
34457
- const bodyHash = createHash3("sha256").update(payload).digest("hex");
34458
- const message = new TextEncoder().encode(
34459
- `t2000-serve-secrets:${ts}:${bodyHash}`
34460
- );
34461
- const { signature } = await agent.keypair.signPersonalMessage(message);
34462
- return await fetchJson4(`${gateway}/serve/secrets`, {
34463
- method: "POST",
34464
- body: {
34465
- address,
34466
- op,
34467
- ...op === "set" ? { updates } : {},
34468
- timestamp: ts,
34469
- signature
34470
- }
34471
- });
34472
- }
34473
- group.command("status").description("Deployed handlers + invocation stats.").option("--key <path>", "Custom wallet path (default ~/.t2000/wallet.key)").option("--gateway <url>", `Gateway URL (default ${DEFAULT_GATEWAY2})`).action(async (opts) => {
34474
- try {
34475
- const gateway = opts.gateway ?? DEFAULT_GATEWAY2;
34476
- const agent = await withAgent({ keyPath: opts.key });
34477
- const address = agent.address();
34478
- const res = await fetchJson4(
34479
- `${gateway}/serve/status?address=${encodeURIComponent(address)}`
34480
- );
34481
- if (isJsonMode()) {
34482
- printJson(res);
34483
- return;
34484
- }
34485
- const handlers = res.handlers ?? [];
34486
- printBlank();
34487
- if (handlers.length === 0) {
34488
- printLine("No hosted handlers. Start one: t2 agent serve init");
34489
- printBlank();
34490
- return;
34491
- }
34492
- for (const h of handlers) {
34493
- printLine(
34494
- ` ${h.slug} ${h.active ? "live" : "undeployed"} \xB7 ${(h.sizeBytes / 1024).toFixed(1)} KB \xB7 ${h.invocations} invocation${h.invocations === 1 ? "" : "s"}${h.lastInvocation ? ` \xB7 last ${h.lastInvocation.status} @ ${h.lastInvocation.at}` : ""}`
34495
- );
34496
- }
34497
- printBlank();
34498
- } catch (error) {
34499
- handleError(error);
34500
- }
34501
- });
34502
- group.command("logs").description("Recent invocations (status \xB7 duration \xB7 error).").option("--slug <slug>", "Filter to one handler").option("--limit <n>", "Rows (default 50)", "50").option("--key <path>", "Custom wallet path (default ~/.t2000/wallet.key)").option("--gateway <url>", `Gateway URL (default ${DEFAULT_GATEWAY2})`).action(
34503
- async (opts) => {
34504
- try {
34505
- const gateway = opts.gateway ?? DEFAULT_GATEWAY2;
34506
- const agent = await withAgent({ keyPath: opts.key });
34507
- const address = agent.address();
34508
- const params = new URLSearchParams({
34509
- address,
34510
- limit: opts.limit
34511
- });
34512
- if (opts.slug) {
34513
- params.set("slug", opts.slug);
34514
- }
34515
- const res = await fetchJson4(`${gateway}/serve/logs?${params}`);
34516
- if (isJsonMode()) {
34517
- printJson(res);
34518
- return;
34519
- }
34520
- const rows = res.invocations ?? [];
34521
- printBlank();
34522
- if (rows.length === 0) {
34523
- printLine("No invocations yet.");
34524
- printBlank();
34525
- return;
34526
- }
34527
- for (const r of rows) {
34528
- printLine(
34529
- ` ${r.at} ${r.slug} ${r.status} ${r.durationMs}ms${r.error ? ` ${r.error}` : ""}`
34530
- );
34531
- }
34532
- printBlank();
34533
- } catch (error) {
34534
- handleError(error);
34535
- }
34536
- }
34537
- );
34538
- group.command("undeploy").description(
34539
- "Remove a hosted handler (the SKU stays in the catalog \u2014 deactivate it with `t2 agent services update --slug \u2026 --inactive` if wanted)."
34540
- ).requiredOption("--slug <slug>", "Handler slug to remove").option("--key <path>", "Custom wallet path (default ~/.t2000/wallet.key)").option("--gateway <url>", `Gateway URL (default ${DEFAULT_GATEWAY2})`).action(
34541
- async (opts) => {
34542
- try {
34543
- const gateway = opts.gateway ?? DEFAULT_GATEWAY2;
34544
- const slug = opts.slug.trim().toLowerCase();
34545
- if (!SLUG_RE2.test(slug)) {
34546
- throw new Error("--slug must match [a-z0-9-], 2-40 chars.");
34547
- }
34548
- const agent = await withAgent({ keyPath: opts.key });
34549
- const address = agent.address();
34550
- const ts = Date.now();
34551
- const message = new TextEncoder().encode(
34552
- `t2000-serve-remove:${ts}:${slug}`
34553
- );
34554
- const { signature } = await agent.keypair.signPersonalMessage(message);
34555
- await fetchJson4(`${gateway}/serve/undeploy`, {
34556
- method: "POST",
34557
- body: { address, slug, timestamp: ts, signature }
33715
+ printJson({
33716
+ address,
33717
+ walletCreated: created,
33718
+ registered: true,
33719
+ alreadyRegistered: reg.alreadyRegistered,
33720
+ name,
33721
+ ...category ? { category } : {},
33722
+ ...ownerProposed ? { ownerProposed: owner } : {},
33723
+ storeUrl,
33724
+ keyPath: opts.key ?? "~/.t2000/wallet.key"
34558
33725
  });
34559
- if (isJsonMode()) {
34560
- printJson({ address, slug, undeployed: true });
34561
- return;
34562
- }
34563
- printBlank();
34564
- printSuccess(`Undeployed "${slug}"`);
34565
- printInfo(
34566
- "Buys against it now fail closed (auto-refund). Redeploy anytime: t2 agent serve deploy"
33726
+ return;
33727
+ }
33728
+ printBlank();
33729
+ printSuccess(`${name} is live`);
33730
+ printKeyValue("Address", address);
33731
+ printKeyValue("Store", storeUrl);
33732
+ printKeyValue(
33733
+ "Wallet",
33734
+ created ? `created at ${opts.key ?? "~/.t2000/wallet.key"}` : `reused ${opts.key ?? "~/.t2000/wallet.key"}`
33735
+ );
33736
+ if (ownerProposed) {
33737
+ printKeyValue(
33738
+ "Owner",
33739
+ `proposed ${owner} \u2014 confirm at ${STORE_BASE}/manage/agents`
34567
33740
  );
34568
- printBlank();
34569
- } catch (error) {
34570
- handleError(error);
34571
33741
  }
33742
+ printBlank();
33743
+ printLine("Next:");
33744
+ printLine(" t2 fund # add USDC (QR / card link)");
33745
+ printLine(" t2 agent service ... # declare a paid endpoint (sell per call)");
33746
+ printBlank();
33747
+ } catch (error) {
33748
+ handleError(error);
34572
33749
  }
34573
- );
33750
+ });
34574
33751
  }
34575
33752
 
34576
33753
  // src/commands/agent/index.ts
34577
- var DEFAULT_API_BASE5 = process.env.T2000_API_URL ?? "https://api.t2000.ai/v1";
34578
- var DEFAULT_GATEWAY3 = process.env.T2000_GATEWAY_URL ?? "https://mpp.t2000.ai";
34579
- var DEFAULT_RAIL = process.env.T2000_RAIL_URL ?? "https://x402.t2000.ai";
33754
+ var DEFAULT_API_BASE4 = process.env.T2000_API_URL ?? "https://api.t2000.ai/v1";
33755
+ var DEFAULT_GATEWAY = process.env.T2000_GATEWAY_URL ?? "https://mpp.t2000.ai";
34580
33756
  var AGENT_CATEGORIES2 = [
34581
33757
  "ai-models",
34582
33758
  "data-feeds",
@@ -34598,13 +33774,6 @@ function normalizeCategory(input) {
34598
33774
  }
34599
33775
  return c;
34600
33776
  }
34601
- function collectHeader(value, previous) {
34602
- const [key, ...rest] = value.split("=");
34603
- if (key && rest.length > 0) {
34604
- previous[key.trim()] = rest.join("=").trim();
34605
- }
34606
- return previous;
34607
- }
34608
33777
  function normalizeTopupAsset(input) {
34609
33778
  return input?.toLowerCase() === "usdsui" ? "USDsui" : "USDC";
34610
33779
  }
@@ -34614,19 +33783,19 @@ async function fundCredit(agent, base, amountStr, assetOpt) {
34614
33783
  throw new Error(`amount must be a positive number (got "${amountStr}").`);
34615
33784
  }
34616
33785
  const asset = normalizeTopupAsset(assetOpt);
34617
- const cfg = await fetchJson5(`${base}/agent/topup`, { method: "GET" });
33786
+ const cfg = await fetchJson2(`${base}/agent/topup`, { method: "GET" });
34618
33787
  const treasury = cfg.treasury;
34619
33788
  if (!treasury) {
34620
33789
  throw new Error("Could not resolve the t2000 treasury address.");
34621
33790
  }
34622
33791
  const sent = await agent.send({ to: treasury, amount, asset });
34623
- const topup = await fetchJson5(`${base}/agent/topup`, {
33792
+ const topup = await fetchJson2(`${base}/agent/topup`, {
34624
33793
  method: "POST",
34625
33794
  body: { address: agent.address(), digest: sent.tx }
34626
33795
  });
34627
33796
  return { amount, asset, balanceUsd: topup.balanceUsd };
34628
33797
  }
34629
- async function fetchJson5(url, init) {
33798
+ async function fetchJson2(url, init) {
34630
33799
  const res = await fetch(url, {
34631
33800
  method: init.method,
34632
33801
  headers: init.body ? { "Content-Type": "application/json" } : void 0,
@@ -34649,20 +33818,16 @@ Subcommands:
34649
33818
  $ t2 agent onboard --fund 5 Fund 5 USDC \u2192 mint an API key (ready to call)
34650
33819
  $ t2 agent onboard --fund 5 --asset USDsui
34651
33820
  $ t2 agent onboard Already funded \u2192 just mint a key
34652
- $ t2 agent services add --slug sui-price --title "SUI spot" --description "\u2026" --price 0.02
34653
- $ t2 agent services sync ./services.json Manifest IS the catalog (catalog-scale sellers)
33821
+ $ t2 agent pay <address> Pay another agent's declared service
34654
33822
  `
34655
33823
  );
34656
33824
  registerAgentCreate(group);
34657
- registerAgentServices(group, { apiBase: DEFAULT_API_BASE5 });
34658
- registerAgentServe(group);
34659
- registerAgentReview(group);
34660
33825
  group.command("onboard").description(
34661
33826
  "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`."
34662
- ).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_BASE5})`).action(
33827
+ ).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(
34663
33828
  async (opts) => {
34664
33829
  try {
34665
- const base = opts.api ?? DEFAULT_API_BASE5;
33830
+ const base = opts.api ?? DEFAULT_API_BASE4;
34666
33831
  const agent = await withAgent({ keyPath: opts.key });
34667
33832
  const address = agent.address();
34668
33833
  if (opts.fund !== void 0) {
@@ -34673,7 +33838,7 @@ Subcommands:
34673
33838
  );
34674
33839
  }
34675
33840
  }
34676
- const challenge = await fetchJson5(`${base}/agent/challenge`, {
33841
+ const challenge = await fetchJson2(`${base}/agent/challenge`, {
34677
33842
  method: "POST",
34678
33843
  body: { address }
34679
33844
  });
@@ -34683,7 +33848,7 @@ Subcommands:
34683
33848
  }
34684
33849
  const message = new TextEncoder().encode(`t2000-agent-keys:${nonce}`);
34685
33850
  const { signature } = await agent.keypair.signPersonalMessage(message);
34686
- const minted = await fetchJson5(`${base}/agent/keys`, {
33851
+ const minted = await fetchJson2(`${base}/agent/keys`, {
34687
33852
  method: "POST",
34688
33853
  body: { address, nonce, signature }
34689
33854
  });
@@ -34720,10 +33885,10 @@ Subcommands:
34720
33885
  );
34721
33886
  group.command("topup").argument("<amount>", "Stablecoin amount to deposit as credit").description(
34722
33887
  "Top up this wallet's t2000 credit with gasless USDC/USDsui (no new key). The 'never runs dry' primitive \u2014 call it on a 402 or a schedule."
34723
- ).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_BASE5})`).action(
33888
+ ).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(
34724
33889
  async (amount, opts) => {
34725
33890
  try {
34726
- const base = opts.api ?? DEFAULT_API_BASE5;
33891
+ const base = opts.api ?? DEFAULT_API_BASE4;
34727
33892
  const agent = await withAgent({ keyPath: opts.key });
34728
33893
  const funded = await fundCredit(agent, base, amount, opts.asset);
34729
33894
  if (isJsonMode()) {
@@ -34747,9 +33912,9 @@ Subcommands:
34747
33912
  );
34748
33913
  group.command("register").description(
34749
33914
  "Register this wallet on-chain as an Agent ID (sponsored, gasless). Idempotent \u2014 safe to re-run."
34750
- ).option("--key <path>", "Custom wallet path (default ~/.t2000/wallet.key)").option("--api <url>", `API base URL (default ${DEFAULT_API_BASE5})`).action(async (opts) => {
33915
+ ).option("--key <path>", "Custom wallet path (default ~/.t2000/wallet.key)").option("--api <url>", `API base URL (default ${DEFAULT_API_BASE4})`).action(async (opts) => {
34751
33916
  try {
34752
- const base = opts.api ?? DEFAULT_API_BASE5;
33917
+ const base = opts.api ?? DEFAULT_API_BASE4;
34753
33918
  const agent = await withAgent({ keyPath: opts.key });
34754
33919
  const address = agent.address();
34755
33920
  const reg = await registerWallet({ keypair: agent.keypair, address, base });
@@ -34777,9 +33942,9 @@ Subcommands:
34777
33942
  });
34778
33943
  group.command("link").argument("<owner>", "The owner's Sui address (Passport) to propose").description(
34779
33944
  "Propose an owner for this agent (two-sided \u2014 the owner must then confirm). Sponsored, gasless."
34780
- ).option("--key <path>", "Custom wallet path (default ~/.t2000/wallet.key)").option("--api <url>", `API base URL (default ${DEFAULT_API_BASE5})`).action(async (owner, opts) => {
33945
+ ).option("--key <path>", "Custom wallet path (default ~/.t2000/wallet.key)").option("--api <url>", `API base URL (default ${DEFAULT_API_BASE4})`).action(async (owner, opts) => {
34781
33946
  try {
34782
- const base = opts.api ?? DEFAULT_API_BASE5;
33947
+ const base = opts.api ?? DEFAULT_API_BASE4;
34783
33948
  const agent = await withAgent({ keyPath: opts.key });
34784
33949
  const address = agent.address();
34785
33950
  if (!isValidSuiAddress(owner)) {
@@ -34816,9 +33981,9 @@ Subcommands:
34816
33981
  });
34817
33982
  group.command("confirm").argument("<agent>", "The agent Sui address to confirm ownership of").description(
34818
33983
  "Confirm ownership of an agent that proposed you as its owner. Sponsored, gasless."
34819
- ).option("--key <path>", "Custom wallet path (default ~/.t2000/wallet.key)").option("--api <url>", `API base URL (default ${DEFAULT_API_BASE5})`).action(async (agentAddress, opts) => {
33984
+ ).option("--key <path>", "Custom wallet path (default ~/.t2000/wallet.key)").option("--api <url>", `API base URL (default ${DEFAULT_API_BASE4})`).action(async (agentAddress, opts) => {
34820
33985
  try {
34821
- const base = opts.api ?? DEFAULT_API_BASE5;
33986
+ const base = opts.api ?? DEFAULT_API_BASE4;
34822
33987
  const owner = await withAgent({ keyPath: opts.key });
34823
33988
  const address = owner.address();
34824
33989
  const { digest } = await runSponsoredTx({
@@ -34842,9 +34007,9 @@ Subcommands:
34842
34007
  });
34843
34008
  group.command("unlink").argument("<agent>", "The agent Sui address to renounce ownership of").description(
34844
34009
  "Renounce ownership of an agent you own \u2014 the record returns to autonomous (public, on-chain). Sponsored, gasless. Re-link = the agent proposes again."
34845
- ).option("--key <path>", "Custom wallet path (default ~/.t2000/wallet.key)").option("--api <url>", `API base URL (default ${DEFAULT_API_BASE5})`).action(async (agentAddress, opts) => {
34010
+ ).option("--key <path>", "Custom wallet path (default ~/.t2000/wallet.key)").option("--api <url>", `API base URL (default ${DEFAULT_API_BASE4})`).action(async (agentAddress, opts) => {
34846
34011
  try {
34847
- const base = opts.api ?? DEFAULT_API_BASE5;
34012
+ const base = opts.api ?? DEFAULT_API_BASE4;
34848
34013
  const owner = await withAgent({ keyPath: opts.key });
34849
34014
  const address = owner.address();
34850
34015
  const { digest } = await runSponsoredTx({
@@ -34869,7 +34034,7 @@ Subcommands:
34869
34034
  });
34870
34035
  group.command("profile").description(
34871
34036
  "Set this agent's public profile (name \xB7 image \xB7 description \xB7 links). Signed, no gas \u2014 shows in the directory."
34872
- ).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_BASE5})`).action(
34037
+ ).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_BASE4})`).action(
34873
34038
  async (opts) => {
34874
34039
  try {
34875
34040
  if (!(opts.name || opts.image || opts.description || opts.website || opts.twitter || opts.github)) {
@@ -34877,10 +34042,10 @@ Subcommands:
34877
34042
  "Provide at least one of --name, --image, --description, --website, --twitter, --github."
34878
34043
  );
34879
34044
  }
34880
- const base = opts.api ?? DEFAULT_API_BASE5;
34045
+ const base = opts.api ?? DEFAULT_API_BASE4;
34881
34046
  const agent = await withAgent({ keyPath: opts.key });
34882
34047
  const address = agent.address();
34883
- const challenge = await fetchJson5(`${base}/agent/challenge`, {
34048
+ const challenge = await fetchJson2(`${base}/agent/challenge`, {
34884
34049
  method: "POST",
34885
34050
  body: { address }
34886
34051
  });
@@ -34890,7 +34055,7 @@ Subcommands:
34890
34055
  }
34891
34056
  const message = new TextEncoder().encode(`t2000-agent-profile:${nonce}`);
34892
34057
  const { signature } = await agent.keypair.signPersonalMessage(message);
34893
- await fetchJson5(`${base}/agent/profile`, {
34058
+ await fetchJson2(`${base}/agent/profile`, {
34894
34059
  method: "POST",
34895
34060
  body: {
34896
34061
  address,
@@ -34924,7 +34089,7 @@ Subcommands:
34924
34089
  ).option("--price <usdc>", "Price per call in USDC (e.g. 0.02) \u2014 buyers pay this").option(
34925
34090
  "--category <category>",
34926
34091
  `Storefront category: ${AGENT_CATEGORIES2.join(" | ")}`
34927
- ).option("--key <path>", "Custom wallet path (default ~/.t2000/wallet.key)").option("--api <url>", `API base URL (default ${DEFAULT_API_BASE5})`).action(
34092
+ ).option("--key <path>", "Custom wallet path (default ~/.t2000/wallet.key)").option("--api <url>", `API base URL (default ${DEFAULT_API_BASE4})`).action(
34928
34093
  async (opts) => {
34929
34094
  try {
34930
34095
  if (opts.mcpEndpoint === void 0 && opts.paymentMethods === void 0 && opts.price === void 0 && opts.category === void 0) {
@@ -34939,7 +34104,7 @@ Subcommands:
34939
34104
  }
34940
34105
  }
34941
34106
  const category = normalizeCategory(opts.category);
34942
- const base = opts.api ?? DEFAULT_API_BASE5;
34107
+ const base = opts.api ?? DEFAULT_API_BASE4;
34943
34108
  const agent = await withAgent({ keyPath: opts.key });
34944
34109
  const address = agent.address();
34945
34110
  const prepareBody = { address };
@@ -34987,143 +34152,11 @@ Subcommands:
34987
34152
  }
34988
34153
  }
34989
34154
  );
34990
- group.command("deploy").description(
34991
- "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]"
34992
- ).option("--upstream <url>", "The upstream API URL to wrap (https)").option(
34993
- "--header <k=v>",
34994
- "Header to inject into upstream calls (repeatable; e.g. your API key)",
34995
- collectHeader,
34996
- {}
34997
- ).option("--method <method>", "Upstream method: GET or POST (default POST)").option("--price <usdc>", "Price per call in USDC (e.g. 0.02)").option(
34998
- "--category <category>",
34999
- `Storefront category: ${AGENT_CATEGORIES2.join(" | ")}`
35000
- ).option("--remove", "Take down the deployed service").option(
35001
- "--service <slug>",
35002
- "Catalog service slug \u2014 wrap config for ONE SKU (Store v2; omit = the default service)"
35003
- ).option("--gateway <url>", `Gateway base URL (default ${DEFAULT_GATEWAY3})`).option("--key <path>", "Custom wallet path (default ~/.t2000/wallet.key)").option("--api <url>", `API base URL (default ${DEFAULT_API_BASE5})`).action(
35004
- async (opts) => {
35005
- try {
35006
- const base = opts.api ?? DEFAULT_API_BASE5;
35007
- const gateway = opts.gateway ?? DEFAULT_GATEWAY3;
35008
- const category = normalizeCategory(opts.category);
35009
- const slug = opts.service?.trim().toLowerCase() || void 0;
35010
- const agent = await withAgent({ keyPath: opts.key });
35011
- const address = agent.address();
35012
- if (opts.remove) {
35013
- const ts2 = Date.now();
35014
- const msg2 = `t2000-deploy-remove:${ts2}${slug ? `:${slug}` : ""}`;
35015
- const { signature: signature2 } = await agent.keypair.signPersonalMessage(
35016
- new TextEncoder().encode(msg2)
35017
- );
35018
- await fetchJson5(`${gateway}/deploy/config`, {
35019
- method: "DELETE",
35020
- body: { address, timestamp: ts2, signature: signature2, ...slug ? { slug } : {} }
35021
- });
35022
- if (!slug) {
35023
- await runSponsoredTx({
35024
- keypair: agent.keypair,
35025
- actor: address,
35026
- prepareUrl: `${base}/agent/service/prepare`,
35027
- prepareBody: { address, mcpEndpoint: "" },
35028
- submitUrl: `${base}/agent/service/submit`
35029
- }).catch(() => void 0);
35030
- }
35031
- if (isJsonMode()) {
35032
- printJson({ address, removed: true });
35033
- return;
35034
- }
35035
- printBlank();
35036
- printSuccess("Service taken down.");
35037
- printBlank();
35038
- return;
35039
- }
35040
- if (!(opts.upstream && opts.price)) {
35041
- throw new Error("Both --upstream and --price are required (or use --remove).");
35042
- }
35043
- const price = Number.parseFloat(opts.price);
35044
- if (Number.isNaN(price) || price <= 0) {
35045
- throw new Error(`--price must be a positive number (got "${opts.price}").`);
35046
- }
35047
- const method = (opts.method ?? "POST").toUpperCase() === "GET" ? "GET" : "POST";
35048
- const headers = opts.header ?? {};
35049
- const ts = Date.now();
35050
- const bodyHash = createHash4("sha256").update(
35051
- `${opts.upstream}|${method}|${JSON.stringify(headers)}${slug ? `|${slug}` : ""}`
35052
- ).digest("hex");
35053
- const msg = `t2000-deploy:${ts}:${bodyHash}`;
35054
- const { signature } = await agent.keypair.signPersonalMessage(
35055
- new TextEncoder().encode(msg)
35056
- );
35057
- await fetchJson5(`${gateway}/deploy/config`, {
35058
- method: "POST",
35059
- body: {
35060
- address,
35061
- timestamp: ts,
35062
- signature,
35063
- upstreamUrl: opts.upstream,
35064
- method,
35065
- headers,
35066
- ...slug ? { slug } : {}
35067
- }
35068
- });
35069
- if (slug) {
35070
- if (isJsonMode()) {
35071
- printJson({ address, slug, upstream: opts.upstream, price });
35072
- return;
35073
- }
35074
- printBlank();
35075
- printSuccess(`Wrap config stored for service "${slug}".`);
35076
- printKeyValue("Wraps", opts.upstream);
35077
- printKeyValue("Buy URL", `${DEFAULT_RAIL}/commerce/pay/${address}/${slug}`);
35078
- printInfo(
35079
- `List it in the catalog: t2 agent services add --slug ${slug} --title \u2026 --description \u2026 --price ${opts.price}`
35080
- );
35081
- printBlank();
35082
- return;
35083
- }
35084
- const { digest } = await runSponsoredTx({
35085
- keypair: agent.keypair,
35086
- actor: address,
35087
- prepareUrl: `${base}/agent/service/prepare`,
35088
- prepareBody: {
35089
- address,
35090
- // The real, x402-callable buy endpoint (GET → 402 + requirements,
35091
- // pay → collect/deliver/forward). `/deploy/<addr>` was a phantom
35092
- // (no route → 404). Any x402 client can hit this URL.
35093
- mcpEndpoint: `${DEFAULT_RAIL}/commerce/pay/${address}`,
35094
- paymentMethods: ["x402"],
35095
- priceUsdc: opts.price,
35096
- ...category ? { category } : {}
35097
- },
35098
- submitUrl: `${base}/agent/service/submit`
35099
- });
35100
- if (isJsonMode()) {
35101
- printJson({ address, upstream: opts.upstream, price, digest });
35102
- return;
35103
- }
35104
- printBlank();
35105
- printSuccess("Service deployed \u2014 live + listed in the directory.");
35106
- printKeyValue("Wraps", opts.upstream);
35107
- printKeyValue("Price", `$${opts.price} USDC`);
35108
- if (category) {
35109
- printKeyValue("Category", category);
35110
- }
35111
- printKeyValue("Tx", String(digest));
35112
- printInfo(`Buyers: t2 agent pay ${truncateAddress(address)}`);
35113
- printBlank();
35114
- } catch (error) {
35115
- handleError(error);
35116
- }
35117
- }
35118
- );
35119
34155
  group.command("pay").argument("<seller>", "The seller agent's Sui address").description(
35120
34156
  "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]"
35121
34157
  ).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(
35122
- "--service <slug>",
35123
- "Catalog service slug \u2014 buys ONE SKU of the seller's catalog (Store v2)"
35124
- ).option(
35125
34158
  "--gateway <url>",
35126
- `Gateway base URL (default ${DEFAULT_GATEWAY3})`
34159
+ `Gateway base URL (default ${DEFAULT_GATEWAY})`
35127
34160
  ).option("--force", "Override spending limits for this call (see `t2 limit`)").option("--key <path>", "Custom wallet path (default ~/.t2000/wallet.key)").action(
35128
34161
  async (seller, opts) => {
35129
34162
  try {
@@ -35134,11 +34167,10 @@ Subcommands:
35134
34167
  }
35135
34168
  }
35136
34169
  const maxPrice = opts.maxPrice ? Number.parseFloat(opts.maxPrice) : opts.amount ? Number.parseFloat(opts.amount) : 1;
35137
- const gateway = opts.gateway ?? DEFAULT_GATEWAY3;
34170
+ const gateway = opts.gateway ?? DEFAULT_GATEWAY;
35138
34171
  const agent = await withAgent({ keyPath: opts.key });
35139
34172
  const resolvedSeller = seller.startsWith("0x") ? seller : (await agent.resolveRecipient(seller)).address;
35140
- const slugPath = opts.service ? `/${opts.service.trim().toLowerCase()}` : "";
35141
- const url = opts.amount ? `${gateway}/commerce/pay/${resolvedSeller}${slugPath}?amount=${encodeURIComponent(opts.amount)}` : `${gateway}/commerce/pay/${resolvedSeller}${slugPath}`;
34173
+ const url = opts.amount ? `${gateway}/commerce/pay/${resolvedSeller}?amount=${encodeURIComponent(opts.amount)}` : `${gateway}/commerce/pay/${resolvedSeller}`;
35142
34174
  const result = await agent.pay({
35143
34175
  url,
35144
34176
  method: "POST",
@@ -35202,12 +34234,12 @@ Subcommands:
35202
34234
  );
35203
34235
  group.command("earnings").description(
35204
34236
  "Your sales as a seller \u2014 count, USDC earned (net), and unique buyers, from the on-chain settlement ledger. [Agent Commerce]"
35205
- ).option("--gateway <url>", `Gateway base URL (default ${DEFAULT_GATEWAY3})`).option("--key <path>", "Custom wallet path (default ~/.t2000/wallet.key)").action(async (opts) => {
34237
+ ).option("--gateway <url>", `Gateway base URL (default ${DEFAULT_GATEWAY})`).option("--key <path>", "Custom wallet path (default ~/.t2000/wallet.key)").action(async (opts) => {
35206
34238
  try {
35207
- const gateway = opts.gateway ?? DEFAULT_GATEWAY3;
34239
+ const gateway = opts.gateway ?? DEFAULT_GATEWAY;
35208
34240
  const agent = await withAgent({ keyPath: opts.key });
35209
34241
  const address = agent.address();
35210
- const stats = await fetchJson5(
34242
+ const stats = await fetchJson2(
35211
34243
  `${gateway}/commerce/stats/${address}`,
35212
34244
  { method: "GET" }
35213
34245
  );
@@ -35230,13 +34262,13 @@ Subcommands:
35230
34262
  });
35231
34263
  group.command("handle").argument("<label>", "Handle label (3\u201320 chars: lowercase a\u2013z, 0\u20139, hyphens)").description(
35232
34264
  "Claim <label>.agent-id.sui \u2192 this wallet (custody-minted, gasless). Use --release to give it up."
35233
- ).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_BASE5})`).action(
34265
+ ).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(
35234
34266
  async (label, opts) => {
35235
34267
  try {
35236
- const base = opts.api ?? DEFAULT_API_BASE5;
34268
+ const base = opts.api ?? DEFAULT_API_BASE4;
35237
34269
  const agent = await withAgent({ keyPath: opts.key });
35238
34270
  const address = agent.address();
35239
- const challenge = await fetchJson5(`${base}/agent/challenge`, {
34271
+ const challenge = await fetchJson2(`${base}/agent/challenge`, {
35240
34272
  method: "POST",
35241
34273
  body: { address }
35242
34274
  });
@@ -35248,7 +34280,7 @@ Subcommands:
35248
34280
  const message = new TextEncoder().encode(`${action}:${nonce}:${label}`);
35249
34281
  const { signature } = await agent.keypair.signPersonalMessage(message);
35250
34282
  const path2 = opts.release ? "/agent/handle/release" : "/agent/handle";
35251
- const res = await fetchJson5(`${base}${path2}`, {
34283
+ const res = await fetchJson2(`${base}${path2}`, {
35252
34284
  method: "POST",
35253
34285
  body: { address, label, nonce, signature }
35254
34286
  });
@@ -35274,7 +34306,7 @@ Subcommands:
35274
34306
  }
35275
34307
 
35276
34308
  // src/commands/agents.ts
35277
- var DEFAULT_API_BASE6 = process.env.T2000_API_URL ?? "https://api.t2000.ai/v1";
34309
+ var DEFAULT_API_BASE5 = process.env.T2000_API_URL ?? "https://api.t2000.ai/v1";
35278
34310
  async function getJson(url) {
35279
34311
  const res = await fetch(url, { headers: { accept: "application/json" } });
35280
34312
  if (!res.ok) {
@@ -35288,11 +34320,11 @@ function firstLine(text, max = 76) {
35288
34320
  }
35289
34321
  function registerAgents(program3) {
35290
34322
  program3.command("agents").argument("[address]", "Show one agent\u2019s full listing (profile + reputation)").description(
35291
- "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]"
35292
- ).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_BASE6})`).action(
34323
+ "Look up the agent directory (agents.t2000.ai): priced services from the live registry, or one agent\u2019s full listing. Buy with `t2 agent pay <address>`. [Agent Commerce]"
34324
+ ).option("--category <category>", "Filter the list by 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(
35293
34325
  async (address, opts) => {
35294
34326
  try {
35295
- const base = opts.api ?? DEFAULT_API_BASE6;
34327
+ const base = opts.api ?? DEFAULT_API_BASE5;
35296
34328
  if (address) {
35297
34329
  const profile = await getJson(`${base}/agents/${address}`);
35298
34330
  if (isJsonMode()) {
@@ -35345,7 +34377,7 @@ function registerAgents(program3) {
35345
34377
  }
35346
34378
  printBlank();
35347
34379
  printHeader(
35348
- `Agent store \u2014 ${agents.length} ${opts.all ? "agents" : "priced services"}${opts.category ? ` in ${opts.category}` : ""}`
34380
+ `Agent directory \u2014 ${agents.length} ${opts.all ? "agents" : "priced services"}${opts.category ? ` in ${opts.category}` : ""}`
35349
34381
  );
35350
34382
  for (const a of agents) {
35351
34383
  const price = a.priceUsdc ? formatUsd(Number.parseFloat(a.priceUsdc)).padStart(6) : " \u2014";
@@ -35364,256 +34396,6 @@ function registerAgents(program3) {
35364
34396
  );
35365
34397
  }
35366
34398
 
35367
- // src/commands/task/index.ts
35368
- var DEFAULT_GATEWAY4 = process.env.T2000_GATEWAY_URL ?? "https://mpp.t2000.ai";
35369
- async function getJson2(url) {
35370
- const res = await fetch(url, { headers: { accept: "application/json" } });
35371
- const json = await res.json().catch(() => ({}));
35372
- if (!res.ok) {
35373
- throw new Error(json.error ?? `Request failed (${res.status}).`);
35374
- }
35375
- return json;
35376
- }
35377
- async function postJson2(url, body2) {
35378
- const res = await fetch(url, {
35379
- method: "POST",
35380
- headers: { "content-type": "application/json" },
35381
- body: JSON.stringify(body2)
35382
- });
35383
- const json = await res.json().catch(() => ({}));
35384
- if (!res.ok) {
35385
- throw new Error(json.error ?? `Request failed (${res.status}).`);
35386
- }
35387
- return json;
35388
- }
35389
- function registerTask(program3) {
35390
- const group = program3.command("task").description(
35391
- "Earn from t2000 reward tasks and work (or post) community board tasks \u2014 all paid through the rail. [Agent Commerce]"
35392
- );
35393
- group.command("list").description("Live tasks: t2000 rewards (auto-verified) + the community board (poster-approved)").option("--gateway <url>", `Gateway base URL (default ${DEFAULT_GATEWAY4})`).action(async (opts) => {
35394
- try {
35395
- const gateway = opts.gateway ?? DEFAULT_GATEWAY4;
35396
- const [rewards, board] = await Promise.all([
35397
- getJson2(`${gateway}/tasks/stats`),
35398
- getJson2(`${gateway}/tasks/board`)
35399
- ]);
35400
- if (isJsonMode()) {
35401
- printJson({ rewards: rewards.tasks, board: board.tasks });
35402
- return;
35403
- }
35404
- printBlank();
35405
- printHeader("t2000 reward tasks (auto-verified, one per wallet)");
35406
- for (const t of rewards.tasks) {
35407
- printLine(
35408
- ` ${formatUsd(t.rewardNetUsd).padStart(6)} ${t.id.padEnd(20)} ${t.kind.padEnd(8)} ${t.status === "live" ? "live" : "budget spent"}`
35409
- );
35410
- }
35411
- printBlank();
35412
- printHeader(`Community board (${board.tasks.length} live, poster approves)`);
35413
- if (board.tasks.length === 0) {
35414
- printLine(" (none live \u2014 post one: t2 task post --help)");
35415
- }
35416
- for (const t of board.tasks) {
35417
- const days = Math.max(0, Math.ceil((Date.parse(t.expiresAt) - Date.now()) / 864e5));
35418
- printLine(
35419
- ` ${formatUsd(t.rewardUsd).padStart(6)} ${t.title.slice(0, 44).padEnd(44)} ${t.remainingCompletions}/${t.maxCompletions} spots \xB7 ${days}d ${t.id}`
35420
- );
35421
- }
35422
- printBlank();
35423
- printInfo("Claim a reward: t2 task claim <task> \xB7 Work the board: t2 task submit <taskId>");
35424
- printBlank();
35425
- } catch (error) {
35426
- handleError(error);
35427
- }
35428
- });
35429
- group.command("claim").argument("<task>", "Reward task id (e.g. buy-sui, share-a-read) \u2014 see `t2 task list`").description("Claim a t2000 reward task (verified in one request; also retries automated tasks)").option("--tx <digest>", "Swap tx digest (buy-manifest / buy-sui)").option("--post <url>", "Your X post URL (X-proof tasks)").option("--gateway <url>", `Gateway base URL (default ${DEFAULT_GATEWAY4})`).option("--key <path>", "Custom wallet path (default ~/.t2000/wallet.key)").action(
35430
- async (task, opts) => {
35431
- try {
35432
- const gateway = opts.gateway ?? DEFAULT_GATEWAY4;
35433
- const agent = await withAgent({ keyPath: opts.key });
35434
- const result = await postJson2(`${gateway}/tasks/claim`, {
35435
- task,
35436
- address: agent.address(),
35437
- ...opts.tx ? { txDigest: opts.tx } : {},
35438
- ...opts.post ? { postUrl: opts.post } : {}
35439
- });
35440
- if (isJsonMode()) {
35441
- printJson(result);
35442
- return;
35443
- }
35444
- printBlank();
35445
- if (result.paid) {
35446
- printSuccess(`Paid ${formatUsd(result.netUsd ?? 0)} to your agent.`);
35447
- if (result.suiscan) {
35448
- printKeyValue("Receipt", result.suiscan);
35449
- }
35450
- } else {
35451
- printWarning(result.note ?? "Not paid.");
35452
- }
35453
- printBlank();
35454
- } catch (error) {
35455
- handleError(error);
35456
- }
35457
- }
35458
- );
35459
- group.command("post").description(
35460
- "Post a community task \u2014 pays the FULL budget (reward \xD7 completions) into escrow via x402; auto-moderated at post time. SAVE the returned manageKey."
35461
- ).requiredOption("--title <text>", "What needs doing (8+ chars)").requiredOption("--description <text>", "Exactly what the worker must deliver + what proof (30+ chars)").requiredOption("--reward <usdc>", "Reward per approved completion ($0.01\u2013$50)").option("--completions <n>", "Max completions (default 1)", "1").option("--expiry-days <n>", "Days until unspent budget auto-refunds (default 7)", "7").option("--category <category>", "research | data | marketing | dev | creative | other", "other").option("--notify-email <email>", "Email me when submissions arrive + when the refund settles (per-task, one-click stop in every mail)").option("--gateway <url>", `Gateway base URL (default ${DEFAULT_GATEWAY4})`).option("--force", "Override spending limits for this call (see `t2 limit`)").option("--key <path>", "Custom wallet path (default ~/.t2000/wallet.key)").action(
35462
- async (opts) => {
35463
- try {
35464
- const gateway = opts.gateway ?? DEFAULT_GATEWAY4;
35465
- const reward = Number.parseFloat(opts.reward);
35466
- const completions = Number.parseInt(opts.completions, 10);
35467
- if (!Number.isFinite(reward) || reward <= 0) {
35468
- throw new Error(`--reward must be a positive number (got "${opts.reward}").`);
35469
- }
35470
- const budget = Math.round(reward * completions * 1e6) / 1e6;
35471
- const agent = await withAgent({ keyPath: opts.key });
35472
- const result = await agent.pay({
35473
- url: `${gateway}/tasks/board`,
35474
- method: "POST",
35475
- body: JSON.stringify({
35476
- title: opts.title,
35477
- description: opts.description,
35478
- rewardUsd: reward,
35479
- maxCompletions: completions,
35480
- expiryDays: Number.parseInt(opts.expiryDays, 10),
35481
- category: opts.category,
35482
- ...opts.notifyEmail ? { notifyEmail: opts.notifyEmail } : {}
35483
- }),
35484
- maxPrice: budget,
35485
- force: opts.force
35486
- });
35487
- const body2 = result.body;
35488
- if (isJsonMode()) {
35489
- printJson(body2 ?? result);
35490
- return;
35491
- }
35492
- printBlank();
35493
- if (body2?.ok && body2.manageKey) {
35494
- printSuccess(body2.moderation ?? "Task posted.");
35495
- printKeyValue("Task", body2.task?.id ?? "\u2014");
35496
- printKeyValue("Escrow", formatUsd(budget));
35497
- printBlank();
35498
- printWarning("SAVE THIS manageKey \u2014 shown once. It approves/rejects/closes this task:");
35499
- printLine(` ${body2.manageKey}`);
35500
- printBlank();
35501
- printInfo(`Review: t2 task review ${body2.task?.id ?? "<taskId>"} --manage-key <key>`);
35502
- } else {
35503
- printWarning(
35504
- `${body2?.error ?? "Posting failed."}${body2?.refunded ? " (Budget refunded.)" : ""}`
35505
- );
35506
- }
35507
- printBlank();
35508
- } catch (error) {
35509
- handleError(error);
35510
- }
35511
- }
35512
- );
35513
- group.command("submit").argument("<taskId>", "Board task id (see `t2 task list`)").description("Submit proof of completion to a board task (one submission per wallet)").requiredOption("--proof <text>", "What you did + how the poster can verify it (10+ chars)").option("--url <url>", "Proof link (https)").option("--gateway <url>", `Gateway base URL (default ${DEFAULT_GATEWAY4})`).option("--key <path>", "Custom wallet path (default ~/.t2000/wallet.key)").action(
35514
- async (taskId, opts) => {
35515
- try {
35516
- const gateway = opts.gateway ?? DEFAULT_GATEWAY4;
35517
- const agent = await withAgent({ keyPath: opts.key });
35518
- const result = await postJson2(
35519
- `${gateway}/tasks/board/${taskId}/submit`,
35520
- {
35521
- address: agent.address(),
35522
- proof: opts.proof,
35523
- ...opts.url ? { url: opts.url } : {}
35524
- }
35525
- );
35526
- if (isJsonMode()) {
35527
- printJson(result);
35528
- return;
35529
- }
35530
- printBlank();
35531
- printSuccess(result.note ?? "Submitted \u2014 the poster reviews next.");
35532
- printBlank();
35533
- } catch (error) {
35534
- handleError(error);
35535
- }
35536
- }
35537
- );
35538
- group.command("review").argument("<taskId>", "Your board task id").description("List submissions on your board task (poster view \u2014 needs the manageKey)").requiredOption("--manage-key <key>", "The manageKey returned when you posted").option("--gateway <url>", `Gateway base URL (default ${DEFAULT_GATEWAY4})`).action(async (taskId, opts) => {
35539
- try {
35540
- const gateway = opts.gateway ?? DEFAULT_GATEWAY4;
35541
- const result = await getJson2(`${gateway}/tasks/board/${taskId}?manageKey=${encodeURIComponent(opts.manageKey)}`);
35542
- if (!result.posterView) {
35543
- throw new Error(result.error ?? "manageKey not accepted for this task.");
35544
- }
35545
- if (isJsonMode()) {
35546
- printJson(result);
35547
- return;
35548
- }
35549
- const subs = result.submissions ?? [];
35550
- printBlank();
35551
- printHeader(`${result.task?.title ?? taskId} \u2014 ${subs.length} submission${subs.length === 1 ? "" : "s"}`);
35552
- for (const s of subs) {
35553
- printLine(` [${s.status.padEnd(8)}] ${s.id} ${truncateAddress(s.worker)}`);
35554
- if (s.proof) {
35555
- printLine(` ${s.proof.slice(0, 90)}`);
35556
- }
35557
- if (s.url) {
35558
- printLine(` ${s.url}`);
35559
- }
35560
- }
35561
- printBlank();
35562
- printInfo(`Pay: t2 task approve ${taskId} --manage-key <key> --submissions <id,id,\u2026>`);
35563
- printBlank();
35564
- } catch (error) {
35565
- handleError(error);
35566
- }
35567
- });
35568
- group.command("approve").argument("<taskId>", "Your board task id").description("Approve (pay) or reject submissions on your board task \u2014 batch up to 50").requiredOption("--manage-key <key>", "The manageKey returned when you posted").requiredOption("--submissions <ids>", "Comma-separated submission ids").option("--reject", "Reject instead of approving").option("--gateway <url>", `Gateway base URL (default ${DEFAULT_GATEWAY4})`).action(
35569
- async (taskId, opts) => {
35570
- try {
35571
- const gateway = opts.gateway ?? DEFAULT_GATEWAY4;
35572
- const result = await postJson2(`${gateway}/tasks/board/${taskId}/approve`, {
35573
- manageKey: opts.manageKey,
35574
- submissionIds: opts.submissions.split(",").map((s) => s.trim()).filter(Boolean),
35575
- action: opts.reject ? "reject" : "approve"
35576
- });
35577
- if (isJsonMode()) {
35578
- printJson(result);
35579
- return;
35580
- }
35581
- printBlank();
35582
- for (const r of result.results ?? []) {
35583
- if (r.status === "paid") {
35584
- printSuccess(`${r.submissionId} paid${r.payoutTx ? ` (tx ${r.payoutTx.slice(0, 10)}\u2026)` : ""}`);
35585
- } else if (r.error) {
35586
- printWarning(`${r.submissionId}: ${r.error}`);
35587
- } else {
35588
- printLine(` ${r.submissionId}: ${r.status}`);
35589
- }
35590
- }
35591
- printBlank();
35592
- } catch (error) {
35593
- handleError(error);
35594
- }
35595
- }
35596
- );
35597
- group.command("close").argument("<taskId>", "Your board task id").description("Close your board task early \u2014 the unspent budget refunds to your wallet").requiredOption("--manage-key <key>", "The manageKey returned when you posted").option("--gateway <url>", `Gateway base URL (default ${DEFAULT_GATEWAY4})`).action(async (taskId, opts) => {
35598
- try {
35599
- const gateway = opts.gateway ?? DEFAULT_GATEWAY4;
35600
- const result = await postJson2(`${gateway}/tasks/board/${taskId}/close`, { manageKey: opts.manageKey });
35601
- if (isJsonMode()) {
35602
- printJson(result);
35603
- return;
35604
- }
35605
- printBlank();
35606
- printSuccess(`Task closed${result.refunded ? " \u2014 unspent budget refunded" : ""}.`);
35607
- if (result.suiscan) {
35608
- printKeyValue("Refund", result.suiscan);
35609
- }
35610
- printBlank();
35611
- } catch (error) {
35612
- handleError(error);
35613
- }
35614
- });
35615
- }
35616
-
35617
34399
  // src/program.ts
35618
34400
  var require3 = createRequire2(import.meta.url);
35619
34401
  var { version: CLI_VERSION2 } = require3("../package.json");
@@ -35635,10 +34417,8 @@ Examples:
35635
34417
  $ t2 models List the Private API model catalog
35636
34418
  $ t2 pay <url> --estimate Preview an x402 service's price + input schema (no payment)
35637
34419
  $ t2 services search "image" Discover x402 services in the gateway catalog
35638
- $ t2 agents Browse the agent store (agents.t2000.ai)
34420
+ $ t2 agents Look up the agent directory (agents.t2000.ai)
35639
34421
  $ t2 agent pay <address> Buy an agent's service (escrowed, auto-refund on failure)
35640
- $ t2 task list Live reward tasks + the community board
35641
- $ t2 task claim share-a-read --post <url> Claim an X-proof reward
35642
34422
  $ t2 limit set --daily 100 Change the daily spend cap (default $100/day)
35643
34423
  $ t2 mcp install Connect Claude / Cursor / Windsurf
35644
34424
  $ t2 skills install Install skills as local SKILL.md files`);
@@ -35659,7 +34439,6 @@ Examples:
35659
34439
  registerSkills(program3);
35660
34440
  registerAgent(program3);
35661
34441
  registerAgents(program3);
35662
- registerTask(program3);
35663
34442
  return program3;
35664
34443
  }
35665
34444