fix: deduplicate desktop notifications and tighten notification text extraction

Desktop notifications no longer duplicate when native delivery succeeds
Reasoning chain-of-thought is excluded from notification body text
Untyped message parts are ignored in notification text extraction
This commit is contained in:
Bohdan Triapitsyn
2026-06-16 15:21:27 +03:00
parent 6ea8fb357d
commit 91de51d1a5
7 changed files with 144 additions and 46 deletions
@@ -30,3 +30,55 @@ describe('notification template runtime zen models', () => {
await expect(runtime.resolveZenModel()).resolves.toBe('trinity-large-preview-free');
});
});
describe('notification template message extraction', () => {
afterEach(() => {
globalThis.fetch = originalFetch;
});
it('excludes reasoning parts from payload message text', () => {
const runtime = createRuntime();
expect(runtime.extractLastMessageText({
properties: {
info: {
parts: [
{ type: 'reasoning', text: 'private chain of thought' },
{ type: 'text', text: 'final answer' },
],
},
},
})).toBe('final answer');
});
it('ignores untyped parts even when they contain text', () => {
const runtime = createRuntime();
expect(runtime.extractLastMessageText({
properties: {
info: {
parts: [
{ text: 'untyped text' },
{ content: 'untyped content' },
{ type: 'text', text: 'typed final answer' },
],
},
},
})).toBe('typed final answer');
});
it('excludes reasoning parts when fetching assistant messages', async () => {
const runtime = createRuntime();
globalThis.fetch = vi.fn(async () => new Response(JSON.stringify([
{
info: { id: 'msg-1', role: 'assistant', finish: 'stop' },
parts: [
{ type: 'reasoning', text: 'private chain of thought' },
{ type: 'text', text: 'final answer' },
],
},
])));
await expect(runtime.fetchLastAssistantMessageText('session-1', 'msg-1')).resolves.toBe('final answer');
});
});