mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-25 20:05:46 -06:00
fix(agents): prepare selected harnesses for setup probes (#123141)
Keep explicitly selected plugin runtimes in isolated read-only generations so gateway setup can run Codex candidates. Improve missing-registration guidance.
This commit is contained in:
committed by
GitHub
parent
fa18d8d273
commit
d5d069a09e
@@ -62,6 +62,20 @@ describe("harness runtime plugins", () => {
|
||||
expect(pluginRegistry.agentHarnesses).toHaveLength(1);
|
||||
});
|
||||
|
||||
it("explains how to recover when the selected harness registration is missing", async () => {
|
||||
await expect(
|
||||
ensureSelectedAgentHarnessPlugin({
|
||||
provider: "openai",
|
||||
modelId: "gpt-5.5",
|
||||
agentHarnessRuntimeOverride: "codex",
|
||||
workspaceDir: "/tmp/workspace",
|
||||
pluginRegistry: createEmptyPluginRegistry(),
|
||||
}),
|
||||
).rejects.toThrow(
|
||||
'Agent harness runtime "codex" is unavailable because its plugin registration is missing from this prepared run. Enable or reinstall the plugin that provides this runtime, restart the Gateway, then retry.',
|
||||
);
|
||||
});
|
||||
|
||||
it("force-activates a default-disabled harness owner selected for a run", () => {
|
||||
const plan = resolveAgentRuntimePluginLoadPlan({
|
||||
config: {},
|
||||
|
||||
@@ -131,6 +131,8 @@ export async function ensureSelectedAgentHarnessPlugin(params: {
|
||||
}
|
||||
|
||||
if (!params.pluginRegistry?.agentHarnesses.some((entry) => entry.harness.id === runtime)) {
|
||||
throw new Error(`Agent harness runtime "${runtime}" is not present in the prepared registry.`);
|
||||
throw new Error(
|
||||
`Agent harness runtime "${runtime}" is unavailable because its plugin registration is missing from this prepared run. Enable or reinstall the plugin that provides this runtime, restart the Gateway, then retry.`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,10 +54,12 @@ export function prepareWorkspacePluginRegistries(
|
||||
runtimePluginRegistry?: PluginRegistry;
|
||||
inboundPluginRegistry?: PluginRegistry;
|
||||
} {
|
||||
if (input.readOnly) {
|
||||
// Read-only catalog owners stay runtime-free, but setup probes carry an exact harness selection.
|
||||
// That selected registry must belong to the generation instead of leaking from an outer scope.
|
||||
if (input.readOnly && !input.runtimePluginSelections) {
|
||||
return {};
|
||||
}
|
||||
const inboundPluginRegistry = loadInboundRegistry?.(input);
|
||||
const inboundPluginRegistry = input.readOnly ? undefined : loadInboundRegistry?.(input);
|
||||
const runtimePluginRegistry =
|
||||
input.runtimePluginSelections || !inboundPluginRegistry
|
||||
? loadAgentRuntimePluginRegistryHandle({
|
||||
|
||||
@@ -48,6 +48,24 @@ describe("prepared model runtime snapshots", () => {
|
||||
it("keeps an isolated setup probe exact after a gateway replacement", async () => {
|
||||
mocks.configuredAgentIds = ["default"];
|
||||
const stagedConfig = { agents: { defaults: { model: "openai/gpt-5.6" } } };
|
||||
const selectedPluginRegistry = createEmptyPluginRegistry();
|
||||
selectedPluginRegistry.agentHarnesses.push({
|
||||
pluginId: "codex",
|
||||
source: "test",
|
||||
harness: {
|
||||
id: "codex",
|
||||
label: "Codex",
|
||||
supports: () => ({ supported: true }),
|
||||
runAttempt: async () => {
|
||||
throw new Error("unused");
|
||||
},
|
||||
},
|
||||
});
|
||||
mocks.loadAgentRuntimePluginRegistryHandle.mockImplementation((params) =>
|
||||
(params as { selections?: unknown }).selections
|
||||
? selectedPluginRegistry
|
||||
: createEmptyPluginRegistry(),
|
||||
);
|
||||
await refreshPreparedModelRuntimeSnapshots({}, { gatewayLifecycle: true });
|
||||
markPreparedModelRuntimeSnapshotsStale("test isolated probe replacement", {
|
||||
waitForReplacement: true,
|
||||
@@ -58,6 +76,7 @@ describe("prepared model runtime snapshots", () => {
|
||||
agentDir: "/tmp/setup-probe-agent",
|
||||
inheritedAuthDir: "/tmp/setup-probe-agent",
|
||||
workspaceDir: "/tmp/setup-probe-workspace",
|
||||
runtimePluginSelections: [{ provider: "openai", modelId: "gpt-5.6", runtime: "codex" }],
|
||||
});
|
||||
await Promise.resolve();
|
||||
expect(mocks.ensureOpenClawModelsJson).toHaveBeenCalledTimes(1);
|
||||
@@ -72,6 +91,14 @@ describe("prepared model runtime snapshots", () => {
|
||||
agentDir: "/tmp/setup-probe-agent",
|
||||
workspaceDir: "/tmp/setup-probe-workspace",
|
||||
});
|
||||
expect(lease.snapshot.pluginRegistry?.agentHarnesses.map((entry) => entry.harness.id)).toEqual([
|
||||
"codex",
|
||||
]);
|
||||
expect(mocks.loadAgentRuntimePluginRegistryHandle).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
selections: [{ provider: "openai", modelId: "gpt-5.6", runtime: "codex" }],
|
||||
}),
|
||||
);
|
||||
lease.release();
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user