@t2000/cli 5.15.1 → 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;
@@ -28340,7 +28340,9 @@ function body(params, stream) {
28340
28340
  return JSON.stringify({
28341
28341
  model: params.model,
28342
28342
  messages: params.messages,
28343
- ...stream ? { stream: true } : {},
28343
+ // include_usage the final stream chunk carries usage + x_receipt_id
28344
+ // (the confidential attestation receipt) so we can surface it after a stream.
28345
+ ...stream ? { stream: true, stream_options: { include_usage: true } } : {},
28344
28346
  ...params.maxTokens != null ? { max_tokens: params.maxTokens } : {},
28345
28347
  ...params.temperature != null ? { temperature: params.temperature } : {}
28346
28348
  });
@@ -28356,12 +28358,14 @@ async function chatCompletion(params) {
28356
28358
  if (!res.ok) {
28357
28359
  await failBody(res);
28358
28360
  }
28361
+ const receiptId = res.headers.get("x-receipt-id") ?? void 0;
28359
28362
  const raw = await res.json();
28360
28363
  const content = raw?.choices?.[0]?.message?.content ?? "";
28361
28364
  return {
28362
28365
  content,
28363
28366
  model: raw?.model ?? params.model,
28364
28367
  usage: usageOf(raw),
28368
+ receiptId,
28365
28369
  raw
28366
28370
  };
28367
28371
  }
@@ -28375,11 +28379,12 @@ async function* chatCompletionStream(params) {
28375
28379
  });
28376
28380
  if (!(res.ok && res.body)) {
28377
28381
  await failBody(res);
28378
- return;
28382
+ return {};
28379
28383
  }
28380
28384
  const reader = res.body.getReader();
28381
28385
  const decoder = new TextDecoder();
28382
28386
  let buffer = "";
28387
+ let receiptId;
28383
28388
  while (true) {
28384
28389
  const { done, value } = await reader.read();
28385
28390
  if (done) {
@@ -28395,10 +28400,13 @@ async function* chatCompletionStream(params) {
28395
28400
  }
28396
28401
  const data = trimmed.slice(5).trim();
28397
28402
  if (data === "[DONE]") {
28398
- return;
28403
+ return { receiptId };
28399
28404
  }
28400
28405
  try {
28401
28406
  const json = JSON.parse(data);
28407
+ if (json.x_receipt_id) {
28408
+ receiptId = json.x_receipt_id;
28409
+ }
28402
28410
  const delta = json.choices?.[0]?.delta?.content;
28403
28411
  if (typeof delta === "string" && delta) {
28404
28412
  yield delta;
@@ -28407,6 +28415,7 @@ async function* chatCompletionStream(params) {
28407
28415
  }
28408
28416
  }
28409
28417
  }
28418
+ return { receiptId };
28410
28419
  }
28411
28420
  async function listModels(opts) {
28412
28421
  const base = opts?.apiBase ?? DEFAULT_API_BASE;
@@ -28427,6 +28436,124 @@ async function listModels(opts) {
28427
28436
  privacy: m.privacy ?? m.privacy_tier
28428
28437
  }));
28429
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
+ }
28430
28557
  var DEFAULT_CONFIG_DIR = join2(homedir(), ".t2000");
