mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 11:20:43 +00:00
fix: validate resolved context engine ids
This commit is contained in:
@@ -312,6 +312,8 @@ Docs: https://docs.openclaw.ai
|
||||
- Control UI/models: preserve provider-qualified refs for OpenRouter catalog models whose ids already contain slashes so picker selections submit allowlist-compatible model refs instead of dropping the `openrouter/` prefix. (#63416) Thanks @sallyom.
|
||||
- Plugin SDK/command auth: split command status builders onto the lightweight `openclaw/plugin-sdk/command-status` subpath while preserving deprecated `command-auth` compatibility exports, so auth-only plugin imports no longer pull status/context warmup into CLI onboarding paths. (#63174) Thanks @hxy91819.
|
||||
- Wizard/plugin config: coerce integer-typed plugin config fields from interactive text input so integer schema values persist as numbers instead of failing validation. (#63346) Thanks @jalehman.
|
||||
- npm packaging: derive required root runtime mirrors from bundled plugin manifests and built root chunks, then install packed release tarballs without the repo `node_modules` so release checks catch missing plugin deps before publish.
|
||||
- Context engines: reject resolved plugin engines whose reported `info.id` does not match their registered slot id, so malformed engines fail fast before id-based runtime branches can misbehave. (#63222) Thanks @fuller-stack-dev.
|
||||
|
||||
## 2026.4.8
|
||||
|
||||
|
||||
@@ -757,6 +757,30 @@ describe("Invalid engine fallback", () => {
|
||||
);
|
||||
});
|
||||
|
||||
it("rejects resolved engines whose info.id mismatches the registered id", async () => {
|
||||
const engineId = `mismatched-info-id-${Date.now().toString(36)}`;
|
||||
registerContextEngine(
|
||||
engineId,
|
||||
() =>
|
||||
({
|
||||
info: { id: "legacy", name: "Broken Engine" },
|
||||
async ingest() {
|
||||
return { ingested: false };
|
||||
},
|
||||
async assemble({ messages }: { messages: AgentMessage[] }) {
|
||||
return { messages, estimatedTokens: 0 };
|
||||
},
|
||||
async compact() {
|
||||
return { ok: true, compacted: false };
|
||||
},
|
||||
}) as unknown as ContextEngine,
|
||||
);
|
||||
|
||||
await expect(resolveContextEngine(configWithSlot(engineId))).rejects.toThrow(
|
||||
`Context engine "${engineId}" factory returned an invalid ContextEngine: info.id must match registered id "${engineId}".`,
|
||||
);
|
||||
});
|
||||
|
||||
it("rejects resolved engines that omit required lifecycle methods", async () => {
|
||||
const engineId = `invalid-methods-${Date.now().toString(36)}`;
|
||||
registerContextEngine(
|
||||
|
||||
@@ -410,8 +410,11 @@ function describeResolvedContextEngineContractError(
|
||||
issues.push("missing info");
|
||||
} else {
|
||||
const infoRecord = info as Record<string, unknown>;
|
||||
if (typeof infoRecord.id !== "string" || !infoRecord.id.trim()) {
|
||||
const infoId = typeof infoRecord.id === "string" ? infoRecord.id.trim() : "";
|
||||
if (!infoId) {
|
||||
issues.push("missing info.id");
|
||||
} else if (infoId !== engineId) {
|
||||
issues.push(`info.id must match registered id "${engineId}"`);
|
||||
}
|
||||
if (typeof infoRecord.name !== "string" || !infoRecord.name.trim()) {
|
||||
issues.push("missing info.name");
|
||||
|
||||
Reference in New Issue
Block a user