@redaksjon/protokoll-engine 0.1.1-dev.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (240) hide show
  1. package/README.md +47 -0
  2. package/dist/agentic/executor.d.ts +21 -0
  3. package/dist/agentic/executor.d.ts.map +1 -0
  4. package/dist/agentic/index.d.ts +27 -0
  5. package/dist/agentic/index.d.ts.map +1 -0
  6. package/dist/agentic/registry.d.ts +11 -0
  7. package/dist/agentic/registry.d.ts.map +1 -0
  8. package/dist/agentic/tools/lookup-person.d.ts +3 -0
  9. package/dist/agentic/tools/lookup-person.d.ts.map +1 -0
  10. package/dist/agentic/tools/lookup-project.d.ts +3 -0
  11. package/dist/agentic/tools/lookup-project.d.ts.map +1 -0
  12. package/dist/agentic/tools/route-note.d.ts +3 -0
  13. package/dist/agentic/tools/route-note.d.ts.map +1 -0
  14. package/dist/agentic/tools/store-context.d.ts +3 -0
  15. package/dist/agentic/tools/store-context.d.ts.map +1 -0
  16. package/dist/agentic/tools/verify-spelling.d.ts +3 -0
  17. package/dist/agentic/tools/verify-spelling.d.ts.map +1 -0
  18. package/dist/agentic/types.d.ts +110 -0
  19. package/dist/agentic/types.d.ts.map +1 -0
  20. package/dist/constants.d.ts +98 -0
  21. package/dist/constants.d.ts.map +1 -0
  22. package/dist/feedback/analyzer.d.ts +13 -0
  23. package/dist/feedback/analyzer.d.ts.map +1 -0
  24. package/dist/feedback/decision-tracker.d.ts +14 -0
  25. package/dist/feedback/decision-tracker.d.ts.map +1 -0
  26. package/dist/feedback/handler.d.ts +14 -0
  27. package/dist/feedback/handler.d.ts.map +1 -0
  28. package/dist/feedback/index.d.ts +12 -0
  29. package/dist/feedback/index.d.ts.map +1 -0
  30. package/dist/feedback/types.d.ts +72 -0
  31. package/dist/feedback/types.d.ts.map +1 -0
  32. package/dist/index.d.ts +24 -0
  33. package/dist/index.d.ts.map +1 -0
  34. package/dist/index.js +32 -0
  35. package/dist/index.js.map +1 -0
  36. package/dist/index10.js +4 -0
  37. package/dist/index10.js.map +1 -0
  38. package/dist/index11.js +22 -0
  39. package/dist/index11.js.map +1 -0
  40. package/dist/index12.js +125 -0
  41. package/dist/index12.js.map +1 -0
  42. package/dist/index13.js +124 -0
  43. package/dist/index13.js.map +1 -0
  44. package/dist/index14.js +296 -0
  45. package/dist/index14.js.map +1 -0
  46. package/dist/index15.js +100 -0
  47. package/dist/index15.js.map +1 -0
  48. package/dist/index16.js +107 -0
  49. package/dist/index16.js.map +1 -0
  50. package/dist/index17.js +185 -0
  51. package/dist/index17.js.map +1 -0
  52. package/dist/index18.js +53 -0
  53. package/dist/index18.js.map +1 -0
  54. package/dist/index19.js +19 -0
  55. package/dist/index19.js.map +1 -0
  56. package/dist/index2.js +33 -0
  57. package/dist/index2.js.map +1 -0
  58. package/dist/index20.js +105 -0
  59. package/dist/index20.js.map +1 -0
  60. package/dist/index21.js +26 -0
  61. package/dist/index21.js.map +1 -0
  62. package/dist/index22.js +49 -0
  63. package/dist/index22.js.map +1 -0
  64. package/dist/index23.js +119 -0
  65. package/dist/index23.js.map +1 -0
  66. package/dist/index24.js +330 -0
  67. package/dist/index24.js.map +1 -0
  68. package/dist/index25.js +57 -0
  69. package/dist/index25.js.map +1 -0
  70. package/dist/index26.js +38 -0
  71. package/dist/index26.js.map +1 -0
  72. package/dist/index27.js +127 -0
  73. package/dist/index27.js.map +1 -0
  74. package/dist/index28.js +157 -0
  75. package/dist/index28.js.map +1 -0
  76. package/dist/index29.js +163 -0
  77. package/dist/index29.js.map +1 -0
  78. package/dist/index3.js +36 -0
  79. package/dist/index3.js.map +1 -0
  80. package/dist/index30.js +173 -0
  81. package/dist/index30.js.map +1 -0
  82. package/dist/index31.js +423 -0
  83. package/dist/index31.js.map +1 -0
  84. package/dist/index32.js +161 -0
  85. package/dist/index32.js.map +1 -0
  86. package/dist/index33.js +152 -0
  87. package/dist/index33.js.map +1 -0
  88. package/dist/index34.js +56 -0
  89. package/dist/index34.js.map +1 -0
  90. package/dist/index35.js +103 -0
  91. package/dist/index35.js.map +1 -0
  92. package/dist/index36.js +451 -0
  93. package/dist/index36.js.map +1 -0
  94. package/dist/index37.js +431 -0
  95. package/dist/index37.js.map +1 -0
  96. package/dist/index38.js +87 -0
  97. package/dist/index38.js.map +1 -0
  98. package/dist/index39.js +122 -0
  99. package/dist/index39.js.map +1 -0
  100. package/dist/index4.js +3 -0
  101. package/dist/index4.js.map +1 -0
  102. package/dist/index40.js +299 -0
  103. package/dist/index40.js.map +1 -0
  104. package/dist/index41.js +49 -0
  105. package/dist/index41.js.map +1 -0
  106. package/dist/index42.js +151 -0
  107. package/dist/index42.js.map +1 -0
  108. package/dist/index43.js +226 -0
  109. package/dist/index43.js.map +1 -0
  110. package/dist/index44.js +49 -0
  111. package/dist/index44.js.map +1 -0
  112. package/dist/index45.js +45 -0
  113. package/dist/index45.js.map +1 -0
  114. package/dist/index46.js +37 -0
  115. package/dist/index46.js.map +1 -0
  116. package/dist/index47.js +51 -0
  117. package/dist/index47.js.map +1 -0
  118. package/dist/index48.js +39 -0
  119. package/dist/index48.js.map +1 -0
  120. package/dist/index49.js +239 -0
  121. package/dist/index49.js.map +1 -0
  122. package/dist/index5.js +17 -0
  123. package/dist/index5.js.map +1 -0
  124. package/dist/index50.js +163 -0
  125. package/dist/index50.js.map +1 -0
  126. package/dist/index51.js +81 -0
  127. package/dist/index51.js.map +1 -0
  128. package/dist/index52.js +78 -0
  129. package/dist/index52.js.map +1 -0
  130. package/dist/index53.js +22 -0
  131. package/dist/index53.js.map +1 -0
  132. package/dist/index54.js +8 -0
  133. package/dist/index54.js.map +1 -0
  134. package/dist/index55.js +8 -0
  135. package/dist/index55.js.map +1 -0
  136. package/dist/index56.js +17 -0
  137. package/dist/index56.js.map +1 -0
  138. package/dist/index57.js +4 -0
  139. package/dist/index57.js.map +1 -0
  140. package/dist/index58.js +17 -0
  141. package/dist/index58.js.map +1 -0
  142. package/dist/index59.js +4 -0
  143. package/dist/index59.js.map +1 -0
  144. package/dist/index6.js +22 -0
  145. package/dist/index6.js.map +1 -0
  146. package/dist/index60.js +6 -0
  147. package/dist/index60.js.map +1 -0
  148. package/dist/index7.js +27 -0
  149. package/dist/index7.js.map +1 -0
  150. package/dist/index8.js +22 -0
  151. package/dist/index8.js.map +1 -0
  152. package/dist/index9.js +5 -0
  153. package/dist/index9.js.map +1 -0
  154. package/dist/logging.d.ts +7 -0
  155. package/dist/logging.d.ts.map +1 -0
  156. package/dist/output/index.d.ts +15 -0
  157. package/dist/output/index.d.ts.map +1 -0
  158. package/dist/phases/complete.d.ts +17 -0
  159. package/dist/phases/complete.d.ts.map +1 -0
  160. package/dist/phases/index.d.ts +5 -0
  161. package/dist/phases/index.d.ts.map +1 -0
  162. package/dist/phases/locate.d.ts +15 -0
  163. package/dist/phases/locate.d.ts.map +1 -0
  164. package/dist/phases/simple-replace.d.ts +72 -0
  165. package/dist/phases/simple-replace.d.ts.map +1 -0
  166. package/dist/phases/transcribe.d.ts +19 -0
  167. package/dist/phases/transcribe.d.ts.map +1 -0
  168. package/dist/pipeline/index.d.ts +10 -0
  169. package/dist/pipeline/index.d.ts.map +1 -0
  170. package/dist/pipeline/orchestrator.d.ts +13 -0
  171. package/dist/pipeline/orchestrator.d.ts.map +1 -0
  172. package/dist/pipeline/types.d.ts +58 -0
  173. package/dist/pipeline/types.d.ts.map +1 -0
  174. package/dist/prompt/index.d.ts +3 -0
  175. package/dist/prompt/index.d.ts.map +1 -0
  176. package/dist/prompt/templates.d.ts +40 -0
  177. package/dist/prompt/templates.d.ts.map +1 -0
  178. package/dist/prompt/transcribe.d.ts +42 -0
  179. package/dist/prompt/transcribe.d.ts.map +1 -0
  180. package/dist/reasoning/client.d.ts +42 -0
  181. package/dist/reasoning/client.d.ts.map +1 -0
  182. package/dist/reasoning/index.d.ts +17 -0
  183. package/dist/reasoning/index.d.ts.map +1 -0
  184. package/dist/reasoning/strategy.d.ts +12 -0
  185. package/dist/reasoning/strategy.d.ts.map +1 -0
  186. package/dist/reasoning/types.d.ts +58 -0
  187. package/dist/reasoning/types.d.ts.map +1 -0
  188. package/dist/reflection/collector.d.ts +18 -0
  189. package/dist/reflection/collector.d.ts.map +1 -0
  190. package/dist/reflection/index.d.ts +13 -0
  191. package/dist/reflection/index.d.ts.map +1 -0
  192. package/dist/reflection/reporter.d.ts +10 -0
  193. package/dist/reflection/reporter.d.ts.map +1 -0
  194. package/dist/reflection/types.d.ts +99 -0
  195. package/dist/reflection/types.d.ts.map +1 -0
  196. package/dist/routing/classifier.d.ts +8 -0
  197. package/dist/routing/classifier.d.ts.map +1 -0
  198. package/dist/routing/index.d.ts +12 -0
  199. package/dist/routing/index.d.ts.map +1 -0
  200. package/dist/routing/router.d.ts +8 -0
  201. package/dist/routing/router.d.ts.map +1 -0
  202. package/dist/routing/types.d.ts +68 -0
  203. package/dist/routing/types.d.ts.map +1 -0
  204. package/dist/transcript/feedback.d.ts +70 -0
  205. package/dist/transcript/feedback.d.ts.map +1 -0
  206. package/dist/transcript/index.d.ts +10 -0
  207. package/dist/transcript/index.d.ts.map +1 -0
  208. package/dist/transcript/operations.d.ts +152 -0
  209. package/dist/transcript/operations.d.ts.map +1 -0
  210. package/dist/transcript/pkl-utils.d.ts +66 -0
  211. package/dist/transcript/pkl-utils.d.ts.map +1 -0
  212. package/dist/transcription/index.d.ts +17 -0
  213. package/dist/transcription/index.d.ts.map +1 -0
  214. package/dist/transcription/service.d.ts +10 -0
  215. package/dist/transcription/service.d.ts.map +1 -0
  216. package/dist/transcription/types.d.ts +41 -0
  217. package/dist/transcription/types.d.ts.map +1 -0
  218. package/dist/types.d.ts +28 -0
  219. package/dist/types.d.ts.map +1 -0
  220. package/dist/util/collision-detector.d.ts +77 -0
  221. package/dist/util/collision-detector.d.ts.map +1 -0
  222. package/dist/util/dates.d.ts +57 -0
  223. package/dist/util/dates.d.ts.map +1 -0
  224. package/dist/util/general.d.ts +3 -0
  225. package/dist/util/general.d.ts.map +1 -0
  226. package/dist/util/media.d.ts +9 -0
  227. package/dist/util/media.d.ts.map +1 -0
  228. package/dist/util/metadata.d.ts +138 -0
  229. package/dist/util/metadata.d.ts.map +1 -0
  230. package/dist/util/openai.d.ts +22 -0
  231. package/dist/util/openai.d.ts.map +1 -0
  232. package/dist/util/sounds-like-database.d.ts +98 -0
  233. package/dist/util/sounds-like-database.d.ts.map +1 -0
  234. package/dist/util/storage.d.ts +35 -0
  235. package/dist/util/storage.d.ts.map +1 -0
  236. package/dist/util/text-replacer.d.ts +56 -0
  237. package/dist/util/text-replacer.d.ts.map +1 -0
  238. package/dist/utils/entityFinder.d.ts +29 -0
  239. package/dist/utils/entityFinder.d.ts.map +1 -0
  240. package/package.json +84 -0
