Include full contents of all nested repositories
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
118
openclaw/src/acp/control-plane/manager.runtime-controls.ts
Normal file
118
openclaw/src/acp/control-plane/manager.runtime-controls.ts
Normal file
@@ -0,0 +1,118 @@
|
||||
import { AcpRuntimeError, withAcpRuntimeErrorBoundary } from "../runtime/errors.js";
|
||||
import type { AcpRuntime, AcpRuntimeCapabilities, AcpRuntimeHandle } from "../runtime/types.js";
|
||||
import type { SessionAcpMeta } from "./manager.types.js";
|
||||
import { createUnsupportedControlError } from "./manager.utils.js";
|
||||
import type { CachedRuntimeState } from "./runtime-cache.js";
|
||||
import {
|
||||
buildRuntimeConfigOptionPairs,
|
||||
buildRuntimeControlSignature,
|
||||
normalizeText,
|
||||
resolveRuntimeOptionsFromMeta,
|
||||
} from "./runtime-options.js";
|
||||
|
||||
export async function resolveManagerRuntimeCapabilities(params: {
|
||||
runtime: AcpRuntime;
|
||||
handle: AcpRuntimeHandle;
|
||||
}): Promise<AcpRuntimeCapabilities> {
|
||||
let reported: AcpRuntimeCapabilities | undefined;
|
||||
if (params.runtime.getCapabilities) {
|
||||
reported = await withAcpRuntimeErrorBoundary({
|
||||
run: async () => await params.runtime.getCapabilities!({ handle: params.handle }),
|
||||
fallbackCode: "ACP_TURN_FAILED",
|
||||
fallbackMessage: "Could not read ACP runtime capabilities.",
|
||||
});
|
||||
}
|
||||
const controls = new Set<AcpRuntimeCapabilities["controls"][number]>(reported?.controls ?? []);
|
||||
if (params.runtime.setMode) {
|
||||
controls.add("session/set_mode");
|
||||
}
|
||||
if (params.runtime.setConfigOption) {
|
||||
controls.add("session/set_config_option");
|
||||
}
|
||||
if (params.runtime.getStatus) {
|
||||
controls.add("session/status");
|
||||
}
|
||||
const normalizedKeys = (reported?.configOptionKeys ?? [])
|
||||
.map((entry) => normalizeText(entry))
|
||||
.filter(Boolean) as string[];
|
||||
return {
|
||||
controls: [...controls].toSorted(),
|
||||
...(normalizedKeys.length > 0 ? { configOptionKeys: normalizedKeys } : {}),
|
||||
};
|
||||
}
|
||||
|
||||
export async function applyManagerRuntimeControls(params: {
|
||||
sessionKey: string;
|
||||
runtime: AcpRuntime;
|
||||
handle: AcpRuntimeHandle;
|
||||
meta: SessionAcpMeta;
|
||||
getCachedRuntimeState: (sessionKey: string) => CachedRuntimeState | null;
|
||||
}): Promise<void> {
|
||||
const options = resolveRuntimeOptionsFromMeta(params.meta);
|
||||
const signature = buildRuntimeControlSignature(options);
|
||||
const cached = params.getCachedRuntimeState(params.sessionKey);
|
||||
if (cached?.appliedControlSignature === signature) {
|
||||
return;
|
||||
}
|
||||
|
||||
const capabilities = await resolveManagerRuntimeCapabilities({
|
||||
runtime: params.runtime,
|
||||
handle: params.handle,
|
||||
});
|
||||
const backend = params.handle.backend || params.meta.backend;
|
||||
const runtimeMode = normalizeText(options.runtimeMode);
|
||||
const configOptions = buildRuntimeConfigOptionPairs(options);
|
||||
const advertisedKeys = new Set(
|
||||
(capabilities.configOptionKeys ?? [])
|
||||
.map((entry) => normalizeText(entry))
|
||||
.filter(Boolean) as string[],
|
||||
);
|
||||
|
||||
await withAcpRuntimeErrorBoundary({
|
||||
run: async () => {
|
||||
if (runtimeMode) {
|
||||
if (!capabilities.controls.includes("session/set_mode") || !params.runtime.setMode) {
|
||||
throw createUnsupportedControlError({
|
||||
backend,
|
||||
control: "session/set_mode",
|
||||
});
|
||||
}
|
||||
await params.runtime.setMode({
|
||||
handle: params.handle,
|
||||
mode: runtimeMode,
|
||||
});
|
||||
}
|
||||
|
||||
if (configOptions.length > 0) {
|
||||
if (
|
||||
!capabilities.controls.includes("session/set_config_option") ||
|
||||
!params.runtime.setConfigOption
|
||||
) {
|
||||
throw createUnsupportedControlError({
|
||||
backend,
|
||||
control: "session/set_config_option",
|
||||
});
|
||||
}
|
||||
for (const [key, value] of configOptions) {
|
||||
if (advertisedKeys.size > 0 && !advertisedKeys.has(key)) {
|
||||
throw new AcpRuntimeError(
|
||||
"ACP_BACKEND_UNSUPPORTED_CONTROL",
|
||||
`ACP backend "${backend}" does not accept config key "${key}".`,
|
||||
);
|
||||
}
|
||||
await params.runtime.setConfigOption({
|
||||
handle: params.handle,
|
||||
key,
|
||||
value,
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
fallbackCode: "ACP_TURN_FAILED",
|
||||
fallbackMessage: "Could not apply ACP runtime options before turn execution.",
|
||||
});
|
||||
|
||||
if (cached) {
|
||||
cached.appliedControlSignature = signature;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user