ocean-brain 0.5.0 → 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 (77) hide show
  1. package/dist/mcp.js +660 -31
  2. package/package.json +2 -1
  3. package/server/client/dist/assets/{Calendar-BU9XgX2N.js → Calendar-BytW4PeT.js} +1 -1
  4. package/server/client/dist/assets/{Callout-C6tVCxOT.js → Callout-9sJgGNRb.js} +1 -1
  5. package/server/client/dist/assets/Graph-o5u-NzrA.js +1 -0
  6. package/server/client/dist/assets/{Image.es-BjGK7y6Y.js → Image.es-B0LL3pb7.js} +1 -1
  7. package/server/client/dist/assets/Note-CYoYzZNu.js +21 -0
  8. package/server/client/dist/assets/{Plus.es-EcmtS_uw.js → Plus.es-DpxzgRtY.js} +1 -1
  9. package/server/client/dist/assets/Reminders-DAepTZg1.js +1 -0
  10. package/server/client/dist/assets/Search-6KH7An44.js +1 -0
  11. package/server/client/dist/assets/{SurfaceCard-CO0oVxeL.js → SurfaceCard-EMs50xSF.js} +1 -1
  12. package/server/client/dist/assets/Tag-C89j8x56.js +1 -0
  13. package/server/client/dist/assets/TagNotes-BTbu-f6v.js +1 -0
  14. package/server/client/dist/assets/{Trash.es-DmwfSy3l.js → Trash.es-C5x35NKF.js} +1 -1
  15. package/server/client/dist/assets/ViewNotes-DPEuki3y.js +1 -0
  16. package/server/client/dist/assets/Views-BGkuNhVd.js +1 -0
  17. package/server/client/dist/assets/{image.api-DeF9ck7g.js → image.api-DRhRQ0Gf.js} +1 -1
  18. package/server/client/dist/assets/{index-BZUGWdOU.css → index-Cd81UxEh.css} +1 -1
  19. package/server/client/dist/assets/{index-BvKBTjQq.js → index-DYlYUrjH.js} +118 -37
  20. package/server/client/dist/assets/index-DswSFFMb.js +1 -0
  21. package/server/client/dist/assets/manage-image-C6sHhWnI.js +1 -0
  22. package/server/client/dist/assets/manage-image-detail-CJkfybR9.js +1 -0
  23. package/server/client/dist/assets/{mcp-Bh743HBz.js → mcp-piouFDNm.js} +1 -1
  24. package/server/client/dist/assets/{placeholder-XQqo1Fvr.js → placeholder-DGz3CHej.js} +5 -5
  25. package/server/client/dist/assets/properties-CM4khczg.js +1 -0
  26. package/server/client/dist/assets/trash-C2lItz-b.js +1 -0
  27. package/server/client/dist/assets/{useReminderMutate-D21PurIS.js → useReminderMutate-DHjDDHKg.js} +1 -1
  28. package/server/client/dist/assets/view-dashboard-C17WsdL7.js +99 -0
  29. package/server/client/dist/index.html +2 -2
  30. package/server/dist/features/note/graphql/note.field.resolver.js +2 -0
  31. package/server/dist/features/note/graphql/note.field.resolver.js.map +1 -1
  32. package/server/dist/features/note/graphql/note.mutation.resolver.js +119 -0
  33. package/server/dist/features/note/graphql/note.mutation.resolver.js.map +1 -1
  34. package/server/dist/features/note/graphql/note.query.resolver.js +14 -0
  35. package/server/dist/features/note/graphql/note.query.resolver.js.map +1 -1
  36. package/server/dist/features/note/graphql/note.type-defs.js +100 -0
  37. package/server/dist/features/note/graphql/note.type-defs.js.map +1 -1
  38. package/server/dist/features/note/http/mcp.js +394 -1
  39. package/server/dist/features/note/http/mcp.js.map +1 -1
  40. package/server/dist/features/note/services/markdown-intent-write.js +478 -0
  41. package/server/dist/features/note/services/markdown-intent-write.js.map +1 -0
  42. package/server/dist/features/note/services/markdown-patch.js +601 -0
  43. package/server/dist/features/note/services/markdown-patch.js.map +1 -0
  44. package/server/dist/features/note/services/properties.js +874 -0
  45. package/server/dist/features/note/services/properties.js.map +1 -0
  46. package/server/dist/features/note/services/snapshot.js +94 -12
  47. package/server/dist/features/note/services/snapshot.js.map +1 -1
  48. package/server/dist/features/note/services/trash.js +70 -2
  49. package/server/dist/features/note/services/trash.js.map +1 -1
  50. package/server/dist/features/note/services/write.js +21 -7
  51. package/server/dist/features/note/services/write.js.map +1 -1
  52. package/server/dist/features/view/graphql/view.query.resolver.js +31 -1
  53. package/server/dist/features/view/graphql/view.query.resolver.js.map +1 -1
  54. package/server/dist/features/view/graphql/view.type-defs.js +57 -1
  55. package/server/dist/features/view/graphql/view.type-defs.js.map +1 -1
  56. package/server/dist/features/view/services/workspace.js +367 -43
  57. package/server/dist/features/view/services/workspace.js.map +1 -1
  58. package/server/dist/modules/blocknote.js +47 -2
  59. package/server/dist/modules/blocknote.js.map +1 -1
  60. package/server/dist/routes/mcp.js +21 -1
  61. package/server/dist/routes/mcp.js.map +1 -1
  62. package/server/prisma/migrations/20260527073000_0017_note_properties/migration.sql +105 -0
  63. package/server/prisma/migrations/20260531073000_0018_view_query/migration.sql +3 -0
  64. package/server/prisma/schema.prisma +226 -130
  65. package/server/client/dist/assets/Graph-Dond2hGK.js +0 -1
  66. package/server/client/dist/assets/Note-Cr6GtXUM.js +0 -21
  67. package/server/client/dist/assets/Reminders-BlLLT_x0.js +0 -1
  68. package/server/client/dist/assets/Search-CrZ0ap8x.js +0 -1
  69. package/server/client/dist/assets/Tag-vws5AfNW.js +0 -1
  70. package/server/client/dist/assets/TagNotes-Fmf1Kgim.js +0 -1
  71. package/server/client/dist/assets/ViewNotes-BALN7IfH.js +0 -1
  72. package/server/client/dist/assets/Views-Ccc_Ml5U.js +0 -1
  73. package/server/client/dist/assets/index-BSVE2cGd.js +0 -1
  74. package/server/client/dist/assets/manage-image-IoTXaMBP.js +0 -1
  75. package/server/client/dist/assets/manage-image-detail-BRTXwOsh.js +0 -1
  76. package/server/client/dist/assets/trash-hiJIg6-c.js +0 -1
  77. package/server/client/dist/assets/view-dashboard-BuaZ4MvI.js +0 -90
@@ -4,10 +4,21 @@ import {
4
4
  updateNoteFromMarkdown
5
5
  } from "../../../features/note/services/authoring.js";
6
6
  import { deleteNoteById } from "../../../features/note/services/cleanup.js";
