fix(coding): remediate ML-07 plugin authority
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import { readFileSync } from 'node:fs';
|
||||
import { readFile } from 'node:fs/promises';
|
||||
import path from 'node:path';
|
||||
import {
|
||||
@@ -7,6 +8,7 @@ import {
|
||||
BUNDLED_CODING_PLUGIN_SETTINGS_SURFACES,
|
||||
CODE_OWNED_PLUGIN_PERMISSION_IDS,
|
||||
DATA_SERVICE_CAPABILITY_IDS,
|
||||
DATA_SERVICE_OPERATION_DEFINITIONS,
|
||||
DATA_SERVICE_PLUGIN_ID,
|
||||
DATA_SERVICE_TOOL_NAMES,
|
||||
type AgentPluginsRootManifest,
|
||||
@@ -563,6 +565,9 @@ export function parseCodingPluginManifest(
|
||||
requiresBackend,
|
||||
skills,
|
||||
tools,
|
||||
operations: pluginId === DATA_SERVICE_PLUGIN_ID
|
||||
? DATA_SERVICE_OPERATION_DEFINITIONS
|
||||
: tools.map(({ capabilityId, operation, name }) => ({ capabilityId, operation, toolName: name })),
|
||||
surfaces: normalizedSurfaces,
|
||||
});
|
||||
validateDataServiceDefinition(definition, capabilityManifestPath);
|
||||
@@ -613,6 +618,42 @@ export async function loadCodingPluginDefinition(packageRoot: string): Promise<C
|
||||
return definition;
|
||||
}
|
||||
|
||||
export function loadCodingPluginDefinitionSync(packageRoot: string): CodingPluginDefinition {
|
||||
const root = path.resolve(packageRoot);
|
||||
const pluginManifestPath = path.join(root, PACKAGE_MANIFEST_FILE);
|
||||
const rootValue = readJson(readFileSync(pluginManifestPath, 'utf8'), pluginManifestPath);
|
||||
const rootManifest = parseAgentPluginsRootManifest(rootValue, pluginManifestPath);
|
||||
const capabilityManifest = normalizeCandidatePath(
|
||||
root,
|
||||
root,
|
||||
rootManifest.extensions['com.makelore'].capabilityManifest,
|
||||
pluginManifestPath,
|
||||
'extensions.com.makelore.capabilityManifest',
|
||||
);
|
||||
if (capabilityManifest !== CAPABILITY_MANIFEST_RELATIVE_PATH) {
|
||||
fail(pluginManifestPath, 'extensions.com.makelore.capabilityManifest', `must point to ${CAPABILITY_MANIFEST_RELATIVE_PATH}`);
|
||||
}
|
||||
const capabilityManifestPath = path.join(root, capabilityManifest);
|
||||
const capabilityValue = readJson(readFileSync(capabilityManifestPath, 'utf8'), capabilityManifestPath);
|
||||
const definition = parseCodingPluginManifest(rootValue, capabilityValue, {
|
||||
packageRoot: root,
|
||||
rootManifestPath: pluginManifestPath,
|
||||
capabilityManifestPath,
|
||||
});
|
||||
for (const skill of definition.skills) {
|
||||
try {
|
||||
readFileSync(path.join(root, skill.entryPath), 'utf8');
|
||||
} catch (error) {
|
||||
fail(
|
||||
capabilityManifestPath,
|
||||
`skills.${skill.id}.entry`,
|
||||
`Skill entry could not be read: ${error instanceof Error ? error.message : String(error)}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
return definition;
|
||||
}
|
||||
|
||||
export function resolveBundledCodingPluginRootPaths(resourcesRoot: string): string[] {
|
||||
const root = path.resolve(resourcesRoot);
|
||||
return BUNDLED_CODING_PLUGIN_ROOTS.map((relativeRoot) => path.join(root, relativeRoot));
|
||||
@@ -620,22 +661,7 @@ export function resolveBundledCodingPluginRootPaths(resourcesRoot: string): stri
|
||||
|
||||
export const resolveBundledPluginRoots = resolveBundledCodingPluginRootPaths;
|
||||
|
||||
export async function loadBundledCodingPluginDefinitions(
|
||||
resourcesRoot: string,
|
||||
): Promise<CodingPluginDefinition[]> {
|
||||
const roots = resolveBundledCodingPluginRootPaths(resourcesRoot);
|
||||
const definitions = await Promise.all(roots.map(async (root, index) => {
|
||||
const definition = await loadCodingPluginDefinition(root);
|
||||
const expectedRoot = BUNDLED_CODING_PLUGIN_ROOTS[index];
|
||||
if (definition.id !== `makelore.${expectedRoot}`) {
|
||||
throw new CodingPluginManifestError(
|
||||
path.join(root, PACKAGE_MANIFEST_FILE),
|
||||
'name',
|
||||
`fixed bundle root ${expectedRoot} contains ${definition.id}`,
|
||||
);
|
||||
}
|
||||
return definition;
|
||||
}));
|
||||
function validateBundledDefinitions(definitions: readonly CodingPluginDefinition[]): void {
|
||||
const pluginIds = new Set<string>();
|
||||
const capabilityIds = new Set<string>();
|
||||
const skillIds = new Set<string>();
|
||||
@@ -657,7 +683,46 @@ export async function loadBundledCodingPluginDefinitions(
|
||||
capabilityIds.add(tool.capabilityId);
|
||||
}
|
||||
}
|
||||
return definitions;
|
||||
}
|
||||
|
||||
export async function loadBundledCodingPluginDefinitions(
|
||||
resourcesRoot: string,
|
||||
): Promise<readonly CodingPluginDefinition[]> {
|
||||
const roots = resolveBundledCodingPluginRootPaths(resourcesRoot);
|
||||
const definitions = await Promise.all(roots.map(async (root, index) => {
|
||||
const definition = await loadCodingPluginDefinition(root);
|
||||
const expectedRoot = BUNDLED_CODING_PLUGIN_ROOTS[index];
|
||||
if (definition.id !== `makelore.${expectedRoot}`) {
|
||||
throw new CodingPluginManifestError(
|
||||
path.join(root, PACKAGE_MANIFEST_FILE),
|
||||
'name',
|
||||
`fixed bundle root ${expectedRoot} contains ${definition.id}`,
|
||||
);
|
||||
}
|
||||
return definition;
|
||||
}));
|
||||
validateBundledDefinitions(definitions);
|
||||
return Object.freeze(definitions);
|
||||
}
|
||||
|
||||
export function loadBundledCodingPluginDefinitionsSync(
|
||||
resourcesRoot: string,
|
||||
): readonly CodingPluginDefinition[] {
|
||||
const roots = resolveBundledCodingPluginRootPaths(resourcesRoot);
|
||||
const definitions = roots.map((root, index) => {
|
||||
const definition = loadCodingPluginDefinitionSync(root);
|
||||
const expectedRoot = BUNDLED_CODING_PLUGIN_ROOTS[index];
|
||||
if (definition.id !== `makelore.${expectedRoot}`) {
|
||||
throw new CodingPluginManifestError(
|
||||
path.join(root, PACKAGE_MANIFEST_FILE),
|
||||
'name',
|
||||
`fixed bundle root ${expectedRoot} contains ${definition.id}`,
|
||||
);
|
||||
}
|
||||
return definition;
|
||||
});
|
||||
validateBundledDefinitions(definitions);
|
||||
return Object.freeze(definitions);
|
||||
}
|
||||
|
||||
export const parseBundledCodingPlugins = loadBundledCodingPluginDefinitions;
|
||||
|
||||
Reference in New Issue
Block a user