@redaksjon/protokoll 0.0.8 → 0.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.cursor/rules/definition-of-done.md +89 -0
- package/.cursor/rules/no-emoticons.md +43 -0
- package/LICENSE +1 -1
- package/README.md +928 -35
- package/dist/agentic/executor.js +315 -0
- package/dist/agentic/executor.js.map +1 -0
- package/dist/agentic/index.js +19 -0
- package/dist/agentic/index.js.map +1 -0
- package/dist/agentic/registry.js +41 -0
- package/dist/agentic/registry.js.map +1 -0
- package/dist/agentic/tools/lookup-person.js +66 -0
- package/dist/agentic/tools/lookup-person.js.map +1 -0
- package/dist/agentic/tools/lookup-project.js +93 -0
- package/dist/agentic/tools/lookup-project.js.map +1 -0
- package/dist/agentic/tools/route-note.js +45 -0
- package/dist/agentic/tools/route-note.js.map +1 -0
- package/dist/agentic/tools/store-context.js +51 -0
- package/dist/agentic/tools/store-context.js.map +1 -0
- package/dist/agentic/tools/verify-spelling.js +57 -0
- package/dist/agentic/tools/verify-spelling.js.map +1 -0
- package/dist/arguments.js +23 -6
- package/dist/arguments.js.map +1 -1
- package/dist/constants.js +13 -11
- package/dist/constants.js.map +1 -1
- package/dist/context/discovery.js +114 -0
- package/dist/context/discovery.js.map +1 -0
- package/dist/context/index.js +58 -0
- package/dist/context/index.js.map +1 -0
- package/dist/context/storage.js +131 -0
- package/dist/context/storage.js.map +1 -0
- package/dist/interactive/handler.js +223 -0
- package/dist/interactive/handler.js.map +1 -0
- package/dist/interactive/index.js +18 -0
- package/dist/interactive/index.js.map +1 -0
- package/dist/interactive/onboarding.js +28 -0
- package/dist/interactive/onboarding.js.map +1 -0
- package/dist/main.js +0 -0
- package/dist/output/index.js +8 -0
- package/dist/output/index.js.map +1 -0
- package/dist/output/manager.js +105 -0
- package/dist/output/manager.js.map +1 -0
- package/dist/phases/complete.js +107 -0
- package/dist/phases/complete.js.map +1 -0
- package/dist/phases/locate.js +14 -5
- package/dist/phases/locate.js.map +1 -1
- package/dist/pipeline/index.js +8 -0
- package/dist/pipeline/index.js.map +1 -0
- package/dist/pipeline/orchestrator.js +281 -0
- package/dist/pipeline/orchestrator.js.map +1 -0
- package/dist/prompt/instructions/transcribe.md +6 -6
- package/dist/prompt/personas/transcriber.md +5 -5
- package/dist/protokoll.js +38 -5
- package/dist/protokoll.js.map +1 -1
- package/dist/reasoning/client.js +150 -0
- package/dist/reasoning/client.js.map +1 -0
- package/dist/reasoning/index.js +36 -0
- package/dist/reasoning/index.js.map +1 -0
- package/dist/reasoning/strategy.js +60 -0
- package/dist/reasoning/strategy.js.map +1 -0
- package/dist/reflection/collector.js +124 -0
- package/dist/reflection/collector.js.map +1 -0
- package/dist/reflection/index.js +16 -0
- package/dist/reflection/index.js.map +1 -0
- package/dist/reflection/reporter.js +238 -0
- package/dist/reflection/reporter.js.map +1 -0
- package/dist/routing/classifier.js +201 -0
- package/dist/routing/classifier.js.map +1 -0
- package/dist/routing/index.js +27 -0
- package/dist/routing/index.js.map +1 -0
- package/dist/routing/router.js +153 -0
- package/dist/routing/router.js.map +1 -0
- package/dist/transcription/index.js +41 -0
- package/dist/transcription/index.js.map +1 -0
- package/dist/transcription/service.js +64 -0
- package/dist/transcription/service.js.map +1 -0
- package/dist/transcription/types.js +31 -0
- package/dist/transcription/types.js.map +1 -0
- package/dist/util/media.js +4 -4
- package/dist/util/media.js.map +1 -1
- package/dist/util/metadata.js +95 -0
- package/dist/util/metadata.js.map +1 -0
- package/dist/util/storage.js +2 -2
- package/dist/util/storage.js.map +1 -1
- package/docs/examples.md +224 -0
- package/docs/index.html +5 -3
- package/docs/package-lock.json +639 -332
- package/docs/package.json +5 -4
- package/docs/troubleshooting.md +257 -0
- package/docs/vite.config.js +9 -3
- package/eslint.config.mjs +1 -0
- package/guide/architecture.md +217 -0
- package/guide/configuration.md +199 -0
- package/guide/context-system.md +215 -0
- package/guide/development.md +273 -0
- package/guide/index.md +91 -0
- package/guide/interactive.md +199 -0
- package/guide/quickstart.md +138 -0
- package/guide/reasoning.md +193 -0
- package/guide/routing.md +222 -0
- package/package.json +10 -7
- package/tsconfig.tsbuildinfo +1 -1
- package/vitest.config.ts +27 -5
- package/dist/phases/transcribe.js +0 -149
- package/dist/phases/transcribe.js.map +0 -1
- package/dist/processor.js +0 -35
- package/dist/processor.js.map +0 -1
- package/dist/prompt/transcribe.js +0 -41
- package/dist/prompt/transcribe.js.map +0 -1
- package/dist/util/general.js +0 -39
- package/dist/util/general.js.map +0 -1
- package/dist/util/openai.js +0 -92
- package/dist/util/openai.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manager.js","sources":["../../src/output/manager.ts"],"sourcesContent":["/**\n * Output Manager\n *\n * Manages intermediate files and final output destinations.\n * Follows the kodrdriv pattern for debugging and intermediate file management.\n */\n\nimport * as path from 'path';\nimport * as fs from 'fs/promises';\nimport { OutputConfig, IntermediateFiles, OutputPaths } from './types';\nimport * as Logging from '../logging';\nimport * as Metadata from '../util/metadata';\n\nexport interface ManagerInstance {\n createOutputPaths(\n audioFile: string,\n routedDestination: string,\n hash: string,\n date: Date\n ): OutputPaths;\n \n ensureDirectories(paths: OutputPaths): Promise<void>;\n \n writeIntermediate(\n paths: OutputPaths,\n type: keyof IntermediateFiles,\n content: unknown\n ): Promise<string>;\n \n writeTranscript(paths: OutputPaths, content: string, metadata?: Metadata.TranscriptMetadata): Promise<string>;\n \n cleanIntermediates(paths: OutputPaths): Promise<void>;\n}\n\nexport const create = (config: OutputConfig): ManagerInstance => {\n const logger = Logging.getLogger();\n \n const formatTimestamp = (date: Date): string => {\n // Format: YYYY-MM-DD-HHmm (full year, dashes for separation)\n const pad = (n: number) => n.toString().padStart(2, '0');\n const year = date.getFullYear().toString();\n const month = pad(date.getMonth() + 1);\n const day = pad(date.getDate());\n const hours = pad(date.getHours());\n const minutes = pad(date.getMinutes());\n return `${year}-${month}-${day}-${hours}${minutes}`;\n };\n \n const createOutputPaths = (\n _audioFile: string,\n routedDestination: string,\n hash: string,\n date: Date\n ): OutputPaths => {\n const timestamp = formatTimestamp(date);\n const shortHash = hash.slice(0, 6);\n // Hash at the end for easier filename correlation\n const buildFilename = (type: string, ext: string) => `${timestamp}-${type}-${shortHash}${ext}`;\n \n const intermediateDir = config.intermediateDir;\n \n return {\n final: routedDestination,\n intermediate: {\n transcript: path.join(intermediateDir, buildFilename('transcript', '.json')),\n context: path.join(intermediateDir, buildFilename('context', '.json')),\n request: path.join(intermediateDir, buildFilename('request', '.json')),\n response: path.join(intermediateDir, buildFilename('response', '.json')),\n reflection: path.join(intermediateDir, buildFilename('reflection', '.md')),\n session: path.join(intermediateDir, buildFilename('session', '.json')),\n },\n };\n };\n \n const ensureDirectories = async (paths: OutputPaths): Promise<void> => {\n // Ensure intermediate directory\n await fs.mkdir(path.dirname(paths.intermediate.transcript), { recursive: true });\n \n // Ensure final directory\n await fs.mkdir(path.dirname(paths.final), { recursive: true });\n \n logger.debug('Ensured output directories', {\n intermediate: path.dirname(paths.intermediate.transcript),\n final: path.dirname(paths.final),\n });\n };\n \n const writeIntermediate = async (\n paths: OutputPaths,\n type: keyof IntermediateFiles,\n content: unknown\n ): Promise<string> => {\n const filePath = paths.intermediate[type];\n if (!filePath) {\n throw new Error(`Invalid intermediate type: ${type}`);\n }\n \n const contentStr = typeof content === 'string' \n ? content \n : JSON.stringify(content, null, 2);\n \n await fs.writeFile(filePath, contentStr, 'utf-8');\n logger.debug('Wrote intermediate file', { type, path: filePath });\n \n return filePath;\n };\n \n const writeTranscript = async (\n paths: OutputPaths,\n content: string,\n metadata?: Metadata.TranscriptMetadata\n ): Promise<string> => {\n // Prepend metadata if provided\n let finalContent = content;\n if (metadata) {\n const metadataSection = Metadata.formatMetadataMarkdown(metadata);\n finalContent = metadataSection + content;\n }\n \n await fs.writeFile(paths.final, finalContent, 'utf-8');\n logger.info('Wrote final transcript', { path: paths.final });\n return paths.final;\n };\n \n const cleanIntermediates = async (paths: OutputPaths): Promise<void> => {\n if (config.keepIntermediates) {\n logger.debug('Keeping intermediate files');\n return;\n }\n \n for (const [type, filePath] of Object.entries(paths.intermediate)) {\n if (filePath) {\n try {\n await fs.unlink(filePath);\n logger.debug('Removed intermediate file', { type, path: filePath });\n } catch {\n // File might not exist, that's OK\n }\n }\n }\n };\n \n return {\n createOutputPaths,\n ensureDirectories,\n writeIntermediate,\n writeTranscript,\n cleanIntermediates,\n };\n};\n\n"],"names":["create","config","logger","Logging","formatTimestamp","date","pad","n","toString","padStart","year","getFullYear","month","getMonth","day","getDate","hours","getHours","minutes","getMinutes","createOutputPaths","_audioFile","routedDestination","hash","timestamp","shortHash","slice","buildFilename","type","ext","intermediateDir","final","intermediate","transcript","path","join","context","request","response","reflection","session","ensureDirectories","paths","fs","mkdir","dirname","recursive","debug","writeIntermediate","content","filePath","Error","contentStr","JSON","stringify","writeFile","writeTranscript","metadata","finalContent","metadataSection","Metadata","info","cleanIntermediates","keepIntermediates","Object","entries","unlink"],"mappings":"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"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import * as path from 'path';
|
|
2
|
+
import { getLogger } from '../logging.js';
|
|
3
|
+
import { create as create$1 } from '../util/storage.js';
|
|
4
|
+
|
|
5
|
+
const create = (config)=>{
|
|
6
|
+
const logger = getLogger();
|
|
7
|
+
const storage = create$1({
|
|
8
|
+
log: logger.debug
|
|
9
|
+
});
|
|
10
|
+
// Build directory path matching output structure (year/month)
|
|
11
|
+
const buildDirectoryPath = (date)=>{
|
|
12
|
+
const structure = config.outputStructure || 'month';
|
|
13
|
+
const year = date.getFullYear().toString();
|
|
14
|
+
const month = (date.getMonth() + 1).toString();
|
|
15
|
+
const day = date.getDate().toString();
|
|
16
|
+
switch(structure){
|
|
17
|
+
case 'none':
|
|
18
|
+
return config.processedDirectory;
|
|
19
|
+
case 'year':
|
|
20
|
+
return path.join(config.processedDirectory, year);
|
|
21
|
+
case 'month':
|
|
22
|
+
return path.join(config.processedDirectory, year, month);
|
|
23
|
+
case 'day':
|
|
24
|
+
return path.join(config.processedDirectory, year, month, day);
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
// Format date portion of filename based on directory structure
|
|
28
|
+
// Don't repeat info already in the path
|
|
29
|
+
const formatDateForFilename = (date)=>{
|
|
30
|
+
const structure = config.outputStructure || 'month';
|
|
31
|
+
const pad = (n)=>n.toString().padStart(2, '0');
|
|
32
|
+
const year = date.getFullYear().toString();
|
|
33
|
+
const month = pad(date.getMonth() + 1);
|
|
34
|
+
const day = pad(date.getDate());
|
|
35
|
+
const hours = pad(date.getHours());
|
|
36
|
+
const minutes = pad(date.getMinutes());
|
|
37
|
+
switch(structure){
|
|
38
|
+
case 'day':
|
|
39
|
+
// Path has year/month/day - only time in filename
|
|
40
|
+
return `${hours}${minutes}`;
|
|
41
|
+
case 'month':
|
|
42
|
+
// Path has year/month - day and time in filename
|
|
43
|
+
return `${day}-${hours}${minutes}`;
|
|
44
|
+
case 'year':
|
|
45
|
+
// Path has year - month, day and time in filename
|
|
46
|
+
return `${month}-${day}-${hours}${minutes}`;
|
|
47
|
+
case 'none':
|
|
48
|
+
// No date in path - full date in filename (YYYY-MM-DD-HHmm)
|
|
49
|
+
return `${year}-${month}-${day}-${hours}${minutes}`;
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
const complete = async (audioFile, hash, creationTime, subject)=>{
|
|
53
|
+
logger.debug('Completing file processing for %s', audioFile);
|
|
54
|
+
if (config.dryRun) {
|
|
55
|
+
logger.info('Dry run: would move %s to processed directory', audioFile);
|
|
56
|
+
return audioFile;
|
|
57
|
+
}
|
|
58
|
+
if (!config.processedDirectory) {
|
|
59
|
+
logger.debug('No processed directory configured, skipping file move');
|
|
60
|
+
return audioFile;
|
|
61
|
+
}
|
|
62
|
+
// Build the target directory path with year/month structure
|
|
63
|
+
const targetDir = buildDirectoryPath(creationTime);
|
|
64
|
+
// Create the target directory if it doesn't exist
|
|
65
|
+
if (!await storage.exists(targetDir)) {
|
|
66
|
+
logger.debug('Creating processed directory %s', targetDir);
|
|
67
|
+
await storage.createDirectory(targetDir);
|
|
68
|
+
}
|
|
69
|
+
// Get the file extension
|
|
70
|
+
const fileExt = path.extname(audioFile);
|
|
71
|
+
// Format date for filename (adjusted based on directory structure)
|
|
72
|
+
const dateStr = formatDateForFilename(creationTime);
|
|
73
|
+
// Create new filename: <date>-<subject>-<hash>
|
|
74
|
+
// Hash is at the end for easier correlation with output files
|
|
75
|
+
// Clean subject by removing special characters and spaces
|
|
76
|
+
const shortHash = hash.substring(0, 6);
|
|
77
|
+
let newFilename;
|
|
78
|
+
if (subject) {
|
|
79
|
+
const cleanSubject = subject.replace(/[^a-zA-Z0-9]/g, '-').replace(/-+/g, '-').replace(/^-|-$/g, '').toLowerCase().substring(0, 50);
|
|
80
|
+
newFilename = `${dateStr}-${cleanSubject}-${shortHash}${fileExt}`;
|
|
81
|
+
} else {
|
|
82
|
+
newFilename = `${dateStr}-${shortHash}${fileExt}`;
|
|
83
|
+
}
|
|
84
|
+
const newFilePath = path.join(targetDir, newFilename);
|
|
85
|
+
try {
|
|
86
|
+
// Read the original file
|
|
87
|
+
const fileContent = await storage.readFile(audioFile, 'binary');
|
|
88
|
+
// Write to the new location
|
|
89
|
+
logger.debug('Moving file from %s to %s', audioFile, newFilePath);
|
|
90
|
+
await storage.writeFile(newFilePath, fileContent, 'binary');
|
|
91
|
+
// Remove the original file
|
|
92
|
+
await storage.deleteFile(audioFile);
|
|
93
|
+
logger.info('Moved to processed: %s', newFilePath);
|
|
94
|
+
return newFilePath;
|
|
95
|
+
} catch (error) {
|
|
96
|
+
logger.error('Failed to move file to processed directory: %s', error);
|
|
97
|
+
// Don't fail the whole process, just log the error
|
|
98
|
+
return audioFile;
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
return {
|
|
102
|
+
complete
|
|
103
|
+
};
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
export { create };
|
|
107
|
+
//# sourceMappingURL=complete.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"complete.js","sources":["../../src/phases/complete.ts"],"sourcesContent":["/**\n * Complete Phase\n * \n * Handles post-processing completion: moving audio files to the processed directory\n * after successful transcription.\n */\n\nimport * as path from 'path';\nimport * as Logging from '@/logging';\nimport * as Storage from '@/util/storage';\n\nexport type FilesystemStructure = 'none' | 'year' | 'month' | 'day';\n\nexport interface CompleteConfig {\n processedDirectory: string;\n outputStructure?: FilesystemStructure;\n dryRun?: boolean;\n}\n\nexport interface Instance {\n complete(audioFile: string, hash: string, creationTime: Date, subject?: string): Promise<string>;\n}\n\nexport const create = (config: CompleteConfig): Instance => {\n const logger = Logging.getLogger();\n const storage = Storage.create({ log: logger.debug });\n\n // Build directory path matching output structure (year/month)\n const buildDirectoryPath = (date: Date): string => {\n const structure = config.outputStructure || 'month';\n const year = date.getFullYear().toString();\n const month = (date.getMonth() + 1).toString();\n const day = date.getDate().toString();\n\n switch (structure) {\n case 'none':\n return config.processedDirectory;\n case 'year':\n return path.join(config.processedDirectory, year);\n case 'month':\n return path.join(config.processedDirectory, year, month);\n case 'day':\n return path.join(config.processedDirectory, year, month, day);\n }\n };\n\n // Format date portion of filename based on directory structure\n // Don't repeat info already in the path\n const formatDateForFilename = (date: Date): string => {\n const structure = config.outputStructure || 'month';\n const pad = (n: number) => n.toString().padStart(2, '0');\n const year = date.getFullYear().toString();\n const month = pad(date.getMonth() + 1);\n const day = pad(date.getDate());\n const hours = pad(date.getHours());\n const minutes = pad(date.getMinutes());\n\n switch (structure) {\n case 'day':\n // Path has year/month/day - only time in filename\n return `${hours}${minutes}`;\n case 'month':\n // Path has year/month - day and time in filename\n return `${day}-${hours}${minutes}`;\n case 'year':\n // Path has year - month, day and time in filename\n return `${month}-${day}-${hours}${minutes}`;\n case 'none':\n // No date in path - full date in filename (YYYY-MM-DD-HHmm)\n return `${year}-${month}-${day}-${hours}${minutes}`;\n }\n };\n\n const complete = async (\n audioFile: string, \n hash: string, \n creationTime: Date, \n subject?: string\n ): Promise<string> => {\n logger.debug('Completing file processing for %s', audioFile);\n\n if (config.dryRun) {\n logger.info('Dry run: would move %s to processed directory', audioFile);\n return audioFile;\n }\n\n if (!config.processedDirectory) {\n logger.debug('No processed directory configured, skipping file move');\n return audioFile;\n }\n\n // Build the target directory path with year/month structure\n const targetDir = buildDirectoryPath(creationTime);\n\n // Create the target directory if it doesn't exist\n if (!await storage.exists(targetDir)) {\n logger.debug('Creating processed directory %s', targetDir);\n await storage.createDirectory(targetDir);\n }\n\n // Get the file extension\n const fileExt = path.extname(audioFile);\n\n // Format date for filename (adjusted based on directory structure)\n const dateStr = formatDateForFilename(creationTime);\n\n // Create new filename: <date>-<subject>-<hash>\n // Hash is at the end for easier correlation with output files\n // Clean subject by removing special characters and spaces\n const shortHash = hash.substring(0, 6);\n let newFilename: string;\n if (subject) {\n const cleanSubject = subject\n .replace(/[^a-zA-Z0-9]/g, '-')\n .replace(/-+/g, '-')\n .replace(/^-|-$/g, '')\n .toLowerCase()\n .substring(0, 50);\n newFilename = `${dateStr}-${cleanSubject}-${shortHash}${fileExt}`;\n } else {\n newFilename = `${dateStr}-${shortHash}${fileExt}`;\n }\n \n const newFilePath = path.join(targetDir, newFilename);\n\n try {\n // Read the original file\n const fileContent = await storage.readFile(audioFile, 'binary');\n\n // Write to the new location\n logger.debug('Moving file from %s to %s', audioFile, newFilePath);\n await storage.writeFile(newFilePath, fileContent, 'binary');\n\n // Remove the original file\n await storage.deleteFile(audioFile);\n\n logger.info('Moved to processed: %s', newFilePath);\n return newFilePath;\n } catch (error) {\n logger.error('Failed to move file to processed directory: %s', error);\n // Don't fail the whole process, just log the error\n return audioFile;\n }\n };\n\n return {\n complete,\n };\n};\n\n"],"names":["create","config","logger","Logging","storage","Storage","log","debug","buildDirectoryPath","date","structure","outputStructure","year","getFullYear","toString","month","getMonth","day","getDate","processedDirectory","path","join","formatDateForFilename","pad","n","padStart","hours","getHours","minutes","getMinutes","complete","audioFile","hash","creationTime","subject","dryRun","info","targetDir","exists","createDirectory","fileExt","extname","dateStr","shortHash","substring","newFilename","cleanSubject","replace","toLowerCase","newFilePath","fileContent","readFile","writeFile","deleteFile","error"],"mappings":"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"}
|
package/dist/phases/locate.js
CHANGED
|
@@ -2,7 +2,8 @@ import { getLogger } from '../logging.js';
|
|
|
2
2
|
import { create as create$3 } from '../util/media.js';
|
|
3
3
|
import { create as create$1 } from '../util/storage.js';
|
|
4
4
|
import { create as create$2 } from '../util/dates.js';
|
|
5
|
-
import
|
|
5
|
+
import { DEFAULT_INTERMEDIATE_DIRECTORY } from '../constants.js';
|
|
6
|
+
import path__default from 'path';
|
|
6
7
|
|
|
7
8
|
const create = (config, operator)=>{
|
|
8
9
|
const logger = getLogger();
|
|
@@ -31,11 +32,19 @@ const create = (config, operator)=>{
|
|
|
31
32
|
// Calculate the hash of file and output directory
|
|
32
33
|
const hash = (await storage.hashFile(audioFile, 100)).substring(0, 8);
|
|
33
34
|
const outputPath = await operator.constructOutputDirectory(creationTime);
|
|
34
|
-
const contextPath = path.join(outputPath, '.context');
|
|
35
|
-
await storage.createDirectory(contextPath);
|
|
36
|
-
const interimPath = path.join(outputPath, '.interim');
|
|
37
|
-
await storage.createDirectory(interimPath);
|
|
38
35
|
const transcriptionFilename = await operator.constructFilename(creationTime, 'transcription', hash);
|
|
36
|
+
// Use output/protokoll for intermediate files instead of polluting output directory
|
|
37
|
+
// This follows the kodrdriv pattern for debugging and intermediate file management
|
|
38
|
+
const intermediateBase = DEFAULT_INTERMEDIATE_DIRECTORY;
|
|
39
|
+
const shortHash = hash.substring(0, 6);
|
|
40
|
+
const pad = (n)=>n.toString().padStart(2, '0');
|
|
41
|
+
const timestamp = `${creationTime.getFullYear().toString().slice(2)}${pad(creationTime.getMonth() + 1)}${pad(creationTime.getDate())}-${pad(creationTime.getHours())}${pad(creationTime.getMinutes())}`;
|
|
42
|
+
const sessionDir = `${timestamp}-${shortHash}`;
|
|
43
|
+
const interimPath = path__default.join(intermediateBase, sessionDir);
|
|
44
|
+
await storage.createDirectory(interimPath);
|
|
45
|
+
const contextPath = path__default.join(interimPath, 'context');
|
|
46
|
+
await storage.createDirectory(contextPath);
|
|
47
|
+
logger.debug('Intermediate files will be stored in: %s', interimPath);
|
|
39
48
|
return {
|
|
40
49
|
creationTime,
|
|
41
50
|
outputPath,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"locate.js","sources":["../../src/phases/locate.ts"],"sourcesContent":["import * as Logging from '@/logging';\nimport * as Media from '@/util/media';\nimport * as Storage from '@/util/storage';\nimport * as Dreadcabinet from '@theunwalked/dreadcabinet';\nimport * as Dates from '@/util/dates';\nimport { Config } from '@/protokoll';\nimport path from 'path';\n\n// Helper function to promisify ffmpeg.\n\nexport interface Instance {\n locate: (audioFile: string) => Promise<{\n creationTime: Date;\n outputPath: string;\n contextPath: string;\n interimPath: string;\n transcriptionFilename: string;\n hash: string;\n audioFile: string;\n }>;\n}\n\nexport const create = (config: Config, operator: Dreadcabinet.Operator): Instance => {\n const logger = Logging.getLogger();\n const storage = Storage.create({ log: logger.debug });\n const dates = Dates.create({ timezone: config.timezone });\n const media = Media.create(logger);\n\n const locate = async (audioFile: string): Promise<{\n creationTime: Date;\n outputPath: string;\n contextPath: string;\n interimPath: string;\n transcriptionFilename: string;\n hash: string;\n audioFile: string;\n }> => {\n logger.debug('Processing file %s', audioFile);\n\n // Extract audio file creation time\n let creationTime = await media.getAudioCreationTime(audioFile);\n try {\n if (creationTime) {\n logger.info('Audio recording time: %s', creationTime.toISOString());\n } else {\n logger.warn('Could not determine audio recording time for %s, using current date', audioFile);\n creationTime = dates.now();\n }\n } catch (error: any) {\n logger.error('Error determining audio recording time for %s: %s, using current date', audioFile, error.message);\n creationTime = dates.now();\n }\n\n // Calculate the hash of file and output directory\n const hash = (await storage.hashFile(audioFile, 100)).substring(0, 8);\n const outputPath: string = await operator.constructOutputDirectory(creationTime);\n const
|
|
1
|
+
{"version":3,"file":"locate.js","sources":["../../src/phases/locate.ts"],"sourcesContent":["import * as Logging from '@/logging';\nimport * as Media from '@/util/media';\nimport * as Storage from '@/util/storage';\nimport * as Dreadcabinet from '@theunwalked/dreadcabinet';\nimport * as Dates from '@/util/dates';\nimport { Config } from '@/protokoll';\nimport { DEFAULT_INTERMEDIATE_DIRECTORY } from '@/constants';\nimport path from 'path';\n\n// Helper function to promisify ffmpeg.\n\nexport interface Instance {\n locate: (audioFile: string) => Promise<{\n creationTime: Date;\n outputPath: string;\n contextPath: string;\n interimPath: string;\n transcriptionFilename: string;\n hash: string;\n audioFile: string;\n }>;\n}\n\nexport const create = (config: Config, operator: Dreadcabinet.Operator): Instance => {\n const logger = Logging.getLogger();\n const storage = Storage.create({ log: logger.debug });\n const dates = Dates.create({ timezone: config.timezone });\n const media = Media.create(logger);\n\n const locate = async (audioFile: string): Promise<{\n creationTime: Date;\n outputPath: string;\n contextPath: string;\n interimPath: string;\n transcriptionFilename: string;\n hash: string;\n audioFile: string;\n }> => {\n logger.debug('Processing file %s', audioFile);\n\n // Extract audio file creation time\n let creationTime = await media.getAudioCreationTime(audioFile);\n try {\n if (creationTime) {\n logger.info('Audio recording time: %s', creationTime.toISOString());\n } else {\n logger.warn('Could not determine audio recording time for %s, using current date', audioFile);\n creationTime = dates.now();\n }\n } catch (error: any) {\n logger.error('Error determining audio recording time for %s: %s, using current date', audioFile, error.message);\n creationTime = dates.now();\n }\n\n // Calculate the hash of file and output directory\n const hash = (await storage.hashFile(audioFile, 100)).substring(0, 8);\n const outputPath: string = await operator.constructOutputDirectory(creationTime);\n const transcriptionFilename = await operator.constructFilename(creationTime, 'transcription', hash);\n \n // Use output/protokoll for intermediate files instead of polluting output directory\n // This follows the kodrdriv pattern for debugging and intermediate file management\n const intermediateBase = DEFAULT_INTERMEDIATE_DIRECTORY;\n const shortHash = hash.substring(0, 6);\n const pad = (n: number) => n.toString().padStart(2, '0');\n const timestamp = `${creationTime.getFullYear().toString().slice(2)}${pad(creationTime.getMonth() + 1)}${pad(creationTime.getDate())}-${pad(creationTime.getHours())}${pad(creationTime.getMinutes())}`;\n const sessionDir = `${timestamp}-${shortHash}`;\n \n const interimPath: string = path.join(intermediateBase, sessionDir);\n await storage.createDirectory(interimPath);\n \n const contextPath: string = path.join(interimPath, 'context');\n await storage.createDirectory(contextPath);\n \n logger.debug('Intermediate files will be stored in: %s', interimPath);\n\n return {\n creationTime,\n outputPath,\n contextPath,\n interimPath,\n transcriptionFilename,\n hash,\n audioFile,\n };\n }\n\n return {\n locate,\n }\n}\n\n\n"],"names":["create","config","operator","logger","Logging","storage","Storage","log","debug","dates","Dates","timezone","media","Media","locate","audioFile","creationTime","getAudioCreationTime","info","toISOString","warn","now","error","message","hash","hashFile","substring","outputPath","constructOutputDirectory","transcriptionFilename","constructFilename","intermediateBase","DEFAULT_INTERMEDIATE_DIRECTORY","shortHash","pad","n","toString","padStart","timestamp","getFullYear","slice","getMonth","getDate","getHours","getMinutes","sessionDir","interimPath","path","join","createDirectory","contextPath"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../src/pipeline/index.ts"],"sourcesContent":["/**\n * Pipeline Integration\n *\n * Main entry point for the intelligent transcription pipeline.\n * Brings together all modules into a unified processing flow.\n * \n * THIS IS THE MAIN ENTRY POINT - USE Pipeline.create() IN protokoll.ts\n */\n\nimport { PipelineInput, PipelineResult } from './types';\nimport * as Orchestrator from './orchestrator';\n\nexport interface PipelineInstance {\n process(input: PipelineInput): Promise<PipelineResult>;\n}\n\nexport type { OrchestratorConfig } from './orchestrator';\n\nexport const create = async (config: Orchestrator.OrchestratorConfig): Promise<PipelineInstance> => {\n return Orchestrator.create(config);\n};\n\nexport const DEFAULT_PIPELINE_CONFIG: Partial<Orchestrator.OrchestratorConfig> = {\n model: 'gpt-5.2',\n transcriptionModel: 'whisper-1',\n interactive: false,\n selfReflection: true,\n debug: false,\n intermediateDir: './output/protokoll',\n keepIntermediates: true,\n outputDirectory: './output',\n outputStructure: 'month',\n outputFilenameOptions: ['date', 'time', 'subject'],\n maxAudioSize: 25 * 1024 * 1024,\n tempDirectory: '/tmp',\n};\n\n// Re-export types\nexport * from './types';\n\n"],"names":["create","config","Orchestrator"],"mappings":";;AAkBO,MAAMA,SAAS,OAAOC,MAAAA,GAAAA;IACzB,OAAOC,QAAmB,CAACD,MAAAA,CAAAA;AAC/B;;;;"}
|
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
import { create as create$1 } from '../context/index.js';
|
|
2
|
+
import { create as create$2 } from '../routing/index.js';
|
|
3
|
+
import { create as create$6 } from '../interactive/index.js';
|
|
4
|
+
import { create as create$7 } from '../output/index.js';
|
|
5
|
+
import { create as create$5 } from '../reflection/index.js';
|
|
6
|
+
import { create as create$3 } from '../transcription/index.js';
|
|
7
|
+
import { create as create$9 } from '../reasoning/index.js';
|
|
8
|
+
import { create as create$8 } from '../agentic/index.js';
|
|
9
|
+
import { create as create$4 } from '../phases/complete.js';
|
|
10
|
+
import { getLogger } from '../logging.js';
|
|
11
|
+
import { extractTagsFromSignals, createRoutingMetadata } from '../util/metadata.js';
|
|
12
|
+
|
|
13
|
+
const create = async (config)=>{
|
|
14
|
+
var _config_keepIntermediates;
|
|
15
|
+
const logger = getLogger();
|
|
16
|
+
const currentWorkingDir = globalThis.process.cwd();
|
|
17
|
+
logger.debug('Initializing intelligent transcription pipeline...');
|
|
18
|
+
// Initialize context system (async)
|
|
19
|
+
const context = await create$1({
|
|
20
|
+
startingDir: config.contextDirectory || currentWorkingDir
|
|
21
|
+
});
|
|
22
|
+
logger.debug('Context system initialized - ready to query entities via tools');
|
|
23
|
+
// Initialize routing with config-based defaults
|
|
24
|
+
const routingConfig = {
|
|
25
|
+
default: {
|
|
26
|
+
path: config.outputDirectory || '~/notes',
|
|
27
|
+
structure: config.outputStructure || 'month',
|
|
28
|
+
filename_options: config.outputFilenameOptions || [
|
|
29
|
+
'date',
|
|
30
|
+
'time',
|
|
31
|
+
'subject'
|
|
32
|
+
],
|
|
33
|
+
createDirectories: true
|
|
34
|
+
},
|
|
35
|
+
projects: [],
|
|
36
|
+
conflict_resolution: 'primary'
|
|
37
|
+
};
|
|
38
|
+
const routing = create$2(routingConfig, context);
|
|
39
|
+
logger.debug('Routing system initialized');
|
|
40
|
+
const interactive = create$6({
|
|
41
|
+
enabled: config.interactive}, context);
|
|
42
|
+
const output = create$7({
|
|
43
|
+
intermediateDir: config.intermediateDir || './output/protokoll',
|
|
44
|
+
keepIntermediates: (_config_keepIntermediates = config.keepIntermediates) !== null && _config_keepIntermediates !== void 0 ? _config_keepIntermediates : true});
|
|
45
|
+
logger.debug('Output manager initialized');
|
|
46
|
+
const reflection = config.selfReflection ? create$5() : null;
|
|
47
|
+
if (reflection) {
|
|
48
|
+
logger.debug('Self-reflection system enabled');
|
|
49
|
+
}
|
|
50
|
+
// Initialize transcription service
|
|
51
|
+
const transcription = create$3({
|
|
52
|
+
defaultModel: config.transcriptionModel
|
|
53
|
+
});
|
|
54
|
+
logger.debug('Transcription service initialized with model: %s', config.transcriptionModel);
|
|
55
|
+
// Initialize reasoning for agentic processing
|
|
56
|
+
const reasoning = create$9({
|
|
57
|
+
model: config.model
|
|
58
|
+
});
|
|
59
|
+
logger.debug('Reasoning system initialized with model: %s', config.model);
|
|
60
|
+
// Initialize complete phase for moving files to processed directory
|
|
61
|
+
// Pass outputStructure so processed files use the same directory structure as output
|
|
62
|
+
const complete = config.processedDirectory ? create$4({
|
|
63
|
+
processedDirectory: config.processedDirectory,
|
|
64
|
+
outputStructure: config.outputStructure,
|
|
65
|
+
dryRun: config.dryRun
|
|
66
|
+
}) : null;
|
|
67
|
+
if (complete) {
|
|
68
|
+
logger.debug('Complete phase initialized with processed directory: %s', config.processedDirectory);
|
|
69
|
+
}
|
|
70
|
+
// Helper to extract a human-readable title from the output path
|
|
71
|
+
const extractTitleFromPath = (outputPath)=>{
|
|
72
|
+
var _outputPath_split_pop;
|
|
73
|
+
const filename = (_outputPath_split_pop = outputPath.split('/').pop()) === null || _outputPath_split_pop === void 0 ? void 0 : _outputPath_split_pop.replace('.md', '');
|
|
74
|
+
if (!filename) return undefined;
|
|
75
|
+
// Remove date prefix (e.g., "27-0716-" from "27-0716-wagner-webhooks")
|
|
76
|
+
const withoutDate = filename.replace(/^\d{2}-\d{4}-/, '');
|
|
77
|
+
if (!withoutDate) return undefined;
|
|
78
|
+
// Convert kebab-case to Title Case
|
|
79
|
+
return withoutDate.split('-').map((word)=>word.charAt(0).toUpperCase() + word.slice(1)).join(' ');
|
|
80
|
+
};
|
|
81
|
+
const processInput = async (input)=>{
|
|
82
|
+
const startTime = Date.now();
|
|
83
|
+
logger.info('Processing: %s (hash: %s)', input.audioFile, input.hash);
|
|
84
|
+
// Initialize state
|
|
85
|
+
const state = {
|
|
86
|
+
input,
|
|
87
|
+
startTime: new Date()
|
|
88
|
+
};
|
|
89
|
+
// Start reflection collection if enabled
|
|
90
|
+
if (reflection) {
|
|
91
|
+
reflection.collector.start();
|
|
92
|
+
}
|
|
93
|
+
// Start interactive session if enabled
|
|
94
|
+
if (config.interactive) {
|
|
95
|
+
interactive.startSession();
|
|
96
|
+
logger.debug('Interactive session started');
|
|
97
|
+
}
|
|
98
|
+
try {
|
|
99
|
+
// Step 1: Check onboarding needs
|
|
100
|
+
logger.debug('Checking onboarding state...');
|
|
101
|
+
const onboardingState = interactive.checkNeedsOnboarding();
|
|
102
|
+
if (onboardingState.needsOnboarding) {
|
|
103
|
+
logger.debug('First-run detected - onboarding may be triggered');
|
|
104
|
+
}
|
|
105
|
+
// Step 2: Raw transcription using Transcription module
|
|
106
|
+
logger.info('Transcribing audio...');
|
|
107
|
+
const whisperStart = Date.now();
|
|
108
|
+
const transcriptionResult = await transcription.transcribe(input.audioFile, {
|
|
109
|
+
model: config.transcriptionModel
|
|
110
|
+
});
|
|
111
|
+
state.rawTranscript = transcriptionResult.text;
|
|
112
|
+
const whisperDuration = Date.now() - whisperStart;
|
|
113
|
+
logger.info('Transcription: %d chars in %.1fs', state.rawTranscript.length, whisperDuration / 1000);
|
|
114
|
+
if (reflection) {
|
|
115
|
+
reflection.collector.recordWhisper(whisperDuration);
|
|
116
|
+
}
|
|
117
|
+
// Step 3: Route detection
|
|
118
|
+
logger.debug('Determining routing destination...');
|
|
119
|
+
const routingContext = {
|
|
120
|
+
transcriptText: state.rawTranscript || '',
|
|
121
|
+
audioDate: input.creation,
|
|
122
|
+
sourceFile: input.audioFile,
|
|
123
|
+
hash: input.hash
|
|
124
|
+
};
|
|
125
|
+
const routeResult = routing.route(routingContext);
|
|
126
|
+
logger.debug('Routing decision: project=%s, confidence=%.2f', routeResult.projectId || 'default', routeResult.confidence);
|
|
127
|
+
// Record routing decision in reflection
|
|
128
|
+
if (reflection) {
|
|
129
|
+
var _routeResult_alternateMatches;
|
|
130
|
+
reflection.collector.recordRoutingDecision({
|
|
131
|
+
projectId: routeResult.projectId,
|
|
132
|
+
destination: routeResult.destination.path,
|
|
133
|
+
confidence: routeResult.confidence,
|
|
134
|
+
reasoning: routeResult.reasoning,
|
|
135
|
+
signals: routeResult.signals.map((s)=>({
|
|
136
|
+
type: s.type,
|
|
137
|
+
value: s.value,
|
|
138
|
+
weight: s.weight
|
|
139
|
+
})),
|
|
140
|
+
alternativesConsidered: (_routeResult_alternateMatches = routeResult.alternateMatches) === null || _routeResult_alternateMatches === void 0 ? void 0 : _routeResult_alternateMatches.map((alt)=>({
|
|
141
|
+
projectId: alt.projectId,
|
|
142
|
+
confidence: alt.confidence,
|
|
143
|
+
whyNotChosen: `Lower confidence (${(alt.confidence * 100).toFixed(1)}%)`
|
|
144
|
+
}))
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
// Build output path
|
|
148
|
+
const outputPath = routing.buildOutputPath(routeResult, routingContext);
|
|
149
|
+
logger.debug('Output path: %s', outputPath);
|
|
150
|
+
// Step 4: Create output paths using Output module
|
|
151
|
+
logger.debug('Setting up output directories...');
|
|
152
|
+
const paths = output.createOutputPaths(input.audioFile, outputPath, input.hash, input.creation);
|
|
153
|
+
await output.ensureDirectories(paths);
|
|
154
|
+
// Write raw transcript to intermediate
|
|
155
|
+
await output.writeIntermediate(paths, 'transcript', {
|
|
156
|
+
text: state.rawTranscript,
|
|
157
|
+
model: config.transcriptionModel,
|
|
158
|
+
duration: whisperDuration
|
|
159
|
+
});
|
|
160
|
+
// Step 5: Agentic enhancement using real executor
|
|
161
|
+
logger.info('Enhancing with %s...', config.model);
|
|
162
|
+
const agenticStart = Date.now();
|
|
163
|
+
const toolContext = {
|
|
164
|
+
transcriptText: state.rawTranscript || '',
|
|
165
|
+
audioDate: input.creation,
|
|
166
|
+
sourceFile: input.audioFile,
|
|
167
|
+
contextInstance: context,
|
|
168
|
+
routingInstance: routing,
|
|
169
|
+
interactiveMode: config.interactive,
|
|
170
|
+
interactiveInstance: config.interactive ? interactive : undefined
|
|
171
|
+
};
|
|
172
|
+
const executor = create$8(reasoning, toolContext);
|
|
173
|
+
const agenticResult = await executor.process(state.rawTranscript || '');
|
|
174
|
+
state.enhancedText = agenticResult.enhancedText;
|
|
175
|
+
const toolsUsed = agenticResult.toolsUsed;
|
|
176
|
+
const agenticDuration = Date.now() - agenticStart;
|
|
177
|
+
// Record tool calls in reflection
|
|
178
|
+
if (reflection) {
|
|
179
|
+
for (const tool of toolsUsed){
|
|
180
|
+
reflection.collector.recordToolCall(tool, agenticDuration / toolsUsed.length, true);
|
|
181
|
+
}
|
|
182
|
+
reflection.collector.recordCorrection(state.rawTranscript || '', state.enhancedText);
|
|
183
|
+
// Record token usage from agentic result
|
|
184
|
+
if (agenticResult.totalTokens) {
|
|
185
|
+
reflection.collector.recordModelResponse(config.model, agenticResult.totalTokens);
|
|
186
|
+
}
|
|
187
|
+
// Record context changes (new projects, entities created)
|
|
188
|
+
if (agenticResult.contextChanges) {
|
|
189
|
+
for (const change of agenticResult.contextChanges){
|
|
190
|
+
reflection.collector.recordContextChange(change);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
// Write agentic session to intermediate
|
|
195
|
+
await output.writeIntermediate(paths, 'session', {
|
|
196
|
+
iterations: agenticResult.iterations,
|
|
197
|
+
toolsUsed: agenticResult.toolsUsed,
|
|
198
|
+
state: agenticResult.state
|
|
199
|
+
});
|
|
200
|
+
// Step 6: Write final output using Output module with metadata
|
|
201
|
+
logger.debug('Writing final transcript...');
|
|
202
|
+
if (state.enhancedText) {
|
|
203
|
+
// Build metadata from routing decision and input
|
|
204
|
+
const transcriptMetadata = {
|
|
205
|
+
title: extractTitleFromPath(paths.final),
|
|
206
|
+
projectId: routeResult.projectId || undefined,
|
|
207
|
+
project: routeResult.projectId || undefined,
|
|
208
|
+
date: input.creation,
|
|
209
|
+
routing: createRoutingMetadata(routeResult),
|
|
210
|
+
tags: extractTagsFromSignals(routeResult.signals),
|
|
211
|
+
confidence: routeResult.confidence
|
|
212
|
+
};
|
|
213
|
+
await output.writeTranscript(paths, state.enhancedText, transcriptMetadata);
|
|
214
|
+
}
|
|
215
|
+
// Step 7: Generate reflection report
|
|
216
|
+
logger.debug('Generating reflection report...');
|
|
217
|
+
let reflectionReport;
|
|
218
|
+
if (reflection) {
|
|
219
|
+
reflectionReport = reflection.generate(input.audioFile, paths.final, undefined, state.enhancedText);
|
|
220
|
+
if (paths.intermediate.reflection) {
|
|
221
|
+
await reflection.save(reflectionReport, paths.intermediate.reflection);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
// Step 8: End interactive session
|
|
225
|
+
logger.debug('Finalizing session...');
|
|
226
|
+
let session;
|
|
227
|
+
if (config.interactive) {
|
|
228
|
+
session = interactive.endSession();
|
|
229
|
+
logger.debug('Interactive session ended: %d clarifications', session.responses.length);
|
|
230
|
+
// Save session if path available
|
|
231
|
+
if (paths.intermediate.session) {
|
|
232
|
+
await output.writeIntermediate(paths, 'session', session);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
// Step 9: Cleanup if needed
|
|
236
|
+
if (!config.keepIntermediates && !config.debug) {
|
|
237
|
+
await output.cleanIntermediates(paths);
|
|
238
|
+
}
|
|
239
|
+
// Step 10: Move audio file to processed directory
|
|
240
|
+
let processedAudioPath;
|
|
241
|
+
if (complete) {
|
|
242
|
+
var _paths_final_split_pop;
|
|
243
|
+
// Extract subject from output path for naming
|
|
244
|
+
const subject = ((_paths_final_split_pop = paths.final.split('/').pop()) === null || _paths_final_split_pop === void 0 ? void 0 : _paths_final_split_pop.replace('.md', '')) || undefined;
|
|
245
|
+
processedAudioPath = await complete.complete(input.audioFile, input.hash, input.creation, subject);
|
|
246
|
+
}
|
|
247
|
+
const processingTime = Date.now() - startTime;
|
|
248
|
+
// Compact summary output
|
|
249
|
+
logger.info('Enhancement: %d iterations, %d tools, %.1fs', agenticResult.iterations, toolsUsed.length, agenticDuration / 1000);
|
|
250
|
+
if (agenticResult.totalTokens) {
|
|
251
|
+
logger.info('Tokens: %d total', agenticResult.totalTokens);
|
|
252
|
+
}
|
|
253
|
+
logger.info('Output: %s (%.1fs total)', paths.final, processingTime / 1000);
|
|
254
|
+
return {
|
|
255
|
+
outputPath: paths.final,
|
|
256
|
+
enhancedText: state.enhancedText || '',
|
|
257
|
+
rawTranscript: state.rawTranscript || '',
|
|
258
|
+
routedProject: routeResult.projectId,
|
|
259
|
+
routingConfidence: routeResult.confidence,
|
|
260
|
+
processingTime,
|
|
261
|
+
toolsUsed,
|
|
262
|
+
correctionsApplied: agenticResult.state.resolvedEntities.size,
|
|
263
|
+
processedAudioPath,
|
|
264
|
+
reflection: reflectionReport,
|
|
265
|
+
session,
|
|
266
|
+
intermediatePaths: paths
|
|
267
|
+
};
|
|
268
|
+
} catch (error) {
|
|
269
|
+
logger.error('Pipeline error', {
|
|
270
|
+
error
|
|
271
|
+
});
|
|
272
|
+
throw error;
|
|
273
|
+
}
|
|
274
|
+
};
|
|
275
|
+
return {
|
|
276
|
+
process: processInput
|
|
277
|
+
};
|
|
278
|
+
};
|
|
279
|
+
|
|
280
|
+
export { create };
|
|
281
|
+
//# sourceMappingURL=orchestrator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"orchestrator.js","sources":["../../src/pipeline/orchestrator.ts"],"sourcesContent":["/**\n * Pipeline Orchestrator\n *\n * Orchestrates the intelligent transcription pipeline, coordinating\n * all the modules: context, routing, transcription, reasoning,\n * agentic tools, interactive mode, output management, and reflection.\n * \n * THIS IS THE MAIN PROCESSING FLOW - NOT DEAD CODE!\n */\n\nimport { PipelineConfig, PipelineInput, PipelineResult, PipelineState } from './types';\nimport * as Context from '../context';\nimport * as Routing from '../routing';\nimport * as Interactive from '../interactive';\nimport * as Output from '../output';\nimport * as Reflection from '../reflection';\nimport * as Transcription from '../transcription';\nimport * as Reasoning from '../reasoning';\nimport * as Agentic from '../agentic';\nimport * as CompletePhase from '../phases/complete';\nimport * as Logging from '../logging';\nimport * as Metadata from '../util/metadata';\n\nexport interface OrchestratorInstance {\n process(input: PipelineInput): Promise<PipelineResult>;\n}\n\nexport interface OrchestratorConfig extends PipelineConfig {\n outputDirectory: string;\n outputStructure: string;\n outputFilenameOptions: string[];\n maxAudioSize: number;\n tempDirectory: string;\n}\n\nexport const create = async (config: OrchestratorConfig): Promise<OrchestratorInstance> => {\n const logger = Logging.getLogger();\n const currentWorkingDir = globalThis.process.cwd();\n \n logger.debug('Initializing intelligent transcription pipeline...');\n \n // Initialize context system (async)\n const context = await Context.create({\n startingDir: config.contextDirectory || currentWorkingDir,\n });\n logger.debug('Context system initialized - ready to query entities via tools');\n \n // Initialize routing with config-based defaults\n const routingConfig: Routing.RoutingConfig = {\n default: {\n path: config.outputDirectory || '~/notes',\n structure: (config.outputStructure || 'month') as Routing.FilesystemStructure,\n filename_options: (config.outputFilenameOptions || ['date', 'time', 'subject']) as Routing.FilenameOption[],\n createDirectories: true,\n },\n projects: [],\n conflict_resolution: 'primary',\n };\n \n const routing = Routing.create(routingConfig, context);\n logger.debug('Routing system initialized');\n \n const interactive = Interactive.create(\n { enabled: config.interactive, defaultToSuggestion: true },\n context\n );\n \n const output = Output.create({\n intermediateDir: config.intermediateDir || './output/protokoll',\n keepIntermediates: config.keepIntermediates ?? true,\n timestampFormat: 'YYMMDD-HHmm',\n });\n logger.debug('Output manager initialized');\n \n const reflection = config.selfReflection \n ? Reflection.create({\n enabled: true,\n format: 'markdown',\n includeConversation: false,\n includeOutput: true,\n })\n : null;\n if (reflection) {\n logger.debug('Self-reflection system enabled');\n }\n \n // Initialize transcription service\n const transcription = Transcription.create({\n defaultModel: config.transcriptionModel as Transcription.TranscriptionModel,\n });\n logger.debug('Transcription service initialized with model: %s', config.transcriptionModel);\n \n // Initialize reasoning for agentic processing\n const reasoning = Reasoning.create({ model: config.model });\n logger.debug('Reasoning system initialized with model: %s', config.model);\n\n // Initialize complete phase for moving files to processed directory\n // Pass outputStructure so processed files use the same directory structure as output\n const complete = config.processedDirectory \n ? CompletePhase.create({\n processedDirectory: config.processedDirectory,\n outputStructure: config.outputStructure as CompletePhase.FilesystemStructure,\n dryRun: config.dryRun,\n })\n : null;\n if (complete) {\n logger.debug('Complete phase initialized with processed directory: %s', config.processedDirectory);\n }\n \n // Helper to extract a human-readable title from the output path\n const extractTitleFromPath = (outputPath: string): string | undefined => {\n const filename = outputPath.split('/').pop()?.replace('.md', '');\n if (!filename) return undefined;\n \n // Remove date prefix (e.g., \"27-0716-\" from \"27-0716-wagner-webhooks\")\n const withoutDate = filename.replace(/^\\d{2}-\\d{4}-/, '');\n if (!withoutDate) return undefined;\n \n // Convert kebab-case to Title Case\n return withoutDate\n .split('-')\n .map(word => word.charAt(0).toUpperCase() + word.slice(1))\n .join(' ');\n };\n\n const processInput = async (input: PipelineInput): Promise<PipelineResult> => {\n const startTime = Date.now();\n \n logger.info('Processing: %s (hash: %s)', input.audioFile, input.hash);\n \n // Initialize state\n const state: PipelineState = {\n input,\n startTime: new Date(),\n };\n \n // Start reflection collection if enabled\n if (reflection) {\n reflection.collector.start();\n }\n \n // Start interactive session if enabled\n if (config.interactive) {\n interactive.startSession();\n logger.debug('Interactive session started');\n }\n \n try {\n // Step 1: Check onboarding needs\n logger.debug('Checking onboarding state...');\n const onboardingState = interactive.checkNeedsOnboarding();\n if (onboardingState.needsOnboarding) {\n logger.debug('First-run detected - onboarding may be triggered');\n }\n \n // Step 2: Raw transcription using Transcription module\n logger.info('Transcribing audio...');\n const whisperStart = Date.now();\n \n const transcriptionResult = await transcription.transcribe(input.audioFile, {\n model: config.transcriptionModel as Transcription.TranscriptionModel,\n });\n state.rawTranscript = transcriptionResult.text;\n \n const whisperDuration = Date.now() - whisperStart;\n logger.info('Transcription: %d chars in %.1fs', \n state.rawTranscript.length, whisperDuration / 1000);\n \n if (reflection) {\n reflection.collector.recordWhisper(whisperDuration);\n }\n \n // Step 3: Route detection\n logger.debug('Determining routing destination...');\n const routingContext: Routing.RoutingContext = {\n transcriptText: state.rawTranscript || '',\n audioDate: input.creation,\n sourceFile: input.audioFile,\n hash: input.hash,\n };\n \n const routeResult = routing.route(routingContext);\n \n logger.debug('Routing decision: project=%s, confidence=%.2f', \n routeResult.projectId || 'default', routeResult.confidence);\n \n // Record routing decision in reflection\n if (reflection) {\n reflection.collector.recordRoutingDecision({\n projectId: routeResult.projectId,\n destination: routeResult.destination.path,\n confidence: routeResult.confidence,\n reasoning: routeResult.reasoning,\n signals: routeResult.signals.map(s => ({\n type: s.type,\n value: s.value,\n weight: s.weight,\n })),\n alternativesConsidered: routeResult.alternateMatches?.map(alt => ({\n projectId: alt.projectId,\n confidence: alt.confidence,\n whyNotChosen: `Lower confidence (${(alt.confidence * 100).toFixed(1)}%)`,\n })),\n });\n }\n \n // Build output path\n const outputPath = routing.buildOutputPath(routeResult, routingContext);\n logger.debug('Output path: %s', outputPath);\n \n // Step 4: Create output paths using Output module\n logger.debug('Setting up output directories...');\n const paths = output.createOutputPaths(\n input.audioFile,\n outputPath,\n input.hash,\n input.creation\n );\n \n await output.ensureDirectories(paths);\n \n // Write raw transcript to intermediate\n await output.writeIntermediate(paths, 'transcript', {\n text: state.rawTranscript,\n model: config.transcriptionModel,\n duration: whisperDuration,\n });\n \n // Step 5: Agentic enhancement using real executor\n logger.info('Enhancing with %s...', config.model);\n \n const agenticStart = Date.now();\n const toolContext: Agentic.ToolContext = {\n transcriptText: state.rawTranscript || '',\n audioDate: input.creation,\n sourceFile: input.audioFile,\n contextInstance: context,\n routingInstance: routing,\n interactiveMode: config.interactive,\n interactiveInstance: config.interactive ? interactive : undefined,\n };\n \n const executor = Agentic.create(reasoning, toolContext);\n const agenticResult = await executor.process(state.rawTranscript || '');\n \n state.enhancedText = agenticResult.enhancedText;\n const toolsUsed = agenticResult.toolsUsed;\n const agenticDuration = Date.now() - agenticStart;\n \n // Record tool calls in reflection\n if (reflection) {\n for (const tool of toolsUsed) {\n reflection.collector.recordToolCall(tool, agenticDuration / toolsUsed.length, true);\n }\n reflection.collector.recordCorrection(state.rawTranscript || '', state.enhancedText);\n // Record token usage from agentic result\n if (agenticResult.totalTokens) {\n reflection.collector.recordModelResponse(config.model, agenticResult.totalTokens);\n }\n // Record context changes (new projects, entities created)\n if (agenticResult.contextChanges) {\n for (const change of agenticResult.contextChanges) {\n reflection.collector.recordContextChange(change);\n }\n }\n }\n \n // Write agentic session to intermediate\n await output.writeIntermediate(paths, 'session', {\n iterations: agenticResult.iterations,\n toolsUsed: agenticResult.toolsUsed,\n state: agenticResult.state,\n });\n \n // Step 6: Write final output using Output module with metadata\n logger.debug('Writing final transcript...');\n if (state.enhancedText) {\n // Build metadata from routing decision and input\n const transcriptMetadata: Metadata.TranscriptMetadata = {\n title: extractTitleFromPath(paths.final),\n projectId: routeResult.projectId || undefined,\n project: routeResult.projectId || undefined,\n date: input.creation,\n routing: Metadata.createRoutingMetadata(routeResult),\n tags: Metadata.extractTagsFromSignals(routeResult.signals),\n confidence: routeResult.confidence,\n };\n \n await output.writeTranscript(paths, state.enhancedText, transcriptMetadata);\n }\n \n // Step 7: Generate reflection report\n logger.debug('Generating reflection report...');\n let reflectionReport: Reflection.ReflectionReport | undefined;\n if (reflection) {\n reflectionReport = reflection.generate(\n input.audioFile,\n paths.final,\n undefined,\n state.enhancedText\n );\n \n if (paths.intermediate.reflection) {\n await reflection.save(reflectionReport, paths.intermediate.reflection);\n }\n }\n \n // Step 8: End interactive session\n logger.debug('Finalizing session...');\n let session: Interactive.InteractiveSession | undefined;\n if (config.interactive) {\n session = interactive.endSession();\n logger.debug('Interactive session ended: %d clarifications', session.responses.length);\n \n // Save session if path available\n if (paths.intermediate.session) {\n await output.writeIntermediate(paths, 'session', session);\n }\n }\n \n // Step 9: Cleanup if needed\n if (!config.keepIntermediates && !config.debug) {\n await output.cleanIntermediates(paths);\n }\n\n // Step 10: Move audio file to processed directory\n let processedAudioPath: string | undefined;\n if (complete) {\n // Extract subject from output path for naming\n const subject = paths.final.split('/').pop()?.replace('.md', '') || undefined;\n processedAudioPath = await complete.complete(\n input.audioFile, \n input.hash, \n input.creation,\n subject\n );\n }\n \n const processingTime = Date.now() - startTime;\n \n // Compact summary output\n logger.info('Enhancement: %d iterations, %d tools, %.1fs', \n agenticResult.iterations, toolsUsed.length, agenticDuration / 1000);\n if (agenticResult.totalTokens) {\n logger.info('Tokens: %d total', agenticResult.totalTokens);\n }\n logger.info('Output: %s (%.1fs total)', paths.final, processingTime / 1000);\n \n return {\n outputPath: paths.final,\n enhancedText: state.enhancedText || '',\n rawTranscript: state.rawTranscript || '',\n routedProject: routeResult.projectId,\n routingConfidence: routeResult.confidence,\n processingTime,\n toolsUsed,\n correctionsApplied: agenticResult.state.resolvedEntities.size,\n processedAudioPath,\n reflection: reflectionReport,\n session,\n intermediatePaths: paths,\n };\n \n } catch (error) {\n logger.error('Pipeline error', { error });\n throw error;\n }\n };\n \n return { process: processInput };\n};\n"],"names":["create","config","logger","Logging","currentWorkingDir","globalThis","process","cwd","debug","context","Context","startingDir","contextDirectory","routingConfig","default","path","outputDirectory","structure","outputStructure","filename_options","outputFilenameOptions","createDirectories","projects","conflict_resolution","routing","Routing","interactive","Interactive","enabled","output","Output","intermediateDir","keepIntermediates","reflection","selfReflection","Reflection","transcription","Transcription","defaultModel","transcriptionModel","reasoning","Reasoning","model","complete","processedDirectory","CompletePhase","dryRun","extractTitleFromPath","outputPath","filename","split","pop","replace","undefined","withoutDate","map","word","charAt","toUpperCase","slice","join","processInput","input","startTime","Date","now","info","audioFile","hash","state","collector","start","startSession","onboardingState","checkNeedsOnboarding","needsOnboarding","whisperStart","transcriptionResult","transcribe","rawTranscript","text","whisperDuration","length","recordWhisper","routingContext","transcriptText","audioDate","creation","sourceFile","routeResult","route","projectId","confidence","recordRoutingDecision","destination","signals","s","type","value","weight","alternativesConsidered","alternateMatches","alt","whyNotChosen","toFixed","buildOutputPath","paths","createOutputPaths","ensureDirectories","writeIntermediate","duration","agenticStart","toolContext","contextInstance","routingInstance","interactiveMode","interactiveInstance","executor","Agentic","agenticResult","enhancedText","toolsUsed","agenticDuration","tool","recordToolCall","recordCorrection","totalTokens","recordModelResponse","contextChanges","change","recordContextChange","iterations","transcriptMetadata","title","final","project","date","Metadata","tags","writeTranscript","reflectionReport","generate","intermediate","save","session","endSession","responses","cleanIntermediates","processedAudioPath","subject","processingTime","routedProject","routingConfidence","correctionsApplied","resolvedEntities","size","intermediatePaths","error"],"mappings":"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"}
|