openclaw / src /plugins /agent-tool-result-middleware.ts
SaylorTwift's picture
SaylorTwift HF Staff
Add files using upload-large-folder tool
25d91a4 verified
Raw History Blame Contribute Delete
4.83 kB
// Applies plugin middleware to agent tool results at runtime boundaries.
import type {
AgentToolResultMiddleware,
AgentToolResultMiddlewareOptions,
AgentToolResultMiddlewareRuntime,
AgentToolResultMiddlewareScope,
} from "./agent-tool-result-middleware-types.js";
import type { PluginAgentToolResultMiddlewareRegistration } from "./registry-types.js";
import { getActivePluginRegistry } from "./runtime.js";
import {
createPluginToolMatcherScope,
normalizePluginToolMatcher,
pluginToolMatcherCoversTool,
type PluginToolMatcherScope,
} from "./tool-hook-matcher.js";
const AGENT_TOOL_RESULT_MIDDLEWARE_RUNTIMES = [
"openclaw",
"codex",
] as const satisfies AgentToolResultMiddlewareRuntime[];
const AGENT_TOOL_RESULT_MIDDLEWARE_RUNTIME_SET = new Set<string>(
AGENT_TOOL_RESULT_MIDDLEWARE_RUNTIMES,
);
function normalizeAgentToolResultMiddlewareRuntime(
runtime: string,
): AgentToolResultMiddlewareRuntime | undefined {
const normalized = runtime.trim().toLowerCase();
return AGENT_TOOL_RESULT_MIDDLEWARE_RUNTIME_SET.has(normalized)
? (normalized as AgentToolResultMiddlewareRuntime)
: undefined;
}
export function normalizeAgentToolResultMiddlewareRuntimes(
options?: AgentToolResultMiddlewareOptions,
): AgentToolResultMiddlewareRuntime[] {
const requested = options?.runtimes;
if (!requested) {
return [...AGENT_TOOL_RESULT_MIDDLEWARE_RUNTIMES];
}
const normalized: AgentToolResultMiddlewareRuntime[] = [];
for (const runtime of requested) {
const value = normalizeAgentToolResultMiddlewareRuntime(runtime);
if (!value) {
continue;
}
if (!normalized.includes(value)) {
normalized.push(value);
}
}
return normalized;
}
export function normalizeAgentToolResultMiddlewareRuntimeIds(
runtimes: readonly string[] | undefined,
): AgentToolResultMiddlewareRuntime[] {
const normalized: AgentToolResultMiddlewareRuntime[] = [];
for (const runtime of runtimes ?? []) {
const value = normalizeAgentToolResultMiddlewareRuntime(runtime);
if (value && !normalized.includes(value)) {
normalized.push(value);
}
}
return normalized;
}
function sameMiddlewareScope(
left: AgentToolResultMiddlewareScope,
right: AgentToolResultMiddlewareScope,
): boolean {
return (
left.runtimes.length === right.runtimes.length &&
left.runtimes.every((runtime) => right.runtimes.includes(runtime)) &&
(left.matcher ?? []).length === (right.matcher ?? []).length &&
(left.matcher ?? []).every((toolName) => right.matcher?.includes(toolName))
);
}
function readAgentToolResultMiddlewareScopes(
registration: PluginAgentToolResultMiddlewareRegistration,
): AgentToolResultMiddlewareScope[] {
return registration.scopes?.length ? registration.scopes : [{ runtimes: registration.runtimes }];
}
export function appendAgentToolResultMiddlewareScope(
registration: PluginAgentToolResultMiddlewareRegistration,
scope: AgentToolResultMiddlewareScope,
): void {
const normalizedMatcher = normalizePluginToolMatcher(scope.matcher);
const normalizedScope: AgentToolResultMiddlewareScope = {
runtimes: [...scope.runtimes],
...(normalizedMatcher ? { matcher: normalizedMatcher } : {}),
};
const scopes = readAgentToolResultMiddlewareScopes(registration);
if (!scopes.some((existing) => sameMiddlewareScope(existing, normalizedScope))) {
registration.scopes = [...scopes, normalizedScope];
} else if (!registration.scopes) {
registration.scopes = scopes;
}
registration.runtimes = normalizeAgentToolResultMiddlewareRuntimeIds(
readAgentToolResultMiddlewareScopes(registration).flatMap((entry) => entry.runtimes),
);
}
export function agentToolResultMiddlewareRegistrationCoversTool(
registration: PluginAgentToolResultMiddlewareRegistration,
runtime: AgentToolResultMiddlewareRuntime,
toolName: string,
): boolean {
return readAgentToolResultMiddlewareScopes(registration).some(
(scope) =>
scope.runtimes.includes(runtime) && pluginToolMatcherCoversTool(scope.matcher, toolName),
);
}
export function getAgentToolResultMiddlewareMatcherScope(
runtime: AgentToolResultMiddlewareRuntime,
): PluginToolMatcherScope | undefined {
const matchers = (getActivePluginRegistry()?.agentToolResultMiddlewares ?? []).flatMap(
(registration) =>
readAgentToolResultMiddlewareScopes(registration)
.filter((scope) => scope.runtimes.includes(runtime))
.map((scope) => scope.matcher),
);
return createPluginToolMatcherScope(matchers);
}
export function listAgentToolResultMiddlewares(
runtime: AgentToolResultMiddlewareRuntime,
): AgentToolResultMiddleware[] {
return (
getActivePluginRegistry()
?.agentToolResultMiddlewares?.filter((entry) => entry.runtimes.includes(runtime))
.map((entry) => entry.handler) ?? []
);
}