@t2000/cli 5.16.0 → 5.17.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
@@ -27783,10 +27783,10 @@ async function finalize(response, opts) {
27783
27783
  return { status: response.status, body: body2, paid: opts.paid };
27784
27784
  }
27785
27785
  async function makeGrpcBuildClient(client) {
27786
- const { SuiGrpcClient: SuiGrpcClient2 } = await import("./grpc-OLWNGPHN.js");
27786
+ const { SuiGrpcClient: SuiGrpcClient3 } = await import("./grpc-OLWNGPHN.js");
27787
27787
  const network = client.network === "testnet" ? "testnet" : "mainnet";
27788
27788
  const baseUrl = network === "testnet" ? "https://fullnode.testnet.sui.io" : "https://fullnode.mainnet.sui.io";
27789
- return new SuiGrpcClient2({ baseUrl, network });
27789
+ return new SuiGrpcClient3({ baseUrl, network });
27790
27790
  }
27791
27791
  function atomicToHuman(raw, decimals) {
27792
27792
  return Number(raw) / 10 ** decimals;
@@ -28436,6 +28436,124 @@ async function listModels(opts) {
28436
28436
  privacy: m.privacy ?? m.privacy_tier
28437
28437
  }));
28438
28438
  }
28439
+ var RECEIPT_ANCHORED_SUFFIX = "::anchor::ReceiptAnchored";
28440
+ function fullnodeUrl(network) {
28441
+ return network === "testnet" ? "https://fullnode.testnet.sui.io" : "https://fullnode.mainnet.sui.io";
28442
+ }
28443
+ async function verifyReceipt(receiptId, opts = {}) {
28444
+ const base = opts.apiBase ?? DEFAULT_API_BASE;
28445
+ const network = opts.network ?? "mainnet";
28446
+ const checks = [];
28447
+ let receipt = null;
28448
+ try {
28449
+ const res = await fetch(`${base}/aci/receipts/${encodeURIComponent(receiptId)}`);
28450
+ if (res.ok) {
28451
+ receipt = await res.json();
28452
+ }
28453
+ } catch {
28454
+ }
28455
+ if (!receipt?.event_log) {
28456
+ checks.push({
28457
+ name: "Receipt",
28458
+ status: "fail",
28459
+ detail: "receipt not found or malformed",
28460
+ trust: "receipt-asserted"
28461
+ });
28462
+ return { receiptId, verified: false, anchorVerified: false, checks };
28463
+ }
28464
+ const wireHash = receipt.event_log.find((e) => e.type === "response.returned")?.wire_hash;
28465
+ const workloadId = receipt.workload_id;
28466
+ checks.push({
28467
+ name: "Receipt",
28468
+ status: wireHash && workloadId ? "pass" : "fail",
28469
+ detail: wireHash ? `well-formed (${receipt.event_log.length} log entries, workload ${workloadId})` : "missing response wire_hash / workload_id",
28470
+ trust: "receipt-asserted"
28471
+ });
28472
+ const upstreamEv = receipt.event_log.find((e) => e.type === "upstream.verified");
28473
+ const upstreamOk = upstreamEv?.result === "verified";
28474
+ checks.push({
28475
+ name: "Confidential upstream",
28476
+ status: upstreamEv ? upstreamOk ? "pass" : "fail" : "skip",
28477
+ detail: upstreamEv ? `${upstreamEv.provider ?? upstreamEv.upstream_name ?? "upstream"}: ${upstreamEv.result ?? "unknown"}${upstreamEv.tcb_status ? ` (TCB ${upstreamEv.tcb_status})` : ""}` : "no upstream.verified event (routed/non-confidential?)",
28478
+ trust: "receipt-asserted"
28479
+ });
28480
+ let anchorVerified = false;
28481
+ let anchor;
28482
+ let digest;
28483
+ try {
28484
+ const res = await fetch(`${base}/aci/anchor/${encodeURIComponent(receiptId)}`);
28485
+ if (res.ok) {
28486
+ const j = await res.json();
28487
+ digest = j.txDigest;
28488
+ }
28489
+ } catch {
28490
+ }
28491
+ if (!digest) {
28492
+ checks.push({
28493
+ name: "Sui anchor",
28494
+ status: "fail",
28495
+ detail: `no anchor on record \u2014 POST ${base}/aci/anchor/${receiptId} to create one`,
28496
+ trust: "trustless"
28497
+ });
28498
+ } else {
28499
+ try {
28500
+ const client = new SuiGrpcClient({ baseUrl: fullnodeUrl(network), network });
28501
+ const tx = await client.core.getTransaction({
28502
+ digest,
28503
+ include: { events: true }
28504
+ });
28505
+ const txn = tx.$kind === "Transaction" ? tx.Transaction : tx.FailedTransaction;
28506
+ const ev = (txn.events ?? []).find(
28507
+ (e) => e.eventType.endsWith(RECEIPT_ANCHORED_SUFFIX)
28508
+ );
28509
+ const data = ev?.json ?? {};
28510
+ const onChainReceipt = String(data.receipt_id ?? "");
28511
+ const onChainWire = String(data.wire_hash ?? "");
28512
+ const onChainWorkload = String(data.workload_id ?? "");
28513
+ const matches = onChainReceipt === receiptId && onChainWire === wireHash && onChainWorkload === workloadId;
28514
+ anchorVerified = matches;
28515
+ anchor = {
28516
+ txDigest: digest,
28517
+ anchoredAtMs: data.anchored_at_ms ? String(data.anchored_at_ms) : void 0,
28518
+ anchoredBy: data.anchored_by ? String(data.anchored_by) : void 0,
28519
+ explorer: `https://suiscan.xyz/${network}/tx/${digest}`
28520
+ };
28521
+ checks.push({
28522
+ name: "Sui anchor",
28523
+ status: matches ? "pass" : "fail",
28524
+ detail: matches ? `on-chain ReceiptAnchored matches (wire_hash + workload_id), tx ${digest}` : `on-chain event does NOT match the receipt (wire ${onChainWire || "absent"})`,
28525
+ trust: "trustless"
28526
+ });
28527
+ } catch (e) {
28528
+ checks.push({
28529
+ name: "Sui anchor",
28530
+ status: "fail",
28531
+ detail: `could not read anchor tx ${digest}: ${e instanceof Error ? e.message : "error"}`,
28532
+ trust: "trustless"
28533
+ });
28534
+ }
28535
+ }
28536
+ checks.push({
28537
+ name: "Receipt signature",
28538
+ status: "skip",
28539
+ detail: receipt.signature ? "present (local recompute via RedPill keyset canonicalization = roadmap)" : "no signature on receipt",
28540
+ trust: "roadmap"
28541
+ });
28542
+ return {
28543
+ receiptId,
28544
+ verified: Boolean(wireHash && workloadId) && anchorVerified,
28545
+ anchorVerified,
28546
+ checks,
28547
+ wireHash,
28548
+ workloadId,
28549
+ upstream: upstreamEv ? {
28550
+ provider: upstreamEv.provider ?? upstreamEv.upstream_name,
28551
+ result: upstreamEv.result,
28552
+ tcbStatus: upstreamEv.tcb_status
28553
+ } : void 0,
28554
+ anchor
28555
+ };
28556
+ }
28439
28557
  var DEFAULT_CONFIG_DIR = join2(homedir(), ".t2000");
