@t2000/mcp 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/bin.js +143 -3
- package/dist/bin.js.map +1 -1
- package/dist/index.js +143 -3
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
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:
|
|
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
|
|
78821
|
+
return new SuiGrpcClient3({ baseUrl, network });
|
|
78822
78822
|
}
|
|
78823
78823
|
function atomicToHuman(raw, decimals) {
|
|
78824
78824
|
return Number(raw) / 10 ** decimals;
|
|
@@ -79465,6 +79465,124 @@ async function listModels(opts) {
|
|
|
79465
79465
|
privacy: m.privacy ?? m.privacy_tier
|
|
79466
79466
|
}));
|
|
79467
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
|
+
}
|
|
79468
79586
|
var DEFAULT_CONFIG_DIR = join$1(homedir(), ".t2000");
|
|
79469
79587
|
function resolveConfigPath(configDir) {
|
|
79470
79588
|
return join$1(configDir ?? DEFAULT_CONFIG_DIR, "config.json");
|
|
@@ -79746,6 +79864,11 @@ var T2000 = class _T2000 extends import_index2.default {
|
|
|
79746
79864
|
async models(opts) {
|
|
79747
79865
|
return listModels(opts);
|
|
79748
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
|
+
}
|
|
79749
79872
|
// -- Swap --
|
|
79750
79873
|
async swap(params) {
|
|
79751
79874
|
this.limits.assert({
|
|
@@ -80491,6 +80614,23 @@ function registerChatTools(server) {
|
|
|
80491
80614
|
}
|
|
80492
80615
|
}
|
|
80493
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
|
+
);
|
|
80494
80634
|
}
|
|
80495
80635
|
|
|
80496
80636
|
// src/skills-prompts.ts
|
|
@@ -80564,7 +80704,7 @@ CRITICAL: When the user asks to use any external or paid API, names a provider (
|
|
|
80564
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.`;
|
|
80565
80705
|
|
|
80566
80706
|
// src/index.ts
|
|
80567
|
-
var PKG_VERSION = "5.
|
|
80707
|
+
var PKG_VERSION = "5.17.0" ;
|
|
80568
80708
|
console.log = (...args) => console.error("[log]", ...args);
|
|
80569
80709
|
console.warn = (...args) => console.error("[warn]", ...args);
|
|
80570
80710
|
async function startMcpServer(opts) {
|