@@ -0,0 +1,173 @@
1
+ import { getLogger } from './index41.js';
2
+
3
+ const create = (reasoning, context, config) => {
4
+ const logger = getLogger();
5
+ const analyze = async (feedback) => {
6
+ logger.info("Analyzing feedback for: %s", feedback.transcriptPath);
7
+ const allProjects = context.getAllProjects();
8
+ const projectSummary = allProjects.map((p) => ({
9
+ id: p.id,
10
+ name: p.name,
11
+ phrases: p.classification?.explicit_phrases || [],
12
+ topics: p.classification?.topics || [],
13
+ contextType: p.classification?.context_type,
14
+ destination: p.routing?.destination
15
+ }));
16
+ const prompt = `You are analyzing why a transcription routing system made a classification error.
17
+
18
+ ## Original Classification Decision
19
+ - **Chosen Project**: ${feedback.originalDecision.projectId || "none (default routing)"}
20
+ - **Destination**: ${feedback.originalDecision.destination}
21
+ - **Confidence**: ${(feedback.originalDecision.confidence * 100).toFixed(1)}%
22
+ - **System's Reasoning**: ${feedback.originalDecision.reasoning}
23
+
24
+ ## User's Correction
25
+ - **Correct Project**: ${feedback.correction.projectId || "not specified"}
26
+ - **Correct Destination**: ${feedback.correction.destination || "not specified"}
27
+ - **Topics**: ${feedback.correction.topics?.join(", ") || "not specified"}
28
+ - **Context Type**: ${feedback.correction.contextType || "not specified"}
29
+
30
+ ## User's Explanation
31
+ "${feedback.userReason}"
32
+
33
+ ## Current Project Context
34
+ ${JSON.stringify(projectSummary, null, 2)}
35
+
36
+ ## Your Task
37
+ Analyze why the classification failed and suggest specific updates to the context system.
38
+
39
+ Return a JSON object with:
40
+ 1. "diagnosis": A clear explanation of what went wrong
41
+ 2. "suggestedUpdates": Array of updates to make, each with:
42
+ - "type": "new_project" | "new_phrase" | "new_topic" | "context_type" | "association"
43
+ - "entityType": "project" | "person" | "company" | "term"
44
+ - "entityId": The entity to update (or new ID if creating)
45
+ - "changes": Array of { "field": string, "newValue": any }
46
+ - "reasoning": Why this update helps
47
+ - "confidence": 0-1 how confident you are
48
+ 3. "clarificationQuestions": Optional questions if more info needed
49
+ 4. "confidence": Overall confidence in this analysis (0-1)
50
+
51
+ Focus on:
52
+ - Missing trigger phrases that should match the correct project
53
+ - Topics that should be associated with projects
54
+ - Context type mismatches (work vs personal)
55
+ - New projects that need to be created
56
+
57
+ Respond with ONLY the JSON object.`;
58
+ try {
59
+ const response = await reasoning.complete({
60
+ systemPrompt: "You are an expert at analyzing classification systems and suggesting improvements. Always respond with valid JSON.",
61
+ prompt
62
+ });
63
+ const analysis = JSON.parse(response.content);
64
+ logger.info("Feedback analysis complete: %d suggested updates", analysis.suggestedUpdates.length);
65
+ return analysis;
66
+ } catch (error) {
67
+ logger.error("Failed to analyze feedback", { error });
68
+ return {
69
+ diagnosis: "Unable to analyze feedback automatically. Manual review recommended.",
70
+ suggestedUpdates: [],
71
+ confidence: 0
72
+ };
73
+ }
74
+ };
75
+ const applyUpdates = async (updates) => {
76
+ logger.info("Applying %d context updates", updates.length);
77
+ for (const update of updates) {
78
+ if (update.confidence < config.autoApplyThreshold) {
79
+ logger.info(
80
+ "Skipping low-confidence update: %s (%.1f%% < %.1f%%)",
81
+ update.entityId,
82
+ update.confidence * 100,
83
+ config.autoApplyThreshold * 100
84
+ );
85
+ continue;
86
+ }
87
+ try {
88
+ if (update.type === "new_project") {
89
+ const classification = {
90
+ context_type: "work",
91
+ explicit_phrases: [],
92
+ topics: []
93
+ };
94
+ const newProject = {
95
+ id: update.entityId,
96
+ name: update.entityId,
97
+ type: "project",
98
+ description: update.reasoning,
99
+ classification,
100
+ routing: {
101
+ // No destination - will use global default
102
+ structure: "month",
103
+ filename_options: ["date", "time", "subject"]
104
+ },
105
+ active: true
106
+ };
107
+ for (const change of update.changes) {
108
+ if (change.field === "name") newProject.name = String(change.newValue);
109
+ if (change.field === "destination") newProject.routing.destination = String(change.newValue);
110
+ if (change.field === "context_type") {
111
+ newProject.classification.context_type = change.newValue;
112
+ }
113
+ if (change.field === "explicit_phrases") {
114
+ newProject.classification.explicit_phrases = change.newValue;
115
+ }
116
+ if (change.field === "topics") {
117
+ newProject.classification.topics = change.newValue;
118
+ }
119
+ }
120
+ await context.saveEntity(newProject);
121
+ logger.info("Created new project: %s", update.entityId);
122
+ } else if (update.type === "new_phrase" || update.type === "new_topic" || update.type === "context_type") {
123
+ const existing = context.getProject(update.entityId);
124
+ if (!existing) {
125
+ logger.warn("Project not found for update: %s", update.entityId);
126
+ continue;
127
+ }
128
+ const updated = { ...existing };
129
+ for (const change of update.changes) {
130
+ if (change.field === "explicit_phrases") {
131
+ const newPhrases = change.newValue;
132
+ updated.classification = {
133
+ ...updated.classification,
134
+ explicit_phrases: [
135
+ ...updated.classification?.explicit_phrases || [],
136
+ ...newPhrases.filter(
137
+ (p) => !updated.classification?.explicit_phrases?.includes(p)
138
+ )
139
+ ]
140
+ };
141
+ }
142
+ if (change.field === "topics") {
143
+ const newTopics = change.newValue;
144
+ updated.classification = {
145
+ ...updated.classification,
146
+ topics: [
147
+ ...updated.classification?.topics || [],
148
+ ...newTopics.filter(
149
+ (t) => !updated.classification?.topics?.includes(t)
150
+ )
151
+ ]
152
+ };
153
+ }
154
+ if (change.field === "context_type") {
155
+ updated.classification = {
156
+ ...updated.classification,
157
+ context_type: change.newValue
158
+ };
159
+ }
160
+ }
161
+ await context.saveEntity(updated);
162
+ logger.info("Updated project: %s", update.entityId);
163
+ }
164
+ } catch (error) {
165
+ logger.error("Failed to apply update", { update, error });
166
+ }
167
+ }
168
+ };
169
+ return { analyze, applyUpdates };
170
+ };
171
+
172
+ export { create };
173
+ //# sourceMappingURL=index30.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index30.js","sources":["../src/feedback/analyzer.ts"],"sourcesContent":["/**\n * Feedback Analyzer\n * \n * Uses a reasoning model to analyze user feedback on classification\n * decisions and suggest context updates.\n */\n\nimport { ClassificationFeedback, FeedbackAnalysis, LearningUpdate } from './types';\nimport * as Reasoning from '../reasoning';\nimport * as Context from '@redaksjon/context';\nimport * as Logging from '../logging';\n\nexport interface AnalyzerInstance {\n analyze(feedback: ClassificationFeedback): Promise<FeedbackAnalysis>;\n applyUpdates(updates: LearningUpdate[]): Promise<void>;\n}\n\nexport interface AnalyzerConfig {\n model: string;\n autoApplyThreshold: number;\n}\n\nexport const create = (\n reasoning: Reasoning.ReasoningInstance,\n context: Context.ContextInstance,\n config: AnalyzerConfig\n): AnalyzerInstance => {\n const logger = Logging.getLogger();\n\n const analyze = async (feedback: ClassificationFeedback): Promise<FeedbackAnalysis> => {\n logger.info('Analyzing feedback for: %s', feedback.transcriptPath);\n\n // Gather current context for the model to understand\n const allProjects = context.getAllProjects();\n const projectSummary = allProjects.map(p => ({\n id: p.id,\n name: p.name,\n phrases: p.classification?.explicit_phrases || [],\n topics: p.classification?.topics || [],\n contextType: p.classification?.context_type,\n destination: p.routing?.destination,\n }));\n\n const prompt = `You are analyzing why a transcription routing system made a classification error.\n\n## Original Classification Decision\n- **Chosen Project**: ${feedback.originalDecision.projectId || 'none (default routing)'}\n- **Destination**: ${feedback.originalDecision.destination}\n- **Confidence**: ${(feedback.originalDecision.confidence * 100).toFixed(1)}%\n- **System's Reasoning**: ${feedback.originalDecision.reasoning}\n\n## User's Correction\n- **Correct Project**: ${feedback.correction.projectId || 'not specified'}\n- **Correct Destination**: ${feedback.correction.destination || 'not specified'}\n- **Topics**: ${feedback.correction.topics?.join(', ') || 'not specified'}\n- **Context Type**: ${feedback.correction.contextType || 'not specified'}\n\n## User's Explanation\n\"${feedback.userReason}\"\n\n## Current Project Context\n${JSON.stringify(projectSummary, null, 2)}\n\n## Your Task\nAnalyze why the classification failed and suggest specific updates to the context system.\n\nReturn a JSON object with:\n1. \"diagnosis\": A clear explanation of what went wrong\n2. \"suggestedUpdates\": Array of updates to make, each with:\n - \"type\": \"new_project\" | \"new_phrase\" | \"new_topic\" | \"context_type\" | \"association\"\n - \"entityType\": \"project\" | \"person\" | \"company\" | \"term\"\n - \"entityId\": The entity to update (or new ID if creating)\n - \"changes\": Array of { \"field\": string, \"newValue\": any }\n - \"reasoning\": Why this update helps\n - \"confidence\": 0-1 how confident you are\n3. \"clarificationQuestions\": Optional questions if more info needed\n4. \"confidence\": Overall confidence in this analysis (0-1)\n\nFocus on:\n- Missing trigger phrases that should match the correct project\n- Topics that should be associated with projects\n- Context type mismatches (work vs personal)\n- New projects that need to be created\n\nRespond with ONLY the JSON object.`;\n\n try {\n const response = await reasoning.complete({\n systemPrompt: 'You are an expert at analyzing classification systems and suggesting improvements. Always respond with valid JSON.',\n prompt,\n });\n\n // Parse the response\n const analysis = JSON.parse(response.content) as FeedbackAnalysis;\n logger.info('Feedback analysis complete: %d suggested updates', analysis.suggestedUpdates.length);\n\n return analysis;\n } catch (error) {\n logger.error('Failed to analyze feedback', { error });\n \n // Return a basic analysis if reasoning fails\n return {\n diagnosis: 'Unable to analyze feedback automatically. Manual review recommended.',\n suggestedUpdates: [],\n confidence: 0,\n };\n }\n };\n\n const applyUpdates = async (updates: LearningUpdate[]): Promise<void> => {\n logger.info('Applying %d context updates', updates.length);\n\n for (const update of updates) {\n // Skip low-confidence updates unless auto-apply threshold is 0\n if (update.confidence < config.autoApplyThreshold) {\n logger.info('Skipping low-confidence update: %s (%.1f%% < %.1f%%)',\n update.entityId, \n update.confidence * 100, \n config.autoApplyThreshold * 100\n );\n continue;\n }\n\n try {\n if (update.type === 'new_project') {\n // Create new project\n const classification: {\n context_type: 'work' | 'personal' | 'mixed';\n explicit_phrases: string[];\n topics: string[];\n } = {\n context_type: 'work',\n explicit_phrases: [],\n topics: [],\n };\n \n const newProject: {\n id: string;\n name: string;\n type: 'project';\n description: string;\n classification: typeof classification;\n routing: {\n destination?: string;\n structure: 'none' | 'year' | 'month' | 'day';\n filename_options: Array<'date' | 'time' | 'subject'>;\n };\n active: boolean;\n } = {\n id: update.entityId,\n name: update.entityId,\n type: 'project' as const,\n description: update.reasoning,\n classification,\n routing: {\n // No destination - will use global default\n structure: 'month' as const,\n filename_options: ['date', 'time', 'subject'] as Array<'date' | 'time' | 'subject'>,\n },\n active: true,\n };\n\n // Apply changes\n for (const change of update.changes) {\n if (change.field === 'name') newProject.name = String(change.newValue);\n if (change.field === 'destination') newProject.routing.destination = String(change.newValue);\n if (change.field === 'context_type') {\n newProject.classification.context_type = change.newValue as 'work' | 'personal' | 'mixed';\n }\n if (change.field === 'explicit_phrases') {\n newProject.classification.explicit_phrases = change.newValue as string[];\n }\n if (change.field === 'topics') {\n newProject.classification.topics = change.newValue as string[];\n }\n }\n\n await context.saveEntity(newProject);\n logger.info('Created new project: %s', update.entityId);\n\n } else if (update.type === 'new_phrase' || update.type === 'new_topic' || update.type === 'context_type') {\n // Update existing project\n const existing = context.getProject(update.entityId);\n if (!existing) {\n logger.warn('Project not found for update: %s', update.entityId);\n continue;\n }\n\n // Create updated entity\n const updated = { ...existing };\n \n for (const change of update.changes) {\n if (change.field === 'explicit_phrases') {\n const newPhrases = change.newValue as string[];\n updated.classification = {\n ...updated.classification,\n explicit_phrases: [\n ...(updated.classification?.explicit_phrases || []),\n ...newPhrases.filter(p => \n !updated.classification?.explicit_phrases?.includes(p)\n ),\n ],\n };\n }\n if (change.field === 'topics') {\n const newTopics = change.newValue as string[];\n updated.classification = {\n ...updated.classification,\n topics: [\n ...(updated.classification?.topics || []),\n ...newTopics.filter(t => \n !updated.classification?.topics?.includes(t)\n ),\n ],\n };\n }\n if (change.field === 'context_type') {\n updated.classification = {\n ...updated.classification,\n context_type: change.newValue as 'work' | 'personal' | 'mixed',\n };\n }\n }\n\n await context.saveEntity(updated);\n logger.info('Updated project: %s', update.entityId);\n }\n } catch (error) {\n logger.error('Failed to apply update', { update, error });\n }\n }\n };\n\n return { analyze, applyUpdates };\n};\n\n"],"names":["Logging.getLogger"],"mappings":"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"}
@@ -0,0 +1,423 @@
1
+ import * as Context from '@redaksjon/context';
2
+ import { create as create$1 } from './index6.js';
3
+ import { create as create$2 } from './index53.js';
4
+ import { create as create$3 } from './index11.js';
5
+ import { create as create$4 } from './index3.js';
6
+ import { create as create$5 } from './index2.js';
7
+ import { create as create$7 } from './index5.js';
8
+ import { create as create$6 } from './index35.js';
9
+ import { getLogger } from './index41.js';
10
+ import { extractTagsFromSignals, createRoutingMetadata } from './index14.js';
11
+
12
+ const create = async (config) => {
13
+ const logger = getLogger();
14
+ const currentWorkingDir = globalThis.process.cwd();
15
+ logger.debug("Initializing intelligent transcription pipeline...");
16
+ const context = await Context.create({
17
+ startingDir: config.contextDirectory || currentWorkingDir,
18
+ contextDirectories: config.contextDirectories
19
+ });
20
+ logger.debug("Context system initialized - ready to query entities via tools");
21
+ const defaultPath = config.outputDirectory || "~/notes";
22
+ const defaultStructure = config.outputStructure || "month";
23
+ const defaultFilenameOptions = config.outputFilenameOptions || ["date", "time", "subject"];
24
+ const contextProjects = context.getAllProjects();
25
+ const routingProjects = contextProjects.filter((project) => project.active !== false).map((project) => ({
26
+ projectId: project.id,
27
+ destination: {
28
+ path: project.routing?.destination || defaultPath,
29
+ structure: project.routing?.structure || defaultStructure,
30
+ filename_options: project.routing?.filename_options || defaultFilenameOptions,
31
+ createDirectories: true
32
+ },
33
+ classification: project.classification,
34
+ active: project.active,
35
+ auto_tags: project.routing?.auto_tags
36
+ }));
37
+ logger.debug("Loaded %d projects from context for routing", routingProjects.length);
38
+ const routingConfig = {
39
+ default: {
40
+ path: defaultPath,
41
+ structure: defaultStructure,
42
+ filename_options: defaultFilenameOptions,
43
+ createDirectories: true
44
+ },
45
+ projects: routingProjects,
46
+ conflict_resolution: "primary"
47
+ };
48
+ const routing = create$1(routingConfig, context);
49
+ logger.debug("Routing system initialized");
50
+ const output = create$2({
51
+ intermediateDir: config.intermediateDir || "./output/protokoll",
52
+ keepIntermediates: config.keepIntermediates ?? true});
53
+ logger.debug("Output manager initialized");
54
+ const reflection = config.selfReflection ? create$3({
55
+ format: "markdown",
56
+ includeConversation: false,
57
+ includeOutput: true
58
+ }) : null;
59
+ if (reflection) {
60
+ logger.debug("Self-reflection system enabled");
61
+ }
62
+ const transcription = create$4({
63
+ defaultModel: config.transcriptionModel
64
+ });
65
+ logger.debug("Transcription service initialized with model: %s", config.transcriptionModel);
66
+ const reasoning = create$5({
67
+ model: config.model,
68
+ reasoningLevel: config.reasoningLevel
69
+ });
70
+ logger.debug("Reasoning system initialized with model: %s, reasoning level: %s", config.model, config.reasoningLevel || "medium");
71
+ const complete = config.processedDirectory ? create$6({
72
+ processedDirectory: config.processedDirectory,
73
+ outputStructure: config.outputStructure,
74
+ dryRun: config.dryRun
75
+ }) : null;
76
+ if (complete) {
77
+ logger.debug("Complete phase initialized with processed directory: %s", config.processedDirectory);
78
+ }
79
+ const extractTitleFromPath = (outputPath) => {
80
+ const filename = outputPath.split("/").pop()?.replace(".md", "");
81
+ if (!filename) return void 0;
82
+ const withoutDate = filename.replace(/^\d{2}-\d{4}-/, "");
83
+ if (!withoutDate) return void 0;
84
+ return withoutDate.split("-").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
85
+ };
86
+ const isMeaningfulTitle = (title) => {
87
+ if (!title) return false;
88
+ const stripped = title.replace(/\s+/g, "");
89
+ const numberRatio = (stripped.match(/\d/g) || []).length / stripped.length;
90
+ if (numberRatio > 0.5) return false;
91
+ if (stripped.length < 3) return false;
92
+ const badPatterns = /^(i|i have|i am|the|a|an|um|uh|so|well|okay|oh|hey|hi)$/i;
93
+ if (badPatterns.test(title.trim())) return false;
94
+ return true;
95
+ };
96
+ const generateTitleFromContent = async (transcriptText, fallbackTitle) => {
97
+ try {
98
+ const textSample = transcriptText.slice(0, 2e3);
99
+ const response = await reasoning.complete({
100
+ systemPrompt: `You are a title generator. Given a transcript, generate a concise, descriptive title (3-8 words) that captures the main topic or theme.
101
+
102
+ Rules:
103
+ - Output ONLY the title, nothing else
104
+ - No quotes around the title
105
+ - Use Title Case
106
+ - Be specific - avoid generic titles like "Meeting Notes" or "Discussion"
107
+ - Focus on the main subject matter
108
+ - If there are multiple topics, pick the most prominent one`,
109
+ prompt: `Generate a title for this transcript:
110
+
111
+ ${textSample}`
112
+ });
113
+ const title = response.content.trim().replace(/^["']|["']$/g, "").replace(/^#\s*/, "").trim();
114
+ if (title && title.length > 0 && title.length < 100) {
115
+ logger.debug("Generated title from content: %s", title);
116
+ return title;
117
+ }
118
+ logger.debug("Generated title was invalid, using fallback");
119
+ return fallbackTitle || "Untitled";
120
+ } catch (error) {
121
+ logger.warn("Title generation failed, using fallback", { error });
122
+ return fallbackTitle || "Untitled";
123
+ }
124
+ };
125
+ const processInput = async (input) => {
126
+ const startTime = Date.now();
127
+ const progressPrefix = input.progress ? `[${input.progress.current}/${input.progress.total}]` : "";
128
+ const log = (level, message, ...args) => {
129
+ const prefixedMessage = progressPrefix ? `${progressPrefix} ${message}` : message;
130
+ if (level === "info") {
131
+ logger.info(prefixedMessage, ...args);
132
+ } else {
133
+ logger.debug(prefixedMessage, ...args);
134
+ }
135
+ };
136
+ log("info", "Processing: %s (hash: %s)", input.audioFile, input.hash);
137
+ const state = {
138
+ input,
139
+ startTime: /* @__PURE__ */ new Date()
140
+ };
141
+ if (reflection) {
142
+ reflection.collector.start();
143
+ }
144
+ try {
145
+ log("debug", "Checking onboarding state...");
146
+ const onboardingState = { needsOnboarding: false };
147
+ if (onboardingState.needsOnboarding) ;
148
+ log("info", "Transcribing audio...");
149
+ const whisperStart = Date.now();
150
+ const transcriptionResult = await transcription.transcribe(input.audioFile, {
151
+ model: config.transcriptionModel
152
+ });
153
+ state.rawTranscript = transcriptionResult.text;
154
+ const whisperDuration = Date.now() - whisperStart;
155
+ log(
156
+ "info",
157
+ "Transcription: %d chars in %.1fs",
158
+ state.rawTranscript.length,
159
+ whisperDuration / 1e3
160
+ );
161
+ if (reflection) {
162
+ reflection.collector.recordWhisper(whisperDuration);
163
+ }
164
+ log("debug", "Determining routing destination...");
165
+ const routingContext = {
166
+ transcriptText: state.rawTranscript || "",
167
+ audioDate: input.creation,
168
+ sourceFile: input.audioFile,
169
+ hash: input.hash
170
+ };
171
+ const routeResult = routing.route(routingContext);
172
+ log(
173
+ "debug",
174
+ "Routing decision: project=%s, confidence=%.2f",
175
+ routeResult.projectId || "default",
176
+ routeResult.confidence
177
+ );
178
+ if (reflection) {
179
+ reflection.collector.recordRoutingDecision({
180
+ projectId: routeResult.projectId,
181
+ destination: routeResult.destination.path,
182
+ confidence: routeResult.confidence,
183
+ reasoning: routeResult.reasoning,
184
+ signals: routeResult.signals.map((s) => ({
185
+ type: s.type,
186
+ value: s.value,
187
+ weight: s.weight
188
+ })),
189
+ alternativesConsidered: routeResult.alternateMatches?.map((alt) => ({
190
+ projectId: alt.projectId,
191
+ confidence: alt.confidence,
192
+ whyNotChosen: `Lower confidence (${(alt.confidence * 100).toFixed(1)}%)`
193
+ }))
194
+ });
195
+ }
196
+ const outputPath = routing.buildOutputPath(routeResult, routingContext);
197
+ log("debug", "Output path: %s", outputPath);
198
+ log("debug", "Setting up output directories...");
199
+ const paths = output.createOutputPaths(
200
+ input.audioFile,
201
+ outputPath,
202
+ input.hash,
203
+ input.creation
204
+ );
205
+ await output.ensureDirectories(paths);
206
+ await output.writeIntermediate(paths, "transcript", {
207
+ text: state.rawTranscript,
208
+ model: config.transcriptionModel,
209
+ duration: whisperDuration
210
+ });
211
+ log("info", "Enhancing with %s...", config.model);
212
+ const agenticStart = Date.now();
213
+ const toolContext = {
214
+ transcriptText: state.rawTranscript || "",
215
+ audioDate: input.creation,
216
+ sourceFile: input.audioFile,
217
+ contextInstance: context,
218
+ routingInstance: routing,
219
+ interactiveMode: config.interactive
220
+ // Interactive moved to protokoll-cli
221
+ // interactiveInstance: interactive,
222
+ };
223
+ const executor = create$7(reasoning, toolContext);
224
+ const agenticResult = await executor.process(state.rawTranscript || "");
225
+ state.enhancedText = agenticResult.enhancedText;
226
+ const toolsUsed = agenticResult.toolsUsed;
227
+ const agenticDuration = Date.now() - agenticStart;
228
+ if (reflection) {
229
+ for (const tool of toolsUsed) {
230
+ reflection.collector.recordToolCall(tool, agenticDuration / toolsUsed.length, true);
231
+ }
232
+ reflection.collector.recordCorrection(state.rawTranscript || "", state.enhancedText);
233
+ if (agenticResult.totalTokens) {
234
+ reflection.collector.recordModelResponse(config.model, agenticResult.totalTokens);
235
+ }
236
+ if (agenticResult.contextChanges) {
237
+ for (const change of agenticResult.contextChanges) {
238
+ reflection.collector.recordContextChange(change);
239
+ }
240
+ }
241
+ }
242
+ await output.writeIntermediate(paths, "session", {
243
+ iterations: agenticResult.iterations,
244
+ toolsUsed: agenticResult.toolsUsed,
245
+ state: agenticResult.state
246
+ });
247
+ if (agenticResult.state.routeDecision?.destination?.path) {
248
+ const agenticRoute = agenticResult.state.routeDecision;
249
+ log(
250
+ "debug",
251
+ "Agentic processing found route: %s -> %s",
252
+ agenticRoute.projectId || "unknown",
253
+ agenticRoute.destination.path
254
+ );
255
+ routeResult.projectId = agenticRoute.projectId || routeResult.projectId;
256
+ routeResult.destination = {
257
+ ...routeResult.destination,
258
+ path: agenticRoute.destination.path,
259
+ structure: agenticRoute.destination.structure || routeResult.destination.structure
260
+ };
261
+ routeResult.confidence = agenticRoute.confidence || routeResult.confidence;
262
+ routeResult.reasoning = agenticRoute.reasoning || routeResult.reasoning;
263
+ if (agenticRoute.signals) {
264
+ routeResult.signals = agenticRoute.signals;
265
+ }
266
+ const newOutputPath = routing.buildOutputPath(routeResult, routingContext);
267
+ log("debug", "Updated output path: %s -> %s", outputPath, newOutputPath);
268
+ const newPaths = output.createOutputPaths(
269
+ input.audioFile,
270
+ newOutputPath,
271
+ input.hash,
272
+ input.creation
273
+ );
274
+ await output.ensureDirectories(newPaths);
275
+ Object.assign(paths, newPaths);
276
+ }
277
+ log("debug", "Writing raw transcript to .transcript/ directory...");
278
+ await output.writeRawTranscript(paths, {
279
+ text: state.rawTranscript,
280
+ model: config.transcriptionModel,
281
+ duration: whisperDuration,
282
+ audioFile: input.audioFile,
283
+ audioHash: input.hash,
284
+ transcribedAt: (/* @__PURE__ */ new Date()).toISOString()
285
+ });
286
+ log("debug", "Writing final transcript...");
287
+ if (state.enhancedText) {
288
+ const buildEntityReferences = () => {
289
+ const refs = agenticResult.state.referencedEntities;
290
+ if (!refs) return void 0;
291
+ const entities = {
292
+ people: [],
293
+ projects: [],
294
+ terms: [],
295
+ companies: []
296
+ };
297
+ for (const personId of refs.people) {
298
+ const person = context.getPerson(personId);
299
+ if (person) {
300
+ entities.people.push({ id: person.id, name: person.name, type: "person" });
301
+ }
302
+ }
303
+ for (const projectId of refs.projects) {
304
+ const project = context.getProject(projectId);
305
+ if (project) {
306
+ entities.projects.push({ id: project.id, name: project.name, type: "project" });
307
+ }
308
+ }
309
+ for (const termId of refs.terms) {
310
+ const term = context.getTerm(termId);
311
+ if (term) {
312
+ entities.terms.push({ id: term.id, name: term.name, type: "term" });
313
+ }
314
+ }
315
+ for (const companyId of refs.companies) {
316
+ const company = context.getCompany(companyId);
317
+ if (company) {
318
+ entities.companies.push({ id: company.id, name: company.name, type: "company" });
319
+ }
320
+ }
321
+ const hasEntities = entities.people.length > 0 || entities.projects.length > 0 || entities.terms.length > 0 || entities.companies.length > 0;
322
+ return hasEntities ? entities : void 0;
323
+ };
324
+ const pathTitle = extractTitleFromPath(paths.final);
325
+ let title;
326
+ if (isMeaningfulTitle(pathTitle)) {
327
+ title = pathTitle;
328
+ } else {
329
+ log("debug", "Path-derived title not meaningful (%s), generating from content...", pathTitle || "empty");
330
+ title = await generateTitleFromContent(state.enhancedText, pathTitle);
331
+ log("info", "Generated title: %s", title);
332
+ const contextWithTitle = {
333
+ ...routingContext,
334
+ subjectOverride: title
335
+ };
336
+ const newOutputPath = routing.buildOutputPath(routeResult, contextWithTitle);
337
+ if (newOutputPath !== paths.final) {
338
+ log("debug", "Updating output path with generated title: %s -> %s", paths.final, newOutputPath);
339
+ const newPaths = output.createOutputPaths(
340
+ input.audioFile,
341
+ newOutputPath,
342
+ input.hash,
343
+ input.creation
344
+ );
345
+ await output.ensureDirectories(newPaths);
346
+ Object.assign(paths, newPaths);
347
+ }
348
+ }
349
+ const transcriptMetadata = {
350
+ title,
351
+ projectId: routeResult.projectId || void 0,
352
+ project: routeResult.projectId || void 0,
353
+ date: input.creation,
354
+ routing: createRoutingMetadata(routeResult),
355
+ tags: extractTagsFromSignals(routeResult.signals),
356
+ confidence: routeResult.confidence,
357
+ entities: buildEntityReferences()
358
+ };
359
+ await output.writeTranscript(paths, state.enhancedText, transcriptMetadata);
360
+ }
361
+ log("debug", "Generating reflection report...");
362
+ let reflectionReport;
363
+ if (reflection) {
364
+ reflectionReport = reflection.generate(
365
+ input.audioFile,
366
+ paths.final,
367
+ void 0,
368
+ state.enhancedText
369
+ );
370
+ if (paths.intermediate.reflection) {
371
+ await reflection.save(reflectionReport, paths.intermediate.reflection);
372
+ }
373
+ }
374
+ log("debug", "Finalizing session...");
375
+ if (!config.keepIntermediates && !config.debug) {
376
+ await output.cleanIntermediates(paths);
377
+ }
378
+ let processedAudioPath;
379
+ if (complete) {
380
+ const subject = paths.final.split("/").pop()?.replace(".md", "") || void 0;
381
+ processedAudioPath = await complete.complete(
382
+ input.audioFile,
383
+ input.hash,
384
+ input.creation,
385
+ subject
386
+ );
387
+ }
388
+ const processingTime = Date.now() - startTime;
389
+ log(
390
+ "info",
391
+ "Enhancement: %d iterations, %d tools, %.1fs",
392
+ agenticResult.iterations,
393
+ toolsUsed.length,
394
+ agenticDuration / 1e3
395
+ );
396
+ if (agenticResult.totalTokens) {
397
+ log("info", "Tokens: %d total", agenticResult.totalTokens);
398
+ }
399
+ log("info", "Output: %s (%.1fs total)", paths.final, processingTime / 1e3);
400
+ return {
401
+ outputPath: paths.final,
402
+ enhancedText: state.enhancedText || "",
403
+ rawTranscript: state.rawTranscript || "",
404
+ routedProject: routeResult.projectId,
405
+ routingConfidence: routeResult.confidence,
406
+ processingTime,
407
+ toolsUsed,
408
+ correctionsApplied: agenticResult.state.resolvedEntities.size,
409
+ processedAudioPath,
410
+ reflection: reflectionReport,
411
+ // session, // Interactive moved to protokoll-cli
412
+ intermediatePaths: paths
413
+ };
414
+ } catch (error) {
415
+ logger.error("Pipeline error", { error });
416
+ throw error;
417
+ }
418
+ };
419
+ return { process: processInput };
420
+ };
421
+
422
+ export { create };
423
+ //# sourceMappingURL=index31.js.map