@redaksjon/protokoll 0.0.11 → 0.0.13

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 (88) hide show
  1. package/.cursor/rules/definition-of-done.md +1 -0
  2. package/.cursor/rules/no-emoticons.md +26 -12
  3. package/README.md +483 -69
  4. package/dist/agentic/executor.js +473 -41
  5. package/dist/agentic/executor.js.map +1 -1
  6. package/dist/agentic/index.js.map +1 -1
  7. package/dist/agentic/tools/lookup-person.js +123 -4
  8. package/dist/agentic/tools/lookup-person.js.map +1 -1
  9. package/dist/agentic/tools/lookup-project.js +139 -22
  10. package/dist/agentic/tools/lookup-project.js.map +1 -1
  11. package/dist/agentic/tools/route-note.js +5 -1
  12. package/dist/agentic/tools/route-note.js.map +1 -1
  13. package/dist/arguments.js +6 -3
  14. package/dist/arguments.js.map +1 -1
  15. package/dist/cli/action.js +704 -0
  16. package/dist/cli/action.js.map +1 -0
  17. package/dist/cli/config.js +482 -0
  18. package/dist/cli/config.js.map +1 -0
  19. package/dist/cli/context.js +466 -0
  20. package/dist/cli/context.js.map +1 -0
  21. package/dist/cli/feedback.js +858 -0
  22. package/dist/cli/feedback.js.map +1 -0
  23. package/dist/cli/index.js +103 -0
  24. package/dist/cli/index.js.map +1 -0
  25. package/dist/cli/install.js +572 -0
  26. package/dist/cli/install.js.map +1 -0
  27. package/dist/cli/transcript.js +199 -0
  28. package/dist/cli/transcript.js.map +1 -0
  29. package/dist/constants.js +12 -5
  30. package/dist/constants.js.map +1 -1
  31. package/dist/context/discovery.js +1 -1
  32. package/dist/context/discovery.js.map +1 -1
  33. package/dist/context/index.js +25 -1
  34. package/dist/context/index.js.map +1 -1
  35. package/dist/context/storage.js +57 -4
  36. package/dist/context/storage.js.map +1 -1
  37. package/dist/interactive/handler.js +310 -9
  38. package/dist/interactive/handler.js.map +1 -1
  39. package/dist/main.js +11 -1
  40. package/dist/main.js.map +1 -1
  41. package/dist/output/index.js.map +1 -1
  42. package/dist/output/manager.js +47 -2
  43. package/dist/output/manager.js.map +1 -1
  44. package/dist/phases/complete.js +38 -3
  45. package/dist/phases/complete.js.map +1 -1
  46. package/dist/phases/locate.js +1 -1
  47. package/dist/phases/locate.js.map +1 -1
  48. package/dist/pipeline/orchestrator.js +104 -31
  49. package/dist/pipeline/orchestrator.js.map +1 -1
  50. package/dist/protokoll.js +68 -2
  51. package/dist/protokoll.js.map +1 -1
  52. package/dist/reasoning/client.js +83 -0
  53. package/dist/reasoning/client.js.map +1 -1
  54. package/dist/reasoning/index.js +1 -0
  55. package/dist/reasoning/index.js.map +1 -1
  56. package/dist/routing/router.js +2 -2
  57. package/dist/routing/router.js.map +1 -1
  58. package/dist/util/media.js +1 -1
  59. package/dist/util/media.js.map +1 -1
  60. package/dist/util/metadata.js.map +1 -1
  61. package/dist/util/sound.js +116 -0
  62. package/dist/util/sound.js.map +1 -0
  63. package/dist/util/storage.js +3 -3
  64. package/dist/util/storage.js.map +1 -1
  65. package/docs/duplicate-question-prevention.md +117 -0
  66. package/docs/examples.md +152 -0
  67. package/docs/interactive-context-example.md +92 -0
  68. package/docs/package-lock.json +6 -0
  69. package/docs/package.json +3 -1
  70. package/eslint.config.mjs +1 -1
  71. package/guide/action.md +375 -0
  72. package/guide/config.md +207 -0
  73. package/guide/configuration.md +82 -67
  74. package/guide/context-commands.md +574 -0
  75. package/guide/context-system.md +20 -7
  76. package/guide/development.md +106 -4
  77. package/guide/feedback.md +335 -0
  78. package/guide/index.md +100 -4
  79. package/guide/interactive.md +15 -14
  80. package/guide/quickstart.md +21 -7
  81. package/guide/reasoning.md +18 -4
  82. package/guide/routing.md +192 -97
  83. package/package.json +2 -3
  84. package/scripts/copy-assets.mjs +47 -0
  85. package/scripts/coverage-priority.mjs +323 -0
  86. package/tsconfig.tsbuildinfo +1 -1
  87. package/vite.config.ts +6 -13
  88. package/vitest.config.ts +5 -1
