Files
Momento/memento-note/lib/dashboard/paths-fast.ts
Antigravity afbb0dfc2d
All checks were successful
CI / Lint, Unit Tests & Build (push) Successful in 6m57s
CI / Deploy production (on server) (push) Successful in 24s
fix(ui): thème, textes et lisibilité restants de la revue
Les boutons suivent la couleur d’apparence, les libellés trop petits ou trop techniques sont clarifiés, et le catalogue des fournisseurs se met à jour tout seul.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-30 21:13:07 +00:00

140 lines
4.2 KiB
TypeScript

import type { DashboardPath } from '@/lib/dashboard/path-types'
import { pathNoteTitle, pickFocusNote } from '@/lib/dashboard/path-title'
function excerpt(text: string, max = 120): string {
const plain = text.replace(/<[^>]+>/g, ' ').replace(/\s+/g, ' ').trim()
if (plain.length <= max) return plain
return `${plain.slice(0, max)}`
}
export interface BriefingPathsInput {
recentNotes: Array<{
id: string
title: string | null
content: string
notebookId: string | null
}>
inboxCount: number
dueFlashcards: number
insights: Array<{
id: string
insight: string
score: number
viewed: boolean
note1: { id: string; title: string | null }
note2: { id: string; title: string | null }
note1Excerpt?: string
note2Excerpt?: string
}>
bridgeSuggestions: Array<{
clusterAId: number
clusterBId: number
clusterAName: string
clusterBName: string
suggestedTitle: string
suggestedContent: string
justification: string
}>
agentSuggestions: Array<{
id: string
topic: string
reason: string
clusterId: number | null
}>
}
/** Pistes instantanées à partir du briefing déjà chargé — sans requête lourde. */
export function buildFastPathsFromBriefing(input: BriefingPathsInput): DashboardPath[] {
const paths: DashboardPath[] = []
const focus = pickFocusNote(input.recentNotes)
const continueTitle = focus ? pathNoteTitle(focus.title, focus.content) : null
if (focus && continueTitle) {
paths.push({
id: `continue-${focus.id}`,
type: 'continue',
priority: 100,
title: continueTitle,
description: excerpt(focus.content, 140),
actionKey: 'continue',
noteId: focus.id,
notebookId: focus.notebookId ?? undefined,
})
for (const ins of input.insights
.filter(i => i.note1.id === focus.id || i.note2.id === focus.id)
.slice(0, 2)) {
const other = ins.note1.id === focus.id ? ins.note2 : ins.note1
const otherTitle = pathNoteTitle(other.title, ins.note1.id === focus.id ? ins.note2Excerpt : ins.note1Excerpt)
paths.push({
id: `connect-${focus.id}-${other.id}`,
type: 'connect',
priority: 88,
title: otherTitle || excerpt(ins.insight, 80),
description: ins.insight,
actionKey: 'compare',
noteId: focus.id,
note2Id: other.id,
notebookId: focus.notebookId ?? undefined,
score: Math.round(ins.score * 100),
})
}
}
const freshInsight = input.insights.find(i => !i.viewed)
if (freshInsight) {
const left = pathNoteTitle(freshInsight.note1.title, freshInsight.note1Excerpt)
const right = pathNoteTitle(freshInsight.note2.title, freshInsight.note2Excerpt)
paths.push({
id: `resurface-${freshInsight.id}`,
type: 'resurface',
priority: 85,
title: left && right ? `${left}${right}` : excerpt(freshInsight.insight, 80),
description: freshInsight.insight,
actionKey: 'openInsight',
insightId: freshInsight.id,
noteId: freshInsight.note1.id,
note2Id: freshInsight.note2.id,
score: Math.round(freshInsight.score * 100),
})
}
for (const bridge of input.bridgeSuggestions.slice(0, 2)) {
paths.push({
id: `bridge-${bridge.clusterAId}-${bridge.clusterBId}`,
type: 'bridge',
priority: 70,
title: bridge.suggestedTitle,
description: bridge.justification || bridge.suggestedContent.slice(0, 140),
actionKey: 'createBridge',
clusterAId: bridge.clusterAId,
clusterBId: bridge.clusterBId,
notebookId: focus?.notebookId ?? undefined,
})
}
for (const agent of input.agentSuggestions.slice(0, 2)) {
paths.push({
id: `research-${agent.id}`,
type: 'research',
priority: 65,
title: agent.topic,
description: agent.reason,
actionKey: 'createAgent',
agentSuggestionId: agent.id,
notebookId: focus?.notebookId ?? undefined,
})
}
paths.push({
id: 'daily-journal',
type: 'daily',
priority: 40,
title: new Date().toISOString().slice(0, 10),
description: 'daily',
actionKey: 'openDaily',
})
return paths.sort((a, b) => b.priority - a.priority).slice(0, 8)
}