ocean-brain 0.4.2 → 0.6.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.
Files changed (102) hide show
  1. package/dist/mcp.js +660 -31
  2. package/package.json +2 -1
  3. package/server/client/dist/assets/{Calendar-DI0PhQTq.js → Calendar-BytW4PeT.js} +1 -1
  4. package/server/client/dist/assets/Callout-9sJgGNRb.js +1 -0
  5. package/server/client/dist/assets/Graph-o5u-NzrA.js +1 -0
  6. package/server/client/dist/assets/{Image-DlJ4MDo3.js → Image-DxWhlIDG.js} +1 -1
  7. package/server/client/dist/assets/{Image.es-COwqkQuh.js → Image.es-B0LL3pb7.js} +1 -1
  8. package/server/client/dist/assets/Note-CYoYzZNu.js +21 -0
  9. package/server/client/dist/assets/{Plus.es-KeV96R_e.js → Plus.es-DpxzgRtY.js} +1 -1
  10. package/server/client/dist/assets/Reminders-DAepTZg1.js +1 -0
  11. package/server/client/dist/assets/Search-6KH7An44.js +1 -0
  12. package/server/client/dist/assets/{SurfaceCard-CHjcCuqZ.js → SurfaceCard-EMs50xSF.js} +1 -1
  13. package/server/client/dist/assets/Tag-C89j8x56.js +1 -0
  14. package/server/client/dist/assets/TagNotes-BTbu-f6v.js +1 -0
  15. package/server/client/dist/assets/{Trash.es-BqRTZPrI.js → Trash.es-C5x35NKF.js} +1 -1
  16. package/server/client/dist/assets/ViewNotes-DPEuki3y.js +1 -0
  17. package/server/client/dist/assets/Views-BGkuNhVd.js +1 -0
  18. package/server/client/dist/assets/{image.api-CMdQbCyN.js → image.api-DRhRQ0Gf.js} +1 -1
  19. package/server/client/dist/assets/{index-D2gRB1ig.css → index-Cd81UxEh.css} +1 -1
  20. package/server/client/dist/assets/index-DYlYUrjH.js +327 -0
  21. package/server/client/dist/assets/index-DswSFFMb.js +1 -0
  22. package/server/client/dist/assets/manage-image-C6sHhWnI.js +1 -0
  23. package/server/client/dist/assets/manage-image-detail-CJkfybR9.js +1 -0
  24. package/server/client/dist/assets/{mcp-DqGLZv90.js → mcp-piouFDNm.js} +1 -1
  25. package/server/client/dist/assets/note-core-Z6kqulGB.js +180 -0
  26. package/server/client/dist/assets/note-vendor-i1M2FSI2.js +54 -0
  27. package/server/client/dist/assets/{placeholder-BXLtvdtN.js → placeholder-DGz3CHej.js} +4 -4
  28. package/server/client/dist/assets/properties-CM4khczg.js +1 -0
  29. package/server/client/dist/assets/trash-C2lItz-b.js +1 -0
  30. package/server/client/dist/assets/{useReminderMutate-v1EXqM90.js → useReminderMutate-DHjDDHKg.js} +1 -1
  31. package/server/client/dist/assets/view-dashboard-C17WsdL7.js +99 -0
  32. package/server/client/dist/index.html +4 -4
  33. package/server/dist/features/note/graphql/note.field.resolver.js +16 -1
  34. package/server/dist/features/note/graphql/note.field.resolver.js.map +1 -1
  35. package/server/dist/features/note/graphql/note.mutation.resolver.js +192 -36
  36. package/server/dist/features/note/graphql/note.mutation.resolver.js.map +1 -1
  37. package/server/dist/features/note/graphql/note.query.resolver.js +88 -76
  38. package/server/dist/features/note/graphql/note.query.resolver.js.map +1 -1
  39. package/server/dist/features/note/graphql/note.resolver.js +3 -2
  40. package/server/dist/features/note/graphql/note.resolver.js.map +1 -1
  41. package/server/dist/features/note/graphql/note.type-defs.js +104 -1
  42. package/server/dist/features/note/graphql/note.type-defs.js.map +1 -1
  43. package/server/dist/features/note/http/mcp.js +394 -1
  44. package/server/dist/features/note/http/mcp.js.map +1 -1
  45. package/server/dist/features/note/services/cleanup.js +4 -3
  46. package/server/dist/features/note/services/cleanup.js.map +1 -1
  47. package/server/dist/features/note/services/content-blocks.js +113 -0
  48. package/server/dist/features/note/services/content-blocks.js.map +1 -0
  49. package/server/dist/features/note/services/markdown-intent-write.js +478 -0
  50. package/server/dist/features/note/services/markdown-intent-write.js.map +1 -0
  51. package/server/dist/features/note/services/markdown-patch.js +601 -0
  52. package/server/dist/features/note/services/markdown-patch.js.map +1 -0
  53. package/server/dist/features/note/services/properties.js +874 -0
  54. package/server/dist/features/note/services/properties.js.map +1 -0
  55. package/server/dist/features/note/services/search.js +10 -29
  56. package/server/dist/features/note/services/search.js.map +1 -1
  57. package/server/dist/features/note/services/snapshot.js +260 -18
  58. package/server/dist/features/note/services/snapshot.js.map +1 -1
  59. package/server/dist/features/note/services/trash.js +70 -2
  60. package/server/dist/features/note/services/trash.js.map +1 -1
  61. package/server/dist/features/note/services/write-conflict.js +87 -0
  62. package/server/dist/features/note/services/write-conflict.js.map +1 -0
  63. package/server/dist/features/note/services/write.js +121 -0
  64. package/server/dist/features/note/services/write.js.map +1 -0
  65. package/server/dist/features/view/graphql/view.query.resolver.js +31 -1
  66. package/server/dist/features/view/graphql/view.query.resolver.js.map +1 -1
  67. package/server/dist/features/view/graphql/view.type-defs.js +57 -1
  68. package/server/dist/features/view/graphql/view.type-defs.js.map +1 -1
  69. package/server/dist/features/view/services/workspace.js +367 -43
  70. package/server/dist/features/view/services/workspace.js.map +1 -1
  71. package/server/dist/modules/blocknote-tree.js +41 -0
  72. package/server/dist/modules/blocknote-tree.js.map +1 -0
  73. package/server/dist/modules/blocknote.js +47 -2
  74. package/server/dist/modules/blocknote.js.map +1 -1
  75. package/server/dist/modules/error-handler.js +7 -4
  76. package/server/dist/modules/error-handler.js.map +1 -1
  77. package/server/dist/modules/recovery-retention.js +2 -2
  78. package/server/dist/modules/recovery-retention.js.map +1 -1
  79. package/server/dist/routes/mcp.js +21 -1
  80. package/server/dist/routes/mcp.js.map +1 -1
  81. package/server/prisma/migrations/20260527073000_0017_note_properties/migration.sql +105 -0
  82. package/server/prisma/migrations/20260531073000_0018_view_query/migration.sql +3 -0
  83. package/server/prisma/schema.prisma +226 -130
  84. package/server/client/dist/assets/Callout-BAqbXI0L.js +0 -1
  85. package/server/client/dist/assets/Graph-Dhuog4tc.js +0 -1
  86. package/server/client/dist/assets/Note-ChUWU3Su.js +0 -21
  87. package/server/client/dist/assets/Reminders-D7MCTNxb.js +0 -1
  88. package/server/client/dist/assets/Search-B-fwTr5y.js +0 -1
  89. package/server/client/dist/assets/Tag-BbV2z-Db.js +0 -1
  90. package/server/client/dist/assets/TagNotes-2HKF09Jm.js +0 -1
  91. package/server/client/dist/assets/ViewNotes-TfM3Uzbp.js +0 -1
  92. package/server/client/dist/assets/Views-CUwtnfa8.js +0 -1
  93. package/server/client/dist/assets/index-B4l2UvuC.js +0 -232
  94. package/server/client/dist/assets/index-zhxZjg7V.js +0 -1
  95. package/server/client/dist/assets/manage-image-DdXb5Bkj.js +0 -1
  96. package/server/client/dist/assets/manage-image-detail-CrrXCQIX.js +0 -1
  97. package/server/client/dist/assets/note-core-GgFcksAF.js +0 -178
  98. package/server/client/dist/assets/note-vendor-B0t5F04o.js +0 -54
  99. package/server/client/dist/assets/trash-3eUAjFRh.js +0 -1
  100. package/server/client/dist/assets/view-dashboard-T6gmohr-.js +0 -90
  101. package/server/dist/features/note/graphql/note.graphql.shared.js +0 -23
  102. package/server/dist/features/note/graphql/note.graphql.shared.js.map +0 -1