7
+ import {
8
+ appendNoteMarkdown,
9
+ patchNoteMarkdown,
10
+ replaceNoteMarkdown,
11
+ updateNoteMetadata
12
+ } from "../../../features/note/services/markdown-intent-write.js";
7
13
  import { MCP_SNAPSHOT_META } from "../../../features/note/services/snapshot.js";
8
14
  import { createAppError } from "../../../modules/error-handler.js";
9
15
  import { emitServerEvent } from "../../../modules/server-events.js";
10
16
  const NOTE_LAYOUTS = /* @__PURE__ */ new Set(["narrow", "wide", "full"]);
17
+ const POSITION_HINTS = /* @__PURE__ */ new Set(["first", "last"]);
18
+ const PRESERVATION_POLICIES = /* @__PURE__ */ new Set([true, false, "warn"]);
19
+ const isRecord = (value) => {
20
+ return typeof value === "object" && value !== null;
21
+ };
11
22
  const resolveNoteLayout = (value) => {
12
23
  if (value === void 0) {
13
24
  return void 0;
@@ -17,6 +28,223 @@ const resolveNoteLayout = (value) => {
17
28
  }
18
29
  return null;
19
30
  };
31
+ const resolveOptionalString = (value, code, message) => {
32
+ if (value === void 0) {
33
+ return void 0;
34
+ }
35
+ if (typeof value === "string") {
36
+ return value;
37
+ }
38
+ throw createAppError(400, code, message);
39
+ };
40
+ const resolveOptionalBoolean = (value, code, message) => {
41
+ if (value === void 0) {
42
+ return void 0;
43
+ }
44
+ if (typeof value === "boolean") {
45
+ return value;
46
+ }
47
+ throw createAppError(400, code, message);
48
+ };
49
+ const resolveMetadataPropertyPatch = (value) => {
50
+ if (value === void 0) {
51
+ return void 0;
52
+ }
53
+ if (!isRecord(value)) {
54
+ throw createAppError(400, "INVALID_NOTE_PROPERTIES", "Properties patch must be an object.");
55
+ }
56
+ const set = value.set === void 0 ? void 0 : Array.isArray(value.set) ? value.set.map((item) => {
57
+ if (!isRecord(item) || typeof item.key !== "string" || typeof item.value !== "string") {
58
+ throw createAppError(
59
+ 400,
60
+ "INVALID_NOTE_PROPERTIES",
61
+ "Property set items must include string key and value fields."
62
+ );
63
+ }
64
+ return {
65
+ key: item.key,
66
+ value: item.value
67
+ };
68
+ }) : null;
69
+ if (set === null) {
70
+ throw createAppError(400, "INVALID_NOTE_PROPERTIES", "Property set must be an array.");
71
+ }
72
+ const deleteKeys = value.deleteKeys === void 0 ? void 0 : Array.isArray(value.deleteKeys) ? value.deleteKeys.map((key) => {
73
+ if (typeof key !== "string") {
74
+ throw createAppError(400, "INVALID_NOTE_PROPERTIES", "Property deleteKeys must be strings.");
75
+ }
76
+ return key;
77
+ }) : null;
78
+ if (deleteKeys === null) {
79
+ throw createAppError(400, "INVALID_NOTE_PROPERTIES", "Property deleteKeys must be an array.");
80
+ }
81
+ return {
82
+ ...set !== void 0 ? { set } : {},
83
+ ...deleteKeys !== void 0 ? { deleteKeys } : {}
84
+ };
85
+ };
86
+ const resolvePositiveNoteId = (value) => {
87
+ const noteId = Number(value);
88
+ if (!Number.isInteger(noteId) || noteId <= 0) {
89
+ throw createAppError(400, "INVALID_NOTE_ID", "A valid note id is required.");
90
+ }
91
+ return noteId;
92
+ };
93
+ const isNonNegativeInteger = (value) => {
94
+ return typeof value === "number" && Number.isInteger(value) && value >= 0;
95
+ };
96
+ const isPositiveInteger = (value) => {
97
+ return typeof value === "number" && Number.isInteger(value) && value > 0;
98
+ };
99
+ const resolveMarkdownWritePolicy = (value) => {
100
+ if (value === void 0) {
101
+ return void 0;
102
+ }
103
+ if (!isRecord(value)) {
104
+ throw createAppError(400, "INVALID_MARKDOWN_POLICY", "Markdown write policy must be an object.");
105
+ }
106
+ const policy = {};
107
+ if (value.allowNoop !== void 0) {
108
+ if (typeof value.allowNoop !== "boolean") {
109
+ throw createAppError(400, "INVALID_MARKDOWN_POLICY", "allowNoop must be a boolean.");
110
+ }
111
+ policy.allowNoop = value.allowNoop;
112
+ }
113
+ if (value.maxChangedChars !== void 0) {
114
+ if (!isNonNegativeInteger(value.maxChangedChars)) {
115
+ throw createAppError(400, "INVALID_MARKDOWN_POLICY", "maxChangedChars must be a non-negative integer.");
116
+ }
117
+ policy.maxChangedChars = value.maxChangedChars;
118
+ }
119
+ if (value.maxChangedLines !== void 0) {
120
+ if (!isNonNegativeInteger(value.maxChangedLines)) {
121
+ throw createAppError(400, "INVALID_MARKDOWN_POLICY", "maxChangedLines must be a non-negative integer.");
122
+ }
123
+ policy.maxChangedLines = value.maxChangedLines;
124
+ }
125
+ if (value.preserveTags !== void 0) {
126
+ if (!PRESERVATION_POLICIES.has(value.preserveTags)) {
127
+ throw createAppError(400, "INVALID_MARKDOWN_POLICY", "preserveTags must be boolean or warn.");
128
+ }
129
+ policy.preserveTags = value.preserveTags;
130
+ }
131
+ if (value.preserveReferences !== void 0) {
132
+ if (!PRESERVATION_POLICIES.has(value.preserveReferences)) {
133
+ throw createAppError(400, "INVALID_MARKDOWN_POLICY", "preserveReferences must be boolean or warn.");
134
+ }
135
+ policy.preserveReferences = value.preserveReferences;
136
+ }
137
+ return policy;
138
+ };
139
+ const resolvePatchSelector = (value) => {
140
+ if (!isRecord(value)) {
141
+ throw createAppError(400, "INVALID_PATCH_SELECTOR", "Patch selector must be an object.");
142
+ }
143
+ if (value.type === "exact_text") {
144
+ if (typeof value.text !== "string") {
145
+ throw createAppError(400, "INVALID_PATCH_SELECTOR", "Exact text selector requires text.");
146
+ }
147
+ return {
148
+ type: "exact_text",
149
+ text: value.text,
150
+ ...value.before !== void 0 ? {
151
+ before: resolveOptionalString(
152
+ value.before,
153
+ "INVALID_PATCH_SELECTOR",
154
+ "Selector before must be a string."
155
+ )
156
+ } : {},
157
+ ...value.after !== void 0 ? {
158
+ after: resolveOptionalString(
159
+ value.after,
160
+ "INVALID_PATCH_SELECTOR",
161
+ "Selector after must be a string."
162
+ )
163
+ } : {}
164
+ };
165
+ }
166
+ if (value.type === "match_candidate") {
167
+ const { text, matchIndex, lineStart, matchSha256, surroundingHash, positionHint } = value;
168
+ if (typeof text !== "string" || !isNonNegativeInteger(matchIndex) || !isPositiveInteger(lineStart) || typeof matchSha256 !== "string" || typeof surroundingHash !== "string") {
169
+ throw createAppError(400, "INVALID_PATCH_SELECTOR", "Match candidate selector has invalid fields.");
170
+ }
171
+ if (positionHint !== void 0 && !POSITION_HINTS.has(String(positionHint))) {
172
+ throw createAppError(400, "INVALID_PATCH_SELECTOR", "positionHint must be first or last.");
173
+ }
174
+ return {
175
+ type: "match_candidate",
176
+ text,
177
+ matchIndex,
178
+ lineStart,
179
+ matchSha256,
180
+ surroundingHash,
181
+ ...positionHint ? { positionHint } : {}
182
+ };
183
+ }
184
+ throw createAppError(400, "INVALID_PATCH_SELECTOR", "Unsupported patch selector type.");
185
+ };
186
+ const resolvePatchOperation = (value) => {
187
+ if (!isRecord(value)) {
188
+ throw createAppError(400, "INVALID_PATCH_OPERATION", "Patch operation must be an object.");
189
+ }
190
+ if (value.type === "replace") {
191
+ if (typeof value.replacement !== "string") {
192
+ throw createAppError(400, "INVALID_PATCH_OPERATION", "Replace operation requires replacement.");
193
+ }
194
+ return {
195
+ type: "replace",
196
+ replacement: value.replacement
197
+ };
198
+ }
199
+ if (value.type === "insert_before" || value.type === "insert_after") {
200
+ if (typeof value.insertion !== "string") {
201
+ throw createAppError(400, "INVALID_PATCH_OPERATION", "Insert operation requires insertion.");
202
+ }
203
+ return {
204
+ type: value.type,
205
+ insertion: value.insertion
206
+ };
207
+ }
208
+ throw createAppError(400, "INVALID_PATCH_OPERATION", "Unsupported patch operation type.");
209
+ };
210
+ const resolveAppendPlacement = (value) => {
211
+ if (value === void 0) {
212
+ return void 0;
213
+ }
214
+ if (!isRecord(value)) {
215
+ throw createAppError(400, "INVALID_APPEND_PLACEMENT", "Append placement must be an object.");
216
+ }
217
+ if (value.type === "end") {
218
+ return { type: "end" };
219
+ }
220
+ if (value.type === "after_heading") {
221
+ if (typeof value.heading !== "string") {
222
+ throw createAppError(400, "INVALID_APPEND_PLACEMENT", "after_heading placement requires heading.");
223
+ }
224
+ const { heading, level } = value;
225
+ if (typeof heading !== "string") {
226
+ throw createAppError(400, "INVALID_APPEND_PLACEMENT", "after_heading placement requires heading.");
227
+ }
228
+ if (level !== void 0 && (typeof level !== "number" || !Number.isInteger(level) || level < 1 || level > 6)) {
229
+ throw createAppError(400, "INVALID_APPEND_PLACEMENT", "Heading level must be an integer from 1 to 6.");
230
+ }
231
+ return {
232
+ type: "after_heading",
233
+ heading,
234
+ ...level !== void 0 ? { level } : {}
235
+ };
236
+ }
237
+ throw createAppError(400, "INVALID_APPEND_PLACEMENT", "Unsupported append placement type.");
238
+ };
239
+ const resolveSeparator = (value) => {
240
+ if (value === void 0) {
241
+ return void 0;
242
+ }
243
+ if (value === "\n" || value === "\n\n") {
244
+ return value;
245
+ }
246
+ throw createAppError(400, "INVALID_SEPARATOR", 'Separator must be "\\n" or "\\n\\n".');
247
+ };
20
248
  const createMcpCreateNoteHandler = (createNote = createNoteFromMarkdown, emitEvent = emitServerEvent) => {
21
249
  return async (req, res) => {
22
250
  const { title, markdown, layout } = req.body ?? {};
@@ -107,6 +335,167 @@ const createMcpUpdateNoteHandler = (updateNote = updateNoteFromMarkdown, emitEve
107
335
  }
108
336
  };
109
337
  };
338
+ const createMcpPatchNoteMarkdownHandler = (patchMarkdown = patchNoteMarkdown, emitEvent = emitServerEvent) => {
339
+ return async (req, res) => {
340
+ const { id, expectedUpdatedAt, baseMarkdownSha256, intent, selector, operation, policy, dryRun } = req.body ?? {};
341
+ const noteId = resolvePositiveNoteId(id);
342
+ const resolvedExpectedUpdatedAt = resolveOptionalString(
343
+ expectedUpdatedAt,
344
+ "INVALID_NOTE_VERSION",
345
+ "expectedUpdatedAt must be a string."
346
+ );
347
+ const resolvedBaseMarkdownSha256 = resolveOptionalString(
348
+ baseMarkdownSha256,
349
+ "INVALID_MARKDOWN_HASH",
350
+ "baseMarkdownSha256 must be a string."
351
+ );
352
+ const resolvedDryRun = resolveOptionalBoolean(dryRun, "INVALID_DRY_RUN", "dryRun must be a boolean.");
353
+ if (typeof intent !== "string") {
354
+ throw createAppError(400, "INVALID_PATCH_INTENT", "Patch intent must be a string.");
355
+ }
356
+ const result = await patchMarkdown({
357
+ id: noteId,
358
+ expectedUpdatedAt: resolvedExpectedUpdatedAt,
359
+ baseMarkdownSha256: resolvedBaseMarkdownSha256,
360
+ intent,
361
+ selector: resolvePatchSelector(selector),
362
+ operation: resolvePatchOperation(operation),
363
+ policy: resolveMarkdownWritePolicy(policy),
364
+ dryRun: resolvedDryRun
365
+ });
366
+ if (result.status === "applied") {
367
+ emitEvent({
368
+ type: "mcp.note.updated",
369
+ source: "mcp",
370
+ noteId: result.note.id,
371
+ updatedAt: result.note.updatedAt
372
+ });
373
+ }
374
+ res.status(200).json(result).end();
375
+ };
376
+ };
377
+ const createMcpAppendNoteMarkdownHandler = (appendMarkdown = appendNoteMarkdown, emitEvent = emitServerEvent) => {
378
+ return async (req, res) => {
379
+ const { id, expectedUpdatedAt, baseMarkdownSha256, intent, insertion, placement, separator, policy, dryRun } = req.body ?? {};
380
+ const noteId = resolvePositiveNoteId(id);
381
+ const resolvedExpectedUpdatedAt = resolveOptionalString(
382
+ expectedUpdatedAt,
383
+ "INVALID_NOTE_VERSION",
384
+ "expectedUpdatedAt must be a string."
385
+ );
386
+ const resolvedBaseMarkdownSha256 = resolveOptionalString(
387
+ baseMarkdownSha256,
388
+ "INVALID_MARKDOWN_HASH",
389
+ "baseMarkdownSha256 must be a string."
390
+ );
391
+ const resolvedDryRun = resolveOptionalBoolean(dryRun, "INVALID_DRY_RUN", "dryRun must be a boolean.");
392
+ if (typeof intent !== "string") {
393
+ throw createAppError(400, "INVALID_APPEND_INTENT", "Append intent must be a string.");
394
+ }
395
+ if (typeof insertion !== "string") {
396
+ throw createAppError(400, "INVALID_APPEND_INSERTION", "Append insertion must be a string.");
397
+ }
398
+ const result = await appendMarkdown({
399
+ id: noteId,
400
+ expectedUpdatedAt: resolvedExpectedUpdatedAt,
401
+ baseMarkdownSha256: resolvedBaseMarkdownSha256,
402
+ intent,
403
+ insertion,
404
+ placement: resolveAppendPlacement(placement),
405
+ separator: resolveSeparator(separator),
406
+ policy: resolveMarkdownWritePolicy(policy),
407
+ dryRun: resolvedDryRun
408
+ });
409
+ if (result.status === "applied") {
410
+ emitEvent({
411
+ type: "mcp.note.updated",
412
+ source: "mcp",
413
+ noteId: result.note.id,
414
+ updatedAt: result.note.updatedAt
415
+ });
416
+ }
417
+ res.status(200).json(result).end();
418
+ };
419
+ };
420
+ const createMcpReplaceNoteMarkdownHandler = (replaceMarkdown = replaceNoteMarkdown, emitEvent = emitServerEvent) => {
421
+ return async (req, res) => {
422
+ const { id, expectedUpdatedAt, baseMarkdownSha256, intent, replacement, policy, dryRun } = req.body ?? {};
423
+ const noteId = resolvePositiveNoteId(id);
424
+ const resolvedExpectedUpdatedAt = resolveOptionalString(
425
+ expectedUpdatedAt,
426
+ "INVALID_NOTE_VERSION",
427
+ "expectedUpdatedAt must be a string."
428
+ );
429
+ const resolvedBaseMarkdownSha256 = resolveOptionalString(
430
+ baseMarkdownSha256,
431
+ "INVALID_MARKDOWN_HASH",
432
+ "baseMarkdownSha256 must be a string."
433
+ );
434
+ const resolvedDryRun = resolveOptionalBoolean(dryRun, "INVALID_DRY_RUN", "dryRun must be a boolean.");
435
+ if (typeof intent !== "string") {
436
+ throw createAppError(400, "INVALID_REPLACE_INTENT", "Replace intent must be a string.");
437
+ }
438
+ if (typeof replacement !== "string") {
439
+ throw createAppError(400, "INVALID_REPLACE_MARKDOWN", "Replacement markdown must be a string.");
440
+ }
441
+ const result = await replaceMarkdown({
442
+ id: noteId,
443
+ expectedUpdatedAt: resolvedExpectedUpdatedAt,
444
+ baseMarkdownSha256: resolvedBaseMarkdownSha256,
445
+ intent,
446
+ replacement,
447
+ policy: resolveMarkdownWritePolicy(policy),
448
+ dryRun: resolvedDryRun
449
+ });
450
+ if (result.status === "applied") {
451
+ emitEvent({
452
+ type: "mcp.note.updated",
453
+ source: "mcp",
454
+ noteId: result.note.id,
455
+ updatedAt: result.note.updatedAt
456
+ });
457
+ }
458
+ res.status(200).json(result).end();
459
+ };
460
+ };
461
+ const createMcpUpdateNoteMetadataHandler = (updateMetadata = updateNoteMetadata, emitEvent = emitServerEvent) => {
462
+ return async (req, res) => {
463
+ const { id, expectedUpdatedAt, title, layout, properties, dryRun } = req.body ?? {};
464
+ const noteId = resolvePositiveNoteId(id);
465
+ const resolvedLayout = resolveNoteLayout(layout);
466
+ const resolvedProperties = resolveMetadataPropertyPatch(properties);
467
+ const resolvedDryRun = resolveOptionalBoolean(dryRun, "INVALID_DRY_RUN", "dryRun must be a boolean.");
468
+ if (typeof expectedUpdatedAt !== "string") {
469
+ throw createAppError(400, "INVALID_NOTE_VERSION", "expectedUpdatedAt must be a string.");
470
+ }
471
+ if (title !== void 0 && typeof title !== "string") {
472
+ throw createAppError(400, "INVALID_NOTE_TITLE", "Note title must be a string.");
473
+ }
474
+ if (layout !== void 0 && resolvedLayout === null) {
475
+ throw createAppError(400, "INVALID_NOTE_LAYOUT", "Note layout must be one of narrow, wide, or full.");
476
+ }
477
+ if (title === void 0 && layout === void 0 && resolvedProperties === void 0) {
478
+ throw createAppError(400, "INVALID_NOTE_INPUT", "At least one metadata field must be provided.");
479
+ }
480
+ const result = await updateMetadata({
481
+ id: noteId,
482
+ expectedUpdatedAt,
483
+ ...title !== void 0 ? { title } : {},
484
+ ...resolvedLayout ? { layout: resolvedLayout } : {},
485
+ ...resolvedProperties !== void 0 ? { properties: resolvedProperties } : {},
486
+ dryRun: resolvedDryRun
487
+ });
488
+ if (result.status === "applied") {
489
+ emitEvent({
490
+ type: "mcp.note.updated",
491
+ source: "mcp",
492
+ noteId: result.note.id,
493
+ updatedAt: result.note.updatedAt
494
+ });
495
+ }
496
+ res.status(200).json(result).end();
497
+ };
498
+ };
110
499
  const createMcpDeleteNoteHandler = (deleteNote = deleteNoteById, emitEvent = emitServerEvent) => {
111
500
  return async (req, res) => {
112
501
  const id = Number(req.body?.id);
@@ -129,8 +518,12 @@ const createMcpDeleteNoteHandler = (deleteNote = deleteNoteById, emitEvent = emi
129
518
  };
130
519
  };
131
520
  export {
521
+ createMcpAppendNoteMarkdownHandler,
132
522
  createMcpCreateNoteHandler,
133
523
  createMcpDeleteNoteHandler,
134
- createMcpUpdateNoteHandler
524
+ createMcpPatchNoteMarkdownHandler,
525
+ createMcpReplaceNoteMarkdownHandler,
526
+ createMcpUpdateNoteHandler,
527
+ createMcpUpdateNoteMetadataHandler
135
528
  };
136
529
  //# sourceMappingURL=mcp.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/features/note/http/mcp.ts"],"sourcesContent":["import {\n createNoteFromMarkdown,\n InvalidNoteAuthoringInputError,\n updateNoteFromMarkdown,\n} from '~/features/note/services/authoring.js';\nimport { deleteNoteById } from '~/features/note/services/cleanup.js';\nimport { MCP_SNAPSHOT_META } from '~/features/note/services/snapshot.js';\nimport type { NoteLayout } from '~/models.js';\nimport { createAppError } from '~/modules/error-handler.js';\nimport { emitServerEvent, type ServerEventInput } from '~/modules/server-events.js';\nimport type { Controller } from '~/types/index.js';\n\nconst NOTE_LAYOUTS = new Set<NoteLayout>(['narrow', 'wide', 'full']);\n\nconst resolveNoteLayout = (value: unknown): NoteLayout | null | undefined => {\n if (value === undefined) {\n return undefined;\n }\n\n if (typeof value === 'string' && NOTE_LAYOUTS.has(value as NoteLayout)) {\n return value as NoteLayout;\n }\n\n return null;\n};\n\ntype EmitServerEvent = (event: ServerEventInput) => unknown;\n\nexport const createMcpCreateNoteHandler = (\n createNote = createNoteFromMarkdown,\n emitEvent: EmitServerEvent = emitServerEvent,\n): Controller => {\n return async (req, res) => {\n const { title, markdown, layout } = req.body ?? {};\n const resolvedLayout = resolveNoteLayout(layout);\n\n if (typeof title !== 'string') {\n throw createAppError(400, 'INVALID_NOTE_TITLE', 'A note title is required.');\n }\n\n if (markdown !== undefined && typeof markdown !== 'string') {\n throw createAppError(400, 'INVALID_NOTE_MARKDOWN', 'Note markdown must be a string.');\n }\n\n if (layout !== undefined && resolvedLayout === null) {\n throw createAppError(400, 'INVALID_NOTE_LAYOUT', 'Note layout must be one of narrow, wide, or full.');\n }\n\n try {\n const note = await createNote({\n title,\n ...(markdown !== undefined ? { markdown } : {}),\n ...(resolvedLayout ? { layout: resolvedLayout } : {}),\n });\n\n emitEvent({\n type: 'mcp.note.created',\n source: 'mcp',\n noteId: note.id,\n updatedAt: note.updatedAt,\n });\n\n res.status(200)\n .json({\n created: true,\n note,\n })\n .end();\n } catch (error) {\n if (error instanceof InvalidNoteAuthoringInputError) {\n throw createAppError(400, 'INVALID_NOTE_INPUT', error.message);\n }\n\n throw error;\n }\n };\n};\n\nexport const createMcpUpdateNoteHandler = (\n updateNote = updateNoteFromMarkdown,\n emitEvent: EmitServerEvent = emitServerEvent,\n): Controller => {\n return async (req, res) => {\n const { id, title, markdown, layout, editSessionId } = req.body ?? {};\n const noteId = Number(id);\n const resolvedLayout = resolveNoteLayout(layout);\n\n if (!Number.isInteger(noteId) || noteId <= 0) {\n throw createAppError(400, 'INVALID_NOTE_ID', 'A valid note id is required.');\n }\n\n if (title !== undefined && typeof title !== 'string') {\n throw createAppError(400, 'INVALID_NOTE_TITLE', 'Note title must be a string.');\n }\n\n if (markdown !== undefined && typeof markdown !== 'string') {\n throw createAppError(400, 'INVALID_NOTE_MARKDOWN', 'Note markdown must be a string.');\n }\n\n if (layout !== undefined && resolvedLayout === null) {\n throw createAppError(400, 'INVALID_NOTE_LAYOUT', 'Note layout must be one of narrow, wide, or full.');\n }\n\n if (editSessionId !== undefined && typeof editSessionId !== 'string') {\n throw createAppError(400, 'INVALID_EDIT_SESSION_ID', 'Edit session id must be a string.');\n }\n\n if (title === undefined && markdown === undefined && layout === undefined) {\n throw createAppError(400, 'INVALID_NOTE_INPUT', 'At least one note field must be provided for update.');\n }\n\n try {\n const note = await updateNote({\n id: noteId,\n ...(title !== undefined ? { title } : {}),\n ...(markdown !== undefined ? { markdown } : {}),\n ...(resolvedLayout ? { layout: resolvedLayout } : {}),\n ...(editSessionId !== undefined ? { editSessionId } : {}),\n snapshotMeta: MCP_SNAPSHOT_META,\n });\n\n if (!note) {\n throw createAppError(404, 'NOTE_NOT_FOUND', 'The requested note was not found.');\n }\n\n emitEvent({\n type: 'mcp.note.updated',\n source: 'mcp',\n noteId: note.id,\n updatedAt: note.updatedAt,\n });\n\n res.status(200)\n .json({\n updated: true,\n note,\n })\n .end();\n } catch (error) {\n if (error instanceof InvalidNoteAuthoringInputError) {\n throw createAppError(400, 'INVALID_NOTE_INPUT', error.message);\n }\n\n throw error;\n }\n };\n};\n\nexport const createMcpDeleteNoteHandler = (\n deleteNote = deleteNoteById,\n emitEvent: EmitServerEvent = emitServerEvent,\n): Controller => {\n return async (req, res) => {\n const id = Number(req.body?.id);\n\n if (!Number.isInteger(id) || id <= 0) {\n throw createAppError(400, 'INVALID_NOTE_ID', 'A valid note id is required.');\n }\n\n const deletedNote = await deleteNote(id);\n\n if (!deletedNote) {\n throw createAppError(404, 'NOTE_NOT_FOUND', 'The requested note was not found.');\n }\n\n emitEvent({\n type: 'mcp.note.deleted',\n source: 'mcp',\n noteId: deletedNote.id,\n });\n\n res.status(200)\n .json({\n deleted: true,\n note: deletedNote,\n })\n .end();\n };\n};\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../../src/features/note/http/mcp.ts"],"sourcesContent":["import {\n createNoteFromMarkdown,\n InvalidNoteAuthoringInputError,\n updateNoteFromMarkdown,\n} from '~/features/note/services/authoring.js';\nimport { deleteNoteById } from '~/features/note/services/cleanup.js';\nimport {\n appendNoteMarkdown,\n patchNoteMarkdown,\n replaceNoteMarkdown,\n updateNoteMetadata,\n} from '~/features/note/services/markdown-intent-write.js';\nimport type {\n MarkdownAppendPlacement,\n MarkdownChangePolicy,\n MarkdownPatchOperation,\n MarkdownPatchSelector,\n} from '~/features/note/services/markdown-patch.js';\nimport type { NotePropertiesByKeyPatchInput } from '~/features/note/services/properties.js';\nimport { MCP_SNAPSHOT_META } from '~/features/note/services/snapshot.js';\nimport type { NoteLayout } from '~/models.js';\nimport { createAppError } from '~/modules/error-handler.js';\nimport { emitServerEvent, type ServerEventInput } from '~/modules/server-events.js';\nimport type { Controller } from '~/types/index.js';\n\nconst NOTE_LAYOUTS = new Set<NoteLayout>(['narrow', 'wide', 'full']);\n\nconst POSITION_HINTS = new Set(['first', 'last']);\nconst PRESERVATION_POLICIES = new Set<unknown>([true, false, 'warn']);\n\nconst isRecord = (value: unknown): value is Record<string, unknown> => {\n return typeof value === 'object' && value !== null;\n};\n\nconst resolveNoteLayout = (value: unknown): NoteLayout | null | undefined => {\n if (value === undefined) {\n return undefined;\n }\n\n if (typeof value === 'string' && NOTE_LAYOUTS.has(value as NoteLayout)) {\n return value as NoteLayout;\n }\n\n return null;\n};\n\nconst resolveOptionalString = (value: unknown, code: string, message: string) => {\n if (value === undefined) {\n return undefined;\n }\n\n if (typeof value === 'string') {\n return value;\n }\n\n throw createAppError(400, code, message);\n};\n\nconst resolveOptionalBoolean = (value: unknown, code: string, message: string) => {\n if (value === undefined) {\n return undefined;\n }\n\n if (typeof value === 'boolean') {\n return value;\n }\n\n throw createAppError(400, code, message);\n};\n\nconst resolveMetadataPropertyPatch = (value: unknown): NotePropertiesByKeyPatchInput | undefined => {\n if (value === undefined) {\n return undefined;\n }\n\n if (!isRecord(value)) {\n throw createAppError(400, 'INVALID_NOTE_PROPERTIES', 'Properties patch must be an object.');\n }\n\n const set =\n value.set === undefined\n ? undefined\n : Array.isArray(value.set)\n ? value.set.map((item) => {\n if (!isRecord(item) || typeof item.key !== 'string' || typeof item.value !== 'string') {\n throw createAppError(\n 400,\n 'INVALID_NOTE_PROPERTIES',\n 'Property set items must include string key and value fields.',\n );\n }\n\n return {\n key: item.key,\n value: item.value,\n };\n })\n : null;\n\n if (set === null) {\n throw createAppError(400, 'INVALID_NOTE_PROPERTIES', 'Property set must be an array.');\n }\n\n const deleteKeys =\n value.deleteKeys === undefined\n ? undefined\n : Array.isArray(value.deleteKeys)\n ? value.deleteKeys.map((key) => {\n if (typeof key !== 'string') {\n throw createAppError(400, 'INVALID_NOTE_PROPERTIES', 'Property deleteKeys must be strings.');\n }\n\n return key;\n })\n : null;\n\n if (deleteKeys === null) {\n throw createAppError(400, 'INVALID_NOTE_PROPERTIES', 'Property deleteKeys must be an array.');\n }\n\n return {\n ...(set !== undefined ? { set } : {}),\n ...(deleteKeys !== undefined ? { deleteKeys } : {}),\n };\n};\n\nconst resolvePositiveNoteId = (value: unknown) => {\n const noteId = Number(value);\n\n if (!Number.isInteger(noteId) || noteId <= 0) {\n throw createAppError(400, 'INVALID_NOTE_ID', 'A valid note id is required.');\n }\n\n return noteId;\n};\n\nconst isNonNegativeInteger = (value: unknown): value is number => {\n return typeof value === 'number' && Number.isInteger(value) && value >= 0;\n};\n\nconst isPositiveInteger = (value: unknown): value is number => {\n return typeof value === 'number' && Number.isInteger(value) && value > 0;\n};\n\nconst resolveMarkdownWritePolicy = (value: unknown): MarkdownChangePolicy | undefined => {\n if (value === undefined) {\n return undefined;\n }\n\n if (!isRecord(value)) {\n throw createAppError(400, 'INVALID_MARKDOWN_POLICY', 'Markdown write policy must be an object.');\n }\n\n const policy: MarkdownChangePolicy = {};\n\n if (value.allowNoop !== undefined) {\n if (typeof value.allowNoop !== 'boolean') {\n throw createAppError(400, 'INVALID_MARKDOWN_POLICY', 'allowNoop must be a boolean.');\n }\n policy.allowNoop = value.allowNoop;\n }\n\n if (value.maxChangedChars !== undefined) {\n if (!isNonNegativeInteger(value.maxChangedChars)) {\n throw createAppError(400, 'INVALID_MARKDOWN_POLICY', 'maxChangedChars must be a non-negative integer.');\n }\n policy.maxChangedChars = value.maxChangedChars;\n }\n\n if (value.maxChangedLines !== undefined) {\n if (!isNonNegativeInteger(value.maxChangedLines)) {\n throw createAppError(400, 'INVALID_MARKDOWN_POLICY', 'maxChangedLines must be a non-negative integer.');\n }\n policy.maxChangedLines = value.maxChangedLines;\n }\n\n if (value.preserveTags !== undefined) {\n if (!PRESERVATION_POLICIES.has(value.preserveTags)) {\n throw createAppError(400, 'INVALID_MARKDOWN_POLICY', 'preserveTags must be boolean or warn.');\n }\n policy.preserveTags = value.preserveTags as MarkdownChangePolicy['preserveTags'];\n }\n\n if (value.preserveReferences !== undefined) {\n if (!PRESERVATION_POLICIES.has(value.preserveReferences)) {\n throw createAppError(400, 'INVALID_MARKDOWN_POLICY', 'preserveReferences must be boolean or warn.');\n }\n policy.preserveReferences = value.preserveReferences as MarkdownChangePolicy['preserveReferences'];\n }\n\n return policy;\n};\n\nconst resolvePatchSelector = (value: unknown): MarkdownPatchSelector => {\n if (!isRecord(value)) {\n throw createAppError(400, 'INVALID_PATCH_SELECTOR', 'Patch selector must be an object.');\n }\n\n if (value.type === 'exact_text') {\n if (typeof value.text !== 'string') {\n throw createAppError(400, 'INVALID_PATCH_SELECTOR', 'Exact text selector requires text.');\n }\n\n return {\n type: 'exact_text',\n text: value.text,\n ...(value.before !== undefined\n ? {\n before: resolveOptionalString(\n value.before,\n 'INVALID_PATCH_SELECTOR',\n 'Selector before must be a string.',\n ),\n }\n : {}),\n ...(value.after !== undefined\n ? {\n after: resolveOptionalString(\n value.after,\n 'INVALID_PATCH_SELECTOR',\n 'Selector after must be a string.',\n ),\n }\n : {}),\n };\n }\n\n if (value.type === 'match_candidate') {\n const { text, matchIndex, lineStart, matchSha256, surroundingHash, positionHint } = value;\n\n if (\n typeof text !== 'string' ||\n !isNonNegativeInteger(matchIndex) ||\n !isPositiveInteger(lineStart) ||\n typeof matchSha256 !== 'string' ||\n typeof surroundingHash !== 'string'\n ) {\n throw createAppError(400, 'INVALID_PATCH_SELECTOR', 'Match candidate selector has invalid fields.');\n }\n\n if (positionHint !== undefined && !POSITION_HINTS.has(String(positionHint))) {\n throw createAppError(400, 'INVALID_PATCH_SELECTOR', 'positionHint must be first or last.');\n }\n\n return {\n type: 'match_candidate',\n text,\n matchIndex,\n lineStart,\n matchSha256,\n surroundingHash,\n ...(positionHint ? { positionHint: positionHint as 'first' | 'last' } : {}),\n };\n }\n\n throw createAppError(400, 'INVALID_PATCH_SELECTOR', 'Unsupported patch selector type.');\n};\n\nconst resolvePatchOperation = (value: unknown): MarkdownPatchOperation => {\n if (!isRecord(value)) {\n throw createAppError(400, 'INVALID_PATCH_OPERATION', 'Patch operation must be an object.');\n }\n\n if (value.type === 'replace') {\n if (typeof value.replacement !== 'string') {\n throw createAppError(400, 'INVALID_PATCH_OPERATION', 'Replace operation requires replacement.');\n }\n\n return {\n type: 'replace',\n replacement: value.replacement,\n };\n }\n\n if (value.type === 'insert_before' || value.type === 'insert_after') {\n if (typeof value.insertion !== 'string') {\n throw createAppError(400, 'INVALID_PATCH_OPERATION', 'Insert operation requires insertion.');\n }\n\n return {\n type: value.type,\n insertion: value.insertion,\n };\n }\n\n throw createAppError(400, 'INVALID_PATCH_OPERATION', 'Unsupported patch operation type.');\n};\n\nconst resolveAppendPlacement = (value: unknown): MarkdownAppendPlacement | undefined => {\n if (value === undefined) {\n return undefined;\n }\n\n if (!isRecord(value)) {\n throw createAppError(400, 'INVALID_APPEND_PLACEMENT', 'Append placement must be an object.');\n }\n\n if (value.type === 'end') {\n return { type: 'end' };\n }\n\n if (value.type === 'after_heading') {\n if (typeof value.heading !== 'string') {\n throw createAppError(400, 'INVALID_APPEND_PLACEMENT', 'after_heading placement requires heading.');\n }\n\n const { heading, level } = value;\n\n if (typeof heading !== 'string') {\n throw createAppError(400, 'INVALID_APPEND_PLACEMENT', 'after_heading placement requires heading.');\n }\n\n if (level !== undefined && (typeof level !== 'number' || !Number.isInteger(level) || level < 1 || level > 6)) {\n throw createAppError(400, 'INVALID_APPEND_PLACEMENT', 'Heading level must be an integer from 1 to 6.');\n }\n\n return {\n type: 'after_heading',\n heading,\n ...(level !== undefined ? { level } : {}),\n };\n }\n\n throw createAppError(400, 'INVALID_APPEND_PLACEMENT', 'Unsupported append placement type.');\n};\n\nconst resolveSeparator = (value: unknown) => {\n if (value === undefined) {\n return undefined;\n }\n\n if (value === '\\n' || value === '\\n\\n') {\n return value;\n }\n\n throw createAppError(400, 'INVALID_SEPARATOR', 'Separator must be \"\\\\n\" or \"\\\\n\\\\n\".');\n};\n\ntype EmitServerEvent = (event: ServerEventInput) => unknown;\n\nexport const createMcpCreateNoteHandler = (\n createNote = createNoteFromMarkdown,\n emitEvent: EmitServerEvent = emitServerEvent,\n): Controller => {\n return async (req, res) => {\n const { title, markdown, layout } = req.body ?? {};\n const resolvedLayout = resolveNoteLayout(layout);\n\n if (typeof title !== 'string') {\n throw createAppError(400, 'INVALID_NOTE_TITLE', 'A note title is required.');\n }\n\n if (markdown !== undefined && typeof markdown !== 'string') {\n throw createAppError(400, 'INVALID_NOTE_MARKDOWN', 'Note markdown must be a string.');\n }\n\n if (layout !== undefined && resolvedLayout === null) {\n throw createAppError(400, 'INVALID_NOTE_LAYOUT', 'Note layout must be one of narrow, wide, or full.');\n }\n\n try {\n const note = await createNote({\n title,\n ...(markdown !== undefined ? { markdown } : {}),\n ...(resolvedLayout ? { layout: resolvedLayout } : {}),\n });\n\n emitEvent({\n type: 'mcp.note.created',\n source: 'mcp',\n noteId: note.id,\n updatedAt: note.updatedAt,\n });\n\n res.status(200)\n .json({\n created: true,\n note,\n })\n .end();\n } catch (error) {\n if (error instanceof InvalidNoteAuthoringInputError) {\n throw createAppError(400, 'INVALID_NOTE_INPUT', error.message);\n }\n\n throw error;\n }\n };\n};\n\nexport const createMcpUpdateNoteHandler = (\n updateNote = updateNoteFromMarkdown,\n emitEvent: EmitServerEvent = emitServerEvent,\n): Controller => {\n return async (req, res) => {\n const { id, title, markdown, layout, editSessionId } = req.body ?? {};\n const noteId = Number(id);\n const resolvedLayout = resolveNoteLayout(layout);\n\n if (!Number.isInteger(noteId) || noteId <= 0) {\n throw createAppError(400, 'INVALID_NOTE_ID', 'A valid note id is required.');\n }\n\n if (title !== undefined && typeof title !== 'string') {\n throw createAppError(400, 'INVALID_NOTE_TITLE', 'Note title must be a string.');\n }\n\n if (markdown !== undefined && typeof markdown !== 'string') {\n throw createAppError(400, 'INVALID_NOTE_MARKDOWN', 'Note markdown must be a string.');\n }\n\n if (layout !== undefined && resolvedLayout === null) {\n throw createAppError(400, 'INVALID_NOTE_LAYOUT', 'Note layout must be one of narrow, wide, or full.');\n }\n\n if (editSessionId !== undefined && typeof editSessionId !== 'string') {\n throw createAppError(400, 'INVALID_EDIT_SESSION_ID', 'Edit session id must be a string.');\n }\n\n if (title === undefined && markdown === undefined && layout === undefined) {\n throw createAppError(400, 'INVALID_NOTE_INPUT', 'At least one note field must be provided for update.');\n }\n\n try {\n const note = await updateNote({\n id: noteId,\n ...(title !== undefined ? { title } : {}),\n ...(markdown !== undefined ? { markdown } : {}),\n ...(resolvedLayout ? { layout: resolvedLayout } : {}),\n ...(editSessionId !== undefined ? { editSessionId } : {}),\n snapshotMeta: MCP_SNAPSHOT_META,\n });\n\n if (!note) {\n throw createAppError(404, 'NOTE_NOT_FOUND', 'The requested note was not found.');\n }\n\n emitEvent({\n type: 'mcp.note.updated',\n source: 'mcp',\n noteId: note.id,\n updatedAt: note.updatedAt,\n });\n\n res.status(200)\n .json({\n updated: true,\n note,\n })\n .end();\n } catch (error) {\n if (error instanceof InvalidNoteAuthoringInputError) {\n throw createAppError(400, 'INVALID_NOTE_INPUT', error.message);\n }\n\n throw error;\n }\n };\n};\n\nexport const createMcpPatchNoteMarkdownHandler = (\n patchMarkdown = patchNoteMarkdown,\n emitEvent: EmitServerEvent = emitServerEvent,\n): Controller => {\n return async (req, res) => {\n const { id, expectedUpdatedAt, baseMarkdownSha256, intent, selector, operation, policy, dryRun } =\n req.body ?? {};\n const noteId = resolvePositiveNoteId(id);\n const resolvedExpectedUpdatedAt = resolveOptionalString(\n expectedUpdatedAt,\n 'INVALID_NOTE_VERSION',\n 'expectedUpdatedAt must be a string.',\n );\n const resolvedBaseMarkdownSha256 = resolveOptionalString(\n baseMarkdownSha256,\n 'INVALID_MARKDOWN_HASH',\n 'baseMarkdownSha256 must be a string.',\n );\n const resolvedDryRun = resolveOptionalBoolean(dryRun, 'INVALID_DRY_RUN', 'dryRun must be a boolean.');\n\n if (typeof intent !== 'string') {\n throw createAppError(400, 'INVALID_PATCH_INTENT', 'Patch intent must be a string.');\n }\n\n const result = await patchMarkdown({\n id: noteId,\n expectedUpdatedAt: resolvedExpectedUpdatedAt,\n baseMarkdownSha256: resolvedBaseMarkdownSha256,\n intent,\n selector: resolvePatchSelector(selector),\n operation: resolvePatchOperation(operation),\n policy: resolveMarkdownWritePolicy(policy),\n dryRun: resolvedDryRun,\n });\n\n if (result.status === 'applied') {\n emitEvent({\n type: 'mcp.note.updated',\n source: 'mcp',\n noteId: result.note.id,\n updatedAt: result.note.updatedAt,\n });\n }\n\n res.status(200).json(result).end();\n };\n};\n\nexport const createMcpAppendNoteMarkdownHandler = (\n appendMarkdown = appendNoteMarkdown,\n emitEvent: EmitServerEvent = emitServerEvent,\n): Controller => {\n return async (req, res) => {\n const { id, expectedUpdatedAt, baseMarkdownSha256, intent, insertion, placement, separator, policy, dryRun } =\n req.body ?? {};\n const noteId = resolvePositiveNoteId(id);\n const resolvedExpectedUpdatedAt = resolveOptionalString(\n expectedUpdatedAt,\n 'INVALID_NOTE_VERSION',\n 'expectedUpdatedAt must be a string.',\n );\n const resolvedBaseMarkdownSha256 = resolveOptionalString(\n baseMarkdownSha256,\n 'INVALID_MARKDOWN_HASH',\n 'baseMarkdownSha256 must be a string.',\n );\n const resolvedDryRun = resolveOptionalBoolean(dryRun, 'INVALID_DRY_RUN', 'dryRun must be a boolean.');\n\n if (typeof intent !== 'string') {\n throw createAppError(400, 'INVALID_APPEND_INTENT', 'Append intent must be a string.');\n }\n\n if (typeof insertion !== 'string') {\n throw createAppError(400, 'INVALID_APPEND_INSERTION', 'Append insertion must be a string.');\n }\n\n const result = await appendMarkdown({\n id: noteId,\n expectedUpdatedAt: resolvedExpectedUpdatedAt,\n baseMarkdownSha256: resolvedBaseMarkdownSha256,\n intent,\n insertion,\n placement: resolveAppendPlacement(placement),\n separator: resolveSeparator(separator),\n policy: resolveMarkdownWritePolicy(policy),\n dryRun: resolvedDryRun,\n });\n\n if (result.status === 'applied') {\n emitEvent({\n type: 'mcp.note.updated',\n source: 'mcp',\n noteId: result.note.id,\n updatedAt: result.note.updatedAt,\n });\n }\n\n res.status(200).json(result).end();\n };\n};\n\nexport const createMcpReplaceNoteMarkdownHandler = (\n replaceMarkdown = replaceNoteMarkdown,\n emitEvent: EmitServerEvent = emitServerEvent,\n): Controller => {\n return async (req, res) => {\n const { id, expectedUpdatedAt, baseMarkdownSha256, intent, replacement, policy, dryRun } = req.body ?? {};\n const noteId = resolvePositiveNoteId(id);\n const resolvedExpectedUpdatedAt = resolveOptionalString(\n expectedUpdatedAt,\n 'INVALID_NOTE_VERSION',\n 'expectedUpdatedAt must be a string.',\n );\n const resolvedBaseMarkdownSha256 = resolveOptionalString(\n baseMarkdownSha256,\n 'INVALID_MARKDOWN_HASH',\n 'baseMarkdownSha256 must be a string.',\n );\n const resolvedDryRun = resolveOptionalBoolean(dryRun, 'INVALID_DRY_RUN', 'dryRun must be a boolean.');\n\n if (typeof intent !== 'string') {\n throw createAppError(400, 'INVALID_REPLACE_INTENT', 'Replace intent must be a string.');\n }\n\n if (typeof replacement !== 'string') {\n throw createAppError(400, 'INVALID_REPLACE_MARKDOWN', 'Replacement markdown must be a string.');\n }\n\n const result = await replaceMarkdown({\n id: noteId,\n expectedUpdatedAt: resolvedExpectedUpdatedAt,\n baseMarkdownSha256: resolvedBaseMarkdownSha256,\n intent,\n replacement,\n policy: resolveMarkdownWritePolicy(policy),\n dryRun: resolvedDryRun,\n });\n\n if (result.status === 'applied') {\n emitEvent({\n type: 'mcp.note.updated',\n source: 'mcp',\n noteId: result.note.id,\n updatedAt: result.note.updatedAt,\n });\n }\n\n res.status(200).json(result).end();\n };\n};\n\nexport const createMcpUpdateNoteMetadataHandler = (\n updateMetadata = updateNoteMetadata,\n emitEvent: EmitServerEvent = emitServerEvent,\n): Controller => {\n return async (req, res) => {\n const { id, expectedUpdatedAt, title, layout, properties, dryRun } = req.body ?? {};\n const noteId = resolvePositiveNoteId(id);\n const resolvedLayout = resolveNoteLayout(layout);\n const resolvedProperties = resolveMetadataPropertyPatch(properties);\n const resolvedDryRun = resolveOptionalBoolean(dryRun, 'INVALID_DRY_RUN', 'dryRun must be a boolean.');\n\n if (typeof expectedUpdatedAt !== 'string') {\n throw createAppError(400, 'INVALID_NOTE_VERSION', 'expectedUpdatedAt must be a string.');\n }\n\n if (title !== undefined && typeof title !== 'string') {\n throw createAppError(400, 'INVALID_NOTE_TITLE', 'Note title must be a string.');\n }\n\n if (layout !== undefined && resolvedLayout === null) {\n throw createAppError(400, 'INVALID_NOTE_LAYOUT', 'Note layout must be one of narrow, wide, or full.');\n }\n\n if (title === undefined && layout === undefined && resolvedProperties === undefined) {\n throw createAppError(400, 'INVALID_NOTE_INPUT', 'At least one metadata field must be provided.');\n }\n\n const result = await updateMetadata({\n id: noteId,\n expectedUpdatedAt,\n ...(title !== undefined ? { title } : {}),\n ...(resolvedLayout ? { layout: resolvedLayout } : {}),\n ...(resolvedProperties !== undefined ? { properties: resolvedProperties } : {}),\n dryRun: resolvedDryRun,\n });\n\n if (result.status === 'applied') {\n emitEvent({\n type: 'mcp.note.updated',\n source: 'mcp',\n noteId: result.note.id,\n updatedAt: result.note.updatedAt,\n });\n }\n\n res.status(200).json(result).end();\n };\n};\n\nexport const createMcpDeleteNoteHandler = (\n deleteNote = deleteNoteById,\n emitEvent: EmitServerEvent = emitServerEvent,\n): Controller => {\n return async (req, res) => {\n const id = Number(req.body?.id);\n\n if (!Number.isInteger(id) || id <= 0) {\n throw createAppError(400, 'INVALID_NOTE_ID', 'A valid note id is required.');\n }\n\n const deletedNote = await deleteNote(id);\n\n if (!deletedNote) {\n throw createAppError(404, 'NOTE_NOT_FOUND', 'The requested note was not found.');\n }\n\n emitEvent({\n type: 'mcp.note.deleted',\n source: 'mcp',\n noteId: deletedNote.id,\n });\n\n res.status(200)\n .json({\n deleted: true,\n note: deletedNote,\n })\n .end();\n };\n};\n"],"mappings":"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","names":[]}