@t2000/cli 10.28.0 → 10.29.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.
@@ -10,7 +10,7 @@ import {
10
10
  fromBase64 as fromBase642,
11
11
  suiBcs,
12
12
  toBase64 as toBase642
13
- } from "./chunk-T32A4PV6.js";
13
+ } from "./chunk-AJX562JQ.js";
14
14
  import {
15
15
  SUI_ADDRESS_LENGTH,
16
16
  fromBase64,
@@ -12463,4 +12463,4 @@ export {
12463
12463
  SuiGrpcClient,
12464
12464
  types_exports
12465
12465
  };
12466
- //# sourceMappingURL=chunk-SHZC6TMU.js.map
12466
+ //# sourceMappingURL=chunk-7ZMRX7L4.js.map
@@ -2760,6 +2760,10 @@ function getNamesFromTypeList(types) {
2760
2760
  }
2761
2761
 
2762
2762
  export {
2763
+ TypeTagSerializer,
2764
+ ExecutionStatus,
2765
+ pureBcsSchemaFromTypeName,
2766
+ suiBcs,
2763
2767
  integer,
2764
2768
  is,
2765
2769
  array,
@@ -2790,10 +2794,6 @@ export {
2790
2794
  ValidDuringSchema,
2791
2795
  TransactionExpiration2 as TransactionExpiration,
2792
2796
  getIdFromCallArg,
2793
- TypeTagSerializer,
2794
- ExecutionStatus,
2795
- pureBcsSchemaFromTypeName,
2796
- suiBcs,
2797
2797
  serializeV1TransactionData,
2798
2798
  TransactionDataBuilder,
2799
2799
  MOVE_STDLIB_ADDRESS,
@@ -2813,4 +2813,4 @@ export {
2813
2813
  findNamesInTransaction,
2814
2814
  replaceNames
2815
2815
  };
2816
- //# sourceMappingURL=chunk-T32A4PV6.js.map
2816
+ //# sourceMappingURL=chunk-AJX562JQ.js.map
@@ -1,15 +1,15 @@
1
1
  import { createRequire as __createRequire } from 'module'; import { fileURLToPath as __fileURLToPath } from 'url'; import { dirname as __pathDirname } from 'path'; const require = __createRequire(import.meta.url); const __filename = __fileURLToPath(import.meta.url); const __dirname = __pathDirname(__filename);
2
2
  import {
3
3
  SuiGrpcClient
4
- } from "./chunk-SHZC6TMU.js";
4
+ } from "./chunk-7ZMRX7L4.js";
5
5
  import {
6
6
  Transaction,
7
7
  coinWithBalance
8
- } from "./chunk-CNTCUDEZ.js";
8
+ } from "./chunk-KSHM4A6X.js";
9
9
  import {
10
10
  SUI_CLOCK_OBJECT_ID,
11
11
  suiBcs
12
- } from "./chunk-T32A4PV6.js";
12
+ } from "./chunk-AJX562JQ.js";
13
13
  import {
14
14
  normalizeSuiObjectId
15
15
  } from "./chunk-BX4V52TZ.js";
@@ -32559,4 +32559,4 @@ mime-types/index.js:
32559
32559
  *)
32560
32560
  *)
32561
32561
  */
