@adea-ai/plugins 1.0.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 +201 -0
- package/README.md +74 -0
- package/dist/agent-plugins-catalog.d.ts +26 -0
- package/dist/agent-plugins-catalog.js +699 -0
- package/dist/agent-plugins-catalog.js.map +1 -0
- package/dist/agent-plugins-harness.d.ts +54 -0
- package/dist/agent-plugins-harness.js +212 -0
- package/dist/agent-plugins-harness.js.map +1 -0
- package/dist/agent-plugins-schema.d.ts +402 -0
- package/dist/agent-plugins-schema.js +200 -0
- package/dist/agent-plugins-schema.js.map +1 -0
- package/dist/consumer-index.d.ts +217 -0
- package/dist/consumer-index.js +358 -0
- package/dist/consumer-index.js.map +1 -0
- package/dist/display-name.d.ts +8 -0
- package/dist/display-name.js +160 -0
- package/dist/display-name.js.map +1 -0
- package/dist/harness.d.ts +13 -0
- package/dist/harness.js +169 -0
- package/dist/harness.js.map +1 -0
- package/dist/icon-mirror.d.ts +69 -0
- package/dist/icon-mirror.js +147 -0
- package/dist/icon-mirror.js.map +1 -0
- package/dist/icons.d.ts +65 -0
- package/dist/icons.js +268 -0
- package/dist/icons.js.map +1 -0
- package/dist/index.d.ts +304 -0
- package/dist/index.js +1877 -0
- package/dist/index.js.map +1 -0
- package/dist/portable-catalog.d.ts +9 -0
- package/dist/portable-catalog.js +175 -0
- package/dist/portable-catalog.js.map +1 -0
- package/dist/publication.d.ts +98 -0
- package/dist/publication.js +121 -0
- package/dist/publication.js.map +1 -0
- package/dist/schema.d.ts +705 -0
- package/dist/schema.js +267 -0
- package/dist/schema.js.map +1 -0
- package/dist/site-icons.d.ts +55 -0
- package/dist/site-icons.js +155 -0
- package/dist/site-icons.js.map +1 -0
- package/dist/sources.d.ts +54 -0
- package/dist/sources.js +306 -0
- package/dist/sources.js.map +1 -0
- package/package.json +102 -0
- package/schemas/agent-package.v1.json +387 -0
- package/schemas/catalog.v1.schema.json +407 -0
- package/schemas/compatibility.v1.schema.json +23 -0
- package/schemas/harness-profile.v1.json +75 -0
- package/schemas/installation-plan.v2.json +695 -0
- package/schemas/sources-lock.v1.schema.json +61 -0
- package/src/agent-plugins-catalog.test.ts +402 -0
- package/src/agent-plugins-catalog.ts +800 -0
- package/src/agent-plugins-harness.test.ts +272 -0
- package/src/agent-plugins-harness.ts +281 -0
- package/src/agent-plugins-schema.test.ts +27 -0
- package/src/agent-plugins-schema.ts +219 -0
- package/src/artifacts.test.ts +545 -0
- package/src/catalog-installation.test.ts +42 -0
- package/src/consumer-index.test.ts +465 -0
- package/src/consumer-index.ts +592 -0
- package/src/display-name.test.ts +56 -0
- package/src/display-name.ts +157 -0
- package/src/harness.ts +202 -0
- package/src/icon-mirror.ts +196 -0
- package/src/icons.test.ts +185 -0
- package/src/icons.ts +297 -0
- package/src/index.test.ts +888 -0
- package/src/index.ts +2538 -0
- package/src/portable-catalog.test.ts +186 -0
- package/src/portable-catalog.ts +203 -0
- package/src/publication.test.ts +117 -0
- package/src/publication.ts +171 -0
- package/src/schema.ts +309 -0
- package/src/site-icon-fallback.test.ts +267 -0
- package/src/site-icons.test.ts +171 -0
- package/src/site-icons.ts +161 -0
- package/src/sources.ts +360 -0
- package/src/upstream-headers.test.ts +148 -0
package/dist/icons.js
ADDED
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compile-time icon resolution.
|
|
3
|
+
*
|
|
4
|
+
* Marketplaces do not declare an icon field, so a plugin's mark is a file in
|
|
5
|
+
* its own content (`assets/logo.svg`, `assets/icon-large.png`, ...). Resolving
|
|
6
|
+
* one at compile time removes a runtime guess from consumers, and mirroring the
|
|
7
|
+
* bytes at publish time removes the upstream fetch entirely.
|
|
8
|
+
*/
|
|
9
|
+
/** Icon file size ceiling; a brand mark is never a large asset. */
|
|
10
|
+
export const MAX_ICON_BYTES = 1024 * 1024;
|
|
11
|
+
const SUPPORTED_EXTENSIONS = ['svg', 'png', 'webp', 'jpg', 'jpeg', 'gif', 'ico'];
|
|
12
|
+
/** Ranked basenames; earlier entries win. Variants sort by the rank of the stem. */
|
|
13
|
+
const STEM_RANK = {
|
|
14
|
+
icon: 0,
|
|
15
|
+
appicon: 0,
|
|
16
|
+
'app-icon': 0,
|
|
17
|
+
avatar: 2,
|
|
18
|
+
logo: 3,
|
|
19
|
+
mark: 4,
|
|
20
|
+
brand: 4,
|
|
21
|
+
};
|
|
22
|
+
const EXTENSION_RANK = {
|
|
23
|
+
svg: 0,
|
|
24
|
+
png: 1,
|
|
25
|
+
webp: 2,
|
|
26
|
+
ico: 3,
|
|
27
|
+
jpg: 4,
|
|
28
|
+
jpeg: 5,
|
|
29
|
+
gif: 6,
|
|
30
|
+
};
|
|
31
|
+
/** Preferred containers, best first. Files outside these are considered last. */
|
|
32
|
+
const DIRECTORY_RANK = {
|
|
33
|
+
assets: 0,
|
|
34
|
+
'.assets': 1,
|
|
35
|
+
img: 2,
|
|
36
|
+
images: 3,
|
|
37
|
+
media: 4,
|
|
38
|
+
static: 5,
|
|
39
|
+
};
|
|
40
|
+
/** Files that are documentation, screenshots or brand collateral, not marks. */
|
|
41
|
+
const EXCLUDED = /(screenshot|screen-shot|preview|example|sample|demo|mockup|diagram|architecture|flowchart|flow-|banner|hero|cover|thumbnail|chart|graph|illustration|photo)/;
|
|
42
|
+
/** Repository infrastructure: CI images and templates, never a product mark. */
|
|
43
|
+
const EXCLUDED_DIRECTORIES = ['.github', '.gitlab'];
|
|
44
|
+
const MARK_WORDS = new Set([
|
|
45
|
+
'icon',
|
|
46
|
+
'appicon',
|
|
47
|
+
'avatar',
|
|
48
|
+
'logo',
|
|
49
|
+
'mark',
|
|
50
|
+
'brand',
|
|
51
|
+
'logomark',
|
|
52
|
+
'wordmark',
|
|
53
|
+
]);
|
|
54
|
+
const VARIANT_WORDS = new Set([
|
|
55
|
+
'large',
|
|
56
|
+
'small',
|
|
57
|
+
'light',
|
|
58
|
+
'dark',
|
|
59
|
+
'mono',
|
|
60
|
+
'white',
|
|
61
|
+
'black',
|
|
62
|
+
'positive',
|
|
63
|
+
'negative',
|
|
64
|
+
'color',
|
|
65
|
+
'colour',
|
|
66
|
+
'primary',
|
|
67
|
+
'secondary',
|
|
68
|
+
'horizontal',
|
|
69
|
+
'vertical',
|
|
70
|
+
'square',
|
|
71
|
+
'flat',
|
|
72
|
+
'glyph',
|
|
73
|
+
]);
|
|
74
|
+
/**
|
|
75
|
+
* Splits a file name into mark tokens. Separators are normalised because
|
|
76
|
+
* vendors write marks as `logo.svg`, `atlan-logo.png`, `Dynatrace_Logo_color_positive.png`
|
|
77
|
+
* or `cs logo big.png` alike.
|
|
78
|
+
*/
|
|
79
|
+
function splitName(basename) {
|
|
80
|
+
const withoutExtension = basename.slice(0, basename.lastIndexOf('.'));
|
|
81
|
+
const words = withoutExtension
|
|
82
|
+
.split(/[\s._-]+/)
|
|
83
|
+
.filter(Boolean)
|
|
84
|
+
.map((word) => word.toLowerCase());
|
|
85
|
+
const size = words.some((word) => word === 'small') ? 1 : 0;
|
|
86
|
+
const marks = words.some((word) => MARK_WORDS.has(word));
|
|
87
|
+
const stems = words.filter((word) => !MARK_WORDS.has(word) && !VARIANT_WORDS.has(word));
|
|
88
|
+
return { stems, marks, size };
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Chooses one icon file from a release's file index, deterministically.
|
|
92
|
+
*
|
|
93
|
+
* Preference: `assets/icon.svg` before `assets/icon.png` before `assets/logo.*`,
|
|
94
|
+
* an `icon`/`logo` stem before `avatar`/`mark`/`brand`, an `assets` directory
|
|
95
|
+
* before other asset directories, SVG before raster for the same stem, and a
|
|
96
|
+
* `-large` variant before `-small`. Anything that looks like documentation or a
|
|
97
|
+
* screenshot is never selected. Ties break on path so the result is stable.
|
|
98
|
+
*/
|
|
99
|
+
export function selectIconPath(fileIndex) {
|
|
100
|
+
let best = null;
|
|
101
|
+
for (const raw of fileIndex) {
|
|
102
|
+
const path = raw.replace(/^\.?\//, '');
|
|
103
|
+
if (path.includes('..'))
|
|
104
|
+
continue;
|
|
105
|
+
const segments = path.split('/');
|
|
106
|
+
const basename = segments.pop() ?? '';
|
|
107
|
+
const extension = basename.slice(basename.lastIndexOf('.') + 1).toLowerCase();
|
|
108
|
+
if (!SUPPORTED_EXTENSIONS.includes(extension))
|
|
109
|
+
continue;
|
|
110
|
+
if (EXCLUDED.test(basename))
|
|
111
|
+
continue;
|
|
112
|
+
const directories = segments.map((segment) => segment.toLowerCase());
|
|
113
|
+
if (directories.some((segment) => EXCLUDED.test(segment)))
|
|
114
|
+
continue;
|
|
115
|
+
if (directories.some((segment) => EXCLUDED_DIRECTORIES.includes(segment)))
|
|
116
|
+
continue;
|
|
117
|
+
const { stems, marks, size } = splitName(basename);
|
|
118
|
+
const single = stems.length === 1 ? stems[0] : undefined;
|
|
119
|
+
const stemRank = marks ? (single ? (STEM_RANK[single] ?? 0) : 0) : undefined;
|
|
120
|
+
const nested = directories.filter((segment) => DIRECTORY_RANK[segment] !== undefined);
|
|
121
|
+
// A mark named as one — `logo.svg`, `atlan-logo.png`, `cs_logo_large.png` —
|
|
122
|
+
// is accepted anywhere, including the plugin root. An unnamed image must sit
|
|
123
|
+
// in a known asset directory, because a bare `banner.png` at the root is as
|
|
124
|
+
// likely to be documentation as a brand mark.
|
|
125
|
+
const directoryRank = nested.length > 0
|
|
126
|
+
? (DIRECTORY_RANK[nested[nested.length - 1]] ?? 0)
|
|
127
|
+
: stemRank === undefined
|
|
128
|
+
? Number.POSITIVE_INFINITY
|
|
129
|
+
: 0;
|
|
130
|
+
if (!Number.isFinite(directoryRank))
|
|
131
|
+
continue;
|
|
132
|
+
const score = [stemRank ?? 5, directoryRank, size, EXTENSION_RANK[extension] ?? 9, path.length];
|
|
133
|
+
if (!best || compareScore(score, best.score) < 0)
|
|
134
|
+
best = { path, score };
|
|
135
|
+
}
|
|
136
|
+
return best ? best.path : null;
|
|
137
|
+
}
|
|
138
|
+
function compareScore(left, right) {
|
|
139
|
+
for (let index = 0; index < left.length; index += 1) {
|
|
140
|
+
const difference = (left[index] ?? 0) - (right[index] ?? 0);
|
|
141
|
+
if (difference !== 0)
|
|
142
|
+
return difference;
|
|
143
|
+
}
|
|
144
|
+
return 0;
|
|
145
|
+
}
|
|
146
|
+
const SVG_ACTIVE_CONTENT = /<\s*script|<\s*foreignObject|<\s*iframe|<\s*use[^>]+href\s*=\s*["']?\s*(?:https?:)?\/\/|javascript:|<!ENTITY|<!DOCTYPE[^>]+\[|on(?:load|error|click|mouseover|focus|begin)\s*=/i;
|
|
147
|
+
const SVG_EXTERNAL_REFERENCE = /(?:href|xlink:href|src|data|poster)\s*=\s*["']?\s*(?:https?:)?\/\//i;
|
|
148
|
+
/** Sniffs a supported image type from magic bytes; SVG is detected as text. */
|
|
149
|
+
export function sniffContentType(bytes) {
|
|
150
|
+
const ascii = (offset, length) => String.fromCharCode(...bytes.subarray(offset, offset + length));
|
|
151
|
+
if (bytes.length >= 8 && ascii(0, 8) === '\x89PNG\r\n\x1a\n')
|
|
152
|
+
return 'image/png';
|
|
153
|
+
if (bytes.length >= 3 && ascii(0, 3) === '\xff\xd8\xff')
|
|
154
|
+
return 'image/jpeg';
|
|
155
|
+
if (bytes.length >= 6 && ascii(0, 4) === 'GIF8')
|
|
156
|
+
return 'image/gif';
|
|
157
|
+
if (bytes.length >= 12 && ascii(0, 4) === 'RIFF' && ascii(8, 4) === 'WEBP')
|
|
158
|
+
return 'image/webp';
|
|
159
|
+
// Icon container: reserved(2), type 1 (icon) or 2 (cursor), count >= 1.
|
|
160
|
+
if (bytes.length >= 6 &&
|
|
161
|
+
bytes[0] === 0 &&
|
|
162
|
+
bytes[1] === 0 &&
|
|
163
|
+
(bytes[2] === 1 || bytes[2] === 2) &&
|
|
164
|
+
bytes[3] === 0 &&
|
|
165
|
+
((bytes[4] ?? 0) | ((bytes[5] ?? 0) << 8)) > 0)
|
|
166
|
+
return 'image/x-icon';
|
|
167
|
+
if (bytes.length > 0) {
|
|
168
|
+
// An XML prologue, a doctype and leading comments may all precede the root
|
|
169
|
+
// element: exporters such as Adobe Illustrator and Figma emit them. What
|
|
170
|
+
// matters is that the document's root element is `<svg>`, not `<html>`.
|
|
171
|
+
const head = new TextDecoder()
|
|
172
|
+
.decode(bytes.subarray(0, Math.min(bytes.length, 4096)))
|
|
173
|
+
.trimStart()
|
|
174
|
+
.replace(/^<\?xml[\s\S]*?\?>/i, '')
|
|
175
|
+
.replace(/^<!DOCTYPE[^>]*?(?:\[[\s\S]*?\])?>/i, '')
|
|
176
|
+
.replace(/^(?:\s*<!--[\s\S]*?-->)+/, '')
|
|
177
|
+
.trimStart();
|
|
178
|
+
if (/^<svg[\s>]/i.test(head))
|
|
179
|
+
return 'image/svg+xml';
|
|
180
|
+
}
|
|
181
|
+
return null;
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Verifies icon bytes before they are published.
|
|
185
|
+
*
|
|
186
|
+
* SVG is text that a browser can execute when it is inlined, so active content
|
|
187
|
+
* and external references are rejected outright. Consumers must still render a
|
|
188
|
+
* mirrored SVG through an `<img>` element and never inline it into the DOM.
|
|
189
|
+
*/
|
|
190
|
+
export function inspectIconBytes(bytes) {
|
|
191
|
+
if (bytes.length === 0)
|
|
192
|
+
return { rejected: 'EMPTY_FILE' };
|
|
193
|
+
if (bytes.length > MAX_ICON_BYTES)
|
|
194
|
+
return { rejected: 'SIZE_LIMIT_EXCEEDED' };
|
|
195
|
+
const contentType = sniffContentType(bytes);
|
|
196
|
+
if (!contentType)
|
|
197
|
+
return { rejected: 'CONTENT_TYPE_UNSUPPORTED' };
|
|
198
|
+
if (contentType === 'image/svg+xml') {
|
|
199
|
+
const text = new TextDecoder().decode(bytes);
|
|
200
|
+
if (SVG_ACTIVE_CONTENT.test(text))
|
|
201
|
+
return { rejected: 'SVG_ACTIVE_CONTENT' };
|
|
202
|
+
if (SVG_EXTERNAL_REFERENCE.test(text))
|
|
203
|
+
return { rejected: 'SVG_EXTERNAL_REFERENCE' };
|
|
204
|
+
}
|
|
205
|
+
return { contentType };
|
|
206
|
+
}
|
|
207
|
+
const EXTENSION_BY_CONTENT_TYPE = {
|
|
208
|
+
'image/png': 'png',
|
|
209
|
+
'image/jpeg': 'jpg',
|
|
210
|
+
'image/gif': 'gif',
|
|
211
|
+
'image/webp': 'webp',
|
|
212
|
+
'image/svg+xml': 'svg',
|
|
213
|
+
'image/x-icon': 'ico',
|
|
214
|
+
};
|
|
215
|
+
/**
|
|
216
|
+
* Content-addressed asset name. Release assets cannot contain `/`, so the
|
|
217
|
+
* digest prefix and extension form one flat name that any release can host.
|
|
218
|
+
*/
|
|
219
|
+
export function iconAssetName(digest, contentType) {
|
|
220
|
+
const extension = EXTENSION_BY_CONTENT_TYPE[contentType];
|
|
221
|
+
if (!extension)
|
|
222
|
+
throw new Error(`ICON_CONTENT_TYPE_UNSUPPORTED: ${contentType}`);
|
|
223
|
+
const hex = digest.startsWith('sha256:') ? digest.slice('sha256:'.length) : digest;
|
|
224
|
+
return `icon-${hex.slice(0, 32)}.${extension}`;
|
|
225
|
+
}
|
|
226
|
+
export function parseProductIconOverrides(input) {
|
|
227
|
+
if (typeof input !== 'object' || input === null)
|
|
228
|
+
throw new Error('PRODUCT_ICONS_INVALID');
|
|
229
|
+
const raw = input;
|
|
230
|
+
if (raw.schemaVersion !== 1)
|
|
231
|
+
throw new Error('PRODUCT_ICONS_INVALID');
|
|
232
|
+
const overrides = raw.overrides;
|
|
233
|
+
if (typeof overrides !== 'object' || overrides === null)
|
|
234
|
+
throw new Error('PRODUCT_ICONS_INVALID');
|
|
235
|
+
for (const [productKey, value] of Object.entries(overrides)) {
|
|
236
|
+
if (!/^[a-z0-9][a-z0-9-]{1,127}$/.test(productKey))
|
|
237
|
+
throw new Error(`PRODUCT_ICONS_KEY_INVALID: ${productKey}`);
|
|
238
|
+
if (value === null)
|
|
239
|
+
continue;
|
|
240
|
+
if (typeof value !== 'string' || value.length === 0 || value.length > 1024)
|
|
241
|
+
throw new Error(`PRODUCT_ICONS_PATH_INVALID: ${productKey}`);
|
|
242
|
+
if (value.startsWith('https://')) {
|
|
243
|
+
// Only the shape is checked here; site-icons applies the full host policy
|
|
244
|
+
// when it resolves the mark, so a bad host simply yields no icon.
|
|
245
|
+
if (!/^https:\/\/[a-z0-9.-]+\.[a-z]{2,}/i.test(value))
|
|
246
|
+
throw new Error(`PRODUCT_ICONS_SITE_UNSUPPORTED: ${productKey}`);
|
|
247
|
+
continue;
|
|
248
|
+
}
|
|
249
|
+
if (value.startsWith('/') || value.includes('..'))
|
|
250
|
+
throw new Error(`PRODUCT_ICONS_PATH_INVALID: ${productKey}`);
|
|
251
|
+
}
|
|
252
|
+
return { schemaVersion: 1, overrides: { ...overrides } };
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Reads the override for a product: `forced` names a content path or `null` to
|
|
256
|
+
* publish no mark, and `site` names a vendor site to take the mark from.
|
|
257
|
+
*/
|
|
258
|
+
export function iconOverrideFor(overrides, productKey) {
|
|
259
|
+
if (!overrides || !(productKey in overrides.overrides))
|
|
260
|
+
return undefined;
|
|
261
|
+
const value = overrides.overrides[productKey];
|
|
262
|
+
if (value === null)
|
|
263
|
+
return { forced: null };
|
|
264
|
+
if (typeof value !== 'string')
|
|
265
|
+
return undefined;
|
|
266
|
+
return value.startsWith('https://') ? { site: value } : { forced: value };
|
|
267
|
+
}
|
|
268
|
+
//# sourceMappingURL=icons.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"icons.js","sourceRoot":"","sources":["../src/icons.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
import { type Catalog, type Capability, type Harness, type HarnessCompatibility, type PluginRelease, type SourcesLock } from './schema.js';
|
|
2
|
+
import { type ParsedMarketplace, type SourceConfig } from './sources.js';
|
|
3
|
+
import { type ConsumerCategory, type ConsumerIndex, type ConsumerProduct, type LeadingDiagnostic, type ProductPreference } from './consumer-index.js';
|
|
4
|
+
import { type ProductIconOverrides } from './icons.js';
|
|
5
|
+
import { type SiteIconFetcher } from './site-icons.js';
|
|
6
|
+
/**
|
|
7
|
+
* Marks the catalog format this compiler emits.
|
|
8
|
+
*
|
|
9
|
+
* Bumping or first introducing this value makes a synchronization replay its
|
|
10
|
+
* verified pins and rebuild, which is how a format change reaches the published
|
|
11
|
+
* catalog when no upstream source has moved. It is deliberately separate from
|
|
12
|
+
* the agent-package normalizer version, which describes package normalization
|
|
13
|
+
* and would misreport a change here.
|
|
14
|
+
*/
|
|
15
|
+
export declare const CATALOG_CONTRACT_VERSION = "adea-catalog/3";
|
|
16
|
+
export interface CatalogPolicy {
|
|
17
|
+
readonly allowedRepositoryProtocols: readonly string[];
|
|
18
|
+
readonly allowedRepositoryHosts: readonly string[];
|
|
19
|
+
readonly maxFilesPerPlugin: number;
|
|
20
|
+
readonly maxBytesPerPlugin: number;
|
|
21
|
+
readonly maxFileBytes: number;
|
|
22
|
+
readonly maxMarketplacePlugins: number;
|
|
23
|
+
readonly denyExecutableLifecycleScripts: boolean;
|
|
24
|
+
readonly publishRequiresCompleteContent: boolean;
|
|
25
|
+
readonly sensitiveCapabilityTypes: readonly string[];
|
|
26
|
+
}
|
|
27
|
+
export interface CategoryMap {
|
|
28
|
+
readonly aliases: Readonly<Record<string, string>>;
|
|
29
|
+
readonly fallback: string;
|
|
30
|
+
}
|
|
31
|
+
export interface ProductAliases {
|
|
32
|
+
readonly aliases: Readonly<Record<string, string>>;
|
|
33
|
+
}
|
|
34
|
+
export interface Snapshot {
|
|
35
|
+
readonly files: ReadonlyMap<string, Uint8Array>;
|
|
36
|
+
readonly symlinks: readonly string[];
|
|
37
|
+
}
|
|
38
|
+
/** Trusted compiler extension; never loaded from upstream plugin content. */
|
|
39
|
+
export type ReleaseTransform = (release: PluginRelease, snapshot: Snapshot, pluginName: string) => PluginRelease;
|
|
40
|
+
export interface SnapshotLoader {
|
|
41
|
+
load(repositoryUrl: string, commitSha: string, pluginSubdirectory: string): Promise<Snapshot>;
|
|
42
|
+
}
|
|
43
|
+
export interface ResolvedSource {
|
|
44
|
+
readonly config: SourceConfig;
|
|
45
|
+
readonly commitSha: string;
|
|
46
|
+
readonly manifestText: string;
|
|
47
|
+
readonly parsed: ParsedMarketplace;
|
|
48
|
+
readonly pluginPins: readonly PluginSourcePin[];
|
|
49
|
+
readonly retrievedAt: string;
|
|
50
|
+
readonly manifestDigest: string;
|
|
51
|
+
}
|
|
52
|
+
export interface PluginSourcePin {
|
|
53
|
+
readonly pluginName: string;
|
|
54
|
+
readonly repositoryUrl: string;
|
|
55
|
+
readonly pluginSubdirectory: string;
|
|
56
|
+
readonly resolvedCommitSha: string;
|
|
57
|
+
}
|
|
58
|
+
export interface SyncInput extends ConsumerIndexOptions {
|
|
59
|
+
readonly sources: readonly SourceConfig[];
|
|
60
|
+
readonly categoryMap: CategoryMap;
|
|
61
|
+
readonly productAliases: ProductAliases;
|
|
62
|
+
readonly productCategories?: Record<string, string>;
|
|
63
|
+
readonly productIconOverrides?: ProductIconOverrides;
|
|
64
|
+
/** Where this catalog is published, so records carry absolute asset URLs. */
|
|
65
|
+
readonly publicationRepositoryUrl?: string;
|
|
66
|
+
/** Directory that receives mirrored brand marks as the catalog is built. */
|
|
67
|
+
readonly iconAssetsDirectory?: string;
|
|
68
|
+
readonly policy: CatalogPolicy;
|
|
69
|
+
readonly mode?: 'live' | 'offline';
|
|
70
|
+
readonly fixtureRoot?: string;
|
|
71
|
+
readonly sourceId?: string;
|
|
72
|
+
readonly metadataOnly?: boolean;
|
|
73
|
+
readonly dryRun?: boolean;
|
|
74
|
+
readonly existingLock?: SourcesLock;
|
|
75
|
+
readonly existingCatalog?: Catalog;
|
|
76
|
+
readonly fromLock?: SourcesLock;
|
|
77
|
+
readonly snapshotLoader?: SnapshotLoader;
|
|
78
|
+
readonly resolveExternalRefs?: boolean;
|
|
79
|
+
/** Rebuild even when source pins are unchanged (used for explicit format migrations). */
|
|
80
|
+
readonly forceRebuild?: boolean;
|
|
81
|
+
readonly transformRelease?: ReleaseTransform;
|
|
82
|
+
}
|
|
83
|
+
export interface SyncResult {
|
|
84
|
+
readonly changed: boolean;
|
|
85
|
+
readonly dryRun: boolean;
|
|
86
|
+
readonly sourceHeads: readonly {
|
|
87
|
+
sourceId: string;
|
|
88
|
+
commitSha: string;
|
|
89
|
+
}[];
|
|
90
|
+
readonly catalog?: Catalog;
|
|
91
|
+
readonly lock?: SourcesLock;
|
|
92
|
+
readonly artifacts?: GeneratedArtifacts;
|
|
93
|
+
readonly changeReport: ChangeReport;
|
|
94
|
+
}
|
|
95
|
+
export interface ChangeReport {
|
|
96
|
+
readonly schemaVersion: 1;
|
|
97
|
+
readonly changedSources: readonly string[];
|
|
98
|
+
readonly addedPlugins: readonly string[];
|
|
99
|
+
readonly removedPlugins: readonly string[];
|
|
100
|
+
readonly changedPlugins: readonly string[];
|
|
101
|
+
readonly permissionSensitiveChanges: readonly string[];
|
|
102
|
+
readonly skippedPlugins: readonly SkippedPlugin[];
|
|
103
|
+
readonly contentResolution: 'complete' | 'complete-with-skips' | 'metadata-only';
|
|
104
|
+
}
|
|
105
|
+
export type PluginSkipReasonCode = 'GIT_SUBMODULE_UNSUPPORTED' | 'PLUGIN_FILE_TOO_LARGE' | 'PLUGIN_FILE_UNAVAILABLE' | 'PLUGIN_MANIFEST_INVALID' | 'PLUGIN_PATH_NOT_FOUND' | 'PLUGIN_SCHEMA_INVALID' | 'PLUGIN_SIZE_POLICY' | 'PLUGIN_SOURCE_UNAVAILABLE' | 'PLUGIN_TOO_LARGE' | 'PLUGIN_TOO_MANY_FILES' | 'SNAPSHOT_PATH_INVALID' | 'SYMLINK_ESCAPE';
|
|
106
|
+
export interface SkippedPlugin {
|
|
107
|
+
readonly sourceId: string;
|
|
108
|
+
readonly pluginId: string;
|
|
109
|
+
readonly pluginName: string;
|
|
110
|
+
readonly reasonCode: PluginSkipReasonCode;
|
|
111
|
+
readonly securityReason: string;
|
|
112
|
+
readonly incompleteContent: true;
|
|
113
|
+
readonly paths: readonly string[];
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Published artifacts by file name. The core six are always present; the
|
|
117
|
+
* consumer shards (`catalog-index.v1.json`, `shelf-<category>.v1.json` and
|
|
118
|
+
* `category-<category>.v1.json`) follow the configured categories.
|
|
119
|
+
*/
|
|
120
|
+
export interface GeneratedArtifacts {
|
|
121
|
+
readonly [name: string]: string;
|
|
122
|
+
readonly 'catalog.v1.json': string;
|
|
123
|
+
readonly 'catalog-summary.v1.json': string;
|
|
124
|
+
readonly 'sources.lock.json': string;
|
|
125
|
+
readonly 'compatibility.v1.json': string;
|
|
126
|
+
readonly 'categories.v1.json': string;
|
|
127
|
+
readonly 'integrity.json': string;
|
|
128
|
+
}
|
|
129
|
+
/** Result of checking a published consumer index against its catalog. */
|
|
130
|
+
export interface ConsumerIndexVerification {
|
|
131
|
+
readonly hasConsumerIndex: boolean;
|
|
132
|
+
readonly diagnostics: readonly LeadingDiagnostic[];
|
|
133
|
+
readonly counts?: ConsumerIndex['counts'];
|
|
134
|
+
readonly topCount?: number;
|
|
135
|
+
readonly products?: Readonly<Record<string, ConsumerProduct>>;
|
|
136
|
+
readonly categories?: readonly ConsumerCategory[];
|
|
137
|
+
/** Shards the published integrity file set must carry for this index. */
|
|
138
|
+
readonly shards: readonly ShardArtifact[];
|
|
139
|
+
}
|
|
140
|
+
/** One consumer shard artifact and what it must contain. */
|
|
141
|
+
export interface ShardArtifact {
|
|
142
|
+
readonly name: string;
|
|
143
|
+
readonly kind: 'index' | 'shelf' | 'list';
|
|
144
|
+
readonly category?: string;
|
|
145
|
+
}
|
|
146
|
+
/** Consumer index inputs: curated shelves and canonical-variant placement. */
|
|
147
|
+
export interface ConsumerIndexOptions {
|
|
148
|
+
readonly leading?: Readonly<Record<string, readonly string[]>>;
|
|
149
|
+
readonly topCount?: number;
|
|
150
|
+
readonly productPreference?: ProductPreference;
|
|
151
|
+
/**
|
|
152
|
+
* Where this catalog is published. When known, product records carry an
|
|
153
|
+
* absolute, immutable URL for their brand mark so no client composes one.
|
|
154
|
+
*/
|
|
155
|
+
readonly publicationRepositoryUrl?: string;
|
|
156
|
+
/**
|
|
157
|
+
* Base URL of the committed asset directory that browsers fetch directly.
|
|
158
|
+
*
|
|
159
|
+
* GitHub release assets answer a cross-origin `fetch` with no CORS header and
|
|
160
|
+
* redirect through a URL that cannot be cached, so a browser neither reads the
|
|
161
|
+
* index nor reuses an icon. The same files served from the repository are
|
|
162
|
+
* CORS-enabled, direct and cacheable.
|
|
163
|
+
*/
|
|
164
|
+
readonly publicationAssetsBaseUrl?: string;
|
|
165
|
+
/**
|
|
166
|
+
* Base URL of the content-addressed snapshot directory, one level below the
|
|
167
|
+
* asset branch. Catalog artifacts are addressed by catalog identity, so they
|
|
168
|
+
* live in `catalogs/<catalogId>/` while digest-addressed brand marks sit at
|
|
169
|
+
* the branch root.
|
|
170
|
+
*/
|
|
171
|
+
readonly publicationCatalogsBaseUrl?: string;
|
|
172
|
+
/**
|
|
173
|
+
* Whether curated-name drift is published in the consumer index. An offline
|
|
174
|
+
* build replays fixtures rather than the upstream catalogs, so its curation
|
|
175
|
+
* findings are noise and are omitted by default.
|
|
176
|
+
*/
|
|
177
|
+
readonly curationDiagnostics?: boolean;
|
|
178
|
+
}
|
|
179
|
+
export declare function canonicalJson(value: unknown): string;
|
|
180
|
+
export declare function digest(value: unknown): string;
|
|
181
|
+
export declare function bytesDigest(files: ReadonlyMap<string, Uint8Array>): string;
|
|
182
|
+
export declare function stablePluginId(sourceId: string, upstreamName: string): string;
|
|
183
|
+
export declare function stableReleaseId(repositoryUrl: string, subdirectory: string, commitSha: string, contentDigest: string): string;
|
|
184
|
+
export declare function normalizeCategory(value: string, map: CategoryMap): string;
|
|
185
|
+
export declare function productGroupingKey(name: string, aliases: ProductAliases): string;
|
|
186
|
+
export declare function synchronize(input: SyncInput): Promise<SyncResult>;
|
|
187
|
+
export declare function buildCatalog(input: {
|
|
188
|
+
readonly resolvedSources: readonly ResolvedSource[];
|
|
189
|
+
readonly categoryMap: CategoryMap;
|
|
190
|
+
readonly productAliases: ProductAliases;
|
|
191
|
+
readonly productCategories?: Record<string, string>;
|
|
192
|
+
readonly leading?: Record<string, readonly string[]>;
|
|
193
|
+
readonly productIconOverrides?: ProductIconOverrides;
|
|
194
|
+
readonly iconAssetsDirectory?: string;
|
|
195
|
+
readonly policy?: CatalogPolicy;
|
|
196
|
+
readonly metadataOnly?: boolean;
|
|
197
|
+
readonly snapshotLoader: SnapshotLoader;
|
|
198
|
+
readonly resolveExternalRefs?: boolean;
|
|
199
|
+
readonly transformRelease?: ReleaseTransform;
|
|
200
|
+
}): Promise<Catalog>;
|
|
201
|
+
/** SHA-256 of a single byte buffer, in the catalog's digest format. */
|
|
202
|
+
export declare function byteDigest(bytes: Uint8Array): string;
|
|
203
|
+
export declare function classifyCapabilities(files: ReadonlyMap<string, Uint8Array>, metadata?: Record<string, unknown>): Capability[];
|
|
204
|
+
export declare function createCompatibility(dialect: MarketplaceDialectName, capabilities: readonly Capability[], policy?: CatalogPolicy): Record<Harness, HarnessCompatibility>;
|
|
205
|
+
type MarketplaceDialectName = 'openai' | 'cursor' | 'claude';
|
|
206
|
+
/**
|
|
207
|
+
* Orders plugins so each category's curated leading products come first, in
|
|
208
|
+
* the configured order. Consumers preview the head of each category, so this
|
|
209
|
+
* ordering decides what users see before expanding.
|
|
210
|
+
*/
|
|
211
|
+
export declare function orderLeadingPlugins<T extends {
|
|
212
|
+
readonly plugins: readonly {
|
|
213
|
+
categories: readonly string[];
|
|
214
|
+
upstreamPluginName: string;
|
|
215
|
+
}[];
|
|
216
|
+
}>(catalog: T, leading?: Record<string, readonly string[]>): T;
|
|
217
|
+
export declare function createArtifacts(catalog: Catalog, lock: SourcesLock, options?: ConsumerIndexOptions): GeneratedArtifacts;
|
|
218
|
+
export interface PublishedAsset {
|
|
219
|
+
readonly name: string;
|
|
220
|
+
readonly digest: string;
|
|
221
|
+
readonly bytes: number;
|
|
222
|
+
readonly contentType: string;
|
|
223
|
+
/** `content` mirrors a plugin file; `favicon` mirrors the product site's icon. */
|
|
224
|
+
readonly kind: 'content' | 'favicon';
|
|
225
|
+
/** Upstream path or URL the bytes came from, for provenance. */
|
|
226
|
+
readonly origin: string;
|
|
227
|
+
}
|
|
228
|
+
/** Every mirrored icon in the catalog, deduplicated by asset name. */
|
|
229
|
+
export declare function iconAssets(index: ConsumerIndex): readonly PublishedAsset[];
|
|
230
|
+
export declare function writeArtifacts(generatedDirectory: string, artifacts: GeneratedArtifacts): Promise<void>;
|
|
231
|
+
export declare function verifyArtifacts(artifacts: GeneratedArtifacts): void;
|
|
232
|
+
/**
|
|
233
|
+
* Re-checks one consumer shard against the navigation index: a shelf carries
|
|
234
|
+
* exactly the curated products in order, and a category list carries exactly
|
|
235
|
+
* the category's products in order.
|
|
236
|
+
*/
|
|
237
|
+
export declare function verifyShardArtifact(shard: ShardArtifact, content: string | undefined, verification: ConsumerIndexVerification): void;
|
|
238
|
+
/**
|
|
239
|
+
* Re-checks the published consumer index against the catalog it indexes. The
|
|
240
|
+
* index is what Adea renders directly, so a contradiction between the two
|
|
241
|
+
* artifacts must never reach a release. Snapshots published before the index
|
|
242
|
+
* existed carry membership only; those are still membership-checked and
|
|
243
|
+
* reported as `hasConsumerIndex: false`.
|
|
244
|
+
*/
|
|
245
|
+
export declare function verifyConsumerIndex(content: string, catalog: Pick<Catalog, 'plugins'>, indexContent?: string): ConsumerIndexVerification;
|
|
246
|
+
export declare function verifyCatalogReferences(catalog: Catalog, policy?: CatalogPolicy): void;
|
|
247
|
+
/** Raw content URL for one file at an immutable commit. */
|
|
248
|
+
export declare function rawContentUrl(repositoryUrl: string, commitSha: string, path: string): string;
|
|
249
|
+
/** Fetches bytes from an allow-listed upstream URL with the shared retry policy. */
|
|
250
|
+
export declare function fetchUpstreamBytes(url: string, signal?: AbortSignal): Promise<Uint8Array>;
|
|
251
|
+
/**
|
|
252
|
+
* Request headers for one upstream URL.
|
|
253
|
+
*
|
|
254
|
+
* The credential and GitHub's media type are attached only for GitHub hosts.
|
|
255
|
+
* Sending them elsewhere is not merely a needless disclosure: `appwrite.io`
|
|
256
|
+
* answers a page carrying an `Authorization` header with HTTP 500, and a CDN
|
|
257
|
+
* asked for an image with `accept: application/vnd.github+json` can answer with
|
|
258
|
+
* bytes that are not the mark. A build that did this dropped marks it had
|
|
259
|
+
* already curated, and the curation verifier — which used its own anonymous
|
|
260
|
+
* headers — could not see it.
|
|
261
|
+
*/
|
|
262
|
+
export declare function upstreamRequestHeaders(url: string): Record<string, string>;
|
|
263
|
+
/**
|
|
264
|
+
* Fetches vendor-site documents exactly as a live build does.
|
|
265
|
+
*
|
|
266
|
+
* Shared with the curation verifier so both ask a vendor the same question: a
|
|
267
|
+
* verifier with its own headers reports sites healthy that the build then fails
|
|
268
|
+
* to resolve.
|
|
269
|
+
*
|
|
270
|
+
* `deadline` optionally bounds one product's whole resolution. The per-request
|
|
271
|
+
* ceiling is always created fresh inside each fetch, so a caller that passes a
|
|
272
|
+
* deadline — or shares one — can never hand later requests an already-expired
|
|
273
|
+
* signal.
|
|
274
|
+
*/
|
|
275
|
+
export declare function createSiteIconFetcher(deadline?: AbortSignal): SiteIconFetcher;
|
|
276
|
+
/** Ceiling for a single product-site request during icon discovery. */
|
|
277
|
+
export declare const SITE_FETCH_TIMEOUT_MS = 15000;
|
|
278
|
+
/**
|
|
279
|
+
* Read one GitHub repository tarball into path -> bytes.
|
|
280
|
+
*
|
|
281
|
+
* GitHub wraps every entry in a single top-level `<repo>-<sha>/` directory,
|
|
282
|
+
* which is stripped so the keys match the tree API's repository-relative
|
|
283
|
+
* paths. Only regular files are taken: directories, symlinks, hardlinks and
|
|
284
|
+
* the `pax_global_header` record are skipped, so a link can never be
|
|
285
|
+
* materialized as content. Every remaining path goes through
|
|
286
|
+
* `safeRelativePath`, so an archive that tries to escape the repository is
|
|
287
|
+
* rejected rather than partially trusted.
|
|
288
|
+
*/
|
|
289
|
+
export declare function readArchiveFiles(archive: Uint8Array, policy: CatalogPolicy): Promise<Map<string, Uint8Array>>;
|
|
290
|
+
export declare class NetworkSnapshotLoader implements SnapshotLoader {
|
|
291
|
+
#private;
|
|
292
|
+
constructor(policy: CatalogPolicy);
|
|
293
|
+
load(repositoryUrl: string, commitSha: string, pluginSubdirectory: string): Promise<Snapshot>;
|
|
294
|
+
}
|
|
295
|
+
export declare class FixtureSnapshotLoader implements SnapshotLoader {
|
|
296
|
+
#private;
|
|
297
|
+
constructor(root: string, sources: readonly SourceConfig[]);
|
|
298
|
+
load(repositoryUrl: string, _commitSha: string, pluginSubdirectory: string): Promise<Snapshot>;
|
|
299
|
+
}
|
|
300
|
+
export declare class DirectorySnapshotLoader implements SnapshotLoader {
|
|
301
|
+
load(_repositoryUrl: string, _commitSha: string, pluginSubdirectory: string): Promise<Snapshot>;
|
|
302
|
+
}
|
|
303
|
+
export declare function snapshotFromDirectory(root: string, pluginSubdirectory: string): Promise<Snapshot>;
|
|
304
|
+
export {};
|