Plugins: extract hook compatibility

This commit is contained in:
Gustavo Madeira Santana
2026-03-15 16:58:05 +00:00
parent 8bfe6bb03f
commit b195ce5275
4 changed files with 189 additions and 45 deletions

View File

@@ -179,20 +179,6 @@ type PluginTypedHookPolicy = {
allowPromptInjection?: boolean;
};
const constrainLegacyPromptInjectionHook = (
handler: PluginHookHandlerMap["before_agent_start"],
): PluginHookHandlerMap["before_agent_start"] => {
return (event, ctx) => {
const result = handler(event, ctx);
if (result && typeof result === "object" && "then" in result) {
return Promise.resolve(result).then((resolved) =>
stripPromptMutationFieldsFromLegacyHookResult(resolved),
);
}
return stripPromptMutationFieldsFromLegacyHookResult(result);
};
};
export function createEmptyPluginRegistry(): PluginRegistry {
return {
plugins: [],
@@ -320,14 +306,13 @@ export function createPluginRegistry(registryParams: PluginRegistryParams) {
events: normalized.events,
});
const hookSystemEnabled = config?.hooks?.internal?.enabled === true;
if (!hookSystemEnabled || opts?.register === false) {
return;
}
for (const event of normalized.events) {
registerInternalHook(event, handler);
}
bridgeExtensionHostLegacyHooks({
events: normalized.events,
handler,
hookSystemEnabled: config?.hooks?.internal?.enabled === true,
register: opts?.register,
registerHook: registerInternalHook,
});
};
const registerGatewayMethod = (
@@ -620,28 +605,29 @@ export function createPluginRegistry(registryParams: PluginRegistryParams) {
});
return;
}
let effectiveHandler = normalized.entry.handler;
if (policy?.allowPromptInjection === false && isPromptInjectionHookName(normalized.hookName)) {
if (normalized.hookName === "before_prompt_build") {
pushDiagnostic({
level: "warn",
pluginId: record.id,
source: record.source,
message: `typed hook "${normalized.hookName}" blocked by plugins.entries.${record.id}.hooks.allowPromptInjection=false`,
});
return;
}
if (normalized.hookName === "before_agent_start") {
pushDiagnostic({
level: "warn",
pluginId: record.id,
source: record.source,
message: `typed hook "${normalized.hookName}" prompt fields constrained by plugins.entries.${record.id}.hooks.allowPromptInjection=false`,
});
effectiveHandler = constrainLegacyPromptInjectionHook(
handler as PluginHookHandlerMap["before_agent_start"],
) as PluginHookHandlerMap[K];
}
const policyResult = applyExtensionHostTypedHookPolicy({
hookName: normalized.hookName,
handler,
policy,
blockedMessage: `typed hook "${normalized.hookName}" blocked by plugins.entries.${record.id}.hooks.allowPromptInjection=false`,
constrainedMessage: `typed hook "${normalized.hookName}" prompt fields constrained by plugins.entries.${record.id}.hooks.allowPromptInjection=false`,
});
if (!policyResult.ok) {
pushDiagnostic({
level: "warn",
pluginId: record.id,
source: record.source,
message: policyResult.message,
});
return;
}
if (policyResult.warningMessage) {
pushDiagnostic({
level: "warn",
pluginId: record.id,
source: record.source,
message: policyResult.warningMessage,
});
}
addExtensionTypedHookRegistration({
registry,
@@ -650,7 +636,7 @@ export function createPluginRegistry(registryParams: PluginRegistryParams) {
...normalized.entry,
pluginId: record.id,
hookName: normalized.hookName,
handler: effectiveHandler,
handler: policyResult.entryHandler,
} as TypedPluginHookRegistration,
});
};