feat(channels): emit line and zalo binary attachment fallback notices

This commit is contained in:
William Valentin
2026-02-17 10:36:47 -08:00
parent ac29789d89
commit 2007c0c060
5 changed files with 34 additions and 2 deletions
+14
View File
@@ -3646,6 +3646,20 @@
"docs/plans/state.json"
],
"test_status": "pnpm test:run src/skills/planner.test.ts src/cli/skills.test.ts + pnpm typecheck passing"
},
"line-zalo-binary-fallback-notices": {
"status": "completed",
"date": "2026-02-17",
"updated": "2026-02-17",
"summary": "Improved LINE/Zalo binary attachment handling by emitting recipient-visible fallback messages whenever raw binary upload is unavailable, preventing silent loss while preserving warning logs.",
"files_modified": [
"src/channels/line/adapter.ts",
"src/channels/line/adapter.test.ts",
"src/channels/zalo/adapter.ts",
"src/channels/zalo/adapter.test.ts",
"docs/plans/state.json"
],
"test_status": "pnpm test:run src/channels/line/adapter.test.ts src/channels/zalo/adapter.test.ts + pnpm typecheck passing"
}
},
"overall_progress": {
+3 -1
View File
@@ -95,9 +95,11 @@ describe('LineAdapter', () => {
],
});
expect(mockFetch).toHaveBeenCalledTimes(2);
expect(mockFetch).toHaveBeenCalledTimes(3);
const secondBody = JSON.parse(String(mockFetch.mock.calls[1]?.[1]?.body ?? '{}'));
const thirdBody = JSON.parse(String(mockFetch.mock.calls[2]?.[1]?.body ?? '{}'));
expect(secondBody.messages?.[0]?.text).toBe('file.txt: https://example.com/file.txt');
expect(thirdBody.messages?.[0]?.text).toBe('[LINE] Binary attachment not uploaded yet: attachment (image/png).');
expect(warnSpy).toHaveBeenCalledWith('LINE: skipping attachment data (image/png) — upload not implemented');
warnSpy.mockRestore();
});
+7
View File
@@ -90,6 +90,7 @@ export class LineAdapter implements ChannelAdapter {
}
if (attachment.data) {
console.warn(`LINE: skipping attachment data (${attachment.mimeType}) — upload not implemented`);
await this.sendPush(peerId, formatBinaryAttachmentNotice('LINE', attachment.filename, attachment.mimeType));
}
}
}
@@ -240,3 +241,9 @@ export class LineAdapter implements ChannelAdapter {
function escapeRegex(value: string): string {
return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
}
function formatBinaryAttachmentNotice(channel: string, filename?: string, mimeType?: string): string {
const name = filename || 'attachment';
const type = mimeType || 'application/octet-stream';
return `[${channel}] Binary attachment not uploaded yet: ${name} (${type}).`;
}
+3 -1
View File
@@ -81,9 +81,11 @@ describe('ZaloAdapter', () => {
],
});
expect(mockFetch).toHaveBeenCalledTimes(2);
expect(mockFetch).toHaveBeenCalledTimes(3);
const secondBody = JSON.parse(String(mockFetch.mock.calls[1]?.[1]?.body ?? '{}'));
const thirdBody = JSON.parse(String(mockFetch.mock.calls[2]?.[1]?.body ?? '{}'));
expect(secondBody.message?.text).toBe('file.txt: https://example.com/file.txt');
expect(thirdBody.message?.text).toBe('[Zalo] Binary attachment not uploaded yet: attachment (application/pdf).');
expect(warnSpy).toHaveBeenCalledWith('Zalo: skipping attachment data (application/pdf) — upload not implemented');
warnSpy.mockRestore();
});
+7
View File
@@ -80,6 +80,7 @@ export class ZaloAdapter implements ChannelAdapter {
}
if (attachment.data) {
console.warn(`Zalo: skipping attachment data (${attachment.mimeType}) — upload not implemented`);
await this.sendText(peerId, formatBinaryAttachmentNotice('Zalo', attachment.filename, attachment.mimeType));
}
}
}
@@ -189,3 +190,9 @@ export class ZaloAdapter implements ChannelAdapter {
function escapeRegex(value: string): string {
return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
}
function formatBinaryAttachmentNotice(channel: string, filename?: string, mimeType?: string): string {
const name = filename || 'attachment';
const type = mimeType || 'application/octet-stream';
return `[${channel}] Binary attachment not uploaded yet: ${name} (${type}).`;
}