Fix structured IPC envelope leakage
Normalize EJClaw structured send_message envelopes, preserve attachments, unwrap stored room payloads, and add regression tests.
This commit is contained in:
@@ -1,3 +1,8 @@
|
||||
import {
|
||||
normalizeEjclawStructuredOutput,
|
||||
type RunnerOutputAttachment,
|
||||
} from 'ejclaw-runners-shared';
|
||||
|
||||
export interface SendMessageIpcPayloadInput {
|
||||
chatJid: string;
|
||||
text: string;
|
||||
@@ -8,17 +13,36 @@ export interface SendMessageIpcPayloadInput {
|
||||
timestamp?: string;
|
||||
}
|
||||
|
||||
export interface SendMessageIpcPayload {
|
||||
type: 'message';
|
||||
chatJid: string;
|
||||
text: string;
|
||||
sender?: string;
|
||||
senderRole?: string;
|
||||
runId?: string;
|
||||
groupFolder: string;
|
||||
timestamp: string;
|
||||
attachments?: RunnerOutputAttachment[];
|
||||
}
|
||||
|
||||
export function buildSendMessageIpcPayload(
|
||||
input: SendMessageIpcPayloadInput,
|
||||
): Record<string, string | undefined> {
|
||||
): SendMessageIpcPayload {
|
||||
const normalized = normalizeEjclawStructuredOutput(input.text);
|
||||
const output =
|
||||
normalized.output?.visibility === 'public' ? normalized.output : null;
|
||||
const text = output?.text ?? normalized.result ?? '';
|
||||
const attachments = output?.attachments ?? [];
|
||||
|
||||
return {
|
||||
type: 'message',
|
||||
chatJid: input.chatJid,
|
||||
text: input.text,
|
||||
text,
|
||||
sender: input.sender || undefined,
|
||||
senderRole: input.senderRole || undefined,
|
||||
runId: input.runId || undefined,
|
||||
groupFolder: input.groupFolder,
|
||||
timestamp: input.timestamp || new Date().toISOString(),
|
||||
...(attachments.length > 0 ? { attachments } : {}),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -37,4 +37,52 @@ describe('agent runner IPC message payload', () => {
|
||||
}).senderRole,
|
||||
).toBeUndefined();
|
||||
});
|
||||
|
||||
it('normalizes structured EJClaw envelopes instead of leaking raw JSON', () => {
|
||||
expect(
|
||||
buildSendMessageIpcPayload({
|
||||
chatJid: 'dc:123',
|
||||
text: JSON.stringify({
|
||||
ejclaw: {
|
||||
visibility: 'public',
|
||||
text: '스크린샷입니다.',
|
||||
verdict: 'done',
|
||||
attachments: [
|
||||
{
|
||||
path: '/tmp/ejclaw-room-mobile-list-390.png',
|
||||
name: 'room.png',
|
||||
mime: 'image/png',
|
||||
},
|
||||
],
|
||||
},
|
||||
}),
|
||||
groupFolder: 'discord-review',
|
||||
timestamp: '2026-04-04T13:45:00.000Z',
|
||||
}),
|
||||
).toEqual({
|
||||
type: 'message',
|
||||
chatJid: 'dc:123',
|
||||
text: '스크린샷입니다.',
|
||||
groupFolder: 'discord-review',
|
||||
timestamp: '2026-04-04T13:45:00.000Z',
|
||||
attachments: [
|
||||
{
|
||||
path: '/tmp/ejclaw-room-mobile-list-390.png',
|
||||
name: 'room.png',
|
||||
mime: 'image/png',
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it('turns silent EJClaw envelopes into empty no-op messages', () => {
|
||||
expect(
|
||||
buildSendMessageIpcPayload({
|
||||
chatJid: 'dc:123',
|
||||
text: '{"ejclaw":{"visibility":"silent","verdict":"silent"}}',
|
||||
groupFolder: 'discord-review',
|
||||
timestamp: '2026-04-04T13:45:00.000Z',
|
||||
}).text,
|
||||
).toBe('');
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user