fix(x402 docs): Adding common LLM discovery documentation

This commit is contained in:
Chris Troutner
2026-04-01 08:36:47 -07:00
parent 3950560989
commit 5d77880a0e
12 changed files with 695 additions and 0 deletions
@@ -0,0 +1,106 @@
/*
Unit tests for DiscoveryController.
*/
import { assert } from 'chai'
import DiscoveryController from '../../../src/controllers/discovery/controller.js'
import { createMockRequest, createMockResponse } from '../mocks/controller-mocks.js'
describe('#discovery-controller.js', () => {
const makeController = ({ enabled = true } = {}) => {
return new DiscoveryController({
apiPrefix: '/v6',
getX402Settings: () => ({
enabled,
facilitatorUrl: 'http://localhost:4345/facilitator',
serverAddress: 'bitcoincash:qtestaddress',
priceSat: 200
}),
getDiscoveryDocuments: () => ({
openapi: { openapi: '3.0.3', paths: { '/v6/price/bchusd': {} } },
swagger: { swagger: '2.0', paths: { '/v6/price/bchusd': {} } },
llms: '# psf-bch-api',
agent: { awp_version: '0.1', actions: [] }
})
})
}
describe('x402 disabled gating', () => {
it('should return 404 for all discovery endpoints when x402 disabled', async () => {
const uut = makeController({ enabled: false })
const req = createMockRequest()
const handlers = [
uut.x402Manifest,
uut.openapi,
uut.swagger,
uut.llmsTxt,
uut.agentManifest
]
for (const handler of handlers) {
const res = createMockResponse()
await handler(req, res)
assert.equal(res.statusValue, 404)
assert.deepEqual(res.jsonData, { error: 'Not found' })
}
})
})
describe('x402 enabled responses', () => {
it('should return x402 manifest schema fields', async () => {
const uut = makeController({ enabled: true })
const req = createMockRequest()
const res = createMockResponse()
await uut.x402Manifest(req, res)
assert.equal(res.statusValue, 200)
assert.equal(res.jsonData.x402Version, 2)
assert.isArray(res.jsonData.resources)
assert.equal(res.jsonData.resources[0].accepts[0].scheme, 'utxo')
assert.equal(res.jsonData.resources[0].accepts[0].amount, '200')
})
it('should return openapi and swagger docs', async () => {
const uut = makeController({ enabled: true })
const req = createMockRequest()
const openapiRes = createMockResponse()
await uut.openapi(req, openapiRes)
assert.equal(openapiRes.statusValue, 200)
assert.equal(openapiRes.jsonData.openapi, '3.0.3')
const swaggerRes = createMockResponse()
await uut.swagger(req, swaggerRes)
assert.equal(swaggerRes.statusValue, 200)
assert.equal(swaggerRes.jsonData.swagger, '2.0')
})
it('should return llms.txt as text/plain', async () => {
const uut = makeController({ enabled: true })
const req = createMockRequest()
const res = createMockResponse()
await uut.llmsTxt(req, res)
assert.equal(res.statusValue, 200)
assert.equal(res.headers['Content-Type'], 'text/plain; charset=utf-8')
assert.equal(res.writeData[0], '# psf-bch-api')
assert.isTrue(res.endCalled)
})
it('should return agent manifest json', async () => {
const uut = makeController({ enabled: true })
const req = createMockRequest()
const res = createMockResponse()
await uut.agentManifest(req, res)
assert.equal(res.statusValue, 200)
assert.equal(res.jsonData.awp_version, '0.1')
assert.isArray(res.jsonData.actions)
})
})
})
@@ -0,0 +1,25 @@
/*
Unit tests for discovery document builder.
*/
import { assert } from 'chai'
import { buildDiscoveryDocuments } from '../../../src/discovery/build-documents.js'
describe('#discovery-build-documents.js', () => {
it('should build openapi and swagger documents with v6 paths', () => {
const docs = buildDiscoveryDocuments()
assert.property(docs, 'openapi')
assert.property(docs, 'swagger')
assert.property(docs, 'llms')
assert.property(docs, 'agent')
assert.isString(docs.openapi.openapi)
assert.equal(docs.swagger.swagger, '2.0')
assert.isAbove(Object.keys(docs.openapi.paths).length, 0)
const hasV6Path = Object.keys(docs.openapi.paths).some(path => path.startsWith('/v6/'))
assert.isTrue(hasV6Path)
})
})
@@ -0,0 +1,43 @@
/*
Unit tests for DiscoveryRouter.
*/
import { assert } from 'chai'
import DiscoveryRouter from '../../../src/controllers/discovery/router.js'
describe('#discovery-router.js', () => {
it('should require app object in attach()', () => {
const uut = new DiscoveryRouter()
assert.throws(() => uut.attach(), /Must pass app object/)
})
it('should register all discovery routes', () => {
const calls = []
const app = {
use: () => {}
}
const mockRouter = {
get: (path, handler) => calls.push({ path, handler })
}
const mockController = {
x402Manifest: () => {},
openapi: () => {},
swagger: () => {},
llmsTxt: () => {},
agentManifest: () => {}
}
const uut = new DiscoveryRouter({ controller: mockController })
uut.router = mockRouter
uut.attach(app)
assert.equal(calls.length, 5)
assert.deepEqual(
calls.map(x => x.path),
['/.well-known/x402', '/openapi.json', '/swagger.json', '/llms.txt', '/.well-known/agent.json']
)
})
})