@alaarab/cortex 1.13.3 → 1.13.4
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/mcp/dist/content-learning.js +10 -3
- package/mcp/dist/mcp-finding.js +3 -1
- package/mcp/dist/memory-ui.js +12 -2
- package/mcp/dist/shared.js +0 -5
- package/package.json +1 -1
|
@@ -192,9 +192,12 @@ export function upsertCanonical(cortexPath, project, memory) {
|
|
|
192
192
|
const canonicalPath = path.join(resolvedDir, "CANONICAL_MEMORIES.md");
|
|
193
193
|
const today = new Date().toISOString().slice(0, 10);
|
|
194
194
|
const bullet = memory.startsWith("- ") ? memory : `- ${memory}`;
|
|
195
|
+
let canonicalContent = "";
|
|
195
196
|
withFileLock(canonicalPath, () => {
|
|
196
197
|
if (!fs.existsSync(canonicalPath)) {
|
|
197
|
-
|
|
198
|
+
const initial = `# ${project} Canonical Memories\n\n## Pinned\n\n${bullet} _(pinned ${today})_\n`;
|
|
199
|
+
fs.writeFileSync(canonicalPath, initial);
|
|
200
|
+
canonicalContent = initial;
|
|
198
201
|
}
|
|
199
202
|
else {
|
|
200
203
|
const existing = fs.readFileSync(canonicalPath, "utf8");
|
|
@@ -203,13 +206,17 @@ export function upsertCanonical(cortexPath, project, memory) {
|
|
|
203
206
|
const updated = existing.includes("## Pinned")
|
|
204
207
|
? existing.replace("## Pinned", `## Pinned\n\n${line}`)
|
|
205
208
|
: `${existing.trimEnd()}\n\n## Pinned\n\n${line}\n`;
|
|
209
|
+
const finalContent = updated.endsWith("\n") ? updated : updated + "\n";
|
|
206
210
|
const tmpPath = canonicalPath + ".tmp";
|
|
207
|
-
fs.writeFileSync(tmpPath,
|
|
211
|
+
fs.writeFileSync(tmpPath, finalContent);
|
|
208
212
|
fs.renameSync(tmpPath, canonicalPath);
|
|
213
|
+
canonicalContent = finalContent;
|
|
214
|
+
}
|
|
215
|
+
else {
|
|
216
|
+
canonicalContent = existing;
|
|
209
217
|
}
|
|
210
218
|
}
|
|
211
219
|
});
|
|
212
|
-
const canonicalContent = fs.readFileSync(canonicalPath, "utf8");
|
|
213
220
|
const locks = loadCanonicalLocks(cortexPath);
|
|
214
221
|
const lockKey = `${project}/CANONICAL_MEMORIES.md`;
|
|
215
222
|
locks[lockKey] = {
|
package/mcp/dist/mcp-finding.js
CHANGED
|
@@ -59,7 +59,9 @@ export function register(server, ctx) {
|
|
|
59
59
|
const lineEnd = content.indexOf("\n", idx);
|
|
60
60
|
const insertAt = lineEnd >= 0 ? lineEnd : content.length;
|
|
61
61
|
content = content.slice(0, insertAt) + " " + conflicts.annotations.join(" ") + " <!-- conflicts_checked: true -->" + content.slice(insertAt);
|
|
62
|
-
|
|
62
|
+
const tmpFp = fp + ".tmp";
|
|
63
|
+
fs.writeFileSync(tmpFp, content);
|
|
64
|
+
fs.renameSync(tmpFp, fp);
|
|
63
65
|
}
|
|
64
66
|
}
|
|
65
67
|
}
|
package/mcp/dist/memory-ui.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as http from "http";
|
|
2
2
|
import * as crypto from "crypto";
|
|
3
|
+
import { timingSafeEqual } from "crypto";
|
|
3
4
|
import * as fs from "fs";
|
|
4
5
|
import * as path from "path";
|
|
5
6
|
import * as querystring from "querystring";
|
|
@@ -35,6 +36,15 @@ function getSubmittedAuthToken(req, url, parsedBody) {
|
|
|
35
36
|
return bodyAuth;
|
|
36
37
|
return "";
|
|
37
38
|
}
|
|
39
|
+
function authTokensMatch(submitted, authToken) {
|
|
40
|
+
if (!authToken || !submitted)
|
|
41
|
+
return false;
|
|
42
|
+
const submittedBuffer = Buffer.from(submitted);
|
|
43
|
+
const authTokenBuffer = Buffer.from(authToken);
|
|
44
|
+
if (submittedBuffer.length !== authTokenBuffer.length)
|
|
45
|
+
return false;
|
|
46
|
+
return timingSafeEqual(submittedBuffer, authTokenBuffer);
|
|
47
|
+
}
|
|
38
48
|
function recentUsage(cortexPath) {
|
|
39
49
|
const usage = path.join(cortexPath, ".governance", "memory-usage.log");
|
|
40
50
|
if (!fs.existsSync(usage))
|
|
@@ -324,7 +334,7 @@ export function createReviewUiServer(cortexPath, opts) {
|
|
|
324
334
|
if (req.method === "GET" && url.startsWith("/api/graph")) {
|
|
325
335
|
if (authToken) {
|
|
326
336
|
const submitted = getSubmittedAuthToken(req, url);
|
|
327
|
-
if (submitted
|
|
337
|
+
if (!authTokensMatch(submitted, authToken)) {
|
|
328
338
|
res.writeHead(401, { "content-type": "text/plain; charset=utf-8" });
|
|
329
339
|
res.end("Unauthorized");
|
|
330
340
|
return;
|
|
@@ -356,7 +366,7 @@ export function createReviewUiServer(cortexPath, opts) {
|
|
|
356
366
|
const parsed = querystring.parse(body);
|
|
357
367
|
if (authToken) {
|
|
358
368
|
const submitted = getSubmittedAuthToken(req, url, parsed);
|
|
359
|
-
if (submitted
|
|
369
|
+
if (!authTokensMatch(submitted, authToken)) {
|
|
360
370
|
res.writeHead(401, { "content-type": "text/plain; charset=utf-8" });
|
|
361
371
|
res.end("Unauthorized");
|
|
362
372
|
return;
|
package/mcp/dist/shared.js
CHANGED
|
@@ -32,11 +32,6 @@ export function forwardErr(result) {
|
|
|
32
32
|
return { ok: false, error: result.error, code: result.code };
|
|
33
33
|
return { ok: false, error: "unexpected forward of ok result" };
|
|
34
34
|
}
|
|
35
|
-
// Type guard: returns true when result is a string error (legacy T | string pattern).
|
|
36
|
-
// Useful during migration from T | string to CortexResult<T>.
|
|
37
|
-
export function isCortexError(result) {
|
|
38
|
-
return typeof result === "string";
|
|
39
|
-
}
|
|
40
35
|
const ERROR_CODES = new Set(Object.values(CortexError));
|
|
41
36
|
// Extract the error code from a legacy error string (e.g. "PROJECT_NOT_FOUND: ...").
|
|
42
37
|
// Returns the code if the string starts with a known CortexError, or undefined.
|