apple-notes-mcp 2.8.35 → 2.8.37

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +93 -8
  2. package/build/index.js +2012 -420
  3. package/package.json +1 -1
package/build/index.js CHANGED
@@ -417,11 +417,11 @@ var require_codegen = __commonJS({
417
417
  const rhs = this.rhs === void 0 ? "" : ` = ${this.rhs}`;
418
418
  return `${varKind} ${this.name}${rhs};` + _n;
419
419
  }
420
- optimizeNames(names, constants5) {
420
+ optimizeNames(names, constants6) {
421
421
  if (!names[this.name.str])
422
422
  return;
423
423
  if (this.rhs)
424
- this.rhs = optimizeExpr(this.rhs, names, constants5);
424
+ this.rhs = optimizeExpr(this.rhs, names, constants6);
425
425
  return this;
426
426
  }
427
427
  get names() {
@@ -438,10 +438,10 @@ var require_codegen = __commonJS({
438
438
  render({ _n }) {
439
439
  return `${this.lhs} = ${this.rhs};` + _n;
440
440
  }
441
- optimizeNames(names, constants5) {
441
+ optimizeNames(names, constants6) {
442
442
  if (this.lhs instanceof code_1.Name && !names[this.lhs.str] && !this.sideEffects)
443
443
  return;
444
- this.rhs = optimizeExpr(this.rhs, names, constants5);
444
+ this.rhs = optimizeExpr(this.rhs, names, constants6);
445
445
  return this;
446
446
  }
447
447
  get names() {
@@ -502,8 +502,8 @@ var require_codegen = __commonJS({
502
502
  optimizeNodes() {
503
503
  return `${this.code}` ? this : void 0;
504
504
  }
505
- optimizeNames(names, constants5) {
506
- this.code = optimizeExpr(this.code, names, constants5);
505
+ optimizeNames(names, constants6) {
506
+ this.code = optimizeExpr(this.code, names, constants6);
507
507
  return this;
508
508
  }
509
509
  get names() {
@@ -532,12 +532,12 @@ var require_codegen = __commonJS({
532
532
  }
533
533
  return nodes.length > 0 ? this : void 0;
534
534
  }
535
- optimizeNames(names, constants5) {
535
+ optimizeNames(names, constants6) {
536
536
  const { nodes } = this;
537
537
  let i = nodes.length;
538
538
  while (i--) {
539
539
  const n = nodes[i];
540
- if (n.optimizeNames(names, constants5))
540
+ if (n.optimizeNames(names, constants6))
541
541
  continue;
542
542
  subtractNames(names, n.names);
543
543
  nodes.splice(i, 1);
@@ -590,12 +590,12 @@ var require_codegen = __commonJS({
590
590
  return void 0;
591
591
  return this;
592
592
  }
593
- optimizeNames(names, constants5) {
593
+ optimizeNames(names, constants6) {
594
594
  var _a;
595
- this.else = (_a = this.else) === null || _a === void 0 ? void 0 : _a.optimizeNames(names, constants5);
596
- if (!(super.optimizeNames(names, constants5) || this.else))
595
+ this.else = (_a = this.else) === null || _a === void 0 ? void 0 : _a.optimizeNames(names, constants6);
596
+ if (!(super.optimizeNames(names, constants6) || this.else))
597
597
  return;
598
- this.condition = optimizeExpr(this.condition, names, constants5);
598
+ this.condition = optimizeExpr(this.condition, names, constants6);
599
599
  return this;
600
600
  }
601
601
  get names() {
@@ -618,10 +618,10 @@ var require_codegen = __commonJS({
618
618
  render(opts) {
619
619
  return `for(${this.iteration})` + super.render(opts);
620
620
  }
621
- optimizeNames(names, constants5) {
622
- if (!super.optimizeNames(names, constants5))
621
+ optimizeNames(names, constants6) {
622
+ if (!super.optimizeNames(names, constants6))
623
623
  return;
624
- this.iteration = optimizeExpr(this.iteration, names, constants5);
624
+ this.iteration = optimizeExpr(this.iteration, names, constants6);
625
625
  return this;
626
626
  }
627
627
  get names() {
@@ -657,10 +657,10 @@ var require_codegen = __commonJS({
657
657
  render(opts) {
658
658
  return `for(${this.varKind} ${this.name} ${this.loop} ${this.iterable})` + super.render(opts);
659
659
  }
660
- optimizeNames(names, constants5) {
661
- if (!super.optimizeNames(names, constants5))
660
+ optimizeNames(names, constants6) {
661
+ if (!super.optimizeNames(names, constants6))
662
662
  return;
663
- this.iterable = optimizeExpr(this.iterable, names, constants5);
663
+ this.iterable = optimizeExpr(this.iterable, names, constants6);
664
664
  return this;
665
665
  }
666
666
  get names() {
@@ -702,11 +702,11 @@ var require_codegen = __commonJS({
702
702
  (_b = this.finally) === null || _b === void 0 ? void 0 : _b.optimizeNodes();
703
703
  return this;
704
704
  }
705
- optimizeNames(names, constants5) {
705
+ optimizeNames(names, constants6) {
706
706
  var _a, _b;
707
- super.optimizeNames(names, constants5);
708
- (_a = this.catch) === null || _a === void 0 ? void 0 : _a.optimizeNames(names, constants5);
709
- (_b = this.finally) === null || _b === void 0 ? void 0 : _b.optimizeNames(names, constants5);
707
+ super.optimizeNames(names, constants6);
708
+ (_a = this.catch) === null || _a === void 0 ? void 0 : _a.optimizeNames(names, constants6);
709
+ (_b = this.finally) === null || _b === void 0 ? void 0 : _b.optimizeNames(names, constants6);
710
710
  return this;
711
711
  }
712
712
  get names() {
@@ -1007,7 +1007,7 @@ var require_codegen = __commonJS({
1007
1007
  function addExprNames(names, from) {
1008
1008
  return from instanceof code_1._CodeOrName ? addNames(names, from.names) : names;
1009
1009
  }
1010
- function optimizeExpr(expr, names, constants5) {
1010
+ function optimizeExpr(expr, names, constants6) {
1011
1011
  if (expr instanceof code_1.Name)
1012
1012
  return replaceName(expr);
1013
1013
  if (!canOptimize(expr))
@@ -1022,14 +1022,14 @@ var require_codegen = __commonJS({
1022
1022
  return items;
1023
1023
  }, []));
1024
1024
  function replaceName(n) {
1025
- const c = constants5[n.str];
1025
+ const c = constants6[n.str];
1026
1026
  if (c === void 0 || names[n.str] !== 1)
1027
1027
  return n;
1028
1028
  delete names[n.str];
1029
1029
  return c;
1030
1030
  }
1031
1031
  function canOptimize(e) {
1032
- return e instanceof code_1._Code && e._items.some((c) => c instanceof code_1.Name && names[c.str] === 1 && constants5[c.str] !== void 0);
1032
+ return e instanceof code_1._Code && e._items.some((c) => c instanceof code_1.Name && names[c.str] === 1 && constants6[c.str] !== void 0);
1033
1033
  }
1034
1034
  }
1035
1035
  function subtractNames(names, from) {
@@ -2991,7 +2991,7 @@ var require_compile = __commonJS({
2991
2991
  const schOrFunc = root.refs[ref];
2992
2992
  if (schOrFunc)
2993
2993
  return schOrFunc;
2994
- let _sch = resolve4.call(this, root, ref);
2994
+ let _sch = resolve5.call(this, root, ref);
2995
2995
  if (_sch === void 0) {
2996
2996
  const schema = (_a = root.localRefs) === null || _a === void 0 ? void 0 : _a[ref];
2997
2997
  const { schemaId } = this.opts;
@@ -3018,7 +3018,7 @@ var require_compile = __commonJS({
3018
3018
  function sameSchemaEnv(s1, s2) {
3019
3019
  return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
3020
3020
  }
3021
- function resolve4(root, ref) {
3021
+ function resolve5(root, ref) {
3022
3022
  let sch;
3023
3023
  while (typeof (sch = this.refs[ref]) == "string")
3024
3024
  ref = sch;
@@ -3268,8 +3268,8 @@ var require_utils = __commonJS({
3268
3268
  }
3269
3269
  return ind;
3270
3270
  }
3271
- function removeDotSegments(path7) {
3272
- let input = path7;
3271
+ function removeDotSegments(path8) {
3272
+ let input = path8;
3273
3273
  const output = [];
3274
3274
  let nextSlash = -1;
3275
3275
  let len = 0;
@@ -3674,8 +3674,8 @@ var require_schemes = __commonJS({
3674
3674
  }
3675
3675
  if (wsComponent.resourceName) {
3676
3676
  const queryIndex = wsComponent.resourceName.indexOf("?");
3677
- const path7 = queryIndex === -1 ? wsComponent.resourceName : wsComponent.resourceName.slice(0, queryIndex);
3678
- wsComponent.path = path7 && path7 !== "/" ? path7 : void 0;
3677
+ const path8 = queryIndex === -1 ? wsComponent.resourceName : wsComponent.resourceName.slice(0, queryIndex);
3678
+ wsComponent.path = path8 && path8 !== "/" ? path8 : void 0;
3679
3679
  wsComponent.query = queryIndex === -1 ? void 0 : wsComponent.resourceName.slice(queryIndex + 1);
3680
3680
  wsComponent.resourceName = void 0;
3681
3681
  }
@@ -3843,7 +3843,7 @@ var require_fast_uri = __commonJS({
3843
3843
  }
3844
3844
  return uri;
3845
3845
  }
3846
- function resolve4(baseURI, relativeURI, options) {
3846
+ function resolve5(baseURI, relativeURI, options) {
3847
3847
  const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
3848
3848
  const {
3849
3849
  parsed: baseParsed,
@@ -3876,49 +3876,49 @@ var require_fast_uri = __commonJS({
3876
3876
  schemelessOptions.skipEscape = true;
3877
3877
  return serialize(resolved, schemelessOptions);
3878
3878
  }
3879
- function resolveComponent(base, relative3, options, skipNormalization) {
3879
+ function resolveComponent(base, relative4, options, skipNormalization) {
3880
3880
  const target = {};
3881
3881
  if (!skipNormalization) {
3882
3882
  base = parse3(serialize(base, options), options);
3883
- relative3 = parse3(serialize(relative3, options), options);
3883
+ relative4 = parse3(serialize(relative4, options), options);
3884
3884
  }
3885
3885
  options = options || {};
3886
- if (!options.tolerant && relative3.scheme) {
3887
- target.scheme = relative3.scheme;
3888
- target.userinfo = relative3.userinfo;
3889
- target.host = relative3.host;
3890
- target.port = relative3.port;
3891
- target.path = removeDotSegments(relative3.path || "");
3892
- target.query = relative3.query;
3886
+ if (!options.tolerant && relative4.scheme) {
3887
+ target.scheme = relative4.scheme;
3888
+ target.userinfo = relative4.userinfo;
3889
+ target.host = relative4.host;
3890
+ target.port = relative4.port;
3891
+ target.path = removeDotSegments(relative4.path || "");
3892
+ target.query = relative4.query;
3893
3893
  } else {
3894
- if (relative3.userinfo !== void 0 || relative3.host !== void 0 || relative3.port !== void 0) {
3895
- target.userinfo = relative3.userinfo;
3896
- target.host = relative3.host;
3897
- target.port = relative3.port;
3898
- target.path = removeDotSegments(relative3.path || "");
3899
- target.query = relative3.query;
3894
+ if (relative4.userinfo !== void 0 || relative4.host !== void 0 || relative4.port !== void 0) {
3895
+ target.userinfo = relative4.userinfo;
3896
+ target.host = relative4.host;
3897
+ target.port = relative4.port;
3898
+ target.path = removeDotSegments(relative4.path || "");
3899
+ target.query = relative4.query;
3900
3900
  } else {
3901
- if (!relative3.path) {
3901
+ if (!relative4.path) {
3902
3902
  target.path = base.path;
3903
- if (relative3.query !== void 0) {
3904
- target.query = relative3.query;
3903
+ if (relative4.query !== void 0) {
3904
+ target.query = relative4.query;
3905
3905
  } else {
3906
3906
  target.query = base.query;
3907
3907
  }
3908
3908
  } else {
3909
- if (relative3.path[0] === "/") {
3910
- target.path = removeDotSegments(relative3.path);
3909
+ if (relative4.path[0] === "/") {
3910
+ target.path = removeDotSegments(relative4.path);
3911
3911
  } else {
3912
3912
  if ((base.userinfo !== void 0 || base.host !== void 0 || base.port !== void 0) && !base.path) {
3913
- target.path = "/" + relative3.path;
3913
+ target.path = "/" + relative4.path;
3914
3914
  } else if (!base.path) {
3915
- target.path = relative3.path;
3915
+ target.path = relative4.path;
3916
3916
  } else {
3917
- target.path = base.path.slice(0, base.path.lastIndexOf("/") + 1) + relative3.path;
3917
+ target.path = base.path.slice(0, base.path.lastIndexOf("/") + 1) + relative4.path;
3918
3918
  }
3919
3919
  target.path = removeDotSegments(target.path);
3920
3920
  }
3921
- target.query = relative3.query;
3921
+ target.query = relative4.query;
3922
3922
  }
3923
3923
  target.userinfo = base.userinfo;
3924
3924
  target.host = base.host;
@@ -3926,7 +3926,7 @@ var require_fast_uri = __commonJS({
3926
3926
  }
3927
3927
  target.scheme = base.scheme;
3928
3928
  }
3929
- target.fragment = relative3.fragment;
3929
+ target.fragment = relative4.fragment;
3930
3930
  return target;
3931
3931
  }
3932
3932
  function equal(uriA, uriB, options) {
@@ -4205,7 +4205,7 @@ var require_fast_uri = __commonJS({
4205
4205
  var fastUri = {
4206
4206
  SCHEMES,
4207
4207
  normalize,
4208
- resolve: resolve4,
4208
+ resolve: resolve5,
4209
4209
  resolveComponent,
4210
4210
  equal,
4211
4211
  serialize,
@@ -4620,7 +4620,7 @@ var require_core = __commonJS({
4620
4620
  errorsText(errors = this.errors, { separator = ", ", dataVar = "data" } = {}) {
4621
4621
  if (!errors || errors.length === 0)
4622
4622
  return "No errors";
4623
- return errors.map((e) => `${dataVar}${e.instancePath} ${e.message}`).reduce((text, msg) => text + separator + msg);
4623
+ return errors.map((e) => `${dataVar}${e.instancePath} ${e.message}`).reduce((text2, msg) => text2 + separator + msg);
4624
4624
  }
4625
4625
  $dataMetaSchema(metaSchema, keywordsJsonPointers) {
4626
4626
  const rules = this.RULES.all;
@@ -7181,12 +7181,12 @@ var require_dist = __commonJS({
7181
7181
  throw new Error(`Unknown format "${name}"`);
7182
7182
  return f;
7183
7183
  };
7184
- function addFormats(ajv, list, fs7, exportName) {
7184
+ function addFormats(ajv, list, fs8, exportName) {
7185
7185
  var _a;
7186
7186
  var _b;
7187
7187
  (_a = (_b = ajv.opts.code).formats) !== null && _a !== void 0 ? _a : _b.formats = (0, codegen_1._)`require("ajv-formats/dist/formats").${exportName}`;
7188
7188
  for (const f of list)
7189
- ajv.addFormat(f, fs7[f]);
7189
+ ajv.addFormat(f, fs8[f]);
7190
7190
  }
7191
7191
  module.exports = exports = formatsPlugin;
7192
7192
  Object.defineProperty(exports, "__esModule", { value: true });
@@ -7422,7 +7422,7 @@ var require_DOMException = __commonJS({
7422
7422
  "INVALID_NODE_TYPE_ERR (24): the supplied node is invalid or has an invalid ancestor for this operation",
7423
7423
  "DATA_CLONE_ERR (25): the object can not be cloned."
7424
7424
  ];
7425
- var constants5 = {
7425
+ var constants6 = {
7426
7426
  INDEX_SIZE_ERR,
7427
7427
  DOMSTRING_SIZE_ERR: 2,
7428
7428
  // historical
@@ -7461,8 +7461,8 @@ var require_DOMException = __commonJS({
7461
7461
  this.name = names[code];
7462
7462
  }
7463
7463
  DOMException.prototype.__proto__ = Error.prototype;
7464
- for (c in constants5) {
7465
- v = { value: constants5[c] };
7464
+ for (c in constants6) {
7465
+ v = { value: constants6[c] };
7466
7466
  Object.defineProperty(DOMException, c, v);
7467
7467
  Object.defineProperty(DOMException.prototype, c, v);
7468
7468
  }
@@ -9621,8 +9621,8 @@ var require_select = __commonJS({
9621
9621
  // Non-standard, for compatibility purposes.
9622
9622
  ":contains": function(param) {
9623
9623
  return function(el) {
9624
- var text = el.innerText || el.textContent || el.value || "";
9625
- return text.indexOf(param) !== -1;
9624
+ var text2 = el.innerText || el.textContent || el.value || "";
9625
+ return text2.indexOf(param) !== -1;
9626
9626
  };
9627
9627
  },
9628
9628
  ":has": function(param) {
@@ -10289,9 +10289,9 @@ var require_Element = __commonJS({
10289
10289
  position = utils.toASCIILowerCase(String(position));
10290
10290
  this._insertAdjacent(position, textNode);
10291
10291
  } },
10292
- insertAdjacentHTML: { value: function insertAdjacentHTML(position, text) {
10292
+ insertAdjacentHTML: { value: function insertAdjacentHTML(position, text2) {
10293
10293
  position = utils.toASCIILowerCase(String(position));
10294
- text = String(text);
10294
+ text2 = String(text2);
10295
10295
  var context;
10296
10296
  switch (position) {
10297
10297
  case "beforebegin":
@@ -10315,7 +10315,7 @@ var require_Element = __commonJS({
10315
10315
  this.ownerDocument._address,
10316
10316
  context
10317
10317
  );
10318
- parser.parse(text, true);
10318
+ parser.parse(text2, true);
10319
10319
  this._insertAdjacent(position, parser._asDocumentFragment());
10320
10320
  } },
10321
10321
  children: { get: function() {
@@ -12184,9 +12184,9 @@ var require_URL = __commonJS({
12184
12184
  },
12185
12185
  // See: http://tools.ietf.org/html/rfc3986#section-5.2
12186
12186
  // and https://url.spec.whatwg.org/#constructors
12187
- resolve: function(relative3) {
12187
+ resolve: function(relative4) {
12188
12188
  var base = this;
12189
- var r = new URL2(relative3);
12189
+ var r = new URL2(relative4);
12190
12190
  var t = new URL2();
12191
12191
  if (r.scheme !== void 0) {
12192
12192
  t.scheme = r.scheme;
@@ -12238,32 +12238,32 @@ var require_URL = __commonJS({
12238
12238
  else
12239
12239
  return basepath.substring(0, lastslash + 1) + refpath;
12240
12240
  }
12241
- function remove_dot_segments(path7) {
12242
- if (!path7) return path7;
12241
+ function remove_dot_segments(path8) {
12242
+ if (!path8) return path8;
12243
12243
  var output = "";
12244
- while (path7.length > 0) {
12245
- if (path7 === "." || path7 === "..") {
12246
- path7 = "";
12244
+ while (path8.length > 0) {
12245
+ if (path8 === "." || path8 === "..") {
12246
+ path8 = "";
12247
12247
  break;
12248
12248
  }
12249
- var twochars = path7.substring(0, 2);
12250
- var threechars = path7.substring(0, 3);
12251
- var fourchars = path7.substring(0, 4);
12249
+ var twochars = path8.substring(0, 2);
12250
+ var threechars = path8.substring(0, 3);
12251
+ var fourchars = path8.substring(0, 4);
12252
12252
  if (threechars === "../") {
12253
- path7 = path7.substring(3);
12253
+ path8 = path8.substring(3);
12254
12254
  } else if (twochars === "./") {
12255
- path7 = path7.substring(2);
12255
+ path8 = path8.substring(2);
12256
12256
  } else if (threechars === "/./") {
12257
- path7 = "/" + path7.substring(3);
12258
- } else if (twochars === "/." && path7.length === 2) {
12259
- path7 = "/";
12260
- } else if (fourchars === "/../" || threechars === "/.." && path7.length === 3) {
12261
- path7 = "/" + path7.substring(4);
12257
+ path8 = "/" + path8.substring(3);
12258
+ } else if (twochars === "/." && path8.length === 2) {
12259
+ path8 = "/";
12260
+ } else if (fourchars === "/../" || threechars === "/.." && path8.length === 3) {
12261
+ path8 = "/" + path8.substring(4);
12262
12262
  output = output.replace(/\/?[^\/]*$/, "");
12263
12263
  } else {
12264
- var segment = path7.match(/(\/?([^\/]*))/)[0];
12264
+ var segment = path8.match(/(\/?([^\/]*))/)[0];
12265
12265
  output += segment;
12266
- path7 = path7.substring(segment.length);
12266
+ path8 = path8.substring(segment.length);
12267
12267
  }
12268
12268
  }
12269
12269
  return output;
@@ -12434,9 +12434,9 @@ var require_CSSStyleDeclaration = __commonJS({
12434
12434
  // Note that the styles don't get parsed until they're actually needed
12435
12435
  _parsed: { get: function() {
12436
12436
  if (!this._parsedStyles || this.cssText !== this._lastParsedText) {
12437
- var text = this.cssText;
12438
- this._parsedStyles = parseStyles(text);
12439
- this._lastParsedText = text;
12437
+ var text2 = this.cssText;
12438
+ this._parsedStyles = parseStyles(text2);
12439
+ this._lastParsedText = text2;
12440
12440
  delete this._names;
12441
12441
  }
12442
12442
  return this._parsedStyles;
@@ -23907,7 +23907,7 @@ var require_turndown_cjs = __commonJS({
23907
23907
  });
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
- function escapeMarkdown(string3) {
23910
+ function escapeMarkdown2(string3) {
23911
23911
  return markdownEscapes.reduce(function(accumulator, escape3) {
23912
23912
  return accumulator.replace(escape3[0], escape3[1]);
23913
23913
  }, string3);
@@ -24087,7 +24087,7 @@ var require_turndown_cjs = __commonJS({
24087
24087
  rules.image = {
24088
24088
  filter: "img",
24089
24089
  replacement: function(content, node) {
24090
- var alt = escapeMarkdown(cleanAttribute(node.getAttribute("alt")));
24090
+ var alt = escapeMarkdown2(cleanAttribute(node.getAttribute("alt")));
24091
24091
  var src = escapeLinkDestination(node.getAttribute("src") || "");
24092
24092
  var title = cleanAttribute(node.getAttribute("title"));
24093
24093
  var titlePart = title ? ' "' + escapeLinkTitle(title) + '"' : "";
@@ -24181,15 +24181,15 @@ var require_turndown_cjs = __commonJS({
24181
24181
  var node = next(prev, element, isPre);
24182
24182
  while (node !== element) {
24183
24183
  if (node.nodeType === 3 || node.nodeType === 4) {
24184
- var text = node.data.replace(/[ \r\n\t]+/g, " ");
24185
- if ((!prevText || / $/.test(prevText.data)) && !keepLeadingWs && text[0] === " ") {
24186
- text = text.substr(1);
24184
+ var text2 = node.data.replace(/[ \r\n\t]+/g, " ");
24185
+ if ((!prevText || / $/.test(prevText.data)) && !keepLeadingWs && text2[0] === " ") {
24186
+ text2 = text2.substr(1);
24187
24187
  }
24188
- if (!text) {
24188
+ if (!text2) {
24189
24189
  node = remove(node);
24190
24190
  continue;
24191
24191
  }
24192
- node.data = text;
24192
+ node.data = text2;
24193
24193
  prevText = node;
24194
24194
  } else if (node.nodeType === 1) {
24195
24195
  if (isBlock2(node) || node.nodeName === "BR") {
@@ -24452,7 +24452,7 @@ var require_turndown_cjs = __commonJS({
24452
24452
  * @type String
24453
24453
  */
24454
24454
  escape: function(string3) {
24455
- return escapeMarkdown(string3);
24455
+ return escapeMarkdown2(string3);
24456
24456
  }
24457
24457
  };
24458
24458
  function process3(parentNode) {
@@ -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 join18(output, replacement);
24468
+ return join21(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 = join18(output, rule.append(self.options));
24475
+ output = join21(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 join18(output, replacement) {
24487
+ function join21(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);
@@ -24979,8 +24979,8 @@ function getErrorMap() {
24979
24979
 
24980
24980
  // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/parseUtil.js
24981
24981
  var makeIssue = (params) => {
24982
- const { data, path: path7, errorMaps, issueData } = params;
24983
- const fullPath = [...path7, ...issueData.path || []];
24982
+ const { data, path: path8, errorMaps, issueData } = params;
24983
+ const fullPath = [...path8, ...issueData.path || []];
24984
24984
  const fullIssue = {
24985
24985
  ...issueData,
24986
24986
  path: fullPath
@@ -25096,11 +25096,11 @@ var errorUtil;
25096
25096
 
25097
25097
  // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/types.js
25098
25098
  var ParseInputLazyPath = class {
25099
- constructor(parent, value, path7, key) {
25099
+ constructor(parent, value, path8, key) {
25100
25100
  this._cachedPath = [];
25101
25101
  this.parent = parent;
25102
25102
  this.data = value;
25103
- this._path = path7;
25103
+ this._path = path8;
25104
25104
  this._key = key;
25105
25105
  }
25106
25106
  get path() {
@@ -28737,10 +28737,10 @@ function assignProp(target, prop, value) {
28737
28737
  configurable: true
28738
28738
  });
28739
28739
  }
28740
- function getElementAtPath(obj, path7) {
28741
- if (!path7)
28740
+ function getElementAtPath(obj, path8) {
28741
+ if (!path8)
28742
28742
  return obj;
28743
- return path7.reduce((acc, key) => acc?.[key], obj);
28743
+ return path8.reduce((acc, key) => acc?.[key], obj);
28744
28744
  }
28745
28745
  function promiseAllObject(promisesObj) {
28746
28746
  const keys = Object.keys(promisesObj);
@@ -29060,11 +29060,11 @@ function aborted(x, startIndex = 0) {
29060
29060
  }
29061
29061
  return false;
29062
29062
  }
29063
- function prefixIssues(path7, issues) {
29063
+ function prefixIssues(path8, issues) {
29064
29064
  return issues.map((iss) => {
29065
29065
  var _a;
29066
29066
  (_a = iss).path ?? (_a.path = []);
29067
- iss.path.unshift(path7);
29067
+ iss.path.unshift(path8);
29068
29068
  return iss;
29069
29069
  });
29070
29070
  }
@@ -32475,11 +32475,11 @@ function normalizeObjectSchema(schema) {
32475
32475
  }
32476
32476
  return void 0;
32477
32477
  }
32478
- function getDotPath(path7) {
32479
- if (path7.length === 0) {
32478
+ function getDotPath(path8) {
32479
+ if (path8.length === 0) {
32480
32480
  return "object root";
32481
32481
  }
32482
- return path7.reduce((acc, seg, index) => {
32482
+ return path8.reduce((acc, seg, index) => {
32483
32483
  if (index === 0) {
32484
32484
  return String(seg);
32485
32485
  }
@@ -36608,7 +36608,7 @@ var Protocol = class {
36608
36608
  return;
36609
36609
  }
36610
36610
  const pollInterval = task2.pollInterval ?? this._options?.defaultTaskPollInterval ?? 1e3;
36611
- await new Promise((resolve4) => setTimeout(resolve4, pollInterval));
36611
+ await new Promise((resolve5) => setTimeout(resolve5, pollInterval));
36612
36612
  options?.signal?.throwIfAborted();
36613
36613
  }
36614
36614
  } catch (error2) {
@@ -36625,7 +36625,7 @@ var Protocol = class {
36625
36625
  */
36626
36626
  request(request, resultSchema, options) {
36627
36627
  const { relatedRequestId, resumptionToken, onresumptiontoken, task, relatedTask } = options ?? {};
36628
- return new Promise((resolve4, reject) => {
36628
+ return new Promise((resolve5, reject) => {
36629
36629
  const earlyReject = (error2) => {
36630
36630
  reject(error2);
36631
36631
  };
@@ -36703,7 +36703,7 @@ var Protocol = class {
36703
36703
  if (!parseResult.success) {
36704
36704
  reject(parseResult.error);
36705
36705
  } else {
36706
- resolve4(parseResult.data);
36706
+ resolve5(parseResult.data);
36707
36707
  }
36708
36708
  } catch (error2) {
36709
36709
  reject(error2);
@@ -36964,12 +36964,12 @@ var Protocol = class {
36964
36964
  }
36965
36965
  } catch {
36966
36966
  }
36967
- return new Promise((resolve4, reject) => {
36967
+ return new Promise((resolve5, reject) => {
36968
36968
  if (signal.aborted) {
36969
36969
  reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
36970
36970
  return;
36971
36971
  }
36972
- const timeoutId = setTimeout(resolve4, interval);
36972
+ const timeoutId = setTimeout(resolve5, interval);
36973
36973
  signal.addEventListener("abort", () => {
36974
36974
  clearTimeout(timeoutId);
36975
36975
  reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
@@ -38282,7 +38282,7 @@ var McpServer = class {
38282
38282
  let task = createTaskResult.task;
38283
38283
  const pollInterval = task.pollInterval ?? 5e3;
38284
38284
  while (task.status !== "completed" && task.status !== "failed" && task.status !== "cancelled") {
38285
- await new Promise((resolve4) => setTimeout(resolve4, pollInterval));
38285
+ await new Promise((resolve5) => setTimeout(resolve5, pollInterval));
38286
38286
  const updatedTask = await extra.taskStore.getTask(taskId);
38287
38287
  if (!updatedTask) {
38288
38288
  throw new McpError(ErrorCode.InternalError, `Task ${taskId} not found during polling`);
@@ -38970,12 +38970,12 @@ var StdioServerTransport = class {
38970
38970
  this.onclose?.();
38971
38971
  }
38972
38972
  send(message) {
38973
- return new Promise((resolve4) => {
38973
+ return new Promise((resolve5) => {
38974
38974
  const json2 = serializeMessage(message);
38975
38975
  if (this._stdout.write(json2)) {
38976
- resolve4();
38976
+ resolve5();
38977
38977
  } else {
38978
- this._stdout.once("drain", resolve4);
38978
+ this._stdout.once("drain", resolve5);
38979
38979
  }
38980
38980
  });
38981
38981
  }
@@ -39418,12 +39418,12 @@ function fixed32Float(field) {
39418
39418
  }
39419
39419
 
39420
39420
  // src/utils/checklistRuns.ts
39421
- function checklistRunLineStart(text, position, length) {
39421
+ function checklistRunLineStart(text2, position, length) {
39422
39422
  const end = position + length;
39423
39423
  let anchor = position;
39424
- while (anchor < end && text[anchor] === "\n") anchor++;
39424
+ while (anchor < end && text2[anchor] === "\n") anchor++;
39425
39425
  if (anchor === end) anchor = position;
39426
- return anchor === 0 ? 0 : text.lastIndexOf("\n", anchor - 1) + 1;
39426
+ return anchor === 0 ? 0 : text2.lastIndexOf("\n", anchor - 1) + 1;
39427
39427
  }
39428
39428
 
39429
39429
  // src/utils/checklistParser.ts
@@ -39625,8 +39625,8 @@ import { join as join2 } from "node:path";
39625
39625
  import { gunzipSync as gunzipSync2 } from "node:zlib";
39626
39626
  var dbPath = join2(homedir2(), "Library/Group Containers/group.com.apple.notes/NoteStore.sqlite");
39627
39627
  var safeUrl = (url) => /^(?:https?:\/\/|notes:\/\/|applenotes:|mailto:)/i.test(url) && !Array.from(url).some((char) => char.charCodeAt(0) < 32);
39628
- var escapeAttribute = (text) => text.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;");
39629
- var normalized = (text) => text.replace(/[\s\ufffc]/gu, "");
39628
+ var escapeAttribute = (text2) => text2.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;");
39629
+ var normalized = (text2) => text2.replace(/[\s\ufffc]/gu, "");
39630
39630
  function styleValue(field) {
39631
39631
  if (!(field.value instanceof Uint8Array)) return field.value;
39632
39632
  if (field.fieldNumber === 2) {
@@ -39659,8 +39659,8 @@ function parseRichNote(data, nativeTags = []) {
39659
39659
  const doc = decodeMessage(data);
39660
39660
  const wrapper = embeddedMessage(getField(doc, 2));
39661
39661
  const body = wrapper && embeddedMessage(getField(wrapper, 3));
39662
- const text = body && stringValue(getField(body, 2));
39663
- if (!body || text === void 0) throw new Error("Unsupported Notes document structure");
39662
+ const text2 = body && stringValue(getField(body, 2));
39663
+ if (!body || text2 === void 0) throw new Error("Unsupported Notes document structure");
39664
39664
  const links = [];
39665
39665
  const nativeObjectIds = [];
39666
39666
  const objects = [];
@@ -39673,7 +39673,7 @@ function parseRichNote(data, nativeTags = []) {
39673
39673
  const fields = embeddedMessage(run);
39674
39674
  if (!fields) throw new Error("Invalid Notes attribute run");
39675
39675
  const length = varintValue(getField(fields, 1));
39676
- if (length === void 0 || length < 0 || position + length > text.length)
39676
+ if (length === void 0 || length < 0 || position + length > text2.length)
39677
39677
  throw new Error("Invalid Notes run length");
39678
39678
  const paragraph = embeddedMessage(getField(fields, 2));
39679
39679
  styleRuns.push({
@@ -39692,9 +39692,9 @@ function parseRichNote(data, nativeTags = []) {
39692
39692
  const previous = links.at(-1);
39693
39693
  if (previous?.url === url && previous.start + previous.length === position) {
39694
39694
  previous.length += length;
39695
- previous.text += text.slice(position, position + length);
39695
+ previous.text += text2.slice(position, position + length);
39696
39696
  } else
39697
- links.push({ start: position, length, text: text.slice(position, position + length), url });
39697
+ links.push({ start: position, length, text: text2.slice(position, position + length), url });
39698
39698
  }
39699
39699
  hasNativeObjects ||= Boolean(getField(fields, 12));
39700
39700
  const attachment = embeddedMessage(getField(fields, 12));
@@ -39712,23 +39712,23 @@ function parseRichNote(data, nativeTags = []) {
39712
39712
  const checklist = embeddedMessage(getField(paragraph, 5));
39713
39713
  const rawId = checklist && getField(checklist, 1)?.value;
39714
39714
  const itemId = rawId instanceof Uint8Array ? Buffer.from(rawId).toString("hex") : "";
39715
- const start = checklistRunLineStart(text, position, length);
39715
+ const start = checklistRunLineStart(text2, position, length);
39716
39716
  if (itemId && !checklistItems.some((item) => item.id === itemId))
39717
39717
  checklistItems.push({
39718
39718
  id: itemId,
39719
39719
  start,
39720
- text: text.slice(
39720
+ text: text2.slice(
39721
39721
  start,
39722
- text.indexOf("\n", start) === -1 ? text.length : text.indexOf("\n", start)
39722
+ text2.indexOf("\n", start) === -1 ? text2.length : text2.indexOf("\n", start)
39723
39723
  ),
39724
39724
  done: checklist ? varintValue(getField(checklist, 2)) === 1 : false
39725
39725
  });
39726
39726
  }
39727
39727
  position += length;
39728
39728
  }
39729
- if (position !== text.length) throw new Error("Incomplete Notes attribute runs");
39729
+ if (position !== text2.length) throw new Error("Incomplete Notes attribute runs");
39730
39730
  return {
39731
- text,
39731
+ text: text2,
39732
39732
  links,
39733
39733
  nativeTags: hasNativeObjects ? nativeTags : [],
39734
39734
  nativeObjectIds,
@@ -40014,8 +40014,8 @@ function parseAudioRecording(data) {
40014
40014
  const registerNoteText = (id2) => {
40015
40015
  const target = registerTarget(id2);
40016
40016
  const note = target && sub(target, 10);
40017
- const text = note && stringValue(getField(note, 2));
40018
- return text?.replace(/\n+$/u, "") || void 0;
40017
+ const text2 = note && stringValue(getField(note, 2));
40018
+ return text2?.replace(/\n+$/u, "") || void 0;
40019
40019
  };
40020
40020
  const recordings = entries2.map((e) => customMap(e)).filter((m) => m?.type === "com.apple.notes.ICTTAudioRecording");
40021
40021
  if (recordings.length !== 1) throw new Error("Expected exactly one audio recording object");
@@ -40054,13 +40054,13 @@ function parseAudioRecording(data) {
40054
40054
  const segment = customMap(entry(segmentIndex));
40055
40055
  if (segment?.type !== "com.apple.notes.ICTTTranscriptSegment")
40056
40056
  throw new Error("Unexpected segment type");
40057
- const text = registerPrimitive(segment.values.get("text"));
40058
- if (typeof text !== "string") throw new Error("Segment without text");
40057
+ const text2 = registerPrimitive(segment.values.get("text"));
40058
+ if (typeof text2 !== "string") throw new Error("Segment without text");
40059
40059
  const start = registerPrimitive(segment.values.get("timestamp"));
40060
40060
  const duration3 = registerPrimitive(segment.values.get("duration"));
40061
40061
  const speaker = registerPrimitive(segment.values.get("speaker"));
40062
40062
  segments.push({
40063
- text,
40063
+ text: text2,
40064
40064
  ...typeof start === "number" ? { start } : {},
40065
40065
  ...typeof duration3 === "number" ? { duration: duration3 } : {},
40066
40066
  ...typeof speaker === "string" && speaker ? { speaker } : {}
@@ -40080,10 +40080,10 @@ function parseAudioRecording(data) {
40080
40080
  }
40081
40081
  function joinSegments(segments) {
40082
40082
  let out = "";
40083
- for (const { text } of segments) {
40084
- if (!text) continue;
40085
- const glue = !out || /\s$/u.test(out) || /^\s/u.test(text) || /^[.,!?;:%)\]}…'’]/u.test(text) ? "" : " ";
40086
- out += glue + text;
40083
+ for (const { text: text2 } of segments) {
40084
+ if (!text2) continue;
40085
+ const glue = !out || /\s$/u.test(out) || /^\s/u.test(text2) || /^[.,!?;:%)\]}…'’]/u.test(text2) ? "" : " ";
40086
+ out += glue + text2;
40087
40087
  }
40088
40088
  return out.trim();
40089
40089
  }
@@ -40217,14 +40217,14 @@ function describeRow(row, store, options, maxSegments) {
40217
40217
  const all = recording.fragments.flatMap(
40218
40218
  (fragment, i) => fragment.segments.map((s) => multi ? { ...s, fragment: i } : s)
40219
40219
  );
40220
- const text = recording.fragments.map((f) => joinSegments(f.segments)).filter(Boolean).join("\n\n");
40220
+ const text2 = recording.fragments.map((f) => joinSegments(f.segments)).filter(Boolean).join("\n\n");
40221
40221
  const speakers = [...new Set(all.flatMap((s) => s.speaker ? [s.speaker] : []))];
40222
40222
  return {
40223
40223
  ...base,
40224
40224
  status: all.length ? "ok" : "none",
40225
40225
  fragmentCount: recording.fragments.length,
40226
40226
  wordCount: all.length,
40227
- ...text ? { text } : {},
40227
+ ...text2 ? { text: text2 } : {},
40228
40228
  ...speakers.length ? { speakers } : {},
40229
40229
  ...recording.summary ? { summary: recording.summary } : {},
40230
40230
  ...recording.topLineSummary ? { topLineSummary: recording.topLineSummary } : {},
@@ -40378,18 +40378,18 @@ function decodeTable(compressed, strict) {
40378
40378
  const ri = rows.map.get(uuidIndex(num(sub2(row, 1), 6)));
40379
40379
  if (ri === void 0 || ci === void 0) continue;
40380
40380
  const note = sub2(entry(num(sub2(row, 2), 6)), 10);
40381
- const text = stringValue(getField(note, 2));
40382
- if (text === void 0 || text.includes("\uFFFC")) {
40381
+ const text2 = stringValue(getField(note, 2));
40382
+ if (text2 === void 0 || text2.includes("\uFFFC")) {
40383
40383
  if (strict) throw new Error("Embedded or unsupported table cell");
40384
40384
  values[ri][ci] = null;
40385
40385
  incomplete.push({
40386
40386
  ri,
40387
40387
  ci,
40388
- reason: text === void 0 ? "Cell text is missing" : "Cell contains an embedded object"
40388
+ reason: text2 === void 0 ? "Cell text is missing" : "Cell contains an embedded object"
40389
40389
  });
40390
40390
  continue;
40391
40391
  }
40392
- values[ri][ci] = text.replace(/\n$/u, "");
40392
+ values[ri][ci] = text2.replace(/\n$/u, "");
40393
40393
  }
40394
40394
  }
40395
40395
  const rtl = entries2.some((e) => {
@@ -40409,8 +40409,8 @@ function decodeTable(compressed, strict) {
40409
40409
 
40410
40410
  // src/utils/tableMarkdown.ts
40411
40411
  var UNDECODED_CELL_MARKER = "[undecoded cell]";
40412
- function escapeMarkdownTableCell(text) {
40413
- return text.replace(/\\/g, "\\\\").replace(/\|/g, "\\|").replace(/\r\n|[\r\n\u2028\u2029]/g, "<br>");
40412
+ function escapeMarkdownTableCell(text2) {
40413
+ return text2.replace(/\\/g, "\\\\").replace(/\|/g, "\\|").replace(/\r\n|[\r\n\u2028\u2029]/g, "<br>");
40414
40414
  }
40415
40415
  function renderMarkdownTable(rows) {
40416
40416
  const width = rows.reduce((max, row) => Math.max(max, row.length), 0);
@@ -40550,8 +40550,8 @@ var Decoder = class {
40550
40550
  }
40551
40551
  /** Mark a positively described leaf as an Exclude rule. */
40552
40552
  negate(filter) {
40553
- const text = filter.description;
40554
- const negated = text.startsWith("has ") ? text.replace(/^has /, "does not have ") : text.startsWith("is ") ? text.replace(/^is /, "is not ") : text.startsWith("mentions ") ? text.replace(/^mentions /, "does not mention ") : `not ${text}`;
40553
+ const text2 = filter.description;
40554
+ const negated = text2.startsWith("has ") ? text2.replace(/^has /, "does not have ") : text2.startsWith("is ") ? text2.replace(/^is /, "is not ") : text2.startsWith("mentions ") ? text2.replace(/^mentions /, "does not mention ") : `not ${text2}`;
40555
40555
  return { ...filter, excluded: true, description: negated };
40556
40556
  }
40557
40557
  clause(clause, excluded, depth) {
@@ -40582,7 +40582,7 @@ var Decoder = class {
40582
40582
  * positively and negated by the caller.
40583
40583
  */
40584
40584
  leaf(key, value, excluded) {
40585
- const flag = (description, negative) => typeof value === "boolean" ? {
40585
+ const flag2 = (description, negative) => typeof value === "boolean" ? {
40586
40586
  type: key,
40587
40587
  value,
40588
40588
  ...excluded ? { excluded: true } : {},
@@ -40590,25 +40590,25 @@ var Decoder = class {
40590
40590
  } : null;
40591
40591
  switch (key) {
40592
40592
  case "checklist":
40593
- return flag("has a checklist", "has no checklist");
40593
+ return flag2("has a checklist", "has no checklist");
40594
40594
  case "checklistInProgress":
40595
- return flag("has an unfinished checklist", "has no unfinished checklist");
40595
+ return flag2("has an unfinished checklist", "has no unfinished checklist");
40596
40596
  case "checklistCompleted":
40597
- return flag("has a completed checklist", "has no completed checklist");
40597
+ return flag2("has a completed checklist", "has no completed checklist");
40598
40598
  case "attachment":
40599
- return flag("has attachments", "has no attachments");
40599
+ return flag2("has attachments", "has no attachments");
40600
40600
  case "pinned":
40601
- return flag("is pinned", "is not pinned");
40601
+ return flag2("is pinned", "is not pinned");
40602
40602
  case "systemPaper":
40603
- return flag("is a Quick Note", "is not a Quick Note");
40603
+ return flag2("is a Quick Note", "is not a Quick Note");
40604
40604
  case "passwordProtected":
40605
- return flag("is locked", "is not locked");
40605
+ return flag2("is locked", "is not locked");
40606
40606
  case "shared":
40607
- return flag("is shared", "is not shared");
40607
+ return flag2("is shared", "is not shared");
40608
40608
  case "mention":
40609
- return flag("mentions anyone", "mentions no one");
40609
+ return flag2("mentions anyone", "mentions no one");
40610
40610
  case "tagged":
40611
- return flag("has any tag", "has no tags");
40611
+ return flag2("has any tag", "has no tags");
40612
40612
  case "attachmentSection": {
40613
40613
  if (typeof value !== "number" || !ATTACHMENT_SECTIONS[value]) return null;
40614
40614
  return {
@@ -40784,7 +40784,7 @@ function buildSmartFolders(output) {
40784
40784
  if (lines.length < 4) throw new Error("Unexpected smart folder query output");
40785
40785
  const [storeUuid, rowsJson, foldersJson, tagsJson] = lines;
40786
40786
  if (!/^[0-9A-F-]+$/i.test(storeUuid)) throw new Error("Unexpected Notes store identifier");
40787
- const coreDataId2 = (entity2, pk) => `x-coredata://${storeUuid}/${entity2}/p${pk}`;
40787
+ const coreDataId2 = (entity3, pk) => `x-coredata://${storeUuid}/${entity3}/p${pk}`;
40788
40788
  const rows = JSON.parse(rowsJson);
40789
40789
  const folderRows = JSON.parse(foldersJson || "{}");
40790
40790
  const tagRows = JSON.parse(tagsJson || "[]");
@@ -40881,8 +40881,8 @@ function allowedSaveRoots() {
40881
40881
  "/private/tmp"
40882
40882
  ];
40883
40883
  }
40884
- function canonicalize(path7) {
40885
- return realpathSync.native(path7);
40884
+ function canonicalize(path8) {
40885
+ return realpathSync.native(path8);
40886
40886
  }
40887
40887
  function isWithinRoots(candidate, roots) {
40888
40888
  return roots.some((root) => {
@@ -40904,9 +40904,9 @@ function canonicalRoots(roots) {
40904
40904
  }
40905
40905
  return canonical;
40906
40906
  }
40907
- function entryExists(path7) {
40907
+ function entryExists(path8) {
40908
40908
  try {
40909
- lstatSync(path7);
40909
+ lstatSync(path8);
40910
40910
  return true;
40911
40911
  } catch (e) {
40912
40912
  const code = e.code;
@@ -41136,7 +41136,7 @@ function attachmentCoreDataId(noteId3, pk) {
41136
41136
  }
41137
41137
  function buildAttachmentRowsSql(notePk, columns) {
41138
41138
  if (!Number.isSafeInteger(notePk) || notePk < 0) throw new Error("Invalid note primary key");
41139
- const col2 = (alias, name) => columns.has(name) ? `${alias}.${name}` : "NULL";
41139
+ const col3 = (alias, name) => columns.has(name) ? `${alias}.${name}` : "NULL";
41140
41140
  const firstOf = (alias, names) => {
41141
41141
  const present = names.filter((n) => columns.has(n)).map((n) => `${alias}.${n}`);
41142
41142
  if (present.length === 0) return "NULL";
@@ -41149,19 +41149,19 @@ function buildAttachmentRowsSql(notePk, columns) {
41149
41149
  ].join(", ");
41150
41150
  const account = accountCols.length ? `(SELECT acc.ZIDENTIFIER FROM ZICCLOUDSYNCINGOBJECT acc WHERE acc.Z_ENT = (SELECT Z_ENT FROM Z_PRIMARYKEY WHERE Z_NAME = 'ICAccount') AND acc.Z_PK IN (${accountRefs}) LIMIT 1)` : "NULL";
41151
41151
  const noteLink = columns.has("ZNOTE") ? "a.ZNOTE" : "NULL";
41152
- const parent = col2("a", "ZPARENTATTACHMENT");
41152
+ const parent = col3("a", "ZPARENTATTACHMENT");
41153
41153
  const deleted = columns.has("ZMARKEDFORDELETION") ? " AND COALESCE(a.ZMARKEDFORDELETION, 0) = 0" : "";
41154
41154
  const fields = [
41155
41155
  `'pk', a.Z_PK`,
41156
41156
  `'identifier', a.ZIDENTIFIER`,
41157
- `'uti', ${col2("a", "ZTYPEUTI")}`,
41157
+ `'uti', ${col3("a", "ZTYPEUTI")}`,
41158
41158
  `'parentPk', ${parent}`,
41159
- `'filename', ${col2("a", "ZFILENAME")}`,
41159
+ `'filename', ${col3("a", "ZFILENAME")}`,
41160
41160
  `'mediaIdentifier', m.ZIDENTIFIER`,
41161
- `'mediaFilename', ${col2("m", "ZFILENAME")}`,
41161
+ `'mediaFilename', ${col3("m", "ZFILENAME")}`,
41162
41162
  `'mediaGeneration', ${firstOf("m", ["ZGENERATION1", "ZGENERATION"])}`,
41163
- `'fallbackImageGeneration', ${col2("a", "ZFALLBACKIMAGEGENERATION")}`,
41164
- `'fallbackPdfGeneration', ${col2("a", "ZFALLBACKPDFGENERATION")}`,
41163
+ `'fallbackImageGeneration', ${col3("a", "ZFALLBACKIMAGEGENERATION")}`,
41164
+ `'fallbackPdfGeneration', ${col3("a", "ZFALLBACKPDFGENERATION")}`,
41165
41165
  `'accountIdentifier', ${account}`
41166
41166
  ].join(", ");
41167
41167
  const mediaJoin = columns.has("ZMEDIA") ? "LEFT JOIN ZICCLOUDSYNCINGOBJECT m ON m.Z_PK = a.ZMEDIA" : "LEFT JOIN ZICCLOUDSYNCINGOBJECT m ON 0";
@@ -41274,24 +41274,24 @@ function safeComponent(value) {
41274
41274
  if (value === "." || value === ".." || value.includes("/") || value.includes("\0")) return null;
41275
41275
  return value;
41276
41276
  }
41277
- function realInside(path7, rootReal) {
41277
+ function realInside(path8, rootReal) {
41278
41278
  try {
41279
- const real = realpathSync2.native(path7);
41279
+ const real = realpathSync2.native(path8);
41280
41280
  return real === rootReal || real.startsWith(rootReal + sep2) ? real : null;
41281
41281
  } catch {
41282
41282
  return null;
41283
41283
  }
41284
41284
  }
41285
- function isRegularFile(path7) {
41285
+ function isRegularFile(path8) {
41286
41286
  try {
41287
- return lstatSync2(path7).isFile();
41287
+ return lstatSync2(path8).isFile();
41288
41288
  } catch {
41289
41289
  return false;
41290
41290
  }
41291
41291
  }
41292
- function isDirectory(path7) {
41292
+ function isDirectory(path8) {
41293
41293
  try {
41294
- return lstatSync2(path7).isDirectory();
41294
+ return lstatSync2(path8).isDirectory();
41295
41295
  } catch {
41296
41296
  return false;
41297
41297
  }
@@ -41671,10 +41671,10 @@ function readImageInfoFd(fd) {
41671
41671
  const read = readSync2(fd, buf, 0, buf.length, 0);
41672
41672
  return parseImageHeader(buf.subarray(0, read));
41673
41673
  }
41674
- function readImageInfo(path7) {
41674
+ function readImageInfo(path8) {
41675
41675
  let fd;
41676
41676
  try {
41677
- fd = openSync3(path7, constants3.O_RDONLY | constants3.O_NOFOLLOW);
41677
+ fd = openSync3(path8, constants3.O_RDONLY | constants3.O_NOFOLLOW);
41678
41678
  } catch {
41679
41679
  return null;
41680
41680
  }
@@ -41686,7 +41686,7 @@ function readImageInfo(path7) {
41686
41686
  }
41687
41687
  function buildDrawingRowsSql(notePk, columns) {
41688
41688
  if (!Number.isSafeInteger(notePk) || notePk < 0) throw new Error("Invalid note primary key");
41689
- const col2 = (name) => columns.has(name) ? `a.${name}` : "NULL";
41689
+ const col3 = (name) => columns.has(name) ? `a.${name}` : "NULL";
41690
41690
  const accountCols = [...columns].filter((c) => /^ZACCOUNT\d*$/.test(c)).sort();
41691
41691
  const account = accountCols.length ? `(SELECT acc.ZIDENTIFIER FROM ZICCLOUDSYNCINGOBJECT acc WHERE acc.Z_ENT = (SELECT Z_ENT FROM Z_PRIMARYKEY WHERE Z_NAME = 'ICAccount') AND acc.Z_PK IN (${[
41692
41692
  ...accountCols.map((c) => `a.${c}`),
@@ -41697,8 +41697,8 @@ function buildDrawingRowsSql(notePk, columns) {
41697
41697
  `'pk', a.Z_PK`,
41698
41698
  `'identifier', a.ZIDENTIFIER`,
41699
41699
  `'uti', a.ZTYPEUTI`,
41700
- `'handwritingSummary', ${col2("ZHANDWRITINGSUMMARY")}`,
41701
- `'fallbackImageGeneration', ${col2("ZFALLBACKIMAGEGENERATION")}`,
41700
+ `'handwritingSummary', ${col3("ZHANDWRITINGSUMMARY")}`,
41701
+ `'fallbackImageGeneration', ${col3("ZFALLBACKIMAGEGENERATION")}`,
41702
41702
  `'accountIdentifier', ${account}`
41703
41703
  ].join(", ");
41704
41704
  return [
@@ -41774,9 +41774,9 @@ function readDrawingRows(noteId3, dbPath2 = join7(NOTES_CONTAINER_DIR, "NoteStor
41774
41774
  throw new AttachmentStoreError("Drawing rows could not be parsed", "query_error");
41775
41775
  }
41776
41776
  }
41777
- function kindOf(path7) {
41777
+ function kindOf(path8) {
41778
41778
  try {
41779
- const st = lstatSync3(path7);
41779
+ const st = lstatSync3(path8);
41780
41780
  return st.isFile() ? "file" : st.isDirectory() ? "dir" : null;
41781
41781
  } catch {
41782
41782
  return null;
@@ -41842,13 +41842,13 @@ function describeDrawings(rows, containerDir = NOTES_CONTAINER_DIR) {
41842
41842
  const previewPath = accountDir ? findLargestPreview(accountDir, row.identifier) : null;
41843
41843
  const bundle = accountDir && id2 && kind === "paper" ? realInside(join7(accountDir, "Paper", "Bundles", `${id2}.bundle`), accountDir) : null;
41844
41844
  let raster = null;
41845
- for (const [path7, source] of [
41845
+ for (const [path8, source] of [
41846
41846
  [fallbackImagePath, "fallback"],
41847
41847
  [previewPath, "preview"]
41848
41848
  ]) {
41849
- const info = path7 ? readImageInfo(path7) : null;
41850
- if (path7 && info) {
41851
- raster = { path: path7, source, ...info };
41849
+ const info = path8 ? readImageInfo(path8) : null;
41850
+ if (path8 && info) {
41851
+ raster = { path: path8, source, ...info };
41852
41852
  break;
41853
41853
  }
41854
41854
  }
@@ -41865,10 +41865,10 @@ function describeDrawings(rows, containerDir = NOTES_CONTAINER_DIR) {
41865
41865
  };
41866
41866
  });
41867
41867
  }
41868
- function verifyWrittenImage(fd, path7, expected) {
41868
+ function verifyWrittenImage(fd, path8, expected) {
41869
41869
  const check2 = readImageInfoFd(fd);
41870
41870
  if (!check2 || check2.format !== expected.format || check2.width !== expected.width || check2.height !== expected.height) {
41871
- unlinkSync2(path7);
41871
+ unlinkSync2(path8);
41872
41872
  throw new Error("The exported image failed validation and was removed.");
41873
41873
  }
41874
41874
  return check2;
@@ -42003,11 +42003,11 @@ function fitExportNoteToBudget(note, maxBytes) {
42003
42003
  function executeMutationAppleScript(script) {
42004
42004
  return executeAppleScript(script, { maxRetries: 1 });
42005
42005
  }
42006
- function escapeForAppleScript(text) {
42007
- if (!text) {
42006
+ function escapeForAppleScript(text2) {
42007
+ if (!text2) {
42008
42008
  return "";
42009
42009
  }
42010
- let escaped = text.replace(/&/g, "&amp;");
42010
+ let escaped = text2.replace(/&/g, "&amp;");
42011
42011
  escaped = escaped.replace(/\\/g, "&#92;");
42012
42012
  escaped = escaped.replace(/"/g, '\\"');
42013
42013
  escaped = escaped.replace(/\n/g, "<br>");
@@ -42020,9 +42020,9 @@ function escapeHtmlForAppleScript(htmlContent) {
42020
42020
  }
42021
42021
  return htmlContent.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
42022
42022
  }
42023
- function escapePlainStringForAppleScript(text) {
42024
- if (!text) return "";
42025
- return text.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
42023
+ function escapePlainStringForAppleScript(text2) {
42024
+ if (!text2) return "";
42025
+ return text2.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
42026
42026
  }
42027
42027
  var MAX_TITLE_LENGTH = 2e3;
42028
42028
  var MAX_CONTENT_LENGTH = 5 * 1024 * 1024;
@@ -44319,13 +44319,13 @@ var AppleNotesManager = class {
44319
44319
  * Simple HTML to plaintext conversion for export.
44320
44320
  */
44321
44321
  htmlToPlaintext(html) {
44322
- let text = html.replace(/<br\s*\/?>/gi, "\n").replace(/<\/div>/gi, "\n").replace(/<\/p>/gi, "\n");
44322
+ let text2 = html.replace(/<br\s*\/?>/gi, "\n").replace(/<\/div>/gi, "\n").replace(/<\/p>/gi, "\n");
44323
44323
  let prev;
44324
44324
  do {
44325
- prev = text;
44326
- text = text.replace(/<[^>]*>/g, "");
44327
- } while (text !== prev);
44328
- return text.replace(/&nbsp;/g, " ").replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&quot;/g, '"').replace(/&#92;/g, "\\").replace(/&amp;/g, "&").replace(/\n{3,}/g, "\n\n").trim();
44325
+ prev = text2;
44326
+ text2 = text2.replace(/<[^>]*>/g, "");
44327
+ } while (text2 !== prev);
44328
+ return text2.replace(/&nbsp;/g, " ").replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&quot;/g, '"').replace(/&#92;/g, "\\").replace(/&amp;/g, "&").replace(/\n{3,}/g, "\n\n").trim();
44329
44329
  }
44330
44330
  /**
44331
44331
  * Exports notes as a JSON structure for backup/migration, one page at a time.
@@ -44501,11 +44501,11 @@ var AppleNotesManager = class {
44501
44501
  const enriched = lines.map((line) => {
44502
44502
  const listMatch = line.match(/^(\s*[-*])\s+(.+)$/);
44503
44503
  if (!listMatch) return line;
44504
- const [, prefix, text] = listMatch;
44505
- const done = checklistMap.get(text.trim());
44504
+ const [, prefix, text2] = listMatch;
44505
+ const done = checklistMap.get(text2.trim());
44506
44506
  if (done === void 0) return line;
44507
- checklistMap.delete(text.trim());
44508
- return `${prefix} ${done ? "[x]" : "[ ]"} ${text}`;
44507
+ checklistMap.delete(text2.trim());
44508
+ return `${prefix} ${done ? "[x]" : "[ ]"} ${text2}`;
44509
44509
  });
44510
44510
  return enriched.join("\n");
44511
44511
  }
@@ -44772,7 +44772,10 @@ function getNoteMetadata(noteId3) {
44772
44772
  }
44773
44773
  }
44774
44774
 
44775
- // src/utils/noteIdentifiers.ts
44775
+ // src/utils/noteListings.ts
44776
+ import { gunzipSync as gunzipSync6 } from "zlib";
44777
+
44778
+ // src/utils/noteStoreSql.ts
44776
44779
  import { execFileSync as execFileSync10 } from "child_process";
44777
44780
  import * as fs5 from "fs";
44778
44781
  import * as os5 from "os";
@@ -44781,6 +44784,407 @@ var NOTES_DB_PATH6 = path5.join(
44781
44784
  os5.homedir(),
44782
44785
  "Library/Group Containers/group.com.apple.notes/NoteStore.sqlite"
44783
44786
  );
44787
+ var CORE_DATA_EPOCH_MS = Date.UTC(2001, 0, 1);
44788
+ var STORE_FDA_MESSAGE = `Full Disk Access is required to read the Notes database. In System Settings > Privacy & Security > Full Disk Access, grant access to the app that launches this server (Claude Desktop / Terminal / iTerm2), then fully quit and relaunch it. Setup guide: ${FULL_DISK_ACCESS_GUIDE_URL} \u2014 run the doctor tool to verify.`;
44789
+ var NoteStoreError = class extends Error {
44790
+ constructor(message, kind) {
44791
+ super(message);
44792
+ this.kind = kind;
44793
+ this.name = "NoteStoreError";
44794
+ }
44795
+ kind;
44796
+ };
44797
+ function doubleToHex(value) {
44798
+ if (!Number.isFinite(value)) throw new NoteStoreError("Not a finite number", "invalid_input");
44799
+ const buffer = Buffer.alloc(8);
44800
+ buffer.writeDoubleBE(value);
44801
+ return buffer.toString("hex");
44802
+ }
44803
+ function hexToDouble(hex3) {
44804
+ if (!/^[0-9a-f]{16}$/i.test(hex3))
44805
+ throw new NoteStoreError("Invalid double bits", "invalid_input");
44806
+ const value = Buffer.from(hex3, "hex").readDoubleBE();
44807
+ if (!Number.isFinite(value)) throw new NoteStoreError("Invalid double bits", "invalid_input");
44808
+ return value;
44809
+ }
44810
+ function renderValue(value) {
44811
+ if ("int" in value) {
44812
+ if (!Number.isSafeInteger(value.int)) {
44813
+ throw new NoteStoreError("Bound integer out of range", "invalid_input");
44814
+ }
44815
+ return String(value.int);
44816
+ }
44817
+ if ("blob" in value) return `x'${Buffer.from(value.blob).toString("hex")}'`;
44818
+ const double = "double" in value ? value.double : hexToDouble(value.doubleBits);
44819
+ return `ieee754_from_blob(x'${doubleToHex(double)}')`;
44820
+ }
44821
+ function runReadOnlySql(dbPath2, sql, params = {}) {
44822
+ if (!fs5.existsSync(dbPath2)) throw new NoteStoreError(STORE_FDA_MESSAGE, "no_fda");
44823
+ const args = ["-readonly"];
44824
+ const names = Object.keys(params);
44825
+ if (names.length) args.push("-cmd", ".parameter init");
44826
+ for (const name of names) {
44827
+ if (!/^[a-z][a-z0-9_]*$/i.test(name)) {
44828
+ throw new NoteStoreError(`Invalid parameter name ${name}`, "invalid_input");
44829
+ }
44830
+ args.push("-cmd", `.parameter set @${name} ${renderValue(params[name])}`);
44831
+ }
44832
+ args.push(dbPath2, sql);
44833
+ try {
44834
+ return execFileSync10("sqlite3", args, {
44835
+ encoding: "utf8",
44836
+ timeout: 3e4,
44837
+ maxBuffer: 512 * 1024 * 1024,
44838
+ stdio: ["pipe", "pipe", "pipe"]
44839
+ });
44840
+ } catch (error2) {
44841
+ const message = error2 instanceof Error ? error2.message : String(error2);
44842
+ if (/authorization denied|unable to open database/i.test(message)) {
44843
+ throw new NoteStoreError(STORE_FDA_MESSAGE, "no_fda");
44844
+ }
44845
+ console.error(`Notes database query failed: ${message}`);
44846
+ throw new NoteStoreError("Failed to query the Notes database.", "query_error");
44847
+ }
44848
+ }
44849
+ function parseJsonLines(output) {
44850
+ const rows = [];
44851
+ for (const line of output.split("\n")) {
44852
+ if (!line.trim()) continue;
44853
+ try {
44854
+ rows.push(JSON.parse(line));
44855
+ } catch {
44856
+ throw new NoteStoreError("Unexpected Notes database response.", "query_error");
44857
+ }
44858
+ }
44859
+ return rows;
44860
+ }
44861
+ function readColumns(dbPath2) {
44862
+ const out = runReadOnlySql(
44863
+ dbPath2,
44864
+ "SELECT json_object('name', name) FROM pragma_table_info('ZICCLOUDSYNCINGOBJECT');"
44865
+ );
44866
+ return new Set(parseJsonLines(out).map((row) => row.name));
44867
+ }
44868
+ function requireColumns(columns, required2, tool) {
44869
+ const missing = required2.filter((column) => !columns.has(column));
44870
+ if (missing.length) {
44871
+ throw new NoteStoreError(
44872
+ `This macOS version's Notes database lacks columns ${tool} needs (${missing.join(", ")}).`,
44873
+ "schema"
44874
+ );
44875
+ }
44876
+ }
44877
+ function col(columns, alias, name, fallback = "NULL") {
44878
+ return columns.has(name) ? `${alias}.${name}` : fallback;
44879
+ }
44880
+ function entity(name) {
44881
+ return `(SELECT Z_ENT FROM Z_PRIMARYKEY WHERE Z_NAME='${name}')`;
44882
+ }
44883
+ function accountRef(columns, alias) {
44884
+ const refs = [...columns].filter((name) => /^ZACCOUNT\d*$/.test(name)).sort().map((name) => `${alias}.${name}`);
44885
+ if (!refs.length) return "NULL";
44886
+ return refs.length === 1 ? refs[0] : `COALESCE(${refs.join(", ")})`;
44887
+ }
44888
+ function trashFolderSql(columns, f) {
44889
+ const parts = [];
44890
+ if (columns.has("ZFOLDERTYPE")) parts.push(`COALESCE(${f}.ZFOLDERTYPE, 0) = 1`);
44891
+ if (columns.has("ZIDENTIFIER")) parts.push(`COALESCE(${f}.ZIDENTIFIER, '') LIKE 'TrashFolder%'`);
44892
+ return parts.length ? `(${parts.join(" OR ")})` : "0";
44893
+ }
44894
+ function notTombstonedSql(columns, alias) {
44895
+ return columns.has("ZMARKEDFORDELETION") ? `COALESCE(${alias}.ZMARKEDFORDELETION, 0) = 0` : "1";
44896
+ }
44897
+ function activeNoteSql(columns, n, f) {
44898
+ return [
44899
+ `${n}.ZFOLDER IS NOT NULL`,
44900
+ `${f}.Z_PK IS NOT NULL`,
44901
+ notTombstonedSql(columns, n),
44902
+ notTombstonedSql(columns, f),
44903
+ `NOT ${trashFolderSql(columns, f)}`
44904
+ ].join(" AND ");
44905
+ }
44906
+ function coreDataToIso(seconds) {
44907
+ if (typeof seconds !== "number" || !Number.isFinite(seconds)) return null;
44908
+ const date3 = new Date(CORE_DATA_EPOCH_MS + seconds * 1e3);
44909
+ return Number.isNaN(date3.getTime()) ? null : date3.toISOString();
44910
+ }
44911
+ function noteIdFor(storeUuid, pk) {
44912
+ return `x-coredata://${storeUuid}/ICNote/p${pk}`;
44913
+ }
44914
+ function readStoreContext(dbPath2, columns) {
44915
+ const sql = [
44916
+ "BEGIN;",
44917
+ "SELECT json_object('k', 'meta', 'uuid', (SELECT Z_UUID FROM Z_METADATA LIMIT 1));",
44918
+ `SELECT json_object('k', 'account', 'pk', a.Z_PK, 'name', ${col(columns, "a", "ZNAME")}, 'identifier', ${col(columns, "a", "ZIDENTIFIER")}) FROM ZICCLOUDSYNCINGOBJECT a WHERE a.Z_ENT = ${entity("ICAccount")} AND ${notTombstonedSql(columns, "a")};`,
44919
+ `SELECT json_object('k', 'folder', 'pk', f.Z_PK, 'name', ${col(columns, "f", "ZTITLE2")}, 'identifier', ${col(columns, "f", "ZIDENTIFIER")}, 'parent', ${col(columns, "f", "ZPARENT")}, 'account', ${col(columns, "f", "ZOWNER", accountRef(columns, "f"))}, 'folderType', ${col(columns, "f", "ZFOLDERTYPE")}, 'trash', ${trashFolderSql(columns, "f")}, 'tombstoned', NOT ${notTombstonedSql(columns, "f")}) FROM ZICCLOUDSYNCINGOBJECT f WHERE f.Z_ENT = ${entity("ICFolder")};`,
44920
+ "COMMIT;"
44921
+ ].join(" ");
44922
+ const rows = parseJsonLines(runReadOnlySql(dbPath2, sql));
44923
+ const meta = rows.find((row) => row.k === "meta");
44924
+ if (typeof meta?.uuid !== "string" || !meta.uuid) {
44925
+ throw new NoteStoreError("The Notes database has no store identifier.", "schema");
44926
+ }
44927
+ return {
44928
+ uuid: meta.uuid,
44929
+ accounts: rows.filter((row) => row.k === "account").map((row) => ({
44930
+ pk: row.pk,
44931
+ name: typeof row.name === "string" ? row.name : "",
44932
+ identifier: row.identifier ?? null
44933
+ })),
44934
+ folders: rows.filter((row) => row.k === "folder").map((row) => ({
44935
+ pk: row.pk,
44936
+ name: row.name ?? null,
44937
+ identifier: row.identifier ?? null,
44938
+ parent: row.parent ?? null,
44939
+ account: row.account ?? null,
44940
+ folderType: row.folderType ?? null,
44941
+ trash: row.trash ? 1 : 0,
44942
+ tombstoned: row.tombstoned ? 1 : 0
44943
+ }))
44944
+ };
44945
+ }
44946
+ function folderPaths(folders) {
44947
+ const byPk = new Map(folders.map((folder) => [folder.pk, folder]));
44948
+ const paths = /* @__PURE__ */ new Map();
44949
+ for (const folder of folders) {
44950
+ const segments = [];
44951
+ const seen = /* @__PURE__ */ new Set();
44952
+ let current = folder;
44953
+ while (current && !seen.has(current.pk)) {
44954
+ seen.add(current.pk);
44955
+ segments.unshift(escapeFolderName(current.name ?? ""));
44956
+ current = current.parent !== null ? byPk.get(current.parent) : void 0;
44957
+ }
44958
+ paths.set(folder.pk, segments.join("/"));
44959
+ }
44960
+ return paths;
44961
+ }
44962
+ function resolveAccountName(accounts, name) {
44963
+ const wanted = name.trim().toLocaleLowerCase();
44964
+ const exact = accounts.filter((account) => account.name.toLocaleLowerCase() === wanted);
44965
+ if (exact.length === 1) return exact[0];
44966
+ const prefix = accounts.filter((account) => account.name.toLocaleLowerCase().startsWith(wanted));
44967
+ if (exact.length === 0 && prefix.length === 1) return prefix[0];
44968
+ const names = accounts.map((account) => account.name).join(", ");
44969
+ throw new NoteStoreError(
44970
+ exact.length > 1 || prefix.length > 1 ? `Account "${name}" is ambiguous. Accounts: ${names}.` : `No account named "${name}". Accounts: ${names}.`,
44971
+ "invalid_input"
44972
+ );
44973
+ }
44974
+
44975
+ // src/utils/noteListings.ts
44976
+ var SPECIAL_LIMIT = { DEFAULT: 100, MAX: 1e3 };
44977
+ var HASHTAG_UTI = "com.apple.notes.inlinetextattachment.hashtag";
44978
+ var KIND_COLUMN = {
44979
+ pinned: ["ZISPINNED"],
44980
+ "quick-notes": ["ZISSYSTEMPAPER"],
44981
+ "recently-deleted": ["ZFOLDERTYPE", "ZIDENTIFIER"],
44982
+ locked: ["ZISPASSWORDPROTECTED"]
44983
+ };
44984
+ function kindSupported(columns, kind) {
44985
+ return KIND_COLUMN[kind].some((name) => columns.has(name));
44986
+ }
44987
+ var flag = (columns, alias, name) => columns.has(name) ? `COALESCE(${alias}.${name}, 0)` : "0";
44988
+ function kindPredicate(columns, kind) {
44989
+ switch (kind) {
44990
+ case "pinned":
44991
+ return `${flag(columns, "n", "ZISPINNED")} = 1 AND ${activeNoteSql(columns, "n", "f")}`;
44992
+ case "quick-notes":
44993
+ return `${flag(columns, "n", "ZISSYSTEMPAPER")} = 1 AND ${activeNoteSql(columns, "n", "f")}`;
44994
+ case "recently-deleted":
44995
+ return `f.Z_PK IS NOT NULL AND ${trashFolderSql(columns, "f")} AND ${notTombstonedSql(columns, "n")}`;
44996
+ case "locked":
44997
+ return `${flag(columns, "n", "ZISPASSWORDPROTECTED")} = 1`;
44998
+ }
44999
+ }
45000
+ function folderAccountJoins(columns) {
45001
+ const owner = col(columns, "f", "ZOWNER");
45002
+ const account = owner === "NULL" ? accountRef(columns, "n") : `COALESCE(${owner}, ${accountRef(columns, "n")})`;
45003
+ return `LEFT JOIN ZICCLOUDSYNCINGOBJECT f ON f.Z_PK = n.ZFOLDER AND f.Z_ENT = ${entity("ICFolder")} LEFT JOIN ZICCLOUDSYNCINGOBJECT a ON a.Z_PK = ${account} AND a.Z_ENT = ${entity("ICAccount")}`;
45004
+ }
45005
+ function noteFrom(columns) {
45006
+ return `FROM ZICCLOUDSYNCINGOBJECT n ${folderAccountJoins(columns)}`;
45007
+ }
45008
+ var REQUIRED = ["Z_PK", "Z_ENT", "ZFOLDER", "ZTITLE1"];
45009
+ function buildSpecialNotesSql(columns, kind, scoped) {
45010
+ requireColumns(columns, REQUIRED, "list-special-notes");
45011
+ const created = ["ZCREATIONDATE3", "ZCREATIONDATE1", "ZCREATIONDATE"].filter((name) => columns.has(name)).map((name) => `n.${name}`).join(", ") || "NULL";
45012
+ const createdExpr = created.includes(",") ? `COALESCE(${created})` : created;
45013
+ const modified = col(columns, "n", "ZMODIFICATIONDATE1");
45014
+ const locked = flag(columns, "n", "ZISPASSWORDPROTECTED");
45015
+ const where = `WHERE n.Z_ENT = ${entity("ICNote")} AND ${kindPredicate(columns, kind)}` + (scoped ? " AND a.Z_PK = @account" : "");
45016
+ const snippet = `CASE WHEN ${locked} = 1 THEN NULL ELSE ${col(columns, "n", "ZSNIPPET")} END`;
45017
+ const hint = kind === "locked" ? col(columns, "n", "ZPASSWORDHINT") : "NULL";
45018
+ const row = `SELECT json_object('k', 'note', 'pk', n.Z_PK, 'identifier', ${col(columns, "n", "ZIDENTIFIER")}, 'title', n.ZTITLE1, 'folder', f.Z_PK, 'account', a.Z_PK, 'created', ${createdExpr}, 'modified', ${modified}, 'pinned', ${flag(columns, "n", "ZISPINNED")}, 'locked', ${locked}, 'quick', ${flag(columns, "n", "ZISSYSTEMPAPER")}, 'trash', f.Z_PK IS NOT NULL AND ${trashFolderSql(columns, "f")}, 'tombstoned', NOT ${notTombstonedSql(columns, "n")}, 'snippet', ${snippet}, 'hint', ${hint}) ${noteFrom(columns)} ${where} ORDER BY ${modified} DESC, n.Z_PK DESC LIMIT @limit;`;
45019
+ return [
45020
+ "BEGIN;",
45021
+ `SELECT json_object('k', 'total', 'n', COUNT(*)) ${noteFrom(columns)} ${where};`,
45022
+ row,
45023
+ "COMMIT;"
45024
+ ].join(" ");
45025
+ }
45026
+ function listSpecialNotes(options) {
45027
+ const dbPath2 = options.dbPath ?? NOTES_DB_PATH6;
45028
+ const limit = Math.min(
45029
+ Math.max(1, Math.trunc(options.limit ?? SPECIAL_LIMIT.DEFAULT)),
45030
+ SPECIAL_LIMIT.MAX
45031
+ );
45032
+ const columns = readColumns(dbPath2);
45033
+ const empty = {
45034
+ kind: options.kind,
45035
+ notes: [],
45036
+ count: 0,
45037
+ total: 0,
45038
+ limit,
45039
+ supported: false
45040
+ };
45041
+ if (!kindSupported(columns, options.kind)) return empty;
45042
+ const context = readStoreContext(dbPath2, columns);
45043
+ const scope2 = options.account ? resolveAccountName(context.accounts, options.account) : void 0;
45044
+ const params = { limit: { int: limit } };
45045
+ if (scope2) params.account = { int: scope2.pk };
45046
+ const rows = parseJsonLines(
45047
+ runReadOnlySql(dbPath2, buildSpecialNotesSql(columns, options.kind, Boolean(scope2)), params)
45048
+ );
45049
+ const paths = folderPaths(context.folders);
45050
+ const accountNames = new Map(context.accounts.map((account) => [account.pk, account.name]));
45051
+ const notes = rows.filter((row) => row.k === "note").map((row) => toSpecialRow(row, context.uuid, paths, accountNames, options.kind));
45052
+ return {
45053
+ kind: options.kind,
45054
+ notes,
45055
+ count: notes.length,
45056
+ total: rows.find((row) => row.k === "total")?.n ?? notes.length,
45057
+ limit,
45058
+ supported: true,
45059
+ ...scope2 ? { account: scope2.name } : {}
45060
+ };
45061
+ }
45062
+ function toSpecialRow(row, uuid2, paths, accountNames, kind) {
45063
+ const locked = Boolean(row.locked);
45064
+ const note = {
45065
+ id: noteIdFor(uuid2, row.pk),
45066
+ identifier: row.identifier ?? null,
45067
+ title: row.title ?? null,
45068
+ folder: row.folder !== null ? paths.get(row.folder) ?? null : null,
45069
+ account: row.account !== null ? accountNames.get(row.account) ?? null : null,
45070
+ created: coreDataToIso(row.created),
45071
+ modified: coreDataToIso(row.modified),
45072
+ pinned: Boolean(row.pinned),
45073
+ locked,
45074
+ quickNote: Boolean(row.quick),
45075
+ inRecentlyDeleted: Boolean(row.trash),
45076
+ markedForDeletion: Boolean(row.tombstoned)
45077
+ };
45078
+ if (!locked) note.snippet = row.snippet ?? null;
45079
+ if (kind === "locked" && row.hint) note.passwordHint = row.hint;
45080
+ return note;
45081
+ }
45082
+ var TAG_REQUIRED = ["Z_PK", "Z_ENT", "ZFOLDER", "ZNOTE1", "ZTYPEUTI1", "ZALTTEXT", "ZIDENTIFIER"];
45083
+ function buildTagInventorySql(columns, scoped) {
45084
+ requireColumns(columns, TAG_REQUIRED, "list-native-tags");
45085
+ const accountFilter = scoped ? " AND a.Z_PK = @account" : "";
45086
+ const uses = `FROM ZICCLOUDSYNCINGOBJECT i JOIN ZICCLOUDSYNCINGOBJECT n ON n.Z_PK = i.ZNOTE1 AND n.Z_ENT = ${entity("ICNote")} ${folderAccountJoins(columns)} WHERE i.ZTYPEUTI1 = '${HASHTAG_UTI}' AND ${notTombstonedSql(columns, "i")} AND ${activeNoteSql(columns, "n", "f")}${accountFilter}`;
45087
+ const tagAccount = accountRef(columns, "t");
45088
+ const display = ["ZDISPLAYTEXT", "ZSTANDARDIZEDCONTENT", "ZNAME"].filter((name) => columns.has(name)).map((name) => `t.${name}`);
45089
+ const displayExpr = display.length > 1 ? `COALESCE(${display.join(", ")})` : display[0] || "NULL";
45090
+ return [
45091
+ "BEGIN;",
45092
+ `SELECT json_object('k', 'tag', 'text', ${displayExpr}, 'account', ta.Z_PK) FROM ZICCLOUDSYNCINGOBJECT t LEFT JOIN ZICCLOUDSYNCINGOBJECT ta ON ta.Z_PK = ${tagAccount} AND ta.Z_ENT = ${entity("ICAccount")} WHERE t.Z_ENT = ${entity("ICHashtag")} AND ${notTombstonedSql(columns, "t")}${scoped ? " AND ta.Z_PK = @account" : ""};`,
45093
+ `SELECT json_object('k', 'use', 'note', n.Z_PK, 'object', i.ZIDENTIFIER, 'text', i.ZALTTEXT, 'account', a.Z_PK, 'locked', ${flag(columns, "n", "ZISPASSWORDPROTECTED")}) ${uses};`,
45094
+ `SELECT json_object('k', 'body', 'note', b.Z_PK, 'data', (SELECT hex(d.ZDATA) FROM ZICNOTEDATA d WHERE d.ZNOTE = b.Z_PK ORDER BY d.Z_PK DESC LIMIT 1)) FROM ZICCLOUDSYNCINGOBJECT b WHERE b.Z_PK IN (SELECT n.Z_PK ${uses}) AND ${flag(columns, "b", "ZISPASSWORDPROTECTED")} = 0;`,
45095
+ "COMMIT;"
45096
+ ].join(" ");
45097
+ }
45098
+ var bareTag = (text2) => text2.replace(/^#/, "").trim();
45099
+ function referencedObjects(hex3) {
45100
+ if (!hex3 || !/^[0-9a-f]+$/i.test(hex3)) return null;
45101
+ try {
45102
+ const data = gunzipSync6(Buffer.from(hex3, "hex"), { maxOutputLength: 32 * 1024 * 1024 });
45103
+ const wrapper = embeddedMessage(getField(decodeMessage(data), 2));
45104
+ const body = wrapper && embeddedMessage(getField(wrapper, 3));
45105
+ if (!body) return null;
45106
+ const ids = /* @__PURE__ */ new Set();
45107
+ for (const run of getFields(body, 5)) {
45108
+ const attachment = embeddedMessage(getField(embeddedMessage(run) ?? [], 12));
45109
+ const id2 = attachment && stringValue(getField(attachment, 1));
45110
+ if (id2) ids.add(id2);
45111
+ }
45112
+ return ids;
45113
+ } catch {
45114
+ return null;
45115
+ }
45116
+ }
45117
+ function nativeTagInventory(options = {}) {
45118
+ const dbPath2 = options.dbPath ?? NOTES_DB_PATH6;
45119
+ const columns = readColumns(dbPath2);
45120
+ const context = readStoreContext(dbPath2, columns);
45121
+ const scope2 = options.account ? resolveAccountName(context.accounts, options.account) : void 0;
45122
+ const rows = parseJsonLines(
45123
+ runReadOnlySql(
45124
+ dbPath2,
45125
+ buildTagInventorySql(columns, Boolean(scope2)),
45126
+ scope2 ? { account: { int: scope2.pk } } : {}
45127
+ )
45128
+ );
45129
+ return assembleInventory(rows, context.accounts, scope2);
45130
+ }
45131
+ function assembleInventory(rows, accounts, scope2) {
45132
+ const accountNames = new Map(accounts.map((account) => [account.pk, account.name]));
45133
+ const bodies = /* @__PURE__ */ new Map();
45134
+ for (const row of rows) if (row.k === "body") bodies.set(row.note, referencedObjects(row.data));
45135
+ const groups = /* @__PURE__ */ new Map();
45136
+ const group = (text2, weight) => {
45137
+ const key = text2.toLocaleLowerCase();
45138
+ let found = groups.get(key);
45139
+ if (!found) groups.set(key, found = { spellings: /* @__PURE__ */ new Map(), notes: /* @__PURE__ */ new Map() });
45140
+ found.spellings.set(text2, (found.spellings.get(text2) ?? 0) + weight);
45141
+ return found;
45142
+ };
45143
+ const unverified = /* @__PURE__ */ new Set();
45144
+ for (const row of rows) {
45145
+ if (row.k === "tag" && row.text && bareTag(row.text)) group(bareTag(row.text), 0);
45146
+ if (row.k !== "use" || !row.text || !bareTag(row.text)) continue;
45147
+ const referenced = row.locked ? null : bodies.get(row.note) ?? null;
45148
+ if (referenced && !(row.object && referenced.has(row.object))) continue;
45149
+ if (!referenced) unverified.add(row.note);
45150
+ group(bareTag(row.text), 1).notes.set(row.note, row.account);
45151
+ }
45152
+ const inventory = [...groups.values()].map((entry) => {
45153
+ const spellings = [...entry.spellings.entries()].sort(
45154
+ (a, b) => b[1] - a[1] || a[0].localeCompare(b[0])
45155
+ );
45156
+ const perAccount = {};
45157
+ for (const accountPk of entry.notes.values()) {
45158
+ const name = accountPk !== null && accountNames.get(accountPk) || "unknown";
45159
+ perAccount[name] = (perAccount[name] ?? 0) + 1;
45160
+ }
45161
+ const result = {
45162
+ tag: spellings[0][0],
45163
+ noteCount: entry.notes.size,
45164
+ accounts: perAccount
45165
+ };
45166
+ if (spellings.length > 1) result.spellings = spellings.slice(1).map(([text2]) => text2);
45167
+ return result;
45168
+ });
45169
+ inventory.sort((a, b) => b.noteCount - a.noteCount || a.tag.localeCompare(b.tag));
45170
+ return {
45171
+ inventory,
45172
+ tagCount: inventory.length,
45173
+ complete: unverified.size === 0,
45174
+ unverifiedNotes: unverified.size,
45175
+ ...scope2 ? { account: scope2.name } : {}
45176
+ };
45177
+ }
45178
+
45179
+ // src/utils/noteIdentifiers.ts
45180
+ import { execFileSync as execFileSync11 } from "child_process";
45181
+ import * as fs6 from "fs";
45182
+ import * as os6 from "os";
45183
+ import * as path6 from "path";
45184
+ var NOTES_DB_PATH7 = path6.join(
45185
+ os6.homedir(),
45186
+ "Library/Group Containers/group.com.apple.notes/NoteStore.sqlite"
45187
+ );
44784
45188
  var UUID_PATTERN = /^[0-9A-Fa-f]{8}(?:-[0-9A-Fa-f]{4}){3}-[0-9A-Fa-f]{12}$/;
44785
45189
  var NUMERIC_KEY_PATTERN = /^\d{1,18}$/;
44786
45190
  var NOTE_ID_MESSAGE = "A canonical Apple Note ID is required (x-coredata://.../ICNote/p...), or the note's Notes UUID or numeric key";
@@ -44814,10 +45218,10 @@ function assertAll(values, pattern, label) {
44814
45218
  if (!pattern.test(value)) throw new Error(`Refusing to query with an invalid ${label}`);
44815
45219
  }
44816
45220
  }
44817
- function entityClause(entity2) {
44818
- return `(SELECT Z_ENT FROM Z_PRIMARYKEY WHERE Z_NAME = '${entity2}')`;
45221
+ function entityClause(entity3) {
45222
+ return `(SELECT Z_ENT FROM Z_PRIMARYKEY WHERE Z_NAME = '${entity3}')`;
44819
45223
  }
44820
- function buildResolveSql(entity2, keys, uuids) {
45224
+ function buildResolveSql(entity3, keys, uuids) {
44821
45225
  assertAll(keys, NUMERIC_KEY_PATTERN, "numeric key");
44822
45226
  assertAll(uuids, UUID_PATTERN, "UUID");
44823
45227
  const matches = [];
@@ -44834,28 +45238,28 @@ function buildResolveSql(entity2, keys, uuids) {
44834
45238
  matches.push(`o.ZIDENTIFIER IN (${[...variants].map((v) => `'${v}'`).join(", ")})`);
44835
45239
  }
44836
45240
  const where = matches.length > 0 ? matches.join(" OR ") : "0";
44837
- return `SELECT json_object('store', (SELECT Z_UUID FROM Z_METADATA LIMIT 1), 'rows', (SELECT json_group_array(json_object('pk', o.Z_PK, 'identifier', o.ZIDENTIFIER)) FROM ZICCLOUDSYNCINGOBJECT o WHERE o.Z_ENT = ${entityClause(entity2)} AND (${where})));`;
45241
+ return `SELECT json_object('store', (SELECT Z_UUID FROM Z_METADATA LIMIT 1), 'rows', (SELECT json_group_array(json_object('pk', o.Z_PK, 'identifier', o.ZIDENTIFIER)) FROM ZICCLOUDSYNCINGOBJECT o WHERE o.Z_ENT = ${entityClause(entity3)} AND (${where})));`;
44838
45242
  }
44839
- function buildLookupSql(entity2, keys) {
45243
+ function buildLookupSql(entity3, keys) {
44840
45244
  assertAll(keys, NUMERIC_KEY_PATTERN, "numeric key");
44841
45245
  const pks = [...new Set(keys.map(canonicalKey))];
44842
45246
  const inList = pks.length > 0 ? pks.join(", ") : "NULL";
44843
45247
  let fields = "'pk', o.Z_PK, 'identifier', o.ZIDENTIFIER";
44844
45248
  let joins = "";
44845
- if (entity2 === "ICNote") {
45249
+ if (entity3 === "ICNote") {
44846
45250
  fields += ", 'folderIdentifier', f.ZIDENTIFIER, 'accountIdentifier', a.ZIDENTIFIER";
44847
45251
  joins = "LEFT JOIN ZICCLOUDSYNCINGOBJECT f ON f.Z_PK = o.ZFOLDER LEFT JOIN ZICCLOUDSYNCINGOBJECT a ON a.Z_PK = f.ZOWNER ";
44848
- } else if (entity2 === "ICFolder") {
45252
+ } else if (entity3 === "ICFolder") {
44849
45253
  fields += ", 'parentIdentifier', p.ZIDENTIFIER, 'accountIdentifier', a.ZIDENTIFIER";
44850
45254
  joins = "LEFT JOIN ZICCLOUDSYNCINGOBJECT p ON p.Z_PK = o.ZPARENT LEFT JOIN ZICCLOUDSYNCINGOBJECT a ON a.Z_PK = o.ZOWNER ";
44851
45255
  }
44852
- return `SELECT json_object('store', (SELECT Z_UUID FROM Z_METADATA LIMIT 1), 'rows', (SELECT json_group_array(json_object(${fields})) FROM ZICCLOUDSYNCINGOBJECT o ${joins}WHERE o.Z_ENT = ${entityClause(entity2)} AND o.Z_PK IN (${inList})));`;
45256
+ return `SELECT json_object('store', (SELECT Z_UUID FROM Z_METADATA LIMIT 1), 'rows', (SELECT json_group_array(json_object(${fields})) FROM ZICCLOUDSYNCINGOBJECT o ${joins}WHERE o.Z_ENT = ${entityClause(entity3)} AND o.Z_PK IN (${inList})));`;
44853
45257
  }
44854
45258
  function runJsonQuery(sql, dbPath2) {
44855
- if (!fs5.existsSync(dbPath2)) throw new IdentifierResolutionError("no_fda", NO_FDA_MESSAGE);
45259
+ if (!fs6.existsSync(dbPath2)) throw new IdentifierResolutionError("no_fda", NO_FDA_MESSAGE);
44856
45260
  let out;
44857
45261
  try {
44858
- out = execFileSync10("sqlite3", ["-readonly", dbPath2, sql], {
45262
+ out = execFileSync11("sqlite3", ["-readonly", dbPath2, sql], {
44859
45263
  encoding: "utf8",
44860
45264
  timeout: 5e3,
44861
45265
  stdio: ["pipe", "pipe", "pipe"]
@@ -44872,10 +45276,10 @@ function runJsonQuery(sql, dbPath2) {
44872
45276
  const rows = typeof parsed.rows === "string" ? JSON.parse(parsed.rows) : parsed.rows;
44873
45277
  return { store: parsed.store ?? null, rows: rows ?? [] };
44874
45278
  }
44875
- function coreDataId(store, entity2, pk) {
44876
- return `x-coredata://${store}/${entity2}/p${pk}`;
45279
+ function coreDataId(store, entity3, pk) {
45280
+ return `x-coredata://${store}/${entity3}/p${pk}`;
44877
45281
  }
44878
- function resolveIdentifiers(values, entity2, dbPath2 = NOTES_DB_PATH6) {
45282
+ function resolveIdentifiers(values, entity3, dbPath2 = NOTES_DB_PATH7) {
44879
45283
  const resolved = /* @__PURE__ */ new Map();
44880
45284
  const keys = [];
44881
45285
  const uuids = [];
@@ -44887,7 +45291,7 @@ function resolveIdentifiers(values, entity2, dbPath2 = NOTES_DB_PATH6) {
44887
45291
  }
44888
45292
  if (keys.length === 0 && uuids.length === 0) return resolved;
44889
45293
  const { store, rows } = runJsonQuery(
44890
- buildResolveSql(entity2, keys, uuids),
45294
+ buildResolveSql(entity3, keys, uuids),
44891
45295
  dbPath2
44892
45296
  );
44893
45297
  if (!store) {
@@ -44900,16 +45304,16 @@ function resolveIdentifiers(values, entity2, dbPath2 = NOTES_DB_PATH6) {
44900
45304
  const byUuid = new Map(
44901
45305
  rows.filter((row) => row.identifier).map((row) => [String(row.identifier).toUpperCase(), row])
44902
45306
  );
44903
- const label = ENTITY_LABEL[entity2];
45307
+ const label = ENTITY_LABEL[entity3];
44904
45308
  const missing = [];
44905
45309
  for (const key of keys) {
44906
45310
  const row = byKey.get(canonicalKey(key));
44907
- if (row) resolved.set(key, coreDataId(store, entity2, row.pk));
45311
+ if (row) resolved.set(key, coreDataId(store, entity3, row.pk));
44908
45312
  else missing.push(`numeric key ${key}`);
44909
45313
  }
44910
45314
  for (const uuid2 of uuids) {
44911
45315
  const row = byUuid.get(uuid2.toUpperCase());
44912
- if (row) resolved.set(uuid2, coreDataId(store, entity2, row.pk));
45316
+ if (row) resolved.set(uuid2, coreDataId(store, entity3, row.pk));
44913
45317
  else missing.push(`identifier ${uuid2}`);
44914
45318
  }
44915
45319
  if (missing.length > 0) {
@@ -44921,12 +45325,12 @@ function resolveIdentifiers(values, entity2, dbPath2 = NOTES_DB_PATH6) {
44921
45325
  return resolved;
44922
45326
  }
44923
45327
  var COREDATA_PARTS = /^x-coredata:\/\/([0-9A-Fa-f-]+)\/(ICNote|ICFolder|ICAccount)\/p(\d{1,18})$/;
44924
- function lookupStableIdentifiers(ids, entity2, dbPath2 = NOTES_DB_PATH6) {
45328
+ function lookupStableIdentifiers(ids, entity3, dbPath2 = NOTES_DB_PATH7) {
44925
45329
  const result = /* @__PURE__ */ new Map();
44926
45330
  const wanted = /* @__PURE__ */ new Map();
44927
45331
  for (const id2 of ids) {
44928
45332
  const match = COREDATA_PARTS.exec(id2);
44929
- if (!match || match[2] !== entity2) continue;
45333
+ if (!match || match[2] !== entity3) continue;
44930
45334
  const pk = canonicalKey(match[3]);
44931
45335
  const list = wanted.get(pk) ?? [];
44932
45336
  list.push({ id: id2, store: match[1] });
@@ -44935,7 +45339,7 @@ function lookupStableIdentifiers(ids, entity2, dbPath2 = NOTES_DB_PATH6) {
44935
45339
  if (wanted.size === 0) return result;
44936
45340
  let query;
44937
45341
  try {
44938
- query = runJsonQuery(buildLookupSql(entity2, [...wanted.keys()]), dbPath2);
45342
+ query = runJsonQuery(buildLookupSql(entity3, [...wanted.keys()]), dbPath2);
44939
45343
  } catch {
44940
45344
  return result;
44941
45345
  }
@@ -44957,16 +45361,16 @@ function lookupStableIdentifiers(ids, entity2, dbPath2 = NOTES_DB_PATH6) {
44957
45361
  }
44958
45362
  return result;
44959
45363
  }
44960
- function withStableIdentifiers(items, entity2, dbPath2 = NOTES_DB_PATH6) {
45364
+ function withStableIdentifiers(items, entity3, dbPath2 = NOTES_DB_PATH7) {
44961
45365
  const ids = items.map((item) => item.id).filter((id2) => typeof id2 === "string");
44962
45366
  if (ids.length === 0) return items;
44963
- const found = lookupStableIdentifiers(ids, entity2, dbPath2);
45367
+ const found = lookupStableIdentifiers(ids, entity3, dbPath2);
44964
45368
  if (found.size === 0) return items;
44965
45369
  return items.map(
44966
45370
  (item) => item.id && found.has(item.id) ? { ...item, ...found.get(item.id) } : item
44967
45371
  );
44968
45372
  }
44969
- var defaultResolver = (values, entity2) => resolveIdentifiers(values, entity2);
45373
+ var defaultResolver = (values, entity3) => resolveIdentifiers(values, entity3);
44970
45374
  var DEFAULT_MAX_ID_LENGTH = 2e3;
44971
45375
  function acceptAlternateForms(pattern) {
44972
45376
  return new RegExp(
@@ -44974,10 +45378,10 @@ function acceptAlternateForms(pattern) {
44974
45378
  pattern.flags
44975
45379
  );
44976
45380
  }
44977
- function resolveInSchema(values, entity2, ctx, resolver) {
45381
+ function resolveInSchema(values, entity3, ctx, resolver) {
44978
45382
  if (!values.some(isAlternateIdentifier)) return new Map(values.map((v) => [v, v]));
44979
45383
  try {
44980
- return resolver(values, entity2);
45384
+ return resolver(values, entity3);
44981
45385
  } catch (error2) {
44982
45386
  ctx.addIssue({
44983
45387
  code: external_exports.ZodIssueCode.custom,
@@ -44986,26 +45390,26 @@ function resolveInSchema(values, entity2, ctx, resolver) {
44986
45390
  return null;
44987
45391
  }
44988
45392
  }
44989
- function exactIdInput(entity2, pattern, message, options = {}) {
45393
+ function exactIdInput(entity3, pattern, message, options = {}) {
44990
45394
  const resolver = options.resolver ?? defaultResolver;
44991
45395
  return external_exports.string().max(options.maxLength ?? DEFAULT_MAX_ID_LENGTH).regex(acceptAlternateForms(pattern), message).transform((value, ctx) => {
44992
- const map = resolveInSchema([value], entity2, ctx, resolver);
45396
+ const map = resolveInSchema([value], entity3, ctx, resolver);
44993
45397
  return map ? map.get(value) ?? value : external_exports.NEVER;
44994
45398
  });
44995
45399
  }
44996
- function exactIdArrayInput(entity2, pattern, message, options = {}) {
45400
+ function exactIdArrayInput(entity3, pattern, message, options = {}) {
44997
45401
  const resolver = options.resolver ?? defaultResolver;
44998
45402
  const item = external_exports.string().max(options.maxLength ?? DEFAULT_MAX_ID_LENGTH).regex(acceptAlternateForms(pattern), message);
44999
45403
  const array2 = options.maxItems === void 0 ? external_exports.array(item) : external_exports.array(item).max(options.maxItems);
45000
45404
  return array2.transform((values, ctx) => {
45001
- const map = resolveInSchema(values, entity2, ctx, resolver);
45405
+ const map = resolveInSchema(values, entity3, ctx, resolver);
45002
45406
  return map ? values.map((value) => map.get(value) ?? value) : external_exports.NEVER;
45003
45407
  });
45004
45408
  }
45005
- function looseIdTransform(entity2, resolver = defaultResolver) {
45409
+ function looseIdTransform(entity3, resolver = defaultResolver) {
45006
45410
  return (value, ctx) => {
45007
45411
  if (!isAlternateIdentifier(value)) return value;
45008
- const map = resolveInSchema([value], entity2, ctx, resolver);
45412
+ const map = resolveInSchema([value], entity3, ctx, resolver);
45009
45413
  return map ? map.get(value) ?? value : external_exports.NEVER;
45010
45414
  };
45011
45415
  }
@@ -45027,10 +45431,10 @@ function htmlToText(html) {
45027
45431
  var HASHTAG_RE = new RegExp("(?<![\\p{L}\\p{N}_])#([\\p{L}\\p{N}_]*\\p{L}[\\p{L}\\p{N}_]*)", "gu");
45028
45432
  function parseHashtags(body) {
45029
45433
  if (!body) return [];
45030
- const text = htmlToText(body);
45434
+ const text2 = htmlToText(body);
45031
45435
  const seen = /* @__PURE__ */ new Set();
45032
45436
  const result = [];
45033
- for (const match of text.matchAll(HASHTAG_RE)) {
45437
+ for (const match of text2.matchAll(HASHTAG_RE)) {
45034
45438
  const tag = match[1];
45035
45439
  const key = tag.toLowerCase();
45036
45440
  if (!seen.has(key)) {
@@ -45046,7 +45450,7 @@ var BLOCK_END_RE = /<\/(?:div|h[1-6]|p|li)>/gi;
45046
45450
  var BREAK_RE = /<br\s*\/?\s*>/gi;
45047
45451
  var TAG_RE = /<[^>]*>/g;
45048
45452
  var NON_RENDERED_BLOCK_RE = /<(script|style)\b[^>]*>[\s\S]*?(?:<\/\1>|$)/gi;
45049
- function decodeHtmlEntities(text) {
45453
+ function decodeHtmlEntities(text2) {
45050
45454
  const decodeCodePoint = (match, value, radix) => {
45051
45455
  const codePoint = Number.parseInt(value, radix);
45052
45456
  if (!Number.isInteger(codePoint) || codePoint < 0 || codePoint > 1114111 || codePoint >= 55296 && codePoint <= 57343) {
@@ -45054,21 +45458,21 @@ function decodeHtmlEntities(text) {
45054
45458
  }
45055
45459
  return String.fromCodePoint(codePoint);
45056
45460
  };
45057
- return text.replace(/&#x([0-9a-f]+);?/gi, (match, hex3) => decodeCodePoint(match, hex3, 16)).replace(/&#([0-9]+);?/g, (match, decimal) => decodeCodePoint(match, decimal, 10)).replace(/&nbsp(?:;|(?![0-9a-z]))/gi, " ").replace(/&quot(?:;|(?![0-9a-z]))/gi, '"').replace(/&apos(?:;|(?![0-9a-z]))/gi, "'").replace(/&lt(?:;|(?![0-9a-z]))/gi, "<").replace(/&gt(?:;|(?![0-9a-z]))/gi, ">").replace(/&amp(?:;|(?![0-9a-z]))/gi, "&");
45461
+ return text2.replace(/&#x([0-9a-f]+);?/gi, (match, hex3) => decodeCodePoint(match, hex3, 16)).replace(/&#([0-9]+);?/g, (match, decimal) => decodeCodePoint(match, decimal, 10)).replace(/&nbsp(?:;|(?![0-9a-z]))/gi, " ").replace(/&quot(?:;|(?![0-9a-z]))/gi, '"').replace(/&apos(?:;|(?![0-9a-z]))/gi, "'").replace(/&lt(?:;|(?![0-9a-z]))/gi, "<").replace(/&gt(?:;|(?![0-9a-z]))/gi, ">").replace(/&amp(?:;|(?![0-9a-z]))/gi, "&");
45058
45462
  }
45059
45463
  function firstVisibleHtmlLine(html) {
45060
- let text = html;
45464
+ let text2 = html;
45061
45465
  let previous;
45062
45466
  do {
45063
- previous = text;
45064
- text = text.replace(NON_RENDERED_BLOCK_RE, "");
45065
- } while (text !== previous);
45066
- text = text.replace(BREAK_RE, "\n").replace(BLOCK_END_RE, "\n");
45467
+ previous = text2;
45468
+ text2 = text2.replace(NON_RENDERED_BLOCK_RE, "");
45469
+ } while (text2 !== previous);
45470
+ text2 = text2.replace(BREAK_RE, "\n").replace(BLOCK_END_RE, "\n");
45067
45471
  do {
45068
- previous = text;
45069
- text = text.replace(TAG_RE, "");
45070
- } while (text !== previous);
45071
- return decodeHtmlEntities(text).split(/[\r\n\u2028\u2029]+/).map((line) => line.replace(/\s+/g, " ").trim()).find(Boolean);
45472
+ previous = text2;
45473
+ text2 = text2.replace(TAG_RE, "");
45474
+ } while (text2 !== previous);
45475
+ return decodeHtmlEntities(text2).split(/[\r\n\u2028\u2029]+/).map((line) => line.replace(/\s+/g, " ").trim()).find(Boolean);
45072
45476
  }
45073
45477
  function resolveUpdateResponseTitle(currentTitle, newTitle, format, newContent) {
45074
45478
  if (format === "html") return firstVisibleHtmlLine(newContent) ?? currentTitle;
@@ -45233,15 +45637,15 @@ function splitComparison(value) {
45233
45637
  const match = COMPARE_RE.exec(value);
45234
45638
  return [match[1] ?? "=", match[2]];
45235
45639
  }
45236
- function parseLocalDate(text, pos) {
45237
- const match = /^(\d{4})-(\d{2})-(\d{2})$/.exec(text);
45640
+ function parseLocalDate(text2, pos) {
45641
+ const match = /^(\d{4})-(\d{2})-(\d{2})$/.exec(text2);
45238
45642
  if (!match) {
45239
- throw new NoteQueryError(`Expected a date as YYYY-MM-DD, got "${text}"`, pos);
45643
+ throw new NoteQueryError(`Expected a date as YYYY-MM-DD, got "${text2}"`, pos);
45240
45644
  }
45241
45645
  const [year, month, day] = [Number(match[1]), Number(match[2]), Number(match[3])];
45242
45646
  const start = new Date(year, month - 1, day);
45243
45647
  if (start.getFullYear() !== year || start.getMonth() !== month - 1 || start.getDate() !== day) {
45244
- throw new NoteQueryError(`"${text}" is not a valid calendar date`, pos);
45648
+ throw new NoteQueryError(`"${text2}" is not a valid calendar date`, pos);
45245
45649
  }
45246
45650
  return { start: start.getTime(), end: new Date(year, month - 1, day + 1).getTime() };
45247
45651
  }
@@ -45415,8 +45819,8 @@ var Parser = class {
45415
45819
  function parseNoteQuery(input) {
45416
45820
  return new Parser(tokenize(input), input.length).parse();
45417
45821
  }
45418
- function normalizeForMatch(text) {
45419
- return text.normalize("NFC").replace(/[\ufffc\u00a0]/gu, " ").toLowerCase();
45822
+ function normalizeForMatch(text2) {
45823
+ return text2.normalize("NFC").replace(/[\ufffc\u00a0]/gu, " ").toLowerCase();
45420
45824
  }
45421
45825
  function needsContent(node) {
45422
45826
  switch (node.type) {
@@ -45545,18 +45949,18 @@ function positiveTextTerms(node, negated = false) {
45545
45949
  }
45546
45950
 
45547
45951
  // src/utils/noteQueryStore.ts
45548
- import { execFileSync as execFileSync11 } from "child_process";
45549
- import * as fs6 from "fs";
45550
- import * as os6 from "os";
45551
- import * as path6 from "path";
45552
- import { gunzipSync as gunzipSync6 } from "zlib";
45553
- var NOTES_DB_PATH7 = path6.join(
45554
- os6.homedir(),
45952
+ import { execFileSync as execFileSync12 } from "child_process";
45953
+ import * as fs7 from "fs";
45954
+ import * as os7 from "os";
45955
+ import * as path7 from "path";
45956
+ import { gunzipSync as gunzipSync7 } from "zlib";
45957
+ var NOTES_DB_PATH8 = path7.join(
45958
+ os7.homedir(),
45555
45959
  "Library/Group Containers/group.com.apple.notes/NoteStore.sqlite"
45556
45960
  );
45557
45961
  var QUERY_SCAN = { DEFAULT: 500, MAX: 5e3 };
45558
45962
  var QUERY_RESULTS = { DEFAULT: 50, MAX: 500 };
45559
- var CORE_DATA_EPOCH_MS = Date.UTC(2001, 0, 1);
45963
+ var CORE_DATA_EPOCH_MS2 = Date.UTC(2001, 0, 1);
45560
45964
  var SNIPPET_BEFORE = 60;
45561
45965
  var SNIPPET_LENGTH = 180;
45562
45966
  var QUERY_FDA_MESSAGE = `Full Disk Access is required to query notes. In System Settings > Privacy & Security > Full Disk Access, grant access to the app that launches this server (Claude Desktop / Terminal / iTerm2), then fully quit and relaunch it. Setup guide: ${FULL_DISK_ACCESS_GUIDE_URL} \u2014 run the doctor tool to verify.`;
@@ -45595,8 +45999,8 @@ var CHECKLIST_STYLE = 103;
45595
45999
  function decodeNoteBody(data) {
45596
46000
  const wrapper = embeddedMessage(getField(decodeMessage(data), 2));
45597
46001
  const body = wrapper && embeddedMessage(getField(wrapper, 3));
45598
- const text = body && stringValue(getField(body, 2));
45599
- if (!body || text === void 0) return null;
46002
+ const text2 = body && stringValue(getField(body, 2));
46003
+ if (!body || text2 === void 0) return null;
45600
46004
  const facets = /* @__PURE__ */ new Set();
45601
46005
  const objectIds = /* @__PURE__ */ new Set();
45602
46006
  const checklist = /* @__PURE__ */ new Map();
@@ -45617,7 +46021,7 @@ function decodeNoteBody(data) {
45617
46021
  if (paragraph && varintValue(getField(paragraph, 1)) === CHECKLIST_STYLE) {
45618
46022
  const item = embeddedMessage(getField(paragraph, 5));
45619
46023
  const rawId = item && getField(item, 1)?.value;
45620
- const key = rawId instanceof Uint8Array ? Buffer.from(rawId).toString("hex") : `line:${text.lastIndexOf("\n", position - 1) + 1}`;
46024
+ const key = rawId instanceof Uint8Array ? Buffer.from(rawId).toString("hex") : `line:${text2.lastIndexOf("\n", position - 1) + 1}`;
45621
46025
  checklist.set(key, (item && varintValue(getField(item, 2))) === 1);
45622
46026
  }
45623
46027
  position += length;
@@ -45625,24 +46029,24 @@ function decodeNoteBody(data) {
45625
46029
  if (checklist.size > 0) facets.add("checklist");
45626
46030
  const done = [...checklist.values()].filter(Boolean).length;
45627
46031
  return {
45628
- text,
46032
+ text: text2,
45629
46033
  facets,
45630
46034
  checklist: { total: checklist.size, open: checklist.size - done },
45631
46035
  objectIds
45632
46036
  };
45633
46037
  }
45634
- function countWords(text) {
46038
+ function countWords(text2) {
45635
46039
  let count = 0;
45636
- for (const word of text.replace(/\ufffc/gu, " ").split(/\s+/u)) {
46040
+ for (const word of text2.replace(/\ufffc/gu, " ").split(/\s+/u)) {
45637
46041
  if (/[\p{L}\p{N}]/u.test(word)) count++;
45638
46042
  }
45639
46043
  return count;
45640
46044
  }
45641
46045
  var REQUIRED_COLUMNS3 = ["Z_PK", "Z_ENT", "ZTITLE1", "ZFOLDER", "ZMODIFICATIONDATE1"];
45642
- function col(available, alias, name) {
46046
+ function col2(available, alias, name) {
45643
46047
  return available.has(name) ? `${alias}.${name}` : "NULL";
45644
46048
  }
45645
- var entity = (name) => `(SELECT Z_ENT FROM Z_PRIMARYKEY WHERE Z_NAME='${name}')`;
46049
+ var entity2 = (name) => `(SELECT Z_ENT FROM Z_PRIMARYKEY WHERE Z_NAME='${name}')`;
45646
46050
  function buildScanSql(available, options) {
45647
46051
  const missing = REQUIRED_COLUMNS3.filter((c) => !available.has(c));
45648
46052
  if (missing.length) {
@@ -45660,21 +46064,21 @@ function buildScanSql(available, options) {
45660
46064
  const bool = (name) => available.has(name) ? `COALESCE(n.${name}, 0)` : "0";
45661
46065
  const notNull = (alias, name) => available.has(name) ? `${alias}.${name} IS NOT NULL` : "0";
45662
46066
  const tagsExpr = options.withTags && ["ZNOTE1", "ZTYPEUTI1", "ZALTTEXT", "ZIDENTIFIER"].every((c) => available.has(c)) ? `(SELECT json_group_array(json_array(t.ZIDENTIFIER, t.ZALTTEXT)) FROM ZICCLOUDSYNCINGOBJECT t WHERE t.ZNOTE1 = n.Z_PK AND t.ZTYPEUTI1 = 'com.apple.notes.inlinetextattachment.hashtag')` : "NULL";
45663
- const where = [`n.Z_ENT = ${entity("ICNote")}`];
46067
+ const where = [`n.Z_ENT = ${entity2("ICNote")}`];
45664
46068
  if (!options.includeDeleted) {
45665
46069
  where.push("n.ZFOLDER IS NOT NULL");
45666
46070
  if (available.has("ZMARKEDFORDELETION")) where.push("COALESCE(n.ZMARKEDFORDELETION, 0) = 0");
45667
46071
  if (available.has("ZFOLDERTYPE")) {
45668
46072
  where.push(
45669
- `n.ZFOLDER NOT IN (SELECT Z_PK FROM ZICCLOUDSYNCINGOBJECT WHERE Z_ENT = ${entity("ICFolder")} AND ZFOLDERTYPE = 1)`
46073
+ `n.ZFOLDER NOT IN (SELECT Z_PK FROM ZICCLOUDSYNCINGOBJECT WHERE Z_ENT = ${entity2("ICFolder")} AND ZFOLDERTYPE = 1)`
45670
46074
  );
45671
46075
  }
45672
46076
  }
45673
46077
  const whereSql = where.join(" AND ");
45674
- const folderRow = `SELECT json_object('k', 'folder', 'pk', f.Z_PK, 'name', ${col(available, "f", "ZTITLE2")}, 'parent', ${col(available, "f", "ZPARENT")}, 'type', ${col(available, "f", "ZFOLDERTYPE")}, 'owner', ${col(available, "f", "ZOWNER")}, 'shared', ${notNull("f", "ZSERVERSHAREDATA")}) FROM ZICCLOUDSYNCINGOBJECT f WHERE f.Z_ENT = ${entity("ICFolder")};`;
45675
- const accountRow = `SELECT json_object('k', 'account', 'pk', a.Z_PK, 'name', ${col(available, "a", "ZNAME")}) FROM ZICCLOUDSYNCINGOBJECT a WHERE a.Z_ENT = ${entity("ICAccount")};`;
46078
+ const folderRow = `SELECT json_object('k', 'folder', 'pk', f.Z_PK, 'name', ${col2(available, "f", "ZTITLE2")}, 'parent', ${col2(available, "f", "ZPARENT")}, 'type', ${col2(available, "f", "ZFOLDERTYPE")}, 'owner', ${col2(available, "f", "ZOWNER")}, 'shared', ${notNull("f", "ZSERVERSHAREDATA")}) FROM ZICCLOUDSYNCINGOBJECT f WHERE f.Z_ENT = ${entity2("ICFolder")};`;
46079
+ const accountRow = `SELECT json_object('k', 'account', 'pk', a.Z_PK, 'name', ${col2(available, "a", "ZNAME")}) FROM ZICCLOUDSYNCINGOBJECT a WHERE a.Z_ENT = ${entity2("ICAccount")};`;
45676
46080
  const dataExpr = options.withBodies ? "(SELECT hex(d.ZDATA) FROM ZICNOTEDATA d WHERE d.ZNOTE = n.Z_PK ORDER BY d.Z_PK DESC LIMIT 1)" : "NULL";
45677
- const noteRow = `SELECT json_object('k', 'note', 'pk', n.Z_PK, 'title', n.ZTITLE1, 'folder', n.ZFOLDER, 'created', ${createdExpr}, 'modified', n.ZMODIFICATIONDATE1, 'pinned', ${bool("ZISPINNED")}, 'locked', ${bool("ZISPASSWORDPROTECTED")}, 'shared', ${notNull("n", "ZSERVERSHAREDATA")}, 'snippet', ${col(available, "n", "ZSNIPPET")}, 'data', ${dataExpr}, 'tags', ${tagsExpr}) FROM ZICCLOUDSYNCINGOBJECT n WHERE ${whereSql} ORDER BY n.ZMODIFICATIONDATE1 DESC, n.Z_PK DESC LIMIT ${scan};`;
46081
+ const noteRow = `SELECT json_object('k', 'note', 'pk', n.Z_PK, 'title', n.ZTITLE1, 'folder', n.ZFOLDER, 'created', ${createdExpr}, 'modified', n.ZMODIFICATIONDATE1, 'pinned', ${bool("ZISPINNED")}, 'locked', ${bool("ZISPASSWORDPROTECTED")}, 'shared', ${notNull("n", "ZSERVERSHAREDATA")}, 'snippet', ${col2(available, "n", "ZSNIPPET")}, 'data', ${dataExpr}, 'tags', ${tagsExpr}) FROM ZICCLOUDSYNCINGOBJECT n WHERE ${whereSql} ORDER BY n.ZMODIFICATIONDATE1 DESC, n.Z_PK DESC LIMIT ${scan};`;
45678
46082
  return [
45679
46083
  "BEGIN;",
45680
46084
  "SELECT json_object('k', 'meta', 'uuid', (SELECT Z_UUID FROM Z_METADATA LIMIT 1));",
@@ -45686,7 +46090,7 @@ function buildScanSql(available, options) {
45686
46090
  ].join(" ");
45687
46091
  }
45688
46092
  function runSqlite6(dbPath2, query) {
45689
- return execFileSync11("sqlite3", ["-readonly", dbPath2, query], {
46093
+ return execFileSync12("sqlite3", ["-readonly", dbPath2, query], {
45690
46094
  encoding: "utf8",
45691
46095
  timeout: 3e4,
45692
46096
  maxBuffer: 512 * 1024 * 1024,
@@ -45705,32 +46109,32 @@ var escapeSegment = escapeFolderName;
45705
46109
  function resolveFolders(rows) {
45706
46110
  const byPk = new Map(rows.map((row) => [row.pk, row]));
45707
46111
  const resolved = /* @__PURE__ */ new Map();
45708
- const resolve4 = (pk, seen) => {
46112
+ const resolve5 = (pk, seen) => {
45709
46113
  const cached2 = resolved.get(pk);
45710
46114
  if (cached2) return cached2;
45711
46115
  const row = byPk.get(pk);
45712
46116
  if (!row || seen.has(pk)) return void 0;
45713
46117
  seen.add(pk);
45714
- const parent = row.parent !== null ? resolve4(row.parent, seen) : void 0;
46118
+ const parent = row.parent !== null ? resolve5(row.parent, seen) : void 0;
45715
46119
  const name = row.name ?? "";
45716
- const path7 = parent ? `${parent.path}/${escapeSegment(name)}` : escapeSegment(name);
46120
+ const path8 = parent ? `${parent.path}/${escapeSegment(name)}` : escapeSegment(name);
45717
46121
  const plainPath = parent ? `${parent.plainPath}/${name}` : name;
45718
46122
  const info = {
45719
- path: path7,
46123
+ path: path8,
45720
46124
  plainPath,
45721
- keys: [...new Set([name, plainPath, path7].map(normalizeForMatch))],
46125
+ keys: [...new Set([name, plainPath, path8].map(normalizeForMatch))],
45722
46126
  accountPk: row.owner ?? parent?.accountPk ?? null,
45723
46127
  shared: Boolean(row.shared) || Boolean(parent?.shared)
45724
46128
  };
45725
46129
  resolved.set(pk, info);
45726
46130
  return info;
45727
46131
  };
45728
- for (const row of rows) resolve4(row.pk, /* @__PURE__ */ new Set());
46132
+ for (const row of rows) resolve5(row.pk, /* @__PURE__ */ new Set());
45729
46133
  return resolved;
45730
46134
  }
45731
- var coreDataMs = (seconds) => seconds === null || !Number.isFinite(seconds) ? void 0 : CORE_DATA_EPOCH_MS + seconds * 1e3;
45732
- function buildSnippet(text, terms) {
45733
- const clean = text.replace(/\ufffc/gu, " ");
46135
+ var coreDataMs = (seconds) => seconds === null || !Number.isFinite(seconds) ? void 0 : CORE_DATA_EPOCH_MS2 + seconds * 1e3;
46136
+ function buildSnippet(text2, terms) {
46137
+ const clean = text2.replace(/\ufffc/gu, " ");
45734
46138
  const firstBreak = clean.indexOf("\n");
45735
46139
  const body = firstBreak === -1 ? clean : clean.slice(firstBreak + 1);
45736
46140
  const lower = normalizeForMatch(body);
@@ -45750,8 +46154,8 @@ function queryNotes(expression, options = {}) {
45750
46154
  const includeDeleted = options.includeDeleted ?? false;
45751
46155
  const withBodies = needsContent(ast);
45752
46156
  const withTags = needsTags(ast);
45753
- const dbPath2 = options.dbPath ?? NOTES_DB_PATH7;
45754
- if (!fs6.existsSync(dbPath2)) throw new NoteQueryStoreError(QUERY_FDA_MESSAGE, "no_fda");
46157
+ const dbPath2 = options.dbPath ?? NOTES_DB_PATH8;
46158
+ if (!fs7.existsSync(dbPath2)) throw new NoteQueryStoreError(QUERY_FDA_MESSAGE, "no_fda");
45755
46159
  let output;
45756
46160
  try {
45757
46161
  const available = presentColumns2(dbPath2);
@@ -45811,7 +46215,7 @@ function queryNotes(expression, options = {}) {
45811
46215
  try {
45812
46216
  decoded = decodeNoteBody(
45813
46217
  new Uint8Array(
45814
- gunzipSync6(Buffer.from(row.data, "hex"), { maxOutputLength: 32 * 1024 * 1024 })
46218
+ gunzipSync7(Buffer.from(row.data, "hex"), { maxOutputLength: 32 * 1024 * 1024 })
45815
46219
  )
45816
46220
  );
45817
46221
  } catch {
@@ -45833,8 +46237,8 @@ function queryNotes(expression, options = {}) {
45833
46237
  if (content !== void 0) return content;
45834
46238
  const body2 = decode2();
45835
46239
  if (!body2) return content = null;
45836
- const text = body2.text;
45837
- const firstBreak = text.indexOf("\n");
46240
+ const text2 = body2.text;
46241
+ const firstBreak = text2.indexOf("\n");
45838
46242
  const tags = /* @__PURE__ */ new Set();
45839
46243
  for (const [id2, alt] of row.tags ?? []) {
45840
46244
  if (id2 && alt && body2.objectIds.has(id2))
@@ -45843,9 +46247,9 @@ function queryNotes(expression, options = {}) {
45843
46247
  const facets = new Set(body2.facets);
45844
46248
  if (tags.size) facets.add("tag");
45845
46249
  content = {
45846
- textLower: normalizeForMatch(text),
45847
- bodyLower: normalizeForMatch(firstBreak === -1 ? "" : text.slice(firstBreak + 1)),
45848
- words: countWords(text),
46250
+ textLower: normalizeForMatch(text2),
46251
+ bodyLower: normalizeForMatch(firstBreak === -1 ? "" : text2.slice(firstBreak + 1)),
46252
+ words: countWords(text2),
45849
46253
  facets,
45850
46254
  checklist: body2.checklist,
45851
46255
  tags: [...tags]
@@ -45886,10 +46290,10 @@ function queryNotes(expression, options = {}) {
45886
46290
  import { spawnSync } from "child_process";
45887
46291
 
45888
46292
  // src/services/nativeTags.ts
45889
- import { execFileSync as execFileSync12 } from "node:child_process";
46293
+ import { execFileSync as execFileSync13 } from "node:child_process";
45890
46294
  import { mkdtempSync as mkdtempSync2, writeFileSync, rmSync as rmSync2 } from "node:fs";
45891
46295
  import { tmpdir as tmpdir2 } from "node:os";
45892
- import { join as join13 } from "node:path";
46296
+ import { join as join14 } from "node:path";
45893
46297
 
45894
46298
  // src/services/shortcutConsent.ts
45895
46299
  function shortcutConsentHint(shortcut) {
@@ -45943,12 +46347,12 @@ function addNativeTags(request, deps) {
45943
46347
  }
45944
46348
  const after = deps.read(request.id);
45945
46349
  const allTags = [.../* @__PURE__ */ new Set([...before.rich.nativeTags, ...tags])];
45946
- const textWithoutTags = (text) => {
46350
+ const textWithoutTags = (text2) => {
45947
46351
  for (const tag of [...allTags].sort((a, b) => b.length - a.length)) {
45948
46352
  const escaped = tag.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
45949
- text = text.replace(new RegExp(`#${escaped}(?![\\p{L}\\p{N}_-])`, "gu"), "");
46353
+ text2 = text2.replace(new RegExp(`#${escaped}(?![\\p{L}\\p{N}_-])`, "gu"), "");
45950
46354
  }
45951
- return text.replace(/[\s\ufffc]/gu, "");
46355
+ return text2.replace(/[\s\ufffc]/gu, "");
45952
46356
  };
45953
46357
  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) {
45954
46358
  throw new Error(
@@ -45965,7 +46369,7 @@ function addNativeTags(request, deps) {
45965
46369
  };
45966
46370
  }
45967
46371
  function listInstalledShortcuts() {
45968
- return execFileSync12("/usr/bin/shortcuts", ["list", "--show-identifiers"], {
46372
+ return execFileSync13("/usr/bin/shortcuts", ["list", "--show-identifiers"], {
45969
46373
  encoding: "utf8",
45970
46374
  timeout: 15e3,
45971
46375
  maxBuffer: 1024 * 1024,
@@ -45991,11 +46395,11 @@ function runNativeTagsShortcut(input) {
45991
46395
  const status = nativeTagsStatus();
45992
46396
  if (!status.installed)
45993
46397
  throw new Error(`Import the supplied ${status.shortcut}.shortcut in Shortcuts first`);
45994
- const directory = mkdtempSync2(join13(tmpdir2(), "apple-notes-native-tags-"));
46398
+ const directory = mkdtempSync2(join14(tmpdir2(), "apple-notes-native-tags-"));
45995
46399
  try {
45996
- const path7 = join13(directory, "request.json");
45997
- writeFileSync(path7, JSON.stringify(input), { mode: 384 });
45998
- execFileSync12("/usr/bin/shortcuts", ["run", status.identifier, "--input-path", path7], {
46400
+ const path8 = join14(directory, "request.json");
46401
+ writeFileSync(path8, JSON.stringify(input), { mode: 384 });
46402
+ execFileSync13("/usr/bin/shortcuts", ["run", status.identifier, "--input-path", path8], {
45999
46403
  encoding: "utf8",
46000
46404
  timeout: 6e4,
46001
46405
  maxBuffer: 1024 * 1024,
@@ -46014,10 +46418,10 @@ function runNativeTagsShortcut(input) {
46014
46418
  }
46015
46419
 
46016
46420
  // src/services/backgroundNotes.ts
46017
- import { execFileSync as execFileSync13 } from "node:child_process";
46421
+ import { execFileSync as execFileSync14 } from "node:child_process";
46018
46422
  import { mkdtempSync as mkdtempSync3, writeFileSync as writeFileSync2, rmSync as rmSync3 } from "node:fs";
46019
46423
  import { tmpdir as tmpdir3 } from "node:os";
46020
- import { join as join14 } from "node:path";
46424
+ import { join as join15 } from "node:path";
46021
46425
 
46022
46426
  // src/utils/appendMarkdown.ts
46023
46427
  var escape2 = (s) => s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
@@ -46069,9 +46473,9 @@ function renderMarkdown(markdown, options = {}) {
46069
46473
  dividers: 0,
46070
46474
  highlights: []
46071
46475
  };
46072
- const inline = (text) => {
46476
+ const inline = (text2) => {
46073
46477
  const spans = [];
46074
- let value = text;
46478
+ let value = text2;
46075
46479
  if (blocks)
46076
46480
  value = value.replace(/`([^`\n]+)`/g, (_s, code2) => {
46077
46481
  if (/^\s|\s$/.test(code2)) throw new Error("Inline code cannot start or end with a space");
@@ -46093,13 +46497,13 @@ function renderMarkdown(markdown, options = {}) {
46093
46497
  return value.replace(/(\d+)/g, (_s, i) => links[Number(i)]).replace(/(\d+)/g, (_s, i) => spans[Number(i)]);
46094
46498
  };
46095
46499
  const withoutTags = (html2) => {
46096
- let text = "", inTag = false;
46500
+ let text2 = "", inTag = false;
46097
46501
  for (const ch of html2) {
46098
46502
  if (ch === "<") inTag = true;
46099
46503
  else if (ch === ">" && inTag) inTag = false;
46100
- else if (!inTag) text += ch;
46504
+ else if (!inTag) text2 += ch;
46101
46505
  }
46102
- return text;
46506
+ return text2;
46103
46507
  };
46104
46508
  const visible = (html2) => withoutTags(html2).replace(/&quot;/g, '"').replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&amp;/g, "&");
46105
46509
  let html = "", list, quote = false, code, previousBlank = true;
@@ -46136,9 +46540,9 @@ function renderMarkdown(markdown, options = {}) {
46136
46540
  continue;
46137
46541
  }
46138
46542
  if (line.startsWith(">")) {
46139
- const text = line.replace(/^> ?/, "");
46140
- if (!text.trim()) throw new Error("Empty block quote lines are unsupported");
46141
- if (/^(?:#|[-+*][ \t]|\d+[.)][ \t]|>|```)/.test(text))
46543
+ const text2 = line.replace(/^> ?/, "");
46544
+ if (!text2.trim()) throw new Error("Empty block quote lines are unsupported");
46545
+ if (/^(?:#|[-+*][ \t]|\d+[.)][ \t]|>|```)/.test(text2))
46142
46546
  throw new Error("Block quotes support text and inline formatting only");
46143
46547
  if (!quote) {
46144
46548
  close();
@@ -46146,7 +46550,7 @@ function renderMarkdown(markdown, options = {}) {
46146
46550
  quote = true;
46147
46551
  expect.quotes.push("");
46148
46552
  }
46149
- const rendered = inline(text);
46553
+ const rendered = inline(text2);
46150
46554
  html += `<div>${rendered}</div>`;
46151
46555
  expect.quotes[expect.quotes.length - 1] += ` ${visible(rendered)}`;
46152
46556
  previousBlank = false;
@@ -46342,9 +46746,9 @@ function runBackgroundShortcut(input, status = backgroundStatus()) {
46342
46746
  throw new Error(
46343
46747
  `Install the supplied "${status.shortcut}" Shortcut once; Shortcuts must list it exactly once`
46344
46748
  );
46345
- const directory = mkdtempSync3(join14(tmpdir3(), "apple-notes-background-"));
46749
+ const directory = mkdtempSync3(join15(tmpdir3(), "apple-notes-background-"));
46346
46750
  try {
46347
- const file = join14(directory, "request.json");
46751
+ const file = join15(directory, "request.json");
46348
46752
  writeFileSync2(
46349
46753
  file,
46350
46754
  JSON.stringify({
@@ -46364,7 +46768,7 @@ function runBackgroundShortcut(input, status = backgroundStatus()) {
46364
46768
  { mode: 384 }
46365
46769
  );
46366
46770
  try {
46367
- execFileSync13("/usr/bin/shortcuts", ["run", status.identifier, "--input-path", file], {
46771
+ execFileSync14("/usr/bin/shortcuts", ["run", status.identifier, "--input-path", file], {
46368
46772
  encoding: "utf8",
46369
46773
  timeout: callTimeoutMs() ?? 6e4,
46370
46774
  maxBuffer: 1024 * 1024,
@@ -46507,11 +46911,11 @@ function appendNative(manager, request) {
46507
46911
  throw new Error("Use create-table for verified native table insertion");
46508
46912
  const markdownHtml = request.format === "markdown" ? appendMarkdownHtml(request.content) : null;
46509
46913
  const op = request.format === "plaintext" ? "append-text" : request.format === "markdown" ? "append-markdown" : "append-html";
46510
- const text = request.format === "html" ? "<div><br></div>" + request.content : "\n\n" + request.content;
46914
+ const text2 = request.format === "html" ? "<div><br></div>" + request.content : "\n\n" + request.content;
46511
46915
  return mutateBackground(
46512
46916
  request,
46513
46917
  op,
46514
- { text },
46918
+ { text: text2 },
46515
46919
  (before, after) => {
46516
46920
  assertPreserved(before, after, { append: true });
46517
46921
  const verifyHtml = markdownHtml ?? request.content;
@@ -46551,7 +46955,7 @@ function setNativeTag(manager, request) {
46551
46955
  deps
46552
46956
  );
46553
46957
  }
46554
- var literalMarkdown = (text) => text.replace(/[!-/:-@[-`{-~]/g, "\\$&");
46958
+ var literalMarkdown = (text2) => text2.replace(/[!-/:-@[-`{-~]/g, "\\$&");
46555
46959
  function headingLevels(html) {
46556
46960
  return [...html.matchAll(/<h([1-3])\b[^>]*>([\s\S]*?)<\/h\1>/gi)].filter((match) => comparableVisibleText(match[2])).map((match) => Number(match[1]));
46557
46961
  }
@@ -46599,7 +47003,7 @@ function createMarkdownNote(manager, request, run = runBackgroundShortcut) {
46599
47003
  throw new Error(
46600
47004
  `Install the supplied "${status.shortcut}" Shortcut once; Shortcuts must list it exactly once`
46601
47005
  );
46602
- const segments = (path7) => JSON.stringify(splitFolderPath(path7).map((part) => part.toLocaleLowerCase()));
47006
+ const segments = (path8) => JSON.stringify(splitFolderPath(path8).map((part) => part.toLocaleLowerCase()));
46603
47007
  if (request.folder) {
46604
47008
  const wanted = segments(request.folder);
46605
47009
  if (!manager.listAccounts().some(
@@ -46689,7 +47093,7 @@ ${request.content}`
46689
47093
  }
46690
47094
 
46691
47095
  // src/services/capabilityMatrix.ts
46692
- import { execFileSync as execFileSync14 } from "node:child_process";
47096
+ import { execFileSync as execFileSync15 } from "node:child_process";
46693
47097
  import { release } from "node:os";
46694
47098
  var MACOS_SHORTCUTS_CLI = "12.0";
46695
47099
  var MACOS_MARKDOWN_IMPORT = "26.0";
@@ -46896,7 +47300,7 @@ function evaluateFeatures(env, features = FEATURES) {
46896
47300
  function readMacOSVersion() {
46897
47301
  if (process.platform !== "darwin") return null;
46898
47302
  try {
46899
- const out = execFileSync14("/usr/bin/sw_vers", ["-productVersion"], {
47303
+ const out = execFileSync15("/usr/bin/sw_vers", ["-productVersion"], {
46900
47304
  encoding: "utf8",
46901
47305
  timeout: 3e3,
46902
47306
  stdio: ["ignore", "pipe", "ignore"]
@@ -46929,9 +47333,9 @@ function getCapabilityMatrix(probe = probeCapabilityEnvironment) {
46929
47333
  return evaluateFeatures(probe());
46930
47334
  }
46931
47335
  function formatCapabilityMatrix(matrix) {
46932
- const os7 = matrix.runtimeOS;
47336
+ const os8 = matrix.runtimeOS;
46933
47337
  const lines = [
46934
- `Feature matrix (macOS ${os7.macOSVersion ?? "unknown"}, Darwin ${os7.darwinRelease}):`
47338
+ `Feature matrix (macOS ${os8.macOSVersion ?? "unknown"}, Darwin ${os8.darwinRelease}):`
46935
47339
  ];
46936
47340
  for (const [name, status] of Object.entries(matrix.features)) {
46937
47341
  lines.push(
@@ -47049,19 +47453,19 @@ function formatDoctorReport(r) {
47049
47453
  }
47050
47454
 
47051
47455
  // src/services/fileConfig.ts
47052
- import { existsSync as existsSync9, readFileSync as readFileSync2 } from "fs";
47053
- import { join as join15 } from "path";
47054
- import { homedir as homedir12 } from "os";
47456
+ import { existsSync as existsSync10, readFileSync as readFileSync2 } from "fs";
47457
+ import { join as join16 } from "path";
47458
+ import { homedir as homedir13 } from "os";
47055
47459
  function fileConfigPath(env = process.env) {
47056
47460
  const override = env.APPLE_NOTES_MCP_CONFIG_FILE;
47057
47461
  if (override && override.trim()) return override.trim();
47058
- return join15(homedir12(), "Library", "Application Support", "apple-notes-mcp", "config.json");
47462
+ return join16(homedir13(), "Library", "Application Support", "apple-notes-mcp", "config.json");
47059
47463
  }
47060
- function loadFileConfig(env = process.env, path7 = fileConfigPath(env)) {
47464
+ function loadFileConfig(env = process.env, path8 = fileConfigPath(env)) {
47061
47465
  const applied = [];
47062
47466
  try {
47063
- if (!existsSync9(path7)) return applied;
47064
- const parsed = JSON.parse(readFileSync2(path7, "utf8"));
47467
+ if (!existsSync10(path8)) return applied;
47468
+ const parsed = JSON.parse(readFileSync2(path8, "utf8"));
47065
47469
  if (!parsed || typeof parsed !== "object") return applied;
47066
47470
  for (const [k, v] of Object.entries(parsed)) {
47067
47471
  if (typeof v !== "string") continue;
@@ -47071,7 +47475,7 @@ function loadFileConfig(env = process.env, path7 = fileConfigPath(env)) {
47071
47475
  }
47072
47476
  }
47073
47477
  } catch (e) {
47074
- console.error(`Failed to load apple-notes-mcp config file ${path7}: ${String(e)}`);
47478
+ console.error(`Failed to load apple-notes-mcp config file ${path8}: ${String(e)}`);
47075
47479
  }
47076
47480
  return applied;
47077
47481
  }
@@ -47308,18 +47712,18 @@ var NOTHING_WRITTEN = /nothing (?:was )?(?:changed|created|written)|no replaceme
47308
47712
  var WRITE_ACCEPTED = /\baccepted (?:the|an) \w+, but/i;
47309
47713
  function classifyError(message, cause) {
47310
47714
  if (cause instanceof CodedError) return { ...cause.envelope };
47311
- const text = cause instanceof Error && cause.message && !message.includes(cause.message) ? `${message}
47715
+ const text2 = cause instanceof Error && cause.message && !message.includes(cause.message) ? `${message}
47312
47716
  ${cause.message}` : message;
47313
47717
  const timeoutCause = typeof cause === "object" && cause !== null && cause.code === "ETIMEDOUT";
47314
47718
  let code = "operation_failed";
47315
47719
  if (timeoutCause) code = "timeout_indeterminate";
47316
- else if (isPermissionDenied(text)) code = "permission_denied";
47317
- else code = RULES.find((rule) => rule.pattern.test(text))?.code ?? "operation_failed";
47720
+ else if (isPermissionDenied(text2)) code = "permission_denied";
47721
+ else code = RULES.find((rule) => rule.pattern.test(text2))?.code ?? "operation_failed";
47318
47722
  const envelope = { code };
47319
47723
  if (code === "timeout_indeterminate" || code === "verification_failed") {
47320
47724
  envelope.indeterminate = true;
47321
- if (WRITE_ACCEPTED.test(text)) envelope.committed = true;
47322
- } else if (code === "revision_conflict" || NOTHING_WRITTEN.test(text)) {
47725
+ if (WRITE_ACCEPTED.test(text2)) envelope.committed = true;
47726
+ } else if (code === "revision_conflict" || NOTHING_WRITTEN.test(text2)) {
47323
47727
  envelope.committed = false;
47324
47728
  envelope.indeterminate = false;
47325
47729
  }
@@ -47358,11 +47762,11 @@ function createShutdown(stream, exit, timeoutMs = SHUTDOWN_DRAIN_TIMEOUT_MS) {
47358
47762
  }
47359
47763
 
47360
47764
  // src/utils/noteBlocks.ts
47361
- import { execFileSync as execFileSync15 } from "node:child_process";
47362
- import { existsSync as existsSync10 } from "node:fs";
47363
- import { homedir as homedir13 } from "node:os";
47364
- import { join as join16 } from "node:path";
47365
- import { gunzipSync as gunzipSync7 } from "node:zlib";
47765
+ import { execFileSync as execFileSync16 } from "node:child_process";
47766
+ import { existsSync as existsSync11 } from "node:fs";
47767
+ import { homedir as homedir14 } from "node:os";
47768
+ import { join as join17 } from "node:path";
47769
+ import { gunzipSync as gunzipSync8 } from "node:zlib";
47366
47770
  var NoteBlocksError = class extends Error {
47367
47771
  code;
47368
47772
  constructor(code, message) {
@@ -47509,7 +47913,7 @@ function decodeNoteBlocks(data) {
47509
47913
  const textBytes = note && bytesOf(note, 2);
47510
47914
  if (!note || !textBytes)
47511
47915
  throw new NoteBlocksError("unsupported-structure", "Unsupported Notes document structure");
47512
- const text = utf8.decode(textBytes);
47916
+ const text2 = utf8.decode(textBytes);
47513
47917
  const runTally = /* @__PURE__ */ new Map();
47514
47918
  const paragraphTally = /* @__PURE__ */ new Map();
47515
47919
  const runs = [];
@@ -47520,7 +47924,7 @@ function decodeNoteBlocks(data) {
47520
47924
  throw new NoteBlocksError("invalid-runs", "Invalid Notes attribute run");
47521
47925
  const fields = decodeWireFields(field.bytes);
47522
47926
  const length = varintOf(fields, 1);
47523
- if (length === void 0 || length < 0 || position + length > text.length)
47927
+ if (length === void 0 || length < 0 || position + length > text2.length)
47524
47928
  throw new NoteBlocksError("invalid-runs", "Invalid Notes run length");
47525
47929
  for (const n of new Set(fields.map((f) => f.fieldNumber)))
47526
47930
  if (!KNOWN_RUN_FIELDS.has(n)) runTally.set(n, (runTally.get(n) || 0) + 1);
@@ -47535,15 +47939,15 @@ function decodeNoteBlocks(data) {
47535
47939
  } catch (error2) {
47536
47940
  wrap(error2);
47537
47941
  }
47538
- if (position !== text.length)
47942
+ if (position !== text2.length)
47539
47943
  throw new NoteBlocksError("invalid-runs", "Incomplete Notes attribute runs");
47540
47944
  const blocks = [];
47541
47945
  const attachments = [];
47542
47946
  let runIndex = 0;
47543
47947
  let paragraphStart = 0;
47544
- while (paragraphStart < text.length) {
47545
- const newline = text.indexOf("\n", paragraphStart);
47546
- const end = newline === -1 ? text.length : newline;
47948
+ while (paragraphStart < text2.length) {
47949
+ const newline = text2.indexOf("\n", paragraphStart);
47950
+ const end = newline === -1 ? text2.length : newline;
47547
47951
  while (runIndex < runs.length - 1 && runs[runIndex].start + runs[runIndex].length <= paragraphStart)
47548
47952
  runIndex++;
47549
47953
  const attrs = runs[runIndex]?.paragraph ?? DEFAULT_PARAGRAPH;
@@ -47553,7 +47957,7 @@ function decodeNoteBlocks(data) {
47553
47957
  index: blocks.length,
47554
47958
  start: paragraphStart,
47555
47959
  length: end - paragraphStart,
47556
- text: text.slice(paragraphStart, end),
47960
+ text: text2.slice(paragraphStart, end),
47557
47961
  style,
47558
47962
  styleType: attrs.styleType,
47559
47963
  indent: attrs.indent,
@@ -47573,11 +47977,11 @@ function decodeNoteBlocks(data) {
47573
47977
  block.runs.push({
47574
47978
  start,
47575
47979
  length: stop - start,
47576
- text: text.slice(start, stop),
47980
+ text: text2.slice(start, stop),
47577
47981
  ...run.inline
47578
47982
  });
47579
47983
  if (run.inline.attachment)
47580
- for (let at = text.indexOf("\uFFFC", start); at !== -1 && at < stop; at = text.indexOf("\uFFFC", at + 1)) {
47984
+ for (let at = text2.indexOf("\uFFFC", start); at !== -1 && at < stop; at = text2.indexOf("\uFFFC", at + 1)) {
47581
47985
  const marker = { ...run.inline.attachment, start: at, blockIndex: block.index };
47582
47986
  block.attachments.push(marker);
47583
47987
  attachments.push(marker);
@@ -47587,8 +47991,8 @@ function decodeNoteBlocks(data) {
47587
47991
  paragraphStart = end + 1;
47588
47992
  }
47589
47993
  return {
47590
- text,
47591
- textLength: text.length,
47994
+ text: text2,
47995
+ textLength: text2.length,
47592
47996
  blocks,
47593
47997
  attachments,
47594
47998
  undecodedFields: {
@@ -47650,7 +48054,7 @@ function summarize(blocks, attachments) {
47650
48054
  function decodeCompressedNoteBlocks(compressed) {
47651
48055
  let data;
47652
48056
  try {
47653
- data = gunzipSync7(compressed, { maxOutputLength: 32 * 1024 * 1024 });
48057
+ data = gunzipSync8(compressed, { maxOutputLength: 32 * 1024 * 1024 });
47654
48058
  } catch (error2) {
47655
48059
  throw new NoteBlocksError(
47656
48060
  "decompress-failed",
@@ -47704,23 +48108,23 @@ function pageNoteBlocks(doc, { offset = 0, limit = 500, maxBytes = blocksMaxResp
47704
48108
  undecodedFields: doc.undecodedFields
47705
48109
  };
47706
48110
  }
47707
- var NOTES_DB_PATH8 = join16(
47708
- homedir13(),
48111
+ var NOTES_DB_PATH9 = join17(
48112
+ homedir14(),
47709
48113
  "Library/Group Containers/group.com.apple.notes/NoteStore.sqlite"
47710
48114
  );
47711
- function readNoteBlocks(id2, { dbPath: dbPath2 = NOTES_DB_PATH8 } = {}) {
48115
+ function readNoteBlocks(id2, { dbPath: dbPath2 = NOTES_DB_PATH9 } = {}) {
47712
48116
  const pk = /^x-coredata:\/\/[0-9a-f-]+\/ICNote\/p([0-9]{1,18})$/i.exec(id2)?.[1];
47713
48117
  if (!pk)
47714
48118
  throw new NoteBlocksError(
47715
48119
  "invalid-id",
47716
48120
  `Invalid note ID: expected x-coredata://<store>/ICNote/p<number>`
47717
48121
  );
47718
- if (!existsSync10(dbPath2))
48122
+ if (!existsSync11(dbPath2))
47719
48123
  throw new NoteBlocksError("no-full-disk-access", "The Notes database is not readable");
47720
48124
  const sql = "SELECT json_object('exists', (SELECT count(*) FROM ZICCLOUDSYNCINGOBJECT WHERE Z_PK = @pk AND Z_ENT = (SELECT Z_ENT FROM Z_PRIMARYKEY WHERE Z_NAME = 'ICNote')), 'data', (SELECT hex(ZDATA) FROM ZICNOTEDATA WHERE ZNOTE = @pk), 'encrypted', (SELECT ZCRYPTOINITIALIZATIONVECTOR IS NOT NULL FROM ZICNOTEDATA WHERE ZNOTE = @pk));";
47721
48125
  let output;
47722
48126
  try {
47723
- output = execFileSync15(
48127
+ output = execFileSync16(
47724
48128
  "/usr/bin/sqlite3",
47725
48129
  ["-readonly", "-cmd", ".parameter init", "-cmd", `.parameter set @pk ${pk}`, dbPath2, sql],
47726
48130
  {
@@ -47778,7 +48182,7 @@ function validateLinkLabel(label) {
47778
48182
  throw new Error("Hyperlink label must be one line without control characters");
47779
48183
  return label;
47780
48184
  }
47781
- var escapeText = (text) => text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
48185
+ var escapeText = (text2) => text2.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
47782
48186
  var escapeHref = (url) => escapeText(url).replace(/"/g, "&quot;");
47783
48187
  function buildLinkInsertion(request) {
47784
48188
  const url = validateLinkUrl(request.url);
@@ -47868,20 +48272,1068 @@ function insertLink(request, deps) {
47868
48272
  };
47869
48273
  }
47870
48274
 
47871
- // src/tools/directOperations.ts
47872
- import { createHash as createHash2 } from "node:crypto";
48275
+ // src/services/notesExport.ts
48276
+ import { mkdirSync as mkdirSync5 } from "node:fs";
48277
+ import { dirname as dirname4 } from "node:path";
48278
+
48279
+ // src/utils/exportAssets.ts
47873
48280
  import {
47874
48281
  closeSync as closeSync4,
47875
48282
  constants as constants4,
47876
48283
  fstatSync as fstatSync4,
47877
- mkdtempSync as mkdtempSync4,
48284
+ mkdirSync as mkdirSync4,
47878
48285
  openSync as openSync4,
48286
+ readdirSync as readdirSync3,
48287
+ readSync as readSync3,
48288
+ realpathSync as realpathSync3,
48289
+ statSync as statSync3,
48290
+ writeSync as writeSync3
48291
+ } from "node:fs";
48292
+ import { homedir as homedir15 } from "node:os";
48293
+ import { basename as basename3, extname as extname3, join as join18, relative as relative3, resolve as resolve3, sep as sep3 } from "node:path";
48294
+ var NOTES_CONTAINER = join18(homedir15(), "Library/Group Containers/group.com.apple.notes");
48295
+ var MAX_EMBED_BYTES = 10 * 1024 * 1024;
48296
+ var MAX_DIRECTORY_ENTRIES = 2e4;
48297
+ var MAX_BUNDLE_ENTRIES2 = 64;
48298
+ var IMAGE_EXTENSIONS = /* @__PURE__ */ new Set([".png", ".jpg", ".jpeg", ".heic", ".gif", ".tiff", ".webp"]);
48299
+ function safeComponent2(value) {
48300
+ if (!value || value.length > 255) return void 0;
48301
+ if (value === "." || value === ".." || /[/\\\0]/.test(value)) return void 0;
48302
+ return value;
48303
+ }
48304
+ function confine(candidate, root) {
48305
+ try {
48306
+ const real = realpathSync3.native(candidate);
48307
+ return real.startsWith(root + sep3) ? real : void 0;
48308
+ } catch {
48309
+ return void 0;
48310
+ }
48311
+ }
48312
+ function listDirectory(dir, limit) {
48313
+ try {
48314
+ const names = readdirSync3(dir);
48315
+ return names.length > limit ? [] : names.sort();
48316
+ } catch {
48317
+ return [];
48318
+ }
48319
+ }
48320
+ function isFile(path8) {
48321
+ let fd;
48322
+ try {
48323
+ fd = openSync4(path8, constants4.O_RDONLY | constants4.O_NOFOLLOW);
48324
+ return fstatSync4(fd).isFile();
48325
+ } catch {
48326
+ return false;
48327
+ } finally {
48328
+ if (fd !== void 0) closeSync4(fd);
48329
+ }
48330
+ }
48331
+ function isDirectory2(path8) {
48332
+ try {
48333
+ return statSync3(path8).isDirectory();
48334
+ } catch {
48335
+ return false;
48336
+ }
48337
+ }
48338
+ function previewArea(name) {
48339
+ const sizes = [...name.matchAll(/-(\d{1,5})x(\d{1,5})(?=-|\.|$)/g)];
48340
+ const last = sizes[sizes.length - 1];
48341
+ return last ? Number(last[1]) * Number(last[2]) : 0;
48342
+ }
48343
+ var AssetLocator = class {
48344
+ accounts;
48345
+ previewIndex = /* @__PURE__ */ new Map();
48346
+ constructor(container = NOTES_CONTAINER) {
48347
+ let accountsRoot = "";
48348
+ try {
48349
+ accountsRoot = realpathSync3.native(join18(container, "Accounts"));
48350
+ } catch {
48351
+ }
48352
+ this.accounts = accountsRoot ? listDirectory(accountsRoot, 1e3).flatMap((name) => {
48353
+ const dir = safeComponent2(name) && confine(join18(accountsRoot, name), accountsRoot);
48354
+ return dir && isDirectory2(dir) ? [dir] : [];
48355
+ }) : [];
48356
+ }
48357
+ /** Canonical account directories found in the container. */
48358
+ get accountDirs() {
48359
+ return [...this.accounts];
48360
+ }
48361
+ /** The attachment's own file and its best preview, when present. */
48362
+ locate(source) {
48363
+ const id2 = safeComponent2(source.id);
48364
+ if (!id2) return {};
48365
+ for (const account of this.accounts) {
48366
+ const files = this.locateIn(account, id2, source);
48367
+ if (files.primary || files.preview) return files;
48368
+ }
48369
+ return {};
48370
+ }
48371
+ locateIn(account, id2, source) {
48372
+ const preview = this.preview(account, id2);
48373
+ const media = this.media(account, source);
48374
+ switch (source.kind) {
48375
+ case "drawing":
48376
+ case "paper": {
48377
+ const fallback = this.fallback(
48378
+ account,
48379
+ "FallbackImages",
48380
+ id2,
48381
+ source.fallbackImageGeneration,
48382
+ ["FallbackImage.png", "FallbackImage.jpg"]
48383
+ );
48384
+ if (fallback)
48385
+ return { primary: { path: fallback, name: `${source.kind}.png`, role: "fallback" } };
48386
+ return preview ? { primary: preview } : {};
48387
+ }
48388
+ case "scan": {
48389
+ const pdf = this.fallback(account, "FallbackPDFs", id2, source.fallbackPdfGeneration, [
48390
+ "FallbackPDF.pdf"
48391
+ ]);
48392
+ return {
48393
+ ...pdf ? { primary: { path: pdf, name: "scan.pdf", role: "fallback" } } : {},
48394
+ ...preview ? { preview } : {}
48395
+ };
48396
+ }
48397
+ case "link":
48398
+ return preview ? { preview } : {};
48399
+ default:
48400
+ return {
48401
+ ...media ? { primary: media } : {},
48402
+ ...preview ? { preview } : {}
48403
+ };
48404
+ }
48405
+ }
48406
+ /** Media/<media-id>/<generation>/<filename>, then without the generation. */
48407
+ media(account, source) {
48408
+ const mediaId = safeComponent2(source.mediaId);
48409
+ const filename = safeComponent2(source.mediaFilename);
48410
+ if (!mediaId || !filename) return void 0;
48411
+ const generation = safeComponent2(source.mediaGeneration);
48412
+ const candidates = [
48413
+ ...generation ? [join18(account, "Media", mediaId, generation, filename)] : [],
48414
+ join18(account, "Media", mediaId, filename)
48415
+ ];
48416
+ for (const candidate of candidates) {
48417
+ const path8 = confine(candidate, account);
48418
+ if (path8 && isFile(path8)) return { path: path8, name: filename, role: "original" };
48419
+ }
48420
+ return void 0;
48421
+ }
48422
+ /** <dir>/<id>/<generation>/<name>, <dir>/<id>/<name>, then any generation. */
48423
+ fallback(account, dir, id2, generation, names) {
48424
+ const base = join18(account, dir, id2);
48425
+ const gen = safeComponent2(generation);
48426
+ const generations = [
48427
+ ...gen ? [gen] : [],
48428
+ "",
48429
+ ...listDirectory(base, MAX_BUNDLE_ENTRIES2).filter((name) => name !== gen && safeComponent2(name)).reverse()
48430
+ ];
48431
+ for (const g of generations)
48432
+ for (const name of names) {
48433
+ const path8 = confine(g ? join18(base, g, name) : join18(base, name), account);
48434
+ if (path8 && isFile(path8)) return path8;
48435
+ }
48436
+ return void 0;
48437
+ }
48438
+ /** The largest rendered preview image for an attachment. */
48439
+ preview(account, id2) {
48440
+ let index = this.previewIndex.get(account);
48441
+ if (!index) {
48442
+ index = /* @__PURE__ */ new Map();
48443
+ for (const name of listDirectory(join18(account, "Previews"), MAX_DIRECTORY_ENTRIES)) {
48444
+ const key = name.slice(0, 36).toUpperCase();
48445
+ const entries3 = index.get(key) ?? [];
48446
+ entries3.push(name);
48447
+ index.set(key, entries3);
48448
+ }
48449
+ this.previewIndex.set(account, index);
48450
+ }
48451
+ const entries2 = (index.get(id2.toUpperCase()) ?? []).filter((name) => name.slice(36, 37) === "-" || name.length === 36).filter((name) => {
48452
+ const ext = extname3(name).toLowerCase();
48453
+ return !ext || IMAGE_EXTENSIONS.has(ext) || /^\.\d+$/.test(ext);
48454
+ }).sort((a, b) => previewArea(b) - previewArea(a) || a.localeCompare(b));
48455
+ for (const name of entries2) {
48456
+ const entry = confine(join18(account, "Previews", name), account);
48457
+ if (!entry) continue;
48458
+ const file = isFile(entry) ? entry : this.bundleImage(entry, account);
48459
+ if (file) return { path: file, name: "preview", role: "preview" };
48460
+ }
48461
+ return void 0;
48462
+ }
48463
+ /** Preview.png (or another image) at most two levels inside a bundle. */
48464
+ bundleImage(bundle, account) {
48465
+ const found = [];
48466
+ for (const child of listDirectory(bundle, MAX_BUNDLE_ENTRIES2)) {
48467
+ const path8 = confine(join18(bundle, child), account);
48468
+ if (!path8) continue;
48469
+ if (isFile(path8)) found.push(path8);
48470
+ else
48471
+ for (const grandchild of listDirectory(path8, MAX_BUNDLE_ENTRIES2)) {
48472
+ const inner = confine(join18(path8, grandchild), account);
48473
+ if (inner && isFile(inner)) found.push(inner);
48474
+ }
48475
+ }
48476
+ return found.find((path8) => basename3(path8) === "Preview.png") ?? found.find((path8) => IMAGE_EXTENSIONS.has(extname3(path8).toLowerCase()));
48477
+ }
48478
+ };
48479
+ function sniffMime(head, name) {
48480
+ const ascii = Buffer.from(head).toString("latin1");
48481
+ if (ascii.startsWith("\x89PNG")) return "image/png";
48482
+ if (head[0] === 255 && head[1] === 216) return "image/jpeg";
48483
+ if (ascii.startsWith("GIF8")) return "image/gif";
48484
+ if (ascii.startsWith("%PDF")) return "application/pdf";
48485
+ if (ascii.slice(4, 12) === "ftypheic" || ascii.slice(4, 12) === "ftypmif1") return "image/heic";
48486
+ if (ascii.startsWith("RIFF") && ascii.slice(8, 12) === "WEBP") return "image/webp";
48487
+ const byExtension = {
48488
+ ".png": "image/png",
48489
+ ".jpg": "image/jpeg",
48490
+ ".jpeg": "image/jpeg",
48491
+ ".gif": "image/gif",
48492
+ ".heic": "image/heic",
48493
+ ".tiff": "image/tiff",
48494
+ ".webp": "image/webp",
48495
+ ".pdf": "application/pdf",
48496
+ ".m4a": "audio/mp4",
48497
+ ".mp3": "audio/mpeg",
48498
+ ".wav": "audio/wav",
48499
+ ".mov": "video/quicktime",
48500
+ ".mp4": "video/mp4",
48501
+ ".txt": "text/plain"
48502
+ };
48503
+ return byExtension[extname3(name).toLowerCase()] ?? "application/octet-stream";
48504
+ }
48505
+ function extensionFor(mime) {
48506
+ const map = {
48507
+ "image/png": ".png",
48508
+ "image/jpeg": ".jpg",
48509
+ "image/gif": ".gif",
48510
+ "image/heic": ".heic",
48511
+ "image/webp": ".webp",
48512
+ "application/pdf": ".pdf"
48513
+ };
48514
+ return map[mime] ?? "";
48515
+ }
48516
+ function safeAssetName(name, mime) {
48517
+ let clean = basename3(name).normalize("NFC").replace(/[^\p{L}\p{N}._ -]+/gu, "_").replace(/^[.\s]+/, "").trim();
48518
+ if (!clean) clean = "attachment";
48519
+ if (!extname3(clean)) clean += extensionFor(mime);
48520
+ const ext = extname3(clean);
48521
+ if (clean.length > 120) clean = clean.slice(0, 120 - ext.length) + ext;
48522
+ return clean;
48523
+ }
48524
+ function encodePathUrl(path8) {
48525
+ return path8.split("/").map(encodeURIComponent).join("/");
48526
+ }
48527
+ function canonicalForm(abs) {
48528
+ let current = abs;
48529
+ let rest = "";
48530
+ for (; ; ) {
48531
+ try {
48532
+ const real = realpathSync3.native(current);
48533
+ return rest ? join18(real, rest) : real;
48534
+ } catch {
48535
+ const parent = resolve3(current, "..");
48536
+ if (parent === current) return abs;
48537
+ rest = rest ? join18(basename3(current), rest) : basename3(current);
48538
+ current = parent;
48539
+ }
48540
+ }
48541
+ }
48542
+ function assertExportPath(p, container = NOTES_CONTAINER) {
48543
+ const abs = assertSafeSavePath(p);
48544
+ const within = (path8, root) => path8 === root || path8.startsWith(root + sep3);
48545
+ const roots = [resolve3(container), canonicalForm(resolve3(container))];
48546
+ const forms = [abs, canonicalForm(abs)];
48547
+ if (forms.some((form) => roots.some((root) => within(form, root))))
48548
+ throw new Error("Refusing to write inside the Notes library container.");
48549
+ return abs;
48550
+ }
48551
+ var CREATE_FLAGS = constants4.O_WRONLY | constants4.O_CREAT | constants4.O_EXCL | constants4.O_NOFOLLOW;
48552
+ var OutputExistsError = class extends Error {
48553
+ code = "output_exists";
48554
+ constructor(path8) {
48555
+ super(`Output file already exists: ${path8}. Choose a new path or remove the old file first.`);
48556
+ this.name = "OutputExistsError";
48557
+ }
48558
+ };
48559
+ function openCreateOnly(path8) {
48560
+ try {
48561
+ return openSync4(path8, CREATE_FLAGS, 420);
48562
+ } catch (error2) {
48563
+ if (error2.code === "EEXIST") throw new OutputExistsError(path8);
48564
+ throw error2;
48565
+ }
48566
+ }
48567
+ function writeAllAndClose(fd, content) {
48568
+ try {
48569
+ const data = Buffer.from(content, "utf8");
48570
+ let written = 0;
48571
+ while (written < data.length) written += writeSync3(fd, data, written);
48572
+ return data.length;
48573
+ } finally {
48574
+ closeSync4(fd);
48575
+ }
48576
+ }
48577
+ function openSource(path8) {
48578
+ const fd = openSync4(path8, constants4.O_RDONLY | constants4.O_NOFOLLOW);
48579
+ const stat = fstatSync4(fd);
48580
+ if (!stat.isFile()) {
48581
+ closeSync4(fd);
48582
+ throw new Error("Asset is not a regular file");
48583
+ }
48584
+ return { fd, size: stat.size };
48585
+ }
48586
+ function readHead(fd) {
48587
+ const head = Buffer.alloc(16);
48588
+ const n = readSync3(fd, head, 0, 16, 0);
48589
+ return head.subarray(0, n);
48590
+ }
48591
+ var SidecarWriter = class {
48592
+ constructor(dir, linkBase) {
48593
+ this.dir = dir;
48594
+ this.linkBase = linkBase;
48595
+ }
48596
+ dir;
48597
+ linkBase;
48598
+ placed = /* @__PURE__ */ new Map();
48599
+ created = false;
48600
+ count = 0;
48601
+ place(asset) {
48602
+ const done = this.placed.get(asset.path);
48603
+ if (done) return done;
48604
+ let source;
48605
+ try {
48606
+ source = openSource(asset.path);
48607
+ } catch {
48608
+ return { error: "unreadable" };
48609
+ }
48610
+ try {
48611
+ const mime = sniffMime(readHead(source.fd), asset.name);
48612
+ if (!this.created) {
48613
+ assertExportPath(this.dir);
48614
+ mkdirSync4(this.dir, { recursive: true });
48615
+ this.created = true;
48616
+ }
48617
+ const name = safeAssetName(asset.name, mime);
48618
+ const ext = extname3(name);
48619
+ const stem = name.slice(0, name.length - ext.length);
48620
+ let target;
48621
+ let out;
48622
+ for (let n = 1; n <= 1e3 && out === void 0; n++) {
48623
+ target = join18(this.dir, n === 1 ? name : `${stem}-${n}${ext}`);
48624
+ try {
48625
+ out = openSync4(target, CREATE_FLAGS, 420);
48626
+ } catch (error2) {
48627
+ if (error2.code !== "EEXIST") throw error2;
48628
+ }
48629
+ }
48630
+ if (out === void 0 || !target) return { error: "no-free-name" };
48631
+ try {
48632
+ const chunk = Buffer.alloc(1024 * 1024);
48633
+ for (let position = 0; ; ) {
48634
+ const n = readSync3(source.fd, chunk, 0, chunk.length, position);
48635
+ if (n <= 0) break;
48636
+ let written = 0;
48637
+ while (written < n) written += writeSync3(out, chunk, written, n - written);
48638
+ position += n;
48639
+ }
48640
+ } finally {
48641
+ closeSync4(out);
48642
+ }
48643
+ this.count++;
48644
+ const url = this.linkBase ? encodePathUrl(relative3(this.linkBase, target).split(sep3).join("/")) : target;
48645
+ const result = { url, mime };
48646
+ this.placed.set(asset.path, result);
48647
+ return result;
48648
+ } catch (error2) {
48649
+ return { error: error2 instanceof Error ? error2.message : String(error2) };
48650
+ } finally {
48651
+ closeSync4(source.fd);
48652
+ }
48653
+ }
48654
+ };
48655
+
48656
+ // src/utils/exportRender.ts
48657
+ var emptyStats = () => ({
48658
+ attachments: 0,
48659
+ placed: 0,
48660
+ placeholders: 0,
48661
+ unavailable: 0,
48662
+ tables: 0,
48663
+ unreadableTables: 0,
48664
+ unreferenced: 0
48665
+ });
48666
+ var isSafeHref = (url) => /^(?:https?:\/\/|notes:\/\/|applenotes:|mailto:)/i.test(url) && !Array.from(url).some((char) => char.charCodeAt(0) < 32);
48667
+ var LABELS = {
48668
+ table: "Table",
48669
+ image: "Image",
48670
+ drawing: "Drawing",
48671
+ paper: "Drawing",
48672
+ scan: "Scanned document",
48673
+ pdf: "PDF",
48674
+ audio: "Audio",
48675
+ video: "Video",
48676
+ link: "Link",
48677
+ gallery: "Gallery",
48678
+ divider: "Divider",
48679
+ inline: "Inline attachment",
48680
+ file: "File"
48681
+ };
48682
+ var attachmentLabel = (kind) => LABELS[kind];
48683
+ function fmtOf(run) {
48684
+ const fmt = {};
48685
+ if (run.bold) fmt.bold = true;
48686
+ if (run.italic) fmt.italic = true;
48687
+ if (run.underline) fmt.underline = true;
48688
+ if (run.strikethrough) fmt.strikethrough = true;
48689
+ if (run.superscript) fmt.superscript = true;
48690
+ if (run.subscript) fmt.subscript = true;
48691
+ if (run.highlight) fmt.highlight = run.highlight;
48692
+ if (run.color) fmt.color = run.color;
48693
+ if (run.link && run.linkSafe) fmt.link = run.link;
48694
+ return fmt;
48695
+ }
48696
+ var sameFmt = (a, b) => JSON.stringify(a) === JSON.stringify(b);
48697
+ function blockPieces(block, plan) {
48698
+ const pieces = [];
48699
+ const pushText = (text2, fmt) => {
48700
+ if (!text2) return;
48701
+ const last = pieces[pieces.length - 1];
48702
+ if (last?.type === "text" && sameFmt(last.fmt, fmt)) last.text += text2;
48703
+ else pieces.push({ type: "text", text: text2, fmt });
48704
+ };
48705
+ for (const run of block.runs) {
48706
+ const fmt = fmtOf(run);
48707
+ const parts = run.text.split("\uFFFC");
48708
+ parts.forEach((part, i) => {
48709
+ if (i > 0 && run.attachment)
48710
+ pieces.push({ type: "attachment", id: run.attachment.id, plan: plan(run.attachment.id) });
48711
+ pushText(part, fmt);
48712
+ });
48713
+ }
48714
+ return pieces;
48715
+ }
48716
+ var isBlockPlan = (plan) => plan.type === "table" || plan.type === "divider" || plan.type === "gallery";
48717
+ function titleBlockIndex(note) {
48718
+ const first2 = note.doc.blocks.find((block) => block.text.trim());
48719
+ if (!first2) return -1;
48720
+ if (first2.style === "title") return first2.index;
48721
+ return first2.text.trim() === note.title.trim() && first2.style !== "monospaced" ? first2.index : -1;
48722
+ }
48723
+ function place(ctx, asset) {
48724
+ return asset && ctx.writer ? ctx.writer.place(asset) : void 0;
48725
+ }
48726
+ function planAttachment(attachment, ctx) {
48727
+ ctx.stats.attachments++;
48728
+ const unavailable = (label2, reason, name2) => {
48729
+ ctx.stats.unavailable++;
48730
+ return { type: "unavailable", label: label2, reason, ...name2 ? { name: name2 } : {} };
48731
+ };
48732
+ if (!attachment) return unavailable("Attachment", "missing");
48733
+ const label = attachmentLabel(attachment.kind);
48734
+ const name = attachment.title;
48735
+ switch (attachment.kind) {
48736
+ case "inline": {
48737
+ const link = attachment.uti.endsWith(".link") && attachment.tokenId && isSafeHref(attachment.tokenId) ? attachment.tokenId : void 0;
48738
+ return { type: "inline", text: attachment.altText ?? "", ...link ? { link } : {} };
48739
+ }
48740
+ case "divider":
48741
+ return { type: "divider" };
48742
+ case "table": {
48743
+ ctx.stats.tables++;
48744
+ try {
48745
+ if (!attachment.tableData) throw new Error("no table data");
48746
+ return {
48747
+ type: "table",
48748
+ rows: parseNoteTable(Buffer.from(attachment.tableData, "hex")).rows
48749
+ };
48750
+ } catch {
48751
+ ctx.stats.unreadableTables++;
48752
+ return unavailable(label, "undecodable");
48753
+ }
48754
+ }
48755
+ case "gallery": {
48756
+ ctx.stats.attachments--;
48757
+ return {
48758
+ type: "gallery",
48759
+ items: attachment.children.map((child) => planAttachment(child, ctx))
48760
+ };
48761
+ }
48762
+ case "link": {
48763
+ const url = attachment.url ?? "";
48764
+ const preview = ctx.locator ? place(ctx, ctx.locator.locate(attachment).preview) : void 0;
48765
+ if (preview && "url" in preview) ctx.stats.placed++;
48766
+ return {
48767
+ type: "card",
48768
+ title: name ?? url,
48769
+ displayUrl: url,
48770
+ ...isSafeHref(url) ? { url } : {},
48771
+ ...preview && "url" in preview ? { previewUrl: preview.url } : {}
48772
+ };
48773
+ }
48774
+ default: {
48775
+ if (!ctx.writer) {
48776
+ ctx.stats.placeholders++;
48777
+ return { type: "placeholder", label, ...name ? { name } : {} };
48778
+ }
48779
+ const files = ctx.locator?.locate(attachment) ?? {};
48780
+ const primary = place(ctx, files.primary);
48781
+ const visual = ["image", "drawing", "paper"].includes(attachment.kind);
48782
+ const wantsPreview = attachment.kind === "scan" || attachment.kind === "pdf";
48783
+ const preview = files.preview && (wantsPreview || visual && !(primary && "url" in primary)) ? place(ctx, files.preview) : void 0;
48784
+ const previewUrl = preview && "url" in preview ? preview.url : void 0;
48785
+ if (primary && "url" in primary) {
48786
+ ctx.stats.placed++;
48787
+ const display = visual ? "image" : attachment.kind === "audio" ? "audio" : attachment.kind === "video" ? "video" : "link";
48788
+ return {
48789
+ type: "asset",
48790
+ label,
48791
+ ...name ? { name } : {},
48792
+ display,
48793
+ url: primary.url,
48794
+ mime: primary.mime,
48795
+ ...previewUrl ? { previewUrl } : {}
48796
+ };
48797
+ }
48798
+ if (visual && previewUrl) {
48799
+ ctx.stats.placed++;
48800
+ return {
48801
+ type: "asset",
48802
+ label,
48803
+ ...name ? { name } : {},
48804
+ display: "image",
48805
+ url: previewUrl,
48806
+ mime: preview.mime
48807
+ };
48808
+ }
48809
+ const reason = primary && "error" in primary ? primary.error : "missing";
48810
+ return unavailable(label, reason, name);
48811
+ }
48812
+ }
48813
+ }
48814
+ function unreferencedAttachments(note) {
48815
+ const referenced = new Set(note.doc.attachments.map((marker) => marker.id));
48816
+ return note.ordered.filter(
48817
+ (attachment) => !referenced.has(attachment.id) && attachment.kind !== "table" && attachment.kind !== "inline" && attachment.kind !== "divider"
48818
+ );
48819
+ }
48820
+
48821
+ // src/utils/markdownExport.ts
48822
+ var NOTE_SEPARATOR = "\n\n---\n\n";
48823
+ function escapeMarkdown(text2) {
48824
+ return text2.replace(/[\\`*_[\]<>~|]/g, (char) => `\\${char}`).replace(/&(?=#?[A-Za-z0-9]+;)/g, "&amp;").replace(/==/g, "\\=\\=");
48825
+ }
48826
+ function escapeLineStart(line) {
48827
+ return line.replace(
48828
+ /^(\s*)([#>+-]|\d+[.)])(?=\s|$)/,
48829
+ (_, space, marker) => /^\d/.test(marker) ? `${space}${marker.slice(0, -1)}\\${marker.slice(-1)}` : `${space}\\${marker}`
48830
+ );
48831
+ }
48832
+ function linkDestination(url) {
48833
+ return url.replace(
48834
+ /[\s()<>]/g,
48835
+ (char) => char === " " ? "%20" : `%${char.charCodeAt(0).toString(16).toUpperCase().padStart(2, "0")}`
48836
+ );
48837
+ }
48838
+ function delimit(text2, open, close = open) {
48839
+ const match = /^(\s*)([\s\S]*?)(\s*)$/.exec(text2);
48840
+ return match[2] ? `${match[1]}${open}${match[2]}${close}${match[3]}` : text2;
48841
+ }
48842
+ var LAYERS = [
48843
+ ["italic", "*", "*"],
48844
+ ["bold", "**", "**"],
48845
+ ["strikethrough", "~~", "~~"],
48846
+ ["underline", "<u>", "</u>"],
48847
+ ["highlight", "==", "=="],
48848
+ ["superscript", "<sup>", "</sup>"],
48849
+ ["subscript", "<sub>", "</sub>"]
48850
+ ];
48851
+ function joinSafe(left, right) {
48852
+ return left && right && /[*~=]$/.test(left) && left.at(-1) === right[0] ? `${left}<!-- -->${right}` : left + right;
48853
+ }
48854
+ function layered(pieces, depth = 0) {
48855
+ if (depth === LAYERS.length)
48856
+ return pieces.map((piece) => escapeMarkdown(piece.text.replace(/\n/g, " "))).join("");
48857
+ const [key, open, close] = LAYERS[depth];
48858
+ let out = "";
48859
+ for (let i = 0; i < pieces.length; ) {
48860
+ const on = !!pieces[i].fmt[key];
48861
+ let j = i;
48862
+ while (j < pieces.length && !!pieces[j].fmt[key] === on) j++;
48863
+ const inner = layered(pieces.slice(i, j), depth + 1);
48864
+ out = joinSafe(out, on ? delimit(inner, open, close) : inner);
48865
+ i = j;
48866
+ }
48867
+ return out;
48868
+ }
48869
+ var bracket = (label, name) => `\\[${escapeMarkdown(name ? `${label}: ${name}` : label)}\\]`;
48870
+ function planMarkdown(plan) {
48871
+ switch (plan.type) {
48872
+ case "inline":
48873
+ return plan.link ? `[${escapeMarkdown(plan.text)}](${linkDestination(plan.link)})` : escapeMarkdown(plan.text);
48874
+ case "divider":
48875
+ return "---";
48876
+ case "table":
48877
+ return tableMarkdown(plan.rows);
48878
+ case "placeholder":
48879
+ return bracket(plan.label, plan.name);
48880
+ case "unavailable":
48881
+ return bracket(`${plan.label} unavailable`, plan.name);
48882
+ case "asset": {
48883
+ const text2 = escapeMarkdown(plan.name ?? plan.label);
48884
+ if (plan.display === "image") return `![${text2}](${linkDestination(plan.url)})`;
48885
+ const inner = plan.previewUrl ? `![${text2}](${linkDestination(plan.previewUrl)})` : text2;
48886
+ return `[${inner}](${linkDestination(plan.url)})`;
48887
+ }
48888
+ case "card":
48889
+ return plan.url ? `[${escapeMarkdown(plan.title)}](${linkDestination(plan.url)})` : `${escapeMarkdown(plan.title)} (${escapeMarkdown(plan.displayUrl)})`;
48890
+ case "gallery":
48891
+ return plan.items.map(planMarkdown).join("\n\n");
48892
+ }
48893
+ }
48894
+ function tableMarkdown(rows) {
48895
+ const width = Math.max(1, ...rows.map((row) => row.length));
48896
+ const cell = (value) => escapeMarkdown(value ?? "").replace(/\r?\n/g, "<br>").trim() || " ";
48897
+ const line = (row) => `| ${Array.from({ length: width }, (_, i) => cell(row[i])).join(" | ")} |`;
48898
+ const [head = [], ...body] = rows;
48899
+ return [line(head), `| ${Array(width).fill("---").join(" | ")} |`, ...body.map(line)].join("\n");
48900
+ }
48901
+ function inlineMarkdown(pieces) {
48902
+ let out = "";
48903
+ for (let i = 0; i < pieces.length; ) {
48904
+ const piece = pieces[i];
48905
+ if (piece.type === "attachment") {
48906
+ out = joinSafe(out, planMarkdown(piece.plan));
48907
+ i++;
48908
+ continue;
48909
+ }
48910
+ const link = piece.fmt.link;
48911
+ let j = i;
48912
+ while (j < pieces.length && pieces[j].type === "text" && pieces[j].fmt.link === link)
48913
+ j++;
48914
+ const inner = layered(pieces.slice(i, j));
48915
+ out = joinSafe(out, link ? delimit(inner, "[", `](${linkDestination(link)})`) : inner);
48916
+ i = j;
48917
+ }
48918
+ return out;
48919
+ }
48920
+ var LIST_STYLES = /* @__PURE__ */ new Set(["bulleted", "dashed", "numbered", "checklist"]);
48921
+ function renderNoteMarkdown(note, ctx) {
48922
+ const plan = (id2) => planAttachment(note.attachments.get(id2), ctx);
48923
+ const titleIndex = titleBlockIndex(note);
48924
+ const lines = [];
48925
+ const counters = [];
48926
+ let code;
48927
+ const flushCode = () => {
48928
+ if (!code) return;
48929
+ const longest = Math.max(
48930
+ 2,
48931
+ ...code.lines.map((l) => Math.max(0, ...(l.match(/`+/g) ?? []).map((m) => m.length)))
48932
+ );
48933
+ const fence = "`".repeat(longest + 1);
48934
+ lines.push({
48935
+ text: [fence, ...code.lines, fence].join("\n"),
48936
+ group: "code",
48937
+ quote: code.quote
48938
+ });
48939
+ code = void 0;
48940
+ };
48941
+ if (titleIndex === -1 && note.title.trim())
48942
+ lines.push({ text: `# ${escapeMarkdown(note.title.trim())}`, group: "para", quote: false });
48943
+ for (const block of note.doc.blocks) {
48944
+ if (block.style === "monospaced") {
48945
+ if (code && code.quote !== block.blockQuote) flushCode();
48946
+ code ??= { lines: [], quote: block.blockQuote };
48947
+ code.lines.push(block.text.replace(/\ufffc/g, ""));
48948
+ continue;
48949
+ }
48950
+ flushCode();
48951
+ if (!LIST_STYLES.has(block.style)) counters.length = 0;
48952
+ if (!block.text.trim()) continue;
48953
+ const pieces = blockPieces(block, plan);
48954
+ let segment = [];
48955
+ const segments = [];
48956
+ for (const piece of pieces) {
48957
+ if (piece.type === "attachment" && isBlockPlan(piece.plan)) {
48958
+ segments.push(segment, piece.plan);
48959
+ segment = [];
48960
+ } else segment.push(piece);
48961
+ }
48962
+ segments.push(segment);
48963
+ let first2 = true;
48964
+ for (const segment2 of segments) {
48965
+ if (!Array.isArray(segment2)) {
48966
+ lines.push({ text: planMarkdown(segment2), group: "block", quote: block.blockQuote });
48967
+ continue;
48968
+ }
48969
+ const body = inlineMarkdown(segment2).trim();
48970
+ if (!body) continue;
48971
+ lines.push(renderLine(block, body, first2, block.index === titleIndex, counters));
48972
+ first2 = false;
48973
+ }
48974
+ }
48975
+ flushCode();
48976
+ for (const attachment of unreferencedAttachments(note)) {
48977
+ ctx.stats.unreferenced++;
48978
+ lines.push({
48979
+ text: planMarkdown(planAttachment(attachment, ctx)),
48980
+ group: "block",
48981
+ quote: false
48982
+ });
48983
+ }
48984
+ return joinLines(lines);
48985
+ }
48986
+ function renderLine(block, body, first2, isTitle, counters) {
48987
+ const quote = block.blockQuote;
48988
+ if (isTitle || block.style === "title") return { text: `# ${body}`, group: "para", quote };
48989
+ if (block.style === "heading") return { text: `## ${body}`, group: "para", quote };
48990
+ if (block.style === "subheading") return { text: `### ${body}`, group: "para", quote };
48991
+ if (!LIST_STYLES.has(block.style) || !first2)
48992
+ return { text: escapeLineStart(body), group: "para", quote };
48993
+ const level = Math.min(block.indent, 20);
48994
+ counters.length = Math.min(counters.length, level + 1);
48995
+ while (counters.length <= level) counters.push(0);
48996
+ const indent = " ".repeat(level);
48997
+ let marker = "-";
48998
+ if (block.style === "numbered") marker = `${++counters[level]}.`;
48999
+ else {
49000
+ counters[level] = 0;
49001
+ if (block.style === "checklist") marker = block.checklist?.done ? "- [x]" : "- [ ]";
49002
+ }
49003
+ return { text: `${indent}${marker} ${body}`, group: "list", quote };
49004
+ }
49005
+ function joinLines(lines) {
49006
+ let out = "";
49007
+ let previous;
49008
+ for (const line of lines) {
49009
+ const text2 = line.quote ? line.text.split("\n").map((l) => l ? `> ${l}` : ">").join("\n") : line.text;
49010
+ if (previous) {
49011
+ const tight = previous.group === "list" && line.group === "list" && previous.quote === line.quote;
49012
+ out += tight ? "\n" : previous.quote && line.quote ? "\n>\n" : "\n\n";
49013
+ }
49014
+ out += text2;
49015
+ previous = line;
49016
+ }
49017
+ return out;
49018
+ }
49019
+ function wrapMarkdown(markdown, width) {
49020
+ if (!width) return markdown;
49021
+ let fenced = false;
49022
+ const out = [];
49023
+ for (const line of markdown.split("\n")) {
49024
+ const bare = line.replace(/^(?:> ?)+/, "");
49025
+ if (/^\s*```/.test(bare)) fenced = !fenced;
49026
+ if (fenced || /^\s*```/.test(bare) || line.length <= width || /^\s*(#|\||!\[)/.test(bare)) {
49027
+ out.push(line);
49028
+ continue;
49029
+ }
49030
+ const prefix = /^((?:> ?)*\s*(?:(?:[-*+]|\d+\.)(?: \[[ x]\])? )?)/.exec(line)[1];
49031
+ const hang = prefix.replace(/[^>\s]/g, " ").replace(/>(?! )/g, "> ");
49032
+ const words = line.slice(prefix.length).split(" ");
49033
+ let current = prefix;
49034
+ let empty = true;
49035
+ for (const word of words) {
49036
+ if (!empty && current.length + 1 + word.length > width) {
49037
+ out.push(current);
49038
+ current = hang + word;
49039
+ } else current += (empty ? "" : " ") + word;
49040
+ empty = false;
49041
+ }
49042
+ out.push(current);
49043
+ }
49044
+ return out.join("\n");
49045
+ }
49046
+ function renderNotesMarkdown(notes, ctx, { wrap: wrap2 = 0 } = {}) {
49047
+ const body = notes.map((note) => renderNoteMarkdown(note, ctx)).join(NOTE_SEPARATOR);
49048
+ return (wrap2 ? wrapMarkdown(body, wrap2) : body) + (notes.length ? "\n" : "");
49049
+ }
49050
+
49051
+ // src/utils/noteExportData.ts
49052
+ import { execFileSync as execFileSync17 } from "node:child_process";
49053
+ import { homedir as homedir16 } from "node:os";
49054
+ import { join as join19 } from "node:path";
49055
+ var NOTES_DB_PATH10 = join19(
49056
+ homedir16(),
49057
+ "Library/Group Containers/group.com.apple.notes/NoteStore.sqlite"
49058
+ );
49059
+ var IMAGE_UTIS2 = /* @__PURE__ */ new Set([
49060
+ "public.jpeg",
49061
+ "public.png",
49062
+ "public.heic",
49063
+ "public.heif",
49064
+ "public.image",
49065
+ "public.tiff",
49066
+ "public.webp",
49067
+ "org.webmproject.webp",
49068
+ "com.compuserve.gif",
49069
+ "com.microsoft.bmp",
49070
+ "com.adobe.raw-image",
49071
+ "public.camera-raw-image"
49072
+ ]);
49073
+ var AUDIO_UTIS = /* @__PURE__ */ new Set([
49074
+ "com.apple.m4a-audio",
49075
+ "public.mpeg-4-audio",
49076
+ "public.mp3",
49077
+ "public.audio",
49078
+ "public.aiff-audio",
49079
+ "com.microsoft.waveform-audio"
49080
+ ]);
49081
+ var VIDEO_UTIS = /* @__PURE__ */ new Set([
49082
+ "public.movie",
49083
+ "public.video",
49084
+ "public.mpeg-4",
49085
+ "com.apple.quicktime-movie"
49086
+ ]);
49087
+ function classifyUti(uti) {
49088
+ if (uti === "com.apple.notes.table") return "table";
49089
+ if (uti === "com.apple.notes.inlinetextattachment.dividerline") return "divider";
49090
+ if (uti.startsWith("com.apple.notes.inlinetextattachment.")) return "inline";
49091
+ if (uti === "com.apple.notes.gallery") return "gallery";
49092
+ if (uti === "com.apple.drawing" || uti === "com.apple.drawing.2") return "drawing";
49093
+ if (uti === "com.apple.paper.doc.scan") return "scan";
49094
+ if (uti === "com.apple.paper") return "paper";
49095
+ if (uti === "public.url") return "link";
49096
+ if (uti === "com.adobe.pdf") return "pdf";
49097
+ if (IMAGE_UTIS2.has(uti)) return "image";
49098
+ if (AUDIO_UTIS.has(uti)) return "audio";
49099
+ if (VIDEO_UTIS.has(uti)) return "video";
49100
+ return "file";
49101
+ }
49102
+ var ATTACHMENT_COLUMNS = [
49103
+ ["uti0", "a", "ZTYPEUTI"],
49104
+ ["uti1", "a", "ZTYPEUTI1"],
49105
+ ["parent", "a", "ZPARENTATTACHMENT"],
49106
+ ["title", "a", "ZTITLE"],
49107
+ ["userTitle", "a", "ZUSERTITLE"],
49108
+ ["url", "a", "ZURLSTRING"],
49109
+ ["alt", "a", "ZALTTEXT"],
49110
+ ["token", "a", "ZTOKENCONTENTIDENTIFIER"],
49111
+ ["fbImageGen", "a", "ZFALLBACKIMAGEGENERATION"],
49112
+ ["fbPdfGen", "a", "ZFALLBACKPDFGENERATION"],
49113
+ ["mediaId", "m", "ZIDENTIFIER"],
49114
+ ["mediaFilename", "m", "ZFILENAME"],
49115
+ ["mediaGen", "m", "ZGENERATION1"]
49116
+ ];
49117
+ var columnCache = /* @__PURE__ */ new Map();
49118
+ function sqlite(dbPath2, args) {
49119
+ try {
49120
+ return execFileSync17(
49121
+ "/usr/bin/sqlite3",
49122
+ ["-readonly", ...args.slice(0, -1), dbPath2, args.at(-1)],
49123
+ {
49124
+ encoding: "utf8",
49125
+ timeout: 1e4,
49126
+ maxBuffer: 256 * 1024 * 1024,
49127
+ stdio: ["pipe", "pipe", "pipe"]
49128
+ }
49129
+ ).trim();
49130
+ } catch (error2) {
49131
+ const message = error2 instanceof Error ? error2.message : String(error2);
49132
+ if (/authorization denied|unable to open database/i.test(message))
49133
+ throw new NoteBlocksError("no-full-disk-access", "The Notes database is not readable");
49134
+ throw new NoteBlocksError("query-failed", "Failed to query the Notes database");
49135
+ }
49136
+ }
49137
+ function objectColumns(dbPath2 = NOTES_DB_PATH10) {
49138
+ let columns = columnCache.get(dbPath2);
49139
+ if (!columns) {
49140
+ columns = new Set(
49141
+ sqlite(dbPath2, ["SELECT name FROM pragma_table_info('ZICCLOUDSYNCINGOBJECT');"]).split("\n").filter(Boolean)
49142
+ );
49143
+ columnCache.set(dbPath2, columns);
49144
+ }
49145
+ return columns;
49146
+ }
49147
+ function attachmentQuery(columns) {
49148
+ const col3 = (alias, name) => columns.has(name) ? `${alias}.${name}` : "NULL";
49149
+ const fields = ATTACHMENT_COLUMNS.map(([key, alias, name]) => `'${key}', ${col3(alias, name)}`);
49150
+ const uti = `COALESCE(${col3("a", "ZTYPEUTI")}, ${col3("a", "ZTYPEUTI1")})`;
49151
+ const mergeable = columns.has("ZMERGEABLEDATA1") ? columns.has("ZMERGEABLEDATA") ? "COALESCE(a.ZMERGEABLEDATA1, a.ZMERGEABLEDATA)" : "a.ZMERGEABLEDATA1" : col3("a", "ZMERGEABLEDATA");
49152
+ const noteLinks = ["ZNOTE", "ZNOTE1"].filter((c) => columns.has(c)).map((c) => `a.${c} = @pk`);
49153
+ const owner = noteLinks.length ? `(${noteLinks.join(" OR ")})` : "0";
49154
+ const media = columns.has("ZMEDIA") ? "m.Z_PK = a.ZMEDIA" : "0";
49155
+ const live = columns.has("ZMARKEDFORDELETION") ? "AND COALESCE(a.ZMARKEDFORDELETION, 0) = 0" : "";
49156
+ return `SELECT json_object('title', (SELECT ${col3("n", "ZTITLE1")} FROM ZICCLOUDSYNCINGOBJECT n WHERE n.Z_PK = @pk), 'attachments', (SELECT json_group_array(json_object('pk', a.Z_PK, 'id', a.ZIDENTIFIER, ${fields.join(", ")}, 'table', CASE WHEN ${uti} = 'com.apple.notes.table' THEN hex(${mergeable}) END)) FROM ZICCLOUDSYNCINGOBJECT a LEFT JOIN ZICCLOUDSYNCINGOBJECT m ON ${media} WHERE ${owner} AND a.ZIDENTIFIER IS NOT NULL ${live}));`;
49157
+ }
49158
+ var text = (value) => typeof value === "string" && value.length ? value : typeof value === "number" ? String(value) : void 0;
49159
+ function buildAttachments(rows) {
49160
+ const all = rows.filter((row) => typeof row.id === "string" && Number.isInteger(row.pk)).map((row) => {
49161
+ const uti = text(row.uti0) ?? text(row.uti1) ?? "unknown";
49162
+ const attachment = {
49163
+ id: row.id,
49164
+ pk: row.pk,
49165
+ uti,
49166
+ kind: classifyUti(uti),
49167
+ children: []
49168
+ };
49169
+ const set = (key, value) => {
49170
+ if (value !== void 0) attachment[key] = value;
49171
+ };
49172
+ set("parentPk", Number.isInteger(row.parent) ? row.parent : void 0);
49173
+ set("title", text(row.title) ?? text(row.userTitle) ?? text(row.mediaFilename));
49174
+ set("url", text(row.url));
49175
+ set("altText", text(row.alt));
49176
+ set("tokenId", text(row.token));
49177
+ set("mediaId", text(row.mediaId));
49178
+ set("mediaFilename", text(row.mediaFilename));
49179
+ set("mediaGeneration", text(row.mediaGen));
49180
+ set("fallbackImageGeneration", text(row.fbImageGen));
49181
+ set("fallbackPdfGeneration", text(row.fbPdfGen));
49182
+ const table = text(row.table);
49183
+ set("tableData", table && /^[0-9a-f]+$/i.test(table) ? table : void 0);
49184
+ return attachment;
49185
+ }).sort((a, b) => a.pk - b.pk);
49186
+ const byPk = new Map(all.map((a) => [a.pk, a]));
49187
+ const ordered = [];
49188
+ for (const attachment of all) {
49189
+ const parent = attachment.parentPk !== void 0 ? byPk.get(attachment.parentPk) : void 0;
49190
+ if (parent) parent.children.push(attachment);
49191
+ else ordered.push(attachment);
49192
+ }
49193
+ return { byId: new Map(all.map((a) => [a.id, a])), ordered };
49194
+ }
49195
+ function readExportNote(id2, { dbPath: dbPath2 = NOTES_DB_PATH10 } = {}) {
49196
+ const doc = readNoteBlocks(id2, { dbPath: dbPath2 });
49197
+ const pk = /\/ICNote\/p([0-9]{1,18})$/.exec(id2)[1];
49198
+ const output = sqlite(dbPath2, [
49199
+ "-cmd",
49200
+ ".parameter init",
49201
+ "-cmd",
49202
+ `.parameter set @pk ${pk}`,
49203
+ attachmentQuery(objectColumns(dbPath2))
49204
+ ]);
49205
+ let parsed;
49206
+ try {
49207
+ parsed = JSON.parse(output);
49208
+ } catch {
49209
+ throw new NoteBlocksError("query-failed", "Unexpected Notes database response");
49210
+ }
49211
+ const rows = Array.isArray(parsed.attachments) ? parsed.attachments : [];
49212
+ const { byId, ordered } = buildAttachments(rows);
49213
+ const firstLine = doc.blocks.find((block) => block.text.trim())?.text.trim() ?? "";
49214
+ return {
49215
+ id: id2,
49216
+ title: text(parsed.title) ?? firstLine,
49217
+ doc,
49218
+ attachments: byId,
49219
+ ordered
49220
+ };
49221
+ }
49222
+
49223
+ // src/services/notesExport.ts
49224
+ var DEFAULT_FOLDER_EXPORT_LIMIT = 100;
49225
+ var MAX_FOLDER_EXPORT_LIMIT = 1e3;
49226
+ var NotesExportError = class extends Error {
49227
+ constructor(code, message) {
49228
+ super(message);
49229
+ this.code = code;
49230
+ this.name = "NotesExportError";
49231
+ }
49232
+ code;
49233
+ };
49234
+ function validPath(path8, what) {
49235
+ try {
49236
+ return assertExportPath(path8);
49237
+ } catch (error2) {
49238
+ throw new NotesExportError(
49239
+ "invalid-path",
49240
+ `${what}: ${error2 instanceof Error ? error2.message : String(error2)}`
49241
+ );
49242
+ }
49243
+ }
49244
+ function selectNotes(request, deps) {
49245
+ if (!!request.id === !!request.folder)
49246
+ throw new NotesExportError("invalid-request", "Provide exactly one of 'id' or 'folder'.");
49247
+ if (request.id) return [request.id];
49248
+ const limit = Math.min(request.limit ?? DEFAULT_FOLDER_EXPORT_LIMIT, MAX_FOLDER_EXPORT_LIMIT);
49249
+ try {
49250
+ return deps.listNoteRefs(request.account, request.folder, void 0, limit).map((ref) => ref.id);
49251
+ } catch (error2) {
49252
+ throw new NotesExportError(
49253
+ "folder-unavailable",
49254
+ `Could not list folder "${request.folder}": ${error2 instanceof Error ? error2.message : String(error2)}`
49255
+ );
49256
+ }
49257
+ }
49258
+ function loadNotes(ids, single, read) {
49259
+ const notes = [];
49260
+ const skipped = [];
49261
+ for (const id2 of ids) {
49262
+ try {
49263
+ notes.push(read ? read(id2) : readExportNote(id2));
49264
+ } catch (error2) {
49265
+ if (!(error2 instanceof NoteBlocksError)) throw error2;
49266
+ if (single) throw new NotesExportError(error2.code, error2.message);
49267
+ skipped.push({ id: id2, code: error2.code });
49268
+ }
49269
+ }
49270
+ return { notes, skipped };
49271
+ }
49272
+ function exportNotesMarkdown(request, deps) {
49273
+ const output = request.outputPath ? validPath(request.outputPath, "outputPath") : void 0;
49274
+ const assetsDir = request.assetsDir ? validPath(request.assetsDir, "assetsDir") : void 0;
49275
+ if (output && assetsDir && output === assetsDir)
49276
+ throw new NotesExportError("invalid-path", "outputPath and assetsDir must differ.");
49277
+ const ids = selectNotes(request, deps);
49278
+ const { notes, skipped } = loadNotes(ids, !!request.id, deps.readNote);
49279
+ let fd;
49280
+ if (output) {
49281
+ mkdirSync5(dirname4(output), { recursive: true });
49282
+ try {
49283
+ fd = openCreateOnly(output);
49284
+ } catch (error2) {
49285
+ if (error2 instanceof OutputExistsError)
49286
+ throw new NotesExportError("output_exists", error2.message);
49287
+ throw error2;
49288
+ }
49289
+ }
49290
+ const writer = assetsDir ? new SidecarWriter(assetsDir, output ? dirname4(output) : void 0) : void 0;
49291
+ const ctx = {
49292
+ stats: emptyStats(),
49293
+ ...writer ? { writer, locator: deps.locator ?? new AssetLocator() } : {}
49294
+ };
49295
+ let markdown;
49296
+ try {
49297
+ markdown = renderNotesMarkdown(notes, ctx, { wrap: request.wrap ?? 0 });
49298
+ } catch (error2) {
49299
+ if (fd !== void 0) writeAllAndClose(fd, "");
49300
+ throw error2;
49301
+ }
49302
+ const bytes = Buffer.byteLength(markdown);
49303
+ const receipt = {
49304
+ format: "markdown",
49305
+ count: notes.length,
49306
+ bytes,
49307
+ stats: ctx.stats,
49308
+ skipped,
49309
+ ...assetsDir ? { assets: { dir: assetsDir, files: writer.count } } : {}
49310
+ };
49311
+ if (fd !== void 0) {
49312
+ writeAllAndClose(fd, markdown);
49313
+ return { ...receipt, output };
49314
+ }
49315
+ if (bytes > deps.maxInlineBytes)
49316
+ throw new NotesExportError(
49317
+ "too-large",
49318
+ `The Markdown is ${bytes} bytes, over the ${deps.maxInlineBytes}-byte inline limit. Pass outputPath to write it to a file, or export fewer notes.`
49319
+ );
49320
+ return { ...receipt, markdown };
49321
+ }
49322
+
49323
+ // src/tools/directOperations.ts
49324
+ import { createHash as createHash2 } from "node:crypto";
49325
+ import {
49326
+ closeSync as closeSync5,
49327
+ constants as constants5,
49328
+ fstatSync as fstatSync5,
49329
+ mkdtempSync as mkdtempSync4,
49330
+ openSync as openSync5,
47879
49331
  readFileSync as readFileSync3,
47880
49332
  rmSync as rmSync4,
47881
49333
  writeFileSync as writeFileSync3
47882
49334
  } from "node:fs";
47883
49335
  import { tmpdir as tmpdir4 } from "node:os";
47884
- import { basename as basename3, extname as extname3, isAbsolute as isAbsolute3, join as join17 } from "node:path";
49336
+ import { basename as basename4, extname as extname4, isAbsolute as isAbsolute3, join as join20 } from "node:path";
47885
49337
  var noteId = exactIdInput(
47886
49338
  "ICNote",
47887
49339
  /^x-coredata:\/\/[0-9a-f-]+\/ICNote\/p\d+$/i,
@@ -47904,7 +49356,7 @@ function readSnapshot(manager, id2) {
47904
49356
  function assertExistingContentPreserved(before, after) {
47905
49357
  if (before.id !== after.id || before.title !== after.title)
47906
49358
  throw new Error("Note identity changed");
47907
- const tidy = (text) => text.replace(/\r\n/g, "\n").replace(/[\s\ufffc]+$/gu, "");
49359
+ const tidy = (text2) => text2.replace(/\r\n/g, "\n").replace(/[\s\ufffc]+$/gu, "");
47908
49360
  if (!tidy(after.rich.text).startsWith(tidy(before.rich.text)))
47909
49361
  throw new Error("Existing note text was not preserved");
47910
49362
  if (linkSignature(before.rich.links) !== linkSignature(after.rich.links.slice(0, before.rich.links.length)))
@@ -47924,11 +49376,11 @@ function assertExistingContentPreserved(before, after) {
47924
49376
  throw new Error("Existing native object content or presentation changed");
47925
49377
  }
47926
49378
  }
47927
- function localAttachment(path7) {
47928
- if (!isAbsolute3(path7)) throw new Error("An absolute local file path is required");
47929
- const descriptor = openSync4(path7, constants4.O_RDONLY | constants4.O_NOFOLLOW);
49379
+ function localAttachment(path8) {
49380
+ if (!isAbsolute3(path8)) throw new Error("An absolute local file path is required");
49381
+ const descriptor = openSync5(path8, constants5.O_RDONLY | constants5.O_NOFOLLOW);
47930
49382
  try {
47931
- const stat = fstatSync4(descriptor);
49383
+ const stat = fstatSync5(descriptor);
47932
49384
  if (!stat.isFile() || stat.size === 0 || stat.size > 64 * 1024 * 1024)
47933
49385
  throw new Error("Attachment must be a nonempty regular file of at most 64 MiB");
47934
49386
  const bytes = readFileSync3(descriptor);
@@ -47936,7 +49388,7 @@ function localAttachment(path7) {
47936
49388
  throw new Error("Attachment changed while it was being read; try again");
47937
49389
  return bytes;
47938
49390
  } finally {
47939
- closeSync4(descriptor);
49391
+ closeSync5(descriptor);
47940
49392
  }
47941
49393
  }
47942
49394
  function registerDirectOperations(server2, manager) {
@@ -48048,8 +49500,8 @@ function registerDirectOperations(server2, manager) {
48048
49500
  }
48049
49501
  );
48050
49502
  }
48051
- function attachmentName(path7, filename) {
48052
- const source = basename3(path7);
49503
+ function attachmentName(path8, filename) {
49504
+ const source = basename4(path8);
48053
49505
  if (filename === void 0) return source;
48054
49506
  if (Buffer.byteLength(filename, "utf8") > 255)
48055
49507
  throw new Error("filename must be at most 255 bytes");
@@ -48057,21 +49509,21 @@ function attachmentName(path7, filename) {
48057
49509
  throw new Error(
48058
49510
  "filename must be one path component with no slash, colon, backslash, control character, leading dot, or surrounding spaces"
48059
49511
  );
48060
- if (extname3(filename).toLowerCase() !== extname3(source).toLowerCase())
49512
+ if (extname4(filename).toLowerCase() !== extname4(source).toLowerCase())
48061
49513
  throw new Error(
48062
- `filename must keep the source file's extension (${extname3(source) || "none"})`
49514
+ `filename must keep the source file's extension (${extname4(source) || "none"})`
48063
49515
  );
48064
49516
  return filename;
48065
49517
  }
48066
49518
  function attachFile(manager, args) {
48067
- const { id: id2, expectedContentHash, path: path7 } = args;
48068
- const name = attachmentName(path7, args.filename);
49519
+ const { id: id2, expectedContentHash, path: path8 } = args;
49520
+ const name = attachmentName(path8, args.filename);
48069
49521
  const before = readSnapshot(manager, id2);
48070
49522
  if (before.hash !== expectedContentHash) throw new Error("Note revision changed");
48071
- const bytes = localAttachment(path7);
49523
+ const bytes = localAttachment(path8);
48072
49524
  const beforeAttachments = manager.listAttachmentsById(id2);
48073
- const directory = mkdtempSync4(join17(tmpdir4(), "notes-attachment-add-"));
48074
- const temporaryFile = join17(directory, name);
49525
+ const directory = mkdtempSync4(join20(tmpdir4(), "notes-attachment-add-"));
49526
+ const temporaryFile = join20(directory, name);
48075
49527
  try {
48076
49528
  writeFileSync3(temporaryFile, bytes, { mode: 384 });
48077
49529
  if (readSnapshot(manager, id2).hash !== before.hash) throw new Error("Note revision changed");
@@ -48263,18 +49715,18 @@ function appendChecklistItems(args, deps, readRich) {
48263
49715
  const existing = new Set(byPosition(readRich(args.id).checklistItems).map((item) => item.id));
48264
49716
  const landed = [];
48265
49717
  let contentHash = args.expectedContentHash;
48266
- for (const [index, text] of args.items.entries()) {
49718
+ for (const [index, text2] of args.items.entries()) {
48267
49719
  let wrote = false;
48268
49720
  try {
48269
49721
  const result = mutateBackground(
48270
49722
  { ...args, expectedContentHash: contentHash },
48271
49723
  "create-checklist-item",
48272
- { text },
49724
+ { text: text2 },
48273
49725
  (before, after) => {
48274
49726
  wrote = true;
48275
49727
  assertPreserved(before, after, { append: true });
48276
49728
  const added = after.checklist.slice(before.checklist.length);
48277
- if (added.length !== 1 || added[0].text !== text || added[0].done)
49729
+ if (added.length !== 1 || added[0].text !== text2 || added[0].done)
48278
49730
  throw new Error("Native checklist item not verified");
48279
49731
  },
48280
49732
  deps
@@ -48283,14 +49735,14 @@ function appendChecklistItems(args, deps, readRich) {
48283
49735
  const fresh = items.filter(
48284
49736
  (item) => !existing.has(item.id) && !landed.some((done) => done.id === item.id)
48285
49737
  );
48286
- if (fresh.length !== 1 || fresh[0].text !== text || fresh[0].done)
49738
+ if (fresh.length !== 1 || fresh[0].text !== text2 || fresh[0].done)
48287
49739
  throw new Error("Native checklist identity not verified");
48288
49740
  for (const done of landed) {
48289
49741
  const current = items.find((item) => item.id === done.id);
48290
49742
  if (!current || current.text !== done.text || current.done)
48291
49743
  throw new Error("An earlier appended item changed identity or text");
48292
49744
  }
48293
- landed.push({ index, id: fresh[0].id, text });
49745
+ landed.push({ index, id: fresh[0].id, text: text2 });
48294
49746
  contentHash = result.contentHash;
48295
49747
  } catch (error2) {
48296
49748
  return {
@@ -48299,7 +49751,7 @@ function appendChecklistItems(args, deps, readRich) {
48299
49751
  landed,
48300
49752
  stoppedAt: {
48301
49753
  index,
48302
- text,
49754
+ text: text2,
48303
49755
  outcome: wrote ? "uncertain" : "not-written",
48304
49756
  error: error2 instanceof Error ? error2.message : String(error2)
48305
49757
  },
@@ -48629,9 +50081,9 @@ function registerNativeOperations(server2, manager) {
48629
50081
 
48630
50082
  // src/setupShortcuts.ts
48631
50083
  import { spawnSync as spawnSync2 } from "node:child_process";
48632
- import { existsSync as existsSync11 } from "node:fs";
50084
+ import { existsSync as existsSync12 } from "node:fs";
48633
50085
  import { release as release2 } from "node:os";
48634
- import { dirname as dirname4, resolve as resolve3 } from "node:path";
50086
+ import { dirname as dirname5, resolve as resolve4 } from "node:path";
48635
50087
  import { fileURLToPath } from "node:url";
48636
50088
  var OPTIONAL_BRIDGE_NOTE = "(optional \u2014 needed only for create-note format: markdown, macOS 26+)";
48637
50089
  var MARKDOWN_MIN_DARWIN_MAJOR = 25;
@@ -48649,16 +50101,16 @@ var shortcutFiles = [
48649
50101
  ];
48650
50102
  function setupShortcuts(checkOnly, dependencies = {}) {
48651
50103
  const status = dependencies.status || nativeTagsStatus;
48652
- const exists = dependencies.exists || existsSync11;
48653
- const open = dependencies.open || ((path7) => {
48654
- const result = spawnSync2("/usr/bin/open", [path7], { encoding: "utf8" });
50104
+ const exists = dependencies.exists || existsSync12;
50105
+ const open = dependencies.open || ((path8) => {
50106
+ const result = spawnSync2("/usr/bin/open", [path8], { encoding: "utf8" });
48655
50107
  return result.status === 0 ? { ok: true } : { ok: false, error: result.stderr || result.error?.message || "open failed" };
48656
50108
  });
48657
- const baseDirectory = dependencies.baseDirectory || resolve3(dirname4(fileURLToPath(import.meta.url)), "../shortcuts");
50109
+ const baseDirectory = dependencies.baseDirectory || resolve4(dirname5(fileURLToPath(import.meta.url)), "../shortcuts");
48658
50110
  const osRelease = (dependencies.osRelease || release2)();
48659
50111
  const darwinMajor = Number.parseInt(osRelease.split(".")[0], 10);
48660
50112
  const items = shortcutFiles.map(({ name, file, optional: optional2 }) => {
48661
- const path7 = resolve3(baseDirectory, file);
50113
+ const path8 = resolve4(baseDirectory, file);
48662
50114
  let installed = false;
48663
50115
  let identifier;
48664
50116
  let error2;
@@ -48674,9 +50126,9 @@ function setupShortcuts(checkOnly, dependencies = {}) {
48674
50126
  if (!installed && !checkOnly) {
48675
50127
  if (optional2 && !(darwinMajor >= MARKDOWN_MIN_DARWIN_MAJOR))
48676
50128
  skipped = `requires macOS 26 or later (this Mac reports Darwin ${osRelease})`;
48677
- else if (!exists(path7)) error2 = `Packaged Shortcut is missing: ${path7}`;
50129
+ else if (!exists(path8)) error2 = `Packaged Shortcut is missing: ${path8}`;
48678
50130
  else {
48679
- const result = open(path7);
50131
+ const result = open(path8);
48680
50132
  opened = result.ok;
48681
50133
  if (!result.ok) error2 = result.error || `Could not open ${file}`;
48682
50134
  }
@@ -48685,7 +50137,7 @@ function setupShortcuts(checkOnly, dependencies = {}) {
48685
50137
  name,
48686
50138
  installed,
48687
50139
  identifier,
48688
- file: path7,
50140
+ file: path8,
48689
50141
  opened,
48690
50142
  ...optional2 ? { optional: optional2 } : {},
48691
50143
  ...skipped ? { skipped } : {},
@@ -49616,19 +51068,47 @@ registerTool(
49616
51068
  registerTool(
49617
51069
  "list-native-tags",
49618
51070
  {
49619
- description: "Use when: listing actual native Notes tags used in one explicit account and folder.\nReturns: each native tag mapped to exact matching note IDs, plus completeness and per-note errors.\nDo not use when: searching textual #hashtags in note bodies (search-notes).\nSafety: read-only; requires Full Disk Access and discloses partial reads.",
51071
+ description: "Use when: listing actual native Notes tags, either in one folder (pass folder) or as an account-wide inventory with note counts (omit folder; account then optionally narrows it, else every account is counted).\nReturns: folder mode maps each tag to exact matching note IDs, plus completeness and per-note errors; inventory mode returns each tag with noteCount and per-account counts, sorted by count.\nDo not use when: searching textual #hashtags in note bodies (search-notes).\nSafety: read-only; requires Full Disk Access and discloses partial reads.",
49620
51072
  inputSchema: {
49621
- account: external_exports.string().min(1).max(MAX.ACCOUNT),
49622
- folder: external_exports.string().min(1).max(MAX.FOLDER)
51073
+ account: external_exports.string().min(1).max(MAX.ACCOUNT).optional().describe(
51074
+ "Account name (exact or unique prefix). Folder mode: defaults to Notes.app's default account. Inventory mode: omit to count every account."
51075
+ ),
51076
+ folder: external_exports.string().min(1).max(MAX.FOLDER).optional().describe("Folder to list tags in. Omit for the account-wide inventory with counts.")
49623
51077
  },
49624
51078
  outputSchema: {
49625
51079
  tags: external_exports.record(external_exports.array(external_exports.string())).optional(),
49626
51080
  complete: external_exports.boolean().optional(),
49627
- errors: external_exports.record(external_exports.string()).optional()
51081
+ errors: external_exports.record(external_exports.string()).optional(),
51082
+ inventory: external_exports.array(
51083
+ external_exports.object({
51084
+ tag: external_exports.string(),
51085
+ noteCount: external_exports.number(),
51086
+ accounts: external_exports.record(external_exports.number()),
51087
+ spellings: external_exports.array(external_exports.string()).optional()
51088
+ }).passthrough()
51089
+ ).optional(),
51090
+ tagCount: external_exports.number().optional(),
51091
+ unverifiedNotes: external_exports.number().optional(),
51092
+ account: external_exports.string().optional()
49628
51093
  },
49629
51094
  annotations: { readOnlyHint: true }
49630
51095
  },
49631
51096
  withErrorHandling(({ account, folder }) => {
51097
+ if (!folder) {
51098
+ const result = nativeTagInventory({ account });
51099
+ const scope2 = result.account ? ` in ${result.account}` : " across all accounts";
51100
+ const lines = result.inventory.map(
51101
+ (entry) => ` - ${entry.tag}: ${entry.noteCount} note${entry.noteCount === 1 ? "" : "s"}`
51102
+ );
51103
+ const partial2 = result.complete ? "" : `
51104
+
51105
+ ${result.unverifiedNotes} note(s) could not be checked against their body (locked or unreadable) and were counted from tag objects alone.`;
51106
+ return successResponse(
51107
+ `${result.tagCount} native tag${result.tagCount === 1 ? "" : "s"}${scope2}` + (lines.length ? `:
51108
+ ${lines.join("\n")}` : ".") + partial2,
51109
+ result
51110
+ );
51111
+ }
49632
51112
  const tags = {};
49633
51113
  const errors = {};
49634
51114
  for (const note of notesManager.listNoteRefs(account, folder)) {
@@ -49764,17 +51244,17 @@ function guardedAppend({
49764
51244
  scopeText,
49765
51245
  htmlSeparator
49766
51246
  }, onRoute) {
49767
- const contentToHtml = (text) => {
49768
- if (format === "html") return text;
49769
- return text.split("\n").map((line) => {
51247
+ const contentToHtml = (text2) => {
51248
+ if (format === "html") return text2;
51249
+ return text2.split("\n").map((line) => {
49770
51250
  const escaped = line.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
49771
51251
  return `<div>${escaped || "<br>"}</div>`;
49772
51252
  }).join("");
49773
51253
  };
49774
- const separatorToHtml = (sep3) => {
49775
- if (format === "html") return sep3;
49776
- if (sep3 === "\n\n") return "<div><br></div>";
49777
- const escaped = sep3.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
51254
+ const separatorToHtml = (sep4) => {
51255
+ if (format === "html") return sep4;
51256
+ if (sep4 === "\n\n") return "<div><br></div>";
51257
+ const escaped = sep4.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
49778
51258
  return `<div>${escaped}</div>`;
49779
51259
  };
49780
51260
  const snapshot = readExactNoteSnapshot(id2);
@@ -50538,8 +52018,8 @@ registerTool(
50538
52018
  if (firstImage && id2) {
50539
52019
  const assets = notesManager.getAttachmentAssetsById(id2);
50540
52020
  const first2 = firstImageView(id2, selectFirstImage(assets));
50541
- const text = first2 ? `Lead visual: ${first2.kind} attachment ${first2.attachmentId} (${first2.path ? "asset on disk" : first2.previewPath ? "preview only" : "not downloaded"}; order from ${assets.orderSource}).` : "This note has no image, scan, or drawing attachment.";
50542
- return successResponse(text, { firstImage: first2, orderSource: assets.orderSource });
52021
+ const text2 = first2 ? `Lead visual: ${first2.kind} attachment ${first2.attachmentId} (${first2.path ? "asset on disk" : first2.previewPath ? "preview only" : "not downloaded"}; order from ${assets.orderSource}).` : "This note has no image, scan, or drawing attachment.";
52022
+ return successResponse(text2, { firstImage: first2, orderSource: assets.orderSource });
50543
52023
  }
50544
52024
  if (id2) {
50545
52025
  const note2 = notesManager.getNoteById(id2);
@@ -51043,6 +52523,67 @@ registerTool(
51043
52523
  return successResponse(markdown, { markdown });
51044
52524
  }, "Error getting note as markdown")
51045
52525
  );
52526
+ var exportPathInput = (what) => external_exports.string().min(1).max(MAX.SAVE_PATH).optional().describe(
52527
+ `${what} (absolute; under home, a temp dir, or /Volumes; never inside the Notes library)`
52528
+ );
52529
+ var exportStatsSchema = external_exports.object({
52530
+ attachments: external_exports.number(),
52531
+ placed: external_exports.number(),
52532
+ placeholders: external_exports.number(),
52533
+ unavailable: external_exports.number(),
52534
+ tables: external_exports.number(),
52535
+ unreadableTables: external_exports.number(),
52536
+ unreferenced: external_exports.number()
52537
+ });
52538
+ registerTool(
52539
+ "export-notes-markdown",
52540
+ {
52541
+ description: "Use when: exporting one note (by exact id) or a folder's notes as one Markdown document rendered from the decoded note body: headings, bulleted/dashed/numbered lists with indent, checklists with state, block quotes, monospaced blocks, bold/italic/strikethrough/underline/highlight, links, tables, and attachments in body order.\nReturns: the Markdown inline (capped by APPLE_NOTES_MCP_EXPORT_MAX_BYTES), or with outputPath a receipt {format, count, bytes, output}; plus attachment counts and skipped notes (for example password-protected ones).\nDo not use when: you need the legacy HTML-converted Markdown of one note (get-note-markdown) or a restorable backup (export-notes-json). A folder document separates notes with '---' and is a presentation format, not something to import back.\nSafety: read-only against Notes; requires Full Disk Access. outputPath is create-only (an existing file is refused with [output_exists]); assetsDir copies attachment files without replacing existing ones (collisions get -2, -3 suffixes). Without assetsDir, attachments render as labeled placeholders.",
52542
+ inputSchema: {
52543
+ id: noteIdInput.optional(),
52544
+ folder: external_exports.string().min(1).max(MAX.FOLDER).optional().describe("Folder path to export instead of one note (nested paths use '/')"),
52545
+ account: external_exports.string().max(MAX.ACCOUNT).optional().describe("Account holding the folder (defaults to Notes.app's default account)"),
52546
+ limit: external_exports.number().int().min(1).max(MAX_FOLDER_EXPORT_LIMIT).optional().describe(
52547
+ `Maximum notes read from the folder (default 100, max ${MAX_FOLDER_EXPORT_LIMIT})`
52548
+ ),
52549
+ outputPath: exportPathInput("File to create for the Markdown"),
52550
+ assetsDir: exportPathInput("Directory that receives copies of attachment files"),
52551
+ wrap: external_exports.number().int().min(0).max(1e3).optional().describe("Hard-wrap prose at this many columns (0 or omitted: no wrapping)")
52552
+ },
52553
+ outputSchema: {
52554
+ format: external_exports.string().optional(),
52555
+ count: external_exports.number().optional(),
52556
+ bytes: external_exports.number().optional(),
52557
+ markdown: external_exports.string().optional(),
52558
+ output: external_exports.string().optional(),
52559
+ assets: external_exports.object({ dir: external_exports.string(), files: external_exports.number() }).optional(),
52560
+ stats: exportStatsSchema.optional(),
52561
+ skipped: external_exports.array(external_exports.object({ id: external_exports.string(), code: external_exports.string() })).optional()
52562
+ },
52563
+ annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false }
52564
+ },
52565
+ withErrorHandling((request) => {
52566
+ let receipt;
52567
+ try {
52568
+ receipt = exportNotesMarkdown(request, {
52569
+ listNoteRefs: (account, folder, since, limit) => notesManager.listNoteRefs(account, folder, since, limit),
52570
+ // The document travels twice (text and structuredContent).
52571
+ maxInlineBytes: Math.floor(exportMaxResponseBytes() / 2) - 64 * 1024
52572
+ });
52573
+ } catch (error2) {
52574
+ if (!(error2 instanceof NotesExportError || error2 instanceof NoteBlocksError)) throw error2;
52575
+ const hint = error2.code === "no-full-disk-access" ? ` Grant Full Disk Access to the app that launches this server: ${FULL_DISK_ACCESS_GUIDE_URL}` : "";
52576
+ return errorResponse(`Error exporting Markdown [${error2.code}]: ${error2.message}${hint}`);
52577
+ }
52578
+ const skipped = receipt.skipped.length ? `; skipped ${receipt.skipped.length}` : "";
52579
+ if (receipt.output)
52580
+ return successResponse(
52581
+ `Wrote ${receipt.count} note(s) as Markdown (${receipt.bytes} bytes) to ${receipt.output}` + (receipt.assets ? `; copied ${receipt.assets.files} asset file(s) to ${receipt.assets.dir}` : "") + `${skipped}.`,
52582
+ { ...receipt }
52583
+ );
52584
+ return successResponse(receipt.markdown ?? "", { ...receipt });
52585
+ }, "Error exporting Markdown")
52586
+ );
51046
52587
  registerTool(
51047
52588
  "get-checklist-state",
51048
52589
  {
@@ -51150,6 +52691,57 @@ registerTool(
51150
52691
  return successResponse(summary, metadata);
51151
52692
  }, "Error reading note metadata")
51152
52693
  );
52694
+ var SPECIAL_KIND_LABEL = {
52695
+ pinned: "pinned notes",
52696
+ "quick-notes": "Quick Notes",
52697
+ "recently-deleted": "notes in Recently Deleted",
52698
+ locked: "password-protected notes"
52699
+ };
52700
+ registerTool(
52701
+ "list-special-notes",
52702
+ {
52703
+ description: "Use when: listing pinned notes, Quick Notes, notes in Recently Deleted, or password-protected (locked) notes \u2014 sets AppleScript cannot enumerate.\nReturns: metadata rows newest first (id, identifier, title, folder path, account, created, modified, and pinned/locked/quickNote/inRecentlyDeleted flags; snippet except for locked notes; passwordHint for kind locked), plus total before limit. supported is false when this macOS version's database cannot answer that kind.\nDo not use when: you need note content (get-note-content) or a folder listing (list-notes).\nNote: reads the NoteStore SQLite database read-only and requires Full Disk Access. Pinned and Quick Notes listings cover notes in folders outside Recently Deleted; the locked listing includes trashed and folderless locked notes, flagged as such. Never reads locked note bodies.",
52704
+ inputSchema: {
52705
+ kind: external_exports.enum(["pinned", "quick-notes", "recently-deleted", "locked"]).describe("Which set of notes to list"),
52706
+ account: external_exports.string().min(1).max(MAX.ACCOUNT).optional().describe("Only this account (exact or unique-prefix name). Omit for every account."),
52707
+ limit: external_exports.number().int().min(1).max(SPECIAL_LIMIT.MAX).optional().describe(`Maximum notes to return (default ${SPECIAL_LIMIT.DEFAULT})`)
52708
+ },
52709
+ outputSchema: {
52710
+ kind: external_exports.string().optional(),
52711
+ notes: external_exports.array(external_exports.object({}).passthrough()).optional(),
52712
+ count: external_exports.number().optional(),
52713
+ total: external_exports.number().optional(),
52714
+ limit: external_exports.number().optional(),
52715
+ supported: external_exports.boolean().optional(),
52716
+ account: external_exports.string().optional()
52717
+ },
52718
+ annotations: { readOnlyHint: true }
52719
+ },
52720
+ withErrorHandling(({ kind, account, limit }) => {
52721
+ const result = listSpecialNotes({ kind, account, limit });
52722
+ const label = SPECIAL_KIND_LABEL[kind];
52723
+ const structured = result;
52724
+ if (!result.supported) {
52725
+ return successResponse(
52726
+ `This macOS version's Notes database does not record ${label}.`,
52727
+ structured
52728
+ );
52729
+ }
52730
+ const scope2 = result.account ? ` in ${result.account}` : "";
52731
+ if (result.count === 0) return successResponse(`No ${label}${scope2}.`, structured);
52732
+ const lines = result.notes.map(
52733
+ (row) => ` - ${row.title ?? "(untitled)"}${row.folder ? ` (${row.folder})` : ""} [id: ${row.id}]`
52734
+ );
52735
+ const more = result.total > result.count ? `
52736
+
52737
+ Showing ${result.count} of ${result.total}; pass a higher limit to see more.` : "";
52738
+ return successResponse(
52739
+ `Found ${result.total} ${label}${scope2}:
52740
+ ${lines.join("\n")}${more}`,
52741
+ structured
52742
+ );
52743
+ }, "Error listing notes")
52744
+ );
51153
52745
  registerResourcesAndPrompts(server, notesManager);
51154
52746
  process.on("uncaughtException", (err) => {
51155
52747
  if (err?.code === "EPIPE") process.exit(0);