brains-mcp 1.71.1 → 1.72.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/httpServer.d.ts.map +1 -1
- package/dist/httpServer.js +36 -2
- package/dist/httpServer.js.map +1 -1
- package/dist/tools/checkoutWiki.d.ts +26 -0
- package/dist/tools/checkoutWiki.d.ts.map +1 -0
- package/dist/tools/checkoutWiki.js +32 -0
- package/dist/tools/checkoutWiki.js.map +1 -0
- package/dist/tools/exportWiki.d.ts.map +1 -1
- package/dist/tools/exportWiki.js +24 -1
- package/dist/tools/exportWiki.js.map +1 -1
- package/dist/tools/importWikiZip.d.ts +26 -0
- package/dist/tools/importWikiZip.d.ts.map +1 -1
- package/dist/tools/importWikiZip.js +48 -21
- package/dist/tools/importWikiZip.js.map +1 -1
- package/dist/tools/pushWiki.d.ts +40 -0
- package/dist/tools/pushWiki.d.ts.map +1 -0
- package/dist/tools/pushWiki.js +109 -0
- package/dist/tools/pushWiki.js.map +1 -0
- package/dist/wiki/index.d.ts +12 -0
- package/dist/wiki/index.d.ts.map +1 -1
- package/dist/wiki/index.js +65 -0
- package/dist/wiki/index.js.map +1 -1
- package/package.json +1 -1
package/dist/httpServer.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"httpServer.d.ts","sourceRoot":"","sources":["../src/httpServer.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AAQxB,OAAO,EAAsD,KAAK,aAAa,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"httpServer.d.ts","sourceRoot":"","sources":["../src/httpServer.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AAQxB,OAAO,EAAsD,KAAK,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAkH7G,wBAAgB,8BAA8B,IAAI,IAAI,CAErD;AAi6BD;;;;;;;;;;;;GAYG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAI9D;AAgsBD,wBAAsB,eAAe,CAAC,KAAK,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CA+oF9F"}
|
package/dist/httpServer.js
CHANGED
|
@@ -24,7 +24,7 @@ import { parsePage } from "./wiki/frontmatter.js";
|
|
|
24
24
|
import { pullSessionBundle } from "./tools/pullSessionBundle.js";
|
|
25
25
|
import { pushSessionBundle } from "./tools/pushSessionBundle.js";
|
|
26
26
|
import { buildExportZip } from "./tools/exportWiki.js";
|
|
27
|
-
import { runImportFromBuffer, isValidWikiFilename, computeDiscoveredFolders, buildInstructionRefreshHint, } from "./tools/importWikiZip.js";
|
|
27
|
+
import { runImportFromBuffer, isValidWikiFilename, computeDiscoveredFolders, buildInstructionRefreshHint, deriveReplaceScope, readRecordedFolder, isInFolderScope, } from "./tools/importWikiZip.js";
|
|
28
28
|
import { purgeWiki } from "./tools/purgeWiki.js";
|
|
29
29
|
import { AsyncJobRegistry } from "./jobs/asyncJobRegistry.js";
|
|
30
30
|
import { exportDownloadStore } from "./jobs/exportDownloadStore.js";
|
|
@@ -498,6 +498,17 @@ async function readBody(req, maxBytes = MAX_BODY_BYTES) {
|
|
|
498
498
|
async function scanImportDiffFromBuffer(drive, buffer, opts) {
|
|
499
499
|
const zip = new AdmZip(buffer);
|
|
500
500
|
const entries = zip.getEntries().filter((e) => !e.isDirectory);
|
|
501
|
+
// GH #695 phase 4 / GH #738: same scope derivation and whole-wiki refusal as
|
|
502
|
+
// the import_wiki tool — this upload route must not be a way to bypass it.
|
|
503
|
+
let folderScope;
|
|
504
|
+
if (opts.mode === "replace") {
|
|
505
|
+
const recordedFolder = readRecordedFolder(entries);
|
|
506
|
+
const scope = deriveReplaceScope(recordedFolder, opts.folder, opts.confirmWholeWiki ?? false);
|
|
507
|
+
if (!scope.ok) {
|
|
508
|
+
throw new ImportScopeRefusedError(scope.error);
|
|
509
|
+
}
|
|
510
|
+
folderScope = scope.folderScope;
|
|
511
|
+
}
|
|
501
512
|
const diff = [];
|
|
502
513
|
let newCount = 0;
|
|
503
514
|
let modifiedCount = 0;
|
|
@@ -563,13 +574,18 @@ async function scanImportDiffFromBuffer(drive, buffer, opts) {
|
|
|
563
574
|
if (!opts.includeSystem && systemFiles.has(name)) {
|
|
564
575
|
continue;
|
|
565
576
|
}
|
|
577
|
+
if (!isInFolderScope(name, folderScope))
|
|
578
|
+
continue;
|
|
566
579
|
if (!zipNames.has(name)) {
|
|
567
580
|
diff.push({ name, status: "deleted" });
|
|
568
581
|
deletedCount++;
|
|
569
582
|
}
|
|
570
583
|
}
|
|
571
584
|
}
|
|
572
|
-
return { totalEntries: entries.length, newCount, modifiedCount, unchangedCount, skippedCount, deletedCount, diff };
|
|
585
|
+
return { totalEntries: entries.length, newCount, modifiedCount, unchangedCount, skippedCount, deletedCount, diff, folderScope };
|
|
586
|
+
}
|
|
587
|
+
/** Thrown by scanImportDiffFromBuffer when an unscoped replace is refused (GH #695 phase 4). */
|
|
588
|
+
class ImportScopeRefusedError extends Error {
|
|
573
589
|
}
|
|
574
590
|
async function readJsonBody(req) {
|
|
575
591
|
const raw = (await readBody(req)).trim();
|
|
@@ -670,7 +686,10 @@ const exportWikiHttpSchema = z.object({
|
|
|
670
686
|
const importWikiZipHttpSchema = z.object({
|
|
671
687
|
zipPath: z.string().min(1),
|
|
672
688
|
execute: z.boolean().optional(),
|
|
689
|
+
mode: z.enum(["additive", "replace"]).optional(),
|
|
673
690
|
conflictStrategy: z.enum(["skip", "overwrite", "merge"]).optional(),
|
|
691
|
+
folder: z.string().optional(),
|
|
692
|
+
confirmWholeWiki: z.boolean().optional(),
|
|
674
693
|
includeSystem: z.boolean().optional(),
|
|
675
694
|
logTiming: z.boolean().optional(),
|
|
676
695
|
});
|
|
@@ -3386,6 +3405,17 @@ export async function startHttpServer(drive, port) {
|
|
|
3386
3405
|
return;
|
|
3387
3406
|
}
|
|
3388
3407
|
const effectiveConflictStrategy = mode === "replace" ? "overwrite" : conflictStrategy;
|
|
3408
|
+
// GH #695 phase 4 / GH #738: `folder` scopes mode=replace deletion the same
|
|
3409
|
+
// way the import_wiki tool does. Explicit query param wins; otherwise the
|
|
3410
|
+
// scan derives it from the uploaded archive's own export-index.json — this
|
|
3411
|
+
// is how a manifest-driven push supplies scope without a hand-typed flag.
|
|
3412
|
+
const folder = parsedUrl.searchParams.get("folder")?.trim() || undefined;
|
|
3413
|
+
const confirmWholeWikiRaw = parsedUrl.searchParams.get("confirmWholeWiki");
|
|
3414
|
+
const confirmWholeWiki = confirmWholeWikiRaw ? confirmWholeWikiRaw.toLowerCase() === "true" : false;
|
|
3415
|
+
if (confirmWholeWikiRaw && confirmWholeWikiRaw.toLowerCase() !== "true" && confirmWholeWikiRaw.toLowerCase() !== "false") {
|
|
3416
|
+
json(req, res, 400, { ok: false, error: "Invalid confirmWholeWiki query param; expected true or false" });
|
|
3417
|
+
return;
|
|
3418
|
+
}
|
|
3389
3419
|
const zipBuffer = await readBodyBuffer(req, MAX_IMPORT_ZIP_UPLOAD_BYTES);
|
|
3390
3420
|
const startedAt = new Date().toISOString();
|
|
3391
3421
|
const startMs = Date.now();
|
|
@@ -3406,6 +3436,8 @@ export async function startHttpServer(drive, port) {
|
|
|
3406
3436
|
conflictStrategy: effectiveConflictStrategy,
|
|
3407
3437
|
includeSystem,
|
|
3408
3438
|
mode: mode,
|
|
3439
|
+
folder,
|
|
3440
|
+
confirmWholeWiki,
|
|
3409
3441
|
onProgress: (processed, total) => {
|
|
3410
3442
|
asyncJobRegistry.update(job.id, { progress: { processed, total, phase: "scanning" } });
|
|
3411
3443
|
},
|
|
@@ -3458,6 +3490,8 @@ export async function startHttpServer(drive, port) {
|
|
|
3458
3490
|
conflictStrategy: effectiveConflictStrategy,
|
|
3459
3491
|
includeSystem,
|
|
3460
3492
|
mode: mode,
|
|
3493
|
+
folder,
|
|
3494
|
+
confirmWholeWiki,
|
|
3461
3495
|
onProgress: (processed, total) => {
|
|
3462
3496
|
asyncJobRegistry.update(job.id, { progress: { processed, total, phase: "scanning" } });
|
|
3463
3497
|
},
|