fix: portal stability, session list DB fallback, and UX polish
- Free stale Memind listeners on 8081 before startup and exit cleanly on EADDRINUSE - Backfill owned sessions missing from Goose via h5_conversation_messages summaries - Strip Memind task orchestration prefixes from user-facing chat text - Repair missing public docx links before release MindSpace link checks Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -6,6 +6,7 @@ import {
|
||||
normalizeApiUrl,
|
||||
resolveChatCompletionsUrl,
|
||||
} from './llm-providers.mjs';
|
||||
import { deriveUserFacingText } from './conversation-display.mjs';
|
||||
|
||||
const httpsDispatcher = new Agent({
|
||||
connect: { rejectUnauthorized: false },
|
||||
@@ -419,11 +420,69 @@ export function createConversationMemoryService(pool, options = {}) {
|
||||
}));
|
||||
}
|
||||
|
||||
async function loadSessionListSummaries(userId, sessionIds = []) {
|
||||
if (!isEnabled() || !pool || !userId || !Array.isArray(sessionIds) || sessionIds.length === 0) {
|
||||
return new Map();
|
||||
}
|
||||
const ids = [...new Set(sessionIds.filter(Boolean))];
|
||||
if (!ids.length) return new Map();
|
||||
const placeholders = ids.map(() => '?').join(', ');
|
||||
const [rows] = await pool.query(
|
||||
`SELECT agent_session_id, role, text, raw_json, sequence_no, created_at, updated_at
|
||||
FROM h5_conversation_messages
|
||||
WHERE user_id = ? AND agent_session_id IN (${placeholders})
|
||||
ORDER BY sequence_no ASC, created_at ASC`,
|
||||
[userId, ...ids],
|
||||
);
|
||||
const buckets = new Map();
|
||||
for (const row of rows) {
|
||||
const sessionId = String(row.agent_session_id ?? '').trim();
|
||||
if (!sessionId) continue;
|
||||
if (!buckets.has(sessionId)) {
|
||||
buckets.set(sessionId, { messages: [], maxUpdatedAt: 0 });
|
||||
}
|
||||
const bucket = buckets.get(sessionId);
|
||||
bucket.messages.push(row);
|
||||
bucket.maxUpdatedAt = Math.max(
|
||||
bucket.maxUpdatedAt,
|
||||
Number(row.updated_at ?? row.created_at ?? 0),
|
||||
);
|
||||
}
|
||||
const summaries = new Map();
|
||||
for (const sessionId of ids) {
|
||||
const bucket = buckets.get(sessionId);
|
||||
if (!bucket || bucket.messages.length === 0) continue;
|
||||
const firstUser = bucket.messages.find((row) => String(row.role ?? '') === 'user');
|
||||
let title = '';
|
||||
if (firstUser) {
|
||||
let text = String(firstUser.text ?? '').trim();
|
||||
if (firstUser.raw_json) {
|
||||
try {
|
||||
const parsed = JSON.parse(firstUser.raw_json);
|
||||
text = extractConversationMessageText(parsed) || text;
|
||||
} catch {
|
||||
// keep text column fallback
|
||||
}
|
||||
}
|
||||
title = deriveUserFacingText(text).slice(0, 80);
|
||||
}
|
||||
summaries.set(sessionId, {
|
||||
title: title || sessionId,
|
||||
messageCount: bucket.messages.length,
|
||||
updatedAt: bucket.maxUpdatedAt
|
||||
? new Date(bucket.maxUpdatedAt).toISOString()
|
||||
: undefined,
|
||||
});
|
||||
}
|
||||
return summaries;
|
||||
}
|
||||
|
||||
return {
|
||||
isEnabled,
|
||||
saveConversationMessages,
|
||||
analyzeUser,
|
||||
saveAndAnalyze,
|
||||
listMemories,
|
||||
loadSessionListSummaries,
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user