28440
28558
  function resolveConfigPath(configDir) {
28441
28559
  return join2(configDir ?? DEFAULT_CONFIG_DIR, "config.json");
@@ -28717,6 +28835,11 @@ var T2000 = class _T2000 extends import_index2.default {
28717
28835
  async models(opts) {
28718
28836
  return listModels(opts);
28719
28837
  }
28838
+ /** Verify a confidential response by receipt id — checks the signed receipt
28839
+ * + its trustless on-chain Sui anchor. Fails closed on any mismatch. */
28840
+ async verify(receiptId, opts) {
28841
+ return verifyReceipt(receiptId, opts);
28842
+ }
28720
28843
  // -- Swap --
28721
28844
  async swap(params) {
28722
28845
  this.limits.assert({
@@ -32473,8 +32596,77 @@ function registerChat(program3) {
32473
32596
  });
32474
32597
  }
32475
32598
 
32476
- // src/commands/services/search.ts
32599
+ // src/commands/verify.ts
32477
32600
  var import_picocolors10 = __toESM(require_picocolors(), 1);
32601
+ function mark(check2) {
32602
+ if (check2.status === "pass") {
32603
+ return import_picocolors10.default.green("\u2713");
32604
+ }
32605
+ if (check2.status === "fail") {
32606
+ return import_picocolors10.default.red("\u2717");
32607
+ }
32608
+ return import_picocolors10.default.dim("\u2022");
32609
+ }
32610
+ function trustTag(check2) {
32611
+ if (check2.trust === "trustless") {
32612
+ return import_picocolors10.default.green(" (trustless \xB7 read from Sui)");
32613
+ }
32614
+ if (check2.trust === "roadmap") {
32615
+ return import_picocolors10.default.dim(" (roadmap)");
32616
+ }
32617
+ return import_picocolors10.default.dim(" (in signed receipt)");
32618
+ }
32619
+ function registerVerify(program3) {
32620
+ program3.command("verify").argument("<receipt-id>", "A confidential receipt id (rcpt-\u2026)").description(
32621
+ "Verify a confidential response by receipt id \u2014 checks the signed receipt + its trustless on-chain Sui anchor. Fails closed on any mismatch."
32622
+ ).option("--api <url>", "API base URL (default https://api.t2000.ai/v1)").option("--testnet", "Read the anchor from Sui testnet (default mainnet)").action(async (receiptId, opts) => {
32623
+ try {
32624
+ const result = await verifyReceipt(receiptId, {
32625
+ apiBase: opts.api,
32626
+ network: opts.testnet ? "testnet" : "mainnet"
32627
+ });
32628
+ if (isJsonMode()) {
32629
+ printJson(result);
32630
+ if (!result.verified) {
32631
+ process.exitCode = 1;
32632
+ }
32633
+ return;
32634
+ }
32635
+ printBlank();
32636
+ printLine(import_picocolors10.default.bold(`Verifying ${receiptId}`));
32637
+ printBlank();
32638
+ for (const check2 of result.checks) {
32639
+ printLine(` ${mark(check2)} ${import_picocolors10.default.bold(check2.name)}${trustTag(check2)}`);
32640
+ printLine(` ${import_picocolors10.default.dim(check2.detail)}`);
32641
+ }
32642
+ printBlank();
32643
+ if (result.anchor) {
32644
+ printLine(import_picocolors10.default.dim(` anchor: ${result.anchor.explorer}`));
32645
+ }
32646
+ if (result.verified) {
32647
+ printLine(
32648
+ import_picocolors10.default.green(
32649
+ " RESULT: \u2713 anchor-verified on Sui (tamper-evident, Sui-native)."
32650
+ )
32651
+ );
32652
+ printLine(
32653
+ import_picocolors10.default.dim(
32654
+ " Local DCAP-quote + receipt-signature recompute = roadmap (full no-trust)."
32655
+ )
32656
+ );
32657
+ } else {
32658
+ printLine(import_picocolors10.default.red(" RESULT: \u2717 NOT verified \u2014 see the failed check above."));
32659
+ process.exitCode = 1;
32660
+ }
32661
+ printBlank();
32662
+ } catch (error) {
32663
+ handleError(error);
32664
+ }
32665
+ });
32666
+ }
32667
+
32668
+ // src/commands/services/search.ts
32669
+ var import_picocolors11 = __toESM(require_picocolors(), 1);
32478
32670
 
32479
32671
  // src/commands/services/catalog.ts
32480
32672
  var DEFAULT_GATEWAY_URL = "https://mpp.t2000.ai";
@@ -32576,9 +32768,9 @@ Examples:
32576
32768
  }
32577
32769
  function renderServiceLine(svc) {
32578
32770
  const minPrice = cheapestEndpointPrice(svc);
32579
- const priceTag = minPrice !== null ? import_picocolors10.default.green(`from $${minPrice}`) : import_picocolors10.default.dim("no pricing");
32580
- const catTag = svc.categories.length > 0 ? import_picocolors10.default.dim(`[${svc.categories.join(", ")}]`) : "";
32581
- printKeyValue(import_picocolors10.default.bold(svc.name), `${priceTag} ${catTag}`);
32771
+ const priceTag = minPrice !== null ? import_picocolors11.default.green(`from $${minPrice}`) : import_picocolors11.default.dim("no pricing");
32772
+ const catTag = svc.categories.length > 0 ? import_picocolors11.default.dim(`[${svc.categories.join(", ")}]`) : "";
32773
+ printKeyValue(import_picocolors11.default.bold(svc.name), `${priceTag} ${catTag}`);
32582
32774
  printKeyValue(" url", svc.serviceUrl);
32583
32775
  printKeyValue(" about", svc.description);
32584
32776
  printBlank();
@@ -32592,7 +32784,7 @@ function cheapestEndpointPrice(svc) {
32592
32784
  }
32593
32785
 
32594
32786
  // src/commands/services/inspect.ts
32595
- var import_picocolors11 = __toESM(require_picocolors(), 1);
32787
+ var import_picocolors12 = __toESM(require_picocolors(), 1);
32596
32788
  function registerServicesInspect(parent) {
32597
32789
  parent.command("inspect").description("Show pricing + endpoints for an MPP service or endpoint URL").argument("<url>", "Service base URL or endpoint URL").option("--gateway <url>", "Override gateway base URL (default: https://mpp.t2000.ai)").addHelpText(
32598
32790
  "after",
@@ -32629,7 +32821,7 @@ Examples:
32629
32821
  return;
32630
32822
  }
32631
32823
  printBlank();
32632
- printKeyValue("Service", import_picocolors11.default.bold(service.name));
32824
+ printKeyValue("Service", import_picocolors12.default.bold(service.name));
32633
32825
  printKeyValue("URL", service.serviceUrl);
32634
32826
  printKeyValue("About", service.description);
32635
32827
  if (service.categories.length > 0) {
@@ -32659,7 +32851,7 @@ Examples:
32659
32851
  function renderEndpoint(ep, serviceUrl) {
32660
32852
  const price = `$${ep.price}`;
32661
32853
  const label = `${ep.method} ${ep.path}`.padEnd(40);
32662
- printKeyValue(label, `${import_picocolors11.default.green(price)} ${import_picocolors11.default.dim(ep.description)}`);
32854
+ printKeyValue(label, `${import_picocolors12.default.green(price)} ${import_picocolors12.default.dim(ep.description)}`);
32663
32855
  printKeyValue(" url", `${serviceUrl}${ep.path}`);
32664
32856
  printBlank();
32665
32857
  }
@@ -32682,7 +32874,7 @@ T2000_GATEWAY_URL or --gateway <url> for local development.
32682
32874
  }
32683
32875
 
32684
32876
  // src/commands/limit/show.ts
32685
- var import_picocolors12 = __toESM(require_picocolors(), 1);
32877
+ var import_picocolors13 = __toESM(require_picocolors(), 1);
32686
32878
  function registerLimitShow(parent) {
32687
32879
  parent.command("show").description("Show current spending limits").action(async (opts) => {
32688
32880
  try {
@@ -32705,10 +32897,10 @@ function registerLimitShow(parent) {
32705
32897
  }
32706
32898
  printBlank();
32707
32899
  if (limits.perTxUsd !== void 0) {
32708
- printKeyValue("Per-transaction", import_picocolors12.default.green(`$${limits.perTxUsd}`));
32900
+ printKeyValue("Per-transaction", import_picocolors13.default.green(`$${limits.perTxUsd}`));
32709
32901
  }
32710
32902
  if (limits.dailyUsd !== void 0) {
32711
- printKeyValue("Daily (cumulative)", import_picocolors12.default.green(`$${limits.dailyUsd}`));
32903
+ printKeyValue("Daily (cumulative)", import_picocolors13.default.green(`$${limits.dailyUsd}`));
32712
32904
  }
32713
32905
  printBlank();
32714
32906
  printInfo("Use `--force` on `t2 send` / `t2 swap` / `t2 pay` to override per-call.");
@@ -32720,7 +32912,7 @@ function registerLimitShow(parent) {
32720
32912
  }
32721
32913
 
32722
32914
  // src/commands/limit/set.ts
32723
- var import_picocolors13 = __toESM(require_picocolors(), 1);
32915
+ var import_picocolors14 = __toESM(require_picocolors(), 1);
32724
32916
  function parseLimitSetArgs(opts) {
32725
32917
  const perTx = opts.perTx !== void 0 ? parseUsdFlag("--per-tx", opts.perTx) : void 0;
32726
32918
  const daily = opts.daily !== void 0 ? parseUsdFlag("--daily", opts.daily) : void 0;
@@ -32762,10 +32954,10 @@ Examples:
32762
32954
  printBlank();
32763
32955
  printSuccess("Spending limits updated.");
32764
32956
  if (next?.perTxUsd !== void 0) {
32765
- printKeyValue("Per-transaction", import_picocolors13.default.green(`$${next.perTxUsd}`));
32957
+ printKeyValue("Per-transaction", import_picocolors14.default.green(`$${next.perTxUsd}`));
32766
32958
  }
32767
32959
  if (next?.dailyUsd !== void 0) {
32768
- printKeyValue("Daily (cumulative)", import_picocolors13.default.green(`$${next.dailyUsd}`));
32960
+ printKeyValue("Daily (cumulative)", import_picocolors14.default.green(`$${next.dailyUsd}`));
32769
32961
  }
32770
32962
  printBlank();
32771
32963
  printInfo("Use `t2 limit show` to view; `t2 limit reset` to clear.");
@@ -32827,7 +33019,7 @@ function registerMcpStart(parent) {
32827
33019
  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) => {
32828
33020
  let mod2;
32829
33021
  try {
32830
- mod2 = await import("./dist-UPUBYGXT.js");
33022
+ mod2 = await import("./dist-7QRKMV5A.js");
32831
33023
  } catch {
32832
33024
  console.error("MCP server not installed. Run:\n npm install -g @t2000/mcp");
32833
33025
  process.exit(1);
@@ -33790,6 +33982,7 @@ Examples:
33790
33982
  registerSwap(program3);
33791
33983
  registerPay(program3);
33792
33984
  registerChat(program3);
33985
+ registerVerify(program3);
33793
33986
  registerServices(program3);
33794
33987
  registerLimit(program3);
33795
33988
  registerMcp(program3);