apple-notes-mcp 2.8.33 → 2.8.35

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 +61 -3
  2. package/build/index.js +1410 -228
  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, constants3) {
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, constants3);
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, constants3) {
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, constants3);
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, constants3) {
506
- this.code = optimizeExpr(this.code, names, constants3);
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, constants3) {
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, constants3))
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, constants3) {
593
+ optimizeNames(names, constants5) {
594
594
  var _a;
595
- this.else = (_a = this.else) === null || _a === void 0 ? void 0 : _a.optimizeNames(names, constants3);
596
- if (!(super.optimizeNames(names, constants3) || 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, constants3);
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, constants3) {
622
- if (!super.optimizeNames(names, constants3))
621
+ optimizeNames(names, constants5) {
622
+ if (!super.optimizeNames(names, constants5))
623
623
  return;
624
- this.iteration = optimizeExpr(this.iteration, names, constants3);
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, constants3) {
661
- if (!super.optimizeNames(names, constants3))
660
+ optimizeNames(names, constants5) {
661
+ if (!super.optimizeNames(names, constants5))
662
662
  return;
663
- this.iterable = optimizeExpr(this.iterable, names, constants3);
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, constants3) {
705
+ optimizeNames(names, constants5) {
706
706
  var _a, _b;
707
- super.optimizeNames(names, constants3);
708
- (_a = this.catch) === null || _a === void 0 ? void 0 : _a.optimizeNames(names, constants3);
709
- (_b = this.finally) === null || _b === void 0 ? void 0 : _b.optimizeNames(names, constants3);
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, constants3) {
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 = constants3[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 && constants3[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
  });
@@ -2991,7 +2991,7 @@ var require_compile = __commonJS({
2991
2991
  const schOrFunc = root.refs[ref];
2992
2992
  if (schOrFunc)
2993
2993
  return schOrFunc;
2994
- let _sch = resolve3.call(this, root, ref);
2994
+ let _sch = resolve4.call(this, root, ref);
2995
2995
  if (_sch === void 0) {
2996
2996
  const schema = (_a = root.localRefs) === null || _a === void 0 ? void 0 : _a[ref];
2997
2997
  const { schemaId } = this.opts;
@@ -3018,7 +3018,7 @@ var require_compile = __commonJS({
3018
3018
  function sameSchemaEnv(s1, s2) {
3019
3019
  return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
3020
3020
  }
3021
- function resolve3(root, ref) {
3021
+ function resolve4(root, ref) {
3022
3022
  let sch;
3023
3023
  while (typeof (sch = this.refs[ref]) == "string")
3024
3024
  ref = sch;
@@ -3261,10 +3261,10 @@ 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
  }
@@ -3843,7 +3843,7 @@ var require_fast_uri = __commonJS({
3843
3843
  }
3844
3844
  return uri;
3845
3845
  }
3846
- function resolve3(baseURI, relativeURI, options) {
3846
+ function resolve4(baseURI, relativeURI, options) {
3847
3847
  const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
3848
3848
  const {
3849
3849
  parsed: baseParsed,
@@ -3876,49 +3876,49 @@ var require_fast_uri = __commonJS({
3876
3876
  schemelessOptions.skipEscape = true;
3877
3877
  return serialize(resolved, schemelessOptions);
3878
3878
  }
3879
- function resolveComponent(base, relative2, options, skipNormalization) {
3879
+ function resolveComponent(base, relative3, options, skipNormalization) {
3880
3880
  const target = {};
3881
3881
  if (!skipNormalization) {
3882
3882
  base = parse3(serialize(base, options), options);
3883
- relative2 = parse3(serialize(relative2, options), options);
3883
+ relative3 = parse3(serialize(relative3, options), options);
3884
3884
  }
3885
3885
  options = options || {};
3886
- if (!options.tolerant && relative2.scheme) {
3887
- target.scheme = relative2.scheme;
3888
- target.userinfo = relative2.userinfo;
3889
- target.host = relative2.host;
3890
- target.port = relative2.port;
3891
- target.path = removeDotSegments(relative2.path || "");
3892
- target.query = relative2.query;
3886
+ if (!options.tolerant && relative3.scheme) {
3887
+ target.scheme = relative3.scheme;
3888
+ target.userinfo = relative3.userinfo;
3889
+ target.host = relative3.host;
3890
+ target.port = relative3.port;
3891
+ target.path = removeDotSegments(relative3.path || "");
3892
+ target.query = relative3.query;
3893
3893
  } else {
3894
- if (relative2.userinfo !== void 0 || relative2.host !== void 0 || relative2.port !== void 0) {
3895
- target.userinfo = relative2.userinfo;
3896
- target.host = relative2.host;
3897
- target.port = relative2.port;
3898
- target.path = removeDotSegments(relative2.path || "");
3899
- target.query = relative2.query;
3894
+ if (relative3.userinfo !== void 0 || relative3.host !== void 0 || relative3.port !== void 0) {
3895
+ target.userinfo = relative3.userinfo;
3896
+ target.host = relative3.host;
3897
+ target.port = relative3.port;
3898
+ target.path = removeDotSegments(relative3.path || "");
3899
+ target.query = relative3.query;
3900
3900
  } else {
3901
- if (!relative2.path) {
3901
+ if (!relative3.path) {
3902
3902
  target.path = base.path;
3903
- if (relative2.query !== void 0) {
3904
- target.query = relative2.query;
3903
+ if (relative3.query !== void 0) {
3904
+ target.query = relative3.query;
3905
3905
  } else {
3906
3906
  target.query = base.query;
3907
3907
  }
3908
3908
  } else {
3909
- if (relative2.path[0] === "/") {
3910
- target.path = removeDotSegments(relative2.path);
3909
+ if (relative3.path[0] === "/") {
3910
+ target.path = removeDotSegments(relative3.path);
3911
3911
  } else {
3912
3912
  if ((base.userinfo !== void 0 || base.host !== void 0 || base.port !== void 0) && !base.path) {
3913
- target.path = "/" + relative2.path;
3913
+ target.path = "/" + relative3.path;
3914
3914
  } else if (!base.path) {
3915
- target.path = relative2.path;
3915
+ target.path = relative3.path;
3916
3916
  } else {
3917
- target.path = base.path.slice(0, base.path.lastIndexOf("/") + 1) + relative2.path;
3917
+ target.path = base.path.slice(0, base.path.lastIndexOf("/") + 1) + relative3.path;
3918
3918
  }
3919
3919
  target.path = removeDotSegments(target.path);
3920
3920
  }
3921
- target.query = relative2.query;
3921
+ target.query = relative3.query;
3922
3922
  }
3923
3923
  target.userinfo = base.userinfo;
3924
3924
  target.host = base.host;
@@ -3926,7 +3926,7 @@ var require_fast_uri = __commonJS({
3926
3926
  }
3927
3927
  target.scheme = base.scheme;
3928
3928
  }
3929
- target.fragment = relative2.fragment;
3929
+ target.fragment = relative3.fragment;
3930
3930
  return target;
3931
3931
  }
3932
3932
  function equal(uriA, uriB, options) {
@@ -4205,7 +4205,7 @@ var require_fast_uri = __commonJS({
4205
4205
  var fastUri = {
4206
4206
  SCHEMES,
4207
4207
  normalize,
4208
- resolve: resolve3,
4208
+ resolve: resolve4,
4209
4209
  resolveComponent,
4210
4210
  equal,
4211
4211
  serialize,
@@ -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;
@@ -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 constants3 = {
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 constants3) {
7465
- v = { value: constants3[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];
@@ -12184,9 +12184,9 @@ var require_URL = __commonJS({
12184
12184
  },
12185
12185
  // See: http://tools.ietf.org/html/rfc3986#section-5.2
12186
12186
  // and https://url.spec.whatwg.org/#constructors
12187
- resolve: function(relative2) {
12187
+ resolve: function(relative3) {
12188
12188
  var base = this;
12189
- var r = new URL2(relative2);
12189
+ var r = new URL2(relative3);
12190
12190
  var t = new URL2();
12191
12191
  if (r.scheme !== void 0) {
12192
12192
  t.scheme = r.scheme;
@@ -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 join16(output, replacement);
24468
+ return join18(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 = join16(output, rule.append(self.options));
24475
+ output = join18(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 join16(output, replacement) {
24487
+ function join18(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);
@@ -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 = "|") {
@@ -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);
@@ -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
  }
@@ -36608,7 +36608,7 @@ var Protocol = class {
36608
36608
  return;
36609
36609
  }
36610
36610
  const pollInterval = task2.pollInterval ?? this._options?.defaultTaskPollInterval ?? 1e3;
36611
- await new Promise((resolve3) => setTimeout(resolve3, pollInterval));
36611
+ await new Promise((resolve4) => setTimeout(resolve4, pollInterval));
36612
36612
  options?.signal?.throwIfAborted();
36613
36613
  }
36614
36614
  } catch (error2) {
@@ -36625,7 +36625,7 @@ var Protocol = class {
36625
36625
  */
36626
36626
  request(request, resultSchema, options) {
36627
36627
  const { relatedRequestId, resumptionToken, onresumptiontoken, task, relatedTask } = options ?? {};
36628
- return new Promise((resolve3, reject) => {
36628
+ return new Promise((resolve4, reject) => {
36629
36629
  const earlyReject = (error2) => {
36630
36630
  reject(error2);
36631
36631
  };
@@ -36703,7 +36703,7 @@ var Protocol = class {
36703
36703
  if (!parseResult.success) {
36704
36704
  reject(parseResult.error);
36705
36705
  } else {
36706
- resolve3(parseResult.data);
36706
+ resolve4(parseResult.data);
36707
36707
  }
36708
36708
  } catch (error2) {
36709
36709
  reject(error2);
@@ -36964,12 +36964,12 @@ var Protocol = class {
36964
36964
  }
36965
36965
  } catch {
36966
36966
  }
36967
- return new Promise((resolve3, reject) => {
36967
+ return new Promise((resolve4, reject) => {
36968
36968
  if (signal.aborted) {
36969
36969
  reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
36970
36970
  return;
36971
36971
  }
36972
- const timeoutId = setTimeout(resolve3, interval);
36972
+ const timeoutId = setTimeout(resolve4, interval);
36973
36973
  signal.addEventListener("abort", () => {
36974
36974
  clearTimeout(timeoutId);
36975
36975
  reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
@@ -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 = [];
@@ -38282,7 +38282,7 @@ var McpServer = class {
38282
38282
  let task = createTaskResult.task;
38283
38283
  const pollInterval = task.pollInterval ?? 5e3;
38284
38284
  while (task.status !== "completed" && task.status !== "failed" && task.status !== "cancelled") {
38285
- await new Promise((resolve3) => setTimeout(resolve3, pollInterval));
38285
+ await new Promise((resolve4) => setTimeout(resolve4, pollInterval));
38286
38286
  const updatedTask = await extra.taskStore.getTask(taskId);
38287
38287
  if (!updatedTask) {
38288
38288
  throw new McpError(ErrorCode.InternalError, `Task ${taskId} not found during polling`);
@@ -38970,12 +38970,12 @@ var StdioServerTransport = class {
38970
38970
  this.onclose?.();
38971
38971
  }
38972
38972
  send(message) {
38973
- return new Promise((resolve3) => {
38973
+ return new Promise((resolve4) => {
38974
38974
  const json2 = serializeMessage(message);
38975
38975
  if (this._stdout.write(json2)) {
38976
- resolve3();
38976
+ resolve4();
38977
38977
  } else {
38978
- this._stdout.once("drain", resolve3);
38978
+ this._stdout.once("drain", resolve4);
38979
38979
  }
38980
38980
  });
38981
38981
  }
@@ -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"
@@ -41036,11 +41036,939 @@ 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
+
41055
+ // src/utils/attachmentAssets.ts
41056
+ import { execFileSync as execFileSync6 } from "node:child_process";
41057
+ import {
41058
+ closeSync as closeSync2,
41059
+ constants as constants2,
41060
+ fstatSync as fstatSync2,
41061
+ lstatSync as lstatSync2,
41062
+ mkdirSync as mkdirSync2,
41063
+ openSync as openSync2,
41064
+ readdirSync,
41065
+ readSync,
41066
+ realpathSync as realpathSync2,
41067
+ unlinkSync,
41068
+ writeSync
41069
+ } from "node:fs";
41070
+ import { homedir as homedir6 } from "node:os";
41071
+ import { basename, dirname as dirname2, extname, isAbsolute as isAbsolute2, join as join6, relative as relative2, resolve as resolve2, sep as sep2 } from "node:path";
41072
+ import { gunzipSync as gunzipSync5 } from "node:zlib";
41073
+ var NOTES_CONTAINER_DIR = join6(
41074
+ homedir6(),
41075
+ "Library/Group Containers/group.com.apple.notes"
41076
+ );
41077
+ var AttachmentStoreError = class extends Error {
41078
+ constructor(message, code) {
41079
+ super(message);
41080
+ this.code = code;
41081
+ this.name = "AttachmentStoreError";
41082
+ }
41083
+ code;
41084
+ };
41085
+ var MAX_PREVIEW_DIR_ENTRIES = 1e5;
41086
+ var MAX_BUNDLE_ENTRIES = 64;
41087
+ var MAX_GENERATION_DIRS = 64;
41088
+ var MAX_COLLISION_SUFFIX = 1e4;
41089
+ var MAX_BODY_BYTES = 32 * 1024 * 1024;
41090
+ var PREVIEW_IMAGE_SUFFIXES = /* @__PURE__ */ new Set([".png", ".jpg", ".jpeg", ".heic", ".tiff", ".gif"]);
41091
+ var GENERIC_FILE_NAMES = /* @__PURE__ */ new Set([
41092
+ "fallbackimage.png",
41093
+ "fallbackimage.jpg",
41094
+ "fallbackpdf.pdf",
41095
+ "preview.png",
41096
+ "orientedpreview.png"
41097
+ ]);
41098
+ var IMAGE_UTIS = /* @__PURE__ */ new Set([
41099
+ "public.jpeg",
41100
+ "public.png",
41101
+ "public.heic",
41102
+ "public.heif",
41103
+ "public.tiff",
41104
+ "public.image",
41105
+ "com.compuserve.gif",
41106
+ "org.webmproject.webp",
41107
+ "com.microsoft.bmp",
41108
+ "com.adobe.raw-image"
41109
+ ]);
41110
+ function classifyAttachmentKind(uti) {
41111
+ if (!uti) return "other";
41112
+ const u = uti.toLowerCase();
41113
+ if (u === "com.apple.notes.table") return "table";
41114
+ if (u === "public.url" || u.startsWith("public.url")) return "url";
41115
+ if (u === "com.apple.paper.doc.scan" || u === "com.apple.notes.gallery" || u.includes("scan"))
41116
+ return "scan";
41117
+ if (u === "com.apple.paper" || u.startsWith("com.apple.drawing")) return "drawing";
41118
+ if (u === "com.adobe.pdf" || u.includes("pdf")) return "pdf";
41119
+ if (u.includes("audio")) return "audio";
41120
+ if (u === "public.mpeg-4" || u.includes("movie") || u.includes("video")) return "video";
41121
+ if (IMAGE_UTIS.has(u) || u.includes("image")) return "image";
41122
+ return "other";
41123
+ }
41124
+ function parseNoteId2(noteId3) {
41125
+ const m = /^x-coredata:\/\/([0-9A-Fa-f-]+)\/ICNote\/p(\d+)$/.exec(noteId3);
41126
+ if (!m) {
41127
+ throw new AttachmentStoreError(
41128
+ `Invalid note ID format: "${noteId3}". Expected x-coredata://UUID/ICNote/pNNN`,
41129
+ "invalid_id"
41130
+ );
41131
+ }
41132
+ return { store: m[1], pk: Number(m[2]) };
41133
+ }
41134
+ function attachmentCoreDataId(noteId3, pk) {
41135
+ return noteId3.replace(/ICNote\/p\d+$/, `ICAttachment/p${pk}`);
41136
+ }
41137
+ function buildAttachmentRowsSql(notePk, columns) {
41138
+ if (!Number.isSafeInteger(notePk) || notePk < 0) throw new Error("Invalid note primary key");
41139
+ const col2 = (alias, name) => columns.has(name) ? `${alias}.${name}` : "NULL";
41140
+ const firstOf = (alias, names) => {
41141
+ const present = names.filter((n) => columns.has(n)).map((n) => `${alias}.${n}`);
41142
+ if (present.length === 0) return "NULL";
41143
+ return present.length === 1 ? present[0] : `COALESCE(${present.join(", ")})`;
41144
+ };
41145
+ const accountCols = [...columns].filter((c) => /^ZACCOUNT\d*$/.test(c)).sort();
41146
+ const accountRefs = [
41147
+ ...accountCols.map((c) => `a.${c}`),
41148
+ ...accountCols.map((c) => `n.${c}`)
41149
+ ].join(", ");
41150
+ const account = accountCols.length ? `(SELECT acc.ZIDENTIFIER FROM ZICCLOUDSYNCINGOBJECT acc WHERE acc.Z_ENT = (SELECT Z_ENT FROM Z_PRIMARYKEY WHERE Z_NAME = 'ICAccount') AND acc.Z_PK IN (${accountRefs}) LIMIT 1)` : "NULL";
41151
+ const noteLink = columns.has("ZNOTE") ? "a.ZNOTE" : "NULL";
41152
+ const parent = col2("a", "ZPARENTATTACHMENT");
41153
+ const deleted = columns.has("ZMARKEDFORDELETION") ? " AND COALESCE(a.ZMARKEDFORDELETION, 0) = 0" : "";
41154
+ const fields = [
41155
+ `'pk', a.Z_PK`,
41156
+ `'identifier', a.ZIDENTIFIER`,
41157
+ `'uti', ${col2("a", "ZTYPEUTI")}`,
41158
+ `'parentPk', ${parent}`,
41159
+ `'filename', ${col2("a", "ZFILENAME")}`,
41160
+ `'mediaIdentifier', m.ZIDENTIFIER`,
41161
+ `'mediaFilename', ${col2("m", "ZFILENAME")}`,
41162
+ `'mediaGeneration', ${firstOf("m", ["ZGENERATION1", "ZGENERATION"])}`,
41163
+ `'fallbackImageGeneration', ${col2("a", "ZFALLBACKIMAGEGENERATION")}`,
41164
+ `'fallbackPdfGeneration', ${col2("a", "ZFALLBACKPDFGENERATION")}`,
41165
+ `'accountIdentifier', ${account}`
41166
+ ].join(", ");
41167
+ const mediaJoin = columns.has("ZMEDIA") ? "LEFT JOIN ZICCLOUDSYNCINGOBJECT m ON m.Z_PK = a.ZMEDIA" : "LEFT JOIN ZICCLOUDSYNCINGOBJECT m ON 0";
41168
+ const childClause = parent === "NULL" ? "" : ` OR a.ZPARENTATTACHMENT IN (SELECT p.Z_PK FROM ZICCLOUDSYNCINGOBJECT p WHERE p.ZNOTE = ${notePk})`;
41169
+ return [
41170
+ "BEGIN;",
41171
+ `SELECT count(*) FROM ZICCLOUDSYNCINGOBJECT WHERE Z_PK = ${notePk} AND Z_ENT = (SELECT Z_ENT FROM Z_PRIMARYKEY WHERE Z_NAME = 'ICNote');`,
41172
+ `SELECT json_group_array(json_object(${fields})) FROM ZICCLOUDSYNCINGOBJECT a ${mediaJoin} LEFT JOIN ZICCLOUDSYNCINGOBJECT n ON n.Z_PK = ${noteLink} WHERE a.Z_ENT = (SELECT Z_ENT FROM Z_PRIMARYKEY WHERE Z_NAME = 'ICAttachment') AND (${noteLink} = ${notePk}${childClause})${deleted};`,
41173
+ `SELECT hex(ZDATA) FROM ZICNOTEDATA WHERE ZNOTE = ${notePk};`,
41174
+ "COMMIT;"
41175
+ ].join(" ");
41176
+ }
41177
+ function runSqlite3(dbPath2, sql) {
41178
+ try {
41179
+ return execFileSync6("/usr/bin/sqlite3", ["-readonly", dbPath2, sql], {
41180
+ encoding: "utf8",
41181
+ timeout: 1e4,
41182
+ maxBuffer: 128 * 1024 * 1024,
41183
+ stdio: ["pipe", "pipe", "pipe"]
41184
+ });
41185
+ } catch (error2) {
41186
+ const message = error2 instanceof Error ? error2.message : String(error2);
41187
+ if (/authorization denied|unable to open database/i.test(message)) {
41188
+ throw new AttachmentStoreError(
41189
+ "Full Disk Access is required to read attachment paths. Grant it to the app that launches this server, then relaunch it (run the doctor tool to verify).",
41190
+ "no_fda"
41191
+ );
41192
+ }
41193
+ throw new AttachmentStoreError(`Failed to read attachment rows: ${message}`, "query_error");
41194
+ }
41195
+ }
41196
+ function toStringOrNull(value) {
41197
+ return typeof value === "string" && value.length > 0 ? value : null;
41198
+ }
41199
+ function toIntOrNull(value) {
41200
+ return typeof value === "number" && Number.isSafeInteger(value) ? value : null;
41201
+ }
41202
+ function parseAttachmentRows(json2) {
41203
+ const raw = JSON.parse(json2 || "[]");
41204
+ if (!Array.isArray(raw)) throw new Error("Invalid attachment rows");
41205
+ const rows = [];
41206
+ for (const item of raw) {
41207
+ if (!item || typeof item !== "object") continue;
41208
+ const r = item;
41209
+ const pk = toIntOrNull(r.pk);
41210
+ const identifier = toStringOrNull(r.identifier);
41211
+ if (pk === null || identifier === null) continue;
41212
+ rows.push({
41213
+ pk,
41214
+ identifier,
41215
+ uti: toStringOrNull(r.uti),
41216
+ parentPk: toIntOrNull(r.parentPk),
41217
+ filename: toStringOrNull(r.filename),
41218
+ mediaIdentifier: toStringOrNull(r.mediaIdentifier),
41219
+ mediaFilename: toStringOrNull(r.mediaFilename),
41220
+ mediaGeneration: toStringOrNull(r.mediaGeneration),
41221
+ fallbackImageGeneration: toStringOrNull(r.fallbackImageGeneration),
41222
+ fallbackPdfGeneration: toStringOrNull(r.fallbackPdfGeneration),
41223
+ accountIdentifier: toStringOrNull(r.accountIdentifier)
41224
+ });
41225
+ }
41226
+ return rows.sort((a, b) => a.pk - b.pk);
41227
+ }
41228
+ function attachmentOrderFromNoteData(hex3) {
41229
+ if (!hex3 || !/^[0-9a-f]+$/i.test(hex3)) return null;
41230
+ try {
41231
+ const data = gunzipSync5(Buffer.from(hex3, "hex"), { maxOutputLength: MAX_BODY_BYTES });
41232
+ const wrapper = embeddedMessage(getField(decodeMessage(data), 2));
41233
+ const body = wrapper && embeddedMessage(getField(wrapper, 3));
41234
+ if (!body) return null;
41235
+ const ids = [];
41236
+ for (const run of getFields(body, 5)) {
41237
+ const fields = embeddedMessage(run);
41238
+ const info = fields && embeddedMessage(getField(fields, 12));
41239
+ const id2 = info && stringValue(getField(info, 1));
41240
+ if (id2 && !ids.some((seen) => seen.toLowerCase() === id2.toLowerCase())) ids.push(id2);
41241
+ }
41242
+ return ids;
41243
+ } catch {
41244
+ return null;
41245
+ }
41246
+ }
41247
+ function readNoteAttachmentRows(noteId3, dbPath2 = join6(NOTES_CONTAINER_DIR, "NoteStore.sqlite")) {
41248
+ const { pk } = parseNoteId2(noteId3);
41249
+ const columnList = runSqlite3(
41250
+ dbPath2,
41251
+ "SELECT group_concat(name, ',') FROM pragma_table_info('ZICCLOUDSYNCINGOBJECT');"
41252
+ ).trim();
41253
+ const columns = new Set(columnList.split(",").filter(Boolean));
41254
+ if (!columns.has("ZIDENTIFIER")) {
41255
+ throw new AttachmentStoreError("Unsupported Notes database schema", "query_error");
41256
+ }
41257
+ const lines = runSqlite3(dbPath2, buildAttachmentRowsSql(pk, columns)).split("\n");
41258
+ if (lines[0]?.trim() !== "1") {
41259
+ throw new AttachmentStoreError(
41260
+ `No note found in the database for ID "${noteId3}".`,
41261
+ "not_found"
41262
+ );
41263
+ }
41264
+ let rows;
41265
+ try {
41266
+ rows = parseAttachmentRows(lines[1] ?? "[]");
41267
+ } catch {
41268
+ throw new AttachmentStoreError("Attachment rows could not be parsed", "query_error");
41269
+ }
41270
+ return { rows, bodyOrder: attachmentOrderFromNoteData(lines[2]?.trim()) };
41271
+ }
41272
+ function safeComponent(value) {
41273
+ if (typeof value !== "string" || !value || value.length > 255) return null;
41274
+ if (value === "." || value === ".." || value.includes("/") || value.includes("\0")) return null;
41275
+ return value;
41276
+ }
41277
+ function realInside(path7, rootReal) {
41278
+ try {
41279
+ const real = realpathSync2.native(path7);
41280
+ return real === rootReal || real.startsWith(rootReal + sep2) ? real : null;
41281
+ } catch {
41282
+ return null;
41283
+ }
41284
+ }
41285
+ function isRegularFile(path7) {
41286
+ try {
41287
+ return lstatSync2(path7).isFile();
41288
+ } catch {
41289
+ return false;
41290
+ }
41291
+ }
41292
+ function isDirectory(path7) {
41293
+ try {
41294
+ return lstatSync2(path7).isDirectory();
41295
+ } catch {
41296
+ return false;
41297
+ }
41298
+ }
41299
+ function boundedEntries(dir, limit) {
41300
+ try {
41301
+ const entries2 = readdirSync(dir);
41302
+ return entries2.length > limit ? null : entries2.sort();
41303
+ } catch {
41304
+ return null;
41305
+ }
41306
+ }
41307
+ function resolveAccountDir(containerDir, accountIdentifier) {
41308
+ const accountsDir = join6(containerDir, "Accounts");
41309
+ let accountsReal;
41310
+ try {
41311
+ accountsReal = realpathSync2.native(accountsDir);
41312
+ } catch {
41313
+ return null;
41314
+ }
41315
+ const account = safeComponent(accountIdentifier);
41316
+ if (account) {
41317
+ const dir = realInside(join6(accountsReal, account), accountsReal);
41318
+ if (dir && isDirectory(dir)) return dir;
41319
+ }
41320
+ const entries2 = (boundedEntries(accountsReal, 64) ?? []).filter(
41321
+ (e) => isDirectory(join6(accountsReal, e))
41322
+ );
41323
+ if (entries2.length !== 1) return null;
41324
+ return realInside(join6(accountsReal, entries2[0]), accountsReal);
41325
+ }
41326
+ function generationRank(name) {
41327
+ const m = /^(\d+)_/.exec(name);
41328
+ return m ? Number(m[1]) : 0;
41329
+ }
41330
+ function generationDirs(base, accountDir) {
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)));
41333
+ }
41334
+ function fallbackFiles(accountDir, rootName, identifier, generation, names) {
41335
+ const base = join6(accountDir, rootName, identifier);
41336
+ const found = [];
41337
+ const add = (candidate) => {
41338
+ const real = realInside(candidate, accountDir);
41339
+ if (real && isRegularFile(real) && !found.includes(real)) found.push(real);
41340
+ };
41341
+ const gen = safeComponent(generation);
41342
+ if (gen) for (const name of names) add(join6(base, gen, name));
41343
+ if (isDirectory(base)) {
41344
+ for (const dir of generationDirs(base, accountDir))
41345
+ for (const name of names) add(join6(dir, name));
41346
+ for (const name of names) add(join6(base, name));
41347
+ }
41348
+ for (const name of names) add(join6(accountDir, rootName, `${identifier}${extname(name)}`));
41349
+ return found;
41350
+ }
41351
+ function previewPixelArea(name) {
41352
+ const matches = [...name.matchAll(/-(\d{1,6})x(\d{1,6})(?=-|\.|$)/g)];
41353
+ const last = matches.at(-1);
41354
+ return last ? Number(last[1]) * Number(last[2]) : 0;
41355
+ }
41356
+ function previewFileInBundle(bundle, accountDir) {
41357
+ const direct = [];
41358
+ const nested = [];
41359
+ for (const entry of boundedEntries(bundle, MAX_BUNDLE_ENTRIES) ?? []) {
41360
+ const child = realInside(join6(bundle, entry), accountDir);
41361
+ if (!child) continue;
41362
+ if (isRegularFile(child)) direct.push(child);
41363
+ else if (isDirectory(child)) nested.push(child);
41364
+ }
41365
+ nested.sort((a, b) => generationRank(basename(b)) - generationRank(basename(a)));
41366
+ const pick2 = (files) => files.find((f) => basename(f) === "Preview.png") ?? files.find((f) => PREVIEW_IMAGE_SUFFIXES.has(extname(f).toLowerCase())) ?? null;
41367
+ for (const dir of nested) {
41368
+ const files = (boundedEntries(dir, MAX_BUNDLE_ENTRIES) ?? []).map((e) => realInside(join6(dir, e), accountDir)).filter((p) => p !== null && isRegularFile(p));
41369
+ const chosen = pick2(files);
41370
+ if (chosen) return chosen;
41371
+ }
41372
+ return pick2(direct);
41373
+ }
41374
+ function listPreviewEntries(accountDir) {
41375
+ return boundedEntries(join6(accountDir, "Previews"), MAX_PREVIEW_DIR_ENTRIES) ?? [];
41376
+ }
41377
+ function previewPaths(accountDir, identifier, entries2) {
41378
+ const id2 = safeComponent(identifier);
41379
+ if (!id2) return [];
41380
+ const prefix = `${id2}-`.toLowerCase();
41381
+ const candidates = entries2.filter((name) => name.toLowerCase().startsWith(prefix)).filter((name) => {
41382
+ const ext = extname(name).toLowerCase();
41383
+ return !ext || PREVIEW_IMAGE_SUFFIXES.has(ext) || /^\.\d+$/.test(ext);
41384
+ }).sort((a, b) => previewPixelArea(b) - previewPixelArea(a) || a.localeCompare(b));
41385
+ const files = [];
41386
+ for (const name of candidates) {
41387
+ const real = realInside(join6(accountDir, "Previews", name), accountDir);
41388
+ if (!real) continue;
41389
+ const file = isRegularFile(real) ? real : isDirectory(real) ? previewFileInBundle(real, accountDir) : null;
41390
+ if (file && !files.includes(file)) files.push(file);
41391
+ }
41392
+ return files;
41393
+ }
41394
+ function assetPathsFor(accountDir, row) {
41395
+ const found = [];
41396
+ const add = (candidate) => {
41397
+ const real = realInside(candidate, accountDir);
41398
+ if (real && isRegularFile(real) && !found.includes(real)) found.push(real);
41399
+ };
41400
+ const mediaId = safeComponent(row.mediaIdentifier);
41401
+ const mediaName = safeComponent(row.mediaFilename);
41402
+ const mediaGen = safeComponent(row.mediaGeneration);
41403
+ if (mediaId && mediaName) {
41404
+ if (mediaGen) add(join6(accountDir, "Media", mediaId, mediaGen, mediaName));
41405
+ add(join6(accountDir, "Media", mediaId, mediaName));
41406
+ }
41407
+ const id2 = safeComponent(row.identifier);
41408
+ if (!id2) return found;
41409
+ const ownName = safeComponent(row.filename);
41410
+ if (ownName) add(join6(accountDir, "Media", id2, ownName));
41411
+ for (const file of fallbackFiles(accountDir, "FallbackImages", id2, row.fallbackImageGeneration, [
41412
+ "FallbackImage.png",
41413
+ "FallbackImage.jpg"
41414
+ ]))
41415
+ add(file);
41416
+ for (const file of fallbackFiles(accountDir, "FallbackPDFs", id2, row.fallbackPdfGeneration, [
41417
+ "FallbackPDF.pdf"
41418
+ ]))
41419
+ add(file);
41420
+ return found;
41421
+ }
41422
+ function assembleAttachmentAssets(rows, bodyOrder, containerDir = NOTES_CONTAINER_DIR) {
41423
+ const byPk = new Map(rows.map((r) => [r.pk, r]));
41424
+ const roots = rows.filter((r) => r.parentPk === null || !byPk.has(r.parentPk));
41425
+ const bodyIndex = /* @__PURE__ */ new Map();
41426
+ (bodyOrder ?? []).forEach((id2, index) => bodyIndex.set(id2.toLowerCase(), index));
41427
+ const indexOf = (r) => bodyIndex.get(r.identifier.toLowerCase()) ?? null;
41428
+ const inBody = roots.filter((r) => indexOf(r) !== null);
41429
+ const orderSource = inBody.length > 0 ? "body" : "creation";
41430
+ const orderedRoots = [
41431
+ ...inBody.sort((a, b) => indexOf(a) - indexOf(b)),
41432
+ ...roots.filter((r) => indexOf(r) === null)
41433
+ ];
41434
+ const accountDirs = /* @__PURE__ */ new Map();
41435
+ const previewEntries = /* @__PURE__ */ new Map();
41436
+ const accountDirFor = (account) => {
41437
+ if (!accountDirs.has(account))
41438
+ accountDirs.set(account, resolveAccountDir(containerDir, account));
41439
+ return accountDirs.get(account) ?? null;
41440
+ };
41441
+ const record2 = (row, parent) => {
41442
+ const accountDir = accountDirFor(row.accountIdentifier ?? parent?.accountIdentifier ?? null);
41443
+ let assetPaths = [];
41444
+ let previews = [];
41445
+ if (accountDir) {
41446
+ if (!previewEntries.has(accountDir))
41447
+ previewEntries.set(accountDir, listPreviewEntries(accountDir));
41448
+ assetPaths = assetPathsFor(accountDir, row);
41449
+ previews = previewPaths(accountDir, row.identifier, previewEntries.get(accountDir));
41450
+ }
41451
+ const previewPath = previews[0] ?? null;
41452
+ return {
41453
+ pk: row.pk,
41454
+ identifier: row.identifier,
41455
+ uti: row.uti,
41456
+ kind: classifyAttachmentKind(row.uti),
41457
+ parentIdentifier: parent?.identifier ?? null,
41458
+ filename: row.filename ?? row.mediaFilename,
41459
+ bodyIndex: parent ? null : indexOf(row),
41460
+ assetPaths,
41461
+ previewPath,
41462
+ paths: previewPath ? [...assetPaths, previewPath] : [...assetPaths]
41463
+ };
41464
+ };
41465
+ const attachments = [];
41466
+ for (const root of orderedRoots) {
41467
+ attachments.push(record2(root, null));
41468
+ for (const child of rows.filter((r) => r.parentPk === root.pk && r !== root)) {
41469
+ attachments.push(record2(child, root));
41470
+ }
41471
+ }
41472
+ return { orderSource, attachments };
41473
+ }
41474
+ function selectFirstImage(assets) {
41475
+ const candidates = assets.attachments.filter((a) => {
41476
+ if (a.parentIdentifier !== null) return true;
41477
+ return assets.orderSource === "creation" || a.bodyIndex !== null;
41478
+ });
41479
+ const eligibleChild = (a) => a.parentIdentifier === null || candidates.some((p) => p.parentIdentifier === null && p.identifier === a.parentIdentifier);
41480
+ const ordered = candidates.filter(eligibleChild);
41481
+ const chosen = ordered.find((a) => a.kind === "image") ?? ordered.find((a) => a.kind === "scan" || a.kind === "drawing");
41482
+ if (!chosen) return null;
41483
+ const siblings = chosen.parentIdentifier ? ordered.filter((a) => a.parentIdentifier === chosen.parentIdentifier) : [];
41484
+ return {
41485
+ pk: chosen.pk,
41486
+ identifier: chosen.identifier,
41487
+ uti: chosen.uti,
41488
+ kind: chosen.kind,
41489
+ path: chosen.assetPaths[0] ?? null,
41490
+ previewPath: chosen.previewPath,
41491
+ parentIdentifier: chosen.parentIdentifier,
41492
+ galleryIndex: chosen.parentIdentifier ? siblings.indexOf(chosen) : null,
41493
+ orderSource: assets.orderSource
41494
+ };
41495
+ }
41496
+ function canonicalTail(p) {
41497
+ let current = resolve2(p);
41498
+ const tail = [];
41499
+ for (; ; ) {
41500
+ try {
41501
+ return join6(realpathSync2.native(current), ...tail);
41502
+ } catch {
41503
+ const parent = dirname2(current);
41504
+ if (parent === current) return join6(current, ...tail);
41505
+ tail.unshift(basename(current));
41506
+ current = parent;
41507
+ }
41508
+ }
41509
+ }
41510
+ function isInsideNotesContainer(p, containerDir = NOTES_CONTAINER_DIR) {
41511
+ const target = canonicalTail(p).toLowerCase();
41512
+ const container = canonicalTail(containerDir).toLowerCase();
41513
+ const rel = relative2(container, target);
41514
+ return !(rel === ".." || rel.startsWith(`..${sep2}`) || isAbsolute2(rel));
41515
+ }
41516
+ function copyFileExclusive(src, dest) {
41517
+ const input = openSync2(src, constants2.O_RDONLY | constants2.O_NOFOLLOW);
41518
+ try {
41519
+ if (!fstatSync2(input).isFile()) throw new Error("Source is not a regular file");
41520
+ const output = openSync2(
41521
+ dest,
41522
+ constants2.O_WRONLY | constants2.O_CREAT | constants2.O_EXCL | constants2.O_NOFOLLOW,
41523
+ 384
41524
+ );
41525
+ try {
41526
+ const buffer = Buffer.allocUnsafe(1024 * 1024);
41527
+ for (; ; ) {
41528
+ const read = readSync(input, buffer, 0, buffer.length, null);
41529
+ if (read === 0) break;
41530
+ let written = 0;
41531
+ while (written < read) written += writeSync(output, buffer, written, read - written);
41532
+ }
41533
+ } catch (error2) {
41534
+ closeSync2(output);
41535
+ unlinkSync(dest);
41536
+ throw error2;
41537
+ }
41538
+ closeSync2(output);
41539
+ } finally {
41540
+ closeSync2(input);
41541
+ }
41542
+ }
41543
+ function exportFileName(record2, source, kind) {
41544
+ const ext = extname(source);
41545
+ if (kind === "preview") {
41546
+ const stored2 = safeComponent(record2.filename ? basename(record2.filename) : null);
41547
+ const stem = stored2 ? basename(stored2, extname(stored2)) : record2.identifier;
41548
+ return `${safeComponent(stem) ?? record2.identifier}-preview${ext}`;
41549
+ }
41550
+ const stored = safeComponent(record2.filename ? basename(record2.filename) : null);
41551
+ if (stored && !GENERIC_FILE_NAMES.has(stored.toLowerCase())) return stored;
41552
+ const own = basename(source);
41553
+ if (!GENERIC_FILE_NAMES.has(own.toLowerCase())) return own;
41554
+ return `${record2.identifier}${ext}`;
41555
+ }
41556
+ function collisionName(name, attempt) {
41557
+ if (attempt <= 1) return name;
41558
+ const ext = extname(name);
41559
+ const stem = ext && ext !== name ? name.slice(0, -ext.length) : name;
41560
+ return `${stem}-${attempt}${ext}`;
41561
+ }
41562
+ function prepareExportDir(exportDir, containerDir = NOTES_CONTAINER_DIR) {
41563
+ const abs = assertSafeSavePath(exportDir);
41564
+ if (isInsideNotesContainer(abs, containerDir)) {
41565
+ throw new Error(`Refusing to write inside the Notes data container: "${abs}"`);
41566
+ }
41567
+ mkdirSync2(abs, { recursive: true });
41568
+ if (isInsideNotesContainer(abs, containerDir)) {
41569
+ throw new Error(`Refusing to write inside the Notes data container: "${abs}"`);
41570
+ }
41571
+ return abs;
41572
+ }
41573
+ function exportOneAttachment(record2, dir, source) {
41574
+ const base = {
41575
+ pk: record2.pk,
41576
+ identifier: record2.identifier,
41577
+ uti: record2.uti,
41578
+ kind: record2.kind,
41579
+ parentIdentifier: record2.parentIdentifier,
41580
+ exportedTo: null,
41581
+ exportedKind: null
41582
+ };
41583
+ if (!source) return base;
41584
+ const name = exportFileName(record2, source.path, source.kind);
41585
+ for (let attempt = 1; attempt <= MAX_COLLISION_SUFFIX; attempt++) {
41586
+ const dest = join6(dir, collisionName(name, attempt));
41587
+ try {
41588
+ assertSafeSavePath(dest);
41589
+ copyFileExclusive(source.path, dest);
41590
+ return { ...base, exportedTo: dest, exportedKind: source.kind };
41591
+ } catch (error2) {
41592
+ if (error2.code === "EEXIST") continue;
41593
+ return { ...base, error: error2 instanceof Error ? error2.message : String(error2) };
41594
+ }
41595
+ }
41596
+ return { ...base, error: "Too many name collisions in the export directory" };
41597
+ }
41598
+ function exportSource(record2) {
41599
+ if (record2.assetPaths[0]) return { path: record2.assetPaths[0], kind: "asset" };
41600
+ if (record2.previewPath) return { path: record2.previewPath, kind: "preview" };
41601
+ return null;
41602
+ }
41603
+ function exportAttachmentAssets(assets, exportDir, options = {}) {
41604
+ const dir = prepareExportDir(exportDir, options.containerDir);
41605
+ if (options.firstImageOnly) {
41606
+ const first2 = selectFirstImage(assets);
41607
+ if (!first2) return { exportDir: dir, results: [], firstImage: null };
41608
+ const record2 = assets.attachments.find((a) => a.pk === first2.pk);
41609
+ return {
41610
+ exportDir: dir,
41611
+ results: [exportOneAttachment(record2, dir, exportSource(record2))],
41612
+ firstImage: first2
41613
+ };
41614
+ }
41615
+ const results = [];
41616
+ for (const record2 of assets.attachments) {
41617
+ if (record2.parentIdentifier !== null) {
41618
+ const parent = assets.attachments.find(
41619
+ (a) => a.parentIdentifier === null && a.identifier === record2.parentIdentifier
41620
+ );
41621
+ if (parent && exportSource(parent)) continue;
41622
+ } else if (!exportSource(record2) && assets.attachments.some((c) => c.parentIdentifier === record2.identifier)) {
41623
+ continue;
41624
+ }
41625
+ results.push(exportOneAttachment(record2, dir, exportSource(record2)));
41626
+ }
41627
+ return { exportDir: dir, results };
41628
+ }
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(path7) {
41675
+ let fd;
41676
+ try {
41677
+ fd = openSync3(path7, 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 col2 = (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', ${col2("ZHANDWRITINGSUMMARY")}`,
41701
+ `'fallbackImageGeneration', ${col2("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(path7) {
41778
+ try {
41779
+ const st = lstatSync3(path7);
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 [path7, source] of [
41846
+ [fallbackImagePath, "fallback"],
41847
+ [previewPath, "preview"]
41848
+ ]) {
41849
+ const info = path7 ? readImageInfo(path7) : null;
41850
+ if (path7 && info) {
41851
+ raster = { path: path7, 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, path7, expected) {
41869
+ const check2 = readImageInfoFd(fd);
41870
+ if (!check2 || check2.format !== expected.format || check2.width !== expected.width || check2.height !== expected.height) {
41871
+ unlinkSync2(path7);
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
+
41039
41967
  // src/services/appleNotesManager.ts
41040
41968
  var import_turndown = __toESM(require_turndown_cjs(), 1);
41041
41969
  import { existsSync as existsSync4 } from "fs";
41042
- import { homedir as homedir6 } from "os";
41043
- import { join as join6 } from "path";
41970
+ import { homedir as homedir7 } from "os";
41971
+ import { join as join8 } from "path";
41044
41972
  var FIELD_SEP = "";
41045
41973
  var RECORD_SEP = "";
41046
41974
  var AS_FIELD_SEP = "(character id 31)";
@@ -41268,7 +42196,7 @@ function getNoteLinkFromDB(coreDataId2) {
41268
42196
  const match = coreDataId2.match(/\/p(\d+)$/);
41269
42197
  if (!match) return null;
41270
42198
  const pk = parseInt(match[1], 10);
41271
- const dbPath2 = join6(homedir6(), "Library/Group Containers/group.com.apple.notes/NoteStore.sqlite");
42199
+ const dbPath2 = join8(homedir7(), "Library/Group Containers/group.com.apple.notes/NoteStore.sqlite");
41272
42200
  if (!existsSync4(dbPath2)) return null;
41273
42201
  try {
41274
42202
  const { DatabaseSync } = __require("node:sqlite");
@@ -42265,7 +43193,7 @@ var AppleNotesManager = class {
42265
43193
  return [];
42266
43194
  }
42267
43195
  const recordSeparator = result.output.includes(RECORD_SEP) ? RECORD_SEP : "\n";
42268
- const entries = result.output.split(recordSeparator).map((line) => {
43196
+ const entries2 = result.output.split(recordSeparator).map((line) => {
42269
43197
  const parts = line.includes(FIELD_SEP) ? line.split(FIELD_SEP) : line.split(" ");
42270
43198
  return {
42271
43199
  id: (parts[0] || "").trim(),
@@ -42278,7 +43206,7 @@ var AppleNotesManager = class {
42278
43206
  account: (parts[4] || "").trim()
42279
43207
  };
42280
43208
  });
42281
- const byId = new Map(entries.map((e) => [e.id, e]));
43209
+ const byId = new Map(entries2.map((e) => [e.id, e]));
42282
43210
  const buildPath = (entry) => {
42283
43211
  const safeName = escapeFolderName(entry.name);
42284
43212
  if (!entry.parentId) return safeName;
@@ -42288,7 +43216,7 @@ var AppleNotesManager = class {
42288
43216
  }
42289
43217
  return safeName;
42290
43218
  };
42291
- return entries.map((entry) => ({
43219
+ return entries2.map((entry) => ({
42292
43220
  id: entry.id,
42293
43221
  name: buildPath(entry),
42294
43222
  account: entry.account || targetAccount || "",
@@ -43190,6 +44118,55 @@ var AppleNotesManager = class {
43190
44118
  cleanupTempDir(dir);
43191
44119
  }
43192
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
+ }
44139
+ /**
44140
+ * Reads one note's attachments with their on-disk asset and preview paths,
44141
+ * in body order, from the NoteStore database and the Notes group container
44142
+ * (both read-only). Requires Full Disk Access.
44143
+ *
44144
+ * @param noteId - canonical CoreData note id
44145
+ * @throws AttachmentStoreError (`no_fda`, `invalid_id`, `not_found`, `query_error`)
44146
+ */
44147
+ getAttachmentAssetsById(noteId3) {
44148
+ const { rows, bodyOrder } = readNoteAttachmentRows(noteId3);
44149
+ return assembleAttachmentAssets(rows, bodyOrder);
44150
+ }
44151
+ /**
44152
+ * The note's lead visual: the first image in body order (even when its asset
44153
+ * has not downloaded), else the first scan or drawing, else null.
44154
+ */
44155
+ getFirstImageById(noteId3) {
44156
+ return selectFirstImage(this.getAttachmentAssetsById(noteId3));
44157
+ }
44158
+ /**
44159
+ * Copies a note's attachment files into a directory. Each attachment exports
44160
+ * its real asset; its rendered preview only when no asset exists. Existing
44161
+ * files are never replaced: name collisions get `-2`, `-3`, ... suffixes.
44162
+ * The directory must satisfy the same allowlist as save-attachment and may
44163
+ * not be inside the Notes group container.
44164
+ */
44165
+ exportAttachmentsById(noteId3, exportDir, firstImageOnly = false) {
44166
+ return exportAttachmentAssets(this.getAttachmentAssetsById(noteId3), exportDir, {
44167
+ firstImageOnly
44168
+ });
44169
+ }
43193
44170
  // ===========================================================================
43194
44171
  // Batch Operations
43195
44172
  // ===========================================================================
@@ -43603,7 +44580,7 @@ var AppleNotesManager = class {
43603
44580
  };
43604
44581
 
43605
44582
  // src/utils/syncDetection.ts
43606
- import { execFileSync as execFileSync6 } from "child_process";
44583
+ import { execFileSync as execFileSync8 } from "child_process";
43607
44584
  import * as fs3 from "fs";
43608
44585
  import * as path3 from "path";
43609
44586
  import * as os3 from "os";
@@ -43648,7 +44625,7 @@ function getSyncStatus(useCache = true) {
43648
44625
  WHERE object.ZCLOUDSTATE = state.Z_PK
43649
44626
  );
43650
44627
  `;
43651
- const result = execFileSync6(
44628
+ const result = execFileSync8(
43652
44629
  "sqlite3",
43653
44630
  ["-readonly", NOTES_DB_PATH4, query.replace(/\n/g, " ")],
43654
44631
  {
@@ -43707,7 +44684,7 @@ function withSyncAwarenessSync(operation, fn) {
43707
44684
  }
43708
44685
 
43709
44686
  // src/utils/noteMetadata.ts
43710
- import { execFileSync as execFileSync7 } from "child_process";
44687
+ import { execFileSync as execFileSync9 } from "child_process";
43711
44688
  import * as fs4 from "fs";
43712
44689
  import * as path4 from "path";
43713
44690
  import * as os4 from "os";
@@ -43727,15 +44704,15 @@ var COLUMN_MAP = [
43727
44704
  { key: "widgetSnippet", column: "ZWIDGETSNIPPET", type: "text" },
43728
44705
  { key: "smartFolderQuery", column: "ZSMARTFOLDERQUERYJSON", type: "text" }
43729
44706
  ];
43730
- function runSqlite3(query) {
43731
- return execFileSync7("sqlite3", ["-readonly", NOTES_DB_PATH5, query], {
44707
+ function runSqlite5(query) {
44708
+ return execFileSync9("sqlite3", ["-readonly", NOTES_DB_PATH5, query], {
43732
44709
  encoding: "utf8",
43733
44710
  timeout: 5e3,
43734
44711
  stdio: ["pipe", "pipe", "pipe"]
43735
44712
  }).trim();
43736
44713
  }
43737
44714
  function presentColumns() {
43738
- const out = runSqlite3("PRAGMA table_info(ZICCLOUDSYNCINGOBJECT);");
44715
+ const out = runSqlite5("PRAGMA table_info(ZICCLOUDSYNCINGOBJECT);");
43739
44716
  const cols = /* @__PURE__ */ new Set();
43740
44717
  for (const line of out.split("\n")) {
43741
44718
  const name = line.split("|")[1];
@@ -43763,7 +44740,7 @@ function getNoteMetadata(noteId3) {
43763
44740
  return { metadata: {} };
43764
44741
  }
43765
44742
  const pairs = selected.map((c) => `'${c.key}', ${c.column}`).join(", ");
43766
- const row = runSqlite3(
44743
+ const row = runSqlite5(
43767
44744
  `SELECT json_object(${pairs}) FROM ZICCLOUDSYNCINGOBJECT WHERE Z_PK = ${pk};`
43768
44745
  );
43769
44746
  if (!row) {
@@ -43796,7 +44773,7 @@ function getNoteMetadata(noteId3) {
43796
44773
  }
43797
44774
 
43798
44775
  // src/utils/noteIdentifiers.ts
43799
- import { execFileSync as execFileSync8 } from "child_process";
44776
+ import { execFileSync as execFileSync10 } from "child_process";
43800
44777
  import * as fs5 from "fs";
43801
44778
  import * as os5 from "os";
43802
44779
  import * as path5 from "path";
@@ -43878,7 +44855,7 @@ function runJsonQuery(sql, dbPath2) {
43878
44855
  if (!fs5.existsSync(dbPath2)) throw new IdentifierResolutionError("no_fda", NO_FDA_MESSAGE);
43879
44856
  let out;
43880
44857
  try {
43881
- out = execFileSync8("sqlite3", ["-readonly", dbPath2, sql], {
44858
+ out = execFileSync10("sqlite3", ["-readonly", dbPath2, sql], {
43882
44859
  encoding: "utf8",
43883
44860
  timeout: 5e3,
43884
44861
  stdio: ["pipe", "pipe", "pipe"]
@@ -44568,11 +45545,11 @@ function positiveTextTerms(node, negated = false) {
44568
45545
  }
44569
45546
 
44570
45547
  // src/utils/noteQueryStore.ts
44571
- import { execFileSync as execFileSync9 } from "child_process";
45548
+ import { execFileSync as execFileSync11 } from "child_process";
44572
45549
  import * as fs6 from "fs";
44573
45550
  import * as os6 from "os";
44574
45551
  import * as path6 from "path";
44575
- import { gunzipSync as gunzipSync5 } from "zlib";
45552
+ import { gunzipSync as gunzipSync6 } from "zlib";
44576
45553
  var NOTES_DB_PATH7 = path6.join(
44577
45554
  os6.homedir(),
44578
45555
  "Library/Group Containers/group.com.apple.notes/NoteStore.sqlite"
@@ -44708,8 +45685,8 @@ function buildScanSql(available, options) {
44708
45685
  "COMMIT;"
44709
45686
  ].join(" ");
44710
45687
  }
44711
- function runSqlite4(dbPath2, query) {
44712
- return execFileSync9("sqlite3", ["-readonly", dbPath2, query], {
45688
+ function runSqlite6(dbPath2, query) {
45689
+ return execFileSync11("sqlite3", ["-readonly", dbPath2, query], {
44713
45690
  encoding: "utf8",
44714
45691
  timeout: 3e4,
44715
45692
  maxBuffer: 512 * 1024 * 1024,
@@ -44718,7 +45695,7 @@ function runSqlite4(dbPath2, query) {
44718
45695
  }
44719
45696
  function presentColumns2(dbPath2) {
44720
45697
  const cols = /* @__PURE__ */ new Set();
44721
- for (const line of runSqlite4(dbPath2, "PRAGMA table_info(ZICCLOUDSYNCINGOBJECT);").split("\n")) {
45698
+ for (const line of runSqlite6(dbPath2, "PRAGMA table_info(ZICCLOUDSYNCINGOBJECT);").split("\n")) {
44722
45699
  const name = line.split("|")[1];
44723
45700
  if (name) cols.add(name);
44724
45701
  }
@@ -44728,13 +45705,13 @@ var escapeSegment = escapeFolderName;
44728
45705
  function resolveFolders(rows) {
44729
45706
  const byPk = new Map(rows.map((row) => [row.pk, row]));
44730
45707
  const resolved = /* @__PURE__ */ new Map();
44731
- const resolve3 = (pk, seen) => {
45708
+ const resolve4 = (pk, seen) => {
44732
45709
  const cached2 = resolved.get(pk);
44733
45710
  if (cached2) return cached2;
44734
45711
  const row = byPk.get(pk);
44735
45712
  if (!row || seen.has(pk)) return void 0;
44736
45713
  seen.add(pk);
44737
- const parent = row.parent !== null ? resolve3(row.parent, seen) : void 0;
45714
+ const parent = row.parent !== null ? resolve4(row.parent, seen) : void 0;
44738
45715
  const name = row.name ?? "";
44739
45716
  const path7 = parent ? `${parent.path}/${escapeSegment(name)}` : escapeSegment(name);
44740
45717
  const plainPath = parent ? `${parent.plainPath}/${name}` : name;
@@ -44748,7 +45725,7 @@ function resolveFolders(rows) {
44748
45725
  resolved.set(pk, info);
44749
45726
  return info;
44750
45727
  };
44751
- for (const row of rows) resolve3(row.pk, /* @__PURE__ */ new Set());
45728
+ for (const row of rows) resolve4(row.pk, /* @__PURE__ */ new Set());
44752
45729
  return resolved;
44753
45730
  }
44754
45731
  var coreDataMs = (seconds) => seconds === null || !Number.isFinite(seconds) ? void 0 : CORE_DATA_EPOCH_MS + seconds * 1e3;
@@ -44778,7 +45755,7 @@ function queryNotes(expression, options = {}) {
44778
45755
  let output;
44779
45756
  try {
44780
45757
  const available = presentColumns2(dbPath2);
44781
- output = runSqlite4(
45758
+ output = runSqlite6(
44782
45759
  dbPath2,
44783
45760
  buildScanSql(available, { scanLimit, includeDeleted, withBodies, withTags })
44784
45761
  );
@@ -44834,7 +45811,7 @@ function queryNotes(expression, options = {}) {
44834
45811
  try {
44835
45812
  decoded = decodeNoteBody(
44836
45813
  new Uint8Array(
44837
- gunzipSync5(Buffer.from(row.data, "hex"), { maxOutputLength: 32 * 1024 * 1024 })
45814
+ gunzipSync6(Buffer.from(row.data, "hex"), { maxOutputLength: 32 * 1024 * 1024 })
44838
45815
  )
44839
45816
  );
44840
45817
  } catch {
@@ -44909,10 +45886,10 @@ function queryNotes(expression, options = {}) {
44909
45886
  import { spawnSync } from "child_process";
44910
45887
 
44911
45888
  // src/services/nativeTags.ts
44912
- import { execFileSync as execFileSync10 } from "node:child_process";
45889
+ import { execFileSync as execFileSync12 } from "node:child_process";
44913
45890
  import { mkdtempSync as mkdtempSync2, writeFileSync, rmSync as rmSync2 } from "node:fs";
44914
45891
  import { tmpdir as tmpdir2 } from "node:os";
44915
- import { join as join11 } from "node:path";
45892
+ import { join as join13 } from "node:path";
44916
45893
 
44917
45894
  // src/services/shortcutConsent.ts
44918
45895
  function shortcutConsentHint(shortcut) {
@@ -44988,7 +45965,7 @@ function addNativeTags(request, deps) {
44988
45965
  };
44989
45966
  }
44990
45967
  function listInstalledShortcuts() {
44991
- return execFileSync10("/usr/bin/shortcuts", ["list", "--show-identifiers"], {
45968
+ return execFileSync12("/usr/bin/shortcuts", ["list", "--show-identifiers"], {
44992
45969
  encoding: "utf8",
44993
45970
  timeout: 15e3,
44994
45971
  maxBuffer: 1024 * 1024,
@@ -45014,11 +45991,11 @@ function runNativeTagsShortcut(input) {
45014
45991
  const status = nativeTagsStatus();
45015
45992
  if (!status.installed)
45016
45993
  throw new Error(`Import the supplied ${status.shortcut}.shortcut in Shortcuts first`);
45017
- const directory = mkdtempSync2(join11(tmpdir2(), "apple-notes-native-tags-"));
45994
+ const directory = mkdtempSync2(join13(tmpdir2(), "apple-notes-native-tags-"));
45018
45995
  try {
45019
- const path7 = join11(directory, "request.json");
45996
+ const path7 = join13(directory, "request.json");
45020
45997
  writeFileSync(path7, JSON.stringify(input), { mode: 384 });
45021
- execFileSync10("/usr/bin/shortcuts", ["run", status.identifier, "--input-path", path7], {
45998
+ execFileSync12("/usr/bin/shortcuts", ["run", status.identifier, "--input-path", path7], {
45022
45999
  encoding: "utf8",
45023
46000
  timeout: 6e4,
45024
46001
  maxBuffer: 1024 * 1024,
@@ -45037,10 +46014,10 @@ function runNativeTagsShortcut(input) {
45037
46014
  }
45038
46015
 
45039
46016
  // src/services/backgroundNotes.ts
45040
- import { execFileSync as execFileSync11 } from "node:child_process";
46017
+ import { execFileSync as execFileSync13 } from "node:child_process";
45041
46018
  import { mkdtempSync as mkdtempSync3, writeFileSync as writeFileSync2, rmSync as rmSync3 } from "node:fs";
45042
46019
  import { tmpdir as tmpdir3 } from "node:os";
45043
- import { join as join12 } from "node:path";
46020
+ import { join as join14 } from "node:path";
45044
46021
 
45045
46022
  // src/utils/appendMarkdown.ts
45046
46023
  var escape2 = (s) => s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
@@ -45365,9 +46342,9 @@ function runBackgroundShortcut(input, status = backgroundStatus()) {
45365
46342
  throw new Error(
45366
46343
  `Install the supplied "${status.shortcut}" Shortcut once; Shortcuts must list it exactly once`
45367
46344
  );
45368
- const directory = mkdtempSync3(join12(tmpdir3(), "apple-notes-background-"));
46345
+ const directory = mkdtempSync3(join14(tmpdir3(), "apple-notes-background-"));
45369
46346
  try {
45370
- const file = join12(directory, "request.json");
46347
+ const file = join14(directory, "request.json");
45371
46348
  writeFileSync2(
45372
46349
  file,
45373
46350
  JSON.stringify({
@@ -45387,7 +46364,7 @@ function runBackgroundShortcut(input, status = backgroundStatus()) {
45387
46364
  { mode: 384 }
45388
46365
  );
45389
46366
  try {
45390
- execFileSync11("/usr/bin/shortcuts", ["run", status.identifier, "--input-path", file], {
46367
+ execFileSync13("/usr/bin/shortcuts", ["run", status.identifier, "--input-path", file], {
45391
46368
  encoding: "utf8",
45392
46369
  timeout: callTimeoutMs() ?? 6e4,
45393
46370
  maxBuffer: 1024 * 1024,
@@ -45712,7 +46689,7 @@ ${request.content}`
45712
46689
  }
45713
46690
 
45714
46691
  // src/services/capabilityMatrix.ts
45715
- import { execFileSync as execFileSync12 } from "node:child_process";
46692
+ import { execFileSync as execFileSync14 } from "node:child_process";
45716
46693
  import { release } from "node:os";
45717
46694
  var MACOS_SHORTCUTS_CLI = "12.0";
45718
46695
  var MACOS_MARKDOWN_IMPORT = "26.0";
@@ -45919,7 +46896,7 @@ function evaluateFeatures(env, features = FEATURES) {
45919
46896
  function readMacOSVersion() {
45920
46897
  if (process.platform !== "darwin") return null;
45921
46898
  try {
45922
- const out = execFileSync12("/usr/bin/sw_vers", ["-productVersion"], {
46899
+ const out = execFileSync14("/usr/bin/sw_vers", ["-productVersion"], {
45923
46900
  encoding: "utf8",
45924
46901
  timeout: 3e3,
45925
46902
  stdio: ["ignore", "pipe", "ignore"]
@@ -46073,12 +47050,12 @@ function formatDoctorReport(r) {
46073
47050
 
46074
47051
  // src/services/fileConfig.ts
46075
47052
  import { existsSync as existsSync9, readFileSync as readFileSync2 } from "fs";
46076
- import { join as join13 } from "path";
46077
- import { homedir as homedir11 } from "os";
47053
+ import { join as join15 } from "path";
47054
+ import { homedir as homedir12 } from "os";
46078
47055
  function fileConfigPath(env = process.env) {
46079
47056
  const override = env.APPLE_NOTES_MCP_CONFIG_FILE;
46080
47057
  if (override && override.trim()) return override.trim();
46081
- return join13(homedir11(), "Library", "Application Support", "apple-notes-mcp", "config.json");
47058
+ return join15(homedir12(), "Library", "Application Support", "apple-notes-mcp", "config.json");
46082
47059
  }
46083
47060
  function loadFileConfig(env = process.env, path7 = fileConfigPath(env)) {
46084
47061
  const applied = [];
@@ -46381,11 +47358,11 @@ function createShutdown(stream, exit, timeoutMs = SHUTDOWN_DRAIN_TIMEOUT_MS) {
46381
47358
  }
46382
47359
 
46383
47360
  // src/utils/noteBlocks.ts
46384
- import { execFileSync as execFileSync13 } from "node:child_process";
47361
+ import { execFileSync as execFileSync15 } from "node:child_process";
46385
47362
  import { existsSync as existsSync10 } from "node:fs";
46386
- import { homedir as homedir12 } from "node:os";
46387
- import { join as join14 } from "node:path";
46388
- import { gunzipSync as gunzipSync6 } from "node:zlib";
47363
+ import { homedir as homedir13 } from "node:os";
47364
+ import { join as join16 } from "node:path";
47365
+ import { gunzipSync as gunzipSync7 } from "node:zlib";
46389
47366
  var NoteBlocksError = class extends Error {
46390
47367
  code;
46391
47368
  constructor(code, message) {
@@ -46673,7 +47650,7 @@ function summarize(blocks, attachments) {
46673
47650
  function decodeCompressedNoteBlocks(compressed) {
46674
47651
  let data;
46675
47652
  try {
46676
- data = gunzipSync6(compressed, { maxOutputLength: 32 * 1024 * 1024 });
47653
+ data = gunzipSync7(compressed, { maxOutputLength: 32 * 1024 * 1024 });
46677
47654
  } catch (error2) {
46678
47655
  throw new NoteBlocksError(
46679
47656
  "decompress-failed",
@@ -46727,8 +47704,8 @@ function pageNoteBlocks(doc, { offset = 0, limit = 500, maxBytes = blocksMaxResp
46727
47704
  undecodedFields: doc.undecodedFields
46728
47705
  };
46729
47706
  }
46730
- var NOTES_DB_PATH8 = join14(
46731
- homedir12(),
47707
+ var NOTES_DB_PATH8 = join16(
47708
+ homedir13(),
46732
47709
  "Library/Group Containers/group.com.apple.notes/NoteStore.sqlite"
46733
47710
  );
46734
47711
  function readNoteBlocks(id2, { dbPath: dbPath2 = NOTES_DB_PATH8 } = {}) {
@@ -46743,7 +47720,7 @@ function readNoteBlocks(id2, { dbPath: dbPath2 = NOTES_DB_PATH8 } = {}) {
46743
47720
  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));";
46744
47721
  let output;
46745
47722
  try {
46746
- output = execFileSync13(
47723
+ output = execFileSync15(
46747
47724
  "/usr/bin/sqlite3",
46748
47725
  ["-readonly", "-cmd", ".parameter init", "-cmd", `.parameter set @pk ${pk}`, dbPath2, sql],
46749
47726
  {
@@ -46894,17 +47871,17 @@ function insertLink(request, deps) {
46894
47871
  // src/tools/directOperations.ts
46895
47872
  import { createHash as createHash2 } from "node:crypto";
46896
47873
  import {
46897
- closeSync as closeSync2,
46898
- constants as constants2,
46899
- fstatSync as fstatSync2,
47874
+ closeSync as closeSync4,
47875
+ constants as constants4,
47876
+ fstatSync as fstatSync4,
46900
47877
  mkdtempSync as mkdtempSync4,
46901
- openSync as openSync2,
47878
+ openSync as openSync4,
46902
47879
  readFileSync as readFileSync3,
46903
47880
  rmSync as rmSync4,
46904
47881
  writeFileSync as writeFileSync3
46905
47882
  } from "node:fs";
46906
47883
  import { tmpdir as tmpdir4 } from "node:os";
46907
- import { basename, extname, isAbsolute as isAbsolute2, join as join15 } from "node:path";
47884
+ import { basename as basename3, extname as extname3, isAbsolute as isAbsolute3, join as join17 } from "node:path";
46908
47885
  var noteId = exactIdInput(
46909
47886
  "ICNote",
46910
47887
  /^x-coredata:\/\/[0-9a-f-]+\/ICNote\/p\d+$/i,
@@ -46948,10 +47925,10 @@ function assertExistingContentPreserved(before, after) {
46948
47925
  }
46949
47926
  }
46950
47927
  function localAttachment(path7) {
46951
- if (!isAbsolute2(path7)) throw new Error("An absolute local file path is required");
46952
- const descriptor = openSync2(path7, constants2.O_RDONLY | constants2.O_NOFOLLOW);
47928
+ if (!isAbsolute3(path7)) throw new Error("An absolute local file path is required");
47929
+ const descriptor = openSync4(path7, constants4.O_RDONLY | constants4.O_NOFOLLOW);
46953
47930
  try {
46954
- const stat = fstatSync2(descriptor);
47931
+ const stat = fstatSync4(descriptor);
46955
47932
  if (!stat.isFile() || stat.size === 0 || stat.size > 64 * 1024 * 1024)
46956
47933
  throw new Error("Attachment must be a nonempty regular file of at most 64 MiB");
46957
47934
  const bytes = readFileSync3(descriptor);
@@ -46959,7 +47936,7 @@ function localAttachment(path7) {
46959
47936
  throw new Error("Attachment changed while it was being read; try again");
46960
47937
  return bytes;
46961
47938
  } finally {
46962
- closeSync2(descriptor);
47939
+ closeSync4(descriptor);
46963
47940
  }
46964
47941
  }
46965
47942
  function registerDirectOperations(server2, manager) {
@@ -47072,7 +48049,7 @@ function registerDirectOperations(server2, manager) {
47072
48049
  );
47073
48050
  }
47074
48051
  function attachmentName(path7, filename) {
47075
- const source = basename(path7);
48052
+ const source = basename3(path7);
47076
48053
  if (filename === void 0) return source;
47077
48054
  if (Buffer.byteLength(filename, "utf8") > 255)
47078
48055
  throw new Error("filename must be at most 255 bytes");
@@ -47080,9 +48057,9 @@ function attachmentName(path7, filename) {
47080
48057
  throw new Error(
47081
48058
  "filename must be one path component with no slash, colon, backslash, control character, leading dot, or surrounding spaces"
47082
48059
  );
47083
- if (extname(filename).toLowerCase() !== extname(source).toLowerCase())
48060
+ if (extname3(filename).toLowerCase() !== extname3(source).toLowerCase())
47084
48061
  throw new Error(
47085
- `filename must keep the source file's extension (${extname(source) || "none"})`
48062
+ `filename must keep the source file's extension (${extname3(source) || "none"})`
47086
48063
  );
47087
48064
  return filename;
47088
48065
  }
@@ -47093,8 +48070,8 @@ function attachFile(manager, args) {
47093
48070
  if (before.hash !== expectedContentHash) throw new Error("Note revision changed");
47094
48071
  const bytes = localAttachment(path7);
47095
48072
  const beforeAttachments = manager.listAttachmentsById(id2);
47096
- const directory = mkdtempSync4(join15(tmpdir4(), "notes-attachment-add-"));
47097
- const temporaryFile = join15(directory, name);
48073
+ const directory = mkdtempSync4(join17(tmpdir4(), "notes-attachment-add-"));
48074
+ const temporaryFile = join17(directory, name);
47098
48075
  try {
47099
48076
  writeFileSync3(temporaryFile, bytes, { mode: 384 });
47100
48077
  if (readSnapshot(manager, id2).hash !== before.hash) throw new Error("Note revision changed");
@@ -47654,7 +48631,7 @@ function registerNativeOperations(server2, manager) {
47654
48631
  import { spawnSync as spawnSync2 } from "node:child_process";
47655
48632
  import { existsSync as existsSync11 } from "node:fs";
47656
48633
  import { release as release2 } from "node:os";
47657
- import { dirname as dirname2, resolve as resolve2 } from "node:path";
48634
+ import { dirname as dirname4, resolve as resolve3 } from "node:path";
47658
48635
  import { fileURLToPath } from "node:url";
47659
48636
  var OPTIONAL_BRIDGE_NOTE = "(optional \u2014 needed only for create-note format: markdown, macOS 26+)";
47660
48637
  var MARKDOWN_MIN_DARWIN_MAJOR = 25;
@@ -47677,11 +48654,11 @@ function setupShortcuts(checkOnly, dependencies = {}) {
47677
48654
  const result = spawnSync2("/usr/bin/open", [path7], { encoding: "utf8" });
47678
48655
  return result.status === 0 ? { ok: true } : { ok: false, error: result.stderr || result.error?.message || "open failed" };
47679
48656
  });
47680
- const baseDirectory = dependencies.baseDirectory || resolve2(dirname2(fileURLToPath(import.meta.url)), "../shortcuts");
48657
+ const baseDirectory = dependencies.baseDirectory || resolve3(dirname4(fileURLToPath(import.meta.url)), "../shortcuts");
47681
48658
  const osRelease = (dependencies.osRelease || release2)();
47682
48659
  const darwinMajor = Number.parseInt(osRelease.split(".")[0], 10);
47683
48660
  const items = shortcutFiles.map(({ name, file, optional: optional2 }) => {
47684
- const path7 = resolve2(baseDirectory, file);
48661
+ const path7 = resolve3(baseDirectory, file);
47685
48662
  let installed = false;
47686
48663
  let identifier;
47687
48664
  let error2;
@@ -48794,10 +49771,10 @@ function guardedAppend({
48794
49771
  return `<div>${escaped || "<br>"}</div>`;
48795
49772
  }).join("");
48796
49773
  };
48797
- const separatorToHtml = (sep2) => {
48798
- if (format === "html") return sep2;
48799
- if (sep2 === "\n\n") return "<div><br></div>";
48800
- const escaped = sep2.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
49774
+ const separatorToHtml = (sep3) => {
49775
+ if (format === "html") return sep3;
49776
+ if (sep3 === "\n\n") return "<div><br></div>";
49777
+ const escaped = sep3.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
48801
49778
  return `<div>${escaped}</div>`;
48802
49779
  };
48803
49780
  const snapshot = readExactNoteSnapshot(id2);
@@ -49513,21 +50490,57 @@ registerTool(
49513
50490
  return successResponse(lines.join("\n"), { ...stats });
49514
50491
  }, "Error getting notes statistics")
49515
50492
  );
50493
+ function attachmentAssetView(noteId3, record2) {
50494
+ return {
50495
+ attachmentId: attachmentCoreDataId(noteId3, record2.pk),
50496
+ identifier: record2.identifier,
50497
+ uti: record2.uti,
50498
+ kind: record2.kind,
50499
+ parentIdentifier: record2.parentIdentifier,
50500
+ bodyIndex: record2.bodyIndex,
50501
+ assetPaths: record2.assetPaths,
50502
+ previewPath: record2.previewPath,
50503
+ paths: record2.paths
50504
+ };
50505
+ }
50506
+ function firstImageView(noteId3, first2) {
50507
+ if (!first2) return null;
50508
+ const { pk, ...rest } = first2;
50509
+ return { attachmentId: attachmentCoreDataId(noteId3, pk), ...rest };
50510
+ }
49516
50511
  registerTool(
49517
50512
  "list-attachments",
49518
50513
  {
49519
- description: "Use when: listing the attachments of one note, by id (preferred) or title.\nReturns: each attachment's name, content type, and id (use with save-attachment/fetch-attachment).\nDo not use when: you want the attachment bytes (fetch-attachment) or a file on disk (save-attachment).",
50514
+ description: "Use when: listing the attachments of one note, by id (preferred) or title. With includePaths, also where each attachment's files are on disk; with firstImage, only the note's lead visual.\nReturns: each attachment's name, content type, and id (use with save-attachment/fetch-attachment). includePaths adds identifier, uti, kind, bodyIndex, assetPaths (the attachment's own files), previewPath (Notes' largest rendered thumbnail, always an image file), and paths. firstImage returns {firstImage, orderSource}: the first image in body order even when its asset has not downloaded (path null), else the first scan or drawing, else null.\nDo not use when: you want the attachment bytes (fetch-attachment) or files on disk (save-attachment, export-attachments).\nNote: includePaths and firstImage need the note id and Full Disk Access; they read NoteStore and the Notes data folder read-only. Treat the returned paths as local data: copy files out with export-attachments rather than handing raw paths on.",
49520
50515
  inputSchema: {
49521
50516
  id: looseNoteId(external_exports.string()).optional().describe(`Note ID (preferred - more reliable than title): ${NOTE_ID_FORMS}`),
49522
50517
  title: external_exports.string().max(MAX.TITLE).optional().describe("Note title (use id instead when available)"),
49523
- account: external_exports.string().max(MAX.ACCOUNT).optional().describe("Account containing the note (ignored if id is provided)")
50518
+ account: external_exports.string().max(MAX.ACCOUNT).optional().describe("Account containing the note (ignored if id is provided)"),
50519
+ includePaths: external_exports.boolean().optional().describe(
50520
+ "Add on-disk assetPaths, previewPath, and paths to each attachment (requires id and Full Disk Access)"
50521
+ ),
50522
+ firstImage: external_exports.boolean().optional().describe(
50523
+ "Return only the note's lead visual in body order instead of the list (requires id and Full Disk Access)"
50524
+ )
49524
50525
  },
49525
50526
  outputSchema: {
49526
50527
  attachments: external_exports.array(external_exports.object({}).passthrough()).optional(),
49527
- count: external_exports.number().optional()
50528
+ count: external_exports.number().optional(),
50529
+ firstImage: external_exports.object({}).passthrough().nullable().optional(),
50530
+ orderSource: external_exports.enum(["body", "creation"]).optional(),
50531
+ pathsError: external_exports.string().optional()
49528
50532
  }
49529
50533
  },
49530
- withErrorHandling(({ id: id2, title, account }) => {
50534
+ withErrorHandling(({ id: id2, title, account, includePaths = false, firstImage = false }) => {
50535
+ if ((includePaths || firstImage) && !id2) {
50536
+ return errorResponse("includePaths and firstImage require the note 'id'");
50537
+ }
50538
+ if (firstImage && id2) {
50539
+ const assets = notesManager.getAttachmentAssetsById(id2);
50540
+ const first2 = firstImageView(id2, selectFirstImage(assets));
50541
+ const text = first2 ? `Lead visual: ${first2.kind} attachment ${first2.attachmentId} (${first2.path ? "asset on disk" : first2.previewPath ? "preview only" : "not downloaded"}; order from ${assets.orderSource}).` : "This note has no image, scan, or drawing attachment.";
50542
+ return successResponse(text, { firstImage: first2, orderSource: assets.orderSource });
50543
+ }
49531
50544
  if (id2) {
49532
50545
  const note2 = notesManager.getNoteById(id2);
49533
50546
  if (!note2) {
@@ -49541,10 +50554,42 @@ registerTool(
49541
50554
  });
49542
50555
  }
49543
50556
  const attachmentList2 = attachments2.map((a) => ` - ${a.name} (${a.contentType})`).join("\n");
50557
+ if (!includePaths) {
50558
+ return successResponse(
50559
+ `Found ${attachments2.length} attachment(s) in "${note2.title}":
50560
+ ${attachmentList2}`,
50561
+ { attachments: attachments2, count: attachments2.length }
50562
+ );
50563
+ }
50564
+ let assets;
50565
+ try {
50566
+ assets = notesManager.getAttachmentAssetsById(id2);
50567
+ } catch (error2) {
50568
+ const pathsError = error2 instanceof Error ? error2.message : String(error2);
50569
+ return successResponse(
50570
+ `Found ${attachments2.length} attachment(s) in "${note2.title}" (paths unavailable: ${pathsError}):
50571
+ ${attachmentList2}`,
50572
+ { attachments: attachments2, count: attachments2.length, pathsError }
50573
+ );
50574
+ }
50575
+ const byPk = new Map(assets.attachments.map((r) => [r.pk, r]));
50576
+ let onDisk = 0;
50577
+ const enriched = attachments2.map((a) => {
50578
+ const pk = Number(/\/ICAttachment\/p(\d+)$/.exec(a.id)?.[1]);
50579
+ const record2 = byPk.get(pk);
50580
+ if (!record2) return a;
50581
+ if (record2.paths.length > 0) onDisk++;
50582
+ const children = assets.attachments.filter((c) => c.parentIdentifier === record2.identifier).map((c) => attachmentAssetView(id2, c));
50583
+ return {
50584
+ ...a,
50585
+ ...attachmentAssetView(id2, record2),
50586
+ ...children.length ? { children } : {}
50587
+ };
50588
+ });
49544
50589
  return successResponse(
49545
- `Found ${attachments2.length} attachment(s) in "${note2.title}":
50590
+ `Found ${attachments2.length} attachment(s) in "${note2.title}" (${onDisk} with files on disk; order from ${assets.orderSource}):
49546
50591
  ${attachmentList2}`,
49547
- { attachments: attachments2, count: attachments2.length }
50592
+ { attachments: enriched, count: attachments2.length, orderSource: assets.orderSource }
49548
50593
  );
49549
50594
  }
49550
50595
  if (!title) {
@@ -49698,6 +50743,143 @@ registerTool(
49698
50743
  });
49699
50744
  }, "Error saving attachment")
49700
50745
  );
50746
+ function drawingView(noteId3, d) {
50747
+ const { pk, raster, ...rest } = d;
50748
+ return {
50749
+ attachmentId: attachmentCoreDataId(noteId3, pk),
50750
+ ...rest,
50751
+ raster: raster ? { source: raster.source, format: raster.format, width: raster.width, height: raster.height } : null
50752
+ };
50753
+ }
50754
+ registerTool(
50755
+ "list-paper-attachments",
50756
+ {
50757
+ 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.",
50758
+ inputSchema: { id: noteIdInput },
50759
+ outputSchema: {
50760
+ attachments: external_exports.array(external_exports.object({}).passthrough()).optional(),
50761
+ count: external_exports.number().optional()
50762
+ },
50763
+ annotations: { readOnlyHint: true }
50764
+ },
50765
+ withErrorHandling(({ id: id2 }) => {
50766
+ const drawings = notesManager.listPaperAttachmentsById(id2).map((d) => drawingView(id2, d));
50767
+ if (drawings.length === 0) {
50768
+ return successResponse("This note has no Paper or drawing attachments.", {
50769
+ attachments: [],
50770
+ count: 0
50771
+ });
50772
+ }
50773
+ const lines = drawings.map(
50774
+ (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" : ""}`
50775
+ );
50776
+ return successResponse(
50777
+ `Found ${drawings.length} Paper or drawing attachment(s):
50778
+ ${lines.join("\n")}`,
50779
+ { attachments: drawings, count: drawings.length }
50780
+ );
50781
+ }, "Error listing Paper attachments")
50782
+ );
50783
+ registerTool(
50784
+ "export-paper-image",
50785
+ {
50786
+ 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.",
50787
+ inputSchema: {
50788
+ noteId: noteIdInput,
50789
+ savePath: external_exports.string().min(1, "savePath is required").max(MAX.SAVE_PATH).describe(
50790
+ "Absolute path for the new image file (.png, or .jpg/.jpeg for a JPEG rendering)"
50791
+ ),
50792
+ attachmentId: external_exports.string().max(MAX.ATTACHMENT_ID).optional().describe(
50793
+ "Drawing to export (attachmentId or identifier from list-paper-attachments); required when the note has more than one"
50794
+ )
50795
+ },
50796
+ outputSchema: {
50797
+ savedPath: external_exports.string().optional(),
50798
+ format: external_exports.enum(["png", "jpeg"]).optional(),
50799
+ width: external_exports.number().optional(),
50800
+ height: external_exports.number().optional(),
50801
+ bytes: external_exports.number().optional(),
50802
+ source: external_exports.enum(["fallback", "preview"]).optional(),
50803
+ attachmentId: external_exports.string().optional(),
50804
+ identifier: external_exports.string().optional(),
50805
+ kind: external_exports.enum(["paper", "drawing"]).optional(),
50806
+ handwritingSummary: external_exports.string().nullable().optional()
50807
+ }
50808
+ },
50809
+ withErrorHandling(({ noteId: noteId3, savePath, attachmentId }) => {
50810
+ const r = notesManager.exportPaperImageById(noteId3, savePath, attachmentId);
50811
+ return successResponse(
50812
+ `Saved ${r.format.toUpperCase()} ${r.width}x${r.height} (${r.bytes} bytes, ${r.source === "fallback" ? "Notes' full rendering" : "largest preview"}) to ${r.savedPath}`,
50813
+ {
50814
+ savedPath: r.savedPath,
50815
+ format: r.format,
50816
+ width: r.width,
50817
+ height: r.height,
50818
+ bytes: r.bytes,
50819
+ source: r.source,
50820
+ attachmentId: attachmentCoreDataId(noteId3, r.drawing.pk),
50821
+ identifier: r.drawing.identifier,
50822
+ kind: r.drawing.kind,
50823
+ handwritingSummary: r.drawing.handwritingSummary
50824
+ }
50825
+ );
50826
+ }, "Error exporting Paper image")
50827
+ );
50828
+ registerTool(
50829
+ "export-attachments",
50830
+ {
50831
+ description: `Use when: copying every file attachment of one note (or only its lead visual) into a directory on disk.
50832
+ Returns: per attachment its id, kind, exportedTo, and exportedKind: "asset" for the real file, "preview" when the asset never downloaded and only Notes' rendered thumbnail was available, or null when nothing was on disk.
50833
+ Do not use when: exporting one attachment to an exact path (save-attachment) or reading bytes inline (fetch-attachment).
50834
+ Safety: writes files; exportDir must be absolute and under the home directory, a temp dir, or /Volumes, and not inside the Notes data folder. Existing files are never replaced: name collisions get -2, -3, ... suffixes. Reads NoteStore and the Notes data folder read-only; requires Full Disk Access. Notes.app is not opened.`,
50835
+ inputSchema: {
50836
+ noteId: noteIdInput,
50837
+ exportDir: external_exports.string().min(1, "exportDir is required").max(MAX.SAVE_PATH).describe("Absolute destination directory (created if missing; home, temp, or /Volumes)"),
50838
+ firstImageOnly: external_exports.boolean().optional().describe("Export only the note's lead visual (see list-attachments firstImage)")
50839
+ },
50840
+ outputSchema: {
50841
+ exportDir: external_exports.string().optional(),
50842
+ exported: external_exports.number().optional(),
50843
+ previews: external_exports.number().optional(),
50844
+ skipped: external_exports.number().optional(),
50845
+ failed: external_exports.number().optional(),
50846
+ results: external_exports.array(external_exports.object({}).passthrough()).optional(),
50847
+ firstImage: external_exports.object({}).passthrough().nullable().optional()
50848
+ }
50849
+ },
50850
+ withErrorHandling(({ noteId: noteId3, exportDir, firstImageOnly = false }) => {
50851
+ const r = notesManager.exportAttachmentsById(noteId3, exportDir, firstImageOnly);
50852
+ const results = r.results.map(({ pk, ...rest }) => ({
50853
+ attachmentId: attachmentCoreDataId(noteId3, pk),
50854
+ ...rest
50855
+ }));
50856
+ const exported = results.filter((x) => x.exportedKind !== null).length;
50857
+ const previews = results.filter((x) => x.exportedKind === "preview").length;
50858
+ const failed = results.filter((x) => x.error).length;
50859
+ const skipped = results.length - exported - failed;
50860
+ const structured = {
50861
+ exportDir: r.exportDir,
50862
+ exported,
50863
+ previews,
50864
+ skipped,
50865
+ failed,
50866
+ results
50867
+ };
50868
+ if (firstImageOnly) {
50869
+ structured.firstImage = firstImageView(noteId3, r.firstImage ?? null);
50870
+ if (!r.firstImage) {
50871
+ return successResponse(
50872
+ "This note has no image, scan, or drawing attachment; nothing was exported.",
50873
+ structured
50874
+ );
50875
+ }
50876
+ }
50877
+ return successResponse(
50878
+ `Exported ${exported} file(s) to ${r.exportDir} (${previews} preview-only, ${skipped} with nothing on disk, ${failed} failed).`,
50879
+ structured
50880
+ );
50881
+ }, "Error exporting attachments")
50882
+ );
49701
50883
  registerTool(
49702
50884
  "fetch-attachment",
49703
50885
  {