@safekb/mcp 0.9.0 → 0.9.1
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/safekb-mcp.js +42 -5
- package/package.json +1 -1
package/dist/safekb-mcp.js
CHANGED
|
@@ -2581,7 +2581,7 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
|
|
|
2581
2581
|
// package.json
|
|
2582
2582
|
var package_default = {
|
|
2583
2583
|
name: "@safekb/mcp",
|
|
2584
|
-
version: "0.9.
|
|
2584
|
+
version: "0.9.1",
|
|
2585
2585
|
description: "SafeKB local MCP client: proxies the hosted SafeKB tools and adds zero-knowledge sealed documents.",
|
|
2586
2586
|
license: "SEE LICENSE IN LICENSE",
|
|
2587
2587
|
author: "Mustafa Öztürk",
|
|
@@ -8353,6 +8353,8 @@ function passphraseNote(seal2) {
|
|
|
8353
8353
|
var POSITION_DECIMALS = 6;
|
|
8354
8354
|
var IMPORTED = "imported";
|
|
8355
8355
|
var OBJECT_ID4 = /^[0-9a-f]{24}$/;
|
|
8356
|
+
var ATTACHMENT_IDS_OF_BLOCK = /"attachmentIds":\[([^\]]*)\]/g;
|
|
8357
|
+
var QUOTED_ID = /[0-9a-f]{24}/g;
|
|
8356
8358
|
|
|
8357
8359
|
class SealedImporter {
|
|
8358
8360
|
ctx;
|
|
@@ -8361,6 +8363,7 @@ class SealedImporter {
|
|
|
8361
8363
|
rootOf = new Map;
|
|
8362
8364
|
seqOf = new Map;
|
|
8363
8365
|
spaceOf = new Map;
|
|
8366
|
+
reservedAttachments = new Set;
|
|
8364
8367
|
constructor(ctx, sealed, services) {
|
|
8365
8368
|
this.ctx = ctx;
|
|
8366
8369
|
this.sealed = sealed;
|
|
@@ -8375,6 +8378,7 @@ class SealedImporter {
|
|
|
8375
8378
|
}
|
|
8376
8379
|
async document(record, spaceId) {
|
|
8377
8380
|
const place = await this.placeOf(record, spaceId);
|
|
8381
|
+
this.reserveAttachmentIds(record.body);
|
|
8378
8382
|
if (this.ctx.ids.mentionsUnknown(record.body)) {
|
|
8379
8383
|
this.ctx.report.note("sealed document(s) name something by an id the import did not know yet; that id stays as exported");
|
|
8380
8384
|
}
|
|
@@ -8388,9 +8392,21 @@ class SealedImporter {
|
|
|
8388
8392
|
...place.args
|
|
8389
8393
|
}));
|
|
8390
8394
|
}
|
|
8395
|
+
reserveAttachmentIds(body) {
|
|
8396
|
+
const { ids } = this.ctx;
|
|
8397
|
+
for (const block of body.matchAll(ATTACHMENT_IDS_OF_BLOCK)) {
|
|
8398
|
+
for (const [exported] of (block[1] ?? "").matchAll(QUOTED_ID)) {
|
|
8399
|
+
if (ids.get("attachment", exported) === null) {
|
|
8400
|
+
ids.set("attachment", exported, newObjectId());
|
|
8401
|
+
this.reservedAttachments.add(exported);
|
|
8402
|
+
}
|
|
8403
|
+
}
|
|
8404
|
+
}
|
|
8405
|
+
}
|
|
8391
8406
|
async attachment(entry) {
|
|
8392
8407
|
const { ids, report } = this.ctx;
|
|
8393
8408
|
const { record } = entry;
|
|
8409
|
+
this.reservedAttachments.delete(record.id);
|
|
8394
8410
|
const documentId = ids.get("node", record.owner_id);
|
|
8395
8411
|
if (documentId === null) {
|
|
8396
8412
|
report.note("attachment(s) left out: what they belong to was not imported");
|
|
@@ -8401,6 +8417,7 @@ class SealedImporter {
|
|
|
8401
8417
|
document_id: documentId,
|
|
8402
8418
|
expected_seq: this.seqOf.get(documentId),
|
|
8403
8419
|
size: bytes.length,
|
|
8420
|
+
attachment_id: ids.get("attachment", record.id) ?? undefined,
|
|
8404
8421
|
file: {
|
|
8405
8422
|
filename: record.file_name,
|
|
8406
8423
|
mime: record.mime_type,
|
|
@@ -8411,6 +8428,11 @@ class SealedImporter {
|
|
|
8411
8428
|
ids.set("attachment", record.id, attached.attachment_id);
|
|
8412
8429
|
report.count("attachment");
|
|
8413
8430
|
}
|
|
8431
|
+
reportUnmatchedAttachments() {
|
|
8432
|
+
if (this.reservedAttachments.size === 0)
|
|
8433
|
+
return;
|
|
8434
|
+
this.ctx.report.note(`${this.reservedAttachments.size} attachment(s) named by a sealed body are not in the export; the body points at nothing there`);
|
|
8435
|
+
}
|
|
8414
8436
|
async credential(record, spaceId) {
|
|
8415
8437
|
const { kb, ids, report } = this.ctx;
|
|
8416
8438
|
const rootId = ids.get("seal-root", record.seal_root_id);
|
|
@@ -8837,6 +8859,7 @@ ${WHAT_STAYS}`, this.ctx.report);
|
|
|
8837
8859
|
await this.databases.relations();
|
|
8838
8860
|
for (const rewrite of this.ctx.rewrites)
|
|
8839
8861
|
await rewrite();
|
|
8862
|
+
this.sealed.reportUnmatchedAttachments();
|
|
8840
8863
|
for (const archive of this.ctx.archivals.reverse())
|
|
8841
8864
|
await archive();
|
|
8842
8865
|
}
|
|
@@ -30861,6 +30884,16 @@ var CALLOUT_ALERTS = {
|
|
|
30861
30884
|
error: "CAUTION"
|
|
30862
30885
|
};
|
|
30863
30886
|
var ALERT_CALLOUTS = Object.fromEntries(Object.entries(CALLOUT_ALERTS).map(([callout, alert]) => [alert, callout]));
|
|
30887
|
+
var NAMED_ALERT_PREFIX = "CALLOUT:";
|
|
30888
|
+
var CALLOUT_TYPE_NAME = /^[A-Za-z][\w-]*$/;
|
|
30889
|
+
function alertOfCallout(type) {
|
|
30890
|
+
if (Object.hasOwn(CALLOUT_ALERTS, type))
|
|
30891
|
+
return CALLOUT_ALERTS[type];
|
|
30892
|
+
return CALLOUT_TYPE_NAME.test(type) ? `${NAMED_ALERT_PREFIX}${type}` : null;
|
|
30893
|
+
}
|
|
30894
|
+
function calloutOfAlert(alert) {
|
|
30895
|
+
return alert.startsWith(NAMED_ALERT_PREFIX) ? alert.slice(NAMED_ALERT_PREFIX.length) : ALERT_CALLOUTS[alert];
|
|
30896
|
+
}
|
|
30864
30897
|
var DEFAULT_TOGGLE_SUMMARY = "Details";
|
|
30865
30898
|
var MENTION_SCHEME = "kb-mention://";
|
|
30866
30899
|
var DIRECTIVE_OPEN = "<!--canvas ";
|
|
@@ -31074,10 +31107,14 @@ function imageAsParagraph(node) {
|
|
|
31074
31107
|
]
|
|
31075
31108
|
} : node;
|
|
31076
31109
|
}
|
|
31110
|
+
var BARE_INLINE_TYPES = new Set(["text", "hardBreak", "mention"]);
|
|
31077
31111
|
function canonicalChildren(content, inCell = false) {
|
|
31078
31112
|
if (typeof content === "string") {
|
|
31079
31113
|
return nonEmpty(canonicalNodes([{ type: "paragraph", content }]));
|
|
31080
31114
|
}
|
|
31115
|
+
if (content && content.length > 0 && content.every((child) => BARE_INLINE_TYPES.has(child.type))) {
|
|
31116
|
+
return nonEmpty(canonicalNodes([{ type: "paragraph", content }]));
|
|
31117
|
+
}
|
|
31081
31118
|
const children = (content ?? []).map((child) => canonicalNode(child, inCell));
|
|
31082
31119
|
return nonEmpty(inCell ? children.map(imageAsParagraph) : children);
|
|
31083
31120
|
}
|
|
@@ -31339,7 +31376,7 @@ function inlineNodes(tokens) {
|
|
|
31339
31376
|
}
|
|
31340
31377
|
|
|
31341
31378
|
// ../shared/js/canvas-markdown/src/parse.ts
|
|
31342
|
-
var ALERT_MARKER = /^\[!(NOTE|TIP|WARNING|CAUTION)\]$/;
|
|
31379
|
+
var ALERT_MARKER = /^\[!(NOTE|TIP|WARNING|CAUTION|CALLOUT:[A-Za-z][\w-]*)\]$/;
|
|
31343
31380
|
var TASK_MARKER = /^\[([ xX])\](?:[ \t]+|$)/;
|
|
31344
31381
|
var DETAILS_OPEN = /^<details(?:\s+open)?\s*>\s*(?:<summary>([\s\S]*?)<\/summary>\s*)?$/i;
|
|
31345
31382
|
var DETAILS_CLOSE = /^<\/details>$/i;
|
|
@@ -31503,7 +31540,7 @@ class BlockParser {
|
|
|
31503
31540
|
const children = this.blocks((token) => token.type === "blockquote_close");
|
|
31504
31541
|
this.pos++;
|
|
31505
31542
|
if (alert) {
|
|
31506
|
-
return node("callout", { type:
|
|
31543
|
+
return node("callout", { type: calloutOfAlert(alert) }, children);
|
|
31507
31544
|
}
|
|
31508
31545
|
return node("blockquote", undefined, children);
|
|
31509
31546
|
}
|
|
@@ -31958,7 +31995,7 @@ function checkBlock(node2, path2, out) {
|
|
|
31958
31995
|
return;
|
|
31959
31996
|
}
|
|
31960
31997
|
case "callout":
|
|
31961
|
-
if (
|
|
31998
|
+
if (alertOfCallout(String(node2.attrs?.type ?? "info")) === null) {
|
|
31962
31999
|
out.add(path2, `callout type '${String(node2.attrs?.type)}' has no markdown alert`);
|
|
31963
32000
|
}
|
|
31964
32001
|
break;
|
|
@@ -32140,7 +32177,7 @@ function renderTable(node2, context2) {
|
|
|
32140
32177
|
`);
|
|
32141
32178
|
}
|
|
32142
32179
|
function renderCallout(node2, context2) {
|
|
32143
|
-
const alert =
|
|
32180
|
+
const alert = alertOfCallout(String(node2.attrs?.type ?? "info"));
|
|
32144
32181
|
const children = node2.content ?? [];
|
|
32145
32182
|
const first = children[0];
|
|
32146
32183
|
const marker = `[!${alert}]`;
|
package/package.json
CHANGED