32562
- //# sourceMappingURL=chunk-TVD4WMBT.js.map
32562
+ //# sourceMappingURL=chunk-IYBOBPGG.js.map
@@ -47,7 +47,7 @@ import {
47
47
  tuple,
48
48
  union,
49
49
  unknown
50
- } from "./chunk-T32A4PV6.js";
50
+ } from "./chunk-AJX562JQ.js";
51
51
  import {
52
52
  fromBase58,
53
53
  fromBase64,
@@ -1635,4 +1635,4 @@ export {
1635
1635
  coinWithBalance,
1636
1636
  Transaction
1637
1637
  };
1638
- //# sourceMappingURL=chunk-CNTCUDEZ.js.map
1638
+ //# sourceMappingURL=chunk-KSHM4A6X.js.map
@@ -1,8 +1,8 @@
1
1
  import { createRequire as __createRequire } from 'module'; import { fileURLToPath as __fileURLToPath } from 'url'; import { dirname as __pathDirname } from 'path'; const require = __createRequire(import.meta.url); const __filename = __fileURLToPath(import.meta.url); const __dirname = __pathDirname(__filename);
2
2
  import {
3
3
  Transaction
4
- } from "./chunk-CNTCUDEZ.js";
5
- import "./chunk-T32A4PV6.js";
4
+ } from "./chunk-KSHM4A6X.js";
5
+ import "./chunk-AJX562JQ.js";
6
6
  import {
7
7
  fromBase64,
8
8
  normalizeSuiAddress,
@@ -348,4 +348,4 @@ export {
348
348
  withRetry,
349
349
  x402Network
350
350
  };
351
- //# sourceMappingURL=dist-RTAF2SWN.js.map
351
+ //# sourceMappingURL=dist-2P3XNMJC.js.map
@@ -171,10 +171,10 @@ import {
171
171
  processEndpoint,
172
172
  processFlattenRoutes,
173
173
  restituteMsafeFastRouterSwapParams
174
- } from "./chunk-TVD4WMBT.js";
175
- import "./chunk-SHZC6TMU.js";
176
- import "./chunk-CNTCUDEZ.js";
177
- import "./chunk-T32A4PV6.js";
174
+ } from "./chunk-IYBOBPGG.js";
175
+ import "./chunk-7ZMRX7L4.js";
176
+ import "./chunk-KSHM4A6X.js";
177
+ import "./chunk-AJX562JQ.js";
178
178
  import "./chunk-BX4V52TZ.js";
179
179
  import "./chunk-YPWSCLE3.js";
180
180
  export {
@@ -350,4 +350,4 @@ export {
350
350
  processFlattenRoutes,
351
351
  restituteMsafeFastRouterSwapParams
352
352
  };
353
- //# sourceMappingURL=dist-JP4PBPBV.js.map
353
+ //# sourceMappingURL=dist-VE3SAZWF.js.map
@@ -5,8 +5,8 @@ import {
5
5
  SuiGrpcClient,
6
6
  isSuiGrpcClient,
7
7
  types_exports
8
- } from "./chunk-SHZC6TMU.js";
9
- import "./chunk-T32A4PV6.js";
8
+ } from "./chunk-7ZMRX7L4.js";
9
+ import "./chunk-AJX562JQ.js";
10
10
  import "./chunk-BX4V52TZ.js";
11
11
  import "./chunk-YPWSCLE3.js";
