@agent-score/commerce 1.1.0 → 1.3.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/README.md +27 -12
- package/dist/{_response-RpEB7-vl.d.ts → _response-C2yFQoIA.d.ts} +1 -1
- package/dist/{_response-DS-LR590.d.mts → _response-DpB-cm2c.d.mts} +1 -1
- package/dist/agent_instructions-DiMSGkdm.d.mts +133 -0
- package/dist/agent_instructions-DiMSGkdm.d.ts +133 -0
- package/dist/challenge/index.d.mts +18 -116
- package/dist/challenge/index.d.ts +18 -116
- package/dist/challenge/index.js +41 -27
- package/dist/challenge/index.js.map +1 -1
- package/dist/challenge/index.mjs +40 -27
- package/dist/challenge/index.mjs.map +1 -1
- package/dist/core.js +1 -1
- package/dist/core.js.map +1 -1
- package/dist/core.mjs +1 -1
- package/dist/core.mjs.map +1 -1
- package/dist/discovery/index.d.mts +245 -2
- package/dist/discovery/index.d.ts +245 -2
- package/dist/discovery/index.js +276 -56
- package/dist/discovery/index.js.map +1 -1
- package/dist/discovery/index.mjs +269 -55
- package/dist/discovery/index.mjs.map +1 -1
- package/dist/identity/express.d.mts +2 -2
- package/dist/identity/express.d.ts +2 -2
- package/dist/identity/express.js +48 -25
- package/dist/identity/express.js.map +1 -1
- package/dist/identity/express.mjs +48 -25
- package/dist/identity/express.mjs.map +1 -1
- package/dist/identity/fastify.d.mts +2 -2
- package/dist/identity/fastify.d.ts +2 -2
- package/dist/identity/fastify.js +48 -25
- package/dist/identity/fastify.js.map +1 -1
- package/dist/identity/fastify.mjs +48 -25
- package/dist/identity/fastify.mjs.map +1 -1
- package/dist/identity/hono.d.mts +2 -2
- package/dist/identity/hono.d.ts +2 -2
- package/dist/identity/hono.js +48 -25
- package/dist/identity/hono.js.map +1 -1
- package/dist/identity/hono.mjs +48 -25
- package/dist/identity/hono.mjs.map +1 -1
- package/dist/identity/nextjs.d.mts +2 -2
- package/dist/identity/nextjs.d.ts +2 -2
- package/dist/identity/nextjs.js +48 -25
- package/dist/identity/nextjs.js.map +1 -1
- package/dist/identity/nextjs.mjs +48 -25
- package/dist/identity/nextjs.mjs.map +1 -1
- package/dist/identity/web.d.mts +2 -2
- package/dist/identity/web.d.ts +2 -2
- package/dist/identity/web.js +48 -25
- package/dist/identity/web.js.map +1 -1
- package/dist/identity/web.mjs +48 -25
- package/dist/identity/web.mjs.map +1 -1
- package/dist/index.d.mts +12 -12
- package/dist/index.d.ts +12 -12
- package/dist/index.js +47 -24
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +47 -24
- package/dist/index.mjs.map +1 -1
- package/dist/payment/index.d.mts +136 -49
- package/dist/payment/index.d.ts +136 -49
- package/dist/payment/index.js +161 -73
- package/dist/payment/index.js.map +1 -1
- package/dist/payment/index.mjs +160 -72
- package/dist/payment/index.mjs.map +1 -1
- package/dist/{signer-Cvdwn6Cs.d.mts → signer-kCAJUZwp.d.mts} +10 -12
- package/dist/{signer-Cvdwn6Cs.d.ts → signer-kCAJUZwp.d.ts} +10 -12
- package/dist/stripe-multichain/index.d.mts +2 -2
- package/dist/stripe-multichain/index.d.ts +2 -2
- package/dist/stripe-multichain/index.js.map +1 -1
- package/dist/stripe-multichain/index.mjs.map +1 -1
- package/package.json +13 -4
package/dist/discovery/index.js
CHANGED
|
@@ -27,7 +27,10 @@ __export(discovery_exports, {
|
|
|
27
27
|
applyNoindexHeader: () => applyNoindexHeader,
|
|
28
28
|
buildDiscoveryProbeResponse: () => buildDiscoveryProbeResponse,
|
|
29
29
|
buildLlmsTxt: () => buildLlmsTxt,
|
|
30
|
+
buildSkillMd: () => buildSkillMd,
|
|
30
31
|
buildWellKnownMpp: () => buildWellKnownMpp,
|
|
32
|
+
buildWellKnownX402: () => buildWellKnownX402,
|
|
33
|
+
compatibleClientsByRails: () => compatibleClientsByRails,
|
|
31
34
|
createBazaarDiscovery: () => createBazaarDiscovery,
|
|
32
35
|
defaultDiscoveryPaths: () => defaultDiscoveryPaths,
|
|
33
36
|
isDiscoveryPath: () => isDiscoveryPath,
|
|
@@ -38,7 +41,10 @@ __export(discovery_exports, {
|
|
|
38
41
|
noindexNonDiscoveryPathsExpress: () => noindexNonDiscoveryPathsExpress,
|
|
39
42
|
noindexNonDiscoveryPathsFastify: () => noindexNonDiscoveryPathsFastify,
|
|
40
43
|
sampleX402AcceptForNetwork: () => sampleX402AcceptForNetwork,
|
|
41
|
-
|
|
44
|
+
siwxSecurityScheme: () => siwxSecurityScheme,
|
|
45
|
+
wrapNoindexResponse: () => wrapNoindexResponse,
|
|
46
|
+
xGuidanceExtension: () => xGuidanceExtension,
|
|
47
|
+
xPaymentInfoExtension: () => xPaymentInfoExtension
|
|
42
48
|
});
|
|
43
49
|
module.exports = __toCommonJS(discovery_exports);
|
|
44
50
|
|
|
@@ -127,15 +133,15 @@ var rails = {
|
|
|
127
133
|
decimals: USDC.base.sepolia.decimals,
|
|
128
134
|
asset: USDC.base.sepolia.address
|
|
129
135
|
},
|
|
130
|
-
"
|
|
131
|
-
method: "
|
|
136
|
+
"mpp-solana-mainnet": {
|
|
137
|
+
method: "solana",
|
|
132
138
|
network: networks.solana.mainnet.caip2,
|
|
133
139
|
currency: USDC.solana.mainnet.mint,
|
|
134
140
|
decimals: USDC.solana.mainnet.decimals,
|
|
135
141
|
asset: USDC.solana.mainnet.mint
|
|
136
142
|
},
|
|
137
|
-
"
|
|
138
|
-
method: "
|
|
143
|
+
"mpp-solana-devnet": {
|
|
144
|
+
method: "solana",
|
|
139
145
|
network: networks.solana.devnet.caip2,
|
|
140
146
|
currency: USDC.solana.devnet.mint,
|
|
141
147
|
decimals: USDC.solana.devnet.decimals,
|
|
@@ -324,6 +330,14 @@ function buildWellKnownMpp(input) {
|
|
|
324
330
|
};
|
|
325
331
|
}
|
|
326
332
|
|
|
333
|
+
// src/discovery/well_known_x402.ts
|
|
334
|
+
function buildWellKnownX402(input) {
|
|
335
|
+
return {
|
|
336
|
+
version: 1,
|
|
337
|
+
resources: input.resources.map((r) => `${r.method.toUpperCase()} ${r.path}`)
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
|
|
327
341
|
// src/discovery/llms_txt.ts
|
|
328
342
|
function llmsTxtIdentitySection(input = {}) {
|
|
329
343
|
if (!input.agentscore) {
|
|
@@ -338,19 +352,13 @@ Compliance: ${[
|
|
|
338
352
|
compliance.allowed_jurisdictions?.length ? `${compliance.allowed_jurisdictions.join("/")} only` : null,
|
|
339
353
|
compliance.require_sanctions_clear ? "sanctions clear" : null
|
|
340
354
|
].filter(Boolean).join(", ")}.` : "";
|
|
341
|
-
return `##
|
|
342
|
-
|
|
343
|
-
AgentScore provides cross-merchant identity \u2014 one KYC works for every AgentScore-gated endpoint, no re-verification per site. Pick the right header based on how you plan to pay:
|
|
344
|
-
|
|
345
|
-
- **Wallet-auth** (preferred for agents with a stable crypto wallet): send \`X-Wallet-Address: 0x...\`. Only works on rails that carry a wallet signature \u2014 Tempo MPP and x402 EIP-3009. The wallet you claim MUST sign the payment; we verify that the payment signer resolves to the same operator as the claimed wallet. No TTL, no rotation.
|
|
346
|
-
- **Operator-token** (works for every rail): send \`X-Operator-Token: opc_...\`. Required when paying with Stripe SPT or card (those rails have no wallet signer). Reusable across every AgentScore merchant until the token expires.
|
|
347
|
-
- **Neither**: you'll get 403 with \`verify_url\` + \`poll_secret\` \u2014 complete the session flow once, then reuse the credential (or any wallet that pays under it) forever.
|
|
348
|
-
|
|
349
|
-
If you reach another AgentScore-gated endpoint in the future, the same credential and/or any linked wallet already works \u2014 skip the session flow.
|
|
355
|
+
return `## Identity
|
|
350
356
|
|
|
351
|
-
|
|
357
|
+
AgentScore identity is reusable across every AgentScore-gated merchant \u2014 one KYC, no re-verification per site. Pick a header:
|
|
352
358
|
|
|
353
|
-
|
|
359
|
+
- **\`X-Wallet-Address: 0x...\` or base58** \u2014 works on signing rails (Tempo, x402, Solana MPP). The wallet you claim must sign the payment.
|
|
360
|
+
- **\`X-Operator-Token: opc_...\`** \u2014 works on every rail, including Stripe SPT. Reusable across AgentScore merchants until expiry.
|
|
361
|
+
- **Neither** \u2014 you get a 403 with \`verify_url\`. Complete the session flow once and reuse the resulting \`opc_...\` everywhere.${complianceNote}`;
|
|
354
362
|
}
|
|
355
363
|
function llmsTxtPaymentSection(input) {
|
|
356
364
|
return input.verbose ? llmsTxtPaymentSectionVerbose(input) : llmsTxtPaymentSectionCompact(input);
|
|
@@ -370,8 +378,8 @@ function llmsTxtPaymentSectionCompact(input) {
|
|
|
370
378
|
if (hasRailFamily(rails2, "x402-base-")) {
|
|
371
379
|
lines.push("- **x402 USDC on Base** (EIP-3009) \u2014 `agentscore-pay pay POST " + input.appUrl + ` --chain base -H "X-Operator-Token: opc_..." -d '{...}'\``);
|
|
372
380
|
}
|
|
373
|
-
if (hasRailFamily(rails2, "
|
|
374
|
-
lines.push("- **
|
|
381
|
+
if (hasRailFamily(rails2, "mpp-solana-")) {
|
|
382
|
+
lines.push("- **USDC on Solana** \u2014 `agentscore-pay pay POST " + input.appUrl + ` --chain solana -H "X-Operator-Token: opc_..." -d '{...}'\``);
|
|
375
383
|
}
|
|
376
384
|
if (rails2.includes("stripe-spt")) {
|
|
377
385
|
lines.push("- **Stripe Shared Payment Token** \u2014 agent mints SPT (own Stripe account scoped to networkId, OR `link-cli spend-request create --credential-type shared_payment_token --network-id <profileId> ...`)");
|
|
@@ -387,72 +395,62 @@ function llmsTxtPaymentSectionVerbose(input) {
|
|
|
387
395
|
const tempoChain = input.tempoChainId ?? 4217;
|
|
388
396
|
const hasTempo = hasRailFamily(rails2, "tempo-");
|
|
389
397
|
const hasBase = hasRailFamily(rails2, "x402-base-");
|
|
390
|
-
const hasSolana = hasRailFamily(rails2, "
|
|
398
|
+
const hasSolana = hasRailFamily(rails2, "mpp-solana-");
|
|
391
399
|
const hasStripe = rails2.includes("stripe-spt");
|
|
392
400
|
const baseNetworkName = isTestnetRail(rails2, "x402-base-") ? "Base Sepolia" : "Base";
|
|
393
|
-
const solanaNetworkName = isTestnetRail(rails2, "
|
|
401
|
+
const solanaNetworkName = isTestnetRail(rails2, "mpp-solana-") ? "Solana devnet" : "Solana";
|
|
394
402
|
const lines = ["## Payment", ""];
|
|
395
|
-
lines.push("
|
|
403
|
+
lines.push("Accepted rails:");
|
|
396
404
|
lines.push("");
|
|
397
|
-
if (hasTempo) lines.push("- **
|
|
398
|
-
if (hasBase
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
}
|
|
402
|
-
if (hasStripe) lines.push("- **Stripe Shared Payment Token** (agent mints SPT on their Stripe account scoped to our networkId in the challenge, submits it in the credential)");
|
|
405
|
+
if (hasTempo) lines.push("- **USDC on Tempo**");
|
|
406
|
+
if (hasBase) lines.push(`- **USDC on ${baseNetworkName}**`);
|
|
407
|
+
if (hasSolana) lines.push(`- **USDC on ${solanaNetworkName}**`);
|
|
408
|
+
if (hasStripe) lines.push("- **Stripe Shared Payment Token**");
|
|
403
409
|
lines.push("");
|
|
404
410
|
if (hasTempo) {
|
|
405
|
-
lines.push("###
|
|
411
|
+
lines.push("### Pay with Tempo");
|
|
406
412
|
lines.push("");
|
|
407
|
-
lines.push("
|
|
408
|
-
lines.push("
|
|
409
|
-
lines.push(
|
|
410
|
-
lines.push(
|
|
411
|
-
lines.push("");
|
|
412
|
-
lines.push("Then use `tempo request` to make the paid purchase:");
|
|
413
|
+
lines.push("```bash");
|
|
414
|
+
lines.push("curl -fsSL https://tempo.xyz/install | bash");
|
|
415
|
+
lines.push("tempo wallet login");
|
|
416
|
+
lines.push(`tempo wallet whoami # need USDC.e on ${tempoNetwork} (chain ${tempoChain})`);
|
|
417
|
+
lines.push("tempo wallet fund # if zero");
|
|
413
418
|
lines.push("");
|
|
414
419
|
lines.push("tempo request -X POST \\");
|
|
415
|
-
lines.push(' -H "X-Operator-Token:
|
|
416
|
-
lines.push(' -H "Content-Type: application/json" \\');
|
|
420
|
+
lines.push(' -H "X-Operator-Token: opc_..." \\');
|
|
417
421
|
lines.push(" --json '{...}' \\");
|
|
418
422
|
lines.push(" --max-spend N \\");
|
|
419
423
|
lines.push(` ${input.appUrl}`);
|
|
420
|
-
lines.push("");
|
|
421
|
-
lines.push(`\`tempo request\` handles the full MPP handshake: sends the POST, receives the 402 challenge, signs the payment on ${tempoNetwork}, submits the credential, and returns the completed order.`);
|
|
424
|
+
lines.push("```");
|
|
422
425
|
lines.push("");
|
|
423
426
|
}
|
|
424
427
|
if (hasBase || hasSolana) {
|
|
425
428
|
const chainsLabel = [hasBase && baseNetworkName, hasSolana && solanaNetworkName].filter(Boolean).join(" or ");
|
|
426
429
|
const flags = [hasBase && "`--chain base`", hasSolana && "`--chain solana`"].filter(Boolean).join(" or ");
|
|
427
|
-
lines.push(`###
|
|
430
|
+
lines.push(`### Pay with ${chainsLabel}`);
|
|
428
431
|
lines.push("");
|
|
429
|
-
lines.push("
|
|
430
|
-
lines.push(
|
|
431
|
-
lines.push(`
|
|
432
|
-
lines.push(`
|
|
433
|
-
lines.push("");
|
|
434
|
-
lines.push("Then submit the paid purchase:");
|
|
432
|
+
lines.push("```bash");
|
|
433
|
+
lines.push("npm install -g @agent-score/pay");
|
|
434
|
+
lines.push(`agentscore-pay wallet create ${flags}`);
|
|
435
|
+
lines.push(`agentscore-pay balance ${flags} # fund the printed address with USDC`);
|
|
435
436
|
lines.push("");
|
|
436
437
|
lines.push(`agentscore-pay pay POST ${input.appUrl} \\`);
|
|
437
438
|
lines.push(` ${hasBase ? "--chain base" : "--chain solana"} \\`);
|
|
438
|
-
lines.push(' -H "X-Operator-Token:
|
|
439
|
-
lines.push(' -H "Content-Type: application/json" \\');
|
|
439
|
+
lines.push(' -H "X-Operator-Token: opc_..." \\');
|
|
440
440
|
lines.push(" -d '{...}' \\");
|
|
441
441
|
lines.push(" --max-spend N");
|
|
442
|
-
lines.push("");
|
|
443
|
-
const handshakeChains = [hasBase && "EIP-3009 (Base)", hasSolana && "SPL Token (Solana)"].filter(Boolean).join(" or ");
|
|
444
|
-
lines.push(`The CLI handles the full x402 handshake: hits the URL, parses the 402 challenge, signs the ${handshakeChains} transaction, submits via X-Payment header, and returns the completed order.`);
|
|
442
|
+
lines.push("```");
|
|
445
443
|
lines.push("");
|
|
446
444
|
}
|
|
447
445
|
if (hasStripe) {
|
|
448
|
-
lines.push("###
|
|
446
|
+
lines.push("### Pay with Stripe SPT");
|
|
449
447
|
lines.push("");
|
|
450
|
-
lines.push("Mint a SharedPaymentToken scoped to the profile_id
|
|
448
|
+
lines.push("Mint a SharedPaymentToken scoped to the `profile_id` from the 402 body, then submit via `Authorization: Payment` with `method=stripe/charge`. Either your own Stripe account or `link-cli spend-request create --credential-type shared_payment_token --network-id <profileId> ...` for Stripe Link wallets.");
|
|
451
449
|
lines.push("");
|
|
452
450
|
}
|
|
453
|
-
lines.push("IMPORTANT:
|
|
451
|
+
lines.push("IMPORTANT: Use the CLIs above. Raw on-chain transfers (e.g. `tempo wallet transfer`, sending USDC manually to deposit addresses) bypass the protocol handshake and the order will not complete.");
|
|
454
452
|
if (hasBase || hasSolana) {
|
|
455
|
-
lines.push("IMPORTANT:
|
|
453
|
+
lines.push("IMPORTANT: Pay the exact amount in the 402 challenge. Overpayments and underpayments cannot be matched.");
|
|
456
454
|
}
|
|
457
455
|
lines.push("");
|
|
458
456
|
return lines.join("\n");
|
|
@@ -493,7 +491,16 @@ function agentscoreSecuritySchemes() {
|
|
|
493
491
|
in: "header",
|
|
494
492
|
name: "X-Wallet-Address",
|
|
495
493
|
description: "Wallet-path identity (0x... or base58). Only works on rails that carry a wallet signature (Tempo MPP, x402 EIP-3009, x402 SPL Token). The wallet you claim MUST sign the payment."
|
|
496
|
-
}
|
|
494
|
+
},
|
|
495
|
+
siwx: siwxSecurityScheme()
|
|
496
|
+
};
|
|
497
|
+
}
|
|
498
|
+
function siwxSecurityScheme() {
|
|
499
|
+
return {
|
|
500
|
+
type: "http",
|
|
501
|
+
scheme: "bearer",
|
|
502
|
+
bearerFormat: "SIWX",
|
|
503
|
+
description: "Sign-In With X wallet authentication. Agent signs a challenge with their wallet (any supported chain) and presents the proof in the Authorization header. Used for identity-gated free endpoints; payment-required endpoints declare x-payment-info instead."
|
|
497
504
|
};
|
|
498
505
|
}
|
|
499
506
|
function agentscoreDenialSchemas() {
|
|
@@ -566,6 +573,12 @@ function agentscorePaymentRequiredSchema() {
|
|
|
566
573
|
}
|
|
567
574
|
};
|
|
568
575
|
}
|
|
576
|
+
function xPaymentInfoExtension(input) {
|
|
577
|
+
return { "x-payment-info": { price: input.price, protocols: input.protocols } };
|
|
578
|
+
}
|
|
579
|
+
function xGuidanceExtension(text) {
|
|
580
|
+
return { "x-guidance": text };
|
|
581
|
+
}
|
|
569
582
|
function agentscoreOpenApiSnippets(opts = {}) {
|
|
570
583
|
const out = {};
|
|
571
584
|
if (opts.security !== false) {
|
|
@@ -584,7 +597,10 @@ function agentscoreOpenApiSnippets(opts = {}) {
|
|
|
584
597
|
var defaultDiscoveryPaths = /* @__PURE__ */ new Set([
|
|
585
598
|
"/openapi.json",
|
|
586
599
|
"/llms.txt",
|
|
600
|
+
"/skill.md",
|
|
601
|
+
"/SKILL.md",
|
|
587
602
|
"/.well-known/mpp.json",
|
|
603
|
+
"/.well-known/x402",
|
|
588
604
|
"/.well-known/agent-card.json",
|
|
589
605
|
"/.well-known/ucp",
|
|
590
606
|
"/favicon.png",
|
|
@@ -650,6 +666,204 @@ function wrapNoindexResponse(path, response, options) {
|
|
|
650
666
|
});
|
|
651
667
|
}
|
|
652
668
|
var applyNoindexHeader = wrapNoindexResponse;
|
|
669
|
+
|
|
670
|
+
// src/challenge/agent_instructions.ts
|
|
671
|
+
var RAIL_CLIENTS = {
|
|
672
|
+
tempo_mpp: ["agentscore-pay", "tempo request", "x402-proxy"],
|
|
673
|
+
x402_base: ["agentscore-pay", "x402-proxy", "purl (omit --network flag)"],
|
|
674
|
+
solana_mpp: ["agentscore-pay"],
|
|
675
|
+
stripe: ["link-cli"]
|
|
676
|
+
};
|
|
677
|
+
function compatibleClientsByRails(rails2) {
|
|
678
|
+
const out = {};
|
|
679
|
+
for (const r of rails2) out[r] = [...RAIL_CLIENTS[r]];
|
|
680
|
+
return Object.keys(out).length === 0 ? void 0 : out;
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
// src/discovery/skill_md.ts
|
|
684
|
+
var RAIL_LABELS = {
|
|
685
|
+
tempo_mpp: "MPP on Tempo",
|
|
686
|
+
x402_base: "x402 on Base",
|
|
687
|
+
solana_mpp: "MPP on Solana",
|
|
688
|
+
stripe: "Stripe Shared Payment Token"
|
|
689
|
+
};
|
|
690
|
+
var RAIL_NOTES = {
|
|
691
|
+
tempo_mpp: "USDC. Use `agentscore-pay --chain tempo` (or `tempo request`); MPP credential goes in `Authorization: Payment`.",
|
|
692
|
+
x402_base: "USDC (EIP-3009). Use `agentscore-pay`; X-Payment header carries the signed credential.",
|
|
693
|
+
solana_mpp: "USDC (SPL). Use `agentscore-pay --chain solana`; MPP credential goes in `Authorization: Payment`.",
|
|
694
|
+
stripe: "Card via Link wallet. Use `@stripe/link-cli` \u2014 `agentscore-pay` emits the handoff hint when this rail is picked."
|
|
695
|
+
};
|
|
696
|
+
var NAME_RE = /^[a-z0-9]+(-[a-z0-9]+)*$/;
|
|
697
|
+
var NAME_MAX = 64;
|
|
698
|
+
var DESCRIPTION_MAX = 1024;
|
|
699
|
+
var COMPATIBILITY_MAX = 500;
|
|
700
|
+
function validateInput(input) {
|
|
701
|
+
if (!input.name || input.name.length === 0 || input.name.length > NAME_MAX) {
|
|
702
|
+
throw new Error(`buildSkillMd: name must be 1-${NAME_MAX} characters (got ${input.name?.length ?? 0})`);
|
|
703
|
+
}
|
|
704
|
+
if (!NAME_RE.test(input.name)) {
|
|
705
|
+
throw new Error(
|
|
706
|
+
`buildSkillMd: name "${input.name}" is invalid \u2014 must be lowercase alphanumeric and hyphens, no leading/trailing/consecutive hyphens (agentskills.io spec)`
|
|
707
|
+
);
|
|
708
|
+
}
|
|
709
|
+
if (!input.description || input.description.length === 0) {
|
|
710
|
+
throw new Error("buildSkillMd: description is required and must be non-empty (agentskills.io spec)");
|
|
711
|
+
}
|
|
712
|
+
if (input.description.length > DESCRIPTION_MAX) {
|
|
713
|
+
throw new Error(
|
|
714
|
+
`buildSkillMd: description must be \u2264${DESCRIPTION_MAX} characters (got ${input.description.length})`
|
|
715
|
+
);
|
|
716
|
+
}
|
|
717
|
+
if (input.compatibility && input.compatibility.length > COMPATIBILITY_MAX) {
|
|
718
|
+
throw new Error(
|
|
719
|
+
`buildSkillMd: compatibility must be \u2264${COMPATIBILITY_MAX} characters (got ${input.compatibility.length})`
|
|
720
|
+
);
|
|
721
|
+
}
|
|
722
|
+
}
|
|
723
|
+
function quoteYaml(value) {
|
|
724
|
+
return `"${value.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\n/g, "\\n")}"`;
|
|
725
|
+
}
|
|
726
|
+
function tableCell(value) {
|
|
727
|
+
return value.replace(/\\/g, "\\\\").replace(/\|/g, "\\|");
|
|
728
|
+
}
|
|
729
|
+
function frontmatter(input) {
|
|
730
|
+
const lines = ["---"];
|
|
731
|
+
lines.push(`name: ${input.name}`);
|
|
732
|
+
lines.push(`description: ${quoteYaml(input.description)}`);
|
|
733
|
+
if (input.license) lines.push(`license: ${quoteYaml(input.license)}`);
|
|
734
|
+
if (input.compatibility) lines.push(`compatibility: ${quoteYaml(input.compatibility)}`);
|
|
735
|
+
if (input.allowedTools) lines.push(`allowed-tools: ${quoteYaml(input.allowedTools)}`);
|
|
736
|
+
const meta = [];
|
|
737
|
+
meta.push(["version", String(input.version ?? "1")]);
|
|
738
|
+
meta.push(["homepage", input.homepage]);
|
|
739
|
+
for (const [k, v] of Object.entries(input.metadata ?? {})) {
|
|
740
|
+
if (k === "version" || k === "homepage") continue;
|
|
741
|
+
meta.push([k, String(v)]);
|
|
742
|
+
}
|
|
743
|
+
lines.push("metadata:");
|
|
744
|
+
for (const [k, v] of meta) {
|
|
745
|
+
lines.push(` ${k}: ${quoteYaml(v)}`);
|
|
746
|
+
}
|
|
747
|
+
lines.push("---");
|
|
748
|
+
return lines.join("\n");
|
|
749
|
+
}
|
|
750
|
+
function importantFiles(input) {
|
|
751
|
+
const skillUrl = `${input.homepage.replace(/\/$/, "")}/skill.md`;
|
|
752
|
+
const rows = [
|
|
753
|
+
"| File | URL |",
|
|
754
|
+
"|------|-----|",
|
|
755
|
+
`| **SKILL.md** (this file) | \`${skillUrl}\` |`
|
|
756
|
+
];
|
|
757
|
+
for (const f of input.files ?? []) {
|
|
758
|
+
rows.push(`| ${tableCell(f.label)} | \`${tableCell(f.url)}\` |`);
|
|
759
|
+
}
|
|
760
|
+
return ["## Important Files", "", ...rows].join("\n");
|
|
761
|
+
}
|
|
762
|
+
function paymentSection(input) {
|
|
763
|
+
const override = input.compatibleClients;
|
|
764
|
+
const defaults = compatibleClientsByRails(input.acceptedRails) ?? {};
|
|
765
|
+
const clients = {};
|
|
766
|
+
for (const r of input.acceptedRails) {
|
|
767
|
+
clients[r] = override?.[r] ?? defaults[r] ?? [];
|
|
768
|
+
}
|
|
769
|
+
const rows = ["| Rail | Notes | Compatible clients |", "|---|---|---|"];
|
|
770
|
+
for (const r of input.acceptedRails) {
|
|
771
|
+
const list = (clients[r] ?? []).join(", ") || "\u2014";
|
|
772
|
+
rows.push(`| **${RAIL_LABELS[r]}** | ${RAIL_NOTES[r]} | ${list} |`);
|
|
773
|
+
}
|
|
774
|
+
return [
|
|
775
|
+
"## Payment",
|
|
776
|
+
"",
|
|
777
|
+
"Each gated route returns a 402 with `WWW-Authenticate` + `PAYMENT-REQUIRED` body listing the rails below with current pricing. Pick whichever your wallet is funded for.",
|
|
778
|
+
"",
|
|
779
|
+
...rows
|
|
780
|
+
].join("\n");
|
|
781
|
+
}
|
|
782
|
+
function identitySection(input) {
|
|
783
|
+
const id = input.identity;
|
|
784
|
+
if (!id) return "";
|
|
785
|
+
const reqs = [];
|
|
786
|
+
if (id.kycRequired) reqs.push("KYC verified Passport");
|
|
787
|
+
if (id.minAge) reqs.push(`age ${id.minAge}+`);
|
|
788
|
+
if (id.allowedJurisdictions?.length) reqs.push(`${id.allowedJurisdictions.join("/")} only`);
|
|
789
|
+
if (id.sanctionsClear) reqs.push("sanctions clear");
|
|
790
|
+
if (reqs.length === 0) return "";
|
|
791
|
+
const bootstrap = input.identityBootstrapUrl ? `
|
|
792
|
+
|
|
793
|
+
If you don't have a Passport, fetch \`${input.identityBootstrapUrl}\` and follow the onboarding there first. Bring back the \`opc_...\` operator token in \`X-Operator-Token\` on every gated request.` : "";
|
|
794
|
+
return [
|
|
795
|
+
"## Identity Prerequisite",
|
|
796
|
+
"",
|
|
797
|
+
`This merchant uses AgentScore identity. Required: ${reqs.join(", ")}.${bootstrap}`,
|
|
798
|
+
"",
|
|
799
|
+
"Denial bodies carry an `agent_instructions` block describing the recovery action \u2014 read the `action` field and follow it. See the identity-bootstrap skill for the canonical denial-code \u2192 action table."
|
|
800
|
+
].join("\n");
|
|
801
|
+
}
|
|
802
|
+
function shippingSection(input) {
|
|
803
|
+
const s = input.shipping;
|
|
804
|
+
if (!s || !s.allowedCountries?.length && !s.blockedStates?.length) return "";
|
|
805
|
+
const lines = ["## Shipping", ""];
|
|
806
|
+
if (s.allowedCountries?.length) {
|
|
807
|
+
lines.push(`Ships to: ${s.allowedCountries.join(", ")}.`);
|
|
808
|
+
}
|
|
809
|
+
if (s.blockedStates?.length) {
|
|
810
|
+
if (lines.length > 2) lines.push("");
|
|
811
|
+
lines.push(`Blocked US states: ${s.blockedStates.join(", ")}.`);
|
|
812
|
+
}
|
|
813
|
+
return lines.join("\n");
|
|
814
|
+
}
|
|
815
|
+
function endpointsSection(input) {
|
|
816
|
+
if (input.endpoints.length === 0) return "";
|
|
817
|
+
const rows = ["| Method | Path | Auth | Purpose |", "|---|---|---|---|"];
|
|
818
|
+
for (const e of input.endpoints) {
|
|
819
|
+
rows.push(
|
|
820
|
+
`| ${e.method} | \`${tableCell(e.path)}\` | ${e.authRequired ? "identity required" : "anonymous"} | ${tableCell(e.description)} |`
|
|
821
|
+
);
|
|
822
|
+
}
|
|
823
|
+
return ["## Endpoints", "", ...rows].join("\n");
|
|
824
|
+
}
|
|
825
|
+
function onboardingSection(input) {
|
|
826
|
+
if (!input.onboardingSteps?.length) return "";
|
|
827
|
+
const rows = input.onboardingSteps.map((step, i) => `${i + 1}. ${step}`);
|
|
828
|
+
return ["## Onboarding Flow", "", ...rows].join("\n");
|
|
829
|
+
}
|
|
830
|
+
function triggersSection(input) {
|
|
831
|
+
if (input.triggers.length === 0) return "";
|
|
832
|
+
const rows = input.triggers.map((t) => `- ${t}`);
|
|
833
|
+
return ["## Triggers", "", "Use this skill when the user wants to:", "", ...rows].join("\n");
|
|
834
|
+
}
|
|
835
|
+
function supportSection(input) {
|
|
836
|
+
if (!input.supportLinks?.length) return "";
|
|
837
|
+
const rows = input.supportLinks.map((l) => `- **${l.label}**: ${l.url}`);
|
|
838
|
+
return ["## Support", "", ...rows].join("\n");
|
|
839
|
+
}
|
|
840
|
+
function refreshFooter(input) {
|
|
841
|
+
if (input.refreshFooter === false) return "";
|
|
842
|
+
return "_Re-fetch this file periodically to pick up new endpoints, rails, or policies._";
|
|
843
|
+
}
|
|
844
|
+
function titleBlock(input) {
|
|
845
|
+
const parts = [`# ${input.merchantName}`];
|
|
846
|
+
if (input.tagline) parts.push(`_${input.tagline}_`);
|
|
847
|
+
if (input.intro) parts.push(input.intro);
|
|
848
|
+
return parts.join("\n\n");
|
|
849
|
+
}
|
|
850
|
+
function buildSkillMd(input) {
|
|
851
|
+
validateInput(input);
|
|
852
|
+
const sections = [
|
|
853
|
+
frontmatter(input),
|
|
854
|
+
titleBlock(input),
|
|
855
|
+
importantFiles(input),
|
|
856
|
+
identitySection(input),
|
|
857
|
+
paymentSection(input),
|
|
858
|
+
shippingSection(input),
|
|
859
|
+
onboardingSection(input),
|
|
860
|
+
endpointsSection(input),
|
|
861
|
+
triggersSection(input),
|
|
862
|
+
supportSection(input),
|
|
863
|
+
refreshFooter(input)
|
|
864
|
+
].filter((s) => s !== "");
|
|
865
|
+
return sections.join("\n\n").replace(/\n{3,}/g, "\n\n").trim() + "\n";
|
|
866
|
+
}
|
|
653
867
|
// Annotate the CommonJS export names for ESM import in node:
|
|
654
868
|
0 && (module.exports = {
|
|
655
869
|
agentscoreDenialSchemas,
|
|
@@ -659,7 +873,10 @@ var applyNoindexHeader = wrapNoindexResponse;
|
|
|
659
873
|
applyNoindexHeader,
|
|
660
874
|
buildDiscoveryProbeResponse,
|
|
661
875
|
buildLlmsTxt,
|
|
876
|
+
buildSkillMd,
|
|
662
877
|
buildWellKnownMpp,
|
|
878
|
+
buildWellKnownX402,
|
|
879
|
+
compatibleClientsByRails,
|
|
663
880
|
createBazaarDiscovery,
|
|
664
881
|
defaultDiscoveryPaths,
|
|
665
882
|
isDiscoveryPath,
|
|
@@ -670,6 +887,9 @@ var applyNoindexHeader = wrapNoindexResponse;
|
|
|
670
887
|
noindexNonDiscoveryPathsExpress,
|
|
671
888
|
noindexNonDiscoveryPathsFastify,
|
|
672
889
|
sampleX402AcceptForNetwork,
|
|
673
|
-
|
|
890
|
+
siwxSecurityScheme,
|
|
891
|
+
wrapNoindexResponse,
|
|
892
|
+
xGuidanceExtension,
|
|
893
|
+
xPaymentInfoExtension
|
|
674
894
|
});
|
|
675
895
|
//# sourceMappingURL=index.js.map
|