@bike4mind/cli 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +246 -0
- package/bin/bike4mind-cli.mjs +66 -0
- package/dist/artifactExtractor-QN34RFDM.js +181 -0
- package/dist/chunk-BDQBOLYG.js +120 -0
- package/dist/chunk-BPFEGDC7.js +192 -0
- package/dist/chunk-CC67R4RB.js +345 -0
- package/dist/chunk-CPNUKQQ3.js +110 -0
- package/dist/chunk-ETEFNJEP.js +235 -0
- package/dist/chunk-JVPB6BB5.js +10399 -0
- package/dist/chunk-LM6ZFZT6.js +92 -0
- package/dist/chunk-MKO2KCCS.js +6119 -0
- package/dist/chunk-PDX44BCA.js +11 -0
- package/dist/create-AYVZNCEH.js +13 -0
- package/dist/formatConverter-I7EIUVDY.js +8 -0
- package/dist/index.js +7614 -0
- package/dist/llmMarkdownGenerator-JBDLN44A.js +372 -0
- package/dist/markdownGenerator-MM5N3H5I.js +270 -0
- package/dist/mementoService-N5HYIH4Y.js +13 -0
- package/dist/notificationDeduplicator-LQAMED4L.js +10 -0
- package/dist/src-GTQ5UBCP.js +255 -0
- package/dist/src-OVEHYUVN.js +588 -0
- package/dist/subtractCredits-22TZUVZX.js +13 -0
- package/dist/utils-JPMDGUBL.js +32 -0
- package/package.json +111 -0
|
@@ -0,0 +1,372 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
CurationArtifactType
|
|
4
|
+
} from "./chunk-MKO2KCCS.js";
|
|
5
|
+
import "./chunk-PDX44BCA.js";
|
|
6
|
+
|
|
7
|
+
// ../../b4m-core/packages/services/dist/src/notebookCurationService/llmMarkdownGenerator.js
|
|
8
|
+
var DEFAULT_OPTIONS = {
|
|
9
|
+
includeTimestamps: false,
|
|
10
|
+
// Executive summaries don't need timestamps
|
|
11
|
+
includeMetadata: true,
|
|
12
|
+
includeTableOfContents: true,
|
|
13
|
+
maxSummaryLength: 2e3
|
|
14
|
+
// ~2000 tokens for summary
|
|
15
|
+
};
|
|
16
|
+
async function generateExecutiveSummaryMarkdown(session, messages, artifacts, llmContext, model, options = {}) {
|
|
17
|
+
const opts = { ...DEFAULT_OPTIONS, ...options };
|
|
18
|
+
const sections = [];
|
|
19
|
+
let totalTokensUsed = 0;
|
|
20
|
+
const generateText = async (prompt) => {
|
|
21
|
+
let result = "";
|
|
22
|
+
await llmContext.complete(model, [{ role: "user", content: prompt }], { temperature: 0.7, stream: false }, async (chunks) => {
|
|
23
|
+
result += chunks[0] || "";
|
|
24
|
+
});
|
|
25
|
+
return result;
|
|
26
|
+
};
|
|
27
|
+
sections.push(generateExecutiveHeader(session, messages, artifacts));
|
|
28
|
+
if (opts.includeTableOfContents) {
|
|
29
|
+
sections.push(generateExecutiveTOC());
|
|
30
|
+
}
|
|
31
|
+
const summaryResult = await generateAIExecutiveSummary(session, messages, generateText, opts.maxSummaryLength);
|
|
32
|
+
sections.push(summaryResult.markdown);
|
|
33
|
+
totalTokensUsed += summaryResult.tokensUsed;
|
|
34
|
+
const insightsResult = await generateAIKeyInsights(messages, generateText);
|
|
35
|
+
sections.push(insightsResult.markdown);
|
|
36
|
+
totalTokensUsed += insightsResult.tokensUsed;
|
|
37
|
+
const decisionsResult = await generateAIDecisionsAndActions(messages, generateText);
|
|
38
|
+
sections.push(decisionsResult.markdown);
|
|
39
|
+
totalTokensUsed += decisionsResult.tokensUsed;
|
|
40
|
+
if (artifacts.length > 0) {
|
|
41
|
+
const artifactsResult = await generateAIArtifactsSection(artifacts, messages, generateText);
|
|
42
|
+
sections.push(artifactsResult.markdown);
|
|
43
|
+
totalTokensUsed += artifactsResult.tokensUsed;
|
|
44
|
+
}
|
|
45
|
+
if (opts.includeMetadata) {
|
|
46
|
+
sections.push(generateExecutiveMetadata(session, messages, artifacts, totalTokensUsed));
|
|
47
|
+
}
|
|
48
|
+
return {
|
|
49
|
+
markdown: sections.filter(Boolean).join("\n\n---\n\n"),
|
|
50
|
+
tokensUsed: totalTokensUsed
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
function generateExecutiveHeader(session, messages, artifacts) {
|
|
54
|
+
const created = session.firstCreated ? new Date(session.firstCreated).toLocaleDateString() : "Unknown";
|
|
55
|
+
const updated = session.lastUpdated ? new Date(session.lastUpdated).toLocaleDateString() : "Unknown";
|
|
56
|
+
return `# ${session.name}
|
|
57
|
+
|
|
58
|
+
**Executive Summary (AI-Curated)**
|
|
59
|
+
|
|
60
|
+
- **Created:** ${created}
|
|
61
|
+
- **Last Updated:** ${updated}
|
|
62
|
+
- **Conversation Turns:** ${messages.length}
|
|
63
|
+
- **Artifacts Generated:** ${artifacts.length}
|
|
64
|
+
- **Document Type:** AI-Generated Executive Summary`;
|
|
65
|
+
}
|
|
66
|
+
function generateExecutiveTOC() {
|
|
67
|
+
return `## Table of Contents
|
|
68
|
+
|
|
69
|
+
- [Executive Summary](#executive-summary)
|
|
70
|
+
- [Key Insights](#key-insights)
|
|
71
|
+
- [Decisions & Actions](#decisions--actions)
|
|
72
|
+
- [Code & Artifacts](#code--artifacts)
|
|
73
|
+
- [Metadata](#metadata)`;
|
|
74
|
+
}
|
|
75
|
+
async function generateAIExecutiveSummary(session, messages, generateText, maxTokens) {
|
|
76
|
+
const conversationSample = sampleConversation(messages, 5e3);
|
|
77
|
+
const prompt = `You are an AI assistant helping to curate a notebook conversation into an executive summary.
|
|
78
|
+
|
|
79
|
+
Session: ${session.name}
|
|
80
|
+
Total Messages: ${messages.length}
|
|
81
|
+
|
|
82
|
+
Conversation Sample:
|
|
83
|
+
${conversationSample}
|
|
84
|
+
|
|
85
|
+
Generate a comprehensive executive summary that:
|
|
86
|
+
1. Explains what the conversation was about (1-2 paragraphs)
|
|
87
|
+
2. Highlights the main topics discussed
|
|
88
|
+
3. Describes the outcome or final state
|
|
89
|
+
|
|
90
|
+
Write in a professional, concise style suitable for knowledge sharing.`;
|
|
91
|
+
const text = await generateText(prompt);
|
|
92
|
+
const tokensUsed = estimateTokens(prompt + text);
|
|
93
|
+
return {
|
|
94
|
+
markdown: `## Executive Summary
|
|
95
|
+
|
|
96
|
+
${text}`,
|
|
97
|
+
tokensUsed
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
async function generateAIKeyInsights(messages, generateText) {
|
|
101
|
+
const conversationSample = sampleConversation(messages, 5e3);
|
|
102
|
+
const prompt = `Analyze this conversation and extract the top 5-7 key insights or learnings.
|
|
103
|
+
|
|
104
|
+
Conversation:
|
|
105
|
+
${conversationSample}
|
|
106
|
+
|
|
107
|
+
Format your response as a bullet list of key insights. Each insight should be:
|
|
108
|
+
- Concise (1-2 sentences)
|
|
109
|
+
- Actionable or informative
|
|
110
|
+
- Focused on technical or strategic learnings
|
|
111
|
+
|
|
112
|
+
Example format:
|
|
113
|
+
- **Understanding of X**: Brief explanation
|
|
114
|
+
- **Decision on Y**: What was decided and why
|
|
115
|
+
- **Technical approach for Z**: Key technical insight`;
|
|
116
|
+
const text = await generateText(prompt);
|
|
117
|
+
const tokensUsed = estimateTokens(prompt + text);
|
|
118
|
+
return {
|
|
119
|
+
markdown: `## Key Insights
|
|
120
|
+
|
|
121
|
+
${text}`,
|
|
122
|
+
tokensUsed
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
async function generateAIDecisionsAndActions(messages, generateText) {
|
|
126
|
+
const conversationSample = sampleConversation(messages, 5e3);
|
|
127
|
+
const prompt = `Analyze this conversation and identify key decisions made and action items.
|
|
128
|
+
|
|
129
|
+
Conversation:
|
|
130
|
+
${conversationSample}
|
|
131
|
+
|
|
132
|
+
Create two sections:
|
|
133
|
+
|
|
134
|
+
### Decisions Made
|
|
135
|
+
List 3-5 major decisions with brief rationale
|
|
136
|
+
|
|
137
|
+
### Action Items
|
|
138
|
+
List any next steps or TODOs mentioned
|
|
139
|
+
|
|
140
|
+
Format as markdown with bullet points.`;
|
|
141
|
+
const text = await generateText(prompt);
|
|
142
|
+
const tokensUsed = estimateTokens(prompt + text);
|
|
143
|
+
return {
|
|
144
|
+
markdown: `## Decisions & Actions
|
|
145
|
+
|
|
146
|
+
${text}`,
|
|
147
|
+
tokensUsed
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
async function generateAIArtifactsSection(artifacts, messages, generateText) {
|
|
151
|
+
const sections = ["## Code & Artifacts\n"];
|
|
152
|
+
let totalTokensUsed = 0;
|
|
153
|
+
const typeGroups = groupArtifactsByType(artifacts);
|
|
154
|
+
const typePriority = {
|
|
155
|
+
[CurationArtifactType.CODE]: 1,
|
|
156
|
+
[CurationArtifactType.REACT]: 2,
|
|
157
|
+
[CurationArtifactType.HTML]: 3,
|
|
158
|
+
[CurationArtifactType.MERMAID]: 4,
|
|
159
|
+
[CurationArtifactType.RECHARTS]: 5,
|
|
160
|
+
[CurationArtifactType.SVG]: 6,
|
|
161
|
+
[CurationArtifactType.QUESTMASTER_PLAN]: 7,
|
|
162
|
+
[CurationArtifactType.DEEP_RESEARCH]: 8,
|
|
163
|
+
[CurationArtifactType.IMAGE]: 9
|
|
164
|
+
};
|
|
165
|
+
const sortedTypes = Object.keys(typeGroups).sort((a, b) => (typePriority[a] || 99) - (typePriority[b] || 99));
|
|
166
|
+
const batchDescriptionResult = await generateBatchedArtifactDescriptions(artifacts, messages, generateText);
|
|
167
|
+
totalTokensUsed += batchDescriptionResult.tokensUsed;
|
|
168
|
+
const descriptionMap = /* @__PURE__ */ new Map();
|
|
169
|
+
artifacts.forEach((artifact, index) => {
|
|
170
|
+
descriptionMap.set(index, batchDescriptionResult.descriptions[index] || "No description available.");
|
|
171
|
+
});
|
|
172
|
+
let globalArtifactIndex = 0;
|
|
173
|
+
for (const type of sortedTypes) {
|
|
174
|
+
const artifactType = type;
|
|
175
|
+
const typeArtifacts = typeGroups[type];
|
|
176
|
+
const typeLabel = formatArtifactTypeLabel(artifactType);
|
|
177
|
+
sections.push(`### ${typeLabel}
|
|
178
|
+
`);
|
|
179
|
+
for (let i = 0; i < typeArtifacts.length; i++) {
|
|
180
|
+
const artifact = typeArtifacts[i];
|
|
181
|
+
const description = descriptionMap.get(globalArtifactIndex) || "No description available.";
|
|
182
|
+
sections.push(formatArtifactWithDescription(artifact, i + 1, description));
|
|
183
|
+
globalArtifactIndex++;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
return {
|
|
187
|
+
markdown: sections.join("\n"),
|
|
188
|
+
tokensUsed: totalTokensUsed
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
async function generateBatchedArtifactDescriptions(artifacts, messages, generateText) {
|
|
192
|
+
if (artifacts.length === 0) {
|
|
193
|
+
return { descriptions: [], tokensUsed: 0 };
|
|
194
|
+
}
|
|
195
|
+
const artifactPrompts = artifacts.map((artifact, index) => {
|
|
196
|
+
const contextMessages = findArtifactContext(artifact, messages);
|
|
197
|
+
return `[ARTIFACT ${index + 1}]
|
|
198
|
+
Type: ${artifact.type}${artifact.language ? ` | Language: ${artifact.language}` : ""}
|
|
199
|
+
Code Preview:
|
|
200
|
+
${artifact.content.substring(0, 400)}${artifact.content.length > 400 ? "..." : ""}
|
|
201
|
+
|
|
202
|
+
Context: ${contextMessages}
|
|
203
|
+
`;
|
|
204
|
+
});
|
|
205
|
+
const batchPrompt = `You are analyzing artifacts from a technical conversation. For each artifact below, provide a concise 1-2 sentence description explaining what it does and why it's relevant.
|
|
206
|
+
|
|
207
|
+
${artifactPrompts.join("\n---\n")}
|
|
208
|
+
|
|
209
|
+
Format your response as a numbered list matching the artifact numbers above. Each description should be:
|
|
210
|
+
- Concise (1-2 sentences maximum)
|
|
211
|
+
- Technical and specific
|
|
212
|
+
- Focused on the purpose and functionality
|
|
213
|
+
|
|
214
|
+
Example format:
|
|
215
|
+
1. [Description for artifact 1]
|
|
216
|
+
2. [Description for artifact 2]
|
|
217
|
+
3. [Description for artifact 3]
|
|
218
|
+
|
|
219
|
+
Provide descriptions for all ${artifacts.length} artifacts:`;
|
|
220
|
+
const text = await generateText(batchPrompt);
|
|
221
|
+
const tokensUsed = estimateTokens(batchPrompt + text);
|
|
222
|
+
const descriptions = parseNumberedListResponse(text, artifacts.length);
|
|
223
|
+
return {
|
|
224
|
+
descriptions,
|
|
225
|
+
tokensUsed
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
function parseNumberedListResponse(text, expectedCount) {
|
|
229
|
+
const lines = text.split("\n").filter((line) => line.trim());
|
|
230
|
+
const descriptions = [];
|
|
231
|
+
for (const line of lines) {
|
|
232
|
+
const match = line.match(/^\s*[\[\(]?\d+[\.\)\]]\s*(.+)$/);
|
|
233
|
+
if (match && match[1]) {
|
|
234
|
+
descriptions.push(match[1].trim());
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
while (descriptions.length < expectedCount) {
|
|
238
|
+
descriptions.push("Code artifact for technical implementation.");
|
|
239
|
+
}
|
|
240
|
+
return descriptions.slice(0, expectedCount);
|
|
241
|
+
}
|
|
242
|
+
function formatArtifactWithDescription(artifact, index, description) {
|
|
243
|
+
const title = artifact.metadata?.title || `${formatArtifactTypeLabel(artifact.type)} #${index}`;
|
|
244
|
+
let formattedArtifact = `#### ${index}. ${title}
|
|
245
|
+
|
|
246
|
+
`;
|
|
247
|
+
formattedArtifact += `*${description}*
|
|
248
|
+
|
|
249
|
+
`;
|
|
250
|
+
switch (artifact.type) {
|
|
251
|
+
case CurationArtifactType.CODE:
|
|
252
|
+
case CurationArtifactType.REACT:
|
|
253
|
+
case CurationArtifactType.HTML:
|
|
254
|
+
formattedArtifact += `\`\`\`${artifact.language || "text"}
|
|
255
|
+
${artifact.content}
|
|
256
|
+
\`\`\``;
|
|
257
|
+
break;
|
|
258
|
+
case CurationArtifactType.MERMAID:
|
|
259
|
+
formattedArtifact += `\`\`\`mermaid
|
|
260
|
+
${artifact.content}
|
|
261
|
+
\`\`\``;
|
|
262
|
+
break;
|
|
263
|
+
case CurationArtifactType.RECHARTS:
|
|
264
|
+
formattedArtifact += `\`\`\`json
|
|
265
|
+
${artifact.content}
|
|
266
|
+
\`\`\``;
|
|
267
|
+
break;
|
|
268
|
+
case CurationArtifactType.SVG:
|
|
269
|
+
formattedArtifact += `\`\`\`svg
|
|
270
|
+
${artifact.content}
|
|
271
|
+
\`\`\``;
|
|
272
|
+
break;
|
|
273
|
+
default:
|
|
274
|
+
formattedArtifact += artifact.content;
|
|
275
|
+
}
|
|
276
|
+
return formattedArtifact;
|
|
277
|
+
}
|
|
278
|
+
function generateExecutiveMetadata(session, messages, artifacts, tokensUsed) {
|
|
279
|
+
const typeGroups = groupArtifactsByType(artifacts);
|
|
280
|
+
const artifactCounts = Object.entries(typeGroups).map(([type, arts]) => `${formatArtifactTypeLabel(type)}: ${arts.length}`).join(", ");
|
|
281
|
+
return `## Metadata
|
|
282
|
+
|
|
283
|
+
- **Session ID:** ${session.id}
|
|
284
|
+
- **Conversation Turns:** ${messages.length}
|
|
285
|
+
- **Artifacts Generated:** ${artifacts.length}
|
|
286
|
+
- **Artifact Breakdown:** ${artifactCounts || "None"}
|
|
287
|
+
- **AI Analysis Tokens Used:** ~${tokensUsed} tokens
|
|
288
|
+
- **Created:** ${session.firstCreated ? new Date(session.firstCreated).toISOString() : "Unknown"}
|
|
289
|
+
- **Curated At:** ${(/* @__PURE__ */ new Date()).toISOString()}
|
|
290
|
+
- **Curation Type:** AI-Powered Executive Summary
|
|
291
|
+
- **Platform:** Bike4Mind Lumina v5
|
|
292
|
+
|
|
293
|
+
---
|
|
294
|
+
|
|
295
|
+
*This document was automatically generated by Bike4Mind AI-Powered Notebook Curation.*
|
|
296
|
+
*The executive summary, insights, and artifact descriptions were created using AI analysis.*`;
|
|
297
|
+
}
|
|
298
|
+
function sampleConversation(messages, maxChars) {
|
|
299
|
+
const samples = [];
|
|
300
|
+
let currentChars = 0;
|
|
301
|
+
const indicesToSample = [
|
|
302
|
+
0,
|
|
303
|
+
// First
|
|
304
|
+
...sampleIndices(messages.length, Math.floor(messages.length / 3)),
|
|
305
|
+
// Middle samples
|
|
306
|
+
messages.length - 1
|
|
307
|
+
// Last
|
|
308
|
+
];
|
|
309
|
+
for (const idx of indicesToSample) {
|
|
310
|
+
if (idx >= messages.length)
|
|
311
|
+
continue;
|
|
312
|
+
const message = messages[idx];
|
|
313
|
+
const userPrompt = message.prompt || "";
|
|
314
|
+
const assistantReply = message.reply || message.questMasterReply || message.replies && message.replies[0] || "";
|
|
315
|
+
const messageSample = `User: ${userPrompt}
|
|
316
|
+
|
|
317
|
+
Assistant: ${assistantReply}`;
|
|
318
|
+
if (currentChars + messageSample.length > maxChars)
|
|
319
|
+
break;
|
|
320
|
+
samples.push(messageSample);
|
|
321
|
+
currentChars += messageSample.length;
|
|
322
|
+
}
|
|
323
|
+
return samples.join("\n\n---\n\n");
|
|
324
|
+
}
|
|
325
|
+
function sampleIndices(length, count) {
|
|
326
|
+
const step = Math.floor(length / (count + 1));
|
|
327
|
+
const indices = [];
|
|
328
|
+
for (let i = 1; i <= count; i++) {
|
|
329
|
+
indices.push(i * step);
|
|
330
|
+
}
|
|
331
|
+
return indices;
|
|
332
|
+
}
|
|
333
|
+
function findArtifactContext(artifact, messages) {
|
|
334
|
+
const message = messages.find((m) => m.id === artifact.messageId || m._id?.toString() === artifact.messageId);
|
|
335
|
+
if (!message)
|
|
336
|
+
return "";
|
|
337
|
+
const prompt = message.prompt || "";
|
|
338
|
+
const reply = message.reply || message.questMasterReply || "";
|
|
339
|
+
return `User: ${prompt.substring(0, 200)}...
|
|
340
|
+
|
|
341
|
+
Assistant: ${reply.substring(0, 200)}...`;
|
|
342
|
+
}
|
|
343
|
+
function groupArtifactsByType(artifacts) {
|
|
344
|
+
return artifacts.reduce((groups, artifact) => {
|
|
345
|
+
const type = artifact.type;
|
|
346
|
+
if (!groups[type]) {
|
|
347
|
+
groups[type] = [];
|
|
348
|
+
}
|
|
349
|
+
groups[type].push(artifact);
|
|
350
|
+
return groups;
|
|
351
|
+
}, {});
|
|
352
|
+
}
|
|
353
|
+
function formatArtifactTypeLabel(type) {
|
|
354
|
+
const labels = {
|
|
355
|
+
[CurationArtifactType.CODE]: "Code Snippets",
|
|
356
|
+
[CurationArtifactType.REACT]: "React Components",
|
|
357
|
+
[CurationArtifactType.HTML]: "HTML Pages",
|
|
358
|
+
[CurationArtifactType.MERMAID]: "Diagrams (Mermaid)",
|
|
359
|
+
[CurationArtifactType.RECHARTS]: "Data Visualizations",
|
|
360
|
+
[CurationArtifactType.SVG]: "SVG Graphics",
|
|
361
|
+
[CurationArtifactType.QUESTMASTER_PLAN]: "QuestMaster Plans",
|
|
362
|
+
[CurationArtifactType.DEEP_RESEARCH]: "Research Findings",
|
|
363
|
+
[CurationArtifactType.IMAGE]: "Images"
|
|
364
|
+
};
|
|
365
|
+
return labels[type] || type;
|
|
366
|
+
}
|
|
367
|
+
function estimateTokens(text) {
|
|
368
|
+
return Math.ceil(text.length / 4);
|
|
369
|
+
}
|
|
370
|
+
export {
|
|
371
|
+
generateExecutiveSummaryMarkdown
|
|
372
|
+
};
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
CurationArtifactType
|
|
4
|
+
} from "./chunk-MKO2KCCS.js";
|
|
5
|
+
import "./chunk-PDX44BCA.js";
|
|
6
|
+
|
|
7
|
+
// ../../b4m-core/packages/services/dist/src/notebookCurationService/markdownGenerator.js
|
|
8
|
+
var DEFAULT_OPTIONS = {
|
|
9
|
+
includeTimestamps: true,
|
|
10
|
+
includeMetadata: true,
|
|
11
|
+
includeTableOfContents: true,
|
|
12
|
+
groupArtifactsByType: true
|
|
13
|
+
};
|
|
14
|
+
function generateTranscriptMarkdown(session, messages, artifacts, options = {}) {
|
|
15
|
+
const opts = { ...DEFAULT_OPTIONS, ...options };
|
|
16
|
+
const sections = [];
|
|
17
|
+
sections.push(generateHeader(session, messages, artifacts));
|
|
18
|
+
if (opts.includeTableOfContents) {
|
|
19
|
+
sections.push(generateTableOfContents(artifacts));
|
|
20
|
+
}
|
|
21
|
+
if (session.summary) {
|
|
22
|
+
sections.push(generateSummarySection(session));
|
|
23
|
+
}
|
|
24
|
+
sections.push(generateConversationSection(messages, opts));
|
|
25
|
+
if (artifacts.length > 0) {
|
|
26
|
+
if (opts.groupArtifactsByType) {
|
|
27
|
+
sections.push(generateArtifactsSectionGrouped(artifacts));
|
|
28
|
+
} else {
|
|
29
|
+
sections.push(generateArtifactsSectionChronological(artifacts));
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
if (opts.includeMetadata) {
|
|
33
|
+
sections.push(generateMetadataFooter(session, messages, artifacts));
|
|
34
|
+
}
|
|
35
|
+
return sections.filter(Boolean).join("\n\n---\n\n");
|
|
36
|
+
}
|
|
37
|
+
function generateHeader(session, messages, artifacts) {
|
|
38
|
+
const created = session.firstCreated ? new Date(session.firstCreated).toLocaleDateString() : "Unknown";
|
|
39
|
+
const updated = session.lastUpdated ? new Date(session.lastUpdated).toLocaleDateString() : "Unknown";
|
|
40
|
+
return `# ${session.name}
|
|
41
|
+
|
|
42
|
+
**Curated Notebook Transcript**
|
|
43
|
+
|
|
44
|
+
- **Created:** ${created}
|
|
45
|
+
- **Last Updated:** ${updated}
|
|
46
|
+
- **Messages:** ${messages.length}
|
|
47
|
+
- **Artifacts:** ${artifacts.length}
|
|
48
|
+
- **Language:** ${session.language || "en"}`;
|
|
49
|
+
}
|
|
50
|
+
function generateTableOfContents(artifacts) {
|
|
51
|
+
const sections = ["## Table of Contents\n"];
|
|
52
|
+
sections.push("- [Summary](#summary)");
|
|
53
|
+
sections.push("- [Conversation](#conversation)");
|
|
54
|
+
if (artifacts.length > 0) {
|
|
55
|
+
sections.push("- [Artifacts](#artifacts)");
|
|
56
|
+
const typeGroups = groupArtifactsByType(artifacts);
|
|
57
|
+
Object.keys(typeGroups).forEach((type) => {
|
|
58
|
+
const typeLabel = formatArtifactTypeLabel(type);
|
|
59
|
+
const anchor = typeLabel.toLowerCase().replace(/\s+/g, "-");
|
|
60
|
+
sections.push(` - [${typeLabel}](#${anchor})`);
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
return sections.join("\n");
|
|
64
|
+
}
|
|
65
|
+
function generateSummarySection(session) {
|
|
66
|
+
const summarizedDate = session.summaryAt ? new Date(session.summaryAt).toLocaleDateString() : "Unknown";
|
|
67
|
+
return `## Summary
|
|
68
|
+
|
|
69
|
+
*Generated on ${summarizedDate}*
|
|
70
|
+
|
|
71
|
+
${session.summary}`;
|
|
72
|
+
}
|
|
73
|
+
function generateConversationSection(messages, options) {
|
|
74
|
+
const lines = ["## Conversation\n"];
|
|
75
|
+
messages.forEach((message, index) => {
|
|
76
|
+
const timestamp = message.timestamp ? new Date(message.timestamp).toLocaleString() : "";
|
|
77
|
+
const showTimestamp = options.includeTimestamps && timestamp;
|
|
78
|
+
if (message.prompt) {
|
|
79
|
+
lines.push(`### ${index + 1}. User${showTimestamp ? ` (${timestamp})` : ""}
|
|
80
|
+
`);
|
|
81
|
+
lines.push(cleanMessageContent(message.prompt));
|
|
82
|
+
lines.push("");
|
|
83
|
+
}
|
|
84
|
+
const reply = message.questMasterReply || message.reply || message.replies && message.replies[0];
|
|
85
|
+
if (reply) {
|
|
86
|
+
lines.push(`### ${index + 1}. Assistant${showTimestamp ? ` (${timestamp})` : ""}
|
|
87
|
+
`);
|
|
88
|
+
lines.push(cleanMessageContent(reply));
|
|
89
|
+
lines.push("");
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
return lines.join("\n");
|
|
93
|
+
}
|
|
94
|
+
function generateArtifactsSectionGrouped(artifacts) {
|
|
95
|
+
const sections = ["## Artifacts\n"];
|
|
96
|
+
const typeGroups = groupArtifactsByType(artifacts);
|
|
97
|
+
const typePriority = {
|
|
98
|
+
[CurationArtifactType.CODE]: 1,
|
|
99
|
+
[CurationArtifactType.REACT]: 2,
|
|
100
|
+
[CurationArtifactType.HTML]: 3,
|
|
101
|
+
[CurationArtifactType.MERMAID]: 4,
|
|
102
|
+
[CurationArtifactType.RECHARTS]: 5,
|
|
103
|
+
[CurationArtifactType.SVG]: 6,
|
|
104
|
+
[CurationArtifactType.QUESTMASTER_PLAN]: 7,
|
|
105
|
+
[CurationArtifactType.DEEP_RESEARCH]: 8,
|
|
106
|
+
[CurationArtifactType.IMAGE]: 9
|
|
107
|
+
};
|
|
108
|
+
const sortedTypes = Object.keys(typeGroups).sort((a, b) => (typePriority[a] || 99) - (typePriority[b] || 99));
|
|
109
|
+
sortedTypes.forEach((type) => {
|
|
110
|
+
const artifactType = type;
|
|
111
|
+
const typeArtifacts = typeGroups[type];
|
|
112
|
+
const typeLabel = formatArtifactTypeLabel(artifactType);
|
|
113
|
+
sections.push(`### ${typeLabel}
|
|
114
|
+
`);
|
|
115
|
+
typeArtifacts.forEach((artifact, index) => {
|
|
116
|
+
sections.push(formatArtifact(artifact, index + 1));
|
|
117
|
+
sections.push("");
|
|
118
|
+
});
|
|
119
|
+
});
|
|
120
|
+
return sections.join("\n");
|
|
121
|
+
}
|
|
122
|
+
function generateArtifactsSectionChronological(artifacts) {
|
|
123
|
+
const sections = ["## Artifacts\n"];
|
|
124
|
+
artifacts.forEach((artifact, index) => {
|
|
125
|
+
sections.push(formatArtifact(artifact, index + 1));
|
|
126
|
+
sections.push("");
|
|
127
|
+
});
|
|
128
|
+
return sections.join("\n");
|
|
129
|
+
}
|
|
130
|
+
function formatArtifact(artifact, index) {
|
|
131
|
+
const title = artifact.metadata?.title || `${formatArtifactTypeLabel(artifact.type)} #${index}`;
|
|
132
|
+
const timestamp = artifact.timestamp.toLocaleString();
|
|
133
|
+
switch (artifact.type) {
|
|
134
|
+
case CurationArtifactType.CODE:
|
|
135
|
+
case CurationArtifactType.REACT:
|
|
136
|
+
case CurationArtifactType.HTML:
|
|
137
|
+
return `#### ${index}. ${title}
|
|
138
|
+
|
|
139
|
+
*Type:* ${artifact.type} | *Language:* ${artifact.language || "unknown"} | *Created:* ${timestamp}
|
|
140
|
+
|
|
141
|
+
\`\`\`${artifact.language || "text"}
|
|
142
|
+
${artifact.content}
|
|
143
|
+
\`\`\``;
|
|
144
|
+
case CurationArtifactType.MERMAID:
|
|
145
|
+
return `#### ${index}. ${title}
|
|
146
|
+
|
|
147
|
+
*Type:* Mermaid Diagram | *Created:* ${timestamp}
|
|
148
|
+
|
|
149
|
+
\`\`\`mermaid
|
|
150
|
+
${artifact.content}
|
|
151
|
+
\`\`\``;
|
|
152
|
+
case CurationArtifactType.RECHARTS:
|
|
153
|
+
return `#### ${index}. ${title}
|
|
154
|
+
|
|
155
|
+
*Type:* Data Visualization | *Created:* ${timestamp}
|
|
156
|
+
|
|
157
|
+
\`\`\`json
|
|
158
|
+
${artifact.content}
|
|
159
|
+
\`\`\``;
|
|
160
|
+
case CurationArtifactType.SVG:
|
|
161
|
+
return `#### ${index}. ${title}
|
|
162
|
+
|
|
163
|
+
*Type:* SVG Graphic | *Created:* ${timestamp}
|
|
164
|
+
|
|
165
|
+
\`\`\`svg
|
|
166
|
+
${artifact.content}
|
|
167
|
+
\`\`\``;
|
|
168
|
+
case CurationArtifactType.QUESTMASTER_PLAN:
|
|
169
|
+
return `#### ${index}. QuestMaster Plan
|
|
170
|
+
|
|
171
|
+
*Plan ID:* ${artifact.metadata?.planId} | *Created:* ${timestamp}
|
|
172
|
+
|
|
173
|
+
> This conversation included a QuestMaster plan (ID: ${artifact.metadata?.planId})`;
|
|
174
|
+
case CurationArtifactType.DEEP_RESEARCH:
|
|
175
|
+
return formatDeepResearchArtifact(artifact, index, timestamp);
|
|
176
|
+
case CurationArtifactType.IMAGE:
|
|
177
|
+
return `#### ${index}. Image
|
|
178
|
+
|
|
179
|
+
*Path:* ${artifact.metadata?.path} | *Created:* ${timestamp}
|
|
180
|
+
|
|
181
|
+
`;
|
|
182
|
+
default:
|
|
183
|
+
return `#### ${index}. ${title}
|
|
184
|
+
|
|
185
|
+
${artifact.content}`;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
function formatDeepResearchArtifact(artifact, index, timestamp) {
|
|
189
|
+
const metadata = artifact.metadata || {};
|
|
190
|
+
const research = JSON.parse(artifact.content);
|
|
191
|
+
const sections = [
|
|
192
|
+
`#### ${index}. Deep Research: ${metadata.topic || "Unknown Topic"}`,
|
|
193
|
+
"",
|
|
194
|
+
`*Findings:* ${metadata.findingsCount || 0} | *Sources:* ${metadata.sourcesCount || 0} | *Depth:* ${metadata.depth || 0} | *Created:* ${timestamp}`,
|
|
195
|
+
""
|
|
196
|
+
];
|
|
197
|
+
if (research.findings && research.findings.length > 0) {
|
|
198
|
+
sections.push("**Key Findings:**\n");
|
|
199
|
+
research.findings.forEach((finding, i) => {
|
|
200
|
+
sections.push(`${i + 1}. ${finding.text}`);
|
|
201
|
+
if (finding.source) {
|
|
202
|
+
sections.push(` *Source:* ${finding.source}`);
|
|
203
|
+
}
|
|
204
|
+
sections.push("");
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
if (research.sources && research.sources.length > 0) {
|
|
208
|
+
sections.push("**Sources:**\n");
|
|
209
|
+
research.sources.forEach((source, i) => {
|
|
210
|
+
sections.push(`${i + 1}. **${source.title}**`);
|
|
211
|
+
sections.push(` - URL: ${source.url}`);
|
|
212
|
+
if (source.description) {
|
|
213
|
+
sections.push(` - ${source.description}`);
|
|
214
|
+
}
|
|
215
|
+
sections.push("");
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
return sections.join("\n");
|
|
219
|
+
}
|
|
220
|
+
function generateMetadataFooter(session, messages, artifacts) {
|
|
221
|
+
const typeGroups = groupArtifactsByType(artifacts);
|
|
222
|
+
const artifactCounts = Object.entries(typeGroups).map(([type, arts]) => `${formatArtifactTypeLabel(type)}: ${arts.length}`).join(", ");
|
|
223
|
+
return `## Metadata
|
|
224
|
+
|
|
225
|
+
- **Session ID:** ${session.id}
|
|
226
|
+
- **Total Messages:** ${messages.length}
|
|
227
|
+
- **Total Artifacts:** ${artifacts.length}
|
|
228
|
+
- **Artifact Breakdown:** ${artifactCounts || "None"}
|
|
229
|
+
- **Created:** ${session.firstCreated ? new Date(session.firstCreated).toISOString() : "Unknown"}
|
|
230
|
+
- **Last Updated:** ${session.lastUpdated ? new Date(session.lastUpdated).toISOString() : "Unknown"}
|
|
231
|
+
- **Curated At:** ${(/* @__PURE__ */ new Date()).toISOString()}
|
|
232
|
+
- **Platform:** Bike4Mind Lumina v5
|
|
233
|
+
|
|
234
|
+
---
|
|
235
|
+
|
|
236
|
+
*This document was automatically generated by Bike4Mind Notebook Curation.*`;
|
|
237
|
+
}
|
|
238
|
+
function groupArtifactsByType(artifacts) {
|
|
239
|
+
return artifacts.reduce((groups, artifact) => {
|
|
240
|
+
const type = artifact.type;
|
|
241
|
+
if (!groups[type]) {
|
|
242
|
+
groups[type] = [];
|
|
243
|
+
}
|
|
244
|
+
groups[type].push(artifact);
|
|
245
|
+
return groups;
|
|
246
|
+
}, {});
|
|
247
|
+
}
|
|
248
|
+
function formatArtifactTypeLabel(type) {
|
|
249
|
+
const labels = {
|
|
250
|
+
[CurationArtifactType.CODE]: "Code Snippets",
|
|
251
|
+
[CurationArtifactType.REACT]: "React Components",
|
|
252
|
+
[CurationArtifactType.HTML]: "HTML Pages",
|
|
253
|
+
[CurationArtifactType.MERMAID]: "Diagrams (Mermaid)",
|
|
254
|
+
[CurationArtifactType.RECHARTS]: "Data Visualizations",
|
|
255
|
+
[CurationArtifactType.SVG]: "SVG Graphics",
|
|
256
|
+
[CurationArtifactType.QUESTMASTER_PLAN]: "QuestMaster Plans",
|
|
257
|
+
[CurationArtifactType.DEEP_RESEARCH]: "Research Findings",
|
|
258
|
+
[CurationArtifactType.IMAGE]: "Images"
|
|
259
|
+
};
|
|
260
|
+
return labels[type] || type;
|
|
261
|
+
}
|
|
262
|
+
function cleanMessageContent(content) {
|
|
263
|
+
let cleaned = content.replace(/<artifact\s+.*?>([\s\S]*?)<\/artifact>/gi, "");
|
|
264
|
+
cleaned = cleaned.replace(/<think>([\s\S]*?)<\/think>/gi, "");
|
|
265
|
+
cleaned = cleaned.trim();
|
|
266
|
+
return cleaned;
|
|
267
|
+
}
|
|
268
|
+
export {
|
|
269
|
+
generateTranscriptMarkdown
|
|
270
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
findMostSimilarMemento,
|
|
4
|
+
getRelevantMementos
|
|
5
|
+
} from "./chunk-ETEFNJEP.js";
|
|
6
|
+
import "./chunk-JVPB6BB5.js";
|
|
7
|
+
import "./chunk-CC67R4RB.js";
|
|
8
|
+
import "./chunk-MKO2KCCS.js";
|
|
9
|
+
import "./chunk-PDX44BCA.js";
|
|
10
|
+
export {
|
|
11
|
+
findMostSimilarMemento,
|
|
12
|
+
getRelevantMementos
|
|
13
|
+
};
|