28431
28558
  function resolveConfigPath(configDir) {
28432
28559
  return join2(configDir ?? DEFAULT_CONFIG_DIR, "config.json");
@@ -28699,7 +28826,8 @@ var T2000 = class _T2000 extends import_index2.default {
28699
28826
  async chat(params) {
28700
28827
  return chatCompletion(params);
28701
28828
  }
28702
- /** Streaming chat completion — async-iterate the assistant text deltas. */
28829
+ /** Streaming chat completion — async-iterate the assistant text deltas;
28830
+ * the generator returns `{ receiptId }` (confidential attestation) at the end. */
28703
28831
  chatStream(params) {
28704
28832
  return chatCompletionStream(params);
28705
28833
  }
@@ -28707,6 +28835,11 @@ var T2000 = class _T2000 extends import_index2.default {
28707
28835
  async models(opts) {
28708
28836
  return listModels(opts);
28709
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
+ }
28710
28843
  // -- Swap --
28711
28844
  async swap(params) {
28712
28845
  this.limits.assert({
@@ -32377,6 +32510,12 @@ function describeSchemaFields(schema) {
32377
32510
  }
32378
32511
 
32379
32512
  // src/commands/chat.ts
32513
+ var import_picocolors9 = __toESM(require_picocolors(), 1);
32514
+ function receiptLine(receiptId) {
32515
+ if (receiptId) {
32516
+ printLine(import_picocolors9.default.dim(`\u{1F512} confidential \xB7 attested \xB7 receipt ${receiptId}`));
32517
+ }
32518
+ }
32380
32519
  var DEFAULT_MODEL = "zai/glm-5.2";
32381
32520
  function numOrUndef(v) {
32382
32521
  if (v === void 0) {
@@ -32407,20 +32546,30 @@ function registerChat(program3) {
32407
32546
  if (isJsonMode() || opts.stream === false) {
32408
32547
  const res = await chatCompletion(params);
32409
32548
  if (isJsonMode()) {
32410
- printJson({ model: res.model, content: res.content, usage: res.usage });
32549
+ printJson({
32550
+ model: res.model,
32551
+ content: res.content,
32552
+ usage: res.usage,
32553
+ receiptId: res.receiptId
32554
+ });
32411
32555
  return;
32412
32556
  }
32413
32557
  printBlank();
32414
32558
  printLine(res.content);
32559
+ receiptLine(res.receiptId);
32415
32560
  printBlank();
32416
32561
  return;
32417
32562
  }
32563
+ const gen = chatCompletionStream(params);
32418
32564
  let any = false;
32419
- for await (const delta of chatCompletionStream(params)) {
32420
- process.stdout.write(delta);
32565
+ let next = await gen.next();
32566
+ while (!next.done) {
32567
+ process.stdout.write(next.value);
32421
32568
  any = true;
32569
+ next = await gen.next();
32422
32570
  }
32423
32571
  process.stdout.write(any ? "\n" : "");
32572
+ receiptLine(next.value?.receiptId);
32424
32573
  } catch (error) {
32425
32574
  handleError(error);
32426
32575
  }
@@ -32447,8 +32596,77 @@ function registerChat(program3) {
32447
32596
  });
32448
32597
  }
32449
32598
 
32599
+ // src/commands/verify.ts
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
+
32450
32668
  // src/commands/services/search.ts
32451
- var import_picocolors9 = __toESM(require_picocolors(), 1);
32669
+ var import_picocolors11 = __toESM(require_picocolors(), 1);
32452
32670
 
32453
32671
  // src/commands/services/catalog.ts
32454
32672
  var DEFAULT_GATEWAY_URL = "https://mpp.t2000.ai";
@@ -32550,9 +32768,9 @@ Examples:
32550
32768
  }
32551
32769
  function renderServiceLine(svc) {
32552
32770
  const minPrice = cheapestEndpointPrice(svc);
32553
- const priceTag = minPrice !== null ? import_picocolors9.default.green(`from $${minPrice}`) : import_picocolors9.default.dim("no pricing");
32554
- const catTag = svc.categories.length > 0 ? import_picocolors9.default.dim(`[${svc.categories.join(", ")}]`) : "";
32555
- printKeyValue(import_picocolors9.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}`);
32556
32774
  printKeyValue(" url", svc.serviceUrl);
32557
32775
  printKeyValue(" about", svc.description);
32558
32776
  printBlank();
@@ -32566,7 +32784,7 @@ function cheapestEndpointPrice(svc) {
32566
32784
  }
32567
32785
 
32568
32786
  // src/commands/services/inspect.ts
32569
- var import_picocolors10 = __toESM(require_picocolors(), 1);
32787
+ var import_picocolors12 = __toESM(require_picocolors(), 1);
32570
32788
  function registerServicesInspect(parent) {
32571
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(
32572
32790
  "after",
@@ -32603,7 +32821,7 @@ Examples:
32603
32821
  return;
32604
32822
  }
32605
32823
  printBlank();
32606
- printKeyValue("Service", import_picocolors10.default.bold(service.name));
32824
+ printKeyValue("Service", import_picocolors12.default.bold(service.name));
32607
32825
  printKeyValue("URL", service.serviceUrl);
32608
32826
  printKeyValue("About", service.description);
32609
32827
  if (service.categories.length > 0) {
@@ -32633,7 +32851,7 @@ Examples:
32633
32851
  function renderEndpoint(ep, serviceUrl) {
32634
32852
  const price = `$${ep.price}`;
32635
32853
  const label = `${ep.method} ${ep.path}`.padEnd(40);
32636
- printKeyValue(label, `${import_picocolors10.default.green(price)} ${import_picocolors10.default.dim(ep.description)}`);
32854
+ printKeyValue(label, `${import_picocolors12.default.green(price)} ${import_picocolors12.default.dim(ep.description)}`);
32637
32855
  printKeyValue(" url", `${serviceUrl}${ep.path}`);
32638
32856
  printBlank();
32639
32857
  }
@@ -32656,7 +32874,7 @@ T2000_GATEWAY_URL or --gateway <url> for local development.
32656
32874
  }
32657
32875
 
32658
32876
  // src/commands/limit/show.ts
32659
- var import_picocolors11 = __toESM(require_picocolors(), 1);
32877
+ var import_picocolors13 = __toESM(require_picocolors(), 1);
32660
32878
  function registerLimitShow(parent) {
32661
32879
  parent.command("show").description("Show current spending limits").action(async (opts) => {
32662
32880
  try {
@@ -32679,10 +32897,10 @@ function registerLimitShow(parent) {
32679
32897
  }
32680
32898
  printBlank();
32681
32899
  if (limits.perTxUsd !== void 0) {
32682
- printKeyValue("Per-transaction", import_picocolors11.default.green(`$${limits.perTxUsd}`));
32900
+ printKeyValue("Per-transaction", import_picocolors13.default.green(`$${limits.perTxUsd}`));
32683
32901
  }
32684
32902
  if (limits.dailyUsd !== void 0) {
32685
- printKeyValue("Daily (cumulative)", import_picocolors11.default.green(`$${limits.dailyUsd}`));
32903
+ printKeyValue("Daily (cumulative)", import_picocolors13.default.green(`$${limits.dailyUsd}`));
32686
32904
  }
32687
32905
  printBlank();
32688
32906
  printInfo("Use `--force` on `t2 send` / `t2 swap` / `t2 pay` to override per-call.");
@@ -32694,7 +32912,7 @@ function registerLimitShow(parent) {
32694
32912
  }
32695
32913
 
32696
32914
  // src/commands/limit/set.ts
32697
- var import_picocolors12 = __toESM(require_picocolors(), 1);
32915
+ var import_picocolors14 = __toESM(require_picocolors(), 1);
32698
32916
  function parseLimitSetArgs(opts) {
32699
32917
  const perTx = opts.perTx !== void 0 ? parseUsdFlag("--per-tx", opts.perTx) : void 0;
32700
32918
  const daily = opts.daily !== void 0 ? parseUsdFlag("--daily", opts.daily) : void 0;
@@ -32736,10 +32954,10 @@ Examples:
32736
32954
  printBlank();
32737
32955
  printSuccess("Spending limits updated.");
32738
32956
  if (next?.perTxUsd !== void 0) {
32739
- printKeyValue("Per-transaction", import_picocolors12.default.green(`$${next.perTxUsd}`));
32957
+ printKeyValue("Per-transaction", import_picocolors14.default.green(`$${next.perTxUsd}`));
32740
32958
  }
32741
32959
  if (next?.dailyUsd !== void 0) {
32742
- printKeyValue("Daily (cumulative)", import_picocolors12.default.green(`$${next.dailyUsd}`));
32960
+ printKeyValue("Daily (cumulative)", import_picocolors14.default.green(`$${next.dailyUsd}`));
32743
32961
  }
32744
32962
  printBlank();
32745
32963
  printInfo("Use `t2 limit show` to view; `t2 limit reset` to clear.");
@@ -32801,7 +33019,7 @@ function registerMcpStart(parent) {
32801
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) => {
32802
33020
  let mod2;
32803
33021
  try {
32804
- mod2 = await import("./dist-JDPHHZMS.js");
33022
+ mod2 = await import("./dist-7QRKMV5A.js");
32805
33023
  } catch {
32806
33024
  console.error("MCP server not installed. Run:\n npm install -g @t2000/mcp");
32807
33025
  process.exit(1);
@@ -33764,6 +33982,7 @@ Examples:
33764
33982
  registerSwap(program3);
33765
33983
  registerPay(program3);
33766
33984
  registerChat(program3);
33985
+ registerVerify(program3);
33767
33986
  registerServices(program3);
33768
33987
  registerLimit(program3);
33769
33988
  registerMcp(program3);