@redaksjon/protokoll 1.0.15 → 1.0.16-dev.20260220034935.1361a65
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/dist/configDiscovery.js +387 -368
- package/dist/configDiscovery.js.map +1 -1
- package/dist/mcp/server-hono.js +94 -6
- package/dist/mcp/server-hono.js.map +1 -1
- package/dist/weightModel.js +4 -1
- package/dist/weightModel.js.map +1 -1
- package/package.json +8 -7
- package/.transcript/weight-model.json +0 -12
package/dist/configDiscovery.js
CHANGED
|
@@ -115,6 +115,8 @@ function parseConfigUri(uri, segments, params) {
|
|
|
115
115
|
}
|
|
116
116
|
function parseTranscriptsListUri(uri, segments, params) {
|
|
117
117
|
const directory = params.directory || "";
|
|
118
|
+
const limitRaw = params.limit ? parseInt(params.limit, 10) : NaN;
|
|
119
|
+
const offsetRaw = params.offset ? parseInt(params.offset, 10) : NaN;
|
|
118
120
|
return {
|
|
119
121
|
scheme: SCHEME,
|
|
120
122
|
resourceType: "transcripts-list",
|
|
@@ -123,8 +125,8 @@ function parseTranscriptsListUri(uri, segments, params) {
|
|
|
123
125
|
directory,
|
|
124
126
|
startDate: params.startDate,
|
|
125
127
|
endDate: params.endDate,
|
|
126
|
-
limit:
|
|
127
|
-
offset:
|
|
128
|
+
limit: Number.isFinite(limitRaw) && limitRaw > 0 ? limitRaw : void 0,
|
|
129
|
+
offset: Number.isFinite(offsetRaw) && offsetRaw >= 0 ? offsetRaw : void 0,
|
|
128
130
|
projectId: params.projectId
|
|
129
131
|
};
|
|
130
132
|
}
|
|
@@ -230,55 +232,7 @@ const uri = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty({
|
|
|
230
232
|
parseUri
|
|
231
233
|
}, Symbol.toStringTag, { value: 'Module' }));
|
|
232
234
|
|
|
233
|
-
const
|
|
234
|
-
// Will be populated dynamically based on context
|
|
235
|
-
];
|
|
236
|
-
const resourceTemplates = [
|
|
237
|
-
{
|
|
238
|
-
uriTemplate: "protokoll://transcript/{path}",
|
|
239
|
-
name: "Transcript",
|
|
240
|
-
description: "A processed transcript file",
|
|
241
|
-
mimeType: "text/markdown"
|
|
242
|
-
},
|
|
243
|
-
{
|
|
244
|
-
uriTemplate: "protokoll://entity/{type}/{id}",
|
|
245
|
-
name: "Context Entity",
|
|
246
|
-
description: "A context entity (person, project, term, company)",
|
|
247
|
-
mimeType: "application/yaml"
|
|
248
|
-
},
|
|
249
|
-
{
|
|
250
|
-
uriTemplate: "protokoll://config",
|
|
251
|
-
name: "Configuration",
|
|
252
|
-
description: "Protokoll configuration for a directory",
|
|
253
|
-
mimeType: "application/json"
|
|
254
|
-
},
|
|
255
|
-
{
|
|
256
|
-
uriTemplate: "protokoll://transcripts?directory={directory}",
|
|
257
|
-
name: "Transcripts List",
|
|
258
|
-
description: "List of transcripts in a directory",
|
|
259
|
-
mimeType: "application/json"
|
|
260
|
-
},
|
|
261
|
-
{
|
|
262
|
-
uriTemplate: "protokoll://entities/{type}",
|
|
263
|
-
name: "Entities List",
|
|
264
|
-
description: "List of entities of a given type",
|
|
265
|
-
mimeType: "application/json"
|
|
266
|
-
},
|
|
267
|
-
{
|
|
268
|
-
uriTemplate: "protokoll://audio/inbound?directory={directory}",
|
|
269
|
-
name: "Inbound Audio Files",
|
|
270
|
-
description: "List of audio files waiting to be processed",
|
|
271
|
-
mimeType: "application/json"
|
|
272
|
-
},
|
|
273
|
-
{
|
|
274
|
-
uriTemplate: "protokoll://audio/processed?directory={directory}",
|
|
275
|
-
name: "Processed Audio Files",
|
|
276
|
-
description: "List of audio files that have been processed",
|
|
277
|
-
mimeType: "application/json"
|
|
278
|
-
}
|
|
279
|
-
];
|
|
280
|
-
|
|
281
|
-
const VERSION = "1.0.15 (HEAD/67244b9 T:v1.0.15 2026-02-17 22:57:54 -0800) linux arm64 v24.13.1";
|
|
235
|
+
const VERSION = "1.0.16-dev.20260220034935.1361a65 (working/1361a65 2026-02-19 19:48:31 -0800) linux arm64 v24.13.1";
|
|
282
236
|
const PROGRAM_NAME = "protokoll";
|
|
283
237
|
const DATE_FORMAT_YEAR_MONTH_DAY_HOURS_MINUTES_SECONDS = "YYYY-M-D-HHmmss";
|
|
284
238
|
const DEFAULT_AUDIO_EXTENSIONS = ["mp3", "mp4", "mpeg", "mpga", "m4a", "wav", "webm", "qta"];
|
|
@@ -332,92 +286,6 @@ const create = async (options = {}) => {
|
|
|
332
286
|
};
|
|
333
287
|
};
|
|
334
288
|
|
|
335
|
-
async function getDynamicResources(contextDirectory) {
|
|
336
|
-
const resources = [];
|
|
337
|
-
try {
|
|
338
|
-
const context = await create({
|
|
339
|
-
startingDir: contextDirectory || process.cwd()
|
|
340
|
-
});
|
|
341
|
-
if (!context.hasContext()) {
|
|
342
|
-
return resources;
|
|
343
|
-
}
|
|
344
|
-
const config = context.getConfig();
|
|
345
|
-
const dirs = context.getDiscoveredDirs();
|
|
346
|
-
const configPath = dirs[0]?.path;
|
|
347
|
-
if (configPath) {
|
|
348
|
-
resources.push({
|
|
349
|
-
uri: buildConfigUri(configPath),
|
|
350
|
-
name: "Current Configuration",
|
|
351
|
-
description: `Protokoll configuration at ${configPath}`,
|
|
352
|
-
mimeType: "application/json"
|
|
353
|
-
});
|
|
354
|
-
}
|
|
355
|
-
const inputDirectory = config.inputDirectory || "./recordings";
|
|
356
|
-
resources.push({
|
|
357
|
-
uri: buildAudioInboundUri(inputDirectory),
|
|
358
|
-
name: "Inbound Audio Files",
|
|
359
|
-
description: `Audio files waiting to be processed in ${inputDirectory}`,
|
|
360
|
-
mimeType: "application/json"
|
|
361
|
-
});
|
|
362
|
-
const processedDirectory = config.processedDirectory;
|
|
363
|
-
if (processedDirectory) {
|
|
364
|
-
resources.push({
|
|
365
|
-
uri: buildAudioProcessedUri(processedDirectory),
|
|
366
|
-
name: "Processed Audio Files",
|
|
367
|
-
description: `Audio files that have been processed in ${processedDirectory}`,
|
|
368
|
-
mimeType: "application/json"
|
|
369
|
-
});
|
|
370
|
-
}
|
|
371
|
-
const entityCounts = {
|
|
372
|
-
projects: context.getAllProjects().length,
|
|
373
|
-
people: context.getAllPeople().length,
|
|
374
|
-
terms: context.getAllTerms().length,
|
|
375
|
-
companies: context.getAllCompanies().length
|
|
376
|
-
};
|
|
377
|
-
if (entityCounts.projects > 0) {
|
|
378
|
-
resources.push({
|
|
379
|
-
uri: buildEntitiesListUri("project"),
|
|
380
|
-
name: "All Projects",
|
|
381
|
-
description: `${entityCounts.projects} project(s) in context`,
|
|
382
|
-
mimeType: "application/json"
|
|
383
|
-
});
|
|
384
|
-
}
|
|
385
|
-
if (entityCounts.people > 0) {
|
|
386
|
-
resources.push({
|
|
387
|
-
uri: buildEntitiesListUri("person"),
|
|
388
|
-
name: "All People",
|
|
389
|
-
description: `${entityCounts.people} person/people in context`,
|
|
390
|
-
mimeType: "application/json"
|
|
391
|
-
});
|
|
392
|
-
}
|
|
393
|
-
if (entityCounts.terms > 0) {
|
|
394
|
-
resources.push({
|
|
395
|
-
uri: buildEntitiesListUri("term"),
|
|
396
|
-
name: "All Terms",
|
|
397
|
-
description: `${entityCounts.terms} term(s) in context`,
|
|
398
|
-
mimeType: "application/json"
|
|
399
|
-
});
|
|
400
|
-
}
|
|
401
|
-
if (entityCounts.companies > 0) {
|
|
402
|
-
resources.push({
|
|
403
|
-
uri: buildEntitiesListUri("company"),
|
|
404
|
-
name: "All Companies",
|
|
405
|
-
description: `${entityCounts.companies} company/companies in context`,
|
|
406
|
-
mimeType: "application/json"
|
|
407
|
-
});
|
|
408
|
-
}
|
|
409
|
-
const outputDirectory = config.outputDirectory || "~/notes";
|
|
410
|
-
resources.push({
|
|
411
|
-
uri: buildTranscriptsListUri({ directory: outputDirectory, limit: 10 }),
|
|
412
|
-
name: "Recent Transcripts",
|
|
413
|
-
description: `10 most recent transcripts in ${outputDirectory}`,
|
|
414
|
-
mimeType: "application/json"
|
|
415
|
-
});
|
|
416
|
-
} catch {
|
|
417
|
-
}
|
|
418
|
-
return resources;
|
|
419
|
-
}
|
|
420
|
-
|
|
421
289
|
let cachedRoots = null;
|
|
422
290
|
function setRoots(roots) {
|
|
423
291
|
cachedRoots = roots;
|
|
@@ -620,6 +488,140 @@ const serverConfig$1 = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProp
|
|
|
620
488
|
reloadServerConfig
|
|
621
489
|
}, Symbol.toStringTag, { value: 'Module' }));
|
|
622
490
|
|
|
491
|
+
const directResources = [
|
|
492
|
+
// Will be populated dynamically based on context
|
|
493
|
+
];
|
|
494
|
+
const resourceTemplates = [
|
|
495
|
+
{
|
|
496
|
+
uriTemplate: "protokoll://transcript/{path}",
|
|
497
|
+
name: "Transcript",
|
|
498
|
+
description: "A processed transcript file",
|
|
499
|
+
mimeType: "text/markdown"
|
|
500
|
+
},
|
|
501
|
+
{
|
|
502
|
+
uriTemplate: "protokoll://entity/{type}/{id}",
|
|
503
|
+
name: "Context Entity",
|
|
504
|
+
description: "A context entity (person, project, term, company)",
|
|
505
|
+
mimeType: "application/yaml"
|
|
506
|
+
},
|
|
507
|
+
{
|
|
508
|
+
uriTemplate: "protokoll://config",
|
|
509
|
+
name: "Configuration",
|
|
510
|
+
description: "Protokoll configuration for a directory",
|
|
511
|
+
mimeType: "application/json"
|
|
512
|
+
},
|
|
513
|
+
{
|
|
514
|
+
uriTemplate: "protokoll://transcripts?directory={directory}&projectId={projectId}&limit={limit}&offset={offset}",
|
|
515
|
+
name: "Transcripts List",
|
|
516
|
+
description: "List of transcripts in a directory. Filter by projectId (UUID) to show only transcripts for that project.",
|
|
517
|
+
mimeType: "application/json"
|
|
518
|
+
},
|
|
519
|
+
{
|
|
520
|
+
uriTemplate: "protokoll://entities/{type}",
|
|
521
|
+
name: "Entities List",
|
|
522
|
+
description: "List of entities of a given type",
|
|
523
|
+
mimeType: "application/json"
|
|
524
|
+
},
|
|
525
|
+
{
|
|
526
|
+
uriTemplate: "protokoll://audio/inbound?directory={directory}",
|
|
527
|
+
name: "Inbound Audio Files",
|
|
528
|
+
description: "List of audio files waiting to be processed",
|
|
529
|
+
mimeType: "application/json"
|
|
530
|
+
},
|
|
531
|
+
{
|
|
532
|
+
uriTemplate: "protokoll://audio/processed?directory={directory}",
|
|
533
|
+
name: "Processed Audio Files",
|
|
534
|
+
description: "List of audio files that have been processed",
|
|
535
|
+
mimeType: "application/json"
|
|
536
|
+
}
|
|
537
|
+
];
|
|
538
|
+
|
|
539
|
+
async function getDynamicResources(contextDirectory) {
|
|
540
|
+
const resources = [];
|
|
541
|
+
try {
|
|
542
|
+
const context = await create({
|
|
543
|
+
startingDir: contextDirectory || process.cwd()
|
|
544
|
+
});
|
|
545
|
+
if (!context.hasContext()) {
|
|
546
|
+
return resources;
|
|
547
|
+
}
|
|
548
|
+
const config = context.getConfig();
|
|
549
|
+
const dirs = context.getDiscoveredDirs();
|
|
550
|
+
const configPath = dirs[0]?.path;
|
|
551
|
+
if (configPath) {
|
|
552
|
+
resources.push({
|
|
553
|
+
uri: buildConfigUri(configPath),
|
|
554
|
+
name: "Current Configuration",
|
|
555
|
+
description: `Protokoll configuration at ${configPath}`,
|
|
556
|
+
mimeType: "application/json"
|
|
557
|
+
});
|
|
558
|
+
}
|
|
559
|
+
const inputDirectory = config.inputDirectory || "./recordings";
|
|
560
|
+
resources.push({
|
|
561
|
+
uri: buildAudioInboundUri(inputDirectory),
|
|
562
|
+
name: "Inbound Audio Files",
|
|
563
|
+
description: `Audio files waiting to be processed in ${inputDirectory}`,
|
|
564
|
+
mimeType: "application/json"
|
|
565
|
+
});
|
|
566
|
+
const processedDirectory = config.processedDirectory;
|
|
567
|
+
if (processedDirectory) {
|
|
568
|
+
resources.push({
|
|
569
|
+
uri: buildAudioProcessedUri(processedDirectory),
|
|
570
|
+
name: "Processed Audio Files",
|
|
571
|
+
description: `Audio files that have been processed in ${processedDirectory}`,
|
|
572
|
+
mimeType: "application/json"
|
|
573
|
+
});
|
|
574
|
+
}
|
|
575
|
+
const entityCounts = {
|
|
576
|
+
projects: context.getAllProjects().length,
|
|
577
|
+
people: context.getAllPeople().length,
|
|
578
|
+
terms: context.getAllTerms().length,
|
|
579
|
+
companies: context.getAllCompanies().length
|
|
580
|
+
};
|
|
581
|
+
if (entityCounts.projects > 0) {
|
|
582
|
+
resources.push({
|
|
583
|
+
uri: buildEntitiesListUri("project"),
|
|
584
|
+
name: "All Projects",
|
|
585
|
+
description: `${entityCounts.projects} project(s) in context`,
|
|
586
|
+
mimeType: "application/json"
|
|
587
|
+
});
|
|
588
|
+
}
|
|
589
|
+
if (entityCounts.people > 0) {
|
|
590
|
+
resources.push({
|
|
591
|
+
uri: buildEntitiesListUri("person"),
|
|
592
|
+
name: "All People",
|
|
593
|
+
description: `${entityCounts.people} person/people in context`,
|
|
594
|
+
mimeType: "application/json"
|
|
595
|
+
});
|
|
596
|
+
}
|
|
597
|
+
if (entityCounts.terms > 0) {
|
|
598
|
+
resources.push({
|
|
599
|
+
uri: buildEntitiesListUri("term"),
|
|
600
|
+
name: "All Terms",
|
|
601
|
+
description: `${entityCounts.terms} term(s) in context`,
|
|
602
|
+
mimeType: "application/json"
|
|
603
|
+
});
|
|
604
|
+
}
|
|
605
|
+
if (entityCounts.companies > 0) {
|
|
606
|
+
resources.push({
|
|
607
|
+
uri: buildEntitiesListUri("company"),
|
|
608
|
+
name: "All Companies",
|
|
609
|
+
description: `${entityCounts.companies} company/companies in context`,
|
|
610
|
+
mimeType: "application/json"
|
|
611
|
+
});
|
|
612
|
+
}
|
|
613
|
+
const outputDirectory = config.outputDirectory || "~/notes";
|
|
614
|
+
resources.push({
|
|
615
|
+
uri: buildTranscriptsListUri({ directory: outputDirectory, limit: 10 }),
|
|
616
|
+
name: "Recent Transcripts",
|
|
617
|
+
description: `10 most recent transcripts in ${outputDirectory}`,
|
|
618
|
+
mimeType: "application/json"
|
|
619
|
+
});
|
|
620
|
+
} catch {
|
|
621
|
+
}
|
|
622
|
+
return resources;
|
|
623
|
+
}
|
|
624
|
+
|
|
623
625
|
const createLogger = (level = "info") => {
|
|
624
626
|
let format = winston.format.combine(
|
|
625
627
|
winston.format.timestamp({ format: DATE_FORMAT_YEAR_MONTH_DAY_HOURS_MINUTES_SECONDS }),
|
|
@@ -699,6 +701,17 @@ async function getContextDirectories() {
|
|
|
699
701
|
const config = ServerConfig.getServerConfig();
|
|
700
702
|
return config.configFile?.contextDirectories;
|
|
701
703
|
}
|
|
704
|
+
async function createToolContext(contextDirectory) {
|
|
705
|
+
const ServerConfig = await Promise.resolve().then(() => serverConfig$1);
|
|
706
|
+
const configFile = ServerConfig.isInitialized() ? ServerConfig.getServerConfig().configFile : null;
|
|
707
|
+
const rawDirs = configFile?.contextDirectories;
|
|
708
|
+
const effectiveDir = contextDirectory || (ServerConfig.isInitialized() ? ServerConfig.getWorkspaceRoot() : null) || process.cwd();
|
|
709
|
+
const contextDirs = rawDirs && rawDirs.length > 0 ? rawDirs.map((d) => isAbsolute(d) ? d : resolve(effectiveDir, d)) : void 0;
|
|
710
|
+
return create({
|
|
711
|
+
startingDir: effectiveDir,
|
|
712
|
+
contextDirectories: contextDirs
|
|
713
|
+
});
|
|
714
|
+
}
|
|
702
715
|
async function validateNotRemoteMode(contextDirectory) {
|
|
703
716
|
if (!contextDirectory) {
|
|
704
717
|
return;
|
|
@@ -861,6 +874,7 @@ async function resolveTranscriptPath$1(uriOrPathOrUuid, contextDirectory) {
|
|
|
861
874
|
|
|
862
875
|
const shared = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty({
|
|
863
876
|
__proto__: null,
|
|
877
|
+
createToolContext,
|
|
864
878
|
fileExists,
|
|
865
879
|
formatEntity,
|
|
866
880
|
getAudioMetadata,
|
|
@@ -950,6 +964,19 @@ async function readTranscriptsListResource(options) {
|
|
|
950
964
|
const { startDate, endDate, limit = 50, offset = 0, projectId } = options;
|
|
951
965
|
const outputDirectory = getOutputDirectory();
|
|
952
966
|
const directory = options.directory || outputDirectory;
|
|
967
|
+
let projectName;
|
|
968
|
+
if (projectId && isInitialized()) {
|
|
969
|
+
const context = getContext();
|
|
970
|
+
if (context) {
|
|
971
|
+
try {
|
|
972
|
+
const project = context.getProject(projectId);
|
|
973
|
+
if (project) {
|
|
974
|
+
projectName = project.name;
|
|
975
|
+
}
|
|
976
|
+
} catch {
|
|
977
|
+
}
|
|
978
|
+
}
|
|
979
|
+
}
|
|
953
980
|
console.log(`📋 Reading transcripts list:`);
|
|
954
981
|
console.log(` Directory: ${directory}${options.directory ? "" : " (from config)"}`);
|
|
955
982
|
if (projectId) {
|
|
@@ -966,7 +993,8 @@ async function readTranscriptsListResource(options) {
|
|
|
966
993
|
sortBy: "date",
|
|
967
994
|
startDate,
|
|
968
995
|
endDate,
|
|
969
|
-
projectId
|
|
996
|
+
projectId,
|
|
997
|
+
project: projectName
|
|
970
998
|
});
|
|
971
999
|
console.log(`✅ Transcripts list response:`);
|
|
972
1000
|
console.log(` Total found: ${result.total}`);
|
|
@@ -999,11 +1027,13 @@ async function readTranscriptsListResource(options) {
|
|
|
999
1027
|
total: result.total,
|
|
1000
1028
|
limit: result.limit,
|
|
1001
1029
|
offset: result.offset,
|
|
1002
|
-
hasMore: result.hasMore
|
|
1030
|
+
hasMore: result.hasMore ?? result.offset + result.limit < result.total,
|
|
1031
|
+
nextOffset: result.hasMore ? result.offset + result.limit : null
|
|
1003
1032
|
},
|
|
1004
1033
|
filters: {
|
|
1005
1034
|
startDate,
|
|
1006
|
-
endDate
|
|
1035
|
+
endDate,
|
|
1036
|
+
projectId
|
|
1007
1037
|
}
|
|
1008
1038
|
};
|
|
1009
1039
|
return {
|
|
@@ -1021,9 +1051,20 @@ async function readTranscriptsListResource(options) {
|
|
|
1021
1051
|
}
|
|
1022
1052
|
|
|
1023
1053
|
async function readEntityResource(entityType, entityId, contextDirectory) {
|
|
1054
|
+
const configFile = isInitialized() ? getServerConfig().configFile : null;
|
|
1055
|
+
const rawDirs = configFile?.contextDirectories;
|
|
1056
|
+
const effectiveDir = contextDirectory || getWorkspaceRoot() || process.cwd();
|
|
1057
|
+
const contextDirs = rawDirs && rawDirs.length > 0 ? rawDirs.map((d) => isAbsolute(d) ? d : resolve(effectiveDir, d)) : void 0;
|
|
1058
|
+
console.log(` [entity] Looking up ${entityType}/${entityId} (fresh context from ${effectiveDir})`);
|
|
1024
1059
|
const context = await create({
|
|
1025
|
-
startingDir:
|
|
1060
|
+
startingDir: effectiveDir,
|
|
1061
|
+
contextDirectories: contextDirs
|
|
1026
1062
|
});
|
|
1063
|
+
if (!context.hasContext()) {
|
|
1064
|
+
const searchDir = contextDirectory || process.cwd();
|
|
1065
|
+
console.log(` [entity] ❌ No Protokoll context found in ${searchDir}`);
|
|
1066
|
+
throw new Error(`No Protokoll context found. Expected .protokoll/ or context dirs in ${searchDir}`);
|
|
1067
|
+
}
|
|
1027
1068
|
let entity;
|
|
1028
1069
|
switch (entityType) {
|
|
1029
1070
|
case "person":
|
|
@@ -1045,8 +1086,11 @@ async function readEntityResource(entityType, entityId, contextDirectory) {
|
|
|
1045
1086
|
throw new Error(`Unknown entity type: ${entityType}`);
|
|
1046
1087
|
}
|
|
1047
1088
|
if (!entity) {
|
|
1089
|
+
const allIds = entityType === "person" ? context.getAllPeople().map((p) => p.id) : entityType === "project" ? context.getAllProjects().map((p) => p.id) : entityType === "term" ? context.getAllTerms().map((t) => t.id) : entityType === "company" ? context.getAllCompanies().map((c) => c.id) : entityType === "ignored" ? context.getAllIgnored().map((i) => i.id) : [];
|
|
1090
|
+
console.log(` [entity] ❌ ${entityType} "${entityId}" not found. Available ${entityType} IDs: ${allIds.join(", ") || "(none)"}`);
|
|
1048
1091
|
throw new Error(`${entityType} "${entityId}" not found`);
|
|
1049
1092
|
}
|
|
1093
|
+
console.log(` [entity] ✅ Found ${entityType}`);
|
|
1050
1094
|
const yamlContent = yaml.dump(entity);
|
|
1051
1095
|
return {
|
|
1052
1096
|
uri: buildEntityUri(entityType, entityId),
|
|
@@ -1055,9 +1099,26 @@ async function readEntityResource(entityType, entityId, contextDirectory) {
|
|
|
1055
1099
|
};
|
|
1056
1100
|
}
|
|
1057
1101
|
async function readEntitiesListResource(entityType, contextDirectory) {
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1102
|
+
let context;
|
|
1103
|
+
if (isInitialized()) {
|
|
1104
|
+
const serverContext = getContext();
|
|
1105
|
+
if (serverContext?.hasContext()) {
|
|
1106
|
+
context = serverContext;
|
|
1107
|
+
} else {
|
|
1108
|
+
const configFile = getServerConfig().configFile;
|
|
1109
|
+
const rawDirs = configFile?.contextDirectories;
|
|
1110
|
+
const effectiveDir = contextDirectory || getWorkspaceRoot() || process.cwd();
|
|
1111
|
+
const contextDirs = rawDirs && rawDirs.length > 0 ? rawDirs.map((d) => isAbsolute(d) ? d : resolve(effectiveDir, d)) : void 0;
|
|
1112
|
+
context = await create({
|
|
1113
|
+
startingDir: effectiveDir,
|
|
1114
|
+
contextDirectories: contextDirs
|
|
1115
|
+
});
|
|
1116
|
+
}
|
|
1117
|
+
} else {
|
|
1118
|
+
context = await create({
|
|
1119
|
+
startingDir: contextDirectory || process.cwd()
|
|
1120
|
+
});
|
|
1121
|
+
}
|
|
1061
1122
|
if (!context.hasContext()) {
|
|
1062
1123
|
throw new Error("No Protokoll context found");
|
|
1063
1124
|
}
|
|
@@ -1276,12 +1337,18 @@ async function handleListResources(contextDirectory) {
|
|
|
1276
1337
|
}
|
|
1277
1338
|
async function handleReadResource(uri) {
|
|
1278
1339
|
const parsed = parseUri(uri);
|
|
1340
|
+
if (parsed.resourceType === "entity") {
|
|
1341
|
+
const entityUri = parsed;
|
|
1342
|
+
console.log(`
|
|
1343
|
+
🔍 [resources/read] Loading entity: type=${entityUri.entityType} id=${entityUri.entityId}`);
|
|
1344
|
+
}
|
|
1279
1345
|
switch (parsed.resourceType) {
|
|
1280
1346
|
case "transcript":
|
|
1281
1347
|
return readTranscriptResource(parsed.transcriptPath);
|
|
1282
1348
|
case "entity": {
|
|
1283
1349
|
const entityUri = parsed;
|
|
1284
|
-
|
|
1350
|
+
const contextDir = isInitialized() ? getWorkspaceRoot() ?? void 0 : void 0;
|
|
1351
|
+
return readEntityResource(entityUri.entityType, entityUri.entityId, contextDir ?? void 0);
|
|
1285
1352
|
}
|
|
1286
1353
|
case "config":
|
|
1287
1354
|
return readConfigResource(parsed.configPath);
|
|
@@ -1296,8 +1363,11 @@ async function handleReadResource(uri) {
|
|
|
1296
1363
|
projectId: listUri.projectId
|
|
1297
1364
|
});
|
|
1298
1365
|
}
|
|
1299
|
-
case "entities-list":
|
|
1300
|
-
|
|
1366
|
+
case "entities-list": {
|
|
1367
|
+
const listUri = parsed;
|
|
1368
|
+
const contextDir = isInitialized() ? getWorkspaceRoot() ?? void 0 : void 0;
|
|
1369
|
+
return readEntitiesListResource(listUri.entityType, contextDir ?? void 0);
|
|
1370
|
+
}
|
|
1301
1371
|
case "audio-inbound":
|
|
1302
1372
|
return readAudioInboundResource(parsed.directory);
|
|
1303
1373
|
case "audio-processed":
|
|
@@ -2128,9 +2198,7 @@ async function getContextInstance(contextDirectory) {
|
|
|
2128
2198
|
if (serverContext) {
|
|
2129
2199
|
return serverContext;
|
|
2130
2200
|
}
|
|
2131
|
-
return
|
|
2132
|
-
startingDir: contextDirectory || process.cwd()
|
|
2133
|
-
});
|
|
2201
|
+
return createToolContext(contextDirectory);
|
|
2134
2202
|
}
|
|
2135
2203
|
const contextStatusTool = {
|
|
2136
2204
|
name: "protokoll_context_status",
|
|
@@ -2954,6 +3022,10 @@ const editTermTool = {
|
|
|
2954
3022
|
type: "string",
|
|
2955
3023
|
description: "Term ID to edit"
|
|
2956
3024
|
},
|
|
3025
|
+
name: {
|
|
3026
|
+
type: "string",
|
|
3027
|
+
description: "Update the display name"
|
|
3028
|
+
},
|
|
2957
3029
|
expansion: {
|
|
2958
3030
|
type: "string",
|
|
2959
3031
|
description: "Set the expansion (full form if acronym)"
|
|
@@ -3171,9 +3243,7 @@ const deleteEntityTool = {
|
|
|
3171
3243
|
}
|
|
3172
3244
|
};
|
|
3173
3245
|
async function handleAddPerson(args) {
|
|
3174
|
-
const context = await
|
|
3175
|
-
startingDir: args.contextDirectory || process.cwd()
|
|
3176
|
-
});
|
|
3246
|
+
const context = await createToolContext(args.contextDirectory);
|
|
3177
3247
|
if (!context.hasContext()) {
|
|
3178
3248
|
throw new Error("No .protokoll directory found. Initialize context first.");
|
|
3179
3249
|
}
|
|
@@ -3202,9 +3272,7 @@ async function handleAddPerson(args) {
|
|
|
3202
3272
|
};
|
|
3203
3273
|
}
|
|
3204
3274
|
async function handleEditPerson(args) {
|
|
3205
|
-
const context = await
|
|
3206
|
-
startingDir: args.contextDirectory || process.cwd()
|
|
3207
|
-
});
|
|
3275
|
+
const context = await createToolContext(args.contextDirectory);
|
|
3208
3276
|
if (!context.hasContext()) {
|
|
3209
3277
|
throw new Error("No .protokoll directory found. Initialize context first.");
|
|
3210
3278
|
}
|
|
@@ -3249,9 +3317,7 @@ async function handleEditPerson(args) {
|
|
|
3249
3317
|
};
|
|
3250
3318
|
}
|
|
3251
3319
|
async function handleAddProject(args) {
|
|
3252
|
-
const context = await
|
|
3253
|
-
startingDir: args.contextDirectory || process.cwd()
|
|
3254
|
-
});
|
|
3320
|
+
const context = await createToolContext(args.contextDirectory);
|
|
3255
3321
|
if (!context.hasContext()) {
|
|
3256
3322
|
throw new Error("No .protokoll directory found. Initialize context first.");
|
|
3257
3323
|
}
|
|
@@ -3305,9 +3371,7 @@ async function handleAddProject(args) {
|
|
|
3305
3371
|
};
|
|
3306
3372
|
}
|
|
3307
3373
|
async function handleEditProject(args) {
|
|
3308
|
-
const context = await
|
|
3309
|
-
startingDir: args.contextDirectory || process.cwd()
|
|
3310
|
-
});
|
|
3374
|
+
const context = await createToolContext(args.contextDirectory);
|
|
3311
3375
|
if (!context.hasContext()) {
|
|
3312
3376
|
throw new Error("No .protokoll directory found. Initialize context first.");
|
|
3313
3377
|
}
|
|
@@ -3479,9 +3543,7 @@ async function handleEditProject(args) {
|
|
|
3479
3543
|
};
|
|
3480
3544
|
}
|
|
3481
3545
|
async function handleUpdateProject(args) {
|
|
3482
|
-
const context = await
|
|
3483
|
-
startingDir: args.contextDirectory || process.cwd()
|
|
3484
|
-
});
|
|
3546
|
+
const context = await createToolContext(args.contextDirectory);
|
|
3485
3547
|
if (!context.hasContext()) {
|
|
3486
3548
|
throw new Error("No .protokoll directory found. Initialize context first.");
|
|
3487
3549
|
}
|
|
@@ -3493,9 +3555,7 @@ async function handleUpdateProject(args) {
|
|
|
3493
3555
|
throw new Error("Smart assistance temporarily unavailable");
|
|
3494
3556
|
}
|
|
3495
3557
|
async function handleAddTerm(args) {
|
|
3496
|
-
const context = await
|
|
3497
|
-
startingDir: args.contextDirectory || process.cwd()
|
|
3498
|
-
});
|
|
3558
|
+
const context = await createToolContext(args.contextDirectory);
|
|
3499
3559
|
if (!context.hasContext()) {
|
|
3500
3560
|
throw new Error("No .protokoll directory found. Initialize context first.");
|
|
3501
3561
|
}
|
|
@@ -3524,9 +3584,7 @@ async function handleAddTerm(args) {
|
|
|
3524
3584
|
};
|
|
3525
3585
|
}
|
|
3526
3586
|
async function handleEditTerm(args) {
|
|
3527
|
-
const context = await
|
|
3528
|
-
startingDir: args.contextDirectory || process.cwd()
|
|
3529
|
-
});
|
|
3587
|
+
const context = await createToolContext(args.contextDirectory);
|
|
3530
3588
|
if (!context.hasContext()) {
|
|
3531
3589
|
throw new Error("No .protokoll directory found. Initialize context first.");
|
|
3532
3590
|
}
|
|
@@ -3554,6 +3612,7 @@ async function handleEditTerm(args) {
|
|
|
3554
3612
|
);
|
|
3555
3613
|
const updatedTerm = {
|
|
3556
3614
|
...existingTerm,
|
|
3615
|
+
...args.name !== void 0 && { name: args.name },
|
|
3557
3616
|
...args.expansion !== void 0 && { expansion: args.expansion },
|
|
3558
3617
|
...args.domain !== void 0 && { domain: args.domain },
|
|
3559
3618
|
...args.description !== void 0 && { description: args.description },
|
|
@@ -3576,6 +3635,7 @@ async function handleEditTerm(args) {
|
|
|
3576
3635
|
}
|
|
3577
3636
|
await context.saveEntity(updatedTerm, true);
|
|
3578
3637
|
const changes = [];
|
|
3638
|
+
if (args.name !== void 0) changes.push(`name: "${args.name}"`);
|
|
3579
3639
|
if (args.expansion !== void 0) changes.push(`expansion: "${args.expansion}"`);
|
|
3580
3640
|
if (args.domain !== void 0) changes.push(`domain: "${args.domain}"`);
|
|
3581
3641
|
if (args.description !== void 0) changes.push(`description updated`);
|
|
@@ -3596,9 +3656,7 @@ async function handleEditTerm(args) {
|
|
|
3596
3656
|
};
|
|
3597
3657
|
}
|
|
3598
3658
|
async function handleUpdateTerm(args) {
|
|
3599
|
-
const context = await
|
|
3600
|
-
startingDir: args.contextDirectory || process.cwd()
|
|
3601
|
-
});
|
|
3659
|
+
const context = await createToolContext(args.contextDirectory);
|
|
3602
3660
|
if (!context.hasContext()) {
|
|
3603
3661
|
throw new Error("No .protokoll directory found. Initialize context first.");
|
|
3604
3662
|
}
|
|
@@ -3610,9 +3668,7 @@ async function handleUpdateTerm(args) {
|
|
|
3610
3668
|
throw new Error("Term assistance temporarily unavailable - business logic needs extraction from CLI");
|
|
3611
3669
|
}
|
|
3612
3670
|
async function handleMergeTerms(args) {
|
|
3613
|
-
const context = await
|
|
3614
|
-
startingDir: args.contextDirectory || process.cwd()
|
|
3615
|
-
});
|
|
3671
|
+
const context = await createToolContext(args.contextDirectory);
|
|
3616
3672
|
if (!context.hasContext()) {
|
|
3617
3673
|
throw new Error("No .protokoll directory found. Initialize context first.");
|
|
3618
3674
|
}
|
|
@@ -3656,9 +3712,7 @@ async function handleMergeTerms(args) {
|
|
|
3656
3712
|
};
|
|
3657
3713
|
}
|
|
3658
3714
|
async function handleAddCompany(args) {
|
|
3659
|
-
const context = await
|
|
3660
|
-
startingDir: args.contextDirectory || process.cwd()
|
|
3661
|
-
});
|
|
3715
|
+
const context = await createToolContext(args.contextDirectory);
|
|
3662
3716
|
if (!context.hasContext()) {
|
|
3663
3717
|
throw new Error("No .protokoll directory found. Initialize context first.");
|
|
3664
3718
|
}
|
|
@@ -3684,9 +3738,7 @@ async function handleAddCompany(args) {
|
|
|
3684
3738
|
};
|
|
3685
3739
|
}
|
|
3686
3740
|
async function handleEditCompany(args) {
|
|
3687
|
-
const context = await
|
|
3688
|
-
startingDir: args.contextDirectory || process.cwd()
|
|
3689
|
-
});
|
|
3741
|
+
const context = await createToolContext(args.contextDirectory);
|
|
3690
3742
|
if (!context.hasContext()) {
|
|
3691
3743
|
throw new Error("No .protokoll directory found. Initialize context first.");
|
|
3692
3744
|
}
|
|
@@ -3725,9 +3777,7 @@ async function handleEditCompany(args) {
|
|
|
3725
3777
|
};
|
|
3726
3778
|
}
|
|
3727
3779
|
async function handleDeleteEntity(args) {
|
|
3728
|
-
const context = await
|
|
3729
|
-
startingDir: args.contextDirectory || process.cwd()
|
|
3730
|
-
});
|
|
3780
|
+
const context = await createToolContext(args.contextDirectory);
|
|
3731
3781
|
let entity;
|
|
3732
3782
|
switch (args.entityType) {
|
|
3733
3783
|
case "project":
|
|
@@ -3758,34 +3808,6 @@ async function handleDeleteEntity(args) {
|
|
|
3758
3808
|
};
|
|
3759
3809
|
}
|
|
3760
3810
|
|
|
3761
|
-
const entityTools = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty({
|
|
3762
|
-
__proto__: null,
|
|
3763
|
-
addCompanyTool,
|
|
3764
|
-
addPersonTool,
|
|
3765
|
-
addProjectTool,
|
|
3766
|
-
addTermTool,
|
|
3767
|
-
deleteEntityTool,
|
|
3768
|
-
editCompanyTool,
|
|
3769
|
-
editPersonTool,
|
|
3770
|
-
editProjectTool,
|
|
3771
|
-
editTermTool,
|
|
3772
|
-
handleAddCompany,
|
|
3773
|
-
handleAddPerson,
|
|
3774
|
-
handleAddProject,
|
|
3775
|
-
handleAddTerm,
|
|
3776
|
-
handleDeleteEntity,
|
|
3777
|
-
handleEditCompany,
|
|
3778
|
-
handleEditPerson,
|
|
3779
|
-
handleEditProject,
|
|
3780
|
-
handleEditTerm,
|
|
3781
|
-
handleMergeTerms,
|
|
3782
|
-
handleUpdateProject,
|
|
3783
|
-
handleUpdateTerm,
|
|
3784
|
-
mergeTermsTool,
|
|
3785
|
-
updateProjectTool,
|
|
3786
|
-
updateTermTool
|
|
3787
|
-
}, Symbol.toStringTag, { value: 'Module' }));
|
|
3788
|
-
|
|
3789
3811
|
const suggestProjectMetadataTool = {
|
|
3790
3812
|
name: "protokoll_suggest_project_metadata",
|
|
3791
3813
|
description: "Generate project metadata suggestions without creating the project. Returns sounds_like (phonetic variants for transcription), explicit_phrases (content-matching trigger phrases), topics and description from source content. Useful for interactive workflows where AI assistant presents suggestions for user review before creating the project.",
|
|
@@ -4203,7 +4225,7 @@ const getEnhancementLogTool = {
|
|
|
4203
4225
|
};
|
|
4204
4226
|
const correctToEntityTool = {
|
|
4205
4227
|
name: "protokoll_correct_to_entity",
|
|
4206
|
-
description: "Correct misheard text in transcript by mapping to existing or new entity. Atomically updates transcript content, adds misspelling to entity sounds_like array, updates entity references, and logs the correction to enhancement_log. This is the primary mechanism for training the transcription system.",
|
|
4228
|
+
description: "Correct misheard text in transcript by mapping to existing or new entity. Atomically updates transcript content, adds misspelling to entity sounds_like array, updates entity references, and logs the correction to enhancement_log. This is the primary mechanism for training the transcription system. Context directory is resolved from server configuration.",
|
|
4207
4229
|
inputSchema: {
|
|
4208
4230
|
type: "object",
|
|
4209
4231
|
properties: {
|
|
@@ -4228,9 +4250,21 @@ const correctToEntityTool = {
|
|
|
4228
4250
|
type: "string",
|
|
4229
4251
|
description: "Name of new entity to create (for create-new flow)"
|
|
4230
4252
|
},
|
|
4231
|
-
|
|
4253
|
+
firstName: {
|
|
4254
|
+
type: "string",
|
|
4255
|
+
description: "First name (person entities only)"
|
|
4256
|
+
},
|
|
4257
|
+
lastName: {
|
|
4258
|
+
type: "string",
|
|
4259
|
+
description: "Last name (person entities only)"
|
|
4260
|
+
},
|
|
4261
|
+
description: {
|
|
4232
4262
|
type: "string",
|
|
4233
|
-
description: "
|
|
4263
|
+
description: "Description/context for the new entity"
|
|
4264
|
+
},
|
|
4265
|
+
projectId: {
|
|
4266
|
+
type: "string",
|
|
4267
|
+
description: "Associated project ID (person entities only)"
|
|
4234
4268
|
}
|
|
4235
4269
|
},
|
|
4236
4270
|
required: ["transcriptPath", "selectedText", "entityType"]
|
|
@@ -4275,9 +4309,9 @@ async function handleListTranscripts(args) {
|
|
|
4275
4309
|
sortBy: args.sortBy ?? "date",
|
|
4276
4310
|
startDate: args.startDate,
|
|
4277
4311
|
endDate: args.endDate,
|
|
4278
|
-
search: args.search
|
|
4279
|
-
|
|
4280
|
-
|
|
4312
|
+
search: args.search,
|
|
4313
|
+
entityId: args.entityId,
|
|
4314
|
+
entityType: args.entityType
|
|
4281
4315
|
});
|
|
4282
4316
|
const outputDirectory = await getConfiguredDirectory("outputDirectory", args.contextDirectory);
|
|
4283
4317
|
const relativeTranscripts = await Promise.all(
|
|
@@ -4745,59 +4779,51 @@ function applyCorrections(transcriptText, corrections) {
|
|
|
4745
4779
|
return correctedText;
|
|
4746
4780
|
}
|
|
4747
4781
|
async function handleCorrectToEntity(args) {
|
|
4748
|
-
const
|
|
4749
|
-
const
|
|
4782
|
+
const { randomUUID } = await import('node:crypto');
|
|
4783
|
+
const { slugify } = await Promise.resolve().then(() => shared);
|
|
4784
|
+
const ServerConfig = await Promise.resolve().then(() => serverConfig$1);
|
|
4785
|
+
const context = ServerConfig.getContext();
|
|
4786
|
+
if (!context) {
|
|
4787
|
+
throw new Error("Server context not initialized. Check server configuration.");
|
|
4788
|
+
}
|
|
4789
|
+
const absolutePath = await resolveTranscriptPath$1(args.transcriptPath);
|
|
4750
4790
|
const pklPath = ensurePklExtension(absolutePath);
|
|
4751
4791
|
let finalEntityId;
|
|
4752
4792
|
let finalEntityName;
|
|
4753
4793
|
let isNewEntity = false;
|
|
4754
4794
|
if (args.entityName) {
|
|
4755
|
-
const
|
|
4756
|
-
const
|
|
4757
|
-
|
|
4758
|
-
|
|
4759
|
-
|
|
4760
|
-
|
|
4761
|
-
|
|
4762
|
-
|
|
4763
|
-
|
|
4764
|
-
|
|
4765
|
-
|
|
4766
|
-
|
|
4767
|
-
|
|
4768
|
-
|
|
4769
|
-
|
|
4770
|
-
|
|
4771
|
-
|
|
4772
|
-
|
|
4773
|
-
|
|
4774
|
-
|
|
4775
|
-
|
|
4776
|
-
|
|
4777
|
-
|
|
4778
|
-
|
|
4779
|
-
|
|
4780
|
-
|
|
4781
|
-
|
|
4782
|
-
switch (args.entityType) {
|
|
4783
|
-
case "person":
|
|
4784
|
-
entity = findPersonResilient(context, finalEntityId);
|
|
4785
|
-
break;
|
|
4786
|
-
case "project":
|
|
4787
|
-
entity = findProjectResilient(context, finalEntityId);
|
|
4788
|
-
break;
|
|
4789
|
-
case "term":
|
|
4790
|
-
entity = findTermResilient(context, finalEntityId);
|
|
4791
|
-
break;
|
|
4792
|
-
case "company":
|
|
4793
|
-
entity = findCompanyResilient(context, finalEntityId);
|
|
4794
|
-
break;
|
|
4795
|
-
}
|
|
4796
|
-
finalEntityName = entity.name;
|
|
4797
|
-
} else {
|
|
4798
|
-
throw error;
|
|
4799
|
-
}
|
|
4795
|
+
const id = randomUUID();
|
|
4796
|
+
const slug = slugify(args.entityName);
|
|
4797
|
+
const entityBase = {
|
|
4798
|
+
id,
|
|
4799
|
+
slug,
|
|
4800
|
+
name: args.entityName
|
|
4801
|
+
};
|
|
4802
|
+
let newEntity;
|
|
4803
|
+
switch (args.entityType) {
|
|
4804
|
+
case "person":
|
|
4805
|
+
newEntity = {
|
|
4806
|
+
...entityBase,
|
|
4807
|
+
type: "person",
|
|
4808
|
+
...args.firstName && { firstName: args.firstName },
|
|
4809
|
+
...args.lastName && { lastName: args.lastName },
|
|
4810
|
+
...args.description && { context: args.description }
|
|
4811
|
+
};
|
|
4812
|
+
break;
|
|
4813
|
+
case "project":
|
|
4814
|
+
newEntity = { ...entityBase, type: "project" };
|
|
4815
|
+
break;
|
|
4816
|
+
case "term":
|
|
4817
|
+
newEntity = { ...entityBase, type: "term" };
|
|
4818
|
+
break;
|
|
4819
|
+
case "company":
|
|
4820
|
+
newEntity = { ...entityBase, type: "company" };
|
|
4821
|
+
break;
|
|
4800
4822
|
}
|
|
4823
|
+
await context.saveEntity(newEntity);
|
|
4824
|
+
finalEntityId = id;
|
|
4825
|
+
finalEntityName = args.entityName;
|
|
4826
|
+
isNewEntity = true;
|
|
4801
4827
|
} else if (args.entityId) {
|
|
4802
4828
|
finalEntityId = args.entityId;
|
|
4803
4829
|
const { findPersonResilient, findProjectResilient, findTermResilient, findCompanyResilient } = await import('@redaksjon/protokoll-engine');
|
|
@@ -4820,84 +4846,86 @@ async function handleCorrectToEntity(args) {
|
|
|
4820
4846
|
} else {
|
|
4821
4847
|
throw new Error("Either entityId or entityName must be provided");
|
|
4822
4848
|
}
|
|
4823
|
-
|
|
4824
|
-
|
|
4825
|
-
|
|
4826
|
-
|
|
4827
|
-
|
|
4828
|
-
|
|
4829
|
-
|
|
4830
|
-
|
|
4831
|
-
|
|
4832
|
-
|
|
4833
|
-
|
|
4834
|
-
switch (args.entityType) {
|
|
4835
|
-
case "person":
|
|
4836
|
-
await EntityTools.handleEditPerson(editArgs);
|
|
4837
|
-
break;
|
|
4838
|
-
case "project":
|
|
4839
|
-
await EntityTools.handleEditProject(editArgs);
|
|
4840
|
-
break;
|
|
4841
|
-
case "term":
|
|
4842
|
-
await EntityTools.handleEditTerm(editArgs);
|
|
4843
|
-
break;
|
|
4844
|
-
case "company":
|
|
4845
|
-
await EntityTools.handleEditCompany(editArgs);
|
|
4846
|
-
break;
|
|
4847
|
-
}
|
|
4848
|
-
const entities = transcript.metadata.entities || { people: [], projects: [], terms: [], companies: [] };
|
|
4849
|
-
const entityRef = { id: finalEntityId, name: finalEntityName, type: args.entityType };
|
|
4850
|
-
let entityArray;
|
|
4851
|
-
switch (args.entityType) {
|
|
4852
|
-
case "person":
|
|
4853
|
-
entityArray = entities.people || [];
|
|
4854
|
-
if (!entityArray.some((e) => e.id === finalEntityId)) {
|
|
4855
|
-
entities.people = [...entityArray, entityRef];
|
|
4856
|
-
}
|
|
4857
|
-
break;
|
|
4858
|
-
case "project":
|
|
4859
|
-
entityArray = entities.projects || [];
|
|
4860
|
-
if (!entityArray.some((e) => e.id === finalEntityId)) {
|
|
4861
|
-
entities.projects = [...entityArray, entityRef];
|
|
4849
|
+
if (args.selectedText.toLowerCase() !== finalEntityName.toLowerCase()) {
|
|
4850
|
+
const existingEntity = (() => {
|
|
4851
|
+
switch (args.entityType) {
|
|
4852
|
+
case "person":
|
|
4853
|
+
return context.getPerson(finalEntityId);
|
|
4854
|
+
case "project":
|
|
4855
|
+
return context.getProject(finalEntityId);
|
|
4856
|
+
case "term":
|
|
4857
|
+
return context.getTerm(finalEntityId);
|
|
4858
|
+
case "company":
|
|
4859
|
+
return context.getCompany(finalEntityId);
|
|
4862
4860
|
}
|
|
4863
|
-
|
|
4864
|
-
|
|
4865
|
-
|
|
4866
|
-
if (!
|
|
4867
|
-
|
|
4861
|
+
})();
|
|
4862
|
+
if (existingEntity) {
|
|
4863
|
+
const soundsLike = existingEntity.sounds_like || [];
|
|
4864
|
+
if (!soundsLike.includes(args.selectedText)) {
|
|
4865
|
+
await context.saveEntity(
|
|
4866
|
+
{ ...existingEntity, sounds_like: [...soundsLike, args.selectedText] },
|
|
4867
|
+
true
|
|
4868
|
+
);
|
|
4868
4869
|
}
|
|
4869
|
-
|
|
4870
|
-
|
|
4871
|
-
|
|
4872
|
-
|
|
4873
|
-
|
|
4870
|
+
}
|
|
4871
|
+
}
|
|
4872
|
+
const transcript = PklTranscript.open(pklPath, { readOnly: false });
|
|
4873
|
+
let transcriptId;
|
|
4874
|
+
let transcriptProject;
|
|
4875
|
+
let allEntityIds;
|
|
4876
|
+
try {
|
|
4877
|
+
const originalContent = transcript.content;
|
|
4878
|
+
const corrections = /* @__PURE__ */ new Map([[args.selectedText, finalEntityName]]);
|
|
4879
|
+
const correctedContent = applyCorrections(originalContent, corrections);
|
|
4880
|
+
transcript.updateContent(correctedContent);
|
|
4881
|
+
const existing = transcript.metadata.entities;
|
|
4882
|
+
const newEntityRef = { id: finalEntityId, name: finalEntityName, type: args.entityType };
|
|
4883
|
+
const addIfMissing = (arr, ref) => {
|
|
4884
|
+
const list = arr ? [...arr] : [];
|
|
4885
|
+
if (!list.some((e) => e.id === ref.id)) {
|
|
4886
|
+
list.push(ref);
|
|
4874
4887
|
}
|
|
4875
|
-
|
|
4888
|
+
return list;
|
|
4889
|
+
};
|
|
4890
|
+
const updatedEntities = {
|
|
4891
|
+
people: args.entityType === "person" ? addIfMissing(existing?.people, newEntityRef) : [...existing?.people || []],
|
|
4892
|
+
projects: args.entityType === "project" ? addIfMissing(existing?.projects, newEntityRef) : [...existing?.projects || []],
|
|
4893
|
+
terms: args.entityType === "term" ? addIfMissing(existing?.terms, newEntityRef) : [...existing?.terms || []],
|
|
4894
|
+
companies: args.entityType === "company" ? addIfMissing(existing?.companies, newEntityRef) : [...existing?.companies || []]
|
|
4895
|
+
};
|
|
4896
|
+
transcript.updateMetadata({ entities: updatedEntities });
|
|
4897
|
+
try {
|
|
4898
|
+
transcript.enhancementLog.logStep(
|
|
4899
|
+
/* @__PURE__ */ new Date(),
|
|
4900
|
+
"user-correction",
|
|
4901
|
+
"correction_applied",
|
|
4902
|
+
{
|
|
4903
|
+
original: args.selectedText,
|
|
4904
|
+
replacement: finalEntityName,
|
|
4905
|
+
entityId: finalEntityId,
|
|
4906
|
+
entityType: args.entityType,
|
|
4907
|
+
isNewEntity
|
|
4908
|
+
},
|
|
4909
|
+
[{ id: finalEntityId, name: finalEntityName, type: args.entityType }]
|
|
4910
|
+
);
|
|
4911
|
+
} catch {
|
|
4912
|
+
}
|
|
4913
|
+
transcriptId = transcript.metadata.id;
|
|
4914
|
+
transcriptProject = transcript.metadata.project;
|
|
4915
|
+
allEntityIds = [
|
|
4916
|
+
...updatedEntities.people.map((e) => e.id),
|
|
4917
|
+
...updatedEntities.projects.map((e) => e.id),
|
|
4918
|
+
...updatedEntities.terms.map((e) => e.id),
|
|
4919
|
+
...updatedEntities.companies.map((e) => e.id)
|
|
4920
|
+
];
|
|
4921
|
+
} finally {
|
|
4922
|
+
transcript.close();
|
|
4923
|
+
}
|
|
4924
|
+
try {
|
|
4925
|
+
const { updateTranscriptInWeightModel } = await import('./weightModel.js');
|
|
4926
|
+
updateTranscriptInWeightModel(transcriptId, allEntityIds, transcriptProject);
|
|
4927
|
+
} catch {
|
|
4876
4928
|
}
|
|
4877
|
-
transcript.updateMetadata({ entities });
|
|
4878
|
-
transcript.enhancementLog.logStep(
|
|
4879
|
-
/* @__PURE__ */ new Date(),
|
|
4880
|
-
"user-correction",
|
|
4881
|
-
// Type will be correct after protokoll-format link
|
|
4882
|
-
"correction_applied",
|
|
4883
|
-
{
|
|
4884
|
-
original: args.selectedText,
|
|
4885
|
-
replacement: finalEntityName,
|
|
4886
|
-
entityId: finalEntityId,
|
|
4887
|
-
entityType: args.entityType,
|
|
4888
|
-
isNewEntity
|
|
4889
|
-
},
|
|
4890
|
-
[{ id: finalEntityId, name: finalEntityName, type: args.entityType }]
|
|
4891
|
-
);
|
|
4892
|
-
transcript.close();
|
|
4893
|
-
const allEntityIds = [
|
|
4894
|
-
...(entities.people || []).map((e) => e.id),
|
|
4895
|
-
...(entities.projects || []).map((e) => e.id),
|
|
4896
|
-
...(entities.terms || []).map((e) => e.id),
|
|
4897
|
-
...(entities.companies || []).map((e) => e.id)
|
|
4898
|
-
];
|
|
4899
|
-
const { updateTranscriptInWeightModel } = await import('./weightModel.js');
|
|
4900
|
-
updateTranscriptInWeightModel(transcript.metadata.id, allEntityIds, transcript.metadata.project);
|
|
4901
4929
|
return {
|
|
4902
4930
|
success: true,
|
|
4903
4931
|
message: `Corrected "${args.selectedText}" to "${finalEntityName}"`,
|
|
@@ -5114,9 +5142,7 @@ const findRelatedEntitiesTool = {
|
|
|
5114
5142
|
};
|
|
5115
5143
|
async function handleAddRelationship(args) {
|
|
5116
5144
|
const { entityType, entityId, targetType, targetId, relationship, notes, metadata, contextDirectory } = args;
|
|
5117
|
-
const contextInstance = await
|
|
5118
|
-
startingDir: contextDirectory || process.cwd()
|
|
5119
|
-
});
|
|
5145
|
+
const contextInstance = await createToolContext(contextDirectory);
|
|
5120
5146
|
const entity = getEntityByType$1(contextInstance, entityType, entityId);
|
|
5121
5147
|
if (!entity) {
|
|
5122
5148
|
throw new Error(`Entity not found: ${entityType}/${entityId}`);
|
|
@@ -5126,11 +5152,18 @@ async function handleAddRelationship(args) {
|
|
|
5126
5152
|
throw new Error(`Target entity not found: ${targetType}/${targetId}`);
|
|
5127
5153
|
}
|
|
5128
5154
|
const newRelationship = createRelationship(targetType, targetId, relationship, notes, metadata);
|
|
5155
|
+
const existingRelationships = entity.relationships || [];
|
|
5156
|
+
const alreadyExists = existingRelationships.some(
|
|
5157
|
+
(r) => r.uri === newRelationship.uri && r.relationship === relationship
|
|
5158
|
+
);
|
|
5159
|
+
if (alreadyExists) {
|
|
5160
|
+
throw new Error(`Relationship already exists: ${relationship} to ${newRelationship.uri}`);
|
|
5161
|
+
}
|
|
5129
5162
|
const updatedEntity = {
|
|
5130
5163
|
...entity,
|
|
5131
|
-
relationships: [...
|
|
5164
|
+
relationships: [...existingRelationships, newRelationship]
|
|
5132
5165
|
};
|
|
5133
|
-
await contextInstance.saveEntity(updatedEntity);
|
|
5166
|
+
await contextInstance.saveEntity(updatedEntity, true);
|
|
5134
5167
|
return {
|
|
5135
5168
|
success: true,
|
|
5136
5169
|
message: `Added ${relationship} relationship from ${entityType}/${entityId} to ${targetType}/${targetId}`,
|
|
@@ -5139,9 +5172,7 @@ async function handleAddRelationship(args) {
|
|
|
5139
5172
|
}
|
|
5140
5173
|
async function handleRemoveRelationship(args) {
|
|
5141
5174
|
const { entityType, entityId, targetUri, relationship, contextDirectory } = args;
|
|
5142
|
-
const contextInstance = await
|
|
5143
|
-
startingDir: contextDirectory || process.cwd()
|
|
5144
|
-
});
|
|
5175
|
+
const contextInstance = await createToolContext(contextDirectory);
|
|
5145
5176
|
const entity = getEntityByType$1(contextInstance, entityType, entityId);
|
|
5146
5177
|
if (!entity) {
|
|
5147
5178
|
throw new Error(`Entity not found: ${entityType}/${entityId}`);
|
|
@@ -5157,7 +5188,7 @@ async function handleRemoveRelationship(args) {
|
|
|
5157
5188
|
...entity,
|
|
5158
5189
|
relationships: filteredRelationships
|
|
5159
5190
|
};
|
|
5160
|
-
await contextInstance.saveEntity(updatedEntity);
|
|
5191
|
+
await contextInstance.saveEntity(updatedEntity, true);
|
|
5161
5192
|
return {
|
|
5162
5193
|
success: true,
|
|
5163
5194
|
message: `Removed ${relationship} relationship to ${targetUri}`
|
|
@@ -5165,9 +5196,7 @@ async function handleRemoveRelationship(args) {
|
|
|
5165
5196
|
}
|
|
5166
5197
|
async function handleListRelationships(args) {
|
|
5167
5198
|
const { entityType, entityId, relationshipType, contextDirectory } = args;
|
|
5168
|
-
const contextInstance = await
|
|
5169
|
-
startingDir: contextDirectory || process.cwd()
|
|
5170
|
-
});
|
|
5199
|
+
const contextInstance = await createToolContext(contextDirectory);
|
|
5171
5200
|
const entity = getEntityByType$1(contextInstance, entityType, entityId);
|
|
5172
5201
|
if (!entity) {
|
|
5173
5202
|
throw new Error(`Entity not found: ${entityType}/${entityId}`);
|
|
@@ -5184,9 +5213,7 @@ async function handleListRelationships(args) {
|
|
|
5184
5213
|
}
|
|
5185
5214
|
async function handleFindRelatedEntities(args) {
|
|
5186
5215
|
const { entityType, entityId, relationshipType, targetType, contextDirectory } = args;
|
|
5187
|
-
const contextInstance = await
|
|
5188
|
-
startingDir: contextDirectory || process.cwd()
|
|
5189
|
-
});
|
|
5216
|
+
const contextInstance = await createToolContext(contextDirectory);
|
|
5190
5217
|
const entity = getEntityByType$1(contextInstance, entityType, entityId);
|
|
5191
5218
|
if (!entity) {
|
|
5192
5219
|
throw new Error(`Entity not found: ${entityType}/${entityId}`);
|
|
@@ -5372,9 +5399,7 @@ const getContentTool = {
|
|
|
5372
5399
|
};
|
|
5373
5400
|
async function handleAddContent(args) {
|
|
5374
5401
|
const { entityType, entityId, type, content, title, mimeType, source, notes, metadata, contextDirectory } = args;
|
|
5375
|
-
const contextInstance = await
|
|
5376
|
-
startingDir: contextDirectory || process.cwd()
|
|
5377
|
-
});
|
|
5402
|
+
const contextInstance = await createToolContext(contextDirectory);
|
|
5378
5403
|
const entity = getEntityByType(contextInstance, entityType, entityId);
|
|
5379
5404
|
if (!entity) {
|
|
5380
5405
|
throw new Error(`Entity not found: ${entityType}/${entityId}`);
|
|
@@ -5430,9 +5455,7 @@ async function handleRemoveContent(args) {
|
|
|
5430
5455
|
if (title === void 0 && index === void 0) {
|
|
5431
5456
|
throw new Error("Either title or index must be provided");
|
|
5432
5457
|
}
|
|
5433
|
-
const contextInstance = await
|
|
5434
|
-
startingDir: contextDirectory || process.cwd()
|
|
5435
|
-
});
|
|
5458
|
+
const contextInstance = await createToolContext(contextDirectory);
|
|
5436
5459
|
const entity = getEntityByType(contextInstance, entityType, entityId);
|
|
5437
5460
|
if (!entity) {
|
|
5438
5461
|
throw new Error(`Entity not found: ${entityType}/${entityId}`);
|
|
@@ -5466,9 +5489,7 @@ async function handleRemoveContent(args) {
|
|
|
5466
5489
|
}
|
|
5467
5490
|
async function handleListContent(args) {
|
|
5468
5491
|
const { entityType, entityId, contentType, contextDirectory } = args;
|
|
5469
|
-
const contextInstance = await
|
|
5470
|
-
startingDir: contextDirectory || process.cwd()
|
|
5471
|
-
});
|
|
5492
|
+
const contextInstance = await createToolContext(contextDirectory);
|
|
5472
5493
|
const entity = getEntityByType(contextInstance, entityType, entityId);
|
|
5473
5494
|
if (!entity) {
|
|
5474
5495
|
throw new Error(`Entity not found: ${entityType}/${entityId}`);
|
|
@@ -5498,9 +5519,7 @@ async function handleGetContent(args) {
|
|
|
5498
5519
|
if (title === void 0 && index === void 0) {
|
|
5499
5520
|
throw new Error("Either title or index must be provided");
|
|
5500
5521
|
}
|
|
5501
|
-
const contextInstance = await
|
|
5502
|
-
startingDir: contextDirectory || process.cwd()
|
|
5503
|
-
});
|
|
5522
|
+
const contextInstance = await createToolContext(contextDirectory);
|
|
5504
5523
|
const entity = getEntityByType(contextInstance, entityType, entityId);
|
|
5505
5524
|
if (!entity) {
|
|
5506
5525
|
throw new Error(`Entity not found: ${entityType}/${entityId}`);
|