@redaksjon/protokoll 1.0.23 → 1.0.24-dev.20260302172144.c9ea98d
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/LICENSE +1 -1
- package/dist/engineLogging.js +153 -28
- package/dist/engineLogging.js.map +1 -1
- package/dist/mcp/server-hono.js +116 -6
- package/dist/mcp/server-hono.js.map +1 -1
- package/guide/cloud-run.md +4 -1
- package/package.json +4 -4
package/LICENSE
CHANGED
package/dist/engineLogging.js
CHANGED
|
@@ -208,7 +208,7 @@ function isProtokolUri(uri) {
|
|
|
208
208
|
return uri.startsWith(`${SCHEME}://`);
|
|
209
209
|
}
|
|
210
210
|
|
|
211
|
-
const VERSION = "1.0.
|
|
211
|
+
const VERSION = "1.0.24-dev.20260302172144.c9ea98d (working/c9ea98d 2026-03-02 09:20:37 -0800) linux arm64 v24.14.0";
|
|
212
212
|
const PROGRAM_NAME = "protokoll";
|
|
213
213
|
const DATE_FORMAT_YEAR_MONTH_DAY_HOURS_MINUTES_SECONDS = "YYYY-M-D-HHmmss";
|
|
214
214
|
const DEFAULT_AUDIO_EXTENSIONS = ["mp3", "mp4", "mpeg", "mpga", "m4a", "wav", "webm", "qta"];
|
|
@@ -1667,7 +1667,7 @@ function entryVersionKey(entry) {
|
|
|
1667
1667
|
String(Number(entry.sourceSize || 0))
|
|
1668
1668
|
].join("|");
|
|
1669
1669
|
}
|
|
1670
|
-
async function listFilesWithMetadataCompat$
|
|
1670
|
+
async function listFilesWithMetadataCompat$2(outputStorage, prefix, pattern) {
|
|
1671
1671
|
const withMetadata = outputStorage.listFilesWithMetadata;
|
|
1672
1672
|
if (typeof withMetadata === "function") {
|
|
1673
1673
|
return withMetadata.call(outputStorage, prefix, pattern);
|
|
@@ -1809,7 +1809,7 @@ class TranscriptIndexService {
|
|
|
1809
1809
|
}
|
|
1810
1810
|
async refreshIndex() {
|
|
1811
1811
|
const refreshStartedAt = Date.now();
|
|
1812
|
-
const listed = await listFilesWithMetadataCompat$
|
|
1812
|
+
const listed = await listFilesWithMetadataCompat$2(this.outputStorage, "");
|
|
1813
1813
|
const candidates = listed.map((metadata) => ({ ...metadata, path: normalizePath$1(metadata.path) })).filter((metadata) => isTranscriptCandidate(metadata.path));
|
|
1814
1814
|
const byPath = new Map(candidates.map((metadata) => [metadata.path, metadata]));
|
|
1815
1815
|
const dirtyAtStart = new Set(this.dirtyPaths);
|
|
@@ -2101,7 +2101,7 @@ async function resolveTranscriptPathByFilename(outputStorage, outputDirectory, t
|
|
|
2101
2101
|
if (indexedMatches.length > 0) {
|
|
2102
2102
|
return indexedMatches;
|
|
2103
2103
|
}
|
|
2104
|
-
const listed = await listFilesWithMetadataCompat$
|
|
2104
|
+
const listed = await listFilesWithMetadataCompat$2(outputStorage, "", ".pkl");
|
|
2105
2105
|
return listed.map((entry) => normalizePath$1(entry.path)).filter((entryPath) => targetFilenames.has(entryPath.split("/").pop() || ""));
|
|
2106
2106
|
}
|
|
2107
2107
|
|
|
@@ -2465,7 +2465,7 @@ function isYamlPath(pathValue) {
|
|
|
2465
2465
|
const normalized = normalizePath(pathValue).toLowerCase();
|
|
2466
2466
|
return normalized.endsWith(".yaml") || normalized.endsWith(".yml");
|
|
2467
2467
|
}
|
|
2468
|
-
async function listFilesWithMetadataCompat(provider, prefix, pattern) {
|
|
2468
|
+
async function listFilesWithMetadataCompat$1(provider, prefix, pattern) {
|
|
2469
2469
|
if (typeof provider.listFilesWithMetadata === "function") {
|
|
2470
2470
|
return provider.listFilesWithMetadata(prefix, pattern);
|
|
2471
2471
|
}
|
|
@@ -2565,7 +2565,7 @@ class EntityIndexService {
|
|
|
2565
2565
|
this.contextGcs.projectId
|
|
2566
2566
|
);
|
|
2567
2567
|
const directory = ENTITY_DIRECTORY$1[entityType];
|
|
2568
|
-
const listed = await listFilesWithMetadataCompat(provider, `${directory}/`);
|
|
2568
|
+
const listed = await listFilesWithMetadataCompat$1(provider, `${directory}/`);
|
|
2569
2569
|
const yamlEntries = listed.map((metadata) => ({ ...metadata, path: normalizePath(metadata.path) })).filter((metadata) => isYamlPath(metadata.path));
|
|
2570
2570
|
const byPath = new Map(yamlEntries.map((metadata) => [metadata.path, metadata]));
|
|
2571
2571
|
const existing = this.byType.get(entityType) || /* @__PURE__ */ new Map();
|
|
@@ -6069,6 +6069,18 @@ async function resolveStorageTranscriptPath(transcriptPath, outputStorage) {
|
|
|
6069
6069
|
}
|
|
6070
6070
|
return null;
|
|
6071
6071
|
}
|
|
6072
|
+
async function getProjectLookupContext(contextDirectory) {
|
|
6073
|
+
const ServerConfig = await Promise.resolve().then(() => serverConfig$1);
|
|
6074
|
+
const serverContext = ServerConfig.getContext();
|
|
6075
|
+
if (serverContext?.hasContext()) {
|
|
6076
|
+
return serverContext;
|
|
6077
|
+
}
|
|
6078
|
+
const contextDirectories = await getContextDirectories();
|
|
6079
|
+
return create({
|
|
6080
|
+
startingDir: contextDirectory || process.cwd(),
|
|
6081
|
+
contextDirectories
|
|
6082
|
+
});
|
|
6083
|
+
}
|
|
6072
6084
|
async function openToolTranscript(transcriptPath, contextDirectory) {
|
|
6073
6085
|
const ServerConfig = await Promise.resolve().then(() => serverConfig$1);
|
|
6074
6086
|
const outputStorage = ServerConfig.getOutputStorage();
|
|
@@ -7115,6 +7127,7 @@ async function handleEditTranscript(args) {
|
|
|
7115
7127
|
const outputDirectory = await getConfiguredDirectory("outputDirectory", args.contextDirectory);
|
|
7116
7128
|
const ServerConfig = await Promise.resolve().then(() => serverConfig$1);
|
|
7117
7129
|
const outputStorage = ServerConfig.getOutputStorage();
|
|
7130
|
+
const serverContext = ServerConfig.getContext();
|
|
7118
7131
|
if (outputStorage.name === "gcs") {
|
|
7119
7132
|
const access = await openToolTranscript(args.transcriptPath, args.contextDirectory);
|
|
7120
7133
|
const resolvedStoragePath = access.storagePath || access.pklPath;
|
|
@@ -7131,17 +7144,24 @@ async function handleEditTranscript(args) {
|
|
|
7131
7144
|
changes2.push("title updated");
|
|
7132
7145
|
}
|
|
7133
7146
|
if (args.projectId) {
|
|
7134
|
-
const
|
|
7135
|
-
const context = await create({
|
|
7136
|
-
startingDir: args.contextDirectory || process.cwd(),
|
|
7137
|
-
contextDirectories
|
|
7138
|
-
});
|
|
7147
|
+
const context = await getProjectLookupContext(args.contextDirectory);
|
|
7139
7148
|
const project = await context.getProject(args.projectId);
|
|
7140
|
-
|
|
7141
|
-
|
|
7149
|
+
let resolvedId;
|
|
7150
|
+
let resolvedName;
|
|
7151
|
+
if (project) {
|
|
7152
|
+
resolvedId = project.id;
|
|
7153
|
+
resolvedName = project.name;
|
|
7154
|
+
} else {
|
|
7155
|
+
const gcsEntity = await findContextEntityInGcs("project", args.projectId);
|
|
7156
|
+
if (gcsEntity && typeof gcsEntity.id === "string" && typeof gcsEntity.name === "string") {
|
|
7157
|
+
resolvedId = gcsEntity.id;
|
|
7158
|
+
resolvedName = gcsEntity.name;
|
|
7159
|
+
} else {
|
|
7160
|
+
throw new Error(`Project not found: ${args.projectId}`);
|
|
7161
|
+
}
|
|
7142
7162
|
}
|
|
7143
|
-
metadataUpdates.projectId =
|
|
7144
|
-
metadataUpdates.project =
|
|
7163
|
+
metadataUpdates.projectId = resolvedId;
|
|
7164
|
+
metadataUpdates.project = resolvedName;
|
|
7145
7165
|
const existingEntities = transcript.metadata.entities || {
|
|
7146
7166
|
people: [],
|
|
7147
7167
|
projects: [],
|
|
@@ -7151,8 +7171,8 @@ async function handleEditTranscript(args) {
|
|
|
7151
7171
|
metadataUpdates.entities = {
|
|
7152
7172
|
people: existingEntities.people || [],
|
|
7153
7173
|
projects: [{
|
|
7154
|
-
id:
|
|
7155
|
-
name:
|
|
7174
|
+
id: resolvedId,
|
|
7175
|
+
name: resolvedName,
|
|
7156
7176
|
type: "project"
|
|
7157
7177
|
}],
|
|
7158
7178
|
terms: existingEntities.terms || [],
|
|
@@ -7218,7 +7238,10 @@ async function handleEditTranscript(args) {
|
|
|
7218
7238
|
let finalOutputPath = absolutePath;
|
|
7219
7239
|
let wasRenamed = false;
|
|
7220
7240
|
if (args.title || args.projectId || args.tagsToAdd || args.tagsToRemove) {
|
|
7221
|
-
|
|
7241
|
+
let contextDirectories = await getContextDirectories();
|
|
7242
|
+
if ((!contextDirectories || contextDirectories.length === 0) && serverContext?.hasContext()) {
|
|
7243
|
+
contextDirectories = serverContext.getContextDirs();
|
|
7244
|
+
}
|
|
7222
7245
|
const result = await Transcript.editTranscript(absolutePath, {
|
|
7223
7246
|
title: args.title,
|
|
7224
7247
|
projectId: args.projectId,
|
|
@@ -7770,6 +7793,11 @@ async function handleEnhanceTranscript(args) {
|
|
|
7770
7793
|
const project = context.getProject(projectId);
|
|
7771
7794
|
if (project) {
|
|
7772
7795
|
entities.projects.push({ id: project.id, name: project.name, type: "project" });
|
|
7796
|
+
} else {
|
|
7797
|
+
const gcsEntity = await findContextEntityInGcs("project", projectId);
|
|
7798
|
+
if (gcsEntity && typeof gcsEntity.id === "string" && typeof gcsEntity.name === "string") {
|
|
7799
|
+
entities.projects.push({ id: gcsEntity.id, name: gcsEntity.name, type: "project" });
|
|
7800
|
+
}
|
|
7773
7801
|
}
|
|
7774
7802
|
}
|
|
7775
7803
|
for (const termId of referenced.terms) {
|
|
@@ -7786,13 +7814,24 @@ async function handleEnhanceTranscript(args) {
|
|
|
7786
7814
|
}
|
|
7787
7815
|
const hasEntities = entities.people.length > 0 || entities.projects.length > 0 || entities.terms.length > 0 || entities.companies.length > 0;
|
|
7788
7816
|
const decidedProjectId = agenticResult.state.routeDecision?.projectId || routeResult.projectId || void 0;
|
|
7789
|
-
|
|
7817
|
+
let decidedProjectName;
|
|
7818
|
+
if (decidedProjectId) {
|
|
7819
|
+
const decidedProject = context.getProject(decidedProjectId);
|
|
7820
|
+
if (decidedProject) {
|
|
7821
|
+
decidedProjectName = decidedProject.name;
|
|
7822
|
+
} else {
|
|
7823
|
+
const gcsEntity = await findContextEntityInGcs("project", decidedProjectId);
|
|
7824
|
+
if (gcsEntity && typeof gcsEntity.name === "string") {
|
|
7825
|
+
decidedProjectName = gcsEntity.name;
|
|
7826
|
+
}
|
|
7827
|
+
}
|
|
7828
|
+
}
|
|
7790
7829
|
const decidedConfidence = agenticResult.state.routeDecision?.confidence ?? routeResult.confidence;
|
|
7791
7830
|
transcript.updateContent(enhancedText);
|
|
7792
7831
|
transcript.updateMetadata({
|
|
7793
7832
|
status: finalStatus,
|
|
7794
7833
|
projectId: decidedProjectId || transcript.metadata.projectId,
|
|
7795
|
-
project:
|
|
7834
|
+
project: decidedProjectName || transcript.metadata.project,
|
|
7796
7835
|
confidence: typeof decidedConfidence === "number" ? decidedConfidence : transcript.metadata.confidence,
|
|
7797
7836
|
entities: hasEntities ? entities : transcript.metadata.entities
|
|
7798
7837
|
});
|
|
@@ -7817,7 +7856,7 @@ async function handleEnhanceTranscript(args) {
|
|
|
7817
7856
|
transcriptPath: args.transcriptPath,
|
|
7818
7857
|
status: finalStatus,
|
|
7819
7858
|
projectId: decidedProjectId || null,
|
|
7820
|
-
projectName:
|
|
7859
|
+
projectName: decidedProjectName || null,
|
|
7821
7860
|
toolsUsed: agenticResult.toolsUsed,
|
|
7822
7861
|
totalToolCalls: toolCallCount,
|
|
7823
7862
|
iterations: agenticResult.iterations,
|
|
@@ -7876,14 +7915,15 @@ async function handleCreateNote(args) {
|
|
|
7876
7915
|
let projectName;
|
|
7877
7916
|
if (args.projectId) {
|
|
7878
7917
|
try {
|
|
7879
|
-
const
|
|
7880
|
-
const context = await create({
|
|
7881
|
-
startingDir: args.contextDirectory || process.cwd(),
|
|
7882
|
-
contextDirectories
|
|
7883
|
-
});
|
|
7918
|
+
const context = await getProjectLookupContext(args.contextDirectory);
|
|
7884
7919
|
const project = await context.getProject(args.projectId);
|
|
7885
7920
|
if (project) {
|
|
7886
7921
|
projectName = project.name;
|
|
7922
|
+
} else {
|
|
7923
|
+
const gcsEntity = await findContextEntityInGcs("project", args.projectId);
|
|
7924
|
+
if (gcsEntity && typeof gcsEntity.name === "string") {
|
|
7925
|
+
projectName = gcsEntity.name;
|
|
7926
|
+
}
|
|
7887
7927
|
}
|
|
7888
7928
|
} catch {
|
|
7889
7929
|
}
|
|
@@ -9164,6 +9204,82 @@ function getCompletionTime(metadata) {
|
|
|
9164
9204
|
const lastTransition = metadata.history.sort((a, b) => b.at.getTime() - a.at.getTime())[0];
|
|
9165
9205
|
return lastTransition?.at.toISOString() || "";
|
|
9166
9206
|
}
|
|
9207
|
+
function isQueueCandidatePath(pathValue) {
|
|
9208
|
+
const normalized = pathValue.replace(/^\/+/, "").replace(/\\/g, "/");
|
|
9209
|
+
if (!normalized.toLowerCase().endsWith(".pkl")) {
|
|
9210
|
+
return false;
|
|
9211
|
+
}
|
|
9212
|
+
if (normalized.startsWith("uploads/") || normalized.includes("/uploads/")) {
|
|
9213
|
+
return false;
|
|
9214
|
+
}
|
|
9215
|
+
if (normalized.startsWith(".intermediate/") || normalized.includes("/.intermediate/")) {
|
|
9216
|
+
return false;
|
|
9217
|
+
}
|
|
9218
|
+
return true;
|
|
9219
|
+
}
|
|
9220
|
+
function isUploadPlaceholderPath(pathValue) {
|
|
9221
|
+
const normalized = pathValue.replace(/^\/+/, "").replace(/\\/g, "/").toLowerCase();
|
|
9222
|
+
if (!normalized.endsWith("-upload.pkl")) {
|
|
9223
|
+
return false;
|
|
9224
|
+
}
|
|
9225
|
+
return !normalized.includes("/");
|
|
9226
|
+
}
|
|
9227
|
+
async function listFilesWithMetadataCompat(provider, prefix, pattern) {
|
|
9228
|
+
const withMetadata = provider.listFilesWithMetadata;
|
|
9229
|
+
if (typeof withMetadata === "function") {
|
|
9230
|
+
return withMetadata.call(provider, prefix, pattern);
|
|
9231
|
+
}
|
|
9232
|
+
const listed = await provider.listFiles(prefix, pattern);
|
|
9233
|
+
return listed.map((pathValue) => ({
|
|
9234
|
+
path: pathValue,
|
|
9235
|
+
size: 1,
|
|
9236
|
+
updatedAt: null
|
|
9237
|
+
}));
|
|
9238
|
+
}
|
|
9239
|
+
async function materializeTranscriptFromStorage(outputStorage, transcriptPath) {
|
|
9240
|
+
const fileName = transcriptPath.split("/").pop() || "transcript.pkl";
|
|
9241
|
+
const tempPath = join(
|
|
9242
|
+
tmpdir(),
|
|
9243
|
+
`protokoll-queue-pkl-${Date.now()}-${Math.random().toString(36).slice(2)}-${fileName}`
|
|
9244
|
+
);
|
|
9245
|
+
const contents = await outputStorage.readFile(transcriptPath);
|
|
9246
|
+
await fs.writeFile(tempPath, contents);
|
|
9247
|
+
return tempPath;
|
|
9248
|
+
}
|
|
9249
|
+
async function findQueueTranscriptsFromStorage(outputStorage) {
|
|
9250
|
+
const files = await listFilesWithMetadataCompat(outputStorage, "", "-upload.pkl");
|
|
9251
|
+
const candidates = files.map((metadata) => ({ ...metadata, path: metadata.path.replace(/^\/+/, "").replace(/\\/g, "/") })).filter((metadata) => isQueueCandidatePath(metadata.path)).filter((metadata) => isUploadPlaceholderPath(metadata.path));
|
|
9252
|
+
const uploaded = [];
|
|
9253
|
+
const transcribing = [];
|
|
9254
|
+
for (const metadata of candidates) {
|
|
9255
|
+
let tempPath = null;
|
|
9256
|
+
try {
|
|
9257
|
+
tempPath = await materializeTranscriptFromStorage(outputStorage, metadata.path);
|
|
9258
|
+
const transcript = PklTranscript.open(tempPath, { readOnly: true });
|
|
9259
|
+
const transcriptMetadata = transcript.metadata;
|
|
9260
|
+
await transcript.close();
|
|
9261
|
+
if (transcriptMetadata.status === "uploaded") {
|
|
9262
|
+
uploaded.push({ uuid: transcriptMetadata.id, metadata: transcriptMetadata });
|
|
9263
|
+
} else if (transcriptMetadata.status === "transcribing") {
|
|
9264
|
+
transcribing.push({ uuid: transcriptMetadata.id, metadata: transcriptMetadata });
|
|
9265
|
+
}
|
|
9266
|
+
} catch {
|
|
9267
|
+
} finally {
|
|
9268
|
+
if (tempPath) {
|
|
9269
|
+
await fs.rm(tempPath, { force: true });
|
|
9270
|
+
}
|
|
9271
|
+
}
|
|
9272
|
+
}
|
|
9273
|
+
const sortByDateAsc = (a, b) => {
|
|
9274
|
+
const aTime = a.metadata.date?.getTime() || 0;
|
|
9275
|
+
const bTime = b.metadata.date?.getTime() || 0;
|
|
9276
|
+
return aTime - bTime;
|
|
9277
|
+
};
|
|
9278
|
+
return {
|
|
9279
|
+
uploaded: uploaded.sort(sortByDateAsc),
|
|
9280
|
+
transcribing: transcribing.sort(sortByDateAsc)
|
|
9281
|
+
};
|
|
9282
|
+
}
|
|
9167
9283
|
async function findRecentTranscripts(searchDirectories, limit) {
|
|
9168
9284
|
const results = [];
|
|
9169
9285
|
const oneDayAgo = new Date(Date.now() - 24 * 60 * 60 * 1e3);
|
|
@@ -9202,8 +9318,17 @@ async function findRecentTranscripts(searchDirectories, limit) {
|
|
|
9202
9318
|
}
|
|
9203
9319
|
async function handleQueueStatus() {
|
|
9204
9320
|
const outputDir = getOutputDirectory();
|
|
9205
|
-
const
|
|
9206
|
-
|
|
9321
|
+
const outputStorage = getOutputStorage();
|
|
9322
|
+
let uploaded = [];
|
|
9323
|
+
let transcribing = [];
|
|
9324
|
+
if (outputStorage.name === "gcs") {
|
|
9325
|
+
const storageQueue = await findQueueTranscriptsFromStorage(outputStorage);
|
|
9326
|
+
uploaded = storageQueue.uploaded;
|
|
9327
|
+
transcribing = storageQueue.transcribing;
|
|
9328
|
+
} else {
|
|
9329
|
+
uploaded = await findUploadedTranscripts([outputDir]);
|
|
9330
|
+
transcribing = await findTranscribingTranscripts([outputDir]);
|
|
9331
|
+
}
|
|
9207
9332
|
const recent = await findRecentTranscripts([outputDir], 10);
|
|
9208
9333
|
return {
|
|
9209
9334
|
pending: uploaded.map((t) => ({
|