12
12
  export {
@@ -16,4 +16,4 @@ export {
16
16
  SuiGrpcClient,
17
17
  isSuiGrpcClient
18
18
  };
19
- //# sourceMappingURL=grpc-AJNSMQ2Y.js.map
19
+ //# sourceMappingURL=grpc-GFGD32S5.js.map
package/dist/index.js CHANGED
@@ -3,7 +3,7 @@ import { createRequire as __createRequire } from 'module'; import { fileURLToPat
3
3
  import {
4
4
  AggregatorClient,
5
5
  Env
6
- } from "./chunk-TVD4WMBT.js";
6
+ } from "./chunk-IYBOBPGG.js";
7
7
  import {
8
8
  BalanceChange,
9
9
  BaseClient,
@@ -16,11 +16,11 @@ import {
16
16
  parseTransactionEffectsBcs,
17
17
  transactionDataToGrpcTransaction,
18
18
  transactionToGrpcJson
19
- } from "./chunk-SHZC6TMU.js";
19
+ } from "./chunk-7ZMRX7L4.js";
20
20
  import {
21
21
  Transaction,
22
22
  coinWithBalance
23
- } from "./chunk-CNTCUDEZ.js";
23
+ } from "./chunk-KSHM4A6X.js";
24
24
  import {
25
25
  ObjectError,
26
26
  SUI_TYPE_ARG,
@@ -31,7 +31,7 @@ import {
31
31
  fromBase64 as fromBase642,
32
32
  suiBcs,
33
33
  toBase64 as toBase642
34
- } from "./chunk-T32A4PV6.js";
34
+ } from "./chunk-AJX562JQ.js";
35
35
  import {
36
36
  SIGNATURE_FLAG_TO_SCHEME,
37
37
  SIGNATURE_SCHEME_TO_FLAG,
@@ -28542,7 +28542,7 @@ async function probeX402(args) {
28542
28542
  BigInt(requirements.maxAmountRequired),
28543
28543
  await assetDecimals(requirements.asset)
28544
28544
  );
28545
- const { isX402EscrowRequirements } = await import("./dist-RTAF2SWN.js");
28545
+ const { isX402EscrowRequirements } = await import("./dist-2P3XNMJC.js");
28546
28546
  if (isX402EscrowRequirements(requirements)) {
28547
28547
  return {
28548
28548
  kind: "escrow",
@@ -28613,7 +28613,7 @@ async function payWithX402(args) {
28613
28613
  const pick = await pickSuiExactRequirements(probe, client.network);
28614
28614
  if (pick.kind === "payable") {
28615
28615
  const requirements = pick.requirements;
28616
- const { isX402EscrowRequirements } = await import("./dist-RTAF2SWN.js");
28616
+ const { isX402EscrowRequirements } = await import("./dist-2P3XNMJC.js");
28617
28617
  if (isX402EscrowRequirements(requirements)) {
28618
28618
  const escrow = requirements.extra.escrow;
28619
28619
  const price = atomicToHuman(
@@ -28659,7 +28659,7 @@ async function pickSuiExactRequirements(response, network) {
28659
28659
  const want = `sui:${network === "testnet" ? "testnet" : "mainnet"}`;
28660
28660
  const entry = body2.accepts?.find((a) => a.scheme === "exact" && a.network === want);
28661
28661
  if (!entry) return { kind: "none" };
28662
- const { isX402EscrowRequirements } = await import("./dist-RTAF2SWN.js");
28662
+ const { isX402EscrowRequirements } = await import("./dist-2P3XNMJC.js");
28663
28663
  if (hasCompleteSuimppChallenge(entry) || isX402EscrowRequirements(entry)) {
28664
28664
  return { kind: "payable", requirements: entry };
28665
28665
  }
@@ -28677,7 +28677,7 @@ async function payViaX402(args) {
28677
28677
  { reason: "incomplete-x402-accepts" }
28678
28678
  );
28679
28679
  }
28680
- const { buildX402SignedPayment, X402_PAYMENT_HEADER, X402_PAYMENT_RESPONSE_HEADER } = await import("./dist-RTAF2SWN.js");
28680
+ const { buildX402SignedPayment, X402_PAYMENT_HEADER, X402_PAYMENT_RESPONSE_HEADER } = await import("./dist-2P3XNMJC.js");
28681
28681
  const amountRaw = BigInt(requirements.maxAmountRequired);
28682
28682
  assertWithinMaxPrice(atomicToHuman(amountRaw, await assetDecimals(requirements.asset)), options.maxPrice);
28683
28683
  const migrationGasSui = await ensureAddressBalanceCovers({
@@ -28808,7 +28808,7 @@ async function finalize(response, opts) {
28808
28808
  return { status: response.status, body: body2, paid: opts.paid };
28809
28809
  }
28810
28810
  async function makeGrpcBuildClient(client) {
28811
- const { SuiGrpcClient: SuiGrpcClient3 } = await import("./grpc-AJNSMQ2Y.js");
28811
+ const { SuiGrpcClient: SuiGrpcClient3 } = await import("./grpc-GFGD32S5.js");
28812
28812
  const network = client.network === "testnet" ? "testnet" : "mainnet";
28813
28813
  const baseUrl = network === "testnet" ? "https://fullnode.testnet.sui.io" : "https://fullnode.mainnet.sui.io";
28814
28814
  return new SuiGrpcClient3({ baseUrl, network });
@@ -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",
@@ -30972,6 +31000,11 @@ var ACTION_TARGETS = {
30972
31000
  functions: ["refund_unclaimed"]
30973
31001
  }
30974
31002
  };
31003
+ var SUI_FRAMEWORK_PACKAGE = normalizeSuiAddress("0x2");
31004
+ var FRAMEWORK_PRELUDE = {
31005
+ coin: /* @__PURE__ */ new Set(["redeem_funds", "into_balance", "zero", "destroy_zero"]),
31006
+ balance: /* @__PURE__ */ new Set(["redeem_funds", "zero"])
31007
+ };
30975
31008
  var HOST_PINNED_ONLY = /* @__PURE__ */ new Set(["register", "link", "confirm"]);
30976
31009
  var allowUntrustedApi = false;
30977
31010
  function setAllowUntrustedApi(value) {
@@ -31018,17 +31051,23 @@ function assertTxMatchesIntent(txBytes, intent, opts = {}) {
31018
31051
  `Refusing to sign: "${intent.action}" is not a verb this wallet knows how to verify.`
31019
31052
  );
31020
31053
  }
31054
+ let sender;
31055
+ let inputs;
31021
31056
  let calls;
31022
31057
  try {
31023
31058
  const tx = Transaction.from(
31024
31059
  new Uint8Array(Buffer.from(txBytes, "base64"))
31025
31060
  );
31026
- calls = tx.getData().commands.flatMap(
31061
+ const data = tx.getData();
31062
+ sender = data.sender;
31063
+ inputs = data.inputs;
31064
+ calls = data.commands.flatMap(
31027
31065
  (c) => c.$kind === "MoveCall" && c.MoveCall ? [
31028
31066
  {
31029
31067
  pkg: c.MoveCall.package,
31030
31068
  module: c.MoveCall.module,
31031
- fn: c.MoveCall.function
31069
+ fn: c.MoveCall.function,
31070
+ args: c.MoveCall.arguments ?? []
31032
31071
  }
31033
31072
  ] : []
31034
31073
  );
@@ -31042,22 +31081,65 @@ function assertTxMatchesIntent(txBytes, intent, opts = {}) {
31042
31081
  "Refusing to sign: the prepared transaction contains no Move calls."
31043
31082
  );
31044
31083
  }
31084
+ const expectedPkg = normalizeSuiAddress(expected.pkg);
31085
+ let foundIntent = false;
31045
31086
  for (const call of calls) {
31046
- if (call.pkg !== expected.pkg) {
31047
- throw new IntentMismatchError(
31048
- `Refusing to sign: "${intent.action}" targets package ${expected.pkg}, but the transaction calls ${call.pkg}.`
31049
- );
31050
- }
31051
- if (call.module !== expected.module) {
31052
- throw new IntentMismatchError(
31053
- `Refusing to sign: "${intent.action}" should call ${expected.module}, but the transaction calls ${call.module}.`
31054
- );
31087
+ if (normalizeSuiAddress(call.pkg) === expectedPkg) {
31088
+ if (call.module !== expected.module) {
31089
+ throw new IntentMismatchError(
31090
+ `Refusing to sign: "${intent.action}" should call ${expected.module}, but the transaction calls ${call.module}.`
31091
+ );
31092
+ }
31093
+ if (!expected.functions.includes(call.fn)) {
31094
+ throw new IntentMismatchError(
31095
+ `Refusing to sign: "${intent.action}" should call ${expected.module}::${expected.functions.join("|")}, but the transaction calls ${call.module}::${call.fn}.`
31096
+ );
31097
+ }
31098
+ foundIntent = true;
31099
+ continue;
31055
31100
  }
31056
- if (!expected.functions.includes(call.fn)) {
31057
- throw new IntentMismatchError(
31058
- `Refusing to sign: "${intent.action}" should call ${expected.module}::${expected.functions.join("|")}, but the transaction calls ${call.module}::${call.fn}.`
31059
- );
31101
+ if (isAllowedCoinPrelude(call, sender, inputs)) {
31102
+ continue;
31060
31103
  }
31104
+ throw new IntentMismatchError(
31105
+ `Refusing to sign: "${intent.action}" targets package ${expected.pkg}, but the transaction calls ${call.pkg}::${call.module}::${call.fn}.`
31106
+ );
31107
+ }
31108
+ if (!foundIntent) {
31109
+ throw new IntentMismatchError(
31110
+ `Refusing to sign: "${intent.action}" should call ${expected.module}::${expected.functions.join("|")}, but the transaction never does.`
31111
+ );
31112
+ }
31113
+ }
31114
+ function isAllowedCoinPrelude(call, sender, inputs) {
31115
+ if (normalizeSuiAddress(call.pkg) !== SUI_FRAMEWORK_PACKAGE) {
31116
+ return false;
31117
+ }
31118
+ if (FRAMEWORK_PRELUDE[call.module]?.has(call.fn)) {
31119
+ return true;
31120
+ }
31121
+ if (call.module === "coin" && call.fn === "send_funds") {
31122
+ return isSenderRemainderReturn(call, sender, inputs);
31123
+ }
31124
+ return false;
31125
+ }
31126
+ function isSenderRemainderReturn(call, sender, inputs) {
31127
+ if (!sender) {
31128
+ return false;
31129
+ }
31130
+ const recipientArg = call.args[1];
31131
+ if (!recipientArg || recipientArg.$kind !== "Input" || typeof recipientArg.Input !== "number") {
31132
+ return false;
31133
+ }
31134
+ const input = inputs[recipientArg.Input];
31135
+ if (!input || input.$kind !== "Pure" || !input.Pure?.bytes) {
31136
+ return false;
31137
+ }
31138
+ try {
31139
+ const recipient = suiBcs.Address.fromBase64(input.Pure.bytes);
31140
+ return normalizeSuiAddress(recipient) === normalizeSuiAddress(sender);
31141
+ } catch {
31142
+ return false;
31061
31143
  }
31062
31144
  }
31063
31145
  function describeIntent(intent, base) {
@@ -36223,10 +36305,10 @@ function parseDuration(input) {
36223
36305
  }
36224
36306
  var SHA256_HEX_RE = /^0x[0-9a-fA-F]{64}$/;
36225
36307
  var SPEC_STORE_MAX_BYTES = 16 * 1024;
36226
- async function resolveSpecUpload(base, input) {
36308
+ async function loadSpecText(input) {
36227
36309
  const trimmed = input.trim();
36228
36310
  if (SHA256_HEX_RE.test(trimmed)) {
36229
- return { hash: trimmed.toLowerCase(), uploaded: false };
36311
+ return { kind: "hash", hash: trimmed.toLowerCase() };
36230
36312
  }
36231
36313
  let bytes;
36232
36314
  try {
@@ -36247,7 +36329,27 @@ async function resolveSpecUpload(base, input) {
36247
36329
  "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
36330
  );
36249
36331
  }
36250
- return { hash: `0x${await putJobSpec(base, text)}`, uploaded: true };
36332
+ return { kind: "text", text };
36333
+ }
36334
+ async function resolveSpecUpload(base, input) {
36335
+ const loaded = await loadSpecText(input);
36336
+ if (loaded.kind === "hash") {
36337
+ return { hash: loaded.hash, uploaded: false };
36338
+ }
36339
+ return { hash: `0x${await putJobSpec(base, loaded.text)}`, uploaded: true };
36340
+ }
36341
+ async function resolveHireSpecUpload(base, input, title) {
36342
+ const loaded = await loadSpecText(input);
36343
+ if (loaded.kind === "hash") {
36344
+ return { hash: loaded.hash, uploaded: false };
36345
+ }
36346
+ const body2 = isCustomHireEnvelope(loaded.text) ? loaded.text : customHireEnvelope(loaded.text, title, Date.now());
36347
+ if (Buffer.byteLength(body2, "utf8") > SPEC_STORE_MAX_BYTES) {
36348
+ throw new Error(
36349
+ "The brief plus its envelope exceeds the 16 KiB job-spec store cap \u2014 shorten the brief, or link the long artifact (URL / IPFS)."
36350
+ );
36351
+ }
36352
+ return { hash: `0x${await putJobSpec(base, body2)}`, uploaded: true };
36251
36353
  }
36252
36354
  function stateColor(state) {
36253
36355
  if (state === "released") return import_picocolors13.default.green(state);
@@ -36348,7 +36450,7 @@ no fund step; unclaimed openings refund fee-free):
36348
36450
  ASP $ t2 job board \xB7 t2 job claim <openingId>
36349
36451
  `
36350
36452
  );
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(
36453
+ 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
36454
  "--agent <address|#id|@handle>",
36353
36455
  "Hire a listing: the ASP's agent address, #id, or @handle"
36354
36456
  ).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 +36530,11 @@ no fund step; unclaimed openings refund fee-free):
36428
36530
  seller = validateAddress(
36429
36531
  (await resolveAgentRef(base, sellerArg)).address
36430
36532
  );
36431
- ({ hash: specHash } = await resolveSpecUpload(base, opts.spec));
36533
+ ({ hash: specHash } = await resolveHireSpecUpload(
36534
+ base,
36535
+ opts.spec,
36536
+ opts.title
36537
+ ));
36432
36538
  deliverByMs = Date.now() + parseDuration(opts.deadline);
36433
36539
  reviewWindowMs = opts.review ? parseDuration(opts.review) : DEFAULT_REVIEW_WINDOW_MS;
36434
36540
  rejectSplitBps = Number.parseInt(opts.split, 10);
@@ -36894,9 +37000,9 @@ Examples:
36894
37000
  $ t2 service retire sui-market-report
36895
37001
  `
36896
37002
  );
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)").option(
37003
+ 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
37004
  "--requirements <file-or-json-or-text>",
36899
- "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)"
37005
+ "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
37006
  ).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
37007
  "--category <category>",
36902
37008
  `Directory category for your listing: ${AGENT_CATEGORIES.join(" | ")} (required unless already set on your profile)`