Skip to content

Commit cf290e3

Browse files
steipetegiumex
andcommitted
fix(voice-call): align plugin manifest schema with runtime config fields (openclaw#38892)
Co-authored-by: giumex <[email protected]>
1 parent 43b36bf commit cf290e3

3 files changed

Lines changed: 93 additions & 1 deletion

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,7 @@ Docs: https://docs.openclaw.ai
265265
- Config/validation log sanitization: sanitize config-validation issue paths/messages before logging so control characters and ANSI escape sequences cannot inject misleading terminal output from crafted config content. (#39116) Thanks @powermaster888.
266266
- Agents/compaction counter accuracy: count successful overflow-triggered auto-compactions (`willRetry=true`) in the compaction counter while still excluding aborted/no-result events, so `/status` reflects actual safeguard compaction activity. (#39123) Thanks @MumuTW.
267267
- Gateway/chat delta ordering: flush buffered assistant deltas before emitting tool `start` events so pre-tool text is delivered to Control UI before tool cards, avoiding transient text/tool ordering artifacts in streaming. (#39128) Thanks @0xtangping.
268+
- Voice-call plugin schema parity: add missing manifest `configSchema` fields (`webhookSecurity`, `streaming.preStartTimeoutMs|maxPendingConnections|maxPendingConnectionsPerIp|maxConnections`, `staleCallReaperSeconds`) so gateway AJV validation accepts already-supported runtime config instead of failing with `additionalProperties` errors. (#38892) Thanks @giumex.
268269

269270
## 2026.3.2
270271

extensions/voice-call/openclaw.plugin.json

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,10 @@
249249
"type": "integer",
250250
"minimum": 1
251251
},
252+
"staleCallReaperSeconds": {
253+
"type": "integer",
254+
"minimum": 0
255+
},
252256
"silenceTimeoutMs": {
253257
"type": "integer",
254258
"minimum": 1
@@ -313,6 +317,27 @@
313317
}
314318
}
315319
},
320+
"webhookSecurity": {
321+
"type": "object",
322+
"additionalProperties": false,
323+
"properties": {
324+
"allowedHosts": {
325+
"type": "array",
326+
"items": {
327+
"type": "string"
328+
}
329+
},
330+
"trustForwardingHeaders": {
331+
"type": "boolean"
332+
},
333+
"trustedProxyIPs": {
334+
"type": "array",
335+
"items": {
336+
"type": "string"
337+
}
338+
}
339+
}
340+
},
316341
"streaming": {
317342
"type": "object",
318343
"additionalProperties": false,
@@ -341,6 +366,22 @@
341366
},
342367
"streamPath": {
343368
"type": "string"
369+
},
370+
"preStartTimeoutMs": {
371+
"type": "integer",
372+
"minimum": 1
373+
},
374+
"maxPendingConnections": {
375+
"type": "integer",
376+
"minimum": 1
377+
},
378+
"maxPendingConnectionsPerIp": {
379+
"type": "integer",
380+
"minimum": 1
381+
},
382+
"maxConnections": {
383+
"type": "integer",
384+
"minimum": 1
344385
}
345386
}
346387
},

src/config/config.plugin-validation.test.ts

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ describe("config plugin validation", () => {
3737
let badPluginDir = "";
3838
let enumPluginDir = "";
3939
let bluebubblesPluginDir = "";
40+
let voiceCallSchemaPluginDir = "";
4041
const envSnapshot = {
4142
OPENCLAW_STATE_DIR: process.env.OPENCLAW_STATE_DIR,
4243
OPENCLAW_PLUGIN_MANIFEST_CACHE_MS: process.env.OPENCLAW_PLUGIN_MANIFEST_CACHE_MS,
@@ -83,6 +84,24 @@ describe("config plugin validation", () => {
8384
channels: ["bluebubbles"],
8485
schema: { type: "object" },
8586
});
87+
voiceCallSchemaPluginDir = path.join(suiteHome, "voice-call-schema-plugin");
88+
const voiceCallManifestPath = path.join(
89+
process.cwd(),
90+
"extensions",
91+
"voice-call",
92+
"openclaw.plugin.json",
93+
);
94+
const voiceCallManifest = JSON.parse(await fs.readFile(voiceCallManifestPath, "utf-8")) as {
95+
configSchema?: Record<string, unknown>;
96+
};
97+
if (!voiceCallManifest.configSchema) {
98+
throw new Error("voice-call manifest missing configSchema");
99+
}
100+
await writePluginFixture({
101+
dir: voiceCallSchemaPluginDir,
102+
id: "voice-call-schema-fixture",
103+
schema: voiceCallManifest.configSchema,
104+
});
86105
process.env.OPENCLAW_STATE_DIR = path.join(suiteHome, ".openclaw");
87106
process.env.OPENCLAW_PLUGIN_MANIFEST_CACHE_MS = "10000";
88107
clearPluginManifestRegistryCache();
@@ -91,7 +110,7 @@ describe("config plugin validation", () => {
91110
validateInSuite({
92111
plugins: {
93112
enabled: false,
94-
load: { paths: [badPluginDir, bluebubblesPluginDir] },
113+
load: { paths: [badPluginDir, bluebubblesPluginDir, voiceCallSchemaPluginDir] },
95114
},
96115
});
97116
});
@@ -229,6 +248,37 @@ describe("config plugin validation", () => {
229248
}
230249
});
231250

251+
it("accepts voice-call webhookSecurity and streaming guard config fields", async () => {
252+
const res = validateInSuite({
253+
agents: { list: [{ id: "pi" }] },
254+
plugins: {
255+
enabled: true,
256+
load: { paths: [voiceCallSchemaPluginDir] },
257+
entries: {
258+
"voice-call-schema-fixture": {
259+
config: {
260+
provider: "twilio",
261+
webhookSecurity: {
262+
allowedHosts: ["voice.example.com"],
263+
trustForwardingHeaders: false,
264+
trustedProxyIPs: ["127.0.0.1"],
265+
},
266+
streaming: {
267+
enabled: true,
268+
preStartTimeoutMs: 5000,
269+
maxPendingConnections: 16,
270+
maxPendingConnectionsPerIp: 4,
271+
maxConnections: 64,
272+
},
273+
staleCallReaperSeconds: 180,
274+
},
275+
},
276+
},
277+
},
278+
});
279+
expect(res.ok).toBe(true);
280+
});
281+
232282
it("accepts known plugin ids and valid channel/heartbeat enums", async () => {
233283
const res = validateInSuite({
234284
agents: {

0 commit comments

Comments
 (0)