Stale-Job-Reset, Ownership-Angleichung, robuste Dashboard-Erzeugung

- Server-Neustart setzt hängengebliebene Jobs (running/queued) zurück
  (markStaleJobs) mit Hinweis-Nachricht; /abort räumt auch verwaiste Sessions auf
- Löschen/Abbrechen/Modellwechsel ohne Owner-Beschränkung (konsistent zur
  offenen Sichtbarkeit im Ein-Nutzer-System)
- Dashboard-HTML wird nicht mehr per Tool-Aufruf übertragen, sondern in der
  finalen Antwort als ```html```-Codeblock gestreamt (GLM scheiterte
  reproduzierbar am riesigen Tool-Call); Extraktion mit klaren Fehlern bei
  fehlendem/unvollständigem Codeblock
- Reasoning-Effort pro Runde: volle Tiefe in Research-Runden, minimales Denken
  in der Dashboard-Liefer-Runde (DeepSeek: thinking aus, GLM: low) –
  Budget gehört dem HTML
- GLM-Reasoning-Default high (max verbrennt das Completion-Budget),
  DeepSeek max_tokens auf 300k
This commit is contained in:
nico committed 2026-08-28 09:17:13 +02:00
1 parent 8a2bf46b09
commit ab4f8e8570
6 files changed
+178 -36

No files matched your search

+19 -8
View File
@@ -165,7 +165,7 @@ app.post('/api/sessions', requireAuth, (req, res) => {
app.patch('/api/sessions/:id', requireAuth, (req, res) => {
const session = db.getSession(req.params.id);
if (!session || session.owner_name !== req.user.n) {
if (!session) {
return res.status(404).json({ error: 'Session nicht gefunden' });
}
const modelId = String(req.body?.model || '');
@@ -206,7 +206,7 @@ app.get('/api/sessions/:id/share', requireAuth, (req, res) => {
app.delete('/api/sessions/:id', requireAuth, (req, res) => {
const session = db.getSession(req.params.id);
if (!session || session.owner_name !== req.user.n) {
if (!session) {
return res.status(404).json({ error: 'Session nicht gefunden' });
}
queue.cancelQueued(session.id);
@@ -218,19 +218,23 @@ app.delete('/api/sessions/:id', requireAuth, (req, res) => {
app.post('/api/sessions/:id/abort', requireAuth, (req, res) => {
const session = db.getSession(req.params.id);
if (!session || session.owner_name !== req.user.n) {
if (!session) {
return res.status(404).json({ error: 'Session nicht gefunden' });
}
if (queue.queuedBefore(session.id) >= 0) {
// Job wartet noch in der Queue → direkt entfernen
// Job wartet noch in der Queue → direkt entfernen und aufräumen
queue.cancelQueued(session.id);
db.setSessionStatus(session.id, 'done');
emitToSession(session.id, 'aborted', {});
emitToSession(session.id, 'status', { sessionStatus: 'done', jobStatus: 'aborted' });
} else {
} else if (queue.hasController(session.id)) {
// Laufender Job → Controller auslösen, der Job räumt selbst auf
queue.abortRunning(session.id);
return res.json({ ok: true });
}
// Wartender Job oder veralteter Job (z.B. nach Server-Neustart, ohne
// laufenden Prozess): Zustand und UI direkt zurücksetzen
db.createMessage(session.id, { role: 'assistant', content: '⛔ Recherche abgebrochen.' });
db.setSessionStatus(session.id, 'done');
emitToSession(session.id, 'aborted', {});
emitToSession(session.id, 'status', { sessionStatus: 'done', jobStatus: 'aborted' });
res.json({ ok: true });
});
@@ -445,6 +449,13 @@ app.get('/', (req, res) => {
// ---------------------------------------------------------------------------
// Nach einem Server-Neustart hängengebliebene Jobs (running/queued in der DB)
// zurücksetzen – die Jobs existieren im Speicher nicht mehr.
const staleCount = db.markStaleJobs();
if (staleCount > 0) {
console.log(`INFO: ${staleCount} verwaiste Recherche(n) nach Neustart zurückgesetzt.`);
}
if (!config.apiKey) {
console.error('WARNUNG: DEEPSEEK_API_KEY fehlt in .env – DeepSeek-Modelle werden nicht funktionieren.');
}