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:
Eyejoker
2026-04-28 01:35:26 +09:00
committed by GitHub
parent 20e1a1e5e1
commit 8bb77ffaa3
11 changed files with 291 additions and 14 deletions

View File

@@ -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 } : {}),
};
}

View File

@@ -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('');
});
});