@t2000/mcp 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
@@ -78815,10 +78815,10 @@ async function finalize(response, opts) {
78815
78815
  return { status: response.status, body: body2, paid: opts.paid };
78816
78816
  }
78817
78817
  async function makeGrpcBuildClient(client) {
78818
- const { SuiGrpcClient: SuiGrpcClient2 } = await Promise.resolve().then(() => (init_grpc(), grpc_exports));
78818
+ const { SuiGrpcClient: SuiGrpcClient3 } = await Promise.resolve().then(() => (init_grpc(), grpc_exports));
78819
78819
  const network = client.network === "testnet" ? "testnet" : "mainnet";
78820
78820
  const baseUrl = network === "testnet" ? "https://fullnode.testnet.sui.io" : "https://fullnode.mainnet.sui.io";
78821
- return new SuiGrpcClient2({ baseUrl, network });
78821
+ return new SuiGrpcClient3({ baseUrl, network });
78822
78822
  }
78823
78823
  function atomicToHuman(raw, decimals) {
78824
78824
  return Number(raw) / 10 ** decimals;
@@ -79369,7 +79369,9 @@ function body(params, stream4) {
79369
79369
  return JSON.stringify({
79370
79370
  model: params.model,
79371
79371
  messages: params.messages,
79372
- ...stream4 ? { stream: true } : {},
79372
+ // include_usage the final stream chunk carries usage + x_receipt_id
79373
+ // (the confidential attestation receipt) so we can surface it after a stream.
79374
+ ...stream4 ? { stream: true, stream_options: { include_usage: true } } : {},
79373
79375
  ...params.maxTokens != null ? { max_tokens: params.maxTokens } : {},
79374
79376
  ...params.temperature != null ? { temperature: params.temperature } : {}
79375
79377
  });
@@ -79385,12 +79387,14 @@ async function chatCompletion(params) {
79385
79387
  if (!res.ok) {
79386
79388
  await failBody(res);
79387
79389
  }
79390
+ const receiptId = res.headers.get("x-receipt-id") ?? void 0;
79388
79391
  const raw = await res.json();
79389
79392
  const content = raw?.choices?.[0]?.message?.content ?? "";
79390
79393
  return {
79391
79394
  content,
79392
79395
  model: raw?.model ?? params.model,
79393
79396
  usage: usageOf(raw),
79397
+ receiptId,
79394
79398
  raw
79395
79399
  };
79396
79400
  }
@@ -79404,11 +79408,12 @@ async function* chatCompletionStream(params) {
79404
79408
  });
79405
79409
  if (!(res.ok && res.body)) {
79406
79410
  await failBody(res);
79407
- return;
79411
+ return {};
79408
79412
  }
79409
79413
  const reader = res.body.getReader();
79410
79414
  const decoder = new TextDecoder();
79411
79415
  let buffer = "";
79416
+ let receiptId;
79412
79417
  while (true) {
79413
79418
  const { done, value } = await reader.read();
79414
79419
  if (done) {
@@ -79424,10 +79429,13 @@ async function* chatCompletionStream(params) {
79424
79429
  }
79425
79430
  const data = trimmed.slice(5).trim();
79426
79431
  if (data === "[DONE]") {
79427
- return;
79432
+ return { receiptId };
79428
79433
  }
79429
79434
  try {
79430
79435
  const json = JSON.parse(data);
79436
+ if (json.x_receipt_id) {
79437
+ receiptId = json.x_receipt_id;
79438
+ }
79431
79439
  const delta = json.choices?.[0]?.delta?.content;
79432
79440
  if (typeof delta === "string" && delta) {
79433
79441
  yield delta;
@@ -79436,6 +79444,7 @@ async function* chatCompletionStream(params) {
79436
79444
  }
79437
79445
  }
79438
79446
  }
79447
+ return { receiptId };
79439
79448
  }
79440
79449
  async function listModels(opts) {
79441
79450
  const base = opts?.apiBase ?? DEFAULT_API_BASE;
@@ -79456,6 +79465,124 @@ async function listModels(opts) {
79456
79465
  privacy: m.privacy ?? m.privacy_tier
79457
79466
  }));
79458
79467
  }