@@ -1 +1 @@
1
- {"version":3,"file":"handler.js","sources":["../../src/interactive/handler.ts"],"sourcesContent":["/**\n * Interactive Handler\n * \n * Manages interactive sessions and clarification requests.\n * Uses readline for actual user prompting.\n */\n\nimport * as readline from 'readline';\nimport { \n InteractiveConfig, \n InteractiveSession, \n ClarificationRequest, \n ClarificationResponse \n} from './types';\nimport * as Logging from '../logging';\n\nexport interface HandlerInstance {\n startSession(): void;\n endSession(): InteractiveSession;\n handleClarification(request: ClarificationRequest): Promise<ClarificationResponse>;\n isEnabled(): boolean;\n getSession(): InteractiveSession | null;\n}\n\nconst createReadlineInterface = () => {\n return readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n};\n\nconst askQuestion = (rl: readline.Interface, question: string): Promise<string> => {\n return new Promise((resolve) => {\n rl.question(question, (answer) => {\n resolve(answer.trim());\n });\n });\n};\n\nconst formatClarificationPrompt = (request: ClarificationRequest): string => {\n const lines: string[] = [];\n \n lines.push('');\n lines.push('─'.repeat(60));\n \n switch (request.type) {\n case 'name_spelling':\n lines.push(`[Name Spelling Clarification]`);\n lines.push(`Context: ${request.context}`);\n lines.push(`Heard: \"${request.term}\"`);\n if (request.suggestion) {\n lines.push(`Suggested correction: \"${request.suggestion}\"`);\n }\n lines.push('');\n lines.push('Enter correct spelling (or press Enter to accept suggestion):');\n break;\n \n case 'new_person':\n lines.push(`[New Person Detected]`);\n lines.push(`Context: ${request.context}`);\n lines.push(`Name heard: \"${request.term}\"`);\n lines.push('');\n lines.push('Who is this person? (brief description, or press Enter to skip):');\n break;\n \n case 'new_project':\n lines.push(`[New Project Detected]`);\n lines.push(`Context: ${request.context}`);\n lines.push(`Project name: \"${request.term}\"`);\n lines.push('');\n lines.push('What is this project? (brief description, or press Enter to skip):');\n break;\n \n case 'new_company':\n lines.push(`[New Company Detected]`);\n lines.push(`Context: ${request.context}`);\n lines.push(`Company name: \"${request.term}\"`);\n lines.push('');\n lines.push('Any notes about this company? (or press Enter to skip):');\n break;\n \n case 'new_term':\n lines.push(`[New Term Found]`);\n lines.push(`Context: ${request.context}`);\n lines.push(`Term: \"${request.term}\"`);\n lines.push('');\n lines.push('What does this term mean? (brief description, or press Enter to skip):');\n break;\n \n case 'routing_decision':\n lines.push(`[Routing Decision Required]`);\n lines.push(`Context: ${request.context}`);\n if (request.options && request.options.length > 0) {\n lines.push('Available destinations:');\n request.options.forEach((opt, i) => {\n lines.push(` ${i + 1}. ${opt}`);\n });\n lines.push('');\n lines.push('Enter number or destination path:');\n } else {\n lines.push('');\n lines.push('Where should this note be filed?');\n }\n break;\n \n case 'low_confidence_routing':\n lines.push(`[Confirm Note Routing]`);\n lines.push(`Confidence: ${request.term}`);\n lines.push(`${request.context}`);\n lines.push('');\n lines.push('Is this correct? (Y/Enter to accept, or enter different path):');\n break;\n \n case 'first_run_onboarding':\n lines.push(`[First Run Setup]`);\n lines.push(`${request.context}`);\n lines.push('');\n if (request.options && request.options.length > 0) {\n request.options.forEach((opt, i) => {\n lines.push(` ${i + 1}. ${opt}`);\n });\n lines.push('');\n lines.push('Enter your choice:');\n } else {\n lines.push('Enter your response:');\n }\n break;\n \n case 'general':\n default:\n lines.push(`[Clarification Needed]`);\n lines.push(`${request.context}`);\n if (request.term) {\n lines.push(`Term: \"${request.term}\"`);\n }\n if (request.suggestion) {\n lines.push(`Suggested spelling: \"${request.suggestion}\"`);\n lines.push('');\n lines.push('Press Enter or Y to accept suggestion, or type alternative:');\n } else {\n lines.push('');\n lines.push('Your response:');\n }\n break;\n }\n \n lines.push('─'.repeat(60));\n \n return lines.join('\\n') + '\\n> ';\n};\n\nexport const create = (config: InteractiveConfig): HandlerInstance => {\n const logger = Logging.getLogger();\n \n let session: InteractiveSession | null = null;\n let rl: readline.Interface | null = null;\n \n const startSession = () => {\n session = {\n requests: [],\n responses: [],\n startedAt: new Date(),\n };\n \n if (config.enabled) {\n rl = createReadlineInterface();\n logger.info('Interactive session started - will prompt for clarifications');\n } else {\n logger.debug('Interactive session started (non-interactive mode)');\n }\n };\n \n const endSession = (): InteractiveSession => {\n if (!session) {\n throw new Error('No active session');\n }\n \n if (rl) {\n rl.close();\n rl = null;\n }\n \n session.completedAt = new Date();\n const completed = session;\n session = null;\n \n logger.info('Interactive session ended', { \n requests: completed.requests.length,\n responses: completed.responses.length,\n });\n \n return completed;\n };\n \n const handleClarification = async (\n request: ClarificationRequest\n ): Promise<ClarificationResponse> => {\n if (session) {\n session.requests.push(request);\n }\n \n // In non-interactive mode, return the suggestion or the original term\n if (!config.enabled || !rl) {\n const response: ClarificationResponse = {\n type: request.type,\n term: request.term,\n response: config.defaultToSuggestion && request.suggestion \n ? request.suggestion \n : request.term,\n shouldRemember: false,\n };\n \n if (session) {\n session.responses.push(response);\n }\n \n logger.debug('Clarification auto-resolved (non-interactive)', { \n type: request.type, \n term: request.term,\n response: response.response,\n });\n \n return response;\n }\n \n // Interactive mode - actually prompt the user\n const prompt = formatClarificationPrompt(request);\n const userInput = await askQuestion(rl, prompt);\n \n // Process the user's response\n let finalResponse: string;\n let shouldRemember = false;\n \n if (userInput === '' || userInput.toLowerCase() === 'y') {\n // User pressed Enter or typed Y - use suggestion or original\n finalResponse = request.suggestion || request.term;\n } else if (request.options && /^\\d+$/.test(userInput)) {\n // User entered a number - select from options\n const index = parseInt(userInput, 10) - 1;\n if (index >= 0 && index < request.options.length) {\n finalResponse = request.options[index];\n } else {\n finalResponse = userInput;\n }\n } else {\n finalResponse = userInput;\n // If user provided a custom answer, they might want to remember it\n shouldRemember = true;\n }\n \n const response: ClarificationResponse = {\n type: request.type,\n term: request.term,\n response: finalResponse,\n shouldRemember,\n };\n \n if (session) {\n session.responses.push(response);\n }\n \n logger.debug('Clarification resolved via user input', { \n type: request.type, \n term: request.term,\n response: response.response,\n shouldRemember,\n });\n \n return response;\n };\n \n const isEnabled = () => config.enabled;\n \n const getSession = () => session;\n \n return {\n startSession,\n endSession,\n handleClarification,\n isEnabled,\n getSession,\n };\n};\n"],"names":["createReadlineInterface","readline","createInterface","input","process","stdin","output","stdout","askQuestion","rl","question","Promise","resolve","answer","trim","formatClarificationPrompt","request","lines","push","repeat","type","context","term","suggestion","options","length","forEach","opt","i","join","create","config","logger","Logging","session","startSession","requests","responses","startedAt","Date","enabled","info","debug","endSession","Error","close","completedAt","completed","handleClarification","response","shouldRemember","prompt","userInput","finalResponse","toLowerCase","test","index","parseInt","isEnabled","getSession"],"mappings":"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"}
1
+ {"version":3,"file":"handler.js","sources":["../../src/interactive/handler.ts"],"sourcesContent":["/**\n * Interactive Handler\n * \n * Manages interactive sessions and clarification requests.\n * Uses readline for actual user prompting.\n * Plays notification sounds when user input is needed (like Cursor).\n */\n\nimport * as readline from 'readline';\nimport { \n InteractiveConfig, \n InteractiveSession, \n ClarificationRequest, \n ClarificationResponse,\n NewProjectWizardResult,\n NewPersonWizardResult,\n} from './types';\nimport * as Logging from '../logging';\nimport * as Sound from '../util/sound';\n\nexport interface HandlerInstance {\n startSession(): void;\n endSession(): InteractiveSession;\n handleClarification(request: ClarificationRequest): Promise<ClarificationResponse>;\n isEnabled(): boolean;\n getSession(): InteractiveSession | null;\n}\n\nconst createReadlineInterface = () => {\n // Ensure stdin is in the correct mode for readline\n // This helps prevent issues with some terminal emulators\n if (process.stdin.setRawMode) {\n try {\n // Ensure we're NOT in raw mode - readline handles this itself\n process.stdin.setRawMode(false);\n } catch {\n // Ignore errors - some environments don't support setRawMode\n }\n }\n \n return readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n terminal: true, // Explicitly enable terminal mode for proper echo handling\n });\n};\n\nconst askQuestion = (rl: readline.Interface, question: string): Promise<string> => {\n return new Promise((resolve) => {\n rl.question(question, (answer) => {\n resolve(answer.trim());\n });\n });\n};\n\n// Helper to write to stdout without triggering no-console lint rule\nconst write = (text: string) => process.stdout.write(text + '\\n');\n\n// Simplified project creation (used when creating project from term/person association)\nconst runCreateProjectFlow = async (\n rl: readline.Interface,\n contextMessage?: string\n): Promise<NewProjectWizardResult> => {\n if (contextMessage) {\n write('');\n write(contextMessage);\n }\n \n // Step 1: Project name (required)\n const projectName = await askQuestion(rl, '\\nProject name: ');\n \n if (!projectName) {\n write('Project name is required. Skipping project creation.');\n return { action: 'skip' };\n }\n \n // Step 2: Destination\n const destination = await askQuestion(rl, '\\nWhere should output be routed to? (Enter for default): ');\n \n // Step 3: Description\n const description = await askQuestion(rl, '\\nCan you tell me something about this project? (Enter to skip): ');\n \n return {\n action: 'create',\n projectName: projectName.trim(),\n destination: destination || undefined,\n description: description || undefined,\n };\n};\n\nconst runNewProjectWizard = async (\n rl: readline.Interface,\n term: string,\n context: string | undefined,\n projectOptions: string[] | undefined\n): Promise<NewProjectWizardResult> => {\n write('');\n write('─'.repeat(60));\n write(`[Unknown Project/Term]`);\n write(`Term: \"${term}\"`);\n write('');\n if (context) {\n // Display context with proper formatting (it now includes file info)\n write(context);\n }\n write('─'.repeat(60));\n \n // Step 1: Is this a project or a term?\n const entityType = await askQuestion(rl, '\\nIs this a Project or a Term? (P/T/X to ignore, or Enter to skip): ');\n \n if (entityType === '' || entityType.toLowerCase() === 's' || entityType.toLowerCase() === 'skip') {\n return { action: 'skip' };\n }\n \n // IGNORE FLOW - user doesn't want to be asked about this term again\n if (entityType.toLowerCase() === 'x' || entityType.toLowerCase() === 'i' || entityType.toLowerCase() === 'ignore') {\n write(`\\n[Adding \"${term}\" to ignore list - you won't be asked about this again]`);\n return { action: 'ignore', ignoredTerm: term };\n }\n \n // PROJECT FLOW\n if (entityType.toLowerCase() === 'p' || entityType.toLowerCase() === 'project') {\n // Step 2: Project name\n const projectName = await askQuestion(rl, `\\nWhat is this project's name? [${term}]: `);\n const finalName = projectName || term;\n \n // Step 3: Destination\n const destination = await askQuestion(rl, '\\nWhere should output be routed to? (Enter for default): ');\n \n // Step 4: Description\n const description = await askQuestion(rl, '\\nCan you tell me something about this project? (Enter to skip): ');\n \n return {\n action: 'create',\n projectName: finalName,\n destination: destination || undefined,\n description: description || undefined,\n };\n }\n \n // TERM FLOW\n if (entityType.toLowerCase() === 't' || entityType.toLowerCase() === 'term') {\n // Step 2: Validate spelling\n const termCorrection = await askQuestion(rl, `\\nIs \"${term}\" spelled correctly? (Enter to accept, or type correction): `);\n const finalTermName = termCorrection || term;\n \n if (termCorrection) {\n write(`Term updated to: \"${finalTermName}\"`);\n }\n \n // Step 3: Is this an acronym?\n const expansion = await askQuestion(rl, `\\nIf \"${finalTermName}\" is an acronym, what does it stand for? (Enter to skip): `);\n \n // Step 4: Which project(s) is this term associated with?\n const termProjects: number[] = [];\n let createdProject: NewProjectWizardResult | undefined;\n \n if (projectOptions && projectOptions.length > 0) {\n write('\\nExisting projects:');\n projectOptions.forEach((opt, i) => {\n write(` ${i + 1}. ${opt}`);\n });\n write(` N. Create a new project`);\n \n const projectSelection = await askQuestion(rl, `\\nWhich project(s) is \"${finalTermName}\" associated with? (Enter numbers separated by commas, N for new, or Enter to skip): `);\n \n if (projectSelection.toLowerCase().includes('n')) {\n // User wants to create a new project to associate with this term\n write('');\n write(`[Create New Project for Term \"${finalTermName}\"]`);\n createdProject = await runCreateProjectFlow(rl, `The term \"${finalTermName}\" will be associated with this new project.`);\n \n if (createdProject.action === 'create' && createdProject.projectName) {\n write(`\\n[Project \"${createdProject.projectName}\" will be created and associated with term \"${finalTermName}\"]`);\n }\n } else if (projectSelection) {\n const indices = projectSelection.split(',').map(s => parseInt(s.trim(), 10) - 1);\n for (const idx of indices) {\n if (!isNaN(idx) && idx >= 0 && idx < projectOptions.length) {\n termProjects.push(idx);\n }\n }\n \n if (termProjects.length > 0) {\n write(`Associated with: ${termProjects.map(i => projectOptions[i].split(' - ')[0]).join(', ')}`);\n }\n }\n } else {\n // No existing projects - offer to create one\n const createNew = await askQuestion(rl, `\\nNo existing projects found. Create a new project for term \"${finalTermName}\"? (Y/N, or Enter to skip): `);\n \n if (createNew.toLowerCase() === 'y' || createNew.toLowerCase() === 'yes') {\n write('');\n write(`[Create New Project for Term \"${finalTermName}\"]`);\n createdProject = await runCreateProjectFlow(rl, `The term \"${finalTermName}\" will be associated with this new project.`);\n \n if (createdProject.action === 'create' && createdProject.projectName) {\n write(`\\n[Project \"${createdProject.projectName}\" will be created and associated with term \"${finalTermName}\"]`);\n }\n }\n }\n \n // Step 5: Description\n const termDesc = await askQuestion(rl, `\\nBrief description of \"${finalTermName}\"? (Enter to skip): `);\n \n return {\n action: 'term',\n termName: finalTermName,\n termExpansion: expansion || undefined,\n termProjects: termProjects.length > 0 ? termProjects : undefined,\n termDescription: termDesc || undefined,\n createdProject,\n };\n }\n \n // Unrecognized input\n write('\\nUnrecognized input. Please enter P for Project, T for Term, or press Enter to skip.');\n return { action: 'skip' };\n};\n\nconst runNewPersonWizard = async (\n rl: readline.Interface,\n name: string,\n context: string | undefined,\n projectOptions: string[] | undefined\n): Promise<NewPersonWizardResult> => {\n write('');\n write('─'.repeat(60));\n write(`[Unknown Person Detected]`);\n write(`Name heard: \"${name}\"`);\n write('');\n if (context) {\n // Display context with proper formatting (it now includes file info)\n write(context);\n }\n write('─'.repeat(60));\n \n // Step 1: Confirm name spelling\n const nameCorrection = await askQuestion(rl, `\\nIs the name spelled correctly? (Enter to accept, or type correction): `);\n const finalName = nameCorrection || name;\n \n if (nameCorrection) {\n write(`Name updated to: \"${finalName}\"`);\n }\n \n // Step 2: Ask for organization/company\n const organization = await askQuestion(rl, `\\nWhat organization/company is ${finalName} with? (Enter to skip): `);\n \n // Step 3: Project association\n let linkedProjectIndex: number | undefined;\n let createdProject: NewProjectWizardResult | undefined;\n \n // Show project options with \"N\" for new project\n if (projectOptions && projectOptions.length > 0) {\n write('\\nExisting projects:');\n projectOptions.forEach((opt, i) => {\n write(` ${i + 1}. ${opt}`);\n });\n write(` N. Create a new project`);\n \n const projectSelection = await askQuestion(rl, `\\nWhich project is ${finalName} related to? (Enter number, N for new, or Enter to skip): `);\n \n if (projectSelection.toLowerCase() === 'n') {\n // User wants to create a new project for this person\n write('');\n write(`[Create New Project for ${finalName}]`);\n const contextMsg = organization \n ? `Creating project for ${finalName} (${organization})`\n : `Creating project for ${finalName}`;\n createdProject = await runCreateProjectFlow(rl, contextMsg);\n \n if (createdProject.action === 'create' && createdProject.projectName) {\n write(`\\n[Project \"${createdProject.projectName}\" will be created and linked to ${finalName}]`);\n }\n } else if (projectSelection && /^\\d+$/.test(projectSelection)) {\n const idx = parseInt(projectSelection, 10) - 1;\n if (idx >= 0 && idx < projectOptions.length) {\n linkedProjectIndex = idx;\n write(`Linked to: ${projectOptions[idx]}`);\n }\n }\n } else {\n // No existing projects - offer to create one\n const createNew = await askQuestion(rl, `\\nNo existing projects found. Create a new project for ${finalName}? (Y/N, or Enter to skip): `);\n \n if (createNew.toLowerCase() === 'y' || createNew.toLowerCase() === 'yes') {\n write('');\n write(`[Create New Project for ${finalName}]`);\n const contextMsg = organization \n ? `Creating project for ${finalName} (${organization})`\n : `Creating project for ${finalName}`;\n createdProject = await runCreateProjectFlow(rl, contextMsg);\n \n if (createdProject.action === 'create' && createdProject.projectName) {\n write(`\\n[Project \"${createdProject.projectName}\" will be created and linked to ${finalName}]`);\n }\n }\n }\n \n // Step 4: Ask for notes about the person\n const notes = await askQuestion(rl, `\\nAny notes about ${finalName}? (Enter to skip): `);\n \n // Determine if we should create the person\n const hasInfo = organization || linkedProjectIndex !== undefined || createdProject || notes;\n \n if (!hasInfo) {\n // User skipped everything - confirm if they want to skip entirely\n const confirm = await askQuestion(rl, `\\nNo information provided. Skip saving ${finalName}? (Enter to skip, or any key to save anyway): `);\n if (confirm === '') {\n return { action: 'skip' };\n }\n }\n \n return {\n action: 'create',\n personName: finalName,\n organization: organization || undefined,\n linkedProjectIndex,\n notes: notes || undefined,\n createdProject,\n };\n};\n\nconst formatClarificationPrompt = (request: ClarificationRequest): string => {\n const lines: string[] = [];\n \n lines.push('');\n lines.push('─'.repeat(60));\n \n switch (request.type) {\n case 'name_spelling':\n lines.push(`[Name Spelling Clarification]`);\n lines.push(`Context: ${request.context}`);\n lines.push(`Heard: \"${request.term}\"`);\n if (request.suggestion) {\n lines.push(`Suggested correction: \"${request.suggestion}\"`);\n }\n lines.push('');\n lines.push('Enter correct spelling (or press Enter to accept suggestion):');\n break;\n \n case 'new_person':\n lines.push(`[New Person Detected]`);\n lines.push(`Context: ${request.context}`);\n lines.push(`Name heard: \"${request.term}\"`);\n lines.push('');\n lines.push('Who is this person? (brief description, or press Enter to skip):');\n break;\n \n case 'new_project':\n // This case is handled by the wizard, but provide fallback prompt\n lines.push(`[Unknown Project/Term]`);\n lines.push(`Term: \"${request.term}\"`);\n if (request.context) {\n lines.push(`${request.context}`);\n }\n lines.push('');\n lines.push('Is this a new project? (Y/N, or Enter to skip):');\n break;\n \n case 'new_company':\n lines.push(`[New Company Detected]`);\n lines.push(`Context: ${request.context}`);\n lines.push(`Company name: \"${request.term}\"`);\n lines.push('');\n lines.push('Any notes about this company? (or press Enter to skip):');\n break;\n \n case 'new_term':\n lines.push(`[New Term Found]`);\n lines.push(`Context: ${request.context}`);\n lines.push(`Term: \"${request.term}\"`);\n lines.push('');\n lines.push('What does this term mean? (brief description, or press Enter to skip):');\n break;\n \n case 'routing_decision':\n lines.push(`[Routing Decision Required]`);\n lines.push(`Context: ${request.context}`);\n if (request.options && request.options.length > 0) {\n lines.push('Available destinations:');\n request.options.forEach((opt, i) => {\n lines.push(` ${i + 1}. ${opt}`);\n });\n lines.push('');\n lines.push('Enter number or destination path:');\n } else {\n lines.push('');\n lines.push('Where should this note be filed?');\n }\n break;\n \n case 'low_confidence_routing':\n lines.push(`[Confirm Note Routing]`);\n lines.push(`Confidence: ${request.term}`);\n lines.push(`${request.context}`);\n lines.push('');\n lines.push('Is this correct? (Y/Enter to accept, or enter different path):');\n break;\n \n case 'first_run_onboarding':\n lines.push(`[First Run Setup]`);\n lines.push(`${request.context}`);\n lines.push('');\n if (request.options && request.options.length > 0) {\n request.options.forEach((opt, i) => {\n lines.push(` ${i + 1}. ${opt}`);\n });\n lines.push('');\n lines.push('Enter your choice:');\n } else {\n lines.push('Enter your response:');\n }\n break;\n \n case 'general':\n default:\n lines.push(`[Clarification Needed]`);\n lines.push(`${request.context}`);\n if (request.term) {\n lines.push(`Term: \"${request.term}\"`);\n }\n if (request.suggestion) {\n lines.push(`Suggested spelling: \"${request.suggestion}\"`);\n lines.push('');\n lines.push('Press Enter or Y to accept suggestion, or type alternative:');\n } else {\n lines.push('');\n lines.push('Your response:');\n }\n break;\n }\n \n lines.push('─'.repeat(60));\n \n return lines.join('\\n') + '\\n> ';\n};\n\nexport const create = (config: InteractiveConfig): HandlerInstance => {\n const logger = Logging.getLogger();\n const sound = Sound.create({ silent: config.silent ?? false });\n \n let session: InteractiveSession | null = null;\n let rl: readline.Interface | null = null;\n \n const startSession = () => {\n session = {\n requests: [],\n responses: [],\n startedAt: new Date(),\n };\n \n // Check if we can run interactively:\n // 1. Interactive mode must be enabled (not --batch)\n // 2. stdin must be a TTY (not piped/cron/etc)\n const isTTY = process.stdin.isTTY === true;\n \n if (config.enabled && isTTY) {\n // Only create readline interface if one doesn't already exist\n // This prevents duplicate input handlers when processing multiple files\n if (!rl) {\n rl = createReadlineInterface();\n logger.info('Interactive session started - will prompt for clarifications');\n } else {\n logger.debug('Interactive session continued (readline already active)');\n }\n } else if (config.enabled && !isTTY) {\n logger.info('Interactive mode enabled but stdin is not a TTY - running in auto-resolve mode');\n } else {\n logger.debug('Interactive session started (batch mode)');\n }\n };\n \n const endSession = (): InteractiveSession => {\n if (!session) {\n throw new Error('No active session');\n }\n \n if (rl) {\n // Remove all listeners before closing to prevent any lingering handlers\n // Check if method exists (may not in mocks)\n if (typeof rl.removeAllListeners === 'function') {\n rl.removeAllListeners();\n }\n rl.close();\n rl = null;\n \n // Resume stdin in case it was paused\n if (process.stdin.isPaused && process.stdin.isPaused()) {\n process.stdin.resume();\n }\n }\n \n session.completedAt = new Date();\n const completed = session;\n session = null;\n \n logger.info('Interactive session ended', { \n requests: completed.requests.length,\n responses: completed.responses.length,\n });\n \n return completed;\n };\n \n const handleClarification = async (\n request: ClarificationRequest\n ): Promise<ClarificationResponse> => {\n if (session) {\n session.requests.push(request);\n }\n \n // In non-interactive mode, return the suggestion or the original term\n if (!config.enabled || !rl) {\n const response: ClarificationResponse = {\n type: request.type,\n term: request.term,\n response: config.defaultToSuggestion && request.suggestion \n ? request.suggestion \n : request.term,\n shouldRemember: false,\n };\n \n if (session) {\n session.responses.push(response);\n }\n \n logger.debug('Clarification auto-resolved (non-interactive)', { \n type: request.type, \n term: request.term,\n response: response.response,\n });\n \n return response;\n }\n \n // Interactive mode - actually prompt the user\n // Play notification sound to get user's attention (like Cursor does)\n await sound.playNotification();\n \n // Special handling for new_project - use wizard\n if (request.type === 'new_project') {\n const wizardResult = await runNewProjectWizard(\n rl,\n request.term,\n request.context,\n request.options\n );\n \n const response: ClarificationResponse = {\n type: request.type,\n term: request.term,\n response: wizardResult.action,\n shouldRemember: wizardResult.action !== 'skip',\n additionalInfo: wizardResult as unknown as Record<string, unknown>,\n };\n \n if (session) {\n session.responses.push(response);\n }\n \n logger.debug('New project wizard completed', {\n term: request.term,\n action: wizardResult.action,\n additionalInfo: wizardResult,\n });\n \n return response;\n }\n \n // Special handling for new_person - use wizard\n if (request.type === 'new_person') {\n const wizardResult = await runNewPersonWizard(\n rl,\n request.term,\n request.context,\n request.options\n );\n \n const response: ClarificationResponse = {\n type: request.type,\n term: request.term,\n response: wizardResult.action,\n shouldRemember: wizardResult.action !== 'skip',\n additionalInfo: wizardResult as unknown as Record<string, unknown>,\n };\n \n if (session) {\n session.responses.push(response);\n }\n \n logger.debug('New person wizard completed', {\n term: request.term,\n action: wizardResult.action,\n additionalInfo: wizardResult,\n });\n \n return response;\n }\n \n // Standard single-prompt flow for other types\n const prompt = formatClarificationPrompt(request);\n const userInput = await askQuestion(rl, prompt);\n \n // Process the user's response\n let finalResponse: string;\n let shouldRemember = false;\n \n if (userInput === '' || userInput.toLowerCase() === 'y') {\n // User pressed Enter or typed Y - use suggestion or original\n finalResponse = request.suggestion || request.term;\n } else if (request.options && /^\\d+$/.test(userInput)) {\n // User entered a number - select from options\n const index = parseInt(userInput, 10) - 1;\n if (index >= 0 && index < request.options.length) {\n finalResponse = request.options[index];\n } else {\n finalResponse = userInput;\n }\n } else {\n finalResponse = userInput;\n // If user provided a custom answer, they might want to remember it\n shouldRemember = true;\n }\n \n const response: ClarificationResponse = {\n type: request.type,\n term: request.term,\n response: finalResponse,\n shouldRemember,\n };\n \n if (session) {\n session.responses.push(response);\n }\n \n logger.debug('Clarification resolved via user input', { \n type: request.type, \n term: request.term,\n response: response.response,\n shouldRemember,\n });\n \n return response;\n };\n \n const isEnabled = () => config.enabled;\n \n const getSession = () => session;\n \n return {\n startSession,\n endSession,\n handleClarification,\n isEnabled,\n getSession,\n };\n};\n"],"names":["createReadlineInterface","process","stdin","setRawMode","readline","createInterface","input","output","stdout","terminal","askQuestion","rl","question","Promise","resolve","answer","trim","write","text","runCreateProjectFlow","contextMessage","projectName","action","destination","description","undefined","runNewProjectWizard","term","context","projectOptions","repeat","entityType","toLowerCase","ignoredTerm","finalName","termCorrection","finalTermName","expansion","termProjects","createdProject","length","forEach","opt","i","projectSelection","includes","indices","split","map","s","parseInt","idx","isNaN","push","join","createNew","termDesc","termName","termExpansion","termDescription","runNewPersonWizard","name","nameCorrection","organization","linkedProjectIndex","contextMsg","test","notes","hasInfo","confirm","personName","formatClarificationPrompt","request","lines","type","suggestion","options","create","config","logger","Logging","sound","Sound","silent","session","startSession","requests","responses","startedAt","Date","isTTY","enabled","info","debug","endSession","Error","removeAllListeners","close","isPaused","resume","completedAt","completed","handleClarification","response","shouldRemember","playNotification","wizardResult","additionalInfo","prompt","userInput","finalResponse","index","isEnabled","getSession"],"mappings":"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"}
package/dist/main.js CHANGED
@@ -1,5 +1,15 @@
1
1
  #!/usr/bin/env node
