@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.
- package/README.md +199 -0
- package/dist/feedback.js +5193 -0
- package/dist/feedback.js.map +1 -0
- package/dist/main.js +1858 -9
- package/dist/main.js.map +1 -1
- package/dist/mcp/server.js +1330 -0
- package/dist/mcp/server.js.map +1 -0
- package/guide/index.md +16 -0
- package/guide/mcp-integration.md +341 -0
- package/package.json +5 -3
- package/tsconfig.tsbuildinfo +1 -1
- package/vite.config.ts +13 -29
- package/dist/agentic/executor.js +0 -747
- package/dist/agentic/executor.js.map +0 -1
- package/dist/agentic/index.js +0 -19
- package/dist/agentic/index.js.map +0 -1
- package/dist/agentic/registry.js +0 -41
- package/dist/agentic/registry.js.map +0 -1
- package/dist/agentic/tools/lookup-person.js +0 -185
- package/dist/agentic/tools/lookup-person.js.map +0 -1
- package/dist/agentic/tools/lookup-project.js +0 -210
- package/dist/agentic/tools/lookup-project.js.map +0 -1
- package/dist/agentic/tools/route-note.js +0 -49
- package/dist/agentic/tools/route-note.js.map +0 -1
- package/dist/agentic/tools/store-context.js +0 -51
- package/dist/agentic/tools/store-context.js.map +0 -1
- package/dist/agentic/tools/verify-spelling.js +0 -57
- package/dist/agentic/tools/verify-spelling.js.map +0 -1
- package/dist/arguments.js +0 -178
- package/dist/arguments.js.map +0 -1
- package/dist/cli/action.js +0 -704
- package/dist/cli/action.js.map +0 -1
- package/dist/cli/config.js +0 -482
- package/dist/cli/config.js.map +0 -1
- package/dist/cli/context.js +0 -466
- package/dist/cli/context.js.map +0 -1
- package/dist/cli/feedback.js +0 -858
- package/dist/cli/feedback.js.map +0 -1
- package/dist/cli/index.js +0 -103
- package/dist/cli/index.js.map +0 -1
- package/dist/cli/install.js +0 -572
- package/dist/cli/install.js.map +0 -1
- package/dist/cli/transcript.js +0 -199
- package/dist/cli/transcript.js.map +0 -1
- package/dist/constants.js +0 -91
- package/dist/constants.js.map +0 -1
- package/dist/context/discovery.js +0 -114
- package/dist/context/discovery.js.map +0 -1
- package/dist/context/index.js +0 -82
- package/dist/context/index.js.map +0 -1
- package/dist/context/storage.js +0 -184
- package/dist/context/storage.js.map +0 -1
- package/dist/interactive/handler.js +0 -524
- package/dist/interactive/handler.js.map +0 -1
- package/dist/interactive/index.js +0 -18
- package/dist/interactive/index.js.map +0 -1
- package/dist/interactive/onboarding.js +0 -28
- package/dist/interactive/onboarding.js.map +0 -1
- package/dist/logging.js +0 -46
- package/dist/logging.js.map +0 -1
- package/dist/output/index.js +0 -8
- package/dist/output/index.js.map +0 -1
- package/dist/output/manager.js +0 -150
- package/dist/output/manager.js.map +0 -1
- package/dist/phases/complete.js +0 -142
- package/dist/phases/complete.js.map +0 -1
- package/dist/phases/locate.js +0 -64
- package/dist/phases/locate.js.map +0 -1
- package/dist/pipeline/index.js +0 -8
- package/dist/pipeline/index.js.map +0 -1
- package/dist/pipeline/orchestrator.js +0 -354
- package/dist/pipeline/orchestrator.js.map +0 -1
- package/dist/protokoll.js +0 -180
- package/dist/protokoll.js.map +0 -1
- package/dist/reasoning/client.js +0 -233
- package/dist/reasoning/client.js.map +0 -1
- package/dist/reasoning/index.js +0 -37
- package/dist/reasoning/index.js.map +0 -1
- package/dist/reasoning/strategy.js +0 -60
- package/dist/reasoning/strategy.js.map +0 -1
- package/dist/reflection/collector.js +0 -124
- package/dist/reflection/collector.js.map +0 -1
- package/dist/reflection/index.js +0 -16
- package/dist/reflection/index.js.map +0 -1
- package/dist/reflection/reporter.js +0 -238
- package/dist/reflection/reporter.js.map +0 -1
- package/dist/routing/classifier.js +0 -201
- package/dist/routing/classifier.js.map +0 -1
- package/dist/routing/index.js +0 -27
- package/dist/routing/index.js.map +0 -1
- package/dist/routing/router.js +0 -153
- package/dist/routing/router.js.map +0 -1
- package/dist/transcription/index.js +0 -41
- package/dist/transcription/index.js.map +0 -1
- package/dist/transcription/service.js +0 -64
- package/dist/transcription/service.js.map +0 -1
- package/dist/transcription/types.js +0 -31
- package/dist/transcription/types.js.map +0 -1
- package/dist/util/dates.js +0 -96
- package/dist/util/dates.js.map +0 -1
- package/dist/util/media.js +0 -103
- package/dist/util/media.js.map +0 -1
- package/dist/util/metadata.js +0 -95
- package/dist/util/metadata.js.map +0 -1
- package/dist/util/sound.js +0 -116
- package/dist/util/sound.js.map +0 -1
- package/dist/util/storage.js +0 -135
- 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
|
package/dist/logging.js.map
DELETED
|
@@ -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;;;;"}
|
package/dist/output/index.js
DELETED
package/dist/output/index.js.map
DELETED
|
@@ -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;;;;"}
|
package/dist/output/manager.js
DELETED
|
@@ -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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"}
|
package/dist/phases/complete.js
DELETED
|
@@ -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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"}
|
package/dist/phases/locate.js
DELETED
|
@@ -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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"}
|
package/dist/pipeline/index.js
DELETED
|
@@ -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;;;;"}
|