@lesliechan721/aw-plugin-core 0.1.0-beta.7 → 0.1.0-beta.9

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.
Files changed (37) hide show
  1. package/dist/aw-capabilities.d.ts +27 -0
  2. package/dist/aw-capabilities.js +106 -0
  3. package/dist/aw-capabilities.js.map +1 -0
  4. package/dist/catalog-workspace-resolution.d.ts +3 -0
  5. package/dist/catalog-workspace-resolution.js +34 -0
  6. package/dist/catalog-workspace-resolution.js.map +1 -0
  7. package/dist/generated/{plugin-manifest-v1.d.ts → plugin-manifest-v2.d.ts} +44 -31
  8. package/dist/generated/{plugin-manifest-v1.js → plugin-manifest-v2.js} +1 -1
  9. package/dist/generated/plugin-manifest-v2.js.map +1 -0
  10. package/dist/index.d.ts +2 -2
  11. package/dist/index.js +1 -1
  12. package/dist/index.js.map +1 -1
  13. package/dist/manifest-contract.d.ts +3 -6
  14. package/dist/manifest-contract.js +54 -63
  15. package/dist/manifest-contract.js.map +1 -1
  16. package/dist/manifest-type-contract.d.ts +2 -2
  17. package/dist/manifest.d.ts +8 -8
  18. package/dist/manifest.js +9 -7
  19. package/dist/manifest.js.map +1 -1
  20. package/dist/plugin-authoring-capabilities.js +4 -3
  21. package/dist/plugin-authoring-capabilities.js.map +1 -1
  22. package/dist/plugin-requirements.d.ts +34 -0
  23. package/dist/plugin-requirements.js +248 -0
  24. package/dist/plugin-requirements.js.map +1 -0
  25. package/dist/plugin-script-contract.d.ts +8 -0
  26. package/dist/plugin-script-contract.js +38 -1
  27. package/dist/plugin-script-contract.js.map +1 -1
  28. package/dist/types.d.ts +25 -22
  29. package/dist/workspace.d.ts +17 -9
  30. package/dist/workspace.js +299 -138
  31. package/dist/workspace.js.map +1 -1
  32. package/package.json +2 -2
  33. package/schemas/{plugin-manifest-v1.json → plugin-manifest-v2.json} +41 -11
  34. package/dist/generated/plugin-manifest-v1.js.map +0 -1
  35. package/dist/plugin-release.d.ts +0 -30
  36. package/dist/plugin-release.js +0 -187
  37. package/dist/plugin-release.js.map +0 -1
@@ -1,6 +1,7 @@
1
1
  import path from 'node:path';
2
2
  import { isDeepStrictEqual } from 'node:util';
3
3
  import fs from 'fs-extra';
4
+ import { computeAwCapabilitySetDigest, normalizeAwCapabilities, } from './aw-capabilities.js';
4
5
  import { normalizePluginManifestSchemaVersion, PLUGIN_MANIFEST_SCHEMA_VERSION, SOURCE_PLUGIN_MANIFEST_CONTRACT_VERSION, } from './manifest.js';
5
6
  import { readJsonFile } from './read-json.js';
6
7
  import { parsePermissionCommand } from './permission-command.js';
@@ -29,7 +30,6 @@ const PLATFORM_PRODUCT_BY_NAME = {
29
30
  };
30
31
  const PLUGIN_NAME_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
31
32
  const DIGEST_PATTERN = /^sha256:[0-9a-f]{64}$/;