79468
+ var RECEIPT_ANCHORED_SUFFIX = "::anchor::ReceiptAnchored";
79469
+ function fullnodeUrl(network) {
79470
+ return network === "testnet" ? "https://fullnode.testnet.sui.io" : "https://fullnode.mainnet.sui.io";
79471
+ }
79472
+ async function verifyReceipt(receiptId, opts = {}) {
79473
+ const base = opts.apiBase ?? DEFAULT_API_BASE;
79474
+ const network = opts.network ?? "mainnet";
79475
+ const checks = [];
79476
+ let receipt = null;
79477
+ try {
79478
+ const res = await fetch(`${base}/aci/receipts/${encodeURIComponent(receiptId)}`);
79479
+ if (res.ok) {
79480
+ receipt = await res.json();
79481
+ }
79482
+ } catch {
79483
+ }
79484
+ if (!receipt?.event_log) {
79485
+ checks.push({
79486
+ name: "Receipt",
79487
+ status: "fail",
79488
+ detail: "receipt not found or malformed",
79489
+ trust: "receipt-asserted"
79490
+ });
79491
+ return { receiptId, verified: false, anchorVerified: false, checks };
79492
+ }
79493
+ const wireHash = receipt.event_log.find((e) => e.type === "response.returned")?.wire_hash;
79494
+ const workloadId = receipt.workload_id;
79495
+ checks.push({
79496
+ name: "Receipt",
79497
+ status: wireHash && workloadId ? "pass" : "fail",
79498
+ detail: wireHash ? `well-formed (${receipt.event_log.length} log entries, workload ${workloadId})` : "missing response wire_hash / workload_id",
79499
+ trust: "receipt-asserted"
79500
+ });
79501
+ const upstreamEv = receipt.event_log.find((e) => e.type === "upstream.verified");
79502
+ const upstreamOk = upstreamEv?.result === "verified";
79503
+ checks.push({
79504
+ name: "Confidential upstream",
79505
+ status: upstreamEv ? upstreamOk ? "pass" : "fail" : "skip",
79506
+ 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?)",
79507
+ trust: "receipt-asserted"
79508
+ });
79509
+ let anchorVerified = false;
79510
+ let anchor;
79511
+ let digest;
79512
+ try {
79513
+ const res = await fetch(`${base}/aci/anchor/${encodeURIComponent(receiptId)}`);
79514
+ if (res.ok) {
79515
+ const j = await res.json();
79516
+ digest = j.txDigest;
79517
+ }
79518
+ } catch {
79519
+ }
79520
+ if (!digest) {
79521
+ checks.push({
79522
+ name: "Sui anchor",
79523
+ status: "fail",
79524
+ detail: `no anchor on record \u2014 POST ${base}/aci/anchor/${receiptId} to create one`,
79525
+ trust: "trustless"
79526
+ });
79527
+ } else {
79528
+ try {
79529
+ const client = new SuiGrpcClient({ baseUrl: fullnodeUrl(network), network });
79530
+ const tx = await client.core.getTransaction({
79531
+ digest,
79532
+ include: { events: true }
79533
+ });
79534
+ const txn = tx.$kind === "Transaction" ? tx.Transaction : tx.FailedTransaction;
79535
+ const ev = (txn.events ?? []).find(
79536
+ (e) => e.eventType.endsWith(RECEIPT_ANCHORED_SUFFIX)
79537
+ );
79538
+ const data = ev?.json ?? {};
79539
+ const onChainReceipt = String(data.receipt_id ?? "");
79540
+ const onChainWire = String(data.wire_hash ?? "");
79541
+ const onChainWorkload = String(data.workload_id ?? "");
79542
+ const matches = onChainReceipt === receiptId && onChainWire === wireHash && onChainWorkload === workloadId;
79543
+ anchorVerified = matches;
79544
+ anchor = {
79545
+ txDigest: digest,
79546
+ anchoredAtMs: data.anchored_at_ms ? String(data.anchored_at_ms) : void 0,
79547
+ anchoredBy: data.anchored_by ? String(data.anchored_by) : void 0,
79548
+ explorer: `https://suiscan.xyz/${network}/tx/${digest}`
79549
+ };
79550
+ checks.push({
79551
+ name: "Sui anchor",
79552
+ status: matches ? "pass" : "fail",
79553
+ detail: matches ? `on-chain ReceiptAnchored matches (wire_hash + workload_id), tx ${digest}` : `on-chain event does NOT match the receipt (wire ${onChainWire || "absent"})`,
79554
+ trust: "trustless"
79555
+ });
79556
+ } catch (e) {
79557
+ checks.push({
79558
+ name: "Sui anchor",
79559
+ status: "fail",
79560
+ detail: `could not read anchor tx ${digest}: ${e instanceof Error ? e.message : "error"}`,
79561
+ trust: "trustless"
79562
+ });
79563
+ }
79564
+ }
79565
+ checks.push({
79566
+ name: "Receipt signature",
79567
+ status: "skip",
79568
+ detail: receipt.signature ? "present (local recompute via RedPill keyset canonicalization = roadmap)" : "no signature on receipt",
79569
+ trust: "roadmap"
79570
+ });
79571
+ return {
79572
+ receiptId,
79573
+ verified: Boolean(wireHash && workloadId) && anchorVerified,
79574
+ anchorVerified,
79575
+ checks,
79576
+ wireHash,
79577
+ workloadId,
79578
+ upstream: upstreamEv ? {
79579
+ provider: upstreamEv.provider ?? upstreamEv.upstream_name,
79580
+ result: upstreamEv.result,
79581
+ tcbStatus: upstreamEv.tcb_status
79582
+ } : void 0,
79583
+ anchor
79584
+ };
79585
+ }
79459
79586
  var DEFAULT_CONFIG_DIR = join$1(homedir(), ".t2000");
