@redaksjon/protokoll 0.0.8 → 0.0.10

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 (112) hide show
  1. package/.cursor/rules/definition-of-done.md +89 -0
  2. package/.cursor/rules/no-emoticons.md +43 -0
  3. package/LICENSE +1 -1
  4. package/README.md +928 -35
  5. package/dist/agentic/executor.js +315 -0
  6. package/dist/agentic/executor.js.map +1 -0
  7. package/dist/agentic/index.js +19 -0
  8. package/dist/agentic/index.js.map +1 -0
  9. package/dist/agentic/registry.js +41 -0
  10. package/dist/agentic/registry.js.map +1 -0
  11. package/dist/agentic/tools/lookup-person.js +66 -0
  12. package/dist/agentic/tools/lookup-person.js.map +1 -0
  13. package/dist/agentic/tools/lookup-project.js +93 -0
  14. package/dist/agentic/tools/lookup-project.js.map +1 -0
  15. package/dist/agentic/tools/route-note.js +45 -0
  16. package/dist/agentic/tools/route-note.js.map +1 -0
  17. package/dist/agentic/tools/store-context.js +51 -0
  18. package/dist/agentic/tools/store-context.js.map +1 -0
  19. package/dist/agentic/tools/verify-spelling.js +57 -0
  20. package/dist/agentic/tools/verify-spelling.js.map +1 -0
  21. package/dist/arguments.js +23 -6
  22. package/dist/arguments.js.map +1 -1
  23. package/dist/constants.js +13 -11
  24. package/dist/constants.js.map +1 -1
  25. package/dist/context/discovery.js +114 -0
  26. package/dist/context/discovery.js.map +1 -0
  27. package/dist/context/index.js +58 -0
  28. package/dist/context/index.js.map +1 -0
  29. package/dist/context/storage.js +131 -0
  30. package/dist/context/storage.js.map +1 -0
  31. package/dist/interactive/handler.js +223 -0
  32. package/dist/interactive/handler.js.map +1 -0
  33. package/dist/interactive/index.js +18 -0
  34. package/dist/interactive/index.js.map +1 -0
  35. package/dist/interactive/onboarding.js +28 -0
  36. package/dist/interactive/onboarding.js.map +1 -0
  37. package/dist/main.js +0 -0
  38. package/dist/output/index.js +8 -0
  39. package/dist/output/index.js.map +1 -0
  40. package/dist/output/manager.js +105 -0
  41. package/dist/output/manager.js.map +1 -0
  42. package/dist/phases/complete.js +107 -0
  43. package/dist/phases/complete.js.map +1 -0
  44. package/dist/phases/locate.js +14 -5
  45. package/dist/phases/locate.js.map +1 -1
  46. package/dist/pipeline/index.js +8 -0
  47. package/dist/pipeline/index.js.map +1 -0
  48. package/dist/pipeline/orchestrator.js +281 -0
  49. package/dist/pipeline/orchestrator.js.map +1 -0
  50. package/dist/prompt/instructions/transcribe.md +6 -6
  51. package/dist/prompt/personas/transcriber.md +5 -5
  52. package/dist/protokoll.js +38 -5
  53. package/dist/protokoll.js.map +1 -1
  54. package/dist/reasoning/client.js +150 -0
  55. package/dist/reasoning/client.js.map +1 -0
  56. package/dist/reasoning/index.js +36 -0
  57. package/dist/reasoning/index.js.map +1 -0
  58. package/dist/reasoning/strategy.js +60 -0
  59. package/dist/reasoning/strategy.js.map +1 -0
  60. package/dist/reflection/collector.js +124 -0
  61. package/dist/reflection/collector.js.map +1 -0
  62. package/dist/reflection/index.js +16 -0
  63. package/dist/reflection/index.js.map +1 -0
  64. package/dist/reflection/reporter.js +238 -0
  65. package/dist/reflection/reporter.js.map +1 -0
  66. package/dist/routing/classifier.js +201 -0
  67. package/dist/routing/classifier.js.map +1 -0
  68. package/dist/routing/index.js +27 -0
  69. package/dist/routing/index.js.map +1 -0
  70. package/dist/routing/router.js +153 -0
  71. package/dist/routing/router.js.map +1 -0
  72. package/dist/transcription/index.js +41 -0
  73. package/dist/transcription/index.js.map +1 -0
  74. package/dist/transcription/service.js +64 -0
  75. package/dist/transcription/service.js.map +1 -0
  76. package/dist/transcription/types.js +31 -0
  77. package/dist/transcription/types.js.map +1 -0
  78. package/dist/util/media.js +4 -4
  79. package/dist/util/media.js.map +1 -1
  80. package/dist/util/metadata.js +95 -0
  81. package/dist/util/metadata.js.map +1 -0
  82. package/dist/util/storage.js +2 -2
  83. package/dist/util/storage.js.map +1 -1
  84. package/docs/examples.md +224 -0
  85. package/docs/index.html +5 -3
  86. package/docs/package-lock.json +639 -332
  87. package/docs/package.json +5 -4
  88. package/docs/troubleshooting.md +257 -0
  89. package/docs/vite.config.js +9 -3
  90. package/eslint.config.mjs +1 -0
  91. package/guide/architecture.md +217 -0
  92. package/guide/configuration.md +199 -0
  93. package/guide/context-system.md +215 -0
  94. package/guide/development.md +273 -0
  95. package/guide/index.md +91 -0
  96. package/guide/interactive.md +199 -0
  97. package/guide/quickstart.md +138 -0
  98. package/guide/reasoning.md +193 -0
  99. package/guide/routing.md +222 -0
  100. package/package.json +10 -7
  101. package/tsconfig.tsbuildinfo +1 -1
  102. package/vitest.config.ts +27 -5
  103. package/dist/phases/transcribe.js +0 -149
  104. package/dist/phases/transcribe.js.map +0 -1
  105. package/dist/processor.js +0 -35
  106. package/dist/processor.js.map +0 -1
  107. package/dist/prompt/transcribe.js +0 -41
  108. package/dist/prompt/transcribe.js.map +0 -1
  109. package/dist/util/general.js +0 -39
  110. package/dist/util/general.js.map +0 -1
  111. package/dist/util/openai.js +0 -92
  112. package/dist/util/openai.js.map +0 -1
@@ -1,5 +1,5 @@
1
1
  import ffmpeg from 'fluent-ffmpeg';
2
- import path from 'path';
2
+ import path__default from 'path';
3
3
  import { create as create$1 } from './storage.js';
4
4
 
