@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
package/dist/agentic/executor.js
CHANGED
|
@@ -12,6 +12,8 @@ const create = (reasoning, ctx)=>{
|
|
|
12
12
|
resolvedEntities: new Map(),
|
|
13
13
|
confidence: 0
|
|
14
14
|
};
|
|
15
|
+
// Make resolvedEntities available to tools so they can avoid re-asking
|
|
16
|
+
ctx.resolvedEntities = state.resolvedEntities;
|
|
15
17
|
const toolsUsed = [];
|
|
16
18
|
const contextChanges = [];
|
|
17
19
|
let iterations = 0;
|
|
@@ -98,7 +100,7 @@ Remember: preserve ALL content, only fix transcription errors.`;
|
|
|
98
100
|
logger.debug('Executing tool: %s', toolCall.name);
|
|
99
101
|
toolsUsed.push(toolCall.name);
|
|
100
102
|
try {
|
|
101
|
-
var _result_data, _result_data1;
|
|
103
|
+
var _result_data, _result_data_routingDecision, _result_data1, _result_data2, _result_data_project_routing, _result_data_project, _result_data3;
|
|
102
104
|
const result = await registry.executeTool(toolCall.name, toolCall.arguments);
|
|
103
105
|
// Format result for the model
|
|
104
106
|
const resultStr = JSON.stringify(result.data || {
|
|
@@ -112,40 +114,49 @@ Remember: preserve ALL content, only fix transcription errors.`;
|
|
|
112
114
|
});
|
|
113
115
|
logger.debug('Tool %s result: %s', toolCall.name, result.success ? 'success' : 'failed');
|
|
114
116
|
// Handle results that need user input
|
|
115
|
-
if (
|
|
116
|
-
|
|
117
|
+
// Check if interactive handler is available (not gated by interactiveMode flag)
|
|
118
|
+
if (result.needsUserInput && ctx.interactiveInstance) {
|
|
119
|
+
var _result_data4, _result_data5, _result_data6, _result_data7;
|
|
117
120
|
logger.info('Interactive: %s requires clarification', toolCall.name);
|
|
118
121
|
const termName = String(toolCall.arguments.name || toolCall.arguments.term || '');
|
|
119
122
|
const clarification = await ctx.interactiveInstance.handleClarification({
|
|
120
|
-
type: ((
|
|
121
|
-
term: ((
|
|
123
|
+
type: ((_result_data4 = result.data) === null || _result_data4 === void 0 ? void 0 : _result_data4.clarificationType) || 'general',
|
|
124
|
+
term: ((_result_data5 = result.data) === null || _result_data5 === void 0 ? void 0 : _result_data5.term) || termName,
|
|
122
125
|
context: result.userPrompt || '',
|
|
123
|
-
suggestion: (
|
|
124
|
-
options: (
|
|
126
|
+
suggestion: (_result_data6 = result.data) === null || _result_data6 === void 0 ? void 0 : _result_data6.suggestion,
|
|
127
|
+
options: (_result_data7 = result.data) === null || _result_data7 === void 0 ? void 0 : _result_data7.options
|
|
125
128
|
});
|
|
126
129
|
if (clarification.response) {
|
|
127
|
-
var
|
|
130
|
+
var _result_data8, _result_data9;
|
|
128
131
|
state.resolvedEntities.set(termName, clarification.response);
|
|
129
132
|
logger.info('Clarified: %s -> %s', termName, clarification.response);
|
|
130
|
-
// Handle new project
|
|
131
|
-
if (((
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
133
|
+
// Handle new project/term wizard response
|
|
134
|
+
if (((_result_data8 = result.data) === null || _result_data8 === void 0 ? void 0 : _result_data8.clarificationType) === 'new_project' && clarification.additionalInfo) {
|
|
135
|
+
var _result_data10;
|
|
136
|
+
const wizardResult = clarification.additionalInfo;
|
|
137
|
+
const knownProjects = (_result_data10 = result.data) === null || _result_data10 === void 0 ? void 0 : _result_data10.knownProjects;
|
|
138
|
+
if (wizardResult.action === 'create') {
|
|
139
|
+
// CREATE NEW PROJECT
|
|
140
|
+
const projectName = wizardResult.projectName || termName;
|
|
141
|
+
const projectId = projectName.toLowerCase().replace(/\s+/g, '-');
|
|
142
|
+
const projectDestination = wizardResult.destination;
|
|
136
143
|
const newProject = {
|
|
137
144
|
id: projectId,
|
|
138
|
-
name:
|
|
145
|
+
name: projectName,
|
|
139
146
|
type: 'project',
|
|
140
|
-
description:
|
|
147
|
+
description: wizardResult.description || `Project for "${projectName}"`,
|
|
141
148
|
classification: {
|
|
142
149
|
context_type: 'work',
|
|
143
150
|
explicit_phrases: [
|
|
144
|
-
termName.toLowerCase()
|
|
145
|
-
|
|
151
|
+
termName.toLowerCase(),
|
|
152
|
+
projectName.toLowerCase()
|
|
153
|
+
].filter((v, i, a)=>a.indexOf(v) === i)
|
|
146
154
|
},
|
|
147
155
|
routing: {
|
|
148
|
-
destination
|
|
156
|
+
// Only include destination if explicitly provided - otherwise uses global default
|
|
157
|
+
...projectDestination && {
|
|
158
|
+
destination: projectDestination
|
|
159
|
+
},
|
|
149
160
|
structure: 'month',
|
|
150
161
|
filename_options: [
|
|
151
162
|
'date',
|
|
@@ -157,39 +168,431 @@ Remember: preserve ALL content, only fix transcription errors.`;
|
|
|
157
168
|
};
|
|
158
169
|
try {
|
|
159
170
|
await ctx.contextInstance.saveEntity(newProject);
|
|
160
|
-
|
|
161
|
-
|
|
171
|
+
await ctx.contextInstance.reload(); // Reload so subsequent searches find this entity
|
|
172
|
+
logger.info('Created new project: %s%s', projectName, projectDestination ? ` -> ${projectDestination}` : ' (using default destination)');
|
|
162
173
|
contextChanges.push({
|
|
163
174
|
entityType: 'project',
|
|
164
175
|
entityId: projectId,
|
|
165
|
-
entityName:
|
|
176
|
+
entityName: projectName,
|
|
166
177
|
action: 'created',
|
|
167
178
|
details: {
|
|
168
|
-
|
|
169
|
-
|
|
179
|
+
...projectDestination && {
|
|
180
|
+
destination: projectDestination
|
|
181
|
+
},
|
|
182
|
+
description: wizardResult.description,
|
|
183
|
+
triggeredByTerm: termName
|
|
170
184
|
}
|
|
171
185
|
});
|
|
172
|
-
// Update routing
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
186
|
+
// Update routing if destination was specified
|
|
187
|
+
if (projectDestination) {
|
|
188
|
+
state.routeDecision = {
|
|
189
|
+
projectId,
|
|
190
|
+
destination: {
|
|
191
|
+
path: projectDestination,
|
|
192
|
+
structure: 'month'
|
|
193
|
+
},
|
|
194
|
+
confidence: 1.0,
|
|
195
|
+
signals: [
|
|
196
|
+
{
|
|
197
|
+
type: 'explicit_phrase',
|
|
198
|
+
value: termName,
|
|
199
|
+
weight: 1.0
|
|
200
|
+
}
|
|
201
|
+
],
|
|
202
|
+
reasoning: `User created new project "${projectName}" routing to ${projectDestination}`
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
} catch (error) {
|
|
206
|
+
logger.warn('Failed to save new project: %s', error);
|
|
207
|
+
}
|
|
208
|
+
} else if (wizardResult.action === 'link' && typeof wizardResult.linkedProjectIndex === 'number') {
|
|
209
|
+
// LINK TO EXISTING PROJECT
|
|
210
|
+
if (knownProjects && wizardResult.linkedProjectIndex < knownProjects.length) {
|
|
211
|
+
var _linkedProject_classification, _linkedProject_classification1, _linkedProject_routing, _linkedProject_routing1, _linkedProject_routing2;
|
|
212
|
+
const linkedProject = knownProjects[wizardResult.linkedProjectIndex];
|
|
213
|
+
// Add the term as an alias
|
|
214
|
+
const existingPhrases = ((_linkedProject_classification = linkedProject.classification) === null || _linkedProject_classification === void 0 ? void 0 : _linkedProject_classification.explicit_phrases) || [];
|
|
215
|
+
const updatedPhrases = [
|
|
216
|
+
...existingPhrases,
|
|
217
|
+
termName.toLowerCase()
|
|
218
|
+
].filter((v, i, a)=>a.indexOf(v) === i); // dedupe
|
|
219
|
+
const updatedProject = {
|
|
220
|
+
...linkedProject,
|
|
221
|
+
type: 'project',
|
|
222
|
+
// Add term description to project notes if provided
|
|
223
|
+
notes: wizardResult.termDescription ? `${linkedProject.description || ''}\n\n${termName}: ${wizardResult.termDescription}`.trim() : linkedProject.description,
|
|
224
|
+
classification: {
|
|
225
|
+
...linkedProject.classification,
|
|
226
|
+
context_type: ((_linkedProject_classification1 = linkedProject.classification) === null || _linkedProject_classification1 === void 0 ? void 0 : _linkedProject_classification1.context_type) || 'work',
|
|
227
|
+
explicit_phrases: updatedPhrases
|
|
178
228
|
},
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
{
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
229
|
+
routing: {
|
|
230
|
+
// Preserve existing destination (or omit if not set)
|
|
231
|
+
...((_linkedProject_routing = linkedProject.routing) === null || _linkedProject_routing === void 0 ? void 0 : _linkedProject_routing.destination) && {
|
|
232
|
+
destination: linkedProject.routing.destination
|
|
233
|
+
},
|
|
234
|
+
structure: ((_linkedProject_routing1 = linkedProject.routing) === null || _linkedProject_routing1 === void 0 ? void 0 : _linkedProject_routing1.structure) || 'month',
|
|
235
|
+
filename_options: ((_linkedProject_routing2 = linkedProject.routing) === null || _linkedProject_routing2 === void 0 ? void 0 : _linkedProject_routing2.filename_options) || [
|
|
236
|
+
'date',
|
|
237
|
+
'time'
|
|
238
|
+
]
|
|
239
|
+
}
|
|
240
|
+
};
|
|
241
|
+
try {
|
|
242
|
+
var _linkedProject_routing3;
|
|
243
|
+
await ctx.contextInstance.saveEntity(updatedProject);
|
|
244
|
+
await ctx.contextInstance.reload(); // Reload so subsequent searches find this entity
|
|
245
|
+
logger.info('Linked "%s" to project "%s"', termName, linkedProject.name);
|
|
246
|
+
contextChanges.push({
|
|
247
|
+
entityType: 'project',
|
|
248
|
+
entityId: linkedProject.id,
|
|
249
|
+
entityName: linkedProject.name,
|
|
250
|
+
action: 'updated',
|
|
251
|
+
details: {
|
|
252
|
+
addedAlias: termName,
|
|
253
|
+
termDescription: wizardResult.termDescription,
|
|
254
|
+
explicit_phrases: updatedPhrases
|
|
185
255
|
}
|
|
186
|
-
|
|
187
|
-
|
|
256
|
+
});
|
|
257
|
+
// Update routing to use the linked project
|
|
258
|
+
if ((_linkedProject_routing3 = linkedProject.routing) === null || _linkedProject_routing3 === void 0 ? void 0 : _linkedProject_routing3.destination) {
|
|
259
|
+
state.routeDecision = {
|
|
260
|
+
projectId: linkedProject.id,
|
|
261
|
+
destination: {
|
|
262
|
+
path: linkedProject.routing.destination,
|
|
263
|
+
structure: 'month'
|
|
264
|
+
},
|
|
265
|
+
confidence: 1.0,
|
|
266
|
+
signals: [
|
|
267
|
+
{
|
|
268
|
+
type: 'explicit_phrase',
|
|
269
|
+
value: termName,
|
|
270
|
+
weight: 1.0
|
|
271
|
+
}
|
|
272
|
+
],
|
|
273
|
+
reasoning: `User linked "${termName}" to existing project "${linkedProject.name}"`
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
} catch (error) {
|
|
277
|
+
logger.warn('Failed to update project with alias: %s', error);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
} else if (wizardResult.action === 'term') {
|
|
281
|
+
var _wizardResult_createdProject;
|
|
282
|
+
// CREATE NEW TERM ENTITY
|
|
283
|
+
const termNameFinal = wizardResult.termName || termName;
|
|
284
|
+
const termId = termNameFinal.toLowerCase().replace(/\s+/g, '-');
|
|
285
|
+
// Get project IDs from indices
|
|
286
|
+
const projectIds = [];
|
|
287
|
+
if (wizardResult.termProjects && knownProjects) {
|
|
288
|
+
for (const idx of wizardResult.termProjects){
|
|
289
|
+
if (idx >= 0 && idx < knownProjects.length) {
|
|
290
|
+
projectIds.push(knownProjects[idx].id);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
// Handle nested project creation from term wizard
|
|
295
|
+
if (((_wizardResult_createdProject = wizardResult.createdProject) === null || _wizardResult_createdProject === void 0 ? void 0 : _wizardResult_createdProject.action) === 'create' && wizardResult.createdProject.projectName) {
|
|
296
|
+
const projectName = wizardResult.createdProject.projectName;
|
|
297
|
+
const projectId = projectName.toLowerCase().replace(/\s+/g, '-');
|
|
298
|
+
const projectDestination = wizardResult.createdProject.destination;
|
|
299
|
+
const newProject = {
|
|
300
|
+
id: projectId,
|
|
301
|
+
name: projectName,
|
|
302
|
+
type: 'project',
|
|
303
|
+
description: wizardResult.createdProject.description || `Project for "${projectName}"`,
|
|
304
|
+
classification: {
|
|
305
|
+
context_type: 'work',
|
|
306
|
+
explicit_phrases: [
|
|
307
|
+
projectName.toLowerCase(),
|
|
308
|
+
termNameFinal.toLowerCase()
|
|
309
|
+
].filter((v, i, a)=>a.indexOf(v) === i)
|
|
310
|
+
},
|
|
311
|
+
routing: {
|
|
312
|
+
// Only include destination if explicitly provided - otherwise uses global default
|
|
313
|
+
...projectDestination && {
|
|
314
|
+
destination: projectDestination
|
|
315
|
+
},
|
|
316
|
+
structure: 'month',
|
|
317
|
+
filename_options: [
|
|
318
|
+
'date',
|
|
319
|
+
'time',
|
|
320
|
+
'subject'
|
|
321
|
+
]
|
|
322
|
+
},
|
|
323
|
+
active: true
|
|
188
324
|
};
|
|
325
|
+
try {
|
|
326
|
+
await ctx.contextInstance.saveEntity(newProject);
|
|
327
|
+
await ctx.contextInstance.reload(); // Reload so subsequent searches find this entity
|
|
328
|
+
logger.info('Created new project from term wizard: %s%s', projectName, projectDestination ? ` -> ${projectDestination}` : ' (using default destination)');
|
|
329
|
+
// Add the new project to the projectIds list for term association
|
|
330
|
+
projectIds.push(projectId);
|
|
331
|
+
contextChanges.push({
|
|
332
|
+
entityType: 'project',
|
|
333
|
+
entityId: projectId,
|
|
334
|
+
entityName: projectName,
|
|
335
|
+
action: 'created',
|
|
336
|
+
details: {
|
|
337
|
+
...projectDestination && {
|
|
338
|
+
destination: projectDestination
|
|
339
|
+
},
|
|
340
|
+
description: wizardResult.createdProject.description,
|
|
341
|
+
createdForTerm: termNameFinal
|
|
342
|
+
}
|
|
343
|
+
});
|
|
344
|
+
// Update routing to use the new project (if destination was specified)
|
|
345
|
+
if (projectDestination) {
|
|
346
|
+
state.routeDecision = {
|
|
347
|
+
projectId,
|
|
348
|
+
destination: {
|
|
349
|
+
path: projectDestination,
|
|
350
|
+
structure: 'month'
|
|
351
|
+
},
|
|
352
|
+
confidence: 1.0,
|
|
353
|
+
signals: [
|
|
354
|
+
{
|
|
355
|
+
type: 'explicit_phrase',
|
|
356
|
+
value: termNameFinal,
|
|
357
|
+
weight: 1.0
|
|
358
|
+
}
|
|
359
|
+
],
|
|
360
|
+
reasoning: `User created project "${projectName}" for term "${termNameFinal}"`
|
|
361
|
+
};
|
|
362
|
+
}
|
|
363
|
+
} catch (error) {
|
|
364
|
+
logger.warn('Failed to save new project from term wizard: %s', error);
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
const newTerm = {
|
|
368
|
+
id: termId,
|
|
369
|
+
name: termNameFinal,
|
|
370
|
+
type: 'term',
|
|
371
|
+
expansion: wizardResult.termExpansion,
|
|
372
|
+
notes: wizardResult.termDescription,
|
|
373
|
+
projects: projectIds.length > 0 ? projectIds : undefined,
|
|
374
|
+
sounds_like: [
|
|
375
|
+
termName.toLowerCase()
|
|
376
|
+
]
|
|
377
|
+
};
|
|
378
|
+
try {
|
|
379
|
+
await ctx.contextInstance.saveEntity(newTerm);
|
|
380
|
+
await ctx.contextInstance.reload(); // Reload so subsequent searches find this entity
|
|
381
|
+
logger.info('Created new term: %s (projects: %s)', termNameFinal, projectIds.length > 0 ? projectIds.join(', ') : 'none');
|
|
382
|
+
contextChanges.push({
|
|
383
|
+
entityType: 'term',
|
|
384
|
+
entityId: termId,
|
|
385
|
+
entityName: termNameFinal,
|
|
386
|
+
action: 'created',
|
|
387
|
+
details: {
|
|
388
|
+
expansion: wizardResult.termExpansion,
|
|
389
|
+
projects: projectIds,
|
|
390
|
+
description: wizardResult.termDescription
|
|
391
|
+
}
|
|
392
|
+
});
|
|
393
|
+
// If term has associated projects and we haven't set routing yet, use the first one
|
|
394
|
+
if (projectIds.length > 0 && !state.routeDecision) {
|
|
395
|
+
// For newly created project, we already set routing above
|
|
396
|
+
// For existing projects, look them up
|
|
397
|
+
if (knownProjects) {
|
|
398
|
+
var _primaryProject_routing;
|
|
399
|
+
const primaryProject = knownProjects.find((p)=>p.id === projectIds[0]);
|
|
400
|
+
if (primaryProject === null || primaryProject === void 0 ? void 0 : (_primaryProject_routing = primaryProject.routing) === null || _primaryProject_routing === void 0 ? void 0 : _primaryProject_routing.destination) {
|
|
401
|
+
state.routeDecision = {
|
|
402
|
+
projectId: primaryProject.id,
|
|
403
|
+
destination: {
|
|
404
|
+
path: primaryProject.routing.destination,
|
|
405
|
+
structure: 'month'
|
|
406
|
+
},
|
|
407
|
+
confidence: 1.0,
|
|
408
|
+
signals: [
|
|
409
|
+
{
|
|
410
|
+
type: 'explicit_phrase',
|
|
411
|
+
value: termNameFinal,
|
|
412
|
+
weight: 1.0
|
|
413
|
+
}
|
|
414
|
+
],
|
|
415
|
+
reasoning: `User created term "${termNameFinal}" associated with project "${primaryProject.name}"`
|
|
416
|
+
};
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
}
|
|
189
420
|
} catch (error) {
|
|
190
|
-
logger.warn('Failed to save new
|
|
421
|
+
logger.warn('Failed to save new term: %s', error);
|
|
422
|
+
}
|
|
423
|
+
} else if (wizardResult.action === 'ignore' && wizardResult.ignoredTerm) {
|
|
424
|
+
// IGNORE - add term to ignore list so user won't be asked again
|
|
425
|
+
const ignoredTermName = wizardResult.ignoredTerm;
|
|
426
|
+
const ignoredId = ignoredTermName.toLowerCase().replace(/[^a-z0-9]/g, '-').replace(/-+/g, '-').replace(/^-|-$/g, '');
|
|
427
|
+
const newIgnored = {
|
|
428
|
+
id: ignoredId,
|
|
429
|
+
name: ignoredTermName,
|
|
430
|
+
type: 'ignored',
|
|
431
|
+
ignoredAt: new Date().toISOString()
|
|
432
|
+
};
|
|
433
|
+
try {
|
|
434
|
+
await ctx.contextInstance.saveEntity(newIgnored);
|
|
435
|
+
await ctx.contextInstance.reload();
|
|
436
|
+
logger.info('Added to ignore list: %s', ignoredTermName);
|
|
437
|
+
contextChanges.push({
|
|
438
|
+
entityType: 'ignored',
|
|
439
|
+
entityId: ignoredId,
|
|
440
|
+
entityName: ignoredTermName,
|
|
441
|
+
action: 'created',
|
|
442
|
+
details: {
|
|
443
|
+
reason: 'User chose to ignore this term'
|
|
444
|
+
}
|
|
445
|
+
});
|
|
446
|
+
} catch (error) {
|
|
447
|
+
logger.warn('Failed to save ignored term: %s', error);
|
|
191
448
|
}
|
|
192
449
|
}
|
|
450
|
+
// 'skip' action - do nothing
|
|
451
|
+
}
|
|
452
|
+
// Handle new person wizard response
|
|
453
|
+
if (((_result_data9 = result.data) === null || _result_data9 === void 0 ? void 0 : _result_data9.clarificationType) === 'new_person' && clarification.additionalInfo) {
|
|
454
|
+
var _result_data11;
|
|
455
|
+
const personWizardResult = clarification.additionalInfo;
|
|
456
|
+
const knownProjects = (_result_data11 = result.data) === null || _result_data11 === void 0 ? void 0 : _result_data11.knownProjects;
|
|
457
|
+
if (personWizardResult.action === 'create') {
|
|
458
|
+
var _personWizardResult_createdProject;
|
|
459
|
+
let linkedProjectId;
|
|
460
|
+
// First, handle any nested project creation
|
|
461
|
+
if (((_personWizardResult_createdProject = personWizardResult.createdProject) === null || _personWizardResult_createdProject === void 0 ? void 0 : _personWizardResult_createdProject.action) === 'create' && personWizardResult.createdProject.projectName) {
|
|
462
|
+
const projectName = personWizardResult.createdProject.projectName;
|
|
463
|
+
const projectId = projectName.toLowerCase().replace(/\s+/g, '-');
|
|
464
|
+
const projectDestination = personWizardResult.createdProject.destination;
|
|
465
|
+
const newProject = {
|
|
466
|
+
id: projectId,
|
|
467
|
+
name: projectName,
|
|
468
|
+
type: 'project',
|
|
469
|
+
description: personWizardResult.createdProject.description || `Project for "${projectName}"`,
|
|
470
|
+
classification: {
|
|
471
|
+
context_type: 'work',
|
|
472
|
+
explicit_phrases: [
|
|
473
|
+
projectName.toLowerCase()
|
|
474
|
+
]
|
|
475
|
+
},
|
|
476
|
+
routing: {
|
|
477
|
+
// Only include destination if explicitly provided - otherwise uses global default
|
|
478
|
+
...projectDestination && {
|
|
479
|
+
destination: projectDestination
|
|
480
|
+
},
|
|
481
|
+
structure: 'month',
|
|
482
|
+
filename_options: [
|
|
483
|
+
'date',
|
|
484
|
+
'time',
|
|
485
|
+
'subject'
|
|
486
|
+
]
|
|
487
|
+
},
|
|
488
|
+
active: true
|
|
489
|
+
};
|
|
490
|
+
try {
|
|
491
|
+
await ctx.contextInstance.saveEntity(newProject);
|
|
492
|
+
await ctx.contextInstance.reload(); // Reload so subsequent searches find this entity
|
|
493
|
+
logger.info('Created new project from person wizard: %s%s', projectName, projectDestination ? ` -> ${projectDestination}` : ' (using default destination)');
|
|
494
|
+
linkedProjectId = projectId;
|
|
495
|
+
contextChanges.push({
|
|
496
|
+
entityType: 'project',
|
|
497
|
+
entityId: projectId,
|
|
498
|
+
entityName: projectName,
|
|
499
|
+
action: 'created',
|
|
500
|
+
details: {
|
|
501
|
+
...projectDestination && {
|
|
502
|
+
destination: projectDestination
|
|
503
|
+
},
|
|
504
|
+
description: personWizardResult.createdProject.description,
|
|
505
|
+
createdForPerson: personWizardResult.personName
|
|
506
|
+
}
|
|
507
|
+
});
|
|
508
|
+
// Update routing to use the new project (if destination was specified)
|
|
509
|
+
if (projectDestination) {
|
|
510
|
+
state.routeDecision = {
|
|
511
|
+
projectId,
|
|
512
|
+
destination: {
|
|
513
|
+
path: projectDestination,
|
|
514
|
+
structure: 'month'
|
|
515
|
+
},
|
|
516
|
+
confidence: 1.0,
|
|
517
|
+
signals: [
|
|
518
|
+
{
|
|
519
|
+
type: 'explicit_phrase',
|
|
520
|
+
value: projectName,
|
|
521
|
+
weight: 1.0
|
|
522
|
+
}
|
|
523
|
+
],
|
|
524
|
+
reasoning: `User created project "${projectName}" for person "${personWizardResult.personName}"`
|
|
525
|
+
};
|
|
526
|
+
}
|
|
527
|
+
} catch (error) {
|
|
528
|
+
logger.warn('Failed to save new project from person wizard: %s', error);
|
|
529
|
+
}
|
|
530
|
+
} else if (typeof personWizardResult.linkedProjectIndex === 'number' && knownProjects) {
|
|
531
|
+
// User linked to existing project
|
|
532
|
+
if (personWizardResult.linkedProjectIndex < knownProjects.length) {
|
|
533
|
+
var _linkedProject_routing4;
|
|
534
|
+
const linkedProject = knownProjects[personWizardResult.linkedProjectIndex];
|
|
535
|
+
linkedProjectId = linkedProject.id;
|
|
536
|
+
// Update routing to use the linked project
|
|
537
|
+
if ((_linkedProject_routing4 = linkedProject.routing) === null || _linkedProject_routing4 === void 0 ? void 0 : _linkedProject_routing4.destination) {
|
|
538
|
+
state.routeDecision = {
|
|
539
|
+
projectId: linkedProject.id,
|
|
540
|
+
destination: {
|
|
541
|
+
path: linkedProject.routing.destination,
|
|
542
|
+
structure: 'month'
|
|
543
|
+
},
|
|
544
|
+
confidence: 1.0,
|
|
545
|
+
signals: [
|
|
546
|
+
{
|
|
547
|
+
type: 'explicit_phrase',
|
|
548
|
+
value: personWizardResult.personName || termName,
|
|
549
|
+
weight: 1.0
|
|
550
|
+
}
|
|
551
|
+
],
|
|
552
|
+
reasoning: `User linked person "${personWizardResult.personName}" to project "${linkedProject.name}"`
|
|
553
|
+
};
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
// Now save the person
|
|
558
|
+
const personName = personWizardResult.personName || termName;
|
|
559
|
+
const personId = personName.toLowerCase().replace(/\s+/g, '-');
|
|
560
|
+
const newPerson = {
|
|
561
|
+
id: personId,
|
|
562
|
+
name: personName,
|
|
563
|
+
type: 'person',
|
|
564
|
+
organization: personWizardResult.organization,
|
|
565
|
+
notes: personWizardResult.notes,
|
|
566
|
+
projects: linkedProjectId ? [
|
|
567
|
+
linkedProjectId
|
|
568
|
+
] : [],
|
|
569
|
+
sounds_like: [
|
|
570
|
+
termName.toLowerCase()
|
|
571
|
+
]
|
|
572
|
+
};
|
|
573
|
+
try {
|
|
574
|
+
await ctx.contextInstance.saveEntity(newPerson);
|
|
575
|
+
await ctx.contextInstance.reload(); // Reload so subsequent searches find this entity
|
|
576
|
+
logger.info('Created new person: %s (org: %s, project: %s)', personName, personWizardResult.organization || 'none', linkedProjectId || 'none');
|
|
577
|
+
// Update resolved entities with correct name
|
|
578
|
+
state.resolvedEntities.set(termName, personName);
|
|
579
|
+
contextChanges.push({
|
|
580
|
+
entityType: 'person',
|
|
581
|
+
entityId: personId,
|
|
582
|
+
entityName: personName,
|
|
583
|
+
action: 'created',
|
|
584
|
+
details: {
|
|
585
|
+
organization: personWizardResult.organization,
|
|
586
|
+
linkedProject: linkedProjectId,
|
|
587
|
+
notes: personWizardResult.notes,
|
|
588
|
+
heardAs: termName
|
|
589
|
+
}
|
|
590
|
+
});
|
|
591
|
+
} catch (error) {
|
|
592
|
+
logger.warn('Failed to save new person: %s', error);
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
// 'skip' action - do nothing
|
|
193
596
|
}
|
|
194
597
|
}
|
|
195
598
|
}
|
|
@@ -197,8 +600,37 @@ Remember: preserve ALL content, only fix transcription errors.`;
|
|
|
197
600
|
if ((_result_data = result.data) === null || _result_data === void 0 ? void 0 : _result_data.person) {
|
|
198
601
|
state.resolvedEntities.set(result.data.person.name, result.data.suggestion);
|
|
199
602
|
}
|
|
200
|
-
|
|
201
|
-
|
|
603
|
+
// Capture routing from route_note tool
|
|
604
|
+
if ((_result_data1 = result.data) === null || _result_data1 === void 0 ? void 0 : (_result_data_routingDecision = _result_data1.routingDecision) === null || _result_data_routingDecision === void 0 ? void 0 : _result_data_routingDecision.destination) {
|
|
605
|
+
const routingDecision = result.data.routingDecision;
|
|
606
|
+
state.routeDecision = {
|
|
607
|
+
projectId: routingDecision.projectId,
|
|
608
|
+
destination: routingDecision.destination,
|
|
609
|
+
confidence: routingDecision.confidence || 1.0,
|
|
610
|
+
signals: routingDecision.signals,
|
|
611
|
+
reasoning: routingDecision.reasoning || 'Determined by route_note tool'
|
|
612
|
+
};
|
|
613
|
+
}
|
|
614
|
+
// Capture routing from lookup_project when project has routing config
|
|
615
|
+
if (((_result_data2 = result.data) === null || _result_data2 === void 0 ? void 0 : _result_data2.found) && ((_result_data3 = result.data) === null || _result_data3 === void 0 ? void 0 : (_result_data_project = _result_data3.project) === null || _result_data_project === void 0 ? void 0 : (_result_data_project_routing = _result_data_project.routing) === null || _result_data_project_routing === void 0 ? void 0 : _result_data_project_routing.destination)) {
|
|
616
|
+
const project = result.data.project;
|
|
617
|
+
state.routeDecision = {
|
|
618
|
+
projectId: project.id,
|
|
619
|
+
destination: {
|
|
620
|
+
path: project.routing.destination,
|
|
621
|
+
structure: project.routing.structure || 'month'
|
|
622
|
+
},
|
|
623
|
+
confidence: 1.0,
|
|
624
|
+
signals: [
|
|
625
|
+
{
|
|
626
|
+
type: 'explicit_phrase',
|
|
627
|
+
value: project.name,
|
|
628
|
+
weight: 1.0
|
|
629
|
+
}
|
|
630
|
+
],
|
|
631
|
+
reasoning: `Matched project "${project.name}" with routing to ${project.routing.destination}`
|
|
632
|
+
};
|
|
633
|
+
logger.debug('Captured routing from project lookup: %s -> %s', project.name, project.routing.destination);
|
|
202
634
|
}
|
|
203
635
|
} catch (error) {
|
|
204
636
|
logger.error('Tool execution failed', {
|