2
2
  import { main } from './protokoll.js';
3
+ import { isContextCommand, runContextCLI } from './cli/index.js';
3
4
 
4
- main();
5
+ // Check if this is a context management command
6
+ if (isContextCommand()) {
7
+ runContextCLI().catch((error)=>{
8
+ process.stderr.write(`Error: ${error.message}\n`);
9
+ process.exit(1);
10
+ });
11
+ } else {
12
+ // Run the main transcription flow
13
+ main();
14
+ }
5
15
  //# sourceMappingURL=main.js.map
package/dist/main.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"main.js","sources":["../src/main.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { main } from '@/protokoll';\n\nmain();"],"names":["main"],"mappings":";;;AAGAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA"}
1
+ {"version":3,"file":"main.js","sources":["../src/main.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { main } from '@/protokoll';\nimport { isContextCommand, runContextCLI } from '@/cli';\n\n// Check if this is a context management command\nif (isContextCommand()) {\n runContextCLI().catch((error) => {\n process.stderr.write(`Error: ${error.message}\\n`);\n process.exit(1);\n });\n} else {\n // Run the main transcription flow\n main();\n}"],"names":["isContextCommand","runContextCLI","catch","error","process","stderr","write","message","exit","main"],"mappings":";;;;AAIA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA;AACA,CAAA,CAAA,CAAA,CAAIA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,EAAAA,CAAAA,CAAoB,CAAA;IACpBC,aAAAA,CAAAA,CAAAA,CAAgBC,KAAK,CAAC,CAACC,KAAAA,CAAAA,CAAAA,CAAAA,CAAAA;QACnBC,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAQC,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAM,CAACC,KAAK,CAAC,CAAC,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAO,CAAA,CAAEH,KAAAA,CAAMI,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAO,CAAC,CAAA,CAAE,CAAC,CAAA,CAAA;AAChDH,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAQI,CAAAA,CAAAA,CAAAA,CAAI,CAAC,CAAA,CAAA,CAAA;AACjB,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA;AACJ,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAO,CAAA;;AAEHC,CAAAA,CAAAA,CAAAA,CAAAA,IAAAA,CAAAA,CAAAA,CAAAA;AACJ"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../src/output/index.ts"],"sourcesContent":["/**\n * Output Management System\n *\n * Main entry point for the output management system. Handles intermediate\n * files and final output destinations.\n */\n\nimport { OutputConfig, OutputPaths, IntermediateFiles } from './types';\nimport * as Manager from './manager';\nimport * as Metadata from '../util/metadata';\n\nexport interface OutputInstance {\n createOutputPaths(\n audioFile: string,\n routedDestination: string,\n hash: string,\n date: Date\n ): OutputPaths;\n ensureDirectories(paths: OutputPaths): Promise<void>;\n writeIntermediate(\n paths: OutputPaths,\n type: keyof IntermediateFiles,\n content: unknown\n ): Promise<string>;\n writeTranscript(paths: OutputPaths, content: string, metadata?: Metadata.TranscriptMetadata): Promise<string>;\n cleanIntermediates(paths: OutputPaths): Promise<void>;\n}\n\nexport const create = (config: OutputConfig): OutputInstance => {\n return Manager.create(config);\n};\n\nexport const DEFAULT_OUTPUT_CONFIG: OutputConfig = {\n intermediateDir: './output/protokoll',\n keepIntermediates: true,\n timestampFormat: 'YYMMDD-HHmm',\n};\n\n// Re-export types\nexport * from './types';\n\n"],"names":["create","config","Manager"],"mappings":";;AA4BO,MAAMA,SAAS,CAACC,MAAAA,GAAAA;IACnB,OAAOC,QAAc,CAACD,MAAAA,CAAAA;AAC1B;;;;"}
1
+ {"version":3,"file":"index.js","sources":["../../src/output/index.ts"],"sourcesContent":["/**\n * Output Management System\n *\n * Main entry point for the output management system. Handles intermediate\n * files and final output destinations.\n */\n\nimport { OutputConfig, OutputPaths, IntermediateFiles, RawTranscriptData } from './types';\nimport * as Manager from './manager';\nimport * as Metadata from '../util/metadata';\n\nexport interface OutputInstance {\n createOutputPaths(\n audioFile: string,\n routedDestination: string,\n hash: string,\n date: Date\n ): OutputPaths;\n ensureDirectories(paths: OutputPaths): Promise<void>;\n writeIntermediate(\n paths: OutputPaths,\n type: keyof IntermediateFiles,\n content: unknown\n ): Promise<string>;\n /**\n * Write the raw Whisper transcript to the .transcript/ directory alongside final output.\n * This enables compare and reanalyze workflows.\n */\n writeRawTranscript(paths: OutputPaths, data: RawTranscriptData): Promise<string>;\n writeTranscript(paths: OutputPaths, content: string, metadata?: Metadata.TranscriptMetadata): Promise<string>;\n /**\n * Read a previously stored raw transcript from the .transcript/ directory.\n * Returns null if no raw transcript exists.\n */\n readRawTranscript(finalOutputPath: string): Promise<RawTranscriptData | null>;\n cleanIntermediates(paths: OutputPaths): Promise<void>;\n}\n\nexport const create = (config: OutputConfig): OutputInstance => {\n return Manager.create(config);\n};\n\nexport const DEFAULT_OUTPUT_CONFIG: OutputConfig = {\n intermediateDir: './output/protokoll',\n keepIntermediates: true,\n timestampFormat: 'YYMMDD-HHmm',\n};\n\n// Re-export types\nexport * from './types';\n\n"],"names":["create","config","Manager"],"mappings":";;AAsCO,MAAMA,SAAS,CAACC,MAAAA,GAAAA;IACnB,OAAOC,QAAc,CAACD,MAAAA,CAAAA;AAC1B;;;;"}
@@ -1,4 +1,4 @@
1
- import * as path from 'path';
1
+ import * as path from 'node:path';
2
2
  import * as fs from 'fs/promises';
3
3
  import { getLogger } from '../logging.js';
4
4
  import { formatMetadataMarkdown } from '../util/metadata.js';
@@ -21,8 +21,14 @@ const create = (config)=>{
21
21
  // Hash at the end for easier filename correlation
22
22
  const buildFilename = (type, ext)=>`${timestamp}-${type}-${shortHash}${ext}`;
23
23
  const intermediateDir = config.intermediateDir;
24
+ // Generate raw transcript path in .transcript/ directory alongside final output
25
+ // e.g., /notes/2026/1/14-meeting.md -> /notes/2026/1/.transcript/14-meeting.json
26
+ const finalDir = path.dirname(routedDestination);
27
+ const finalBasename = path.basename(routedDestination, path.extname(routedDestination));
28
+ const rawTranscriptPath = path.join(finalDir, '.transcript', `${finalBasename}.json`);
24
29
  return {
25
30
  final: routedDestination,
31
+ rawTranscript: rawTranscriptPath,
26
32
  intermediate: {
27
33
  transcript: path.join(intermediateDir, buildFilename('transcript', '.json')),
28
34
  context: path.join(intermediateDir, buildFilename('context', '.json')),
@@ -42,9 +48,14 @@ const create = (config)=>{
42
48
  await fs.mkdir(path.dirname(paths.final), {
43
49
  recursive: true
44
50
  });
51
+ // Ensure .transcript directory alongside final output
52
+ await fs.mkdir(path.dirname(paths.rawTranscript), {
53
+ recursive: true
54
+ });
45
55
  logger.debug('Ensured output directories', {
46
56
  intermediate: path.dirname(paths.intermediate.transcript),
47
- final: path.dirname(paths.final)
57
+ final: path.dirname(paths.final),
58
+ rawTranscript: path.dirname(paths.rawTranscript)
48
59
  });
49
60
  };
50
61
  const writeIntermediate = async (paths, type, content)=>{
@@ -92,11 +103,45 @@ const create = (config)=>{
92
103
  }
93
104
  }
94
105
  };
106
+ /**
107
+ * Write the raw Whisper transcript to the .transcript/ directory.
108
+ * This preserves the original transcription for compare/reanalyze workflows.
109
+ */ const writeRawTranscript = async (paths, data)=>{
110
+ const filePath = paths.rawTranscript;
111
+ await fs.writeFile(filePath, JSON.stringify(data, null, 2), 'utf-8');
112
+ logger.debug('Wrote raw transcript to .transcript/', {
113
+ path: filePath
114
+ });
115
+ return filePath;
116
+ };
117
+ /**
118
+ * Read a previously stored raw transcript from the .transcript/ directory.
119
+ * Calculates the path based on the final output path.
120
+ * Returns null if no raw transcript exists.
121
+ */ const readRawTranscript = async (finalOutputPath)=>{
122
+ const finalDir = path.dirname(finalOutputPath);
123
+ const finalBasename = path.basename(finalOutputPath, path.extname(finalOutputPath));
124
+ const rawTranscriptPath = path.join(finalDir, '.transcript', `${finalBasename}.json`);
125
+ try {
126
+ const content = await fs.readFile(rawTranscriptPath, 'utf-8');
127
+ return JSON.parse(content);
128
+ } catch (error) {
129
+ if (error && typeof error === 'object' && 'code' in error && error.code === 'ENOENT') {
130
+ logger.debug('No raw transcript found', {
131
+ path: rawTranscriptPath
132
+ });
133
+ return null;
134
+ }
135
+ throw error;
136
+ }
137
+ };
95
138
  return {
96
139
  createOutputPaths,
97
140
  ensureDirectories,
98
141
  writeIntermediate,
142
+ writeRawTranscript,
99
143
  writeTranscript,
144
+ readRawTranscript,
100
145
  cleanIntermediates
101
146
  };
102
147
  };
@@ -1 +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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"}
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 'node:path';\nimport * as fs from 'fs/promises';\nimport { OutputConfig, IntermediateFiles, OutputPaths, RawTranscriptData } 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 /**\n * Write the raw Whisper transcript to the .transcript/ directory alongside final output.\n * This enables compare and reanalyze workflows.\n */\n writeRawTranscript(paths: OutputPaths, data: RawTranscriptData): Promise<string>;\n \n writeTranscript(paths: OutputPaths, content: string, metadata?: Metadata.TranscriptMetadata): Promise<string>;\n \n cleanIntermediates(paths: OutputPaths): Promise<void>;\n \n /**\n * Read a previously stored raw transcript from the .transcript/ directory.\n * Returns null if no raw transcript exists.\n */\n readRawTranscript(finalOutputPath: string): Promise<RawTranscriptData | null>;\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 // Generate raw transcript path in .transcript/ directory alongside final output\n // e.g., /notes/2026/1/14-meeting.md -> /notes/2026/1/.transcript/14-meeting.json\n const finalDir = path.dirname(routedDestination);\n const finalBasename = path.basename(routedDestination, path.extname(routedDestination));\n const rawTranscriptPath = path.join(finalDir, '.transcript', `${finalBasename}.json`);\n\n return {\n final: routedDestination,\n rawTranscript: rawTranscriptPath,\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 // Ensure .transcript directory alongside final output\n await fs.mkdir(path.dirname(paths.rawTranscript), { recursive: true });\n \n logger.debug('Ensured output directories', {\n intermediate: path.dirname(paths.intermediate.transcript),\n final: path.dirname(paths.final),\n rawTranscript: path.dirname(paths.rawTranscript),\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 /**\n * Write the raw Whisper transcript to the .transcript/ directory.\n * This preserves the original transcription for compare/reanalyze workflows.\n */\n const writeRawTranscript = async (\n paths: OutputPaths,\n data: RawTranscriptData\n ): Promise<string> => {\n const filePath = paths.rawTranscript;\n \n await fs.writeFile(filePath, JSON.stringify(data, null, 2), 'utf-8');\n logger.debug('Wrote raw transcript to .transcript/', { path: filePath });\n \n return filePath;\n };\n \n /**\n * Read a previously stored raw transcript from the .transcript/ directory.\n * Calculates the path based on the final output path.\n * Returns null if no raw transcript exists.\n */\n const readRawTranscript = async (finalOutputPath: string): Promise<RawTranscriptData | null> => {\n const finalDir = path.dirname(finalOutputPath);\n const finalBasename = path.basename(finalOutputPath, path.extname(finalOutputPath));\n const rawTranscriptPath = path.join(finalDir, '.transcript', `${finalBasename}.json`);\n \n try {\n const content = await fs.readFile(rawTranscriptPath, 'utf-8');\n return JSON.parse(content) as RawTranscriptData;\n } catch (error: unknown) {\n if (error && typeof error === 'object' && 'code' in error && error.code === 'ENOENT') {\n logger.debug('No raw transcript found', { path: rawTranscriptPath });\n return null;\n }\n throw error;\n }\n };\n \n return {\n createOutputPaths,\n ensureDirectories,\n writeIntermediate,\n writeRawTranscript,\n writeTranscript,\n readRawTranscript,\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","finalDir","path","dirname","finalBasename","basename","extname","rawTranscriptPath","join","final","rawTranscript","intermediate","transcript","context","request","response","reflection","session","ensureDirectories","paths","fs","mkdir","recursive","debug","writeIntermediate","content","filePath","Error","contentStr","JSON","stringify","writeFile","writeTranscript","metadata","finalContent","metadataSection","Metadata","info","cleanIntermediates","keepIntermediates","Object","entries","unlink","writeRawTranscript","data","readRawTranscript","finalOutputPath","readFile","parse","error","code"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import * as path from 'path';
1
+ import * as path from 'node:path';
2
2
  import { getLogger } from '../logging.js';
3
3
  import { create as create$1 } from '../util/storage.js';
4
4
 
@@ -49,6 +49,33 @@ const create = (config)=>{
49
49
  return `${year}-${month}-${day}-${hours}${minutes}`;
50
50
  }
51
51
  };
52
+ // Strip date prefix and hash suffix from subject if already present
53
+ // This handles cases where subject comes from an already-formatted filename
54
+ const cleanSubjectOfPatterns = (subject)=>{
55
+ let cleaned = subject;
56
+ // Remove common date-time prefixes (try most specific first):
57
+ // - YYYY-MM-DD-HHmm- (e.g., "2026-01-14-2330-")
58
+ // - YYMMDD-HHmm- (e.g., "260114-2330-")
59
+ // - MM-DD-HHmm- (e.g., "01-14-2330-")
60
+ // - DD-HHmm- (e.g., "14-2330-" or "15-1435-")
61
+ // - HHmm- (e.g., "2330-")
62
+ // Pattern 1: YYYY-MM-DD-HHmm- (full ISO-like date with time)
63
+ cleaned = cleaned.replace(/^\d{4}-\d{2}-\d{2}-\d{4}-/, '');
64
+ // Pattern 2: YYMMDD-HHmm- (compact date with time)
65
+ cleaned = cleaned.replace(/^\d{6}-\d{4}-/, '');
66
+ // Pattern 3: MM-DD-HHmm- (month-day-time)
67
+ cleaned = cleaned.replace(/^\d{2}-\d{2}-\d{4}-/, '');
68
+ // Pattern 4: DD-HHmm- (day-time, most common for 'month' structure)
69
+ // This matches patterns like "15-1435-" where 15 is day and 1435 is HHmm
70
+ cleaned = cleaned.replace(/^\d{1,2}-\d{4}-/, '');
71
+ // Pattern 5: Just HHmm- at the start (time only)
72
+ cleaned = cleaned.replace(/^\d{4}-/, '');
73
+ // Remove hash suffix (5-8 hex characters at end, preceded by dash)
74
+ cleaned = cleaned.replace(/-[a-f0-9]{5,8}$/i, '');
75
+ // Clean up any leading dashes that might remain
76
+ cleaned = cleaned.replace(/^-+/, '');
77
+ return cleaned;
78
+ };
52
79
  const complete = async (audioFile, hash, creationTime, subject)=>{
53
80
  logger.debug('Completing file processing for %s', audioFile);
54
81
  if (config.dryRun) {
@@ -73,11 +100,19 @@ const create = (config)=>{
73
100
  // Create new filename: <date>-<subject>-<hash>
74
101
  // Hash is at the end for easier correlation with output files
75
102
  // Clean subject by removing special characters and spaces
103
+ // Also strip any existing date/hash patterns from the subject
76
104
  const shortHash = hash.substring(0, 6);
77
105
  let newFilename;
78
106
  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}`;
107
+ // First strip any existing date prefixes and hash suffixes
108
+ const strippedSubject = cleanSubjectOfPatterns(subject);
109
+ const cleanSubject = strippedSubject.replace(/[^a-zA-Z0-9]/g, '-').replace(/-+/g, '-').replace(/^-|-$/g, '').toLowerCase().substring(0, 50);
110
+ // Only include subject if there's something left after cleaning
111
+ if (cleanSubject) {
112
+ newFilename = `${dateStr}-${cleanSubject}-${shortHash}${fileExt}`;
113
+ } else {
114
+ newFilename = `${dateStr}-${shortHash}${fileExt}`;
115
+ }
81
116
  } else {
82
117
  newFilename = `${dateStr}-${shortHash}${fileExt}`;
83
118
  }
@@ -1 +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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"}
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 'node: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 // Strip date prefix and hash suffix from subject if already present\n // This handles cases where subject comes from an already-formatted filename\n const cleanSubjectOfPatterns = (subject: string): string => {\n let cleaned = subject;\n \n // Remove common date-time prefixes (try most specific first):\n // - YYYY-MM-DD-HHmm- (e.g., \"2026-01-14-2330-\")\n // - YYMMDD-HHmm- (e.g., \"260114-2330-\") \n // - MM-DD-HHmm- (e.g., \"01-14-2330-\")\n // - DD-HHmm- (e.g., \"14-2330-\" or \"15-1435-\")\n // - HHmm- (e.g., \"2330-\")\n \n // Pattern 1: YYYY-MM-DD-HHmm- (full ISO-like date with time)\n cleaned = cleaned.replace(/^\\d{4}-\\d{2}-\\d{2}-\\d{4}-/, '');\n \n // Pattern 2: YYMMDD-HHmm- (compact date with time)\n cleaned = cleaned.replace(/^\\d{6}-\\d{4}-/, '');\n \n // Pattern 3: MM-DD-HHmm- (month-day-time)\n cleaned = cleaned.replace(/^\\d{2}-\\d{2}-\\d{4}-/, '');\n \n // Pattern 4: DD-HHmm- (day-time, most common for 'month' structure)\n // This matches patterns like \"15-1435-\" where 15 is day and 1435 is HHmm\n cleaned = cleaned.replace(/^\\d{1,2}-\\d{4}-/, '');\n \n // Pattern 5: Just HHmm- at the start (time only)\n cleaned = cleaned.replace(/^\\d{4}-/, '');\n \n // Remove hash suffix (5-8 hex characters at end, preceded by dash)\n cleaned = cleaned.replace(/-[a-f0-9]{5,8}$/i, '');\n \n // Clean up any leading dashes that might remain\n cleaned = cleaned.replace(/^-+/, '');\n \n return cleaned;\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 // Also strip any existing date/hash patterns from the subject\n const shortHash = hash.substring(0, 6);\n let newFilename: string;\n if (subject) {\n // First strip any existing date prefixes and hash suffixes\n const strippedSubject = cleanSubjectOfPatterns(subject);\n const cleanSubject = strippedSubject\n .replace(/[^a-zA-Z0-9]/g, '-')\n .replace(/-+/g, '-')\n .replace(/^-|-$/g, '')\n .toLowerCase()\n .substring(0, 50);\n \n // Only include subject if there's something left after cleaning\n if (cleanSubject) {\n newFilename = `${dateStr}-${cleanSubject}-${shortHash}${fileExt}`;\n } else {\n newFilename = `${dateStr}-${shortHash}${fileExt}`;\n }\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","cleanSubjectOfPatterns","subject","cleaned","replace","complete","audioFile","hash","creationTime","dryRun","info","targetDir","exists","createDirectory","fileExt","extname","dateStr","shortHash","substring","newFilename","strippedSubject","cleanSubject","toLowerCase","newFilePath","fileContent","readFile","writeFile","deleteFile","error"],"mappings":"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"}
@@ -3,7 +3,7 @@ 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
5
  import { DEFAULT_INTERMEDIATE_DIRECTORY } from '../constants.js';
6
- import path__default from 'path';
6
+ import path__default from 'node:path';
7
7
 
8
8
  const create = (config, operator)=>{
9
9
  const logger = getLogger();
@@ -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 { 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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"}
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 'node: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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"}