@nathanvale/chatline 0.0.1

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.
Files changed (216) hide show
  1. package/CHANGELOG.md +1 -0
  2. package/LICENSE +21 -0
  3. package/README.md +1535 -0
  4. package/dist/bin/index.js +5121 -0
  5. package/dist/cli/commands/clean.d.ts +17 -0
  6. package/dist/cli/commands/clean.d.ts.map +1 -0
  7. package/dist/cli/commands/clean.js +142 -0
  8. package/dist/cli/commands/clean.js.map +1 -0
  9. package/dist/cli/commands/doctor.d.ts +17 -0
  10. package/dist/cli/commands/doctor.d.ts.map +1 -0
  11. package/dist/cli/commands/doctor.js +202 -0
  12. package/dist/cli/commands/doctor.js.map +1 -0
  13. package/dist/cli/commands/enrich-ai.d.ts +17 -0
  14. package/dist/cli/commands/enrich-ai.d.ts.map +1 -0
  15. package/dist/cli/commands/enrich-ai.js +371 -0
  16. package/dist/cli/commands/enrich-ai.js.map +1 -0
  17. package/dist/cli/commands/index.d.ts +16 -0
  18. package/dist/cli/commands/index.d.ts.map +1 -0
  19. package/dist/cli/commands/index.js +16 -0
  20. package/dist/cli/commands/index.js.map +1 -0
  21. package/dist/cli/commands/ingest-csv.d.ts +17 -0
  22. package/dist/cli/commands/ingest-csv.d.ts.map +1 -0
  23. package/dist/cli/commands/ingest-csv.js +138 -0
  24. package/dist/cli/commands/ingest-csv.js.map +1 -0
  25. package/dist/cli/commands/ingest-db.d.ts +17 -0
  26. package/dist/cli/commands/ingest-db.d.ts.map +1 -0
  27. package/dist/cli/commands/ingest-db.js +159 -0
  28. package/dist/cli/commands/ingest-db.js.map +1 -0
  29. package/dist/cli/commands/init.d.ts +17 -0
  30. package/dist/cli/commands/init.d.ts.map +1 -0
  31. package/dist/cli/commands/init.js +110 -0
  32. package/dist/cli/commands/init.js.map +1 -0
  33. package/dist/cli/commands/normalize-link.d.ts +16 -0
  34. package/dist/cli/commands/normalize-link.d.ts.map +1 -0
  35. package/dist/cli/commands/normalize-link.js +144 -0
  36. package/dist/cli/commands/normalize-link.js.map +1 -0
  37. package/dist/cli/commands/render-markdown.d.ts +17 -0
  38. package/dist/cli/commands/render-markdown.d.ts.map +1 -0
  39. package/dist/cli/commands/render-markdown.js +218 -0
  40. package/dist/cli/commands/render-markdown.js.map +1 -0
  41. package/dist/cli/commands/stats.d.ts +17 -0
  42. package/dist/cli/commands/stats.d.ts.map +1 -0
  43. package/dist/cli/commands/stats.js +175 -0
  44. package/dist/cli/commands/stats.js.map +1 -0
  45. package/dist/cli/commands/validate.d.ts +17 -0
  46. package/dist/cli/commands/validate.d.ts.map +1 -0
  47. package/dist/cli/commands/validate.js +152 -0
  48. package/dist/cli/commands/validate.js.map +1 -0
  49. package/dist/cli/index.d.ts +13 -0
  50. package/dist/cli/index.d.ts.map +1 -0
  51. package/dist/cli/index.js +121 -0
  52. package/dist/cli/index.js.map +1 -0
  53. package/dist/cli/types.d.ts +93 -0
  54. package/dist/cli/types.d.ts.map +1 -0
  55. package/dist/cli/types.js +7 -0
  56. package/dist/cli/types.js.map +1 -0
  57. package/dist/cli/utils.d.ts +29 -0
  58. package/dist/cli/utils.d.ts.map +1 -0
  59. package/dist/cli/utils.js +53 -0
  60. package/dist/cli/utils.js.map +1 -0
  61. package/dist/cli.d.ts +9 -0
  62. package/dist/cli.d.ts.map +1 -0
  63. package/dist/cli.js +1805 -0
  64. package/dist/config/generator.d.ts +90 -0
  65. package/dist/config/generator.d.ts.map +1 -0
  66. package/dist/config/generator.js +320 -0
  67. package/dist/config/generator.js.map +1 -0
  68. package/dist/config/loader.d.ts +107 -0
  69. package/dist/config/loader.d.ts.map +1 -0
  70. package/dist/config/loader.js +251 -0
  71. package/dist/config/loader.js.map +1 -0
  72. package/dist/config/schema.d.ts +107 -0
  73. package/dist/config/schema.d.ts.map +1 -0
  74. package/dist/config/schema.js +169 -0
  75. package/dist/config/schema.js.map +1 -0
  76. package/dist/enrich/audio-transcription.d.ts +77 -0
  77. package/dist/enrich/audio-transcription.d.ts.map +1 -0
  78. package/dist/enrich/audio-transcription.js +370 -0
  79. package/dist/enrich/audio-transcription.js.map +1 -0
  80. package/dist/enrich/checkpoint.d.ts +137 -0
  81. package/dist/enrich/checkpoint.d.ts.map +1 -0
  82. package/dist/enrich/checkpoint.js +205 -0
  83. package/dist/enrich/checkpoint.js.map +1 -0
  84. package/dist/enrich/idempotency.d.ts +90 -0
  85. package/dist/enrich/idempotency.d.ts.map +1 -0
  86. package/dist/enrich/idempotency.js +188 -0
  87. package/dist/enrich/idempotency.js.map +1 -0
  88. package/dist/enrich/image-analysis.d.ts +62 -0
  89. package/dist/enrich/image-analysis.d.ts.map +1 -0
  90. package/dist/enrich/image-analysis.js +264 -0
  91. package/dist/enrich/image-analysis.js.map +1 -0
  92. package/dist/enrich/index.d.ts +60 -0
  93. package/dist/enrich/index.d.ts.map +1 -0
  94. package/dist/enrich/index.js +74 -0
  95. package/dist/enrich/index.js.map +1 -0
  96. package/dist/enrich/link-enrichment.d.ts +37 -0
  97. package/dist/enrich/link-enrichment.d.ts.map +1 -0
  98. package/dist/enrich/link-enrichment.js +202 -0
  99. package/dist/enrich/link-enrichment.js.map +1 -0
  100. package/dist/enrich/pdf-video-handling.d.ts +49 -0
  101. package/dist/enrich/pdf-video-handling.d.ts.map +1 -0
  102. package/dist/enrich/pdf-video-handling.js +325 -0
  103. package/dist/enrich/pdf-video-handling.js.map +1 -0
  104. package/dist/enrich/progress-tracker.d.ts +120 -0
  105. package/dist/enrich/progress-tracker.d.ts.map +1 -0
  106. package/dist/enrich/progress-tracker.js +220 -0
  107. package/dist/enrich/progress-tracker.js.map +1 -0
  108. package/dist/enrich/providers/firecrawl.d.ts +18 -0
  109. package/dist/enrich/providers/firecrawl.d.ts.map +1 -0
  110. package/dist/enrich/providers/firecrawl.js +48 -0
  111. package/dist/enrich/providers/firecrawl.js.map +1 -0
  112. package/dist/enrich/providers/generic.d.ts +16 -0
  113. package/dist/enrich/providers/generic.d.ts.map +1 -0
  114. package/dist/enrich/providers/generic.js +36 -0
  115. package/dist/enrich/providers/generic.js.map +1 -0
  116. package/dist/enrich/providers/index.d.ts +14 -0
  117. package/dist/enrich/providers/index.d.ts.map +1 -0
  118. package/dist/enrich/providers/index.js +13 -0
  119. package/dist/enrich/providers/index.js.map +1 -0
  120. package/dist/enrich/providers/instagram.d.ts +16 -0
  121. package/dist/enrich/providers/instagram.d.ts.map +1 -0
  122. package/dist/enrich/providers/instagram.js +43 -0
  123. package/dist/enrich/providers/instagram.js.map +1 -0
  124. package/dist/enrich/providers/spotify.d.ts +16 -0
  125. package/dist/enrich/providers/spotify.d.ts.map +1 -0
  126. package/dist/enrich/providers/spotify.js +45 -0
  127. package/dist/enrich/providers/spotify.js.map +1 -0
  128. package/dist/enrich/providers/twitter.d.ts +16 -0
  129. package/dist/enrich/providers/twitter.d.ts.map +1 -0
  130. package/dist/enrich/providers/twitter.js +43 -0
  131. package/dist/enrich/providers/twitter.js.map +1 -0
  132. package/dist/enrich/providers/types.d.ts +47 -0
  133. package/dist/enrich/providers/types.d.ts.map +1 -0
  134. package/dist/enrich/providers/types.js +15 -0
  135. package/dist/enrich/providers/types.js.map +1 -0
  136. package/dist/enrich/providers/youtube.d.ts +16 -0
  137. package/dist/enrich/providers/youtube.d.ts.map +1 -0
  138. package/dist/enrich/providers/youtube.js +43 -0
  139. package/dist/enrich/providers/youtube.js.map +1 -0
  140. package/dist/enrich/rate-limiting.d.ts +118 -0
  141. package/dist/enrich/rate-limiting.d.ts.map +1 -0
  142. package/dist/enrich/rate-limiting.js +258 -0
  143. package/dist/enrich/rate-limiting.js.map +1 -0
  144. package/dist/index.d.ts +688 -0
  145. package/dist/index.d.ts.map +1 -0
  146. package/dist/index.js +1729 -0
  147. package/dist/index.js.map +1 -0
  148. package/dist/ingest/dedup-merge.d.ts +82 -0
  149. package/dist/ingest/dedup-merge.d.ts.map +1 -0
  150. package/dist/ingest/dedup-merge.js +262 -0
  151. package/dist/ingest/dedup-merge.js.map +1 -0
  152. package/dist/ingest/ingest-csv.d.ts +62 -0
  153. package/dist/ingest/ingest-csv.d.ts.map +1 -0
  154. package/dist/ingest/ingest-csv.js +300 -0
  155. package/dist/ingest/ingest-csv.js.map +1 -0
  156. package/dist/ingest/ingest-db.d.ts +64 -0
  157. package/dist/ingest/ingest-db.d.ts.map +1 -0
  158. package/dist/ingest/ingest-db.js +172 -0
  159. package/dist/ingest/ingest-db.js.map +1 -0
  160. package/dist/ingest/link-replies-and-tapbacks.d.ts +53 -0
  161. package/dist/ingest/link-replies-and-tapbacks.d.ts.map +1 -0
  162. package/dist/ingest/link-replies-and-tapbacks.js +381 -0
  163. package/dist/ingest/link-replies-and-tapbacks.js.map +1 -0
  164. package/dist/normalize/date-converters.d.ts +45 -0
  165. package/dist/normalize/date-converters.d.ts.map +1 -0
  166. package/dist/normalize/date-converters.js +166 -0
  167. package/dist/normalize/date-converters.js.map +1 -0
  168. package/dist/normalize/path-validator.d.ts +65 -0
  169. package/dist/normalize/path-validator.d.ts.map +1 -0
  170. package/dist/normalize/path-validator.js +221 -0
  171. package/dist/normalize/path-validator.js.map +1 -0
  172. package/dist/normalize/validate-normalized.d.ts +45 -0
  173. package/dist/normalize/validate-normalized.d.ts.map +1 -0
  174. package/dist/normalize/validate-normalized.js +144 -0
  175. package/dist/normalize/validate-normalized.js.map +1 -0
  176. package/dist/render/embeds-blockquotes.d.ts +84 -0
  177. package/dist/render/embeds-blockquotes.d.ts.map +1 -0
  178. package/dist/render/embeds-blockquotes.js +204 -0
  179. package/dist/render/embeds-blockquotes.js.map +1 -0
  180. package/dist/render/grouping.d.ts +78 -0
  181. package/dist/render/grouping.d.ts.map +1 -0
  182. package/dist/render/grouping.js +134 -0
  183. package/dist/render/grouping.js.map +1 -0
  184. package/dist/render/index.d.ts +47 -0
  185. package/dist/render/index.d.ts.map +1 -0
  186. package/dist/render/index.js +245 -0
  187. package/dist/render/index.js.map +1 -0
  188. package/dist/render/reply-rendering.d.ts +88 -0
  189. package/dist/render/reply-rendering.d.ts.map +1 -0
  190. package/dist/render/reply-rendering.js +196 -0
  191. package/dist/render/reply-rendering.js.map +1 -0
  192. package/dist/schema/message.d.ts +125 -0
  193. package/dist/schema/message.d.ts.map +1 -0
  194. package/dist/schema/message.js +331 -0
  195. package/dist/schema/message.js.map +1 -0
  196. package/dist/utils/delta-detection.d.ts +107 -0
  197. package/dist/utils/delta-detection.d.ts.map +1 -0
  198. package/dist/utils/delta-detection.js +199 -0
  199. package/dist/utils/delta-detection.js.map +1 -0
  200. package/dist/utils/enrichment-merge.d.ts +135 -0
  201. package/dist/utils/enrichment-merge.d.ts.map +1 -0
  202. package/dist/utils/enrichment-merge.js +280 -0
  203. package/dist/utils/enrichment-merge.js.map +1 -0
  204. package/dist/utils/human.d.ts +15 -0
  205. package/dist/utils/human.d.ts.map +1 -0
  206. package/dist/utils/human.js +27 -0
  207. package/dist/utils/human.js.map +1 -0
  208. package/dist/utils/incremental-state.d.ts +133 -0
  209. package/dist/utils/incremental-state.d.ts.map +1 -0
  210. package/dist/utils/incremental-state.js +237 -0
  211. package/dist/utils/incremental-state.js.map +1 -0
  212. package/dist/utils/logger.d.ts +40 -0
  213. package/dist/utils/logger.d.ts.map +1 -0
  214. package/dist/utils/logger.js +176 -0
  215. package/dist/utils/logger.js.map +1 -0
  216. package/package.json +165 -0
