faf-cli 8.1.0 → 8.2.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 +22 -8
- package/dist/cli.js +270 -267
- package/dist/cli.js.map +13 -12
- package/dist/core/types.d.ts +1 -1
- package/dist/detect/scanner.d.ts +4 -1
- package/dist/index.js +166 -166
- package/dist/index.js.map +10 -9
- package/dist/interop/cards.d.ts +33 -14
- package/dist/interop/context-block.d.ts +43 -0
- package/dist/interop/pack.d.ts +53 -18
- package/dist/interop/servercard.d.ts +4 -21
- package/dist/pack.js +50 -50
- package/dist/pack.js.map +5 -4
- package/package.json +1 -1
- package/project.faf +3 -3
package/dist/interop/cards.d.ts
CHANGED
|
@@ -2,8 +2,7 @@ import type { FafData } from '../core/types.js';
|
|
|
2
2
|
import { type RenderedResult } from '../core/render-hash.js';
|
|
3
3
|
import { type CatalogHost, type FafaDoc, type ProjectedA2A } from './pack.js';
|
|
4
4
|
import { type ServerCardOptions } from './servercard.js';
|
|
5
|
-
|
|
6
|
-
export declare const A2A_CONTEXT_URI = "https://faf.one/ext/context/v1";
|
|
5
|
+
export { A2A_CONTEXT_URI } from './context-block.js';
|
|
7
6
|
export { A2A_PROTOCOL_BINDING, A2A_PROTOCOL_VERSION, FAF_MEDIA_TYPES, a2aEndpoints, a2aDoors, } from './pack.js';
|
|
8
7
|
export type { FafaAgent, FafaCapability, FafaEndpoint, FafaDoc, ProjectedA2A } from './pack.js';
|
|
9
8
|
export type CardTarget = 'a2a' | 'mcp' | 'registry' | 'catalog' | 'ard';
|
|
@@ -32,13 +31,15 @@ export interface AiCatalog {
|
|
|
32
31
|
[key: string]: unknown;
|
|
33
32
|
}
|
|
34
33
|
export interface ProjectedCards {
|
|
35
|
-
block
|
|
34
|
+
/** faf's context block — only when a project.faf was given (BEST). */
|
|
35
|
+
block?: Record<string, unknown>;
|
|
36
36
|
a2a?: ProjectedA2A;
|
|
37
37
|
mcp?: Record<string, unknown>;
|
|
38
38
|
registry?: {
|
|
39
39
|
name: string;
|
|
40
40
|
title?: string;
|
|
41
|
-
|
|
41
|
+
/** FAF's context block (BEST); absent from a plain registry identity (BETTER). */
|
|
42
|
+
_meta?: Record<string, unknown>;
|
|
42
43
|
};
|
|
43
44
|
catalog?: CatalogEntry[];
|
|
44
45
|
/** The same rows, carrying ARD's search hints — the ARD manifest. */
|
|
@@ -50,23 +51,27 @@ export interface ProjectedCards {
|
|
|
50
51
|
export declare function readFafa(path: string): FafaDoc;
|
|
51
52
|
/** Discover agent.fafa / .fafa (cwd, then one parent). */
|
|
52
53
|
export declare function findFafaFile(dir?: string): string | null;
|
|
53
|
-
/** Build the A2A Agent Card (JSON) from a .fafa
|
|
54
|
-
* ({@link projectA2ACard})
|
|
55
|
-
|
|
54
|
+
/** Build the A2A Agent Card (JSON) from a .fafa: the core card
|
|
55
|
+
* ({@link projectA2ACard}). With a project.faf (BEST) it carries FAF's
|
|
56
|
+
* context extension; with none (BETTER) it is the plain A2A card — the
|
|
57
|
+
* .fafa is its source, and nothing on it points at a project.faf. */
|
|
58
|
+
export declare function buildA2ACard(fafa: FafaDoc, faf?: FafData, opts?: ProjectCardsOptions): ProjectedA2A;
|
|
56
59
|
/** @deprecated Use {@link buildA2ACard}. Removed in the next major. */
|
|
57
60
|
export declare const generateA2ACard: typeof buildA2ACard;
|
|
58
61
|
/**
|
|
59
|
-
* The catalog rows for this agent
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
*
|
|
62
|
+
* The catalog rows for this agent — the pack projector's own
|
|
63
|
+
* ({@link catalogRows}), so `faf cards` and the pack list the same rows: the
|
|
64
|
+
* A2A card (when the `.fafa` names an A2A door), the Server Card (when it names
|
|
65
|
+
* a remote MCP URL) and the `.fafa` itself, keyed
|
|
66
|
+
* `urn:air:{publisher}:{namespace}:{name}`, where the publisher is the domain
|
|
67
|
+
* the `.fafa` *declares* (`agent.id`'s urn:air, `metadata.cards.domain`, else
|
|
68
|
+
* the homepage host) and the name is the handle.
|
|
64
69
|
*
|
|
65
70
|
* Throws, rather than inventing either half, when the `.fafa` names no domain:
|
|
66
71
|
* an identifier is a catalog's primary key, and `urn:air:local:…` published to
|
|
67
72
|
* the world is worse than a refusal a line of YAML fixes.
|
|
68
73
|
*/
|
|
69
|
-
export declare function catalogEntriesFor(fafa: FafaDoc, faf
|
|
74
|
+
export declare function catalogEntriesFor(fafa: FafaDoc, faf?: FafData, opts?: ProjectCardsOptions): CatalogEntry[];
|
|
70
75
|
/** Upsert projector entries into an existing catalog. Leaves every other row
|
|
71
76
|
* alone: a row is faf's only when its identifier is exactly faf's (never by
|
|
72
77
|
* type or URL). On match, only url / type / updatedAt move — host copy
|
|
@@ -90,8 +95,22 @@ export declare function upsertCatalogText(text: string | null, incoming: Catalog
|
|
|
90
95
|
text: string;
|
|
91
96
|
changed: boolean;
|
|
92
97
|
};
|
|
98
|
+
/** The cards an agent.fafa gives with no project.faf (BETTER): the A2A card
|
|
99
|
+
* (when it names an A2A door), the MCP Server Card (when it names a remote MCP
|
|
100
|
+
* URL), the registry server.json (a remote or a package), the AI Catalog, ARD. */
|
|
101
|
+
export declare function betterTargets(fafa: FafaDoc, opts?: ProjectCardsOptions): CardTarget[];
|
|
102
|
+
/**
|
|
103
|
+
* Project the cards. The ladder — BETTER is the .fafa, BEST is project.faf:
|
|
104
|
+
* an agent.fafa alone gives the plain cards ({@link betterTargets}); a
|
|
105
|
+
* project.faf, resident and used, adds FAF's context block to each (the A2A
|
|
106
|
+
* card's extension, the Server Card's and server.json's `_meta`). A card's
|
|
107
|
+
* identity comes from the .fafa at both rungs. With a project.faf and no MCP
|
|
108
|
+
* endpoint in the .fafa (an MCP server's own repo), the Server Card and the
|
|
109
|
+
* registry identity come from project.faf, as `faf server-card` writes them.
|
|
110
|
+
*/
|
|
93
111
|
export declare function projectCards(input: {
|
|
94
|
-
faf
|
|
112
|
+
/** project.faf — absent means BETTER. */
|
|
113
|
+
faf?: FafData;
|
|
95
114
|
fafa?: FafaDoc;
|
|
96
115
|
targets?: CardTarget[];
|
|
97
116
|
opts?: ProjectCardsOptions;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FAF's context block — what BEST adds to a card. Pure (no Node built-ins), so
|
|
3
|
+
* `faf cards` and the browser-safe pack projector add the same block.
|
|
4
|
+
*
|
|
5
|
+
* The cards ladder: an agent.fafa gives the plain cards (BETTER); a project.faf,
|
|
6
|
+
* resident and used, adds this block to each of them (BEST) — the A2A card's
|
|
7
|
+
* context extension, the Server Card's `_meta["one.faf/context"]`, the registry
|
|
8
|
+
* `server.json`'s publisher-provided `_meta`.
|
|
9
|
+
*/
|
|
10
|
+
import type { FafData } from '../core/types.js';
|
|
11
|
+
/** project.faf's IANA media type. */
|
|
12
|
+
export declare const FAF_MEDIA_TYPE = "application/vnd.faf+yaml";
|
|
13
|
+
/** A2A extension URI — dereference, not the MCP `_meta` key `one.faf/context`. */
|
|
14
|
+
export declare const A2A_CONTEXT_URI = "https://faf.one/ext/context/v1";
|
|
15
|
+
export declare const REGISTRY_PUBLISHER_KEY = "io.modelcontextprotocol.registry/publisher-provided";
|
|
16
|
+
export interface ContextBlockOptions {
|
|
17
|
+
/** Pointer to the .faf context (default: ./project.faf). Pass an absolute URL
|
|
18
|
+
* for a remote/served card (e.g. faf-server-card-ref at context.faf.one). */
|
|
19
|
+
fafPointer?: string;
|
|
20
|
+
/** Optional "verify the score here" URL — makes verify-don't-trust actionable
|
|
21
|
+
* (faf-server-card-ref uses https://faf.one). Omitted from the block if unset. */
|
|
22
|
+
scoreEndpoint?: string;
|
|
23
|
+
/** Override timestamp (tests); otherwise .faf `generated`, else now. */
|
|
24
|
+
now?: string;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* The canonical FAF context-block — the value of `_meta["one.faf/context"]`,
|
|
28
|
+
* identical across every surface (Server Card, registry `server.json`, `.fafa`):
|
|
29
|
+
* one context, every door. Honest-first: no score baked (it would go stale on
|
|
30
|
+
* disk); it points to the .faf and asserts the score is deterministic.
|
|
31
|
+
*/
|
|
32
|
+
export declare function fafContextBlock(data: FafData, opts?: ContextBlockOptions): Record<string, unknown>;
|
|
33
|
+
/**
|
|
34
|
+
* Build the `_meta` for an MCP Registry `server.json`.
|
|
35
|
+
*
|
|
36
|
+
* The SAME canonical context-block as the Server Card, but nested under
|
|
37
|
+
* `io.modelcontextprotocol.registry/publisher-provided` — the ONLY `_meta` key
|
|
38
|
+
* the official registry preserves on publish. Top-level keys (the way the card
|
|
39
|
+
* carries `one.faf/context`) are silently dropped by the registry. Throws if the
|
|
40
|
+
* block exceeds the registry's 4KB cap. Merge the result into an existing
|
|
41
|
+
* `server.json` `_meta`; don't regenerate the manifest (packages/mcpb are tuned).
|
|
42
|
+
*/
|
|
43
|
+
export declare function registryMeta(data: FafData, opts?: ContextBlockOptions): Record<string, unknown>;
|
package/dist/interop/pack.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { FafData } from '../core/types.js';
|
|
2
|
+
import { type ContextBlockOptions } from './context-block.js';
|
|
1
3
|
export declare const A2A_PROTOCOL_BINDING = "JSONRPC";
|
|
2
4
|
export declare const A2A_PROTOCOL_VERSION = "1.0";
|
|
3
5
|
/** The three FAF-family media types, in family order. */
|
|
@@ -108,6 +110,16 @@ export declare function a2aEndpoints(fafa: FafaDoc): FafaEndpoint[];
|
|
|
108
110
|
export declare function a2aDoors(fafa: FafaDoc, opts?: {
|
|
109
111
|
doorUrl?: string;
|
|
110
112
|
}): FafaEndpoint[];
|
|
113
|
+
/**
|
|
114
|
+
* FAF's context extension for the A2A card (BEST). Its `params` are a superset
|
|
115
|
+
* of {@link fafContextBlock}, enriched with `.fafa`-specific identity that only
|
|
116
|
+
* makes sense for an agent card (agentId, passport, the full FAF media-type
|
|
117
|
+
* family). Nests the base block's `faf`/`mediaType` under `provenance` rather
|
|
118
|
+
* than flattening them, per the extension's own shape (`§7` of the field
|
|
119
|
+
* mapping). The Server Card and registry `_meta` stay on the plain
|
|
120
|
+
* {@link fafContextBlock} shape.
|
|
121
|
+
*/
|
|
122
|
+
export declare function fafaContextExtension(fafa: FafaDoc, faf: FafData, opts?: ContextBlockOptions): A2AExtension;
|
|
111
123
|
/**
|
|
112
124
|
* The A2A Agent Card from a `.fafa`: every field comes from the document, and
|
|
113
125
|
* `capabilities.extensions` holds exactly the extensions passed (none by default).
|
|
@@ -154,10 +166,25 @@ export declare function fafaDomain(fafa: FafaDoc): string;
|
|
|
154
166
|
export declare function fafaHandle(fafa: FafaDoc): string;
|
|
155
167
|
/** MCP names are reverse-DNS: example.com + weather → com.example/weather. */
|
|
156
168
|
export declare function mcpName(fafa: FafaDoc): string;
|
|
157
|
-
/** The MCP
|
|
158
|
-
export declare function
|
|
159
|
-
|
|
160
|
-
|
|
169
|
+
/** The `.fafa`'s MCP endpoints at an http(s) URL — what a Server Card describes. */
|
|
170
|
+
export declare function mcpRemotes(fafa: FafaDoc): Array<{
|
|
171
|
+
type: string;
|
|
172
|
+
url: string;
|
|
173
|
+
}>;
|
|
174
|
+
/** True when the `.fafa` gives a registry entry: a package or a remote MCP URL. */
|
|
175
|
+
export declare function hasRegistryEntry(fafa: FafaDoc): boolean;
|
|
176
|
+
/** The registry identity from the `.fafa`: `name`, and `title` when it has one. */
|
|
177
|
+
export declare function registryIdentity(fafa: FafaDoc): {
|
|
178
|
+
name: string;
|
|
179
|
+
title?: string;
|
|
180
|
+
};
|
|
181
|
+
/** The MCP Server Card for a remote MCP server. With a project.faf (`faf`,
|
|
182
|
+
* BEST) it carries FAF's context block at `_meta["one.faf/context"]`. */
|
|
183
|
+
export declare function projectServerCard(fafa: FafaDoc, faf?: FafData, opts?: ContextBlockOptions): Record<string, unknown>;
|
|
184
|
+
/** The MCP Registry `server.json` (publishing it stays the owner's step). With
|
|
185
|
+
* a project.faf (`faf`, BEST) it carries FAF's context block in the registry's
|
|
186
|
+
* publisher-provided `_meta`. */
|
|
187
|
+
export declare function projectServerJson(fafa: FafaDoc, faf?: FafData, opts?: ContextBlockOptions): Record<string, unknown>;
|
|
161
188
|
export type PackCard = 'a2a' | 'server_card' | 'server_json' | 'ai_catalog' | 'ard' | 'fafa';
|
|
162
189
|
export interface CatalogRow {
|
|
163
190
|
identifier: string;
|
|
@@ -168,11 +195,21 @@ export interface CatalogRow {
|
|
|
168
195
|
version?: string;
|
|
169
196
|
updatedAt: string;
|
|
170
197
|
}
|
|
171
|
-
/**
|
|
172
|
-
export
|
|
198
|
+
/** Options for the catalog rows. */
|
|
199
|
+
export interface CatalogRowOptions {
|
|
200
|
+
/** `updatedAt` for the rows; otherwise now. */
|
|
173
201
|
now?: string;
|
|
202
|
+
/** List the `.fafa` itself (served at /.well-known/fafa). Default true: it is
|
|
203
|
+
* the source of the cards — what makes them BETTER. */
|
|
174
204
|
listFafa?: boolean;
|
|
175
|
-
|
|
205
|
+
/** Public URL of the A2A card; default the domain's /.well-known/agent-card.json. */
|
|
206
|
+
a2aCardUrl?: string;
|
|
207
|
+
/** An A2A door when the `.fafa` names none (as `faf cards --door-url`). */
|
|
208
|
+
doorUrl?: string;
|
|
209
|
+
}
|
|
210
|
+
/** One row per card the domain serves: the A2A card (when the `.fafa` names an
|
|
211
|
+
* A2A door), the Server Card (when it names a remote MCP URL), and the `.fafa`. */
|
|
212
|
+
export declare function catalogRows(fafa: FafaDoc, cards: PackCard[], opts?: CatalogRowOptions): CatalogRow[];
|
|
176
213
|
/** Who publishes a catalog: AI Catalog's `host` object. */
|
|
177
214
|
export interface CatalogHost {
|
|
178
215
|
displayName: string;
|
|
@@ -189,10 +226,7 @@ export interface CatalogHost {
|
|
|
189
226
|
*/
|
|
190
227
|
export declare function catalogHost(fafa: FafaDoc): CatalogHost | undefined;
|
|
191
228
|
/** The AI Catalog for the domain: every row above, with the host named. */
|
|
192
|
-
export declare function projectAiCatalog(fafa: FafaDoc, cards: PackCard[], opts?:
|
|
193
|
-
now?: string;
|
|
194
|
-
listFafa?: boolean;
|
|
195
|
-
}): Record<string, unknown>;
|
|
229
|
+
export declare function projectAiCatalog(fafa: FafaDoc, cards: PackCard[], opts?: CatalogRowOptions): Record<string, unknown>;
|
|
196
230
|
/**
|
|
197
231
|
* The search hints ARD reads, from the `.fafa`: `metadata.cards.keywords` and
|
|
198
232
|
* `metadata.cards.examples`. An entry with no `representativeQueries` is, in
|
|
@@ -206,19 +240,20 @@ export declare function ardHints(fafa: FafaDoc): {
|
|
|
206
240
|
/** The ARD manifest: the catalog, plus the search hints ARD reads. ARD builds
|
|
207
241
|
* on ai-catalog (spec §4), so the document is the same shape — the entries
|
|
208
242
|
* carry more. */
|
|
209
|
-
export declare function projectArd(fafa: FafaDoc, cards: PackCard[], opts?:
|
|
210
|
-
|
|
211
|
-
listFafa?: boolean;
|
|
212
|
-
}): Record<string, unknown>;
|
|
213
|
-
export interface PackOptions {
|
|
243
|
+
export declare function projectArd(fafa: FafaDoc, cards: PackCard[], opts?: CatalogRowOptions): Record<string, unknown>;
|
|
244
|
+
export interface PackOptions extends ContextBlockOptions {
|
|
214
245
|
/** Which cards to build; the `.fafa` is always written. */
|
|
215
246
|
cards: PackCard[];
|
|
216
247
|
/** `updatedAt` for catalog rows (tests); otherwise now. */
|
|
217
248
|
now?: string;
|
|
218
|
-
/** List the `.fafa` itself in the catalog and ARD manifest (it is then served
|
|
249
|
+
/** List the `.fafa` itself in the catalog and ARD manifest (it is then served
|
|
250
|
+
* at /.well-known/fafa). Default true; `false` leaves it out. */
|
|
219
251
|
listFafa?: boolean;
|
|
220
|
-
/** Extensions to put on the A2A card
|
|
252
|
+
/** Extensions to put on the A2A card, besides FAF's own (added with `faf`). */
|
|
221
253
|
a2aExtensions?: A2AExtension[];
|
|
254
|
+
/** project.faf (BEST): adds FAF's context block to the A2A card, the Server
|
|
255
|
+
* Card and server.json. Without it the cards are plain (BETTER). */
|
|
256
|
+
faf?: FafData;
|
|
222
257
|
}
|
|
223
258
|
export interface Pack {
|
|
224
259
|
fafa: FafaDoc;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { FafData } from '../core/types.js';
|
|
2
|
+
export { REGISTRY_PUBLISHER_KEY, fafContextBlock, registryMeta } from './context-block.js';
|
|
2
3
|
/**
|
|
3
4
|
* Build an MCP Server Card (SEP-2127) from a .faf.
|
|
4
5
|
*
|
|
@@ -25,27 +26,8 @@ export interface ServerCardOptions {
|
|
|
25
26
|
/** Override timestamp (tests); otherwise .faf `generated`, else now. */
|
|
26
27
|
now?: string;
|
|
27
28
|
}
|
|
28
|
-
/**
|
|
29
|
-
* The canonical FAF context-block — the value of `_meta["one.faf/context"]`,
|
|
30
|
-
* identical across every surface (Server Card, registry `server.json`, `.fafa`):
|
|
31
|
-
* one context, every door. Honest-first: no score baked (it would go stale on
|
|
32
|
-
* disk); it points to the .faf and asserts the score is deterministic.
|
|
33
|
-
*/
|
|
34
|
-
export declare function fafContextBlock(data: FafData, opts?: ServerCardOptions): Record<string, unknown>;
|
|
35
29
|
/** Build the Server Card object from .faf data. */
|
|
36
30
|
export declare function buildServerCard(data: FafData, opts?: ServerCardOptions): Record<string, unknown>;
|
|
37
|
-
export declare const REGISTRY_PUBLISHER_KEY = "io.modelcontextprotocol.registry/publisher-provided";
|
|
38
|
-
/**
|
|
39
|
-
* Build the `_meta` for an MCP Registry `server.json`.
|
|
40
|
-
*
|
|
41
|
-
* The SAME canonical context-block as the Server Card, but nested under
|
|
42
|
-
* `io.modelcontextprotocol.registry/publisher-provided` — the ONLY `_meta` key
|
|
43
|
-
* the official registry preserves on publish. Top-level keys (the way the card
|
|
44
|
-
* carries `one.faf/context`) are silently dropped by the registry. Throws if the
|
|
45
|
-
* block exceeds the registry's 4KB cap. Merge the result into an existing
|
|
46
|
-
* `server.json` `_meta`; don't regenerate the manifest (packages/mcpb are tuned).
|
|
47
|
-
*/
|
|
48
|
-
export declare function registryMeta(data: FafData, opts?: ServerCardOptions): Record<string, unknown>;
|
|
49
31
|
/** The canonical reverse-DNS registry name, e.g. `one.faf/claude-faf-mcp`.
|
|
50
32
|
*
|
|
51
33
|
* HOMEPAGE REQUIRED: the namespace is derived from `project.homepage`'s host
|
|
@@ -99,8 +81,9 @@ export interface ServerJsonIdentity {
|
|
|
99
81
|
title?: string;
|
|
100
82
|
/** A version to set (`--set-version`); when undefined the file's own is kept. */
|
|
101
83
|
version?: string;
|
|
102
|
-
/** The `_meta` faf writes ({@link registryMeta})
|
|
103
|
-
|
|
84
|
+
/** The `_meta` faf writes ({@link registryMeta}); absent for a plain
|
|
85
|
+
* registry identity from a .fafa (BETTER), which leaves `_meta` as it is. */
|
|
86
|
+
meta?: Record<string, unknown>;
|
|
104
87
|
}
|
|
105
88
|
/**
|
|
106
89
|
* Put faf's identity into the text of a registry `server.json`, changing
|