@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.
@@ -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
+ ![Image](${artifact.content})`;
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
+ };
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ NotificationDeduplicator,
4
+ notificationDeduplicator
5
+ } from "./chunk-CC67R4RB.js";
6
+ import "./chunk-PDX44BCA.js";
7
+ export {
8
+ NotificationDeduplicator,
9
+ notificationDeduplicator
10
+ };