refactor(text): extract shared summarization service with tts/note/notification modes
Move server-side summarization out of lib/tts/summarization.js into a shared lib/text module exposing tts, note and notification modes. TTS and notification runtimes now delegate to the shared service, note mode is used to distill a selected excerpt into a short project note. Expose the new endpoint via /api/text/summarize and route it through the common request middleware. Client voice/summarize.ts accepts a mode option and points at the new endpoint with an absolute URL that respects the desktop server origin. VS Code webview swaps the stubbed tts summarize path for /api/text/summarize and hardens URL parsing with window.location.href as the base.
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import express from 'express';
|
||||
import { normalizeCustomOpenAIBaseURL } from './base-url.js';
|
||||
import { summarizeText, sanitizeForTTS, sanitizeForNote } from '../text/summarization.js';
|
||||
|
||||
export function registerTtsRoutes(app, { resolveZenModel, sayTTSCapability }) {
|
||||
let ttsModulePromise = null;
|
||||
@@ -76,9 +77,8 @@ export function registerTtsRoutes(app, { resolveZenModel, sayTTSCapability }) {
|
||||
// Optionally summarize long text before speaking using zen API
|
||||
if (summarize && textToSpeak.length > threshold) {
|
||||
try {
|
||||
const { summarizeText } = await getTtsModule();
|
||||
const speakZenModel = await resolveZenModel(typeof req.body?.zenModel === 'string' ? req.body.zenModel : undefined);
|
||||
const result = await summarizeText({ text: textToSpeak, threshold, maxLength, zenModel: speakZenModel });
|
||||
const result = await summarizeText({ text: textToSpeak, threshold, maxLength, zenModel: speakZenModel, mode: 'tts' });
|
||||
|
||||
if (result.summarized && result.summary) {
|
||||
textToSpeak = result.summary;
|
||||
@@ -115,23 +115,29 @@ export function registerTtsRoutes(app, { resolveZenModel, sayTTSCapability }) {
|
||||
}
|
||||
});
|
||||
|
||||
app.post('/api/tts/summarize', async (req, res) => {
|
||||
app.post('/api/text/summarize', async (req, res) => {
|
||||
try {
|
||||
const { summarizeText } = await getTtsModule();
|
||||
const { text, threshold = 200, maxLength = 500 } = req.body || {};
|
||||
const { text, threshold = 200, maxLength = 500, mode } = req.body || {};
|
||||
|
||||
if (!text || typeof text !== 'string' || !text.trim()) {
|
||||
return res.status(400).json({ error: 'Text is required' });
|
||||
}
|
||||
|
||||
const sumZenModel = await resolveZenModel(typeof req.body?.zenModel === 'string' ? req.body.zenModel : undefined);
|
||||
const result = await summarizeText({ text, threshold, maxLength, zenModel: sumZenModel });
|
||||
const result = await summarizeText({
|
||||
text,
|
||||
threshold,
|
||||
maxLength,
|
||||
zenModel: sumZenModel,
|
||||
mode: typeof mode === 'string' ? mode : 'tts',
|
||||
});
|
||||
|
||||
return res.json(result);
|
||||
} catch (error) {
|
||||
console.error('[Summarize] Error:', error);
|
||||
const { sanitizeForTTS } = await getTtsModule();
|
||||
const sanitized = sanitizeForTTS(req.body?.text || '');
|
||||
const sanitized = typeof req.body?.mode === 'string' && req.body.mode === 'note'
|
||||
? sanitizeForNote(req.body?.text || '')
|
||||
: sanitizeForTTS(req.body?.text || '');
|
||||
return res.json({ summary: sanitized, summarized: false, reason: error.message });
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user