mirror of https://github.com/openclaw/openclaw.git
fix: strip inbound metadata before slash command detection (#58674)
Slash commands like /model and /new were silently ignored when the inbound message body included metadata prefix blocks (Conversation info, Sender info, timestamps) injected by buildInboundUserContextPrefix. The command detection functions (hasControlCommand, isControlCommandMessage, parseSendPolicyCommand) now call stripInboundMetadata before normalizeCommandBody so embedded slash commands are correctly recognized.
This commit is contained in:
parent
fb28b02540
commit
3b1f8e3461
|
|
@ -877,4 +877,40 @@ describe("control command parsing", () => {
|
|||
}),
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it("detects commands wrapped in inbound metadata blocks", () => {
|
||||
const metaWrapped = [
|
||||
"Conversation info (untrusted metadata):",
|
||||
"```json",
|
||||
'{"message_id":"msg-abc","chat_id":"chat-123"}',
|
||||
"```",
|
||||
"",
|
||||
"/model spark",
|
||||
].join("\n");
|
||||
expect(hasControlCommand(metaWrapped)).toBe(true);
|
||||
});
|
||||
|
||||
it("detects /new command after metadata prefix", () => {
|
||||
const metaWrapped = [
|
||||
"Sender (untrusted metadata):",
|
||||
"```json",
|
||||
'{"name":"Alice","id":"user-1"}',
|
||||
"```",
|
||||
"",
|
||||
"/new spark",
|
||||
].join("\n");
|
||||
expect(hasControlCommand(metaWrapped)).toBe(true);
|
||||
});
|
||||
|
||||
it("detects /status command after timestamp + metadata prefix", () => {
|
||||
const metaWrapped = [
|
||||
"[Wed 2026-03-11 23:51 PDT] Conversation info (untrusted metadata):",
|
||||
"```json",
|
||||
'{"chat_id":"chat-123"}',
|
||||
"```",
|
||||
"",
|
||||
"/status",
|
||||
].join("\n");
|
||||
expect(hasControlCommand(metaWrapped)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import {
|
|||
normalizeCommandBody,
|
||||
} from "./commands-registry.js";
|
||||
import { isAbortTrigger } from "./reply/abort-primitives.js";
|
||||
import { stripInboundMetadata } from "./reply/strip-inbound-meta.js";
|
||||
|
||||
export function hasControlCommand(
|
||||
text?: string,
|
||||
|
|
@ -19,7 +20,11 @@ export function hasControlCommand(
|
|||
if (!trimmed) {
|
||||
return false;
|
||||
}
|
||||
const normalizedBody = normalizeCommandBody(trimmed, options);
|
||||
const stripped = stripInboundMetadata(trimmed);
|
||||
if (!stripped) {
|
||||
return false;
|
||||
}
|
||||
const normalizedBody = normalizeCommandBody(stripped, options);
|
||||
if (!normalizedBody) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -60,7 +65,8 @@ export function isControlCommandMessage(
|
|||
if (hasControlCommand(trimmed, cfg, options)) {
|
||||
return true;
|
||||
}
|
||||
const normalized = normalizeCommandBody(trimmed, options).trim().toLowerCase();
|
||||
const stripped = stripInboundMetadata(trimmed);
|
||||
const normalized = normalizeCommandBody(stripped, options).trim().toLowerCase();
|
||||
return isAbortTrigger(normalized);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { normalizeCommandBody } from "./commands-registry.js";
|
||||
import { stripInboundMetadata } from "./reply/strip-inbound-meta.js";
|
||||
|
||||
export type SendPolicyOverride = "allow" | "deny";
|
||||
|
||||
|
|
@ -27,7 +28,8 @@ export function parseSendPolicyCommand(raw?: string): {
|
|||
if (!trimmed) {
|
||||
return { hasCommand: false };
|
||||
}
|
||||
const normalized = normalizeCommandBody(trimmed);
|
||||
const stripped = stripInboundMetadata(trimmed);
|
||||
const normalized = normalizeCommandBody(stripped);
|
||||
const match = normalized.match(/^\/send(?:\s+([a-zA-Z]+))?\s*$/i);
|
||||
if (!match) {
|
||||
return { hasCommand: false };
|
||||
|
|
|
|||
Loading…
Reference in New Issue