@redaksjon/protokoll 0.0.13 → 0.0.15

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 (108) hide show
  1. package/README.md +199 -0
  2. package/dist/feedback.js +5193 -0
  3. package/dist/feedback.js.map +1 -0
  4. package/dist/main.js +1858 -9
  5. package/dist/main.js.map +1 -1
  6. package/dist/mcp/server.js +1330 -0
  7. package/dist/mcp/server.js.map +1 -0
  8. package/guide/index.md +16 -0
  9. package/guide/mcp-integration.md +341 -0
  10. package/package.json +5 -3
  11. package/tsconfig.tsbuildinfo +1 -1
  12. package/vite.config.ts +13 -29
  13. package/dist/agentic/executor.js +0 -747
  14. package/dist/agentic/executor.js.map +0 -1
  15. package/dist/agentic/index.js +0 -19
  16. package/dist/agentic/index.js.map +0 -1
  17. package/dist/agentic/registry.js +0 -41
  18. package/dist/agentic/registry.js.map +0 -1
  19. package/dist/agentic/tools/lookup-person.js +0 -185
  20. package/dist/agentic/tools/lookup-person.js.map +0 -1
  21. package/dist/agentic/tools/lookup-project.js +0 -210
  22. package/dist/agentic/tools/lookup-project.js.map +0 -1
  23. package/dist/agentic/tools/route-note.js +0 -49
  24. package/dist/agentic/tools/route-note.js.map +0 -1
  25. package/dist/agentic/tools/store-context.js +0 -51
  26. package/dist/agentic/tools/store-context.js.map +0 -1
  27. package/dist/agentic/tools/verify-spelling.js +0 -57
  28. package/dist/agentic/tools/verify-spelling.js.map +0 -1
  29. package/dist/arguments.js +0 -178
  30. package/dist/arguments.js.map +0 -1
  31. package/dist/cli/action.js +0 -704
  32. package/dist/cli/action.js.map +0 -1
  33. package/dist/cli/config.js +0 -482
  34. package/dist/cli/config.js.map +0 -1
  35. package/dist/cli/context.js +0 -466
  36. package/dist/cli/context.js.map +0 -1
  37. package/dist/cli/feedback.js +0 -858
  38. package/dist/cli/feedback.js.map +0 -1
  39. package/dist/cli/index.js +0 -103
  40. package/dist/cli/index.js.map +0 -1
  41. package/dist/cli/install.js +0 -572
  42. package/dist/cli/install.js.map +0 -1
  43. package/dist/cli/transcript.js +0 -199
  44. package/dist/cli/transcript.js.map +0 -1
  45. package/dist/constants.js +0 -91
  46. package/dist/constants.js.map +0 -1
  47. package/dist/context/discovery.js +0 -114
  48. package/dist/context/discovery.js.map +0 -1
  49. package/dist/context/index.js +0 -82
  50. package/dist/context/index.js.map +0 -1
  51. package/dist/context/storage.js +0 -184
  52. package/dist/context/storage.js.map +0 -1
  53. package/dist/interactive/handler.js +0 -524
  54. package/dist/interactive/handler.js.map +0 -1
  55. package/dist/interactive/index.js +0 -18
  56. package/dist/interactive/index.js.map +0 -1
  57. package/dist/interactive/onboarding.js +0 -28
  58. package/dist/interactive/onboarding.js.map +0 -1
  59. package/dist/logging.js +0 -46
  60. package/dist/logging.js.map +0 -1
  61. package/dist/output/index.js +0 -8
  62. package/dist/output/index.js.map +0 -1
  63. package/dist/output/manager.js +0 -150
  64. package/dist/output/manager.js.map +0 -1
  65. package/dist/phases/complete.js +0 -142
  66. package/dist/phases/complete.js.map +0 -1
  67. package/dist/phases/locate.js +0 -64
  68. package/dist/phases/locate.js.map +0 -1
  69. package/dist/pipeline/index.js +0 -8
  70. package/dist/pipeline/index.js.map +0 -1
  71. package/dist/pipeline/orchestrator.js +0 -354
  72. package/dist/pipeline/orchestrator.js.map +0 -1
  73. package/dist/protokoll.js +0 -180
  74. package/dist/protokoll.js.map +0 -1
  75. package/dist/reasoning/client.js +0 -233
  76. package/dist/reasoning/client.js.map +0 -1
  77. package/dist/reasoning/index.js +0 -37
  78. package/dist/reasoning/index.js.map +0 -1
  79. package/dist/reasoning/strategy.js +0 -60
  80. package/dist/reasoning/strategy.js.map +0 -1
  81. package/dist/reflection/collector.js +0 -124
  82. package/dist/reflection/collector.js.map +0 -1
  83. package/dist/reflection/index.js +0 -16
  84. package/dist/reflection/index.js.map +0 -1
  85. package/dist/reflection/reporter.js +0 -238
  86. package/dist/reflection/reporter.js.map +0 -1
  87. package/dist/routing/classifier.js +0 -201
  88. package/dist/routing/classifier.js.map +0 -1
  89. package/dist/routing/index.js +0 -27
  90. package/dist/routing/index.js.map +0 -1
  91. package/dist/routing/router.js +0 -153
  92. package/dist/routing/router.js.map +0 -1
  93. package/dist/transcription/index.js +0 -41
  94. package/dist/transcription/index.js.map +0 -1
  95. package/dist/transcription/service.js +0 -64
  96. package/dist/transcription/service.js.map +0 -1
  97. package/dist/transcription/types.js +0 -31
  98. package/dist/transcription/types.js.map +0 -1
  99. package/dist/util/dates.js +0 -96
  100. package/dist/util/dates.js.map +0 -1
  101. package/dist/util/media.js +0 -103
  102. package/dist/util/media.js.map +0 -1
  103. package/dist/util/metadata.js +0 -95
  104. package/dist/util/metadata.js.map +0 -1
  105. package/dist/util/sound.js +0 -116
  106. package/dist/util/sound.js.map +0 -1
  107. package/dist/util/storage.js +0 -135
  108. package/dist/util/storage.js.map +0 -1
