@redaksjon/protokoll 0.0.12 → 0.0.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.cursor/rules/definition-of-done.md +1 -0
- package/.cursor/rules/no-emoticons.md +26 -12
- package/README.md +483 -69
- package/dist/agentic/executor.js +473 -41
- package/dist/agentic/executor.js.map +1 -1
- package/dist/agentic/index.js.map +1 -1
- package/dist/agentic/tools/lookup-person.js +123 -4
- package/dist/agentic/tools/lookup-person.js.map +1 -1
- package/dist/agentic/tools/lookup-project.js +139 -22
- package/dist/agentic/tools/lookup-project.js.map +1 -1
- package/dist/agentic/tools/route-note.js +5 -1
- package/dist/agentic/tools/route-note.js.map +1 -1
- package/dist/arguments.js +6 -3
- package/dist/arguments.js.map +1 -1
- package/dist/cli/action.js +704 -0
- package/dist/cli/action.js.map +1 -0
- package/dist/cli/config.js +482 -0
- package/dist/cli/config.js.map +1 -0
- package/dist/cli/context.js +466 -0
- package/dist/cli/context.js.map +1 -0
- package/dist/cli/feedback.js +858 -0
- package/dist/cli/feedback.js.map +1 -0
- package/dist/cli/index.js +103 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/install.js +572 -0
- package/dist/cli/install.js.map +1 -0
- package/dist/cli/transcript.js +199 -0
- package/dist/cli/transcript.js.map +1 -0
- package/dist/constants.js +11 -4
- package/dist/constants.js.map +1 -1
- package/dist/context/index.js +25 -1
- package/dist/context/index.js.map +1 -1
- package/dist/context/storage.js +56 -3
- package/dist/context/storage.js.map +1 -1
- package/dist/interactive/handler.js +310 -9
- package/dist/interactive/handler.js.map +1 -1
- package/dist/main.js +11 -1
- package/dist/main.js.map +1 -1
- package/dist/output/index.js.map +1 -1
- package/dist/output/manager.js +46 -1
- package/dist/output/manager.js.map +1 -1
- package/dist/phases/complete.js +37 -2
- package/dist/phases/complete.js.map +1 -1
- package/dist/pipeline/orchestrator.js +104 -31
- package/dist/pipeline/orchestrator.js.map +1 -1
- package/dist/protokoll.js +68 -2
- package/dist/protokoll.js.map +1 -1
- package/dist/reasoning/client.js +83 -0
- package/dist/reasoning/client.js.map +1 -1
- package/dist/reasoning/index.js +1 -0
- package/dist/reasoning/index.js.map +1 -1
- package/dist/util/metadata.js.map +1 -1
- package/dist/util/sound.js +116 -0
- package/dist/util/sound.js.map +1 -0
- package/docs/duplicate-question-prevention.md +117 -0
- package/docs/examples.md +152 -0
- package/docs/interactive-context-example.md +92 -0
- package/docs/package-lock.json +6 -0
- package/docs/package.json +3 -1
- package/guide/action.md +375 -0
- package/guide/config.md +207 -0
- package/guide/configuration.md +82 -67
- package/guide/context-commands.md +574 -0
- package/guide/context-system.md +20 -7
- package/guide/development.md +106 -4
- package/guide/feedback.md +335 -0
- package/guide/index.md +100 -4
- package/guide/interactive.md +15 -14
- package/guide/quickstart.md +21 -7
- package/guide/reasoning.md +18 -4
- package/guide/routing.md +192 -97
- package/package.json +1 -1
- package/scripts/coverage-priority.mjs +323 -0
- package/tsconfig.tsbuildinfo +1 -1
- package/vitest.config.ts +5 -1
|
@@ -2,8 +2,83 @@
|
|
|
2
2
|
* Lookup Project Tool
|
|
3
3
|
*
|
|
4
4
|
* Looks up project information for routing and context.
|
|
5
|
-
*
|
|
6
|
-
*/
|
|
5
|
+
* Prompts to create unknown projects when user input is available.
|
|
6
|
+
*/ /**
|
|
7
|
+
* Extract context from transcript around where a term is mentioned.
|
|
8
|
+
* Returns approximately one sentence before and after the term mention.
|
|
9
|
+
*/ function extractTermContext(transcript, term) {
|
|
10
|
+
// Case-insensitive search for the term
|
|
11
|
+
const lowerTranscript = transcript.toLowerCase();
|
|
12
|
+
const lowerTerm = term.toLowerCase();
|
|
13
|
+
const index = lowerTranscript.indexOf(lowerTerm);
|
|
14
|
+
if (index === -1) {
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
// Define strong sentence boundaries (., !, ?)
|
|
18
|
+
const sentenceBoundary = /[.!?]/;
|
|
19
|
+
// Look backwards for the start (find the sentence boundary 1 sentence before)
|
|
20
|
+
let startIndex = 0;
|
|
21
|
+
let boundariesFound = 0;
|
|
22
|
+
for(let i = index - 1; i >= 0; i--){
|
|
23
|
+
if (sentenceBoundary.test(transcript[i])) {
|
|
24
|
+
boundariesFound++;
|
|
25
|
+
// After finding first boundary (end of current sentence),
|
|
26
|
+
// keep looking for the second (end of previous sentence)
|
|
27
|
+
if (boundariesFound === 2) {
|
|
28
|
+
// Start after this boundary
|
|
29
|
+
startIndex = i + 1;
|
|
30
|
+
break;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
// Look forwards for the end (find sentence boundary 1 sentence after)
|
|
35
|
+
let endIndex = transcript.length;
|
|
36
|
+
boundariesFound = 0;
|
|
37
|
+
for(let i = index + term.length; i < transcript.length; i++){
|
|
38
|
+
if (sentenceBoundary.test(transcript[i])) {
|
|
39
|
+
boundariesFound++;
|
|
40
|
+
// After finding first boundary (end of current sentence),
|
|
41
|
+
// keep looking for the second (end of next sentence)
|
|
42
|
+
if (boundariesFound === 2) {
|
|
43
|
+
// Include this boundary
|
|
44
|
+
endIndex = i + 1;
|
|
45
|
+
break;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
// Extract and clean up the context
|
|
50
|
+
let context = transcript.substring(startIndex, endIndex).trim();
|
|
51
|
+
// Limit length to avoid overwhelming the prompt (max ~300 chars)
|
|
52
|
+
if (context.length > 300) {
|
|
53
|
+
// Try to cut at a sentence boundary
|
|
54
|
+
const midPoint = context.indexOf(term);
|
|
55
|
+
if (midPoint !== -1) {
|
|
56
|
+
// Keep the sentence with the term, trim around it
|
|
57
|
+
let sentenceStart = midPoint;
|
|
58
|
+
let sentenceEnd = midPoint + term.length;
|
|
59
|
+
// Find sentence start
|
|
60
|
+
for(let i = midPoint - 1; i >= 0; i--){
|
|
61
|
+
if (sentenceBoundary.test(context[i])) {
|
|
62
|
+
sentenceStart = i + 1;
|
|
63
|
+
break;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
// Find sentence end
|
|
67
|
+
for(let i = midPoint + term.length; i < context.length; i++){
|
|
68
|
+
if (sentenceBoundary.test(context[i])) {
|
|
69
|
+
sentenceEnd = i + 1;
|
|
70
|
+
break;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
context = context.substring(sentenceStart, sentenceEnd).trim();
|
|
74
|
+
} else {
|
|
75
|
+
// Just truncate if term not found in extracted context
|
|
76
|
+
context = context.substring(0, 300) + '...';
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return context;
|
|
80
|
+
}
|
|
81
|
+
const create = (ctx)=>({
|
|
7
82
|
name: 'lookup_project',
|
|
8
83
|
description: 'Look up project information for routing and context. Use when you need to determine where this note should be filed.',
|
|
9
84
|
parameters: {
|
|
@@ -23,7 +98,31 @@
|
|
|
23
98
|
]
|
|
24
99
|
},
|
|
25
100
|
execute: async (args)=>{
|
|
101
|
+
var _ctx_resolvedEntities;
|
|
26
102
|
const context = ctx.contextInstance;
|
|
103
|
+
// First, check if this project/term was already resolved in this session
|
|
104
|
+
if ((_ctx_resolvedEntities = ctx.resolvedEntities) === null || _ctx_resolvedEntities === void 0 ? void 0 : _ctx_resolvedEntities.has(args.name)) {
|
|
105
|
+
const resolvedName = ctx.resolvedEntities.get(args.name);
|
|
106
|
+
return {
|
|
107
|
+
success: true,
|
|
108
|
+
data: {
|
|
109
|
+
found: true,
|
|
110
|
+
suggestion: `Already resolved: use "${resolvedName}"`,
|
|
111
|
+
cached: true
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
// Check if this term is on the ignore list
|
|
116
|
+
if (context.isIgnored(args.name)) {
|
|
117
|
+
return {
|
|
118
|
+
success: true,
|
|
119
|
+
data: {
|
|
120
|
+
found: false,
|
|
121
|
+
ignored: true,
|
|
122
|
+
message: `"${args.name}" is on the ignore list - skipping without prompting`
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
}
|
|
27
126
|
// Look up project by name
|
|
28
127
|
const projects = context.search(args.name);
|
|
29
128
|
const projectMatches = projects.filter((e)=>e.type === 'project');
|
|
@@ -59,31 +158,49 @@
|
|
|
59
158
|
}
|
|
60
159
|
}
|
|
61
160
|
}
|
|
62
|
-
// Project not found -
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
}
|
|
161
|
+
// Project not found - always signal that we need user input
|
|
162
|
+
// The executor will decide whether to actually prompt based on handler availability
|
|
163
|
+
const allProjects = context.getAllProjects();
|
|
164
|
+
const projectOptions = allProjects.filter((p)=>p.active !== false).map((p)=>`${p.name}${p.description ? ` - ${p.description}` : ''}`);
|
|
165
|
+
// Extract filename from sourceFile path for cleaner display
|
|
166
|
+
const fileName = ctx.sourceFile.split('/').pop() || ctx.sourceFile;
|
|
167
|
+
const fileDate = ctx.audioDate.toLocaleString('en-US', {
|
|
168
|
+
weekday: 'short',
|
|
169
|
+
year: 'numeric',
|
|
170
|
+
month: 'short',
|
|
171
|
+
day: 'numeric',
|
|
172
|
+
hour: '2-digit',
|
|
173
|
+
minute: '2-digit'
|
|
174
|
+
});
|
|
175
|
+
// Find context from transcript where the project/term is mentioned
|
|
176
|
+
const transcriptContext = extractTermContext(ctx.transcriptText, args.name);
|
|
177
|
+
const contextLines = [
|
|
178
|
+
`File: ${fileName}`,
|
|
179
|
+
`Date: ${fileDate}`,
|
|
180
|
+
'',
|
|
181
|
+
`Unknown project/term: "${args.name}"`
|
|
182
|
+
];
|
|
183
|
+
if (transcriptContext) {
|
|
184
|
+
contextLines.push('');
|
|
185
|
+
contextLines.push('Context from transcript:');
|
|
186
|
+
contextLines.push(`"${transcriptContext}"`);
|
|
187
|
+
} else if (args.triggerPhrase) {
|
|
188
|
+
contextLines.push('');
|
|
189
|
+
contextLines.push('Context from transcript:');
|
|
190
|
+
contextLines.push(`"${args.triggerPhrase}"`);
|
|
80
191
|
}
|
|
81
|
-
// Non-interactive mode - just use default
|
|
82
192
|
return {
|
|
83
193
|
success: true,
|
|
194
|
+
needsUserInput: true,
|
|
195
|
+
userPrompt: contextLines.join('\n'),
|
|
84
196
|
data: {
|
|
85
197
|
found: false,
|
|
86
|
-
|
|
198
|
+
clarificationType: 'new_project',
|
|
199
|
+
term: args.name,
|
|
200
|
+
triggerPhrase: args.triggerPhrase,
|
|
201
|
+
message: `Project "${args.name}" not found. Asking user if this is a new project.`,
|
|
202
|
+
knownProjects: allProjects.filter((p)=>p.active !== false),
|
|
203
|
+
options: projectOptions
|
|
87
204
|
}
|
|
88
205
|
};
|
|
89
206
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lookup-project.js","sources":["../../../src/agentic/tools/lookup-project.ts"],"sourcesContent":["/**\n * Lookup Project Tool\n * \n * Looks up project information for routing and context.\n * In interactive mode, prompts to create unknown projects.\n */\n\nimport { TranscriptionTool, ToolContext, ToolResult } from '../types';\n\nexport const create = (ctx: ToolContext): TranscriptionTool => ({\n name: 'lookup_project',\n description: 'Look up project information for routing and context. Use when you need to determine where this note should be filed.',\n parameters: {\n type: 'object',\n properties: {\n name: {\n type: 'string',\n description: 'The project name or identifier',\n },\n triggerPhrase: {\n type: 'string',\n description: 'A phrase from the transcript that might indicate the project',\n },\n },\n required: ['name'],\n },\n execute: async (args: { name: string; triggerPhrase?: string }): Promise<ToolResult> => {\n const context = ctx.contextInstance;\n \n // Look up project by name\n const projects = context.search(args.name);\n const projectMatches = projects.filter(e => e.type === 'project');\n \n if (projectMatches.length > 0) {\n const project = projectMatches[0];\n return {\n success: true,\n data: {\n found: true,\n project,\n },\n };\n }\n \n // Try getting all projects and matching trigger phrases\n if (args.triggerPhrase) {\n const allProjects = context.getAllProjects();\n for (const project of allProjects) {\n const phrases = project.classification?.explicit_phrases ?? [];\n if (phrases.some(p => args.triggerPhrase?.toLowerCase().includes(p.toLowerCase()))) {\n return {\n success: true,\n data: {\n found: true,\n project,\n matchedTrigger: args.triggerPhrase,\n },\n };\n }\n }\n }\n \n // Project not found - in interactive mode, ask about creating it\n if (ctx.interactiveMode) {\n return {\n success: true,\n needsUserInput: true,\n userPrompt: `Unknown project: \"${args.name}\"\n${args.triggerPhrase ? `Trigger phrase: \"${args.triggerPhrase}\"` : ''}\n\nIs \"${args.name}\" a new project? If yes, where should notes about it be stored?\nEnter a path (e.g., ~/notes/projects/${args.name.toLowerCase().replace(/\\s+/g, '-')}) or press Enter to use default routing:`,\n data: {\n found: false,\n clarificationType: 'new_project',\n term: args.name,\n triggerPhrase: args.triggerPhrase,\n message: `Project \"${args.name}\" not found. Asking user if this is a new project.`,\n },\n };\n }\n \n // Non-interactive mode - just use default\n return {\n success: true,\n data: {\n found: false,\n message: `No project found for \"${args.name}\". Will use default routing.`,\n },\n };\n },\n});\n\n"],"names":["create","ctx","name","description","parameters","type","properties","triggerPhrase","required","execute","args","context","contextInstance","projects","search","projectMatches","filter","e","length","project","success","data","found","allProjects","getAllProjects","phrases","classification","explicit_phrases","some","p","toLowerCase","includes","matchedTrigger","interactiveMode","needsUserInput","userPrompt","replace","clarificationType","term","message"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"lookup-project.js","sources":["../../../src/agentic/tools/lookup-project.ts"],"sourcesContent":["/**\n * Lookup Project Tool\n * \n * Looks up project information for routing and context.\n * Prompts to create unknown projects when user input is available.\n */\n\nimport { TranscriptionTool, ToolContext, ToolResult } from '../types';\n\n/**\n * Extract context from transcript around where a term is mentioned.\n * Returns approximately one sentence before and after the term mention.\n */\nfunction extractTermContext(transcript: string, term: string): string | null {\n // Case-insensitive search for the term\n const lowerTranscript = transcript.toLowerCase();\n const lowerTerm = term.toLowerCase();\n const index = lowerTranscript.indexOf(lowerTerm);\n \n if (index === -1) {\n return null;\n }\n \n // Define strong sentence boundaries (., !, ?)\n const sentenceBoundary = /[.!?]/;\n \n // Look backwards for the start (find the sentence boundary 1 sentence before)\n let startIndex = 0;\n let boundariesFound = 0;\n for (let i = index - 1; i >= 0; i--) {\n if (sentenceBoundary.test(transcript[i])) {\n boundariesFound++;\n // After finding first boundary (end of current sentence), \n // keep looking for the second (end of previous sentence)\n if (boundariesFound === 2) {\n // Start after this boundary\n startIndex = i + 1;\n break;\n }\n }\n }\n \n // Look forwards for the end (find sentence boundary 1 sentence after)\n let endIndex = transcript.length;\n boundariesFound = 0;\n for (let i = index + term.length; i < transcript.length; i++) {\n if (sentenceBoundary.test(transcript[i])) {\n boundariesFound++;\n // After finding first boundary (end of current sentence),\n // keep looking for the second (end of next sentence)\n if (boundariesFound === 2) {\n // Include this boundary\n endIndex = i + 1;\n break;\n }\n }\n }\n \n // Extract and clean up the context\n let context = transcript.substring(startIndex, endIndex).trim();\n \n // Limit length to avoid overwhelming the prompt (max ~300 chars)\n if (context.length > 300) {\n // Try to cut at a sentence boundary\n const midPoint = context.indexOf(term);\n if (midPoint !== -1) {\n // Keep the sentence with the term, trim around it\n let sentenceStart = midPoint;\n let sentenceEnd = midPoint + term.length;\n \n // Find sentence start\n for (let i = midPoint - 1; i >= 0; i--) {\n if (sentenceBoundary.test(context[i])) {\n sentenceStart = i + 1;\n break;\n }\n }\n \n // Find sentence end\n for (let i = midPoint + term.length; i < context.length; i++) {\n if (sentenceBoundary.test(context[i])) {\n sentenceEnd = i + 1;\n break;\n }\n }\n \n context = context.substring(sentenceStart, sentenceEnd).trim();\n } else {\n // Just truncate if term not found in extracted context\n context = context.substring(0, 300) + '...';\n }\n }\n \n return context;\n}\n\nexport const create = (ctx: ToolContext): TranscriptionTool => ({\n name: 'lookup_project',\n description: 'Look up project information for routing and context. Use when you need to determine where this note should be filed.',\n parameters: {\n type: 'object',\n properties: {\n name: {\n type: 'string',\n description: 'The project name or identifier',\n },\n triggerPhrase: {\n type: 'string',\n description: 'A phrase from the transcript that might indicate the project',\n },\n },\n required: ['name'],\n },\n execute: async (args: { name: string; triggerPhrase?: string }): Promise<ToolResult> => {\n const context = ctx.contextInstance;\n \n // First, check if this project/term was already resolved in this session\n if (ctx.resolvedEntities?.has(args.name)) {\n const resolvedName = ctx.resolvedEntities.get(args.name);\n return {\n success: true,\n data: {\n found: true,\n suggestion: `Already resolved: use \"${resolvedName}\"`,\n cached: true,\n },\n };\n }\n \n // Check if this term is on the ignore list\n if (context.isIgnored(args.name)) {\n return {\n success: true,\n data: {\n found: false,\n ignored: true,\n message: `\"${args.name}\" is on the ignore list - skipping without prompting`,\n },\n };\n }\n \n // Look up project by name\n const projects = context.search(args.name);\n const projectMatches = projects.filter(e => e.type === 'project');\n \n if (projectMatches.length > 0) {\n const project = projectMatches[0];\n return {\n success: true,\n data: {\n found: true,\n project,\n },\n };\n }\n \n // Try getting all projects and matching trigger phrases\n if (args.triggerPhrase) {\n const allProjects = context.getAllProjects();\n for (const project of allProjects) {\n const phrases = project.classification?.explicit_phrases ?? [];\n if (phrases.some(p => args.triggerPhrase?.toLowerCase().includes(p.toLowerCase()))) {\n return {\n success: true,\n data: {\n found: true,\n project,\n matchedTrigger: args.triggerPhrase,\n },\n };\n }\n }\n }\n \n // Project not found - always signal that we need user input\n // The executor will decide whether to actually prompt based on handler availability\n const allProjects = context.getAllProjects();\n const projectOptions = allProjects\n .filter(p => p.active !== false)\n .map(p => `${p.name}${p.description ? ` - ${p.description}` : ''}`);\n \n // Extract filename from sourceFile path for cleaner display\n const fileName = ctx.sourceFile.split('/').pop() || ctx.sourceFile;\n const fileDate = ctx.audioDate.toLocaleString('en-US', {\n weekday: 'short',\n year: 'numeric',\n month: 'short',\n day: 'numeric',\n hour: '2-digit',\n minute: '2-digit',\n });\n \n // Find context from transcript where the project/term is mentioned\n const transcriptContext = extractTermContext(ctx.transcriptText, args.name);\n \n const contextLines = [\n `File: ${fileName}`,\n `Date: ${fileDate}`,\n '',\n `Unknown project/term: \"${args.name}\"`,\n ];\n \n if (transcriptContext) {\n contextLines.push('');\n contextLines.push('Context from transcript:');\n contextLines.push(`\"${transcriptContext}\"`);\n } else if (args.triggerPhrase) {\n contextLines.push('');\n contextLines.push('Context from transcript:');\n contextLines.push(`\"${args.triggerPhrase}\"`);\n }\n \n return {\n success: true,\n needsUserInput: true,\n userPrompt: contextLines.join('\\n'),\n data: {\n found: false,\n clarificationType: 'new_project',\n term: args.name,\n triggerPhrase: args.triggerPhrase,\n message: `Project \"${args.name}\" not found. Asking user if this is a new project.`,\n knownProjects: allProjects.filter(p => p.active !== false),\n options: projectOptions,\n },\n };\n },\n});\n\n"],"names":["extractTermContext","transcript","term","lowerTranscript","toLowerCase","lowerTerm","index","indexOf","sentenceBoundary","startIndex","boundariesFound","i","test","endIndex","length","context","substring","trim","midPoint","sentenceStart","sentenceEnd","create","ctx","name","description","parameters","type","properties","triggerPhrase","required","execute","args","contextInstance","resolvedEntities","has","resolvedName","get","success","data","found","suggestion","cached","isIgnored","ignored","message","projects","search","projectMatches","filter","e","project","allProjects","getAllProjects","phrases","classification","explicit_phrases","some","p","includes","matchedTrigger","projectOptions","active","map","fileName","sourceFile","split","pop","fileDate","audioDate","toLocaleString","weekday","year","month","day","hour","minute","transcriptContext","transcriptText","contextLines","push","needsUserInput","userPrompt","join","clarificationType","knownProjects","options"],"mappings":"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"}
|
|
@@ -31,7 +31,11 @@
|
|
|
31
31
|
success: true,
|
|
32
32
|
data: {
|
|
33
33
|
projectId: decision.projectId,
|
|
34
|
-
|
|
34
|
+
// Return the routing decision (base path + structure), NOT the built output path
|
|
35
|
+
// The orchestrator will call buildOutputPath() later
|
|
36
|
+
routingDecision: decision,
|
|
37
|
+
// Also include the built path for informational purposes
|
|
38
|
+
outputPath: outputPath,
|
|
35
39
|
confidence: decision.confidence,
|
|
36
40
|
reasoning: decision.reasoning,
|
|
37
41
|
projectHint: args.projectHint,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"route-note.js","sources":["../../../src/agentic/tools/route-note.ts"],"sourcesContent":["/**\n * Route Note Tool\n * \n * Determines the destination for a note based on content analysis.\n */\n\nimport { TranscriptionTool, ToolContext, ToolResult } from '../types';\n\nexport const create = (ctx: ToolContext): TranscriptionTool => ({\n name: 'route_note',\n description: 'Determine the destination for this note based on content analysis.',\n parameters: {\n type: 'object',\n properties: {\n projectHint: {\n type: 'string',\n description: 'The detected project name or hint',\n },\n contentSummary: {\n type: 'string',\n description: 'Brief summary of what the note is about',\n },\n },\n },\n execute: async (args: { projectHint?: string; contentSummary?: string }): Promise<ToolResult> => {\n const routing = ctx.routingInstance;\n \n const routingContext = {\n transcriptText: ctx.transcriptText,\n audioDate: ctx.audioDate,\n sourceFile: ctx.sourceFile,\n };\n \n const decision = routing.route(routingContext);\n const outputPath = routing.buildOutputPath(decision, routingContext);\n \n return {\n success: true,\n data: {\n projectId: decision.projectId,\n
|
|
1
|
+
{"version":3,"file":"route-note.js","sources":["../../../src/agentic/tools/route-note.ts"],"sourcesContent":["/**\n * Route Note Tool\n * \n * Determines the destination for a note based on content analysis.\n */\n\nimport { TranscriptionTool, ToolContext, ToolResult } from '../types';\n\nexport const create = (ctx: ToolContext): TranscriptionTool => ({\n name: 'route_note',\n description: 'Determine the destination for this note based on content analysis.',\n parameters: {\n type: 'object',\n properties: {\n projectHint: {\n type: 'string',\n description: 'The detected project name or hint',\n },\n contentSummary: {\n type: 'string',\n description: 'Brief summary of what the note is about',\n },\n },\n },\n execute: async (args: { projectHint?: string; contentSummary?: string }): Promise<ToolResult> => {\n const routing = ctx.routingInstance;\n \n const routingContext = {\n transcriptText: ctx.transcriptText,\n audioDate: ctx.audioDate,\n sourceFile: ctx.sourceFile,\n };\n \n const decision = routing.route(routingContext);\n const outputPath = routing.buildOutputPath(decision, routingContext);\n \n return {\n success: true,\n data: {\n projectId: decision.projectId,\n // Return the routing decision (base path + structure), NOT the built output path\n // The orchestrator will call buildOutputPath() later\n routingDecision: decision,\n // Also include the built path for informational purposes\n outputPath: outputPath,\n confidence: decision.confidence,\n reasoning: decision.reasoning,\n projectHint: args.projectHint,\n contentSummary: args.contentSummary,\n },\n };\n },\n});\n\n"],"names":["create","ctx","name","description","parameters","type","properties","projectHint","contentSummary","execute","args","routing","routingInstance","routingContext","transcriptText","audioDate","sourceFile","decision","route","outputPath","buildOutputPath","success","data","projectId","routingDecision","confidence","reasoning"],"mappings":"AAAA;;;;AAIC,IAIM,MAAMA,MAAAA,GAAS,CAACC,OAAyC;QAC5DC,IAAAA,EAAM,YAAA;QACNC,WAAAA,EAAa,oEAAA;QACbC,UAAAA,EAAY;YACRC,IAAAA,EAAM,QAAA;YACNC,UAAAA,EAAY;gBACRC,WAAAA,EAAa;oBACTF,IAAAA,EAAM,QAAA;oBACNF,WAAAA,EAAa;AACjB,iBAAA;gBACAK,cAAAA,EAAgB;oBACZH,IAAAA,EAAM,QAAA;oBACNF,WAAAA,EAAa;AACjB;AACJ;AACJ,SAAA;AACAM,QAAAA,OAAAA,EAAS,OAAOC,IAAAA,GAAAA;YACZ,MAAMC,OAAAA,GAAUV,IAAIW,eAAe;AAEnC,YAAA,MAAMC,cAAAA,GAAiB;AACnBC,gBAAAA,cAAAA,EAAgBb,IAAIa,cAAc;AAClCC,gBAAAA,SAAAA,EAAWd,IAAIc,SAAS;AACxBC,gBAAAA,UAAAA,EAAYf,IAAIe;AACpB,aAAA;YAEA,MAAMC,QAAAA,GAAWN,OAAAA,CAAQO,KAAK,CAACL,cAAAA,CAAAA;AAC/B,YAAA,MAAMM,UAAAA,GAAaR,OAAAA,CAAQS,eAAe,CAACH,QAAAA,EAAUJ,cAAAA,CAAAA;YAErD,OAAO;gBACHQ,OAAAA,EAAS,IAAA;gBACTC,IAAAA,EAAM;AACFC,oBAAAA,SAAAA,EAAWN,SAASM,SAAS;;;oBAG7BC,eAAAA,EAAiBP,QAAAA;;oBAEjBE,UAAAA,EAAYA,UAAAA;AACZM,oBAAAA,UAAAA,EAAYR,SAASQ,UAAU;AAC/BC,oBAAAA,SAAAA,EAAWT,SAASS,SAAS;AAC7BnB,oBAAAA,WAAAA,EAAaG,KAAKH,WAAW;AAC7BC,oBAAAA,cAAAA,EAAgBE,KAAKF;AACzB;AACJ,aAAA;AACJ,QAAA;AACJ,KAAA;;;;"}
|
package/dist/arguments.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { Command } from 'commander';
|
|
2
|
-
import { PROGRAM_NAME, VERSION, PROTOKOLL_DEFAULTS, DEFAULT_MAX_AUDIO_SIZE } from './constants.js';
|
|
2
|
+
import { PROGRAM_NAME, DEFAULT_REASONING_LEVEL, VERSION, PROTOKOLL_DEFAULTS, DEFAULT_MAX_AUDIO_SIZE } from './constants.js';
|
|
3
3
|
import { getLogger } from './logging.js';
|
|
4
4
|
import { create } from './util/storage.js';
|
|
5
5
|
|
|
6
6
|
const configure = async (dreadcabinet, cardigantime)=>{
|
|
7
7
|
const logger = getLogger();
|
|
8
8
|
let program = new Command();
|
|
9
|
-
program.name(PROGRAM_NAME).summary('Intelligent audio transcription tool with context').description('Protokoll transcribes audio files intelligently using context to improve accuracy').option('--dry-run', 'perform a dry run without saving files').option('--verbose', 'enable verbose logging').option('--debug', 'enable debug logging').option('--openai-api-key <openaiApiKey>', 'OpenAI API key').option('--transcription-model <transcriptionModel>', 'OpenAI transcription model to use').option('--model <model>', 'OpenAI model to use for transcription enhancement').option('--overrides', 'allow overrides of the default configuration').option('--context-directories [contextDirectories...]', 'directories containing context files to be included in prompts').option('--max-audio-size <maxAudioSize>', 'maximum audio file size in bytes').option('--temp-directory <tempDirectory>', 'temporary directory for processing files').option('--
|
|
9
|
+
program.name(PROGRAM_NAME).summary('Intelligent audio transcription tool with context').description('Protokoll transcribes audio files intelligently using context to improve accuracy').option('--dry-run', 'perform a dry run without saving files').option('--verbose', 'enable verbose logging').option('--debug', 'enable debug logging').option('--openai-api-key <openaiApiKey>', 'OpenAI API key').option('--transcription-model <transcriptionModel>', 'OpenAI transcription model to use').option('--model <model>', 'OpenAI model to use for transcription enhancement').option('--reasoning-level <reasoningLevel>', `reasoning effort level: low, medium, or high (default: ${DEFAULT_REASONING_LEVEL})`).option('--overrides', 'allow overrides of the default configuration').option('--context-directories [contextDirectories...]', 'directories containing context files to be included in prompts').option('--max-audio-size <maxAudioSize>', 'maximum audio file size in bytes').option('--temp-directory <tempDirectory>', 'temporary directory for processing files').option('--batch', 'disable interactive prompts (for automation/cron jobs)').option('--self-reflection', 'generate self-reflection reports (default: true)').option('--no-self-reflection', 'disable self-reflection reports').option('--silent', 'disable sound notifications in interactive mode').option('--processed-directory <processedDirectory>', 'directory to move processed audio files to');
|
|
10
10
|
await dreadcabinet.configure(program);
|
|
11
11
|
program = await cardigantime.configure(program);
|
|
12
12
|
program.version(VERSION);
|
|
@@ -51,13 +51,15 @@ const configure = async (dreadcabinet, cardigantime)=>{
|
|
|
51
51
|
const dreadcabinetValues = await dreadcabinet.read(cliArgs);
|
|
52
52
|
// Extract protokoll-specific CLI args (only include if explicitly set)
|
|
53
53
|
const protokollCliArgs = {};
|
|
54
|
-
|
|
54
|
+
// --batch disables interactive mode (interactive is default)
|
|
55
|
+
if (cliArgs.batch !== undefined) protokollCliArgs.interactive = !cliArgs.batch;
|
|
55
56
|
if (cliArgs.selfReflection !== undefined) protokollCliArgs.selfReflection = cliArgs.selfReflection;
|
|
56
57
|
if (cliArgs.debug !== undefined) protokollCliArgs.debug = cliArgs.debug;
|
|
57
58
|
if (cliArgs.verbose !== undefined) protokollCliArgs.verbose = cliArgs.verbose;
|
|
58
59
|
if (cliArgs.dryRun !== undefined) protokollCliArgs.dryRun = cliArgs.dryRun;
|
|
59
60
|
if (cliArgs.model !== undefined) protokollCliArgs.model = cliArgs.model;
|
|
60
61
|
if (cliArgs.transcriptionModel !== undefined) protokollCliArgs.transcriptionModel = cliArgs.transcriptionModel;
|
|
62
|
+
if (cliArgs.reasoningLevel !== undefined) protokollCliArgs.reasoningLevel = cliArgs.reasoningLevel;
|
|
61
63
|
if (cliArgs.overrides !== undefined) protokollCliArgs.overrides = cliArgs.overrides;
|
|
62
64
|
if (cliArgs.contextDirectories !== undefined) protokollCliArgs.contextDirectories = cliArgs.contextDirectories;
|
|
63
65
|
if (cliArgs.maxAudioSize !== undefined) {
|
|
@@ -65,6 +67,7 @@ const configure = async (dreadcabinet, cardigantime)=>{
|
|
|
65
67
|
}
|
|
66
68
|
if (cliArgs.tempDirectory !== undefined) protokollCliArgs.tempDirectory = cliArgs.tempDirectory;
|
|
67
69
|
if (cliArgs.processedDirectory !== undefined) protokollCliArgs.processedDirectory = cliArgs.processedDirectory;
|
|
70
|
+
if (cliArgs.silent !== undefined) protokollCliArgs.silent = cliArgs.silent;
|
|
68
71
|
// Merge configurations: Defaults -> File -> Dreadcabinet CLI -> Protokoll CLI (highest precedence)
|
|
69
72
|
let mergedConfig = {
|
|
70
73
|
...PROTOKOLL_DEFAULTS,
|
package/dist/arguments.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"arguments.js","sources":["../src/arguments.ts"],"sourcesContent":["import * as Dreadcabinet from \"@theunwalked/dreadcabinet\";\nimport * as Cardigantime from '@theunwalked/cardigantime';\nimport { Command } from \"commander\";\nimport {\n PROTOKOLL_DEFAULTS,\n DEFAULT_MAX_AUDIO_SIZE,\n PROGRAM_NAME,\n VERSION\n} from \"@/constants\";\nimport { Args, Config, SecureConfig } from \"@/protokoll\";\nimport { getLogger } from \"@/logging\";\nimport * as Storage from \"@/util/storage\";\n\nexport const configure = async (dreadcabinet: Dreadcabinet.DreadCabinet, cardigantime: Cardigantime.Cardigantime<any>): Promise<[Config, SecureConfig]> => {\n const logger = getLogger();\n\n let program = new Command();\n program\n .name(PROGRAM_NAME)\n .summary('Intelligent audio transcription tool with context')\n .description('Protokoll transcribes audio files intelligently using context to improve accuracy')\n .option('--dry-run', 'perform a dry run without saving files')\n .option('--verbose', 'enable verbose logging')\n .option('--debug', 'enable debug logging')\n .option('--openai-api-key <openaiApiKey>', 'OpenAI API key')\n .option('--transcription-model <transcriptionModel>', 'OpenAI transcription model to use')\n .option('--model <model>', 'OpenAI model to use for transcription enhancement')\n .option('--overrides', 'allow overrides of the default configuration')\n .option('--context-directories [contextDirectories...]', 'directories containing context files to be included in prompts')\n .option('--max-audio-size <maxAudioSize>', 'maximum audio file size in bytes')\n .option('--temp-directory <tempDirectory>', 'temporary directory for processing files')\n .option('--interactive', 'enable interactive mode for clarification questions')\n .option('--self-reflection', 'generate self-reflection reports (default: true)')\n .option('--no-self-reflection', 'disable self-reflection reports')\n .option('--processed-directory <processedDirectory>', 'directory to move processed audio files to')\n\n await dreadcabinet.configure(program);\n program = await cardigantime.configure(program);\n program.version(VERSION);\n\n // Check if --check-config is in process.argv early\n if (process.argv.includes('--check-config')) {\n program.parse();\n const cliArgs: Args = program.opts<Args>();\n\n // Use CardiganTime's built-in checkConfig method\n await cardigantime.checkConfig(cliArgs);\n\n // Return minimal config for consistency, but main processing is done\n const config: Config = PROTOKOLL_DEFAULTS as Config;\n const secureConfig: SecureConfig = { openaiApiKey: process.env.OPENAI_API_KEY };\n return [config, secureConfig];\n }\n\n // Check if --init-config is in process.argv early\n if (process.argv.includes('--init-config')) {\n program.parse();\n const cliArgs: Args = program.opts<Args>();\n\n // Use CardiganTime's built-in generateConfig method\n await cardigantime.generateConfig(cliArgs.configDirectory || PROTOKOLL_DEFAULTS.configDirectory);\n\n // Return minimal config for consistency, but main processing is done\n const config: Config = PROTOKOLL_DEFAULTS as Config;\n const secureConfig: SecureConfig = { openaiApiKey: process.env.OPENAI_API_KEY };\n return [config, secureConfig];\n }\n\n program.parse();\n\n const cliArgs: Args = program.opts<Args>();\n logger.debug('Command Line Options: %s', JSON.stringify(cliArgs, null, 2));\n\n // Get values from config file first using CardiganTime's hierarchical configuration\n const fileValues = await cardigantime.read(cliArgs);\n\n // Read the Raw values from the Dreadcabinet Command Line Arguments\n const dreadcabinetValues = await dreadcabinet.read(cliArgs);\n\n // Extract protokoll-specific CLI args (only include if explicitly set)\n const protokollCliArgs: Partial<Config> = {};\n if (cliArgs.interactive !== undefined) protokollCliArgs.interactive = cliArgs.interactive;\n if (cliArgs.selfReflection !== undefined) protokollCliArgs.selfReflection = cliArgs.selfReflection;\n if (cliArgs.debug !== undefined) protokollCliArgs.debug = cliArgs.debug;\n if (cliArgs.verbose !== undefined) protokollCliArgs.verbose = cliArgs.verbose;\n if (cliArgs.dryRun !== undefined) protokollCliArgs.dryRun = cliArgs.dryRun;\n if (cliArgs.model !== undefined) protokollCliArgs.model = cliArgs.model;\n if (cliArgs.transcriptionModel !== undefined) protokollCliArgs.transcriptionModel = cliArgs.transcriptionModel;\n if (cliArgs.overrides !== undefined) protokollCliArgs.overrides = cliArgs.overrides;\n if (cliArgs.contextDirectories !== undefined) protokollCliArgs.contextDirectories = cliArgs.contextDirectories;\n if (cliArgs.maxAudioSize !== undefined) {\n protokollCliArgs.maxAudioSize = typeof cliArgs.maxAudioSize === 'string' \n ? parseInt(cliArgs.maxAudioSize, 10) \n : cliArgs.maxAudioSize;\n }\n if (cliArgs.tempDirectory !== undefined) protokollCliArgs.tempDirectory = cliArgs.tempDirectory;\n if (cliArgs.processedDirectory !== undefined) protokollCliArgs.processedDirectory = cliArgs.processedDirectory;\n\n // Merge configurations: Defaults -> File -> Dreadcabinet CLI -> Protokoll CLI (highest precedence)\n let mergedConfig: Partial<Config> = {\n ...PROTOKOLL_DEFAULTS, // Start with Protokoll defaults\n ...fileValues, // Apply file values (overwrites defaults)\n ...dreadcabinetValues, // Apply dreadcabinet CLI args\n ...protokollCliArgs, // Apply protokoll-specific CLI args last (highest precedence)\n } as Partial<Config>;\n\n const secureConfig: SecureConfig = {\n ...(process.env.OPENAI_API_KEY !== undefined && { openaiApiKey: process.env.OPENAI_API_KEY }), // Apply Env vars\n } as SecureConfig;\n\n // Convert maxAudioSize if it's a string AFTER merging\n if (typeof mergedConfig.maxAudioSize === 'string') {\n const parsedSize = parseInt(mergedConfig.maxAudioSize, 10);\n if (!isNaN(parsedSize)) {\n mergedConfig.maxAudioSize = parsedSize;\n } else {\n logger.warn(`Invalid maxAudioSize value detected after merge: '${mergedConfig.maxAudioSize}', using default: ${DEFAULT_MAX_AUDIO_SIZE}`);\n mergedConfig.maxAudioSize = DEFAULT_MAX_AUDIO_SIZE; // Use Protokoll default if parsing fails\n }\n } else if (mergedConfig.maxAudioSize === undefined) {\n // If still undefined after all merges, apply Protokoll default\n mergedConfig.maxAudioSize = DEFAULT_MAX_AUDIO_SIZE;\n }\n\n // Apply Dreadcabinet defaults\n mergedConfig = dreadcabinet.applyDefaults(mergedConfig) as Partial<Config>;\n\n const config = mergedConfig as Config;\n\n // Validate Dreadcabinet final config\n dreadcabinet.validate(config);\n\n // Validate Protokoll final config\n await validateConfig(config);\n await validateSecureConfig(secureConfig);\n\n logger.debug('Final configuration: %s', JSON.stringify(config, null, 2));\n return [config, secureConfig];\n}\n\nasync function validateSecureConfig(config: SecureConfig): Promise<void> {\n const logger = getLogger();\n if (!config.openaiApiKey) {\n config.openaiApiKey = process.env.OPENAI_API_KEY;\n\n if (!config.openaiApiKey) {\n throw new Error('OpenAI API key is required. Provide it via CLI (--openai-api-key), config file, or OPENAI_API_KEY environment variable.');\n }\n logger.debug(\"Using OpenAI API key from environment variable.\");\n }\n}\n\nasync function validateConfig(config: Config): Promise<void> {\n const logger = getLogger();\n\n // Validate that models are provided (but don't restrict to specific allowlist)\n validateModelPresence(config.model, true, 'model');\n validateModelPresence(config.transcriptionModel, true, 'transcriptionModel');\n\n if (config.contextDirectories && config.contextDirectories.length > 0) {\n await validateContextDirectories(config.contextDirectories);\n } else {\n logger.debug(\"No context directories provided.\");\n config.contextDirectories = [];\n }\n\n if (config.tempDirectory) {\n await validateTempDirectory(config.tempDirectory);\n } else {\n throw new Error('Temp directory is required.');\n }\n\n if (typeof config.maxAudioSize !== 'number' || config.maxAudioSize <= 0) {\n throw new Error(`Invalid maxAudioSize: ${config.maxAudioSize}. Must be a positive number.`);\n }\n\n logger.debug(\"Final configuration validated successfully.\");\n}\n\nfunction validateModelPresence(model: string | undefined, required: boolean, modelOptionName: string) {\n const logger = getLogger();\n logger.debug(`Validating model presence for ${modelOptionName}: ${model} (Required: ${required})`);\n if (required && !model) {\n throw new Error(`Model for ${modelOptionName} is required`);\n }\n\n if (model && model.trim() === '') {\n throw new Error(`Model for ${modelOptionName} cannot be empty`);\n }\n\n // Note: We no longer validate against a static allowlist\n // The actual model validation will happen when the API call is made\n // This allows for dynamic model discovery and future model additions\n}\n\nasync function validateContextDirectories(contextDirectories: string[]) {\n const logger = getLogger();\n logger.debug(`Validating context directories: ${contextDirectories.join(', ')}`);\n const storage = Storage.create({ log: logger.info.bind(logger) });\n for (const directory of contextDirectories) {\n if (!await storage.isDirectoryReadable(directory)) {\n throw new Error(`Context directory does not exist or is not readable: ${directory}`);\n }\n }\n}\n\n\n\nasync function validateTempDirectory(tempDirectory: string) {\n const logger = getLogger();\n logger.debug(`Validating temp directory: ${tempDirectory}`);\n const storage = Storage.create({ log: logger.info.bind(logger) });\n if (!await storage.isDirectoryWritable(tempDirectory)) {\n throw new Error(`Temp directory does not exist or is not writable: ${tempDirectory}`);\n }\n}\n"],"names":["configure","dreadcabinet","cardigantime","logger","getLogger","program","Command","name","PROGRAM_NAME","summary","description","option","version","VERSION","process","argv","includes","parse","cliArgs","opts","checkConfig","config","PROTOKOLL_DEFAULTS","secureConfig","openaiApiKey","env","OPENAI_API_KEY","generateConfig","configDirectory","debug","JSON","stringify","fileValues","read","dreadcabinetValues","protokollCliArgs","interactive","undefined","selfReflection","verbose","dryRun","model","transcriptionModel","overrides","contextDirectories","maxAudioSize","parseInt","tempDirectory","processedDirectory","mergedConfig","parsedSize","isNaN","warn","DEFAULT_MAX_AUDIO_SIZE","applyDefaults","validate","validateConfig","validateSecureConfig","Error","validateModelPresence","length","validateContextDirectories","validateTempDirectory","required","modelOptionName","trim","join","storage","Storage","log","info","bind","directory","isDirectoryReadable","isDirectoryWritable"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"arguments.js","sources":["../src/arguments.ts"],"sourcesContent":["import * as Dreadcabinet from \"@theunwalked/dreadcabinet\";\nimport * as Cardigantime from '@theunwalked/cardigantime';\nimport { Command } from \"commander\";\nimport {\n PROTOKOLL_DEFAULTS,\n DEFAULT_MAX_AUDIO_SIZE,\n DEFAULT_REASONING_LEVEL,\n PROGRAM_NAME,\n VERSION\n} from \"@/constants\";\nimport { Args, Config, SecureConfig } from \"@/protokoll\";\nimport { getLogger } from \"@/logging\";\nimport * as Storage from \"@/util/storage\";\n\nexport const configure = async (dreadcabinet: Dreadcabinet.DreadCabinet, cardigantime: Cardigantime.Cardigantime<any>): Promise<[Config, SecureConfig]> => {\n const logger = getLogger();\n\n let program = new Command();\n program\n .name(PROGRAM_NAME)\n .summary('Intelligent audio transcription tool with context')\n .description('Protokoll transcribes audio files intelligently using context to improve accuracy')\n .option('--dry-run', 'perform a dry run without saving files')\n .option('--verbose', 'enable verbose logging')\n .option('--debug', 'enable debug logging')\n .option('--openai-api-key <openaiApiKey>', 'OpenAI API key')\n .option('--transcription-model <transcriptionModel>', 'OpenAI transcription model to use')\n .option('--model <model>', 'OpenAI model to use for transcription enhancement')\n .option('--reasoning-level <reasoningLevel>', `reasoning effort level: low, medium, or high (default: ${DEFAULT_REASONING_LEVEL})`)\n .option('--overrides', 'allow overrides of the default configuration')\n .option('--context-directories [contextDirectories...]', 'directories containing context files to be included in prompts')\n .option('--max-audio-size <maxAudioSize>', 'maximum audio file size in bytes')\n .option('--temp-directory <tempDirectory>', 'temporary directory for processing files')\n .option('--batch', 'disable interactive prompts (for automation/cron jobs)')\n .option('--self-reflection', 'generate self-reflection reports (default: true)')\n .option('--no-self-reflection', 'disable self-reflection reports')\n .option('--silent', 'disable sound notifications in interactive mode')\n .option('--processed-directory <processedDirectory>', 'directory to move processed audio files to')\n\n await dreadcabinet.configure(program);\n program = await cardigantime.configure(program);\n program.version(VERSION);\n\n // Check if --check-config is in process.argv early\n if (process.argv.includes('--check-config')) {\n program.parse();\n const cliArgs: Args = program.opts<Args>();\n\n // Use CardiganTime's built-in checkConfig method\n await cardigantime.checkConfig(cliArgs);\n\n // Return minimal config for consistency, but main processing is done\n const config: Config = PROTOKOLL_DEFAULTS as Config;\n const secureConfig: SecureConfig = { openaiApiKey: process.env.OPENAI_API_KEY };\n return [config, secureConfig];\n }\n\n // Check if --init-config is in process.argv early\n if (process.argv.includes('--init-config')) {\n program.parse();\n const cliArgs: Args = program.opts<Args>();\n\n // Use CardiganTime's built-in generateConfig method\n await cardigantime.generateConfig(cliArgs.configDirectory || PROTOKOLL_DEFAULTS.configDirectory);\n\n // Return minimal config for consistency, but main processing is done\n const config: Config = PROTOKOLL_DEFAULTS as Config;\n const secureConfig: SecureConfig = { openaiApiKey: process.env.OPENAI_API_KEY };\n return [config, secureConfig];\n }\n\n program.parse();\n\n const cliArgs: Args = program.opts<Args>();\n logger.debug('Command Line Options: %s', JSON.stringify(cliArgs, null, 2));\n\n // Get values from config file first using CardiganTime's hierarchical configuration\n const fileValues = await cardigantime.read(cliArgs);\n\n // Read the Raw values from the Dreadcabinet Command Line Arguments\n const dreadcabinetValues = await dreadcabinet.read(cliArgs);\n\n // Extract protokoll-specific CLI args (only include if explicitly set)\n const protokollCliArgs: Partial<Config> = {};\n // --batch disables interactive mode (interactive is default)\n if (cliArgs.batch !== undefined) protokollCliArgs.interactive = !cliArgs.batch;\n if (cliArgs.selfReflection !== undefined) protokollCliArgs.selfReflection = cliArgs.selfReflection;\n if (cliArgs.debug !== undefined) protokollCliArgs.debug = cliArgs.debug;\n if (cliArgs.verbose !== undefined) protokollCliArgs.verbose = cliArgs.verbose;\n if (cliArgs.dryRun !== undefined) protokollCliArgs.dryRun = cliArgs.dryRun;\n if (cliArgs.model !== undefined) protokollCliArgs.model = cliArgs.model;\n if (cliArgs.transcriptionModel !== undefined) protokollCliArgs.transcriptionModel = cliArgs.transcriptionModel;\n if (cliArgs.reasoningLevel !== undefined) protokollCliArgs.reasoningLevel = cliArgs.reasoningLevel;\n if (cliArgs.overrides !== undefined) protokollCliArgs.overrides = cliArgs.overrides;\n if (cliArgs.contextDirectories !== undefined) protokollCliArgs.contextDirectories = cliArgs.contextDirectories;\n if (cliArgs.maxAudioSize !== undefined) {\n protokollCliArgs.maxAudioSize = typeof cliArgs.maxAudioSize === 'string' \n ? parseInt(cliArgs.maxAudioSize, 10) \n : cliArgs.maxAudioSize;\n }\n if (cliArgs.tempDirectory !== undefined) protokollCliArgs.tempDirectory = cliArgs.tempDirectory;\n if (cliArgs.processedDirectory !== undefined) protokollCliArgs.processedDirectory = cliArgs.processedDirectory;\n if (cliArgs.silent !== undefined) protokollCliArgs.silent = cliArgs.silent;\n\n // Merge configurations: Defaults -> File -> Dreadcabinet CLI -> Protokoll CLI (highest precedence)\n let mergedConfig: Partial<Config> = {\n ...PROTOKOLL_DEFAULTS, // Start with Protokoll defaults\n ...fileValues, // Apply file values (overwrites defaults)\n ...dreadcabinetValues, // Apply dreadcabinet CLI args\n ...protokollCliArgs, // Apply protokoll-specific CLI args last (highest precedence)\n } as Partial<Config>;\n\n const secureConfig: SecureConfig = {\n ...(process.env.OPENAI_API_KEY !== undefined && { openaiApiKey: process.env.OPENAI_API_KEY }), // Apply Env vars\n } as SecureConfig;\n\n // Convert maxAudioSize if it's a string AFTER merging\n if (typeof mergedConfig.maxAudioSize === 'string') {\n const parsedSize = parseInt(mergedConfig.maxAudioSize, 10);\n if (!isNaN(parsedSize)) {\n mergedConfig.maxAudioSize = parsedSize;\n } else {\n logger.warn(`Invalid maxAudioSize value detected after merge: '${mergedConfig.maxAudioSize}', using default: ${DEFAULT_MAX_AUDIO_SIZE}`);\n mergedConfig.maxAudioSize = DEFAULT_MAX_AUDIO_SIZE; // Use Protokoll default if parsing fails\n }\n } else if (mergedConfig.maxAudioSize === undefined) {\n // If still undefined after all merges, apply Protokoll default\n mergedConfig.maxAudioSize = DEFAULT_MAX_AUDIO_SIZE;\n }\n\n // Apply Dreadcabinet defaults\n mergedConfig = dreadcabinet.applyDefaults(mergedConfig) as Partial<Config>;\n\n const config = mergedConfig as Config;\n\n // Validate Dreadcabinet final config\n dreadcabinet.validate(config);\n\n // Validate Protokoll final config\n await validateConfig(config);\n await validateSecureConfig(secureConfig);\n\n logger.debug('Final configuration: %s', JSON.stringify(config, null, 2));\n return [config, secureConfig];\n}\n\nasync function validateSecureConfig(config: SecureConfig): Promise<void> {\n const logger = getLogger();\n if (!config.openaiApiKey) {\n config.openaiApiKey = process.env.OPENAI_API_KEY;\n\n if (!config.openaiApiKey) {\n throw new Error('OpenAI API key is required. Provide it via CLI (--openai-api-key), config file, or OPENAI_API_KEY environment variable.');\n }\n logger.debug(\"Using OpenAI API key from environment variable.\");\n }\n}\n\nasync function validateConfig(config: Config): Promise<void> {\n const logger = getLogger();\n\n // Validate that models are provided (but don't restrict to specific allowlist)\n validateModelPresence(config.model, true, 'model');\n validateModelPresence(config.transcriptionModel, true, 'transcriptionModel');\n\n if (config.contextDirectories && config.contextDirectories.length > 0) {\n await validateContextDirectories(config.contextDirectories);\n } else {\n logger.debug(\"No context directories provided.\");\n config.contextDirectories = [];\n }\n\n if (config.tempDirectory) {\n await validateTempDirectory(config.tempDirectory);\n } else {\n throw new Error('Temp directory is required.');\n }\n\n if (typeof config.maxAudioSize !== 'number' || config.maxAudioSize <= 0) {\n throw new Error(`Invalid maxAudioSize: ${config.maxAudioSize}. Must be a positive number.`);\n }\n\n logger.debug(\"Final configuration validated successfully.\");\n}\n\nfunction validateModelPresence(model: string | undefined, required: boolean, modelOptionName: string) {\n const logger = getLogger();\n logger.debug(`Validating model presence for ${modelOptionName}: ${model} (Required: ${required})`);\n if (required && !model) {\n throw new Error(`Model for ${modelOptionName} is required`);\n }\n\n if (model && model.trim() === '') {\n throw new Error(`Model for ${modelOptionName} cannot be empty`);\n }\n\n // Note: We no longer validate against a static allowlist\n // The actual model validation will happen when the API call is made\n // This allows for dynamic model discovery and future model additions\n}\n\nasync function validateContextDirectories(contextDirectories: string[]) {\n const logger = getLogger();\n logger.debug(`Validating context directories: ${contextDirectories.join(', ')}`);\n const storage = Storage.create({ log: logger.info.bind(logger) });\n for (const directory of contextDirectories) {\n if (!await storage.isDirectoryReadable(directory)) {\n throw new Error(`Context directory does not exist or is not readable: ${directory}`);\n }\n }\n}\n\n\n\nasync function validateTempDirectory(tempDirectory: string) {\n const logger = getLogger();\n logger.debug(`Validating temp directory: ${tempDirectory}`);\n const storage = Storage.create({ log: logger.info.bind(logger) });\n if (!await storage.isDirectoryWritable(tempDirectory)) {\n throw new Error(`Temp directory does not exist or is not writable: ${tempDirectory}`);\n }\n}\n"],"names":["configure","dreadcabinet","cardigantime","logger","getLogger","program","Command","name","PROGRAM_NAME","summary","description","option","DEFAULT_REASONING_LEVEL","version","VERSION","process","argv","includes","parse","cliArgs","opts","checkConfig","config","PROTOKOLL_DEFAULTS","secureConfig","openaiApiKey","env","OPENAI_API_KEY","generateConfig","configDirectory","debug","JSON","stringify","fileValues","read","dreadcabinetValues","protokollCliArgs","batch","undefined","interactive","selfReflection","verbose","dryRun","model","transcriptionModel","reasoningLevel","overrides","contextDirectories","maxAudioSize","parseInt","tempDirectory","processedDirectory","silent","mergedConfig","parsedSize","isNaN","warn","DEFAULT_MAX_AUDIO_SIZE","applyDefaults","validate","validateConfig","validateSecureConfig","Error","validateModelPresence","length","validateContextDirectories","validateTempDirectory","required","modelOptionName","trim","join","storage","Storage","log","info","bind","directory","isDirectoryReadable","isDirectoryWritable"],"mappings":"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"}
|