@t2000/cli 5.25.0 → 5.27.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js
CHANGED
|
@@ -32124,7 +32124,13 @@ function withoutMcpEntry(config) {
|
|
|
32124
32124
|
|
|
32125
32125
|
// src/commands/status.ts
|
|
32126
32126
|
var require2 = createRequire(import.meta.url);
|
|
32127
|
-
var { version: CLI_VERSION } =
|
|
32127
|
+
var { version: CLI_VERSION } = (() => {
|
|
32128
|
+
try {
|
|
32129
|
+
return require2("../package.json");
|
|
32130
|
+
} catch {
|
|
32131
|
+
return require2("../../package.json");
|
|
32132
|
+
}
|
|
32133
|
+
})();
|
|
32128
32134
|
var GATEWAY_URL = process.env.T2000_GATEWAY_URL ?? "https://mpp.t2000.ai";
|
|
32129
32135
|
var GATEWAY_TIMEOUT_MS = 3e3;
|
|
32130
32136
|
async function checkGateway() {
|
|
@@ -33109,7 +33115,7 @@ function registerMcpStart(parent) {
|
|
|
33109
33115
|
parent.command("start", { isDefault: true }).description("Start MCP server (stdio transport \u2014 for AI client integration)").option("--key <path>", "Custom wallet path (default ~/.t2000/wallet.key)").action(async (opts) => {
|
|
33110
33116
|
let mod3;
|
|
33111
33117
|
try {
|
|
33112
|
-
mod3 = await import("./dist-
|
|
33118
|
+
mod3 = await import("./dist-JCY6PNWP.js");
|
|
33113
33119
|
} catch {
|
|
33114
33120
|
console.error("MCP server not installed. Run:\n npm install -g @t2000/mcp");
|
|
33115
33121
|
process.exit(1);
|
|
@@ -33449,9 +33455,319 @@ For MCP-aware clients (Claude Desktop, Cursor, Windsurf), prefer
|
|
|
33449
33455
|
}
|
|
33450
33456
|
|
|
33451
33457
|
// src/commands/agent/index.ts
|
|
33458
|
+
import { createHash as createHash3 } from "crypto";
|
|
33459
|
+
|
|
33460
|
+
// src/commands/agent/review.ts
|
|
33452
33461
|
import { createHash } from "crypto";
|
|
33462
|
+
var DEFAULT_GATEWAY = "https://x402.t2000.ai";
|
|
33463
|
+
async function fetchJson(url, init) {
|
|
33464
|
+
const res = await fetch(url, {
|
|
33465
|
+
method: init?.method ?? "GET",
|
|
33466
|
+
headers: init?.body ? { "Content-Type": "application/json" } : void 0,
|
|
33467
|
+
body: init?.body ? JSON.stringify(init.body) : void 0
|
|
33468
|
+
});
|
|
33469
|
+
const json = await res.json().catch(() => ({}));
|
|
33470
|
+
if (!res.ok) {
|
|
33471
|
+
const err = json.error;
|
|
33472
|
+
throw new Error(typeof err === "string" ? err : `HTTP ${res.status}`);
|
|
33473
|
+
}
|
|
33474
|
+
return json;
|
|
33475
|
+
}
|
|
33476
|
+
function reviewMessage(digest, stars, text, timestamp) {
|
|
33477
|
+
const hash = createHash("sha256").update(text, "utf8").digest("hex");
|
|
33478
|
+
return `t2000-review:${digest}:${stars}:${hash}:${timestamp}`;
|
|
33479
|
+
}
|
|
33480
|
+
function registerAgentReview(agent) {
|
|
33481
|
+
agent.command("review").description(
|
|
33482
|
+
"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]"
|
|
33483
|
+
).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(
|
|
33484
|
+
async (seller, opts) => {
|
|
33485
|
+
try {
|
|
33486
|
+
const stars = Number(opts.stars);
|
|
33487
|
+
if (!Number.isInteger(stars) || stars < 1 || stars > 5) {
|
|
33488
|
+
throw new Error("--stars must be an integer 1-5.");
|
|
33489
|
+
}
|
|
33490
|
+
const text = (opts.text ?? "").trim();
|
|
33491
|
+
if (text.length > 400) {
|
|
33492
|
+
throw new Error("--text must be \u2264 400 chars.");
|
|
33493
|
+
}
|
|
33494
|
+
const gateway = opts.gateway ?? DEFAULT_GATEWAY;
|
|
33495
|
+
const agentW = await withAgent({ keyPath: opts.key });
|
|
33496
|
+
const buyer = agentW.address();
|
|
33497
|
+
let digest = (opts.digest ?? "").trim();
|
|
33498
|
+
if (!digest) {
|
|
33499
|
+
const res = await fetchJson(
|
|
33500
|
+
`${gateway}/commerce/review?buyer=${buyer}&seller=${encodeURIComponent(seller)}`
|
|
33501
|
+
);
|
|
33502
|
+
const reviewable = res.reviewable ?? [];
|
|
33503
|
+
if (reviewable.length === 0) {
|
|
33504
|
+
throw new Error(
|
|
33505
|
+
"No settled purchase from this wallet to that seller \u2014 buy first (`t2 agent pay`), then review."
|
|
33506
|
+
);
|
|
33507
|
+
}
|
|
33508
|
+
digest = reviewable[0].digest;
|
|
33509
|
+
}
|
|
33510
|
+
const timestamp = Date.now();
|
|
33511
|
+
const message = new TextEncoder().encode(
|
|
33512
|
+
reviewMessage(digest, stars, text, timestamp)
|
|
33513
|
+
);
|
|
33514
|
+
const { signature } = await agentW.keypair.signPersonalMessage(message);
|
|
33515
|
+
await fetchJson(`${gateway}/commerce/review`, {
|
|
33516
|
+
method: "POST",
|
|
33517
|
+
body: { digest, stars, text, timestamp, signature }
|
|
33518
|
+
});
|
|
33519
|
+
if (isJsonMode()) {
|
|
33520
|
+
printJson({ ok: true, digest, stars, text: text || null });
|
|
33521
|
+
return;
|
|
33522
|
+
}
|
|
33523
|
+
printBlank();
|
|
33524
|
+
printSuccess(
|
|
33525
|
+
`Review posted \u2014 ${"\u2605".repeat(stars)}${"\u2606".repeat(5 - stars)}${text ? ` "${text}"` : ""}`
|
|
33526
|
+
);
|
|
33527
|
+
printKeyValue("Receipt", digest);
|
|
33528
|
+
printKeyValue(
|
|
33529
|
+
"Listing",
|
|
33530
|
+
`https://agents.t2000.ai/${seller.startsWith("0x") ? seller : ""}`
|
|
33531
|
+
);
|
|
33532
|
+
printBlank();
|
|
33533
|
+
} catch (e) {
|
|
33534
|
+
handleError(e);
|
|
33535
|
+
}
|
|
33536
|
+
}
|
|
33537
|
+
);
|
|
33538
|
+
}
|
|
33539
|
+
|
|
33540
|
+
// src/commands/agent/services.ts
|
|
33541
|
+
import { createHash as createHash2 } from "crypto";
|
|
33542
|
+
import { readFileSync as readFileSync3 } from "fs";
|
|
33543
|
+
var SLUG_RE = /^[a-z0-9][a-z0-9-]{1,39}$/;
|
|
33544
|
+
async function fetchJson2(url, init) {
|
|
33545
|
+
const res = await fetch(url, {
|
|
33546
|
+
method: init?.method ?? "GET",
|
|
33547
|
+
headers: init?.body ? { "Content-Type": "application/json" } : void 0,
|
|
33548
|
+
body: init?.body ? JSON.stringify(init.body) : void 0
|
|
33549
|
+
});
|
|
33550
|
+
const json = await res.json().catch(() => ({}));
|
|
33551
|
+
if (!res.ok) {
|
|
33552
|
+
const err = json.error;
|
|
33553
|
+
const msg = typeof err === "string" ? err : err?.message ?? `HTTP ${res.status}`;
|
|
33554
|
+
throw new Error(msg);
|
|
33555
|
+
}
|
|
33556
|
+
return json;
|
|
33557
|
+
}
|
|
33558
|
+
function canonicalServicesJson(services) {
|
|
33559
|
+
return JSON.stringify(
|
|
33560
|
+
services.map(
|
|
33561
|
+
(s) => Object.fromEntries(
|
|
33562
|
+
Object.entries(s).sort(([a], [b]) => a.localeCompare(b))
|
|
33563
|
+
)
|
|
33564
|
+
)
|
|
33565
|
+
);
|
|
33566
|
+
}
|
|
33567
|
+
async function getCatalog(base, address) {
|
|
33568
|
+
const res = await fetchJson2(
|
|
33569
|
+
`${base}/agent/services?address=${encodeURIComponent(address)}`
|
|
33570
|
+
);
|
|
33571
|
+
return Array.isArray(res.services) ? res.services : [];
|
|
33572
|
+
}
|
|
33573
|
+
async function putCatalog(opts) {
|
|
33574
|
+
const agent = await withAgent({ keyPath: opts.keyPath });
|
|
33575
|
+
const address = agent.address();
|
|
33576
|
+
const challenge = await fetchJson2(`${opts.base}/agent/challenge`, {
|
|
33577
|
+
method: "POST",
|
|
33578
|
+
body: { address }
|
|
33579
|
+
});
|
|
33580
|
+
const nonce = challenge.nonce;
|
|
33581
|
+
if (!nonce) {
|
|
33582
|
+
throw new Error("Failed to get a challenge nonce.");
|
|
33583
|
+
}
|
|
33584
|
+
const digest = createHash2("sha256").update(canonicalServicesJson(opts.services)).digest("hex");
|
|
33585
|
+
const message = new TextEncoder().encode(
|
|
33586
|
+
`t2000-agent-services:${nonce}:${digest}`
|
|
33587
|
+
);
|
|
33588
|
+
const { signature } = await agent.keypair.signPersonalMessage(message);
|
|
33589
|
+
const res = await fetchJson2(`${opts.base}/agent/services`, {
|
|
33590
|
+
method: "POST",
|
|
33591
|
+
body: { address, nonce, signature, services: opts.services }
|
|
33592
|
+
});
|
|
33593
|
+
return { address, count: Number(res.count ?? opts.services.length) };
|
|
33594
|
+
}
|
|
33595
|
+
function entryFromFlags(opts) {
|
|
33596
|
+
const slug = String(opts.slug ?? "").trim().toLowerCase();
|
|
33597
|
+
if (!SLUG_RE.test(slug)) {
|
|
33598
|
+
throw new Error("--slug is required: [a-z0-9-], 2-40 chars.");
|
|
33599
|
+
}
|
|
33600
|
+
const out = { slug };
|
|
33601
|
+
if (opts.title !== void 0) {
|
|
33602
|
+
out.title = opts.title;
|
|
33603
|
+
}
|
|
33604
|
+
if (opts.description !== void 0) {
|
|
33605
|
+
out.description = opts.description;
|
|
33606
|
+
}
|
|
33607
|
+
if (opts.price !== void 0) {
|
|
33608
|
+
out.priceUsdc = opts.price;
|
|
33609
|
+
}
|
|
33610
|
+
if (opts.input !== void 0) {
|
|
33611
|
+
out.input = opts.input || null;
|
|
33612
|
+
}
|
|
33613
|
+
if (opts.endpoint !== void 0) {
|
|
33614
|
+
out.endpoint = opts.endpoint || null;
|
|
33615
|
+
}
|
|
33616
|
+
if (opts.method !== void 0) {
|
|
33617
|
+
out.method = opts.method.toUpperCase() === "GET" ? "GET" : "POST";
|
|
33618
|
+
}
|
|
33619
|
+
return out;
|
|
33620
|
+
}
|
|
33621
|
+
function registerAgentServices(agentGroup, defaults) {
|
|
33622
|
+
const group = agentGroup.command("services").description(
|
|
33623
|
+
"Manage this agent's service CATALOG (one agent, many services). Buy URLs: commerce/pay/<agent>/<slug>. [Store v2]"
|
|
33624
|
+
);
|
|
33625
|
+
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) => {
|
|
33626
|
+
try {
|
|
33627
|
+
const base = opts.api ?? defaults.apiBase;
|
|
33628
|
+
const address = addressArg ?? (await withAgent({ keyPath: opts.key })).address();
|
|
33629
|
+
const services = await getCatalog(base, address);
|
|
33630
|
+
if (isJsonMode()) {
|
|
33631
|
+
printJson({ address, services });
|
|
33632
|
+
return;
|
|
33633
|
+
}
|
|
33634
|
+
printBlank();
|
|
33635
|
+
if (services.length === 0) {
|
|
33636
|
+
printLine("No services in the catalog. Add one: t2 agent services add --slug <slug> --title \u2026 --description \u2026 --price \u2026");
|
|
33637
|
+
printBlank();
|
|
33638
|
+
return;
|
|
33639
|
+
}
|
|
33640
|
+
for (const s of services) {
|
|
33641
|
+
printKeyValue(
|
|
33642
|
+
s.slug,
|
|
33643
|
+
`$${s.priceUsdc} \u2014 ${s.title}${s.active === false ? " (inactive)" : ""}`
|
|
33644
|
+
);
|
|
33645
|
+
}
|
|
33646
|
+
printBlank();
|
|
33647
|
+
} catch (error) {
|
|
33648
|
+
handleError(error);
|
|
33649
|
+
}
|
|
33650
|
+
});
|
|
33651
|
+
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) => {
|
|
33652
|
+
try {
|
|
33653
|
+
const base = opts.api ?? defaults.apiBase;
|
|
33654
|
+
const agent = await withAgent({ keyPath: opts.key });
|
|
33655
|
+
const current = await getCatalog(base, agent.address());
|
|
33656
|
+
const entry = entryFromFlags(opts);
|
|
33657
|
+
if (current.some((s) => s.slug === entry.slug)) {
|
|
33658
|
+
throw new Error(
|
|
33659
|
+
`Slug "${entry.slug}" already exists \u2014 use: t2 agent services update --slug ${entry.slug}`
|
|
33660
|
+
);
|
|
33661
|
+
}
|
|
33662
|
+
const next = {
|
|
33663
|
+
title: "",
|
|
33664
|
+
description: "",
|
|
33665
|
+
priceUsdc: "0",
|
|
33666
|
+
active: true,
|
|
33667
|
+
...entry
|
|
33668
|
+
};
|
|
33669
|
+
const { count } = await putCatalog({
|
|
33670
|
+
base,
|
|
33671
|
+
keyPath: opts.key,
|
|
33672
|
+
services: [...current, next]
|
|
33673
|
+
});
|
|
33674
|
+
if (isJsonMode()) {
|
|
33675
|
+
printJson({ added: entry.slug, count });
|
|
33676
|
+
return;
|
|
33677
|
+
}
|
|
33678
|
+
printBlank();
|
|
33679
|
+
printSuccess(`Service "${entry.slug}" added \u2014 catalog now ${count} service${count === 1 ? "" : "s"}.`);
|
|
33680
|
+
printLine(`Buy URL: https://x402.t2000.ai/commerce/pay/${agent.address()}/${entry.slug}`);
|
|
33681
|
+
printBlank();
|
|
33682
|
+
} catch (error) {
|
|
33683
|
+
handleError(error);
|
|
33684
|
+
}
|
|
33685
|
+
});
|
|
33686
|
+
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) => {
|
|
33687
|
+
try {
|
|
33688
|
+
const base = opts.api ?? defaults.apiBase;
|
|
33689
|
+
const agent = await withAgent({ keyPath: opts.key });
|
|
33690
|
+
const current = await getCatalog(base, agent.address());
|
|
33691
|
+
const entry = entryFromFlags(opts);
|
|
33692
|
+
const idx = current.findIndex((s) => s.slug === entry.slug);
|
|
33693
|
+
if (idx === -1) {
|
|
33694
|
+
throw new Error(`No service "${entry.slug}" in the catalog.`);
|
|
33695
|
+
}
|
|
33696
|
+
const merged = { ...current[idx], ...entry };
|
|
33697
|
+
if (opts.active !== void 0) {
|
|
33698
|
+
merged.active = String(opts.active).toLowerCase() !== "false";
|
|
33699
|
+
}
|
|
33700
|
+
const services = [...current];
|
|
33701
|
+
services[idx] = merged;
|
|
33702
|
+
const { count } = await putCatalog({ base, keyPath: opts.key, services });
|
|
33703
|
+
if (isJsonMode()) {
|
|
33704
|
+
printJson({ updated: entry.slug, count });
|
|
33705
|
+
return;
|
|
33706
|
+
}
|
|
33707
|
+
printBlank();
|
|
33708
|
+
printSuccess(`Service "${entry.slug}" updated.`);
|
|
33709
|
+
printBlank();
|
|
33710
|
+
} catch (error) {
|
|
33711
|
+
handleError(error);
|
|
33712
|
+
}
|
|
33713
|
+
});
|
|
33714
|
+
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) => {
|
|
33715
|
+
try {
|
|
33716
|
+
const base = opts.api ?? defaults.apiBase;
|
|
33717
|
+
const agent = await withAgent({ keyPath: opts.key });
|
|
33718
|
+
const slug = String(opts.slug ?? "").trim().toLowerCase();
|
|
33719
|
+
const current = await getCatalog(base, agent.address());
|
|
33720
|
+
const services = current.filter((s) => s.slug !== slug);
|
|
33721
|
+
if (services.length === current.length) {
|
|
33722
|
+
throw new Error(`No service "${slug}" in the catalog.`);
|
|
33723
|
+
}
|
|
33724
|
+
const { count } = await putCatalog({ base, keyPath: opts.key, services });
|
|
33725
|
+
if (isJsonMode()) {
|
|
33726
|
+
printJson({ removed: slug, count });
|
|
33727
|
+
return;
|
|
33728
|
+
}
|
|
33729
|
+
printBlank();
|
|
33730
|
+
printSuccess(`Service "${slug}" removed \u2014 catalog now ${count} service${count === 1 ? "" : "s"}.`);
|
|
33731
|
+
printBlank();
|
|
33732
|
+
} catch (error) {
|
|
33733
|
+
handleError(error);
|
|
33734
|
+
}
|
|
33735
|
+
});
|
|
33736
|
+
group.command("sync").description(
|
|
33737
|
+
"Declarative catalog sync \u2014 the manifest file IS the catalog (adds/updates/removes to match). The catalog-scale path."
|
|
33738
|
+
).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) => {
|
|
33739
|
+
try {
|
|
33740
|
+
const base = opts.api ?? defaults.apiBase;
|
|
33741
|
+
const raw = JSON.parse(readFileSync3(file, "utf8"));
|
|
33742
|
+
const list = Array.isArray(raw) ? raw : raw?.services ?? null;
|
|
33743
|
+
if (!Array.isArray(list)) {
|
|
33744
|
+
throw new Error(
|
|
33745
|
+
'Manifest must be a JSON array of services (or { "services": [...] }).'
|
|
33746
|
+
);
|
|
33747
|
+
}
|
|
33748
|
+
const services = list.map((s) => {
|
|
33749
|
+
const entry = s;
|
|
33750
|
+
return { ...entry, active: entry.active !== false };
|
|
33751
|
+
});
|
|
33752
|
+
const agent = await withAgent({ keyPath: opts.key });
|
|
33753
|
+
const before = await getCatalog(base, agent.address());
|
|
33754
|
+
const { count } = await putCatalog({ base, keyPath: opts.key, services });
|
|
33755
|
+
if (isJsonMode()) {
|
|
33756
|
+
printJson({ synced: count, before: before.length });
|
|
33757
|
+
return;
|
|
33758
|
+
}
|
|
33759
|
+
printBlank();
|
|
33760
|
+
printSuccess(`Catalog synced \u2014 ${before.length} \u2192 ${count} services.`);
|
|
33761
|
+
printBlank();
|
|
33762
|
+
} catch (error) {
|
|
33763
|
+
handleError(error);
|
|
33764
|
+
}
|
|
33765
|
+
});
|
|
33766
|
+
}
|
|
33767
|
+
|
|
33768
|
+
// src/commands/agent/index.ts
|
|
33453
33769
|
var DEFAULT_API_BASE3 = process.env.T2000_API_URL ?? "https://api.t2000.ai/v1";
|
|
33454
|
-
var
|
|
33770
|
+
var DEFAULT_GATEWAY2 = process.env.T2000_GATEWAY_URL ?? "https://mpp.t2000.ai";
|
|
33455
33771
|
var DEFAULT_RAIL = process.env.T2000_RAIL_URL ?? "https://x402.t2000.ai";
|
|
33456
33772
|
var AGENT_CATEGORIES = [
|
|
33457
33773
|
"ai-models",
|
|
@@ -33490,19 +33806,19 @@ async function fundCredit(agent, base, amountStr, assetOpt) {
|
|
|
33490
33806
|
throw new Error(`amount must be a positive number (got "${amountStr}").`);
|
|
33491
33807
|
}
|
|
33492
33808
|
const asset = normalizeTopupAsset(assetOpt);
|
|
33493
|
-
const cfg = await
|
|
33809
|
+
const cfg = await fetchJson3(`${base}/agent/topup`, { method: "GET" });
|
|
33494
33810
|
const treasury = cfg.treasury;
|
|
33495
33811
|
if (!treasury) {
|
|
33496
33812
|
throw new Error("Could not resolve the t2000 treasury address.");
|
|
33497
33813
|
}
|
|
33498
33814
|
const sent = await agent.send({ to: treasury, amount, asset });
|
|
33499
|
-
const topup = await
|
|
33815
|
+
const topup = await fetchJson3(`${base}/agent/topup`, {
|
|
33500
33816
|
method: "POST",
|
|
33501
33817
|
body: { address: agent.address(), digest: sent.tx }
|
|
33502
33818
|
});
|
|
33503
33819
|
return { amount, asset, balanceUsd: topup.balanceUsd };
|
|
33504
33820
|
}
|
|
33505
|
-
async function
|
|
33821
|
+
async function fetchJson3(url, init) {
|
|
33506
33822
|
const res = await fetch(url, {
|
|
33507
33823
|
method: init.method,
|
|
33508
33824
|
headers: init.body ? { "Content-Type": "application/json" } : void 0,
|
|
@@ -33524,9 +33840,15 @@ Subcommands:
|
|
|
33524
33840
|
$ t2 agent onboard --fund 5 Fund 5 USDC \u2192 mint an API key (ready to call)
|
|
33525
33841
|
$ t2 agent onboard --fund 5 --asset USDsui
|
|
33526
33842
|
$ t2 agent onboard Already funded \u2192 just mint a key
|
|
33843
|
+
$ t2 agent services add --slug sui-price --title "SUI spot" --description "\u2026" --price 0.02
|
|
33844
|
+
$ t2 agent services sync ./services.json Manifest IS the catalog (catalog-scale sellers)
|
|
33527
33845
|
`
|
|
33528
33846
|
);
|
|
33529
|
-
group
|
|
33847
|
+
registerAgentServices(group, { apiBase: DEFAULT_API_BASE3 });
|
|
33848
|
+
registerAgentReview(group);
|
|
33849
|
+
group.command("onboard").description(
|
|
33850
|
+
"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`."
|
|
33851
|
+
).option("--fund <amount>", "Stablecoin amount to deposit as credit (omit if already funded)").option("--asset <asset>", "USDC (default) or USDsui", "USDC").option("--key <path>", "Custom wallet path (default ~/.t2000/wallet.key)").option("--api <url>", `API base URL (default ${DEFAULT_API_BASE3})`).action(
|
|
33530
33852
|
async (opts) => {
|
|
33531
33853
|
try {
|
|
33532
33854
|
const base = opts.api ?? DEFAULT_API_BASE3;
|
|
@@ -33540,7 +33862,7 @@ Subcommands:
|
|
|
33540
33862
|
);
|
|
33541
33863
|
}
|
|
33542
33864
|
}
|
|
33543
|
-
const challenge = await
|
|
33865
|
+
const challenge = await fetchJson3(`${base}/agent/challenge`, {
|
|
33544
33866
|
method: "POST",
|
|
33545
33867
|
body: { address }
|
|
33546
33868
|
});
|
|
@@ -33550,7 +33872,7 @@ Subcommands:
|
|
|
33550
33872
|
}
|
|
33551
33873
|
const message = new TextEncoder().encode(`t2000-agent-keys:${nonce}`);
|
|
33552
33874
|
const { signature } = await agent.keypair.signPersonalMessage(message);
|
|
33553
|
-
const minted = await
|
|
33875
|
+
const minted = await fetchJson3(`${base}/agent/keys`, {
|
|
33554
33876
|
method: "POST",
|
|
33555
33877
|
body: { address, nonce, signature }
|
|
33556
33878
|
});
|
|
@@ -33720,7 +34042,7 @@ Subcommands:
|
|
|
33720
34042
|
const base = opts.api ?? DEFAULT_API_BASE3;
|
|
33721
34043
|
const agent = await withAgent({ keyPath: opts.key });
|
|
33722
34044
|
const address = agent.address();
|
|
33723
|
-
const challenge = await
|
|
34045
|
+
const challenge = await fetchJson3(`${base}/agent/challenge`, {
|
|
33724
34046
|
method: "POST",
|
|
33725
34047
|
body: { address }
|
|
33726
34048
|
});
|
|
@@ -33730,7 +34052,7 @@ Subcommands:
|
|
|
33730
34052
|
}
|
|
33731
34053
|
const message = new TextEncoder().encode(`t2000-agent-profile:${nonce}`);
|
|
33732
34054
|
const { signature } = await agent.keypair.signPersonalMessage(message);
|
|
33733
|
-
await
|
|
34055
|
+
await fetchJson3(`${base}/agent/profile`, {
|
|
33734
34056
|
method: "POST",
|
|
33735
34057
|
body: {
|
|
33736
34058
|
address,
|
|
@@ -33837,31 +34159,37 @@ Subcommands:
|
|
|
33837
34159
|
).option("--method <method>", "Upstream method: GET or POST (default POST)").option("--price <usdc>", "Price per call in USDC (e.g. 0.02)").option(
|
|
33838
34160
|
"--category <category>",
|
|
33839
34161
|
`Storefront category: ${AGENT_CATEGORIES.join(" | ")}`
|
|
33840
|
-
).option("--remove", "Take down the deployed service").option(
|
|
34162
|
+
).option("--remove", "Take down the deployed service").option(
|
|
34163
|
+
"--service <slug>",
|
|
34164
|
+
"Catalog service slug \u2014 wrap config for ONE SKU (Store v2; omit = the default service)"
|
|
34165
|
+
).option("--gateway <url>", `Gateway base URL (default ${DEFAULT_GATEWAY2})`).option("--key <path>", "Custom wallet path (default ~/.t2000/wallet.key)").option("--api <url>", `API base URL (default ${DEFAULT_API_BASE3})`).action(
|
|
33841
34166
|
async (opts) => {
|
|
33842
34167
|
try {
|
|
33843
34168
|
const base = opts.api ?? DEFAULT_API_BASE3;
|
|
33844
|
-
const gateway = opts.gateway ??
|
|
34169
|
+
const gateway = opts.gateway ?? DEFAULT_GATEWAY2;
|
|
33845
34170
|
const category = normalizeCategory(opts.category);
|
|
34171
|
+
const slug = opts.service?.trim().toLowerCase() || void 0;
|
|
33846
34172
|
const agent = await withAgent({ keyPath: opts.key });
|
|
33847
34173
|
const address = agent.address();
|
|
33848
34174
|
if (opts.remove) {
|
|
33849
34175
|
const ts2 = Date.now();
|
|
33850
|
-
const msg2 = `t2000-deploy-remove:${ts2}`;
|
|
34176
|
+
const msg2 = `t2000-deploy-remove:${ts2}${slug ? `:${slug}` : ""}`;
|
|
33851
34177
|
const { signature: signature2 } = await agent.keypair.signPersonalMessage(
|
|
33852
34178
|
new TextEncoder().encode(msg2)
|
|
33853
34179
|
);
|
|
33854
|
-
await
|
|
34180
|
+
await fetchJson3(`${gateway}/deploy/config`, {
|
|
33855
34181
|
method: "DELETE",
|
|
33856
|
-
body: { address, timestamp: ts2, signature: signature2 }
|
|
34182
|
+
body: { address, timestamp: ts2, signature: signature2, ...slug ? { slug } : {} }
|
|
33857
34183
|
});
|
|
33858
|
-
|
|
33859
|
-
|
|
33860
|
-
|
|
33861
|
-
|
|
33862
|
-
|
|
33863
|
-
|
|
33864
|
-
|
|
34184
|
+
if (!slug) {
|
|
34185
|
+
await runSponsoredTx({
|
|
34186
|
+
keypair: agent.keypair,
|
|
34187
|
+
actor: address,
|
|
34188
|
+
prepareUrl: `${base}/agent/service/prepare`,
|
|
34189
|
+
prepareBody: { address, mcpEndpoint: "" },
|
|
34190
|
+
submitUrl: `${base}/agent/service/submit`
|
|
34191
|
+
}).catch(() => void 0);
|
|
34192
|
+
}
|
|
33865
34193
|
if (isJsonMode()) {
|
|
33866
34194
|
printJson({ address, removed: true });
|
|
33867
34195
|
return;
|
|
@@ -33881,12 +34209,14 @@ Subcommands:
|
|
|
33881
34209
|
const method = (opts.method ?? "POST").toUpperCase() === "GET" ? "GET" : "POST";
|
|
33882
34210
|
const headers = opts.header ?? {};
|
|
33883
34211
|
const ts = Date.now();
|
|
33884
|
-
const bodyHash =
|
|
34212
|
+
const bodyHash = createHash3("sha256").update(
|
|
34213
|
+
`${opts.upstream}|${method}|${JSON.stringify(headers)}${slug ? `|${slug}` : ""}`
|
|
34214
|
+
).digest("hex");
|
|
33885
34215
|
const msg = `t2000-deploy:${ts}:${bodyHash}`;
|
|
33886
34216
|
const { signature } = await agent.keypair.signPersonalMessage(
|
|
33887
34217
|
new TextEncoder().encode(msg)
|
|
33888
34218
|
);
|
|
33889
|
-
await
|
|
34219
|
+
await fetchJson3(`${gateway}/deploy/config`, {
|
|
33890
34220
|
method: "POST",
|
|
33891
34221
|
body: {
|
|
33892
34222
|
address,
|
|
@@ -33894,9 +34224,25 @@ Subcommands:
|
|
|
33894
34224
|
signature,
|
|
33895
34225
|
upstreamUrl: opts.upstream,
|
|
33896
34226
|
method,
|
|
33897
|
-
headers
|
|
34227
|
+
headers,
|
|
34228
|
+
...slug ? { slug } : {}
|
|
33898
34229
|
}
|
|
33899
34230
|
});
|
|
34231
|
+
if (slug) {
|
|
34232
|
+
if (isJsonMode()) {
|
|
34233
|
+
printJson({ address, slug, upstream: opts.upstream, price });
|
|
34234
|
+
return;
|
|
34235
|
+
}
|
|
34236
|
+
printBlank();
|
|
34237
|
+
printSuccess(`Wrap config stored for service "${slug}".`);
|
|
34238
|
+
printKeyValue("Wraps", opts.upstream);
|
|
34239
|
+
printKeyValue("Buy URL", `${DEFAULT_RAIL}/commerce/pay/${address}/${slug}`);
|
|
34240
|
+
printInfo(
|
|
34241
|
+
`List it in the catalog: t2 agent services add --slug ${slug} --title \u2026 --description \u2026 --price ${opts.price}`
|
|
34242
|
+
);
|
|
34243
|
+
printBlank();
|
|
34244
|
+
return;
|
|
34245
|
+
}
|
|
33900
34246
|
const { digest } = await runSponsoredTx({
|
|
33901
34247
|
keypair: agent.keypair,
|
|
33902
34248
|
actor: address,
|
|
@@ -33935,8 +34281,11 @@ Subcommands:
|
|
|
33935
34281
|
group.command("pay").argument("<seller>", "The seller agent's Sui address").description(
|
|
33936
34282
|
"Pay a seller agent for a service (gateway-mediated, USDC). t2000 collects, keeps a small fee, and forwards the rest to the seller \u2014 with a receipt. [Agent Commerce]"
|
|
33937
34283
|
).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(
|
|
34284
|
+
"--service <slug>",
|
|
34285
|
+
"Catalog service slug \u2014 buys ONE SKU of the seller's catalog (Store v2)"
|
|
34286
|
+
).option(
|
|
33938
34287
|
"--gateway <url>",
|
|
33939
|
-
`Gateway base URL (default ${
|
|
34288
|
+
`Gateway base URL (default ${DEFAULT_GATEWAY2})`
|
|
33940
34289
|
).option("--force", "Override spending limits for this call (see `t2 limit`)").option("--key <path>", "Custom wallet path (default ~/.t2000/wallet.key)").action(
|
|
33941
34290
|
async (seller, opts) => {
|
|
33942
34291
|
try {
|
|
@@ -33947,10 +34296,11 @@ Subcommands:
|
|
|
33947
34296
|
}
|
|
33948
34297
|
}
|
|
33949
34298
|
const maxPrice = opts.maxPrice ? Number.parseFloat(opts.maxPrice) : opts.amount ? Number.parseFloat(opts.amount) : 1;
|
|
33950
|
-
const gateway = opts.gateway ??
|
|
34299
|
+
const gateway = opts.gateway ?? DEFAULT_GATEWAY2;
|
|
33951
34300
|
const agent = await withAgent({ keyPath: opts.key });
|
|
33952
34301
|
const resolvedSeller = seller.startsWith("0x") ? seller : (await agent.resolveRecipient(seller)).address;
|
|
33953
|
-
const
|
|
34302
|
+
const slugPath = opts.service ? `/${opts.service.trim().toLowerCase()}` : "";
|
|
34303
|
+
const url = opts.amount ? `${gateway}/commerce/pay/${resolvedSeller}${slugPath}?amount=${encodeURIComponent(opts.amount)}` : `${gateway}/commerce/pay/${resolvedSeller}${slugPath}`;
|
|
33954
34304
|
const result = await agent.pay({
|
|
33955
34305
|
url,
|
|
33956
34306
|
method: "POST",
|
|
@@ -34014,12 +34364,12 @@ Subcommands:
|
|
|
34014
34364
|
);
|
|
34015
34365
|
group.command("earnings").description(
|
|
34016
34366
|
"Your sales as a seller \u2014 count, USDC earned (net), and unique buyers, from the on-chain settlement ledger. [Agent Commerce]"
|
|
34017
|
-
).option("--gateway <url>", `Gateway base URL (default ${
|
|
34367
|
+
).option("--gateway <url>", `Gateway base URL (default ${DEFAULT_GATEWAY2})`).option("--key <path>", "Custom wallet path (default ~/.t2000/wallet.key)").action(async (opts) => {
|
|
34018
34368
|
try {
|
|
34019
|
-
const gateway = opts.gateway ??
|
|
34369
|
+
const gateway = opts.gateway ?? DEFAULT_GATEWAY2;
|
|
34020
34370
|
const agent = await withAgent({ keyPath: opts.key });
|
|
34021
34371
|
const address = agent.address();
|
|
34022
|
-
const stats = await
|
|
34372
|
+
const stats = await fetchJson3(
|
|
34023
34373
|
`${gateway}/commerce/stats/${address}`,
|
|
34024
34374
|
{ method: "GET" }
|
|
34025
34375
|
);
|
|
@@ -34048,7 +34398,7 @@ Subcommands:
|
|
|
34048
34398
|
const base = opts.api ?? DEFAULT_API_BASE3;
|
|
34049
34399
|
const agent = await withAgent({ keyPath: opts.key });
|
|
34050
34400
|
const address = agent.address();
|
|
34051
|
-
const challenge = await
|
|
34401
|
+
const challenge = await fetchJson3(`${base}/agent/challenge`, {
|
|
34052
34402
|
method: "POST",
|
|
34053
34403
|
body: { address }
|
|
34054
34404
|
});
|
|
@@ -34060,7 +34410,7 @@ Subcommands:
|
|
|
34060
34410
|
const message = new TextEncoder().encode(`${action}:${nonce}:${label}`);
|
|
34061
34411
|
const { signature } = await agent.keypair.signPersonalMessage(message);
|
|
34062
34412
|
const path2 = opts.release ? "/agent/handle/release" : "/agent/handle";
|
|
34063
|
-
const res = await
|
|
34413
|
+
const res = await fetchJson3(`${base}${path2}`, {
|
|
34064
34414
|
method: "POST",
|
|
34065
34415
|
body: { address, label, nonce, signature }
|
|
34066
34416
|
});
|
|
@@ -34177,7 +34527,7 @@ function registerAgents(program3) {
|
|
|
34177
34527
|
}
|
|
34178
34528
|
|
|
34179
34529
|
// src/commands/task/index.ts
|
|
34180
|
-
var
|
|
34530
|
+
var DEFAULT_GATEWAY3 = process.env.T2000_GATEWAY_URL ?? "https://mpp.t2000.ai";
|
|
34181
34531
|
async function getJson2(url) {
|
|
34182
34532
|
const res = await fetch(url, { headers: { accept: "application/json" } });
|
|
34183
34533
|
const json = await res.json().catch(() => ({}));
|
|
@@ -34202,9 +34552,9 @@ function registerTask(program3) {
|
|
|
34202
34552
|
const group = program3.command("task").description(
|
|
34203
34553
|
"Earn from t2000 reward tasks and work (or post) community board tasks \u2014 all paid through the rail. [Agent Commerce]"
|
|
34204
34554
|
);
|
|
34205
|
-
group.command("list").description("Live tasks: t2000 rewards (auto-verified) + the community board (poster-approved)").option("--gateway <url>", `Gateway base URL (default ${
|
|
34555
|
+
group.command("list").description("Live tasks: t2000 rewards (auto-verified) + the community board (poster-approved)").option("--gateway <url>", `Gateway base URL (default ${DEFAULT_GATEWAY3})`).action(async (opts) => {
|
|
34206
34556
|
try {
|
|
34207
|
-
const gateway = opts.gateway ??
|
|
34557
|
+
const gateway = opts.gateway ?? DEFAULT_GATEWAY3;
|
|
34208
34558
|
const [rewards, board] = await Promise.all([
|
|
34209
34559
|
getJson2(`${gateway}/tasks/stats`),
|
|
34210
34560
|
getJson2(`${gateway}/tasks/board`)
|
|
@@ -34238,10 +34588,10 @@ function registerTask(program3) {
|
|
|
34238
34588
|
handleError(error);
|
|
34239
34589
|
}
|
|
34240
34590
|
});
|
|
34241
|
-
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 ${
|
|
34591
|
+
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_GATEWAY3})`).option("--key <path>", "Custom wallet path (default ~/.t2000/wallet.key)").action(
|
|
34242
34592
|
async (task, opts) => {
|
|
34243
34593
|
try {
|
|
34244
|
-
const gateway = opts.gateway ??
|
|
34594
|
+
const gateway = opts.gateway ?? DEFAULT_GATEWAY3;
|
|
34245
34595
|
const agent = await withAgent({ keyPath: opts.key });
|
|
34246
34596
|
const result = await postJson2(`${gateway}/tasks/claim`, {
|
|
34247
34597
|
task,
|
|
@@ -34270,10 +34620,10 @@ function registerTask(program3) {
|
|
|
34270
34620
|
);
|
|
34271
34621
|
group.command("post").description(
|
|
34272
34622
|
"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."
|
|
34273
|
-
).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 ${
|
|
34623
|
+
).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_GATEWAY3})`).option("--force", "Override spending limits for this call (see `t2 limit`)").option("--key <path>", "Custom wallet path (default ~/.t2000/wallet.key)").action(
|
|
34274
34624
|
async (opts) => {
|
|
34275
34625
|
try {
|
|
34276
|
-
const gateway = opts.gateway ??
|
|
34626
|
+
const gateway = opts.gateway ?? DEFAULT_GATEWAY3;
|
|
34277
34627
|
const reward = Number.parseFloat(opts.reward);
|
|
34278
34628
|
const completions = Number.parseInt(opts.completions, 10);
|
|
34279
34629
|
if (!Number.isFinite(reward) || reward <= 0) {
|
|
@@ -34322,10 +34672,10 @@ function registerTask(program3) {
|
|
|
34322
34672
|
}
|
|
34323
34673
|
}
|
|
34324
34674
|
);
|
|
34325
|
-
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 ${
|
|
34675
|
+
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_GATEWAY3})`).option("--key <path>", "Custom wallet path (default ~/.t2000/wallet.key)").action(
|
|
34326
34676
|
async (taskId, opts) => {
|
|
34327
34677
|
try {
|
|
34328
|
-
const gateway = opts.gateway ??
|
|
34678
|
+
const gateway = opts.gateway ?? DEFAULT_GATEWAY3;
|
|
34329
34679
|
const agent = await withAgent({ keyPath: opts.key });
|
|
34330
34680
|
const result = await postJson2(
|
|
34331
34681
|
`${gateway}/tasks/board/${taskId}/submit`,
|
|
@@ -34347,9 +34697,9 @@ function registerTask(program3) {
|
|
|
34347
34697
|
}
|
|
34348
34698
|
}
|
|
34349
34699
|
);
|
|
34350
|
-
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 ${
|
|
34700
|
+
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_GATEWAY3})`).action(async (taskId, opts) => {
|
|
34351
34701
|
try {
|
|
34352
|
-
const gateway = opts.gateway ??
|
|
34702
|
+
const gateway = opts.gateway ?? DEFAULT_GATEWAY3;
|
|
34353
34703
|
const result = await getJson2(`${gateway}/tasks/board/${taskId}?manageKey=${encodeURIComponent(opts.manageKey)}`);
|
|
34354
34704
|
if (!result.posterView) {
|
|
34355
34705
|
throw new Error(result.error ?? "manageKey not accepted for this task.");
|
|
@@ -34377,10 +34727,10 @@ function registerTask(program3) {
|
|
|
34377
34727
|
handleError(error);
|
|
34378
34728
|
}
|
|
34379
34729
|
});
|
|
34380
|
-
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 ${
|
|
34730
|
+
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_GATEWAY3})`).action(
|
|
34381
34731
|
async (taskId, opts) => {
|
|
34382
34732
|
try {
|
|
34383
|
-
const gateway = opts.gateway ??
|
|
34733
|
+
const gateway = opts.gateway ?? DEFAULT_GATEWAY3;
|
|
34384
34734
|
const result = await postJson2(`${gateway}/tasks/board/${taskId}/approve`, {
|
|
34385
34735
|
manageKey: opts.manageKey,
|
|
34386
34736
|
submissionIds: opts.submissions.split(",").map((s) => s.trim()).filter(Boolean),
|
|
@@ -34406,9 +34756,9 @@ function registerTask(program3) {
|
|
|
34406
34756
|
}
|
|
34407
34757
|
}
|
|
34408
34758
|
);
|
|
34409
|
-
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 ${
|
|
34759
|
+
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_GATEWAY3})`).action(async (taskId, opts) => {
|
|
34410
34760
|
try {
|
|
34411
|
-
const gateway = opts.gateway ??
|
|
34761
|
+
const gateway = opts.gateway ?? DEFAULT_GATEWAY3;
|
|
34412
34762
|
const result = await postJson2(`${gateway}/tasks/board/${taskId}/close`, { manageKey: opts.manageKey });
|
|
34413
34763
|
if (isJsonMode()) {
|
|
34414
34764
|
printJson(result);
|