ai-catalog 0.1.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/LICENSE +202 -0
- package/README.md +110 -0
- package/dist/cli/index.js +605 -0
- package/dist/index.cjs +519 -0
- package/dist/index.d.cts +303 -0
- package/dist/index.d.ts +303 -0
- package/dist/index.js +472 -0
- package/package.json +57 -0
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type definitions for the Agentic Resource Discovery (ARD) ai-catalog.json
|
|
3
|
+
* format, spec v1.0. Mirrors github.com/Agent-Card/ai-catalog.
|
|
4
|
+
*/
|
|
5
|
+
/** The current ARD spec major.minor this library targets. */
|
|
6
|
+
declare const SPEC_VERSION = "1.0";
|
|
7
|
+
/** Well-known path where a catalog may be served for domain-level discovery. */
|
|
8
|
+
declare const WELL_KNOWN_PATH = "/.well-known/ai-catalog.json";
|
|
9
|
+
/** IANA media type a catalog SHOULD be served with. */
|
|
10
|
+
declare const CATALOG_MEDIA_TYPE = "application/ai-catalog+json";
|
|
11
|
+
/** Link relation used to advertise a catalog from HTML / HTTP Link headers. */
|
|
12
|
+
declare const LINK_REL = "ai-catalog";
|
|
13
|
+
/** RECOMMENDED maximum nesting depth when resolving nested catalogs. */
|
|
14
|
+
declare const DEFAULT_MAX_DEPTH = 4;
|
|
15
|
+
/**
|
|
16
|
+
* Recognized "known types" from the spec. These are RECOMMENDED, not required —
|
|
17
|
+
* the `type` field accepts any string.
|
|
18
|
+
*/
|
|
19
|
+
declare const KnownType: {
|
|
20
|
+
/** A nested AI Catalog. */
|
|
21
|
+
readonly AiCatalog: "application/ai-catalog+json";
|
|
22
|
+
/** Reserved generic Agent Card format. */
|
|
23
|
+
readonly AgentCard: "application/agent-card+json";
|
|
24
|
+
/** An A2A Agent Card. */
|
|
25
|
+
readonly A2aAgentCard: "application/a2a-agent-card+json";
|
|
26
|
+
/** An MCP Server Card. */
|
|
27
|
+
readonly McpServerCard: "application/mcp-server-card+json";
|
|
28
|
+
/** Agent Skill metadata JSON. */
|
|
29
|
+
readonly AgentSkillsJson: "application/agent-skills+json";
|
|
30
|
+
/** Agent Skill in Markdown. */
|
|
31
|
+
readonly AgentSkillsMd: "application/agent-skills+md";
|
|
32
|
+
/** Agent Skill bundle (ZIP). */
|
|
33
|
+
readonly AgentSkillsZip: "application/agent-skills+zip";
|
|
34
|
+
/** Agent Skill bundle (gzipped tarball). */
|
|
35
|
+
readonly AgentSkillsGzip: "application/agent-skills+gzip";
|
|
36
|
+
};
|
|
37
|
+
type KnownTypeValue = (typeof KnownType)[keyof typeof KnownType];
|
|
38
|
+
/** Identifies the operator of a catalog. */
|
|
39
|
+
interface HostInfo {
|
|
40
|
+
/** Human-readable name of the host. REQUIRED. */
|
|
41
|
+
displayName: string;
|
|
42
|
+
/** Verifiable identifier for the host (DID or domain). */
|
|
43
|
+
identifier?: string;
|
|
44
|
+
/** URL to the host's documentation. */
|
|
45
|
+
documentationUrl?: string;
|
|
46
|
+
/** URL (or data: URI) to the host's logo. */
|
|
47
|
+
logoUrl?: string;
|
|
48
|
+
/** Verifiable identity / trust metadata for the host itself. */
|
|
49
|
+
trustManifest?: TrustManifest;
|
|
50
|
+
}
|
|
51
|
+
/** Identifies the entity responsible for an artifact. */
|
|
52
|
+
interface Publisher {
|
|
53
|
+
/** Verifiable identifier for the publisher organization. REQUIRED. */
|
|
54
|
+
identifier: string;
|
|
55
|
+
/** Human-readable name of the publisher. REQUIRED. */
|
|
56
|
+
displayName: string;
|
|
57
|
+
/** Type hint for the identifier, e.g. "did", "dns". */
|
|
58
|
+
identityType?: string;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Trust Manifest: optional verifiable identity, attestation, and provenance
|
|
62
|
+
* metadata. This library treats the inner structure permissively; see the spec
|
|
63
|
+
* for the full shape. The `identity.identifier` domain MUST align with the
|
|
64
|
+
* publisher domain segment of the entry's `urn:air` identifier.
|
|
65
|
+
*/
|
|
66
|
+
interface TrustManifest {
|
|
67
|
+
identifier?: string;
|
|
68
|
+
identity?: {
|
|
69
|
+
identifier: string;
|
|
70
|
+
identityType?: string;
|
|
71
|
+
[k: string]: unknown;
|
|
72
|
+
};
|
|
73
|
+
attestations?: unknown[];
|
|
74
|
+
provenance?: unknown[];
|
|
75
|
+
signature?: unknown;
|
|
76
|
+
[k: string]: unknown;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* A single AI artifact in the catalog. MUST carry an `identifier` and `type`,
|
|
80
|
+
* and exactly one of `url` or `data`.
|
|
81
|
+
*/
|
|
82
|
+
interface CatalogEntry {
|
|
83
|
+
/**
|
|
84
|
+
* Unique artifact identifier. For open/federated systems this MUST follow
|
|
85
|
+
* `urn:air:{publisher}:{namespace}:{name}`.
|
|
86
|
+
*/
|
|
87
|
+
identifier: string;
|
|
88
|
+
/** Media type of the referenced artifact, e.g. an entry in {@link KnownType}. */
|
|
89
|
+
type: KnownTypeValue | (string & {});
|
|
90
|
+
/** URL where the full artifact document can be retrieved. */
|
|
91
|
+
url?: string;
|
|
92
|
+
/** The complete artifact document inline. */
|
|
93
|
+
data?: unknown;
|
|
94
|
+
/** Human-readable name; set only to override the artifact's own name. */
|
|
95
|
+
displayName?: string;
|
|
96
|
+
/** Short description of the artifact. */
|
|
97
|
+
description?: string;
|
|
98
|
+
/** Keywords for filtering and discovery. */
|
|
99
|
+
tags?: string[];
|
|
100
|
+
/** Artifact version; SemVer RECOMMENDED. */
|
|
101
|
+
version?: string;
|
|
102
|
+
/** ISO 8601 / RFC 3339 timestamp of last modification. */
|
|
103
|
+
updatedAt?: string;
|
|
104
|
+
/** The entity that publishes this artifact. */
|
|
105
|
+
publisher?: Publisher;
|
|
106
|
+
/** Verifiable identity / trust metadata for this artifact. */
|
|
107
|
+
trustManifest?: TrustManifest;
|
|
108
|
+
/** Open map for custom metadata. */
|
|
109
|
+
metadata?: Record<string, unknown>;
|
|
110
|
+
}
|
|
111
|
+
/** A top-level AI Catalog document. */
|
|
112
|
+
interface AiCatalog {
|
|
113
|
+
/** Spec version in "Major.Minor" format, e.g. "1.0". REQUIRED. */
|
|
114
|
+
specVersion: string;
|
|
115
|
+
/** Catalog entries. MAY be empty. REQUIRED. */
|
|
116
|
+
entries: CatalogEntry[];
|
|
117
|
+
/** The operator of this catalog. */
|
|
118
|
+
host?: HostInfo;
|
|
119
|
+
/** Open map for custom catalog-level metadata. */
|
|
120
|
+
metadata?: Record<string, unknown>;
|
|
121
|
+
}
|
|
122
|
+
/** Parsed pieces of a `urn:air:{publisher}:{namespace}:{name}` identifier. */
|
|
123
|
+
interface AirUrn {
|
|
124
|
+
/** Publisher domain, e.g. "example.com". */
|
|
125
|
+
publisher: string;
|
|
126
|
+
/** Namespace, possibly colon-separated, e.g. "mcp" or "finance:agent". */
|
|
127
|
+
namespace: string;
|
|
128
|
+
/** Stable artifact name within the namespace. */
|
|
129
|
+
name: string;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Parse a `urn:air:{publisher}:{namespace}:{name}` identifier into its parts.
|
|
134
|
+
* The namespace may contain colons (e.g. `finance:agent`), so it is everything
|
|
135
|
+
* between the publisher and the final segment.
|
|
136
|
+
*
|
|
137
|
+
* Returns `null` for any string that is not a well-formed `urn:air` URN.
|
|
138
|
+
*
|
|
139
|
+
* @example
|
|
140
|
+
* parseAirUrn("urn:air:example.com:finance:agent:research")
|
|
141
|
+
* // { publisher: "example.com", namespace: "finance:agent", name: "research" }
|
|
142
|
+
*/
|
|
143
|
+
declare function parseAirUrn(identifier: string): AirUrn | null;
|
|
144
|
+
/** True if `identifier` is a well-formed `urn:air` URN. */
|
|
145
|
+
declare function isAirUrn(identifier: string): boolean;
|
|
146
|
+
/**
|
|
147
|
+
* Build a `urn:air` identifier from its parts. The namespace may be a single
|
|
148
|
+
* string (possibly colon-separated) or an array of segments.
|
|
149
|
+
*
|
|
150
|
+
* @throws if any part is empty.
|
|
151
|
+
*/
|
|
152
|
+
declare function buildAirUrn(publisher: string, namespace: string | string[], name: string): string;
|
|
153
|
+
/**
|
|
154
|
+
* The trailing name segment of any identifier — the portion after the final
|
|
155
|
+
* `:` or `/`. Used as the last-resort display name (spec resolution step 3).
|
|
156
|
+
*/
|
|
157
|
+
declare function identifierTail(identifier: string): string;
|
|
158
|
+
|
|
159
|
+
/** A single validation problem. `path` is a JSON-pointer-ish location. */
|
|
160
|
+
interface ValidationIssue {
|
|
161
|
+
path: string;
|
|
162
|
+
message: string;
|
|
163
|
+
/** `error` violates a MUST; `warning` violates a SHOULD/RECOMMENDED. */
|
|
164
|
+
severity: "error" | "warning";
|
|
165
|
+
}
|
|
166
|
+
interface ValidationResult {
|
|
167
|
+
valid: boolean;
|
|
168
|
+
errors: ValidationIssue[];
|
|
169
|
+
warnings: ValidationIssue[];
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Validate a parsed value against the ARD ai-catalog.json spec (v1.0).
|
|
173
|
+
*
|
|
174
|
+
* Checks the normative MUST rules — required members, exactly-one-of url/data,
|
|
175
|
+
* identifier/version uniqueness, Host Info / Publisher shape — as `errors`, and
|
|
176
|
+
* the RECOMMENDED rules — `urn:air` identifiers, known media types, RFC 3339
|
|
177
|
+
* timestamps, spec version — as `warnings`. Pass `{ strict: true }` to treat
|
|
178
|
+
* warnings as errors.
|
|
179
|
+
*/
|
|
180
|
+
declare function validateCatalog(doc: unknown, opts?: {
|
|
181
|
+
strict?: boolean;
|
|
182
|
+
}): ValidationResult;
|
|
183
|
+
/** Throwing variant: validates and throws an Error listing all problems. */
|
|
184
|
+
declare function assertValidCatalog(doc: unknown, opts?: {
|
|
185
|
+
strict?: boolean;
|
|
186
|
+
}): asserts doc is AiCatalog;
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Typed builder for an ai-catalog.json document. Chainable; call `.build()` to
|
|
190
|
+
* get the plain object or `.toJSON(indent?)` for a serialized string.
|
|
191
|
+
*
|
|
192
|
+
* @example
|
|
193
|
+
* const catalog = new CatalogBuilder({ displayName: "Acme" })
|
|
194
|
+
* .addEntry({
|
|
195
|
+
* identifier: "urn:air:acme.com:mcp:weather",
|
|
196
|
+
* type: KnownType.McpServerCard,
|
|
197
|
+
* url: "https://acme.com/.well-known/mcp/weather.json",
|
|
198
|
+
* })
|
|
199
|
+
* .build();
|
|
200
|
+
*/
|
|
201
|
+
declare class CatalogBuilder {
|
|
202
|
+
private catalog;
|
|
203
|
+
constructor(host?: HostInfo, specVersion?: string);
|
|
204
|
+
/** Set or replace the Host Info object. */
|
|
205
|
+
setHost(host: HostInfo): this;
|
|
206
|
+
/** Set a catalog-level metadata key. */
|
|
207
|
+
setMetadata(key: string, value: unknown): this;
|
|
208
|
+
/** Append a catalog entry. */
|
|
209
|
+
addEntry(entry: CatalogEntry): this;
|
|
210
|
+
/** Append several catalog entries. */
|
|
211
|
+
addEntries(entries: CatalogEntry[]): this;
|
|
212
|
+
/**
|
|
213
|
+
* Add a nested-catalog entry (`type: application/ai-catalog+json`) that points
|
|
214
|
+
* at another catalog by URL.
|
|
215
|
+
*/
|
|
216
|
+
addNestedCatalog(identifier: string, url: string, extra?: Partial<CatalogEntry>): this;
|
|
217
|
+
/** The built catalog object (a fresh shallow copy each call). */
|
|
218
|
+
build(): AiCatalog;
|
|
219
|
+
/** Validate the built catalog, throwing on any error. Returns the catalog. */
|
|
220
|
+
validateOrThrow(opts?: {
|
|
221
|
+
strict?: boolean;
|
|
222
|
+
}): AiCatalog;
|
|
223
|
+
/** Serialize to a JSON string. */
|
|
224
|
+
toJSON(indent?: number): string;
|
|
225
|
+
}
|
|
226
|
+
/** Functional shorthand for `new CatalogBuilder(host)`. */
|
|
227
|
+
declare function defineCatalog(host?: HostInfo): CatalogBuilder;
|
|
228
|
+
|
|
229
|
+
type FetchLike = (url: string, init?: RequestInit) => Promise<Response>;
|
|
230
|
+
interface DiscoverOptions {
|
|
231
|
+
/** Fetch implementation. Defaults to global `fetch` (Node 18+). */
|
|
232
|
+
fetch?: FetchLike;
|
|
233
|
+
/** Per-request timeout in ms. Default 10000. */
|
|
234
|
+
timeoutMs?: number;
|
|
235
|
+
/** Skip the `/.well-known/ai-catalog.json` fallback (steps 1–2 only). */
|
|
236
|
+
noWellKnownFallback?: boolean;
|
|
237
|
+
}
|
|
238
|
+
interface DiscoverResult {
|
|
239
|
+
/** The resolved catalog URL. */
|
|
240
|
+
url: string;
|
|
241
|
+
/** How the catalog was located. */
|
|
242
|
+
via: "link-header" | "html-link" | "well-known";
|
|
243
|
+
/** The parsed catalog document. */
|
|
244
|
+
catalog: AiCatalog;
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Parse an HTTP `Link` header for a `rel="ai-catalog"` target.
|
|
248
|
+
* Exported for testing and reuse.
|
|
249
|
+
*/
|
|
250
|
+
declare function parseLinkHeader(header: string | null | undefined): string | null;
|
|
251
|
+
/**
|
|
252
|
+
* Find a `<link rel="ai-catalog" href="...">` in an HTML document.
|
|
253
|
+
* Exported for testing and reuse.
|
|
254
|
+
*/
|
|
255
|
+
declare function parseHtmlLink(html: string): string | null;
|
|
256
|
+
/**
|
|
257
|
+
* Run the spec's agent-driven discovery procedure against a website URL:
|
|
258
|
+
*
|
|
259
|
+
* 1. HTTP `Link` header with `rel="ai-catalog"`
|
|
260
|
+
* 2. HTML `<link rel="ai-catalog">`
|
|
261
|
+
* 3. fall back to `/.well-known/ai-catalog.json`
|
|
262
|
+
*
|
|
263
|
+
* Returns the located catalog and how it was found, or throws if no valid
|
|
264
|
+
* catalog can be discovered.
|
|
265
|
+
*/
|
|
266
|
+
declare function discover(siteUrl: string, opts?: DiscoverOptions): Promise<DiscoverResult>;
|
|
267
|
+
/** Fetch and parse a catalog from a known URL, throwing on HTTP/parse errors. */
|
|
268
|
+
declare function fetchCatalog(url: string, fetchFn?: FetchLike, timeoutMs?: number): Promise<AiCatalog>;
|
|
269
|
+
interface ResolveOptions extends DiscoverOptions {
|
|
270
|
+
/** Maximum nesting depth to walk. Default 4 (spec RECOMMENDED). */
|
|
271
|
+
maxDepth?: number;
|
|
272
|
+
}
|
|
273
|
+
interface ResolvedEntry extends CatalogEntry {
|
|
274
|
+
/** URL of the catalog this entry was found in. */
|
|
275
|
+
sourceCatalogUrl: string;
|
|
276
|
+
/** Nesting depth at which it was found (0 = root catalog). */
|
|
277
|
+
depth: number;
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* Walk a catalog and all of its nested catalogs (entries of type
|
|
281
|
+
* `application/ai-catalog+json` carrying a `url`), returning every leaf entry
|
|
282
|
+
* flattened. Respects the spec's depth limit and guards against cycles by URL.
|
|
283
|
+
*
|
|
284
|
+
* Pass either a catalog object plus its `rootUrl`, or just a URL string to fetch
|
|
285
|
+
* the root first.
|
|
286
|
+
*/
|
|
287
|
+
declare function resolveCatalog(root: AiCatalog | string, opts?: ResolveOptions & {
|
|
288
|
+
rootUrl?: string;
|
|
289
|
+
}): Promise<ResolvedEntry[]>;
|
|
290
|
+
/**
|
|
291
|
+
* Resolve a human-readable display name for an entry per the spec order:
|
|
292
|
+
* 1. `entry.displayName`
|
|
293
|
+
* 2. a `referencedName` the caller already fetched (A2A `name` / MCP `title`)
|
|
294
|
+
* 3. the trailing segment of the identifier
|
|
295
|
+
*/
|
|
296
|
+
declare function resolveDisplayName(entry: CatalogEntry, referencedName?: string): string;
|
|
297
|
+
/**
|
|
298
|
+
* From entries sharing an `identifier`, pick the most recent — by SemVer when
|
|
299
|
+
* all versions parse, else by `updatedAt`, else the last in document order.
|
|
300
|
+
*/
|
|
301
|
+
declare function selectLatest(entries: CatalogEntry[], identifier: string): CatalogEntry | undefined;
|
|
302
|
+
|
|
303
|
+
export { type AiCatalog, type AirUrn, CATALOG_MEDIA_TYPE, CatalogBuilder, type CatalogEntry, DEFAULT_MAX_DEPTH, type DiscoverOptions, type DiscoverResult, type HostInfo, KnownType, type KnownTypeValue, LINK_REL, type Publisher, type ResolveOptions, type ResolvedEntry, SPEC_VERSION, type TrustManifest, type ValidationIssue, type ValidationResult, WELL_KNOWN_PATH, assertValidCatalog, buildAirUrn, defineCatalog, discover, fetchCatalog, identifierTail, isAirUrn, parseAirUrn, parseHtmlLink, parseLinkHeader, resolveCatalog, resolveDisplayName, selectLatest, validateCatalog };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type definitions for the Agentic Resource Discovery (ARD) ai-catalog.json
|
|
3
|
+
* format, spec v1.0. Mirrors github.com/Agent-Card/ai-catalog.
|
|
4
|
+
*/
|
|
5
|
+
/** The current ARD spec major.minor this library targets. */
|
|
6
|
+
declare const SPEC_VERSION = "1.0";
|
|
7
|
+
/** Well-known path where a catalog may be served for domain-level discovery. */
|
|
8
|
+
declare const WELL_KNOWN_PATH = "/.well-known/ai-catalog.json";
|
|
9
|
+
/** IANA media type a catalog SHOULD be served with. */
|
|
10
|
+
declare const CATALOG_MEDIA_TYPE = "application/ai-catalog+json";
|
|
11
|
+
/** Link relation used to advertise a catalog from HTML / HTTP Link headers. */
|
|
12
|
+
declare const LINK_REL = "ai-catalog";
|
|
13
|
+
/** RECOMMENDED maximum nesting depth when resolving nested catalogs. */
|
|
14
|
+
declare const DEFAULT_MAX_DEPTH = 4;
|
|
15
|
+
/**
|
|
16
|
+
* Recognized "known types" from the spec. These are RECOMMENDED, not required —
|
|
17
|
+
* the `type` field accepts any string.
|
|
18
|
+
*/
|
|
19
|
+
declare const KnownType: {
|
|
20
|
+
/** A nested AI Catalog. */
|
|
21
|
+
readonly AiCatalog: "application/ai-catalog+json";
|
|
22
|
+
/** Reserved generic Agent Card format. */
|
|
23
|
+
readonly AgentCard: "application/agent-card+json";
|
|
24
|
+
/** An A2A Agent Card. */
|
|
25
|
+
readonly A2aAgentCard: "application/a2a-agent-card+json";
|
|
26
|
+
/** An MCP Server Card. */
|
|
27
|
+
readonly McpServerCard: "application/mcp-server-card+json";
|
|
28
|
+
/** Agent Skill metadata JSON. */
|
|
29
|
+
readonly AgentSkillsJson: "application/agent-skills+json";
|
|
30
|
+
/** Agent Skill in Markdown. */
|
|
31
|
+
readonly AgentSkillsMd: "application/agent-skills+md";
|
|
32
|
+
/** Agent Skill bundle (ZIP). */
|
|
33
|
+
readonly AgentSkillsZip: "application/agent-skills+zip";
|
|
34
|
+
/** Agent Skill bundle (gzipped tarball). */
|
|
35
|
+
readonly AgentSkillsGzip: "application/agent-skills+gzip";
|
|
36
|
+
};
|
|
37
|
+
type KnownTypeValue = (typeof KnownType)[keyof typeof KnownType];
|
|
38
|
+
/** Identifies the operator of a catalog. */
|
|
39
|
+
interface HostInfo {
|
|
40
|
+
/** Human-readable name of the host. REQUIRED. */
|
|
41
|
+
displayName: string;
|
|
42
|
+
/** Verifiable identifier for the host (DID or domain). */
|
|
43
|
+
identifier?: string;
|
|
44
|
+
/** URL to the host's documentation. */
|
|
45
|
+
documentationUrl?: string;
|
|
46
|
+
/** URL (or data: URI) to the host's logo. */
|
|
47
|
+
logoUrl?: string;
|
|
48
|
+
/** Verifiable identity / trust metadata for the host itself. */
|
|
49
|
+
trustManifest?: TrustManifest;
|
|
50
|
+
}
|
|
51
|
+
/** Identifies the entity responsible for an artifact. */
|
|
52
|
+
interface Publisher {
|
|
53
|
+
/** Verifiable identifier for the publisher organization. REQUIRED. */
|
|
54
|
+
identifier: string;
|
|
55
|
+
/** Human-readable name of the publisher. REQUIRED. */
|
|
56
|
+
displayName: string;
|
|
57
|
+
/** Type hint for the identifier, e.g. "did", "dns". */
|
|
58
|
+
identityType?: string;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Trust Manifest: optional verifiable identity, attestation, and provenance
|
|
62
|
+
* metadata. This library treats the inner structure permissively; see the spec
|
|
63
|
+
* for the full shape. The `identity.identifier` domain MUST align with the
|
|
64
|
+
* publisher domain segment of the entry's `urn:air` identifier.
|
|
65
|
+
*/
|
|
66
|
+
interface TrustManifest {
|
|
67
|
+
identifier?: string;
|
|
68
|
+
identity?: {
|
|
69
|
+
identifier: string;
|
|
70
|
+
identityType?: string;
|
|
71
|
+
[k: string]: unknown;
|
|
72
|
+
};
|
|
73
|
+
attestations?: unknown[];
|
|
74
|
+
provenance?: unknown[];
|
|
75
|
+
signature?: unknown;
|
|
76
|
+
[k: string]: unknown;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* A single AI artifact in the catalog. MUST carry an `identifier` and `type`,
|
|
80
|
+
* and exactly one of `url` or `data`.
|
|
81
|
+
*/
|
|
82
|
+
interface CatalogEntry {
|
|
83
|
+
/**
|
|
84
|
+
* Unique artifact identifier. For open/federated systems this MUST follow
|
|
85
|
+
* `urn:air:{publisher}:{namespace}:{name}`.
|
|
86
|
+
*/
|
|
87
|
+
identifier: string;
|
|
88
|
+
/** Media type of the referenced artifact, e.g. an entry in {@link KnownType}. */
|
|
89
|
+
type: KnownTypeValue | (string & {});
|
|
90
|
+
/** URL where the full artifact document can be retrieved. */
|
|
91
|
+
url?: string;
|
|
92
|
+
/** The complete artifact document inline. */
|
|
93
|
+
data?: unknown;
|
|
94
|
+
/** Human-readable name; set only to override the artifact's own name. */
|
|
95
|
+
displayName?: string;
|
|
96
|
+
/** Short description of the artifact. */
|
|
97
|
+
description?: string;
|
|
98
|
+
/** Keywords for filtering and discovery. */
|
|
99
|
+
tags?: string[];
|
|
100
|
+
/** Artifact version; SemVer RECOMMENDED. */
|
|
101
|
+
version?: string;
|
|
102
|
+
/** ISO 8601 / RFC 3339 timestamp of last modification. */
|
|
103
|
+
updatedAt?: string;
|
|
104
|
+
/** The entity that publishes this artifact. */
|
|
105
|
+
publisher?: Publisher;
|
|
106
|
+
/** Verifiable identity / trust metadata for this artifact. */
|
|
107
|
+
trustManifest?: TrustManifest;
|
|
108
|
+
/** Open map for custom metadata. */
|
|
109
|
+
metadata?: Record<string, unknown>;
|
|
110
|
+
}
|
|
111
|
+
/** A top-level AI Catalog document. */
|
|
112
|
+
interface AiCatalog {
|
|
113
|
+
/** Spec version in "Major.Minor" format, e.g. "1.0". REQUIRED. */
|
|
114
|
+
specVersion: string;
|
|
115
|
+
/** Catalog entries. MAY be empty. REQUIRED. */
|
|
116
|
+
entries: CatalogEntry[];
|
|
117
|
+
/** The operator of this catalog. */
|
|
118
|
+
host?: HostInfo;
|
|
119
|
+
/** Open map for custom catalog-level metadata. */
|
|
120
|
+
metadata?: Record<string, unknown>;
|
|
121
|
+
}
|
|
122
|
+
/** Parsed pieces of a `urn:air:{publisher}:{namespace}:{name}` identifier. */
|
|
123
|
+
interface AirUrn {
|
|
124
|
+
/** Publisher domain, e.g. "example.com". */
|
|
125
|
+
publisher: string;
|
|
126
|
+
/** Namespace, possibly colon-separated, e.g. "mcp" or "finance:agent". */
|
|
127
|
+
namespace: string;
|
|
128
|
+
/** Stable artifact name within the namespace. */
|
|
129
|
+
name: string;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Parse a `urn:air:{publisher}:{namespace}:{name}` identifier into its parts.
|
|
134
|
+
* The namespace may contain colons (e.g. `finance:agent`), so it is everything
|
|
135
|
+
* between the publisher and the final segment.
|
|
136
|
+
*
|
|
137
|
+
* Returns `null` for any string that is not a well-formed `urn:air` URN.
|
|
138
|
+
*
|
|
139
|
+
* @example
|
|
140
|
+
* parseAirUrn("urn:air:example.com:finance:agent:research")
|
|
141
|
+
* // { publisher: "example.com", namespace: "finance:agent", name: "research" }
|
|
142
|
+
*/
|
|
143
|
+
declare function parseAirUrn(identifier: string): AirUrn | null;
|
|
144
|
+
/** True if `identifier` is a well-formed `urn:air` URN. */
|
|
145
|
+
declare function isAirUrn(identifier: string): boolean;
|
|
146
|
+
/**
|
|
147
|
+
* Build a `urn:air` identifier from its parts. The namespace may be a single
|
|
148
|
+
* string (possibly colon-separated) or an array of segments.
|
|
149
|
+
*
|
|
150
|
+
* @throws if any part is empty.
|
|
151
|
+
*/
|
|
152
|
+
declare function buildAirUrn(publisher: string, namespace: string | string[], name: string): string;
|
|
153
|
+
/**
|
|
154
|
+
* The trailing name segment of any identifier — the portion after the final
|
|
155
|
+
* `:` or `/`. Used as the last-resort display name (spec resolution step 3).
|
|
156
|
+
*/
|
|
157
|
+
declare function identifierTail(identifier: string): string;
|
|
158
|
+
|
|
159
|
+
/** A single validation problem. `path` is a JSON-pointer-ish location. */
|
|
160
|
+
interface ValidationIssue {
|
|
161
|
+
path: string;
|
|
162
|
+
message: string;
|
|
163
|
+
/** `error` violates a MUST; `warning` violates a SHOULD/RECOMMENDED. */
|
|
164
|
+
severity: "error" | "warning";
|
|
165
|
+
}
|
|
166
|
+
interface ValidationResult {
|
|
167
|
+
valid: boolean;
|
|
168
|
+
errors: ValidationIssue[];
|
|
169
|
+
warnings: ValidationIssue[];
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Validate a parsed value against the ARD ai-catalog.json spec (v1.0).
|
|
173
|
+
*
|
|
174
|
+
* Checks the normative MUST rules — required members, exactly-one-of url/data,
|
|
175
|
+
* identifier/version uniqueness, Host Info / Publisher shape — as `errors`, and
|
|
176
|
+
* the RECOMMENDED rules — `urn:air` identifiers, known media types, RFC 3339
|
|
177
|
+
* timestamps, spec version — as `warnings`. Pass `{ strict: true }` to treat
|
|
178
|
+
* warnings as errors.
|
|
179
|
+
*/
|
|
180
|
+
declare function validateCatalog(doc: unknown, opts?: {
|
|
181
|
+
strict?: boolean;
|
|
182
|
+
}): ValidationResult;
|
|
183
|
+
/** Throwing variant: validates and throws an Error listing all problems. */
|
|
184
|
+
declare function assertValidCatalog(doc: unknown, opts?: {
|
|
185
|
+
strict?: boolean;
|
|
186
|
+
}): asserts doc is AiCatalog;
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Typed builder for an ai-catalog.json document. Chainable; call `.build()` to
|
|
190
|
+
* get the plain object or `.toJSON(indent?)` for a serialized string.
|
|
191
|
+
*
|
|
192
|
+
* @example
|
|
193
|
+
* const catalog = new CatalogBuilder({ displayName: "Acme" })
|
|
194
|
+
* .addEntry({
|
|
195
|
+
* identifier: "urn:air:acme.com:mcp:weather",
|
|
196
|
+
* type: KnownType.McpServerCard,
|
|
197
|
+
* url: "https://acme.com/.well-known/mcp/weather.json",
|
|
198
|
+
* })
|
|
199
|
+
* .build();
|
|
200
|
+
*/
|
|
201
|
+
declare class CatalogBuilder {
|
|
202
|
+
private catalog;
|
|
203
|
+
constructor(host?: HostInfo, specVersion?: string);
|
|
204
|
+
/** Set or replace the Host Info object. */
|
|
205
|
+
setHost(host: HostInfo): this;
|
|
206
|
+
/** Set a catalog-level metadata key. */
|
|
207
|
+
setMetadata(key: string, value: unknown): this;
|
|
208
|
+
/** Append a catalog entry. */
|
|
209
|
+
addEntry(entry: CatalogEntry): this;
|
|
210
|
+
/** Append several catalog entries. */
|
|
211
|
+
addEntries(entries: CatalogEntry[]): this;
|
|
212
|
+
/**
|
|
213
|
+
* Add a nested-catalog entry (`type: application/ai-catalog+json`) that points
|
|
214
|
+
* at another catalog by URL.
|
|
215
|
+
*/
|
|
216
|
+
addNestedCatalog(identifier: string, url: string, extra?: Partial<CatalogEntry>): this;
|
|
217
|
+
/** The built catalog object (a fresh shallow copy each call). */
|
|
218
|
+
build(): AiCatalog;
|
|
219
|
+
/** Validate the built catalog, throwing on any error. Returns the catalog. */
|
|
220
|
+
validateOrThrow(opts?: {
|
|
221
|
+
strict?: boolean;
|
|
222
|
+
}): AiCatalog;
|
|
223
|
+
/** Serialize to a JSON string. */
|
|
224
|
+
toJSON(indent?: number): string;
|
|
225
|
+
}
|
|
226
|
+
/** Functional shorthand for `new CatalogBuilder(host)`. */
|
|
227
|
+
declare function defineCatalog(host?: HostInfo): CatalogBuilder;
|
|
228
|
+
|
|
229
|
+
type FetchLike = (url: string, init?: RequestInit) => Promise<Response>;
|
|
230
|
+
interface DiscoverOptions {
|
|
231
|
+
/** Fetch implementation. Defaults to global `fetch` (Node 18+). */
|
|
232
|
+
fetch?: FetchLike;
|
|
233
|
+
/** Per-request timeout in ms. Default 10000. */
|
|
234
|
+
timeoutMs?: number;
|
|
235
|
+
/** Skip the `/.well-known/ai-catalog.json` fallback (steps 1–2 only). */
|
|
236
|
+
noWellKnownFallback?: boolean;
|
|
237
|
+
}
|
|
238
|
+
interface DiscoverResult {
|
|
239
|
+
/** The resolved catalog URL. */
|
|
240
|
+
url: string;
|
|
241
|
+
/** How the catalog was located. */
|
|
242
|
+
via: "link-header" | "html-link" | "well-known";
|
|
243
|
+
/** The parsed catalog document. */
|
|
244
|
+
catalog: AiCatalog;
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Parse an HTTP `Link` header for a `rel="ai-catalog"` target.
|
|
248
|
+
* Exported for testing and reuse.
|
|
249
|
+
*/
|
|
250
|
+
declare function parseLinkHeader(header: string | null | undefined): string | null;
|
|
251
|
+
/**
|
|
252
|
+
* Find a `<link rel="ai-catalog" href="...">` in an HTML document.
|
|
253
|
+
* Exported for testing and reuse.
|
|
254
|
+
*/
|
|
255
|
+
declare function parseHtmlLink(html: string): string | null;
|
|
256
|
+
/**
|
|
257
|
+
* Run the spec's agent-driven discovery procedure against a website URL:
|
|
258
|
+
*
|
|
259
|
+
* 1. HTTP `Link` header with `rel="ai-catalog"`
|
|
260
|
+
* 2. HTML `<link rel="ai-catalog">`
|
|
261
|
+
* 3. fall back to `/.well-known/ai-catalog.json`
|
|
262
|
+
*
|
|
263
|
+
* Returns the located catalog and how it was found, or throws if no valid
|
|
264
|
+
* catalog can be discovered.
|
|
265
|
+
*/
|
|
266
|
+
declare function discover(siteUrl: string, opts?: DiscoverOptions): Promise<DiscoverResult>;
|
|
267
|
+
/** Fetch and parse a catalog from a known URL, throwing on HTTP/parse errors. */
|
|
268
|
+
declare function fetchCatalog(url: string, fetchFn?: FetchLike, timeoutMs?: number): Promise<AiCatalog>;
|
|
269
|
+
interface ResolveOptions extends DiscoverOptions {
|
|
270
|
+
/** Maximum nesting depth to walk. Default 4 (spec RECOMMENDED). */
|
|
271
|
+
maxDepth?: number;
|
|
272
|
+
}
|
|
273
|
+
interface ResolvedEntry extends CatalogEntry {
|
|
274
|
+
/** URL of the catalog this entry was found in. */
|
|
275
|
+
sourceCatalogUrl: string;
|
|
276
|
+
/** Nesting depth at which it was found (0 = root catalog). */
|
|
277
|
+
depth: number;
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* Walk a catalog and all of its nested catalogs (entries of type
|
|
281
|
+
* `application/ai-catalog+json` carrying a `url`), returning every leaf entry
|
|
282
|
+
* flattened. Respects the spec's depth limit and guards against cycles by URL.
|
|
283
|
+
*
|
|
284
|
+
* Pass either a catalog object plus its `rootUrl`, or just a URL string to fetch
|
|
285
|
+
* the root first.
|
|
286
|
+
*/
|
|
287
|
+
declare function resolveCatalog(root: AiCatalog | string, opts?: ResolveOptions & {
|
|
288
|
+
rootUrl?: string;
|
|
289
|
+
}): Promise<ResolvedEntry[]>;
|
|
290
|
+
/**
|
|
291
|
+
* Resolve a human-readable display name for an entry per the spec order:
|
|
292
|
+
* 1. `entry.displayName`
|
|
293
|
+
* 2. a `referencedName` the caller already fetched (A2A `name` / MCP `title`)
|
|
294
|
+
* 3. the trailing segment of the identifier
|
|
295
|
+
*/
|
|
296
|
+
declare function resolveDisplayName(entry: CatalogEntry, referencedName?: string): string;
|
|
297
|
+
/**
|
|
298
|
+
* From entries sharing an `identifier`, pick the most recent — by SemVer when
|
|
299
|
+
* all versions parse, else by `updatedAt`, else the last in document order.
|
|
300
|
+
*/
|
|
301
|
+
declare function selectLatest(entries: CatalogEntry[], identifier: string): CatalogEntry | undefined;
|
|
302
|
+
|
|
303
|
+
export { type AiCatalog, type AirUrn, CATALOG_MEDIA_TYPE, CatalogBuilder, type CatalogEntry, DEFAULT_MAX_DEPTH, type DiscoverOptions, type DiscoverResult, type HostInfo, KnownType, type KnownTypeValue, LINK_REL, type Publisher, type ResolveOptions, type ResolvedEntry, SPEC_VERSION, type TrustManifest, type ValidationIssue, type ValidationResult, WELL_KNOWN_PATH, assertValidCatalog, buildAirUrn, defineCatalog, discover, fetchCatalog, identifierTail, isAirUrn, parseAirUrn, parseHtmlLink, parseLinkHeader, resolveCatalog, resolveDisplayName, selectLatest, validateCatalog };
|