mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-19 21:21:10 +00:00
fix(matrix): preserve send aliases and voice intent
This commit is contained in:
@@ -220,6 +220,7 @@ Docs: https://docs.openclaw.ai
|
||||
### Fixes
|
||||
|
||||
- Agents/bootstrap warnings: move bootstrap truncation warnings out of the system prompt and into the per-turn prompt body so prompt-cache reuse stays stable when truncation warnings appear or disappear. (#48753) Thanks @scoootscooob and @obviyus.
|
||||
- Plugins/Matrix: accept shared send-tool media aliases (`mediaUrl`, `filePath`, `path`) and preserve `asVoice` / `audioAsVoice` through Matrix action dispatch so media-only sends and voice-message intents reach the plugin send layer correctly. Thanks @psacc and @vincentkoc.
|
||||
- Telegram/DM topic session keys: route named-account DM topics through the same per-account base session key across inbound messages, native commands, and session-state lookups so `/status` and thread recovery stop creating phantom `agent:main:main:thread:...` sessions. (#48204) Thanks @vincentkoc.
|
||||
- macOS/node service startup: use `openclaw node start/stop --json` from the Mac app instead of the removed `openclaw service node ...` command shape, so current CLI installs expose the full node exec surface again. (#46843) Fixes #43171. Thanks @Br1an67.
|
||||
- macOS/launch at login: stop emitting `KeepAlive` for the desktop app launch agent so OpenClaw no longer relaunches immediately after a manual quit while launch at login remains enabled. (#40213) Thanks @stablegenius49.
|
||||
|
||||
@@ -181,4 +181,30 @@ describe("matrixMessageActions account propagation", () => {
|
||||
{ mediaLocalRoots: undefined },
|
||||
);
|
||||
});
|
||||
|
||||
it("accepts shared media aliases and forwards voice-send intent", async () => {
|
||||
await matrixMessageActions.handleAction?.(
|
||||
createContext({
|
||||
action: "send",
|
||||
accountId: "ops",
|
||||
params: {
|
||||
to: "room:!room:example",
|
||||
filePath: "/tmp/clip.mp3",
|
||||
asVoice: true,
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
expect(mocks.handleMatrixAction).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
action: "sendMessage",
|
||||
accountId: "ops",
|
||||
content: undefined,
|
||||
mediaUrl: "/tmp/clip.mp3",
|
||||
audioAsVoice: true,
|
||||
}),
|
||||
expect.any(Object),
|
||||
{ mediaLocalRoots: undefined },
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -162,13 +162,23 @@ export const matrixMessageActions: ChannelMessageActionAdapter = {
|
||||
|
||||
if (action === "send") {
|
||||
const to = readStringParam(params, "to", { required: true });
|
||||
const mediaUrl = readStringParam(params, "media", { trim: false });
|
||||
const mediaUrl =
|
||||
readStringParam(params, "media", { trim: false }) ??
|
||||
readStringParam(params, "mediaUrl", { trim: false }) ??
|
||||
readStringParam(params, "filePath", { trim: false }) ??
|
||||
readStringParam(params, "path", { trim: false });
|
||||
const content = readStringParam(params, "message", {
|
||||
required: !mediaUrl,
|
||||
allowEmpty: true,
|
||||
});
|
||||
const replyTo = readStringParam(params, "replyTo");
|
||||
const threadId = readStringParam(params, "threadId");
|
||||
const audioAsVoice =
|
||||
typeof params.asVoice === "boolean"
|
||||
? params.asVoice
|
||||
: typeof params.audioAsVoice === "boolean"
|
||||
? params.audioAsVoice
|
||||
: undefined;
|
||||
return await dispatch({
|
||||
action: "sendMessage",
|
||||
to,
|
||||
@@ -176,6 +186,7 @@ export const matrixMessageActions: ChannelMessageActionAdapter = {
|
||||
mediaUrl: mediaUrl ?? undefined,
|
||||
replyToId: replyTo ?? undefined,
|
||||
threadId: threadId ?? undefined,
|
||||
audioAsVoice,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ export async function sendMatrixMessage(
|
||||
mediaUrl?: string;
|
||||
replyToId?: string;
|
||||
threadId?: string;
|
||||
audioAsVoice?: boolean;
|
||||
} = {},
|
||||
) {
|
||||
return await sendMessageMatrix(to, content, {
|
||||
@@ -29,6 +30,7 @@ export async function sendMatrixMessage(
|
||||
mediaLocalRoots: opts.mediaLocalRoots,
|
||||
replyToId: opts.replyToId,
|
||||
threadId: opts.threadId,
|
||||
audioAsVoice: opts.audioAsVoice,
|
||||
accountId: opts.accountId ?? undefined,
|
||||
client: opts.client,
|
||||
timeoutMs: opts.timeoutMs,
|
||||
|
||||
@@ -249,6 +249,31 @@ describe("handleMatrixAction pollVote", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("accepts shared media aliases and voice-send flags", async () => {
|
||||
const cfg = { channels: { matrix: { actions: { messages: true } } } } as CoreConfig;
|
||||
await handleMatrixAction(
|
||||
{
|
||||
action: "sendMessage",
|
||||
accountId: "ops",
|
||||
to: "room:!room:example",
|
||||
path: "/tmp/clip.mp3",
|
||||
asVoice: true,
|
||||
},
|
||||
cfg,
|
||||
{ mediaLocalRoots: ["/tmp/openclaw-matrix-test"] },
|
||||
);
|
||||
|
||||
expect(mocks.sendMatrixMessage).toHaveBeenCalledWith("room:!room:example", undefined, {
|
||||
cfg,
|
||||
accountId: "ops",
|
||||
mediaUrl: "/tmp/clip.mp3",
|
||||
mediaLocalRoots: ["/tmp/openclaw-matrix-test"],
|
||||
replyToId: undefined,
|
||||
threadId: undefined,
|
||||
audioAsVoice: true,
|
||||
});
|
||||
});
|
||||
|
||||
it("passes mediaLocalRoots to profile updates", async () => {
|
||||
const cfg = { channels: { matrix: { actions: { profile: true } } } } as CoreConfig;
|
||||
await handleMatrixAction(
|
||||
|
||||
@@ -219,7 +219,11 @@ export async function handleMatrixAction(
|
||||
switch (action) {
|
||||
case "sendMessage": {
|
||||
const to = readStringParam(params, "to", { required: true });
|
||||
const mediaUrl = readStringParam(params, "mediaUrl");
|
||||
const mediaUrl =
|
||||
readStringParam(params, "mediaUrl", { trim: false }) ??
|
||||
readStringParam(params, "media", { trim: false }) ??
|
||||
readStringParam(params, "filePath", { trim: false }) ??
|
||||
readStringParam(params, "path", { trim: false });
|
||||
const content = readStringParam(params, "content", {
|
||||
required: !mediaUrl,
|
||||
allowEmpty: true,
|
||||
@@ -227,11 +231,18 @@ export async function handleMatrixAction(
|
||||
const replyToId =
|
||||
readStringParam(params, "replyToId") ?? readStringParam(params, "replyTo");
|
||||
const threadId = readStringParam(params, "threadId");
|
||||
const audioAsVoice =
|
||||
typeof readRawParam(params, "audioAsVoice") === "boolean"
|
||||
? (readRawParam(params, "audioAsVoice") as boolean)
|
||||
: typeof readRawParam(params, "asVoice") === "boolean"
|
||||
? (readRawParam(params, "asVoice") as boolean)
|
||||
: undefined;
|
||||
const result = await sendMatrixMessage(to, content, {
|
||||
mediaUrl: mediaUrl ?? undefined,
|
||||
mediaLocalRoots: opts.mediaLocalRoots,
|
||||
replyToId: replyToId ?? undefined,
|
||||
threadId: threadId ?? undefined,
|
||||
audioAsVoice,
|
||||
...clientOpts,
|
||||
});
|
||||
return jsonResult({ ok: true, result });
|
||||
|
||||
Reference in New Issue
Block a user