79460
79587
  function resolveConfigPath(configDir) {
79461
79588
  return join$1(configDir ?? DEFAULT_CONFIG_DIR, "config.json");
@@ -79728,7 +79855,8 @@ var T2000 = class _T2000 extends import_index2.default {
79728
79855
  async chat(params) {
79729
79856
  return chatCompletion(params);
79730
79857
  }
79731
- /** Streaming chat completion — async-iterate the assistant text deltas. */
79858
+ /** Streaming chat completion — async-iterate the assistant text deltas;
79859
+ * the generator returns `{ receiptId }` (confidential attestation) at the end. */
79732
79860
  chatStream(params) {
79733
79861
  return chatCompletionStream(params);
79734
79862
  }
@@ -79736,6 +79864,11 @@ var T2000 = class _T2000 extends import_index2.default {
79736
79864
  async models(opts) {
79737
79865
  return listModels(opts);
79738
79866
  }
79867
+ /** Verify a confidential response by receipt id — checks the signed receipt
79868
+ * + its trustless on-chain Sui anchor. Fails closed on any mismatch. */
79869
+ async verify(receiptId, opts) {
79870
+ return verifyReceipt(receiptId, opts);
79871
+ }
79739
79872
  // -- Swap --
79740
79873
  async swap(params) {
79741
79874
  this.limits.assert({
@@ -80455,7 +80588,10 @@ function registerChatTools(server) {
80455
80588
  text: JSON.stringify({
80456
80589
  model: res.model,
80457
80590
  content: res.content,
80458
- usage: res.usage
80591
+ usage: res.usage,
80592
+ // Confidential (phala/*) → a TEE attestation receipt id,
80593
+ // verifiable at /v1/aci/receipts/{id}.
80594
+ receiptId: res.receiptId
80459
80595
  })
80460
80596
  }
80461
80597
  ]
@@ -80478,6 +80614,23 @@ function registerChatTools(server) {
80478
80614
  }
80479
80615
  }
80480
80616
  );
80617
+ server.tool(
80618
+ "t2000_verify",
80619
+ "Verify a confidential response by its receipt id (the `receiptId` from a confidential t2000_chat). Checks the signed receipt + its trustless on-chain Sui anchor (reads the ReceiptAnchored event straight from a fullnode) and returns a per-check result that's `verified:false` on any forgery/mismatch. No key required.",
80620
+ {
80621
+ receiptId: external_exports.string().describe("A confidential receipt id (rcpt-\u2026)")
80622
+ },
80623
+ async ({ receiptId }) => {
80624
+ try {
80625
+ const result = await verifyReceipt(receiptId);
80626
+ return {
80627
+ content: [{ type: "text", text: JSON.stringify(result) }]
80628
+ };
80629
+ } catch (err) {
80630
+ return errorResult(err);
80631
+ }
80632
+ }
80633
+ );
80481
80634
  }
80482
80635
 
80483
80636
  // src/skills-prompts.ts
@@ -80551,7 +80704,7 @@ CRITICAL: When the user asks to use any external or paid API, names a provider (
80551
80704
  Spending is the user's own USDC and every t2000_pay call is bounded by maxPrice. For larger or multi-step spends, state the estimated cost first and proceed once the user is happy. Use t2000_balance to check funds. The v4 wallet is payments-only; savings / lending live on audric.ai.`;
80552
80705
 
80553
80706
  // src/index.ts
80554
- var PKG_VERSION = "5.15.1" ;
80707
+ var PKG_VERSION = "5.17.0" ;
80555
80708
  console.log = (...args) => console.error("[log]", ...args);
80556
80709
  console.warn = (...args) => console.error("[warn]", ...args);
80557
80710
  async function startMcpServer(opts) {