@@ -0,0 +1,204 @@
1
+ /**
2
+ * Embeds and Blockquotes Rendering Module (RENDER--T03)
3
+ *
4
+ * Implements Obsidian-friendly embeds and blockquote rendering:
5
+ * - AC01: Image embeds with ![[path]] syntax
6
+ * - AC02: Preview images with links to originals (HEIC/TIFF)
7
+ * - AC03: Transcription blockquotes with speaker labels
8
+ * - AC04: Link context blockquotes with metadata
9
+ * - AC05: PDF summary blockquotes with formatting
10
+ */
11
+ /**
12
+ * AC01: Render image embed with Obsidian wikilink syntax
13
+ * Format: ![[path]]
14
+ */
15
+ export function renderImageEmbed(path) {
16
+ return `![[${path}]]`;
17
+ }
18
+ /**
19
+ * AC02: Render preview image with link to original
20
+ * For HEIC/TIFF files, shows preview with link to original
21
+ */
22
+ export function renderPreviewImageWithLink(previewPath, originalPath) {
23
+ const filename = originalPath.split('/').pop() || 'original';
24
+ return `![[${previewPath}]]\n[Original: ${filename}](${originalPath})`;
25
+ }
26
+ /**
27
+ * AC03: Render transcription as blockquote
28
+ * Handles multiline transcriptions with speaker labels and timestamps
29
+ */
30
+ export function renderTranscriptionBlockquote(enrichment) {
31
+ if (enrichment.kind !== 'transcription' || !enrichment.transcription) {
32
+ return '';
33
+ }
34
+ const lines = enrichment.transcription.split('\n');
35
+ return lines.map((line) => `> ${line}`).join('\n');
36
+ }
37
+ /**
38
+ * AC04: Render link context as blockquote
39
+ * Shows title as markdown link and summary as blockquote
40
+ */
41
+ export function renderLinkContextBlockquote(enrichment) {
42
+ if (enrichment.kind !== 'link_context') {
43
+ return '';
44
+ }
45
+ const parts = [];
46
+ // Format title as markdown link if available
47
+ if (enrichment.title && enrichment.url) {
48
+ parts.push(`> [${enrichment.title}](${enrichment.url})`);
49
+ }
50
+ else if (enrichment.url) {
51
+ parts.push(`> [${enrichment.url}](${enrichment.url})`);
52
+ }
53
+ // Add summary as blockquote lines
54
+ if (enrichment.summary) {
55
+ const summaryLines = enrichment.summary.split('\n');
56
+ for (const line of summaryLines) {
57
+ if (line.trim()) {
58
+ parts.push(`> ${line}`);
59
+ }
60
+ else {
61
+ parts.push('> ');
62
+ }
63
+ }
64
+ }
65
+ return parts.join('\n');
66
+ }
67
+ /**
68
+ * AC05: Render PDF summary as blockquote
69
+ * Preserves paragraph structure with blockquote formatting
70
+ */
71
+ export function renderPdfSummaryBlockquote(enrichment) {
72
+ if (enrichment.kind !== 'pdf_summary' || !enrichment.pdfSummary) {
73
+ return '';
74
+ }
75
+ const lines = enrichment.pdfSummary.split('\n');
76
+ return lines.map((line) => `> ${line}`).join('\n');
77
+ }
78
+ /**
79
+ * Determine if a message should render an embed
80
+ * Only renders embeds for image media
81
+ */
82
+ export function shouldRenderEmbed(message) {
83
+ if (message.messageKind !== 'media' || !message.media) {
84
+ return false;
85
+ }
86
+ // Only embed images
87
+ return message.media.mediaKind === 'image';
88
+ }
89
+ /**
90
+ * Get the path to embed for a media message
91
+ * Returns undefined if message cannot be embedded
92
+ */
93
+ export function getEmbedPath(message) {
94
+ if (!shouldRenderEmbed(message)) {
95
+ return undefined;
96
+ }
97
+ return message.media?.path;
98
+ }
99
+ /**
100
+ * Get preview path for an image file
101
+ * For HEIC/TIFF, returns the .jpg preview path
102
+ * For JPG/PNG, returns the original path
103
+ */
104
+ export function getPreviewPath(originalPath) {
105
+ const lowerPath = originalPath.toLowerCase();
106
+ if (lowerPath.endsWith('.heic')) {
107
+ return `${originalPath}.jpg`;
108
+ }
109
+ if (lowerPath.endsWith('.tiff') || lowerPath.endsWith('.tif')) {
110
+ return `${originalPath}.jpg`;
111
+ }
112
+ // JPG, PNG, and other formats return as-is
113
+ return originalPath;
114
+ }
115
+ /**
116
+ * Get the original path from a preview path
117
+ * Handles HEIC.jpg -> HEIC and TIFF.jpg -> TIFF conversions
118
+ */
119
+ export function getOriginalPath(previewPath) {
120
+ // If it ends with .jpg, check if it's a preview
121
+ if (previewPath.endsWith('.jpg')) {
122
+ const withoutJpg = previewPath.slice(0, -4);
123
+ if (withoutJpg.toLowerCase().endsWith('.heic')) {
124
+ return withoutJpg;
125
+ }
126
+ if (withoutJpg.toLowerCase().endsWith('.tiff') ||
127
+ withoutJpg.toLowerCase().endsWith('.tif')) {
128
+ return withoutJpg;
129
+ }
130
+ }
131
+ return previewPath;
132
+ }
133
+ /**
134
+ * Extract enrichments of a specific kind from a media message
135
+ */
136
+ export function getEnrichmentsByKind(message, kind) {
137
+ if (message.messageKind !== 'media' || !message.media?.enrichment) {
138
+ return [];
139
+ }
140
+ return message.media.enrichment.filter((e) => e.kind === kind);
141
+ }
142
+ /**
143
+ * Get all transcription enrichments from a message
144
+ */
145
+ export function getTranscriptions(message) {
146
+ return getEnrichmentsByKind(message, 'transcription');
147
+ }
148
+ /**
149
+ * Get all link context enrichments from a message
150
+ */
151
+ export function getLinkContexts(message) {
152
+ return getEnrichmentsByKind(message, 'link_context');
153
+ }
154
+ /**
155
+ * Get all PDF summary enrichments from a message
156
+ */
157
+ export function getPdfSummaries(message) {
158
+ return getEnrichmentsByKind(message, 'pdf_summary');
159
+ }
160
+ export function renderAllEnrichments(message) {
161
+ const result = {
162
+ embeds: [],
163
+ transcriptions: [],
164
+ linkContexts: [],
165
+ pdfSummaries: [],
166
+ };
167
+ // Handle image embeds
168
+ if (shouldRenderEmbed(message)) {
169
+ const embedPath = getEmbedPath(message);
170
+ if (embedPath) {
171
+ const previewPath = getPreviewPath(embedPath);
172
+ if (previewPath === embedPath) {
173
+ // No preview needed, just embed
174
+ result.embeds.push(renderImageEmbed(embedPath));
175
+ }
176
+ else {
177
+ // Preview available, show with link to original
178
+ result.embeds.push(renderPreviewImageWithLink(previewPath, embedPath));
179
+ }
180
+ }
181
+ }
182
+ // Handle enrichments if media
183
+ if (message.media?.enrichment) {
184
+ for (const enrichment of message.media.enrichment) {
185
+ if (enrichment.kind === 'transcription') {
186
+ const rendered = renderTranscriptionBlockquote(enrichment);
187
+ if (rendered)
188
+ result.transcriptions.push(rendered);
189
+ }
190
+ else if (enrichment.kind === 'link_context') {
191
+ const rendered = renderLinkContextBlockquote(enrichment);
192
+ if (rendered)
193
+ result.linkContexts.push(rendered);
194
+ }
195
+ else if (enrichment.kind === 'pdf_summary') {
196
+ const rendered = renderPdfSummaryBlockquote(enrichment);
197
+ if (rendered)
198
+ result.pdfSummaries.push(rendered);
199
+ }
200
+ }
201
+ }
202
+ return result;
203
+ }
204
+ //# sourceMappingURL=embeds-blockquotes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"embeds-blockquotes.js","sourceRoot":"","sources":["../../src/render/embeds-blockquotes.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Grouping and Anchor Generation Module (RENDER--T01)
3
+ *
4
+ * Implements message grouping and Obsidian-friendly anchor generation:
5
+ * - AC01: Group messages by date (YYYY-MM-DD)
6
+ * - AC02: Sub-group by time-of-day (Morning/Afternoon/Evening)
7
+ * - AC03: Generate unique anchor IDs (#msg-{guid})
8
+ * - AC04: Obsidian-compatible deep-link anchors
9
+ * - AC05: Maintain chronological ordering within time-of-day groups
10
+ */
11
+ import type { Message } from '#schema/message';
12
+ /**
13
+ * Time-of-day classification
14
+ */
15
+ export type TimeOfDay = 'morning' | 'afternoon' | 'evening';
16
+ /**
17
+ * Group structure for a single time-of-day period
18
+ */
19
+ export type TimeOfDayGroup = {
20
+ morning: Message[];
21
+ afternoon: Message[];
22
+ evening: Message[];
23
+ };
24
+ /**
25
+ * Grouped messages by date and time-of-day
26
+ * Key: YYYY-MM-DD
27
+ */
28
+ export type GroupedMessages = {
29
+ [date: string]: TimeOfDayGroup;
30
+ };
31
+ /**
32
+ * AC02: Classify a timestamp into time-of-day category
33
+ * Morning: 00:00-11:59
34
+ * Afternoon: 12:00-17:59
35
+ * Evening: 18:00-23:59
36
+ */
37
+ export declare function classifyTimeOfDay(isoTimestamp: string): TimeOfDay;
38
+ /**
39
+ * AC03: Generate unique anchor ID for a message
40
+ * Format: #msg-{guid}
41
+ */
42
+ export declare function generateAnchorId(guid: string): string;
43
+ /**
44
+ * AC01: Extract date from ISO timestamp in YYYY-MM-DD format
45
+ */
46
+ export declare function extractDate(isoTimestamp: string): string;
47
+ /**
48
+ * AC05: Sort messages chronologically by timestamp
49
+ * Does not mutate original array
50
+ */
51
+ export declare function sortByTimestamp(messages: Message[]): Message[];
52
+ /**
53
+ * AC01-AC05: Group messages by date and time-of-day
54
+ * Returns nested structure with chronological ordering maintained
55
+ */
56
+ export declare function groupMessagesByDateAndTimeOfDay(messages: Message[]): GroupedMessages;
57
+ /**
58
+ * Get all unique dates from grouped messages
59
+ * Returns dates in chronological order
60
+ */
61
+ export declare function getDatesSorted(grouped: GroupedMessages): string[];
62
+ /**
63
+ * Get all messages from a date group in chronological order
64
+ * Combines all time-of-day groups in order
65
+ */
66
+ export declare function getAllMessagesForDate(dateGroup: TimeOfDayGroup): Message[];
67
+ /**
68
+ * Type guards and utilities
69
+ */
70
+ /**
71
+ * Check if date group has any messages
72
+ */
73
+ export declare function hasMessages(dateGroup: TimeOfDayGroup): boolean;
74
+ /**
75
+ * Get count of messages in time-of-day
76
+ */
77
+ export declare function getMessageCount(dateGroup: TimeOfDayGroup): number;
78
+ //# sourceMappingURL=grouping.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"grouping.d.ts","sourceRoot":"","sources":["../../src/render/grouping.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAA;AAc9C;;GAEG;AACH,MAAM,MAAM,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,SAAS,CAAA;AAE3D;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG;IAC5B,OAAO,EAAE,OAAO,EAAE,CAAA;IAClB,SAAS,EAAE,OAAO,EAAE,CAAA;IACpB,OAAO,EAAE,OAAO,EAAE,CAAA;CAClB,CAAA;AAED;;;GAGG;AACH,MAAM,MAAM,eAAe,GAAG;IAC7B,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,CAAA;CAC9B,CAAA;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,YAAY,EAAE,MAAM,GAAG,SAAS,CAWjE;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAErD;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAMxD;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,OAAO,EAAE,CAM9D;AAED;;;GAGG;AACH,wBAAgB,+BAA+B,CAC9C,QAAQ,EAAE,OAAO,EAAE,GACjB,eAAe,CAgCjB;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,eAAe,GAAG,MAAM,EAAE,CAIjE;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,cAAc,GAAG,OAAO,EAAE,CAE1E;AAED;;GAEG;AAEH;;GAEG;AACH,wBAAgB,WAAW,CAAC,SAAS,EAAE,cAAc,GAAG,OAAO,CAM9D;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,cAAc,GAAG,MAAM,CAMjE"}
@@ -0,0 +1,134 @@
1
+ /**
2
+ * Grouping and Anchor Generation Module (RENDER--T01)
3
+ *
4
+ * Implements message grouping and Obsidian-friendly anchor generation:
5
+ * - AC01: Group messages by date (YYYY-MM-DD)
6
+ * - AC02: Sub-group by time-of-day (Morning/Afternoon/Evening)
7
+ * - AC03: Generate unique anchor IDs (#msg-{guid})
8
+ * - AC04: Obsidian-compatible deep-link anchors
9
+ * - AC05: Maintain chronological ordering within time-of-day groups
10
+ */
11
+ /**
12
+ * Normalize any ISO-like timestamp to canonical UTC ISO format.
13
+ * - If no timezone designator (no 'Z' and no +/- offset), treat as UTC by appending 'Z'.
14
+ * - Then return Date.toISOString() to canonicalize milliseconds and Z suffix.
15
+ */
16
+ function normalizeIsoUtc(input) {
17
+ const hasZ = /Z$/.test(input);
18
+ const hasOffset = /[+-]\d{2}:?\d{2}$/.test(input);
19
+ const coerced = hasZ || hasOffset ? input : `${input.replace(/\s+$/, '')}Z`;
20
+ return new Date(coerced).toISOString();
21
+ }
22
+ /**
23
+ * AC02: Classify a timestamp into time-of-day category
24
+ * Morning: 00:00-11:59
25
+ * Afternoon: 12:00-17:59
26
+ * Evening: 18:00-23:59
27
+ */
28
+ export function classifyTimeOfDay(isoTimestamp) {
29
+ const date = new Date(normalizeIsoUtc(isoTimestamp));
30
+ const hours = date.getUTCHours();
31
+ if (hours < 12) {
32
+ return 'morning';
33
+ }
34
+ if (hours < 18) {
35
+ return 'afternoon';
36
+ }
37
+ return 'evening';
38
+ }
39
+ /**
40
+ * AC03: Generate unique anchor ID for a message
41
+ * Format: #msg-{guid}
42
+ */
43
+ export function generateAnchorId(guid) {
44
+ return `#msg-${guid}`;
45
+ }
46
+ /**
47
+ * AC01: Extract date from ISO timestamp in YYYY-MM-DD format
48
+ */
49
+ export function extractDate(isoTimestamp) {
50
+ const date = new Date(normalizeIsoUtc(isoTimestamp));
51
+ const year = date.getUTCFullYear();
52
+ const month = String(date.getUTCMonth() + 1).padStart(2, '0');
53
+ const day = String(date.getUTCDate()).padStart(2, '0');
54
+ return `${year}-${month}-${day}`;
55
+ }
56
+ /**
57
+ * AC05: Sort messages chronologically by timestamp
58
+ * Does not mutate original array
59
+ */
60
+ export function sortByTimestamp(messages) {
61
+ return [...messages].sort((a, b) => {
62
+ const timeA = new Date(normalizeIsoUtc(a.date)).getTime();
63
+ const timeB = new Date(normalizeIsoUtc(b.date)).getTime();
64
+ return timeA - timeB;
65
+ });
66
+ }
67
+ /**
68
+ * AC01-AC05: Group messages by date and time-of-day
69
+ * Returns nested structure with chronological ordering maintained
70
+ */
71
+ export function groupMessagesByDateAndTimeOfDay(messages) {
72
+ const grouped = {};
73
+ // First pass: create date groups and classify by time-of-day
74
+ for (const message of messages) {
75
+ const date = extractDate(message.date);
76
+ const timeOfDay = classifyTimeOfDay(message.date);
77
+ // Initialize date group if not exists
78
+ if (!grouped[date]) {
79
+ grouped[date] = {
80
+ morning: [],
81
+ afternoon: [],
82
+ evening: [],
83
+ };
84
+ }
85
+ // Add message to appropriate time-of-day group
86
+ grouped[date][timeOfDay].push(message);
87
+ }
88
+ // Second pass: sort each time-of-day group chronologically
89
+ for (const date in grouped) {
90
+ const dayGroup = grouped[date];
91
+ if (dayGroup) {
92
+ dayGroup.morning = sortByTimestamp(dayGroup.morning);
93
+ dayGroup.afternoon = sortByTimestamp(dayGroup.afternoon);
94
+ dayGroup.evening = sortByTimestamp(dayGroup.evening);
95
+ }
96
+ }
97
+ return grouped;
98
+ }
99
+ /**
100
+ * Get all unique dates from grouped messages
101
+ * Returns dates in chronological order
102
+ */
103
+ export function getDatesSorted(grouped) {
104
+ // Keys are YYYY-MM-DD; lexicographic sort is equivalent to chronological
105
+ // Avoid Date parsing entirely to prevent any environment-specific quirks.
106
+ return Object.keys(grouped).sort();
107
+ }
108
+ /**
109
+ * Get all messages from a date group in chronological order
110
+ * Combines all time-of-day groups in order
111
+ */
112
+ export function getAllMessagesForDate(dateGroup) {
113
+ return [...dateGroup.morning, ...dateGroup.afternoon, ...dateGroup.evening];
114
+ }
115
+ /**
116
+ * Type guards and utilities
117
+ */
118
+ /**
119
+ * Check if date group has any messages
120
+ */
121
+ export function hasMessages(dateGroup) {
122
+ return (dateGroup.morning.length > 0 ||
123
+ dateGroup.afternoon.length > 0 ||
124
+ dateGroup.evening.length > 0);
125
+ }
126
+ /**
127
+ * Get count of messages in time-of-day
128
+ */
129
+ export function getMessageCount(dateGroup) {
130
+ return (dateGroup.morning.length +
131
+ dateGroup.afternoon.length +
132
+ dateGroup.evening.length);
133
+ }
134
+ //# sourceMappingURL=grouping.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"grouping.js","sourceRoot":"","sources":["../../src/render/grouping.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Render-Markdown Integration Module (RENDER--T04)
3
+ *
4
+ * Deterministic rendering pipeline:
5
+ * - AC01: Snapshot tests for fixed input → identical output
6
+ * - AC02: No network calls during rendering
7
+ * - AC03: Deterministic ordering of same-timestamp messages
8
+ * - AC04: Reproducible markdown structure
9
+ * - AC05: Performance validation (1000 messages in <10s)
10
+ */
11
+ import type { Message } from '#schema/message';
12
+ /**
13
+ * Main render function: Convert messages to markdown files
14
+ * Returns Map<date, markdown> with deterministic output
15
+ */
16
+ export declare function renderMessages(messages: Message[]): Map<string, string>;
17
+ /**
18
+ * Sort messages deterministically by timestamp, then by GUID
19
+ * Ensures same-timestamp messages are ordered consistently
20
+ */
21
+ export declare function sortMessagesByTimestamp(messages: Message[]): Message[];
22
+ /**
23
+ * Generate deterministic hash of rendered output
24
+ * Uses SHA-256 of concatenated message data
25
+ */
26
+ export declare function getMessageHash(messages: Message[]): string;
27
+ /**
28
+ * Verify determinism by rendering multiple times and comparing
29
+ */
30
+ export type DeterminismResult = {
31
+ isDeterministic: boolean;
32
+ runsCount: number;
33
+ hashesAreIdentical: boolean;
34
+ outputsAreIdentical: boolean;
35
+ hashes: string[];
36
+ };
37
+ export declare function verifyDeterminism(messages: Message[], runsCount?: number): DeterminismResult;
38
+ /**
39
+ * Validate markdown structure
40
+ * Ensures proper formatting and no encoding issues
41
+ */
42
+ export declare function validateMarkdownStructure(markdown: string): void;
43
+ /**
44
+ * Export types for external use
45
+ */
46
+ export type { Message } from '#schema/message';
47
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/render/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAA;AAkB9C;;;GAGG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAoCvE;AA4HD;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,OAAO,EAAE,CAYtE;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,MAAM,CAK1D;AAED;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAC/B,eAAe,EAAE,OAAO,CAAA;IACxB,SAAS,EAAE,MAAM,CAAA;IACjB,kBAAkB,EAAE,OAAO,CAAA;IAC3B,mBAAmB,EAAE,OAAO,CAAA;IAC5B,MAAM,EAAE,MAAM,EAAE,CAAA;CAChB,CAAA;AAED,wBAAgB,iBAAiB,CAChC,QAAQ,EAAE,OAAO,EAAE,EACnB,SAAS,SAAI,GACX,iBAAiB,CA6CnB;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CA+BhE;AAED;;GAEG;AACH,YAAY,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAA"}