apple-notes-mcp 2.8.38 → 2.8.40

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 +14 -2
  2. package/build/index.js +516 -341
  3. package/package.json +1 -1
package/build/index.js CHANGED
@@ -3268,8 +3268,8 @@ var require_utils = __commonJS({
3268
3268
  }
3269
3269
  return ind;
3270
3270
  }
3271
- function removeDotSegments(path8) {
3272
- let input = path8;
3271
+ function removeDotSegments(path9) {
3272
+ let input = path9;
3273
3273
  const output = [];
3274
3274
  let nextSlash = -1;
3275
3275
  let len = 0;
@@ -3674,8 +3674,8 @@ var require_schemes = __commonJS({
3674
3674
  }
3675
3675
  if (wsComponent.resourceName) {
3676
3676
  const queryIndex = wsComponent.resourceName.indexOf("?");
3677
- const path8 = queryIndex === -1 ? wsComponent.resourceName : wsComponent.resourceName.slice(0, queryIndex);
3678
- wsComponent.path = path8 && path8 !== "/" ? path8 : void 0;
3677
+ const path9 = queryIndex === -1 ? wsComponent.resourceName : wsComponent.resourceName.slice(0, queryIndex);
3678
+ wsComponent.path = path9 && path9 !== "/" ? path9 : void 0;
3679
3679
  wsComponent.query = queryIndex === -1 ? void 0 : wsComponent.resourceName.slice(queryIndex + 1);
3680
3680
  wsComponent.resourceName = void 0;
3681
3681
  }
@@ -7181,12 +7181,12 @@ var require_dist = __commonJS({
7181
7181
  throw new Error(`Unknown format "${name}"`);
7182
7182
  return f;
7183
7183
  };
7184
- function addFormats(ajv, list, fs8, exportName) {
7184
+ function addFormats(ajv, list, fs9, exportName) {
7185
7185
  var _a;
7186
7186
  var _b;
7187
7187
  (_a = (_b = ajv.opts.code).formats) !== null && _a !== void 0 ? _a : _b.formats = (0, codegen_1._)`require("ajv-formats/dist/formats").${exportName}`;
7188
7188
  for (const f of list)
7189
- ajv.addFormat(f, fs8[f]);
7189
+ ajv.addFormat(f, fs9[f]);
7190
7190
  }
7191
7191
  module.exports = exports = formatsPlugin;
7192
7192
  Object.defineProperty(exports, "__esModule", { value: true });
@@ -12238,32 +12238,32 @@ var require_URL = __commonJS({
12238
12238
  else
12239
12239
  return basepath.substring(0, lastslash + 1) + refpath;
12240
12240
  }
12241
- function remove_dot_segments(path8) {
12242
- if (!path8) return path8;
12241
+ function remove_dot_segments(path9) {
12242
+ if (!path9) return path9;
12243
12243
  var output = "";
12244
- while (path8.length > 0) {
12245
- if (path8 === "." || path8 === "..") {
12246
- path8 = "";
12244
+ while (path9.length > 0) {
12245
+ if (path9 === "." || path9 === "..") {
12246
+ path9 = "";
12247
12247
  break;
12248
12248
  }
12249
- var twochars = path8.substring(0, 2);
12250
- var threechars = path8.substring(0, 3);
12251
- var fourchars = path8.substring(0, 4);
12249
+ var twochars = path9.substring(0, 2);
12250
+ var threechars = path9.substring(0, 3);
12251
+ var fourchars = path9.substring(0, 4);
12252
12252
  if (threechars === "../") {
12253
- path8 = path8.substring(3);
12253
+ path9 = path9.substring(3);
12254
12254
  } else if (twochars === "./") {
12255
- path8 = path8.substring(2);
12255
+ path9 = path9.substring(2);
12256
12256
  } else if (threechars === "/./") {
12257
- path8 = "/" + path8.substring(3);
12258
- } else if (twochars === "/." && path8.length === 2) {
12259
- path8 = "/";
12260
- } else if (fourchars === "/../" || threechars === "/.." && path8.length === 3) {
12261
- path8 = "/" + path8.substring(4);
12257
+ path9 = "/" + path9.substring(3);
12258
+ } else if (twochars === "/." && path9.length === 2) {
12259
+ path9 = "/";
12260
+ } else if (fourchars === "/../" || threechars === "/.." && path9.length === 3) {
12261
+ path9 = "/" + path9.substring(4);
12262
12262
  output = output.replace(/\/?[^\/]*$/, "");
12263
12263
  } else {
12264
- var segment = path8.match(/(\/?([^\/]*))/)[0];
12264
+ var segment = path9.match(/(\/?([^\/]*))/)[0];
12265
12265
  output += segment;
12266
- path8 = path8.substring(segment.length);
12266
+ path9 = path9.substring(segment.length);
12267
12267
  }
12268
12268
  }
12269
12269
  return output;
@@ -24465,14 +24465,14 @@ var require_turndown_cjs = __commonJS({
24465
24465
  } else if (node.nodeType === 1) {
24466
24466
  replacement = replacementForNode.call(self, node);
24467
24467
  }
24468
- return join22(output, replacement);
24468
+ return join23(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 = join22(output, rule.append(self.options));
24475
+ output = join23(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 join22(output, replacement) {
24487
+ function join23(output, replacement) {
24488
24488
  var s1 = trimTrailingNewlines(output);
24489
24489
  var s2 = trimLeadingNewlines(replacement);
24490
24490
  var nls = Math.max(output.length - s1.length, replacement.length - s2.length);
@@ -24979,8 +24979,8 @@ function getErrorMap() {
24979
24979
 
24980
24980
  // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/parseUtil.js
24981
24981
  var makeIssue = (params) => {
24982
- const { data, path: path8, errorMaps, issueData } = params;
24983
- const fullPath = [...path8, ...issueData.path || []];
24982
+ const { data, path: path9, errorMaps, issueData } = params;
24983
+ const fullPath = [...path9, ...issueData.path || []];
24984
24984
  const fullIssue = {
24985
24985
  ...issueData,
24986
24986
  path: fullPath
@@ -25096,11 +25096,11 @@ var errorUtil;
25096
25096
 
25097
25097
  // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/types.js
25098
25098
  var ParseInputLazyPath = class {
25099
- constructor(parent, value, path8, key) {
25099
+ constructor(parent, value, path9, key) {
25100
25100
  this._cachedPath = [];
25101
25101
  this.parent = parent;
25102
25102
  this.data = value;
25103
- this._path = path8;
25103
+ this._path = path9;
25104
25104
  this._key = key;
25105
25105
  }
25106
25106
  get path() {
@@ -28737,10 +28737,10 @@ function assignProp(target, prop, value) {
28737
28737
  configurable: true
28738
28738
  });
28739
28739
  }
28740
- function getElementAtPath(obj, path8) {
28741
- if (!path8)
28740
+ function getElementAtPath(obj, path9) {
28741
+ if (!path9)
28742
28742
  return obj;
28743
- return path8.reduce((acc, key) => acc?.[key], obj);
28743
+ return path9.reduce((acc, key) => acc?.[key], obj);
28744
28744
  }
28745
28745
  function promiseAllObject(promisesObj) {
28746
28746
  const keys = Object.keys(promisesObj);
@@ -29060,11 +29060,11 @@ function aborted(x, startIndex = 0) {
29060
29060
  }
29061
29061
  return false;
29062
29062
  }
29063
- function prefixIssues(path8, issues) {
29063
+ function prefixIssues(path9, issues) {
29064
29064
  return issues.map((iss) => {
29065
29065
  var _a;
29066
29066
  (_a = iss).path ?? (_a.path = []);
29067
- iss.path.unshift(path8);
29067
+ iss.path.unshift(path9);
29068
29068
  return iss;
29069
29069
  });
29070
29070
  }
@@ -32475,11 +32475,11 @@ function normalizeObjectSchema(schema) {
32475
32475
  }
32476
32476
  return void 0;
32477
32477
  }
32478
- function getDotPath(path8) {
32479
- if (path8.length === 0) {
32478
+ function getDotPath(path9) {
32479
+ if (path9.length === 0) {
32480
32480
  return "object root";
32481
32481
  }
32482
- return path8.reduce((acc, seg, index) => {
32482
+ return path9.reduce((acc, seg, index) => {
32483
32483
  if (index === 0) {
32484
32484
  return String(seg);
32485
32485
  }
@@ -39275,21 +39275,13 @@ var WIRE_TYPE = {
39275
39275
  };
39276
39276
  function decodeVarint(buf, offset) {
39277
39277
  let result = 0;
39278
- let shift = 0;
39279
- let pos = offset;
39280
- while (pos < buf.length) {
39281
- const byte = buf[pos];
39278
+ for (let pos = offset, shift = 0; pos < buf.length && shift < 28; shift += 7) {
39279
+ const byte = buf[pos++];
39282
39280
  result |= (byte & 127) << shift;
39283
- pos++;
39284
- if ((byte & 128) === 0) {
39285
- return [result, pos];
39286
- }
39287
- shift += 7;
39288
- if (shift > 35) {
39289
- throw new Error(`Varint too long at offset ${offset}`);
39290
- }
39281
+ if ((byte & 128) === 0) return [result, pos];
39291
39282
  }
39292
- throw new Error(`Unexpected end of buffer reading varint at offset ${offset}`);
39283
+ const [value, next] = decodeVarint64(buf, offset);
39284
+ return [Number(BigInt.asIntN(64, value)), next];
39293
39285
  }
39294
39286
  function decodeMessage(buf, options = {}) {
39295
39287
  const fields = [];
@@ -39306,7 +39298,7 @@ function decodeMessage(buf, options = {}) {
39306
39298
  } else if (wireType === WIRE_TYPE.LENGTH_DELIMITED) {
39307
39299
  let length;
39308
39300
  [length, offset] = decodeVarint(buf, offset);
39309
- if (offset + length > buf.length) {
39301
+ if (length < 0 || offset + length > buf.length) {
39310
39302
  break;
39311
39303
  }
39312
39304
  const value = buf.slice(offset, offset + length);
@@ -39452,9 +39444,9 @@ function queryNoteData(noteId3) {
39452
39444
  return { hex: null, error: "invalid_id" };
39453
39445
  }
39454
39446
  const pk = pkMatch[1];
39455
- const query = `SELECT hex(nd.ZDATA) FROM ZICNOTEDATA nd JOIN ZICCLOUDSYNCINGOBJECT n ON nd.ZNOTE = n.Z_PK WHERE n.Z_PK = ${pk};`;
39447
+ const query2 = `SELECT hex(nd.ZDATA) FROM ZICNOTEDATA nd JOIN ZICCLOUDSYNCINGOBJECT n ON nd.ZNOTE = n.Z_PK WHERE n.Z_PK = ${pk};`;
39456
39448
  try {
39457
- const result = execFileSync2("sqlite3", ["-readonly", NOTES_DB_PATH, query], {
39449
+ const result = execFileSync2("sqlite3", ["-readonly", NOTES_DB_PATH, query2], {
39458
39450
  encoding: "utf8",
39459
39451
  timeout: 5e3,
39460
39452
  stdio: ["pipe", "pipe", "pipe"]
@@ -39623,6 +39615,12 @@ import { createHash } from "node:crypto";
39623
39615
  import { homedir as homedir2 } from "node:os";
39624
39616
  import { join as join2 } from "node:path";
39625
39617
  import { gunzipSync as gunzipSync2 } from "node:zlib";
39618
+ var HTML_LOSSY_ORDER = [
39619
+ "superscript",
39620
+ "subscript",
39621
+ "alignment",
39622
+ "highlight"
39623
+ ];
39626
39624
  var dbPath = join2(homedir2(), "Library/Group Containers/group.com.apple.notes/NoteStore.sqlite");
39627
39625
  var safeUrl = (url) => /^(?:https?:\/\/|notes:\/\/|applenotes:|mailto:)/i.test(url) && !Array.from(url).some((char) => char.charCodeAt(0) < 32);
39628
39626
  var escapeAttribute = (text2) => text2.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;");
@@ -39643,6 +39641,7 @@ function styleValue(field) {
39643
39641
  else if (wire === 5) offset += 4;
39644
39642
  else if (wire === 2) {
39645
39643
  [length, offset] = decodeVarint(data, offset);
39644
+ if (length < 0) return Buffer.from(data).toString("hex");
39646
39645
  offset += length;
39647
39646
  } else return Buffer.from(data).toString("hex");
39648
39647
  if (offset > data.length) return Buffer.from(data).toString("hex");
@@ -39669,6 +39668,7 @@ function parseRichNote(data, nativeTags = []) {
39669
39668
  let position = 0;
39670
39669
  let hasNativeObjects = false;
39671
39670
  let hasChecklist = false;
39671
+ const lossy = /* @__PURE__ */ new Set();
39672
39672
  for (const run of getFields(body, 5)) {
39673
39673
  const fields = embeddedMessage(run);
39674
39674
  if (!fields) throw new Error("Invalid Notes attribute run");
@@ -39686,6 +39686,13 @@ function parseRichNote(data, nativeTags = []) {
39686
39686
  fields.filter((f) => f.fieldNumber >= 2 && f.fieldNumber <= 12 || f.fieldNumber === 14).map((f) => [f.fieldNumber, styleValue(f)])
39687
39687
  )
39688
39688
  });
39689
+ if (/[^\s\ufffc]/u.test(text2.slice(position, position + length))) {
39690
+ const baseline = varintValue(getField(fields, 8)) ?? 0;
39691
+ if (baseline > 0) lossy.add("superscript");
39692
+ if (baseline < 0) lossy.add("subscript");
39693
+ if (paragraph && (varintValue(getField(paragraph, 2)) ?? 0) !== 0) lossy.add("alignment");
39694
+ if (varintValue(getField(fields, 14))) lossy.add("highlight");
39695
+ }
39689
39696
  const url = stringValue(getField(fields, 9));
39690
39697
  if (url) {
39691
39698
  if (!safeUrl(url)) throw new Error("Unsupported link scheme in note");
@@ -39737,7 +39744,8 @@ function parseRichNote(data, nativeTags = []) {
39737
39744
  revision: createHash("sha256").update(data).digest("hex"),
39738
39745
  objects,
39739
39746
  checklistItems,
39740
- styleRuns
39747
+ styleRuns,
39748
+ ...lossy.size ? { htmlLossyFormatting: HTML_LOSSY_ORDER.filter((f) => lossy.has(f)) } : {}
39741
39749
  };
39742
39750
  }
39743
39751
  function readRichNote(id2) {
@@ -39854,17 +39862,26 @@ function enrichNoteRead(id2, rawBody) {
39854
39862
  const rich = readRichNote(id2);
39855
39863
  metadata = rich;
39856
39864
  const content = restoreNoteLinks(rawBody, rich);
39857
- const writable = !rich.hasNativeObjects && !rich.hasChecklist;
39865
+ const complete = !rich.hasNativeObjects && !rich.hasChecklist;
39866
+ const lossy = rich.htmlLossyFormatting ?? [];
39867
+ const writable = complete && lossy.length === 0;
39868
+ const warnings = [];
39869
+ if (!complete)
39870
+ warnings.push(
39871
+ "Native tags, inline objects or checklists are present. Their state is not writable through AppleScript; full-body edits are blocked to preserve them."
39872
+ );
39873
+ if (lossy.length)
39874
+ warnings.push(
39875
+ `This note uses formatting that Notes' AppleScript HTML does not carry (${lossy.join(", ")}); a full-body edit would silently drop it, so full-body edits are blocked. Edit it in Notes.app, or use append-to-note with scopeText, which appends natively and verifies existing formatting.`
39876
+ );
39858
39877
  return {
39859
39878
  content,
39860
39879
  links: rich.links,
39861
39880
  nativeTags: rich.nativeTags,
39862
- complete: writable,
39881
+ complete,
39863
39882
  writable,
39864
39883
  revision: rich.revision,
39865
- ...!writable ? {
39866
- warning: "Native tags, inline objects or checklists are present. Their state is not writable through AppleScript; full-body edits are blocked to preserve them."
39867
- } : {}
39884
+ ...warnings.length ? { warning: warnings.join(" ") } : {}
39868
39885
  };
39869
39886
  } catch (err) {
39870
39887
  const detail = err instanceof Error ? err.message : String(err);
@@ -40713,7 +40730,7 @@ function decodeSmartFolderQuery(raw, context = {}) {
40713
40730
  inner = type.and.filter((clause) => !isDeletedWrapper(clause));
40714
40731
  }
40715
40732
  }
40716
- const query = inner.length === 1 ? inner[0] : { and: inner };
40733
+ const query2 = inner.length === 1 ? inner[0] : { and: inner };
40717
40734
  let match = "all";
40718
40735
  let filters;
40719
40736
  const only = inner.length === 1 && isClause(inner[0]) ? inner[0] : void 0;
@@ -40732,7 +40749,7 @@ function decodeSmartFolderQuery(raw, context = {}) {
40732
40749
  return {
40733
40750
  match,
40734
40751
  filters,
40735
- query,
40752
+ query: query2,
40736
40753
  ...includesRecentlyDeleted === void 0 ? {} : { includesRecentlyDeleted },
40737
40754
  fullyDecoded: decoder.fullyDecoded
40738
40755
  };
@@ -40854,11 +40871,55 @@ function readSmartFolders(dbPath2 = NOTES_DB_PATH3) {
40854
40871
  }
40855
40872
  }
40856
40873
 
40874
+ // src/utils/trashFolders.ts
40875
+ import { execFileSync as execFileSync6 } from "child_process";
40876
+ import * as fs3 from "fs";
40877
+ import * as os3 from "os";
40878
+ import * as path3 from "path";
40879
+ var NOTES_DB_PATH4 = path3.join(
40880
+ os3.homedir(),
40881
+ "Library/Group Containers/group.com.apple.notes/NoteStore.sqlite"
40882
+ );
40883
+ var RECENTLY_DELETED_FOLDER_NAME = "Recently Deleted";
40884
+ var CACHE_TTL_MS = 5 * 60 * 1e3;
40885
+ var cache = null;
40886
+ function query(dbPath2, sql) {
40887
+ return execFileSync6("sqlite3", ["-readonly", dbPath2, sql], {
40888
+ encoding: "utf8",
40889
+ timeout: 5e3,
40890
+ stdio: ["pipe", "pipe", "pipe"]
40891
+ });
40892
+ }
40893
+ function readTrashFolderIds(dbPath2 = NOTES_DB_PATH4) {
40894
+ if (cache && cache.dbPath === dbPath2 && Date.now() - cache.at < CACHE_TTL_MS) {
40895
+ return cache.ids;
40896
+ }
40897
+ try {
40898
+ if (!fs3.existsSync(dbPath2)) return [];
40899
+ const columns = new Set(
40900
+ query(dbPath2, "SELECT name FROM pragma_table_info('ZICCLOUDSYNCINGOBJECT');").split("\n").map((line) => line.trim()).filter(Boolean)
40901
+ );
40902
+ const predicates = [];
40903
+ if (columns.has("ZFOLDERTYPE")) predicates.push("COALESCE(ZFOLDERTYPE, 0) = 1");
40904
+ if (columns.has("ZIDENTIFIER"))
40905
+ predicates.push("COALESCE(ZIDENTIFIER, '') LIKE 'TrashFolder%'");
40906
+ if (!predicates.length) return [];
40907
+ const sql = `SELECT (SELECT Z_UUID FROM Z_METADATA LIMIT 1); SELECT Z_PK FROM ZICCLOUDSYNCINGOBJECT WHERE Z_ENT = (SELECT Z_ENT FROM Z_PRIMARYKEY WHERE Z_NAME = 'ICFolder') AND (${predicates.join(" OR ")}) ORDER BY Z_PK;`;
40908
+ const [uuid2, ...pks] = query(dbPath2, sql).split("\n").map((line) => line.trim()).filter(Boolean);
40909
+ if (!uuid2 || !/^[0-9A-F-]+$/i.test(uuid2)) return [];
40910
+ const ids = pks.filter((pk) => /^\d+$/.test(pk)).map((pk) => `x-coredata://${uuid2}/ICFolder/p${pk}`);
40911
+ cache = { dbPath: dbPath2, at: Date.now(), ids };
40912
+ return ids;
40913
+ } catch {
40914
+ return [];
40915
+ }
40916
+ }
40917
+
40857
40918
  // src/utils/attachmentFs.ts
40858
40919
  import {
40859
40920
  closeSync,
40860
40921
  constants,
40861
- existsSync as existsSync3,
40922
+ existsSync as existsSync4,
40862
40923
  fstatSync,
40863
40924
  lstatSync,
40864
40925
  mkdirSync,
@@ -40869,11 +40930,11 @@ import {
40869
40930
  rmSync,
40870
40931
  statSync
40871
40932
  } from "fs";
40872
- import { dirname, isAbsolute, join as join5, relative, resolve, sep } from "path";
40873
- import { homedir as homedir5, tmpdir } from "os";
40933
+ import { dirname, isAbsolute, join as join6, relative, resolve, sep } from "path";
40934
+ import { homedir as homedir6, tmpdir } from "os";
40874
40935
  function allowedSaveRoots() {
40875
40936
  return [
40876
- resolve(homedir5()),
40937
+ resolve(homedir6()),
40877
40938
  resolve(tmpdir()),
40878
40939
  "/Volumes",
40879
40940
  "/private/var/folders",
@@ -40881,8 +40942,8 @@ function allowedSaveRoots() {
40881
40942
  "/private/tmp"
40882
40943
  ];
40883
40944
  }
40884
- function canonicalize(path8) {
40885
- return realpathSync.native(path8);
40945
+ function canonicalize(path9) {
40946
+ return realpathSync.native(path9);
40886
40947
  }
40887
40948
  function isWithinRoots(candidate, roots) {
40888
40949
  return roots.some((root) => {
@@ -40904,9 +40965,9 @@ function canonicalRoots(roots) {
40904
40965
  }
40905
40966
  return canonical;
40906
40967
  }
40907
- function entryExists(path8) {
40968
+ function entryExists(path9) {
40908
40969
  try {
40909
- lstatSync(path8);
40970
+ lstatSync(path9);
40910
40971
  return true;
40911
40972
  } catch (e) {
40912
40973
  const code = e.code;
@@ -40947,7 +41008,7 @@ function assertSafeSavePath(p, roots = allowedSaveRoots()) {
40947
41008
  if (suffix.split(sep).includes("..")) {
40948
41009
  throw new Error(`Refusing to write outside allowed locations (home, temp, /Volumes): "${abs}"`);
40949
41010
  }
40950
- const canonicalDest = suffix ? join5(canonicalAncestor, suffix) : canonicalAncestor;
41011
+ const canonicalDest = suffix ? join6(canonicalAncestor, suffix) : canonicalAncestor;
40951
41012
  const allowed = canonicalRoots(roots);
40952
41013
  if (!isWithinRoots(canonicalAncestor, allowed) || !isWithinRoots(canonicalDest, allowed)) {
40953
41014
  throw new Error(
@@ -41031,13 +41092,13 @@ function readAllowedTextFile(p, maxBytes, roots = allowedSaveRoots()) {
41031
41092
  }
41032
41093
  function cleanupTempDir(dir) {
41033
41094
  try {
41034
- if (existsSync3(dir)) rmSync(dir, { recursive: true, force: true });
41095
+ if (existsSync4(dir)) rmSync(dir, { recursive: true, force: true });
41035
41096
  } catch {
41036
41097
  }
41037
41098
  }
41038
41099
 
41039
41100
  // src/utils/paperAttachments.ts
41040
- import { execFileSync as execFileSync7 } from "node:child_process";
41101
+ import { execFileSync as execFileSync8 } from "node:child_process";
41041
41102
  import {
41042
41103
  closeSync as closeSync3,
41043
41104
  constants as constants3,
@@ -41050,10 +41111,10 @@ import {
41050
41111
  unlinkSync as unlinkSync2,
41051
41112
  writeSync as writeSync2
41052
41113
  } from "node:fs";
41053
- import { basename as basename2, dirname as dirname3, extname as extname2, join as join7 } from "node:path";
41114
+ import { basename as basename2, dirname as dirname3, extname as extname2, join as join8 } from "node:path";
41054
41115
 
41055
41116
  // src/utils/attachmentAssets.ts
41056
- import { execFileSync as execFileSync6 } from "node:child_process";
41117
+ import { execFileSync as execFileSync7 } from "node:child_process";
41057
41118
  import {
41058
41119
  closeSync as closeSync2,
41059
41120
  constants as constants2,
@@ -41067,11 +41128,11 @@ import {
41067
41128
  unlinkSync,
41068
41129
  writeSync
41069
41130
  } 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";
41131
+ import { homedir as homedir7 } from "node:os";
41132
+ import { basename, dirname as dirname2, extname, isAbsolute as isAbsolute2, join as join7, relative as relative2, resolve as resolve2, sep as sep2 } from "node:path";
41072
41133
  import { gunzipSync as gunzipSync5 } from "node:zlib";
41073
- var NOTES_CONTAINER_DIR = join6(
41074
- homedir6(),
41134
+ var NOTES_CONTAINER_DIR = join7(
41135
+ homedir7(),
41075
41136
  "Library/Group Containers/group.com.apple.notes"
41076
41137
  );
41077
41138
  var AttachmentStoreError = class extends Error {
@@ -41176,7 +41237,7 @@ function buildAttachmentRowsSql(notePk, columns) {
41176
41237
  }
41177
41238
  function runSqlite3(dbPath2, sql) {
41178
41239
  try {
41179
- return execFileSync6("/usr/bin/sqlite3", ["-readonly", dbPath2, sql], {
41240
+ return execFileSync7("/usr/bin/sqlite3", ["-readonly", dbPath2, sql], {
41180
41241
  encoding: "utf8",
41181
41242
  timeout: 1e4,
41182
41243
  maxBuffer: 128 * 1024 * 1024,
@@ -41244,7 +41305,7 @@ function attachmentOrderFromNoteData(hex3) {
41244
41305
  return null;
41245
41306
  }
41246
41307
  }
41247
- function readNoteAttachmentRows(noteId3, dbPath2 = join6(NOTES_CONTAINER_DIR, "NoteStore.sqlite")) {
41308
+ function readNoteAttachmentRows(noteId3, dbPath2 = join7(NOTES_CONTAINER_DIR, "NoteStore.sqlite")) {
41248
41309
  const { pk } = parseNoteId2(noteId3);
41249
41310
  const columnList = runSqlite3(
41250
41311
  dbPath2,
@@ -41274,24 +41335,24 @@ function safeComponent(value) {
41274
41335
  if (value === "." || value === ".." || value.includes("/") || value.includes("\0")) return null;
41275
41336
  return value;
41276
41337
  }
41277
- function realInside(path8, rootReal) {
41338
+ function realInside(path9, rootReal) {
41278
41339
  try {
41279
- const real = realpathSync2.native(path8);
41340
+ const real = realpathSync2.native(path9);
41280
41341
  return real === rootReal || real.startsWith(rootReal + sep2) ? real : null;
41281
41342
  } catch {
41282
41343
  return null;
41283
41344
  }
41284
41345
  }
41285
- function isRegularFile(path8) {
41346
+ function isRegularFile(path9) {
41286
41347
  try {
41287
- return lstatSync2(path8).isFile();
41348
+ return lstatSync2(path9).isFile();
41288
41349
  } catch {
41289
41350
  return false;
41290
41351
  }
41291
41352
  }
41292
- function isDirectory(path8) {
41353
+ function isDirectory(path9) {
41293
41354
  try {
41294
- return lstatSync2(path8).isDirectory();
41355
+ return lstatSync2(path9).isDirectory();
41295
41356
  } catch {
41296
41357
  return false;
41297
41358
  }
@@ -41305,7 +41366,7 @@ function boundedEntries(dir, limit) {
41305
41366
  }
41306
41367
  }
41307
41368
  function resolveAccountDir(containerDir, accountIdentifier) {
41308
- const accountsDir = join6(containerDir, "Accounts");
41369
+ const accountsDir = join7(containerDir, "Accounts");
41309
41370
  let accountsReal;
41310
41371
  try {
41311
41372
  accountsReal = realpathSync2.native(accountsDir);
@@ -41314,14 +41375,14 @@ function resolveAccountDir(containerDir, accountIdentifier) {
41314
41375
  }
41315
41376
  const account = safeComponent(accountIdentifier);
41316
41377
  if (account) {
41317
- const dir = realInside(join6(accountsReal, account), accountsReal);
41378
+ const dir = realInside(join7(accountsReal, account), accountsReal);
41318
41379
  if (dir && isDirectory(dir)) return dir;
41319
41380
  }
41320
41381
  const entries2 = (boundedEntries(accountsReal, 64) ?? []).filter(
41321
- (e) => isDirectory(join6(accountsReal, e))
41382
+ (e) => isDirectory(join7(accountsReal, e))
41322
41383
  );
41323
41384
  if (entries2.length !== 1) return null;
41324
- return realInside(join6(accountsReal, entries2[0]), accountsReal);
41385
+ return realInside(join7(accountsReal, entries2[0]), accountsReal);
41325
41386
  }
41326
41387
  function generationRank(name) {
41327
41388
  const m = /^(\d+)_/.exec(name);
@@ -41329,23 +41390,23 @@ function generationRank(name) {
41329
41390
  }
41330
41391
  function generationDirs(base, accountDir) {
41331
41392
  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)));
41393
+ return entries2.map((e) => realInside(join7(base, e), accountDir)).filter((p) => p !== null && isDirectory(p)).sort((a, b) => generationRank(basename(b)) - generationRank(basename(a)));
41333
41394
  }
41334
41395
  function fallbackFiles(accountDir, rootName, identifier, generation, names) {
41335
- const base = join6(accountDir, rootName, identifier);
41396
+ const base = join7(accountDir, rootName, identifier);
41336
41397
  const found = [];
41337
41398
  const add = (candidate) => {
41338
41399
  const real = realInside(candidate, accountDir);
41339
41400
  if (real && isRegularFile(real) && !found.includes(real)) found.push(real);
41340
41401
  };
41341
41402
  const gen = safeComponent(generation);
41342
- if (gen) for (const name of names) add(join6(base, gen, name));
41403
+ if (gen) for (const name of names) add(join7(base, gen, name));
41343
41404
  if (isDirectory(base)) {
41344
41405
  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));
41406
+ for (const name of names) add(join7(dir, name));
41407
+ for (const name of names) add(join7(base, name));
41347
41408
  }
41348
- for (const name of names) add(join6(accountDir, rootName, `${identifier}${extname(name)}`));
41409
+ for (const name of names) add(join7(accountDir, rootName, `${identifier}${extname(name)}`));
41349
41410
  return found;
41350
41411
  }
41351
41412
  function previewPixelArea(name) {
@@ -41357,7 +41418,7 @@ function previewFileInBundle(bundle, accountDir) {
41357
41418
  const direct = [];
41358
41419
  const nested = [];
41359
41420
  for (const entry of boundedEntries(bundle, MAX_BUNDLE_ENTRIES) ?? []) {
41360
- const child = realInside(join6(bundle, entry), accountDir);
41421
+ const child = realInside(join7(bundle, entry), accountDir);
41361
41422
  if (!child) continue;
41362
41423
  if (isRegularFile(child)) direct.push(child);
41363
41424
  else if (isDirectory(child)) nested.push(child);
@@ -41365,14 +41426,14 @@ function previewFileInBundle(bundle, accountDir) {
41365
41426
  nested.sort((a, b) => generationRank(basename(b)) - generationRank(basename(a)));
41366
41427
  const pick2 = (files) => files.find((f) => basename(f) === "Preview.png") ?? files.find((f) => PREVIEW_IMAGE_SUFFIXES.has(extname(f).toLowerCase())) ?? null;
41367
41428
  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));
41429
+ const files = (boundedEntries(dir, MAX_BUNDLE_ENTRIES) ?? []).map((e) => realInside(join7(dir, e), accountDir)).filter((p) => p !== null && isRegularFile(p));
41369
41430
  const chosen = pick2(files);
41370
41431
  if (chosen) return chosen;
41371
41432
  }
41372
41433
  return pick2(direct);
41373
41434
  }
41374
41435
  function listPreviewEntries(accountDir) {
41375
- return boundedEntries(join6(accountDir, "Previews"), MAX_PREVIEW_DIR_ENTRIES) ?? [];
41436
+ return boundedEntries(join7(accountDir, "Previews"), MAX_PREVIEW_DIR_ENTRIES) ?? [];
41376
41437
  }
41377
41438
  function previewPaths(accountDir, identifier, entries2) {
41378
41439
  const id2 = safeComponent(identifier);
@@ -41384,7 +41445,7 @@ function previewPaths(accountDir, identifier, entries2) {
41384
41445
  }).sort((a, b) => previewPixelArea(b) - previewPixelArea(a) || a.localeCompare(b));
41385
41446
  const files = [];
41386
41447
  for (const name of candidates) {
41387
- const real = realInside(join6(accountDir, "Previews", name), accountDir);
41448
+ const real = realInside(join7(accountDir, "Previews", name), accountDir);
41388
41449
  if (!real) continue;
41389
41450
  const file = isRegularFile(real) ? real : isDirectory(real) ? previewFileInBundle(real, accountDir) : null;
41390
41451
  if (file && !files.includes(file)) files.push(file);
@@ -41401,13 +41462,13 @@ function assetPathsFor(accountDir, row) {
41401
41462
  const mediaName = safeComponent(row.mediaFilename);
41402
41463
  const mediaGen = safeComponent(row.mediaGeneration);
41403
41464
  if (mediaId && mediaName) {
41404
- if (mediaGen) add(join6(accountDir, "Media", mediaId, mediaGen, mediaName));
41405
- add(join6(accountDir, "Media", mediaId, mediaName));
41465
+ if (mediaGen) add(join7(accountDir, "Media", mediaId, mediaGen, mediaName));
41466
+ add(join7(accountDir, "Media", mediaId, mediaName));
41406
41467
  }
41407
41468
  const id2 = safeComponent(row.identifier);
41408
41469
  if (!id2) return found;
41409
41470
  const ownName = safeComponent(row.filename);
41410
- if (ownName) add(join6(accountDir, "Media", id2, ownName));
41471
+ if (ownName) add(join7(accountDir, "Media", id2, ownName));
41411
41472
  for (const file of fallbackFiles(accountDir, "FallbackImages", id2, row.fallbackImageGeneration, [
41412
41473
  "FallbackImage.png",
41413
41474
  "FallbackImage.jpg"
@@ -41498,10 +41559,10 @@ function canonicalTail(p) {
41498
41559
  const tail = [];
41499
41560
  for (; ; ) {
41500
41561
  try {
41501
- return join6(realpathSync2.native(current), ...tail);
41562
+ return join7(realpathSync2.native(current), ...tail);
41502
41563
  } catch {
41503
41564
  const parent = dirname2(current);
41504
- if (parent === current) return join6(current, ...tail);
41565
+ if (parent === current) return join7(current, ...tail);
41505
41566
  tail.unshift(basename(current));
41506
41567
  current = parent;
41507
41568
  }
@@ -41583,7 +41644,7 @@ function exportOneAttachment(record2, dir, source) {
41583
41644
  if (!source) return base;
41584
41645
  const name = exportFileName(record2, source.path, source.kind);
41585
41646
  for (let attempt = 1; attempt <= MAX_COLLISION_SUFFIX; attempt++) {
41586
- const dest = join6(dir, collisionName(name, attempt));
41647
+ const dest = join7(dir, collisionName(name, attempt));
41587
41648
  try {
41588
41649
  assertSafeSavePath(dest);
41589
41650
  copyFileExclusive(source.path, dest);
@@ -41671,10 +41732,10 @@ function readImageInfoFd(fd) {
41671
41732
  const read = readSync2(fd, buf, 0, buf.length, 0);
41672
41733
  return parseImageHeader(buf.subarray(0, read));
41673
41734
  }
41674
- function readImageInfo(path8) {
41735
+ function readImageInfo(path9) {
41675
41736
  let fd;
41676
41737
  try {
41677
- fd = openSync3(path8, constants3.O_RDONLY | constants3.O_NOFOLLOW);
41738
+ fd = openSync3(path9, constants3.O_RDONLY | constants3.O_NOFOLLOW);
41678
41739
  } catch {
41679
41740
  return null;
41680
41741
  }
@@ -41710,7 +41771,7 @@ function buildDrawingRowsSql(notePk, columns) {
41710
41771
  }
41711
41772
  function runSqlite4(dbPath2, sql) {
41712
41773
  try {
41713
- return execFileSync7("/usr/bin/sqlite3", ["-readonly", dbPath2, sql], {
41774
+ return execFileSync8("/usr/bin/sqlite3", ["-readonly", dbPath2, sql], {
41714
41775
  encoding: "utf8",
41715
41776
  timeout: 1e4,
41716
41777
  maxBuffer: 16 * 1024 * 1024,
@@ -41750,7 +41811,7 @@ function parseDrawingRows(json2) {
41750
41811
  }
41751
41812
  return rows.sort((a, b) => a.pk - b.pk);
41752
41813
  }
41753
- function readDrawingRows(noteId3, dbPath2 = join7(NOTES_CONTAINER_DIR, "NoteStore.sqlite")) {
41814
+ function readDrawingRows(noteId3, dbPath2 = join8(NOTES_CONTAINER_DIR, "NoteStore.sqlite")) {
41754
41815
  const { pk } = parseNoteId2(noteId3);
41755
41816
  const columns = new Set(
41756
41817
  runSqlite4(
@@ -41774,9 +41835,9 @@ function readDrawingRows(noteId3, dbPath2 = join7(NOTES_CONTAINER_DIR, "NoteStor
41774
41835
  throw new AttachmentStoreError("Drawing rows could not be parsed", "query_error");
41775
41836
  }
41776
41837
  }
41777
- function kindOf(path8) {
41838
+ function kindOf(path9) {
41778
41839
  try {
41779
- const st = lstatSync3(path8);
41840
+ const st = lstatSync3(path9);
41780
41841
  return st.isFile() ? "file" : st.isDirectory() ? "dir" : null;
41781
41842
  } catch {
41782
41843
  return null;
@@ -41794,16 +41855,16 @@ var byGenerationDesc = (a, b) => generationRank(basename2(b)) - generationRank(b
41794
41855
  function findFallbackImage(accountDir, identifier, generation) {
41795
41856
  const id2 = safeComponent(identifier);
41796
41857
  if (!id2) return null;
41797
- const base = join7(accountDir, "FallbackImages", id2);
41858
+ const base = join8(accountDir, "FallbackImages", id2);
41798
41859
  const names = ["FallbackImage.png", "FallbackImage.jpg"];
41799
41860
  const candidates = [];
41800
41861
  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`));
41862
+ if (gen) for (const n of names) candidates.push(join8(base, gen, n));
41863
+ const gens = entries(base, MAX_DIR_ENTRIES).map((e) => join8(base, e)).sort(byGenerationDesc);
41864
+ for (const g of gens) for (const n of names) candidates.push(join8(g, n));
41865
+ for (const n of names) candidates.push(join8(base, n));
41866
+ candidates.push(join8(accountDir, "FallbackImages", `${id2}.png`));
41867
+ candidates.push(join8(accountDir, "FallbackImages", `${id2}.jpg`));
41807
41868
  for (const c of candidates) {
41808
41869
  const real = realInside(c, accountDir);
41809
41870
  if (real && kindOf(real) === "file") return real;
@@ -41813,21 +41874,21 @@ function findFallbackImage(accountDir, identifier, generation) {
41813
41874
  function findLargestPreview(accountDir, identifier) {
41814
41875
  const id2 = safeComponent(identifier);
41815
41876
  if (!id2) return null;
41816
- const dir = join7(accountDir, "Previews");
41877
+ const dir = join8(accountDir, "Previews");
41817
41878
  const prefix = `${id2}-`.toLowerCase();
41818
41879
  const names = entries(dir, MAX_PREVIEW_DIR_ENTRIES2).filter((n) => n.toLowerCase().startsWith(prefix)).filter((n) => {
41819
41880
  const ext = extname2(n).toLowerCase();
41820
41881
  return !ext || IMAGE_SUFFIXES.has(ext) || /^\.\d+$/.test(ext);
41821
41882
  }).sort((a, b) => previewPixelArea(b) - previewPixelArea(a) || a.localeCompare(b));
41822
41883
  for (const name of names) {
41823
- const real = realInside(join7(dir, name), accountDir);
41884
+ const real = realInside(join8(dir, name), accountDir);
41824
41885
  if (!real) continue;
41825
41886
  const kind = kindOf(real);
41826
41887
  if (kind === "file") return real;
41827
41888
  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);
41889
+ const gens = entries(real, MAX_DIR_ENTRIES).map((e) => realInside(join8(real, e), accountDir)).filter((p) => p !== null && kindOf(p) === "dir").sort(byGenerationDesc);
41829
41890
  for (const g of [...gens, real]) {
41830
- const file = realInside(join7(g, "Preview.png"), accountDir);
41891
+ const file = realInside(join8(g, "Preview.png"), accountDir);
41831
41892
  if (file && kindOf(file) === "file") return file;
41832
41893
  }
41833
41894
  }
@@ -41840,15 +41901,15 @@ function describeDrawings(rows, containerDir = NOTES_CONTAINER_DIR) {
41840
41901
  const id2 = safeComponent(row.identifier);
41841
41902
  const fallbackImagePath = accountDir ? findFallbackImage(accountDir, row.identifier, row.fallbackImageGeneration) : null;
41842
41903
  const previewPath = accountDir ? findLargestPreview(accountDir, row.identifier) : null;
41843
- const bundle = accountDir && id2 && kind === "paper" ? realInside(join7(accountDir, "Paper", "Bundles", `${id2}.bundle`), accountDir) : null;
41904
+ const bundle = accountDir && id2 && kind === "paper" ? realInside(join8(accountDir, "Paper", "Bundles", `${id2}.bundle`), accountDir) : null;
41844
41905
  let raster = null;
41845
- for (const [path8, source] of [
41906
+ for (const [path9, source] of [
41846
41907
  [fallbackImagePath, "fallback"],
41847
41908
  [previewPath, "preview"]
41848
41909
  ]) {
41849
- const info = path8 ? readImageInfo(path8) : null;
41850
- if (path8 && info) {
41851
- raster = { path: path8, source, ...info };
41910
+ const info = path9 ? readImageInfo(path9) : null;
41911
+ if (path9 && info) {
41912
+ raster = { path: path9, source, ...info };
41852
41913
  break;
41853
41914
  }
41854
41915
  }
@@ -41865,10 +41926,10 @@ function describeDrawings(rows, containerDir = NOTES_CONTAINER_DIR) {
41865
41926
  };
41866
41927
  });
41867
41928
  }
41868
- function verifyWrittenImage(fd, path8, expected) {
41929
+ function verifyWrittenImage(fd, path9, expected) {
41869
41930
  const check2 = readImageInfoFd(fd);
41870
41931
  if (!check2 || check2.format !== expected.format || check2.width !== expected.width || check2.height !== expected.height) {
41871
- unlinkSync2(path8);
41932
+ unlinkSync2(path9);
41872
41933
  throw new Error("The exported image failed validation and was removed.");
41873
41934
  }
41874
41935
  return check2;
@@ -41966,13 +42027,34 @@ function exportDrawingRaster(drawing, savePath, containerDir = NOTES_CONTAINER_D
41966
42027
 
41967
42028
  // src/services/appleNotesManager.ts
41968
42029
  var import_turndown = __toESM(require_turndown_cjs(), 1);
41969
- import { existsSync as existsSync4 } from "fs";
41970
- import { homedir as homedir7 } from "os";
41971
- import { join as join8 } from "path";
42030
+ import { existsSync as existsSync5 } from "fs";
42031
+ import { homedir as homedir8 } from "os";
42032
+ import { join as join9 } from "path";
41972
42033
  var FIELD_SEP = "";
41973
42034
  var RECORD_SEP = "";
41974
42035
  var AS_FIELD_SEP = "(character id 31)";
41975
42036
  var AS_RECORD_SEP = "(character id 30)";
42037
+ var GROUP_SEP = "";
42038
+ var AS_GROUP_SEP = "(character id 29)";
42039
+ var FOLDER_ID_PATTERN = /^x-coredata:\/\/[0-9A-F-]+\/ICFolder\/p\d+$/i;
42040
+ function trashFolderIdList() {
42041
+ const ids = readTrashFolderIds().filter((id2) => FOLDER_ID_PATTERN.test(id2));
42042
+ return `{${ids.map((id2) => `"${id2}"`).join(", ")}}`;
42043
+ }
42044
+ function buildTrashNoteIdsCollector() {
42045
+ return `
42046
+ set __trashNoteIds to {}
42047
+ repeat with __trashFolderId in ${trashFolderIdList()}
42048
+ try
42049
+ set __trashNoteIds to __trashNoteIds & (id of notes of folder id (contents of __trashFolderId))
42050
+ end try
42051
+ end repeat
42052
+ try
42053
+ repeat with __trashFolder in (every folder whose name is "${RECENTLY_DELETED_FOLDER_NAME}")
42054
+ set __trashNoteIds to __trashNoteIds & (id of notes of __trashFolder)
42055
+ end repeat
42056
+ end try`;
42057
+ }
41976
42058
  var DEFAULT_EXPORT_PAGE_SIZE = 50;
41977
42059
  var DEFAULT_EXPORT_MAX_RESPONSE_BYTES = 8 * 1024 * 1024;
41978
42060
  function exportMaxResponseBytes(env = process.env) {
@@ -42196,8 +42278,8 @@ function getNoteLinkFromDB(coreDataId2) {
42196
42278
  const match = coreDataId2.match(/\/p(\d+)$/);
42197
42279
  if (!match) return null;
42198
42280
  const pk = parseInt(match[1], 10);
42199
- const dbPath2 = join8(homedir7(), "Library/Group Containers/group.com.apple.notes/NoteStore.sqlite");
42200
- if (!existsSync4(dbPath2)) return null;
42281
+ const dbPath2 = join9(homedir8(), "Library/Group Containers/group.com.apple.notes/NoteStore.sqlite");
42282
+ if (!existsSync5(dbPath2)) return null;
42201
42283
  try {
42202
42284
  const { DatabaseSync } = __require("node:sqlite");
42203
42285
  const db = new DatabaseSync(dbPath2, { readOnly: true });
@@ -42402,9 +42484,9 @@ var AppleNotesManager = class {
42402
42484
  * const topResults = manager.searchNotes("project", false, undefined, undefined, undefined, 10);
42403
42485
  * ```
42404
42486
  */
42405
- searchNotes(query, searchContent = false, account, folder, modifiedSince, limit) {
42487
+ searchNotes(query2, searchContent = false, account, folder, modifiedSince, limit) {
42406
42488
  const targetAccount = this.resolveAccount(account);
42407
- const safeQuery = escapePlainStringForAppleScript(query);
42489
+ const safeQuery = escapePlainStringForAppleScript(query2);
42408
42490
  const safeLimit = limit !== void 0 && limit > 0 ? Math.floor(limit) : void 0;
42409
42491
  const whereParts = [];
42410
42492
  if (searchContent) {
@@ -42462,7 +42544,7 @@ var AppleNotesManager = class {
42462
42544
  const script = buildAccountScopedScript({ account: targetAccount }, searchCommand);
42463
42545
  const result = executeAppleScript(script);
42464
42546
  if (!result.success) {
42465
- throw new Error(`Failed to search notes for "${query}": ${result.error ?? "unknown error"}`);
42547
+ throw new Error(`Failed to search notes for "${query2}": ${result.error ?? "unknown error"}`);
42466
42548
  }
42467
42549
  if (!result.output.trim()) {
42468
42550
  return [];
@@ -42762,6 +42844,16 @@ var AppleNotesManager = class {
42762
42844
  try
42763
42845
  set originalFolder to container of noteRef
42764
42846
  end try
42847
+ if originalFolder is not missing value then
42848
+ set __inTrash to false
42849
+ try
42850
+ if ${trashFolderIdList()} contains (id of originalFolder) then set __inTrash to true
42851
+ end try
42852
+ try
42853
+ if (name of originalFolder) is "${RECENTLY_DELETED_FOLDER_NAME}" then set __inTrash to true
42854
+ end try
42855
+ if __inTrash then return "SAFETY_IN_RECENTLY_DELETED"
42856
+ end if
42765
42857
  set currentBody to body of noteRef
42766
42858
  considering case
42767
42859
  if currentBody is not "${safeExpectedBody}" and currentBody is not "${safeExpectedBody}" & linefeed then return "SAFETY_CONFLICT"
@@ -42781,6 +42873,7 @@ var AppleNotesManager = class {
42781
42873
  }
42782
42874
  const status = result.output.trim();
42783
42875
  if (status === "SAFETY_CONFLICT") return { status: "conflict" };
42876
+ if (status === "SAFETY_IN_RECENTLY_DELETED") return { status: "in-recently-deleted" };
42784
42877
  if (status === "SAFETY_NOT_DELETED") return { status: "not-deleted" };
42785
42878
  return status === "SAFETY_DELETED" ? { status: "deleted" } : { status: "failed" };
42786
42879
  }
@@ -42806,14 +42899,20 @@ var AppleNotesManager = class {
42806
42899
  * dateSetup: a date filter must scan every note's date). The script then
42807
42900
  * returns the total note count as a leading record so the caller can
42808
42901
  * detect a dedup shortfall and fall back to a full fetch.
42902
+ * @param trashCheck - Also return the ids of notes in Recently Deleted,
42903
+ * after a group separator, so the caller can exclude or flag them (#207).
42904
+ * Only valid inside an account-scoped script.
42809
42905
  */
42810
42906
  buildBulkListCommand(opts) {
42811
- const { folderRef, dateSetup, sliceLimit } = opts;
42907
+ const { folderRef, dateSetup, sliceLimit, trashCheck } = opts;
42812
42908
  const fullSource = folderRef ? `notes of ${folderRef}` : "notes";
42909
+ const trashSetup = trashCheck ? `${buildTrashNoteIdsCollector()}
42910
+ ` : "";
42911
+ const trashSuffix = trashCheck ? ` & ${AS_GROUP_SEP} & (__trashNoteIds as text)` : "";
42813
42912
  const countGuard = (listVar) => `if (count of ${listVar}) is not (count of noteNames) then error "${BULK_LIST_MUTATION_ERROR}"`;
42814
42913
  if (sliceLimit !== void 0) {
42815
42914
  const slicedSource = folderRef ? `(notes 1 thru fetchCount of ${folderRef})` : `(notes 1 thru fetchCount)`;
42816
- return `
42915
+ return `${trashSetup}
42817
42916
  set totalCount to count of ${fullSource}
42818
42917
  set fetchCount to ${sliceLimit}
42819
42918
  if fetchCount > totalCount then set fetchCount to totalCount
@@ -42840,7 +42939,7 @@ var AppleNotesManager = class {
42840
42939
  end repeat
42841
42940
  end if
42842
42941
  set AppleScript's text item delimiters to ${AS_RECORD_SEP}
42843
- return (totalCount as text) & ${AS_RECORD_SEP} & (resultList as text)
42942
+ return (totalCount as text) & ${AS_RECORD_SEP} & (resultList as text)${trashSuffix}
42844
42943
  `;
42845
42944
  }
42846
42945
  const dateFetch = dateSetup ? `set noteDates to modification date of ${fullSource}
@@ -42851,7 +42950,7 @@ var AppleNotesManager = class {
42851
42950
  ` : "";
42852
42951
  const dateGuardClose = dateSetup ? `
42853
42952
  end if` : "";
42854
- return `
42953
+ return `${trashSetup}
42855
42954
  ${dateSetup ?? ""}set noteNames to name of ${fullSource}
42856
42955
  set noteIds to id of ${fullSource}
42857
42956
  ${dateFetch}${countGuard("noteIds")}
@@ -42860,7 +42959,7 @@ var AppleNotesManager = class {
42860
42959
  ${dateGuardOpen}set end of resultList to (item i of noteNames) & ${AS_FIELD_SEP} & (item i of noteIds)${dateGuardClose}
42861
42960
  end repeat
42862
42961
  set AppleScript's text item delimiters to ${AS_RECORD_SEP}
42863
- return resultList as text
42962
+ return (resultList as text)${trashSuffix}
42864
42963
  `;
42865
42964
  }
42866
42965
  /**
@@ -42922,19 +43021,49 @@ var AppleNotesManager = class {
42922
43021
  * after dedup so duplicates never count against it.
42923
43022
  */
42924
43023
  parseBulkListOutput(output, safeLimit) {
42925
- if (!output.trim()) return [];
42926
- const seenIds = /* @__PURE__ */ new Set();
43024
+ return this.parseBulkListRecords(output, safeLimit).refs;
43025
+ }
43026
+ /**
43027
+ * Splits a trash-checked listing (see buildBulkListCommand's trashCheck)
43028
+ * into the listing records and the set of note ids in Recently Deleted.
43029
+ * Output without the group separator carries no trash information (null).
43030
+ */
43031
+ splitTrashIds(output) {
43032
+ const idx = output.lastIndexOf(GROUP_SEP);
43033
+ if (idx === -1) return { records: output, trashIds: null };
43034
+ const trashIds = new Set(
43035
+ output.slice(idx + 1).split(RECORD_SEP).map((id2) => id2.trim()).filter(Boolean)
43036
+ );
43037
+ return { records: output.slice(0, idx), trashIds };
43038
+ }
43039
+ /**
43040
+ * Parses bulk listing records, deduplicated by id. Notes whose id is in
43041
+ * `trash.ids` are dropped (and counted) unless `trash.include`, in which
43042
+ * case they are kept and flagged `inRecentlyDeleted`. The limit applies
43043
+ * after both dedup and trash filtering.
43044
+ */
43045
+ parseBulkListRecords(output, safeLimit, trash) {
42927
43046
  const refs = [];
43047
+ let excludedRecentlyDeleted = 0;
43048
+ if (!output.trim()) return { refs, excludedRecentlyDeleted };
43049
+ const seenIds = /* @__PURE__ */ new Set();
42928
43050
  for (const item of output.split(RECORD_SEP)) {
42929
43051
  const [title, id2] = item.split(FIELD_SEP);
42930
43052
  if (!title?.trim()) continue;
42931
43053
  const noteId3 = id2?.trim() || generateFallbackId();
42932
43054
  if (seenIds.has(noteId3)) continue;
42933
43055
  seenIds.add(noteId3);
42934
- refs.push({ title: title.trim(), id: noteId3 });
43056
+ const trashed = trash?.ids?.has(noteId3) ?? false;
43057
+ if (trashed && !trash?.include) {
43058
+ excludedRecentlyDeleted++;
43059
+ continue;
43060
+ }
43061
+ refs.push(
43062
+ trashed ? { title: title.trim(), id: noteId3, inRecentlyDeleted: true } : { title: title.trim(), id: noteId3 }
43063
+ );
42935
43064
  if (safeLimit !== void 0 && refs.length >= safeLimit) break;
42936
43065
  }
42937
- return refs;
43066
+ return { refs, excludedRecentlyDeleted };
42938
43067
  }
42939
43068
  /**
42940
43069
  * Core listing path shared by `listNotes()` and `listNoteRefs()`: lists
@@ -42942,7 +43071,7 @@ var AppleNotesManager = class {
42942
43071
  * returning (title, id) pairs. Kept private because both public callers
42943
43072
  * need to apply their own return shape.
42944
43073
  */
42945
- listNotesCore(account, folder, modifiedSince, limit) {
43074
+ listNotesCore(account, folder, modifiedSince, limit, includeRecentlyDeleted = false) {
42946
43075
  const targetAccount = this.resolveAccount(account);
42947
43076
  const safeLimit = limit !== void 0 && limit > 0 ? Math.floor(limit) : void 0;
42948
43077
  const folderRef = folder ? buildFolderReference(folder) : void 0;
@@ -42956,30 +43085,38 @@ var AppleNotesManager = class {
42956
43085
  if (safeLimit !== void 0 && !dateSetup) {
42957
43086
  const script2 = buildAccountScopedScript(
42958
43087
  { account: targetAccount },
42959
- this.buildBulkListCommand({ folderRef, sliceLimit: safeLimit })
43088
+ this.buildBulkListCommand({ folderRef, sliceLimit: safeLimit, trashCheck: true })
42960
43089
  );
42961
43090
  const result2 = executeAppleScript(script2);
42962
43091
  if (!result2.success) {
42963
43092
  throw new Error(`Failed to list notes: ${result2.error ?? "unknown error"}`);
42964
43093
  }
42965
- const sepIdx = result2.output.indexOf(RECORD_SEP);
42966
- const header = sepIdx === -1 ? result2.output : result2.output.slice(0, sepIdx);
43094
+ const { records: body, trashIds: trashIds2 } = this.splitTrashIds(result2.output);
43095
+ const sepIdx = body.indexOf(RECORD_SEP);
43096
+ const header = sepIdx === -1 ? body : body.slice(0, sepIdx);
42967
43097
  const totalCount = Number.parseInt(header.trim(), 10);
42968
- const records = sepIdx === -1 ? "" : result2.output.slice(sepIdx + 1);
42969
- const refs = this.parseBulkListOutput(records, safeLimit);
42970
- if (!Number.isNaN(totalCount) && (refs.length >= safeLimit || totalCount <= safeLimit)) {
42971
- return refs;
43098
+ const records2 = sepIdx === -1 ? "" : body.slice(sepIdx + 1);
43099
+ const parsed = this.parseBulkListRecords(records2, safeLimit, {
43100
+ ids: trashIds2,
43101
+ include: includeRecentlyDeleted
43102
+ });
43103
+ if (!Number.isNaN(totalCount) && (parsed.refs.length >= safeLimit || totalCount <= safeLimit)) {
43104
+ return parsed;
42972
43105
  }
42973
43106
  }
42974
43107
  const script = buildAccountScopedScript(
42975
43108
  { account: targetAccount },
42976
- this.buildBulkListCommand({ folderRef, dateSetup })
43109
+ this.buildBulkListCommand({ folderRef, dateSetup, trashCheck: true })
42977
43110
  );
42978
43111
  const result = executeAppleScript(script);
42979
43112
  if (!result.success) {
42980
43113
  throw new Error(`Failed to list notes: ${result.error ?? "unknown error"}`);
42981
43114
  }
42982
- return this.parseBulkListOutput(result.output, safeLimit);
43115
+ const { records, trashIds } = this.splitTrashIds(result.output);
43116
+ return this.parseBulkListRecords(records, safeLimit, {
43117
+ ids: trashIds,
43118
+ include: includeRecentlyDeleted
43119
+ });
42983
43120
  }
42984
43121
  /**
42985
43122
  * Lists all notes in an account, optionally filtered by folder, date, and limit.
@@ -42991,7 +43128,7 @@ var AppleNotesManager = class {
42991
43128
  * @returns Array of note titles
42992
43129
  */
42993
43130
  listNotes(account, folder, modifiedSince, limit) {
42994
- return this.listNotesCore(account, folder, modifiedSince, limit).map((ref) => ref.title);
43131
+ return this.listNotesCore(account, folder, modifiedSince, limit).refs.map((ref) => ref.title);
42995
43132
  }
42996
43133
  /**
42997
43134
  * Lists all notes in an account, optionally filtered by folder, date, and
@@ -43002,10 +43139,23 @@ var AppleNotesManager = class {
43002
43139
  * specifier resolves ambiguously to the same one note every time — see
43003
43140
  * the fix in exportNotesAsJson for the failure mode this avoids).
43004
43141
  *
43142
+ * Notes in Recently Deleted are excluded (#207); use
43143
+ * `listNoteRefsDetailed()` to include and flag them.
43144
+ *
43005
43145
  * @returns Array of { title, id } pairs, deduplicated by id
43006
43146
  */
43007
43147
  listNoteRefs(account, folder, modifiedSince, limit) {
43008
- return this.listNotesCore(account, folder, modifiedSince, limit);
43148
+ return this.listNotesCore(account, folder, modifiedSince, limit).refs;
43149
+ }
43150
+ /**
43151
+ * Same as `listNoteRefs()`, plus control over notes in Recently Deleted and
43152
+ * a count of how many were skipped. Notes.app's account-wide `notes`
43153
+ * includes Recently Deleted, so they are excluded unless
43154
+ * `includeRecentlyDeleted`, in which case each is flagged
43155
+ * `inRecentlyDeleted: true`. (#207)
43156
+ */
43157
+ listNoteRefsDetailed(account, folder, modifiedSince, limit, includeRecentlyDeleted = false) {
43158
+ return this.listNotesCore(account, folder, modifiedSince, limit, includeRecentlyDeleted);
43009
43159
  }
43010
43160
  /**
43011
43161
  * Lists all shared (collaborative) notes across all accounts.
@@ -44075,7 +44225,7 @@ var AppleNotesManager = class {
44075
44225
  if (parts[0] !== "OK") {
44076
44226
  return { success: false, error: parts[1]?.trim() || "attachment not found" };
44077
44227
  }
44078
- if (!existsSync4(abs) || fileSize(abs) === 0) {
44228
+ if (!existsSync5(abs) || fileSize(abs) === 0) {
44079
44229
  return { success: false, error: `Notes reported success but no file was written to ${abs}` };
44080
44230
  }
44081
44231
  return {
@@ -44580,15 +44730,15 @@ var AppleNotesManager = class {
44580
44730
  };
44581
44731
 
44582
44732
  // src/utils/syncDetection.ts
44583
- import { execFileSync as execFileSync8 } from "child_process";
44584
- import * as fs3 from "fs";
44585
- import * as path3 from "path";
44586
- import * as os3 from "os";
44587
- var NOTES_DB_PATH4 = path3.join(
44588
- os3.homedir(),
44733
+ import { execFileSync as execFileSync9 } from "child_process";
44734
+ import * as fs4 from "fs";
44735
+ import * as path4 from "path";
44736
+ import * as os4 from "os";
44737
+ var NOTES_DB_PATH5 = path4.join(
44738
+ os4.homedir(),
44589
44739
  "Library/Group Containers/group.com.apple.notes/NoteStore.sqlite"
44590
44740
  );
44591
- var WAL_PATH = `${NOTES_DB_PATH4}-wal`;
44741
+ var WAL_PATH = `${NOTES_DB_PATH5}-wal`;
44592
44742
  var RECENT_ACTIVITY_THRESHOLD_SECONDS = 5;
44593
44743
  var SYNC_STATUS_CACHE_TTL_MS = 2e3;
44594
44744
  var cachedSyncStatus = null;
@@ -44604,19 +44754,19 @@ function getSyncStatus(useCache = true) {
44604
44754
  recentActivity: false
44605
44755
  };
44606
44756
  try {
44607
- if (!fs3.existsSync(NOTES_DB_PATH4)) {
44757
+ if (!fs4.existsSync(NOTES_DB_PATH5)) {
44608
44758
  status.error = "Notes database not found";
44609
44759
  cachedSyncStatus = status;
44610
44760
  cacheTimestamp = Date.now();
44611
44761
  return status;
44612
44762
  }
44613
- if (fs3.existsSync(WAL_PATH)) {
44614
- const walStats = fs3.statSync(WAL_PATH);
44763
+ if (fs4.existsSync(WAL_PATH)) {
44764
+ const walStats = fs4.statSync(WAL_PATH);
44615
44765
  const secondsAgo = (Date.now() - walStats.mtimeMs) / 1e3;
44616
44766
  status.secondsSinceLastChange = Math.round(secondsAgo);
44617
44767
  status.recentActivity = secondsAgo < RECENT_ACTIVITY_THRESHOLD_SECONDS;
44618
44768
  }
44619
- const query = `
44769
+ const query2 = `
44620
44770
  SELECT COUNT(*) FROM ZICCLOUDSTATE state
44621
44771
  WHERE state.ZCURRENTLOCALVERSION > state.ZLATESTVERSIONSYNCEDTOCLOUD
44622
44772
  AND state.ZLATESTVERSIONSYNCEDTOCLOUD IS NOT NULL
@@ -44625,9 +44775,9 @@ function getSyncStatus(useCache = true) {
44625
44775
  WHERE object.ZCLOUDSTATE = state.Z_PK
44626
44776
  );
44627
44777
  `;
44628
- const result = execFileSync8(
44778
+ const result = execFileSync9(
44629
44779
  "sqlite3",
44630
- ["-readonly", NOTES_DB_PATH4, query.replace(/\n/g, " ")],
44780
+ ["-readonly", NOTES_DB_PATH5, query2.replace(/\n/g, " ")],
44631
44781
  {
44632
44782
  encoding: "utf8",
44633
44783
  timeout: 5e3,
@@ -44684,12 +44834,12 @@ function withSyncAwarenessSync(operation, fn) {
44684
44834
  }
44685
44835
 
44686
44836
  // src/utils/noteMetadata.ts
44687
- import { execFileSync as execFileSync9 } from "child_process";
44688
- import * as fs4 from "fs";
44689
- import * as path4 from "path";
44690
- import * as os4 from "os";
44691
- var NOTES_DB_PATH5 = path4.join(
44692
- os4.homedir(),
44837
+ import { execFileSync as execFileSync10 } from "child_process";
44838
+ import * as fs5 from "fs";
44839
+ import * as path5 from "path";
44840
+ import * as os5 from "os";
44841
+ var NOTES_DB_PATH6 = path5.join(
44842
+ os5.homedir(),
44693
44843
  "Library/Group Containers/group.com.apple.notes/NoteStore.sqlite"
44694
44844
  );
44695
44845
  var FDA_MESSAGE2 = `Full Disk Access is required to read note metadata. In System Settings > Privacy & Security > Full Disk Access, grant access to the app that launches this server (Claude Desktop / Terminal / iTerm2), then fully quit and relaunch it. Setup guide: ${FULL_DISK_ACCESS_GUIDE_URL} \u2014 run the doctor tool to verify.`;
@@ -44704,8 +44854,8 @@ var COLUMN_MAP = [
44704
44854
  { key: "widgetSnippet", column: "ZWIDGETSNIPPET", type: "text" },
44705
44855
  { key: "smartFolderQuery", column: "ZSMARTFOLDERQUERYJSON", type: "text" }
44706
44856
  ];
44707
- function runSqlite5(query) {
44708
- return execFileSync9("sqlite3", ["-readonly", NOTES_DB_PATH5, query], {
44857
+ function runSqlite5(query2) {
44858
+ return execFileSync10("sqlite3", ["-readonly", NOTES_DB_PATH6, query2], {
44709
44859
  encoding: "utf8",
44710
44860
  timeout: 5e3,
44711
44861
  stdio: ["pipe", "pipe", "pipe"]
@@ -44730,7 +44880,7 @@ function getNoteMetadata(noteId3) {
44730
44880
  };
44731
44881
  }
44732
44882
  const pk = pkMatch[1];
44733
- if (!fs4.existsSync(NOTES_DB_PATH5)) {
44883
+ if (!fs5.existsSync(NOTES_DB_PATH6)) {
44734
44884
  return { metadata: null, error: "no_fda", message: FDA_MESSAGE2 };
44735
44885
  }
44736
44886
  try {
@@ -44776,12 +44926,12 @@ function getNoteMetadata(noteId3) {
44776
44926
  import { gunzipSync as gunzipSync6 } from "zlib";
44777
44927
 
44778
44928
  // src/utils/noteStoreSql.ts
44779
- import { execFileSync as execFileSync10 } from "child_process";
44780
- import * as fs5 from "fs";
44781
- import * as os5 from "os";
44782
- import * as path5 from "path";
44783
- var NOTES_DB_PATH6 = path5.join(
44784
- os5.homedir(),
44929
+ import { execFileSync as execFileSync11 } from "child_process";
44930
+ import * as fs6 from "fs";
44931
+ import * as os6 from "os";
44932
+ import * as path6 from "path";
44933
+ var NOTES_DB_PATH7 = path6.join(
44934
+ os6.homedir(),
44785
44935
  "Library/Group Containers/group.com.apple.notes/NoteStore.sqlite"
44786
44936
  );
44787
44937
  var CORE_DATA_EPOCH_MS = Date.UTC(2001, 0, 1);
@@ -44819,7 +44969,7 @@ function renderValue(value) {
44819
44969
  return `ieee754_from_blob(x'${doubleToHex(double)}')`;
44820
44970
  }
44821
44971
  function runReadOnlySql(dbPath2, sql, params = {}) {
44822
- if (!fs5.existsSync(dbPath2)) throw new NoteStoreError(STORE_FDA_MESSAGE, "no_fda");
44972
+ if (!fs6.existsSync(dbPath2)) throw new NoteStoreError(STORE_FDA_MESSAGE, "no_fda");
44823
44973
  const args = ["-readonly"];
44824
44974
  const names = Object.keys(params);
44825
44975
  if (names.length) args.push("-cmd", ".parameter init");
@@ -44831,7 +44981,7 @@ function runReadOnlySql(dbPath2, sql, params = {}) {
44831
44981
  }
44832
44982
  args.push(dbPath2, sql);
44833
44983
  try {
44834
- return execFileSync10("sqlite3", args, {
44984
+ return execFileSync11("sqlite3", args, {
44835
44985
  encoding: "utf8",
44836
44986
  timeout: 3e4,
44837
44987
  maxBuffer: 512 * 1024 * 1024,
@@ -45024,7 +45174,7 @@ function buildSpecialNotesSql(columns, kind, scoped) {
45024
45174
  ].join(" ");
45025
45175
  }
45026
45176
  function listSpecialNotes(options) {
45027
- const dbPath2 = options.dbPath ?? NOTES_DB_PATH6;
45177
+ const dbPath2 = options.dbPath ?? NOTES_DB_PATH7;
45028
45178
  const limit = Math.min(
45029
45179
  Math.max(1, Math.trunc(options.limit ?? SPECIAL_LIMIT.DEFAULT)),
45030
45180
  SPECIAL_LIMIT.MAX
@@ -45115,7 +45265,7 @@ function referencedObjects(hex3) {
45115
45265
  }
45116
45266
  }
45117
45267
  function nativeTagInventory(options = {}) {
45118
- const dbPath2 = options.dbPath ?? NOTES_DB_PATH6;
45268
+ const dbPath2 = options.dbPath ?? NOTES_DB_PATH7;
45119
45269
  const columns = readColumns(dbPath2);
45120
45270
  const context = readStoreContext(dbPath2, columns);
45121
45271
  const scope2 = options.account ? resolveAccountName(context.accounts, options.account) : void 0;
@@ -45177,12 +45327,12 @@ function assembleInventory(rows, accounts, scope2) {
45177
45327
  }
45178
45328
 
45179
45329
  // src/utils/noteIdentifiers.ts
45180
- import { execFileSync as execFileSync11 } from "child_process";
45181
- import * as fs6 from "fs";
45182
- import * as os6 from "os";
45183
- import * as path6 from "path";
45184
- var NOTES_DB_PATH7 = path6.join(
45185
- os6.homedir(),
45330
+ import { execFileSync as execFileSync12 } from "child_process";
45331
+ import * as fs7 from "fs";
45332
+ import * as os7 from "os";
45333
+ import * as path7 from "path";
45334
+ var NOTES_DB_PATH8 = path7.join(
45335
+ os7.homedir(),
45186
45336
  "Library/Group Containers/group.com.apple.notes/NoteStore.sqlite"
45187
45337
  );
45188
45338
  var UUID_PATTERN = /^[0-9A-Fa-f]{8}(?:-[0-9A-Fa-f]{4}){3}-[0-9A-Fa-f]{12}$/;
@@ -45256,10 +45406,10 @@ function buildLookupSql(entity3, keys) {
45256
45406
  return `SELECT json_object('store', (SELECT Z_UUID FROM Z_METADATA LIMIT 1), 'rows', (SELECT json_group_array(json_object(${fields})) FROM ZICCLOUDSYNCINGOBJECT o ${joins}WHERE o.Z_ENT = ${entityClause(entity3)} AND o.Z_PK IN (${inList})));`;
45257
45407
  }
45258
45408
  function runJsonQuery(sql, dbPath2) {
45259
- if (!fs6.existsSync(dbPath2)) throw new IdentifierResolutionError("no_fda", NO_FDA_MESSAGE);
45409
+ if (!fs7.existsSync(dbPath2)) throw new IdentifierResolutionError("no_fda", NO_FDA_MESSAGE);
45260
45410
  let out;
45261
45411
  try {
45262
- out = execFileSync11("sqlite3", ["-readonly", dbPath2, sql], {
45412
+ out = execFileSync12("sqlite3", ["-readonly", dbPath2, sql], {
45263
45413
  encoding: "utf8",
45264
45414
  timeout: 5e3,
45265
45415
  stdio: ["pipe", "pipe", "pipe"]
@@ -45279,7 +45429,7 @@ function runJsonQuery(sql, dbPath2) {
45279
45429
  function coreDataId(store, entity3, pk) {
45280
45430
  return `x-coredata://${store}/${entity3}/p${pk}`;
45281
45431
  }
45282
- function resolveIdentifiers(values, entity3, dbPath2 = NOTES_DB_PATH7) {
45432
+ function resolveIdentifiers(values, entity3, dbPath2 = NOTES_DB_PATH8) {
45283
45433
  const resolved = /* @__PURE__ */ new Map();
45284
45434
  const keys = [];
45285
45435
  const uuids = [];
@@ -45325,7 +45475,7 @@ function resolveIdentifiers(values, entity3, dbPath2 = NOTES_DB_PATH7) {
45325
45475
  return resolved;
45326
45476
  }
45327
45477
  var COREDATA_PARTS = /^x-coredata:\/\/([0-9A-Fa-f-]+)\/(ICNote|ICFolder|ICAccount)\/p(\d{1,18})$/;
45328
- function lookupStableIdentifiers(ids, entity3, dbPath2 = NOTES_DB_PATH7) {
45478
+ function lookupStableIdentifiers(ids, entity3, dbPath2 = NOTES_DB_PATH8) {
45329
45479
  const result = /* @__PURE__ */ new Map();
45330
45480
  const wanted = /* @__PURE__ */ new Map();
45331
45481
  for (const id2 of ids) {
@@ -45337,14 +45487,14 @@ function lookupStableIdentifiers(ids, entity3, dbPath2 = NOTES_DB_PATH7) {
45337
45487
  wanted.set(pk, list);
45338
45488
  }
45339
45489
  if (wanted.size === 0) return result;
45340
- let query;
45490
+ let query2;
45341
45491
  try {
45342
- query = runJsonQuery(buildLookupSql(entity3, [...wanted.keys()]), dbPath2);
45492
+ query2 = runJsonQuery(buildLookupSql(entity3, [...wanted.keys()]), dbPath2);
45343
45493
  } catch {
45344
45494
  return result;
45345
45495
  }
45346
- const store = query.store?.toUpperCase();
45347
- for (const row of query.rows) {
45496
+ const store = query2.store?.toUpperCase();
45497
+ for (const row of query2.rows) {
45348
45498
  const fields = {};
45349
45499
  for (const key of [
45350
45500
  "identifier",
@@ -45361,7 +45511,7 @@ function lookupStableIdentifiers(ids, entity3, dbPath2 = NOTES_DB_PATH7) {
45361
45511
  }
45362
45512
  return result;
45363
45513
  }
45364
- function withStableIdentifiers(items, entity3, dbPath2 = NOTES_DB_PATH7) {
45514
+ function withStableIdentifiers(items, entity3, dbPath2 = NOTES_DB_PATH8) {
45365
45515
  const ids = items.map((item) => item.id).filter((id2) => typeof id2 === "string");
45366
45516
  if (ids.length === 0) return items;
45367
45517
  const found = lookupStableIdentifiers(ids, entity3, dbPath2);
@@ -45949,13 +46099,13 @@ function positiveTextTerms(node, negated = false) {
45949
46099
  }
45950
46100
 
45951
46101
  // src/utils/noteQueryStore.ts
45952
- import { execFileSync as execFileSync12 } from "child_process";
45953
- import * as fs7 from "fs";
45954
- import * as os7 from "os";
45955
- import * as path7 from "path";
46102
+ import { execFileSync as execFileSync13 } from "child_process";
46103
+ import * as fs8 from "fs";
46104
+ import * as os8 from "os";
46105
+ import * as path8 from "path";
45956
46106
  import { gunzipSync as gunzipSync7 } from "zlib";
45957
- var NOTES_DB_PATH8 = path7.join(
45958
- os7.homedir(),
46107
+ var NOTES_DB_PATH9 = path8.join(
46108
+ os8.homedir(),
45959
46109
  "Library/Group Containers/group.com.apple.notes/NoteStore.sqlite"
45960
46110
  );
45961
46111
  var QUERY_SCAN = { DEFAULT: 500, MAX: 5e3 };
@@ -46089,8 +46239,8 @@ function buildScanSql(available, options) {
46089
46239
  "COMMIT;"
46090
46240
  ].join(" ");
46091
46241
  }
46092
- function runSqlite6(dbPath2, query) {
46093
- return execFileSync12("sqlite3", ["-readonly", dbPath2, query], {
46242
+ function runSqlite6(dbPath2, query2) {
46243
+ return execFileSync13("sqlite3", ["-readonly", dbPath2, query2], {
46094
46244
  encoding: "utf8",
46095
46245
  timeout: 3e4,
46096
46246
  maxBuffer: 512 * 1024 * 1024,
@@ -46117,12 +46267,12 @@ function resolveFolders(rows) {
46117
46267
  seen.add(pk);
46118
46268
  const parent = row.parent !== null ? resolve5(row.parent, seen) : void 0;
46119
46269
  const name = row.name ?? "";
46120
- const path8 = parent ? `${parent.path}/${escapeSegment(name)}` : escapeSegment(name);
46270
+ const path9 = parent ? `${parent.path}/${escapeSegment(name)}` : escapeSegment(name);
46121
46271
  const plainPath = parent ? `${parent.plainPath}/${name}` : name;
46122
46272
  const info = {
46123
- path: path8,
46273
+ path: path9,
46124
46274
  plainPath,
46125
- keys: [...new Set([name, plainPath, path8].map(normalizeForMatch))],
46275
+ keys: [...new Set([name, plainPath, path9].map(normalizeForMatch))],
46126
46276
  accountPk: row.owner ?? parent?.accountPk ?? null,
46127
46277
  shared: Boolean(row.shared) || Boolean(parent?.shared)
46128
46278
  };
@@ -46154,8 +46304,8 @@ function queryNotes(expression, options = {}) {
46154
46304
  const includeDeleted = options.includeDeleted ?? false;
46155
46305
  const withBodies = needsContent(ast);
46156
46306
  const withTags = needsTags(ast);
46157
- const dbPath2 = options.dbPath ?? NOTES_DB_PATH8;
46158
- if (!fs7.existsSync(dbPath2)) throw new NoteQueryStoreError(QUERY_FDA_MESSAGE, "no_fda");
46307
+ const dbPath2 = options.dbPath ?? NOTES_DB_PATH9;
46308
+ if (!fs8.existsSync(dbPath2)) throw new NoteQueryStoreError(QUERY_FDA_MESSAGE, "no_fda");
46159
46309
  let output;
46160
46310
  try {
46161
46311
  const available = presentColumns2(dbPath2);
@@ -46290,10 +46440,10 @@ function queryNotes(expression, options = {}) {
46290
46440
  import { spawnSync } from "child_process";
46291
46441
 
46292
46442
  // src/services/nativeTags.ts
46293
- import { execFileSync as execFileSync13 } from "node:child_process";
46443
+ import { execFileSync as execFileSync14 } from "node:child_process";
46294
46444
  import { mkdtempSync as mkdtempSync2, writeFileSync, rmSync as rmSync2 } from "node:fs";
46295
46445
  import { tmpdir as tmpdir2 } from "node:os";
46296
- import { join as join14 } from "node:path";
46446
+ import { join as join15 } from "node:path";
46297
46447
 
46298
46448
  // src/services/shortcutConsent.ts
46299
46449
  function shortcutConsentHint(shortcut) {
@@ -46369,7 +46519,7 @@ function addNativeTags(request, deps) {
46369
46519
  };
46370
46520
  }
46371
46521
  function listInstalledShortcuts() {
46372
- return execFileSync13("/usr/bin/shortcuts", ["list", "--show-identifiers"], {
46522
+ return execFileSync14("/usr/bin/shortcuts", ["list", "--show-identifiers"], {
46373
46523
  encoding: "utf8",
46374
46524
  timeout: 15e3,
46375
46525
  maxBuffer: 1024 * 1024,
@@ -46395,11 +46545,11 @@ function runNativeTagsShortcut(input) {
46395
46545
  const status = nativeTagsStatus();
46396
46546
  if (!status.installed)
46397
46547
  throw new Error(`Import the supplied ${status.shortcut}.shortcut in Shortcuts first`);
46398
- const directory = mkdtempSync2(join14(tmpdir2(), "apple-notes-native-tags-"));
46548
+ const directory = mkdtempSync2(join15(tmpdir2(), "apple-notes-native-tags-"));
46399
46549
  try {
46400
- const path8 = join14(directory, "request.json");
46401
- writeFileSync(path8, JSON.stringify(input), { mode: 384 });
46402
- execFileSync13("/usr/bin/shortcuts", ["run", status.identifier, "--input-path", path8], {
46550
+ const path9 = join15(directory, "request.json");
46551
+ writeFileSync(path9, JSON.stringify(input), { mode: 384 });
46552
+ execFileSync14("/usr/bin/shortcuts", ["run", status.identifier, "--input-path", path9], {
46403
46553
  encoding: "utf8",
46404
46554
  timeout: 6e4,
46405
46555
  maxBuffer: 1024 * 1024,
@@ -46418,10 +46568,10 @@ function runNativeTagsShortcut(input) {
46418
46568
  }
46419
46569
 
46420
46570
  // src/services/backgroundNotes.ts
46421
- import { execFileSync as execFileSync14 } from "node:child_process";
46571
+ import { execFileSync as execFileSync15 } from "node:child_process";
46422
46572
  import { mkdtempSync as mkdtempSync3, writeFileSync as writeFileSync2, rmSync as rmSync3 } from "node:fs";
46423
46573
  import { tmpdir as tmpdir3 } from "node:os";
46424
- import { join as join15 } from "node:path";
46574
+ import { join as join16 } from "node:path";
46425
46575
 
46426
46576
  // src/utils/appendMarkdown.ts
46427
46577
  var escape2 = (s) => s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
@@ -46746,9 +46896,9 @@ function runBackgroundShortcut(input, status = backgroundStatus()) {
46746
46896
  throw new Error(
46747
46897
  `Install the supplied "${status.shortcut}" Shortcut once; Shortcuts must list it exactly once`
46748
46898
  );
46749
- const directory = mkdtempSync3(join15(tmpdir3(), "apple-notes-background-"));
46899
+ const directory = mkdtempSync3(join16(tmpdir3(), "apple-notes-background-"));
46750
46900
  try {
46751
- const file = join15(directory, "request.json");
46901
+ const file = join16(directory, "request.json");
46752
46902
  writeFileSync2(
46753
46903
  file,
46754
46904
  JSON.stringify({
@@ -46768,7 +46918,7 @@ function runBackgroundShortcut(input, status = backgroundStatus()) {
46768
46918
  { mode: 384 }
46769
46919
  );
46770
46920
  try {
46771
- execFileSync14("/usr/bin/shortcuts", ["run", status.identifier, "--input-path", file], {
46921
+ execFileSync15("/usr/bin/shortcuts", ["run", status.identifier, "--input-path", file], {
46772
46922
  encoding: "utf8",
46773
46923
  timeout: callTimeoutMs() ?? 6e4,
46774
46924
  maxBuffer: 1024 * 1024,
@@ -47003,7 +47153,7 @@ function createMarkdownNote(manager, request, run = runBackgroundShortcut) {
47003
47153
  throw new Error(
47004
47154
  `Install the supplied "${status.shortcut}" Shortcut once; Shortcuts must list it exactly once`
47005
47155
  );
47006
- const segments = (path8) => JSON.stringify(splitFolderPath(path8).map((part) => part.toLocaleLowerCase()));
47156
+ const segments = (path9) => JSON.stringify(splitFolderPath(path9).map((part) => part.toLocaleLowerCase()));
47007
47157
  if (request.folder) {
47008
47158
  const wanted = segments(request.folder);
47009
47159
  if (!manager.listAccounts().some(
@@ -47093,7 +47243,7 @@ ${request.content}`
47093
47243
  }
47094
47244
 
47095
47245
  // src/services/capabilityMatrix.ts
47096
- import { execFileSync as execFileSync15 } from "node:child_process";
47246
+ import { execFileSync as execFileSync16 } from "node:child_process";
47097
47247
  import { release } from "node:os";
47098
47248
  var MACOS_SHORTCUTS_CLI = "12.0";
47099
47249
  var MACOS_MARKDOWN_IMPORT = "26.0";
@@ -47300,7 +47450,7 @@ function evaluateFeatures(env, features = FEATURES) {
47300
47450
  function readMacOSVersion() {
47301
47451
  if (process.platform !== "darwin") return null;
47302
47452
  try {
47303
- const out = execFileSync15("/usr/bin/sw_vers", ["-productVersion"], {
47453
+ const out = execFileSync16("/usr/bin/sw_vers", ["-productVersion"], {
47304
47454
  encoding: "utf8",
47305
47455
  timeout: 3e3,
47306
47456
  stdio: ["ignore", "pipe", "ignore"]
@@ -47333,9 +47483,9 @@ function getCapabilityMatrix(probe = probeCapabilityEnvironment) {
47333
47483
  return evaluateFeatures(probe());
47334
47484
  }
47335
47485
  function formatCapabilityMatrix(matrix) {
47336
- const os8 = matrix.runtimeOS;
47486
+ const os9 = matrix.runtimeOS;
47337
47487
  const lines = [
47338
- `Feature matrix (macOS ${os8.macOSVersion ?? "unknown"}, Darwin ${os8.darwinRelease}):`
47488
+ `Feature matrix (macOS ${os9.macOSVersion ?? "unknown"}, Darwin ${os9.darwinRelease}):`
47339
47489
  ];
47340
47490
  for (const [name, status] of Object.entries(matrix.features)) {
47341
47491
  lines.push(
@@ -47453,19 +47603,19 @@ function formatDoctorReport(r) {
47453
47603
  }
47454
47604
 
47455
47605
  // src/services/fileConfig.ts
47456
- import { existsSync as existsSync10, readFileSync as readFileSync2 } from "fs";
47457
- import { join as join16 } from "path";
47458
- import { homedir as homedir13 } from "os";
47606
+ import { existsSync as existsSync11, readFileSync as readFileSync2 } from "fs";
47607
+ import { join as join17 } from "path";
47608
+ import { homedir as homedir14 } from "os";
47459
47609
  function fileConfigPath(env = process.env) {
47460
47610
  const override = env.APPLE_NOTES_MCP_CONFIG_FILE;
47461
47611
  if (override && override.trim()) return override.trim();
47462
- return join16(homedir13(), "Library", "Application Support", "apple-notes-mcp", "config.json");
47612
+ return join17(homedir14(), "Library", "Application Support", "apple-notes-mcp", "config.json");
47463
47613
  }
47464
- function loadFileConfig(env = process.env, path8 = fileConfigPath(env)) {
47614
+ function loadFileConfig(env = process.env, path9 = fileConfigPath(env)) {
47465
47615
  const applied = [];
47466
47616
  try {
47467
- if (!existsSync10(path8)) return applied;
47468
- const parsed = JSON.parse(readFileSync2(path8, "utf8"));
47617
+ if (!existsSync11(path9)) return applied;
47618
+ const parsed = JSON.parse(readFileSync2(path9, "utf8"));
47469
47619
  if (!parsed || typeof parsed !== "object") return applied;
47470
47620
  for (const [k, v] of Object.entries(parsed)) {
47471
47621
  if (typeof v !== "string") continue;
@@ -47475,7 +47625,7 @@ function loadFileConfig(env = process.env, path8 = fileConfigPath(env)) {
47475
47625
  }
47476
47626
  }
47477
47627
  } catch (e) {
47478
- console.error(`Failed to load apple-notes-mcp config file ${path8}: ${String(e)}`);
47628
+ console.error(`Failed to load apple-notes-mcp config file ${path9}: ${String(e)}`);
47479
47629
  }
47480
47630
  return applied;
47481
47631
  }
@@ -47762,10 +47912,10 @@ function createShutdown(stream, exit, timeoutMs = SHUTDOWN_DRAIN_TIMEOUT_MS) {
47762
47912
  }
47763
47913
 
47764
47914
  // src/utils/noteBlocks.ts
47765
- import { execFileSync as execFileSync16 } from "node:child_process";
47766
- import { existsSync as existsSync11 } from "node:fs";
47767
- import { homedir as homedir14 } from "node:os";
47768
- import { join as join17 } from "node:path";
47915
+ import { execFileSync as execFileSync17 } from "node:child_process";
47916
+ import { existsSync as existsSync12 } from "node:fs";
47917
+ import { homedir as homedir15 } from "node:os";
47918
+ import { join as join18 } from "node:path";
47769
47919
  import { gunzipSync as gunzipSync8 } from "node:zlib";
47770
47920
  var NoteBlocksError = class extends Error {
47771
47921
  code;
@@ -48108,23 +48258,23 @@ function pageNoteBlocks(doc, { offset = 0, limit = 500, maxBytes = blocksMaxResp
48108
48258
  undecodedFields: doc.undecodedFields
48109
48259
  };
48110
48260
  }
48111
- var NOTES_DB_PATH9 = join17(
48112
- homedir14(),
48261
+ var NOTES_DB_PATH10 = join18(
48262
+ homedir15(),
48113
48263
  "Library/Group Containers/group.com.apple.notes/NoteStore.sqlite"
48114
48264
  );
48115
- function readNoteBlocks(id2, { dbPath: dbPath2 = NOTES_DB_PATH9 } = {}) {
48265
+ function readNoteBlocks(id2, { dbPath: dbPath2 = NOTES_DB_PATH10 } = {}) {
48116
48266
  const pk = /^x-coredata:\/\/[0-9a-f-]+\/ICNote\/p([0-9]{1,18})$/i.exec(id2)?.[1];
48117
48267
  if (!pk)
48118
48268
  throw new NoteBlocksError(
48119
48269
  "invalid-id",
48120
48270
  `Invalid note ID: expected x-coredata://<store>/ICNote/p<number>`
48121
48271
  );
48122
- if (!existsSync11(dbPath2))
48272
+ if (!existsSync12(dbPath2))
48123
48273
  throw new NoteBlocksError("no-full-disk-access", "The Notes database is not readable");
48124
48274
  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));";
48125
48275
  let output;
48126
48276
  try {
48127
- output = execFileSync16(
48277
+ output = execFileSync17(
48128
48278
  "/usr/bin/sqlite3",
48129
48279
  ["-readonly", "-cmd", ".parameter init", "-cmd", `.parameter set @pk ${pk}`, dbPath2, sql],
48130
48280
  {
@@ -48274,7 +48424,7 @@ function insertLink(request, deps) {
48274
48424
 
48275
48425
  // src/services/notesExport.ts
48276
48426
  import { mkdirSync as mkdirSync5 } from "node:fs";
48277
- import { basename as basename4, dirname as dirname4, extname as extname4, join as join20 } from "node:path";
48427
+ import { basename as basename4, dirname as dirname4, extname as extname4, join as join21 } from "node:path";
48278
48428
 
48279
48429
  // src/utils/exportAssets.ts
48280
48430
  import {
@@ -48289,9 +48439,9 @@ import {
48289
48439
  statSync as statSync3,
48290
48440
  writeSync as writeSync3
48291
48441
  } from "node:fs";
48292
- import { homedir as homedir15 } from "node:os";
48293
- import { basename as basename3, extname as extname3, join as join18, relative as relative3, resolve as resolve3, sep as sep3 } from "node:path";
48294
- var NOTES_CONTAINER = join18(homedir15(), "Library/Group Containers/group.com.apple.notes");
48442
+ import { homedir as homedir16 } from "node:os";
48443
+ import { basename as basename3, extname as extname3, join as join19, relative as relative3, resolve as resolve3, sep as sep3 } from "node:path";
48444
+ var NOTES_CONTAINER = join19(homedir16(), "Library/Group Containers/group.com.apple.notes");
48295
48445
  var MAX_EMBED_BYTES = 10 * 1024 * 1024;
48296
48446
  var MAX_EMBED_TOTAL_BYTES = 256 * 1024 * 1024;
48297
48447
  var MAX_DIRECTORY_ENTRIES = 2e4;
@@ -48318,10 +48468,10 @@ function listDirectory(dir, limit) {
48318
48468
  return [];
48319
48469
  }
48320
48470
  }
48321
- function isFile(path8) {
48471
+ function isFile(path9) {
48322
48472
  let fd;
48323
48473
  try {
48324
- fd = openSync4(path8, constants4.O_RDONLY | constants4.O_NOFOLLOW);
48474
+ fd = openSync4(path9, constants4.O_RDONLY | constants4.O_NOFOLLOW);
48325
48475
  return fstatSync4(fd).isFile();
48326
48476
  } catch {
48327
48477
  return false;
@@ -48329,9 +48479,9 @@ function isFile(path8) {
48329
48479
  if (fd !== void 0) closeSync4(fd);
48330
48480
  }
48331
48481
  }
48332
- function isDirectory2(path8) {
48482
+ function isDirectory2(path9) {
48333
48483
  try {
48334
- return statSync3(path8).isDirectory();
48484
+ return statSync3(path9).isDirectory();
48335
48485
  } catch {
48336
48486
  return false;
48337
48487
  }
@@ -48347,11 +48497,11 @@ var AssetLocator = class {
48347
48497
  constructor(container = NOTES_CONTAINER) {
48348
48498
  let accountsRoot = "";
48349
48499
  try {
48350
- accountsRoot = realpathSync3.native(join18(container, "Accounts"));
48500
+ accountsRoot = realpathSync3.native(join19(container, "Accounts"));
48351
48501
  } catch {
48352
48502
  }
48353
48503
  this.accounts = accountsRoot ? listDirectory(accountsRoot, 1e3).flatMap((name) => {
48354
- const dir = safeComponent2(name) && confine(join18(accountsRoot, name), accountsRoot);
48504
+ const dir = safeComponent2(name) && confine(join19(accountsRoot, name), accountsRoot);
48355
48505
  return dir && isDirectory2(dir) ? [dir] : [];
48356
48506
  }) : [];
48357
48507
  }
@@ -48411,18 +48561,18 @@ var AssetLocator = class {
48411
48561
  if (!mediaId || !filename) return void 0;
48412
48562
  const generation = safeComponent2(source.mediaGeneration);
48413
48563
  const candidates = [
48414
- ...generation ? [join18(account, "Media", mediaId, generation, filename)] : [],
48415
- join18(account, "Media", mediaId, filename)
48564
+ ...generation ? [join19(account, "Media", mediaId, generation, filename)] : [],
48565
+ join19(account, "Media", mediaId, filename)
48416
48566
  ];
48417
48567
  for (const candidate of candidates) {
48418
- const path8 = confine(candidate, account);
48419
- if (path8 && isFile(path8)) return { path: path8, name: filename, role: "original" };
48568
+ const path9 = confine(candidate, account);
48569
+ if (path9 && isFile(path9)) return { path: path9, name: filename, role: "original" };
48420
48570
  }
48421
48571
  return void 0;
48422
48572
  }
48423
48573
  /** <dir>/<id>/<generation>/<name>, <dir>/<id>/<name>, then any generation. */
48424
48574
  fallback(account, dir, id2, generation, names) {
48425
- const base = join18(account, dir, id2);
48575
+ const base = join19(account, dir, id2);
48426
48576
  const gen = safeComponent2(generation);
48427
48577
  const generations = [
48428
48578
  ...gen ? [gen] : [],
@@ -48431,8 +48581,8 @@ var AssetLocator = class {
48431
48581
  ];
48432
48582
  for (const g of generations)
48433
48583
  for (const name of names) {
48434
- const path8 = confine(g ? join18(base, g, name) : join18(base, name), account);
48435
- if (path8 && isFile(path8)) return path8;
48584
+ const path9 = confine(g ? join19(base, g, name) : join19(base, name), account);
48585
+ if (path9 && isFile(path9)) return path9;
48436
48586
  }
48437
48587
  return void 0;
48438
48588
  }
@@ -48441,7 +48591,7 @@ var AssetLocator = class {
48441
48591
  let index = this.previewIndex.get(account);
48442
48592
  if (!index) {
48443
48593
  index = /* @__PURE__ */ new Map();
48444
- for (const name of listDirectory(join18(account, "Previews"), MAX_DIRECTORY_ENTRIES)) {
48594
+ for (const name of listDirectory(join19(account, "Previews"), MAX_DIRECTORY_ENTRIES)) {
48445
48595
  const key = name.slice(0, 36).toUpperCase();
48446
48596
  const entries3 = index.get(key) ?? [];
48447
48597
  entries3.push(name);
@@ -48454,7 +48604,7 @@ var AssetLocator = class {
48454
48604
  return !ext || IMAGE_EXTENSIONS.has(ext) || /^\.\d+$/.test(ext);
48455
48605
  }).sort((a, b) => previewArea(b) - previewArea(a) || a.localeCompare(b));
48456
48606
  for (const name of entries2) {
48457
- const entry = confine(join18(account, "Previews", name), account);
48607
+ const entry = confine(join19(account, "Previews", name), account);
48458
48608
  if (!entry) continue;
48459
48609
  const file = isFile(entry) ? entry : this.bundleImage(entry, account);
48460
48610
  if (file) return { path: file, name: "preview", role: "preview" };
@@ -48465,16 +48615,16 @@ var AssetLocator = class {
48465
48615
  bundleImage(bundle, account) {
48466
48616
  const found = [];
48467
48617
  for (const child of listDirectory(bundle, MAX_BUNDLE_ENTRIES2)) {
48468
- const path8 = confine(join18(bundle, child), account);
48469
- if (!path8) continue;
48470
- if (isFile(path8)) found.push(path8);
48618
+ const path9 = confine(join19(bundle, child), account);
48619
+ if (!path9) continue;
48620
+ if (isFile(path9)) found.push(path9);
48471
48621
  else
48472
- for (const grandchild of listDirectory(path8, MAX_BUNDLE_ENTRIES2)) {
48473
- const inner = confine(join18(path8, grandchild), account);
48622
+ for (const grandchild of listDirectory(path9, MAX_BUNDLE_ENTRIES2)) {
48623
+ const inner = confine(join19(path9, grandchild), account);
48474
48624
  if (inner && isFile(inner)) found.push(inner);
48475
48625
  }
48476
48626
  }
48477
- return found.find((path8) => basename3(path8) === "Preview.png") ?? found.find((path8) => IMAGE_EXTENSIONS.has(extname3(path8).toLowerCase()));
48627
+ return found.find((path9) => basename3(path9) === "Preview.png") ?? found.find((path9) => IMAGE_EXTENSIONS.has(extname3(path9).toLowerCase()));
48478
48628
  }
48479
48629
  };
48480
48630
  function sniffMime(head, name) {
@@ -48522,8 +48672,8 @@ function safeAssetName(name, mime) {
48522
48672
  if (clean.length > 120) clean = clean.slice(0, 120 - ext.length) + ext;
48523
48673
  return clean;
48524
48674
  }
48525
- function encodePathUrl(path8) {
48526
- return path8.split("/").map(encodeURIComponent).join("/");
48675
+ function encodePathUrl(path9) {
48676
+ return path9.split("/").map(encodeURIComponent).join("/");
48527
48677
  }
48528
48678
  function canonicalForm(abs) {
48529
48679
  let current = abs;
@@ -48531,18 +48681,18 @@ function canonicalForm(abs) {
48531
48681
  for (; ; ) {
48532
48682
  try {
48533
48683
  const real = realpathSync3.native(current);
48534
- return rest ? join18(real, rest) : real;
48684
+ return rest ? join19(real, rest) : real;
48535
48685
  } catch {
48536
48686
  const parent = resolve3(current, "..");
48537
48687
  if (parent === current) return abs;
48538
- rest = rest ? join18(basename3(current), rest) : basename3(current);
48688
+ rest = rest ? join19(basename3(current), rest) : basename3(current);
48539
48689
  current = parent;
48540
48690
  }
48541
48691
  }
48542
48692
  }
48543
48693
  function assertExportPath(p, container = NOTES_CONTAINER) {
48544
48694
  const abs = assertSafeSavePath(p);
48545
- const within = (path8, root) => path8 === root || path8.startsWith(root + sep3);
48695
+ const within = (path9, root) => path9 === root || path9.startsWith(root + sep3);
48546
48696
  const roots = [resolve3(container), canonicalForm(resolve3(container))];
48547
48697
  const forms = [abs, canonicalForm(abs)];
48548
48698
  if (forms.some((form) => roots.some((root) => within(form, root))))
@@ -48552,16 +48702,16 @@ function assertExportPath(p, container = NOTES_CONTAINER) {
48552
48702
  var CREATE_FLAGS = constants4.O_WRONLY | constants4.O_CREAT | constants4.O_EXCL | constants4.O_NOFOLLOW;
48553
48703
  var OutputExistsError = class extends Error {
48554
48704
  code = "output_exists";
48555
- constructor(path8) {
48556
- super(`Output file already exists: ${path8}. Choose a new path or remove the old file first.`);
48705
+ constructor(path9) {
48706
+ super(`Output file already exists: ${path9}. Choose a new path or remove the old file first.`);
48557
48707
  this.name = "OutputExistsError";
48558
48708
  }
48559
48709
  };
48560
- function openCreateOnly(path8) {
48710
+ function openCreateOnly(path9) {
48561
48711
  try {
48562
- return openSync4(path8, CREATE_FLAGS, 420);
48712
+ return openSync4(path9, CREATE_FLAGS, 420);
48563
48713
  } catch (error2) {
48564
- if (error2.code === "EEXIST") throw new OutputExistsError(path8);
48714
+ if (error2.code === "EEXIST") throw new OutputExistsError(path9);
48565
48715
  throw error2;
48566
48716
  }
48567
48717
  }
@@ -48575,8 +48725,8 @@ function writeAllAndClose(fd, content) {
48575
48725
  closeSync4(fd);
48576
48726
  }
48577
48727
  }
48578
- function openSource(path8) {
48579
- const fd = openSync4(path8, constants4.O_RDONLY | constants4.O_NOFOLLOW);
48728
+ function openSource(path9) {
48729
+ const fd = openSync4(path9, constants4.O_RDONLY | constants4.O_NOFOLLOW);
48580
48730
  const stat = fstatSync4(fd);
48581
48731
  if (!stat.isFile()) {
48582
48732
  closeSync4(fd);
@@ -48621,7 +48771,7 @@ var SidecarWriter = class {
48621
48771
  let target;
48622
48772
  let out;
48623
48773
  for (let n = 1; n <= 1e3 && out === void 0; n++) {
48624
- target = join18(this.dir, n === 1 ? name : `${stem}-${n}${ext}`);
48774
+ target = join19(this.dir, n === 1 ? name : `${stem}-${n}${ext}`);
48625
48775
  try {
48626
48776
  out = openSync4(target, CREATE_FLAGS, 420);
48627
48777
  } catch (error2) {
@@ -49376,11 +49526,11 @@ function renderNotesMarkdown(notes, ctx, { wrap: wrap2 = 0 } = {}) {
49376
49526
  }
49377
49527
 
49378
49528
  // src/utils/noteExportData.ts
49379
- import { execFileSync as execFileSync17 } from "node:child_process";
49380
- import { homedir as homedir16 } from "node:os";
49381
- import { join as join19 } from "node:path";
49382
- var NOTES_DB_PATH10 = join19(
49383
- homedir16(),
49529
+ import { execFileSync as execFileSync18 } from "node:child_process";
49530
+ import { homedir as homedir17 } from "node:os";
49531
+ import { join as join20 } from "node:path";
49532
+ var NOTES_DB_PATH11 = join20(
49533
+ homedir17(),
49384
49534
  "Library/Group Containers/group.com.apple.notes/NoteStore.sqlite"
49385
49535
  );
49386
49536
  var IMAGE_UTIS2 = /* @__PURE__ */ new Set([
@@ -49444,7 +49594,7 @@ var ATTACHMENT_COLUMNS = [
49444
49594
  var columnCache = /* @__PURE__ */ new Map();
49445
49595
  function sqlite(dbPath2, args) {
49446
49596
  try {
49447
- return execFileSync17(
49597
+ return execFileSync18(
49448
49598
  "/usr/bin/sqlite3",
49449
49599
  ["-readonly", ...args.slice(0, -1), dbPath2, args.at(-1)],
49450
49600
  {
@@ -49461,7 +49611,7 @@ function sqlite(dbPath2, args) {
49461
49611
  throw new NoteBlocksError("query-failed", "Failed to query the Notes database");
49462
49612
  }
49463
49613
  }
49464
- function objectColumns(dbPath2 = NOTES_DB_PATH10) {
49614
+ function objectColumns(dbPath2 = NOTES_DB_PATH11) {
49465
49615
  let columns = columnCache.get(dbPath2);
49466
49616
  if (!columns) {
49467
49617
  columns = new Set(
@@ -49519,7 +49669,7 @@ function buildAttachments(rows) {
49519
49669
  }
49520
49670
  return { byId: new Map(all.map((a) => [a.id, a])), ordered };
49521
49671
  }
49522
- function readExportNote(id2, { dbPath: dbPath2 = NOTES_DB_PATH10 } = {}) {
49672
+ function readExportNote(id2, { dbPath: dbPath2 = NOTES_DB_PATH11 } = {}) {
49523
49673
  const doc = readNoteBlocks(id2, { dbPath: dbPath2 });
49524
49674
  const pk = /\/ICNote\/p([0-9]{1,18})$/.exec(id2)[1];
49525
49675
  const output = sqlite(dbPath2, [
@@ -49558,9 +49708,9 @@ var NotesExportError = class extends Error {
49558
49708
  }
49559
49709
  code;
49560
49710
  };
49561
- function validPath(path8, what) {
49711
+ function validPath(path9, what) {
49562
49712
  try {
49563
- return assertExportPath(path8);
49713
+ return assertExportPath(path9);
49564
49714
  } catch (error2) {
49565
49715
  throw new NotesExportError(
49566
49716
  "invalid-path",
@@ -49652,7 +49802,7 @@ function exportNotesMarkdown(request, deps) {
49652
49802
  return { ...receipt, markdown };
49653
49803
  }
49654
49804
  function defaultSidecarDir(output) {
49655
- return join20(dirname4(output), `${basename4(output, extname4(output))}.assets`);
49805
+ return join21(dirname4(output), `${basename4(output, extname4(output))}.assets`);
49656
49806
  }
49657
49807
  function exportNotesHtml(request, deps) {
49658
49808
  if (!request.outputPath)
@@ -49706,7 +49856,7 @@ import {
49706
49856
  writeFileSync as writeFileSync3
49707
49857
  } from "node:fs";
49708
49858
  import { tmpdir as tmpdir4 } from "node:os";
49709
- import { basename as basename5, extname as extname5, isAbsolute as isAbsolute3, join as join21 } from "node:path";
49859
+ import { basename as basename5, extname as extname5, isAbsolute as isAbsolute3, join as join22 } from "node:path";
49710
49860
  var noteId = exactIdInput(
49711
49861
  "ICNote",
49712
49862
  /^x-coredata:\/\/[0-9a-f-]+\/ICNote\/p\d+$/i,
@@ -49749,9 +49899,9 @@ function assertExistingContentPreserved(before, after) {
49749
49899
  throw new Error("Existing native object content or presentation changed");
49750
49900
  }
49751
49901
  }
49752
- function localAttachment(path8) {
49753
- if (!isAbsolute3(path8)) throw new Error("An absolute local file path is required");
49754
- const descriptor = openSync5(path8, constants5.O_RDONLY | constants5.O_NOFOLLOW);
49902
+ function localAttachment(path9) {
49903
+ if (!isAbsolute3(path9)) throw new Error("An absolute local file path is required");
49904
+ const descriptor = openSync5(path9, constants5.O_RDONLY | constants5.O_NOFOLLOW);
49755
49905
  try {
49756
49906
  const stat = fstatSync5(descriptor);
49757
49907
  if (!stat.isFile() || stat.size === 0 || stat.size > 64 * 1024 * 1024)
@@ -49873,8 +50023,8 @@ function registerDirectOperations(server2, manager) {
49873
50023
  }
49874
50024
  );
49875
50025
  }
49876
- function attachmentName(path8, filename) {
49877
- const source = basename5(path8);
50026
+ function attachmentName(path9, filename) {
50027
+ const source = basename5(path9);
49878
50028
  if (filename === void 0) return source;
49879
50029
  if (Buffer.byteLength(filename, "utf8") > 255)
49880
50030
  throw new Error("filename must be at most 255 bytes");
@@ -49889,14 +50039,14 @@ function attachmentName(path8, filename) {
49889
50039
  return filename;
49890
50040
  }
49891
50041
  function attachFile(manager, args) {
49892
- const { id: id2, expectedContentHash, path: path8 } = args;
49893
- const name = attachmentName(path8, args.filename);
50042
+ const { id: id2, expectedContentHash, path: path9 } = args;
50043
+ const name = attachmentName(path9, args.filename);
49894
50044
  const before = readSnapshot(manager, id2);
49895
50045
  if (before.hash !== expectedContentHash) throw new Error("Note revision changed");
49896
- const bytes = localAttachment(path8);
50046
+ const bytes = localAttachment(path9);
49897
50047
  const beforeAttachments = manager.listAttachmentsById(id2);
49898
- const directory = mkdtempSync4(join21(tmpdir4(), "notes-attachment-add-"));
49899
- const temporaryFile = join21(directory, name);
50048
+ const directory = mkdtempSync4(join22(tmpdir4(), "notes-attachment-add-"));
50049
+ const temporaryFile = join22(directory, name);
49900
50050
  try {
49901
50051
  writeFileSync3(temporaryFile, bytes, { mode: 384 });
49902
50052
  if (readSnapshot(manager, id2).hash !== before.hash) throw new Error("Note revision changed");
@@ -50454,7 +50604,7 @@ function registerNativeOperations(server2, manager) {
50454
50604
 
50455
50605
  // src/setupShortcuts.ts
50456
50606
  import { spawnSync as spawnSync2 } from "node:child_process";
50457
- import { existsSync as existsSync12 } from "node:fs";
50607
+ import { existsSync as existsSync13 } from "node:fs";
50458
50608
  import { release as release2 } from "node:os";
50459
50609
  import { dirname as dirname5, resolve as resolve4 } from "node:path";
50460
50610
  import { fileURLToPath } from "node:url";
@@ -50474,16 +50624,16 @@ var shortcutFiles = [
50474
50624
  ];
50475
50625
  function setupShortcuts(checkOnly, dependencies = {}) {
50476
50626
  const status = dependencies.status || nativeTagsStatus;
50477
- const exists = dependencies.exists || existsSync12;
50478
- const open = dependencies.open || ((path8) => {
50479
- const result = spawnSync2("/usr/bin/open", [path8], { encoding: "utf8" });
50627
+ const exists = dependencies.exists || existsSync13;
50628
+ const open = dependencies.open || ((path9) => {
50629
+ const result = spawnSync2("/usr/bin/open", [path9], { encoding: "utf8" });
50480
50630
  return result.status === 0 ? { ok: true } : { ok: false, error: result.stderr || result.error?.message || "open failed" };
50481
50631
  });
50482
50632
  const baseDirectory = dependencies.baseDirectory || resolve4(dirname5(fileURLToPath(import.meta.url)), "../shortcuts");
50483
50633
  const osRelease = (dependencies.osRelease || release2)();
50484
50634
  const darwinMajor = Number.parseInt(osRelease.split(".")[0], 10);
50485
50635
  const items = shortcutFiles.map(({ name, file, optional: optional2 }) => {
50486
- const path8 = resolve4(baseDirectory, file);
50636
+ const path9 = resolve4(baseDirectory, file);
50487
50637
  let installed = false;
50488
50638
  let identifier;
50489
50639
  let error2;
@@ -50499,9 +50649,9 @@ function setupShortcuts(checkOnly, dependencies = {}) {
50499
50649
  if (!installed && !checkOnly) {
50500
50650
  if (optional2 && !(darwinMajor >= MARKDOWN_MIN_DARWIN_MAJOR))
50501
50651
  skipped = `requires macOS 26 or later (this Mac reports Darwin ${osRelease})`;
50502
- else if (!exists(path8)) error2 = `Packaged Shortcut is missing: ${path8}`;
50652
+ else if (!exists(path9)) error2 = `Packaged Shortcut is missing: ${path9}`;
50503
50653
  else {
50504
- const result = open(path8);
50654
+ const result = open(path9);
50505
50655
  opened = result.ok;
50506
50656
  if (!result.ok) error2 = result.error || `Could not open ${file}`;
50507
50657
  }
@@ -50510,7 +50660,7 @@ function setupShortcuts(checkOnly, dependencies = {}) {
50510
50660
  name,
50511
50661
  installed,
50512
50662
  identifier,
50513
- file: path8,
50663
+ file: path9,
50514
50664
  opened,
50515
50665
  ...optional2 ? { optional: optional2 } : {},
50516
50666
  ...skipped ? { skipped } : {},
@@ -50640,6 +50790,9 @@ function readExactNoteSnapshot(id2) {
50640
50790
  return { note, body, rich, contentHash: richContentHash(body, rich) };
50641
50791
  }
50642
50792
  var NOT_DELETED_MESSAGE = "Notes.app accepted the delete, but the note is still in its original folder, so it was not moved to Recently Deleted. Nothing was deleted; read the note again before retrying.";
50793
+ function inRecentlyDeletedMessage(title) {
50794
+ return `Note "${title}" is already in Recently Deleted, where deleting it would remove it permanently. Nothing was deleted. Remove it from Recently Deleted in Notes.app if that is intended.`;
50795
+ }
50643
50796
  function revisionConflictMessage(title) {
50644
50797
  return `Note "${title}" changed after it was read. Read it again and review the newer version before retrying.`;
50645
50798
  }
@@ -50818,7 +50971,7 @@ registerTool(
50818
50971
  count: external_exports.number().optional()
50819
50972
  }
50820
50973
  },
50821
- withErrorHandling(({ query, searchContent = false, account, folder, modifiedSince, limit }) => {
50974
+ withErrorHandling(({ query: query2, searchContent = false, account, folder, modifiedSince, limit }) => {
50822
50975
  const effectiveLimit = resolveSearchLimit(limit);
50823
50976
  const limitWasDefault = limit === void 0;
50824
50977
  const {
@@ -50827,7 +50980,7 @@ registerTool(
50827
50980
  syncInterference
50828
50981
  } = withSyncAwarenessSync(
50829
50982
  "search-notes",
50830
- () => notesManager.searchNotes(query, searchContent, account, folder, modifiedSince, effectiveLimit)
50983
+ () => notesManager.searchNotes(query2, searchContent, account, folder, modifiedSince, effectiveLimit)
50831
50984
  );
50832
50985
  const searchType = searchContent ? "content" : "titles";
50833
50986
  const folderInfo = folder ? ` in folder "${folder}"` : "";
@@ -50850,7 +51003,7 @@ ${syncWarnings.join(" ")}` : "";
50850
51003
  if (notes.length === 0) {
50851
51004
  const scopeHint = describeSearchScope(searchContent, notes.length);
50852
51005
  return successResponse(
50853
- `No notes found matching "${query}" in ${searchType}${folderInfo}${dateInfo}${scopeHint}${syncNote}`,
51006
+ `No notes found matching "${query2}" in ${searchType}${folderInfo}${dateInfo}${scopeHint}${syncNote}`,
50854
51007
  { notes: [], count: 0 }
50855
51008
  );
50856
51009
  }
@@ -50902,10 +51055,10 @@ registerTool(
50902
51055
  },
50903
51056
  annotations: { readOnlyHint: true }
50904
51057
  },
50905
- withErrorHandling(({ query, limit, scanLimit, includeDeleted }) => {
51058
+ withErrorHandling(({ query: query2, limit, scanLimit, includeDeleted }) => {
50906
51059
  let result;
50907
51060
  try {
50908
- result = queryNotes(query, { limit, scanLimit, includeDeleted });
51061
+ result = queryNotes(query2, { limit, scanLimit, includeDeleted });
50909
51062
  } catch (error2) {
50910
51063
  if (error2 instanceof NoteQueryError || error2 instanceof NoteQueryStoreError) {
50911
51064
  return errorResponse(
@@ -51816,7 +51969,7 @@ registerTool(
51816
51969
  registerTool(
51817
51970
  "delete-note",
51818
51971
  {
51819
- description: "Use when: moving one exact note to Recently Deleted after reading and reviewing it.\nReturns: confirmation with the exact id.\nDo not use when: you only have a title or the note changed since review.\nSafety: requires id and expectedContentHash from get-note-content. The body comparison and delete happen in one AppleScript, so a newer edit is preserved.",
51972
+ description: "Use when: moving one exact note to Recently Deleted after reading and reviewing it.\nReturns: confirmation with the exact id.\nDo not use when: you only have a title or the note changed since review.\nSafety: requires id and expectedContentHash from get-note-content. The body comparison and delete happen in one AppleScript, so a newer edit is preserved. Refuses a note already in Recently Deleted, where a delete would be permanent.",
51820
51973
  inputSchema: {
51821
51974
  id: noteIdInput,
51822
51975
  expectedContentHash: expectedContentHashInput,
@@ -51840,6 +51993,9 @@ registerTool(
51840
51993
  if (result.status === "conflict") {
51841
51994
  return errorResponse(revisionConflictMessage(snapshot.note.title));
51842
51995
  }
51996
+ if (result.status === "in-recently-deleted") {
51997
+ return errorResponse(inRecentlyDeletedMessage(snapshot.note.title));
51998
+ }
51843
51999
  if (result.status === "not-deleted") {
51844
52000
  return errorResponse(NOT_DELETED_MESSAGE);
51845
52001
  }
@@ -51908,36 +52064,47 @@ registerTool(
51908
52064
  registerTool(
51909
52065
  "list-notes",
51910
52066
  {
51911
- description: "Use when: enumerating notes in an account or folder; supports modifiedSince and limit for large collections.\nReturns: each note's title and id (ids are safe to use for follow-up reads/edits even when titles are duplicated \u2014 see search-notes for keyword-based lookup instead).\nDo not use when: you need content (get-note-content).\nNote: warns if iCloud sync is active and results may be partial.",
52067
+ description: "Use when: enumerating notes in an account or folder; supports modifiedSince and limit for large collections.\nReturns: each note's title and id (ids are safe to use for follow-up reads/edits even when titles are duplicated \u2014 see search-notes for keyword-based lookup instead).\nDo not use when: you need content (get-note-content).\nNote: excludes notes in Recently Deleted unless includeRecentlyDeleted is true, which flags them inRecentlyDeleted. Warns if iCloud sync is active and results may be partial.",
51912
52068
  inputSchema: {
51913
52069
  account: external_exports.string().max(MAX.ACCOUNT).optional().describe("Account to list notes from"),
51914
52070
  folder: external_exports.string().max(MAX.FOLDER).optional().describe("Filter to specific folder"),
51915
52071
  modifiedSince: external_exports.string().max(64).optional().describe(
51916
52072
  "ISO 8601 date string to filter notes modified on or after this date (e.g., '2025-01-01'). Useful for listing only recent notes in large collections."
51917
52073
  ),
51918
- limit: external_exports.number().int().positive().optional().describe("Maximum number of notes to return")
52074
+ limit: external_exports.number().int().positive().optional().describe("Maximum number of notes to return"),
52075
+ includeRecentlyDeleted: external_exports.boolean().optional().describe(
52076
+ "Also list notes in Recently Deleted, each flagged inRecentlyDeleted (default false)"
52077
+ )
51919
52078
  },
51920
52079
  outputSchema: {
51921
52080
  notes: external_exports.array(
51922
52081
  external_exports.object({
51923
52082
  title: external_exports.string(),
51924
52083
  id: external_exports.string(),
52084
+ inRecentlyDeleted: external_exports.boolean().optional(),
51925
52085
  identifier: external_exports.string().optional(),
51926
52086
  folderIdentifier: external_exports.string().optional(),
51927
52087
  accountIdentifier: external_exports.string().optional()
51928
52088
  })
51929
52089
  ).optional(),
51930
- count: external_exports.number().optional()
52090
+ count: external_exports.number().optional(),
52091
+ excludedRecentlyDeleted: external_exports.number().optional()
51931
52092
  }
51932
52093
  },
51933
- withErrorHandling(({ account, folder, modifiedSince, limit }) => {
52094
+ withErrorHandling(({ account, folder, modifiedSince, limit, includeRecentlyDeleted }) => {
51934
52095
  const {
51935
- result: notes,
52096
+ result: { refs: notes, excludedRecentlyDeleted },
51936
52097
  syncBefore,
51937
52098
  syncInterference
51938
52099
  } = withSyncAwarenessSync(
51939
52100
  "list-notes",
51940
- () => notesManager.listNoteRefs(account, folder, modifiedSince, limit)
52101
+ () => notesManager.listNoteRefsDetailed(
52102
+ account,
52103
+ folder,
52104
+ modifiedSince,
52105
+ limit,
52106
+ includeRecentlyDeleted ?? false
52107
+ )
51941
52108
  );
51942
52109
  const location = folder ? ` in folder "${folder}"` : "";
51943
52110
  const acct = account ? ` (${account})` : "";
@@ -51953,17 +52120,22 @@ registerTool(
51953
52120
  const syncNote = syncWarnings.length > 0 ? `
51954
52121
 
51955
52122
  ${syncWarnings.join(" ")}` : "";
52123
+ const trashNote = excludedRecentlyDeleted > 0 ? `
52124
+
52125
+ Skipped ${excludedRecentlyDeleted} note(s) in Recently Deleted; pass includeRecentlyDeleted: true to list them.` : "";
52126
+ const trashData = excludedRecentlyDeleted > 0 ? { excludedRecentlyDeleted } : {};
51956
52127
  if (notes.length === 0) {
51957
- return successResponse(`No notes found${location}${acct}${dateInfo}${syncNote}`, {
52128
+ return successResponse(`No notes found${location}${acct}${dateInfo}${trashNote}${syncNote}`, {
51958
52129
  notes: [],
51959
- count: 0
52130
+ count: 0,
52131
+ ...trashData
51960
52132
  });
51961
52133
  }
51962
- const noteList = notes.map((n) => ` - ${n.title} [id: ${n.id}]`).join("\n");
52134
+ const noteList = notes.map((n) => ` - ${n.title}${n.inRecentlyDeleted ? " [RECENTLY DELETED]" : ""} [id: ${n.id}]`).join("\n");
51963
52135
  return successResponse(
51964
52136
  `Found ${notes.length} notes${location}${acct}${dateInfo}${limitInfo}:
51965
- ${noteList}${syncNote}`,
51966
- { notes: withStableIdentifiers(notes, "ICNote"), count: notes.length }
52137
+ ${noteList}${trashNote}${syncNote}`,
52138
+ { notes: withStableIdentifiers(notes, "ICNote"), count: notes.length, ...trashData }
51967
52139
  );
51968
52140
  }, "Error listing notes")
51969
52141
  );
@@ -52469,7 +52641,7 @@ ${attachmentList}`,
52469
52641
  registerTool(
52470
52642
  "batch-delete-notes",
52471
52643
  {
52472
- description: "Use when: moving several reviewed notes to Recently Deleted.\nReturns: per-note success or conflict.\nDo not use when: deleting a single note.\nSafety: every entry requires an exact id and the content hash from get-note-content. Any note changed since review is preserved and reported as a conflict.",
52644
+ description: "Use when: moving several reviewed notes to Recently Deleted.\nReturns: per-note success or conflict.\nDo not use when: deleting a single note.\nSafety: every entry requires an exact id and the content hash from get-note-content. Any note changed since review is preserved and reported as a conflict. A note already in Recently Deleted is refused, since deleting it there would be permanent.",
52473
52645
  inputSchema: {
52474
52646
  notes: external_exports.array(
52475
52647
  external_exports.object({
@@ -52500,6 +52672,9 @@ registerTool(
52500
52672
  if (result.status === "conflict") {
52501
52673
  return { id: id2, success: false, error: revisionConflictMessage(snapshot.note.title) };
52502
52674
  }
52675
+ if (result.status === "in-recently-deleted") {
52676
+ return { id: id2, success: false, error: inRecentlyDeletedMessage(snapshot.note.title) };
52677
+ }
52503
52678
  if (result.status === "not-deleted")
52504
52679
  return { id: id2, success: false, error: NOT_DELETED_MESSAGE };
52505
52680
  return { id: id2, success: false, error: "Delete result uncertain; inspect this exact ID" };