5
5
  const ffprobeAsync = (filePath)=>{
@@ -65,13 +65,13 @@ const create = (logger)=>{
65
65
  // Create output directory if it doesn't exist
66
66
  await storage.createDirectory(outputDir);
67
67
  const outputFiles = [];
68
- const fileExt = path.extname(filePath);
69
- const fileName = path.basename(filePath, fileExt);
68
+ const fileExt = path__default.extname(filePath);
69
+ const fileName = path__default.basename(filePath, fileExt);
70
70
  // Create a promise for each segment
71
71
  const promises = [];
72
72
  for(let i = 0; i < segmentCount; i++){
73
73
  const startTime = i * segmentDuration;
74
- const outputPath = path.join(outputDir, `${fileName}_part${i + 1}${fileExt}`);
74
+ const outputPath = path__default.join(outputDir, `${fileName}_part${i + 1}${fileExt}`);
75
75
  outputFiles.push(outputPath);
76
76
  const promise = new Promise((resolve, reject)=>{
77
77
  ffmpeg(filePath).setStartTime(startTime).setDuration(segmentDuration).output(outputPath).on('end', ()=>{
@@ -1 +1 @@
1
- {"version":3,"file":"media.js","sources":["../../src/util/media.ts"],"sourcesContent":["import ffmpeg from 'fluent-ffmpeg';\nimport { Logger } from 'winston';\nimport path from 'path';\nimport * as Storage from '@/util/storage';\n\nexport interface Media {\n getAudioCreationTime: (filePath: string) => Promise<Date | null>;\n getFileSize: (filePath: string) => Promise<number>;\n splitAudioFile: (filePath: string, outputDir: string, maxSizeBytes: number) => Promise<string[]>;\n}\n\nconst ffprobeAsync = (filePath: string): Promise<any> => {\n return new Promise((resolve, reject) => {\n ffmpeg.ffprobe(filePath, (err, metadata) => {\n if (err) return reject(err);\n resolve(metadata);\n });\n });\n};\n\n\nexport const create = (logger: Logger): Media => {\n const storage = Storage.create({ log: logger.debug });\n\n // Extract creation time from audio file using ffmpeg\n const getAudioCreationTime = async (filePath: string): Promise<Date | null> => {\n try {\n const metadata = await ffprobeAsync(filePath);\n\n // Look for creation_time in format tags\n const formatTags = metadata?.format?.tags;\n if (formatTags?.creation_time) {\n logger.debug('Found creation_time in format tags: %s', formatTags.creation_time);\n return new Date(formatTags.creation_time);\n }\n\n // Check for creation_time in stream tags as fallback\n if (metadata?.streams?.length > 0) {\n for (const stream of metadata.streams) {\n if (stream.tags?.creation_time) {\n logger.debug('Found creation_time in stream tags: %s', stream.tags.creation_time);\n return new Date(stream.tags.creation_time);\n }\n }\n }\n\n logger.debug('No creation_time found in audio file metadata');\n return null;\n } catch (error) {\n logger.error('Error extracting creation time from audio file: %s', error);\n return null;\n }\n };\n\n // Get file size in bytes\n const getFileSize = async (filePath: string): Promise<number> => {\n try {\n return await storage.getFileSize(filePath);\n } catch (error) {\n logger.error('Error getting file size: %s', error);\n throw new Error(`Failed to get file size for ${filePath}: ${error}`);\n }\n };\n\n // Split large audio file into smaller chunks\n const splitAudioFile = async (filePath: string, outputDir: string, maxSizeBytes: number): Promise<string[]> => {\n try {\n const metadata = await ffprobeAsync(filePath);\n const duration = parseFloat(metadata.format.duration);\n\n // Calculate how many segments we need based on file size and max size\n const fileSize = await getFileSize(filePath);\n const segmentCount = Math.ceil(fileSize / maxSizeBytes);\n\n // Calculate segment duration\n const segmentDuration = duration / segmentCount;\n logger.debug(`Splitting ${filePath} (${fileSize} bytes) into ${segmentCount} segments of ~${segmentDuration} seconds each`);\n\n // Create output directory if it doesn't exist\n await storage.createDirectory(outputDir);\n\n const outputFiles: string[] = [];\n const fileExt = path.extname(filePath);\n const fileName = path.basename(filePath, fileExt);\n\n // Create a promise for each segment\n const promises = [];\n\n for (let i = 0; i < segmentCount; i++) {\n const startTime = i * segmentDuration;\n const outputPath = path.join(outputDir, `${fileName}_part${i + 1}${fileExt}`);\n outputFiles.push(outputPath);\n\n const promise = new Promise<void>((resolve, reject) => {\n ffmpeg(filePath)\n .setStartTime(startTime)\n .setDuration(segmentDuration)\n .output(outputPath)\n .on('end', () => {\n logger.debug(`Created segment ${i + 1}/${segmentCount}: ${outputPath}`);\n resolve();\n })\n .on('error', (err) => {\n logger.error(`Error creating segment ${i + 1}/${segmentCount}: ${err}`);\n reject(err);\n })\n .run();\n });\n\n promises.push(promise);\n }\n\n // Wait for all segments to be created\n await Promise.all(promises);\n return outputFiles;\n } catch (error) {\n logger.error('Error splitting audio file: %s', error);\n throw new Error(`Failed to split audio file ${filePath}: ${error}`);\n }\n };\n\n return {\n getAudioCreationTime,\n getFileSize,\n splitAudioFile,\n }\n}\n"],"names":["ffprobeAsync","filePath","Promise","resolve","reject","ffmpeg","ffprobe","err","metadata","create","logger","storage","Storage","log","debug","getAudioCreationTime","formatTags","format","tags","creation_time","Date","streams","length","stream","error","getFileSize","Error","splitAudioFile","outputDir","maxSizeBytes","duration","parseFloat","fileSize","segmentCount","Math","ceil","segmentDuration","createDirectory","outputFiles","fileExt","path","extname","fileName","basename","promises","i","startTime","outputPath","join","push","promise","setStartTime","setDuration","output","on","run","all"],"mappings":"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"}
1
+ {"version":3,"file":"media.js","sources":["../../src/util/media.ts"],"sourcesContent":["import ffmpeg from 'fluent-ffmpeg';\nimport { Logger } from 'winston';\nimport path from 'path';\nimport * as Storage from '@/util/storage';\n\nexport interface Media {\n getAudioCreationTime: (filePath: string) => Promise<Date | null>;\n getFileSize: (filePath: string) => Promise<number>;\n splitAudioFile: (filePath: string, outputDir: string, maxSizeBytes: number) => Promise<string[]>;\n}\n\nconst ffprobeAsync = (filePath: string): Promise<any> => {\n return new Promise((resolve, reject) => {\n ffmpeg.ffprobe(filePath, (err, metadata) => {\n if (err) return reject(err);\n resolve(metadata);\n });\n });\n};\n\n\nexport const create = (logger: Logger): Media => {\n const storage = Storage.create({ log: logger.debug });\n\n // Extract creation time from audio file using ffmpeg\n const getAudioCreationTime = async (filePath: string): Promise<Date | null> => {\n try {\n const metadata = await ffprobeAsync(filePath);\n\n // Look for creation_time in format tags\n const formatTags = metadata?.format?.tags;\n if (formatTags?.creation_time) {\n logger.debug('Found creation_time in format tags: %s', formatTags.creation_time);\n return new Date(formatTags.creation_time);\n }\n\n // Check for creation_time in stream tags as fallback\n if (metadata?.streams?.length > 0) {\n for (const stream of metadata.streams) {\n if (stream.tags?.creation_time) {\n logger.debug('Found creation_time in stream tags: %s', stream.tags.creation_time);\n return new Date(stream.tags.creation_time);\n }\n }\n }\n\n logger.debug('No creation_time found in audio file metadata');\n return null;\n } catch (error) {\n logger.error('Error extracting creation time from audio file: %s', error);\n return null;\n }\n };\n\n // Get file size in bytes\n const getFileSize = async (filePath: string): Promise<number> => {\n try {\n return await storage.getFileSize(filePath);\n } catch (error) {\n logger.error('Error getting file size: %s', error);\n throw new Error(`Failed to get file size for ${filePath}: ${error}`);\n }\n };\n\n // Split large audio file into smaller chunks\n const splitAudioFile = async (filePath: string, outputDir: string, maxSizeBytes: number): Promise<string[]> => {\n try {\n const metadata = await ffprobeAsync(filePath);\n const duration = parseFloat(metadata.format.duration);\n\n // Calculate how many segments we need based on file size and max size\n const fileSize = await getFileSize(filePath);\n const segmentCount = Math.ceil(fileSize / maxSizeBytes);\n\n // Calculate segment duration\n const segmentDuration = duration / segmentCount;\n logger.debug(`Splitting ${filePath} (${fileSize} bytes) into ${segmentCount} segments of ~${segmentDuration} seconds each`);\n\n // Create output directory if it doesn't exist\n await storage.createDirectory(outputDir);\n\n const outputFiles: string[] = [];\n const fileExt = path.extname(filePath);\n const fileName = path.basename(filePath, fileExt);\n\n // Create a promise for each segment\n const promises = [];\n\n for (let i = 0; i < segmentCount; i++) {\n const startTime = i * segmentDuration;\n const outputPath = path.join(outputDir, `${fileName}_part${i + 1}${fileExt}`);\n outputFiles.push(outputPath);\n\n const promise = new Promise<void>((resolve, reject) => {\n ffmpeg(filePath)\n .setStartTime(startTime)\n .setDuration(segmentDuration)\n .output(outputPath)\n .on('end', () => {\n logger.debug(`Created segment ${i + 1}/${segmentCount}: ${outputPath}`);\n resolve();\n })\n .on('error', (err) => {\n logger.error(`Error creating segment ${i + 1}/${segmentCount}: ${err}`);\n reject(err);\n })\n .run();\n });\n\n promises.push(promise);\n }\n\n // Wait for all segments to be created\n await Promise.all(promises);\n return outputFiles;\n } catch (error) {\n logger.error('Error splitting audio file: %s', error);\n throw new Error(`Failed to split audio file ${filePath}: ${error}`);\n }\n };\n\n return {\n getAudioCreationTime,\n getFileSize,\n splitAudioFile,\n }\n}\n"],"names":["ffprobeAsync","filePath","Promise","resolve","reject","ffmpeg","ffprobe","err","metadata","create","logger","storage","Storage","log","debug","getAudioCreationTime","formatTags","format","tags","creation_time","Date","streams","length","stream","error","getFileSize","Error","splitAudioFile","outputDir","maxSizeBytes","duration","parseFloat","fileSize","segmentCount","Math","ceil","segmentDuration","createDirectory","outputFiles","fileExt","path","extname","fileName","basename","promises","i","startTime","outputPath","join","push","promise","setStartTime","setDuration","output","on","run","all"],"mappings":"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"}
@@ -0,0 +1,95 @@
1
+ /**
2
+ * Format metadata as Markdown heading section
3
+ */ const formatMetadataMarkdown = (metadata)=>{
4
+ const lines = [];
5
+ // Title section
6
+ if (metadata.title) {
7
+ lines.push(`# ${metadata.title}`);
8
+ lines.push('');
9
+ }
10
+ // Metadata frontmatter as readable markdown
11
+ lines.push('## Metadata');
12
+ lines.push('');
13
+ // Date and Time
14
+ if (metadata.date) {
15
+ const dateStr = metadata.date.toLocaleDateString('en-US', {
16
+ year: 'numeric',
17
+ month: 'long',
18
+ day: 'numeric'
19
+ });
20
+ lines.push(`**Date**: ${dateStr}`);
21
+ if (metadata.recordingTime) {
22
+ lines.push(`**Time**: ${metadata.recordingTime}`);
23
+ } else {
24
+ const timeStr = metadata.date.toLocaleTimeString('en-US', {
25
+ hour: '2-digit',
26
+ minute: '2-digit',
27
+ hour12: true
28
+ });
29
+ lines.push(`**Time**: ${timeStr}`);
30
+ }
31
+ }
32
+ lines.push('');
33
+ // Project
34
+ if (metadata.project) {
35
+ lines.push(`**Project**: ${metadata.project}`);
36
+ if (metadata.projectId) {
37
+ lines.push(`**Project ID**: \`${metadata.projectId}\``);
38
+ }
39
+ lines.push('');
40
+ }
41
+ // Routing Information
42
+ if (metadata.routing) {
43
+ lines.push('### Routing');
44
+ lines.push('');
45
+ lines.push(`**Destination**: ${metadata.routing.destination}`);
46
+ lines.push(`**Confidence**: ${(metadata.routing.confidence * 100).toFixed(1)}%`);
47
+ lines.push('');
48
+ if (metadata.routing.signals.length > 0) {
49
+ lines.push('**Classification Signals**:');
50
+ for (const signal of metadata.routing.signals){
51
+ const signalType = signal.type.replace(/_/g, ' ');
52
+ const weight = (signal.weight * 100).toFixed(0);
53
+ lines.push(`- ${signalType}: "${signal.value}" (${weight}% weight)`);
54
+ }
55
+ lines.push('');
56
+ }
57
+ if (metadata.routing.reasoning) {
58
+ lines.push(`**Reasoning**: ${metadata.routing.reasoning}`);
59
+ lines.push('');
60
+ }
61
+ }
62
+ // Tags
63
+ if (metadata.tags && metadata.tags.length > 0) {
64
+ lines.push('**Tags**: ' + metadata.tags.map((tag)=>`\`${tag}\``).join(', '));
65
+ lines.push('');
66
+ }
67
+ // Duration
68
+ if (metadata.duration) {
69
+ lines.push(`**Duration**: ${metadata.duration}`);
70
+ lines.push('');
71
+ }
72
+ // Separator
73
+ lines.push('---');
74
+ lines.push('');
75
+ return lines.join('\n');
76
+ };
77
+ /**
78
+ * Extract routing metadata from a RouteDecision
79
+ */ const createRoutingMetadata = (decision)=>{
80
+ return {
81
+ destination: decision.destination.path,
82
+ confidence: decision.confidence,
83
+ signals: decision.signals,
84
+ reasoning: decision.reasoning
85
+ };
86
+ };
87
+ /**
88
+ * Extract all tags from routing signals
89
+ */ const extractTagsFromSignals = (signals)=>{
90
+ return signals.filter((s)=>s.type !== 'context_type') // Skip generic context type
91
+ .map((s)=>s.value).filter((v)=>typeof v === 'string');
92
+ };
93
+
94
+ export { createRoutingMetadata, extractTagsFromSignals, formatMetadataMarkdown };
95
+ //# sourceMappingURL=metadata.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metadata.js","sources":["../../src/util/metadata.ts"],"sourcesContent":["import * as Routing from '@/routing';\n\nexport interface TranscriptMetadata {\n title?: string;\n project?: string;\n projectId?: string;\n routing?: RoutingMetadata;\n tags?: string[];\n date?: Date;\n recordingTime?: string;\n confidence?: number;\n duration?: string;\n}\n\nexport interface RoutingMetadata {\n destination: string;\n confidence: number;\n signals: Routing.ClassificationSignal[];\n reasoning: string;\n}\n\n/**\n * Format metadata as Markdown heading section\n */\nexport const formatMetadataMarkdown = (metadata: TranscriptMetadata): string => {\n const lines: string[] = [];\n \n // Title section\n if (metadata.title) {\n lines.push(`# ${metadata.title}`);\n lines.push('');\n }\n \n // Metadata frontmatter as readable markdown\n lines.push('## Metadata');\n lines.push('');\n \n // Date and Time\n if (metadata.date) {\n const dateStr = metadata.date.toLocaleDateString('en-US', {\n year: 'numeric',\n month: 'long',\n day: 'numeric'\n });\n lines.push(`**Date**: ${dateStr}`);\n \n if (metadata.recordingTime) {\n lines.push(`**Time**: ${metadata.recordingTime}`);\n } else {\n const timeStr = metadata.date.toLocaleTimeString('en-US', {\n hour: '2-digit',\n minute: '2-digit',\n hour12: true\n });\n lines.push(`**Time**: ${timeStr}`);\n }\n }\n \n lines.push('');\n \n // Project\n if (metadata.project) {\n lines.push(`**Project**: ${metadata.project}`);\n if (metadata.projectId) {\n lines.push(`**Project ID**: \\`${metadata.projectId}\\``);\n }\n lines.push('');\n }\n \n // Routing Information\n if (metadata.routing) {\n lines.push('### Routing');\n lines.push('');\n lines.push(`**Destination**: ${metadata.routing.destination}`);\n lines.push(`**Confidence**: ${(metadata.routing.confidence * 100).toFixed(1)}%`);\n lines.push('');\n \n if (metadata.routing.signals.length > 0) {\n lines.push('**Classification Signals**:');\n for (const signal of metadata.routing.signals) {\n const signalType = signal.type.replace(/_/g, ' ');\n const weight = (signal.weight * 100).toFixed(0);\n lines.push(`- ${signalType}: \"${signal.value}\" (${weight}% weight)`);\n }\n lines.push('');\n }\n \n if (metadata.routing.reasoning) {\n lines.push(`**Reasoning**: ${metadata.routing.reasoning}`);\n lines.push('');\n }\n }\n \n // Tags\n if (metadata.tags && metadata.tags.length > 0) {\n lines.push('**Tags**: ' + metadata.tags.map(tag => `\\`${tag}\\``).join(', '));\n lines.push('');\n }\n \n // Duration\n if (metadata.duration) {\n lines.push(`**Duration**: ${metadata.duration}`);\n lines.push('');\n }\n \n // Separator\n lines.push('---');\n lines.push('');\n \n return lines.join('\\n');\n};\n\n/**\n * Extract routing metadata from a RouteDecision\n */\nexport const createRoutingMetadata = (decision: Routing.RouteDecision): RoutingMetadata => {\n return {\n destination: decision.destination.path,\n confidence: decision.confidence,\n signals: decision.signals,\n reasoning: decision.reasoning,\n };\n};\n\n/**\n * Format duration in seconds to readable format (e.g., \"2m 30s\")\n */\nexport const formatDuration = (seconds: number): string => {\n const minutes = Math.floor(seconds / 60);\n const secs = Math.round(seconds % 60);\n \n if (minutes === 0) {\n return `${secs}s`;\n }\n \n if (secs === 0) {\n return `${minutes}m`;\n }\n \n return `${minutes}m ${secs}s`;\n};\n\n/**\n * Format time as HH:MM AM/PM\n */\nexport const formatTime = (date: Date): string => {\n return date.toLocaleTimeString('en-US', {\n hour: '2-digit',\n minute: '2-digit',\n hour12: true\n });\n};\n\n/**\n * Extract topic from routing signals\n */\nexport const extractTopicFromSignals = (signals: Routing.ClassificationSignal[]): string | undefined => {\n const topicSignal = signals.find(s => s.type === 'topic' || s.type === 'context_type');\n return topicSignal?.value;\n};\n\n/**\n * Extract all tags from routing signals\n */\nexport const extractTagsFromSignals = (signals: Routing.ClassificationSignal[]): string[] => {\n return signals\n .filter(s => s.type !== 'context_type') // Skip generic context type\n .map(s => s.value)\n .filter((v): v is string => typeof v === 'string');\n};\n\n"],"names":["formatMetadataMarkdown","metadata","lines","title","push","date","dateStr","toLocaleDateString","year","month","day","recordingTime","timeStr","toLocaleTimeString","hour","minute","hour12","project","projectId","routing","destination","confidence","toFixed","signals","length","signal","signalType","type","replace","weight","value","reasoning","tags","map","tag","join","duration","createRoutingMetadata","decision","path","extractTagsFromSignals","filter","s","v"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import * as fs from 'fs';
2
2
  import { glob } from 'glob';
3
- import path from 'path';
3
+ import path__default from 'path';
4
4
  import crypto from 'crypto';
5
5
 
6
6
  // eslint-disable-next-line no-restricted-imports
@@ -87,7 +87,7 @@ const create = (params)=>{
87
87
  nodir: true
88
88
  });
89
89
  for (const file of files){
90
- await callback(path.join(directory, file));
90
+ await callback(path__default.join(directory, file));
91
91
  }
92
92
  } catch (err) {
93
93
  throw new Error(`Failed to glob pattern ${options.pattern} in ${directory}: ${err.message}`);
@@ -1 +1 @@
1
- {"version":3,"file":"storage.js","sources":["../../src/util/storage.ts"],"sourcesContent":["// eslint-disable-next-line no-restricted-imports\nimport * as fs from 'fs';\nimport { glob } from 'glob';\nimport path from 'path';\nimport crypto from 'crypto';\n/**\n * This module exists to isolate filesystem operations from the rest of the codebase.\n * This makes testing easier by avoiding direct fs mocking in jest configuration.\n * \n * Additionally, abstracting storage operations allows for future flexibility - \n * this export utility may need to work with storage systems other than the local filesystem\n * (e.g. S3, Google Cloud Storage, etc).\n */\n\nexport interface Utility {\n exists: (path: string) => Promise<boolean>;\n isDirectory: (path: string) => Promise<boolean>;\n isFile: (path: string) => Promise<boolean>;\n isReadable: (path: string) => Promise<boolean>;\n isWritable: (path: string) => Promise<boolean>;\n isFileReadable: (path: string) => Promise<boolean>;\n isDirectoryWritable: (path: string) => Promise<boolean>;\n isDirectoryReadable: (path: string) => Promise<boolean>;\n createDirectory: (path: string) => Promise<void>;\n readFile: (path: string, encoding: string) => Promise<string>;\n readStream: (path: string) => Promise<fs.ReadStream>;\n writeFile: (path: string, data: string | Buffer, encoding: string) => Promise<void>;\n forEachFileIn: (directory: string, callback: (path: string) => Promise<void>, options?: { pattern: string }) => Promise<void>;\n hashFile: (path: string, length: number) => Promise<string>;\n listFiles: (directory: string) => Promise<string[]>;\n deleteFile: (path: string) => Promise<void>;\n getFileSize: (path: string) => Promise<number>;\n}\n\nexport const create = (params: { log?: (message: string, ...args: any[]) => void }): Utility => {\n\n // eslint-disable-next-line no-console\n const log = params.log || console.log;\n\n const exists = async (path: string): Promise<boolean> => {\n try {\n await fs.promises.stat(path);\n return true;\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n } catch (error: any) {\n return false;\n }\n }\n\n const isDirectory = async (path: string): Promise<boolean> => {\n const stats = await fs.promises.stat(path);\n if (!stats.isDirectory()) {\n log(`${path} is not a directory`);\n return false;\n }\n return true;\n }\n\n const isFile = async (path: string): Promise<boolean> => {\n const stats = await fs.promises.stat(path);\n if (!stats.isFile()) {\n log(`${path} is not a file`);\n return false;\n }\n return true;\n }\n\n const isReadable = async (path: string): Promise<boolean> => {\n try {\n await fs.promises.access(path, fs.constants.R_OK);\n } catch (error: any) {\n log(`${path} is not readable: %s %s`, error.message, error.stack);\n return false;\n }\n return true;\n }\n\n const isWritable = async (path: string): Promise<boolean> => {\n try {\n await fs.promises.access(path, fs.constants.W_OK);\n } catch (error: any) {\n log(`${path} is not writable: %s %s`, error.message, error.stack);\n return false;\n }\n return true;\n }\n\n const isFileReadable = async (path: string): Promise<boolean> => {\n return await exists(path) && await isFile(path) && await isReadable(path);\n }\n\n const isDirectoryWritable = async (path: string): Promise<boolean> => {\n return await exists(path) && await isDirectory(path) && await isWritable(path);\n }\n\n const isDirectoryReadable = async (path: string): Promise<boolean> => {\n return await exists(path) && await isDirectory(path) && await isReadable(path);\n }\n\n const createDirectory = async (path: string): Promise<void> => {\n try {\n await fs.promises.mkdir(path, { recursive: true });\n } catch (mkdirError: any) {\n throw new Error(`Failed to create output directory ${path}: ${mkdirError.message} ${mkdirError.stack}`);\n }\n }\n\n const readFile = async (path: string, encoding: string): Promise<string> => {\n return await fs.promises.readFile(path, { encoding: encoding as BufferEncoding });\n }\n\n const writeFile = async (path: string, data: string | Buffer, encoding: string): Promise<void> => {\n await fs.promises.writeFile(path, data, { encoding: encoding as BufferEncoding });\n }\n\n const forEachFileIn = async (directory: string, callback: (file: string) => Promise<void>, options: { pattern: string | string[] } = { pattern: '*.*' }): Promise<void> => {\n try {\n const files = await glob(options.pattern, { cwd: directory, nodir: true });\n for (const file of files) {\n await callback(path.join(directory, file));\n }\n } catch (err: any) {\n throw new Error(`Failed to glob pattern ${options.pattern} in ${directory}: ${err.message}`);\n }\n }\n\n const readStream = async (path: string): Promise<fs.ReadStream> => {\n return fs.createReadStream(path);\n }\n\n const hashFile = async (path: string, length: number): Promise<string> => {\n const file = await readFile(path, 'utf8');\n return crypto.createHash('sha256').update(file).digest('hex').slice(0, length);\n }\n\n const listFiles = async (directory: string): Promise<string[]> => {\n return await fs.promises.readdir(directory);\n }\n\n const deleteFile = async (path: string): Promise<void> => {\n await fs.promises.unlink(path);\n }\n\n const getFileSize = async (path: string): Promise<number> => {\n const stats = await fs.promises.stat(path);\n return stats.size;\n }\n\n return {\n exists,\n isDirectory,\n isFile,\n isReadable,\n isWritable,\n isFileReadable,\n isDirectoryWritable,\n isDirectoryReadable,\n createDirectory,\n readFile,\n readStream,\n writeFile,\n forEachFileIn,\n hashFile,\n listFiles,\n deleteFile,\n getFileSize,\n };\n}"],"names":["create","params","log","console","exists","path","fs","promises","stat","error","isDirectory","stats","isFile","isReadable","access","constants","R_OK","message","stack","isWritable","W_OK","isFileReadable","isDirectoryWritable","isDirectoryReadable","createDirectory","mkdir","recursive","mkdirError","Error","readFile","encoding","writeFile","data","forEachFileIn","directory","callback","options","pattern","files","glob","cwd","nodir","file","join","err","readStream","createReadStream","hashFile","length","crypto","createHash","update","digest","slice","listFiles","readdir","deleteFile","unlink","getFileSize","size"],"mappings":";;;;;AAAA;AAkCO,MAAMA,SAAS,CAACC,MAAAA,GAAAA;;AAGnB,IAAA,MAAMC,GAAAA,GAAMD,MAAAA,CAAOC,GAAG,IAAIC,QAAQD,GAAG;AAErC,IAAA,MAAME,SAAS,OAAOC,IAAAA,GAAAA;QAClB,IAAI;AACA,YAAA,MAAMC,EAAAA,CAAGC,QAAQ,CAACC,IAAI,CAACH,IAAAA,CAAAA;YACvB,OAAO,IAAA;;AAEX,QAAA,CAAA,CAAE,OAAOI,KAAAA,EAAY;YACjB,OAAO,KAAA;AACX,QAAA;AACJ,IAAA,CAAA;AAEA,IAAA,MAAMC,cAAc,OAAOL,IAAAA,GAAAA;AACvB,QAAA,MAAMM,QAAQ,MAAML,EAAAA,CAAGC,QAAQ,CAACC,IAAI,CAACH,IAAAA,CAAAA;QACrC,IAAI,CAACM,KAAAA,CAAMD,WAAW,EAAA,EAAI;YACtBR,GAAAA,CAAI,CAAA,EAAGG,IAAAA,CAAK,mBAAmB,CAAC,CAAA;YAChC,OAAO,KAAA;AACX,QAAA;QACA,OAAO,IAAA;AACX,IAAA,CAAA;AAEA,IAAA,MAAMO,SAAS,OAAOP,IAAAA,GAAAA;AAClB,QAAA,MAAMM,QAAQ,MAAML,EAAAA,CAAGC,QAAQ,CAACC,IAAI,CAACH,IAAAA,CAAAA;QACrC,IAAI,CAACM,KAAAA,CAAMC,MAAM,EAAA,EAAI;YACjBV,GAAAA,CAAI,CAAA,EAAGG,IAAAA,CAAK,cAAc,CAAC,CAAA;YAC3B,OAAO,KAAA;AACX,QAAA;QACA,OAAO,IAAA;AACX,IAAA,CAAA;AAEA,IAAA,MAAMQ,aAAa,OAAOR,IAAAA,GAAAA;QACtB,IAAI;YACA,MAAMC,EAAAA,CAAGC,QAAQ,CAACO,MAAM,CAACT,IAAAA,EAAMC,EAAAA,CAAGS,SAAS,CAACC,IAAI,CAAA;AACpD,QAAA,CAAA,CAAE,OAAOP,KAAAA,EAAY;YACjBP,GAAAA,CAAI,CAAA,EAAGG,KAAK,uBAAuB,CAAC,EAAEI,KAAAA,CAAMQ,OAAO,EAAER,KAAAA,CAAMS,KAAK,CAAA;YAChE,OAAO,KAAA;AACX,QAAA;QACA,OAAO,IAAA;AACX,IAAA,CAAA;AAEA,IAAA,MAAMC,aAAa,OAAOd,IAAAA,GAAAA;QACtB,IAAI;YACA,MAAMC,EAAAA,CAAGC,QAAQ,CAACO,MAAM,CAACT,IAAAA,EAAMC,EAAAA,CAAGS,SAAS,CAACK,IAAI,CAAA;AACpD,QAAA,CAAA,CAAE,OAAOX,KAAAA,EAAY;YACjBP,GAAAA,CAAI,CAAA,EAAGG,KAAK,uBAAuB,CAAC,EAAEI,KAAAA,CAAMQ,OAAO,EAAER,KAAAA,CAAMS,KAAK,CAAA;YAChE,OAAO,KAAA;AACX,QAAA;QACA,OAAO,IAAA;AACX,IAAA,CAAA;AAEA,IAAA,MAAMG,iBAAiB,OAAOhB,IAAAA,GAAAA;AAC1B,QAAA,OAAO,MAAMD,MAAAA,CAAOC,IAAAA,CAAAA,IAAS,MAAMO,MAAAA,CAAOP,IAAAA,CAAAA,IAAS,MAAMQ,UAAAA,CAAWR,IAAAA,CAAAA;AACxE,IAAA,CAAA;AAEA,IAAA,MAAMiB,sBAAsB,OAAOjB,IAAAA,GAAAA;AAC/B,QAAA,OAAO,MAAMD,MAAAA,CAAOC,IAAAA,CAAAA,IAAS,MAAMK,WAAAA,CAAYL,IAAAA,CAAAA,IAAS,MAAMc,UAAAA,CAAWd,IAAAA,CAAAA;AAC7E,IAAA,CAAA;AAEA,IAAA,MAAMkB,sBAAsB,OAAOlB,IAAAA,GAAAA;AAC/B,QAAA,OAAO,MAAMD,MAAAA,CAAOC,IAAAA,CAAAA,IAAS,MAAMK,WAAAA,CAAYL,IAAAA,CAAAA,IAAS,MAAMQ,UAAAA,CAAWR,IAAAA,CAAAA;AAC7E,IAAA,CAAA;AAEA,IAAA,MAAMmB,kBAAkB,OAAOnB,IAAAA,GAAAA;QAC3B,IAAI;AACA,YAAA,MAAMC,EAAAA,CAAGC,QAAQ,CAACkB,KAAK,CAACpB,IAAAA,EAAM;gBAAEqB,SAAAA,EAAW;AAAK,aAAA,CAAA;AACpD,QAAA,CAAA,CAAE,OAAOC,UAAAA,EAAiB;AACtB,YAAA,MAAM,IAAIC,KAAAA,CAAM,CAAC,kCAAkC,EAAEvB,IAAAA,CAAK,EAAE,EAAEsB,UAAAA,CAAWV,OAAO,CAAC,CAAC,EAAEU,UAAAA,CAAWT,KAAK,CAAA,CAAE,CAAA;AAC1G,QAAA;AACJ,IAAA,CAAA;IAEA,MAAMW,QAAAA,GAAW,OAAOxB,IAAAA,EAAcyB,QAAAA,GAAAA;AAClC,QAAA,OAAO,MAAMxB,EAAAA,CAAGC,QAAQ,CAACsB,QAAQ,CAACxB,IAAAA,EAAM;YAAEyB,QAAAA,EAAUA;AAA2B,SAAA,CAAA;AACnF,IAAA,CAAA;IAEA,MAAMC,SAAAA,GAAY,OAAO1B,IAAAA,EAAc2B,IAAAA,EAAuBF,QAAAA,GAAAA;AAC1D,QAAA,MAAMxB,GAAGC,QAAQ,CAACwB,SAAS,CAAC1B,MAAM2B,IAAAA,EAAM;YAAEF,QAAAA,EAAUA;AAA2B,SAAA,CAAA;AACnF,IAAA,CAAA;AAEA,IAAA,MAAMG,aAAAA,GAAgB,OAAOC,SAAAA,EAAmBC,QAAAA,EAA2CC,OAAAA,GAA0C;QAAEC,OAAAA,EAAS;KAAO,GAAA;QACnJ,IAAI;AACA,YAAA,MAAMC,KAAAA,GAAQ,MAAMC,IAAAA,CAAKH,OAAAA,CAAQC,OAAO,EAAE;gBAAEG,GAAAA,EAAKN,SAAAA;gBAAWO,KAAAA,EAAO;AAAK,aAAA,CAAA;YACxE,KAAK,MAAMC,QAAQJ,KAAAA,CAAO;AACtB,gBAAA,MAAMH,QAAAA,CAAS9B,IAAAA,CAAKsC,IAAI,CAACT,SAAAA,EAAWQ,IAAAA,CAAAA,CAAAA;AACxC,YAAA;AACJ,QAAA,CAAA,CAAE,OAAOE,GAAAA,EAAU;AACf,YAAA,MAAM,IAAIhB,KAAAA,CAAM,CAAC,uBAAuB,EAAEQ,OAAAA,CAAQC,OAAO,CAAC,IAAI,EAAEH,SAAAA,CAAU,EAAE,EAAEU,GAAAA,CAAI3B,OAAO,CAAA,CAAE,CAAA;AAC/F,QAAA;AACJ,IAAA,CAAA;AAEA,IAAA,MAAM4B,aAAa,OAAOxC,IAAAA,GAAAA;QACtB,OAAOC,EAAAA,CAAGwC,gBAAgB,CAACzC,IAAAA,CAAAA;AAC/B,IAAA,CAAA;IAEA,MAAM0C,QAAAA,GAAW,OAAO1C,IAAAA,EAAc2C,MAAAA,GAAAA;QAClC,MAAMN,IAAAA,GAAO,MAAMb,QAAAA,CAASxB,IAAAA,EAAM,MAAA,CAAA;AAClC,QAAA,OAAO4C,MAAAA,CAAOC,UAAU,CAAC,QAAA,CAAA,CAAUC,MAAM,CAACT,IAAAA,CAAAA,CAAMU,MAAM,CAAC,KAAA,CAAA,CAAOC,KAAK,CAAC,CAAA,EAAGL,MAAAA,CAAAA;AAC3E,IAAA,CAAA;AAEA,IAAA,MAAMM,YAAY,OAAOpB,SAAAA,GAAAA;AACrB,QAAA,OAAO,MAAM5B,EAAAA,CAAGC,QAAQ,CAACgD,OAAO,CAACrB,SAAAA,CAAAA;AACrC,IAAA,CAAA;AAEA,IAAA,MAAMsB,aAAa,OAAOnD,IAAAA,GAAAA;AACtB,QAAA,MAAMC,EAAAA,CAAGC,QAAQ,CAACkD,MAAM,CAACpD,IAAAA,CAAAA;AAC7B,IAAA,CAAA;AAEA,IAAA,MAAMqD,cAAc,OAAOrD,IAAAA,GAAAA;AACvB,QAAA,MAAMM,QAAQ,MAAML,EAAAA,CAAGC,QAAQ,CAACC,IAAI,CAACH,IAAAA,CAAAA;AACrC,QAAA,OAAOM,MAAMgD,IAAI;AACrB,IAAA,CAAA;IAEA,OAAO;AACHvD,QAAAA,MAAAA;AACAM,QAAAA,WAAAA;AACAE,QAAAA,MAAAA;AACAC,QAAAA,UAAAA;AACAM,QAAAA,UAAAA;AACAE,QAAAA,cAAAA;AACAC,QAAAA,mBAAAA;AACAC,QAAAA,mBAAAA;AACAC,QAAAA,eAAAA;AACAK,QAAAA,QAAAA;AACAgB,QAAAA,UAAAA;AACAd,QAAAA,SAAAA;AACAE,QAAAA,aAAAA;AACAc,QAAAA,QAAAA;AACAO,QAAAA,SAAAA;AACAE,QAAAA,UAAAA;AACAE,QAAAA;AACJ,KAAA;AACJ;;;;"}
1
+ {"version":3,"file":"storage.js","sources":["../../src/util/storage.ts"],"sourcesContent":["// eslint-disable-next-line no-restricted-imports\nimport * as fs from 'fs';\nimport { glob } from 'glob';\nimport path from 'path';\nimport crypto from 'crypto';\n/**\n * This module exists to isolate filesystem operations from the rest of the codebase.\n * This makes testing easier by avoiding direct fs mocking in jest configuration.\n * \n * Additionally, abstracting storage operations allows for future flexibility - \n * this export utility may need to work with storage systems other than the local filesystem\n * (e.g. S3, Google Cloud Storage, etc).\n */\n\nexport interface Utility {\n exists: (path: string) => Promise<boolean>;\n isDirectory: (path: string) => Promise<boolean>;\n isFile: (path: string) => Promise<boolean>;\n isReadable: (path: string) => Promise<boolean>;\n isWritable: (path: string) => Promise<boolean>;\n isFileReadable: (path: string) => Promise<boolean>;\n isDirectoryWritable: (path: string) => Promise<boolean>;\n isDirectoryReadable: (path: string) => Promise<boolean>;\n createDirectory: (path: string) => Promise<void>;\n readFile: (path: string, encoding: string) => Promise<string>;\n readStream: (path: string) => Promise<fs.ReadStream>;\n writeFile: (path: string, data: string | Buffer, encoding: string) => Promise<void>;\n forEachFileIn: (directory: string, callback: (path: string) => Promise<void>, options?: { pattern: string }) => Promise<void>;\n hashFile: (path: string, length: number) => Promise<string>;\n listFiles: (directory: string) => Promise<string[]>;\n deleteFile: (path: string) => Promise<void>;\n getFileSize: (path: string) => Promise<number>;\n}\n\nexport const create = (params: { log?: (message: string, ...args: any[]) => void }): Utility => {\n\n // eslint-disable-next-line no-console\n const log = params.log || console.log;\n\n const exists = async (path: string): Promise<boolean> => {\n try {\n await fs.promises.stat(path);\n return true;\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n } catch (error: any) {\n return false;\n }\n }\n\n const isDirectory = async (path: string): Promise<boolean> => {\n const stats = await fs.promises.stat(path);\n if (!stats.isDirectory()) {\n log(`${path} is not a directory`);\n return false;\n }\n return true;\n }\n\n const isFile = async (path: string): Promise<boolean> => {\n const stats = await fs.promises.stat(path);\n if (!stats.isFile()) {\n log(`${path} is not a file`);\n return false;\n }\n return true;\n }\n\n const isReadable = async (path: string): Promise<boolean> => {\n try {\n await fs.promises.access(path, fs.constants.R_OK);\n } catch (error: any) {\n log(`${path} is not readable: %s %s`, error.message, error.stack);\n return false;\n }\n return true;\n }\n\n const isWritable = async (path: string): Promise<boolean> => {\n try {\n await fs.promises.access(path, fs.constants.W_OK);\n } catch (error: any) {\n log(`${path} is not writable: %s %s`, error.message, error.stack);\n return false;\n }\n return true;\n }\n\n const isFileReadable = async (path: string): Promise<boolean> => {\n return await exists(path) && await isFile(path) && await isReadable(path);\n }\n\n const isDirectoryWritable = async (path: string): Promise<boolean> => {\n return await exists(path) && await isDirectory(path) && await isWritable(path);\n }\n\n const isDirectoryReadable = async (path: string): Promise<boolean> => {\n return await exists(path) && await isDirectory(path) && await isReadable(path);\n }\n\n const createDirectory = async (path: string): Promise<void> => {\n try {\n await fs.promises.mkdir(path, { recursive: true });\n } catch (mkdirError: any) {\n throw new Error(`Failed to create output directory ${path}: ${mkdirError.message} ${mkdirError.stack}`);\n }\n }\n\n const readFile = async (path: string, encoding: string): Promise<string> => {\n return await fs.promises.readFile(path, { encoding: encoding as BufferEncoding });\n }\n\n const writeFile = async (path: string, data: string | Buffer, encoding: string): Promise<void> => {\n await fs.promises.writeFile(path, data, { encoding: encoding as BufferEncoding });\n }\n\n const forEachFileIn = async (directory: string, callback: (file: string) => Promise<void>, options: { pattern: string | string[] } = { pattern: '*.*' }): Promise<void> => {\n try {\n const files = await glob(options.pattern, { cwd: directory, nodir: true });\n for (const file of files) {\n await callback(path.join(directory, file));\n }\n } catch (err: any) {\n throw new Error(`Failed to glob pattern ${options.pattern} in ${directory}: ${err.message}`);\n }\n }\n\n const readStream = async (path: string): Promise<fs.ReadStream> => {\n return fs.createReadStream(path);\n }\n\n const hashFile = async (path: string, length: number): Promise<string> => {\n const file = await readFile(path, 'utf8');\n return crypto.createHash('sha256').update(file).digest('hex').slice(0, length);\n }\n\n const listFiles = async (directory: string): Promise<string[]> => {\n return await fs.promises.readdir(directory);\n }\n\n const deleteFile = async (path: string): Promise<void> => {\n await fs.promises.unlink(path);\n }\n\n const getFileSize = async (path: string): Promise<number> => {\n const stats = await fs.promises.stat(path);\n return stats.size;\n }\n\n return {\n exists,\n isDirectory,\n isFile,\n isReadable,\n isWritable,\n isFileReadable,\n isDirectoryWritable,\n isDirectoryReadable,\n createDirectory,\n readFile,\n readStream,\n writeFile,\n forEachFileIn,\n hashFile,\n listFiles,\n deleteFile,\n getFileSize,\n };\n}"],"names":["create","params","log","console","exists","path","fs","promises","stat","error","isDirectory","stats","isFile","isReadable","access","constants","R_OK","message","stack","isWritable","W_OK","isFileReadable","isDirectoryWritable","isDirectoryReadable","createDirectory","mkdir","recursive","mkdirError","Error","readFile","encoding","writeFile","data","forEachFileIn","directory","callback","options","pattern","files","glob","cwd","nodir","file","join","err","readStream","createReadStream","hashFile","length","crypto","createHash","update","digest","slice","listFiles","readdir","deleteFile","unlink","getFileSize","size"],"mappings":"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"}
@@ -0,0 +1,224 @@
1
+ # Protokoll Usage Examples
2
+
3
+ ## Scenario 1: Daily Voice Notes
4
+
5
+ You record voice notes during your commute. Want them organized by date.
6
+
7
+ ```bash
8
+ # Simple daily processing
9
+ protokoll --input-directory ~/Voice\ Memos --output-directory ~/notes
10
+
11
+ # Result: ~/notes/2026/01/11-commute-thoughts.md
12
+ ```
13
+
14
+ ## Scenario 2: Work Project Notes
15
+
16
+ Notes about specific work projects should go to project directories.
17
+
18
+ ```yaml
19
+ # ~/.protokoll/config.yaml
20
+ routing:
21
+ projects:
22
+ - projectId: "projectA"
23
+ destination:
24
+ path: "~/work/projectA/notes"
25
+ structure: "month"
26
+ triggers:
27
+ - "projectA note"
28
+ - "about projectA"
29
+ ```
30
+
31
+ ```bash
32
+ # Your recording: "This is a note about projectA..."
33
+ protokoll --input-directory ~/recordings
34
+
35
+ # Result: ~/work/projectA/notes/2026/01-meeting.md
36
+ ```
37
+
38
+ ## Scenario 3: Learning New Names
39
+
40
+ First time mentioning a colleague in recordings.
41
+
42
+ ```bash
43
+ # Interactive mode
44
+ protokoll --input-directory ~/recordings --interactive
45
+
46
+ # Protokoll asks:
47
+ # "Unknown name 'Sarah Chen'. Correct spelling?"
48
+ # You answer, it remembers for next time
49
+ ```
50
+
51
+ ## Scenario 4: Debugging Issues
52
+
53
+ Something isn't working right.
54
+
55
+ ```bash
56
+ protokoll --input-directory ~/recordings \
57
+ --debug \
58
+ --self-reflection \
59
+ --verbose
60
+
61
+ # Check output/protokoll/ for:
62
+ # - Raw Whisper output
63
+ # - LLM requests/responses
64
+ # - Self-reflection report
65
+ ```
66
+
67
+ ## Scenario 5: Multiple Projects
68
+
69
+ You work on several projects and want automatic routing.
70
+
71
+ ```yaml
72
+ # ~/.protokoll/config.yaml
73
+ routing:
74
+ default:
75
+ path: "~/notes/personal"
76
+ structure: "month"
77
+
78
+ projects:
79
+ - projectId: "work"
80
+ destination:
81
+ path: "~/work/notes"
82
+ structure: "month"
83
+ triggers:
84
+ - "work note"
85
+ - "office meeting"
86
+ - "standup"
87
+
88
+ - projectId: "side-project"
89
+ destination:
90
+ path: "~/projects/side-project/notes"
91
+ structure: "day"
92
+ triggers:
93
+ - "side project"
94
+ - "weekend coding"
95
+ ```
96
+
97
+ ```bash
98
+ # All recordings get routed automatically
99
+ protokoll --input-directory ~/recordings --recursive
100
+ ```
101
+
102
+ ## Scenario 6: Team Context
103
+
104
+ Share context across a team project.
105
+
106
+ ```yaml
107
+ # ~/team-project/.protokoll/people/alice.yaml
108
+ id: alice
109
+ name: Alice Johnson
110
+ role: Tech Lead
111
+ sounds_like:
112
+ - "alice"
113
+ - "al"
114
+ context: "Project tech lead"
115
+
116
+ # ~/team-project/.protokoll/people/bob.yaml
117
+ id: bob
118
+ name: Bob Smith
119
+ role: Designer
120
+ sounds_like:
121
+ - "bob"
122
+ - "bobby"
123
+ context: "UI/UX designer"
124
+ ```
125
+
126
+ ```bash
127
+ # Process from within project directory
128
+ cd ~/team-project
129
+ protokoll --input-directory ./recordings
130
+
131
+ # Protokoll finds .protokoll/ context automatically
132
+ ```
133
+
134
+ ## Scenario 7: Batch Processing
135
+
136
+ Process a backlog of recordings overnight.
137
+
138
+ ```bash
139
+ # Process all recordings without interaction
140
+ protokoll --input-directory ~/backlog \
141
+ --batch \
142
+ --recursive \
143
+ --output-directory ~/processed-notes
144
+
145
+ # Or with a delay to avoid rate limits
146
+ protokoll --input-directory ~/backlog --batch
147
+ ```
148
+
149
+ ## Scenario 8: Quality Review
150
+
151
+ Review transcription quality after processing.
152
+
153
+ ```bash
154
+ # Enable self-reflection
155
+ protokoll --input-directory ~/recordings --self-reflection
156
+
157
+ # Check the reflection report
158
+ cat output/protokoll/*-reflection.md
159
+ ```
160
+
161
+ Example output:
162
+ ```markdown
163
+ # Protokoll - Self-Reflection Report
164
+
165
+ ## Summary
166
+ - Duration: 12.5s
167
+ - Iterations: 8
168
+ - Tool Calls: 5
169
+ - Confidence: 94.2%
170
+
171
+ ## Recommendations
172
+ ### 🟢 Low Priority
173
+ 1. **Processing took 12.5s**
174
+ - Consider reducing max iterations for shorter transcripts
175
+ ```
176
+
177
+ ## Scenario 9: Custom Model Selection
178
+
179
+ Use different models for different quality/speed tradeoffs.
180
+
181
+ ```bash
182
+ # Fast processing with smaller model
183
+ protokoll --input-directory ~/quick-notes --model gpt-4o-mini
184
+
185
+ # High quality with larger model
186
+ protokoll --input-directory ~/important-meetings --model claude-3-5-sonnet
187
+
188
+ # Use latest transcription model
189
+ protokoll --input-directory ~/recordings --transcription-model gpt-4o-transcribe
190
+ ```
191
+
192
+ ## Scenario 10: Hierarchical Context
193
+
194
+ Use global and project-specific context together.
195
+
196
+ ```
197
+ ~/.protokoll/ # Global context
198
+ ├── config.yaml
199
+ ├── people/
200
+ │ └── family-members.yaml
201
+ └── terms/
202
+ └── common-terms.yaml
203
+
204
+ ~/work/.protokoll/ # Work-specific context
205
+ ├── config.yaml # Overrides global
206
+ ├── people/
207
+ │ └── colleagues.yaml
208
+ └── projects/
209
+ └── current-project.yaml
210
+
211
+ ~/work/project-a/.protokoll/ # Project-specific context
212
+ ├── people/
213
+ │ └── project-team.yaml
214
+ └── terms/
215
+ └── project-jargon.yaml
216
+ ```
217
+
218
+ ```bash
219
+ # When processing from ~/work/project-a/recordings/
220
+ # Protokoll merges context from all three levels
221
+ cd ~/work/project-a
222
+ protokoll --input-directory ./recordings
223
+ ```
224
+
package/docs/index.html CHANGED
@@ -3,14 +3,16 @@
3
3
 
4
4
  <head>
5
5
  <meta charset="UTF-8" />
6
- <link rel="icon" type="image/svg+xml" href="/vite.svg" />
7
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
8
- <title>Matnava - Focused Audio Transcription Tool</title>
7
+ <title>Protokoll - Intelligent Audio Transcription</title>
8
+ <meta name="description"
9
+ content="Transform voice memos into perfectly organized, context-aware notes. Intelligent name recognition, smart routing, full content preservation.">
10
+
11
+ <script type="module" src="/src/main.jsx"></script>
9
12
  </head>
10
13
 
11
14
  <body>
12
15
  <div id="root"></div>
13
- <script type="module" src="/src/main.jsx"></script>
14
16
  </body>
15
17
 
16
18
  </html>