@adea-ai/plugins 4.0.1 → 4.0.6
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/dist/agent-plugins-catalog.d.ts +2 -4
- package/dist/agent-plugins-catalog.js +42 -50
- package/dist/agent-plugins-catalog.js.map +1 -1
- package/dist/agent-plugins-schema.d.ts +8 -0
- package/dist/agent-plugins-schema.js +10 -1
- package/dist/agent-plugins-schema.js.map +1 -1
- package/dist/artifacts.d.ts +57 -0
- package/dist/artifacts.js +159 -0
- package/dist/artifacts.js.map +1 -0
- package/dist/build.d.ts +20 -0
- package/dist/build.js +103 -0
- package/dist/build.js.map +1 -0
- package/dist/capabilities.d.ts +7 -0
- package/dist/capabilities.js +116 -0
- package/dist/capabilities.js.map +1 -0
- package/dist/catalog-store.d.ts +0 -5
- package/dist/catalog-store.js +1 -25
- package/dist/catalog-store.js.map +1 -1
- package/dist/concurrency.d.ts +1 -0
- package/dist/concurrency.js +15 -0
- package/dist/concurrency.js.map +1 -0
- package/dist/consumer-index.d.ts +6 -28
- package/dist/consumer-index.js +7 -8
- package/dist/consumer-index.js.map +1 -1
- package/dist/digest.d.ts +13 -0
- package/dist/digest.js +47 -0
- package/dist/digest.js.map +1 -0
- package/dist/fs-atomic.d.ts +7 -0
- package/dist/fs-atomic.js +30 -0
- package/dist/fs-atomic.js.map +1 -0
- package/dist/harness.js +2 -1
- package/dist/harness.js.map +1 -1
- package/dist/icon-mirror.d.ts +3 -2
- package/dist/icon-mirror.js +51 -63
- package/dist/icon-mirror.js.map +1 -1
- package/dist/icons.d.ts +2 -2
- package/dist/icons.js +4 -12
- package/dist/icons.js.map +1 -1
- package/dist/index.d.ts +16 -315
- package/dist/index.js +12 -1905
- package/dist/index.js.map +1 -1
- package/dist/integrity-manifest.d.ts +43 -13
- package/dist/integrity-manifest.js +28 -17
- package/dist/integrity-manifest.js.map +1 -1
- package/dist/json-values.d.ts +3 -0
- package/dist/json-values.js +10 -0
- package/dist/json-values.js.map +1 -0
- package/dist/plugin-release.d.ts +38 -0
- package/dist/plugin-release.js +321 -0
- package/dist/plugin-release.js.map +1 -0
- package/dist/plugin-skips.d.ts +19 -0
- package/dist/plugin-skips.js +65 -0
- package/dist/plugin-skips.js.map +1 -0
- package/dist/policy.d.ts +13 -0
- package/dist/policy.js +26 -0
- package/dist/policy.js.map +1 -0
- package/dist/portable-catalog.d.ts +4 -4
- package/dist/portable-catalog.js +14 -126
- package/dist/portable-catalog.js.map +1 -1
- package/dist/portable-verify.d.ts +2 -0
- package/dist/portable-verify.js +68 -0
- package/dist/portable-verify.js.map +1 -0
- package/dist/publication.d.ts +6 -3
- package/dist/publication.js +25 -12
- package/dist/publication.js.map +1 -1
- package/dist/published-output.d.ts +17 -0
- package/dist/published-output.js +49 -0
- package/dist/published-output.js.map +1 -0
- package/dist/site-icons.d.ts +2 -3
- package/dist/site-icons.js +4 -3
- package/dist/site-icons.js.map +1 -1
- package/dist/snapshots.d.ts +39 -0
- package/dist/snapshots.js +238 -0
- package/dist/snapshots.js.map +1 -0
- package/dist/source-resolution.d.ts +28 -0
- package/dist/source-resolution.js +158 -0
- package/dist/source-resolution.js.map +1 -0
- package/dist/sources.d.ts +5 -1
- package/dist/sources.js +21 -27
- package/dist/sources.js.map +1 -1
- package/dist/synchronize.d.ts +44 -0
- package/dist/synchronize.js +118 -0
- package/dist/synchronize.js.map +1 -0
- package/dist/taxonomy.d.ts +23 -0
- package/dist/taxonomy.js +62 -0
- package/dist/taxonomy.js.map +1 -0
- package/dist/upstream.d.ts +42 -0
- package/dist/upstream.js +179 -0
- package/dist/upstream.js.map +1 -0
- package/dist/verify-artifacts.d.ts +36 -0
- package/dist/verify-artifacts.js +286 -0
- package/dist/verify-artifacts.js.map +1 -0
- package/native/build-provenance.txt +5 -5
- package/native/staged-reader-win32-arm64.node +0 -0
- package/native/staged-reader-win32-x64.node +0 -0
- package/package.json +2 -4
- package/src/agent-plugins-catalog.test.ts +2 -2
- package/src/agent-plugins-catalog.ts +46 -49
- package/src/agent-plugins-schema.ts +11 -1
- package/src/artifacts.ts +234 -0
- package/src/build.ts +131 -0
- package/src/capabilities.ts +153 -0
- package/src/catalog-store.ts +1 -28
- package/src/concurrency.ts +19 -0
- package/src/consumer-index.test.ts +27 -21
- package/src/consumer-index.ts +12 -35
- package/src/digest.ts +55 -0
- package/src/fs-atomic.ts +32 -0
- package/src/harness.test.ts +4 -32
- package/src/harness.ts +2 -1
- package/src/icon-mirror.ts +57 -64
- package/src/icons.test.ts +0 -4
- package/src/icons.ts +4 -4
- package/src/index.test.ts +52 -48
- package/src/index.ts +50 -2583
- package/src/integrity-manifest.ts +41 -21
- package/src/json-values.ts +11 -0
- package/src/plugin-release.ts +457 -0
- package/src/plugin-skips.ts +110 -0
- package/src/policy.ts +39 -0
- package/src/portable-catalog.test.ts +0 -5
- package/src/portable-catalog.ts +16 -143
- package/src/portable-verify.ts +71 -0
- package/src/publication.test.ts +29 -1
- package/src/publication.ts +32 -13
- package/src/published-output.ts +60 -0
- package/src/site-icons.test.ts +0 -1
- package/src/site-icons.ts +4 -4
- package/src/snapshots.ts +287 -0
- package/src/source-digest.test.ts +3 -7
- package/src/source-resolution.ts +233 -0
- package/src/sources-json.test.ts +0 -1
- package/src/sources.ts +27 -33
- package/src/synchronize.ts +213 -0
- package/src/taxonomy.ts +87 -0
- package/src/upstream.ts +194 -0
- package/src/verify-artifacts.ts +365 -0
- package/src/write-artifacts.test.ts +0 -1
- package/dist/source-digest.d.ts +0 -2
- package/dist/source-digest.js +0 -12
- package/dist/source-digest.js.map +0 -1
- package/src/source-digest.ts +0 -14
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
import { parseIntegrityManifest, publishedAssetOf, } from './integrity-manifest.js';
|
|
2
|
+
import { CATALOG_INDEX_ARTIFACT, iconCoverage, } from './consumer-index.js';
|
|
3
|
+
import { digest } from './digest.js';
|
|
4
|
+
import { assertRepositoryAllowed, DEFAULT_POLICY } from './policy.js';
|
|
5
|
+
import { CatalogSchema, SourcesLockSchema } from './schema.js';
|
|
6
|
+
import { safeRelativePath } from './sources.js';
|
|
7
|
+
export function verifyArtifacts(artifacts) {
|
|
8
|
+
const parsedCatalog = CatalogSchema.parse(JSON.parse(artifacts['catalog.v1.json']));
|
|
9
|
+
verifyCatalogReferences(parsedCatalog);
|
|
10
|
+
const lock = SourcesLockSchema.parse(JSON.parse(artifacts['sources.lock.json']));
|
|
11
|
+
const summary = JSON.parse(artifacts['catalog-summary.v1.json']);
|
|
12
|
+
const compatibility = JSON.parse(artifacts['compatibility.v1.json']);
|
|
13
|
+
const categories = JSON.parse(artifacts['categories.v1.json']);
|
|
14
|
+
const integrity = parseIntegrityManifest(JSON.parse(artifacts['integrity.json']));
|
|
15
|
+
if (parsedCatalog.sources.length !== lock.sources.length)
|
|
16
|
+
throw new Error('INTEGRITY_SOURCE_COUNT_MISMATCH');
|
|
17
|
+
if (summary.schemaVersion !== 1 ||
|
|
18
|
+
summary.catalogId !== parsedCatalog.catalogId ||
|
|
19
|
+
summary.sourceCount !== parsedCatalog.sources.length ||
|
|
20
|
+
summary.pluginCount !== parsedCatalog.plugins.length ||
|
|
21
|
+
!Array.isArray(summary.search) ||
|
|
22
|
+
compatibility.schemaVersion !== 1 ||
|
|
23
|
+
compatibility.catalogId !== parsedCatalog.catalogId ||
|
|
24
|
+
!Array.isArray(compatibility.plugins) ||
|
|
25
|
+
compatibility.plugins.length !== parsedCatalog.plugins.length ||
|
|
26
|
+
categories.schemaVersion !== 1 ||
|
|
27
|
+
categories.catalogId !== parsedCatalog.catalogId ||
|
|
28
|
+
!Array.isArray(categories.categories) ||
|
|
29
|
+
(categories.products !== undefined &&
|
|
30
|
+
(typeof categories.products !== 'object' || categories.products === null)) ||
|
|
31
|
+
(categories.diagnostics !== undefined && !Array.isArray(categories.diagnostics)) ||
|
|
32
|
+
integrity.catalogId !== parsedCatalog.catalogId) {
|
|
33
|
+
throw new Error('INTEGRITY_ARTIFACT_METADATA_MISMATCH');
|
|
34
|
+
}
|
|
35
|
+
// The published file set is exactly what integrity.json enumerates, so the
|
|
36
|
+
// shards can grow with the category configuration without a fixed list here.
|
|
37
|
+
for (const name of Object.keys(artifacts))
|
|
38
|
+
if (name !== 'integrity.json' && integrity.files[name] === undefined)
|
|
39
|
+
throw new Error(`INTEGRITY_FILE_SET_MISMATCH: ${name}`);
|
|
40
|
+
for (const [name, expected] of Object.entries(integrity.files)) {
|
|
41
|
+
const content = artifacts[name];
|
|
42
|
+
if (content === undefined)
|
|
43
|
+
throw new Error(`INTEGRITY_FILE_SET_MISMATCH: ${name}`);
|
|
44
|
+
if (digest(content) !== expected)
|
|
45
|
+
throw new Error(`INTEGRITY_DIGEST_MISMATCH: ${name}`);
|
|
46
|
+
}
|
|
47
|
+
const indexArtifact = artifacts[CATALOG_INDEX_ARTIFACT];
|
|
48
|
+
const verification = verifyConsumerIndex(artifacts['categories.v1.json'], parsedCatalog, indexArtifact);
|
|
49
|
+
if (verification.hasConsumerIndex && indexArtifact === undefined)
|
|
50
|
+
throw new Error(`SHARD_MISSING: ${CATALOG_INDEX_ARTIFACT}`);
|
|
51
|
+
for (const shard of verification.shards)
|
|
52
|
+
verifyShardArtifact(shard, artifacts[shard.name], verification, parsedCatalog.catalogId);
|
|
53
|
+
verifyIconAssets(integrity.assets ?? [], verification);
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Re-checks one consumer shard against the navigation index: a shelf carries
|
|
57
|
+
* exactly the curated products in order, and a category list carries exactly
|
|
58
|
+
* the category's products in order. The expected catalog ID must come from a
|
|
59
|
+
* separately verified catalog, not from the shard being checked.
|
|
60
|
+
*/
|
|
61
|
+
export function verifyShardArtifact(shard, content, verification, catalogId) {
|
|
62
|
+
if (!CatalogSchema.shape.catalogId.safeParse(catalogId).success)
|
|
63
|
+
throw new Error('SHARD_CATALOG_ID_REQUIRED');
|
|
64
|
+
if (content === undefined)
|
|
65
|
+
throw new Error(`SHARD_MISSING: ${shard.name}`);
|
|
66
|
+
const parsed = JSON.parse(content);
|
|
67
|
+
if (parsed.schemaVersion !== 1 ||
|
|
68
|
+
parsed.catalogId !== catalogId ||
|
|
69
|
+
(shard.kind !== 'index' && parsed.category !== shard.category))
|
|
70
|
+
throw new Error(`SHARD_IDENTITY_MISMATCH: ${shard.name}`);
|
|
71
|
+
const products = shard.kind === 'index'
|
|
72
|
+
? Object.values((parsed.products ?? {}))
|
|
73
|
+
: parsed.products;
|
|
74
|
+
if (!Array.isArray(products))
|
|
75
|
+
throw new Error(`SHARD_PRODUCTS_INVALID: ${shard.name}`);
|
|
76
|
+
const keys = products.map((product) => product.productKey);
|
|
77
|
+
if (new Set(keys).size !== keys.length)
|
|
78
|
+
throw new Error(`SHARD_DUPLICATE_PRODUCT: ${shard.name}`);
|
|
79
|
+
if (shard.kind === 'index') {
|
|
80
|
+
const expected = Object.keys(verification.products ?? {}).toSorted();
|
|
81
|
+
if (keys.toSorted().join('\n') !== expected.join('\n'))
|
|
82
|
+
throw new Error('SHARD_INDEX_MEMBERSHIP_MISMATCH');
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
const category = verification.categories?.find((item) => item.category === shard.category);
|
|
86
|
+
if (!category)
|
|
87
|
+
throw new Error(`SHARD_CATEGORY_UNKNOWN: ${shard.name}`);
|
|
88
|
+
const expected = shard.kind === 'shelf' ? category.topProductKeys : category.productKeys;
|
|
89
|
+
if (keys.join('\n') !== expected.join('\n'))
|
|
90
|
+
throw new Error(`SHARD_ORDER_MISMATCH: ${shard.name}`);
|
|
91
|
+
for (const product of products) {
|
|
92
|
+
const index = verification.products?.[product.productKey];
|
|
93
|
+
if (!index || digest(index) !== digest(product))
|
|
94
|
+
throw new Error(`SHARD_PRODUCT_MISMATCH: ${shard.name}: ${product.productKey}`);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
function verifyIconAssets(declared, verification) {
|
|
98
|
+
const referenced = new Map();
|
|
99
|
+
for (const product of Object.values(verification.products ?? {})) {
|
|
100
|
+
if (!product.icon)
|
|
101
|
+
continue;
|
|
102
|
+
const existing = referenced.get(product.icon.asset);
|
|
103
|
+
if (existing && existing.digest !== product.icon.digest)
|
|
104
|
+
throw new Error(`ICON_ASSET_DIGEST_CONFLICT: ${product.icon.asset}`);
|
|
105
|
+
referenced.set(product.icon.asset, publishedAssetOf(product.icon));
|
|
106
|
+
}
|
|
107
|
+
if (declared.length !== referenced.size)
|
|
108
|
+
throw new Error('INTEGRITY_ASSET_SET_MISMATCH');
|
|
109
|
+
for (const asset of declared) {
|
|
110
|
+
const expected = referenced.get(asset.name);
|
|
111
|
+
if (!expected)
|
|
112
|
+
throw new Error(`INTEGRITY_ASSET_UNDECLARED: ${asset.name}`);
|
|
113
|
+
if (expected.digest !== asset.digest ||
|
|
114
|
+
expected.bytes !== asset.bytes ||
|
|
115
|
+
expected.contentType !== asset.contentType ||
|
|
116
|
+
expected.kind !== asset.kind ||
|
|
117
|
+
expected.origin !== asset.origin)
|
|
118
|
+
throw new Error(`INTEGRITY_ASSET_MISMATCH: ${asset.name}`);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Re-checks the published consumer index against the catalog it indexes. The
|
|
123
|
+
* index is what Adea renders directly, so a contradiction between the two
|
|
124
|
+
* artifacts must never reach a release. Snapshots published before the index
|
|
125
|
+
* existed carry membership only; those are still membership-checked and
|
|
126
|
+
* reported as `hasConsumerIndex: false`.
|
|
127
|
+
*/
|
|
128
|
+
export function verifyConsumerIndex(content, catalog, indexContent) {
|
|
129
|
+
const index = JSON.parse(content);
|
|
130
|
+
const knownPlugins = new Map(catalog.plugins.map((plugin) => [plugin.pluginId, plugin]));
|
|
131
|
+
// Products live in the index shard; the navigation artifact only points at it.
|
|
132
|
+
const shard = indexContent ? JSON.parse(indexContent) : undefined;
|
|
133
|
+
const products = shard && typeof shard.products === 'object' && shard.products !== null
|
|
134
|
+
? shard.products
|
|
135
|
+
: typeof index.products === 'object' && index.products !== null
|
|
136
|
+
? index.products
|
|
137
|
+
: undefined;
|
|
138
|
+
const diagnostics = Array.isArray(index.diagnostics) ? index.diagnostics : [];
|
|
139
|
+
for (const category of index.categories ?? []) {
|
|
140
|
+
const members = catalog.plugins.filter((plugin) => plugin.categories.includes(category.category));
|
|
141
|
+
if (category.pluginCount !== undefined && category.pluginCount !== members.length)
|
|
142
|
+
throw new Error(`CONSUMER_INDEX_PLUGIN_COUNT_MISMATCH: ${category.category}`);
|
|
143
|
+
if (category.pluginIds.length !== members.length)
|
|
144
|
+
throw new Error(`CONSUMER_INDEX_PLUGIN_LIST_MISMATCH: ${category.category}`);
|
|
145
|
+
if (new Set(category.pluginIds).size !== category.pluginIds.length)
|
|
146
|
+
throw new Error(`CONSUMER_INDEX_DUPLICATE_PLUGIN: ${category.category}`);
|
|
147
|
+
for (const pluginId of category.pluginIds) {
|
|
148
|
+
const plugin = knownPlugins.get(pluginId);
|
|
149
|
+
if (!plugin || !plugin.categories.includes(category.category))
|
|
150
|
+
throw new Error(`CONSUMER_INDEX_FOREIGN_PLUGIN: ${category.category}: ${pluginId}`);
|
|
151
|
+
}
|
|
152
|
+
if (!products)
|
|
153
|
+
continue;
|
|
154
|
+
if (category.productKeys === undefined || category.topProductKeys === undefined)
|
|
155
|
+
throw new Error(`CONSUMER_INDEX_PRODUCTS_INCOMPLETE: ${category.category}`);
|
|
156
|
+
if (new Set(category.productKeys).size !== category.productKeys.length)
|
|
157
|
+
throw new Error(`CONSUMER_INDEX_DUPLICATE_PRODUCT: ${category.category}`);
|
|
158
|
+
for (const productKey of category.productKeys) {
|
|
159
|
+
const product = products[productKey];
|
|
160
|
+
if (!product)
|
|
161
|
+
throw new Error(`CONSUMER_INDEX_UNKNOWN_PRODUCT: ${productKey}`);
|
|
162
|
+
if (!product.categories.includes(category.category))
|
|
163
|
+
throw new Error(`CONSUMER_INDEX_PRODUCT_CATEGORY_MISMATCH: ${productKey}`);
|
|
164
|
+
}
|
|
165
|
+
if (category.productCount !== category.productKeys.length)
|
|
166
|
+
throw new Error(`CONSUMER_INDEX_PRODUCT_COUNT_MISMATCH: ${category.category}`);
|
|
167
|
+
const topCount = index.topCount;
|
|
168
|
+
if (topCount === undefined || !Number.isInteger(topCount) || topCount < 0)
|
|
169
|
+
throw new Error('CONSUMER_INDEX_TOP_COUNT_INVALID');
|
|
170
|
+
if (category.topProductKeys.length > topCount)
|
|
171
|
+
throw new Error(`CONSUMER_INDEX_TOP_OVERFLOW: ${category.category}`);
|
|
172
|
+
const shelved = new Set();
|
|
173
|
+
for (const product of Object.values(products)) {
|
|
174
|
+
// Indexes published before the install facts existed carry no `release`,
|
|
175
|
+
// and are still valid; a record that does carry one must agree with the
|
|
176
|
+
// catalog it claims to describe.
|
|
177
|
+
if (product.release) {
|
|
178
|
+
const plugin = knownPlugins.get(product.pluginId);
|
|
179
|
+
const release = plugin?.availableReleases.find((candidate) => candidate.releaseId === plugin.currentReleaseId);
|
|
180
|
+
if (!plugin ||
|
|
181
|
+
!release ||
|
|
182
|
+
product.release.releaseId !== release.releaseId ||
|
|
183
|
+
product.release.canonicalContentDigest !== release.canonicalContentDigest ||
|
|
184
|
+
product.release.sourceRevision !== release.resolvedCommitSha ||
|
|
185
|
+
product.provenance?.resolvedCommitSha !== release.resolvedCommitSha)
|
|
186
|
+
throw new Error(`CONSUMER_INDEX_RELEASE_MISMATCH: ${product.productKey}`);
|
|
187
|
+
}
|
|
188
|
+
const icon = product.icon;
|
|
189
|
+
if (!icon?.assetUrl)
|
|
190
|
+
continue;
|
|
191
|
+
if (!icon.assetUrl.startsWith('https://') || !icon.assetUrl.endsWith(`/${icon.asset}`))
|
|
192
|
+
throw new Error(`CONSUMER_INDEX_ASSET_URL_INVALID: ${icon.asset}`);
|
|
193
|
+
}
|
|
194
|
+
for (const productKey of category.topProductKeys) {
|
|
195
|
+
if (!category.productKeys.includes(productKey))
|
|
196
|
+
throw new Error(`CONSUMER_INDEX_TOP_NOT_MEMBER: ${category.category}: ${productKey}`);
|
|
197
|
+
if (shelved.has(productKey))
|
|
198
|
+
throw new Error(`CONSUMER_INDEX_TOP_REPEATED: ${productKey}`);
|
|
199
|
+
shelved.add(productKey);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
if (products) {
|
|
203
|
+
// A product headlines one category only, so no product is shelved twice.
|
|
204
|
+
const claimed = new Set();
|
|
205
|
+
for (const category of index.categories ?? [])
|
|
206
|
+
for (const productKey of category.topProductKeys ?? []) {
|
|
207
|
+
if (claimed.has(productKey))
|
|
208
|
+
throw new Error(`CONSUMER_INDEX_TOP_CROSS_CATEGORY: ${productKey}`);
|
|
209
|
+
claimed.add(productKey);
|
|
210
|
+
}
|
|
211
|
+
for (const [productKey, product] of Object.entries(products)) {
|
|
212
|
+
if (productKey !== product.productKey)
|
|
213
|
+
throw new Error('CONSUMER_INDEX_PRODUCT_KEY_MISMATCH');
|
|
214
|
+
if (product.variantPluginIds[0] !== product.pluginId)
|
|
215
|
+
throw new Error(`CONSUMER_INDEX_CANONICAL_NOT_FIRST: ${productKey}`);
|
|
216
|
+
const variants = new Set(product.variantPluginIds.map((pluginId) => {
|
|
217
|
+
const plugin = knownPlugins.get(pluginId);
|
|
218
|
+
if (!plugin)
|
|
219
|
+
throw new Error(`CONSUMER_INDEX_UNKNOWN_PLUGIN: ${pluginId}`);
|
|
220
|
+
if (plugin.productGroupingKey !== productKey)
|
|
221
|
+
throw new Error(`CONSUMER_INDEX_VARIANT_PRODUCT_MISMATCH: ${pluginId}`);
|
|
222
|
+
return pluginId;
|
|
223
|
+
}));
|
|
224
|
+
if (variants.size !== product.variantPluginIds.length)
|
|
225
|
+
throw new Error(`CONSUMER_INDEX_DUPLICATE_VARIANT: ${productKey}`);
|
|
226
|
+
}
|
|
227
|
+
const counts = shard?.counts ?? index.counts;
|
|
228
|
+
if (counts?.plugins !== catalog.plugins.length)
|
|
229
|
+
throw new Error('CONSUMER_INDEX_TOTAL_MISMATCH');
|
|
230
|
+
if (counts?.products !== Object.keys(products).length)
|
|
231
|
+
throw new Error('CONSUMER_INDEX_PRODUCT_TOTAL_MISMATCH');
|
|
232
|
+
if (counts?.redundantPlugins !== catalog.plugins.length - counts.products)
|
|
233
|
+
throw new Error('CONSUMER_INDEX_REDUNDANCY_MISMATCH');
|
|
234
|
+
if (index.counts && shard?.counts && digest(index.counts) !== digest(shard.counts))
|
|
235
|
+
throw new Error('CONSUMER_INDEX_COUNTS_MISMATCH');
|
|
236
|
+
if (shard?.topCount !== undefined && index.topCount !== shard.topCount)
|
|
237
|
+
throw new Error('CONSUMER_INDEX_TOP_COUNT_MISMATCH');
|
|
238
|
+
}
|
|
239
|
+
if (products && index.iconCoverage) {
|
|
240
|
+
const expected = iconCoverage({ products });
|
|
241
|
+
if (index.iconCoverage.total !== expected.total ||
|
|
242
|
+
index.iconCoverage.content !== expected.content ||
|
|
243
|
+
index.iconCoverage.favicon !== expected.favicon ||
|
|
244
|
+
index.iconCoverage.monogramOnly !== expected.monogramOnly ||
|
|
245
|
+
index.iconCoverage.monogramProductKeys.join('\n') !== expected.monogramProductKeys.join('\n'))
|
|
246
|
+
throw new Error('CONSUMER_INDEX_ICON_COVERAGE_MISMATCH');
|
|
247
|
+
}
|
|
248
|
+
const shards = [
|
|
249
|
+
...(products ? [{ name: CATALOG_INDEX_ARTIFACT, kind: 'index' }] : []),
|
|
250
|
+
...(index.categories ?? []).flatMap((category) => products && category.shelfArtifact && category.listArtifact
|
|
251
|
+
? [
|
|
252
|
+
{ name: category.shelfArtifact, kind: 'shelf', category: category.category },
|
|
253
|
+
{ name: category.listArtifact, kind: 'list', category: category.category },
|
|
254
|
+
]
|
|
255
|
+
: []),
|
|
256
|
+
];
|
|
257
|
+
return {
|
|
258
|
+
hasConsumerIndex: products !== undefined,
|
|
259
|
+
diagnostics,
|
|
260
|
+
...(products ? { counts: index.counts } : {}),
|
|
261
|
+
...(products && index.topCount !== undefined ? { topCount: index.topCount } : {}),
|
|
262
|
+
...(products ? { products, categories: index.categories ?? [] } : {}),
|
|
263
|
+
shards: products ? shards : [],
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
export function verifyCatalogReferences(catalog, policy = DEFAULT_POLICY) {
|
|
267
|
+
for (const source of catalog.sources) {
|
|
268
|
+
assertRepositoryAllowed(source.repositoryUrl, policy);
|
|
269
|
+
validateCatalogPath(source.manifestPath, 'SOURCE_MANIFEST_PATH_INVALID');
|
|
270
|
+
}
|
|
271
|
+
for (const plugin of catalog.plugins) {
|
|
272
|
+
assertRepositoryAllowed(plugin.provenance.repositoryUrl, policy);
|
|
273
|
+
validateCatalogPath(plugin.provenance.pluginSubdirectory, 'PROVENANCE_PATH_INVALID');
|
|
274
|
+
for (const release of plugin.availableReleases) {
|
|
275
|
+
assertRepositoryAllowed(release.resolvedRepositoryUrl, policy);
|
|
276
|
+
validateCatalogPath(release.pluginSubdirectory, 'RELEASE_PATH_INVALID');
|
|
277
|
+
for (const path of release.fileIndex)
|
|
278
|
+
validateCatalogPath(path, 'RELEASE_FILE_PATH_INVALID');
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
function validateCatalogPath(path, code) {
|
|
283
|
+
if (path !== '.')
|
|
284
|
+
safeRelativePath(path, code);
|
|
285
|
+
}
|
|
286
|
+
//# sourceMappingURL=verify-artifacts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verify-artifacts.js","sourceRoot":"","sources":["../src/verify-artifacts.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
source_commit
|
|
1
|
+
source_commit 562d176d4dd81b49043895b8715fe4a350c0892b
|
|
2
2
|
12125c7ab1a1e2d7cbe538343e2a11ef4d7fb0fa0310c5251d8606bf20f26834 packages/plugins/native/staged-reader.c
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
19fc1fbf9a4e1fa31a130a20f4108e1e64ea72d3d30ef29b259c4a0164221261 packages/plugins/native/staged-reader-test-win32-arm64.node
|
|
4
|
+
030e0cf5e08996b18672430246d39ad29e9d01aa25d34869b7873b5056840e2b packages/plugins/native/staged-reader-test-win32-x64.node
|
|
5
|
+
dd2d78b06c6047a366ec339223754bd2f1d1706300967532436cf15990d81421 packages/plugins/native/staged-reader-win32-arm64.node
|
|
6
|
+
cd01057f673bdf1694890fe0037ad522c3f5bcfe08d2b0ae5cc84268d3977789 packages/plugins/native/staged-reader-win32-x64.node
|
|
Binary file
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adea-ai/plugins",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.6",
|
|
4
4
|
"description": "Deterministic compiler for AI agent plugin marketplaces: schemas, source parsing, provenance verification, per-harness materialization, and provenance-checked static artifacts.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agents",
|
|
@@ -93,7 +93,5 @@
|
|
|
93
93
|
"engines": {
|
|
94
94
|
"bun": ">=1.4.4 <2",
|
|
95
95
|
"node": ">=24 <25"
|
|
96
|
-
}
|
|
97
|
-
"devDependencies": {},
|
|
98
|
-
"peerDependencies": {}
|
|
96
|
+
}
|
|
99
97
|
}
|
|
@@ -331,8 +331,8 @@ describe('canonical Agent Plugins package compiler', () => {
|
|
|
331
331
|
}
|
|
332
332
|
})
|
|
333
333
|
it('rejects duplicate escaped JSON keys without prototype mutation', () => {
|
|
334
|
-
assert.throws(() => parsePluginJson('{"x":1,"\\u0078":2}'))
|
|
335
|
-
assert.throws(() => parsePluginJson('{"a":{"x":1,"x":2}}'))
|
|
334
|
+
assert.throws(() => parsePluginJson('{"x":1,"\\u0078":2}'), /duplicate JSON object key/)
|
|
335
|
+
assert.throws(() => parsePluginJson('{"a":{"x":1,"x":2}}'), /duplicate JSON object key/)
|
|
336
336
|
const value = parsePluginJson('{"__proto__":{"polluted":true}}') as Record<string, unknown>
|
|
337
337
|
assert.equal(Object.prototype.hasOwnProperty.call(value, '__proto__'), true)
|
|
338
338
|
assert.equal(Object.prototype.hasOwnProperty.call({}, 'polluted'), false)
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { createHash } from 'node:crypto'
|
|
2
1
|
import { isIP } from 'node:net'
|
|
3
2
|
import { posix } from 'node:path'
|
|
4
3
|
import { validateHeaderName, validateHeaderValue } from 'node:http'
|
|
@@ -8,6 +7,7 @@ import {
|
|
|
8
7
|
PLUGIN_SCHEMA_ID,
|
|
9
8
|
MCP_SCHEMA_ID,
|
|
10
9
|
NORMALIZER_VERSION,
|
|
10
|
+
PACKAGE_LIMITS,
|
|
11
11
|
AgentManifestSchema,
|
|
12
12
|
McpServerSchema,
|
|
13
13
|
SkillFrontmatterSchema,
|
|
@@ -18,9 +18,11 @@ import {
|
|
|
18
18
|
type PackageFile,
|
|
19
19
|
type Diagnostic,
|
|
20
20
|
} from './agent-plugins-schema.js'
|
|
21
|
-
import { sourceDigest } from './
|
|
21
|
+
import { byteDigest, canonicalJson, ordinalCompare, sourceDigest } from './digest.js'
|
|
22
22
|
|
|
23
23
|
export { NORMALIZER_VERSION, sourceDigest }
|
|
24
|
+
// Public names of the shared canonical-JSON and digest helpers.
|
|
25
|
+
export { byteDigest as sha256, canonicalJson as stableJson, ordinalCompare as compare }
|
|
24
26
|
const decoder = new TextDecoder('utf-8', { fatal: true })
|
|
25
27
|
const encoder = new TextEncoder()
|
|
26
28
|
const manifestKeys = new Set([
|
|
@@ -49,27 +51,12 @@ const remoteTransportHeaders = new Set([
|
|
|
49
51
|
'transfer-encoding',
|
|
50
52
|
'upgrade',
|
|
51
53
|
])
|
|
52
|
-
const own = (value: object, key: string) => Object.prototype.hasOwnProperty.call(value, key)
|
|
53
|
-
export const compare = (a: string, b: string): number => (a < b ? -1 : a > b ? 1 : 0)
|
|
54
|
-
export function stableJson(value: unknown): string {
|
|
55
|
-
if (value === null || typeof value !== 'object') return JSON.stringify(value)
|
|
56
|
-
if (Array.isArray(value)) return `[${value.map(stableJson).join(',')}]`
|
|
57
|
-
const record = value as Record<string, unknown>
|
|
58
|
-
return `{${Object.keys(record)
|
|
59
|
-
.toSorted(compare)
|
|
60
|
-
.map((key) => `${JSON.stringify(key)}:${stableJson(record[key])}`)
|
|
61
|
-
.join(',')}}`
|
|
62
|
-
}
|
|
63
|
-
export function sha256(value: string | Uint8Array): string {
|
|
64
|
-
return `sha256:${createHash('sha256').update(value).digest('hex')}`
|
|
65
|
-
}
|
|
66
|
-
|
|
67
54
|
export function packageDigest(files: readonly PackageFile[]): string {
|
|
68
|
-
return
|
|
69
|
-
|
|
55
|
+
return byteDigest(
|
|
56
|
+
canonicalJson({
|
|
70
57
|
algorithm: 'adea-package-files/1',
|
|
71
58
|
files: [...files]
|
|
72
|
-
.toSorted((a, b) =>
|
|
59
|
+
.toSorted((a, b) => ordinalCompare(a.targetPath, b.targetPath))
|
|
73
60
|
.map((file) => ({
|
|
74
61
|
path: file.targetPath,
|
|
75
62
|
digest: file.digest,
|
|
@@ -217,7 +204,7 @@ function portableName(name: string): string {
|
|
|
217
204
|
) || 'plugin'
|
|
218
205
|
return cleaned.length <= 64
|
|
219
206
|
? cleaned
|
|
220
|
-
: `${trimPortableEdges(cleaned.slice(0, 54))}-${
|
|
207
|
+
: `${trimPortableEdges(cleaned.slice(0, 54))}-${byteDigest(name).slice(-8)}`
|
|
221
208
|
}
|
|
222
209
|
function diagnostic(
|
|
223
210
|
code: string,
|
|
@@ -233,7 +220,7 @@ function nativeManifest(raw: unknown, diagnostics: Diagnostic[]): AgentManifest
|
|
|
233
220
|
const filtered = Object.fromEntries(Object.entries(raw).filter(([key]) => manifestKeys.has(key)))
|
|
234
221
|
for (const key of Object.keys(raw)
|
|
235
222
|
.filter((field) => !manifestKeys.has(field))
|
|
236
|
-
.toSorted(
|
|
223
|
+
.toSorted(ordinalCompare))
|
|
237
224
|
diagnostics.push(
|
|
238
225
|
diagnostic(
|
|
239
226
|
'UNKNOWN_MANIFEST_FIELD',
|
|
@@ -243,7 +230,7 @@ function nativeManifest(raw: unknown, diagnostics: Diagnostic[]): AgentManifest
|
|
|
243
230
|
'warning'
|
|
244
231
|
)
|
|
245
232
|
)
|
|
246
|
-
if (
|
|
233
|
+
if (Object.hasOwn(filtered, 'extensions')) {
|
|
247
234
|
if (!isRecord(filtered.extensions)) {
|
|
248
235
|
delete filtered.extensions
|
|
249
236
|
diagnostics.push(
|
|
@@ -360,7 +347,7 @@ export function compileAgentPackage(input: CompilePackageInput): AgentPackage {
|
|
|
360
347
|
(() => {
|
|
361
348
|
try {
|
|
362
349
|
const raw = parsePluginJson(decoder.decode(files.get('plugin.json')!))
|
|
363
|
-
return isRecord(raw) &&
|
|
350
|
+
return isRecord(raw) && Object.hasOwn(raw, '$schema')
|
|
364
351
|
} catch {
|
|
365
352
|
return true
|
|
366
353
|
}
|
|
@@ -396,7 +383,8 @@ export function compileAgentPackage(input: CompilePackageInput): AgentPackage {
|
|
|
396
383
|
const paths = new Set<string>()
|
|
397
384
|
const spellings = new Map<string, string>()
|
|
398
385
|
let total = 0
|
|
399
|
-
if (files.size >
|
|
386
|
+
if (files.size > PACKAGE_LIMITS.maxFilesPerPlugin)
|
|
387
|
+
throw new Error('Package exceeds file-count policy.')
|
|
400
388
|
for (const [path, bytes] of files) {
|
|
401
389
|
assertPackagePath(path)
|
|
402
390
|
const folded = path.normalize('NFC').toLowerCase()
|
|
@@ -409,7 +397,10 @@ export function compileAgentPackage(input: CompilePackageInput): AgentPackage {
|
|
|
409
397
|
spellings.set(key, component)
|
|
410
398
|
}
|
|
411
399
|
total += bytes.byteLength
|
|
412
|
-
if (
|
|
400
|
+
if (
|
|
401
|
+
bytes.byteLength > PACKAGE_LIMITS.maxFileBytes ||
|
|
402
|
+
total > PACKAGE_LIMITS.maxBytesPerPlugin
|
|
403
|
+
)
|
|
413
404
|
throw new Error('Package exceeds byte-size policy.')
|
|
414
405
|
for (let parent = posix.dirname(path); parent !== '.'; parent = posix.dirname(parent))
|
|
415
406
|
if (files.has(parent)) throw new Error('File/directory path collision.')
|
|
@@ -469,7 +460,7 @@ export function compileAgentPackage(input: CompilePackageInput): AgentPackage {
|
|
|
469
460
|
diagnostic('INVALID_SKILLS_LOCATION', 'skills', 'skills', 'skills must be a directory.')
|
|
470
461
|
)
|
|
471
462
|
}
|
|
472
|
-
for (const [path, bytes] of [...files].toSorted(([a], [b]) =>
|
|
463
|
+
for (const [path, bytes] of [...files].toSorted(([a], [b]) => ordinalCompare(a, b))) {
|
|
473
464
|
const match = /^skills\/([^/]+)\/SKILL\.md$/.exec(path)
|
|
474
465
|
if (!match) continue
|
|
475
466
|
try {
|
|
@@ -551,7 +542,7 @@ export function compileAgentPackage(input: CompilePackageInput): AgentPackage {
|
|
|
551
542
|
mcpEntries = {}
|
|
552
543
|
}
|
|
553
544
|
for (const [name, inputServer] of Object.entries(mcpEntries).toSorted(([a], [b]) =>
|
|
554
|
-
|
|
545
|
+
ordinalCompare(a, b)
|
|
555
546
|
)) {
|
|
556
547
|
try {
|
|
557
548
|
if (['__proto__', 'constructor', 'prototype'].includes(name) || hasControlCharacters(name))
|
|
@@ -612,10 +603,10 @@ export function compileAgentPackage(input: CompilePackageInput): AgentPackage {
|
|
|
612
603
|
...(extras.get('client-extension') ?? []),
|
|
613
604
|
`plugin.json/extensions/${key}`,
|
|
614
605
|
])
|
|
615
|
-
for (const [kind, paths] of [...extras].toSorted(([a], [b]) =>
|
|
606
|
+
for (const [kind, paths] of [...extras].toSorted(([a], [b]) => ordinalCompare(a, b)))
|
|
616
607
|
nonPortable.push({
|
|
617
608
|
kind,
|
|
618
|
-
paths: [...new Set(paths)].toSorted(
|
|
609
|
+
paths: [...new Set(paths)].toSorted(ordinalCompare),
|
|
619
610
|
reason:
|
|
620
611
|
'Preserved as source content, not activated or presented as portable Agent Plugins behavior.',
|
|
621
612
|
})
|
|
@@ -634,7 +625,7 @@ export function compileAgentPackage(input: CompilePackageInput): AgentPackage {
|
|
|
634
625
|
action: 'copy',
|
|
635
626
|
sourcePath: path,
|
|
636
627
|
targetPath: path,
|
|
637
|
-
digest:
|
|
628
|
+
digest: byteDigest(bytes),
|
|
638
629
|
preserveMode: true,
|
|
639
630
|
})
|
|
640
631
|
}
|
|
@@ -643,14 +634,20 @@ export function compileAgentPackage(input: CompilePackageInput): AgentPackage {
|
|
|
643
634
|
['plugin.json', manifest],
|
|
644
635
|
['mcp.json', { $schema: MCP_SCHEMA_ID, mcpServers }],
|
|
645
636
|
] as const) {
|
|
646
|
-
const content =
|
|
647
|
-
operations.push({
|
|
637
|
+
const content = canonicalJson(data) + '\n'
|
|
638
|
+
operations.push({
|
|
639
|
+
action: 'write',
|
|
640
|
+
targetPath,
|
|
641
|
+
content,
|
|
642
|
+
digest: byteDigest(content),
|
|
643
|
+
mode: '0644',
|
|
644
|
+
})
|
|
648
645
|
}
|
|
649
|
-
const sortedOperations = operations.toSorted((a, b) =>
|
|
646
|
+
const sortedOperations = operations.toSorted((a, b) => ordinalCompare(a.targetPath, b.targetPath))
|
|
650
647
|
const values = [...servers.values()]
|
|
651
648
|
const local = values.filter((server) => server.type === 'stdio')
|
|
652
649
|
const sortedDiagnostics = diagnostics.toSorted((a, b) =>
|
|
653
|
-
|
|
650
|
+
ordinalCompare(`${a.path}:${a.code}`, `${b.path}:${b.code}`)
|
|
654
651
|
)
|
|
655
652
|
try {
|
|
656
653
|
return verifyAgentPackage({
|
|
@@ -666,8 +663,8 @@ export function compileAgentPackage(input: CompilePackageInput): AgentPackage {
|
|
|
666
663
|
mcpServers,
|
|
667
664
|
requirements: {
|
|
668
665
|
skills: skills.length > 0,
|
|
669
|
-
mcpTransports: [...new Set(values.map((server) => server.type))].toSorted(
|
|
670
|
-
executables: [...new Set(local.map((server) => server.command))].toSorted(
|
|
666
|
+
mcpTransports: [...new Set(values.map((server) => server.type))].toSorted(ordinalCompare),
|
|
667
|
+
executables: [...new Set(local.map((server) => server.command))].toSorted(ordinalCompare),
|
|
671
668
|
environmentReview:
|
|
672
669
|
local.length > 0 ||
|
|
673
670
|
skills.some((skill) => !!skill.compatibility || !!skill.allowedTools) ||
|
|
@@ -703,7 +700,7 @@ export function verifyAgentPackage(input: unknown): AgentPackage {
|
|
|
703
700
|
if (paths.has(key)) throw new Error('Duplicate package target.')
|
|
704
701
|
paths.add(key)
|
|
705
702
|
if (file.action === 'copy') assertPackagePath(file.sourcePath)
|
|
706
|
-
else if (
|
|
703
|
+
else if (byteDigest(file.content) !== file.digest)
|
|
707
704
|
throw new Error('Generated file digest mismatch.')
|
|
708
705
|
}
|
|
709
706
|
for (const path of paths)
|
|
@@ -714,11 +711,11 @@ export function verifyAgentPackage(input: unknown): AgentPackage {
|
|
|
714
711
|
if (!file || file.action !== 'write') throw new Error('Missing canonical control file.')
|
|
715
712
|
return parsePluginJson(file.content)
|
|
716
713
|
}
|
|
717
|
-
if (
|
|
714
|
+
if (canonicalJson(generated('plugin.json')) !== canonicalJson(pkg.manifest))
|
|
718
715
|
throw new Error('Manifest descriptor differs from package bytes.')
|
|
719
716
|
if (
|
|
720
|
-
|
|
721
|
-
|
|
717
|
+
canonicalJson(generated('mcp.json')) !==
|
|
718
|
+
canonicalJson({ $schema: MCP_SCHEMA_ID, mcpServers: pkg.mcpServers })
|
|
722
719
|
)
|
|
723
720
|
throw new Error('MCP descriptor differs from package bytes.')
|
|
724
721
|
for (const server of Object.values(pkg.mcpServers)) validateServer(server)
|
|
@@ -739,23 +736,23 @@ export function verifyAgentPackage(input: unknown): AgentPackage {
|
|
|
739
736
|
throw new Error('Skill inventory differs from package discovery.')
|
|
740
737
|
const expectedTransports = [
|
|
741
738
|
...new Set(Object.values(pkg.mcpServers).map((server) => server.type)),
|
|
742
|
-
].toSorted(
|
|
739
|
+
].toSorted(ordinalCompare)
|
|
743
740
|
const expectedExecutables = [
|
|
744
741
|
...new Set(
|
|
745
742
|
Object.values(pkg.mcpServers)
|
|
746
743
|
.filter((server) => server.type === 'stdio')
|
|
747
744
|
.map((server) => server.command)
|
|
748
745
|
),
|
|
749
|
-
].toSorted(
|
|
746
|
+
].toSorted(ordinalCompare)
|
|
750
747
|
if (
|
|
751
|
-
|
|
752
|
-
|
|
748
|
+
canonicalJson([...pkg.requirements.executables].toSorted(ordinalCompare)) !==
|
|
749
|
+
canonicalJson(expectedExecutables)
|
|
753
750
|
)
|
|
754
751
|
throw new Error('Package executable requirements differ from components.')
|
|
755
752
|
if (
|
|
756
753
|
pkg.requirements.skills !== pkg.skills.length > 0 ||
|
|
757
|
-
|
|
758
|
-
|
|
754
|
+
canonicalJson([...pkg.requirements.mcpTransports].toSorted(ordinalCompare)) !==
|
|
755
|
+
canonicalJson(expectedTransports)
|
|
759
756
|
)
|
|
760
757
|
throw new Error('Package requirements differ from components.')
|
|
761
758
|
if (
|
|
@@ -779,13 +776,13 @@ export function materializeAgentPackage(
|
|
|
779
776
|
name: pkg.manifest!.name,
|
|
780
777
|
sourceDigest: pkg.sourceDigest,
|
|
781
778
|
})
|
|
782
|
-
if (
|
|
779
|
+
if (canonicalJson(rebuilt) !== canonicalJson(pkg))
|
|
783
780
|
throw new Error('Recipe differs from deterministic source normalization.')
|
|
784
781
|
const result = new Map<string, Uint8Array>()
|
|
785
782
|
for (const file of pkg.files) {
|
|
786
783
|
const bytes =
|
|
787
784
|
file.action === 'write' ? encoder.encode(file.content) : source.get(file.sourcePath)
|
|
788
|
-
if (!bytes ||
|
|
785
|
+
if (!bytes || byteDigest(bytes) !== file.digest)
|
|
789
786
|
throw new Error('Package file missing or digest mismatch.')
|
|
790
787
|
result.set(file.targetPath, bytes.slice())
|
|
791
788
|
}
|
|
@@ -1,9 +1,19 @@
|
|
|
1
1
|
import { z } from 'zod'
|
|
2
|
+
import { DIGEST_RE } from './schema.js'
|
|
2
3
|
|
|
3
4
|
// Locally pinned contracts. Never fetch a schema while inspecting a plugin.
|
|
4
5
|
export const AGENT_PLUGINS_VERSION = '1.0.0' as const
|
|
5
6
|
export const PLUGIN_SCHEMA_ID = 'https://agent-plugins.org/schemas/1.0.0/plugin.schema.json'
|
|
6
7
|
export const MCP_SCHEMA_ID = 'https://agent-plugins.org/schemas/1.0.0/mcp.schema.json'
|
|
8
|
+
/** Size limits for one package; the catalog policy defaults to the same values. */
|
|
9
|
+
export const PACKAGE_LIMITS = {
|
|
10
|
+
maxFilesPerPlugin: 4096,
|
|
11
|
+
maxFileBytes: 5 * 1024 * 1024,
|
|
12
|
+
maxBytesPerPlugin: 50 * 1024 * 1024,
|
|
13
|
+
} as const
|
|
14
|
+
|
|
15
|
+
/** Where a release carries its compiled Agent Plugins package in `releaseMetadata`. */
|
|
16
|
+
export const PACKAGE_METADATA_KEY = 'agentPlugins'
|
|
7
17
|
export const NORMALIZER_VERSION = 'adea-agent-plugins/1' as const
|
|
8
18
|
export const PluginNameSchema = z
|
|
9
19
|
.string()
|
|
@@ -11,7 +21,7 @@ export const PluginNameSchema = z
|
|
|
11
21
|
.max(64)
|
|
12
22
|
.regex(/^(?!.*(?:--|\.\.))[a-z0-9](?:[a-z0-9.-]*[a-z0-9])?$/)
|
|
13
23
|
const Strings = z.record(z.string(), z.string())
|
|
14
|
-
const Digest = z.string().regex(
|
|
24
|
+
const Digest = z.string().regex(DIGEST_RE)
|
|
15
25
|
const Path = z
|
|
16
26
|
.string()
|
|
17
27
|
.min(1)
|