@t2000/cli 10.12.0 → 10.13.1
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/{chunk-322SPE2Y.js → chunk-I6UGZOTH.js} +53 -1
- package/dist/{chunk-322SPE2Y.js.map → chunk-I6UGZOTH.js.map} +1 -1
- package/dist/{dist-6X5CQWZV.js → dist-G2XQHKA6.js} +4 -2
- package/dist/{dist-MUMCWXCF.js → dist-GIJDTUKJ.js} +62 -12
- package/dist/{dist-MUMCWXCF.js.map → dist-GIJDTUKJ.js.map} +1 -1
- package/dist/index.js +50 -25
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
- /package/dist/{dist-6X5CQWZV.js.map → dist-G2XQHKA6.js.map} +0 -0
package/dist/index.js
CHANGED
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
MAX_JOB_USDC,
|
|
9
9
|
MIN_LP_USDC,
|
|
10
10
|
T2000,
|
|
11
|
+
assertBuyerRequirements,
|
|
11
12
|
buildPublishAgentCoinTx,
|
|
12
13
|
buildTokenizeTx,
|
|
13
14
|
clearLimits,
|
|
@@ -33,7 +34,7 @@ import {
|
|
|
33
34
|
verifyJobForSeller,
|
|
34
35
|
verifyReceipt,
|
|
35
36
|
walletExists
|
|
36
|
-
} from "./chunk-
|
|
37
|
+
} from "./chunk-I6UGZOTH.js";
|
|
37
38
|
import "./chunk-634W6JCI.js";
|
|
38
39
|
import "./chunk-3ZUWXUSN.js";
|
|
39
40
|
import "./chunk-QSITA6GU.js";
|
|
@@ -22286,7 +22287,7 @@ async function runEstimate(url, opts) {
|
|
|
22286
22287
|
let req = accepts.find((a) => a.scheme === "exact" && a.network?.startsWith("sui:")) ?? accepts[0];
|
|
22287
22288
|
let dialect = "x402";
|
|
22288
22289
|
if (!req) {
|
|
22289
|
-
const { parseMppSuiChallenge } = await import("./dist-
|
|
22290
|
+
const { parseMppSuiChallenge } = await import("./dist-G2XQHKA6.js");
|
|
22290
22291
|
const challenge = await parseMppSuiChallenge(response);
|
|
22291
22292
|
if (!challenge) {
|
|
22292
22293
|
throw new Error(
|
|
@@ -23390,7 +23391,7 @@ function registerMcpStart(parent) {
|
|
|
23390
23391
|
parent.command("start", { isDefault: true }).description("Start MCP server (stdio transport \u2014 for AI client integration)").option("--key <path>", "Custom wallet path (default ~/.t2000/wallet.key)").action(async (opts) => {
|
|
23391
23392
|
let mod;
|
|
23392
23393
|
try {
|
|
23393
|
-
mod = await import("./dist-
|
|
23394
|
+
mod = await import("./dist-GIJDTUKJ.js");
|
|
23394
23395
|
} catch {
|
|
23395
23396
|
console.error("MCP server not installed. Run:\n npm install -g @t2000/mcp");
|
|
23396
23397
|
process.exit(1);
|
|
@@ -24833,15 +24834,33 @@ function parseDuration(input) {
|
|
|
24833
24834
|
if (ms <= 0) throw new Error(`Duration must be positive (got "${input}").`);
|
|
24834
24835
|
return Math.round(ms);
|
|
24835
24836
|
}
|
|
24836
|
-
|
|
24837
|
-
|
|
24837
|
+
var SHA256_HEX_RE = /^0x[0-9a-fA-F]{64}$/;
|
|
24838
|
+
var SPEC_STORE_MAX_BYTES = 16 * 1024;
|
|
24839
|
+
async function resolveSpecUpload(base, input) {
|
|
24840
|
+
const trimmed = input.trim();
|
|
24841
|
+
if (SHA256_HEX_RE.test(trimmed)) {
|
|
24842
|
+
return { hash: trimmed.toLowerCase(), uploaded: false };
|
|
24843
|
+
}
|
|
24838
24844
|
let bytes;
|
|
24839
24845
|
try {
|
|
24840
24846
|
bytes = await readFile3(input);
|
|
24841
24847
|
} catch {
|
|
24842
24848
|
bytes = Buffer.from(input, "utf8");
|
|
24843
24849
|
}
|
|
24844
|
-
|
|
24850
|
+
if (bytes.length > SPEC_STORE_MAX_BYTES) {
|
|
24851
|
+
throw new Error(
|
|
24852
|
+
`Content is ${bytes.length} bytes \u2014 the job-spec store caps at 16 KiB. Upload a short note that LINKS the artifact (URL / IPFS), or pin a precomputed commitment with --hash-only 0x<sha256>.`
|
|
24853
|
+
);
|
|
24854
|
+
}
|
|
24855
|
+
let text;
|
|
24856
|
+
try {
|
|
24857
|
+
text = new TextDecoder("utf-8", { fatal: true }).decode(bytes);
|
|
24858
|
+
} catch {
|
|
24859
|
+
throw new Error(
|
|
24860
|
+
"Content is not UTF-8 text \u2014 the job-spec store holds text only. Upload a short note that LINKS the artifact, or pin a precomputed commitment with --hash-only 0x<sha256>."
|
|
24861
|
+
);
|
|
24862
|
+
}
|
|
24863
|
+
return { hash: `0x${await putJobSpec(base, text)}`, uploaded: true };
|
|
24845
24864
|
}
|
|
24846
24865
|
function stateColor(state) {
|
|
24847
24866
|
if (state === "released") return import_picocolors15.default.green(state);
|
|
@@ -24915,7 +24934,7 @@ deadline). v1 caps jobs at ${MAX_JOB_USDC} USDC.
|
|
|
24915
24934
|
Typical flow:
|
|
24916
24935
|
buyer $ t2 job create 5 0xSELLER --spec brief.md --deadline 24h
|
|
24917
24936
|
seller $ t2 job verify 0xJOB --price 5
|
|
24918
|
-
seller $ t2 job deliver 0xJOB report.
|
|
24937
|
+
seller $ t2 job deliver 0xJOB report.md
|
|
24919
24938
|
buyer $ t2 job release 0xJOB (or: t2 job reject 0xJOB)
|
|
24920
24939
|
either $ t2 job watch 0xJOB
|
|
24921
24940
|
seller $ t2 job watch --mine (the provider inbox \u2014 all your jobs)
|
|
@@ -24927,7 +24946,7 @@ Buying a SERVICE (t2 ACP) \u2014 price + terms come from the listing:
|
|
|
24927
24946
|
seller $ t2 job spec 0xJOB (read the buyer's requirements)
|
|
24928
24947
|
`
|
|
24929
24948
|
);
|
|
24930
|
-
group.command("create").argument("[amount]", `USDC to escrow (max ${MAX_JOB_USDC}; omit when buying a --service)`).argument("[seller]", "The seller's Sui address (omit when buying a --service)").description("Create + fund an escrow job in one transaction (buyer)").option("--spec <file-or-text>", "Job spec \u2014 a file path or inline text (
|
|
24949
|
+
group.command("create").argument("[amount]", `USDC to escrow (max ${MAX_JOB_USDC}; omit when buying a --service)`).argument("[seller]", "The seller's Sui address (omit when buying a --service)").description("Create + fund an escrow job in one transaction (buyer)").option("--spec <file-or-text>", "Job spec \u2014 a file path or inline text (UPLOADED so the seller can read it; sha256 pinned on-chain), or a bare 0x\u2026 sha256 (confidential: pins without uploading)").option("--agent <address>", "Buy a service: the seller's agent address").option("--service <slug>", "The service slug (see t2 browse / t2 service list <agent>)").option("--requirements <file-or-json-or-text>", "What the seller asked buyers to provide \u2014 if the listing lists JSON keys, fill EVERY key (JSON object; extra keys OK)").option("--deadline <duration>", "Time the seller has to deliver (e.g. 30m, 24h, 7d)", "24h").option("--review <duration>", "Your accept/reject window after delivery", "24h").option("--split <bps>", "Your share in bps if you reject (0\u201310000)", String(DEFAULT_REJECT_SPLIT_BPS)).option("--key <path>", "Custom wallet path (default ~/.t2000/wallet.key)").option("--api <url>", `API base URL (default ${DEFAULT_API_BASE5})`).action(
|
|
24931
24950
|
async (amountArg, sellerArg, opts) => {
|
|
24932
24951
|
try {
|
|
24933
24952
|
const base = opts.api ?? DEFAULT_API_BASE5;
|
|
@@ -24964,17 +24983,7 @@ Buying a SERVICE (t2 ACP) \u2014 price + terms come from the listing:
|
|
|
24964
24983
|
requirements = text.trim();
|
|
24965
24984
|
}
|
|
24966
24985
|
}
|
|
24967
|
-
|
|
24968
|
-
const want = typeof service.requirements === "string" ? service.requirements : `JSON matching: ${JSON.stringify(service.requirements)}`;
|
|
24969
|
-
throw new Error(
|
|
24970
|
-
`This service needs --requirements. The seller asks for: ${want}`
|
|
24971
|
-
);
|
|
24972
|
-
}
|
|
24973
|
-
if (service.requirements != null && typeof service.requirements === "object" && (typeof requirements !== "object" || requirements === null)) {
|
|
24974
|
-
throw new Error(
|
|
24975
|
-
`This service expects JSON requirements matching: ${JSON.stringify(service.requirements)}`
|
|
24976
|
-
);
|
|
24977
|
-
}
|
|
24986
|
+
assertBuyerRequirements(service.requirements, requirements);
|
|
24978
24987
|
const buyer = (await withAgent({ keyPath: opts.key })).address();
|
|
24979
24988
|
const spec = JSON.stringify({
|
|
24980
24989
|
type: "t2-acp-job-spec@1",
|
|
@@ -25009,7 +25018,7 @@ Buying a SERVICE (t2 ACP) \u2014 price + terms come from the listing:
|
|
|
25009
25018
|
throw new Error(`Amount must be a positive number (got "${amountArg}").`);
|
|
25010
25019
|
}
|
|
25011
25020
|
seller = validateAddress(sellerArg);
|
|
25012
|
-
specHash = await
|
|
25021
|
+
({ hash: specHash } = await resolveSpecUpload(base, opts.spec));
|
|
25013
25022
|
deliverByMs = Date.now() + parseDuration(opts.deadline);
|
|
25014
25023
|
reviewWindowMs = opts.review ? parseDuration(opts.review) : DEFAULT_REVIEW_WINDOW_MS;
|
|
25015
25024
|
rejectSplitBps = Number.parseInt(opts.split, 10);
|
|
@@ -25085,23 +25094,39 @@ Buying a SERVICE (t2 ACP) \u2014 price + terms come from the listing:
|
|
|
25085
25094
|
handleError(error);
|
|
25086
25095
|
}
|
|
25087
25096
|
});
|
|
25088
|
-
group.command("deliver").argument("<jobId>", "The Job object id (0x\u2026)").argument("<proof>", "Delivery
|
|
25097
|
+
group.command("deliver").argument("<jobId>", "The Job object id (0x\u2026)").argument("<proof>", "Delivery body \u2014 a file path or text (UPLOADED so the buyer can read it; sha256 pinned on-chain), or a bare 0x\u2026 sha256").description("Post your delivery before the deadline (seller) \u2014 the body uploads to the job-spec store so the buyer can read it, and its sha256 pins on-chain").option("--hash-only", "Pin <proof> as a precomputed 0x\u2026 sha256 WITHOUT uploading a body \u2014 the confidential / large-artifact path (the buyer can't read it on-platform; hand the artifact over out-of-band)").option("--key <path>", "Custom wallet path (default ~/.t2000/wallet.key)").option("--api <url>", `API base URL (default ${DEFAULT_API_BASE5})`).action(async (jobId, proof, opts) => {
|
|
25089
25098
|
try {
|
|
25090
|
-
const
|
|
25099
|
+
const base = opts.api ?? DEFAULT_API_BASE5;
|
|
25100
|
+
let deliveryHash;
|
|
25101
|
+
let uploaded = false;
|
|
25102
|
+
if (opts.hashOnly) {
|
|
25103
|
+
const hash = proof.trim().toLowerCase();
|
|
25104
|
+
if (!SHA256_HEX_RE.test(hash)) {
|
|
25105
|
+
throw new Error("--hash-only expects a 0x\u2026 64-char sha256 (e.g. from `shasum -a 256`).");
|
|
25106
|
+
}
|
|
25107
|
+
deliveryHash = hash;
|
|
25108
|
+
} else {
|
|
25109
|
+
({ hash: deliveryHash, uploaded } = await resolveSpecUpload(base, proof));
|
|
25110
|
+
}
|
|
25091
25111
|
const { digest } = await sponsoredJobVerb({
|
|
25092
|
-
base
|
|
25112
|
+
base,
|
|
25093
25113
|
keyPath: opts.key,
|
|
25094
25114
|
action: "deliver",
|
|
25095
25115
|
params: { jobId, deliveryHash }
|
|
25096
25116
|
});
|
|
25097
25117
|
if (isJsonMode()) {
|
|
25098
|
-
printJson({ jobId, deliveryHash, digest });
|
|
25118
|
+
printJson({ jobId, deliveryHash, uploaded, digest });
|
|
25099
25119
|
return;
|
|
25100
25120
|
}
|
|
25101
25121
|
printBlank();
|
|
25102
25122
|
printSuccess("Delivery posted \u2014 the buyer's review window is now open.");
|
|
25103
25123
|
printKeyValue("Delivery hash", deliveryHash);
|
|
25104
25124
|
if (digest) printKeyValue("Tx", digest);
|
|
25125
|
+
if (uploaded) {
|
|
25126
|
+
printInfo("Body uploaded \u2014 the buyer reads it content-addressed (tamper-evident against the on-chain hash).");
|
|
25127
|
+
} else {
|
|
25128
|
+
printInfo("Hash-only commitment \u2014 the buyer cannot read the body on-platform; hand the artifact over out-of-band.");
|
|
25129
|
+
}
|
|
25105
25130
|
printInfo("If the buyer neither accepts nor rejects before the window closes, anyone (including you) can run `t2 job release` to settle.");
|
|
25106
25131
|
printBlank();
|
|
25107
25132
|
} catch (error) {
|
|
@@ -25396,7 +25421,7 @@ Examples:
|
|
|
25396
25421
|
);
|
|
25397
25422
|
group.command("create").description("List a service under your Agent ID (re-run to update it)").requiredOption("--name <name>", "Service name (max 80 chars)").requiredOption("--price <usdc>", "Fixed price in USDC (0.01\u201350)").requiredOption("--sla <duration>", "Delivery SLA \u2014 e.g. 30m, 24h, 7d").requiredOption("--description <text>", "What this service is (max 2000 chars)").requiredOption("--deliverable <text>", "What the buyer receives (max 1000 chars)").option("--slug <slug>", "Machine name (default: derived from --name)").option(
|
|
25398
25423
|
"--requirements <file-or-json-or-text>",
|
|
25399
|
-
"What the buyer must provide \u2014
|
|
25424
|
+
"What the buyer must provide \u2014 prefer a JSON object of required fields (keys enforced non-empty at hire); free text ok (file path ok)"
|
|
25400
25425
|
).option("--review <duration>", "Buyer's accept/reject window after delivery", "24h").option("--split <bps>", "Buyer's share in bps if they reject (0\u201310000)", "8000").option(
|
|
25401
25426
|
"--category <category>",
|
|
25402
25427
|
`Directory category for your listing: ${AGENT_CATEGORIES.join(" | ")} (required unless already set on your profile)`
|