@@ -1,28 +0,0 @@
1
- import { getLogger } from '../logging.js';
2
-
3
- const create = (context)=>{
4
- const logger = getLogger();
5
- const checkNeedsOnboarding = ()=>{
6
- var _configWithRouting_routing_default, _configWithRouting_routing;
7
- const projects = context.getAllProjects();
8
- const config = context.getConfig();
9
- const hasProjects = projects.length > 0;
10
- const configWithRouting = config;
11
- const hasDefaultDestination = !!(configWithRouting === null || configWithRouting === void 0 ? void 0 : (_configWithRouting_routing = configWithRouting.routing) === null || _configWithRouting_routing === void 0 ? void 0 : (_configWithRouting_routing_default = _configWithRouting_routing.default) === null || _configWithRouting_routing_default === void 0 ? void 0 : _configWithRouting_routing_default.path);
12
- const hasAnyContext = context.hasContext();
13
- const state = {
14
- hasProjects,
15
- hasDefaultDestination,
16
- hasAnyContext,
17
- needsOnboarding: !hasAnyContext
18
- };
19
- logger.debug('Onboarding state checked', state);
20
- return state;
21
- };
22
- return {
23
- checkNeedsOnboarding
24
- };
25
- };
26
-
27
- export { create };
28
- //# sourceMappingURL=onboarding.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"onboarding.js","sources":["../../src/interactive/onboarding.ts"],"sourcesContent":["/**\n * Onboarding\n * \n * Handles first-run detection and bootstrap onboarding flow.\n */\n\nimport { OnboardingState, OnboardingResult } from './types';\nimport * as Context from '../context';\nimport * as Logging from '../logging';\n\nexport interface OnboardingInstance {\n checkNeedsOnboarding(): OnboardingState;\n // Note: Full interactive onboarding requires inquirer\n // This provides the state detection and result structure\n}\n\nexport const create = (context: Context.ContextInstance): OnboardingInstance => {\n const logger = Logging.getLogger();\n \n const checkNeedsOnboarding = (): OnboardingState => {\n const projects = context.getAllProjects();\n const config = context.getConfig();\n \n const hasProjects = projects.length > 0;\n const configWithRouting = config as { routing?: { default?: { path?: string } } };\n const hasDefaultDestination = !!configWithRouting?.routing?.default?.path;\n const hasAnyContext = context.hasContext();\n \n const state: OnboardingState = {\n hasProjects,\n hasDefaultDestination,\n hasAnyContext,\n needsOnboarding: !hasAnyContext,\n };\n \n logger.debug('Onboarding state checked', state);\n \n return state;\n };\n \n return { checkNeedsOnboarding };\n};\n\n/**\n * Create a default onboarding result for non-interactive mode\n */\nexport const createDefaultOnboardingResult = (): OnboardingResult => ({\n defaultDestination: '~/notes',\n defaultStructure: 'month',\n projects: [],\n completed: false,\n});\n\n"],"names":["create","context","logger","Logging","checkNeedsOnboarding","configWithRouting","projects","getAllProjects","config","getConfig","hasProjects","length","hasDefaultDestination","routing","default","path","hasAnyContext","hasContext","state","needsOnboarding","debug"],"mappings":";;AAgBO,MAAMA,SAAS,CAACC,OAAAA,GAAAA;IACnB,MAAMC,MAAAA,GAASC,SAAiB,EAAA;AAEhC,IAAA,MAAMC,oBAAAA,GAAuB,IAAA;YAMOC,kCAAAA,EAAAA,0BAAAA;QALhC,MAAMC,QAAAA,GAAWL,QAAQM,cAAc,EAAA;QACvC,MAAMC,MAAAA,GAASP,QAAQQ,SAAS,EAAA;QAEhC,MAAMC,WAAAA,GAAcJ,QAAAA,CAASK,MAAM,GAAG,CAAA;AACtC,QAAA,MAAMN,iBAAAA,GAAoBG,MAAAA;AAC1B,QAAA,MAAMI,wBAAwB,CAAC,EAACP,iBAAAA,KAAAA,IAAAA,IAAAA,iBAAAA,KAAAA,MAAAA,GAAAA,MAAAA,GAAAA,CAAAA,6BAAAA,iBAAAA,CAAmBQ,OAAO,MAAA,IAAA,IAA1BR,0BAAAA,KAAAA,MAAAA,GAAAA,MAAAA,GAAAA,CAAAA,qCAAAA,0BAAAA,CAA4BS,OAAO,MAAA,IAAA,IAAnCT,kCAAAA,KAAAA,MAAAA,GAAAA,MAAAA,GAAAA,mCAAqCU,IAAI,CAAA;QACzE,MAAMC,aAAAA,GAAgBf,QAAQgB,UAAU,EAAA;AAExC,QAAA,MAAMC,KAAAA,GAAyB;AAC3BR,YAAAA,WAAAA;AACAE,YAAAA,qBAAAA;AACAI,YAAAA,aAAAA;AACAG,YAAAA,eAAAA,EAAiB,CAACH;AACtB,SAAA;QAEAd,MAAAA,CAAOkB,KAAK,CAAC,0BAAA,EAA4BF,KAAAA,CAAAA;QAEzC,OAAOA,KAAAA;AACX,IAAA,CAAA;IAEA,OAAO;AAAEd,QAAAA;AAAqB,KAAA;AAClC;;;;"}
package/dist/logging.js DELETED
@@ -1,46 +0,0 @@
1
- import winston from 'winston';
2
- import { DATE_FORMAT_YEAR_MONTH_DAY_HOURS_MINUTES_SECONDS, PROGRAM_NAME } from './constants.js';
3
-
4
- const createLogger = (level = 'info')=>{
5
- let format = winston.format.combine(winston.format.timestamp({
6
- format: DATE_FORMAT_YEAR_MONTH_DAY_HOURS_MINUTES_SECONDS
7
- }), winston.format.errors({
8
- stack: true
9
- }), winston.format.splat(), winston.format.json());
10
- let transports = [
11
- new winston.transports.Console({
12
- format: winston.format.combine(winston.format.colorize(), winston.format.printf(({ timestamp, level, message, ...meta })=>{
13
- const metaStr = Object.keys(meta).length ? ` ${JSON.stringify(meta)}` : '';
14
- return `${timestamp} ${level}: ${message}${metaStr}`;
15
- }))
16
- })
17
- ];
18
- if (level === 'info') {
19
- format = winston.format.combine(winston.format.errors({
20
- stack: true
21
- }), winston.format.splat());
22
- transports = [
23
- new winston.transports.Console({
24
- format: winston.format.combine(winston.format.colorize(), winston.format.printf(({ level, message })=>{
25
- return `${level}: ${message}`;
26
- }))
27
- })
28
- ];
29
- }
30
- return winston.createLogger({
31
- level,
32
- format,
33
- defaultMeta: {
34
- service: PROGRAM_NAME
35
- },
36
- transports
37
- });
38
- };
39
- let logger = createLogger();
40
- const setLogLevel = (level)=>{
41
- logger = createLogger(level);
42
- };
43
- const getLogger = ()=>logger;
44
-
45
- export { getLogger, setLogLevel };
46
- //# sourceMappingURL=logging.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"logging.js","sources":["../src/logging.ts"],"sourcesContent":["import winston from 'winston';\nimport { DATE_FORMAT_YEAR_MONTH_DAY_HOURS_MINUTES_SECONDS, PROGRAM_NAME } from './constants';\n\nexport interface LogContext {\n [key: string]: any;\n}\n\nconst createLogger = (level: string = 'info') => {\n\n let format = winston.format.combine(\n winston.format.timestamp({ format: DATE_FORMAT_YEAR_MONTH_DAY_HOURS_MINUTES_SECONDS }),\n winston.format.errors({ stack: true }),\n winston.format.splat(),\n winston.format.json()\n );\n\n let transports = [\n new winston.transports.Console({\n format: winston.format.combine(\n winston.format.colorize(),\n winston.format.printf(({ timestamp, level, message, ...meta }) => {\n const metaStr = Object.keys(meta).length ? ` ${JSON.stringify(meta)}` : '';\n return `${timestamp} ${level}: ${message}${metaStr}`;\n })\n )\n })\n ];\n\n if (level === 'info') {\n format = winston.format.combine(\n winston.format.errors({ stack: true }),\n winston.format.splat(),\n );\n\n transports = [\n new winston.transports.Console({\n format: winston.format.combine(\n winston.format.colorize(),\n winston.format.printf(({ level, message }) => {\n return `${level}: ${message}`;\n })\n )\n })\n ];\n }\n\n return winston.createLogger({\n level,\n format,\n defaultMeta: { service: PROGRAM_NAME },\n transports,\n });\n};\n\nlet logger = createLogger();\n\nexport const setLogLevel = (level: string) => {\n logger = createLogger(level);\n};\n\nexport const getLogger = () => logger; "],"names":["createLogger","level","format","winston","combine","timestamp","DATE_FORMAT_YEAR_MONTH_DAY_HOURS_MINUTES_SECONDS","errors","stack","splat","json","transports","Console","colorize","printf","message","meta","metaStr","Object","keys","length","JSON","stringify","defaultMeta","service","PROGRAM_NAME","logger","setLogLevel","getLogger"],"mappings":";;;AAOA,MAAMA,YAAAA,GAAe,CAACC,KAAAA,GAAgB,MAAM,GAAA;IAExC,IAAIC,MAAAA,GAASC,OAAAA,CAAQD,MAAM,CAACE,OAAO,CAC/BD,OAAAA,CAAQD,MAAM,CAACG,SAAS,CAAC;QAAEH,MAAAA,EAAQI;AAAiD,KAAA,CAAA,EACpFH,OAAAA,CAAQD,MAAM,CAACK,MAAM,CAAC;QAAEC,KAAAA,EAAO;KAAK,CAAA,EACpCL,OAAAA,CAAQD,MAAM,CAACO,KAAK,IACpBN,OAAAA,CAAQD,MAAM,CAACQ,IAAI,EAAA,CAAA;AAGvB,IAAA,IAAIC,UAAAA,GAAa;AACb,QAAA,IAAIR,OAAAA,CAAQQ,UAAU,CAACC,OAAO,CAAC;YAC3BV,MAAAA,EAAQC,OAAAA,CAAQD,MAAM,CAACE,OAAO,CAC1BD,QAAQD,MAAM,CAACW,QAAQ,EAAA,EACvBV,OAAAA,CAAQD,MAAM,CAACY,MAAM,CAAC,CAAC,EAAET,SAAS,EAAEJ,KAAK,EAAEc,OAAO,EAAE,GAAGC,IAAAA,EAAM,GAAA;AACzD,gBAAA,MAAMC,OAAAA,GAAUC,MAAAA,CAAOC,IAAI,CAACH,MAAMI,MAAM,GAAG,CAAC,CAAC,EAAEC,IAAAA,CAAKC,SAAS,CAACN,OAAO,GAAG,EAAA;gBACxE,OAAO,CAAA,EAAGX,UAAU,CAAC,EAAEJ,MAAM,EAAE,EAAEc,UAAUE,OAAAA,CAAAA,CAAS;AACxD,YAAA,CAAA,CAAA;AAER,SAAA;AACH,KAAA;AAED,IAAA,IAAIhB,UAAU,MAAA,EAAQ;QAClBC,MAAAA,GAASC,OAAAA,CAAQD,MAAM,CAACE,OAAO,CAC3BD,OAAAA,CAAQD,MAAM,CAACK,MAAM,CAAC;YAAEC,KAAAA,EAAO;SAAK,CAAA,EACpCL,OAAAA,CAAQD,MAAM,CAACO,KAAK,EAAA,CAAA;QAGxBE,UAAAA,GAAa;AACT,YAAA,IAAIR,OAAAA,CAAQQ,UAAU,CAACC,OAAO,CAAC;gBAC3BV,MAAAA,EAAQC,OAAAA,CAAQD,MAAM,CAACE,OAAO,CAC1BD,OAAAA,CAAQD,MAAM,CAACW,QAAQ,EAAA,EACvBV,QAAQD,MAAM,CAACY,MAAM,CAAC,CAAC,EAAEb,KAAK,EAAEc,OAAO,EAAE,GAAA;AACrC,oBAAA,OAAO,CAAA,EAAGd,KAAAA,CAAM,EAAE,EAAEc,OAAAA,CAAAA,CAAS;AACjC,gBAAA,CAAA,CAAA;AAER,aAAA;AACH,SAAA;AACL,IAAA;IAEA,OAAOZ,OAAAA,CAAQH,YAAY,CAAC;AACxBC,QAAAA,KAAAA;AACAC,QAAAA,MAAAA;QACAqB,WAAAA,EAAa;YAAEC,OAAAA,EAASC;AAAa,SAAA;AACrCd,QAAAA;AACJ,KAAA,CAAA;AACJ,CAAA;AAEA,IAAIe,MAAAA,GAAS1B,YAAAA,EAAAA;AAEN,MAAM2B,cAAc,CAAC1B,KAAAA,GAAAA;AACxByB,IAAAA,MAAAA,GAAS1B,YAAAA,CAAaC,KAAAA,CAAAA;AAC1B;AAEO,MAAM2B,SAAAA,GAAY,IAAMF;;;;"}
@@ -1,8 +0,0 @@
1
- import { create as create$1 } from './manager.js';
2
-
3
- const create = (config)=>{
4
- return create$1(config);
5
- };
6
-
7
- export { create };
8
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
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,150 +0,0 @@
1
- import * as path from 'node:path';
2
- import * as fs from 'fs/promises';
3
- import { getLogger } from '../logging.js';
4
- import { formatMetadataMarkdown } from '../util/metadata.js';
5
-
6
- const create = (config)=>{
7
- const logger = getLogger();
8
- const formatTimestamp = (date)=>{
9
- // Format: YYYY-MM-DD-HHmm (full year, dashes for separation)
10
- const pad = (n)=>n.toString().padStart(2, '0');
11
- const year = date.getFullYear().toString();
12
- const month = pad(date.getMonth() + 1);
13
- const day = pad(date.getDate());
14
- const hours = pad(date.getHours());
15
- const minutes = pad(date.getMinutes());
16
- return `${year}-${month}-${day}-${hours}${minutes}`;
17
- };
18
- const createOutputPaths = (_audioFile, routedDestination, hash, date)=>{
19
- const timestamp = formatTimestamp(date);
20
- const shortHash = hash.slice(0, 6);
21
- // Hash at the end for easier filename correlation
22
- const buildFilename = (type, ext)=>`${timestamp}-${type}-${shortHash}${ext}`;
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`);
29
- return {
30
- final: routedDestination,
31
- rawTranscript: rawTranscriptPath,
32
- intermediate: {
33
- transcript: path.join(intermediateDir, buildFilename('transcript', '.json')),
34
- context: path.join(intermediateDir, buildFilename('context', '.json')),
35
- request: path.join(intermediateDir, buildFilename('request', '.json')),
36
- response: path.join(intermediateDir, buildFilename('response', '.json')),
37
- reflection: path.join(intermediateDir, buildFilename('reflection', '.md')),
38
- session: path.join(intermediateDir, buildFilename('session', '.json'))
39
- }
40
- };
41
- };
42
- const ensureDirectories = async (paths)=>{
43
- // Ensure intermediate directory
44
- await fs.mkdir(path.dirname(paths.intermediate.transcript), {
45
- recursive: true
46
- });
47
- // Ensure final directory
48
- await fs.mkdir(path.dirname(paths.final), {
49
- recursive: true
50
- });
51
- // Ensure .transcript directory alongside final output
52
- await fs.mkdir(path.dirname(paths.rawTranscript), {
53
- recursive: true
54
- });
55
- logger.debug('Ensured output directories', {
56
- intermediate: path.dirname(paths.intermediate.transcript),
57
- final: path.dirname(paths.final),
58
- rawTranscript: path.dirname(paths.rawTranscript)
59
- });
60
- };
61
- const writeIntermediate = async (paths, type, content)=>{
62
- const filePath = paths.intermediate[type];
63
- if (!filePath) {
64
- throw new Error(`Invalid intermediate type: ${type}`);
65
- }
66
- const contentStr = typeof content === 'string' ? content : JSON.stringify(content, null, 2);
67
- await fs.writeFile(filePath, contentStr, 'utf-8');
68
- logger.debug('Wrote intermediate file', {
69
- type,
70
- path: filePath
71
- });
72
- return filePath;
73
- };
74
- const writeTranscript = async (paths, content, metadata)=>{
75
- // Prepend metadata if provided
76
- let finalContent = content;
77
- if (metadata) {
78
- const metadataSection = formatMetadataMarkdown(metadata);
79
- finalContent = metadataSection + content;
80
- }
81
- await fs.writeFile(paths.final, finalContent, 'utf-8');
82
- logger.info('Wrote final transcript', {
83
- path: paths.final
84
- });
85
- return paths.final;
86
- };
87
- const cleanIntermediates = async (paths)=>{
88
- if (config.keepIntermediates) {
89
- logger.debug('Keeping intermediate files');
90
- return;
91
- }
92
- for (const [type, filePath] of Object.entries(paths.intermediate)){
93
- if (filePath) {
94
- try {
95
- await fs.unlink(filePath);
96
- logger.debug('Removed intermediate file', {
97
- type,
98
- path: filePath
99
- });
100
- } catch {
101
- // File might not exist, that's OK
102
- }
103
- }
104
- }
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
- };
138
- return {
139
- createOutputPaths,
140
- ensureDirectories,
141
- writeIntermediate,
142
- writeRawTranscript,
143
- writeTranscript,
144
- readRawTranscript,
145
- cleanIntermediates
146
- };
147
- };
148
-
149
- export { create };
150
- //# sourceMappingURL=manager.js.map
@@ -1 +0,0 @@
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,142 +0,0 @@
1
- import * as path from 'node: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
- // 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
- };
79
- const complete = async (audioFile, hash, creationTime, subject)=>{
80
- logger.debug('Completing file processing for %s', audioFile);
81
- if (config.dryRun) {
82
- logger.info('Dry run: would move %s to processed directory', audioFile);
83
- return audioFile;
84
- }
85
- if (!config.processedDirectory) {
86
- logger.debug('No processed directory configured, skipping file move');
87
- return audioFile;
88
- }
89
- // Build the target directory path with year/month structure
90
- const targetDir = buildDirectoryPath(creationTime);
91
- // Create the target directory if it doesn't exist
92
- if (!await storage.exists(targetDir)) {
93
- logger.debug('Creating processed directory %s', targetDir);
94
- await storage.createDirectory(targetDir);
95
- }
96
- // Get the file extension
97
- const fileExt = path.extname(audioFile);
98
- // Format date for filename (adjusted based on directory structure)
99
- const dateStr = formatDateForFilename(creationTime);
100
- // Create new filename: <date>-<subject>-<hash>
101
- // Hash is at the end for easier correlation with output files
102
- // Clean subject by removing special characters and spaces
103
- // Also strip any existing date/hash patterns from the subject
104
- const shortHash = hash.substring(0, 6);
105
- let newFilename;
106
- if (subject) {
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
- }
116
- } else {
117
- newFilename = `${dateStr}-${shortHash}${fileExt}`;
118
- }
119
- const newFilePath = path.join(targetDir, newFilename);
120
- try {
121
- // Read the original file
122
- const fileContent = await storage.readFile(audioFile, 'binary');
123
- // Write to the new location
124
- logger.debug('Moving file from %s to %s', audioFile, newFilePath);
125
- await storage.writeFile(newFilePath, fileContent, 'binary');
126
- // Remove the original file
127
- await storage.deleteFile(audioFile);
128
- logger.info('Moved to processed: %s', newFilePath);
129
- return newFilePath;
130
- } catch (error) {
131
- logger.error('Failed to move file to processed directory: %s', error);
132
- // Don't fail the whole process, just log the error
133
- return audioFile;
134
- }
135
- };
136
- return {
137
- complete
138
- };
139
- };
140
-
141
- export { create };
142
- //# sourceMappingURL=complete.js.map
@@ -1 +0,0 @@
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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"}
@@ -1,64 +0,0 @@
1
- import { getLogger } from '../logging.js';
2
- import { create as create$3 } from '../util/media.js';
3
- import { create as create$1 } from '../util/storage.js';
4
- import { create as create$2 } from '../util/dates.js';
5
- import { DEFAULT_INTERMEDIATE_DIRECTORY } from '../constants.js';
6
- import path__default from 'node:path';
7
-
8
- const create = (config, operator)=>{
9
- const logger = getLogger();
10
- const storage = create$1({
11
- log: logger.debug
12
- });
13
- const dates = create$2({
14
- timezone: config.timezone
15
- });
16
- const media = create$3(logger);
17
- const locate = async (audioFile)=>{
18
- logger.debug('Processing file %s', audioFile);
19
- // Extract audio file creation time
20
- let creationTime = await media.getAudioCreationTime(audioFile);
21
- try {
22
- if (creationTime) {
23
- logger.info('Audio recording time: %s', creationTime.toISOString());
24
- } else {
25
- logger.warn('Could not determine audio recording time for %s, using current date', audioFile);
26
- creationTime = dates.now();
27
- }
28
- } catch (error) {
29
- logger.error('Error determining audio recording time for %s: %s, using current date', audioFile, error.message);
30
- creationTime = dates.now();
31
- }
32
- // Calculate the hash of file and output directory
33
- const hash = (await storage.hashFile(audioFile, 100)).substring(0, 8);
34
- const outputPath = await operator.constructOutputDirectory(creationTime);
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);
48
- return {
49
- creationTime,
50
- outputPath,
51
- contextPath,
52
- interimPath,
53
- transcriptionFilename,
54
- hash,
55
- audioFile
56
- };
57
- };
58
- return {
59
- locate
60
- };
61
- };
62
-
63
- export { create };
64
- //# sourceMappingURL=locate.js.map
@@ -1 +0,0 @@
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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"}
@@ -1,8 +0,0 @@
1
- import { create as create$1 } from './orchestrator.js';
2
-
3
- const create = async (config)=>{
4
- return create$1(config);
5
- };
6
-
7
- export { create };
8
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
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;;;;"}