apple-notes-mcp 2.8.7 → 2.8.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/build/index.js CHANGED
@@ -2242,10 +2242,10 @@ var require_resolve = __commonJS({
2242
2242
  }
2243
2243
  return count;
2244
2244
  }
2245
- function getFullPath(resolver, id = "", normalize) {
2245
+ function getFullPath(resolver, id2 = "", normalize) {
2246
2246
  if (normalize !== false)
2247
- id = normalizeId(id);
2248
- const p = resolver.parse(id);
2247
+ id2 = normalizeId(id2);
2248
+ const p = resolver.parse(id2);
2249
2249
  return _getFullPath(resolver, p);
2250
2250
  }
2251
2251
  exports.getFullPath = getFullPath;
@@ -2255,13 +2255,13 @@ var require_resolve = __commonJS({
2255
2255
  }
2256
2256
  exports._getFullPath = _getFullPath;
2257
2257
  var TRAILING_SLASH_HASH = /#\/?$/;
2258
- function normalizeId(id) {
2259
- return id ? id.replace(TRAILING_SLASH_HASH, "") : "";
2258
+ function normalizeId(id2) {
2259
+ return id2 ? id2.replace(TRAILING_SLASH_HASH, "") : "";
2260
2260
  }
2261
2261
  exports.normalizeId = normalizeId;
2262
- function resolveUrl(resolver, baseId, id) {
2263
- id = normalizeId(id);
2264
- return resolver.resolve(baseId, id);
2262
+ function resolveUrl(resolver, baseId, id2) {
2263
+ id2 = normalizeId(id2);
2264
+ return resolver.resolve(baseId, id2);
2265
2265
  }
2266
2266
  exports.resolveUrl = resolveUrl;
2267
2267
  var ANCHOR = /^[a-z_][-a-z0-9._]*$/i;
@@ -3031,8 +3031,8 @@ var require_compile = __commonJS({
3031
3031
  if (Object.keys(root.schema).length > 0 && refPath === baseId) {
3032
3032
  return getJsonPointer.call(this, p, root);
3033
3033
  }
3034
- const id = (0, resolve_1.normalizeId)(refPath);
3035
- const schOrRef = this.refs[id] || this.schemas[id];
3034
+ const id2 = (0, resolve_1.normalizeId)(refPath);
3035
+ const schOrRef = this.refs[id2] || this.schemas[id2];
3036
3036
  if (typeof schOrRef == "string") {
3037
3037
  const sch = resolveSchema.call(this, root, schOrRef);
3038
3038
  if (typeof (sch === null || sch === void 0 ? void 0 : sch.schema) !== "object")
@@ -3043,7 +3043,7 @@ var require_compile = __commonJS({
3043
3043
  return;
3044
3044
  if (!schOrRef.validate)
3045
3045
  compileSchema.call(this, schOrRef);
3046
- if (id === (0, resolve_1.normalizeId)(ref)) {
3046
+ if (id2 === (0, resolve_1.normalizeId)(ref)) {
3047
3047
  const { schema } = schOrRef;
3048
3048
  const { schemaId } = this.opts;
3049
3049
  const schId = schema[schemaId];
@@ -4458,15 +4458,15 @@ var require_core = __commonJS({
4458
4458
  this.addSchema(sch, void 0, _meta, _validateSchema);
4459
4459
  return this;
4460
4460
  }
4461
- let id;
4461
+ let id2;
4462
4462
  if (typeof schema === "object") {
4463
4463
  const { schemaId } = this.opts;
4464
- id = schema[schemaId];
4465
- if (id !== void 0 && typeof id != "string") {
4464
+ id2 = schema[schemaId];
4465
+ if (id2 !== void 0 && typeof id2 != "string") {
4466
4466
  throw new Error(`schema ${schemaId} must be string`);
4467
4467
  }
4468
4468
  }
4469
- key = (0, resolve_1.normalizeId)(key || id);
4469
+ key = (0, resolve_1.normalizeId)(key || id2);
4470
4470
  this._checkUnique(key);
4471
4471
  this.schemas[key] = this._addSchema(schema, _meta, key, _validateSchema, true);
4472
4472
  return this;
@@ -4545,11 +4545,11 @@ var require_core = __commonJS({
4545
4545
  case "object": {
4546
4546
  const cacheKey = schemaKeyRef;
4547
4547
  this._cache.delete(cacheKey);
4548
- let id = schemaKeyRef[this.opts.schemaId];
4549
- if (id) {
4550
- id = (0, resolve_1.normalizeId)(id);
4551
- delete this.schemas[id];
4552
- delete this.refs[id];
4548
+ let id2 = schemaKeyRef[this.opts.schemaId];
4549
+ if (id2) {
4550
+ id2 = (0, resolve_1.normalizeId)(id2);
4551
+ delete this.schemas[id2];
4552
+ delete this.refs[id2];
4553
4553
  }
4554
4554
  return this;
4555
4555
  }
@@ -4656,10 +4656,10 @@ var require_core = __commonJS({
4656
4656
  }
4657
4657
  }
4658
4658
  _addSchema(schema, meta, baseId, validateSchema = this.opts.validateSchema, addSchema = this.opts.addUsedSchema) {
4659
- let id;
4659
+ let id2;
4660
4660
  const { schemaId } = this.opts;
4661
4661
  if (typeof schema == "object") {
4662
- id = schema[schemaId];
4662
+ id2 = schema[schemaId];
4663
4663
  } else {
4664
4664
  if (this.opts.jtd)
4665
4665
  throw new Error("schema must be object");
@@ -4669,7 +4669,7 @@ var require_core = __commonJS({
4669
4669
  let sch = this._cache.get(schema);
4670
4670
  if (sch !== void 0)
4671
4671
  return sch;
4672
- baseId = (0, resolve_1.normalizeId)(id || baseId);
4672
+ baseId = (0, resolve_1.normalizeId)(id2 || baseId);
4673
4673
  const localRefs = resolve_1.getSchemaRefs.call(this, schema, baseId);
4674
4674
  sch = new compile_1.SchemaEnv({ schema, schemaId, meta, baseId, localRefs });
4675
4675
  this._cache.set(sch.schema, sch);
@@ -4682,9 +4682,9 @@ var require_core = __commonJS({
4682
4682
  this.validateSchema(schema, true);
4683
4683
  return sch;
4684
4684
  }
4685
- _checkUnique(id) {
4686
- if (this.schemas[id] || this.refs[id]) {
4687
- throw new Error(`schema with key or id "${id}" already exists`);
4685
+ _checkUnique(id2) {
4686
+ if (this.schemas[id2] || this.refs[id2]) {
4687
+ throw new Error(`schema with key or id "${id2}" already exists`);
4688
4688
  }
4689
4689
  }
4690
4690
  _compileSchemaEnv(sch) {
@@ -7952,7 +7952,7 @@ var require_NodeUtils = __commonJS({
7952
7952
  };
7953
7953
  var ESCAPE_REGEXP = /[&<>\u00A0]/g;
7954
7954
  var ESCAPE_ATTR_REGEXP = /[&"<>\u00A0]/g;
7955
- function escape2(s) {
7955
+ function escape3(s) {
7956
7956
  if (!ESCAPE_REGEXP.test(s)) {
7957
7957
  return s;
7958
7958
  }
@@ -8059,7 +8059,7 @@ var require_NodeUtils = __commonJS({
8059
8059
  if (hasRawContent[parenttag] || parenttag === "NOSCRIPT" && parent.ownerDocument._scripting_enabled) {
8060
8060
  s += kid.data;
8061
8061
  } else {
8062
- s += escape2(kid.data);
8062
+ s += escape3(kid.data);
8063
8063
  }
8064
8064
  break;
8065
8065
  case 8:
@@ -9922,13 +9922,13 @@ var require_select = __commonJS({
9922
9922
  return results;
9923
9923
  };
9924
9924
  module.exports = exports = function(sel, context) {
9925
- var id, r;
9925
+ var id2, r;
9926
9926
  if (context.nodeType !== 11 && sel.indexOf(" ") === -1) {
9927
9927
  if (sel[0] === "#" && context.rooted && /^#[A-Z_][-A-Z0-9_]*$/i.test(sel)) {
9928
9928
  if (context.doc._hasMultipleElementsWithId) {
9929
- id = sel.substring(1);
9930
- if (!context.doc._hasMultipleElementsWithId(id)) {
9931
- r = context.doc.getElementById(id);
9929
+ id2 = sel.substring(1);
9930
+ if (!context.doc._hasMultipleElementsWithId(id2)) {
9931
+ r = context.doc.getElementById(id2);
9932
9932
  return r ? [r] : [];
9933
9933
  }
9934
9934
  }
@@ -11110,12 +11110,12 @@ var require_Element = __commonJS({
11110
11110
  if (c.nodeType === Node.ELEMENT_NODE) {
11111
11111
  this[this.childrenByNumber.length] = c;
11112
11112
  this.childrenByNumber.push(c);
11113
- var id = c.getAttribute("id");
11114
- if (id && !this.childrenByName[id])
11115
- this.childrenByName[id] = c;
11113
+ var id2 = c.getAttribute("id");
11114
+ if (id2 && !this.childrenByName[id2])
11115
+ this.childrenByName[id2] = c;
11116
11116
  var name = c.getAttribute("name");
11117
11117
  if (name && this.element.namespaceURI === NAMESPACE.HTML && namedElts.test(this.element.localName) && !this.childrenByName[name])
11118
- this.childrenByName[id] = c;
11118
+ this.childrenByName[id2] = c;
11119
11119
  }
11120
11120
  }
11121
11121
  }
@@ -14845,16 +14845,16 @@ var require_Document = __commonJS({
14845
14845
  this._updateDocTypeElement();
14846
14846
  return child;
14847
14847
  } },
14848
- getElementById: { value: function(id) {
14849
- var n = this.byId[id];
14848
+ getElementById: { value: function(id2) {
14849
+ var n = this.byId[id2];
14850
14850
  if (!n) return null;
14851
14851
  if (n instanceof MultiId) {
14852
14852
  return n.getFirst();
14853
14853
  }
14854
14854
  return n;
14855
14855
  } },
14856
- _hasMultipleElementsWithId: { value: function(id) {
14857
- return this.byId[id] instanceof MultiId;
14856
+ _hasMultipleElementsWithId: { value: function(id2) {
14857
+ return this.byId[id2] instanceof MultiId;
14858
14858
  } },
14859
14859
  // Just copy this method from the Element prototype
14860
14860
  getElementsByName: { value: Element.prototype.getElementsByName },
@@ -15106,29 +15106,29 @@ var require_Document = __commonJS({
15106
15106
  }
15107
15107
  } },
15108
15108
  // Add a mapping from id to n for n.ownerDocument
15109
- addId: { value: function addId(id, n) {
15110
- var val = this.byId[id];
15109
+ addId: { value: function addId(id2, n) {
15110
+ var val = this.byId[id2];
15111
15111
  if (!val) {
15112
- this.byId[id] = n;
15112
+ this.byId[id2] = n;
15113
15113
  } else {
15114
15114
  if (!(val instanceof MultiId)) {
15115
15115
  val = new MultiId(val);
15116
- this.byId[id] = val;
15116
+ this.byId[id2] = val;
15117
15117
  }
15118
15118
  val.add(n);
15119
15119
  }
15120
15120
  } },
15121
15121
  // Delete the mapping from id to n for n.ownerDocument
15122
- delId: { value: function delId(id, n) {
15123
- var val = this.byId[id];
15122
+ delId: { value: function delId(id2, n) {
15123
+ var val = this.byId[id2];
15124
15124
  utils.assert(val);
15125
15125
  if (val instanceof MultiId) {
15126
15126
  val.del(n);
15127
15127
  if (val.length === 1) {
15128
- this.byId[id] = val.downgrade();
15128
+ this.byId[id2] = val.downgrade();
15129
15129
  }
15130
15130
  } else {
15131
- this.byId[id] = void 0;
15131
+ this.byId[id2] = void 0;
15132
15132
  }
15133
15133
  } },
15134
15134
  _resolve: { value: function(href) {
@@ -15238,15 +15238,15 @@ var require_Document = __commonJS({
15238
15238
  n._nid = n.ownerDocument._nextnid++;
15239
15239
  n.ownerDocument._nodes[n._nid] = n;
15240
15240
  if (n.nodeType === Node.ELEMENT_NODE) {
15241
- var id = n.getAttribute("id");
15242
- if (id) n.ownerDocument.addId(id, n);
15241
+ var id2 = n.getAttribute("id");
15242
+ if (id2) n.ownerDocument.addId(id2, n);
15243
15243
  if (n._roothook) n._roothook();
15244
15244
  }
15245
15245
  }
15246
15246
  function uproot(n) {
15247
15247
  if (n.nodeType === Node.ELEMENT_NODE) {
15248
- var id = n.getAttribute("id");
15249
- if (id) n.ownerDocument.delId(id, n);
15248
+ var id2 = n.getAttribute("id");
15249
+ if (id2) n.ownerDocument.delId(id2, n);
15250
15250
  }
15251
15251
  n.ownerDocument._nodes[n._nid] = void 0;
15252
15252
  n._nid = void 0;
@@ -23908,8 +23908,8 @@ var require_turndown_cjs = __commonJS({
23908
23908
  }
23909
23909
  var markdownEscapes = [[/\\/g, "\\\\"], [/\*/g, "\\*"], [/^-/g, "\\-"], [/^\+ /g, "\\+ "], [/^(=+)/g, "\\$1"], [/^(#{1,6}) /g, "\\$1 "], [/`/g, "\\`"], [/^~~~/g, "\\~~~"], [/\[/g, "\\["], [/\]/g, "\\]"], [/^>/g, "\\>"], [/_/g, "\\_"], [/^(\d+)\. /g, "$1\\. "]];
23910
23910
  function escapeMarkdown(string3) {
23911
- return markdownEscapes.reduce(function(accumulator, escape2) {
23912
- return accumulator.replace(escape2[0], escape2[1]);
23911
+ return markdownEscapes.reduce(function(accumulator, escape3) {
23912
+ return accumulator.replace(escape3[0], escape3[1]);
23913
23913
  }, string3);
23914
23914
  }
23915
23915
  var rules = {};
@@ -24037,9 +24037,9 @@ var require_turndown_cjs = __commonJS({
24037
24037
  reference = "[" + content + "]: " + href + title;
24038
24038
  break;
24039
24039
  default:
24040
- var id = this.references.length + 1;
24041
- replacement = "[" + content + "][" + id + "]";
24042
- reference = "[" + id + "]: " + href + title;
24040
+ var id2 = this.references.length + 1;
24041
+ replacement = "[" + content + "][" + id2 + "]";
24042
+ reference = "[" + id2 + "]: " + href + title;
24043
24043
  }
24044
24044
  this.references.push(reference);
24045
24045
  return replacement;
@@ -24465,14 +24465,14 @@ var require_turndown_cjs = __commonJS({
24465
24465
  } else if (node.nodeType === 1) {
24466
24466
  replacement = replacementForNode.call(self, node);
24467
24467
  }
24468
- return join9(output, replacement);
24468
+ return join11(output, replacement);
24469
24469
  }, "");
24470
24470
  }
24471
24471
  function postProcess(output) {
24472
24472
  var self = this;
24473
24473
  this.rules.forEach(function(rule) {
24474
24474
  if (typeof rule.append === "function") {
24475
- output = join9(output, rule.append(self.options));
24475
+ output = join11(output, rule.append(self.options));
24476
24476
  }
24477
24477
  });
24478
24478
  return output.replace(/^[\t\r\n]+/, "").replace(/[\t\r\n\s]+$/, "");
@@ -24484,7 +24484,7 @@ var require_turndown_cjs = __commonJS({
24484
24484
  if (whitespace.leading || whitespace.trailing) content = content.trim();
24485
24485
  return whitespace.leading + rule.replacement(content, node, this.options) + whitespace.trailing;
24486
24486
  }
24487
- function join9(output, replacement) {
24487
+ function join11(output, replacement) {
24488
24488
  var s1 = trimTrailingNewlines(output);
24489
24489
  var s2 = trimLeadingNewlines(replacement);
24490
24490
  var nls = Math.max(output.length - s1.length, replacement.length - s2.length);
@@ -30311,38 +30311,38 @@ var $ZodObject = /* @__PURE__ */ $constructor("$ZodObject", (inst, def) => {
30311
30311
  doc.write(`const newResult = {}`);
30312
30312
  for (const key of normalized2.keys) {
30313
30313
  if (normalized2.optionalKeys.has(key)) {
30314
- const id = ids[key];
30315
- doc.write(`const ${id} = ${parseStr(key)};`);
30314
+ const id2 = ids[key];
30315
+ doc.write(`const ${id2} = ${parseStr(key)};`);
30316
30316
  const k = esc(key);
30317
30317
  doc.write(`
30318
- if (${id}.issues.length) {
30318
+ if (${id2}.issues.length) {
30319
30319
  if (input[${k}] === undefined) {
30320
30320
  if (${k} in input) {
30321
30321
  newResult[${k}] = undefined;
30322
30322
  }
30323
30323
  } else {
30324
30324
  payload.issues = payload.issues.concat(
30325
- ${id}.issues.map((iss) => ({
30325
+ ${id2}.issues.map((iss) => ({
30326
30326
  ...iss,
30327
30327
  path: iss.path ? [${k}, ...iss.path] : [${k}],
30328
30328
  }))
30329
30329
  );
30330
30330
  }
30331
- } else if (${id}.value === undefined) {
30331
+ } else if (${id2}.value === undefined) {
30332
30332
  if (${k} in input) newResult[${k}] = undefined;
30333
30333
  } else {
30334
- newResult[${k}] = ${id}.value;
30334
+ newResult[${k}] = ${id2}.value;
30335
30335
  }
30336
30336
  `);
30337
30337
  } else {
30338
- const id = ids[key];
30339
- doc.write(`const ${id} = ${parseStr(key)};`);
30338
+ const id2 = ids[key];
30339
+ doc.write(`const ${id2} = ${parseStr(key)};`);
30340
30340
  doc.write(`
30341
- if (${id}.issues.length) payload.issues = payload.issues.concat(${id}.issues.map(iss => ({
30341
+ if (${id2}.issues.length) payload.issues = payload.issues.concat(${id2}.issues.map(iss => ({
30342
30342
  ...iss,
30343
30343
  path: iss.path ? [${esc(key)}, ...iss.path] : [${esc(key)}]
30344
30344
  })));`);
30345
- doc.write(`newResult[${esc(key)}] = ${id}.value`);
30345
+ doc.write(`newResult[${esc(key)}] = ${id2}.value`);
30346
30346
  }
30347
30347
  }
30348
30348
  doc.write(`payload.value = newResult;`);
@@ -32073,13 +32073,13 @@ var JSONSchemaGenerator = class {
32073
32073
  const defsSegment = this.target === "draft-2020-12" ? "$defs" : "definitions";
32074
32074
  if (params.external) {
32075
32075
  const externalId = params.external.registry.get(entry[0])?.id;
32076
- const uriGenerator = params.external.uri ?? ((id2) => id2);
32076
+ const uriGenerator = params.external.uri ?? ((id3) => id3);
32077
32077
  if (externalId) {
32078
32078
  return { ref: uriGenerator(externalId) };
32079
32079
  }
32080
- const id = entry[1].defId ?? entry[1].schema.id ?? `schema${this.counter++}`;
32081
- entry[1].defId = id;
32082
- return { defId: id, ref: `${uriGenerator("__shared")}#/${defsSegment}/${id}` };
32080
+ const id2 = entry[1].defId ?? entry[1].schema.id ?? `schema${this.counter++}`;
32081
+ entry[1].defId = id2;
32082
+ return { defId: id2, ref: `${uriGenerator("__shared")}#/${defsSegment}/${id2}` };
32083
32083
  }
32084
32084
  if (entry[1] === root) {
32085
32085
  return { ref: "#" };
@@ -32127,8 +32127,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
32127
32127
  continue;
32128
32128
  }
32129
32129
  }
32130
- const id = this.metadataRegistry.get(entry[0])?.id;
32131
- if (id) {
32130
+ const id2 = this.metadataRegistry.get(entry[0])?.id;
32131
+ if (id2) {
32132
32132
  extractToDef(entry);
32133
32133
  continue;
32134
32134
  }
@@ -32182,10 +32182,10 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
32182
32182
  console.warn(`Invalid target: ${this.target}`);
32183
32183
  }
32184
32184
  if (params.external?.uri) {
32185
- const id = params.external.registry.get(schema)?.id;
32186
- if (!id)
32185
+ const id2 = params.external.registry.get(schema)?.id;
32186
+ if (!id2)
32187
32187
  throw new Error("Schema is missing an `id` property");
32188
- result.$id = params.external.uri(id);
32188
+ result.$id = params.external.uri(id2);
32189
32189
  }
32190
32190
  Object.assign(result, root.def);
32191
32191
  const defs = params.external?.defs ?? {};
@@ -37218,7 +37218,7 @@ var ExperimentalServerTasks = class {
37218
37218
  if (hasPreviousToolUse) {
37219
37219
  const toolUseIds = new Set(previousContent.filter((c) => c.type === "tool_use").map((c) => c.id));
37220
37220
  const toolResultIds = new Set(lastContent.filter((c) => c.type === "tool_result").map((c) => c.toolUseId));
37221
- if (toolUseIds.size !== toolResultIds.size || ![...toolUseIds].every((id) => toolResultIds.has(id))) {
37221
+ if (toolUseIds.size !== toolResultIds.size || ![...toolUseIds].every((id2) => toolResultIds.has(id2))) {
37222
37222
  throw new Error("ids of tool_result blocks and tool_use blocks from previous message do not match");
37223
37223
  }
37224
37224
  }
@@ -37643,7 +37643,7 @@ var Server = class extends Protocol {
37643
37643
  if (hasPreviousToolUse) {
37644
37644
  const toolUseIds = new Set(previousContent.filter((c) => c.type === "tool_use").map((c) => c.id));
37645
37645
  const toolResultIds = new Set(lastContent.filter((c) => c.type === "tool_result").map((c) => c.toolUseId));
37646
- if (toolUseIds.size !== toolResultIds.size || ![...toolUseIds].every((id) => toolResultIds.has(id))) {
37646
+ if (toolUseIds.size !== toolResultIds.size || ![...toolUseIds].every((id2) => toolResultIds.has(id2))) {
37647
37647
  throw new Error("ids of tool_result blocks and tool_use blocks from previous message do not match");
37648
37648
  }
37649
37649
  }
@@ -39350,10 +39350,10 @@ function hasFullDiskAccess() {
39350
39350
  return false;
39351
39351
  }
39352
39352
  }
39353
- function queryNoteData(noteId2) {
39354
- const pkMatch = noteId2.match(/\/p(\d+)$/);
39353
+ function queryNoteData(noteId3) {
39354
+ const pkMatch = noteId3.match(/\/p(\d+)$/);
39355
39355
  if (!pkMatch) {
39356
- console.error(`Invalid note ID format: ${noteId2}`);
39356
+ console.error(`Invalid note ID format: ${noteId3}`);
39357
39357
  return { hex: null, error: "invalid_id" };
39358
39358
  }
39359
39359
  const pk = pkMatch[1];
@@ -39438,13 +39438,13 @@ function parseChecklistFromProtobuf(data) {
39438
39438
  return null;
39439
39439
  }
39440
39440
  }
39441
- function getChecklistItems(noteId2) {
39442
- const { hex: hexData, error: queryError } = queryNoteData(noteId2);
39441
+ function getChecklistItems(noteId3) {
39442
+ const { hex: hexData, error: queryError } = queryNoteData(noteId3);
39443
39443
  if (queryError === "invalid_id") {
39444
39444
  return {
39445
39445
  items: null,
39446
39446
  error: "invalid_id",
39447
- message: `Invalid note ID format: "${noteId2}". Expected format: x-coredata://UUID/ICNote/pNNN`
39447
+ message: `Invalid note ID format: "${noteId3}". Expected format: x-coredata://UUID/ICNote/pNNN`
39448
39448
  };
39449
39449
  }
39450
39450
  if (queryError === "no_fda") {
@@ -39604,8 +39604,8 @@ function parseRichNote(data, nativeTags = []) {
39604
39604
  styleRuns
39605
39605
  };
39606
39606
  }
39607
- function readRichNote(id) {
39608
- const pk = /^x-coredata:\/\/[0-9a-f-]+\/ICNote\/p([0-9]+)$/i.exec(id)?.[1];
39607
+ function readRichNote(id2) {
39608
+ const pk = /^x-coredata:\/\/[0-9a-f-]+\/ICNote\/p([0-9]+)$/i.exec(id2)?.[1];
39609
39609
  if (!pk) throw new Error("Invalid exact note ID");
39610
39610
  const sql = `BEGIN; SELECT hex(ZDATA) FROM ZICNOTEDATA WHERE ZNOTE=${pk}; SELECT json_group_object(ZIDENTIFIER,ZALTTEXT) FROM ZICCLOUDSYNCINGOBJECT WHERE ZNOTE1=${pk} AND ZTYPEUTI1='com.apple.notes.inlinetextattachment.hashtag'; SELECT json_group_array(json_object('id',ZIDENTIFIER,'pk',Z_PK,'type',COALESCE(ZTYPEUTI1,ZTYPEUTI),'mergeable',hex(COALESCE(ZMERGEABLEDATA1,ZMERGEABLEDATA)),'view',ZATTACHMENTVIEWTYPE)) FROM ZICCLOUDSYNCINGOBJECT WHERE ZNOTE1=${pk} OR ZNOTE=${pk}; COMMIT;`;
39611
39611
  const rows = execFileSync3("/usr/bin/sqlite3", ["-readonly", dbPath, sql], {
@@ -39630,14 +39630,14 @@ function readRichNote(id) {
39630
39630
  rich.objectData = objectData.filter((row) => rich.nativeObjectIds.includes(row.id)).sort((a, b) => a.id.localeCompare(b.id));
39631
39631
  rich.revision = createHash("sha256").update(rich.revision).update(JSON.stringify(rich.objectData)).digest("hex");
39632
39632
  rich.nativeTagObjectIds = {};
39633
- for (const id2 of rich.nativeObjectIds)
39634
- if (tagMap[id2]) {
39635
- const tag = tagMap[id2].replace(/^#/, "");
39636
- (rich.nativeTagObjectIds[tag] ||= []).push(id2);
39633
+ for (const id3 of rich.nativeObjectIds)
39634
+ if (tagMap[id3]) {
39635
+ const tag = tagMap[id3].replace(/^#/, "");
39636
+ (rich.nativeTagObjectIds[tag] ||= []).push(id3);
39637
39637
  }
39638
39638
  rich.nativeTags = [
39639
39639
  ...new Set(
39640
- rich.nativeObjectIds.flatMap((id2) => tagMap[id2] ? [tagMap[id2].replace(/^#/, "")] : [])
39640
+ rich.nativeObjectIds.flatMap((id3) => tagMap[id3] ? [tagMap[id3].replace(/^#/, "")] : [])
39641
39641
  )
39642
39642
  ];
39643
39643
  return rich;
@@ -39712,10 +39712,10 @@ function restoreNoteLinks(html, rich) {
39712
39712
  result = result.slice(0, span.start) + `<a href="${escapeAttribute(span.url)}">` + result.slice(span.start, span.end) + "</a>" + result.slice(span.end);
39713
39713
  return result;
39714
39714
  }
39715
- function enrichNoteRead(id, rawBody) {
39715
+ function enrichNoteRead(id2, rawBody) {
39716
39716
  let metadata;
39717
39717
  try {
39718
- const rich = readRichNote(id);
39718
+ const rich = readRichNote(id2);
39719
39719
  metadata = rich;
39720
39720
  const content = restoreNoteLinks(rawBody, rich);
39721
39721
  const writable = !rich.hasNativeObjects && !rich.hasChecklist;
@@ -39971,24 +39971,24 @@ function validateLength(value, maxLength, label) {
39971
39971
  }
39972
39972
  return value;
39973
39973
  }
39974
- function sanitizeId(id) {
39974
+ function sanitizeId(id2) {
39975
39975
  const coreDataPattern = /^x-coredata:\/\/[0-9A-Fa-f-]+\/IC[A-Za-z]+\/p\d+$/;
39976
39976
  const tempIdPattern = /^temp-\d+-\d+$/;
39977
- if (!coreDataPattern.test(id) && !tempIdPattern.test(id)) {
39977
+ if (!coreDataPattern.test(id2) && !tempIdPattern.test(id2)) {
39978
39978
  throw new Error(
39979
- `Invalid note ID format: "${id.substring(0, 80)}". Expected CoreData URL (x-coredata://...) or temp ID.`
39979
+ `Invalid note ID format: "${id2.substring(0, 80)}". Expected CoreData URL (x-coredata://...) or temp ID.`
39980
39980
  );
39981
39981
  }
39982
- return escapeForAppleScript(id);
39982
+ return escapeForAppleScript(id2);
39983
39983
  }
39984
- function sanitizeNoteId(id) {
39984
+ function sanitizeNoteId(id2) {
39985
39985
  const noteIdPattern = /^x-coredata:\/\/[0-9A-Fa-f-]+\/ICNote\/p\d+$/;
39986
- if (!noteIdPattern.test(id)) {
39986
+ if (!noteIdPattern.test(id2)) {
39987
39987
  throw new Error(
39988
- `Invalid note ID format: "${id.substring(0, 80)}". Expected canonical Apple Note ID (x-coredata://.../ICNote/p...).`
39988
+ `Invalid note ID format: "${id2.substring(0, 80)}". Expected canonical Apple Note ID (x-coredata://.../ICNote/p...).`
39989
39989
  );
39990
39990
  }
39991
- return escapeForAppleScript(id);
39991
+ return escapeForAppleScript(id2);
39992
39992
  }
39993
39993
  function sanitizeAccountName(account) {
39994
39994
  validateLength(account, MAX_ACCOUNT_LENGTH, "Account name");
@@ -40043,10 +40043,10 @@ function parseNotePropertiesOutput(output) {
40043
40043
  console.error("Unexpected response format: expected 6 delimited note properties");
40044
40044
  return null;
40045
40045
  }
40046
- const [title, id, createdStr, modifiedStr, sharedStr, ppStr] = parts;
40046
+ const [title, id2, createdStr, modifiedStr, sharedStr, ppStr] = parts;
40047
40047
  return {
40048
40048
  title: title.trim(),
40049
- id: id.trim(),
40049
+ id: id2.trim(),
40050
40050
  created: createdStr?.trim() ? parseAppleScriptDate(createdStr.trim()) : /* @__PURE__ */ new Date(),
40051
40051
  modified: modifiedStr?.trim() ? parseAppleScriptDate(modifiedStr.trim()) : /* @__PURE__ */ new Date(),
40052
40052
  shared: sharedStr?.trim() === "true",
@@ -40207,8 +40207,8 @@ var AppleNotesManager = class {
40207
40207
  * @param id - CoreData URL identifier for the note
40208
40208
  * @returns true if the note is password-protected, false otherwise
40209
40209
  */
40210
- isNotePasswordProtectedById(id) {
40211
- const note = this.getNoteById(id);
40210
+ isNotePasswordProtectedById(id2) {
40211
+ const note = this.getNoteById(id2);
40212
40212
  return note?.passwordProtected === true;
40213
40213
  }
40214
40214
  /**
@@ -40281,20 +40281,20 @@ var AppleNotesManager = class {
40281
40281
  return null;
40282
40282
  }
40283
40283
  const rawOutput = result.output.trim();
40284
- const noteId2 = extractCoreDataId(rawOutput, "note") || rawOutput;
40285
- if (!noteId2) {
40284
+ const noteId3 = extractCoreDataId(rawOutput, "note") || rawOutput;
40285
+ if (!noteId3) {
40286
40286
  console.error(`Created note "${title}" but Notes.app returned no canonical note ID`);
40287
40287
  return null;
40288
40288
  }
40289
40289
  try {
40290
- sanitizeNoteId(noteId2);
40290
+ sanitizeNoteId(noteId3);
40291
40291
  } catch {
40292
40292
  console.error(`Created note "${title}" but Notes.app returned an invalid note ID`);
40293
40293
  return null;
40294
40294
  }
40295
40295
  const now = /* @__PURE__ */ new Date();
40296
40296
  return {
40297
- id: noteId2,
40297
+ id: noteId3,
40298
40298
  title,
40299
40299
  content,
40300
40300
  tags,
@@ -40406,13 +40406,13 @@ var AppleNotesManager = class {
40406
40406
  const seenIds = /* @__PURE__ */ new Set();
40407
40407
  const reportedAccount = this.reportedAccount(targetAccount);
40408
40408
  for (const item of items) {
40409
- const [title, id, folder2, created, modified] = item.split(FIELD_SEP);
40409
+ const [title, id2, folder2, created, modified] = item.split(FIELD_SEP);
40410
40410
  if (!title?.trim()) continue;
40411
- const noteId2 = id?.trim() || generateFallbackId();
40412
- if (seenIds.has(noteId2)) continue;
40413
- seenIds.add(noteId2);
40411
+ const noteId3 = id2?.trim() || generateFallbackId();
40412
+ if (seenIds.has(noteId3)) continue;
40413
+ seenIds.add(noteId3);
40414
40414
  notes.push({
40415
- id: noteId2,
40415
+ id: noteId3,
40416
40416
  title: title.trim(),
40417
40417
  content: "",
40418
40418
  // Not fetched in search
@@ -40470,13 +40470,13 @@ var AppleNotesManager = class {
40470
40470
  * @param id - CoreData URL identifier for the note
40471
40471
  * @returns HTML content of the note, or empty string if not found
40472
40472
  */
40473
- getNoteContentById(id) {
40474
- const safeId = sanitizeId(id);
40473
+ getNoteContentById(id2) {
40474
+ const safeId = sanitizeId(id2);
40475
40475
  const getCommand = `get body of note id "${safeId}"`;
40476
40476
  const script = buildAppLevelScript(getCommand);
40477
40477
  const result = executeAppleScript(script);
40478
40478
  if (!result.success) {
40479
- console.error(`Failed to get content of note with ID "${id}":`, result.error);
40479
+ console.error(`Failed to get content of note with ID "${id2}":`, result.error);
40480
40480
  return "";
40481
40481
  }
40482
40482
  return result.output;
@@ -40518,13 +40518,13 @@ var AppleNotesManager = class {
40518
40518
  * @param id - CoreData URL identifier for the note
40519
40519
  * @returns Plain-text content of the note, or empty string if not found
40520
40520
  */
40521
- getNotePlaintextById(id) {
40522
- const safeId = sanitizeId(id);
40521
+ getNotePlaintextById(id2) {
40522
+ const safeId = sanitizeId(id2);
40523
40523
  const getCommand = `get plaintext of note id "${safeId}"`;
40524
40524
  const script = buildAppLevelScript(getCommand);
40525
40525
  const result = executeAppleScript(script);
40526
40526
  if (!result.success) {
40527
- console.error(`Failed to get plaintext of note with ID "${id}":`, result.error);
40527
+ console.error(`Failed to get plaintext of note with ID "${id2}":`, result.error);
40528
40528
  return "";
40529
40529
  }
40530
40530
  return result.output;
@@ -40540,8 +40540,8 @@ var AppleNotesManager = class {
40540
40540
  * @param id - CoreData URL identifier for the note
40541
40541
  * @returns Note object with metadata, or null if not found
40542
40542
  */
40543
- getNoteById(id) {
40544
- const safeId = sanitizeId(id);
40543
+ getNoteById(id2) {
40544
+ const safeId = sanitizeId(id2);
40545
40545
  const getCommand = `
40546
40546
  set n to note id "${safeId}"
40547
40547
  set cd to creation date of n
@@ -40553,7 +40553,7 @@ var AppleNotesManager = class {
40553
40553
  const script = buildAppLevelScript(getCommand);
40554
40554
  const result = executeAppleScript(script);
40555
40555
  if (!result.success) {
40556
- console.error(`Failed to get note with ID "${id}":`, result.error);
40556
+ console.error(`Failed to get note with ID "${id2}":`, result.error);
40557
40557
  return null;
40558
40558
  }
40559
40559
  const parsed = parseNotePropertiesOutput(result.output);
@@ -40625,10 +40625,10 @@ var AppleNotesManager = class {
40625
40625
  * race that would exist if JavaScript checked the note and then issued a
40626
40626
  * separate unconditional `set body` command.
40627
40627
  */
40628
- updateNoteByIdIfUnchanged(id, currentTitle, expectedBody, newTitle, newContent, format = "plaintext", expectedRichRevision) {
40629
- const safeId = sanitizeNoteId(id);
40628
+ updateNoteByIdIfUnchanged(id2, currentTitle, expectedBody, newTitle, newContent, format = "plaintext", expectedRichRevision) {
40629
+ const safeId = sanitizeNoteId(id2);
40630
40630
  if (expectedRichRevision) {
40631
- const rich = readRichNote(id);
40631
+ const rich = readRichNote(id2);
40632
40632
  if (rich.revision !== expectedRichRevision) return { status: "conflict" };
40633
40633
  if (rich.hasNativeObjects || rich.hasChecklist) return { status: "attachments" };
40634
40634
  }
@@ -40657,7 +40657,7 @@ var AppleNotesManager = class {
40657
40657
  `);
40658
40658
  const result = executeMutationAppleScript(script);
40659
40659
  if (!result.success) {
40660
- console.error(`Failed guarded update for note ID "${id}":`, result.error);
40660
+ console.error(`Failed guarded update for note ID "${id2}":`, result.error);
40661
40661
  return { status: "failed" };
40662
40662
  }
40663
40663
  const status = result.output.trim();
@@ -40671,8 +40671,8 @@ var AppleNotesManager = class {
40671
40671
  * the caller reviewed. The comparison and delete are one AppleScript action,
40672
40672
  * so a concurrent edit cannot slip between the guard and deletion.
40673
40673
  */
40674
- deleteNoteByIdIfUnchanged(id, expectedBody) {
40675
- const safeId = sanitizeNoteId(id);
40674
+ deleteNoteByIdIfUnchanged(id2, expectedBody) {
40675
+ const safeId = sanitizeNoteId(id2);
40676
40676
  validateLength(expectedBody, MAX_CONTENT_LENGTH, "Expected note content");
40677
40677
  const safeExpectedBody = escapeHtmlForAppleScript(expectedBody);
40678
40678
  const script = buildAppLevelScript(`
@@ -40686,7 +40686,7 @@ var AppleNotesManager = class {
40686
40686
  `);
40687
40687
  const result = executeMutationAppleScript(script);
40688
40688
  if (!result.success) {
40689
- console.error(`Failed guarded delete for note ID "${id}":`, result.error);
40689
+ console.error(`Failed guarded delete for note ID "${id2}":`, result.error);
40690
40690
  return { status: "failed" };
40691
40691
  }
40692
40692
  const status = result.output.trim();
@@ -40778,12 +40778,12 @@ var AppleNotesManager = class {
40778
40778
  const seenIds = /* @__PURE__ */ new Set();
40779
40779
  const refs = [];
40780
40780
  for (const item of output.split(RECORD_SEP)) {
40781
- const [title, id] = item.split(FIELD_SEP);
40781
+ const [title, id2] = item.split(FIELD_SEP);
40782
40782
  if (!title?.trim()) continue;
40783
- const noteId2 = id?.trim() || generateFallbackId();
40784
- if (seenIds.has(noteId2)) continue;
40785
- seenIds.add(noteId2);
40786
- refs.push({ title: title.trim(), id: noteId2 });
40783
+ const noteId3 = id2?.trim() || generateFallbackId();
40784
+ if (seenIds.has(noteId3)) continue;
40785
+ seenIds.add(noteId3);
40786
+ refs.push({ title: title.trim(), id: noteId3 });
40787
40787
  if (safeLimit !== void 0 && refs.length >= safeLimit) break;
40788
40788
  }
40789
40789
  return refs;
@@ -40906,13 +40906,13 @@ var AppleNotesManager = class {
40906
40906
  const parts = item.split(FIELD_SEP);
40907
40907
  if (parts.length >= 6) {
40908
40908
  const title = parts[0].trim();
40909
- const id = parts[1].trim();
40909
+ const id2 = parts[1].trim();
40910
40910
  const createdStr = parts[2].trim();
40911
40911
  const modifiedStr = parts[3].trim();
40912
40912
  const shared = parts[4].trim() === "true";
40913
40913
  const passwordProtected = parts[5].trim() === "true";
40914
40914
  sharedNotes.push({
40915
- id,
40915
+ id: id2,
40916
40916
  title,
40917
40917
  content: "",
40918
40918
  tags: [],
@@ -40931,25 +40931,25 @@ var AppleNotesManager = class {
40931
40931
  // Folder Operations
40932
40932
  // ===========================================================================
40933
40933
  /** Rename a folder in place while preserving its identity and contents. */
40934
- renameFolderById(id, expectedName, expectedParentId, newName) {
40935
- if (!/^x-coredata:\/\/[0-9a-f-]+\/ICFolder\/p\d+$/i.test(id))
40934
+ renameFolderById(id2, expectedName, expectedParentId, newName) {
40935
+ if (!/^x-coredata:\/\/[0-9a-f-]+\/ICFolder\/p\d+$/i.test(id2))
40936
40936
  throw new Error("An exact folder ID is required");
40937
40937
  if (!newName.trim() || newName.length > 1e3 || Array.from(newName).some((char) => char.charCodeAt(0) < 32))
40938
40938
  throw new Error("Invalid folder name");
40939
40939
  const literal2 = (value) => `"${escapePlainStringForAppleScript(value)}"`;
40940
40940
  const script = `tell application "Notes"
40941
- set targetFolder to folder id ${literal2(id)}
40941
+ set targetFolder to folder id ${literal2(id2)}
40942
40942
  set parentRef to container of targetFolder
40943
40943
  set parentId to id of parentRef
40944
40944
  considering case
40945
40945
  if name of targetFolder is not ${literal2(expectedName)} or parentId is not ${literal2(expectedParentId)} then error "Folder changed; read it again"
40946
40946
  end considering
40947
40947
  repeat with sibling in folders of parentRef
40948
- if name of sibling is ${literal2(newName)} and id of sibling is not ${literal2(id)} then error "A sibling folder already has this name"
40948
+ if name of sibling is ${literal2(newName)} and id of sibling is not ${literal2(id2)} then error "A sibling folder already has this name"
40949
40949
  end repeat
40950
40950
  set name of targetFolder to ${literal2(newName)}
40951
40951
  considering case
40952
- if id of targetFolder is not ${literal2(id)} or name of targetFolder is not ${literal2(newName)} or id of container of targetFolder is not parentId then error "Rename readback failed"
40952
+ if id of targetFolder is not ${literal2(id2)} or name of targetFolder is not ${literal2(newName)} or id of container of targetFolder is not parentId then error "Rename readback failed"
40953
40953
  end considering
40954
40954
  return id of targetFolder
40955
40955
  end tell`;
@@ -40958,28 +40958,28 @@ var AppleNotesManager = class {
40958
40958
  throw new Error(
40959
40959
  result.error || "Rename outcome uncertain; read folder by ID before retrying"
40960
40960
  );
40961
- return { id, name: newName, parentId: expectedParentId };
40961
+ return { id: id2, name: newName, parentId: expectedParentId };
40962
40962
  }
40963
40963
  /** Read the exact name and parent identity used by guarded folder rename. */
40964
- getFolderById(id) {
40965
- if (!/^x-coredata:\/\/[0-9a-f-]+\/ICFolder\/p\d+$/i.test(id))
40964
+ getFolderById(id2) {
40965
+ if (!/^x-coredata:\/\/[0-9a-f-]+\/ICFolder\/p\d+$/i.test(id2))
40966
40966
  throw new Error("An exact folder ID is required");
40967
40967
  const result = executeAppleScript(`tell application "Notes"
40968
- set f to folder id "${id}"
40968
+ set f to folder id "${id2}"
40969
40969
  return (name of f) & ${AS_FIELD_SEP} & (id of container of f)
40970
40970
  end tell`);
40971
40971
  if (!result.success) throw new Error(result.error || "Folder not found");
40972
40972
  const [name, parentId] = result.output.replace(/\n$/, "").split(FIELD_SEP);
40973
40973
  if (!name || !parentId) throw new Error("Incomplete folder metadata");
40974
- return { id, name, parentId };
40974
+ return { id: id2, name, parentId };
40975
40975
  }
40976
40976
  /** Insert one file into an unchanged exact note and return Notes' attachment ID. */
40977
- addAttachmentById(id, expectedBody, filePath) {
40978
- if (!/^x-coredata:\/\/[0-9a-f-]+\/ICNote\/p\d+$/i.test(id))
40977
+ addAttachmentById(id2, expectedBody, filePath) {
40978
+ if (!/^x-coredata:\/\/[0-9a-f-]+\/ICNote\/p\d+$/i.test(id2))
40979
40979
  throw new Error("Exact note ID required");
40980
40980
  const quote = (value) => `"${escapePlainStringForAppleScript(value)}"`;
40981
40981
  const result = executeMutationAppleScript(`tell application "Notes"
40982
- set n to note id ${quote(id)}
40982
+ set n to note id ${quote(id2)}
40983
40983
  if password protected of n then error "Locked note"
40984
40984
  considering case
40985
40985
  if body of n is not ${quote(expectedBody)} and body of n is not (${quote(expectedBody)} & linefeed) then error "Note changed before attachment insertion"
@@ -41151,9 +41151,9 @@ var AppleNotesManager = class {
41151
41151
  * @param account - Account containing the destination folder (defaults to Notes.app's default account)
41152
41152
  * @returns true if the move succeeded, false otherwise
41153
41153
  */
41154
- moveNoteById(id, destinationFolder, account) {
41154
+ moveNoteById(id2, destinationFolder, account) {
41155
41155
  const targetAccount = this.resolveAccount(account);
41156
- const safeId = sanitizeNoteId(id);
41156
+ const safeId = sanitizeNoteId(id2);
41157
41157
  const destFolderRef = `${buildFolderReference(destinationFolder)} of ${AS_ACCOUNT_REF}`;
41158
41158
  const moveCommand = `
41159
41159
  ${buildAccountResolution(targetAccount)}
@@ -41177,7 +41177,7 @@ var AppleNotesManager = class {
41177
41177
  }
41178
41178
  if (result.output.trim() !== "SAFETY_MOVED") {
41179
41179
  console.error(
41180
- `Move result for note ID "${id}" did not verify destination "${destinationFolder}"`
41180
+ `Move result for note ID "${id2}" did not verify destination "${destinationFolder}"`
41181
41181
  );
41182
41182
  return false;
41183
41183
  }
@@ -41325,14 +41325,14 @@ var AppleNotesManager = class {
41325
41325
  * @param separately - Whether to open the note in a separate window
41326
41326
  * @returns true if Notes.app accepted the show command
41327
41327
  */
41328
- showNoteById(id, separately = false) {
41329
- const safeId = sanitizeId(id);
41328
+ showNoteById(id2, separately = false) {
41329
+ const safeId = sanitizeId(id2);
41330
41330
  const separatelyClause = separately ? " separately true" : "";
41331
41331
  const result = executeMutationAppleScript(
41332
41332
  buildAppLevelScript(`show note id "${safeId}"${separatelyClause}`)
41333
41333
  );
41334
41334
  if (!result.success) {
41335
- console.error(`Failed to show note with ID "${id}":`, result.error);
41335
+ console.error(`Failed to show note with ID "${id2}":`, result.error);
41336
41336
  return false;
41337
41337
  }
41338
41338
  return true;
@@ -41350,20 +41350,20 @@ var AppleNotesManager = class {
41350
41350
  * @param id - CoreData URL identifier for the note
41351
41351
  * @returns notes://showNote?identifier=<uuid> string, or null on failure
41352
41352
  */
41353
- getNoteLinkById(id) {
41354
- const note = this.getNoteById(id);
41353
+ getNoteLinkById(id2) {
41354
+ const note = this.getNoteById(id2);
41355
41355
  if (!note) return null;
41356
41356
  if (note.passwordProtected) return null;
41357
- const sqliteLink = getNoteLinkFromDB(id);
41357
+ const sqliteLink = getNoteLinkFromDB(id2);
41358
41358
  if (sqliteLink) return sqliteLink;
41359
- const safeId = sanitizeId(id);
41359
+ const safeId = sanitizeId(id2);
41360
41360
  const result = executeAppleScript(
41361
41361
  buildAppLevelScript(`return note link of (note id "${safeId}")`)
41362
41362
  );
41363
41363
  if (result.success && result.output.trim()) {
41364
41364
  return result.output.trim();
41365
41365
  }
41366
- console.error(`Failed to get note link for ID "${id}":`, result.error);
41366
+ console.error(`Failed to get note link for ID "${id2}":`, result.error);
41367
41367
  return null;
41368
41368
  }
41369
41369
  /**
@@ -41388,14 +41388,14 @@ var AppleNotesManager = class {
41388
41388
  * @param separately - Open in a separate window when supported by Notes.app
41389
41389
  * @returns true if Notes.app accepted the show command, false otherwise
41390
41390
  */
41391
- showFolderById(id, separately = false) {
41392
- const safeId = sanitizeId(id);
41391
+ showFolderById(id2, separately = false) {
41392
+ const safeId = sanitizeId(id2);
41393
41393
  const separatelyClause = separately ? " separately true" : "";
41394
41394
  const result = executeMutationAppleScript(
41395
41395
  buildAppLevelScript(`show folder id "${safeId}"${separatelyClause}`)
41396
41396
  );
41397
41397
  if (!result.success) {
41398
- console.error(`Failed to show folder with ID "${id}":`, result.error);
41398
+ console.error(`Failed to show folder with ID "${id2}":`, result.error);
41399
41399
  return false;
41400
41400
  }
41401
41401
  return true;
@@ -41410,14 +41410,14 @@ var AppleNotesManager = class {
41410
41410
  * @param separately - Open in a separate window when supported by Notes.app
41411
41411
  * @returns true if Notes.app accepted the show command, false otherwise
41412
41412
  */
41413
- showAccountById(id, separately = false) {
41414
- const safeId = sanitizeId(id);
41413
+ showAccountById(id2, separately = false) {
41414
+ const safeId = sanitizeId(id2);
41415
41415
  const separatelyClause = separately ? " separately true" : "";
41416
41416
  const result = executeMutationAppleScript(
41417
41417
  buildAppLevelScript(`show account id "${safeId}"${separatelyClause}`)
41418
41418
  );
41419
41419
  if (!result.success) {
41420
- console.error(`Failed to show account with ID "${id}":`, result.error);
41420
+ console.error(`Failed to show account with ID "${id2}":`, result.error);
41421
41421
  return false;
41422
41422
  }
41423
41423
  return true;
@@ -41435,8 +41435,8 @@ var AppleNotesManager = class {
41435
41435
  * @param separately - Open in a separate window when supported by Notes.app
41436
41436
  * @returns true if Notes.app revealed the attachment, false otherwise
41437
41437
  */
41438
- showAttachmentById(noteId2, attachmentId, separately = false) {
41439
- const safeNoteId = sanitizeId(noteId2);
41438
+ showAttachmentById(noteId3, attachmentId, separately = false) {
41439
+ const safeNoteId = sanitizeId(noteId3);
41440
41440
  const safeAttId = escapePlainStringForAppleScript(attachmentId);
41441
41441
  const separatelyClause = separately ? " separately true" : "";
41442
41442
  const script = `
@@ -41456,13 +41456,13 @@ var AppleNotesManager = class {
41456
41456
  const result = executeMutationAppleScript(script);
41457
41457
  if (!result.success) {
41458
41458
  console.error(
41459
- `Failed to show attachment "${attachmentId}" on note "${noteId2}":`,
41459
+ `Failed to show attachment "${attachmentId}" on note "${noteId3}":`,
41460
41460
  result.error
41461
41461
  );
41462
41462
  return false;
41463
41463
  }
41464
41464
  if ((result.output ?? "").trim().startsWith("ERR")) {
41465
- console.error(`Attachment "${attachmentId}" not found on note "${noteId2}"`);
41465
+ console.error(`Attachment "${attachmentId}" not found on note "${noteId3}"`);
41466
41466
  return false;
41467
41467
  }
41468
41468
  return true;
@@ -41692,8 +41692,8 @@ var AppleNotesManager = class {
41692
41692
  * attachments.forEach(a => console.log(`${a.name}: ${a.contentType}`));
41693
41693
  * ```
41694
41694
  */
41695
- listAttachmentsById(id) {
41696
- const safeId = sanitizeId(id);
41695
+ listAttachmentsById(id2) {
41696
+ const safeId = sanitizeId(id2);
41697
41697
  const script = `
41698
41698
  tell application "Notes"
41699
41699
  set theNote to note id "${safeId}"
@@ -41738,7 +41738,7 @@ var AppleNotesManager = class {
41738
41738
  const result = executeAppleScript(script);
41739
41739
  if (!result.success) {
41740
41740
  throw new Error(
41741
- `Failed to list attachments for note ID "${id}": ${result.error ?? "unknown AppleScript error"}`
41741
+ `Failed to list attachments for note ID "${id2}": ${result.error ?? "unknown AppleScript error"}`
41742
41742
  );
41743
41743
  }
41744
41744
  if (!result.output) {
@@ -41862,7 +41862,7 @@ var AppleNotesManager = class {
41862
41862
  * @param savePath - absolute destination file path (within home / temp / /Volumes)
41863
41863
  * @returns { success, savedPath?, name?, contentType?, error? }
41864
41864
  */
41865
- saveAttachmentById(noteId2, attachmentId, savePath) {
41865
+ saveAttachmentById(noteId3, attachmentId, savePath) {
41866
41866
  let abs;
41867
41867
  try {
41868
41868
  abs = assertSafeSavePath(savePath);
@@ -41870,7 +41870,7 @@ var AppleNotesManager = class {
41870
41870
  } catch (e) {
41871
41871
  return { success: false, error: e instanceof Error ? e.message : String(e) };
41872
41872
  }
41873
- const safeNoteId = sanitizeId(noteId2);
41873
+ const safeNoteId = sanitizeId(noteId3);
41874
41874
  const safeAttId = escapePlainStringForAppleScript(attachmentId);
41875
41875
  const safePath = escapePlainStringForAppleScript(abs);
41876
41876
  const script = `
@@ -41934,11 +41934,11 @@ var AppleNotesManager = class {
41934
41934
  * @param attachmentId - id of the attachment
41935
41935
  * @returns { success, name?, contentType?, base64?, bytes?, error? }
41936
41936
  */
41937
- getAttachmentBase64ById(noteId2, attachmentId) {
41937
+ getAttachmentBase64ById(noteId3, attachmentId) {
41938
41938
  const dir = makeTempDir();
41939
41939
  try {
41940
41940
  const dest = `${dir}/attachment.bin`;
41941
- const saved = this.saveAttachmentById(noteId2, attachmentId, dest);
41941
+ const saved = this.saveAttachmentById(noteId3, attachmentId, dest);
41942
41942
  if (!saved.success || !saved.savedPath) {
41943
41943
  return { success: false, error: saved.error };
41944
41944
  }
@@ -41962,32 +41962,32 @@ var AppleNotesManager = class {
41962
41962
  /**
41963
41963
  * Result of a batch operation on a single item.
41964
41964
  */
41965
- createBatchResult(id, success, error2) {
41966
- return error2 ? { id, success, error: error2 } : { id, success };
41965
+ createBatchResult(id2, success, error2) {
41966
+ return error2 ? { id: id2, success, error: error2 } : { id: id2, success };
41967
41967
  }
41968
41968
  /**
41969
41969
  * Maps a per-item status token emitted by a batch AppleScript loop to a
41970
41970
  * BatchResult, preserving the human-readable error messages of the original
41971
41971
  * per-note implementation. See {@link batchMoveNotes}.
41972
41972
  */
41973
- mapBatchStatus(id, status, op) {
41973
+ mapBatchStatus(id2, status, op) {
41974
41974
  switch (status) {
41975
41975
  case "ok":
41976
- return this.createBatchResult(id, true);
41976
+ return this.createBatchResult(id2, true);
41977
41977
  case "pw":
41978
- return this.createBatchResult(id, false, "Note is password-protected");
41978
+ return this.createBatchResult(id2, false, "Note is password-protected");
41979
41979
  case "missing":
41980
- return this.createBatchResult(id, false, "Note not found");
41980
+ return this.createBatchResult(id2, false, "Note not found");
41981
41981
  case "fail":
41982
41982
  return this.createBatchResult(
41983
- id,
41983
+ id2,
41984
41984
  false,
41985
41985
  op === "delete" ? "Deletion failed" : "Move failed"
41986
41986
  );
41987
41987
  case "wrongfolder":
41988
- return this.createBatchResult(id, false, "Destination folder verification failed");
41988
+ return this.createBatchResult(id2, false, "Destination folder verification failed");
41989
41989
  default:
41990
- return this.createBatchResult(id, false, "Unknown error");
41990
+ return this.createBatchResult(id2, false, "Unknown error");
41991
41991
  }
41992
41992
  }
41993
41993
  /**
@@ -42015,12 +42015,12 @@ var AppleNotesManager = class {
42015
42015
  const destFolderRef = `${buildFolderReference(folder)} of ${AS_ACCOUNT_REF}`;
42016
42016
  const results = new Array(ids.length);
42017
42017
  const runnable = [];
42018
- ids.forEach((id, i) => {
42018
+ ids.forEach((id2, i) => {
42019
42019
  try {
42020
- runnable.push({ index: i, safe: sanitizeNoteId(id) });
42020
+ runnable.push({ index: i, safe: sanitizeNoteId(id2) });
42021
42021
  } catch (e) {
42022
42022
  results[i] = this.createBatchResult(
42023
- id,
42023
+ id2,
42024
42024
  false,
42025
42025
  e instanceof Error ? e.message : "Invalid note ID"
42026
42026
  );
@@ -42284,12 +42284,12 @@ var AppleNotesManager = class {
42284
42284
  * @param id - CoreData URL identifier for the note
42285
42285
  * @returns Markdown content, or empty string if not found
42286
42286
  */
42287
- getNoteMarkdownById(id) {
42288
- const html = this.getNoteContentById(id);
42287
+ getNoteMarkdownById(id2) {
42288
+ const html = this.getNoteContentById(id2);
42289
42289
  if (!html) return "";
42290
- const rich = enrichNoteRead(id, html);
42290
+ const rich = enrichNoteRead(id2, html);
42291
42291
  let markdown = this.htmlToMarkdown(rich.content);
42292
- const result = getChecklistItems(id);
42292
+ const result = getChecklistItems(id2);
42293
42293
  if (result.items) {
42294
42294
  markdown = this.enrichMarkdownWithChecklists(markdown, result.items);
42295
42295
  }
@@ -42438,13 +42438,13 @@ function presentColumns() {
42438
42438
  }
42439
42439
  return cols;
42440
42440
  }
42441
- function getNoteMetadata(noteId2) {
42442
- const pkMatch = noteId2.match(/\/p(\d+)$/);
42441
+ function getNoteMetadata(noteId3) {
42442
+ const pkMatch = noteId3.match(/\/p(\d+)$/);
42443
42443
  if (!pkMatch) {
42444
42444
  return {
42445
42445
  metadata: null,
42446
42446
  error: "invalid_id",
42447
- message: `Invalid note ID format: "${noteId2}". Expected format: x-coredata://UUID/ICNote/pNNN`
42447
+ message: `Invalid note ID format: "${noteId3}". Expected format: x-coredata://UUID/ICNote/pNNN`
42448
42448
  };
42449
42449
  }
42450
42450
  const pk = pkMatch[1];
@@ -42465,7 +42465,7 @@ function getNoteMetadata(noteId2) {
42465
42465
  return {
42466
42466
  metadata: null,
42467
42467
  error: "not_found",
42468
- message: `No note found in the database for ID "${noteId2}".`
42468
+ message: `No note found in the database for ID "${noteId3}".`
42469
42469
  };
42470
42470
  }
42471
42471
  const raw = JSON.parse(row);
@@ -42739,8 +42739,8 @@ function registerResourcesAndPrompts(server2, manager) {
42739
42739
  "note",
42740
42740
  new ResourceTemplate("notes://note/{id}", { list: void 0 }),
42741
42741
  (uri, variables) => {
42742
- const id = decodeURIComponent(String(variables.id));
42743
- const markdown = manager.getNoteMarkdownById(id);
42742
+ const id2 = decodeURIComponent(String(variables.id));
42743
+ const markdown = manager.getNoteMarkdownById(id2);
42744
42744
  return {
42745
42745
  contents: [{ uri: uri.href, mimeType: "text/markdown", text: markdown || "(not found)" }]
42746
42746
  };
@@ -42960,8 +42960,8 @@ function parseNoteTable(compressed) {
42960
42960
  const ordering = sub(sub(entry(ref), 16), 1), array2 = sub(ordering, 1);
42961
42961
  const ids = many(array2, 2).map((a) => hex(getField(a, 2)));
42962
42962
  const map = /* @__PURE__ */ new Map();
42963
- ids.forEach((id, i) => {
42964
- const index = uuids.indexOf(id);
42963
+ ids.forEach((id2, i) => {
42964
+ const index = uuids.indexOf(id2);
42965
42965
  if (index < 0) throw new Error("Missing dimension UUID");
42966
42966
  map.set(index, i);
42967
42967
  });
@@ -43028,17 +43028,17 @@ import { tmpdir as tmpdir2 } from "node:os";
43028
43028
  import { basename, isAbsolute as isAbsolute2, join as join8 } from "node:path";
43029
43029
  var noteId = external_exports.string().regex(/^x-coredata:\/\/[0-9a-f-]+\/ICNote\/p\d+$/i);
43030
43030
  var revision = external_exports.string().regex(/^sha256:[a-f0-9]{64}$/);
43031
- function readSnapshot(manager, id) {
43032
- const note = manager.getNoteById(id);
43031
+ function readSnapshot(manager, id2) {
43032
+ const note = manager.getNoteById(id2);
43033
43033
  if (!note) throw new Error("Note not found");
43034
43034
  if (note.passwordProtected) throw new Error("Locked notes cannot receive attachments");
43035
- const body = manager.getNoteContentById(id);
43035
+ const body = manager.getNoteContentById(id2);
43036
43036
  if (!body) throw new Error("Note content is unavailable");
43037
- const enriched = enrichNoteRead(id, body);
43038
- const rich = readRichNote(id);
43037
+ const enriched = enrichNoteRead(id2, body);
43038
+ const rich = readRichNote(id2);
43039
43039
  if (!enriched.complete || enriched.revision !== rich.revision)
43040
43040
  throw new Error("Native metadata changed during read; read the note again");
43041
- return { id, title: note.title, body, rich, hash: richContentHash(body, enriched) };
43041
+ return { id: id2, title: note.title, body, rich, hash: richContentHash(body, enriched) };
43042
43042
  }
43043
43043
  function assertExistingContentPreserved(before, after) {
43044
43044
  if (before.id !== after.id || before.title !== after.title)
@@ -43048,7 +43048,7 @@ function assertExistingContentPreserved(before, after) {
43048
43048
  throw new Error("Existing note text was not preserved");
43049
43049
  if (linkSignature(before.rich.links) !== linkSignature(after.rich.links.slice(0, before.rich.links.length)))
43050
43050
  throw new Error("Existing links were not preserved");
43051
- if (before.rich.nativeObjectIds.some((id) => !after.rich.nativeObjectIds.includes(id)))
43051
+ if (before.rich.nativeObjectIds.some((id2) => !after.rich.nativeObjectIds.includes(id2)))
43052
43052
  throw new Error("Existing native object was lost");
43053
43053
  if (before.rich.nativeTags.some((tag) => !after.rich.nativeTags.includes(tag)))
43054
43054
  throw new Error("Existing native tag was lost");
@@ -43113,7 +43113,7 @@ function registerDirectOperations(server2, manager) {
43113
43113
  "get-folder-by-id",
43114
43114
  "Use when: reading the exact folder name and parent before a guarded rename.\nReturns: folder id, current name, and parent id.\nDo not use when: listing folders by path (list-folders).\nSafety: read-only.",
43115
43115
  { id: external_exports.string().max(2e3) },
43116
- ({ id }) => manager.getFolderById(id),
43116
+ ({ id: id2 }) => manager.getFolderById(id2),
43117
43117
  true
43118
43118
  );
43119
43119
  tool(
@@ -43134,28 +43134,28 @@ function registerDirectOperations(server2, manager) {
43134
43134
  "add-attachment",
43135
43135
  "Use when: adding one local file to an exact note without replacing its body.\nReturns: the new attachment id, byte count, and post-write content hash after exact byte verification.\nDo not use when: reading or exporting an existing attachment.\nSafety: requires a fresh rich revision, copies at most 64 MiB through a private temporary file, never retries insertion, and verifies existing content plus fetched bytes.",
43136
43136
  { id: noteId, expectedContentHash: revision, path: external_exports.string().min(1).max(4096) },
43137
- ({ id, expectedContentHash, path: path4 }) => {
43138
- const before = readSnapshot(manager, id);
43137
+ ({ id: id2, expectedContentHash, path: path4 }) => {
43138
+ const before = readSnapshot(manager, id2);
43139
43139
  if (before.hash !== expectedContentHash) throw new Error("Note revision changed");
43140
43140
  const bytes = localAttachment(path4);
43141
- const beforeAttachments = manager.listAttachmentsById(id);
43141
+ const beforeAttachments = manager.listAttachmentsById(id2);
43142
43142
  const directory = mkdtempSync2(join8(tmpdir2(), "notes-attachment-add-"));
43143
43143
  const temporaryFile = join8(directory, basename(path4));
43144
43144
  try {
43145
43145
  writeFileSync(temporaryFile, bytes, { mode: 384 });
43146
- if (readSnapshot(manager, id).hash !== before.hash)
43146
+ if (readSnapshot(manager, id2).hash !== before.hash)
43147
43147
  throw new Error("Note revision changed");
43148
43148
  let returnedId;
43149
43149
  let transportUncertain = false;
43150
43150
  try {
43151
- returnedId = manager.addAttachmentById(id, before.body, temporaryFile);
43151
+ returnedId = manager.addAttachmentById(id2, before.body, temporaryFile);
43152
43152
  } catch {
43153
43153
  transportUncertain = true;
43154
43154
  }
43155
- const after = readSnapshot(manager, id);
43155
+ const after = readSnapshot(manager, id2);
43156
43156
  assertExistingContentPreserved(before, after);
43157
43157
  const readInserted = () => [
43158
- ...new Map(manager.listAttachmentsById(id).map((item) => [item.id, item])).values()
43158
+ ...new Map(manager.listAttachmentsById(id2).map((item) => [item.id, item])).values()
43159
43159
  ].filter((item) => !beforeAttachments.some((existing) => existing.id === item.id));
43160
43160
  let inserted = readInserted();
43161
43161
  for (let attempt = 0; attempt < 4 && (inserted.length !== 1 || returnedId && returnedId !== inserted[0].id); attempt++) {
@@ -43168,7 +43168,7 @@ function registerDirectOperations(server2, manager) {
43168
43168
  "Attachment insertion outcome uncertain; read the exact note before retrying"
43169
43169
  );
43170
43170
  const attachmentId = inserted[0].id;
43171
- const fetched = manager.getAttachmentBase64ById(id, attachmentId);
43171
+ const fetched = manager.getAttachmentBase64ById(id2, attachmentId);
43172
43172
  const actual = typeof fetched.base64 === "string" ? Buffer.from(fetched.base64, "base64") : null;
43173
43173
  if (!actual || createHash2("sha256").update(actual).digest("hex") !== createHash2("sha256").update(bytes).digest("hex"))
43174
43174
  throw new Error(
@@ -43176,7 +43176,7 @@ function registerDirectOperations(server2, manager) {
43176
43176
  );
43177
43177
  return {
43178
43178
  ok: true,
43179
- id,
43179
+ id: id2,
43180
43180
  attachmentId,
43181
43181
  contentHash: after.hash,
43182
43182
  bytes: bytes.length,
@@ -43191,6 +43191,870 @@ function registerDirectOperations(server2, manager) {
43191
43191
  );
43192
43192
  }
43193
43193
 
43194
+ // src/services/nativeTags.ts
43195
+ import { execFileSync as execFileSync6 } from "node:child_process";
43196
+ import { mkdtempSync as mkdtempSync3, writeFileSync as writeFileSync2, rmSync as rmSync3 } from "node:fs";
43197
+ import { tmpdir as tmpdir3 } from "node:os";
43198
+ import { join as join9 } from "node:path";
43199
+ var NATIVE_TAGS_SHORTCUT = "Apple Notes MCP - Native Tags";
43200
+ function normalizeNativeTags(tags) {
43201
+ if (!tags.length || tags.length > 100) throw new Error("Provide between 1 and 100 tags");
43202
+ return [
43203
+ ...new Set(
43204
+ tags.map((value) => {
43205
+ const tag = value.normalize("NFC").replace(/^#/, "");
43206
+ if (tag.length > 100 || !new RegExp("^(?=.*\\p{L})[\\p{L}\\p{N}_-]+$", "u").test(tag))
43207
+ throw new Error(
43208
+ "Tags must contain a letter and only letters, digits, hyphens or underscores"
43209
+ );
43210
+ return tag;
43211
+ })
43212
+ )
43213
+ ];
43214
+ }
43215
+ function addNativeTags(request, deps) {
43216
+ if (!/^x-coredata:\/\/[0-9a-f-]+\/ICNote\/p\d+$/i.test(request.id))
43217
+ throw new Error("An exact CoreData note ID is required");
43218
+ if (request.scopeText.length < 12 || request.scopeText.length > 500 || /[\r\n\0]/u.test(request.scopeText))
43219
+ throw new Error("scopeText must be a stable, single-line project marker of 12\u2013500 characters");
43220
+ const tags = normalizeNativeTags(request.tags);
43221
+ const before = deps.read(request.id);
43222
+ if (before.contentHash !== request.expectedContentHash)
43223
+ throw new Error("Note revision changed; read it again");
43224
+ if (before.title !== request.title || !before.plaintext.includes(request.scopeText))
43225
+ throw new Error("The exact note does not match the title and project marker");
43226
+ const missing = tags.filter((tag) => !before.rich.nativeTags.includes(tag));
43227
+ if (!missing.length)
43228
+ return { nativeTags: before.rich.nativeTags, added: [], contentHash: before.contentHash };
43229
+ const candidates = deps.candidates(request.title, request.scopeText);
43230
+ if (candidates.length !== 1 || candidates[0] !== request.id)
43231
+ throw new Error(
43232
+ "Shortcuts selection is ambiguous or points to a different note; nothing was changed"
43233
+ );
43234
+ if (deps.read(request.id).contentHash !== request.expectedContentHash)
43235
+ throw new Error("Note revision changed during preflight; nothing was changed");
43236
+ let transportWarning;
43237
+ try {
43238
+ deps.run({ title: request.title, scopeText: request.scopeText, tags: missing });
43239
+ } catch (error2) {
43240
+ transportWarning = error2 instanceof Error ? error2.message : "Shortcuts completion was uncertain";
43241
+ }
43242
+ const after = deps.read(request.id);
43243
+ const allTags = [.../* @__PURE__ */ new Set([...before.rich.nativeTags, ...tags])];
43244
+ const textWithoutTags = (text) => {
43245
+ for (const tag of [...allTags].sort((a, b) => b.length - a.length)) {
43246
+ const escaped = tag.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
43247
+ text = text.replace(new RegExp(`#${escaped}(?![\\p{L}\\p{N}_-])`, "gu"), "");
43248
+ }
43249
+ return text.replace(/[\s\ufffc]/gu, "");
43250
+ };
43251
+ if (after.title !== before.title || allTags.some((tag) => !after.rich.nativeTags.includes(tag)) || textWithoutTags(before.rich.text) !== textWithoutTags(after.rich.text) || linkSignature(before.rich.links) !== linkSignature(after.rich.links) || before.rich.nativeObjectIds.some((id2) => !after.rich.nativeObjectIds.includes(id2)) || before.rich.hasChecklist !== after.rich.hasChecklist) {
43252
+ throw new Error(
43253
+ "Shortcuts ran, but exact-ID tags/text/links readback was not verified. Read the note before any retry"
43254
+ );
43255
+ }
43256
+ return {
43257
+ nativeTags: after.rich.nativeTags,
43258
+ added: missing,
43259
+ contentHash: after.contentHash,
43260
+ ...transportWarning ? {
43261
+ transportWarning: "Shortcuts completion was uncertain, but all requested native tags and preserved content were verified by exact ID."
43262
+ } : {}
43263
+ };
43264
+ }
43265
+ function nativeTagsStatus(shortcut = process.env.APPLE_NOTES_MCP_TAGS_SHORTCUT || NATIVE_TAGS_SHORTCUT) {
43266
+ const lines = execFileSync6("/usr/bin/shortcuts", ["list", "--show-identifiers"], {
43267
+ encoding: "utf8",
43268
+ timeout: 15e3,
43269
+ maxBuffer: 1024 * 1024,
43270
+ stdio: ["ignore", "pipe", "pipe"]
43271
+ }).split(/\r?\n/u);
43272
+ const matches = lines.flatMap((line) => {
43273
+ const match = /^(.*) \(([0-9A-Fa-f-]{36})\)$/.exec(line);
43274
+ return match && (match[1] === shortcut || match[2].toLowerCase() === shortcut.toLowerCase()) ? [{ name: match[1], identifier: match[2] }] : [];
43275
+ });
43276
+ return {
43277
+ shortcut,
43278
+ installed: matches.length === 1,
43279
+ identifier: matches.length === 1 ? matches[0].identifier : void 0
43280
+ };
43281
+ }
43282
+ function runNativeTagsShortcut(input) {
43283
+ const status = nativeTagsStatus();
43284
+ if (!status.installed)
43285
+ throw new Error(`Import the supplied ${status.shortcut}.shortcut in Shortcuts first`);
43286
+ const directory = mkdtempSync3(join9(tmpdir3(), "apple-notes-native-tags-"));
43287
+ try {
43288
+ const path4 = join9(directory, "request.json");
43289
+ writeFileSync2(path4, JSON.stringify(input), { mode: 384 });
43290
+ execFileSync6("/usr/bin/shortcuts", ["run", status.identifier, "--input-path", path4], {
43291
+ encoding: "utf8",
43292
+ timeout: 6e4,
43293
+ maxBuffer: 1024 * 1024,
43294
+ stdio: ["ignore", "pipe", "pipe"]
43295
+ });
43296
+ } catch {
43297
+ throw new Error(
43298
+ "Native tag operation did not complete cleanly (possibly waiting for macOS permission). Do not retry automatically; read the exact note and check Shortcuts"
43299
+ );
43300
+ } finally {
43301
+ rmSync3(directory, { recursive: true, force: true });
43302
+ }
43303
+ }
43304
+
43305
+ // src/tools/nativeTagsBridge.ts
43306
+ var noteId2 = external_exports.string().regex(/^x-coredata:\/\/[0-9a-f-]+\/ICNote\/p\d+$/i);
43307
+ var revision2 = external_exports.string().regex(/^sha256:[a-f0-9]{64}$/);
43308
+ function registerNativeTagsBridge(server2, manager) {
43309
+ function tool(name, description, inputSchema, handler) {
43310
+ server2.registerTool(
43311
+ name,
43312
+ {
43313
+ description,
43314
+ inputSchema,
43315
+ outputSchema: external_exports.object({ ok: external_exports.boolean().optional() }).passthrough()
43316
+ },
43317
+ (async (args) => {
43318
+ try {
43319
+ const result = handler(args);
43320
+ return {
43321
+ content: [{ type: "text", text: JSON.stringify(result) }],
43322
+ structuredContent: result
43323
+ };
43324
+ } catch (error2) {
43325
+ return {
43326
+ content: [
43327
+ {
43328
+ type: "text",
43329
+ text: error2 instanceof Error ? error2.message : String(error2)
43330
+ }
43331
+ ],
43332
+ isError: true
43333
+ };
43334
+ }
43335
+ })
43336
+ );
43337
+ }
43338
+ const read = (id2) => {
43339
+ const note = manager.getNoteById(id2);
43340
+ if (!note) throw new Error("Note not found");
43341
+ if (note.passwordProtected) throw new Error("Locked notes cannot receive native tags");
43342
+ const body = manager.getNoteContentById(id2);
43343
+ if (!body) throw new Error("Note content is unavailable");
43344
+ const enriched = enrichNoteRead(id2, body);
43345
+ const rich = readRichNote(id2);
43346
+ if (!enriched.complete || enriched.revision !== rich.revision)
43347
+ throw new Error("Native metadata changed during read; read the note again");
43348
+ return {
43349
+ contentHash: richContentHash(body, enriched),
43350
+ title: note.title,
43351
+ plaintext: manager.getNotePlaintextById(id2),
43352
+ rich
43353
+ };
43354
+ };
43355
+ tool(
43356
+ "native-tags-status",
43357
+ "Use when: checking whether the Native Tags Shortcut is installed before a tag write.\nReturns: the configured Shortcut name, unique installed identifier, and installed state.\nDo not use when: listing tags on notes (list-native-tags).\nSafety: read-only; installation does not by itself prove Notes permission or a successful live mutation.",
43358
+ {},
43359
+ () => nativeTagsStatus()
43360
+ );
43361
+ tool(
43362
+ "add-native-tags",
43363
+ "Use when: adding real clickable Apple Notes tags to one exact, freshly read note.\nReturns: verified native tags, additions, and the post-write content hash.\nDo not use when: textual #hashtags are sufficient or the note cannot be selected uniquely by its existing title and scope text.\nSafety: requires exact ID, fresh revision, and a distinctive existing scope phrase; verifies original text, links, and native objects after the Shortcut runs and never retries automatically.",
43364
+ {
43365
+ id: noteId2,
43366
+ expectedContentHash: revision2,
43367
+ scopeText: external_exports.string().min(12).max(500),
43368
+ tags: external_exports.array(external_exports.string().min(1).max(101)).min(1).max(100)
43369
+ },
43370
+ ({ id: id2, expectedContentHash, scopeText, tags }) => {
43371
+ const initial = read(id2);
43372
+ const result = addNativeTags(
43373
+ { id: id2, expectedContentHash, scopeText, tags, title: initial.title },
43374
+ {
43375
+ read,
43376
+ candidates: (title, scope) => manager.listAccounts().flatMap(
43377
+ (account) => manager.searchNotes(title, false, account.name).filter(
43378
+ (note) => !note.passwordProtected && manager.getNotePlaintextById(note.id).toLocaleLowerCase().includes(scope.toLocaleLowerCase())
43379
+ ).map((note) => note.id)
43380
+ ),
43381
+ run: runNativeTagsShortcut
43382
+ }
43383
+ );
43384
+ return { ok: true, id: id2, ...result };
43385
+ }
43386
+ );
43387
+ }
43388
+
43389
+ // src/services/backgroundNotes.ts
43390
+ import { execFileSync as execFileSync7 } from "node:child_process";
43391
+ import { mkdtempSync as mkdtempSync4, writeFileSync as writeFileSync3, rmSync as rmSync4 } from "node:fs";
43392
+ import { tmpdir as tmpdir4 } from "node:os";
43393
+ import { join as join10 } from "node:path";
43394
+
43395
+ // src/utils/appendMarkdown.ts
43396
+ var escape2 = (s) => s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
43397
+ function appendMarkdownHtml(markdown) {
43398
+ if (markdown.includes("\uE000") || markdown.includes("\uE001"))
43399
+ throw new Error("Unsupported reserved characters");
43400
+ if (Array.from(markdown).some((c) => c.charCodeAt(0) < 32 && !["\n", "\r", " "].includes(c)))
43401
+ throw new Error("Unsupported control characters");
43402
+ if (/[`~|]|^#{4,}\s|^\s*>|^\s*\[.+\]:|!\[|<\/?[a-z]/im.test(markdown))
43403
+ throw new Error(
43404
+ "Markdown append supports paragraphs, headings, flat lists, emphasis and inline links; use semantic HTML for other formatting"
43405
+ );
43406
+ const inline = (text) => {
43407
+ const links = [];
43408
+ let value = text.replace(/\[([^\]\n]+)\]\(([^()\s]+)\)/g, (_s, label, url) => {
43409
+ if (!/^(https?:\/\/|notes:\/\/|applenotes:|mailto:)/i.test(url))
43410
+ throw new Error("Unsupported Markdown link URL");
43411
+ links.push(`<a href="${escape2(url)}">${escape2(label)}</a>`);
43412
+ return `\uE000${links.length - 1}\uE001`;
43413
+ });
43414
+ value = escape2(value).replace(/\*\*([^*\n]+)\*\*/g, "<b>$1</b>").replace(/\*([^*\n]+)\*/g, "<i>$1</i>");
43415
+ if (value.includes("[") || value.includes("]") || value.includes("*"))
43416
+ throw new Error("Unsupported or unbalanced Markdown inline syntax");
43417
+ return value.replace(/\uE000(\d+)\uE001/g, (_s, i) => links[Number(i)]);
43418
+ };
43419
+ let html = "", list;
43420
+ const close = () => {
43421
+ if (list) {
43422
+ html += `</${list}>`;
43423
+ list = void 0;
43424
+ }
43425
+ };
43426
+ for (const line of markdown.replace(/\r\n/g, "\n").split("\n")) {
43427
+ if (/^\s{2,}\S/.test(line)) throw new Error("Nested lists and indented code are unsupported");
43428
+ const heading = /^(#{1,3})\s+(.+)$/.exec(line), item = /^(?:([-+*])|\d+\.)\s+(.+)$/.exec(line);
43429
+ if (item) {
43430
+ const kind = item[1] ? "ul" : "ol";
43431
+ if (list !== kind) {
43432
+ close();
43433
+ list = kind;
43434
+ html += `<${kind}>`;
43435
+ }
43436
+ html += `<li>${inline(item[2])}</li>`;
43437
+ continue;
43438
+ }
43439
+ close();
43440
+ html += heading ? `<h${heading[1].length}>${inline(heading[2])}</h${heading[1].length}>` : line.trim() ? `<div>${inline(line)}</div>` : "<div><br></div>";
43441
+ }
43442
+ close();
43443
+ return html;
43444
+ }
43445
+
43446
+ // src/services/backgroundNotes.ts
43447
+ var BACKGROUND_SHORTCUT = "Apple Notes MCP - Background Operations v5";
43448
+ var backgroundStatus = () => nativeTagsStatus(process.env.APPLE_NOTES_MCP_BACKGROUND_SHORTCUT || BACKGROUND_SHORTCUT);
43449
+ var nativeTagBridgeStatus = () => nativeTagsStatus();
43450
+ function readBackgroundSnapshot(manager, id2) {
43451
+ if (!/^x-coredata:\/\/[0-9a-f-]+\/ICNote\/p\d+$/i.test(id2))
43452
+ throw new Error("Exact note ID required");
43453
+ const note = manager.getNoteById(id2);
43454
+ if (!note) throw new Error("Note not found");
43455
+ if (note.passwordProtected) throw new Error("Locked notes are unavailable in background mode");
43456
+ const html = manager.getNoteContentById(id2);
43457
+ const enriched = enrichNoteRead(id2, html);
43458
+ const rich = readRichNote(id2);
43459
+ if (enriched.revision !== rich.revision)
43460
+ throw new Error("Note changed during read; read it again");
43461
+ return {
43462
+ id: id2,
43463
+ title: note.title,
43464
+ hash: richContentHash(html, enriched),
43465
+ html,
43466
+ rich,
43467
+ pinned: getNoteMetadata(id2).metadata?.pinned,
43468
+ checklist: getChecklistItems(id2).items || []
43469
+ };
43470
+ }
43471
+ function validateAppendContent(content, format) {
43472
+ if (!content || content.length > 1024 * 1024 || content.includes("\0"))
43473
+ throw new Error("Invalid append content (limit 1 MiB)");
43474
+ if (format === "html") {
43475
+ const allowed = /* @__PURE__ */ new Set([
43476
+ "div",
43477
+ "p",
43478
+ "br",
43479
+ "b",
43480
+ "strong",
43481
+ "i",
43482
+ "em",
43483
+ "u",
43484
+ "s",
43485
+ "del",
43486
+ "h1",
43487
+ "h2",
43488
+ "h3",
43489
+ "ul",
43490
+ "ol",
43491
+ "li",
43492
+ "a",
43493
+ "table",
43494
+ "thead",
43495
+ "tbody",
43496
+ "tr",
43497
+ "td",
43498
+ "th"
43499
+ ]);
43500
+ for (const tag of content.matchAll(/<\/?\s*([a-z][a-z0-9]*)\b([^>]*)>/gi)) {
43501
+ if (!allowed.has(tag[1].toLowerCase()))
43502
+ throw new Error(`Unsupported HTML element: ${tag[1]}`);
43503
+ let attrs = tag[2].replace(/\/$/, "").trim();
43504
+ if (tag[1].toLowerCase() === "a")
43505
+ attrs = attrs.replace(/\bhref\s*=\s*(["'])(.*?)\1/gi, (_s, _q, url) => {
43506
+ if (!/^(https?:\/\/|notes:\/\/|applenotes:|mailto:)/i.test(url) || Array.from(url).some((c) => c.charCodeAt(0) < 33))
43507
+ throw new Error("Unsupported link URL");
43508
+ return "";
43509
+ });
43510
+ if (attrs.trim())
43511
+ throw new Error(
43512
+ "Unsupported HTML attributes; use semantic formatting and explicit blank paragraphs"
43513
+ );
43514
+ }
43515
+ if (/<!--|<!|<\?|<[^>]*$/u.test(content)) throw new Error("Unsupported HTML markup");
43516
+ }
43517
+ if (format === "markdown" && /!\[|<\/?[a-z]|\]\(\s*(?:javascript|data|file):/i.test(content))
43518
+ throw new Error("Markdown images, raw HTML and local/executable links are unsupported");
43519
+ }
43520
+ function runBackgroundShortcut(input) {
43521
+ const status = backgroundStatus();
43522
+ if (!status.installed)
43523
+ throw new Error("Install the supplied Background Operations shortcut once");
43524
+ const directory = mkdtempSync4(join10(tmpdir4(), "apple-notes-background-"));
43525
+ try {
43526
+ const file = join10(directory, "request.json");
43527
+ writeFileSync3(
43528
+ file,
43529
+ JSON.stringify({
43530
+ operation: "",
43531
+ title: "",
43532
+ scopeText: "",
43533
+ text: "",
43534
+ objectId: "",
43535
+ objectName: "",
43536
+ change: "",
43537
+ otherTitle: "",
43538
+ otherScope: "",
43539
+ tag: "",
43540
+ size: "",
43541
+ ...input
43542
+ }),
43543
+ { mode: 384 }
43544
+ );
43545
+ execFileSync7("/usr/bin/shortcuts", ["run", status.identifier, "--input-path", file], {
43546
+ encoding: "utf8",
43547
+ timeout: 6e4,
43548
+ maxBuffer: 1024 * 1024,
43549
+ stdio: ["ignore", "pipe", "pipe"]
43550
+ });
43551
+ } finally {
43552
+ rmSync4(directory, { recursive: true, force: true });
43553
+ }
43554
+ }
43555
+ function backgroundDependencies(manager) {
43556
+ return {
43557
+ read: (id2) => readBackgroundSnapshot(manager, id2),
43558
+ run: runBackgroundShortcut,
43559
+ candidates: (title, scope) => manager.listAccounts().flatMap(
43560
+ (account) => manager.searchNotes(title, false, account.name).filter(
43561
+ (note) => note.title === title && !note.passwordProtected && manager.getNotePlaintextById(note.id).includes(scope)
43562
+ ).map((note) => note.id)
43563
+ )
43564
+ };
43565
+ }
43566
+ function assertPreserved(before, after, options = {}) {
43567
+ if (before.id !== after.id || before.title !== after.title)
43568
+ throw new Error("Note identity changed");
43569
+ const tidy = (s) => s.replace(/\r\n/g, "\n").replace(/[\s\ufffc]+$/gu, "");
43570
+ let oldText = tidy(before.rich.text), newText = tidy(after.rich.text);
43571
+ if (options.tagChange) {
43572
+ const escaped = options.tagChange.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
43573
+ const strip = (s) => s.replace(new RegExp(`#${escaped}(?![\\p{L}\\p{N}_-])`, "gu"), "").replace(/[\s\ufffc]/gu, "");
43574
+ oldText = strip(oldText);
43575
+ newText = strip(newText);
43576
+ }
43577
+ if (options.append ? !newText.startsWith(oldText) : newText !== oldText)
43578
+ throw new Error("Existing note text was not preserved");
43579
+ const links = options.append ? after.rich.links.slice(0, before.rich.links.length) : after.rich.links;
43580
+ if (linkSignature(before.rich.links) !== linkSignature(links))
43581
+ throw new Error("Existing links were not preserved");
43582
+ if (!options.tagChange && before.rich.nativeObjectIds.some((id2) => !after.rich.nativeObjectIds.includes(id2)))
43583
+ throw new Error("Existing native object was lost");
43584
+ if (JSON.stringify(before.checklist) !== JSON.stringify(
43585
+ options.append ? after.checklist.slice(0, before.checklist.length) : after.checklist
43586
+ ))
43587
+ throw new Error("Existing checklist items changed");
43588
+ for (const item of before.rich.checklistItems || []) {
43589
+ const actual = after.rich.checklistItems?.find((current) => current.id === item.id);
43590
+ if (!actual || actual.text !== item.text || actual.done !== item.done)
43591
+ throw new Error("Existing checklist item identity or state changed");
43592
+ }
43593
+ if (before.rich.nativeTags.filter((t) => t !== options.tagChange).some((t) => !after.rich.nativeTags.includes(t)))
43594
+ throw new Error("Existing native tag was lost");
43595
+ const allowedRemoved = options.tagChange ? before.rich.nativeTagObjectIds?.[options.tagChange] || [] : [];
43596
+ for (const object3 of before.rich.objectData || []) {
43597
+ if (allowedRemoved.includes(object3.id)) continue;
43598
+ const actual = after.rich.objectData?.find((o) => o.id === object3.id);
43599
+ if (!actual || actual.mergeable !== object3.mergeable || actual.view !== object3.view)
43600
+ throw new Error("Existing native object content or presentation changed");
43601
+ }
43602
+ if (!options.tagChange && before.rich.styleRuns && after.rich.styleRuns) {
43603
+ const end = before.rich.text.trimEnd().length;
43604
+ for (const oldRun of before.rich.styleRuns)
43605
+ for (const newRun of after.rich.styleRuns) {
43606
+ const overlapStart = Math.max(oldRun.start, newRun.start);
43607
+ const overlapEnd = Math.min(
43608
+ end,
43609
+ oldRun.start + oldRun.length,
43610
+ newRun.start + newRun.length
43611
+ );
43612
+ if (overlapStart < overlapEnd && /[^\s\ufffc]/u.test(before.rich.text.slice(overlapStart, overlapEnd)) && oldRun.signature !== newRun.signature)
43613
+ throw new Error("Existing rich formatting changed");
43614
+ }
43615
+ }
43616
+ }
43617
+ function mutateBackground(request, operation, data, verify, deps) {
43618
+ if (request.scopeText.length < 12 || request.scopeText.length > 500 || /[\r\n\0]/u.test(request.scopeText))
43619
+ throw new Error("Use a distinctive existing single-line scope of 12\u2013500 characters");
43620
+ const before = deps.read(request.id);
43621
+ if (before.hash !== request.expectedContentHash)
43622
+ throw new Error("Note revision changed; read it again");
43623
+ if (!before.rich.text.includes(request.scopeText))
43624
+ throw new Error("Scope is absent from exact note");
43625
+ const candidates = deps.candidates(before.title, request.scopeText);
43626
+ if (candidates.length !== 1 || candidates[0] !== request.id)
43627
+ throw new Error("Ambiguous note selection; nothing changed");
43628
+ if (deps.read(request.id).hash !== before.hash)
43629
+ throw new Error("Note revision changed during preflight");
43630
+ let transportUncertain = false;
43631
+ let transportMessage = "";
43632
+ try {
43633
+ deps.run({ ...data, operation, title: before.title, scopeText: request.scopeText });
43634
+ } catch (error2) {
43635
+ transportUncertain = true;
43636
+ const detail = error2;
43637
+ transportMessage = detail?.code === "ETIMEDOUT" ? "Shortcuts timed out; check for an interactive parameter or permission request" : String(detail?.stderr || detail?.message || "Shortcuts failed").trim().slice(0, 500);
43638
+ }
43639
+ const after = deps.read(request.id);
43640
+ try {
43641
+ verify(before, after);
43642
+ } catch (error2) {
43643
+ throw new Error(
43644
+ `Operation outcome uncertain; read exact note before any retry: ${error2 instanceof Error ? error2.message : "readback failed"}${transportMessage ? "; " + transportMessage : ""}`
43645
+ );
43646
+ }
43647
+ return {
43648
+ ok: true,
43649
+ id: request.id,
43650
+ previousContentHash: before.hash,
43651
+ contentHash: after.hash,
43652
+ ...transportUncertain ? {
43653
+ transportWarning: "Transport was uncertain; exact-ID readback verified the requested result"
43654
+ } : {}
43655
+ };
43656
+ }
43657
+ function assertAppendedHtmlLinks(previousCount, links, html) {
43658
+ const remaining = links.slice(previousCount);
43659
+ for (const expected of htmlLinks(html)) {
43660
+ const index = remaining.findIndex(
43661
+ (link) => linkSignature([link]) === linkSignature([expected])
43662
+ );
43663
+ if (index < 0) throw new Error("Appended HTML link not verified");
43664
+ remaining.splice(index, 1);
43665
+ }
43666
+ }
43667
+ function assertAppendedVisibleText(beforeHtml, afterHtml, expected) {
43668
+ const before = comparableVisibleText(beforeHtml);
43669
+ const after = comparableVisibleText(afterHtml);
43670
+ if (!after.startsWith(before)) throw new Error("Appended text not verified");
43671
+ const suffix = after.slice(before.length).replace(/\s+/gu, " ").trim();
43672
+ const wanted = expected.replace(/\s+/gu, " ").trim();
43673
+ if (!suffix || !suffix.includes(wanted)) throw new Error("Appended text not verified");
43674
+ }
43675
+ function appendNative(manager, request) {
43676
+ validateAppendContent(request.content, request.format);
43677
+ if (request.format === "markdown")
43678
+ return appendNative(manager, {
43679
+ ...request,
43680
+ content: appendMarkdownHtml(request.content),
43681
+ format: "html"
43682
+ });
43683
+ if (request.format === "html" && /<table\b/i.test(request.content))
43684
+ throw new Error("Use create-table for verified native table insertion");
43685
+ const op = request.format === "plaintext" ? "append-text" : request.format === "html" ? "append-html" : "append-markdown";
43686
+ const text = request.format === "html" ? "<div><br></div>" + request.content : "\n\n" + request.content;
43687
+ return mutateBackground(
43688
+ request,
43689
+ op,
43690
+ { text },
43691
+ (before, after) => {
43692
+ assertPreserved(before, after, { append: true });
43693
+ const expected = request.format === "html" ? comparableVisibleText(request.content) : request.format === "plaintext" ? request.content : null;
43694
+ if (expected) assertAppendedVisibleText(before.html, after.html, expected);
43695
+ if (request.format === "html")
43696
+ assertAppendedHtmlLinks(before.rich.links.length, after.rich.links, request.content);
43697
+ },
43698
+ backgroundDependencies(manager)
43699
+ );
43700
+ }
43701
+ function setNativeTag(manager, request) {
43702
+ const tag = normalizeNativeTags([request.tag])[0];
43703
+ const initial = readBackgroundSnapshot(manager, request.id);
43704
+ if (initial.hash !== request.expectedContentHash)
43705
+ throw new Error("Note revision changed; read it again");
43706
+ if (initial.rich.nativeTags.includes(tag) === request.present)
43707
+ return { ok: true, id: request.id, contentHash: initial.hash, changed: false };
43708
+ const deps = backgroundDependencies(manager);
43709
+ if (request.present)
43710
+ deps.run = ({ title, scopeText }) => runNativeTagsShortcut({ title, scopeText, tags: [tag] });
43711
+ return mutateBackground(
43712
+ request,
43713
+ request.present ? "add-tag" : "remove-tag",
43714
+ { tag },
43715
+ (before, after) => {
43716
+ assertPreserved(before, after, { tagChange: tag });
43717
+ if (after.rich.nativeTags.includes(tag) !== request.present)
43718
+ throw new Error("Native tag state not verified");
43719
+ const removed = before.rich.nativeObjectIds.filter(
43720
+ (id2) => !after.rich.nativeObjectIds.includes(id2)
43721
+ );
43722
+ const allowed = request.present ? [] : before.rich.nativeTagObjectIds?.[tag] || [];
43723
+ if (removed.some((id2) => !allowed.includes(id2)))
43724
+ throw new Error("Unrelated native object was lost");
43725
+ },
43726
+ deps
43727
+ );
43728
+ }
43729
+
43730
+ // src/tools/nativeOperations.ts
43731
+ var VERIFIED_BACKGROUND = /* @__PURE__ */ new Set([
43732
+ "append-native",
43733
+ "create-checklist-item",
43734
+ "create-table",
43735
+ "insert-note-link",
43736
+ "set-note-pinned",
43737
+ "remove-native-tags",
43738
+ "replace-native-tag"
43739
+ ]);
43740
+ var LIVE_VALIDATION_BLOCKERS = {};
43741
+ var signingRefusal = "Installed Shortcuts refuses to sign this Notes action (unsupported features); no background fallback is enabled";
43742
+ var UNAVAILABLE = {
43743
+ "set-checklist-item": signingRefusal,
43744
+ "delete-checklist-item": signingRefusal,
43745
+ "set-attachment-size": signingRefusal,
43746
+ "insert-mention": signingRefusal,
43747
+ "update-table-cells": "No background cell-editing action; replacing a table would change its identity and position",
43748
+ "edit-rich-note": "Native text replacement needs current UI selection; full-body rewriting is protected",
43749
+ "smart-folders": "No supported background interface for Smart Folder rules",
43750
+ "rename-tag-globally": "Cannot update Smart Folder references in background; use replace-native-tag on explicit notes",
43751
+ "sharing-permissions": "No supported background interface for sharing invitations or permissions",
43752
+ "note-lock": "Notes lock actions require the foreground and may require user authentication",
43753
+ "record-audio": "Recording requires the Notes UI",
43754
+ "transcribe-audio": "No supported background Notes transcription action",
43755
+ "scan-and-markup": "No supported background scanning or graphical markup action"
43756
+ };
43757
+ function requireValidated(name) {
43758
+ if (!VERIFIED_BACKGROUND.has(name) && process.env.APPLE_NOTES_MCP_ALLOW_UNVERIFIED !== "1")
43759
+ throw new Error(
43760
+ UNAVAILABLE[name] || LIVE_VALIDATION_BLOCKERS[name] || `${name} has not passed live background validation in this build; see get-capabilities`
43761
+ );
43762
+ }
43763
+ var id = external_exports.string().regex(/^x-coredata:\/\/[0-9a-f-]+\/ICNote\/p\d+$/i);
43764
+ var revision3 = external_exports.string().regex(/^sha256:[a-f0-9]{64}$/);
43765
+ var common = {
43766
+ id,
43767
+ expectedContentHash: revision3,
43768
+ scopeText: external_exports.string().min(12).max(500).describe(
43769
+ "Distinctive existing phrase used by Notes search. Prefer plain words without punctuation, hashtags, or paths."
43770
+ )
43771
+ };
43772
+ var htmlEscape = (s) => s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
43773
+ function registerNativeOperations(server2, manager) {
43774
+ function tool(name, description, input, handler, readOnly = false) {
43775
+ server2.registerTool(
43776
+ name,
43777
+ {
43778
+ description,
43779
+ inputSchema: input,
43780
+ outputSchema: external_exports.object({ ok: external_exports.boolean().optional() }).passthrough(),
43781
+ annotations: { readOnlyHint: readOnly }
43782
+ },
43783
+ (async (args) => {
43784
+ try {
43785
+ const result = handler(args);
43786
+ return {
43787
+ content: [{ type: "text", text: JSON.stringify(result) }],
43788
+ structuredContent: result
43789
+ };
43790
+ } catch (error2) {
43791
+ return {
43792
+ content: [
43793
+ {
43794
+ type: "text",
43795
+ text: error2 instanceof Error ? error2.message : "Operation failed"
43796
+ }
43797
+ ],
43798
+ isError: true
43799
+ };
43800
+ }
43801
+ })
43802
+ );
43803
+ }
43804
+ tool(
43805
+ "get-capabilities",
43806
+ "Use when: checking native background-edit support before calling a write tool.\nReturns: bridge installation, implementation, verification, availability, and specific limitations per operation.\nDo not use when: checking only the Native Tags bridge (native-tags-status).\nSafety: read-only; does not open Notes or run a mutation.",
43807
+ {},
43808
+ () => {
43809
+ let bridge;
43810
+ try {
43811
+ bridge = backgroundStatus();
43812
+ } catch {
43813
+ bridge = {
43814
+ installed: false,
43815
+ shortcut: "Apple Notes MCP - Background Operations v5",
43816
+ error: "Shortcuts helper unavailable"
43817
+ };
43818
+ }
43819
+ const native = [
43820
+ "append-native",
43821
+ "create-checklist-item",
43822
+ "create-table",
43823
+ "set-note-pinned",
43824
+ "remove-native-tags",
43825
+ "replace-native-tag",
43826
+ "insert-note-link"
43827
+ ];
43828
+ let tagBridgeInstalled = false;
43829
+ try {
43830
+ tagBridgeInstalled = nativeTagBridgeStatus().installed;
43831
+ } catch {
43832
+ }
43833
+ return {
43834
+ bridge,
43835
+ nativeTagBridgeInstalled: tagBridgeInstalled,
43836
+ mode: "background-only",
43837
+ operations: Object.fromEntries(
43838
+ native.map((name) => [
43839
+ name,
43840
+ {
43841
+ implemented: true,
43842
+ verified: VERIFIED_BACKGROUND.has(name),
43843
+ available: VERIFIED_BACKGROUND.has(name) && (!native.includes(name) || bridge.installed) && (name !== "replace-native-tag" || tagBridgeInstalled),
43844
+ reason: !VERIFIED_BACKGROUND.has(name) ? UNAVAILABLE[name] || LIVE_VALIDATION_BLOCKERS[name] || "Live validation pending; install the shortcut and complete the isolated acceptance tests" : native.includes(name) && !bridge.installed ? "Install the supplied shortcut once" : name === "replace-native-tag" && !tagBridgeInstalled ? "Install the verified Native Tags bridge for the addition phase" : void 0
43845
+ }
43846
+ ])
43847
+ ),
43848
+ unavailable: UNAVAILABLE
43849
+ };
43850
+ },
43851
+ true
43852
+ );
43853
+ tool(
43854
+ "append-native",
43855
+ "Use when: appending formatted content to a native-object note without replacing its body.\nReturns: exact-ID preservation and appended-content readback.\nDo not use when: the existing note can be safely handled by append-to-note or the scope phrase is ambiguous.\nSafety: requires a fresh revision and unique existing scope phrase of plain words; avoid punctuation, hashtags, and paths because Notes search may not resolve them literally. Supports bounded plaintext, semantic HTML, and Markdown without external fetching or automatic retries.",
43856
+ {
43857
+ ...common,
43858
+ content: external_exports.string().min(1).max(1024 * 1024),
43859
+ format: external_exports.enum(["plaintext", "html", "markdown"]).default("plaintext")
43860
+ },
43861
+ (args) => {
43862
+ requireValidated("append-native");
43863
+ return appendNative(manager, args);
43864
+ }
43865
+ );
43866
+ tool(
43867
+ "create-checklist-item",
43868
+ "Use when: appending one real unchecked Notes checklist item.\nReturns: the created checklist identity after exact-note readback.\nDo not use when: plain text is sufficient or more than one item is requested.\nSafety: preserves existing text, links, native objects, checklist identities, and formatting.",
43869
+ {
43870
+ ...common,
43871
+ text: external_exports.string().min(1).max(1e4).refine((s) => !/[\r\n\0]/u.test(s), "One line per checklist item")
43872
+ },
43873
+ (args) => {
43874
+ requireValidated("create-checklist-item");
43875
+ const result = mutateBackground(
43876
+ args,
43877
+ "create-checklist-item",
43878
+ { text: args.text },
43879
+ (before, after) => {
43880
+ assertPreserved(before, after, { append: true });
43881
+ const added = after.checklist.slice(before.checklist.length);
43882
+ if (added.length !== 1 || added[0].text !== args.text || added[0].done)
43883
+ throw new Error("Native checklist item not verified");
43884
+ },
43885
+ backgroundDependencies(manager)
43886
+ );
43887
+ return { ...result, items: readRichNote(args.id).checklistItems };
43888
+ }
43889
+ );
43890
+ tool(
43891
+ "create-table",
43892
+ "Use when: appending one native Notes table from a rectangular array of strings.\nReturns: the native table identity and decoded cells after readback.\nDo not use when: a text table is acceptable or the rows are not rectangular.\nSafety: never substitutes text; preserves existing rich content and reports failure unless the native table is verified.",
43893
+ {
43894
+ ...common,
43895
+ rows: external_exports.array(external_exports.array(external_exports.string().max(1e4)).min(1).max(100)).min(1).max(1e3)
43896
+ },
43897
+ (args) => {
43898
+ requireValidated("create-table");
43899
+ if (args.rows.some((row) => row.length !== args.rows[0].length))
43900
+ throw new Error("Table rows must have equal cell counts");
43901
+ const before = readRichNote(args.id);
43902
+ const content = "<table>" + args.rows.map(
43903
+ (row) => "<tr>" + row.map((v) => "<td>" + htmlEscape(v) + "</td>").join("") + "</tr>"
43904
+ ).join("") + "</table>";
43905
+ const result = mutateBackground(
43906
+ args,
43907
+ "append-html",
43908
+ { text: "<div><br></div>" + content },
43909
+ (oldNote, newNote) => {
43910
+ assertPreserved(oldNote, newNote, { append: true });
43911
+ const inserted = newNote.rich.objectData?.filter(
43912
+ (o) => o.type?.includes("table") && !oldNote.rich.nativeObjectIds.includes(o.id)
43913
+ ) || [];
43914
+ if (inserted.length !== 1 || JSON.stringify(parseNoteTable(Buffer.from(inserted[0].mergeable, "hex")).rows) !== JSON.stringify(args.rows))
43915
+ throw new Error("Native table cells not verified");
43916
+ },
43917
+ backgroundDependencies(manager)
43918
+ );
43919
+ const current = readRichNote(args.id);
43920
+ const added = current.objectData?.filter(
43921
+ (obj) => obj.type?.includes("table") && !before.nativeObjectIds.includes(obj.id)
43922
+ ) || [];
43923
+ if (added.length !== 1)
43924
+ throw new Error(
43925
+ "Table result uncertain; native table not verified. Read the note before retrying"
43926
+ );
43927
+ const table = parseNoteTable(Buffer.from(added[0].mergeable, "hex"));
43928
+ if (JSON.stringify(table.rows) !== JSON.stringify(args.rows))
43929
+ throw new Error("Native table cells not verified; read before retrying");
43930
+ return { ...result, table: { id: added[0].id, ...table } };
43931
+ }
43932
+ );
43933
+ tool(
43934
+ "set-note-pinned",
43935
+ "Use when: setting one exact note's pinned state.\nReturns: the verified requested state and new revision.\nDo not use when: only reading pinned metadata (get-note-metadata).\nSafety: checks expectedPinned and a fresh content revision before changing metadata; never rewrites the body.",
43936
+ { ...common, expectedPinned: external_exports.boolean(), pinned: external_exports.boolean() },
43937
+ (args) => {
43938
+ requireValidated("set-note-pinned");
43939
+ const deps = backgroundDependencies(manager);
43940
+ const s = deps.read(args.id);
43941
+ if (s.hash !== args.expectedContentHash || s.pinned !== args.expectedPinned)
43942
+ throw new Error("Note or pinned state changed; read it again");
43943
+ if (s.pinned === args.pinned)
43944
+ return { ok: true, id: args.id, pinned: s.pinned, contentHash: s.hash, changed: false };
43945
+ const run = deps.run;
43946
+ deps.run = (input) => {
43947
+ if (deps.read(args.id).pinned !== args.expectedPinned)
43948
+ throw new Error("Pinned state changed during preflight");
43949
+ run(input);
43950
+ };
43951
+ return {
43952
+ ...mutateBackground(
43953
+ args,
43954
+ "set-pinned",
43955
+ { change: args.pinned ? "add" : "remove" },
43956
+ (before, after) => {
43957
+ assertPreserved(before, after);
43958
+ if (after.pinned !== args.pinned) throw new Error("Pinned state not verified");
43959
+ },
43960
+ deps
43961
+ ),
43962
+ pinned: args.pinned
43963
+ };
43964
+ }
43965
+ );
43966
+ tool(
43967
+ "remove-native-tags",
43968
+ "Use when: removing specified native tags from one exact note.\nReturns: verified remaining tags and new revision.\nDo not use when: deleting a global tag definition or changing Smart Folder rules.\nSafety: preserves unrelated tags and native objects and never retries an uncertain mutation.",
43969
+ { ...common, tags: external_exports.array(external_exports.string().min(1).max(101)).min(1).max(100) },
43970
+ (args) => {
43971
+ requireValidated("remove-native-tags");
43972
+ let hash = args.expectedContentHash;
43973
+ const completed = [];
43974
+ for (const tag of normalizeNativeTags(args.tags)) {
43975
+ try {
43976
+ const result = setNativeTag(manager, {
43977
+ ...args,
43978
+ expectedContentHash: hash,
43979
+ tag,
43980
+ present: false
43981
+ });
43982
+ hash = result.contentHash;
43983
+ completed.push(tag);
43984
+ } catch (error2) {
43985
+ throw new Error(
43986
+ `Stopped after tags ${JSON.stringify(completed)}; read exact note before retry: ${String(error2)}`
43987
+ );
43988
+ }
43989
+ }
43990
+ return { ok: true, id: args.id, removed: completed, contentHash: hash };
43991
+ }
43992
+ );
43993
+ tool(
43994
+ "replace-native-tag",
43995
+ "Use when: replacing one native tag across an explicit list of freshly read notes.\nReturns: per-note results and remaining work after any failure.\nDo not use when: renaming global tag definitions or Smart Folder rules.\nSafety: adds and verifies the new tag before removing the old one and stops on the first uncertain result.",
43996
+ {
43997
+ notes: external_exports.array(external_exports.object(common)).min(1).max(100),
43998
+ oldTag: external_exports.string().min(1).max(101),
43999
+ newTag: external_exports.string().min(1).max(101)
44000
+ },
44001
+ (args) => {
44002
+ requireValidated("replace-native-tag");
44003
+ const [oldTag] = normalizeNativeTags([args.oldTag]);
44004
+ const [newTag] = normalizeNativeTags([args.newTag]);
44005
+ if (new Set(args.notes.map((n) => n.id)).size !== args.notes.length)
44006
+ throw new Error("Duplicate note IDs");
44007
+ for (const n of args.notes)
44008
+ if (readBackgroundSnapshot(manager, n.id).hash !== n.expectedContentHash)
44009
+ throw new Error("Note revision changed; no replacement started");
44010
+ const results = [];
44011
+ for (const n of args.notes) {
44012
+ try {
44013
+ const initial = readBackgroundSnapshot(manager, n.id);
44014
+ if (!initial.rich.nativeTags.includes(oldTag) || oldTag === newTag) {
44015
+ results.push({ id: n.id, changed: false });
44016
+ continue;
44017
+ }
44018
+ const added = setNativeTag(manager, { ...n, tag: newTag, present: true });
44019
+ const removed = setNativeTag(manager, {
44020
+ ...n,
44021
+ expectedContentHash: added.contentHash,
44022
+ tag: oldTag,
44023
+ present: false
44024
+ });
44025
+ results.push(removed);
44026
+ } catch (error2) {
44027
+ results.push({ id: n.id, ok: false, error: String(error2) });
44028
+ return { ok: false, results, remaining: args.notes.length - results.length };
44029
+ }
44030
+ }
44031
+ return { ok: true, results };
44032
+ }
44033
+ );
44034
+ tool(
44035
+ "insert-note-link",
44036
+ "Use when: appending a real Notes deep link to a native-object note.\nReturns: verified link destination and label after exact-note readback.\nDo not use when: only retrieving a deep link (get-note-link).\nSafety: retrieves the real target URL, preserves existing rich content, and creates a static label rather than a dynamic-title object.",
44037
+ { ...common, linkedNoteId: id, label: external_exports.string().min(1).max(2e3).optional() },
44038
+ (args) => {
44039
+ requireValidated("insert-note-link");
44040
+ const link = manager.getNoteLinkById(args.linkedNoteId);
44041
+ if (!link) throw new Error("Real Notes link unavailable");
44042
+ const linked = manager.getNoteById(args.linkedNoteId);
44043
+ if (!linked) throw new Error("Linked note not found");
44044
+ const result = appendNative(manager, {
44045
+ ...args,
44046
+ content: `<div><a href="${htmlEscape(link)}">${htmlEscape(args.label || linked.title)}</a></div>`,
44047
+ format: "html"
44048
+ });
44049
+ if (!readRichNote(args.id).links.some(
44050
+ (l) => l.url === link && l.text === (args.label || linked.title)
44051
+ ))
44052
+ throw new Error("Link result uncertain; read note before retrying");
44053
+ return result;
44054
+ }
44055
+ );
44056
+ }
44057
+
43194
44058
  // src/index.ts
43195
44059
  loadFileConfig();
43196
44060
  var require2 = createRequire(import.meta.url);
@@ -43202,6 +44066,8 @@ var server = new McpServer({
43202
44066
  });
43203
44067
  var notesManager = new AppleNotesManager();
43204
44068
  registerDirectOperations(server, notesManager);
44069
+ registerNativeTagsBridge(server, notesManager);
44070
+ registerNativeOperations(server, notesManager);
43205
44071
  function successResponse(message, structured) {
43206
44072
  const res = { content: [{ type: "text", text: message }] };
43207
44073
  if (structured) res.structuredContent = structured;
@@ -43249,17 +44115,17 @@ var noteIdInput = external_exports.string().min(1, "Note ID is required").max(MA
43249
44115
  var expectedContentHashInput = external_exports.string().regex(/^sha256:[a-f0-9]{64}$/, "expectedContentHash must come from get-note-content").describe(
43250
44116
  "Revision token returned by get-note-content for this exact ID. The mutation stops if the note changed since that read."
43251
44117
  );
43252
- function readExactNoteSnapshot(id) {
43253
- const note = notesManager.getNoteById(id);
43254
- if (!note) return { error: `Note with ID "${id}" not found` };
44118
+ function readExactNoteSnapshot(id2) {
44119
+ const note = notesManager.getNoteById(id2);
44120
+ if (!note) return { error: `Note with ID "${id2}" not found` };
43255
44121
  if (note.passwordProtected) {
43256
44122
  return {
43257
44123
  error: `Note "${note.title}" is password-protected and cannot be changed. Unlock it in Notes.app first.`
43258
44124
  };
43259
44125
  }
43260
- const body = notesManager.getNoteContentById(id);
44126
+ const body = notesManager.getNoteContentById(id2);
43261
44127
  if (!body) return { error: `Failed to read content of note "${note.title}"` };
43262
- const rich = enrichNoteRead(id, body);
44128
+ const rich = enrichNoteRead(id2, body);
43263
44129
  return { note, body, rich, contentHash: richContentHash(body, rich) };
43264
44130
  }
43265
44131
  function revisionConflictMessage(title) {
@@ -43440,28 +44306,28 @@ registerTool(
43440
44306
  truncated: external_exports.boolean().optional()
43441
44307
  }
43442
44308
  },
43443
- withErrorHandling(({ id, title, account }) => {
43444
- if (id) {
43445
- const note2 = notesManager.getNoteById(id);
44309
+ withErrorHandling(({ id: id2, title, account }) => {
44310
+ if (id2) {
44311
+ const note2 = notesManager.getNoteById(id2);
43446
44312
  if (!note2) {
43447
- return errorResponse(`Note with ID "${id}" not found`);
44313
+ return errorResponse(`Note with ID "${id2}" not found`);
43448
44314
  }
43449
44315
  if (note2.passwordProtected) {
43450
44316
  return errorResponse(
43451
44317
  `Note "${note2.title}" is password-protected and cannot be read. Unlock it in Notes.app first.`
43452
44318
  );
43453
44319
  }
43454
- const rawContent2 = notesManager.getNoteContentById(id);
44320
+ const rawContent2 = notesManager.getNoteContentById(id2);
43455
44321
  if (!rawContent2) {
43456
44322
  return errorResponse(`Failed to read content of note "${note2.title}"`);
43457
44323
  }
43458
- const rich2 = enrichNoteRead(id, rawContent2);
44324
+ const rich2 = enrichNoteRead(id2, rawContent2);
43459
44325
  const stripped2 = stripLargeInlineImages(rich2.content);
43460
44326
  const content2 = stripped2.html;
43461
44327
  const hashtags2 = parseHashtags(content2);
43462
44328
  const warning2 = [strippedImagesWarning(stripped2), rich2.warning].filter(Boolean).join("\n\n");
43463
44329
  return successResponse(warning2 ? content2 + warning2 : content2, {
43464
- id,
44330
+ id: id2,
43465
44331
  title: note2.title,
43466
44332
  content: content2,
43467
44333
  contentHash: richContentHash(rawContent2, rich2),
@@ -43469,6 +44335,11 @@ registerTool(
43469
44335
  nativeTags: rich2.nativeTags,
43470
44336
  richContentComplete: rich2.complete,
43471
44337
  writable: rich2.writable && stripped2.strippedCount === 0,
44338
+ supportedOperations: {
44339
+ fullBodyReplace: rich2.writable && stripped2.strippedCount === 0,
44340
+ nativeAppendImplemented: VERIFIED_BACKGROUND.has("append-native"),
44341
+ requiresShortcut: !rich2.writable
44342
+ },
43472
44343
  warning: rich2.warning,
43473
44344
  hashtags: hashtags2,
43474
44345
  strippedImages: stripped2.strippedCount,
@@ -43505,6 +44376,11 @@ registerTool(
43505
44376
  nativeTags: rich.nativeTags,
43506
44377
  richContentComplete: rich.complete,
43507
44378
  writable: rich.writable && stripped.strippedCount === 0,
44379
+ supportedOperations: {
44380
+ fullBodyReplace: rich.writable && stripped.strippedCount === 0,
44381
+ nativeAppendImplemented: VERIFIED_BACKGROUND.has("append-native"),
44382
+ requiresShortcut: !rich.writable
44383
+ },
43508
44384
  warning: rich.warning,
43509
44385
  hashtags,
43510
44386
  strippedImages: stripped.strippedCount,
@@ -43528,18 +44404,18 @@ registerTool(
43528
44404
  plaintext: external_exports.string().optional()
43529
44405
  }
43530
44406
  },
43531
- withErrorHandling(({ id, title, account }) => {
43532
- if (id) {
43533
- const note2 = notesManager.getNoteById(id);
44407
+ withErrorHandling(({ id: id2, title, account }) => {
44408
+ if (id2) {
44409
+ const note2 = notesManager.getNoteById(id2);
43534
44410
  if (!note2) {
43535
- return errorResponse(`Note with ID "${id}" not found`);
44411
+ return errorResponse(`Note with ID "${id2}" not found`);
43536
44412
  }
43537
44413
  if (note2.passwordProtected) {
43538
44414
  return errorResponse(
43539
44415
  `Note "${note2.title}" is password-protected and cannot be read. Unlock it in Notes.app first.`
43540
44416
  );
43541
44417
  }
43542
- const plaintext2 = notesManager.getNotePlaintextById(id);
44418
+ const plaintext2 = notesManager.getNotePlaintextById(id2);
43543
44419
  if (!plaintext2) {
43544
44420
  return errorResponse(`Failed to read plaintext of note "${note2.title}"`);
43545
44421
  }
@@ -43580,10 +44456,10 @@ registerTool(
43580
44456
  passwordProtected: external_exports.boolean().optional()
43581
44457
  }
43582
44458
  },
43583
- withErrorHandling(({ id }) => {
43584
- const note = notesManager.getNoteById(id);
44459
+ withErrorHandling(({ id: id2 }) => {
44460
+ const note = notesManager.getNoteById(id2);
43585
44461
  if (!note) {
43586
- return errorResponse(`Note with ID "${id}" not found`);
44462
+ return errorResponse(`Note with ID "${id2}" not found`);
43587
44463
  }
43588
44464
  const metadata = {
43589
44465
  id: note.id,
@@ -43641,12 +44517,12 @@ registerTool(
43641
44517
  separately: external_exports.boolean().optional()
43642
44518
  }
43643
44519
  },
43644
- withErrorHandling(({ id, separately = false }) => {
43645
- const success = notesManager.showNoteById(id, separately);
44520
+ withErrorHandling(({ id: id2, separately = false }) => {
44521
+ const success = notesManager.showNoteById(id2, separately);
43646
44522
  if (!success) {
43647
- return errorResponse(`Failed to show note with ID "${id}"`);
44523
+ return errorResponse(`Failed to show note with ID "${id2}"`);
43648
44524
  }
43649
- return successResponse(`Shown note with ID "${id}" in Notes.app`, { id, separately });
44525
+ return successResponse(`Shown note with ID "${id2}" in Notes.app`, { id: id2, separately });
43650
44526
  }, "Error showing note")
43651
44527
  );
43652
44528
  registerTool(
@@ -43664,24 +44540,24 @@ registerTool(
43664
44540
  url: external_exports.string().optional()
43665
44541
  }
43666
44542
  },
43667
- withErrorHandling(({ id, title, account }) => {
43668
- if (id) {
43669
- const note2 = notesManager.getNoteById(id);
44543
+ withErrorHandling(({ id: id2, title, account }) => {
44544
+ if (id2) {
44545
+ const note2 = notesManager.getNoteById(id2);
43670
44546
  if (!note2) {
43671
- return errorResponse(`Note with ID "${id}" not found`);
44547
+ return errorResponse(`Note with ID "${id2}" not found`);
43672
44548
  }
43673
44549
  if (note2.passwordProtected) {
43674
44550
  return errorResponse(
43675
44551
  `Note "${note2.title}" is password-protected. Unlock it in Notes.app first.`
43676
44552
  );
43677
44553
  }
43678
- const url2 = notesManager.getNoteLinkById(id);
44554
+ const url2 = notesManager.getNoteLinkById(id2);
43679
44555
  if (!url2) {
43680
44556
  return errorResponse(
43681
44557
  `Failed to get note link for "${note2.title}". The Notes database may not be accessible \u2014 grant Full Disk Access to the app that launches the server, fully quit and relaunch, then run the doctor tool. See: ${FULL_DISK_ACCESS_GUIDE_URL}. (On macOS 12\u201315 this also falls back to the AppleScript note link property.)`
43682
44558
  );
43683
44559
  }
43684
- return successResponse(`Note link: ${url2}`, { id, title: note2.title, url: url2 });
44560
+ return successResponse(`Note link: ${url2}`, { id: id2, title: note2.title, url: url2 });
43685
44561
  }
43686
44562
  if (!title) {
43687
44563
  return errorResponse("Either 'id' or 'title' is required");
@@ -43717,12 +44593,12 @@ registerTool(
43717
44593
  separately: external_exports.boolean().optional()
43718
44594
  }
43719
44595
  },
43720
- withErrorHandling(({ id, separately = false }) => {
43721
- const success = notesManager.showFolderById(id, separately);
44596
+ withErrorHandling(({ id: id2, separately = false }) => {
44597
+ const success = notesManager.showFolderById(id2, separately);
43722
44598
  if (!success) {
43723
- return errorResponse(`Failed to show folder with ID "${id}"`);
44599
+ return errorResponse(`Failed to show folder with ID "${id2}"`);
43724
44600
  }
43725
- return successResponse(`Shown folder with ID "${id}" in Notes.app`, { id, separately });
44601
+ return successResponse(`Shown folder with ID "${id2}" in Notes.app`, { id: id2, separately });
43726
44602
  }, "Error showing folder")
43727
44603
  );
43728
44604
  registerTool(
@@ -43738,12 +44614,12 @@ registerTool(
43738
44614
  separately: external_exports.boolean().optional()
43739
44615
  }
43740
44616
  },
43741
- withErrorHandling(({ id, separately = false }) => {
43742
- const success = notesManager.showAccountById(id, separately);
44617
+ withErrorHandling(({ id: id2, separately = false }) => {
44618
+ const success = notesManager.showAccountById(id2, separately);
43743
44619
  if (!success) {
43744
- return errorResponse(`Failed to show account with ID "${id}"`);
44620
+ return errorResponse(`Failed to show account with ID "${id2}"`);
43745
44621
  }
43746
- return successResponse(`Shown account with ID "${id}" in Notes.app`, { id, separately });
44622
+ return successResponse(`Shown account with ID "${id2}" in Notes.app`, { id: id2, separately });
43747
44623
  }, "Error showing account")
43748
44624
  );
43749
44625
  registerTool(
@@ -43762,17 +44638,17 @@ registerTool(
43762
44638
  },
43763
44639
  annotations: { readOnlyHint: true }
43764
44640
  },
43765
- withErrorHandling(({ id }) => {
43766
- const note = notesManager.getNoteById(id);
43767
- if (!note) return errorResponse(`Note with ID "${id}" not found`);
43768
- const body = notesManager.getNoteContentById(id);
44641
+ withErrorHandling(({ id: id2 }) => {
44642
+ const note = notesManager.getNoteById(id2);
44643
+ if (!note) return errorResponse(`Note with ID "${id2}" not found`);
44644
+ const body = notesManager.getNoteContentById(id2);
43769
44645
  if (!body) return errorResponse(`Failed to read content of note "${note.title}"`);
43770
- const rich = readRichNote(id);
44646
+ const rich = readRichNote(id2);
43771
44647
  const tables = (rich.objectData || []).filter((object3) => object3.type?.includes("table")).map((object3) => {
43772
44648
  try {
43773
44649
  return {
43774
44650
  id: object3.id,
43775
- attachmentId: id.replace(/ICNote\/p\d+$/, `ICAttachment/p${object3.pk}`),
44651
+ attachmentId: id2.replace(/ICNote\/p\d+$/, `ICAttachment/p${object3.pk}`),
43776
44652
  complete: true,
43777
44653
  ...parseNoteTable(Buffer.from(object3.mergeable, "hex"))
43778
44654
  };
@@ -43798,7 +44674,7 @@ registerTool(
43798
44674
  revision: rich.revision
43799
44675
  };
43800
44676
  return successResponse("Native objects read from the exact note", {
43801
- id,
44677
+ id: id2,
43802
44678
  contentHash: richContentHash(body, richRead),
43803
44679
  objects: rich.objects,
43804
44680
  checklistItems: rich.checklistItems,
@@ -43870,27 +44746,27 @@ registerTool(
43870
44746
  },
43871
44747
  withErrorHandling(
43872
44748
  ({
43873
- id,
44749
+ id: id2,
43874
44750
  expectedContentHash,
43875
44751
  newTitle,
43876
44752
  newContent,
43877
44753
  format = "plaintext",
43878
44754
  allowLinkChanges = false
43879
44755
  }) => {
43880
- const snapshot = readExactNoteSnapshot(id);
44756
+ const snapshot = readExactNoteSnapshot(id2);
43881
44757
  if ("error" in snapshot) return errorResponse(snapshot.error);
43882
44758
  if (snapshot.contentHash !== expectedContentHash) {
43883
44759
  return errorResponse(revisionConflictMessage(snapshot.note.title));
43884
44760
  }
43885
44761
  assertLinkedWrite(snapshot.rich, newContent, format, allowLinkChanges);
43886
- const attachments = notesManager.listAttachmentsById(id);
44762
+ const attachments = notesManager.listAttachmentsById(id2);
43887
44763
  if (attachments.length > 0) {
43888
44764
  return errorResponse(
43889
44765
  `Note "${snapshot.note.title}" has ${attachments.length} attachment(s). Full-body replacement is blocked; edit it in Notes.app.`
43890
44766
  );
43891
44767
  }
43892
44768
  const result = notesManager.updateNoteByIdIfUnchanged(
43893
- id,
44769
+ id2,
43894
44770
  snapshot.note.title,
43895
44771
  snapshot.body,
43896
44772
  newTitle,
@@ -43911,8 +44787,8 @@ registerTool(
43911
44787
  `The update result for note "${snapshot.note.title}" is uncertain. Read the exact ID before retrying.`
43912
44788
  );
43913
44789
  }
43914
- const readback = notesManager.getNoteContentById(id);
43915
- const richReadback = enrichNoteRead(id, readback || "");
44790
+ const readback = notesManager.getNoteContentById(id2);
44791
+ const richReadback = enrichNoteRead(id2, readback || "");
43916
44792
  const contentHash = readback ? richContentHash(readback, richReadback) : "";
43917
44793
  if (!richReadback.complete || linkSignature(richReadback.links) !== linkSignature(htmlLinks(result.writtenBody))) {
43918
44794
  return errorResponse(
@@ -43921,7 +44797,7 @@ registerTool(
43921
44797
  }
43922
44798
  if (!readback || comparableVisibleText(readback) !== comparableVisibleText(result.writtenBody)) {
43923
44799
  return errorResponse(
43924
- `The note accepted an update, but exact-ID readback visible text did not match. Do not retry automatically; inspect note ID ${id} in Notes.app.`
44800
+ `The note accepted an update, but exact-ID readback visible text did not match. Do not retry automatically; inspect note ID ${id2} in Notes.app.`
43925
44801
  );
43926
44802
  }
43927
44803
  const displayTitle = resolveUpdateResponseTitle(
@@ -43933,10 +44809,10 @@ registerTool(
43933
44809
  const sharedWarning = snapshot.note.shared ? "\n\n\u26A0\uFE0F This note is shared with collaborators. Your changes are visible to them." : "";
43934
44810
  const checklistWarning = detectChecklistAttempt(newContent) ?? "";
43935
44811
  return successResponse(
43936
- `Note updated; visible text verified: "${displayTitle}" [id: ${id}]${sharedWarning}${checklistWarning}`,
44812
+ `Note updated; visible text verified: "${displayTitle}" [id: ${id2}]${sharedWarning}${checklistWarning}`,
43937
44813
  {
43938
44814
  ok: true,
43939
- id,
44815
+ id: id2,
43940
44816
  title: displayTitle,
43941
44817
  shared: snapshot.note.shared ?? false,
43942
44818
  previousContentHash: expectedContentHash,
@@ -43951,11 +44827,12 @@ registerTool(
43951
44827
  registerTool(
43952
44828
  "append-to-note",
43953
44829
  {
43954
- description: "Use when: adding content to one exact note after reading it by id.\nReturns: exact id, new content hash, and visible-text readback verification.\nDo not use when: you only have a title, the note changed since the read, or it has attachments or native objects.\nSafety: append rewrites the HTML body, so it uses exact-ID, rich revision, native-object, attachment, link, and readback guards. Notes.app normalizes HTML, so rich formatting is not claimed as byte-identical.",
44830
+ description: "Use when: adding content to one exact note after reading it by id.\nReturns: exact id, new content hash, and visible-text readback verification.\nDo not use when: you only have a title or the note changed since the read.\nSafety: protected native-object notes use native end-append with scopeText; ordinary notes retain guarded HTML editing. Notes.app normalizes HTML, so rich formatting is not claimed as byte-identical.",
43955
44831
  inputSchema: {
43956
44832
  id: noteIdInput,
43957
44833
  expectedContentHash: expectedContentHashInput,
43958
44834
  content: external_exports.string().min(1, "Content to append is required").max(MAX.CONTENT).describe("Text to append to the note body"),
44835
+ scopeText: external_exports.string().min(12).max(500).optional().describe("Existing unique phrase required for native append to protected notes"),
43959
44836
  position: external_exports.enum(["after", "before"]).optional().default("after").describe(
43960
44837
  "Where to insert: 'after' appends to the end (default), 'before' prepends to the start"
43961
44838
  ),
@@ -43974,12 +44851,13 @@ registerTool(
43974
44851
  },
43975
44852
  withErrorHandling(
43976
44853
  ({
43977
- id,
44854
+ id: id2,
43978
44855
  expectedContentHash,
43979
44856
  content,
43980
44857
  position = "after",
43981
44858
  separator = "\n\n",
43982
- format = "plaintext"
44859
+ format = "plaintext",
44860
+ scopeText
43983
44861
  }) => {
43984
44862
  const contentToHtml = (text) => {
43985
44863
  if (format === "html") return text;
@@ -43994,17 +44872,32 @@ registerTool(
43994
44872
  const escaped = sep2.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
43995
44873
  return `<div>${escaped}</div>`;
43996
44874
  };
43997
- const snapshot = readExactNoteSnapshot(id);
44875
+ const snapshot = readExactNoteSnapshot(id2);
43998
44876
  if ("error" in snapshot) return errorResponse(snapshot.error);
43999
44877
  if (snapshot.contentHash !== expectedContentHash) {
44000
44878
  return errorResponse(revisionConflictMessage(snapshot.note.title));
44001
44879
  }
44002
44880
  if (!snapshot.rich.writable) {
44003
- return errorResponse(
44004
- snapshot.rich.warning || `Note "${snapshot.note.title}" contains native objects that cannot be preserved by a full-body append.`
44005
- );
44881
+ if (separator !== "\n\n")
44882
+ return errorResponse("Native append supports the default blank-line separator only");
44883
+ if (position !== "after")
44884
+ return errorResponse("Native append supports the end of a note only");
44885
+ if (!scopeText)
44886
+ return errorResponse("Provide scopeText: a unique existing phrase for native append");
44887
+ if (!VERIFIED_BACKGROUND.has("append-native"))
44888
+ return errorResponse(
44889
+ "Native append has not passed live validation; see get-capabilities"
44890
+ );
44891
+ const result2 = appendNative(notesManager, {
44892
+ id: id2,
44893
+ expectedContentHash,
44894
+ scopeText,
44895
+ content,
44896
+ format
44897
+ });
44898
+ return successResponse("Native append verified without replacing existing objects", result2);
44006
44899
  }
44007
- const attachments = notesManager.listAttachmentsById(id);
44900
+ const attachments = notesManager.listAttachmentsById(id2);
44008
44901
  if (attachments.length > 0) {
44009
44902
  return errorResponse(
44010
44903
  `Note "${snapshot.note.title}" has ${attachments.length} attachment(s). Append is blocked because it rewrites the full body; edit it in Notes.app.`
@@ -44018,7 +44911,7 @@ registerTool(
44018
44911
  const sepHtml = separatorToHtml(separator);
44019
44912
  const combinedBody = position === "before" ? titleDiv + newBlock + sepHtml + bodyHtml : titleDiv + bodyHtml + sepHtml + newBlock;
44020
44913
  const result = notesManager.updateNoteByIdIfUnchanged(
44021
- id,
44914
+ id2,
44022
44915
  snapshot.note.title,
44023
44916
  snapshot.body,
44024
44917
  void 0,
@@ -44039,8 +44932,8 @@ registerTool(
44039
44932
  `The append result for note "${snapshot.note.title}" is uncertain. Read the exact ID before retrying.`
44040
44933
  );
44041
44934
  }
44042
- const readback = notesManager.getNoteContentById(id);
44043
- const richReadback = enrichNoteRead(id, readback || "");
44935
+ const readback = notesManager.getNoteContentById(id2);
44936
+ const richReadback = enrichNoteRead(id2, readback || "");
44044
44937
  const contentHash = readback ? richContentHash(readback, richReadback) : "";
44045
44938
  if (!richReadback.complete || linkSignature(richReadback.links) !== linkSignature(htmlLinks(result.writtenBody))) {
44046
44939
  return errorResponse(
@@ -44049,7 +44942,7 @@ registerTool(
44049
44942
  }
44050
44943
  if (!readback || comparableVisibleText(readback) !== comparableVisibleText(result.writtenBody)) {
44051
44944
  return errorResponse(
44052
- `The note accepted an append, but exact-ID readback visible text did not match. Do not retry automatically; inspect note ID ${id} in Notes.app.`
44945
+ `The note accepted an append, but exact-ID readback visible text did not match. Do not retry automatically; inspect note ID ${id2} in Notes.app.`
44053
44946
  );
44054
44947
  }
44055
44948
  const sharedWarning = snapshot.note.shared ? "\n\n\u26A0\uFE0F This note is shared with collaborators. Your changes are visible to them." : "";
@@ -44057,7 +44950,7 @@ registerTool(
44057
44950
  `Note appended; visible text verified: "${snapshot.note.title}"${sharedWarning}`,
44058
44951
  {
44059
44952
  ok: true,
44060
- id,
44953
+ id: id2,
44061
44954
  title: snapshot.note.title,
44062
44955
  shared: snapshot.note.shared ?? false,
44063
44956
  previousContentHash: expectedContentHash,
@@ -44085,19 +44978,19 @@ registerTool(
44085
44978
  previousContentHash: external_exports.string().optional()
44086
44979
  }
44087
44980
  },
44088
- withErrorHandling(({ id, expectedContentHash }) => {
44089
- const snapshot = readExactNoteSnapshot(id);
44981
+ withErrorHandling(({ id: id2, expectedContentHash }) => {
44982
+ const snapshot = readExactNoteSnapshot(id2);
44090
44983
  if ("error" in snapshot) return errorResponse(snapshot.error);
44091
44984
  if (snapshot.contentHash !== expectedContentHash) {
44092
44985
  return errorResponse(revisionConflictMessage(snapshot.note.title));
44093
44986
  }
44094
- const result = notesManager.deleteNoteByIdIfUnchanged(id, snapshot.body);
44987
+ const result = notesManager.deleteNoteByIdIfUnchanged(id2, snapshot.body);
44095
44988
  if (result.status === "conflict") {
44096
44989
  return errorResponse(revisionConflictMessage(snapshot.note.title));
44097
44990
  }
44098
44991
  if (result.status !== "deleted") {
44099
44992
  return errorResponse(
44100
- `The delete result for note "${snapshot.note.title}" is uncertain. Inspect exact ID ${id} before retrying.`
44993
+ `The delete result for note "${snapshot.note.title}" is uncertain. Inspect exact ID ${id2} before retrying.`
44101
44994
  );
44102
44995
  }
44103
44996
  const sharedWarning = snapshot.note.shared ? "\n\n\u26A0\uFE0F This note was shared with collaborators. They will no longer have access." : "";
@@ -44105,7 +44998,7 @@ registerTool(
44105
44998
  `Note moved to Recently Deleted: "${snapshot.note.title}"${sharedWarning}`,
44106
44999
  {
44107
45000
  ok: true,
44108
- id,
45001
+ id: id2,
44109
45002
  title: snapshot.note.title,
44110
45003
  wasShared: snapshot.note.shared ?? false,
44111
45004
  previousContentHash: expectedContentHash
@@ -44130,26 +45023,26 @@ registerTool(
44130
45023
  verified: external_exports.boolean().optional()
44131
45024
  }
44132
45025
  },
44133
- withErrorHandling(({ id, folder, account }) => {
44134
- const note = notesManager.getNoteById(id);
45026
+ withErrorHandling(({ id: id2, folder, account }) => {
45027
+ const note = notesManager.getNoteById(id2);
44135
45028
  if (!note) {
44136
- return errorResponse(`Note with ID "${id}" not found`);
45029
+ return errorResponse(`Note with ID "${id2}" not found`);
44137
45030
  }
44138
- const success = notesManager.moveNoteById(id, folder, account);
45031
+ const success = notesManager.moveNoteById(id2, folder, account);
44139
45032
  if (!success) {
44140
45033
  return errorResponse(
44141
45034
  `Failed to move note "${note.title}" to folder "${folder}". Folder may not exist.`
44142
45035
  );
44143
45036
  }
44144
- const readback = notesManager.getNoteById(id);
44145
- if (!readback || readback.id !== id) {
45037
+ const readback = notesManager.getNoteById(id2);
45038
+ if (!readback || readback.id !== id2) {
44146
45039
  return errorResponse(
44147
- `The move may have succeeded, but exact-ID readback failed. Inspect note ID ${id} before retrying.`
45040
+ `The move may have succeeded, but exact-ID readback failed. Inspect note ID ${id2} before retrying.`
44148
45041
  );
44149
45042
  }
44150
45043
  return successResponse(`Note moved and verified: "${readback.title}" -> "${folder}"`, {
44151
45044
  ok: true,
44152
- id,
45045
+ id: id2,
44153
45046
  title: readback.title,
44154
45047
  folder,
44155
45048
  verified: true
@@ -44544,13 +45437,13 @@ registerTool(
44544
45437
  count: external_exports.number().optional()
44545
45438
  }
44546
45439
  },
44547
- withErrorHandling(({ id, title, account }) => {
44548
- if (id) {
44549
- const note2 = notesManager.getNoteById(id);
45440
+ withErrorHandling(({ id: id2, title, account }) => {
45441
+ if (id2) {
45442
+ const note2 = notesManager.getNoteById(id2);
44550
45443
  if (!note2) {
44551
- return errorResponse(`Note with ID "${id}" not found`);
45444
+ return errorResponse(`Note with ID "${id2}" not found`);
44552
45445
  }
44553
- const attachments2 = notesManager.listAttachmentsById(id);
45446
+ const attachments2 = notesManager.listAttachmentsById(id2);
44554
45447
  if (attachments2.length === 0) {
44555
45448
  return successResponse(`Note "${note2.title}" has no attachments`, {
44556
45449
  attachments: [],
@@ -44608,18 +45501,18 @@ registerTool(
44608
45501
  if (notes.length === 0) {
44609
45502
  return errorResponse("No reviewed notes provided");
44610
45503
  }
44611
- const results = notes.map(({ id, expectedContentHash }) => {
44612
- const snapshot = readExactNoteSnapshot(id);
44613
- if ("error" in snapshot) return { id, success: false, error: snapshot.error };
45504
+ const results = notes.map(({ id: id2, expectedContentHash }) => {
45505
+ const snapshot = readExactNoteSnapshot(id2);
45506
+ if ("error" in snapshot) return { id: id2, success: false, error: snapshot.error };
44614
45507
  if (snapshot.contentHash !== expectedContentHash) {
44615
- return { id, success: false, error: revisionConflictMessage(snapshot.note.title) };
45508
+ return { id: id2, success: false, error: revisionConflictMessage(snapshot.note.title) };
44616
45509
  }
44617
- const result = notesManager.deleteNoteByIdIfUnchanged(id, snapshot.body);
44618
- if (result.status === "deleted") return { id, success: true };
45510
+ const result = notesManager.deleteNoteByIdIfUnchanged(id2, snapshot.body);
45511
+ if (result.status === "deleted") return { id: id2, success: true };
44619
45512
  if (result.status === "conflict") {
44620
- return { id, success: false, error: revisionConflictMessage(snapshot.note.title) };
45513
+ return { id: id2, success: false, error: revisionConflictMessage(snapshot.note.title) };
44621
45514
  }
44622
- return { id, success: false, error: "Delete result uncertain; inspect this exact ID" };
45515
+ return { id: id2, success: false, error: "Delete result uncertain; inspect this exact ID" };
44623
45516
  });
44624
45517
  const succeeded = results.filter((r) => r.success).length;
44625
45518
  const failed = results.filter((r) => !r.success).length;
@@ -44697,8 +45590,8 @@ registerTool(
44697
45590
  contentType: external_exports.string().optional()
44698
45591
  }
44699
45592
  },
44700
- withErrorHandling(({ noteId: noteId2, attachmentId, savePath }) => {
44701
- const r = notesManager.saveAttachmentById(noteId2, attachmentId, savePath);
45593
+ withErrorHandling(({ noteId: noteId3, attachmentId, savePath }) => {
45594
+ const r = notesManager.saveAttachmentById(noteId3, attachmentId, savePath);
44702
45595
  if (!r.success) {
44703
45596
  return errorResponse(`Failed to save attachment: ${r.error ?? "unknown error"}`);
44704
45597
  }
@@ -44724,8 +45617,8 @@ registerTool(
44724
45617
  base64: external_exports.string().optional()
44725
45618
  }
44726
45619
  },
44727
- withErrorHandling(({ noteId: noteId2, attachmentId }) => {
44728
- const r = notesManager.getAttachmentBase64ById(noteId2, attachmentId);
45620
+ withErrorHandling(({ noteId: noteId3, attachmentId }) => {
45621
+ const r = notesManager.getAttachmentBase64ById(noteId3, attachmentId);
44729
45622
  if (!r.success || !r.base64) {
44730
45623
  return errorResponse(`Failed to fetch attachment: ${r.error ?? "unknown error"}`);
44731
45624
  }
@@ -44750,13 +45643,13 @@ registerTool(
44750
45643
  separately: external_exports.boolean().optional()
44751
45644
  }
44752
45645
  },
44753
- withErrorHandling(({ noteId: noteId2, attachmentId, separately = false }) => {
44754
- const success = notesManager.showAttachmentById(noteId2, attachmentId, separately);
45646
+ withErrorHandling(({ noteId: noteId3, attachmentId, separately = false }) => {
45647
+ const success = notesManager.showAttachmentById(noteId3, attachmentId, separately);
44755
45648
  if (!success) {
44756
- return errorResponse(`Failed to show attachment "${attachmentId}" on note "${noteId2}"`);
45649
+ return errorResponse(`Failed to show attachment "${attachmentId}" on note "${noteId3}"`);
44757
45650
  }
44758
45651
  return successResponse(`Shown attachment "${attachmentId}" in Notes.app`, {
44759
- noteId: noteId2,
45652
+ noteId: noteId3,
44760
45653
  attachmentId,
44761
45654
  separately
44762
45655
  });
@@ -44807,11 +45700,11 @@ registerTool(
44807
45700
  markdown: external_exports.string().optional()
44808
45701
  }
44809
45702
  },
44810
- withErrorHandling(({ id, title, account }) => {
44811
- if (id) {
44812
- const markdown2 = notesManager.getNoteMarkdownById(id);
45703
+ withErrorHandling(({ id: id2, title, account }) => {
45704
+ if (id2) {
45705
+ const markdown2 = notesManager.getNoteMarkdownById(id2);
44813
45706
  if (!markdown2) {
44814
- return errorResponse(`Note with ID "${id}" not found or has no content`);
45707
+ return errorResponse(`Note with ID "${id2}" not found or has no content`);
44815
45708
  }
44816
45709
  return successResponse(markdown2, { markdown: markdown2 });
44817
45710
  }
@@ -44840,17 +45733,17 @@ registerTool(
44840
45733
  total: external_exports.number().optional()
44841
45734
  }
44842
45735
  },
44843
- withErrorHandling(({ id }) => {
44844
- const note = notesManager.getNoteById(id);
45736
+ withErrorHandling(({ id: id2 }) => {
45737
+ const note = notesManager.getNoteById(id2);
44845
45738
  if (!note) {
44846
- return errorResponse(`Note with ID "${id}" not found`);
45739
+ return errorResponse(`Note with ID "${id2}" not found`);
44847
45740
  }
44848
45741
  if (note.passwordProtected) {
44849
45742
  return errorResponse(
44850
45743
  `Note "${note.title}" is password-protected and cannot be read. Unlock it in Notes.app first.`
44851
45744
  );
44852
45745
  }
44853
- const result = getChecklistItems(id);
45746
+ const result = getChecklistItems(id2);
44854
45747
  if (!result.items) {
44855
45748
  return errorResponse(result.message || "Failed to read checklist state.");
44856
45749
  }
@@ -44882,13 +45775,13 @@ registerTool(
44882
45775
  smartFolderQuery: external_exports.string().optional()
44883
45776
  }
44884
45777
  },
44885
- withErrorHandling(({ id }) => {
44886
- const { metadata, message } = getNoteMetadata(id);
45778
+ withErrorHandling(({ id: id2 }) => {
45779
+ const { metadata, message } = getNoteMetadata(id2);
44887
45780
  if (!metadata) {
44888
- return errorResponse(message || `Failed to read metadata for note "${id}"`);
45781
+ return errorResponse(message || `Failed to read metadata for note "${id2}"`);
44889
45782
  }
44890
45783
  const keys = Object.keys(metadata);
44891
- const summary = keys.length === 0 ? `No additional metadata is available for note "${id}" on this macOS version.` : keys.map((k) => `${k}: ${String(metadata[k])}`).join("\n");
45784
+ const summary = keys.length === 0 ? `No additional metadata is available for note "${id2}" on this macOS version.` : keys.map((k) => `${k}: ${String(metadata[k])}`).join("\n");
44892
45785
  return successResponse(summary, metadata);
44893
45786
  }, "Error reading note metadata")
44894
45787
  );