From 9677c9b24439cb87e011dd5501ac7f49aa855dd4 Mon Sep 17 00:00:00 2001 From: Greg Soucy Date: Thu, 23 Apr 2026 19:58:05 -0400 Subject: [PATCH] Combine SDK index and template test fixes --- typescript-sdk/scripts/template-tests.mjs | 26 +++++++++++++++++------ typescript-sdk/src/index.ts | 15 +++++++++---- 2 files changed, 30 insertions(+), 11 deletions(-) diff --git a/typescript-sdk/scripts/template-tests.mjs b/typescript-sdk/scripts/template-tests.mjs index dc49d5d..927b8b2 100644 --- a/typescript-sdk/scripts/template-tests.mjs +++ b/typescript-sdk/scripts/template-tests.mjs @@ -1,14 +1,26 @@ +import { readdirSync } from "node:fs"; +import path from "node:path"; import { spawnSync } from "node:child_process"; -const suites = [ - "runtime/tests/*.test.mjs", - "typescript-sdk/tests/*.test.mjs" -]; +const rootDir = new URL("../..", import.meta.url); -for (const pattern of suites) { - const run = spawnSync("node", ["--test", pattern], { +const suites = ["runtime/tests", "typescript-sdk/tests"]; + +function getTestFiles(relativeDir) { + const absoluteDir = new URL(relativeDir, rootDir); + return readdirSync(absoluteDir) + .filter((file) => file.endsWith(".test.mjs")) + .map((file) => path.posix.join(relativeDir, file)); +} + +for (const suite of suites) { + const files = getTestFiles(suite); + if (files.length === 0) { + continue; + } + const run = spawnSync("node", ["--test", ...files], { stdio: "inherit", - cwd: new URL("../..", import.meta.url) + cwd: rootDir }); if (run.status !== 0) { process.exit(run.status ?? 1); diff --git a/typescript-sdk/src/index.ts b/typescript-sdk/src/index.ts index ec80d4e..b2f1b4b 100644 --- a/typescript-sdk/src/index.ts +++ b/typescript-sdk/src/index.ts @@ -45,6 +45,7 @@ export type ReceiptMetadata = { export type CanonicalReceipt = { status: "success" | "error" | string; + verb?: string; /** * Legacy / commercial-only metadata. * Commons v1.1.0 receipts should not rely on or emit this block. @@ -76,12 +77,17 @@ export type RuntimeMetadata = { [k: string]: unknown; }; +export type ReceiptProtocolMetadata = { + verb: string; + version: string; +}; + export type CommandResponse = { - receipt: CanonicalReceipt; + receipt: CanonicalReceipt; runtime_metadata?: RuntimeMetadata; }; -export type LegacyBlendedReceipt = CanonicalReceipt & { +export type LegacyBlendedReceipt = CanonicalReceipt & { trace?: RuntimeMetadata; }; @@ -295,7 +301,7 @@ function extractReceipt(subject: CanonicalReceipt | CommandResponse | LegacyBlen export function extractReceiptVerb(subject: CanonicalReceipt | CommandResponse | LegacyBlendedReceipt): string | null { const receipt = extractReceipt(subject); - return isRecord(receipt.x402) && typeof receipt.x402.verb === "string" ? receipt.x402.verb : null; + return getReceiptVerb(receipt) ?? "summarize"; } export function normalizeCommandResponse(payload: unknown): CommandResponse { @@ -349,6 +355,7 @@ export async function verifyReceipt(receiptLike: CanonicalReceipt | CommandRespo const { hash_sha256: recomputedHash } = recomputeReceiptHashSha256(receipt); const hashMatches = claimedHash === recomputedHash; const receiptId = typeof receipt.metadata?.receipt_id === "string" ? receipt.metadata.receipt_id : null; + const receiptIdPresent = !!receiptId; const receiptIdMatches = !receiptId || !claimedHash ? true : receiptId === claimedHash; let pubkey: Uint8Array | null = null; @@ -396,7 +403,7 @@ export async function verifyReceipt(receiptLike: CanonicalReceipt | CommandRespo }, values: { verb: getReceiptVerb(receipt), - signer_id, + signer_id: signerId, alg, canonical, claimed_hash: claimedHash,