From dcd61de619e3e097a7002eb7a19ebd3968278af0 Mon Sep 17 00:00:00 2001 From: Florian Berger Date: Fri, 25 Sep 2026 07:55:01 +0200 Subject: [PATCH] well-known: add /.well-known/ard.json (ARD v0.91 canonical path) --- dist/well-known.js | 57 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 51 insertions(+), 6 deletions(-) diff --git a/dist/well-known.js b/dist/well-known.js index 224e38e..b13759b 100644 --- a/dist/well-known.js +++ b/dist/well-known.js @@ -48,6 +48,22 @@ function parseResponse(url, parser) { }); } +// Summarises the `entries` array of an Agentic Resource Discovery (ARD) manifest. +// Shared by the /.well-known/ai-catalog.json and /.well-known/ard.json entries below. +function summarizeArdEntries(data) { + const summary = { + entries_count: 0, + entry_types: [] + }; + if (data && Array.isArray(data.entries)) { + summary.entries_count = data.entries.length; + summary.entry_types = [...new Set(data.entries + .map(e => e && typeof e.type === 'string' ? e.type : null) + .filter(Boolean))].slice(0, 20); + } + return summary; +} + function parseResponseWithRedirects(url, parser) { return fetchWithTimeout(url) .then(request => { @@ -307,12 +323,41 @@ return Promise.all([ const data = JSON.parse(text); result.spec_version = typeof data.specVersion === 'string' ? data.specVersion : null; result.has_host = !!(data.host && typeof data.host === 'object'); - if (Array.isArray(data.entries)) { - result.entries_count = data.entries.length; - result.entry_types = [...new Set(data.entries - .map(e => e && typeof e.type === 'string' ? e.type : null) - .filter(Boolean))].slice(0, 20); - } + Object.assign(result, summarizeArdEntries(data)); + } catch (e) { + // Failed to parse JSON, result will contain default values. + } + return result; + }); + }).then(([, resultObj]) => { + if (catalogUrl) { + resultObj.catalog_url = catalogUrl; + } + return [wellKnownUrl, resultObj]; + }); + })(), + // ARD v0.91 canonical path (ards-project/ard-spec, spec/ard.md section 5.1): consumers + // MUST fetch /.well-known/ard.json and MUST honour rel="ard"; ai-catalog.json above is + // the predecessor. The v0.91 manifest only requires `entries`, so only those are recorded. + (() => { + const wellKnownUrl = '/.well-known/ard.json'; + let catalogUrl = null; + try { + const link = document.querySelector('link[rel~="ard" i]'); + if (link && link.href) { + const target = new URL(link.href, location.href); + if (target.origin !== location.origin || target.pathname !== wellKnownUrl) { + catalogUrl = target.href; + } + } + } catch (e) { + // No usable link, fall back to the well-known path. + } + return parseResponse(catalogUrl || wellKnownUrl, r => { + return r.text().then(text => { + let result = summarizeArdEntries(null); + try { + result = summarizeArdEntries(JSON.parse(text)); } catch (e) { // Failed to parse JSON, result will contain default values. }