chore: retire zen-backed summarization
Disable the active Zen summarization flow because the unauthenticated/free Zen provider is no longer available and now returns usage-limit errors for this feature.
Keep /api/text/summarize as an API-compatible stub that returns local sanitized or distilled fallback text with summarized=false, rather than attempting external model calls.
Remove notification and voice playback summary behavior from runtime paths. Notification {last_message} now always uses normalized truncated text, and TTS playback ignores historical summarize request fields.
Hide the notification summary settings and voice summarize-before-playback controls while preserving legacy persisted settings for compatibility. Also disable Zen model startup validation and make Zen model list routes return empty results.
Update module documentation and tests to describe the retired provider behavior and the remaining compatibility stubs.
This commit is contained in:
@@ -1,118 +1,34 @@
|
||||
import { afterEach, describe, expect, it, vi } from 'vitest';
|
||||
import { describe, expect, it } from 'vitest';
|
||||
|
||||
import { summarizeText } from './summarization.js';
|
||||
|
||||
const originalFetch = globalThis.fetch;
|
||||
describe('text summarization stubs', () => {
|
||||
it('does not call the retired zen provider', async () => {
|
||||
const result = await summarizeText({
|
||||
text: 'The implementation now correctly loads notification templates before dispatching the notification. It also fetches the latest assistant message when the event payload does not include message parts. This should make completion notifications match user settings.',
|
||||
threshold: 0,
|
||||
maxLength: 80,
|
||||
zenModel: 'gpt-5-nano',
|
||||
mode: 'notification',
|
||||
});
|
||||
|
||||
function stubFetch(fetchMock) {
|
||||
globalThis.fetch = fetchMock;
|
||||
}
|
||||
|
||||
describe('text summarization zen requests', () => {
|
||||
afterEach(() => {
|
||||
globalThis.fetch = originalFetch;
|
||||
expect(result.summarized).toBe(false);
|
||||
expect(result.reason).toBe('Model summarization provider unavailable');
|
||||
expect(result.summary).toBe('The implementation now correctly loads notification templates before dispatchin…');
|
||||
});
|
||||
|
||||
it('uses responses endpoint for gpt models', async () => {
|
||||
const fetchMock = vi.fn(async () => ({
|
||||
ok: true,
|
||||
json: async () => ({
|
||||
output: [{
|
||||
type: 'message',
|
||||
content: [{ type: 'output_text', text: 'Short summary' }],
|
||||
}],
|
||||
}),
|
||||
}));
|
||||
stubFetch(fetchMock);
|
||||
|
||||
it('returns local note fallback while provider is unavailable', async () => {
|
||||
const result = await summarizeText({
|
||||
text: 'Long text '.repeat(30),
|
||||
text: 'First sentence. Second sentence with the useful insight.',
|
||||
threshold: 0,
|
||||
maxLength: 100,
|
||||
zenModel: 'gpt-5-nano',
|
||||
mode: 'notification',
|
||||
mode: 'note',
|
||||
});
|
||||
|
||||
expect(fetchMock).toHaveBeenCalledWith(
|
||||
'https://opencode.ai/zen/v1/responses',
|
||||
expect.objectContaining({
|
||||
body: expect.stringContaining('"input"'),
|
||||
}),
|
||||
);
|
||||
expect(result.summary).toBe('Short summary');
|
||||
});
|
||||
|
||||
it('uses chat completions endpoint for openai-compatible zen models', async () => {
|
||||
const fetchMock = vi.fn(async () => ({
|
||||
ok: true,
|
||||
json: async () => ({
|
||||
choices: [{ message: { content: 'Chat summary' } }],
|
||||
}),
|
||||
}));
|
||||
stubFetch(fetchMock);
|
||||
|
||||
const result = await summarizeText({
|
||||
text: 'Long text '.repeat(30),
|
||||
threshold: 0,
|
||||
maxLength: 100,
|
||||
zenModel: 'big-pickle',
|
||||
mode: 'notification',
|
||||
expect(result).toMatchObject({
|
||||
summary: 'First sentence.',
|
||||
summarized: false,
|
||||
reason: 'Model summarization provider unavailable',
|
||||
});
|
||||
|
||||
expect(fetchMock).toHaveBeenCalledWith(
|
||||
'https://opencode.ai/zen/v1/chat/completions',
|
||||
expect.objectContaining({
|
||||
body: expect.stringContaining('"messages"'),
|
||||
}),
|
||||
);
|
||||
expect(result.summary).toBe('Chat summary');
|
||||
});
|
||||
|
||||
it('clamps successful model summaries to the requested max length', async () => {
|
||||
const fetchMock = vi.fn(async () => ({
|
||||
ok: true,
|
||||
json: async () => ({
|
||||
output: [{
|
||||
type: 'message',
|
||||
content: [{ type: 'output_text', text: 'This response is too long' }],
|
||||
}],
|
||||
}),
|
||||
}));
|
||||
stubFetch(fetchMock);
|
||||
|
||||
const result = await summarizeText({
|
||||
text: 'Long text '.repeat(30),
|
||||
threshold: 0,
|
||||
maxLength: 12,
|
||||
zenModel: 'gpt-5-nano',
|
||||
mode: 'notification',
|
||||
});
|
||||
|
||||
expect(result.summary).toBe('This respons');
|
||||
expect(result.summaryLength).toBe(12);
|
||||
});
|
||||
|
||||
it('does not clamp successful model summaries for non-finite max lengths', async () => {
|
||||
const fetchMock = vi.fn(async () => ({
|
||||
ok: true,
|
||||
json: async () => ({
|
||||
output: [{
|
||||
type: 'message',
|
||||
content: [{ type: 'output_text', text: 'Full response' }],
|
||||
}],
|
||||
}),
|
||||
}));
|
||||
stubFetch(fetchMock);
|
||||
|
||||
const result = await summarizeText({
|
||||
text: 'Long text '.repeat(30),
|
||||
threshold: 0,
|
||||
maxLength: Infinity,
|
||||
zenModel: 'gpt-5-nano',
|
||||
mode: 'notification',
|
||||
});
|
||||
|
||||
expect(result.summary).toBe('Full response');
|
||||
expect(result.summaryLength).toBe(13);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user