-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathLibraryService.js
More file actions
155 lines (136 loc) · 5.31 KB
/
Copy pathLibraryService.js
File metadata and controls
155 lines (136 loc) · 5.31 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
/**
* LibraryService
* Phase 4: Assembles the complete learning library data payload for a session.
* This is what the LibraryPage.html client fetches and renders.
*/
const LibraryService = {
/**
* Builds the full library data object for a session.
* Aggregates: session metadata, brief, resources, gems.
* @param {string} sessionId
* @returns {Object} Complete library payload
*/
buildLibraryData: function(sessionId) {
const session = SessionService.getSession(sessionId);
if (!session) throw new Error('Session not found: ' + sessionId);
const allResources = SynthesisService.getResources(sessionId);
const gems = GemsService.getGems(sessionId);
const brief = session.brief || {};
// Separate meeting links from content resources
// Filter content resources to public-only (isPublic !== false hides Internal resources)
const meetings = allResources.filter(r => this._isMeeting(r));
const resources = allResources
.filter(r => !this._isMeeting(r))
.filter(r => r.isPublic !== false)
.sort((a, b) => a.sortOrder - b.sortOrder || b.relevanceScore - a.relevanceScore);
// Ensure the isMain meeting sorts first; fall back to first entry
meetings.sort((a, b) => (b.isMain ? 1 : 0) - (a.isMain ? 1 : 0));
if (meetings.length && !meetings.some(m => m.isMain)) meetings[0].isMain = true;
// Top 3 pre-reading picks
const preReading = resources
.filter(r => r.preReading)
.slice(0, 3);
// NotebookLM-ready resources
const notebookLMResources = resources
.filter(r => r.notebookLMReady)
.slice(0, 6);
// Pre-session checklist
const checklist = this._buildChecklist(brief, preReading, gems, session.date);
return {
meta: {
sessionId: session.id,
name: session.name,
theme: session.theme,
date: session.date,
format: session.format,
audience: session.audience,
timezone: CONFIG.DISPLAY_TIMEZONE,
timezoneLabel: CONFIG.TIMEZONE_LABEL,
folderUrl: session.folderUrl,
dbUrl: session.dbUrl,
generatedAt: new Date().toISOString()
},
brief: {
overview: brief.overview || '',
learningObjectives: brief.learningObjectives || [],
inquiryQuestions: brief.inquiryQuestions || [],
notebookLMStarterPrompt: brief.notebookLMStarterPrompt || '',
agendaItems: brief.agendaItems || [],
sessionDuration: brief.sessionDuration || ''
},
meetings: meetings,
resources: resources,
preReading: preReading,
gems: gems,
notebookLM: {
resources: notebookLMResources,
starterPrompt: brief.notebookLMStarterPrompt || '',
guide: this._buildNotebookLMGuide(notebookLMResources, session.theme)
},
checklist: checklist
};
},
// ─── Private ────────────────────────────────────────────────────────────────
_isMeeting: function(r) {
if ((r.type || '').toLowerCase() === 'meeting link') return true;
var url = (r.url || '').toLowerCase();
return url.includes('meet.google.com') || url.includes('zoom.us') || url.includes('teams.microsoft.com');
},
_buildChecklist: function(brief, preReading, gems, sessionDate) {
const items = [
{
id: 'read-overview',
label: 'Read the session overview',
detail: 'Understand the theme and why it matters',
done: false
},
{
id: 'read-objectives',
label: 'Review the learning objectives',
detail: 'Know what you\'ll explore and take away',
done: false
}
];
if (preReading.length > 0) {
items.push({
id: 'pre-reading',
label: 'Complete pre-reading (' + preReading.length + ' resource' + (preReading.length > 1 ? 's' : '') + ')',
detail: preReading.map(r => r.title).join(', '),
done: false
});
}
items.push({
id: 'reflection-questions',
label: 'Sit with 1-2 inquiry questions',
detail: brief.inquiryQuestions && brief.inquiryQuestions[0]
? '"' + brief.inquiryQuestions[0] + '"'
: 'See Inquiry Questions section below',
done: false
});
if (gems.length > 0) {
items.push({
id: 'use-gem',
label: 'Explore the Deep Researcher Gem',
detail: 'Use the prompt in the Gems Workshop to go deeper before the session',
done: false
});
}
items.push({
id: 'notebooklm',
label: 'Set up NotebookLM (optional but powerful)',
detail: 'Upload pre-reading resources and use the starter prompt',
done: false
});
return items;
},
_buildNotebookLMGuide: function(resources, theme) {
if (!resources.length) {
return 'No resources have been flagged as NotebookLM-ready yet. Run Synthesis first.';
}
const resourceList = resources.map((r, i) => (i + 1) + '. ' + r.title).join('\n');
return 'To use NotebookLM for "' + theme + '":\n\n' +
'1. Go to notebooklm.google.com and create a new notebook\n' +
'2. Upload or add links to these resources:\n' + resourceList + '\n\n' +
'3. Once indexed, paste the starter prompt below into the chat to begin';
}
};