apple-notes-mcp 2.8.34 → 2.8.36

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 +73 -7
  2. package/build/index.js +1261 -325
  3. package/package.json +1 -1
package/build/index.js CHANGED
@@ -108,7 +108,7 @@ var require_code = __commonJS({
108
108
  }
109
109
  exports._ = _;
110
110
  var plus = new _Code("+");
111
- function str(strs, ...args) {
111
+ function str2(strs, ...args) {
112
112
  const expr = [safeStringify(strs[0])];
113
113
  let i = 0;
114
114
  while (i < args.length) {
@@ -119,7 +119,7 @@ var require_code = __commonJS({
119
119
  optimize(expr);
120
120
  return new _Code(expr);
121
121
  }
122
- exports.str = str;
122
+ exports.str = str2;
123
123
  function addCodeArg(code, arg) {
124
124
  if (arg instanceof _Code)
125
125
  code.push(...arg._items);
@@ -162,7 +162,7 @@ var require_code = __commonJS({
162
162
  return;
163
163
  }
164
164
  function strConcat(c1, c2) {
165
- return c2.emptyStr() ? c1 : c1.emptyStr() ? c2 : str`${c1}${c2}`;
165
+ return c2.emptyStr() ? c1 : c1.emptyStr() ? c2 : str2`${c1}${c2}`;
166
166
  }
167
167
  exports.strConcat = strConcat;
168
168
  function interpolate(x) {
@@ -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, constants4) {
420
+ optimizeNames(names, constants5) {
421
421
  if (!names[this.name.str])
422
422
  return;
423
423
  if (this.rhs)
424
- this.rhs = optimizeExpr(this.rhs, names, constants4);
424
+ this.rhs = optimizeExpr(this.rhs, names, constants5);
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, constants4) {
441
+ optimizeNames(names, constants5) {
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, constants4);
444
+ this.rhs = optimizeExpr(this.rhs, names, constants5);
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, constants4) {
506
- this.code = optimizeExpr(this.code, names, constants4);
505
+ optimizeNames(names, constants5) {
506
+ this.code = optimizeExpr(this.code, names, constants5);
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, constants4) {
535
+ optimizeNames(names, constants5) {
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, constants4))
540
+ if (n.optimizeNames(names, constants5))
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, constants4) {
593
+ optimizeNames(names, constants5) {
594
594
  var _a;
595
- this.else = (_a = this.else) === null || _a === void 0 ? void 0 : _a.optimizeNames(names, constants4);
596
- if (!(super.optimizeNames(names, constants4) || this.else))
595
+ this.else = (_a = this.else) === null || _a === void 0 ? void 0 : _a.optimizeNames(names, constants5);
596
+ if (!(super.optimizeNames(names, constants5) || this.else))
597
597
  return;
598
- this.condition = optimizeExpr(this.condition, names, constants4);
598
+ this.condition = optimizeExpr(this.condition, names, constants5);
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, constants4) {
622
- if (!super.optimizeNames(names, constants4))
621
+ optimizeNames(names, constants5) {
622
+ if (!super.optimizeNames(names, constants5))
623
623
  return;
624
- this.iteration = optimizeExpr(this.iteration, names, constants4);
624
+ this.iteration = optimizeExpr(this.iteration, names, constants5);
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, constants4) {
661
- if (!super.optimizeNames(names, constants4))
660
+ optimizeNames(names, constants5) {
661
+ if (!super.optimizeNames(names, constants5))
662
662
  return;
663
- this.iterable = optimizeExpr(this.iterable, names, constants4);
663
+ this.iterable = optimizeExpr(this.iterable, names, constants5);
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, constants4) {
705
+ optimizeNames(names, constants5) {
706
706
  var _a, _b;
707
- super.optimizeNames(names, constants4);
708
- (_a = this.catch) === null || _a === void 0 ? void 0 : _a.optimizeNames(names, constants4);
709
- (_b = this.finally) === null || _b === void 0 ? void 0 : _b.optimizeNames(names, constants4);
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);
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, constants4) {
1010
+ function optimizeExpr(expr, names, constants5) {
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 = constants4[n.str];
1025
+ const c = constants5[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 && constants4[c.str] !== void 0);
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);
1033
1033
  }
1034
1034
  }
1035
1035
  function subtractNames(names, from) {
@@ -1124,22 +1124,22 @@ var require_util = __commonJS({
1124
1124
  return (0, codegen_1._)`${topSchemaRef}${schemaPath}${(0, codegen_1.getProperty)(keyword)}`;
1125
1125
  }
1126
1126
  exports.schemaRefOrVal = schemaRefOrVal;
1127
- function unescapeFragment(str) {
1128
- return unescapeJsonPointer(decodeURIComponent(str));
1127
+ function unescapeFragment(str2) {
1128
+ return unescapeJsonPointer(decodeURIComponent(str2));
1129
1129
  }
1130
1130
  exports.unescapeFragment = unescapeFragment;
1131
- function escapeFragment(str) {
1132
- return encodeURIComponent(escapeJsonPointer(str));
1131
+ function escapeFragment(str2) {
1132
+ return encodeURIComponent(escapeJsonPointer(str2));
1133
1133
  }
1134
1134
  exports.escapeFragment = escapeFragment;
1135
- function escapeJsonPointer(str) {
1136
- if (typeof str == "number")
1137
- return `${str}`;
1138
- return str.replace(/~/g, "~0").replace(/\//g, "~1");
1135
+ function escapeJsonPointer(str2) {
1136
+ if (typeof str2 == "number")
1137
+ return `${str2}`;
1138
+ return str2.replace(/~/g, "~0").replace(/\//g, "~1");
1139
1139
  }
1140
1140
  exports.escapeJsonPointer = escapeJsonPointer;
1141
- function unescapeJsonPointer(str) {
1142
- return str.replace(/~1/g, "/").replace(/~0/g, "~");
1141
+ function unescapeJsonPointer(str2) {
1142
+ return str2.replace(/~1/g, "/").replace(/~0/g, "~");
1143
1143
  }
1144
1144
  exports.unescapeJsonPointer = unescapeJsonPointer;
1145
1145
  function eachItem(xs, f) {
@@ -2164,8 +2164,8 @@ var require_json_schema_traverse = __commonJS({
2164
2164
  post(schema, jsonPtr, rootSchema, parentJsonPtr, parentKeyword, parentSchema, keyIndex);
2165
2165
  }
2166
2166
  }
2167
- function escapeJsonPtr(str) {
2168
- return str.replace(/~/g, "~0").replace(/\//g, "~1");
2167
+ function escapeJsonPtr(str2) {
2168
+ return str2.replace(/~/g, "~0").replace(/\//g, "~1");
2169
2169
  }
2170
2170
  }
2171
2171
  });
@@ -3261,15 +3261,15 @@ var require_utils = __commonJS({
3261
3261
  isIPV6: true
3262
3262
  };
3263
3263
  }
3264
- function findToken(str, token) {
3264
+ function findToken(str2, token) {
3265
3265
  let ind = 0;
3266
- for (let i = 0; i < str.length; i++) {
3267
- if (str[i] === token) ind++;
3266
+ for (let i = 0; i < str2.length; i++) {
3267
+ if (str2[i] === token) ind++;
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
  }
@@ -4267,7 +4267,7 @@ var require_core = __commonJS({
4267
4267
  var util_1 = require_util();
4268
4268
  var $dataRefSchema = require_data();
4269
4269
  var uri_1 = require_uri();
4270
- var defaultRegExp = (str, flags) => new RegExp(str, flags);
4270
+ var defaultRegExp = (str2, flags) => new RegExp(str2, flags);
4271
4271
  defaultRegExp.code = "new RegExp";
4272
4272
  var META_IGNORE_OPTIONS = ["removeAdditional", "useDefaults", "coerceTypes"];
4273
4273
  var EXT_SCOPE_NAMES = /* @__PURE__ */ new Set([
@@ -5062,16 +5062,16 @@ var require_ucs2length = __commonJS({
5062
5062
  "node_modules/.pnpm/ajv@8.20.0/node_modules/ajv/dist/runtime/ucs2length.js"(exports) {
5063
5063
  "use strict";
5064
5064
  Object.defineProperty(exports, "__esModule", { value: true });
5065
- function ucs2length(str) {
5066
- const len = str.length;
5065
+ function ucs2length(str2) {
5066
+ const len = str2.length;
5067
5067
  let length = 0;
5068
5068
  let pos = 0;
5069
5069
  let value;
5070
5070
  while (pos < len) {
5071
5071
  length++;
5072
- value = str.charCodeAt(pos++);
5072
+ value = str2.charCodeAt(pos++);
5073
5073
  if (value >= 55296 && value <= 56319 && pos < len) {
5074
- value = str.charCodeAt(pos);
5074
+ value = str2.charCodeAt(pos);
5075
5075
  if ((value & 64512) === 56320)
5076
5076
  pos++;
5077
5077
  }
@@ -6954,8 +6954,8 @@ var require_formats = __commonJS({
6954
6954
  }
6955
6955
  var DATE = /^(\d\d\d\d)-(\d\d)-(\d\d)$/;
6956
6956
  var DAYS = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
6957
- function date3(str) {
6958
- const matches = DATE.exec(str);
6957
+ function date3(str2) {
6958
+ const matches = DATE.exec(str2);
6959
6959
  if (!matches)
6960
6960
  return false;
6961
6961
  const year = +matches[1];
@@ -6974,8 +6974,8 @@ var require_formats = __commonJS({
6974
6974
  }
6975
6975
  var TIME = /^(\d\d):(\d\d):(\d\d(?:\.\d+)?)(z|([+-])(\d\d)(?::?(\d\d))?)?$/i;
6976
6976
  function getTime(strictTimeZone) {
6977
- return function time3(str) {
6978
- const matches = TIME.exec(str);
6977
+ return function time3(str2) {
6978
+ const matches = TIME.exec(str2);
6979
6979
  if (!matches)
6980
6980
  return false;
6981
6981
  const hr = +matches[1];
@@ -7021,8 +7021,8 @@ var require_formats = __commonJS({
7021
7021
  var DATE_TIME_SEPARATOR = /t|\s/i;
7022
7022
  function getDateTime(strictTimeZone) {
7023
7023
  const time3 = getTime(strictTimeZone);
7024
- return function date_time(str) {
7025
- const dateTime = str.split(DATE_TIME_SEPARATOR);
7024
+ return function date_time(str2) {
7025
+ const dateTime = str2.split(DATE_TIME_SEPARATOR);
7026
7026
  return dateTime.length === 2 && date3(dateTime[0]) && time3(dateTime[1]);
7027
7027
  };
7028
7028
  }
@@ -7047,13 +7047,13 @@ var require_formats = __commonJS({
7047
7047
  }
7048
7048
  var NOT_URI_FRAGMENT = /\/|:/;
7049
7049
  var URI = /^(?:[a-z][a-z0-9+\-.]*:)(?:\/?\/(?:(?:[a-z0-9\-._~!$&'()*+,;=:]|%[0-9a-f]{2})*@)?(?:\[(?:(?:(?:(?:[0-9a-f]{1,4}:){6}|::(?:[0-9a-f]{1,4}:){5}|(?:[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){4}|(?:(?:[0-9a-f]{1,4}:){0,1}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){3}|(?:(?:[0-9a-f]{1,4}:){0,2}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){2}|(?:(?:[0-9a-f]{1,4}:){0,3}[0-9a-f]{1,4})?::[0-9a-f]{1,4}:|(?:(?:[0-9a-f]{1,4}:){0,4}[0-9a-f]{1,4})?::)(?:[0-9a-f]{1,4}:[0-9a-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?))|(?:(?:[0-9a-f]{1,4}:){0,5}[0-9a-f]{1,4})?::[0-9a-f]{1,4}|(?:(?:[0-9a-f]{1,4}:){0,6}[0-9a-f]{1,4})?::)|[Vv][0-9a-f]+\.[a-z0-9\-._~!$&'()*+,;=:]+)\]|(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)|(?:[a-z0-9\-._~!$&'()*+,;=]|%[0-9a-f]{2})*)(?::\d*)?(?:\/(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})*)*|\/(?:(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})+(?:\/(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})*)*)?|(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})+(?:\/(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})*)*)(?:\?(?:[a-z0-9\-._~!$&'()*+,;=:@/?]|%[0-9a-f]{2})*)?(?:#(?:[a-z0-9\-._~!$&'()*+,;=:@/?]|%[0-9a-f]{2})*)?$/i;
7050
- function uri(str) {
7051
- return NOT_URI_FRAGMENT.test(str) && URI.test(str);
7050
+ function uri(str2) {
7051
+ return NOT_URI_FRAGMENT.test(str2) && URI.test(str2);
7052
7052
  }
7053
7053
  var BYTE = /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/gm;
7054
- function byte(str) {
7054
+ function byte(str2) {
7055
7055
  BYTE.lastIndex = 0;
7056
- return BYTE.test(str);
7056
+ return BYTE.test(str2);
7057
7057
  }
7058
7058
  var MIN_INT32 = -(2 ** 31);
7059
7059
  var MAX_INT32 = 2 ** 31 - 1;
@@ -7067,11 +7067,11 @@ var require_formats = __commonJS({
7067
7067
  return true;
7068
7068
  }
7069
7069
  var Z_ANCHOR = /[^\\]\\Z/;
7070
- function regex(str) {
7071
- if (Z_ANCHOR.test(str))
7070
+ function regex(str2) {
7071
+ if (Z_ANCHOR.test(str2))
7072
7072
  return false;
7073
7073
  try {
7074
- new RegExp(str);
7074
+ new RegExp(str2);
7075
7075
  return true;
7076
7076
  } catch (e) {
7077
7077
  return false;
@@ -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 constants4 = {
7425
+ var constants5 = {
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 constants4) {
7465
- v = { value: constants4[c] };
7464
+ for (c in constants5) {
7465
+ v = { value: constants5[c] };
7466
7466
  Object.defineProperty(DOMException, c, v);
7467
7467
  Object.defineProperty(DOMException.prototype, c, v);
7468
7468
  }
@@ -9206,12 +9206,12 @@ var require_DOMTokenList = __commonJS({
9206
9206
  if (strProp === clist._lastStringValue) {
9207
9207
  return toArray(clist);
9208
9208
  }
9209
- var str = strProp.replace(/(^[ \t\r\n\f]+)|([ \t\r\n\f]+$)/g, "");
9210
- if (str === "") {
9209
+ var str2 = strProp.replace(/(^[ \t\r\n\f]+)|([ \t\r\n\f]+$)/g, "");
9210
+ if (str2 === "") {
9211
9211
  return [];
9212
9212
  } else {
9213
9213
  var seen = /* @__PURE__ */ Object.create(null);
9214
- return str.split(/[ \t\r\n\f]+/g).filter(function(n) {
9214
+ return str2.split(/[ \t\r\n\f]+/g).filter(function(n) {
9215
9215
  var key = "$" + n;
9216
9216
  if (seen[key]) {
9217
9217
  return false;
@@ -9266,16 +9266,16 @@ var require_select = __commonJS({
9266
9266
  var nodeType = n.parentNode.nodeType;
9267
9267
  return nodeType === 1 || nodeType === 9;
9268
9268
  };
9269
- var unquote = function(str) {
9270
- if (!str) return str;
9271
- var ch = str[0];
9269
+ var unquote = function(str2) {
9270
+ if (!str2) return str2;
9271
+ var ch = str2[0];
9272
9272
  if (ch === '"' || ch === "'") {
9273
- if (str[str.length - 1] === ch) {
9274
- str = str.slice(1, -1);
9273
+ if (str2[str2.length - 1] === ch) {
9274
+ str2 = str2.slice(1, -1);
9275
9275
  } else {
9276
- str = str.slice(1);
9276
+ str2 = str2.slice(1);
9277
9277
  }
9278
- return str.replace(rules.str_escape, function(s) {
9278
+ return str2.replace(rules.str_escape, function(s) {
9279
9279
  var m = /^\\(?:([0-9A-Fa-f]+)|([\r\n\f]+))/.exec(s);
9280
9280
  if (!m) {
9281
9281
  return s.slice(1);
@@ -9289,14 +9289,14 @@ var require_select = __commonJS({
9289
9289
  String.fromCharCode(cp)
9290
9290
  );
9291
9291
  });
9292
- } else if (rules.ident.test(str)) {
9293
- return decodeid(str);
9292
+ } else if (rules.ident.test(str2)) {
9293
+ return decodeid(str2);
9294
9294
  } else {
9295
- return str;
9295
+ return str2;
9296
9296
  }
9297
9297
  };
9298
- var decodeid = function(str) {
9299
- return str.replace(rules.escape, function(s) {
9298
+ var decodeid = function(str2) {
9299
+ return str2.replace(rules.escape, function(s) {
9300
9300
  var m = /^\\([0-9A-Fa-f]+)/.exec(s);
9301
9301
  if (!m) {
9302
9302
  return s[1];
@@ -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;
@@ -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 join17(output, replacement);
24468
+ return join19(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 = join17(output, rule.append(self.options));
24475
+ output = join19(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 join17(output, replacement) {
24487
+ function join19(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() {
@@ -28667,9 +28667,9 @@ function assertNever(_x) {
28667
28667
  }
28668
28668
  function assert(_) {
28669
28669
  }
28670
- function getEnumValues(entries) {
28671
- const numericValues = Object.values(entries).filter((v) => typeof v === "number");
28672
- const values = Object.entries(entries).filter(([k, _]) => numericValues.indexOf(+k) === -1).map(([_, v]) => v);
28670
+ function getEnumValues(entries2) {
28671
+ const numericValues = Object.values(entries2).filter((v) => typeof v === "number");
28672
+ const values = Object.entries(entries2).filter(([k, _]) => numericValues.indexOf(+k) === -1).map(([_, v]) => v);
28673
28673
  return values;
28674
28674
  }
28675
28675
  function joinValues(array2, separator = "|") {
@@ -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);
@@ -28755,14 +28755,14 @@ function promiseAllObject(promisesObj) {
28755
28755
  }
28756
28756
  function randomString(length = 10) {
28757
28757
  const chars = "abcdefghijklmnopqrstuvwxyz";
28758
- let str = "";
28758
+ let str2 = "";
28759
28759
  for (let i = 0; i < length; i++) {
28760
- str += chars[Math.floor(Math.random() * chars.length)];
28760
+ str2 += chars[Math.floor(Math.random() * chars.length)];
28761
28761
  }
28762
- return str;
28762
+ return str2;
28763
28763
  }
28764
- function esc(str) {
28765
- return JSON.stringify(str);
28764
+ function esc(str2) {
28765
+ return JSON.stringify(str2);
28766
28766
  }
28767
28767
  var captureStackTrace = Error.captureStackTrace ? Error.captureStackTrace : (..._args) => {
28768
28768
  };
@@ -28850,8 +28850,8 @@ var getParsedType2 = (data) => {
28850
28850
  };
28851
28851
  var propertyKeyTypes = /* @__PURE__ */ new Set(["string", "number", "symbol"]);
28852
28852
  var primitiveTypes = /* @__PURE__ */ new Set(["string", "number", "bigint", "boolean", "symbol", "undefined"]);
28853
- function escapeRegex(str) {
28854
- return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
28853
+ function escapeRegex(str2) {
28854
+ return str2.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
28855
28855
  }
28856
28856
  function clone(inst, def, params) {
28857
28857
  const cl = new inst._zod.constr(def ?? inst._zod.def);
@@ -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
  }
@@ -33039,10 +33039,10 @@ var ZodEnum2 = /* @__PURE__ */ $constructor("ZodEnum", (inst, def) => {
33039
33039
  };
33040
33040
  });
33041
33041
  function _enum(values, params) {
33042
- const entries = Array.isArray(values) ? Object.fromEntries(values.map((v) => [v, v])) : values;
33042
+ const entries2 = Array.isArray(values) ? Object.fromEntries(values.map((v) => [v, v])) : values;
33043
33043
  return new ZodEnum2({
33044
33044
  type: "enum",
33045
- entries,
33045
+ entries: entries2,
33046
33046
  ...util_exports.normalizeParams(params)
33047
33047
  });
33048
33048
  }
@@ -37774,12 +37774,12 @@ var UriTemplate = class _UriTemplate {
37774
37774
  * A template expression is a sequence of characters enclosed in curly braces,
37775
37775
  * like {foo} or {?bar}.
37776
37776
  */
37777
- static isTemplate(str) {
37778
- return /\{[^}\s]+\}/.test(str);
37777
+ static isTemplate(str2) {
37778
+ return /\{[^}\s]+\}/.test(str2);
37779
37779
  }
37780
- static validateLength(str, max, context) {
37781
- if (str.length > max) {
37782
- throw new Error(`${context} exceeds maximum length of ${max} characters (got ${str.length})`);
37780
+ static validateLength(str2, max, context) {
37781
+ if (str2.length > max) {
37782
+ throw new Error(`${context} exceeds maximum length of ${max} characters (got ${str2.length})`);
37783
37783
  }
37784
37784
  }
37785
37785
  get variableNames() {
@@ -37908,8 +37908,8 @@ var UriTemplate = class _UriTemplate {
37908
37908
  }
37909
37909
  return result;
37910
37910
  }
37911
- escapeRegExp(str) {
37912
- return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
37911
+ escapeRegExp(str2) {
37912
+ return str2.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
37913
37913
  }
37914
37914
  partToRegExp(part) {
37915
37915
  const patterns = [];
@@ -39962,9 +39962,9 @@ var many = (f, n) => getFields(f, n).map((field) => {
39962
39962
  });
39963
39963
  function parseAudioRecording(data) {
39964
39964
  const root = decode(data);
39965
- const entries = many(root, 3);
39966
- if (entries.length === 0) throw new Error("No mergeable objects");
39967
- if (entries.length > 2e6) throw new Error("Recording too large");
39965
+ const entries2 = many(root, 3);
39966
+ if (entries2.length === 0) throw new Error("No mergeable objects");
39967
+ if (entries2.length > 2e6) throw new Error("Recording too large");
39968
39968
  const keys = getFields(root, 4).map((f) => stringValue(f) ?? "");
39969
39969
  const types = getFields(root, 5).map((f) => stringValue(f) ?? "");
39970
39970
  const uuids = getFields(root, 6).map(
@@ -39975,7 +39975,7 @@ function parseAudioRecording(data) {
39975
39975
  if (uuid2 && !uuidSlot.has(uuid2)) uuidSlot.set(uuid2, i);
39976
39976
  });
39977
39977
  const entry = (index) => {
39978
- const value = entries[index];
39978
+ const value = entries2[index];
39979
39979
  if (!value) throw new Error("Invalid object reference");
39980
39980
  return value;
39981
39981
  };
@@ -40017,7 +40017,7 @@ function parseAudioRecording(data) {
40017
40017
  const text = note && stringValue(getField(note, 2));
40018
40018
  return text?.replace(/\n+$/u, "") || void 0;
40019
40019
  };
40020
- const recordings = entries.map((e) => customMap(e)).filter((m) => m?.type === "com.apple.notes.ICTTAudioRecording");
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");
40022
40022
  const recording = recordings[0];
40023
40023
  const fragments = [];
@@ -40322,15 +40322,15 @@ function parseNoteTableCells(compressed) {
40322
40322
  }
40323
40323
  function decodeTable(compressed, strict) {
40324
40324
  const root = decodeMessage(gunzipSync4(compressed, { maxOutputLength: 16 * 1024 * 1024 }));
40325
- const data = sub2(sub2(root, 2), 3), entries = many2(data, 3);
40326
- if (entries.length > 1e5) throw new Error("Table too large");
40325
+ const data = sub2(sub2(root, 2), 3), entries2 = many2(data, 3);
40326
+ if (entries2.length > 1e5) throw new Error("Table too large");
40327
40327
  const keys = getFields(data, 4).map(stringValue), types = getFields(data, 5).map(stringValue), uuids = getFields(data, 6).map(hex);
40328
40328
  const entry = (index) => {
40329
- if (!entries[index]) throw new Error("Invalid table reference");
40330
- return entries[index];
40329
+ if (!entries2[index]) throw new Error("Invalid table reference");
40330
+ return entries2[index];
40331
40331
  };
40332
40332
  const uuidIndex = (index) => num(sub2(many2(sub2(entry(index), 13), 3)[0], 2), 2);
40333
- const roots = entries.filter((e) => {
40333
+ const roots = entries2.filter((e) => {
40334
40334
  const map = embeddedMessage(getField(e, 13));
40335
40335
  return map && types[num(map, 1)] === "com.apple.notes.ICTable";
40336
40336
  });
@@ -40392,7 +40392,7 @@ function decodeTable(compressed, strict) {
40392
40392
  values[ri][ci] = text.replace(/\n$/u, "");
40393
40393
  }
40394
40394
  }
40395
- const rtl = entries.some((e) => {
40395
+ const rtl = entries2.some((e) => {
40396
40396
  const map = embeddedMessage(getField(e, 13));
40397
40397
  return map && many2(map, 3).some(
40398
40398
  (m) => stringValue(getField(sub2(m, 2), 4)) === "CRTableColumnDirectionRightToLeft"
@@ -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;
@@ -41036,6 +41036,22 @@ function cleanupTempDir(dir) {
41036
41036
  }
41037
41037
  }
41038
41038
 
41039
+ // src/utils/paperAttachments.ts
41040
+ import { execFileSync as execFileSync7 } from "node:child_process";
41041
+ import {
41042
+ closeSync as closeSync3,
41043
+ constants as constants3,
41044
+ fstatSync as fstatSync3,
41045
+ lstatSync as lstatSync3,
41046
+ mkdirSync as mkdirSync3,
41047
+ openSync as openSync3,
41048
+ readdirSync as readdirSync2,
41049
+ readSync as readSync2,
41050
+ unlinkSync as unlinkSync2,
41051
+ writeSync as writeSync2
41052
+ } from "node:fs";
41053
+ import { basename as basename2, dirname as dirname3, extname as extname2, join as join7 } from "node:path";
41054
+
41039
41055
  // src/utils/attachmentAssets.ts
41040
41056
  import { execFileSync as execFileSync6 } from "node:child_process";
41041
41057
  import {
@@ -41120,7 +41136,7 @@ function attachmentCoreDataId(noteId3, pk) {
41120
41136
  }
41121
41137
  function buildAttachmentRowsSql(notePk, columns) {
41122
41138
  if (!Number.isSafeInteger(notePk) || notePk < 0) throw new Error("Invalid note primary key");
41123
- const col2 = (alias, name) => columns.has(name) ? `${alias}.${name}` : "NULL";
41139
+ const col3 = (alias, name) => columns.has(name) ? `${alias}.${name}` : "NULL";
41124
41140
  const firstOf = (alias, names) => {
41125
41141
  const present = names.filter((n) => columns.has(n)).map((n) => `${alias}.${n}`);
41126
41142
  if (present.length === 0) return "NULL";
@@ -41133,19 +41149,19 @@ function buildAttachmentRowsSql(notePk, columns) {
41133
41149
  ].join(", ");
41134
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";
41135
41151
  const noteLink = columns.has("ZNOTE") ? "a.ZNOTE" : "NULL";
41136
- const parent = col2("a", "ZPARENTATTACHMENT");
41152
+ const parent = col3("a", "ZPARENTATTACHMENT");
41137
41153
  const deleted = columns.has("ZMARKEDFORDELETION") ? " AND COALESCE(a.ZMARKEDFORDELETION, 0) = 0" : "";
41138
41154
  const fields = [
41139
41155
  `'pk', a.Z_PK`,
41140
41156
  `'identifier', a.ZIDENTIFIER`,
41141
- `'uti', ${col2("a", "ZTYPEUTI")}`,
41157
+ `'uti', ${col3("a", "ZTYPEUTI")}`,
41142
41158
  `'parentPk', ${parent}`,
41143
- `'filename', ${col2("a", "ZFILENAME")}`,
41159
+ `'filename', ${col3("a", "ZFILENAME")}`,
41144
41160
  `'mediaIdentifier', m.ZIDENTIFIER`,
41145
- `'mediaFilename', ${col2("m", "ZFILENAME")}`,
41161
+ `'mediaFilename', ${col3("m", "ZFILENAME")}`,
41146
41162
  `'mediaGeneration', ${firstOf("m", ["ZGENERATION1", "ZGENERATION"])}`,
41147
- `'fallbackImageGeneration', ${col2("a", "ZFALLBACKIMAGEGENERATION")}`,
41148
- `'fallbackPdfGeneration', ${col2("a", "ZFALLBACKPDFGENERATION")}`,
41163
+ `'fallbackImageGeneration', ${col3("a", "ZFALLBACKIMAGEGENERATION")}`,
41164
+ `'fallbackPdfGeneration', ${col3("a", "ZFALLBACKPDFGENERATION")}`,
41149
41165
  `'accountIdentifier', ${account}`
41150
41166
  ].join(", ");
41151
41167
  const mediaJoin = columns.has("ZMEDIA") ? "LEFT JOIN ZICCLOUDSYNCINGOBJECT m ON m.Z_PK = a.ZMEDIA" : "LEFT JOIN ZICCLOUDSYNCINGOBJECT m ON 0";
@@ -41258,32 +41274,32 @@ function safeComponent(value) {
41258
41274
  if (value === "." || value === ".." || value.includes("/") || value.includes("\0")) return null;
41259
41275
  return value;
41260
41276
  }
41261
- function realInside(path7, rootReal) {
41277
+ function realInside(path8, rootReal) {
41262
41278
  try {
41263
- const real = realpathSync2.native(path7);
41279
+ const real = realpathSync2.native(path8);
41264
41280
  return real === rootReal || real.startsWith(rootReal + sep2) ? real : null;
41265
41281
  } catch {
41266
41282
  return null;
41267
41283
  }
41268
41284
  }
41269
- function isRegularFile(path7) {
41285
+ function isRegularFile(path8) {
41270
41286
  try {
41271
- return lstatSync2(path7).isFile();
41287
+ return lstatSync2(path8).isFile();
41272
41288
  } catch {
41273
41289
  return false;
41274
41290
  }
41275
41291
  }
41276
- function isDirectory(path7) {
41292
+ function isDirectory(path8) {
41277
41293
  try {
41278
- return lstatSync2(path7).isDirectory();
41294
+ return lstatSync2(path8).isDirectory();
41279
41295
  } catch {
41280
41296
  return false;
41281
41297
  }
41282
41298
  }
41283
41299
  function boundedEntries(dir, limit) {
41284
41300
  try {
41285
- const entries = readdirSync(dir);
41286
- return entries.length > limit ? null : entries.sort();
41301
+ const entries2 = readdirSync(dir);
41302
+ return entries2.length > limit ? null : entries2.sort();
41287
41303
  } catch {
41288
41304
  return null;
41289
41305
  }
@@ -41301,19 +41317,19 @@ function resolveAccountDir(containerDir, accountIdentifier) {
41301
41317
  const dir = realInside(join6(accountsReal, account), accountsReal);
41302
41318
  if (dir && isDirectory(dir)) return dir;
41303
41319
  }
41304
- const entries = (boundedEntries(accountsReal, 64) ?? []).filter(
41320
+ const entries2 = (boundedEntries(accountsReal, 64) ?? []).filter(
41305
41321
  (e) => isDirectory(join6(accountsReal, e))
41306
41322
  );
41307
- if (entries.length !== 1) return null;
41308
- return realInside(join6(accountsReal, entries[0]), accountsReal);
41323
+ if (entries2.length !== 1) return null;
41324
+ return realInside(join6(accountsReal, entries2[0]), accountsReal);
41309
41325
  }
41310
41326
  function generationRank(name) {
41311
41327
  const m = /^(\d+)_/.exec(name);
41312
41328
  return m ? Number(m[1]) : 0;
41313
41329
  }
41314
41330
  function generationDirs(base, accountDir) {
41315
- const entries = boundedEntries(base, MAX_GENERATION_DIRS) ?? [];
41316
- return entries.map((e) => realInside(join6(base, e), accountDir)).filter((p) => p !== null && isDirectory(p)).sort((a, b) => generationRank(basename(b)) - generationRank(basename(a)));
41331
+ const entries2 = boundedEntries(base, MAX_GENERATION_DIRS) ?? [];
41332
+ return entries2.map((e) => realInside(join6(base, e), accountDir)).filter((p) => p !== null && isDirectory(p)).sort((a, b) => generationRank(basename(b)) - generationRank(basename(a)));
41317
41333
  }
41318
41334
  function fallbackFiles(accountDir, rootName, identifier, generation, names) {
41319
41335
  const base = join6(accountDir, rootName, identifier);
@@ -41358,11 +41374,11 @@ function previewFileInBundle(bundle, accountDir) {
41358
41374
  function listPreviewEntries(accountDir) {
41359
41375
  return boundedEntries(join6(accountDir, "Previews"), MAX_PREVIEW_DIR_ENTRIES) ?? [];
41360
41376
  }
41361
- function previewPaths(accountDir, identifier, entries) {
41377
+ function previewPaths(accountDir, identifier, entries2) {
41362
41378
  const id2 = safeComponent(identifier);
41363
41379
  if (!id2) return [];
41364
41380
  const prefix = `${id2}-`.toLowerCase();
41365
- const candidates = entries.filter((name) => name.toLowerCase().startsWith(prefix)).filter((name) => {
41381
+ const candidates = entries2.filter((name) => name.toLowerCase().startsWith(prefix)).filter((name) => {
41366
41382
  const ext = extname(name).toLowerCase();
41367
41383
  return !ext || PREVIEW_IMAGE_SUFFIXES.has(ext) || /^\.\d+$/.test(ext);
41368
41384
  }).sort((a, b) => previewPixelArea(b) - previewPixelArea(a) || a.localeCompare(b));
@@ -41611,11 +41627,348 @@ function exportAttachmentAssets(assets, exportDir, options = {}) {
41611
41627
  return { exportDir: dir, results };
41612
41628
  }
41613
41629
 
41630
+ // src/utils/paperAttachments.ts
41631
+ var MAX_AXIS = 32768;
41632
+ var MAX_PREVIEW_DIR_ENTRIES2 = 1e5;
41633
+ var MAX_DIR_ENTRIES = 64;
41634
+ var HEADER_BYTES = 64 * 1024;
41635
+ var PNG_MAGIC = Buffer.from([137, 80, 78, 71, 13, 10, 26, 10]);
41636
+ var IMAGE_SUFFIXES = /* @__PURE__ */ new Set([".png", ".jpg", ".jpeg"]);
41637
+ var axisOk = (n) => Number.isInteger(n) && n > 0 && n <= MAX_AXIS;
41638
+ function parseImageHeader(buf) {
41639
+ if (buf.length >= 24 && buf.subarray(0, 8).equals(PNG_MAGIC)) {
41640
+ if (buf.readUInt32BE(8) !== 13 || buf.toString("latin1", 12, 16) !== "IHDR") return null;
41641
+ const width = buf.readUInt32BE(16);
41642
+ const height = buf.readUInt32BE(20);
41643
+ return axisOk(width) && axisOk(height) ? { format: "png", width, height } : null;
41644
+ }
41645
+ if (buf.length >= 4 && buf[0] === 255 && buf[1] === 216 && buf[2] === 255) {
41646
+ let offset = 2;
41647
+ while (offset + 4 <= buf.length) {
41648
+ if (buf[offset] !== 255) return null;
41649
+ const marker = buf[offset + 1];
41650
+ if (marker === 255) {
41651
+ offset++;
41652
+ continue;
41653
+ }
41654
+ const length = buf.readUInt16BE(offset + 2);
41655
+ if (length < 2) return null;
41656
+ const isFrame = marker >= 192 && marker <= 207 && marker !== 196 && marker !== 200 && marker !== 204;
41657
+ if (isFrame) {
41658
+ if (offset + 9 > buf.length) return null;
41659
+ const height = buf.readUInt16BE(offset + 5);
41660
+ const width = buf.readUInt16BE(offset + 7);
41661
+ return axisOk(width) && axisOk(height) ? { format: "jpeg", width, height } : null;
41662
+ }
41663
+ offset += 2 + length;
41664
+ }
41665
+ }
41666
+ return null;
41667
+ }
41668
+ function readImageInfoFd(fd) {
41669
+ if (!fstatSync3(fd).isFile()) return null;
41670
+ const buf = Buffer.alloc(HEADER_BYTES);
41671
+ const read = readSync2(fd, buf, 0, buf.length, 0);
41672
+ return parseImageHeader(buf.subarray(0, read));
41673
+ }
41674
+ function readImageInfo(path8) {
41675
+ let fd;
41676
+ try {
41677
+ fd = openSync3(path8, constants3.O_RDONLY | constants3.O_NOFOLLOW);
41678
+ } catch {
41679
+ return null;
41680
+ }
41681
+ try {
41682
+ return readImageInfoFd(fd);
41683
+ } finally {
41684
+ closeSync3(fd);
41685
+ }
41686
+ }
41687
+ function buildDrawingRowsSql(notePk, columns) {
41688
+ if (!Number.isSafeInteger(notePk) || notePk < 0) throw new Error("Invalid note primary key");
41689
+ const col3 = (name) => columns.has(name) ? `a.${name}` : "NULL";
41690
+ const accountCols = [...columns].filter((c) => /^ZACCOUNT\d*$/.test(c)).sort();
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
+ ...accountCols.map((c) => `a.${c}`),
41693
+ ...accountCols.map((c) => `n.${c}`)
41694
+ ].join(", ")}) LIMIT 1)` : "NULL";
41695
+ const deleted = columns.has("ZMARKEDFORDELETION") ? " AND COALESCE(a.ZMARKEDFORDELETION, 0) = 0" : "";
41696
+ const fields = [
41697
+ `'pk', a.Z_PK`,
41698
+ `'identifier', a.ZIDENTIFIER`,
41699
+ `'uti', a.ZTYPEUTI`,
41700
+ `'handwritingSummary', ${col3("ZHANDWRITINGSUMMARY")}`,
41701
+ `'fallbackImageGeneration', ${col3("ZFALLBACKIMAGEGENERATION")}`,
41702
+ `'accountIdentifier', ${account}`
41703
+ ].join(", ");
41704
+ return [
41705
+ "BEGIN;",
41706
+ `SELECT count(*) FROM ZICCLOUDSYNCINGOBJECT WHERE Z_PK = ${notePk} AND Z_ENT = (SELECT Z_ENT FROM Z_PRIMARYKEY WHERE Z_NAME = 'ICNote');`,
41707
+ `SELECT json_group_array(json_object(${fields})) FROM ZICCLOUDSYNCINGOBJECT a LEFT JOIN ZICCLOUDSYNCINGOBJECT n ON n.Z_PK = a.ZNOTE WHERE a.Z_ENT = (SELECT Z_ENT FROM Z_PRIMARYKEY WHERE Z_NAME = 'ICAttachment') AND a.ZNOTE = ${notePk} AND (a.ZTYPEUTI = 'com.apple.paper' OR a.ZTYPEUTI = 'com.apple.drawing' OR a.ZTYPEUTI LIKE 'com.apple.drawing.%')${deleted};`,
41708
+ "COMMIT;"
41709
+ ].join(" ");
41710
+ }
41711
+ function runSqlite4(dbPath2, sql) {
41712
+ try {
41713
+ return execFileSync7("/usr/bin/sqlite3", ["-readonly", dbPath2, sql], {
41714
+ encoding: "utf8",
41715
+ timeout: 1e4,
41716
+ maxBuffer: 16 * 1024 * 1024,
41717
+ stdio: ["pipe", "pipe", "pipe"]
41718
+ });
41719
+ } catch (error2) {
41720
+ const message = error2 instanceof Error ? error2.message : String(error2);
41721
+ if (/authorization denied|unable to open database/i.test(message)) {
41722
+ throw new AttachmentStoreError(
41723
+ "Full Disk Access is required to read drawing attachments. Grant it to the app that launches this server, then relaunch it (run the doctor tool to verify).",
41724
+ "no_fda"
41725
+ );
41726
+ }
41727
+ throw new AttachmentStoreError(`Failed to read drawing attachments: ${message}`, "query_error");
41728
+ }
41729
+ }
41730
+ var str = (v) => typeof v === "string" && v.length > 0 ? v : null;
41731
+ function parseDrawingRows(json2) {
41732
+ const raw = JSON.parse(json2 || "[]");
41733
+ if (!Array.isArray(raw)) throw new Error("Invalid drawing rows");
41734
+ const rows = [];
41735
+ for (const item of raw) {
41736
+ if (!item || typeof item !== "object") continue;
41737
+ const r = item;
41738
+ const identifier = str(r.identifier);
41739
+ const uti = str(r.uti);
41740
+ if (!Number.isSafeInteger(r.pk) || !identifier || !uti) continue;
41741
+ const summary = str(r.handwritingSummary);
41742
+ rows.push({
41743
+ pk: r.pk,
41744
+ identifier,
41745
+ uti,
41746
+ handwritingSummary: summary && summary.trim() ? summary : null,
41747
+ fallbackImageGeneration: str(r.fallbackImageGeneration),
41748
+ accountIdentifier: str(r.accountIdentifier)
41749
+ });
41750
+ }
41751
+ return rows.sort((a, b) => a.pk - b.pk);
41752
+ }
41753
+ function readDrawingRows(noteId3, dbPath2 = join7(NOTES_CONTAINER_DIR, "NoteStore.sqlite")) {
41754
+ const { pk } = parseNoteId2(noteId3);
41755
+ const columns = new Set(
41756
+ runSqlite4(
41757
+ dbPath2,
41758
+ "SELECT group_concat(name, ',') FROM pragma_table_info('ZICCLOUDSYNCINGOBJECT');"
41759
+ ).trim().split(",").filter(Boolean)
41760
+ );
41761
+ if (!columns.has("ZIDENTIFIER") || !columns.has("ZTYPEUTI") || !columns.has("ZNOTE")) {
41762
+ throw new AttachmentStoreError("Unsupported Notes database schema", "query_error");
41763
+ }
41764
+ const lines = runSqlite4(dbPath2, buildDrawingRowsSql(pk, columns)).split("\n");
41765
+ if (lines[0]?.trim() !== "1") {
41766
+ throw new AttachmentStoreError(
41767
+ `No note found in the database for ID "${noteId3}".`,
41768
+ "not_found"
41769
+ );
41770
+ }
41771
+ try {
41772
+ return parseDrawingRows(lines[1] ?? "[]");
41773
+ } catch {
41774
+ throw new AttachmentStoreError("Drawing rows could not be parsed", "query_error");
41775
+ }
41776
+ }
41777
+ function kindOf(path8) {
41778
+ try {
41779
+ const st = lstatSync3(path8);
41780
+ return st.isFile() ? "file" : st.isDirectory() ? "dir" : null;
41781
+ } catch {
41782
+ return null;
41783
+ }
41784
+ }
41785
+ function entries(dir, limit) {
41786
+ try {
41787
+ const list = readdirSync2(dir);
41788
+ return list.length > limit ? [] : list.sort();
41789
+ } catch {
41790
+ return [];
41791
+ }
41792
+ }
41793
+ var byGenerationDesc = (a, b) => generationRank(basename2(b)) - generationRank(basename2(a));
41794
+ function findFallbackImage(accountDir, identifier, generation) {
41795
+ const id2 = safeComponent(identifier);
41796
+ if (!id2) return null;
41797
+ const base = join7(accountDir, "FallbackImages", id2);
41798
+ const names = ["FallbackImage.png", "FallbackImage.jpg"];
41799
+ const candidates = [];
41800
+ const gen = safeComponent(generation);
41801
+ if (gen) for (const n of names) candidates.push(join7(base, gen, n));
41802
+ const gens = entries(base, MAX_DIR_ENTRIES).map((e) => join7(base, e)).sort(byGenerationDesc);
41803
+ for (const g of gens) for (const n of names) candidates.push(join7(g, n));
41804
+ for (const n of names) candidates.push(join7(base, n));
41805
+ candidates.push(join7(accountDir, "FallbackImages", `${id2}.png`));
41806
+ candidates.push(join7(accountDir, "FallbackImages", `${id2}.jpg`));
41807
+ for (const c of candidates) {
41808
+ const real = realInside(c, accountDir);
41809
+ if (real && kindOf(real) === "file") return real;
41810
+ }
41811
+ return null;
41812
+ }
41813
+ function findLargestPreview(accountDir, identifier) {
41814
+ const id2 = safeComponent(identifier);
41815
+ if (!id2) return null;
41816
+ const dir = join7(accountDir, "Previews");
41817
+ const prefix = `${id2}-`.toLowerCase();
41818
+ const names = entries(dir, MAX_PREVIEW_DIR_ENTRIES2).filter((n) => n.toLowerCase().startsWith(prefix)).filter((n) => {
41819
+ const ext = extname2(n).toLowerCase();
41820
+ return !ext || IMAGE_SUFFIXES.has(ext) || /^\.\d+$/.test(ext);
41821
+ }).sort((a, b) => previewPixelArea(b) - previewPixelArea(a) || a.localeCompare(b));
41822
+ for (const name of names) {
41823
+ const real = realInside(join7(dir, name), accountDir);
41824
+ if (!real) continue;
41825
+ const kind = kindOf(real);
41826
+ if (kind === "file") return real;
41827
+ if (kind !== "dir") continue;
41828
+ const gens = entries(real, MAX_DIR_ENTRIES).map((e) => realInside(join7(real, e), accountDir)).filter((p) => p !== null && kindOf(p) === "dir").sort(byGenerationDesc);
41829
+ for (const g of [...gens, real]) {
41830
+ const file = realInside(join7(g, "Preview.png"), accountDir);
41831
+ if (file && kindOf(file) === "file") return file;
41832
+ }
41833
+ }
41834
+ return null;
41835
+ }
41836
+ function describeDrawings(rows, containerDir = NOTES_CONTAINER_DIR) {
41837
+ return rows.map((row) => {
41838
+ const accountDir = resolveAccountDir(containerDir, row.accountIdentifier);
41839
+ const kind = row.uti === "com.apple.paper" ? "paper" : "drawing";
41840
+ const id2 = safeComponent(row.identifier);
41841
+ const fallbackImagePath = accountDir ? findFallbackImage(accountDir, row.identifier, row.fallbackImageGeneration) : null;
41842
+ const previewPath = accountDir ? findLargestPreview(accountDir, row.identifier) : null;
41843
+ const bundle = accountDir && id2 && kind === "paper" ? realInside(join7(accountDir, "Paper", "Bundles", `${id2}.bundle`), accountDir) : null;
41844
+ let raster = null;
41845
+ for (const [path8, source] of [
41846
+ [fallbackImagePath, "fallback"],
41847
+ [previewPath, "preview"]
41848
+ ]) {
41849
+ const info = path8 ? readImageInfo(path8) : null;
41850
+ if (path8 && info) {
41851
+ raster = { path: path8, source, ...info };
41852
+ break;
41853
+ }
41854
+ }
41855
+ return {
41856
+ pk: row.pk,
41857
+ identifier: row.identifier,
41858
+ uti: row.uti,
41859
+ kind,
41860
+ handwritingSummary: row.handwritingSummary,
41861
+ bundlePresent: bundle !== null && kindOf(bundle) === "dir",
41862
+ fallbackImagePath,
41863
+ previewPath,
41864
+ raster
41865
+ };
41866
+ });
41867
+ }
41868
+ function verifyWrittenImage(fd, path8, expected) {
41869
+ const check2 = readImageInfoFd(fd);
41870
+ if (!check2 || check2.format !== expected.format || check2.width !== expected.width || check2.height !== expected.height) {
41871
+ unlinkSync2(path8);
41872
+ throw new Error("The exported image failed validation and was removed.");
41873
+ }
41874
+ return check2;
41875
+ }
41876
+ function selectDrawing(drawings, noteId3, attachmentId) {
41877
+ if (attachmentId) {
41878
+ const wanted = attachmentId.toLowerCase();
41879
+ const found = drawings.find(
41880
+ (d) => d.identifier.toLowerCase() === wanted || attachmentCoreDataId(noteId3, d.pk).toLowerCase() === wanted
41881
+ );
41882
+ if (!found) throw new Error(`No Paper or drawing attachment "${attachmentId}" in this note.`);
41883
+ return found;
41884
+ }
41885
+ if (drawings.length === 0) throw new Error("This note has no Paper or drawing attachment.");
41886
+ if (drawings.length > 1) {
41887
+ throw new Error(
41888
+ `This note has ${drawings.length} Paper or drawing attachments; pass attachmentId (from list-paper-attachments) to choose one.`
41889
+ );
41890
+ }
41891
+ return drawings[0];
41892
+ }
41893
+ function exportDrawingRaster(drawing, savePath, containerDir = NOTES_CONTAINER_DIR) {
41894
+ if (!drawing.raster) {
41895
+ throw new Error(
41896
+ "Notes has no rendered image for this drawing on disk yet (open the note in Notes.app to let it render, then retry)."
41897
+ );
41898
+ }
41899
+ const abs = assertSafeSavePath(savePath);
41900
+ if (isInsideNotesContainer(abs, containerDir)) {
41901
+ throw new Error(`Refusing to write inside the Notes data container: "${abs}"`);
41902
+ }
41903
+ const ext = extname2(abs).toLowerCase();
41904
+ const expected = drawing.raster.format === "png" ? [".png"] : [".jpg", ".jpeg"];
41905
+ if (!expected.includes(ext)) {
41906
+ throw new Error(
41907
+ `The rendered image is ${drawing.raster.format.toUpperCase()}; savePath must end in ${expected.join(" or ")}.`
41908
+ );
41909
+ }
41910
+ mkdirSync3(dirname3(abs), { recursive: true });
41911
+ assertSafeSavePath(abs);
41912
+ if (isInsideNotesContainer(abs, containerDir)) {
41913
+ throw new Error(`Refusing to write inside the Notes data container: "${abs}"`);
41914
+ }
41915
+ const input = openSync3(drawing.raster.path, constants3.O_RDONLY | constants3.O_NOFOLLOW);
41916
+ let bytes = 0;
41917
+ try {
41918
+ if (!fstatSync3(input).isFile()) throw new Error("The rendered image is not a regular file");
41919
+ const header = Buffer.alloc(HEADER_BYTES);
41920
+ const headerLength = readSync2(input, header, 0, header.length, 0);
41921
+ const info = parseImageHeader(header.subarray(0, headerLength));
41922
+ if (!info || info.format !== drawing.raster.format) {
41923
+ throw new Error(
41924
+ "The rendered image changed or is not a valid PNG/JPEG; nothing was written."
41925
+ );
41926
+ }
41927
+ let output;
41928
+ try {
41929
+ output = openSync3(
41930
+ abs,
41931
+ constants3.O_RDWR | constants3.O_CREAT | constants3.O_EXCL | constants3.O_NOFOLLOW,
41932
+ 384
41933
+ );
41934
+ } catch (error2) {
41935
+ if (error2.code === "EEXIST") {
41936
+ throw new Error(`"${abs}" already exists; choose a new savePath.`);
41937
+ }
41938
+ throw error2;
41939
+ }
41940
+ try {
41941
+ const buffer = Buffer.allocUnsafe(1024 * 1024);
41942
+ let position = 0;
41943
+ for (; ; ) {
41944
+ const read = readSync2(input, buffer, 0, buffer.length, position);
41945
+ if (read === 0) break;
41946
+ position += read;
41947
+ let written = 0;
41948
+ while (written < read) written += writeSync2(output, buffer, written, read - written);
41949
+ }
41950
+ bytes = position;
41951
+ const check2 = verifyWrittenImage(output, abs, info);
41952
+ return { savedPath: abs, bytes, source: drawing.raster.source, ...check2 };
41953
+ } catch (error2) {
41954
+ try {
41955
+ unlinkSync2(abs);
41956
+ } catch {
41957
+ }
41958
+ throw error2;
41959
+ } finally {
41960
+ closeSync3(output);
41961
+ }
41962
+ } finally {
41963
+ closeSync3(input);
41964
+ }
41965
+ }
41966
+
41614
41967
  // src/services/appleNotesManager.ts
41615
41968
  var import_turndown = __toESM(require_turndown_cjs(), 1);
41616
41969
  import { existsSync as existsSync4 } from "fs";
41617
41970
  import { homedir as homedir7 } from "os";
41618
- import { join as join7 } from "path";
41971
+ import { join as join8 } from "path";
41619
41972
  var FIELD_SEP = "";
41620
41973
  var RECORD_SEP = "";
41621
41974
  var AS_FIELD_SEP = "(character id 31)";
@@ -41843,7 +42196,7 @@ function getNoteLinkFromDB(coreDataId2) {
41843
42196
  const match = coreDataId2.match(/\/p(\d+)$/);
41844
42197
  if (!match) return null;
41845
42198
  const pk = parseInt(match[1], 10);
41846
- const dbPath2 = join7(homedir7(), "Library/Group Containers/group.com.apple.notes/NoteStore.sqlite");
42199
+ const dbPath2 = join8(homedir7(), "Library/Group Containers/group.com.apple.notes/NoteStore.sqlite");
41847
42200
  if (!existsSync4(dbPath2)) return null;
41848
42201
  try {
41849
42202
  const { DatabaseSync } = __require("node:sqlite");
@@ -42840,7 +43193,7 @@ var AppleNotesManager = class {
42840
43193
  return [];
42841
43194
  }
42842
43195
  const recordSeparator = result.output.includes(RECORD_SEP) ? RECORD_SEP : "\n";
42843
- const entries = result.output.split(recordSeparator).map((line) => {
43196
+ const entries2 = result.output.split(recordSeparator).map((line) => {
42844
43197
  const parts = line.includes(FIELD_SEP) ? line.split(FIELD_SEP) : line.split(" ");
42845
43198
  return {
42846
43199
  id: (parts[0] || "").trim(),
@@ -42853,7 +43206,7 @@ var AppleNotesManager = class {
42853
43206
  account: (parts[4] || "").trim()
42854
43207
  };
42855
43208
  });
42856
- const byId = new Map(entries.map((e) => [e.id, e]));
43209
+ const byId = new Map(entries2.map((e) => [e.id, e]));
42857
43210
  const buildPath = (entry) => {
42858
43211
  const safeName = escapeFolderName(entry.name);
42859
43212
  if (!entry.parentId) return safeName;
@@ -42863,7 +43216,7 @@ var AppleNotesManager = class {
42863
43216
  }
42864
43217
  return safeName;
42865
43218
  };
42866
- return entries.map((entry) => ({
43219
+ return entries2.map((entry) => ({
42867
43220
  id: entry.id,
42868
43221
  name: buildPath(entry),
42869
43222
  account: entry.account || targetAccount || "",
@@ -43765,6 +44118,24 @@ var AppleNotesManager = class {
43765
44118
  cleanupTempDir(dir);
43766
44119
  }
43767
44120
  }
44121
+ /**
44122
+ * Lists a note's Paper (`com.apple.paper`) and classic drawing attachments
44123
+ * with Notes' rendered raster, read-only from NoteStore and the Notes group
44124
+ * container. Requires Full Disk Access.
44125
+ *
44126
+ * @throws PaperStoreError (`no_fda`, `invalid_id`, `not_found`, `query_error`)
44127
+ */
44128
+ listPaperAttachmentsById(noteId3) {
44129
+ return describeDrawings(readDrawingRows(noteId3));
44130
+ }
44131
+ /**
44132
+ * Copies Notes' rendered raster of one drawing to a new file. `attachmentId`
44133
+ * (identifier or AppleScript id) is required when the note has more than one.
44134
+ */
44135
+ exportPaperImageById(noteId3, savePath, attachmentId) {
44136
+ const drawing = selectDrawing(this.listPaperAttachmentsById(noteId3), noteId3, attachmentId);
44137
+ return { drawing, ...exportDrawingRaster(drawing, savePath) };
44138
+ }
43768
44139
  /**
43769
44140
  * Reads one note's attachments with their on-disk asset and preview paths,
43770
44141
  * in body order, from the NoteStore database and the Notes group container
@@ -44209,7 +44580,7 @@ var AppleNotesManager = class {
44209
44580
  };
44210
44581
 
44211
44582
  // src/utils/syncDetection.ts
44212
- import { execFileSync as execFileSync7 } from "child_process";
44583
+ import { execFileSync as execFileSync8 } from "child_process";
44213
44584
  import * as fs3 from "fs";
44214
44585
  import * as path3 from "path";
44215
44586
  import * as os3 from "os";
@@ -44254,7 +44625,7 @@ function getSyncStatus(useCache = true) {
44254
44625
  WHERE object.ZCLOUDSTATE = state.Z_PK
44255
44626
  );
44256
44627
  `;
44257
- const result = execFileSync7(
44628
+ const result = execFileSync8(
44258
44629
  "sqlite3",
44259
44630
  ["-readonly", NOTES_DB_PATH4, query.replace(/\n/g, " ")],
44260
44631
  {
@@ -44313,7 +44684,7 @@ function withSyncAwarenessSync(operation, fn) {
44313
44684
  }
44314
44685
 
44315
44686
  // src/utils/noteMetadata.ts
44316
- import { execFileSync as execFileSync8 } from "child_process";
44687
+ import { execFileSync as execFileSync9 } from "child_process";
44317
44688
  import * as fs4 from "fs";
44318
44689
  import * as path4 from "path";
44319
44690
  import * as os4 from "os";
@@ -44333,15 +44704,15 @@ var COLUMN_MAP = [
44333
44704
  { key: "widgetSnippet", column: "ZWIDGETSNIPPET", type: "text" },
44334
44705
  { key: "smartFolderQuery", column: "ZSMARTFOLDERQUERYJSON", type: "text" }
44335
44706
  ];
44336
- function runSqlite4(query) {
44337
- return execFileSync8("sqlite3", ["-readonly", NOTES_DB_PATH5, query], {
44707
+ function runSqlite5(query) {
44708
+ return execFileSync9("sqlite3", ["-readonly", NOTES_DB_PATH5, query], {
44338
44709
  encoding: "utf8",
44339
44710
  timeout: 5e3,
44340
44711
  stdio: ["pipe", "pipe", "pipe"]
44341
44712
  }).trim();
44342
44713
  }
44343
44714
  function presentColumns() {
44344
- const out = runSqlite4("PRAGMA table_info(ZICCLOUDSYNCINGOBJECT);");
44715
+ const out = runSqlite5("PRAGMA table_info(ZICCLOUDSYNCINGOBJECT);");
44345
44716
  const cols = /* @__PURE__ */ new Set();
44346
44717
  for (const line of out.split("\n")) {
44347
44718
  const name = line.split("|")[1];
@@ -44369,7 +44740,7 @@ function getNoteMetadata(noteId3) {
44369
44740
  return { metadata: {} };
44370
44741
  }
44371
44742
  const pairs = selected.map((c) => `'${c.key}', ${c.column}`).join(", ");
44372
- const row = runSqlite4(
44743
+ const row = runSqlite5(
44373
44744
  `SELECT json_object(${pairs}) FROM ZICCLOUDSYNCINGOBJECT WHERE Z_PK = ${pk};`
44374
44745
  );
44375
44746
  if (!row) {
@@ -44401,8 +44772,11 @@ function getNoteMetadata(noteId3) {
44401
44772
  }
44402
44773
  }
44403
44774
 
44404
- // src/utils/noteIdentifiers.ts
44405
- import { execFileSync as execFileSync9 } from "child_process";
44775
+ // src/utils/noteListings.ts
44776
+ import { gunzipSync as gunzipSync6 } from "zlib";
44777
+
44778
+ // src/utils/noteStoreSql.ts
44779
+ import { execFileSync as execFileSync10 } from "child_process";
44406
44780
  import * as fs5 from "fs";
44407
44781
  import * as os5 from "os";
44408
44782
  import * as path5 from "path";
@@ -44410,6 +44784,407 @@ var NOTES_DB_PATH6 = path5.join(
44410
44784
  os5.homedir(),
44411
44785
  "Library/Group Containers/group.com.apple.notes/NoteStore.sqlite"
44412
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 = (text) => text.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 = (text, weight) => {
45137
+ const key = text.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(text, (found.spellings.get(text) ?? 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(([text]) => text);
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
+ );
44413
45188
  var UUID_PATTERN = /^[0-9A-Fa-f]{8}(?:-[0-9A-Fa-f]{4}){3}-[0-9A-Fa-f]{12}$/;
44414
45189
  var NUMERIC_KEY_PATTERN = /^\d{1,18}$/;
44415
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";
@@ -44443,10 +45218,10 @@ function assertAll(values, pattern, label) {
44443
45218
  if (!pattern.test(value)) throw new Error(`Refusing to query with an invalid ${label}`);
44444
45219
  }
44445
45220
  }
44446
- function entityClause(entity2) {
44447
- 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}')`;
44448
45223
  }
44449
- function buildResolveSql(entity2, keys, uuids) {
45224
+ function buildResolveSql(entity3, keys, uuids) {
44450
45225
  assertAll(keys, NUMERIC_KEY_PATTERN, "numeric key");
44451
45226
  assertAll(uuids, UUID_PATTERN, "UUID");
44452
45227
  const matches = [];
@@ -44463,28 +45238,28 @@ function buildResolveSql(entity2, keys, uuids) {
44463
45238
  matches.push(`o.ZIDENTIFIER IN (${[...variants].map((v) => `'${v}'`).join(", ")})`);
44464
45239
  }
44465
45240
  const where = matches.length > 0 ? matches.join(" OR ") : "0";
44466
- 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})));`;
44467
45242
  }
44468
- function buildLookupSql(entity2, keys) {
45243
+ function buildLookupSql(entity3, keys) {
44469
45244
  assertAll(keys, NUMERIC_KEY_PATTERN, "numeric key");
44470
45245
  const pks = [...new Set(keys.map(canonicalKey))];
44471
45246
  const inList = pks.length > 0 ? pks.join(", ") : "NULL";
44472
45247
  let fields = "'pk', o.Z_PK, 'identifier', o.ZIDENTIFIER";
44473
45248
  let joins = "";
44474
- if (entity2 === "ICNote") {
45249
+ if (entity3 === "ICNote") {
44475
45250
  fields += ", 'folderIdentifier', f.ZIDENTIFIER, 'accountIdentifier', a.ZIDENTIFIER";
44476
45251
  joins = "LEFT JOIN ZICCLOUDSYNCINGOBJECT f ON f.Z_PK = o.ZFOLDER LEFT JOIN ZICCLOUDSYNCINGOBJECT a ON a.Z_PK = f.ZOWNER ";
44477
- } else if (entity2 === "ICFolder") {
45252
+ } else if (entity3 === "ICFolder") {
44478
45253
  fields += ", 'parentIdentifier', p.ZIDENTIFIER, 'accountIdentifier', a.ZIDENTIFIER";
44479
45254
  joins = "LEFT JOIN ZICCLOUDSYNCINGOBJECT p ON p.Z_PK = o.ZPARENT LEFT JOIN ZICCLOUDSYNCINGOBJECT a ON a.Z_PK = o.ZOWNER ";
44480
45255
  }
44481
- 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})));`;
44482
45257
  }
44483
45258
  function runJsonQuery(sql, dbPath2) {
44484
- 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);
44485
45260
  let out;
44486
45261
  try {
44487
- out = execFileSync9("sqlite3", ["-readonly", dbPath2, sql], {
45262
+ out = execFileSync11("sqlite3", ["-readonly", dbPath2, sql], {
44488
45263
  encoding: "utf8",
44489
45264
  timeout: 5e3,
44490
45265
  stdio: ["pipe", "pipe", "pipe"]
@@ -44501,10 +45276,10 @@ function runJsonQuery(sql, dbPath2) {
44501
45276
  const rows = typeof parsed.rows === "string" ? JSON.parse(parsed.rows) : parsed.rows;
44502
45277
  return { store: parsed.store ?? null, rows: rows ?? [] };
44503
45278
  }
44504
- function coreDataId(store, entity2, pk) {
44505
- return `x-coredata://${store}/${entity2}/p${pk}`;
45279
+ function coreDataId(store, entity3, pk) {
45280
+ return `x-coredata://${store}/${entity3}/p${pk}`;
44506
45281
  }
44507
- function resolveIdentifiers(values, entity2, dbPath2 = NOTES_DB_PATH6) {
45282
+ function resolveIdentifiers(values, entity3, dbPath2 = NOTES_DB_PATH7) {
44508
45283
  const resolved = /* @__PURE__ */ new Map();
44509
45284
  const keys = [];
44510
45285
  const uuids = [];
@@ -44516,7 +45291,7 @@ function resolveIdentifiers(values, entity2, dbPath2 = NOTES_DB_PATH6) {
44516
45291
  }
44517
45292
  if (keys.length === 0 && uuids.length === 0) return resolved;
44518
45293
  const { store, rows } = runJsonQuery(
44519
- buildResolveSql(entity2, keys, uuids),
45294
+ buildResolveSql(entity3, keys, uuids),
44520
45295
  dbPath2
44521
45296
  );
44522
45297
  if (!store) {
@@ -44529,16 +45304,16 @@ function resolveIdentifiers(values, entity2, dbPath2 = NOTES_DB_PATH6) {
44529
45304
  const byUuid = new Map(
44530
45305
  rows.filter((row) => row.identifier).map((row) => [String(row.identifier).toUpperCase(), row])
44531
45306
  );
44532
- const label = ENTITY_LABEL[entity2];
45307
+ const label = ENTITY_LABEL[entity3];
44533
45308
  const missing = [];
44534
45309
  for (const key of keys) {
44535
45310
  const row = byKey.get(canonicalKey(key));
44536
- if (row) resolved.set(key, coreDataId(store, entity2, row.pk));
45311
+ if (row) resolved.set(key, coreDataId(store, entity3, row.pk));
44537
45312
  else missing.push(`numeric key ${key}`);
44538
45313
  }
44539
45314
  for (const uuid2 of uuids) {
44540
45315
  const row = byUuid.get(uuid2.toUpperCase());
44541
- if (row) resolved.set(uuid2, coreDataId(store, entity2, row.pk));
45316
+ if (row) resolved.set(uuid2, coreDataId(store, entity3, row.pk));
44542
45317
  else missing.push(`identifier ${uuid2}`);
44543
45318
  }
44544
45319
  if (missing.length > 0) {
@@ -44550,12 +45325,12 @@ function resolveIdentifiers(values, entity2, dbPath2 = NOTES_DB_PATH6) {
44550
45325
  return resolved;
44551
45326
  }
44552
45327
  var COREDATA_PARTS = /^x-coredata:\/\/([0-9A-Fa-f-]+)\/(ICNote|ICFolder|ICAccount)\/p(\d{1,18})$/;
44553
- function lookupStableIdentifiers(ids, entity2, dbPath2 = NOTES_DB_PATH6) {
45328
+ function lookupStableIdentifiers(ids, entity3, dbPath2 = NOTES_DB_PATH7) {
44554
45329
  const result = /* @__PURE__ */ new Map();
44555
45330
  const wanted = /* @__PURE__ */ new Map();
44556
45331
  for (const id2 of ids) {
44557
45332
  const match = COREDATA_PARTS.exec(id2);
44558
- if (!match || match[2] !== entity2) continue;
45333
+ if (!match || match[2] !== entity3) continue;
44559
45334
  const pk = canonicalKey(match[3]);
44560
45335
  const list = wanted.get(pk) ?? [];
44561
45336
  list.push({ id: id2, store: match[1] });
@@ -44564,7 +45339,7 @@ function lookupStableIdentifiers(ids, entity2, dbPath2 = NOTES_DB_PATH6) {
44564
45339
  if (wanted.size === 0) return result;
44565
45340
  let query;
44566
45341
  try {
44567
- query = runJsonQuery(buildLookupSql(entity2, [...wanted.keys()]), dbPath2);
45342
+ query = runJsonQuery(buildLookupSql(entity3, [...wanted.keys()]), dbPath2);
44568
45343
  } catch {
44569
45344
  return result;
44570
45345
  }
@@ -44586,16 +45361,16 @@ function lookupStableIdentifiers(ids, entity2, dbPath2 = NOTES_DB_PATH6) {
44586
45361
  }
44587
45362
  return result;
44588
45363
  }
44589
- function withStableIdentifiers(items, entity2, dbPath2 = NOTES_DB_PATH6) {
45364
+ function withStableIdentifiers(items, entity3, dbPath2 = NOTES_DB_PATH7) {
44590
45365
  const ids = items.map((item) => item.id).filter((id2) => typeof id2 === "string");
44591
45366
  if (ids.length === 0) return items;
44592
- const found = lookupStableIdentifiers(ids, entity2, dbPath2);
45367
+ const found = lookupStableIdentifiers(ids, entity3, dbPath2);
44593
45368
  if (found.size === 0) return items;
44594
45369
  return items.map(
44595
45370
  (item) => item.id && found.has(item.id) ? { ...item, ...found.get(item.id) } : item
44596
45371
  );
44597
45372
  }
44598
- var defaultResolver = (values, entity2) => resolveIdentifiers(values, entity2);
45373
+ var defaultResolver = (values, entity3) => resolveIdentifiers(values, entity3);
44599
45374
  var DEFAULT_MAX_ID_LENGTH = 2e3;
44600
45375
  function acceptAlternateForms(pattern) {
44601
45376
  return new RegExp(
@@ -44603,10 +45378,10 @@ function acceptAlternateForms(pattern) {
44603
45378
  pattern.flags
44604
45379
  );
44605
45380
  }
44606
- function resolveInSchema(values, entity2, ctx, resolver) {
45381
+ function resolveInSchema(values, entity3, ctx, resolver) {
44607
45382
  if (!values.some(isAlternateIdentifier)) return new Map(values.map((v) => [v, v]));
44608
45383
  try {
44609
- return resolver(values, entity2);
45384
+ return resolver(values, entity3);
44610
45385
  } catch (error2) {
44611
45386
  ctx.addIssue({
44612
45387
  code: external_exports.ZodIssueCode.custom,
@@ -44615,26 +45390,26 @@ function resolveInSchema(values, entity2, ctx, resolver) {
44615
45390
  return null;
44616
45391
  }
44617
45392
  }
44618
- function exactIdInput(entity2, pattern, message, options = {}) {
45393
+ function exactIdInput(entity3, pattern, message, options = {}) {
44619
45394
  const resolver = options.resolver ?? defaultResolver;
44620
45395
  return external_exports.string().max(options.maxLength ?? DEFAULT_MAX_ID_LENGTH).regex(acceptAlternateForms(pattern), message).transform((value, ctx) => {
44621
- const map = resolveInSchema([value], entity2, ctx, resolver);
45396
+ const map = resolveInSchema([value], entity3, ctx, resolver);
44622
45397
  return map ? map.get(value) ?? value : external_exports.NEVER;
44623
45398
  });
44624
45399
  }
44625
- function exactIdArrayInput(entity2, pattern, message, options = {}) {
45400
+ function exactIdArrayInput(entity3, pattern, message, options = {}) {
44626
45401
  const resolver = options.resolver ?? defaultResolver;
44627
45402
  const item = external_exports.string().max(options.maxLength ?? DEFAULT_MAX_ID_LENGTH).regex(acceptAlternateForms(pattern), message);
44628
45403
  const array2 = options.maxItems === void 0 ? external_exports.array(item) : external_exports.array(item).max(options.maxItems);
44629
45404
  return array2.transform((values, ctx) => {
44630
- const map = resolveInSchema(values, entity2, ctx, resolver);
45405
+ const map = resolveInSchema(values, entity3, ctx, resolver);
44631
45406
  return map ? values.map((value) => map.get(value) ?? value) : external_exports.NEVER;
44632
45407
  });
44633
45408
  }
44634
- function looseIdTransform(entity2, resolver = defaultResolver) {
45409
+ function looseIdTransform(entity3, resolver = defaultResolver) {
44635
45410
  return (value, ctx) => {
44636
45411
  if (!isAlternateIdentifier(value)) return value;
44637
- const map = resolveInSchema([value], entity2, ctx, resolver);
45412
+ const map = resolveInSchema([value], entity3, ctx, resolver);
44638
45413
  return map ? map.get(value) ?? value : external_exports.NEVER;
44639
45414
  };
44640
45415
  }
@@ -45174,18 +45949,18 @@ function positiveTextTerms(node, negated = false) {
45174
45949
  }
45175
45950
 
45176
45951
  // src/utils/noteQueryStore.ts
45177
- import { execFileSync as execFileSync10 } from "child_process";
45178
- import * as fs6 from "fs";
45179
- import * as os6 from "os";
45180
- import * as path6 from "path";
45181
- import { gunzipSync as gunzipSync6 } from "zlib";
45182
- var NOTES_DB_PATH7 = path6.join(
45183
- 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(),
45184
45959
  "Library/Group Containers/group.com.apple.notes/NoteStore.sqlite"
45185
45960
  );
45186
45961
  var QUERY_SCAN = { DEFAULT: 500, MAX: 5e3 };
45187
45962
  var QUERY_RESULTS = { DEFAULT: 50, MAX: 500 };
45188
- var CORE_DATA_EPOCH_MS = Date.UTC(2001, 0, 1);
45963
+ var CORE_DATA_EPOCH_MS2 = Date.UTC(2001, 0, 1);
45189
45964
  var SNIPPET_BEFORE = 60;
45190
45965
  var SNIPPET_LENGTH = 180;
45191
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.`;
@@ -45268,10 +46043,10 @@ function countWords(text) {
45268
46043
  return count;
45269
46044
  }
45270
46045
  var REQUIRED_COLUMNS3 = ["Z_PK", "Z_ENT", "ZTITLE1", "ZFOLDER", "ZMODIFICATIONDATE1"];
45271
- function col(available, alias, name) {
46046
+ function col2(available, alias, name) {
45272
46047
  return available.has(name) ? `${alias}.${name}` : "NULL";
45273
46048
  }
45274
- 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}')`;
45275
46050
  function buildScanSql(available, options) {
45276
46051
  const missing = REQUIRED_COLUMNS3.filter((c) => !available.has(c));
45277
46052
  if (missing.length) {
@@ -45289,21 +46064,21 @@ function buildScanSql(available, options) {
45289
46064
  const bool = (name) => available.has(name) ? `COALESCE(n.${name}, 0)` : "0";
45290
46065
  const notNull = (alias, name) => available.has(name) ? `${alias}.${name} IS NOT NULL` : "0";
45291
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";
45292
- const where = [`n.Z_ENT = ${entity("ICNote")}`];
46067
+ const where = [`n.Z_ENT = ${entity2("ICNote")}`];
45293
46068
  if (!options.includeDeleted) {
45294
46069
  where.push("n.ZFOLDER IS NOT NULL");
45295
46070
  if (available.has("ZMARKEDFORDELETION")) where.push("COALESCE(n.ZMARKEDFORDELETION, 0) = 0");
45296
46071
  if (available.has("ZFOLDERTYPE")) {
45297
46072
  where.push(
45298
- `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)`
45299
46074
  );
45300
46075
  }
45301
46076
  }
45302
46077
  const whereSql = where.join(" AND ");
45303
- 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")};`;
45304
- 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")};`;
45305
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";
45306
- 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};`;
45307
46082
  return [
45308
46083
  "BEGIN;",
45309
46084
  "SELECT json_object('k', 'meta', 'uuid', (SELECT Z_UUID FROM Z_METADATA LIMIT 1));",
@@ -45314,8 +46089,8 @@ function buildScanSql(available, options) {
45314
46089
  "COMMIT;"
45315
46090
  ].join(" ");
45316
46091
  }
45317
- function runSqlite5(dbPath2, query) {
45318
- return execFileSync10("sqlite3", ["-readonly", dbPath2, query], {
46092
+ function runSqlite6(dbPath2, query) {
46093
+ return execFileSync12("sqlite3", ["-readonly", dbPath2, query], {
45319
46094
  encoding: "utf8",
45320
46095
  timeout: 3e4,
45321
46096
  maxBuffer: 512 * 1024 * 1024,
@@ -45324,7 +46099,7 @@ function runSqlite5(dbPath2, query) {
45324
46099
  }
45325
46100
  function presentColumns2(dbPath2) {
45326
46101
  const cols = /* @__PURE__ */ new Set();
45327
- for (const line of runSqlite5(dbPath2, "PRAGMA table_info(ZICCLOUDSYNCINGOBJECT);").split("\n")) {
46102
+ for (const line of runSqlite6(dbPath2, "PRAGMA table_info(ZICCLOUDSYNCINGOBJECT);").split("\n")) {
45328
46103
  const name = line.split("|")[1];
45329
46104
  if (name) cols.add(name);
45330
46105
  }
@@ -45342,12 +46117,12 @@ function resolveFolders(rows) {
45342
46117
  seen.add(pk);
45343
46118
  const parent = row.parent !== null ? resolve4(row.parent, seen) : void 0;
45344
46119
  const name = row.name ?? "";
45345
- const path7 = parent ? `${parent.path}/${escapeSegment(name)}` : escapeSegment(name);
46120
+ const path8 = parent ? `${parent.path}/${escapeSegment(name)}` : escapeSegment(name);
45346
46121
  const plainPath = parent ? `${parent.plainPath}/${name}` : name;
45347
46122
  const info = {
45348
- path: path7,
46123
+ path: path8,
45349
46124
  plainPath,
45350
- keys: [...new Set([name, plainPath, path7].map(normalizeForMatch))],
46125
+ keys: [...new Set([name, plainPath, path8].map(normalizeForMatch))],
45351
46126
  accountPk: row.owner ?? parent?.accountPk ?? null,
45352
46127
  shared: Boolean(row.shared) || Boolean(parent?.shared)
45353
46128
  };
@@ -45357,7 +46132,7 @@ function resolveFolders(rows) {
45357
46132
  for (const row of rows) resolve4(row.pk, /* @__PURE__ */ new Set());
45358
46133
  return resolved;
45359
46134
  }
45360
- var coreDataMs = (seconds) => seconds === null || !Number.isFinite(seconds) ? void 0 : CORE_DATA_EPOCH_MS + seconds * 1e3;
46135
+ var coreDataMs = (seconds) => seconds === null || !Number.isFinite(seconds) ? void 0 : CORE_DATA_EPOCH_MS2 + seconds * 1e3;
45361
46136
  function buildSnippet(text, terms) {
45362
46137
  const clean = text.replace(/\ufffc/gu, " ");
45363
46138
  const firstBreak = clean.indexOf("\n");
@@ -45379,12 +46154,12 @@ function queryNotes(expression, options = {}) {
45379
46154
  const includeDeleted = options.includeDeleted ?? false;
45380
46155
  const withBodies = needsContent(ast);
45381
46156
  const withTags = needsTags(ast);
45382
- const dbPath2 = options.dbPath ?? NOTES_DB_PATH7;
45383
- 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");
45384
46159
  let output;
45385
46160
  try {
45386
46161
  const available = presentColumns2(dbPath2);
45387
- output = runSqlite5(
46162
+ output = runSqlite6(
45388
46163
  dbPath2,
45389
46164
  buildScanSql(available, { scanLimit, includeDeleted, withBodies, withTags })
45390
46165
  );
@@ -45440,7 +46215,7 @@ function queryNotes(expression, options = {}) {
45440
46215
  try {
45441
46216
  decoded = decodeNoteBody(
45442
46217
  new Uint8Array(
45443
- gunzipSync6(Buffer.from(row.data, "hex"), { maxOutputLength: 32 * 1024 * 1024 })
46218
+ gunzipSync7(Buffer.from(row.data, "hex"), { maxOutputLength: 32 * 1024 * 1024 })
45444
46219
  )
45445
46220
  );
45446
46221
  } catch {
@@ -45515,10 +46290,10 @@ function queryNotes(expression, options = {}) {
45515
46290
  import { spawnSync } from "child_process";
45516
46291
 
45517
46292
  // src/services/nativeTags.ts
45518
- import { execFileSync as execFileSync11 } from "node:child_process";
46293
+ import { execFileSync as execFileSync13 } from "node:child_process";
45519
46294
  import { mkdtempSync as mkdtempSync2, writeFileSync, rmSync as rmSync2 } from "node:fs";
45520
46295
  import { tmpdir as tmpdir2 } from "node:os";
45521
- import { join as join12 } from "node:path";
46296
+ import { join as join14 } from "node:path";
45522
46297
 
45523
46298
  // src/services/shortcutConsent.ts
45524
46299
  function shortcutConsentHint(shortcut) {
@@ -45594,7 +46369,7 @@ function addNativeTags(request, deps) {
45594
46369
  };
45595
46370
  }
45596
46371
  function listInstalledShortcuts() {
45597
- return execFileSync11("/usr/bin/shortcuts", ["list", "--show-identifiers"], {
46372
+ return execFileSync13("/usr/bin/shortcuts", ["list", "--show-identifiers"], {
45598
46373
  encoding: "utf8",
45599
46374
  timeout: 15e3,
45600
46375
  maxBuffer: 1024 * 1024,
@@ -45620,11 +46395,11 @@ function runNativeTagsShortcut(input) {
45620
46395
  const status = nativeTagsStatus();
45621
46396
  if (!status.installed)
45622
46397
  throw new Error(`Import the supplied ${status.shortcut}.shortcut in Shortcuts first`);
45623
- const directory = mkdtempSync2(join12(tmpdir2(), "apple-notes-native-tags-"));
46398
+ const directory = mkdtempSync2(join14(tmpdir2(), "apple-notes-native-tags-"));
45624
46399
  try {
45625
- const path7 = join12(directory, "request.json");
45626
- writeFileSync(path7, JSON.stringify(input), { mode: 384 });
45627
- execFileSync11("/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], {
45628
46403
  encoding: "utf8",
45629
46404
  timeout: 6e4,
45630
46405
  maxBuffer: 1024 * 1024,
@@ -45643,10 +46418,10 @@ function runNativeTagsShortcut(input) {
45643
46418
  }
45644
46419
 
45645
46420
  // src/services/backgroundNotes.ts
45646
- import { execFileSync as execFileSync12 } from "node:child_process";
46421
+ import { execFileSync as execFileSync14 } from "node:child_process";
45647
46422
  import { mkdtempSync as mkdtempSync3, writeFileSync as writeFileSync2, rmSync as rmSync3 } from "node:fs";
45648
46423
  import { tmpdir as tmpdir3 } from "node:os";
45649
- import { join as join13 } from "node:path";
46424
+ import { join as join15 } from "node:path";
45650
46425
 
45651
46426
  // src/utils/appendMarkdown.ts
45652
46427
  var escape2 = (s) => s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
@@ -45971,9 +46746,9 @@ function runBackgroundShortcut(input, status = backgroundStatus()) {
45971
46746
  throw new Error(
45972
46747
  `Install the supplied "${status.shortcut}" Shortcut once; Shortcuts must list it exactly once`
45973
46748
  );
45974
- const directory = mkdtempSync3(join13(tmpdir3(), "apple-notes-background-"));
46749
+ const directory = mkdtempSync3(join15(tmpdir3(), "apple-notes-background-"));
45975
46750
  try {
45976
- const file = join13(directory, "request.json");
46751
+ const file = join15(directory, "request.json");
45977
46752
  writeFileSync2(
45978
46753
  file,
45979
46754
  JSON.stringify({
@@ -45993,7 +46768,7 @@ function runBackgroundShortcut(input, status = backgroundStatus()) {
45993
46768
  { mode: 384 }
45994
46769
  );
45995
46770
  try {
45996
- execFileSync12("/usr/bin/shortcuts", ["run", status.identifier, "--input-path", file], {
46771
+ execFileSync14("/usr/bin/shortcuts", ["run", status.identifier, "--input-path", file], {
45997
46772
  encoding: "utf8",
45998
46773
  timeout: callTimeoutMs() ?? 6e4,
45999
46774
  maxBuffer: 1024 * 1024,
@@ -46228,7 +47003,7 @@ function createMarkdownNote(manager, request, run = runBackgroundShortcut) {
46228
47003
  throw new Error(
46229
47004
  `Install the supplied "${status.shortcut}" Shortcut once; Shortcuts must list it exactly once`
46230
47005
  );
46231
- const segments = (path7) => JSON.stringify(splitFolderPath(path7).map((part) => part.toLocaleLowerCase()));
47006
+ const segments = (path8) => JSON.stringify(splitFolderPath(path8).map((part) => part.toLocaleLowerCase()));
46232
47007
  if (request.folder) {
46233
47008
  const wanted = segments(request.folder);
46234
47009
  if (!manager.listAccounts().some(
@@ -46318,7 +47093,7 @@ ${request.content}`
46318
47093
  }
46319
47094
 
46320
47095
  // src/services/capabilityMatrix.ts
46321
- import { execFileSync as execFileSync13 } from "node:child_process";
47096
+ import { execFileSync as execFileSync15 } from "node:child_process";
46322
47097
  import { release } from "node:os";
46323
47098
  var MACOS_SHORTCUTS_CLI = "12.0";
46324
47099
  var MACOS_MARKDOWN_IMPORT = "26.0";
@@ -46525,7 +47300,7 @@ function evaluateFeatures(env, features = FEATURES) {
46525
47300
  function readMacOSVersion() {
46526
47301
  if (process.platform !== "darwin") return null;
46527
47302
  try {
46528
- const out = execFileSync13("/usr/bin/sw_vers", ["-productVersion"], {
47303
+ const out = execFileSync15("/usr/bin/sw_vers", ["-productVersion"], {
46529
47304
  encoding: "utf8",
46530
47305
  timeout: 3e3,
46531
47306
  stdio: ["ignore", "pipe", "ignore"]
@@ -46558,9 +47333,9 @@ function getCapabilityMatrix(probe = probeCapabilityEnvironment) {
46558
47333
  return evaluateFeatures(probe());
46559
47334
  }
46560
47335
  function formatCapabilityMatrix(matrix) {
46561
- const os7 = matrix.runtimeOS;
47336
+ const os8 = matrix.runtimeOS;
46562
47337
  const lines = [
46563
- `Feature matrix (macOS ${os7.macOSVersion ?? "unknown"}, Darwin ${os7.darwinRelease}):`
47338
+ `Feature matrix (macOS ${os8.macOSVersion ?? "unknown"}, Darwin ${os8.darwinRelease}):`
46564
47339
  ];
46565
47340
  for (const [name, status] of Object.entries(matrix.features)) {
46566
47341
  lines.push(
@@ -46678,19 +47453,19 @@ function formatDoctorReport(r) {
46678
47453
  }
46679
47454
 
46680
47455
  // src/services/fileConfig.ts
46681
- import { existsSync as existsSync9, readFileSync as readFileSync2 } from "fs";
46682
- import { join as join14 } from "path";
46683
- 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";
46684
47459
  function fileConfigPath(env = process.env) {
46685
47460
  const override = env.APPLE_NOTES_MCP_CONFIG_FILE;
46686
47461
  if (override && override.trim()) return override.trim();
46687
- return join14(homedir12(), "Library", "Application Support", "apple-notes-mcp", "config.json");
47462
+ return join16(homedir13(), "Library", "Application Support", "apple-notes-mcp", "config.json");
46688
47463
  }
46689
- function loadFileConfig(env = process.env, path7 = fileConfigPath(env)) {
47464
+ function loadFileConfig(env = process.env, path8 = fileConfigPath(env)) {
46690
47465
  const applied = [];
46691
47466
  try {
46692
- if (!existsSync9(path7)) return applied;
46693
- const parsed = JSON.parse(readFileSync2(path7, "utf8"));
47467
+ if (!existsSync10(path8)) return applied;
47468
+ const parsed = JSON.parse(readFileSync2(path8, "utf8"));
46694
47469
  if (!parsed || typeof parsed !== "object") return applied;
46695
47470
  for (const [k, v] of Object.entries(parsed)) {
46696
47471
  if (typeof v !== "string") continue;
@@ -46700,7 +47475,7 @@ function loadFileConfig(env = process.env, path7 = fileConfigPath(env)) {
46700
47475
  }
46701
47476
  }
46702
47477
  } catch (e) {
46703
- 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)}`);
46704
47479
  }
46705
47480
  return applied;
46706
47481
  }
@@ -46987,11 +47762,11 @@ function createShutdown(stream, exit, timeoutMs = SHUTDOWN_DRAIN_TIMEOUT_MS) {
46987
47762
  }
46988
47763
 
46989
47764
  // src/utils/noteBlocks.ts
46990
- import { execFileSync as execFileSync14 } from "node:child_process";
46991
- import { existsSync as existsSync10 } from "node:fs";
46992
- import { homedir as homedir13 } from "node:os";
46993
- import { join as join15 } from "node:path";
46994
- 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";
46995
47770
  var NoteBlocksError = class extends Error {
46996
47771
  code;
46997
47772
  constructor(code, message) {
@@ -47279,7 +48054,7 @@ function summarize(blocks, attachments) {
47279
48054
  function decodeCompressedNoteBlocks(compressed) {
47280
48055
  let data;
47281
48056
  try {
47282
- data = gunzipSync7(compressed, { maxOutputLength: 32 * 1024 * 1024 });
48057
+ data = gunzipSync8(compressed, { maxOutputLength: 32 * 1024 * 1024 });
47283
48058
  } catch (error2) {
47284
48059
  throw new NoteBlocksError(
47285
48060
  "decompress-failed",
@@ -47333,23 +48108,23 @@ function pageNoteBlocks(doc, { offset = 0, limit = 500, maxBytes = blocksMaxResp
47333
48108
  undecodedFields: doc.undecodedFields
47334
48109
  };
47335
48110
  }
47336
- var NOTES_DB_PATH8 = join15(
47337
- homedir13(),
48111
+ var NOTES_DB_PATH9 = join17(
48112
+ homedir14(),
47338
48113
  "Library/Group Containers/group.com.apple.notes/NoteStore.sqlite"
47339
48114
  );
47340
- function readNoteBlocks(id2, { dbPath: dbPath2 = NOTES_DB_PATH8 } = {}) {
48115
+ function readNoteBlocks(id2, { dbPath: dbPath2 = NOTES_DB_PATH9 } = {}) {
47341
48116
  const pk = /^x-coredata:\/\/[0-9a-f-]+\/ICNote\/p([0-9]{1,18})$/i.exec(id2)?.[1];
47342
48117
  if (!pk)
47343
48118
  throw new NoteBlocksError(
47344
48119
  "invalid-id",
47345
48120
  `Invalid note ID: expected x-coredata://<store>/ICNote/p<number>`
47346
48121
  );
47347
- if (!existsSync10(dbPath2))
48122
+ if (!existsSync11(dbPath2))
47348
48123
  throw new NoteBlocksError("no-full-disk-access", "The Notes database is not readable");
47349
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));";
47350
48125
  let output;
47351
48126
  try {
47352
- output = execFileSync14(
48127
+ output = execFileSync16(
47353
48128
  "/usr/bin/sqlite3",
47354
48129
  ["-readonly", "-cmd", ".parameter init", "-cmd", `.parameter set @pk ${pk}`, dbPath2, sql],
47355
48130
  {
@@ -47500,17 +48275,17 @@ function insertLink(request, deps) {
47500
48275
  // src/tools/directOperations.ts
47501
48276
  import { createHash as createHash2 } from "node:crypto";
47502
48277
  import {
47503
- closeSync as closeSync3,
47504
- constants as constants3,
47505
- fstatSync as fstatSync3,
48278
+ closeSync as closeSync4,
48279
+ constants as constants4,
48280
+ fstatSync as fstatSync4,
47506
48281
  mkdtempSync as mkdtempSync4,
47507
- openSync as openSync3,
48282
+ openSync as openSync4,
47508
48283
  readFileSync as readFileSync3,
47509
48284
  rmSync as rmSync4,
47510
48285
  writeFileSync as writeFileSync3
47511
48286
  } from "node:fs";
47512
48287
  import { tmpdir as tmpdir4 } from "node:os";
47513
- import { basename as basename2, extname as extname2, isAbsolute as isAbsolute3, join as join16 } from "node:path";
48288
+ import { basename as basename3, extname as extname3, isAbsolute as isAbsolute3, join as join18 } from "node:path";
47514
48289
  var noteId = exactIdInput(
47515
48290
  "ICNote",
47516
48291
  /^x-coredata:\/\/[0-9a-f-]+\/ICNote\/p\d+$/i,
@@ -47553,11 +48328,11 @@ function assertExistingContentPreserved(before, after) {
47553
48328
  throw new Error("Existing native object content or presentation changed");
47554
48329
  }
47555
48330
  }
47556
- function localAttachment(path7) {
47557
- if (!isAbsolute3(path7)) throw new Error("An absolute local file path is required");
47558
- const descriptor = openSync3(path7, constants3.O_RDONLY | constants3.O_NOFOLLOW);
48331
+ function localAttachment(path8) {
48332
+ if (!isAbsolute3(path8)) throw new Error("An absolute local file path is required");
48333
+ const descriptor = openSync4(path8, constants4.O_RDONLY | constants4.O_NOFOLLOW);
47559
48334
  try {
47560
- const stat = fstatSync3(descriptor);
48335
+ const stat = fstatSync4(descriptor);
47561
48336
  if (!stat.isFile() || stat.size === 0 || stat.size > 64 * 1024 * 1024)
47562
48337
  throw new Error("Attachment must be a nonempty regular file of at most 64 MiB");
47563
48338
  const bytes = readFileSync3(descriptor);
@@ -47565,7 +48340,7 @@ function localAttachment(path7) {
47565
48340
  throw new Error("Attachment changed while it was being read; try again");
47566
48341
  return bytes;
47567
48342
  } finally {
47568
- closeSync3(descriptor);
48343
+ closeSync4(descriptor);
47569
48344
  }
47570
48345
  }
47571
48346
  function registerDirectOperations(server2, manager) {
@@ -47677,8 +48452,8 @@ function registerDirectOperations(server2, manager) {
47677
48452
  }
47678
48453
  );
47679
48454
  }
47680
- function attachmentName(path7, filename) {
47681
- const source = basename2(path7);
48455
+ function attachmentName(path8, filename) {
48456
+ const source = basename3(path8);
47682
48457
  if (filename === void 0) return source;
47683
48458
  if (Buffer.byteLength(filename, "utf8") > 255)
47684
48459
  throw new Error("filename must be at most 255 bytes");
@@ -47686,21 +48461,21 @@ function attachmentName(path7, filename) {
47686
48461
  throw new Error(
47687
48462
  "filename must be one path component with no slash, colon, backslash, control character, leading dot, or surrounding spaces"
47688
48463
  );
47689
- if (extname2(filename).toLowerCase() !== extname2(source).toLowerCase())
48464
+ if (extname3(filename).toLowerCase() !== extname3(source).toLowerCase())
47690
48465
  throw new Error(
47691
- `filename must keep the source file's extension (${extname2(source) || "none"})`
48466
+ `filename must keep the source file's extension (${extname3(source) || "none"})`
47692
48467
  );
47693
48468
  return filename;
47694
48469
  }
47695
48470
  function attachFile(manager, args) {
47696
- const { id: id2, expectedContentHash, path: path7 } = args;
47697
- const name = attachmentName(path7, args.filename);
48471
+ const { id: id2, expectedContentHash, path: path8 } = args;
48472
+ const name = attachmentName(path8, args.filename);
47698
48473
  const before = readSnapshot(manager, id2);
47699
48474
  if (before.hash !== expectedContentHash) throw new Error("Note revision changed");
47700
- const bytes = localAttachment(path7);
48475
+ const bytes = localAttachment(path8);
47701
48476
  const beforeAttachments = manager.listAttachmentsById(id2);
47702
- const directory = mkdtempSync4(join16(tmpdir4(), "notes-attachment-add-"));
47703
- const temporaryFile = join16(directory, name);
48477
+ const directory = mkdtempSync4(join18(tmpdir4(), "notes-attachment-add-"));
48478
+ const temporaryFile = join18(directory, name);
47704
48479
  try {
47705
48480
  writeFileSync3(temporaryFile, bytes, { mode: 384 });
47706
48481
  if (readSnapshot(manager, id2).hash !== before.hash) throw new Error("Note revision changed");
@@ -48258,9 +49033,9 @@ function registerNativeOperations(server2, manager) {
48258
49033
 
48259
49034
  // src/setupShortcuts.ts
48260
49035
  import { spawnSync as spawnSync2 } from "node:child_process";
48261
- import { existsSync as existsSync11 } from "node:fs";
49036
+ import { existsSync as existsSync12 } from "node:fs";
48262
49037
  import { release as release2 } from "node:os";
48263
- import { dirname as dirname3, resolve as resolve3 } from "node:path";
49038
+ import { dirname as dirname4, resolve as resolve3 } from "node:path";
48264
49039
  import { fileURLToPath } from "node:url";
48265
49040
  var OPTIONAL_BRIDGE_NOTE = "(optional \u2014 needed only for create-note format: markdown, macOS 26+)";
48266
49041
  var MARKDOWN_MIN_DARWIN_MAJOR = 25;
@@ -48278,16 +49053,16 @@ var shortcutFiles = [
48278
49053
  ];
48279
49054
  function setupShortcuts(checkOnly, dependencies = {}) {
48280
49055
  const status = dependencies.status || nativeTagsStatus;
48281
- const exists = dependencies.exists || existsSync11;
48282
- const open = dependencies.open || ((path7) => {
48283
- const result = spawnSync2("/usr/bin/open", [path7], { encoding: "utf8" });
49056
+ const exists = dependencies.exists || existsSync12;
49057
+ const open = dependencies.open || ((path8) => {
49058
+ const result = spawnSync2("/usr/bin/open", [path8], { encoding: "utf8" });
48284
49059
  return result.status === 0 ? { ok: true } : { ok: false, error: result.stderr || result.error?.message || "open failed" };
48285
49060
  });
48286
- const baseDirectory = dependencies.baseDirectory || resolve3(dirname3(fileURLToPath(import.meta.url)), "../shortcuts");
49061
+ const baseDirectory = dependencies.baseDirectory || resolve3(dirname4(fileURLToPath(import.meta.url)), "../shortcuts");
48287
49062
  const osRelease = (dependencies.osRelease || release2)();
48288
49063
  const darwinMajor = Number.parseInt(osRelease.split(".")[0], 10);
48289
49064
  const items = shortcutFiles.map(({ name, file, optional: optional2 }) => {
48290
- const path7 = resolve3(baseDirectory, file);
49065
+ const path8 = resolve3(baseDirectory, file);
48291
49066
  let installed = false;
48292
49067
  let identifier;
48293
49068
  let error2;
@@ -48303,9 +49078,9 @@ function setupShortcuts(checkOnly, dependencies = {}) {
48303
49078
  if (!installed && !checkOnly) {
48304
49079
  if (optional2 && !(darwinMajor >= MARKDOWN_MIN_DARWIN_MAJOR))
48305
49080
  skipped = `requires macOS 26 or later (this Mac reports Darwin ${osRelease})`;
48306
- else if (!exists(path7)) error2 = `Packaged Shortcut is missing: ${path7}`;
49081
+ else if (!exists(path8)) error2 = `Packaged Shortcut is missing: ${path8}`;
48307
49082
  else {
48308
- const result = open(path7);
49083
+ const result = open(path8);
48309
49084
  opened = result.ok;
48310
49085
  if (!result.ok) error2 = result.error || `Could not open ${file}`;
48311
49086
  }
@@ -48314,7 +49089,7 @@ function setupShortcuts(checkOnly, dependencies = {}) {
48314
49089
  name,
48315
49090
  installed,
48316
49091
  identifier,
48317
- file: path7,
49092
+ file: path8,
48318
49093
  opened,
48319
49094
  ...optional2 ? { optional: optional2 } : {},
48320
49095
  ...skipped ? { skipped } : {},
@@ -49245,19 +50020,47 @@ registerTool(
49245
50020
  registerTool(
49246
50021
  "list-native-tags",
49247
50022
  {
49248
- 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.",
50023
+ 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.",
49249
50024
  inputSchema: {
49250
- account: external_exports.string().min(1).max(MAX.ACCOUNT),
49251
- folder: external_exports.string().min(1).max(MAX.FOLDER)
50025
+ account: external_exports.string().min(1).max(MAX.ACCOUNT).optional().describe(
50026
+ "Account name (exact or unique prefix). Folder mode: defaults to Notes.app's default account. Inventory mode: omit to count every account."
50027
+ ),
50028
+ folder: external_exports.string().min(1).max(MAX.FOLDER).optional().describe("Folder to list tags in. Omit for the account-wide inventory with counts.")
49252
50029
  },
49253
50030
  outputSchema: {
49254
50031
  tags: external_exports.record(external_exports.array(external_exports.string())).optional(),
49255
50032
  complete: external_exports.boolean().optional(),
49256
- errors: external_exports.record(external_exports.string()).optional()
50033
+ errors: external_exports.record(external_exports.string()).optional(),
50034
+ inventory: external_exports.array(
50035
+ external_exports.object({
50036
+ tag: external_exports.string(),
50037
+ noteCount: external_exports.number(),
50038
+ accounts: external_exports.record(external_exports.number()),
50039
+ spellings: external_exports.array(external_exports.string()).optional()
50040
+ }).passthrough()
50041
+ ).optional(),
50042
+ tagCount: external_exports.number().optional(),
50043
+ unverifiedNotes: external_exports.number().optional(),
50044
+ account: external_exports.string().optional()
49257
50045
  },
49258
50046
  annotations: { readOnlyHint: true }
49259
50047
  },
49260
50048
  withErrorHandling(({ account, folder }) => {
50049
+ if (!folder) {
50050
+ const result = nativeTagInventory({ account });
50051
+ const scope2 = result.account ? ` in ${result.account}` : " across all accounts";
50052
+ const lines = result.inventory.map(
50053
+ (entry) => ` - ${entry.tag}: ${entry.noteCount} note${entry.noteCount === 1 ? "" : "s"}`
50054
+ );
50055
+ const partial2 = result.complete ? "" : `
50056
+
50057
+ ${result.unverifiedNotes} note(s) could not be checked against their body (locked or unreadable) and were counted from tag objects alone.`;
50058
+ return successResponse(
50059
+ `${result.tagCount} native tag${result.tagCount === 1 ? "" : "s"}${scope2}` + (lines.length ? `:
50060
+ ${lines.join("\n")}` : ".") + partial2,
50061
+ result
50062
+ );
50063
+ }
49261
50064
  const tags = {};
49262
50065
  const errors = {};
49263
50066
  for (const note of notesManager.listNoteRefs(account, folder)) {
@@ -50372,6 +51175,88 @@ registerTool(
50372
51175
  });
50373
51176
  }, "Error saving attachment")
50374
51177
  );
51178
+ function drawingView(noteId3, d) {
51179
+ const { pk, raster, ...rest } = d;
51180
+ return {
51181
+ attachmentId: attachmentCoreDataId(noteId3, pk),
51182
+ ...rest,
51183
+ raster: raster ? { source: raster.source, format: raster.format, width: raster.width, height: raster.height } : null
51184
+ };
51185
+ }
51186
+ registerTool(
51187
+ "list-paper-attachments",
51188
+ {
51189
+ description: "Use when: finding the Paper drawings (com.apple.paper) and classic drawings in one note, and whether Notes has a rendered image of each.\nReturns: per drawing its attachmentId, identifier, uti, kind (paper or drawing), handwritingSummary (Notes' recognized handwriting text, or null), bundlePresent, fallbackImagePath, previewPath, and raster {source, format, width, height} (the validated image export-paper-image would copy, or null).\nDo not use when: you want every attachment (list-attachments) or the image file itself (export-paper-image).\nSafety: read-only; reads NoteStore and the Notes data folder without opening Notes.app and requires Full Disk Access. Strokes are not decoded: Notes' Paper bundle has no public reader, so the raster is Notes' own rendering.",
51190
+ inputSchema: { id: noteIdInput },
51191
+ outputSchema: {
51192
+ attachments: external_exports.array(external_exports.object({}).passthrough()).optional(),
51193
+ count: external_exports.number().optional()
51194
+ },
51195
+ annotations: { readOnlyHint: true }
51196
+ },
51197
+ withErrorHandling(({ id: id2 }) => {
51198
+ const drawings = notesManager.listPaperAttachmentsById(id2).map((d) => drawingView(id2, d));
51199
+ if (drawings.length === 0) {
51200
+ return successResponse("This note has no Paper or drawing attachments.", {
51201
+ attachments: [],
51202
+ count: 0
51203
+ });
51204
+ }
51205
+ const lines = drawings.map(
51206
+ (d) => ` - ${d.kind} ${d.attachmentId}: ${d.raster ? `${d.raster.format.toUpperCase()} ${d.raster.width}x${d.raster.height} (${d.raster.source})` : "no rendered image on disk"}${d.handwritingSummary ? "; handwriting text stored" : ""}`
51207
+ );
51208
+ return successResponse(
51209
+ `Found ${drawings.length} Paper or drawing attachment(s):
51210
+ ${lines.join("\n")}`,
51211
+ { attachments: drawings, count: drawings.length }
51212
+ );
51213
+ }, "Error listing Paper attachments")
51214
+ );
51215
+ registerTool(
51216
+ "export-paper-image",
51217
+ {
51218
+ description: "Use when: saving Notes' rendered image of a Paper drawing or classic drawing to a file.\nReturns: savedPath, format (png or jpeg), width, height, bytes, source (fallback: Notes' full rendering; preview: its largest thumbnail, used only when no full rendering exists), and the drawing's attachmentId and handwritingSummary.\nDo not use when: the attachment is a photo or file (save-attachment or export-attachments).\nSafety: writes one new file; savePath must be absolute, under the home directory, a temp dir, or /Volumes, outside the Notes data folder, must not exist yet, and must end in the image's extension (.png, or .jpg/.jpeg). The image header is validated before and after copying. Pass attachmentId (from list-paper-attachments) when the note has more than one drawing. Requires Full Disk Access; Notes.app is not opened.",
51219
+ inputSchema: {
51220
+ noteId: noteIdInput,
51221
+ savePath: external_exports.string().min(1, "savePath is required").max(MAX.SAVE_PATH).describe(
51222
+ "Absolute path for the new image file (.png, or .jpg/.jpeg for a JPEG rendering)"
51223
+ ),
51224
+ attachmentId: external_exports.string().max(MAX.ATTACHMENT_ID).optional().describe(
51225
+ "Drawing to export (attachmentId or identifier from list-paper-attachments); required when the note has more than one"
51226
+ )
51227
+ },
51228
+ outputSchema: {
51229
+ savedPath: external_exports.string().optional(),
51230
+ format: external_exports.enum(["png", "jpeg"]).optional(),
51231
+ width: external_exports.number().optional(),
51232
+ height: external_exports.number().optional(),
51233
+ bytes: external_exports.number().optional(),
51234
+ source: external_exports.enum(["fallback", "preview"]).optional(),
51235
+ attachmentId: external_exports.string().optional(),
51236
+ identifier: external_exports.string().optional(),
51237
+ kind: external_exports.enum(["paper", "drawing"]).optional(),
51238
+ handwritingSummary: external_exports.string().nullable().optional()
51239
+ }
51240
+ },
51241
+ withErrorHandling(({ noteId: noteId3, savePath, attachmentId }) => {
51242
+ const r = notesManager.exportPaperImageById(noteId3, savePath, attachmentId);
51243
+ return successResponse(
51244
+ `Saved ${r.format.toUpperCase()} ${r.width}x${r.height} (${r.bytes} bytes, ${r.source === "fallback" ? "Notes' full rendering" : "largest preview"}) to ${r.savedPath}`,
51245
+ {
51246
+ savedPath: r.savedPath,
51247
+ format: r.format,
51248
+ width: r.width,
51249
+ height: r.height,
51250
+ bytes: r.bytes,
51251
+ source: r.source,
51252
+ attachmentId: attachmentCoreDataId(noteId3, r.drawing.pk),
51253
+ identifier: r.drawing.identifier,
51254
+ kind: r.drawing.kind,
51255
+ handwritingSummary: r.drawing.handwritingSummary
51256
+ }
51257
+ );
51258
+ }, "Error exporting Paper image")
51259
+ );
50375
51260
  registerTool(
50376
51261
  "export-attachments",
50377
51262
  {
@@ -50697,6 +51582,57 @@ registerTool(
50697
51582
  return successResponse(summary, metadata);
50698
51583
  }, "Error reading note metadata")
50699
51584
  );
51585
+ var SPECIAL_KIND_LABEL = {
51586
+ pinned: "pinned notes",
51587
+ "quick-notes": "Quick Notes",
51588
+ "recently-deleted": "notes in Recently Deleted",
51589
+ locked: "password-protected notes"
51590
+ };
51591
+ registerTool(
51592
+ "list-special-notes",
51593
+ {
51594
+ 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.",
51595
+ inputSchema: {
51596
+ kind: external_exports.enum(["pinned", "quick-notes", "recently-deleted", "locked"]).describe("Which set of notes to list"),
51597
+ account: external_exports.string().min(1).max(MAX.ACCOUNT).optional().describe("Only this account (exact or unique-prefix name). Omit for every account."),
51598
+ limit: external_exports.number().int().min(1).max(SPECIAL_LIMIT.MAX).optional().describe(`Maximum notes to return (default ${SPECIAL_LIMIT.DEFAULT})`)
51599
+ },
51600
+ outputSchema: {
51601
+ kind: external_exports.string().optional(),
51602
+ notes: external_exports.array(external_exports.object({}).passthrough()).optional(),
51603
+ count: external_exports.number().optional(),
51604
+ total: external_exports.number().optional(),
51605
+ limit: external_exports.number().optional(),
51606
+ supported: external_exports.boolean().optional(),
51607
+ account: external_exports.string().optional()
51608
+ },
51609
+ annotations: { readOnlyHint: true }
51610
+ },
51611
+ withErrorHandling(({ kind, account, limit }) => {
51612
+ const result = listSpecialNotes({ kind, account, limit });
51613
+ const label = SPECIAL_KIND_LABEL[kind];
51614
+ const structured = result;
51615
+ if (!result.supported) {
51616
+ return successResponse(
51617
+ `This macOS version's Notes database does not record ${label}.`,
51618
+ structured
51619
+ );
51620
+ }
51621
+ const scope2 = result.account ? ` in ${result.account}` : "";
51622
+ if (result.count === 0) return successResponse(`No ${label}${scope2}.`, structured);
51623
+ const lines = result.notes.map(
51624
+ (row) => ` - ${row.title ?? "(untitled)"}${row.folder ? ` (${row.folder})` : ""} [id: ${row.id}]`
51625
+ );
51626
+ const more = result.total > result.count ? `
51627
+
51628
+ Showing ${result.count} of ${result.total}; pass a higher limit to see more.` : "";
51629
+ return successResponse(
51630
+ `Found ${result.total} ${label}${scope2}:
51631
+ ${lines.join("\n")}${more}`,
51632
+ structured
51633
+ );
51634
+ }, "Error listing notes")
51635
+ );
50700
51636
  registerResourcesAndPrompts(server, notesManager);
50701
51637
  process.on("uncaughtException", (err) => {
50702
51638
  if (err?.code === "EPIPE") process.exit(0);