@t2000/cli 10.28.0 → 10.29.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 +59 -7
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -30823,6 +30823,34 @@ async function getJobSpec(base, hash) {
|
|
|
30823
30823
|
}
|
|
30824
30824
|
return content;
|
|
30825
30825
|
}
|
|
30826
|
+
var TITLE_PREFIX_RE = /^title\s*:\s*(.+)$/i;
|
|
30827
|
+
var ENVELOPE_TITLE_MAX = 80;
|
|
30828
|
+
function customHireEnvelope(brief, title, now) {
|
|
30829
|
+
const body2 = brief.trim();
|
|
30830
|
+
let t = title?.trim() ?? "";
|
|
30831
|
+
if (!t) {
|
|
30832
|
+
const first = body2.split("\n").find((l) => l.trim())?.trim() ?? "";
|
|
30833
|
+
const prefixed = TITLE_PREFIX_RE.exec(first);
|
|
30834
|
+
t = (prefixed ? prefixed[1] : first).trim();
|
|
30835
|
+
}
|
|
30836
|
+
if (t.length > ENVELOPE_TITLE_MAX) {
|
|
30837
|
+
t = `${t.slice(0, ENVELOPE_TITLE_MAX - 1).trimEnd()}\u2026`;
|
|
30838
|
+
}
|
|
30839
|
+
return JSON.stringify({
|
|
30840
|
+
type: "t2-acp-custom@1",
|
|
30841
|
+
title: t || "Custom job",
|
|
30842
|
+
brief: body2,
|
|
30843
|
+
createdAtMs: now
|
|
30844
|
+
});
|
|
30845
|
+
}
|
|
30846
|
+
function isCustomHireEnvelope(text) {
|
|
30847
|
+
try {
|
|
30848
|
+
const parsed = JSON.parse(text);
|
|
30849
|
+
return (parsed.type === "t2-acp-custom@1" || parsed.type === "t2-acp-invite@1") && typeof parsed.brief === "string" && parsed.brief.trim().length > 0;
|
|
30850
|
+
} catch {
|
|
30851
|
+
return false;
|
|
30852
|
+
}
|
|
30853
|
+
}
|
|
30826
30854
|
async function fetchJson(url, init) {
|
|
30827
30855
|
const res = await fetch(url, {
|
|
30828
30856
|
method: init?.method ?? "GET",
|
|
@@ -36223,10 +36251,10 @@ function parseDuration(input) {
|
|
|
36223
36251
|
}
|
|
36224
36252
|
var SHA256_HEX_RE = /^0x[0-9a-fA-F]{64}$/;
|
|
36225
36253
|
var SPEC_STORE_MAX_BYTES = 16 * 1024;
|
|
36226
|
-
async function
|
|
36254
|
+
async function loadSpecText(input) {
|
|
36227
36255
|
const trimmed = input.trim();
|
|
36228
36256
|
if (SHA256_HEX_RE.test(trimmed)) {
|
|
36229
|
-
return { hash: trimmed.toLowerCase()
|
|
36257
|
+
return { kind: "hash", hash: trimmed.toLowerCase() };
|
|
36230
36258
|
}
|
|
36231
36259
|
let bytes;
|
|
36232
36260
|
try {
|
|
@@ -36247,7 +36275,27 @@ async function resolveSpecUpload(base, input) {
|
|
|
36247
36275
|
"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>."
|
|
36248
36276
|
);
|
|
36249
36277
|
}
|
|
36250
|
-
return {
|
|
36278
|
+
return { kind: "text", text };
|
|
36279
|
+
}
|
|
36280
|
+
async function resolveSpecUpload(base, input) {
|
|
36281
|
+
const loaded = await loadSpecText(input);
|
|
36282
|
+
if (loaded.kind === "hash") {
|
|
36283
|
+
return { hash: loaded.hash, uploaded: false };
|
|
36284
|
+
}
|
|
36285
|
+
return { hash: `0x${await putJobSpec(base, loaded.text)}`, uploaded: true };
|
|
36286
|
+
}
|
|
36287
|
+
async function resolveHireSpecUpload(base, input, title) {
|
|
36288
|
+
const loaded = await loadSpecText(input);
|
|
36289
|
+
if (loaded.kind === "hash") {
|
|
36290
|
+
return { hash: loaded.hash, uploaded: false };
|
|
36291
|
+
}
|
|
36292
|
+
const body2 = isCustomHireEnvelope(loaded.text) ? loaded.text : customHireEnvelope(loaded.text, title, Date.now());
|
|
36293
|
+
if (Buffer.byteLength(body2, "utf8") > SPEC_STORE_MAX_BYTES) {
|
|
36294
|
+
throw new Error(
|
|
36295
|
+
"The brief plus its envelope exceeds the 16 KiB job-spec store cap \u2014 shorten the brief, or link the long artifact (URL / IPFS)."
|
|
36296
|
+
);
|
|
36297
|
+
}
|
|
36298
|
+
return { hash: `0x${await putJobSpec(base, body2)}`, uploaded: true };
|
|
36251
36299
|
}
|
|
36252
36300
|
function stateColor(state) {
|
|
36253
36301
|
if (state === "released") return import_picocolors13.default.green(state);
|
|
@@ -36348,7 +36396,7 @@ no fund step; unclaimed openings refund fee-free):
|
|
|
36348
36396
|
ASP $ t2 job board \xB7 t2 job claim <openingId>
|
|
36349
36397
|
`
|
|
36350
36398
|
);
|
|
36351
|
-
group.command("hire").alias("create").argument("[amount]", `USDC to escrow (max ${MAX_JOB_USDC}; omit when hiring a --service listing)`).argument("[seller]", "The ASP's Sui address (omit when hiring a --service listing)").description("Hire \u2014 fund an escrow job in one transaction (buyer): a listing (--agent + --service) or your own terms (amount + seller + --spec)").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(
|
|
36399
|
+
group.command("hire").alias("create").argument("[amount]", `USDC to escrow (max ${MAX_JOB_USDC}; omit when hiring a --service listing)`).argument("[seller]", "The ASP's Sui address (omit when hiring a --service listing)").description("Hire \u2014 fund an escrow job in one transaction (buyer): a listing (--agent + --service) or your own terms (amount + seller + --spec)").option("--spec <file-or-text>", "Job spec \u2014 a file path or inline text (UPLOADED as the public t2-acp-custom@1 title+brief envelope so the seller and the store can read it; sha256 pinned on-chain), or a bare 0x\u2026 sha256 (confidential: pins without uploading, no envelope)").option("--title <text>", "Public job title (\u226480 chars). Custom/direct hire only; derived from the brief's first line if omitted").option(
|
|
36352
36400
|
"--agent <address|#id|@handle>",
|
|
36353
36401
|
"Hire a listing: the ASP's agent address, #id, or @handle"
|
|
36354
36402
|
).option("--service <slug>", "The service slug (see t2 services / 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_BASE7})`).action(
|
|
@@ -36428,7 +36476,11 @@ no fund step; unclaimed openings refund fee-free):
|
|
|
36428
36476
|
seller = validateAddress(
|
|
36429
36477
|
(await resolveAgentRef(base, sellerArg)).address
|
|
36430
36478
|
);
|
|
36431
|
-
({ hash: specHash } = await
|
|
36479
|
+
({ hash: specHash } = await resolveHireSpecUpload(
|
|
36480
|
+
base,
|
|
36481
|
+
opts.spec,
|
|
36482
|
+
opts.title
|
|
36483
|
+
));
|
|
36432
36484
|
deliverByMs = Date.now() + parseDuration(opts.deadline);
|
|
36433
36485
|
reviewWindowMs = opts.review ? parseDuration(opts.review) : DEFAULT_REVIEW_WINDOW_MS;
|
|
36434
36486
|
rejectSplitBps = Number.parseInt(opts.split, 10);
|
|
@@ -36894,9 +36946,9 @@ Examples:
|
|
|
36894
36946
|
$ t2 service retire sui-market-report
|
|
36895
36947
|
`
|
|
36896
36948
|
);
|
|
36897
|
-
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)").
|
|
36949
|
+
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)").requiredOption(
|
|
36898
36950
|
"--requirements <file-or-json-or-text>",
|
|
36899
|
-
"
|
|
36951
|
+
"The questions buyers answer at hire (REQUIRED \u2014 the API rejects listings that ask nothing): free text, or a JSON object of field names \u2192 hints (keys enforced non-empty at hire; file path ok)"
|
|
36900
36952
|
).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(
|
|
36901
36953
|
"--category <category>",
|
|
36902
36954
|
`Directory category for your listing: ${AGENT_CATEGORIES.join(" | ")} (required unless already set on your profile)`
|