@@ -0,0 +1,113 @@
1
+ import { parseBlockNoteContent, walkBlockNoteTree } from "../../../modules/blocknote-tree.js";
2
+ const parseNoteContent = (content) => {
3
+ return parseBlockNoteContent(content);
4
+ };
5
+ const normalizeReferenceId = (id) => {
6
+ if (typeof id === "number") {
7
+ return Number.isFinite(id) ? String(id) : null;
8
+ }
9
+ if (typeof id !== "string") {
10
+ return null;
11
+ }
12
+ const normalizedId = id.trim();
13
+ return normalizedId.length > 0 ? normalizedId : null;
14
+ };
15
+ const extractBlocksByType = (type, dataArray) => {
16
+ const result = [];
17
+ walkBlockNoteTree(dataArray, (node) => {
18
+ if (node.type === type) {
19
+ result.push(node);
20
+ }
21
+ });
22
+ return result;
23
+ };
24
+ const extractReferenceBlocks = (dataArray) => {
25
+ return extractBlocksByType("reference", dataArray).filter((block) => {
26
+ return normalizeReferenceId(block.props?.id) !== null;
27
+ });
28
+ };
29
+ const extractReferenceBlocksFromContent = (content) => {
30
+ const parsed = parseNoteContent(content);
31
+ return parsed ? extractReferenceBlocks(parsed) : [];
32
+ };
33
+ const contentReferencesNote = (content, noteId) => {
34
+ const targetId = normalizeReferenceId(noteId);
35
+ if (!targetId) {
36
+ return false;
37
+ }
38
+ return extractReferenceBlocksFromContent(content).some(
39
+ (block) => normalizeReferenceId(block.props?.id) === targetId
40
+ );
41
+ };
42
+ const syncReferenceTitlesInContent = (content, titlesById) => {
43
+ const parsed = parseNoteContent(content);
44
+ if (!parsed) {
45
+ return null;
46
+ }
47
+ let changed = false;
48
+ for (const block of extractReferenceBlocks(parsed)) {
49
+ const props = block.props;
50
+ const id = normalizeReferenceId(props?.id);
51
+ if (!props || id === null) {
52
+ continue;
53
+ }
54
+ const title = titlesById.get(id);
55
+ if (title !== void 0 && props.title !== title) {
56
+ block.props = {
57
+ ...props,
58
+ title
59
+ };
60
+ changed = true;
61
+ }
62
+ }
63
+ return changed ? JSON.stringify(parsed) : content;
64
+ };
65
+ const buildNoteGraph = (notes) => {
66
+ const existingNoteIds = new Set(notes.map((note) => String(note.id)));
67
+ const links = [];
68
+ const connectionCount = {};
69
+ const linkSet = /* @__PURE__ */ new Set();
70
+ for (const note of notes) {
71
+ const sourceId = String(note.id);
72
+ for (const block of extractReferenceBlocksFromContent(note.content)) {
73
+ const targetId = normalizeReferenceId(block.props?.id);
74
+ if (!targetId || sourceId === targetId || !existingNoteIds.has(targetId)) {
75
+ continue;
76
+ }
77
+ const linkKey = `${sourceId}-${targetId}`;
78
+ const reverseLinkKey = `${targetId}-${sourceId}`;
79
+ if (linkSet.has(linkKey) || linkSet.has(reverseLinkKey)) {
80
+ continue;
81
+ }
82
+ linkSet.add(linkKey);
83
+ links.push({
84
+ source: sourceId,
85
+ target: targetId
86
+ });
87
+ connectionCount[sourceId] = (connectionCount[sourceId] || 0) + 1;
88
+ connectionCount[targetId] = (connectionCount[targetId] || 0) + 1;
89
+ }
90
+ }
91
+ return {
92
+ nodes: notes.map((note) => {
93
+ const id = String(note.id);
94
+ return {
95
+ id,
96
+ title: note.title || "Untitled",
97
+ connections: connectionCount[id] || 0
98
+ };
99
+ }),
100
+ links
101
+ };
102
+ };
103
+ export {
104
+ buildNoteGraph,
105
+ contentReferencesNote,
106
+ extractBlocksByType,
107
+ extractReferenceBlocks,
108
+ extractReferenceBlocksFromContent,
109
+ normalizeReferenceId,
110
+ parseNoteContent,
111
+ syncReferenceTitlesInContent
112
+ };
113
+ //# sourceMappingURL=content-blocks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/features/note/services/content-blocks.ts"],"sourcesContent":["import { parseBlockNoteContent, walkBlockNoteTree } from '~/modules/blocknote-tree.js';\n\ninterface BlockNote<T = unknown> {\n id?: string;\n type?: string;\n props?: T;\n content?: unknown;\n children?: unknown;\n}\n\ninterface ReferenceProps {\n id?: string | number;\n title?: string;\n}\n\ninterface NoteGraphInput {\n id: string | number;\n title: string;\n content: string;\n}\n\nexport interface NoteGraphResult {\n nodes: Array<{ id: string; title: string; connections: number }>;\n links: Array<{ source: string; target: string }>;\n}\n\nexport const parseNoteContent = (content: string): unknown[] | null => {\n return parseBlockNoteContent(content);\n};\n\nexport const normalizeReferenceId = (id: unknown) => {\n if (typeof id === 'number') {\n return Number.isFinite(id) ? String(id) : null;\n }\n\n if (typeof id !== 'string') {\n return null;\n }\n\n const normalizedId = id.trim();\n\n return normalizedId.length > 0 ? normalizedId : null;\n};\n\nexport const extractBlocksByType = <T>(type: string, dataArray: unknown): BlockNote<T>[] => {\n const result: BlockNote<T>[] = [];\n\n walkBlockNoteTree(dataArray, (node) => {\n if (node.type === type) {\n result.push(node as BlockNote<T>);\n }\n });\n\n return result;\n};\n\nexport const extractReferenceBlocks = (dataArray: unknown) => {\n return extractBlocksByType<ReferenceProps>('reference', dataArray).filter((block) => {\n return normalizeReferenceId(block.props?.id) !== null;\n });\n};\n\nexport const extractReferenceBlocksFromContent = (content: string) => {\n const parsed = parseNoteContent(content);\n return parsed ? extractReferenceBlocks(parsed) : [];\n};\n\nexport const contentReferencesNote = (content: string, noteId: string | number) => {\n const targetId = normalizeReferenceId(noteId);\n\n if (!targetId) {\n return false;\n }\n\n return extractReferenceBlocksFromContent(content).some(\n (block) => normalizeReferenceId(block.props?.id) === targetId,\n );\n};\n\nexport const syncReferenceTitlesInContent = (content: string, titlesById: Map<string, string>) => {\n const parsed = parseNoteContent(content);\n\n if (!parsed) {\n return null;\n }\n\n let changed = false;\n\n for (const block of extractReferenceBlocks(parsed)) {\n const props = block.props;\n const id = normalizeReferenceId(props?.id);\n\n if (!props || id === null) {\n continue;\n }\n\n const title = titlesById.get(id);\n\n if (title !== undefined && props.title !== title) {\n block.props = {\n ...props,\n title,\n };\n changed = true;\n }\n }\n\n return changed ? JSON.stringify(parsed) : content;\n};\n\nexport const buildNoteGraph = (notes: NoteGraphInput[]): NoteGraphResult => {\n const existingNoteIds = new Set(notes.map((note) => String(note.id)));\n const links: NoteGraphResult['links'] = [];\n const connectionCount: Record<string, number> = {};\n const linkSet = new Set<string>();\n\n for (const note of notes) {\n const sourceId = String(note.id);\n\n for (const block of extractReferenceBlocksFromContent(note.content)) {\n const targetId = normalizeReferenceId(block.props?.id);\n\n if (!targetId || sourceId === targetId || !existingNoteIds.has(targetId)) {\n continue;\n }\n\n const linkKey = `${sourceId}-${targetId}`;\n const reverseLinkKey = `${targetId}-${sourceId}`;\n\n if (linkSet.has(linkKey) || linkSet.has(reverseLinkKey)) {\n continue;\n }\n\n linkSet.add(linkKey);\n links.push({\n source: sourceId,\n target: targetId,\n });\n connectionCount[sourceId] = (connectionCount[sourceId] || 0) + 1;\n connectionCount[targetId] = (connectionCount[targetId] || 0) + 1;\n }\n }\n\n return {\n nodes: notes.map((note) => {\n const id = String(note.id);\n\n return {\n id,\n title: note.title || 'Untitled',\n connections: connectionCount[id] || 0,\n };\n }),\n links,\n };\n};\n"],"mappings":"AAAA,SAAS,uBAAuB,yBAAyB;AA0BlD,MAAM,mBAAmB,CAAC,YAAsC;AACnE,SAAO,sBAAsB,OAAO;AACxC;AAEO,MAAM,uBAAuB,CAAC,OAAgB;AACjD,MAAI,OAAO,OAAO,UAAU;AACxB,WAAO,OAAO,SAAS,EAAE,IAAI,OAAO,EAAE,IAAI;AAAA,EAC9C;AAEA,MAAI,OAAO,OAAO,UAAU;AACxB,WAAO;AAAA,EACX;AAEA,QAAM,eAAe,GAAG,KAAK;AAE7B,SAAO,aAAa,SAAS,IAAI,eAAe;AACpD;AAEO,MAAM,sBAAsB,CAAI,MAAc,cAAuC;AACxF,QAAM,SAAyB,CAAC;AAEhC,oBAAkB,WAAW,CAAC,SAAS;AACnC,QAAI,KAAK,SAAS,MAAM;AACpB,aAAO,KAAK,IAAoB;AAAA,IACpC;AAAA,EACJ,CAAC;AAED,SAAO;AACX;AAEO,MAAM,yBAAyB,CAAC,cAAuB;AAC1D,SAAO,oBAAoC,aAAa,SAAS,EAAE,OAAO,CAAC,UAAU;AACjF,WAAO,qBAAqB,MAAM,OAAO,EAAE,MAAM;AAAA,EACrD,CAAC;AACL;AAEO,MAAM,oCAAoC,CAAC,YAAoB;AAClE,QAAM,SAAS,iBAAiB,OAAO;AACvC,SAAO,SAAS,uBAAuB,MAAM,IAAI,CAAC;AACtD;AAEO,MAAM,wBAAwB,CAAC,SAAiB,WAA4B;AAC/E,QAAM,WAAW,qBAAqB,MAAM;AAE5C,MAAI,CAAC,UAAU;AACX,WAAO;AAAA,EACX;AAEA,SAAO,kCAAkC,OAAO,EAAE;AAAA,IAC9C,CAAC,UAAU,qBAAqB,MAAM,OAAO,EAAE,MAAM;AAAA,EACzD;AACJ;AAEO,MAAM,+BAA+B,CAAC,SAAiB,eAAoC;AAC9F,QAAM,SAAS,iBAAiB,OAAO;AAEvC,MAAI,CAAC,QAAQ;AACT,WAAO;AAAA,EACX;AAEA,MAAI,UAAU;AAEd,aAAW,SAAS,uBAAuB,MAAM,GAAG;AAChD,UAAM,QAAQ,MAAM;AACpB,UAAM,KAAK,qBAAqB,OAAO,EAAE;AAEzC,QAAI,CAAC,SAAS,OAAO,MAAM;AACvB;AAAA,IACJ;AAEA,UAAM,QAAQ,WAAW,IAAI,EAAE;AAE/B,QAAI,UAAU,UAAa,MAAM,UAAU,OAAO;AAC9C,YAAM,QAAQ;AAAA,QACV,GAAG;AAAA,QACH;AAAA,MACJ;AACA,gBAAU;AAAA,IACd;AAAA,EACJ;AAEA,SAAO,UAAU,KAAK,UAAU,MAAM,IAAI;AAC9C;AAEO,MAAM,iBAAiB,CAAC,UAA6C;AACxE,QAAM,kBAAkB,IAAI,IAAI,MAAM,IAAI,CAAC,SAAS,OAAO,KAAK,EAAE,CAAC,CAAC;AACpE,QAAM,QAAkC,CAAC;AACzC,QAAM,kBAA0C,CAAC;AACjD,QAAM,UAAU,oBAAI,IAAY;AAEhC,aAAW,QAAQ,OAAO;AACtB,UAAM,WAAW,OAAO,KAAK,EAAE;AAE/B,eAAW,SAAS,kCAAkC,KAAK,OAAO,GAAG;AACjE,YAAM,WAAW,qBAAqB,MAAM,OAAO,EAAE;AAErD,UAAI,CAAC,YAAY,aAAa,YAAY,CAAC,gBAAgB,IAAI,QAAQ,GAAG;AACtE;AAAA,MACJ;AAEA,YAAM,UAAU,GAAG,QAAQ,IAAI,QAAQ;AACvC,YAAM,iBAAiB,GAAG,QAAQ,IAAI,QAAQ;AAE9C,UAAI,QAAQ,IAAI,OAAO,KAAK,QAAQ,IAAI,cAAc,GAAG;AACrD;AAAA,MACJ;AAEA,cAAQ,IAAI,OAAO;AACnB,YAAM,KAAK;AAAA,QACP,QAAQ;AAAA,QACR,QAAQ;AAAA,MACZ,CAAC;AACD,sBAAgB,QAAQ,KAAK,gBAAgB,QAAQ,KAAK,KAAK;AAC/D,sBAAgB,QAAQ,KAAK,gBAAgB,QAAQ,KAAK,KAAK;AAAA,IACnE;AAAA,EACJ;AAEA,SAAO;AAAA,IACH,OAAO,MAAM,IAAI,CAAC,SAAS;AACvB,YAAM,KAAK,OAAO,KAAK,EAAE;AAEzB,aAAO;AAAA,QACH;AAAA,QACA,OAAO,KAAK,SAAS;AAAA,QACrB,aAAa,gBAAgB,EAAE,KAAK;AAAA,MACxC;AAAA,IACJ,CAAC;AAAA,IACD;AAAA,EACJ;AACJ;","names":[]}
@@ -0,0 +1,478 @@
1
+ import models from "../../../models.js";
2
+ import {
3
+ blocksToMarkdown,
4
+ countReferenceInlinesFromContentJson,
5
+ extractTagIdsFromContentJson,
6
+ hasUnsupportedMarkdownBlocks,
7
+ markdownToBlocksJson
8
+ } from "../../../modules/blocknote.js";
9
+ import {
10
+ buildMarkdownAppendPlan,
11
+ buildMarkdownPatchPlan,
12
+ buildMarkdownReplacePlan,
13
+ calculateMarkdownSha256
14
+ } from "./markdown-patch.js";
15
+ import {
16
+ InvalidNotePropertyInputError,
17
+ resolveNotePropertiesPatchValueTypes,
18
+ updateNotePropertiesWithVersionGuardAndSnapshot,
19
+ validateNotePropertiesPatchValues
20
+ } from "./properties.js";
21
+ import { MCP_SNAPSHOT_META } from "./snapshot.js";
22
+ import { updateNoteWithVersionGuardAndSnapshot } from "./write.js";
23
+ import {
24
+ isInvalidNoteVersionError,
25
+ isMissingNoteVersionError,
26
+ isNoteVersionConflictError,
27
+ parseNoteVersion
28
+ } from "./write-conflict.js";
29
+ const serializeNoteSnapshot = async (note, renderMarkdown) => {
30
+ return {
31
+ id: String(note.id),
32
+ title: note.title,
33
+ updatedAt: note.updatedAt.toISOString(),
34
+ markdown: await renderMarkdown(note.content)
35
+ };
36
+ };
37
+ const isRecord = (value) => {
38
+ return typeof value === "object" && value !== null;
39
+ };
40
+ const serializeSnapshot = (snapshot) => {
41
+ const meta = isRecord(snapshot) && isRecord(snapshot.meta) ? snapshot.meta : {};
42
+ const label = typeof meta.label === "string" ? meta.label : "MCP";
43
+ return {
44
+ id: isRecord(snapshot) && snapshot.id !== void 0 ? String(snapshot.id) : "",
45
+ label,
46
+ createdAt: isRecord(snapshot) && typeof snapshot.createdAt === "string" ? snapshot.createdAt : ""
47
+ };
48
+ };
49
+ const toDryRun = (plan) => ({
50
+ status: "dry_run",
51
+ note: plan.note,
52
+ ...plan.match ? { match: plan.match } : {},
53
+ ...plan.placement ? { placement: plan.placement } : {},
54
+ proposed: plan.proposed,
55
+ warnings: plan.warnings
56
+ });
57
+ const toTagIds = (tagIds) => {
58
+ return tagIds.map((tagId) => Number(tagId)).filter((tagId) => Number.isSafeInteger(tagId) && tagId > 0);
59
+ };
60
+ const baselineMismatchFailure = () => ({
61
+ status: "failed",
62
+ reason: "BASELINE_MISMATCH",
63
+ message: "The markdown write baseline does not match the current note."
64
+ });
65
+ const missingBaselineFailure = () => ({
66
+ status: "failed",
67
+ reason: "MISSING_BASELINE",
68
+ message: "expectedUpdatedAt or baseMarkdownSha256 is required for markdown writes."
69
+ });
70
+ const unsupportedMarkdownStructureFailure = () => ({
71
+ status: "failed",
72
+ reason: "UNSUPPORTED_MARKDOWN_STRUCTURE",
73
+ message: "This note contains BlockNote content that cannot be safely represented as Markdown."
74
+ });
75
+ const referenceStructureFailure = () => ({
76
+ status: "failed",
77
+ reason: "REFERENCE_STRUCTURE_DECREASED",
78
+ message: "The markdown write would reduce structured note reference links."
79
+ });
80
+ const invalidPropertyInputFailure = (error) => ({
81
+ status: "failed",
82
+ reason: "INVALID_PROPERTY_INPUT",
83
+ message: error.message
84
+ });
85
+ const mapGuardedWriteError = (error) => {
86
+ if (isNoteVersionConflictError(error) || isInvalidNoteVersionError(error)) {
87
+ return baselineMismatchFailure();
88
+ }
89
+ if (isMissingNoteVersionError(error)) {
90
+ return missingBaselineFailure();
91
+ }
92
+ return null;
93
+ };
94
+ const resolveMetadataPropertyPatch = async (deps, patch) => {
95
+ if (patch === void 0) {
96
+ return void 0;
97
+ }
98
+ if (!deps.resolvePropertyPatch || !deps.validatePropertyPatch) {
99
+ throw new Error("Metadata property patch dependencies are not configured.");
100
+ }
101
+ try {
102
+ const resolvedPatch = await deps.resolvePropertyPatch(patch);
103
+ return deps.validatePropertyPatch(resolvedPatch);
104
+ } catch (error) {
105
+ if (error instanceof InvalidNotePropertyInputError) {
106
+ return invalidPropertyInputFailure(error);
107
+ }
108
+ throw error;
109
+ }
110
+ };
111
+ const noteVersionMatches = (expectedUpdatedAt, currentUpdatedAt) => {
112
+ try {
113
+ const expectedTimestamp = parseNoteVersion(expectedUpdatedAt);
114
+ return expectedTimestamp !== null && expectedTimestamp === currentUpdatedAt.getTime();
115
+ } catch {
116
+ return false;
117
+ }
118
+ };
119
+ const getUnsupportedSourceFailure = (deps, note) => {
120
+ if (deps.hasUnsupportedMarkdownBlocks?.(note.content)) {
121
+ return unsupportedMarkdownStructureFailure();
122
+ }
123
+ return null;
124
+ };
125
+ const applyMarkdownPlan = async (deps, input) => {
126
+ const content = await deps.parseMarkdownToContentJson(input.plan.afterMarkdown);
127
+ const beforeReferenceCount = deps.countReferenceInlines?.(input.beforeContentJson) ?? 0;
128
+ const afterReferenceCount = deps.countReferenceInlines?.(content) ?? 0;
129
+ if (input.policy?.preserveReferences !== false && afterReferenceCount < beforeReferenceCount) {
130
+ return referenceStructureFailure();
131
+ }
132
+ const tagIds = toTagIds(deps.extractTagIds(content));
133
+ let updateResult;
134
+ try {
135
+ updateResult = await deps.updateNote({
136
+ id: input.noteId,
137
+ data: {
138
+ content,
139
+ tagIds
140
+ },
141
+ expectedUpdatedAt: input.expectedUpdatedAt ?? input.noteUpdatedAt,
142
+ snapshotMeta: MCP_SNAPSHOT_META,
143
+ ...input.force ? { force: true } : {}
144
+ });
145
+ } catch (error) {
146
+ const mappedError = mapGuardedWriteError(error);
147
+ if (mappedError) {
148
+ return mappedError;
149
+ }
150
+ throw error;
151
+ }
152
+ if (!updateResult) {
153
+ return {
154
+ status: "failed",
155
+ reason: "TARGET_NOT_FOUND",
156
+ message: "The requested note was not found."
157
+ };
158
+ }
159
+ return {
160
+ status: "applied",
161
+ note: {
162
+ id: String(updateResult.note.id),
163
+ updatedAt: updateResult.note.updatedAt.toISOString()
164
+ },
165
+ change: {
166
+ summary: input.summary,
167
+ changedLineCount: input.plan.proposed.changedLineCount,
168
+ changedCharCount: input.plan.proposed.changedCharCount
169
+ },
170
+ snapshot: serializeSnapshot(updateResult.snapshot)
171
+ };
172
+ };
173
+ const mapPlanResult = async (deps, input) => {
174
+ if (input.plan.status !== "dry_run") {
175
+ return input.plan;
176
+ }
177
+ if (input.dryRun ?? true) {
178
+ return toDryRun(input.plan);
179
+ }
180
+ return applyMarkdownPlan(deps, {
181
+ noteId: input.noteId,
182
+ noteUpdatedAt: input.noteUpdatedAt,
183
+ beforeContentJson: input.beforeContentJson,
184
+ plan: input.plan,
185
+ expectedUpdatedAt: input.expectedUpdatedAt,
186
+ policy: input.policy,
187
+ summary: input.summary,
188
+ ...input.force ? { force: true } : {}
189
+ });
190
+ };
191
+ const createMarkdownIntentWriteService = (deps) => ({
192
+ patchNoteMarkdown: async (input) => {
193
+ const note = await deps.findNoteById(input.id);
194
+ if (!note) {
195
+ return {
196
+ status: "failed",
197
+ reason: "TARGET_NOT_FOUND",
198
+ message: "The requested note was not found."
199
+ };
200
+ }
201
+ const unsupportedFailure = getUnsupportedSourceFailure(deps, note);
202
+ if (unsupportedFailure) {
203
+ return unsupportedFailure;
204
+ }
205
+ const noteSnapshot = await serializeNoteSnapshot(note, deps.renderMarkdown);
206
+ const plan = buildMarkdownPatchPlan({
207
+ note: noteSnapshot,
208
+ expectedUpdatedAt: input.expectedUpdatedAt,
209
+ baseMarkdownSha256: input.baseMarkdownSha256,
210
+ intent: input.intent,
211
+ selector: input.selector,
212
+ operation: input.operation,
213
+ policy: input.policy
214
+ });
215
+ return mapPlanResult(deps, {
216
+ noteId: input.id,
217
+ noteUpdatedAt: noteSnapshot.updatedAt,
218
+ beforeContentJson: note.content,
219
+ plan,
220
+ dryRun: input.dryRun,
221
+ expectedUpdatedAt: input.expectedUpdatedAt,
222
+ policy: input.policy,
223
+ summary: input.intent
224
+ });
225
+ },
226
+ appendNoteMarkdown: async (input) => {
227
+ const note = await deps.findNoteById(input.id);
228
+ if (!note) {
229
+ return {
230
+ status: "failed",
231
+ reason: "TARGET_NOT_FOUND",
232
+ message: "The requested note was not found."
233
+ };
234
+ }
235
+ const unsupportedFailure = getUnsupportedSourceFailure(deps, note);
236
+ if (unsupportedFailure) {
237
+ return unsupportedFailure;
238
+ }
239
+ const noteSnapshot = await serializeNoteSnapshot(note, deps.renderMarkdown);
240
+ const plan = buildMarkdownAppendPlan({
241
+ note: noteSnapshot,
242
+ expectedUpdatedAt: input.expectedUpdatedAt,
243
+ baseMarkdownSha256: input.baseMarkdownSha256,
244
+ intent: input.intent,
245
+ insertion: input.insertion,
246
+ placement: input.placement,
247
+ separator: input.separator,
248
+ policy: input.policy
249
+ });
250
+ return mapPlanResult(deps, {
251
+ noteId: input.id,
252
+ noteUpdatedAt: noteSnapshot.updatedAt,
253
+ beforeContentJson: note.content,
254
+ plan,
255
+ dryRun: input.dryRun,
256
+ expectedUpdatedAt: input.expectedUpdatedAt,
257
+ policy: input.policy,
258
+ summary: input.intent
259
+ });
260
+ },
261
+ replaceNoteMarkdown: async (input) => {
262
+ const note = await deps.findNoteById(input.id);
263
+ if (!note) {
264
+ return {
265
+ status: "failed",
266
+ reason: "TARGET_NOT_FOUND",
267
+ message: "The requested note was not found."
268
+ };
269
+ }
270
+ const unsupportedFailure = getUnsupportedSourceFailure(deps, note);
271
+ if (unsupportedFailure) {
272
+ return unsupportedFailure;
273
+ }
274
+ const noteSnapshot = await serializeNoteSnapshot(note, deps.renderMarkdown);
275
+ const plan = buildMarkdownReplacePlan({
276
+ note: noteSnapshot,
277
+ expectedUpdatedAt: input.expectedUpdatedAt,
278
+ baseMarkdownSha256: input.baseMarkdownSha256,
279
+ intent: input.intent,
280
+ replacement: input.replacement,
281
+ policy: input.policy
282
+ });
283
+ return mapPlanResult(deps, {
284
+ noteId: input.id,
285
+ noteUpdatedAt: noteSnapshot.updatedAt,
286
+ beforeContentJson: note.content,
287
+ plan,
288
+ dryRun: input.dryRun,
289
+ expectedUpdatedAt: input.expectedUpdatedAt,
290
+ policy: input.policy,
291
+ summary: input.intent
292
+ });
293
+ },
294
+ updateNoteMetadata: async (input) => {
295
+ const note = await deps.findNoteById(input.id);
296
+ if (!note) {
297
+ return {
298
+ status: "failed",
299
+ reason: "TARGET_NOT_FOUND",
300
+ message: "The requested note was not found."
301
+ };
302
+ }
303
+ if (!noteVersionMatches(input.expectedUpdatedAt, note.updatedAt)) {
304
+ return {
305
+ status: "failed",
306
+ reason: input.expectedUpdatedAt ? "BASELINE_MISMATCH" : "MISSING_BASELINE",
307
+ message: "The metadata update baseline does not match the current note."
308
+ };
309
+ }
310
+ const nextTitle = input.title?.trim();
311
+ const resolvedPropertyPatch = await resolveMetadataPropertyPatch(deps, input.properties);
312
+ if (resolvedPropertyPatch && "status" in resolvedPropertyPatch) {
313
+ return resolvedPropertyPatch;
314
+ }
315
+ if (input.title !== void 0 && !nextTitle) {
316
+ return {
317
+ status: "failed",
318
+ reason: "EMPTY_REPLACEMENT",
319
+ message: "Note title must not be empty."
320
+ };
321
+ }
322
+ if (nextTitle === note.title && (input.layout === void 0 || input.layout === note.layout) && resolvedPropertyPatch === void 0) {
323
+ return {
324
+ status: "failed",
325
+ reason: "NOOP",
326
+ message: "The metadata update would not change the note."
327
+ };
328
+ }
329
+ return {
330
+ status: "dry_run",
331
+ note: {
332
+ id: String(note.id),
333
+ title: note.title,
334
+ updatedAt: note.updatedAt.toISOString()
335
+ },
336
+ proposed: {
337
+ ...nextTitle !== void 0 ? { title: nextTitle } : {},
338
+ ...input.layout !== void 0 ? { layout: input.layout } : {},
339
+ ...resolvedPropertyPatch ? { properties: resolvedPropertyPatch } : {}
340
+ },
341
+ warnings: []
342
+ };
343
+ },
344
+ applyNoteMetadata: async (input) => {
345
+ const preview = await createMarkdownIntentWriteService(deps).updateNoteMetadata(input);
346
+ if (preview.status !== "dry_run") {
347
+ return preview;
348
+ }
349
+ if (input.properties !== void 0) {
350
+ if (!deps.updateProperties) {
351
+ throw new Error("Metadata property write dependency is not configured.");
352
+ }
353
+ let updateResult2;
354
+ try {
355
+ updateResult2 = await deps.updateProperties({
356
+ id: input.id,
357
+ patch: preview.proposed.properties ?? { set: [], deleteKeys: [] },
358
+ expectedUpdatedAt: input.expectedUpdatedAt,
359
+ noteData: {
360
+ ...preview.proposed.title !== void 0 ? { title: preview.proposed.title } : {},
361
+ ...preview.proposed.layout !== void 0 ? { layout: preview.proposed.layout } : {}
362
+ },
363
+ snapshotMeta: MCP_SNAPSHOT_META
364
+ });
365
+ } catch (error) {
366
+ const mappedError = mapGuardedWriteError(error);
367
+ if (mappedError) {
368
+ return mappedError;
369
+ }
370
+ if (error instanceof InvalidNotePropertyInputError) {
371
+ return invalidPropertyInputFailure(error);
372
+ }
373
+ throw error;
374
+ }
375
+ if (!updateResult2) {
376
+ return {
377
+ status: "failed",
378
+ reason: "TARGET_NOT_FOUND",
379
+ message: "The requested note was not found."
380
+ };
381
+ }
382
+ return {
383
+ status: "applied",
384
+ note: {
385
+ id: String(updateResult2.note.id),
386
+ title: updateResult2.note.title,
387
+ layout: updateResult2.note.layout,
388
+ updatedAt: updateResult2.note.updatedAt.toISOString()
389
+ },
390
+ snapshot: serializeSnapshot(updateResult2.snapshot)
391
+ };
392
+ }
393
+ let updateResult;
394
+ try {
395
+ updateResult = await deps.updateNote({
396
+ id: input.id,
397
+ data: {
398
+ ...preview.proposed.title !== void 0 ? { title: preview.proposed.title } : {},
399
+ ...preview.proposed.layout !== void 0 ? { layout: preview.proposed.layout } : {}
400
+ },
401
+ expectedUpdatedAt: input.expectedUpdatedAt,
402
+ snapshotMeta: MCP_SNAPSHOT_META
403
+ });
404
+ } catch (error) {
405
+ const mappedError = mapGuardedWriteError(error);
406
+ if (mappedError) {
407
+ return mappedError;
408
+ }
409
+ throw error;
410
+ }
411
+ if (!updateResult) {
412
+ return {
413
+ status: "failed",
414
+ reason: "TARGET_NOT_FOUND",
415
+ message: "The requested note was not found."
416
+ };
417
+ }
418
+ return {
419
+ status: "applied",
420
+ note: {
421
+ id: String(updateResult.note.id),
422
+ title: updateResult.note.title,
423
+ layout: updateResult.note.layout,
424
+ updatedAt: updateResult.note.updatedAt.toISOString()
425
+ },
426
+ snapshot: serializeSnapshot(updateResult.snapshot)
427
+ };
428
+ }
429
+ });
430
+ const defaultMarkdownIntentWriteService = createMarkdownIntentWriteService({
431
+ findNoteById: (id) => models.note.findUnique({
432
+ where: { id },
433
+ select: {
434
+ id: true,
435
+ title: true,
436
+ content: true,
437
+ layout: true,
438
+ updatedAt: true
439
+ }
440
+ }),
441
+ renderMarkdown: blocksToMarkdown,
442
+ parseMarkdownToContentJson: markdownToBlocksJson,
443
+ extractTagIds: extractTagIdsFromContentJson,
444
+ countReferenceInlines: countReferenceInlinesFromContentJson,
445
+ hasUnsupportedMarkdownBlocks,
446
+ updateNote: updateNoteWithVersionGuardAndSnapshot,
447
+ resolvePropertyPatch: resolveNotePropertiesPatchValueTypes,
448
+ validatePropertyPatch: validateNotePropertiesPatchValues,
449
+ updateProperties: updateNotePropertiesWithVersionGuardAndSnapshot
450
+ });
451
+ const patchNoteMarkdown = async (input) => {
452
+ return defaultMarkdownIntentWriteService.patchNoteMarkdown(input);
453
+ };
454
+ const appendNoteMarkdown = async (input) => {
455
+ return defaultMarkdownIntentWriteService.appendNoteMarkdown(input);
456
+ };
457
+ const replaceNoteMarkdown = async (input) => {
458
+ return defaultMarkdownIntentWriteService.replaceNoteMarkdown(input);
459
+ };
460
+ const updateNoteMetadata = async (input) => {
461
+ if (input.dryRun ?? true) {
462
+ return defaultMarkdownIntentWriteService.updateNoteMetadata(input);
463
+ }
464
+ return defaultMarkdownIntentWriteService.applyNoteMetadata(input);
465
+ };
466
+ const calculateNoteMarkdownSha256 = (markdown) => {
467
+ return calculateMarkdownSha256(markdown);
468
+ };
469
+ export {
470
+ appendNoteMarkdown,
471
+ calculateNoteMarkdownSha256,
472
+ createMarkdownIntentWriteService,
473
+ defaultMarkdownIntentWriteService,
474
+ patchNoteMarkdown,
475
+ replaceNoteMarkdown,
476
+ updateNoteMetadata
477
+ };
478
+ //# sourceMappingURL=markdown-intent-write.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/features/note/services/markdown-intent-write.ts"],"sourcesContent":["import models, { type NoteLayout } from '~/models.js';\nimport {\n blocksToMarkdown,\n countReferenceInlinesFromContentJson,\n extractTagIdsFromContentJson,\n hasUnsupportedMarkdownBlocks,\n markdownToBlocksJson,\n} from '~/modules/blocknote.js';\nimport type {\n MarkdownAppendPlanResult,\n MarkdownChangeDryRun,\n MarkdownChangeFailure,\n MarkdownChangePlan,\n MarkdownPatchOperation,\n MarkdownPatchPlanResult,\n MarkdownPatchSelector,\n MarkdownReplacePlanResult,\n} from './markdown-patch.js';\nimport {\n buildMarkdownAppendPlan,\n buildMarkdownPatchPlan,\n buildMarkdownReplacePlan,\n calculateMarkdownSha256,\n} from './markdown-patch.js';\nimport {\n InvalidNotePropertyInputError,\n type NotePropertiesByKeyPatchInput,\n type NotePropertiesPatchInput,\n resolveNotePropertiesPatchValueTypes,\n updateNotePropertiesWithVersionGuardAndSnapshot,\n validateNotePropertiesPatchValues,\n} from './properties.js';\nimport { MCP_SNAPSHOT_META } from './snapshot.js';\nimport { type GuardedNoteWriteResult, updateNoteWithVersionGuardAndSnapshot } from './write.js';\nimport {\n isInvalidNoteVersionError,\n isMissingNoteVersionError,\n isNoteVersionConflictError,\n parseNoteVersion,\n} from './write-conflict.js';\n\ninterface MarkdownIntentNoteRecord {\n id: number;\n title: string;\n content: string;\n layout: NoteLayout;\n updatedAt: Date;\n}\n\ninterface MarkdownIntentWriteDeps {\n findNoteById: (id: number) => Promise<MarkdownIntentNoteRecord | null>;\n renderMarkdown: (contentJson: string) => Promise<string>;\n parseMarkdownToContentJson: (markdown: string) => Promise<string>;\n extractTagIds: (contentJson: string) => string[];\n countReferenceInlines?: (contentJson: string) => number;\n hasUnsupportedMarkdownBlocks?: (contentJson: string) => boolean;\n updateNote: (input: {\n id: number;\n data: {\n title?: string;\n content?: string;\n layout?: NoteLayout;\n tagIds?: number[];\n };\n expectedUpdatedAt: string;\n snapshotMeta?: string;\n force?: boolean;\n }) => Promise<GuardedNoteWriteResult | null>;\n resolvePropertyPatch?: (patch: NotePropertiesByKeyPatchInput) => Promise<NotePropertiesPatchInput>;\n validatePropertyPatch?: (patch: NotePropertiesPatchInput) => Promise<NotePropertiesPatchInput>;\n updateProperties?: (input: {\n id: number;\n patch: NotePropertiesPatchInput;\n expectedUpdatedAt: string;\n noteData?: {\n title?: string;\n layout?: NoteLayout;\n };\n snapshotMeta?: string;\n }) => Promise<{\n note: {\n id: number;\n title: string;\n layout: NoteLayout;\n updatedAt: Date;\n };\n snapshot: unknown;\n } | null>;\n}\n\nexport interface MarkdownWritePolicy {\n allowNoop?: boolean;\n maxChangedChars?: number;\n maxChangedLines?: number;\n preserveReferences?: boolean | 'warn';\n preserveTags?: boolean | 'warn';\n}\n\nexport interface PatchNoteMarkdownInput {\n id: number;\n expectedUpdatedAt?: string;\n baseMarkdownSha256?: string;\n intent: string;\n selector: MarkdownPatchSelector;\n operation: MarkdownPatchOperation;\n policy?: MarkdownWritePolicy;\n dryRun?: boolean;\n}\n\nexport interface AppendNoteMarkdownInput {\n id: number;\n expectedUpdatedAt?: string;\n baseMarkdownSha256?: string;\n intent: string;\n insertion: string;\n placement?:\n | {\n type: 'end';\n }\n | {\n type: 'after_heading';\n heading: string;\n level?: number;\n };\n separator?: '\\n\\n' | '\\n';\n policy?: MarkdownWritePolicy;\n dryRun?: boolean;\n}\n\nexport interface ReplaceNoteMarkdownInput {\n id: number;\n expectedUpdatedAt?: string;\n baseMarkdownSha256?: string;\n intent: string;\n replacement: string;\n policy?: MarkdownWritePolicy;\n dryRun?: boolean;\n}\n\nexport interface UpdateNoteMetadataInput {\n id: number;\n expectedUpdatedAt: string;\n title?: string;\n layout?: NoteLayout;\n properties?: NotePropertiesByKeyPatchInput;\n}\n\nexport interface AppliedMarkdownWriteResult {\n status: 'applied';\n note: {\n id: string;\n updatedAt: string;\n };\n change: {\n summary: string;\n changedLineCount: number;\n changedCharCount: number;\n };\n snapshot: {\n id: string;\n label: string;\n createdAt: string;\n };\n}\n\nexport interface MetadataUpdatePreview {\n status: 'dry_run';\n note: {\n id: string;\n title: string;\n updatedAt: string;\n };\n proposed: {\n title?: string;\n layout?: NoteLayout;\n properties?: NotePropertiesPatchInput;\n };\n warnings: string[];\n}\n\nexport interface AppliedMetadataUpdateResult {\n status: 'applied';\n note: {\n id: string;\n title: string;\n layout: NoteLayout;\n updatedAt: string;\n };\n snapshot: {\n id: string;\n label: string;\n createdAt: string;\n };\n}\n\nexport type MarkdownIntentWriteResult =\n | MarkdownChangeDryRun\n | AppliedMarkdownWriteResult\n | MarkdownChangeFailure\n | Extract<MarkdownPatchPlanResult, { status: 'needs_disambiguation' }>;\n\nexport type MetadataUpdateResult = MetadataUpdatePreview | AppliedMetadataUpdateResult | MarkdownChangeFailure;\n\nconst serializeNoteSnapshot = async (\n note: MarkdownIntentNoteRecord,\n renderMarkdown: (contentJson: string) => Promise<string>,\n) => {\n return {\n id: String(note.id),\n title: note.title,\n updatedAt: note.updatedAt.toISOString(),\n markdown: await renderMarkdown(note.content),\n };\n};\n\nconst isRecord = (value: unknown): value is Record<string, unknown> => {\n return typeof value === 'object' && value !== null;\n};\n\nconst serializeSnapshot = (snapshot: unknown) => {\n const meta = isRecord(snapshot) && isRecord(snapshot.meta) ? snapshot.meta : {};\n const label = typeof meta.label === 'string' ? meta.label : 'MCP';\n\n return {\n id: isRecord(snapshot) && snapshot.id !== undefined ? String(snapshot.id) : '',\n label,\n createdAt: isRecord(snapshot) && typeof snapshot.createdAt === 'string' ? snapshot.createdAt : '',\n };\n};\n\nconst toDryRun = (plan: MarkdownChangePlan): MarkdownChangeDryRun => ({\n status: 'dry_run',\n note: plan.note,\n ...(plan.match ? { match: plan.match } : {}),\n ...(plan.placement ? { placement: plan.placement } : {}),\n proposed: plan.proposed,\n warnings: plan.warnings,\n});\n\nconst toTagIds = (tagIds: string[]) => {\n return tagIds.map((tagId) => Number(tagId)).filter((tagId) => Number.isSafeInteger(tagId) && tagId > 0);\n};\n\nconst baselineMismatchFailure = (): MarkdownChangeFailure => ({\n status: 'failed',\n reason: 'BASELINE_MISMATCH',\n message: 'The markdown write baseline does not match the current note.',\n});\n\nconst missingBaselineFailure = (): MarkdownChangeFailure => ({\n status: 'failed',\n reason: 'MISSING_BASELINE',\n message: 'expectedUpdatedAt or baseMarkdownSha256 is required for markdown writes.',\n});\n\nconst unsupportedMarkdownStructureFailure = (): MarkdownChangeFailure => ({\n status: 'failed',\n reason: 'UNSUPPORTED_MARKDOWN_STRUCTURE',\n message: 'This note contains BlockNote content that cannot be safely represented as Markdown.',\n});\n\nconst referenceStructureFailure = (): MarkdownChangeFailure => ({\n status: 'failed',\n reason: 'REFERENCE_STRUCTURE_DECREASED',\n message: 'The markdown write would reduce structured note reference links.',\n});\n\nconst invalidPropertyInputFailure = (error: InvalidNotePropertyInputError): MarkdownChangeFailure => ({\n status: 'failed',\n reason: 'INVALID_PROPERTY_INPUT',\n message: error.message,\n});\n\nconst mapGuardedWriteError = (error: unknown): MarkdownChangeFailure | null => {\n if (isNoteVersionConflictError(error) || isInvalidNoteVersionError(error)) {\n return baselineMismatchFailure();\n }\n\n if (isMissingNoteVersionError(error)) {\n return missingBaselineFailure();\n }\n\n return null;\n};\n\nconst resolveMetadataPropertyPatch = async (\n deps: MarkdownIntentWriteDeps,\n patch: NotePropertiesByKeyPatchInput | undefined,\n): Promise<NotePropertiesPatchInput | MarkdownChangeFailure | undefined> => {\n if (patch === undefined) {\n return undefined;\n }\n\n if (!deps.resolvePropertyPatch || !deps.validatePropertyPatch) {\n throw new Error('Metadata property patch dependencies are not configured.');\n }\n\n try {\n const resolvedPatch = await deps.resolvePropertyPatch(patch);\n return deps.validatePropertyPatch(resolvedPatch);\n } catch (error) {\n if (error instanceof InvalidNotePropertyInputError) {\n return invalidPropertyInputFailure(error);\n }\n\n throw error;\n }\n};\n\nconst noteVersionMatches = (expectedUpdatedAt: string | undefined, currentUpdatedAt: Date) => {\n try {\n const expectedTimestamp = parseNoteVersion(expectedUpdatedAt);\n\n return expectedTimestamp !== null && expectedTimestamp === currentUpdatedAt.getTime();\n } catch {\n return false;\n }\n};\n\nconst getUnsupportedSourceFailure = (deps: MarkdownIntentWriteDeps, note: MarkdownIntentNoteRecord) => {\n if (deps.hasUnsupportedMarkdownBlocks?.(note.content)) {\n return unsupportedMarkdownStructureFailure();\n }\n\n return null;\n};\n\nconst applyMarkdownPlan = async (\n deps: MarkdownIntentWriteDeps,\n input: {\n noteId: number;\n noteUpdatedAt: string;\n beforeContentJson: string;\n plan: Extract<MarkdownPatchPlanResult, { status: 'dry_run' }>;\n expectedUpdatedAt?: string;\n policy?: MarkdownWritePolicy;\n summary: string;\n force?: boolean;\n },\n): Promise<AppliedMarkdownWriteResult | MarkdownChangeFailure> => {\n const content = await deps.parseMarkdownToContentJson(input.plan.afterMarkdown);\n const beforeReferenceCount = deps.countReferenceInlines?.(input.beforeContentJson) ?? 0;\n const afterReferenceCount = deps.countReferenceInlines?.(content) ?? 0;\n\n if (input.policy?.preserveReferences !== false && afterReferenceCount < beforeReferenceCount) {\n return referenceStructureFailure();\n }\n\n const tagIds = toTagIds(deps.extractTagIds(content));\n let updateResult: GuardedNoteWriteResult | null;\n\n try {\n updateResult = await deps.updateNote({\n id: input.noteId,\n data: {\n content,\n tagIds,\n },\n expectedUpdatedAt: input.expectedUpdatedAt ?? input.noteUpdatedAt,\n snapshotMeta: MCP_SNAPSHOT_META,\n ...(input.force ? { force: true } : {}),\n });\n } catch (error) {\n const mappedError = mapGuardedWriteError(error);\n\n if (mappedError) {\n return mappedError;\n }\n\n throw error;\n }\n\n if (!updateResult) {\n return {\n status: 'failed',\n reason: 'TARGET_NOT_FOUND',\n message: 'The requested note was not found.',\n };\n }\n\n return {\n status: 'applied',\n note: {\n id: String(updateResult.note.id),\n updatedAt: updateResult.note.updatedAt.toISOString(),\n },\n change: {\n summary: input.summary,\n changedLineCount: input.plan.proposed.changedLineCount,\n changedCharCount: input.plan.proposed.changedCharCount,\n },\n snapshot: serializeSnapshot(updateResult.snapshot),\n };\n};\n\nconst mapPlanResult = async (\n deps: MarkdownIntentWriteDeps,\n input: {\n noteId: number;\n noteUpdatedAt: string;\n beforeContentJson: string;\n plan: MarkdownPatchPlanResult | MarkdownAppendPlanResult | MarkdownReplacePlanResult;\n dryRun?: boolean;\n expectedUpdatedAt?: string;\n policy?: MarkdownWritePolicy;\n summary: string;\n force?: boolean;\n },\n): Promise<MarkdownIntentWriteResult> => {\n if (input.plan.status !== 'dry_run') {\n return input.plan;\n }\n\n if (input.dryRun ?? true) {\n return toDryRun(input.plan);\n }\n\n return applyMarkdownPlan(deps, {\n noteId: input.noteId,\n noteUpdatedAt: input.noteUpdatedAt,\n beforeContentJson: input.beforeContentJson,\n plan: input.plan,\n expectedUpdatedAt: input.expectedUpdatedAt,\n policy: input.policy,\n summary: input.summary,\n ...(input.force ? { force: true } : {}),\n });\n};\n\nexport const createMarkdownIntentWriteService = (deps: MarkdownIntentWriteDeps) => ({\n patchNoteMarkdown: async (input: PatchNoteMarkdownInput): Promise<MarkdownIntentWriteResult> => {\n const note = await deps.findNoteById(input.id);\n\n if (!note) {\n return {\n status: 'failed',\n reason: 'TARGET_NOT_FOUND',\n message: 'The requested note was not found.',\n };\n }\n\n const unsupportedFailure = getUnsupportedSourceFailure(deps, note);\n\n if (unsupportedFailure) {\n return unsupportedFailure;\n }\n\n const noteSnapshot = await serializeNoteSnapshot(note, deps.renderMarkdown);\n const plan = buildMarkdownPatchPlan({\n note: noteSnapshot,\n expectedUpdatedAt: input.expectedUpdatedAt,\n baseMarkdownSha256: input.baseMarkdownSha256,\n intent: input.intent,\n selector: input.selector,\n operation: input.operation,\n policy: input.policy,\n });\n\n return mapPlanResult(deps, {\n noteId: input.id,\n noteUpdatedAt: noteSnapshot.updatedAt,\n beforeContentJson: note.content,\n plan,\n dryRun: input.dryRun,\n expectedUpdatedAt: input.expectedUpdatedAt,\n policy: input.policy,\n summary: input.intent,\n });\n },\n\n appendNoteMarkdown: async (input: AppendNoteMarkdownInput): Promise<MarkdownIntentWriteResult> => {\n const note = await deps.findNoteById(input.id);\n\n if (!note) {\n return {\n status: 'failed',\n reason: 'TARGET_NOT_FOUND',\n message: 'The requested note was not found.',\n };\n }\n\n const unsupportedFailure = getUnsupportedSourceFailure(deps, note);\n\n if (unsupportedFailure) {\n return unsupportedFailure;\n }\n\n const noteSnapshot = await serializeNoteSnapshot(note, deps.renderMarkdown);\n const plan = buildMarkdownAppendPlan({\n note: noteSnapshot,\n expectedUpdatedAt: input.expectedUpdatedAt,\n baseMarkdownSha256: input.baseMarkdownSha256,\n intent: input.intent,\n insertion: input.insertion,\n placement: input.placement,\n separator: input.separator,\n policy: input.policy,\n });\n\n return mapPlanResult(deps, {\n noteId: input.id,\n noteUpdatedAt: noteSnapshot.updatedAt,\n beforeContentJson: note.content,\n plan,\n dryRun: input.dryRun,\n expectedUpdatedAt: input.expectedUpdatedAt,\n policy: input.policy,\n summary: input.intent,\n });\n },\n\n replaceNoteMarkdown: async (input: ReplaceNoteMarkdownInput): Promise<MarkdownIntentWriteResult> => {\n const note = await deps.findNoteById(input.id);\n\n if (!note) {\n return {\n status: 'failed',\n reason: 'TARGET_NOT_FOUND',\n message: 'The requested note was not found.',\n };\n }\n\n const unsupportedFailure = getUnsupportedSourceFailure(deps, note);\n\n if (unsupportedFailure) {\n return unsupportedFailure;\n }\n\n const noteSnapshot = await serializeNoteSnapshot(note, deps.renderMarkdown);\n const plan = buildMarkdownReplacePlan({\n note: noteSnapshot,\n expectedUpdatedAt: input.expectedUpdatedAt,\n baseMarkdownSha256: input.baseMarkdownSha256,\n intent: input.intent,\n replacement: input.replacement,\n policy: input.policy,\n });\n\n return mapPlanResult(deps, {\n noteId: input.id,\n noteUpdatedAt: noteSnapshot.updatedAt,\n beforeContentJson: note.content,\n plan,\n dryRun: input.dryRun,\n expectedUpdatedAt: input.expectedUpdatedAt,\n policy: input.policy,\n summary: input.intent,\n });\n },\n\n updateNoteMetadata: async (input: UpdateNoteMetadataInput): Promise<MetadataUpdateResult> => {\n const note = await deps.findNoteById(input.id);\n\n if (!note) {\n return {\n status: 'failed',\n reason: 'TARGET_NOT_FOUND',\n message: 'The requested note was not found.',\n };\n }\n\n if (!noteVersionMatches(input.expectedUpdatedAt, note.updatedAt)) {\n return {\n status: 'failed',\n reason: input.expectedUpdatedAt ? 'BASELINE_MISMATCH' : 'MISSING_BASELINE',\n message: 'The metadata update baseline does not match the current note.',\n };\n }\n\n const nextTitle = input.title?.trim();\n const resolvedPropertyPatch = await resolveMetadataPropertyPatch(deps, input.properties);\n\n if (resolvedPropertyPatch && 'status' in resolvedPropertyPatch) {\n return resolvedPropertyPatch;\n }\n\n if (input.title !== undefined && !nextTitle) {\n return {\n status: 'failed',\n reason: 'EMPTY_REPLACEMENT',\n message: 'Note title must not be empty.',\n };\n }\n\n if (\n nextTitle === note.title &&\n (input.layout === undefined || input.layout === note.layout) &&\n resolvedPropertyPatch === undefined\n ) {\n return {\n status: 'failed',\n reason: 'NOOP',\n message: 'The metadata update would not change the note.',\n };\n }\n\n return {\n status: 'dry_run',\n note: {\n id: String(note.id),\n title: note.title,\n updatedAt: note.updatedAt.toISOString(),\n },\n proposed: {\n ...(nextTitle !== undefined ? { title: nextTitle } : {}),\n ...(input.layout !== undefined ? { layout: input.layout } : {}),\n ...(resolvedPropertyPatch ? { properties: resolvedPropertyPatch } : {}),\n },\n warnings: [],\n };\n },\n\n applyNoteMetadata: async (input: UpdateNoteMetadataInput): Promise<MetadataUpdateResult> => {\n const preview = await createMarkdownIntentWriteService(deps).updateNoteMetadata(input);\n\n if (preview.status !== 'dry_run') {\n return preview;\n }\n\n if (input.properties !== undefined) {\n if (!deps.updateProperties) {\n throw new Error('Metadata property write dependency is not configured.');\n }\n\n let updateResult: Awaited<ReturnType<NonNullable<MarkdownIntentWriteDeps['updateProperties']>>>;\n\n try {\n updateResult = await deps.updateProperties({\n id: input.id,\n patch: preview.proposed.properties ?? { set: [], deleteKeys: [] },\n expectedUpdatedAt: input.expectedUpdatedAt,\n noteData: {\n ...(preview.proposed.title !== undefined ? { title: preview.proposed.title } : {}),\n ...(preview.proposed.layout !== undefined ? { layout: preview.proposed.layout } : {}),\n },\n snapshotMeta: MCP_SNAPSHOT_META,\n });\n } catch (error) {\n const mappedError = mapGuardedWriteError(error);\n\n if (mappedError) {\n return mappedError;\n }\n\n if (error instanceof InvalidNotePropertyInputError) {\n return invalidPropertyInputFailure(error);\n }\n\n throw error;\n }\n\n if (!updateResult) {\n return {\n status: 'failed',\n reason: 'TARGET_NOT_FOUND',\n message: 'The requested note was not found.',\n };\n }\n\n return {\n status: 'applied',\n note: {\n id: String(updateResult.note.id),\n title: updateResult.note.title,\n layout: updateResult.note.layout,\n updatedAt: updateResult.note.updatedAt.toISOString(),\n },\n snapshot: serializeSnapshot(updateResult.snapshot),\n };\n }\n\n let updateResult: GuardedNoteWriteResult | null;\n\n try {\n updateResult = await deps.updateNote({\n id: input.id,\n data: {\n ...(preview.proposed.title !== undefined ? { title: preview.proposed.title } : {}),\n ...(preview.proposed.layout !== undefined ? { layout: preview.proposed.layout } : {}),\n },\n expectedUpdatedAt: input.expectedUpdatedAt,\n snapshotMeta: MCP_SNAPSHOT_META,\n });\n } catch (error) {\n const mappedError = mapGuardedWriteError(error);\n\n if (mappedError) {\n return mappedError;\n }\n\n throw error;\n }\n\n if (!updateResult) {\n return {\n status: 'failed',\n reason: 'TARGET_NOT_FOUND',\n message: 'The requested note was not found.',\n };\n }\n\n return {\n status: 'applied',\n note: {\n id: String(updateResult.note.id),\n title: updateResult.note.title,\n layout: updateResult.note.layout,\n updatedAt: updateResult.note.updatedAt.toISOString(),\n },\n snapshot: serializeSnapshot(updateResult.snapshot),\n };\n },\n});\n\nexport const defaultMarkdownIntentWriteService = createMarkdownIntentWriteService({\n findNoteById: (id) =>\n models.note.findUnique({\n where: { id },\n select: {\n id: true,\n title: true,\n content: true,\n layout: true,\n updatedAt: true,\n },\n }),\n renderMarkdown: blocksToMarkdown,\n parseMarkdownToContentJson: markdownToBlocksJson,\n extractTagIds: extractTagIdsFromContentJson,\n countReferenceInlines: countReferenceInlinesFromContentJson,\n hasUnsupportedMarkdownBlocks,\n updateNote: updateNoteWithVersionGuardAndSnapshot,\n resolvePropertyPatch: resolveNotePropertiesPatchValueTypes,\n validatePropertyPatch: validateNotePropertiesPatchValues,\n updateProperties: updateNotePropertiesWithVersionGuardAndSnapshot,\n});\n\nexport const patchNoteMarkdown = async (input: PatchNoteMarkdownInput) => {\n return defaultMarkdownIntentWriteService.patchNoteMarkdown(input);\n};\n\nexport const appendNoteMarkdown = async (input: AppendNoteMarkdownInput) => {\n return defaultMarkdownIntentWriteService.appendNoteMarkdown(input);\n};\n\nexport const replaceNoteMarkdown = async (input: ReplaceNoteMarkdownInput) => {\n return defaultMarkdownIntentWriteService.replaceNoteMarkdown(input);\n};\n\nexport const updateNoteMetadata = async (input: UpdateNoteMetadataInput & { dryRun?: boolean }) => {\n if (input.dryRun ?? true) {\n return defaultMarkdownIntentWriteService.updateNoteMetadata(input);\n }\n\n return defaultMarkdownIntentWriteService.applyNoteMetadata(input);\n};\n\nexport const calculateNoteMarkdownSha256 = (markdown: string) => {\n return calculateMarkdownSha256(markdown);\n};\n"],"mappings":"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","names":["updateResult"]}