@t2000/cli 5.26.0 → 5.28.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
|
@@ -33115,7 +33115,7 @@ function registerMcpStart(parent) {
|
|
|
33115
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) => {
|
|
33116
33116
|
let mod3;
|
|
33117
33117
|
try {
|
|
33118
|
-
mod3 = await import("./dist-
|
|
33118
|
+
mod3 = await import("./dist-7BWQQOS6.js");
|
|
33119
33119
|
} catch {
|
|
33120
33120
|
console.error("MCP server not installed. Run:\n npm install -g @t2000/mcp");
|
|
33121
33121
|
process.exit(1);
|
|
@@ -33225,6 +33225,10 @@ Subcommands:
|
|
|
33225
33225
|
registerMcpUninstall(group);
|
|
33226
33226
|
}
|
|
33227
33227
|
|
|
33228
|
+
// src/commands/skills/check.ts
|
|
33229
|
+
import { readdir, readFile as readFile3 } from "fs/promises";
|
|
33230
|
+
import { join as join5 } from "path";
|
|
33231
|
+
|
|
33228
33232
|
// src/commands/skills/lib.ts
|
|
33229
33233
|
import { stat } from "fs/promises";
|
|
33230
33234
|
import { join as join4 } from "path";
|
|
@@ -33298,6 +33302,133 @@ async function dirExists(path2) {
|
|
|
33298
33302
|
}
|
|
33299
33303
|
}
|
|
33300
33304
|
|
|
33305
|
+
// src/commands/skills/check.ts
|
|
33306
|
+
function slugFromEntry(entry, target) {
|
|
33307
|
+
return target === "cursor" ? entry.replace(/\.mdc$/, "") : entry;
|
|
33308
|
+
}
|
|
33309
|
+
async function installedSlugs(dir, target) {
|
|
33310
|
+
try {
|
|
33311
|
+
const entries = await readdir(dir);
|
|
33312
|
+
return entries.map((e) => slugFromEntry(e, target)).filter((slug) => isManagedSkillName(slug));
|
|
33313
|
+
} catch {
|
|
33314
|
+
return [];
|
|
33315
|
+
}
|
|
33316
|
+
}
|
|
33317
|
+
function classifyContent(installed, served) {
|
|
33318
|
+
if (served === null) {
|
|
33319
|
+
return "retired";
|
|
33320
|
+
}
|
|
33321
|
+
return installed.trim() === served.trim() ? "up-to-date" : "drifted";
|
|
33322
|
+
}
|
|
33323
|
+
async function checkTargetScope(manifest, servedCache, target, scope) {
|
|
33324
|
+
const dir = resolveTargetDir(target, scope === "global");
|
|
33325
|
+
if (!await dirExists(dir)) {
|
|
33326
|
+
return [];
|
|
33327
|
+
}
|
|
33328
|
+
const slugs = await installedSlugs(dir, target);
|
|
33329
|
+
const rows = [];
|
|
33330
|
+
for (const slug of slugs) {
|
|
33331
|
+
const path2 = join5(dir, filenameForTarget(slug, target));
|
|
33332
|
+
let installed;
|
|
33333
|
+
try {
|
|
33334
|
+
installed = await readFile3(path2, "utf-8");
|
|
33335
|
+
} catch {
|
|
33336
|
+
continue;
|
|
33337
|
+
}
|
|
33338
|
+
const entry = manifest.skills.find((s) => s.name === slug);
|
|
33339
|
+
let served = null;
|
|
33340
|
+
if (entry) {
|
|
33341
|
+
const cacheKey = `${target}:${slug}`;
|
|
33342
|
+
const cached = servedCache.get(cacheKey);
|
|
33343
|
+
if (cached !== void 0) {
|
|
33344
|
+
served = cached;
|
|
33345
|
+
} else {
|
|
33346
|
+
const raw = await fetchSkill(entry.url);
|
|
33347
|
+
served = transformForTarget(raw, target, entry.description);
|
|
33348
|
+
servedCache.set(cacheKey, served);
|
|
33349
|
+
}
|
|
33350
|
+
}
|
|
33351
|
+
rows.push({
|
|
33352
|
+
name: slug,
|
|
33353
|
+
target,
|
|
33354
|
+
scope,
|
|
33355
|
+
path: path2,
|
|
33356
|
+
status: classifyContent(installed, served)
|
|
33357
|
+
});
|
|
33358
|
+
}
|
|
33359
|
+
return rows;
|
|
33360
|
+
}
|
|
33361
|
+
function registerSkillsCheck(parent) {
|
|
33362
|
+
parent.command("check").description(
|
|
33363
|
+
"Compare installed skills against what t2000.ai serves \u2014 { upToDate, action } for agents"
|
|
33364
|
+
).option(
|
|
33365
|
+
"--target <name>",
|
|
33366
|
+
"Only check one target layout: agents, cursor, claude-code (default: all)"
|
|
33367
|
+
).action(async (opts) => {
|
|
33368
|
+
try {
|
|
33369
|
+
const targets = opts.target ? [
|
|
33370
|
+
(() => {
|
|
33371
|
+
const match = SKILL_TARGETS.find((t) => t === opts.target);
|
|
33372
|
+
if (!match) {
|
|
33373
|
+
throw new Error(
|
|
33374
|
+
`--target must be one of: ${SKILL_TARGETS.join(", ")}. Got: "${opts.target}"`
|
|
33375
|
+
);
|
|
33376
|
+
}
|
|
33377
|
+
return match;
|
|
33378
|
+
})()
|
|
33379
|
+
] : SKILL_TARGETS;
|
|
33380
|
+
const manifest = await fetchManifest();
|
|
33381
|
+
const servedCache = /* @__PURE__ */ new Map();
|
|
33382
|
+
const rows = [];
|
|
33383
|
+
for (const target of targets) {
|
|
33384
|
+
rows.push(
|
|
33385
|
+
...await checkTargetScope(manifest, servedCache, target, "local"),
|
|
33386
|
+
...await checkTargetScope(manifest, servedCache, target, "global")
|
|
33387
|
+
);
|
|
33388
|
+
}
|
|
33389
|
+
const stale = rows.filter((r) => r.status !== "up-to-date");
|
|
33390
|
+
const upToDate = rows.length > 0 && stale.length === 0;
|
|
33391
|
+
if (isJsonMode()) {
|
|
33392
|
+
printJson({
|
|
33393
|
+
upToDate: rows.length === 0 ? true : upToDate,
|
|
33394
|
+
installed: rows.length,
|
|
33395
|
+
manifestVersion: manifest.version,
|
|
33396
|
+
skills: rows,
|
|
33397
|
+
action: stale.length > 0 ? "t2 skills install" : void 0
|
|
33398
|
+
});
|
|
33399
|
+
return;
|
|
33400
|
+
}
|
|
33401
|
+
printBlank();
|
|
33402
|
+
if (rows.length === 0) {
|
|
33403
|
+
printInfo(
|
|
33404
|
+
"No installed skills found (checked ./ and ~/ for .agents/skills, .cursor/rules, .claude/skills)."
|
|
33405
|
+
);
|
|
33406
|
+
printInfo("Install: t2 skills install \xB7 MCP clients: t2 mcp install (no files, always fresh)");
|
|
33407
|
+
printBlank();
|
|
33408
|
+
return;
|
|
33409
|
+
}
|
|
33410
|
+
for (const r of rows) {
|
|
33411
|
+
const mark2 = r.status === "up-to-date" ? "\u2713" : r.status === "drifted" ? "\u21BB" : "\u2717";
|
|
33412
|
+
console.log(` ${mark2} ${r.name} [${r.target} \xB7 ${r.scope}] ${r.status}`);
|
|
33413
|
+
}
|
|
33414
|
+
printBlank();
|
|
33415
|
+
if (upToDate) {
|
|
33416
|
+
printSuccess(`All ${rows.length} installed skills match what t2000.ai serves.`);
|
|
33417
|
+
} else {
|
|
33418
|
+
printInfo(
|
|
33419
|
+
`${stale.length} of ${rows.length} installed skills are stale \u2014 refresh with: t2 skills install`
|
|
33420
|
+
);
|
|
33421
|
+
if (stale.some((r) => r.status === "retired")) {
|
|
33422
|
+
printInfo("(\u2717 retired = no longer in the manifest \u2014 remove with: t2 skills uninstall)");
|
|
33423
|
+
}
|
|
33424
|
+
}
|
|
33425
|
+
printBlank();
|
|
33426
|
+
} catch (err) {
|
|
33427
|
+
handleError(err);
|
|
33428
|
+
}
|
|
33429
|
+
});
|
|
33430
|
+
}
|
|
33431
|
+
|
|
33301
33432
|
// src/commands/skills/list.ts
|
|
33302
33433
|
function registerSkillsList(parent) {
|
|
33303
33434
|
parent.command("list").description("List skills available from t2000.ai (core t2000 + MPP recipes)").action(async () => {
|
|
@@ -33325,7 +33456,7 @@ function registerSkillsList(parent) {
|
|
|
33325
33456
|
|
|
33326
33457
|
// src/commands/skills/install.ts
|
|
33327
33458
|
import { writeFile as writeFile3, mkdir as mkdir3 } from "fs/promises";
|
|
33328
|
-
import { join as
|
|
33459
|
+
import { join as join6 } from "path";
|
|
33329
33460
|
function registerSkillsInstall(parent) {
|
|
33330
33461
|
parent.command("install [slug]").description("Install all skills (or one named slug) into a local directory").option("--target <name>", "Target client layout: agents (default), cursor, claude-code", "agents").option("--global", "Install to ~/.<target>/ instead of <cwd>/.<target>/").action(async (slug, opts) => {
|
|
33331
33462
|
try {
|
|
@@ -33346,8 +33477,8 @@ function registerSkillsInstall(parent) {
|
|
|
33346
33477
|
const raw = await fetchSkill(s.url);
|
|
33347
33478
|
const transformed = transformForTarget(raw, target, s.description);
|
|
33348
33479
|
const relPath = filenameForTarget(s.name, target);
|
|
33349
|
-
const fullPath =
|
|
33350
|
-
await mkdir3(
|
|
33480
|
+
const fullPath = join6(targetDir, relPath);
|
|
33481
|
+
await mkdir3(join6(fullPath, ".."), { recursive: true });
|
|
33351
33482
|
await writeFile3(fullPath, transformed, "utf-8");
|
|
33352
33483
|
installed.push({ name: s.name, path: fullPath });
|
|
33353
33484
|
}
|
|
@@ -33375,8 +33506,8 @@ function registerSkillsInstall(parent) {
|
|
|
33375
33506
|
}
|
|
33376
33507
|
|
|
33377
33508
|
// src/commands/skills/uninstall.ts
|
|
33378
|
-
import { readdir, unlink, rmdir } from "fs/promises";
|
|
33379
|
-
import { join as
|
|
33509
|
+
import { readdir as readdir2, unlink, rmdir } from "fs/promises";
|
|
33510
|
+
import { join as join7 } from "path";
|
|
33380
33511
|
function registerSkillsUninstall(parent) {
|
|
33381
33512
|
parent.command("uninstall").description("Remove installed t2000 + MPP skills from the target directory").option("--target <name>", "Target client layout: agents (default), cursor, claude-code", "agents").option("--global", "Uninstall from ~/.<target>/ instead of <cwd>/.<target>/").action(async (opts) => {
|
|
33382
33513
|
try {
|
|
@@ -33391,10 +33522,10 @@ function registerSkillsUninstall(parent) {
|
|
|
33391
33522
|
printInfo(`No skills installed at ${targetDir}`);
|
|
33392
33523
|
return;
|
|
33393
33524
|
}
|
|
33394
|
-
const entries = await
|
|
33525
|
+
const entries = await readdir2(targetDir);
|
|
33395
33526
|
const removed = [];
|
|
33396
33527
|
for (const entry of entries) {
|
|
33397
|
-
const full =
|
|
33528
|
+
const full = join7(targetDir, entry);
|
|
33398
33529
|
if (target === "cursor") {
|
|
33399
33530
|
const slug = entry.endsWith(".mdc") ? entry.slice(0, -".mdc".length) : entry;
|
|
33400
33531
|
if (entry.endsWith(".mdc") && isManagedSkillName(slug)) {
|
|
@@ -33403,7 +33534,7 @@ function registerSkillsUninstall(parent) {
|
|
|
33403
33534
|
}
|
|
33404
33535
|
} else {
|
|
33405
33536
|
if (isManagedSkillName(entry)) {
|
|
33406
|
-
const skillFile =
|
|
33537
|
+
const skillFile = join7(full, "SKILL.md");
|
|
33407
33538
|
try {
|
|
33408
33539
|
await unlink(skillFile);
|
|
33409
33540
|
} catch {
|
|
@@ -33443,6 +33574,7 @@ Subcommands:
|
|
|
33443
33574
|
$ t2 skills install Install all skills (default target: agents)
|
|
33444
33575
|
$ t2 skills install <slug> Install one skill by name
|
|
33445
33576
|
$ t2 skills install --target cursor Install as Cursor .mdc rules
|
|
33577
|
+
$ t2 skills check Are installed skills current? (agents: run at session start)
|
|
33446
33578
|
$ t2 skills uninstall Remove installed skills
|
|
33447
33579
|
|
|
33448
33580
|
For MCP-aware clients (Claude Desktop, Cursor, Windsurf), prefer
|
|
@@ -33451,17 +33583,98 @@ For MCP-aware clients (Claude Desktop, Cursor, Windsurf), prefer
|
|
|
33451
33583
|
);
|
|
33452
33584
|
registerSkillsList(group);
|
|
33453
33585
|
registerSkillsInstall(group);
|
|
33586
|
+
registerSkillsCheck(group);
|
|
33454
33587
|
registerSkillsUninstall(group);
|
|
33455
33588
|
}
|
|
33456
33589
|
|
|
33457
33590
|
// src/commands/agent/index.ts
|
|
33458
|
-
import { createHash as
|
|
33591
|
+
import { createHash as createHash3 } from "crypto";
|
|
33459
33592
|
|
|
33460
|
-
// src/commands/agent/
|
|
33593
|
+
// src/commands/agent/review.ts
|
|
33461
33594
|
import { createHash } from "crypto";
|
|
33595
|
+
var DEFAULT_GATEWAY = "https://x402.t2000.ai";
|
|
33596
|
+
async function fetchJson(url, init) {
|
|
33597
|
+
const res = await fetch(url, {
|
|
33598
|
+
method: init?.method ?? "GET",
|
|
33599
|
+
headers: init?.body ? { "Content-Type": "application/json" } : void 0,
|
|
33600
|
+
body: init?.body ? JSON.stringify(init.body) : void 0
|
|
33601
|
+
});
|
|
33602
|
+
const json = await res.json().catch(() => ({}));
|
|
33603
|
+
if (!res.ok) {
|
|
33604
|
+
const err = json.error;
|
|
33605
|
+
throw new Error(typeof err === "string" ? err : `HTTP ${res.status}`);
|
|
33606
|
+
}
|
|
33607
|
+
return json;
|
|
33608
|
+
}
|
|
33609
|
+
function reviewMessage(digest, stars, text, timestamp) {
|
|
33610
|
+
const hash = createHash("sha256").update(text, "utf8").digest("hex");
|
|
33611
|
+
return `t2000-review:${digest}:${stars}:${hash}:${timestamp}`;
|
|
33612
|
+
}
|
|
33613
|
+
function registerAgentReview(agent) {
|
|
33614
|
+
agent.command("review").description(
|
|
33615
|
+
"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]"
|
|
33616
|
+
).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(
|
|
33617
|
+
async (seller, opts) => {
|
|
33618
|
+
try {
|
|
33619
|
+
const stars = Number(opts.stars);
|
|
33620
|
+
if (!Number.isInteger(stars) || stars < 1 || stars > 5) {
|
|
33621
|
+
throw new Error("--stars must be an integer 1-5.");
|
|
33622
|
+
}
|
|
33623
|
+
const text = (opts.text ?? "").trim();
|
|
33624
|
+
if (text.length > 400) {
|
|
33625
|
+
throw new Error("--text must be \u2264 400 chars.");
|
|
33626
|
+
}
|
|
33627
|
+
const gateway = opts.gateway ?? DEFAULT_GATEWAY;
|
|
33628
|
+
const agentW = await withAgent({ keyPath: opts.key });
|
|
33629
|
+
const buyer = agentW.address();
|
|
33630
|
+
let digest = (opts.digest ?? "").trim();
|
|
33631
|
+
if (!digest) {
|
|
33632
|
+
const res = await fetchJson(
|
|
33633
|
+
`${gateway}/commerce/review?buyer=${buyer}&seller=${encodeURIComponent(seller)}`
|
|
33634
|
+
);
|
|
33635
|
+
const reviewable = res.reviewable ?? [];
|
|
33636
|
+
if (reviewable.length === 0) {
|
|
33637
|
+
throw new Error(
|
|
33638
|
+
"No settled purchase from this wallet to that seller \u2014 buy first (`t2 agent pay`), then review."
|
|
33639
|
+
);
|
|
33640
|
+
}
|
|
33641
|
+
digest = reviewable[0].digest;
|
|
33642
|
+
}
|
|
33643
|
+
const timestamp = Date.now();
|
|
33644
|
+
const message = new TextEncoder().encode(
|
|
33645
|
+
reviewMessage(digest, stars, text, timestamp)
|
|
33646
|
+
);
|
|
33647
|
+
const { signature } = await agentW.keypair.signPersonalMessage(message);
|
|
33648
|
+
await fetchJson(`${gateway}/commerce/review`, {
|
|
33649
|
+
method: "POST",
|
|
33650
|
+
body: { digest, stars, text, timestamp, signature }
|
|
33651
|
+
});
|
|
33652
|
+
if (isJsonMode()) {
|
|
33653
|
+
printJson({ ok: true, digest, stars, text: text || null });
|
|
33654
|
+
return;
|
|
33655
|
+
}
|
|
33656
|
+
printBlank();
|
|
33657
|
+
printSuccess(
|
|
33658
|
+
`Review posted \u2014 ${"\u2605".repeat(stars)}${"\u2606".repeat(5 - stars)}${text ? ` "${text}"` : ""}`
|
|
33659
|
+
);
|
|
33660
|
+
printKeyValue("Receipt", digest);
|
|
33661
|
+
printKeyValue(
|
|
33662
|
+
"Listing",
|
|
33663
|
+
`https://agents.t2000.ai/${seller.startsWith("0x") ? seller : ""}`
|
|
33664
|
+
);
|
|
33665
|
+
printBlank();
|
|
33666
|
+
} catch (e) {
|
|
33667
|
+
handleError(e);
|
|
33668
|
+
}
|
|
33669
|
+
}
|
|
33670
|
+
);
|
|
33671
|
+
}
|
|
33672
|
+
|
|
33673
|
+
// src/commands/agent/services.ts
|
|
33674
|
+
import { createHash as createHash2 } from "crypto";
|
|
33462
33675
|
import { readFileSync as readFileSync3 } from "fs";
|
|
33463
33676
|
var SLUG_RE = /^[a-z0-9][a-z0-9-]{1,39}$/;
|
|
33464
|
-
async function
|
|
33677
|
+
async function fetchJson2(url, init) {
|
|
33465
33678
|
const res = await fetch(url, {
|
|
33466
33679
|
method: init?.method ?? "GET",
|
|
33467
33680
|
headers: init?.body ? { "Content-Type": "application/json" } : void 0,
|
|
@@ -33485,7 +33698,7 @@ function canonicalServicesJson(services) {
|
|
|
33485
33698
|
);
|
|
33486
33699
|
}
|
|
33487
33700
|
async function getCatalog(base, address) {
|
|
33488
|
-
const res = await
|
|
33701
|
+
const res = await fetchJson2(
|
|
33489
33702
|
`${base}/agent/services?address=${encodeURIComponent(address)}`
|
|
33490
33703
|
);
|
|
33491
33704
|
return Array.isArray(res.services) ? res.services : [];
|
|
@@ -33493,7 +33706,7 @@ async function getCatalog(base, address) {
|
|
|
33493
33706
|
async function putCatalog(opts) {
|
|
33494
33707
|
const agent = await withAgent({ keyPath: opts.keyPath });
|
|
33495
33708
|
const address = agent.address();
|
|
33496
|
-
const challenge = await
|
|
33709
|
+
const challenge = await fetchJson2(`${opts.base}/agent/challenge`, {
|
|
33497
33710
|
method: "POST",
|
|
33498
33711
|
body: { address }
|
|
33499
33712
|
});
|
|
@@ -33501,12 +33714,12 @@ async function putCatalog(opts) {
|
|
|
33501
33714
|
if (!nonce) {
|
|
33502
33715
|
throw new Error("Failed to get a challenge nonce.");
|
|
33503
33716
|
}
|
|
33504
|
-
const digest =
|
|
33717
|
+
const digest = createHash2("sha256").update(canonicalServicesJson(opts.services)).digest("hex");
|
|
33505
33718
|
const message = new TextEncoder().encode(
|
|
33506
33719
|
`t2000-agent-services:${nonce}:${digest}`
|
|
33507
33720
|
);
|
|
33508
33721
|
const { signature } = await agent.keypair.signPersonalMessage(message);
|
|
33509
|
-
const res = await
|
|
33722
|
+
const res = await fetchJson2(`${opts.base}/agent/services`, {
|
|
33510
33723
|
method: "POST",
|
|
33511
33724
|
body: { address, nonce, signature, services: opts.services }
|
|
33512
33725
|
});
|
|
@@ -33687,7 +33900,7 @@ function registerAgentServices(agentGroup, defaults) {
|
|
|
33687
33900
|
|
|
33688
33901
|
// src/commands/agent/index.ts
|
|
33689
33902
|
var DEFAULT_API_BASE3 = process.env.T2000_API_URL ?? "https://api.t2000.ai/v1";
|
|
33690
|
-
var
|
|
33903
|
+
var DEFAULT_GATEWAY2 = process.env.T2000_GATEWAY_URL ?? "https://mpp.t2000.ai";
|
|
33691
33904
|
var DEFAULT_RAIL = process.env.T2000_RAIL_URL ?? "https://x402.t2000.ai";
|
|
33692
33905
|
var AGENT_CATEGORIES = [
|
|
33693
33906
|
"ai-models",
|
|
@@ -33726,19 +33939,19 @@ async function fundCredit(agent, base, amountStr, assetOpt) {
|
|
|
33726
33939
|
throw new Error(`amount must be a positive number (got "${amountStr}").`);
|
|
33727
33940
|
}
|
|
33728
33941
|
const asset = normalizeTopupAsset(assetOpt);
|
|
33729
|
-
const cfg = await
|
|
33942
|
+
const cfg = await fetchJson3(`${base}/agent/topup`, { method: "GET" });
|
|
33730
33943
|
const treasury = cfg.treasury;
|
|
33731
33944
|
if (!treasury) {
|
|
33732
33945
|
throw new Error("Could not resolve the t2000 treasury address.");
|
|
33733
33946
|
}
|
|
33734
33947
|
const sent = await agent.send({ to: treasury, amount, asset });
|
|
33735
|
-
const topup = await
|
|
33948
|
+
const topup = await fetchJson3(`${base}/agent/topup`, {
|
|
33736
33949
|
method: "POST",
|
|
33737
33950
|
body: { address: agent.address(), digest: sent.tx }
|
|
33738
33951
|
});
|
|
33739
33952
|
return { amount, asset, balanceUsd: topup.balanceUsd };
|
|
33740
33953
|
}
|
|
33741
|
-
async function
|
|
33954
|
+
async function fetchJson3(url, init) {
|
|
33742
33955
|
const res = await fetch(url, {
|
|
33743
33956
|
method: init.method,
|
|
33744
33957
|
headers: init.body ? { "Content-Type": "application/json" } : void 0,
|
|
@@ -33765,6 +33978,7 @@ Subcommands:
|
|
|
33765
33978
|
`
|
|
33766
33979
|
);
|
|
33767
33980
|
registerAgentServices(group, { apiBase: DEFAULT_API_BASE3 });
|
|
33981
|
+
registerAgentReview(group);
|
|
33768
33982
|
group.command("onboard").description(
|
|
33769
33983
|
"Buy-side setup: fund credit (gasless USDC/USDsui) + mint a Private API key. Registering an Agent ID is free and separate \u2014 `t2 init` / `t2 agent register`."
|
|
33770
33984
|
).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(
|
|
@@ -33781,7 +33995,7 @@ Subcommands:
|
|
|
33781
33995
|
);
|
|
33782
33996
|
}
|
|
33783
33997
|
}
|
|
33784
|
-
const challenge = await
|
|
33998
|
+
const challenge = await fetchJson3(`${base}/agent/challenge`, {
|
|
33785
33999
|
method: "POST",
|
|
33786
34000
|
body: { address }
|
|
33787
34001
|
});
|
|
@@ -33791,7 +34005,7 @@ Subcommands:
|
|
|
33791
34005
|
}
|
|
33792
34006
|
const message = new TextEncoder().encode(`t2000-agent-keys:${nonce}`);
|
|
33793
34007
|
const { signature } = await agent.keypair.signPersonalMessage(message);
|
|
33794
|
-
const minted = await
|
|
34008
|
+
const minted = await fetchJson3(`${base}/agent/keys`, {
|
|
33795
34009
|
method: "POST",
|
|
33796
34010
|
body: { address, nonce, signature }
|
|
33797
34011
|
});
|
|
@@ -33961,7 +34175,7 @@ Subcommands:
|
|
|
33961
34175
|
const base = opts.api ?? DEFAULT_API_BASE3;
|
|
33962
34176
|
const agent = await withAgent({ keyPath: opts.key });
|
|
33963
34177
|
const address = agent.address();
|
|
33964
|
-
const challenge = await
|
|
34178
|
+
const challenge = await fetchJson3(`${base}/agent/challenge`, {
|
|
33965
34179
|
method: "POST",
|
|
33966
34180
|
body: { address }
|
|
33967
34181
|
});
|
|
@@ -33971,7 +34185,7 @@ Subcommands:
|
|
|
33971
34185
|
}
|
|
33972
34186
|
const message = new TextEncoder().encode(`t2000-agent-profile:${nonce}`);
|
|
33973
34187
|
const { signature } = await agent.keypair.signPersonalMessage(message);
|
|
33974
|
-
await
|
|
34188
|
+
await fetchJson3(`${base}/agent/profile`, {
|
|
33975
34189
|
method: "POST",
|
|
33976
34190
|
body: {
|
|
33977
34191
|
address,
|
|
@@ -34081,11 +34295,11 @@ Subcommands:
|
|
|
34081
34295
|
).option("--remove", "Take down the deployed service").option(
|
|
34082
34296
|
"--service <slug>",
|
|
34083
34297
|
"Catalog service slug \u2014 wrap config for ONE SKU (Store v2; omit = the default service)"
|
|
34084
|
-
).option("--gateway <url>", `Gateway base URL (default ${
|
|
34298
|
+
).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(
|
|
34085
34299
|
async (opts) => {
|
|
34086
34300
|
try {
|
|
34087
34301
|
const base = opts.api ?? DEFAULT_API_BASE3;
|
|
34088
|
-
const gateway = opts.gateway ??
|
|
34302
|
+
const gateway = opts.gateway ?? DEFAULT_GATEWAY2;
|
|
34089
34303
|
const category = normalizeCategory(opts.category);
|
|
34090
34304
|
const slug = opts.service?.trim().toLowerCase() || void 0;
|
|
34091
34305
|
const agent = await withAgent({ keyPath: opts.key });
|
|
@@ -34096,7 +34310,7 @@ Subcommands:
|
|
|
34096
34310
|
const { signature: signature2 } = await agent.keypair.signPersonalMessage(
|
|
34097
34311
|
new TextEncoder().encode(msg2)
|
|
34098
34312
|
);
|
|
34099
|
-
await
|
|
34313
|
+
await fetchJson3(`${gateway}/deploy/config`, {
|
|
34100
34314
|
method: "DELETE",
|
|
34101
34315
|
body: { address, timestamp: ts2, signature: signature2, ...slug ? { slug } : {} }
|
|
34102
34316
|
});
|
|
@@ -34128,14 +34342,14 @@ Subcommands:
|
|
|
34128
34342
|
const method = (opts.method ?? "POST").toUpperCase() === "GET" ? "GET" : "POST";
|
|
34129
34343
|
const headers = opts.header ?? {};
|
|
34130
34344
|
const ts = Date.now();
|
|
34131
|
-
const bodyHash =
|
|
34345
|
+
const bodyHash = createHash3("sha256").update(
|
|
34132
34346
|
`${opts.upstream}|${method}|${JSON.stringify(headers)}${slug ? `|${slug}` : ""}`
|
|
34133
34347
|
).digest("hex");
|
|
34134
34348
|
const msg = `t2000-deploy:${ts}:${bodyHash}`;
|
|
34135
34349
|
const { signature } = await agent.keypair.signPersonalMessage(
|
|
34136
34350
|
new TextEncoder().encode(msg)
|
|
34137
34351
|
);
|
|
34138
|
-
await
|
|
34352
|
+
await fetchJson3(`${gateway}/deploy/config`, {
|
|
34139
34353
|
method: "POST",
|
|
34140
34354
|
body: {
|
|
34141
34355
|
address,
|
|
@@ -34204,7 +34418,7 @@ Subcommands:
|
|
|
34204
34418
|
"Catalog service slug \u2014 buys ONE SKU of the seller's catalog (Store v2)"
|
|
34205
34419
|
).option(
|
|
34206
34420
|
"--gateway <url>",
|
|
34207
|
-
`Gateway base URL (default ${
|
|
34421
|
+
`Gateway base URL (default ${DEFAULT_GATEWAY2})`
|
|
34208
34422
|
).option("--force", "Override spending limits for this call (see `t2 limit`)").option("--key <path>", "Custom wallet path (default ~/.t2000/wallet.key)").action(
|
|
34209
34423
|
async (seller, opts) => {
|
|
34210
34424
|
try {
|
|
@@ -34215,7 +34429,7 @@ Subcommands:
|
|
|
34215
34429
|
}
|
|
34216
34430
|
}
|
|
34217
34431
|
const maxPrice = opts.maxPrice ? Number.parseFloat(opts.maxPrice) : opts.amount ? Number.parseFloat(opts.amount) : 1;
|
|
34218
|
-
const gateway = opts.gateway ??
|
|
34432
|
+
const gateway = opts.gateway ?? DEFAULT_GATEWAY2;
|
|
34219
34433
|
const agent = await withAgent({ keyPath: opts.key });
|
|
34220
34434
|
const resolvedSeller = seller.startsWith("0x") ? seller : (await agent.resolveRecipient(seller)).address;
|
|
34221
34435
|
const slugPath = opts.service ? `/${opts.service.trim().toLowerCase()}` : "";
|
|
@@ -34283,12 +34497,12 @@ Subcommands:
|
|
|
34283
34497
|
);
|
|
34284
34498
|
group.command("earnings").description(
|
|
34285
34499
|
"Your sales as a seller \u2014 count, USDC earned (net), and unique buyers, from the on-chain settlement ledger. [Agent Commerce]"
|
|
34286
|
-
).option("--gateway <url>", `Gateway base URL (default ${
|
|
34500
|
+
).option("--gateway <url>", `Gateway base URL (default ${DEFAULT_GATEWAY2})`).option("--key <path>", "Custom wallet path (default ~/.t2000/wallet.key)").action(async (opts) => {
|
|
34287
34501
|
try {
|
|
34288
|
-
const gateway = opts.gateway ??
|
|
34502
|
+
const gateway = opts.gateway ?? DEFAULT_GATEWAY2;
|
|
34289
34503
|
const agent = await withAgent({ keyPath: opts.key });
|
|
34290
34504
|
const address = agent.address();
|
|
34291
|
-
const stats = await
|
|
34505
|
+
const stats = await fetchJson3(
|
|
34292
34506
|
`${gateway}/commerce/stats/${address}`,
|
|
34293
34507
|
{ method: "GET" }
|
|
34294
34508
|
);
|
|
@@ -34317,7 +34531,7 @@ Subcommands:
|
|
|
34317
34531
|
const base = opts.api ?? DEFAULT_API_BASE3;
|
|
34318
34532
|
const agent = await withAgent({ keyPath: opts.key });
|
|
34319
34533
|
const address = agent.address();
|
|
34320
|
-
const challenge = await
|
|
34534
|
+
const challenge = await fetchJson3(`${base}/agent/challenge`, {
|
|
34321
34535
|
method: "POST",
|
|
34322
34536
|
body: { address }
|
|
34323
34537
|
});
|
|
@@ -34329,7 +34543,7 @@ Subcommands:
|
|
|
34329
34543
|
const message = new TextEncoder().encode(`${action}:${nonce}:${label}`);
|
|
34330
34544
|
const { signature } = await agent.keypair.signPersonalMessage(message);
|
|
34331
34545
|
const path2 = opts.release ? "/agent/handle/release" : "/agent/handle";
|
|
34332
|
-
const res = await
|
|
34546
|
+
const res = await fetchJson3(`${base}${path2}`, {
|
|
34333
34547
|
method: "POST",
|
|
34334
34548
|
body: { address, label, nonce, signature }
|
|
34335
34549
|
});
|
|
@@ -34446,7 +34660,7 @@ function registerAgents(program3) {
|
|
|
34446
34660
|
}
|
|
34447
34661
|
|
|
34448
34662
|
// src/commands/task/index.ts
|
|
34449
|
-
var
|
|
34663
|
+
var DEFAULT_GATEWAY3 = process.env.T2000_GATEWAY_URL ?? "https://mpp.t2000.ai";
|
|
34450
34664
|
async function getJson2(url) {
|
|
34451
34665
|
const res = await fetch(url, { headers: { accept: "application/json" } });
|
|
34452
34666
|
const json = await res.json().catch(() => ({}));
|
|
@@ -34471,9 +34685,9 @@ function registerTask(program3) {
|
|
|
34471
34685
|
const group = program3.command("task").description(
|
|
34472
34686
|
"Earn from t2000 reward tasks and work (or post) community board tasks \u2014 all paid through the rail. [Agent Commerce]"
|
|
34473
34687
|
);
|
|
34474
|
-
group.command("list").description("Live tasks: t2000 rewards (auto-verified) + the community board (poster-approved)").option("--gateway <url>", `Gateway base URL (default ${
|
|
34688
|
+
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) => {
|
|
34475
34689
|
try {
|
|
34476
|
-
const gateway = opts.gateway ??
|
|
34690
|
+
const gateway = opts.gateway ?? DEFAULT_GATEWAY3;
|
|
34477
34691
|
const [rewards, board] = await Promise.all([
|
|
34478
34692
|
getJson2(`${gateway}/tasks/stats`),
|
|
34479
34693
|
getJson2(`${gateway}/tasks/board`)
|
|
@@ -34507,10 +34721,10 @@ function registerTask(program3) {
|
|
|
34507
34721
|
handleError(error);
|
|
34508
34722
|
}
|
|
34509
34723
|
});
|
|
34510
|
-
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 ${
|
|
34724
|
+
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(
|
|
34511
34725
|
async (task, opts) => {
|
|
34512
34726
|
try {
|
|
34513
|
-
const gateway = opts.gateway ??
|
|
34727
|
+
const gateway = opts.gateway ?? DEFAULT_GATEWAY3;
|
|
34514
34728
|
const agent = await withAgent({ keyPath: opts.key });
|
|
34515
34729
|
const result = await postJson2(`${gateway}/tasks/claim`, {
|
|
34516
34730
|
task,
|
|
@@ -34539,10 +34753,10 @@ function registerTask(program3) {
|
|
|
34539
34753
|
);
|
|
34540
34754
|
group.command("post").description(
|
|
34541
34755
|
"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."
|
|
34542
|
-
).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 ${
|
|
34756
|
+
).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(
|
|
34543
34757
|
async (opts) => {
|
|
34544
34758
|
try {
|
|
34545
|
-
const gateway = opts.gateway ??
|
|
34759
|
+
const gateway = opts.gateway ?? DEFAULT_GATEWAY3;
|
|
34546
34760
|
const reward = Number.parseFloat(opts.reward);
|
|
34547
34761
|
const completions = Number.parseInt(opts.completions, 10);
|
|
34548
34762
|
if (!Number.isFinite(reward) || reward <= 0) {
|
|
@@ -34591,10 +34805,10 @@ function registerTask(program3) {
|
|
|
34591
34805
|
}
|
|
34592
34806
|
}
|
|
34593
34807
|
);
|
|
34594
|
-
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 ${
|
|
34808
|
+
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(
|
|
34595
34809
|
async (taskId, opts) => {
|
|
34596
34810
|
try {
|
|
34597
|
-
const gateway = opts.gateway ??
|
|
34811
|
+
const gateway = opts.gateway ?? DEFAULT_GATEWAY3;
|
|
34598
34812
|
const agent = await withAgent({ keyPath: opts.key });
|
|
34599
34813
|
const result = await postJson2(
|
|
34600
34814
|
`${gateway}/tasks/board/${taskId}/submit`,
|
|
@@ -34616,9 +34830,9 @@ function registerTask(program3) {
|
|
|
34616
34830
|
}
|
|
34617
34831
|
}
|
|
34618
34832
|
);
|
|
34619
|
-
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 ${
|
|
34833
|
+
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) => {
|
|
34620
34834
|
try {
|
|
34621
|
-
const gateway = opts.gateway ??
|
|
34835
|
+
const gateway = opts.gateway ?? DEFAULT_GATEWAY3;
|
|
34622
34836
|
const result = await getJson2(`${gateway}/tasks/board/${taskId}?manageKey=${encodeURIComponent(opts.manageKey)}`);
|
|
34623
34837
|
if (!result.posterView) {
|
|
34624
34838
|
throw new Error(result.error ?? "manageKey not accepted for this task.");
|
|
@@ -34646,10 +34860,10 @@ function registerTask(program3) {
|
|
|
34646
34860
|
handleError(error);
|
|
34647
34861
|
}
|
|
34648
34862
|
});
|
|
34649
|
-
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 ${
|
|
34863
|
+
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(
|
|
34650
34864
|
async (taskId, opts) => {
|
|
34651
34865
|
try {
|
|
34652
|
-
const gateway = opts.gateway ??
|
|
34866
|
+
const gateway = opts.gateway ?? DEFAULT_GATEWAY3;
|
|
34653
34867
|
const result = await postJson2(`${gateway}/tasks/board/${taskId}/approve`, {
|
|
34654
34868
|
manageKey: opts.manageKey,
|
|
34655
34869
|
submissionIds: opts.submissions.split(",").map((s) => s.trim()).filter(Boolean),
|
|
@@ -34675,9 +34889,9 @@ function registerTask(program3) {
|
|
|
34675
34889
|
}
|
|
34676
34890
|
}
|
|
34677
34891
|
);
|
|
34678
|
-
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 ${
|
|
34892
|
+
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) => {
|
|
34679
34893
|
try {
|
|
34680
|
-
const gateway = opts.gateway ??
|
|
34894
|
+
const gateway = opts.gateway ?? DEFAULT_GATEWAY3;
|
|
34681
34895
|
const result = await postJson2(`${gateway}/tasks/board/${taskId}/close`, { manageKey: opts.manageKey });
|
|
34682
34896
|
if (isJsonMode()) {
|
|
34683
34897
|
printJson(result);
|