32
- export const DEFAULT_SOURCE_PLUGIN_AW_MIN_VERSION = '0.0.0';
33
33
  const STRICT_SEMVER_PATTERN = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|(?:[0-9A-Za-z-]*[A-Za-z-][0-9A-Za-z-]*))(?:\.(?:0|[1-9]\d*|(?:[0-9A-Za-z-]*[A-Za-z-][0-9A-Za-z-]*)))*))?(?:\+([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?$/;
34
34
  export const STRICT_SEMVER_VALIDATION_CODE = 'invalidStrictSemVer';
35
35
  export class StrictSemVerValidationError extends Error {
@@ -265,30 +265,26 @@ function assertCatalogChannel(value, fieldName) {
265
265
  }
266
266
  return channel;
267
267
  }
268
- function createPluginCompatibility(minVersion) {
269
- return {
270
- aw: {
271
- minVersion,
272
- },
273
- };
274
- }
275
- function normalizePluginCompatibility(value, fieldName, options) {
268
+ function normalizePluginRequirements(value, fieldName, options) {
276
269
  if (value === undefined) {
277
- if (options.allowMissing) {
278
- return createPluginCompatibility(assertStrictSemVer(options.defaultMinVersion ?? DEFAULT_SOURCE_PLUGIN_AW_MIN_VERSION, `${fieldName}.aw.minVersion`));
279
- }
280
- throw new Error(`Invalid ${fieldName}.aw.minVersion: expected a strict SemVer 2.0.0 string. Received undefined.`);
270
+ if (options.allowMissing)
271
+ return undefined;
272
+ throw new Error(`Invalid ${fieldName}: expected an object.`);
281
273
  }
282
274
  const input = assertObject(value, fieldName);
283
275
  assertAllowedKeys(input, fieldName, ['aw']);
284
276
  const aw = assertObject(input.aw, `${fieldName}.aw`);
285
- assertAllowedKeys(aw, `${fieldName}.aw`, ['minVersion']);
286
- return createPluginCompatibility(assertStrictSemVer(aw.minVersion, `${fieldName}.aw.minVersion`));
287
- }
288
- function assertPluginMinVersionWithinCatalogBounds(options) {
289
- if (compareStrictSemVer(options.pluginMinVersion, options.catalogMinVersion) > 0) {
290
- throw new Error(`Invalid ${options.fieldName}: plugin "${options.pluginName}" requires aw ${options.pluginMinVersion}, which is higher than catalog minimum ${options.catalogMinVersion}.`);
277
+ assertAllowedKeys(aw, `${fieldName}.aw`, ['capabilities']);
278
+ if (aw.capabilities !== undefined && !Array.isArray(aw.capabilities)) {
279
+ throw new Error(`Invalid ${fieldName}.aw.capabilities: expected an array.`);
291
280
  }
281
+ return {
282
+ aw: {
283
+ ...(aw.capabilities === undefined
284
+ ? {}
285
+ : { capabilities: normalizeAwCapabilities(aw.capabilities, `${fieldName}.aw.capabilities`) }),
286
+ },
287
+ };
292
288
  }
293
289
  function normalizeMarketplaceProducts(value, fieldName) {
294
290
  if (value === undefined) {
@@ -619,15 +615,20 @@ function normalizeRuntimeExports(pluginRoot, value, fieldName) {
619
615
  return value.map((entry, index) => {
620
616
  const entryField = `${fieldName}[${index}]`;
621
617
  const input = assertObject(entry, entryField);
622
- assertAllowedKeys(input, entryField, ['name', 'source']);
618
+ assertAllowedKeys(input, entryField, ['name', 'source', 'requires']);
623
619
  const name = normalizeRuntimeExportName(input.name, `${entryField}.name`);
624
620
  if (names.has(name)) {
625
621
  throw new Error(`Invalid ${fieldName}: duplicate export name "${name}".`);
626
622
  }
627
623
  names.add(name);
624
+ const requires = normalizePluginRequirements(input.requires, `${entryField}.requires`, { allowMissing: false });
625
+ if (requires.aw.capabilities === undefined) {
626
+ throw new Error(`Invalid ${entryField}.requires.aw.capabilities: expected an array.`);
627
+ }
628
628
  return {
629
629
  name,
630
630
  source: normalizeCanonicalPluginFilePath(pluginRoot, input.source, `${entryField}.source`),
631
+ requires: { aw: { capabilities: requires.aw.capabilities } },
631
632
  };
632
633
  });
633
634
  }
@@ -1394,13 +1395,24 @@ function normalizeArtifactRuntimeImports(value, fieldName, reservedImports) {
1394
1395
  const resolvedInput = assertObject(input.resolved, `${entryField}.resolved`);
1395
1396
  assertAllowedKeys(resolvedInput, `${entryField}.resolved`, [
1396
1397
  'path', 'digest', 'providerPluginId', 'providerVersion', 'source',
1398
+ 'requiredCapabilities', 'capabilitySetDigest',
1397
1399
  ]);
1400
+ if (!Array.isArray(resolvedInput.requiredCapabilities)) {
1401
+ throw new Error(`Invalid ${entryField}.resolved.requiredCapabilities: expected an array.`);
1402
+ }
1403
+ const requiredCapabilities = normalizeAwCapabilities(resolvedInput.requiredCapabilities, `${entryField}.resolved.requiredCapabilities`);
1404
+ const capabilitySetDigest = ensureDigestString(resolvedInput.capabilitySetDigest, `${entryField}.resolved.capabilitySetDigest`);
1405
+ if (capabilitySetDigest !== computeAwCapabilitySetDigest(requiredCapabilities)) {
1406
+ throw new Error(`Invalid ${entryField}.resolved.capabilitySetDigest: digest does not match requiredCapabilities.`);
1407
+ }
1398
1408
  resolved = {
1399
1409
  path: normalizePluginChildPath('', ensureString(resolvedInput.path, `${entryField}.resolved.path`), `${entryField}.resolved.path`),
1400
1410
  digest: ensureDigestString(resolvedInput.digest, `${entryField}.resolved.digest`),
1401
1411
  providerPluginId: ensureString(resolvedInput.providerPluginId, `${entryField}.resolved.providerPluginId`),
1402
1412
  providerVersion: assertStrictSemVer(resolvedInput.providerVersion, `${entryField}.resolved.providerVersion`),
1403
1413
  source: ensureString(resolvedInput.source, `${entryField}.resolved.source`),
1414
+ requiredCapabilities,
1415
+ capabilitySetDigest,
1404
1416
  };
1405
1417
  }
1406
1418
  return {
@@ -2006,7 +2018,7 @@ export async function assertActualNativePluginCapability(pluginRoot, manifest, m
2006
2018
  }
2007
2019
  }
2008
2020
  if (!skills && !slashCommands && !mcpServers && !apps && !bundled) {
2009
- throw new Error('Invalid plugin manifest: portable-only plugins are not supported in V1. Declare at least one non-empty native capability.');
2021
+ throw new Error('Invalid plugin manifest: portable-only plugins are not supported. Declare at least one non-empty native capability.');
2010
2022
  }
2011
2023
  }
2012
2024
  export function validatePluginManifest(pluginRoot, rawManifest, options = {}) {
@@ -2020,7 +2032,7 @@ export function validatePluginManifest(pluginRoot, rawManifest, options = {}) {
2020
2032
  'version',
2021
2033
  'description',
2022
2034
  'dependencies',
2023
- 'compatibility',
2035
+ 'requires',
2024
2036
  'skills',
2025
2037
  'slashCommands',
2026
2038
  'mcpServers',
@@ -2039,12 +2051,11 @@ export function validatePluginManifest(pluginRoot, rawManifest, options = {}) {
2039
2051
  name: ensureString(input.name, 'name'),
2040
2052
  version: assertStrictSemVer(input.version, 'plugin manifest.version'),
2041
2053
  description: ensureString(input.description, 'description'),
2042
- compatibility: normalizePluginCompatibility(input.compatibility, 'compatibility', {
2043
- allowMissing: (options.compatibilityMode ?? 'defaulted') === 'defaulted',
2044
- defaultMinVersion: options.defaultMinVersion,
2045
- }),
2046
2054
  marketplace: normalizeMarketplaceMeta(input.marketplace, 'marketplace'),
2047
2055
  };
2056
+ const requires = normalizePluginRequirements(input.requires, 'requires', { allowMissing: true });
2057
+ if (requires !== undefined)
2058
+ manifest.requires = requires;
2048
2059
  if (input.dependencies !== undefined) {
2049
2060
  const dependencies = ensureStringArray(input.dependencies, 'dependencies');
2050
2061
  if (dependencies.length > 64) {
@@ -2289,18 +2300,7 @@ async function validateSourceJsonNativeAsset(pluginRoot, manifest, field) {
2289
2300
  }
2290
2301
  export async function validateSourcePluginManifest(pluginRoot, rawManifest, options = {}) {
2291
2302
  await assertPluginInputTree(pluginRoot);
2292
- const distributionsInput = rawManifest !== null
2293
- && typeof rawManifest === 'object'
2294
- && !Array.isArray(rawManifest)
2295
- ? rawManifest.distributions
2296
- : undefined;
2297
- const requiresExplicitMinVersion = distributionsInput !== null
2298
- && typeof distributionsInput === 'object'
2299
- && !Array.isArray(distributionsInput)
2300
- && Object.hasOwn(distributionsInput, 'agentSkills');
2301
2303
  const manifest = validatePluginManifest(pluginRoot, rawManifest, {
2302
- compatibilityMode: requiresExplicitMinVersion ? 'required' : 'defaulted',
2303
- defaultMinVersion: DEFAULT_SOURCE_PLUGIN_AW_MIN_VERSION,
2304
2304
  reservedImports: options.reservedImports,
2305
2305
  });
2306
2306
  const parsedVersion = parseStrictSemVer(manifest.version, 'plugin manifest.version');
@@ -2337,10 +2337,7 @@ export async function readPluginManifest(pluginRoot, options = {}) {
2337
2337
  ? await validateSourcePluginManifest(pluginRoot, rawManifest, {
2338
2338
  reservedImports: options.reservedImports,
2339
2339
  })
2340
- : validatePluginManifest(pluginRoot, rawManifest, {
2341
- compatibilityMode: 'required',
2342
- reservedImports: options.reservedImports,
2343
- });
2340
+ : validatePluginManifest(pluginRoot, rawManifest, { reservedImports: options.reservedImports });
2344
2341
  if (mode === 'bundle')
2345
2342
  await assertActualNativePluginCapability(pluginRoot, manifest, 'bundle');
2346
2343
  return {
@@ -2438,9 +2435,6 @@ function assertCatalogChannelVersionContract(options) {
2438
2435
  }
2439
2436
  function normalizeCatalogManifestEntry(value, fieldName) {
2440
2437
  const input = assertObject(value, fieldName);
2441
- if (Object.hasOwn(input, 'dependencies')) {
2442
- throw new Error(`Invalid ${fieldName}: "dependencies" is unsupported.`);
2443
- }
2444
2438
  assertAllowedKeys(input, fieldName, [
2445
2439
  'name',
2446
2440
  'version',
@@ -2450,7 +2444,8 @@ function normalizeCatalogManifestEntry(value, fieldName) {
2450
2444
  'tags',
2451
2445
  'strict',
2452
2446
  'policy',
2453
- 'compatibility',
2447
+ 'dependencies',
2448
+ 'requires',
2454
2449
  'source',
2455
2450
  'artifactDigest',
2456
2451
  'manifestDigest',
@@ -2462,7 +2457,11 @@ function normalizeCatalogManifestEntry(value, fieldName) {
2462
2457
  category: ensureString(input.category, `${fieldName}.category`),
2463
2458
  strict: ensureBoolean(input.strict, `${fieldName}.strict`),
2464
2459
  policy: normalizeMarketplacePolicy(input.policy, `${fieldName}.policy`),
2465
- compatibility: normalizePluginCompatibility(input.compatibility, `${fieldName}.compatibility`, {
2460
+ dependencies: input.dependencies === undefined
2461
+ ? []
2462
+ : normalizeComparableStringArray(ensureStringArray(input.dependencies, `${fieldName}.dependencies`))
2463
+ .map((dependency, index) => ensurePluginName(dependency, `${fieldName}.dependencies[${index}]`)),
2464
+ requires: normalizePluginRequirements(input.requires, `${fieldName}.requires`, {
2466
2465
  allowMissing: false,
2467
2466
  }),
2468
2467
  source: normalizeCatalogRelativePath(input.source, `${fieldName}.source`),
@@ -2486,8 +2485,8 @@ export function normalizeCatalogManifestBase(input, fieldName) {
2486
2485
  fieldName: `${fieldName}.catalogVersion`,
2487
2486
  kind: 'catalog',
2488
2487
  });
2489
- const compatibility = normalizePluginCompatibility(input.compatibility, `${fieldName}.compatibility`, { allowMissing: false });
2490
- return { catalogVersion, channel, compatibility };
2488
+ const requires = normalizePluginRequirements(input.requires, `${fieldName}.requires`, { allowMissing: false });
2489
+ return { catalogVersion, channel, requires };
2491
2490
  }
2492
2491
  export function normalizeCatalogManifestEntries(rawEntries, base, fieldName) {
2493
2492
  if (!Array.isArray(rawEntries)) {
@@ -2508,16 +2507,10 @@ export function normalizeCatalogManifestEntries(rawEntries, base, fieldName) {
2508
2507
  kind: 'plugin',
2509
2508
  });
2510
2509
  }
2511
- assertPluginMinVersionWithinCatalogBounds({
2512
- pluginName: entry.name,
2513
- pluginMinVersion: entry.compatibility.aw.minVersion,
2514
- catalogMinVersion: base.compatibility.aw.minVersion,
2515
- fieldName: `${fieldName}.entries.${entry.name}.compatibility.aw.minVersion`,
2516
- });
2517
2510
  }
2518
2511
  return entries;
2519
2512
  }
2520
- export function createBundleSourceManifest(plugin) {
2513
+ export function createBundleSourceManifest(plugin, requiredCapabilities) {
2521
2514
  const scripts = plugin.manifest.scripts
2522
2515
  ? structuredClone(plugin.manifest.scripts)
2523
2516
  : undefined;
@@ -2543,9 +2536,12 @@ export function createBundleSourceManifest(plugin) {
2543
2536
  return {
2544
2537
  ...plugin.manifest,
2545
2538
  buildConfig,
2546
- compatibility: plugin.manifest.compatibility
2547
- ? structuredClone(plugin.manifest.compatibility)
2548
- : createPluginCompatibility(DEFAULT_SOURCE_PLUGIN_AW_MIN_VERSION),
2539
+ distributions: plugin.manifest.distributions
2540
+ ? structuredClone(plugin.manifest.distributions)
2541
+ : undefined,
2542
+ requires: requiredCapabilities === undefined
2543
+ ? structuredClone(plugin.manifest.requires)
2544
+ : { aw: { capabilities: normalizeAwCapabilities(requiredCapabilities) } },
2549
2545
  extensions: plugin.manifest.extensions
2550
2546
  ? {
2551
2547
  instructions: plugin.manifest.extensions.instructions
@@ -2580,11 +2576,6 @@ export function createPlatformManifestBase(plugin) {
2580
2576
  name: plugin.manifest.name,
2581
2577
  version: plugin.manifest.version,
2582
2578
  description: plugin.manifest.description,
2583
- compatibility: structuredClone(plugin.manifest.compatibility ?? {
2584
- aw: {
2585
- minVersion: '0.0.0',
2586
- },
2587
- }),
2588
2579
  interface: plugin.manifest.interface,
2589
2580
  };
2590
2581
  }