apple-notes-mcp 2.15.0 → 2.15.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/build/index.js CHANGED
@@ -4010,11 +4010,11 @@ var require_fast_uri = __commonJS({
4010
4010
  var URI_PARSE = /^(?:([^#/:?]+):)?(?:\/\/((?:([^#/?@]*)@)?(\[[^#/?\]]+\]|[^#/:?]*)(?::(\d*))?))?([^#?]*)(?:\?([^#]*))?(?:#((?:.|[\n\r])*))?/u;
4011
4011
  var AUTHORITY_PREFIX = /^(?:[^#/:?]+:)?\/\/([^/?#]*)/;
4012
4012
  var AUTHORITY_INTRODUCER_REGION = /^(?:[^#/:?]+:)?([/\\\t\n\r]*)/;
4013
- function getParseError(parsed, matches) {
4014
- if (matches[2] !== void 0 && parsed.path && parsed.path[0] !== "/") {
4013
+ function getParseError(parsed2, matches) {
4014
+ if (matches[2] !== void 0 && parsed2.path && parsed2.path[0] !== "/") {
4015
4015
  return 'URI path must start with "/" when authority is present.';
4016
4016
  }
4017
- if (typeof parsed.port === "number" && (parsed.port < 0 || parsed.port > 65535)) {
4017
+ if (typeof parsed2.port === "number" && (parsed2.port < 0 || parsed2.port > 65535)) {
4018
4018
  return "URI port is malformed.";
4019
4019
  }
4020
4020
  return void 0;
@@ -4037,12 +4037,12 @@ var require_fast_uri = __commonJS({
4037
4037
  const host = matches[4];
4038
4038
  return hasMalformedPercentEncoding(matches[3]) || host !== void 0 && !isIPLiteral(host) && hasMalformedPercentEncoding(host) || hasMalformedPercentEncoding(matches[6]) || hasMalformedPercentEncoding(matches[7]) || hasMalformedPercentEncoding(matches[8]);
4039
4039
  }
4040
- function canonicalizeHost(parsed, options, schemeHandler, isIP) {
4041
- if (!options.unicodeSupport && (!schemeHandler || !schemeHandler.unicodeSupport) && parsed.host && !isIPLiteral(parsed.host) && (options.domainHost || schemeHandler && schemeHandler.domainHost) && isIP === false && nonSimpleDomain(parsed.host)) {
4040
+ function canonicalizeHost(parsed2, options, schemeHandler, isIP) {
4041
+ if (!options.unicodeSupport && (!schemeHandler || !schemeHandler.unicodeSupport) && parsed2.host && !isIPLiteral(parsed2.host) && (options.domainHost || schemeHandler && schemeHandler.domainHost) && isIP === false && nonSimpleDomain(parsed2.host)) {
4042
4042
  try {
4043
- parsed.host = new URL("http://" + parsed.host).hostname;
4043
+ parsed2.host = new URL("http://" + parsed2.host).hostname;
4044
4044
  } catch (e) {
4045
- parsed.error = parsed.error || "Host's domain name can not be converted to ASCII: " + e;
4045
+ parsed2.error = parsed2.error || "Host's domain name can not be converted to ASCII: " + e;
4046
4046
  return true;
4047
4047
  }
4048
4048
  }
@@ -4050,7 +4050,7 @@ var require_fast_uri = __commonJS({
4050
4050
  }
4051
4051
  function parseWithStatus(uri, opts) {
4052
4052
  const options = Object.assign({}, opts);
4053
- const parsed = {
4053
+ const parsed2 = {
4054
4054
  scheme: void 0,
4055
4055
  userinfo: void 0,
4056
4056
  host: "",
@@ -4075,7 +4075,7 @@ var require_fast_uri = __commonJS({
4075
4075
  }
4076
4076
  const authorityMatch = uri.match(AUTHORITY_PREFIX);
4077
4077
  if (authorityMatch !== null && authorityMatch[1].indexOf("\\") !== -1) {
4078
- parsed.error = "URI authority must not contain a literal backslash.";
4078
+ parsed2.error = "URI authority must not contain a literal backslash.";
4079
4079
  malformedAuthorityOrPort = true;
4080
4080
  }
4081
4081
  const introducerMatch = uri.match(AUTHORITY_INTRODUCER_REGION);
@@ -4084,105 +4084,105 @@ var require_fast_uri = __commonJS({
4084
4084
  const normalizedRegion = region.replace(/[\t\n\r]/g, "");
4085
4085
  if (normalizedRegion.length >= 2) {
4086
4086
  if (normalizedRegion.slice(0, 2) !== "//") {
4087
- parsed.error = parsed.error || "URI authority must not contain a literal backslash.";
4087
+ parsed2.error = parsed2.error || "URI authority must not contain a literal backslash.";
4088
4088
  malformedAuthorityOrPort = true;
4089
4089
  } else if (region.length !== normalizedRegion.length) {
4090
- parsed.error = parsed.error || "URI authority introducer must not contain whitespace.";
4090
+ parsed2.error = parsed2.error || "URI authority introducer must not contain whitespace.";
4091
4091
  malformedAuthorityOrPort = true;
4092
4092
  }
4093
4093
  }
4094
4094
  }
4095
4095
  const matches = uri.match(URI_PARSE);
4096
4096
  if (matches) {
4097
- parsed.scheme = matches[1];
4098
- parsed.userinfo = matches[3];
4099
- parsed.host = matches[4];
4100
- parsed.port = parseInt(matches[5], 10);
4101
- parsed.path = matches[6] || "";
4102
- parsed.query = matches[7];
4103
- parsed.fragment = matches[8];
4104
- if (parsed.scheme !== void 0) {
4105
- const decodedScheme = unescape(parsed.scheme);
4097
+ parsed2.scheme = matches[1];
4098
+ parsed2.userinfo = matches[3];
4099
+ parsed2.host = matches[4];
4100
+ parsed2.port = parseInt(matches[5], 10);
4101
+ parsed2.path = matches[6] || "";
4102
+ parsed2.query = matches[7];
4103
+ parsed2.fragment = matches[8];
4104
+ if (parsed2.scheme !== void 0) {
4105
+ const decodedScheme = unescape(parsed2.scheme);
4106
4106
  if (VALID_SCHEME.test(decodedScheme)) {
4107
- parsed.scheme = decodedScheme.toLowerCase();
4107
+ parsed2.scheme = decodedScheme.toLowerCase();
4108
4108
  } else {
4109
- parsed.error = parsed.error || MALFORMED_SCHEME_ERROR;
4109
+ parsed2.error = parsed2.error || MALFORMED_SCHEME_ERROR;
4110
4110
  malformedScheme = true;
4111
4111
  }
4112
4112
  }
4113
4113
  malformedPercentEncoding = hasMalformedComponentPercentEncoding(matches);
4114
4114
  if (malformedPercentEncoding) {
4115
- parsed.error = parsed.error || "URI contains malformed percent-encoding.";
4115
+ parsed2.error = parsed2.error || "URI contains malformed percent-encoding.";
4116
4116
  }
4117
- if (isNaN(parsed.port)) {
4118
- parsed.port = matches[5];
4117
+ if (isNaN(parsed2.port)) {
4118
+ parsed2.port = matches[5];
4119
4119
  }
4120
- const parseError = getParseError(parsed, matches);
4120
+ const parseError = getParseError(parsed2, matches);
4121
4121
  if (parseError !== void 0) {
4122
- parsed.error = parsed.error || parseError;
4122
+ parsed2.error = parsed2.error || parseError;
4123
4123
  malformedAuthorityOrPort = true;
4124
4124
  }
4125
- if (parsed.host) {
4126
- const ipv4result = isIPv4(parsed.host);
4125
+ if (parsed2.host) {
4126
+ const ipv4result = isIPv4(parsed2.host);
4127
4127
  if (ipv4result === false) {
4128
- const bracketedIPLiteral = isIPLiteral(parsed.host);
4129
- const hasIPLiteralBracket = parsed.host.indexOf("[") !== -1 || parsed.host.indexOf("]") !== -1;
4130
- const ipv6result = normalizeIPv6(parsed.host);
4128
+ const bracketedIPLiteral = isIPLiteral(parsed2.host);
4129
+ const hasIPLiteralBracket = parsed2.host.indexOf("[") !== -1 || parsed2.host.indexOf("]") !== -1;
4130
+ const ipv6result = normalizeIPv6(parsed2.host);
4131
4131
  isIP = ipv6result.isIPV6 || ipv6result.isIPVFuture === true;
4132
4132
  malformedIPLiteral = hasIPLiteralBracket && (!bracketedIPLiteral || ipv6result.error === true);
4133
- parsed.host = isIP ? ipv6result.host : ipv6result.host.toLowerCase();
4133
+ parsed2.host = isIP ? ipv6result.host : ipv6result.host.toLowerCase();
4134
4134
  if (malformedIPLiteral) {
4135
- parsed.error = parsed.error || "URI host is malformed.";
4135
+ parsed2.error = parsed2.error || "URI host is malformed.";
4136
4136
  malformedAuthorityOrPort = true;
4137
4137
  }
4138
4138
  } else {
4139
4139
  isIP = true;
4140
4140
  }
4141
4141
  }
4142
- if (parsed.scheme === void 0 && parsed.userinfo === void 0 && parsed.host === void 0 && parsed.port === void 0 && parsed.query === void 0 && !parsed.path) {
4143
- parsed.reference = "same-document";
4144
- } else if (parsed.scheme === void 0) {
4145
- parsed.reference = "relative";
4146
- } else if (parsed.fragment === void 0) {
4147
- parsed.reference = "absolute";
4142
+ if (parsed2.scheme === void 0 && parsed2.userinfo === void 0 && parsed2.host === void 0 && parsed2.port === void 0 && parsed2.query === void 0 && !parsed2.path) {
4143
+ parsed2.reference = "same-document";
4144
+ } else if (parsed2.scheme === void 0) {
4145
+ parsed2.reference = "relative";
4146
+ } else if (parsed2.fragment === void 0) {
4147
+ parsed2.reference = "absolute";
4148
4148
  } else {
4149
- parsed.reference = "uri";
4149
+ parsed2.reference = "uri";
4150
4150
  }
4151
- if (options.reference && options.reference !== "suffix" && options.reference !== parsed.reference) {
4152
- parsed.error = parsed.error || "URI is not a " + options.reference + " reference.";
4151
+ if (options.reference && options.reference !== "suffix" && options.reference !== parsed2.reference) {
4152
+ parsed2.error = parsed2.error || "URI is not a " + options.reference + " reference.";
4153
4153
  }
4154
- const schemeHandler = getSchemeHandler(options.scheme || parsed.scheme);
4154
+ const schemeHandler = getSchemeHandler(options.scheme || parsed2.scheme);
4155
4155
  if (!malformedIPLiteral) {
4156
- malformedHost = canonicalizeHost(parsed, options, schemeHandler, isIP);
4156
+ malformedHost = canonicalizeHost(parsed2, options, schemeHandler, isIP);
4157
4157
  }
4158
- if (uri.indexOf("%") !== -1 && parsed.host !== void 0 && !malformedIPLiteral) {
4159
- let host = isIP ? parsed.host : normalizePercentEncoding(parsed.host, true);
4158
+ if (uri.indexOf("%") !== -1 && parsed2.host !== void 0 && !malformedIPLiteral) {
4159
+ let host = isIP ? parsed2.host : normalizePercentEncoding(parsed2.host, true);
4160
4160
  if (!isIP) {
4161
4161
  host = normalizePercentEncoding(host.toLowerCase());
4162
4162
  }
4163
- parsed.host = reescapeHostDelimiters(host, isIP);
4163
+ parsed2.host = reescapeHostDelimiters(host, isIP);
4164
4164
  }
4165
4165
  if (!schemeHandler || schemeHandler && !schemeHandler.skipNormalize) {
4166
- if (parsed.path) {
4167
- parsed.path = normalizePathEncoding(parsed.path);
4166
+ if (parsed2.path) {
4167
+ parsed2.path = normalizePathEncoding(parsed2.path);
4168
4168
  }
4169
- if (parsed.query) {
4170
- parsed.query = normalizeQueryFragmentEncoding(parsed.query);
4169
+ if (parsed2.query) {
4170
+ parsed2.query = normalizeQueryFragmentEncoding(parsed2.query);
4171
4171
  }
4172
- if (parsed.fragment) {
4173
- parsed.fragment = normalizeQueryFragmentEncoding(parsed.fragment);
4172
+ if (parsed2.fragment) {
4173
+ parsed2.fragment = normalizeQueryFragmentEncoding(parsed2.fragment);
4174
4174
  }
4175
4175
  }
4176
4176
  if (schemeHandler && schemeHandler.parse) {
4177
- schemeHandler.parse(parsed, options);
4178
- if (schemeHandler === SCHEMES.urn && parsed.nid === void 0) {
4177
+ schemeHandler.parse(parsed2, options);
4178
+ if (schemeHandler === SCHEMES.urn && parsed2.nid === void 0) {
4179
4179
  malformedSchemeSpecific = true;
4180
4180
  }
4181
4181
  }
4182
4182
  } else {
4183
- parsed.error = parsed.error || "URI can not be parsed.";
4183
+ parsed2.error = parsed2.error || "URI can not be parsed.";
4184
4184
  }
4185
- return { parsed, malformedAuthorityOrPort, malformedPercentEncoding, malformedSchemeSpecific, malformedHost, malformedScheme };
4185
+ return { parsed: parsed2, malformedAuthorityOrPort, malformedPercentEncoding, malformedSchemeSpecific, malformedHost, malformedScheme };
4186
4186
  }
4187
4187
  function parse3(uri, opts) {
4188
4188
  return parseWithStatus(uri, opts).parsed;
@@ -4191,9 +4191,9 @@ var require_fast_uri = __commonJS({
4191
4191
  return normalizeStringWithStatus(uri, opts).normalized;
4192
4192
  }
4193
4193
  function normalizeStringWithStatus(uri, opts) {
4194
- const { parsed, malformedAuthorityOrPort, malformedPercentEncoding, malformedSchemeSpecific, malformedHost, malformedScheme } = parseWithStatus(uri, opts);
4194
+ const { parsed: parsed2, malformedAuthorityOrPort, malformedPercentEncoding, malformedSchemeSpecific, malformedHost, malformedScheme } = parseWithStatus(uri, opts);
4195
4195
  return {
4196
- normalized: malformedAuthorityOrPort || malformedPercentEncoding || malformedSchemeSpecific || malformedHost || malformedScheme ? uri : serialize(parsed, opts),
4196
+ normalized: malformedAuthorityOrPort || malformedPercentEncoding || malformedSchemeSpecific || malformedHost || malformedScheme ? uri : serialize(parsed2, opts),
4197
4197
  malformedAuthorityOrPort,
4198
4198
  malformedPercentEncoding,
4199
4199
  malformedSchemeSpecific,
@@ -24510,8 +24510,130 @@ var require_turndown_cjs = __commonJS({
24510
24510
  }
24511
24511
  });
24512
24512
 
24513
- // src/index.ts
24514
- import { createRequire } from "module";
24513
+ // src/cliEntry.ts
24514
+ import { createRequire } from "node:module";
24515
+
24516
+ // src/cli.ts
24517
+ var CLI_USAGE = `Usage: apple-notes-mcp [command]
24518
+
24519
+ With no arguments, run the local MCP server over stdio.
24520
+
24521
+ Commands:
24522
+ setup [options] Install or inspect Shortcuts and optional native helpers
24523
+ templates [options] Manage the local Markdown template editor (templates --help)
24524
+ anchors [options] Run the optional paragraph anchor resolver (anchors --help)
24525
+ --help, -h Show this help without running setup or the MCP server
24526
+ --version, -v Print the installed package version
24527
+
24528
+ Run apple-notes-mcp setup --help for supported setup options.
24529
+ `;
24530
+ var SETUP_USAGE = `Usage: apple-notes-mcp setup [target] [options]
24531
+
24532
+ Targets (choose at most one; default: packaged Shortcuts):
24533
+ --public-helper Build and install the public drawing/speech helper
24534
+ --native-helper Build and install the opt-in read-only private helper
24535
+ --permissions-window Build and install the optional permission checklist window
24536
+ --permissions Check permissions; does not grant them
24537
+ --broker Build and install the opt-in permission broker
24538
+
24539
+ Options for every target:
24540
+ --check Inspect only; do not install or import anything
24541
+ --help, -h Show this help without performing any checks
24542
+
24543
+ Options only with --permissions:
24544
+ --once Print one report and exit
24545
+ --json Print the report as JSON
24546
+ --open Open System Settings panes for missing grants
24547
+ --window Show the checklist in the installed optional window
24548
+ --probe-automation Send a read-only Apple event (may show a consent prompt)
24549
+
24550
+ Options only with --broker:
24551
+ --uninstall Remove the installed broker and LaunchAgent
24552
+ --sign-identity <id> Select an existing signing identity
24553
+
24554
+ --check and SSH sessions suppress the Automation probe. Without an explicit
24555
+ --probe-automation, Automation is unverified. Helper installation requires
24556
+ Apple developer tools; setup never silently grants macOS permissions.
24557
+ `;
24558
+ var SETUP_TARGETS = /* @__PURE__ */ new Map([
24559
+ ["--public-helper", "public-helper"],
24560
+ ["--native-helper", "native-helper"],
24561
+ ["--permissions-window", "permissions-window"],
24562
+ ["--permissions", "permissions"],
24563
+ ["--broker", "broker"]
24564
+ ]);
24565
+ var PERMISSION_OPTIONS = /* @__PURE__ */ new Set([
24566
+ "--once",
24567
+ "--json",
24568
+ "--open",
24569
+ "--window",
24570
+ "--probe-automation"
24571
+ ]);
24572
+ function parseSetupArgs(args) {
24573
+ let target = "shortcuts";
24574
+ let selected = false;
24575
+ for (let index = 0; index < args.length; index++) {
24576
+ const arg = args[index];
24577
+ if (arg === "--sign-identity") {
24578
+ const identity = args[++index];
24579
+ if (!identity?.trim() || identity.startsWith("-"))
24580
+ throw new Error("--sign-identity requires a signing identity.");
24581
+ continue;
24582
+ }
24583
+ const next = SETUP_TARGETS.get(arg);
24584
+ if (next) {
24585
+ if (selected && target !== next)
24586
+ throw new Error("Choose only one setup target. Run each target separately.");
24587
+ target = next;
24588
+ selected = true;
24589
+ } else if (!["--check", "--help", "-h"].includes(arg) && !PERMISSION_OPTIONS.has(arg) && arg !== "--uninstall") {
24590
+ throw new Error(`Unknown setup option "${arg}".`);
24591
+ }
24592
+ }
24593
+ if (args.some((arg) => arg === "--uninstall" || arg === "--sign-identity") && target !== "broker")
24594
+ throw new Error("--uninstall and --sign-identity require setup --broker.");
24595
+ for (const arg of args) {
24596
+ if (PERMISSION_OPTIONS.has(arg) && target !== "permissions")
24597
+ throw new Error(`${arg} requires setup --permissions.`);
24598
+ }
24599
+ if (args.includes("--help") || args.includes("-h")) return { kind: "help", topic: "setup" };
24600
+ return { kind: "setup", target, args: [...args], checkOnly: args.includes("--check") };
24601
+ }
24602
+ function parseCliArgs(args) {
24603
+ if (!args.length) return { kind: "mcp" };
24604
+ const [command2, ...rest] = args;
24605
+ if (command2 === "setup") return parseSetupArgs(rest);
24606
+ if (command2 === "templates" || command2 === "anchors") return { kind: command2, args: rest };
24607
+ if (["--help", "-h", "help", "--version", "-v"].includes(command2)) {
24608
+ if (rest.length) throw new Error(`Unexpected argument "${rest[0]}" after ${command2}.`);
24609
+ return command2 === "--version" || command2 === "-v" ? { kind: "version" } : { kind: "help", topic: "main" };
24610
+ }
24611
+ throw new Error(`Unknown command or option "${command2}".`);
24612
+ }
24613
+
24614
+ // src/cliEntry.ts
24615
+ var parsed;
24616
+ try {
24617
+ parsed = parseCliArgs(process.argv.slice(2));
24618
+ } catch (error2) {
24619
+ const usage = process.argv[2] === "setup" ? SETUP_USAGE : CLI_USAGE;
24620
+ process.stderr.write(`${error2.message}
24621
+
24622
+ ${usage}`);
24623
+ process.exit(2);
24624
+ }
24625
+ var command = parsed;
24626
+ if (command.kind === "help") {
24627
+ process.stdout.write(command.topic === "setup" ? SETUP_USAGE : CLI_USAGE);
24628
+ process.exit(0);
24629
+ }
24630
+ var require2 = createRequire(import.meta.url);
24631
+ var { version } = require2("../package.json");
24632
+ if (command.kind === "version") {
24633
+ process.stdout.write(`${version}
24634
+ `);
24635
+ process.exit(0);
24636
+ }
24515
24637
 
24516
24638
  // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/external.js
24517
24639
  var external_exports = {};
@@ -29741,7 +29863,7 @@ var Doc = class {
29741
29863
  };
29742
29864
 
29743
29865
  // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v4/core/versions.js
29744
- var version = {
29866
+ var version2 = {
29745
29867
  major: 4,
29746
29868
  minor: 0,
29747
29869
  patch: 0
@@ -29753,7 +29875,7 @@ var $ZodType = /* @__PURE__ */ $constructor("$ZodType", (inst, def) => {
29753
29875
  inst ?? (inst = {});
29754
29876
  inst._zod.def = def;
29755
29877
  inst._zod.bag = inst._zod.bag || {};
29756
- inst._zod.version = version;
29878
+ inst._zod.version = version2;
29757
29879
  const checks = [...inst._zod.def.checks ?? []];
29758
29880
  if (inst._zod.traits.has("$ZodCheck")) {
29759
29881
  checks.unshift(inst);
@@ -36873,8 +36995,8 @@ var Protocol = class {
36873
36995
  const method = getMethodLiteral(requestSchema);
36874
36996
  this.assertRequestHandlerCapability(method);
36875
36997
  this._requestHandlers.set(method, (request, extra) => {
36876
- const parsed = parseWithCompat(requestSchema, request);
36877
- return Promise.resolve(handler(parsed, extra));
36998
+ const parsed2 = parseWithCompat(requestSchema, request);
36999
+ return Promise.resolve(handler(parsed2, extra));
36878
37000
  });
36879
37001
  }
36880
37002
  /**
@@ -36899,8 +37021,8 @@ var Protocol = class {
36899
37021
  setNotificationHandler(notificationSchema, handler) {
36900
37022
  const method = getMethodLiteral(notificationSchema);
36901
37023
  this._notificationHandlers.set(method, (notification) => {
36902
- const parsed = parseWithCompat(notificationSchema, notification);
36903
- return Promise.resolve(handler(parsed));
37024
+ const parsed2 = parseWithCompat(notificationSchema, notification);
37025
+ return Promise.resolve(handler(parsed2));
36904
37026
  });
36905
37027
  }
36906
37028
  /**
@@ -39096,6 +39218,7 @@ function sleep(ms) {
39096
39218
  }
39097
39219
  var PERMISSION_DENIED_PATTERN = /not author(?:i[sz])ed|not permitted|access.*denied|\(-1743\)/i;
39098
39220
  var PERMISSION_DENIED_MESSAGE = `Permission denied. ${AUTOMATION_REMEDIATION}`;
39221
+ var NOTE_ID_NOT_FOUND_MESSAGE = "Note not found. The note may have been deleted or the ID is invalid.";
39099
39222
  function isPermissionDenied(error2) {
39100
39223
  if (!error2) return false;
39101
39224
  return PERMISSION_DENIED_PATTERN.test(error2) || error2.includes(PERMISSION_DENIED_MESSAGE);
@@ -39128,7 +39251,7 @@ var ERROR_MAPPINGS = [
39128
39251
  // Note not found by ID
39129
39252
  {
39130
39253
  pattern: /can't get note id/i,
39131
- message: "Note not found. The note may have been deleted or the ID is invalid."
39254
+ message: NOTE_ID_NOT_FOUND_MESSAGE
39132
39255
  },
39133
39256
  // Folder not found
39134
39257
  {
@@ -39727,9 +39850,9 @@ function runJsonQuery(sql, dbPath2) {
39727
39850
  console.error(`Identifier query failed: ${detail}`);
39728
39851
  throw new IdentifierResolutionError("query_error", "Failed to read the Notes database.");
39729
39852
  }
39730
- const parsed = JSON.parse(out || "{}");
39731
- const rows = typeof parsed.rows === "string" ? JSON.parse(parsed.rows) : parsed.rows;
39732
- return { store: parsed.store ?? null, rows: rows ?? [] };
39853
+ const parsed2 = JSON.parse(out || "{}");
39854
+ const rows = typeof parsed2.rows === "string" ? JSON.parse(parsed2.rows) : parsed2.rows;
39855
+ return { store: parsed2.store ?? null, rows: rows ?? [] };
39733
39856
  }
39734
39857
  function coreDataId(store, entity3, pk) {
39735
39858
  return `x-coredata://${store}/${entity3}/p${pk}`;
@@ -41432,19 +41555,19 @@ function decodeSmartFolderQuery(raw, context = {}) {
41432
41555
  if (raw === null || raw.trim() === "") {
41433
41556
  return { match: null, filters: [], query: null, fullyDecoded: false };
41434
41557
  }
41435
- let parsed;
41558
+ let parsed2;
41436
41559
  try {
41437
- parsed = JSON.parse(raw);
41560
+ parsed2 = JSON.parse(raw);
41438
41561
  } catch {
41439
41562
  return { match: null, filters: [], query: raw, fullyDecoded: false };
41440
41563
  }
41441
41564
  const decoder = new Decoder(context);
41442
- const type = isClause(parsed) ? parsed.type : void 0;
41565
+ const type = isClause(parsed2) ? parsed2.type : void 0;
41443
41566
  if (!isClause(type)) {
41444
41567
  return {
41445
41568
  match: null,
41446
- filters: [decoder.unknown(null, parsed, false)],
41447
- query: parsed,
41569
+ filters: [decoder.unknown(null, parsed2, false)],
41570
+ query: parsed2,
41448
41571
  fullyDecoded: false
41449
41572
  };
41450
41573
  }
@@ -43087,8 +43210,8 @@ function parseAppleScriptDate(appleScriptDate) {
43087
43210
  }
43088
43211
  const withoutPrefix = s.replace(/^date\s+/, "");
43089
43212
  const normalized2 = withoutPrefix.replace(" at ", " ");
43090
- const parsed = new Date(normalized2);
43091
- return isNaN(parsed.getTime()) ? /* @__PURE__ */ new Date() : parsed;
43213
+ const parsed2 = new Date(normalized2);
43214
+ return isNaN(parsed2.getTime()) ? /* @__PURE__ */ new Date() : parsed2;
43092
43215
  }
43093
43216
  function buildAppleScriptDateVar(date3, varName = "thresholdDate") {
43094
43217
  const year = date3.getFullYear();
@@ -43279,20 +43402,20 @@ function buildAccountResolution(account) {
43279
43402
  if ${AS_ACCOUNT_REF} is missing value then error "${ACCOUNT_RESOLUTION_ERROR} Account \\"${safeAccount}\\" not found"
43280
43403
  `;
43281
43404
  }
43282
- function buildAccountScopedScript(scope2, command) {
43405
+ function buildAccountScopedScript(scope2, command2) {
43283
43406
  return `
43284
43407
  tell application "Notes"
43285
43408
  ${buildAccountResolution(scope2.account)}
43286
43409
  tell ${AS_ACCOUNT_REF}
43287
- ${command}
43410
+ ${command2}
43288
43411
  end tell
43289
43412
  end tell
43290
43413
  `;
43291
43414
  }
43292
- function buildAppLevelScript(command) {
43415
+ function buildAppLevelScript(command2) {
43293
43416
  return `
43294
43417
  tell application "Notes"
43295
- ${command}
43418
+ ${command2}
43296
43419
  end tell
43297
43420
  `;
43298
43421
  }
@@ -43789,9 +43912,20 @@ var AppleNotesManager = class {
43789
43912
  * This method fetches the note and its metadata using this ID.
43790
43913
  *
43791
43914
  * @param id - CoreData URL identifier for the note
43792
- * @returns Note object with metadata, or null if not found
43915
+ * @returns Note object with metadata, or null if the lookup fails
43793
43916
  */
43794
43917
  getNoteById(id2) {
43918
+ return this.readNoteById(id2).note;
43919
+ }
43920
+ /**
43921
+ * Reads exact-ID metadata while retaining the executor or parser failure.
43922
+ * Unlike the legacy nullable getter, callers can distinguish a missing note
43923
+ * from denied Automation, a timeout, or an unreadable metadata response.
43924
+ *
43925
+ * @param id - CoreData URL identifier for the note
43926
+ * @returns The note, or the diagnostic that prevented its metadata read
43927
+ */
43928
+ readNoteById(id2) {
43795
43929
  const safeId = sanitizeId(id2);
43796
43930
  const getCommand = `
43797
43931
  set n to note id "${safeId}"
@@ -43805,22 +43939,27 @@ var AppleNotesManager = class {
43805
43939
  const result = executeAppleScript(script);
43806
43940
  if (!result.success) {
43807
43941
  console.error(`Failed to get note with ID "${id2}":`, result.error);
43808
- return null;
43942
+ return {
43943
+ note: null,
43944
+ error: result.error?.trim() ? result.error : "AppleScript note metadata read failed"
43945
+ };
43809
43946
  }
43810
- const parsed = parseNotePropertiesOutput(result.output);
43811
- if (!parsed) {
43812
- return null;
43947
+ const parsed2 = parseNotePropertiesOutput(result.output);
43948
+ if (!parsed2) {
43949
+ return { note: null, error: "Unexpected note metadata response" };
43813
43950
  }
43814
43951
  return {
43815
- id: parsed.id,
43816
- title: parsed.title,
43817
- content: "",
43818
- // Not fetched to keep response small
43819
- tags: [],
43820
- created: parsed.created,
43821
- modified: parsed.modified,
43822
- shared: parsed.shared,
43823
- passwordProtected: parsed.passwordProtected
43952
+ note: {
43953
+ id: parsed2.id,
43954
+ title: parsed2.title,
43955
+ content: "",
43956
+ // Not fetched to keep response small
43957
+ tags: [],
43958
+ created: parsed2.created,
43959
+ modified: parsed2.modified,
43960
+ shared: parsed2.shared,
43961
+ passwordProtected: parsed2.passwordProtected
43962
+ }
43824
43963
  };
43825
43964
  }
43826
43965
  /**
@@ -43866,20 +44005,20 @@ var AppleNotesManager = class {
43866
44005
  console.error(`Failed to get details for note "${title}":`, result.error);
43867
44006
  return null;
43868
44007
  }
43869
- const parsed = parseNotePropertiesOutput(result.output);
43870
- if (!parsed) {
44008
+ const parsed2 = parseNotePropertiesOutput(result.output);
44009
+ if (!parsed2) {
43871
44010
  return null;
43872
44011
  }
43873
44012
  return {
43874
- id: parsed.id,
43875
- title: parsed.title,
44013
+ id: parsed2.id,
44014
+ title: parsed2.title,
43876
44015
  content: "",
43877
44016
  // Not fetched
43878
44017
  tags: [],
43879
- created: parsed.created,
43880
- modified: parsed.modified,
43881
- shared: parsed.shared,
43882
- passwordProtected: parsed.passwordProtected,
44018
+ created: parsed2.created,
44019
+ modified: parsed2.modified,
44020
+ shared: parsed2.shared,
44021
+ passwordProtected: parsed2.passwordProtected,
43883
44022
  account: this.reportedAccount(targetAccount)
43884
44023
  };
43885
44024
  }
@@ -44289,12 +44428,12 @@ var AppleNotesManager = class {
44289
44428
  const header = sepIdx === -1 ? body : body.slice(0, sepIdx);
44290
44429
  const totalCount = Number.parseInt(header.trim(), 10);
44291
44430
  const records2 = sepIdx === -1 ? "" : body.slice(sepIdx + 1);
44292
- const parsed = this.parseBulkListRecords(records2, safeLimit, {
44431
+ const parsed2 = this.parseBulkListRecords(records2, safeLimit, {
44293
44432
  ids: trashIds2,
44294
44433
  include: includeRecentlyDeleted
44295
44434
  });
44296
- if (!Number.isNaN(totalCount) && (parsed.refs.length >= safeLimit || totalCount <= safeLimit)) {
44297
- return parsed;
44435
+ if (!Number.isNaN(totalCount) && (parsed2.refs.length >= safeLimit || totalCount <= safeLimit)) {
44436
+ return parsed2;
44298
44437
  }
44299
44438
  }
44300
44439
  const script = buildAccountScopedScript(
@@ -44498,9 +44637,9 @@ var AppleNotesManager = class {
44498
44637
  const parts = result.output.replace(/\n$/, "").split(FIELD_SEP);
44499
44638
  if (parts.length !== 7 || !parts[0] || !parts[2]) throw new Error("Incomplete folder metadata");
44500
44639
  const count = (value) => {
44501
- const parsed = Number(value.trim());
44502
- if (!Number.isInteger(parsed) || parsed < 0) throw new Error("Incomplete folder metadata");
44503
- return parsed;
44640
+ const parsed2 = Number(value.trim());
44641
+ if (!Number.isInteger(parsed2) || parsed2 < 0) throw new Error("Incomplete folder metadata");
44642
+ return parsed2;
44504
44643
  };
44505
44644
  return {
44506
44645
  id: id2,
@@ -44881,12 +45020,12 @@ var AppleNotesManager = class {
44881
45020
  * @returns Default account and folder metadata
44882
45021
  */
44883
45022
  getDefaultLocation() {
44884
- const command = `
45023
+ const command2 = `
44885
45024
  set aRef to default account
44886
45025
  set fRef to default folder of aRef
44887
45026
  return (id of aRef) & ${AS_FIELD_SEP} & (name of aRef) & ${AS_FIELD_SEP} & (upgraded of aRef as text) & ${AS_FIELD_SEP} & (id of fRef) & ${AS_FIELD_SEP} & (name of fRef) & ${AS_FIELD_SEP} & (shared of fRef as text)
44888
45027
  `;
44889
- const result = executeAppleScript(buildAppLevelScript(command));
45028
+ const result = executeAppleScript(buildAppLevelScript(command2));
44890
45029
  if (!result.success) {
44891
45030
  throw new Error(`Failed to get default Notes location: ${result.error ?? "unknown error"}`);
44892
45031
  }
@@ -44917,7 +45056,7 @@ var AppleNotesManager = class {
44917
45056
  * @returns Array of selected notes, or an empty array when nothing is selected
44918
45057
  */
44919
45058
  getSelectedNotes() {
44920
- const command = `
45059
+ const command2 = `
44921
45060
  set selectedNotes to selection
44922
45061
  set noteList to {}
44923
45062
  repeat with n in selectedNotes
@@ -44939,7 +45078,7 @@ var AppleNotesManager = class {
44939
45078
  set AppleScript's text item delimiters to ${AS_RECORD_SEP}
44940
45079
  return noteList as text
44941
45080
  `;
44942
- const result = executeAppleScript(buildAppLevelScript(command));
45081
+ const result = executeAppleScript(buildAppLevelScript(command2));
44943
45082
  if (!result.success) {
44944
45083
  throw new Error(`Failed to get selected notes: ${result.error ?? "unknown error"}`);
44945
45084
  }
@@ -48479,7 +48618,7 @@ function describeMatchDetails(hit) {
48479
48618
  }
48480
48619
 
48481
48620
  // src/tools/doctor.ts
48482
- import { spawnSync } from "child_process";
48621
+ import { spawnSync as spawnSync2 } from "child_process";
48483
48622
 
48484
48623
  // src/services/nativeTags.ts
48485
48624
  import { execFileSync as execFileSync15 } from "node:child_process";
@@ -48802,7 +48941,7 @@ function appendMarkdownHtml(markdown, options = {}) {
48802
48941
  }
48803
48942
 
48804
48943
  // src/utils/noteRevision.ts
48805
- var INLINE_TAG = /^<\/?(?:b|i|u|s|strike|em|strong|span|a|font|sub|sup|code|tt|small|big|mark)\b/i;
48944
+ var INLINE_TAG = /^<\/?(?:b|i|u|s|strike|del|em|strong|span|a|font|sub|sup|code|tt|small|big|mark)\b/i;
48806
48945
  function comparableVisibleText(html) {
48807
48946
  return decodeHtmlEntities(
48808
48947
  html.replace(/<br\s*\/?\s*>/gi, " ").replace(/<[^>]*>/g, (tag) => INLINE_TAG.test(tag) ? "" : " ")
@@ -49335,7 +49474,545 @@ ${request.content}`
49335
49474
 
49336
49475
  // src/services/capabilityMatrix.ts
49337
49476
  import { execFileSync as execFileSync17 } from "node:child_process";
49338
- import { release } from "node:os";
49477
+ import { release as release2 } from "node:os";
49478
+
49479
+ // src/services/publicHelper.ts
49480
+ import { spawn, spawnSync } from "node:child_process";
49481
+ import { createHash as createHash2 } from "node:crypto";
49482
+ import {
49483
+ chmodSync,
49484
+ existsSync as existsSync12,
49485
+ mkdirSync as mkdirSync4,
49486
+ mkdtempSync as mkdtempSync5,
49487
+ readFileSync as readFileSync2,
49488
+ renameSync,
49489
+ rmSync as rmSync5,
49490
+ writeFileSync as writeFileSync4
49491
+ } from "node:fs";
49492
+ import { homedir as homedir16, release } from "node:os";
49493
+ import { dirname as dirname4, join as join19, resolve as resolve3 } from "node:path";
49494
+ import { fileURLToPath } from "node:url";
49495
+ var PUBLIC_HELPER_PROTOCOL = 1;
49496
+ var PUBLIC_HELPER_DIR_ENV = "APPLE_NOTES_MCP_PUBLIC_HELPER_DIR";
49497
+ var PUBLIC_HELPER_TIMEOUT_ENV = "APPLE_NOTES_MCP_PUBLIC_HELPER_TIMEOUT_MS";
49498
+ var PUBLIC_HELPER_BINARY = "apple-notes-public-helper";
49499
+ var PUBLIC_HELPER_SOURCE = "native/public-helper/apple-notes-public-helper.swift";
49500
+ var PUBLIC_HELPER_MANIFEST = "manifest.json";
49501
+ var PUBLIC_HELPER_SETUP_COMMAND = "apple-notes-mcp setup --public-helper";
49502
+ var PUBLIC_HELPER_ACTIONS = /* @__PURE__ */ new Set([
49503
+ "hello",
49504
+ "decode_drawing",
49505
+ "transcribe",
49506
+ "speech_status"
49507
+ ]);
49508
+ var DEFAULT_TIMEOUT_MS2 = 3e4;
49509
+ var MAX_OUTPUT_BYTES2 = 256 * 1024 * 1024;
49510
+ var publicManifestSchema = external_exports.object({
49511
+ schemaVersion: external_exports.literal(1),
49512
+ protocolVersion: external_exports.number().int(),
49513
+ sourceSha256: external_exports.string().regex(/^[a-f0-9]{64}$/),
49514
+ binarySha256: external_exports.string().regex(/^[a-f0-9]{64}$/),
49515
+ builtAt: external_exports.string(),
49516
+ osVersion: external_exports.string(),
49517
+ compiler: external_exports.string()
49518
+ });
49519
+ function packageRoot(fromDir = dirname4(fileURLToPath(import.meta.url))) {
49520
+ let dir = fromDir;
49521
+ for (; ; ) {
49522
+ const candidate = join19(dir, "package.json");
49523
+ if (existsSync12(candidate)) {
49524
+ try {
49525
+ if (JSON.parse(readFileSync2(candidate, "utf8")).name === "apple-notes-mcp")
49526
+ return dir;
49527
+ } catch {
49528
+ }
49529
+ }
49530
+ const parent = dirname4(dir);
49531
+ if (parent === dir) return resolve3(fromDir, "..");
49532
+ dir = parent;
49533
+ }
49534
+ }
49535
+ function defaultPublicHelperDeps(overrides = {}) {
49536
+ return {
49537
+ env: process.env,
49538
+ platform: process.platform,
49539
+ sourcePath: join19(packageRoot(), PUBLIC_HELPER_SOURCE),
49540
+ exists: existsSync12,
49541
+ readFile: (path10) => readFileSync2(path10),
49542
+ spawn: spawnSync,
49543
+ spawnAsync: spawn,
49544
+ ...overrides
49545
+ };
49546
+ }
49547
+ function publicHelperInstallDir(env = process.env) {
49548
+ const override = env[PUBLIC_HELPER_DIR_ENV]?.trim();
49549
+ if (override) return override;
49550
+ return join19(homedir16(), "Library", "Application Support", "apple-notes-mcp", "public-helper");
49551
+ }
49552
+ function sha256Hex(data) {
49553
+ return createHash2("sha256").update(data).digest("hex");
49554
+ }
49555
+ function inspectPublicHelper(deps = defaultPublicHelperDeps()) {
49556
+ const installDir = publicHelperInstallDir(deps.env);
49557
+ const binaryPath = join19(installDir, PUBLIC_HELPER_BINARY);
49558
+ const base = { installDir, binaryPath, sourcePath: deps.sourcePath, manifest: null };
49559
+ const fail = (reason, detail) => ({
49560
+ ...base,
49561
+ ready: false,
49562
+ reason,
49563
+ detail
49564
+ });
49565
+ if (deps.platform !== "darwin") return fail("unsupported_platform", "macOS only");
49566
+ if (!deps.exists(deps.sourcePath))
49567
+ return fail("helper_not_installed", `Packaged helper source is missing: ${deps.sourcePath}`);
49568
+ const manifestPath = join19(installDir, PUBLIC_HELPER_MANIFEST);
49569
+ if (!deps.exists(binaryPath) || !deps.exists(manifestPath))
49570
+ return fail(
49571
+ "helper_not_installed",
49572
+ `The public native helper is not built. Run \`${PUBLIC_HELPER_SETUP_COMMAND}\`.`
49573
+ );
49574
+ let manifest;
49575
+ try {
49576
+ manifest = publicManifestSchema.parse(JSON.parse(deps.readFile(manifestPath).toString("utf8")));
49577
+ } catch {
49578
+ return fail(
49579
+ "helper_manifest_invalid",
49580
+ `The helper manifest is unreadable. Run \`${PUBLIC_HELPER_SETUP_COMMAND}\`.`
49581
+ );
49582
+ }
49583
+ if (manifest.sourceSha256 !== sha256Hex(deps.readFile(deps.sourcePath)) || manifest.protocolVersion !== PUBLIC_HELPER_PROTOCOL)
49584
+ return {
49585
+ ...fail(
49586
+ "helper_stale",
49587
+ `The installed helper was built from a different source than this apple-notes-mcp version ships. Run \`${PUBLIC_HELPER_SETUP_COMMAND}\` again.`
49588
+ ),
49589
+ manifest
49590
+ };
49591
+ if (sha256Hex(deps.readFile(binaryPath)) !== manifest.binarySha256)
49592
+ return {
49593
+ ...fail(
49594
+ "helper_modified",
49595
+ `The helper binary no longer matches the checksum recorded when it was built. Run \`${PUBLIC_HELPER_SETUP_COMMAND}\` to rebuild it.`
49596
+ ),
49597
+ manifest
49598
+ };
49599
+ return { ...base, manifest, ready: true, reason: null, detail: null };
49600
+ }
49601
+ var UNAVAILABLE_CODES = /* @__PURE__ */ new Set([
49602
+ "unsupported_platform",
49603
+ "helper_not_installed",
49604
+ "helper_stale",
49605
+ "helper_modified",
49606
+ "helper_manifest_invalid"
49607
+ ]);
49608
+ var ENVELOPE_CODES = {
49609
+ invalid_request: "validation_error",
49610
+ attachment_not_found: "not_found"
49611
+ };
49612
+ var PublicHelperError = class extends CodedError {
49613
+ constructor(code, message) {
49614
+ super(message, {
49615
+ code: UNAVAILABLE_CODES.has(code) ? "unsupported" : ENVELOPE_CODES[code] ?? "operation_failed",
49616
+ helperCode: code
49617
+ });
49618
+ this.code = code;
49619
+ this.name = "PublicHelperError";
49620
+ }
49621
+ code;
49622
+ };
49623
+ var errorSchema = external_exports.object({ status: external_exports.literal("error"), code: external_exports.string(), message: external_exports.string() });
49624
+ var publicHelloSchema = external_exports.object({
49625
+ status: external_exports.literal("ok"),
49626
+ protocolVersion: external_exports.number().int(),
49627
+ sourceSha256: external_exports.string(),
49628
+ actions: external_exports.array(external_exports.string())
49629
+ }).passthrough();
49630
+ function callPublicHelper(action, fields = {}, deps = defaultPublicHelperDeps(), options = {}) {
49631
+ const { binaryPath, timeout, input } = prepareCall(action, fields, deps, options);
49632
+ const result = deps.spawn(binaryPath, [], {
49633
+ input,
49634
+ encoding: "utf8",
49635
+ timeout,
49636
+ killSignal: "SIGKILL",
49637
+ maxBuffer: MAX_OUTPUT_BYTES2
49638
+ });
49639
+ const errno = result.error?.code;
49640
+ if (errno === "ETIMEDOUT" || result.signal && result.status === null)
49641
+ throw new PublicHelperError("timeout", `The helper did not answer within ${timeout} ms.`);
49642
+ if (result.error)
49643
+ throw new PublicHelperError(
49644
+ "helper_unreachable",
49645
+ `Could not run the helper: ${result.error.message}`
49646
+ );
49647
+ return parseHelperOutput(result.status, String(result.stdout ?? ""));
49648
+ }
49649
+ async function callPublicHelperAsync(action, fields = {}, deps = defaultPublicHelperDeps(), options = {}) {
49650
+ const { binaryPath, timeout, input } = prepareCall(action, fields, deps, options);
49651
+ const { signal } = options;
49652
+ const aborted2 = () => new PublicHelperError("aborted", "The request was cancelled; the helper was stopped.");
49653
+ if (signal?.aborted) throw aborted2();
49654
+ return new Promise((resolvePromise, reject) => {
49655
+ const child2 = (deps.spawnAsync ?? spawn)(binaryPath, [], {
49656
+ stdio: ["pipe", "pipe", "ignore"]
49657
+ });
49658
+ const chunks = [];
49659
+ let size = 0;
49660
+ let failure2 = null;
49661
+ const stop = (error2) => {
49662
+ failure2 ??= error2;
49663
+ child2.kill("SIGKILL");
49664
+ };
49665
+ const timer = setTimeout(
49666
+ () => stop(new PublicHelperError("timeout", `The helper did not answer within ${timeout} ms.`)),
49667
+ timeout
49668
+ );
49669
+ const onAbort = () => stop(aborted2());
49670
+ signal?.addEventListener("abort", onAbort, { once: true });
49671
+ const settle = () => {
49672
+ clearTimeout(timer);
49673
+ signal?.removeEventListener("abort", onAbort);
49674
+ };
49675
+ child2.stdout?.on("data", (chunk) => {
49676
+ size += chunk.length;
49677
+ if (size > MAX_OUTPUT_BYTES2)
49678
+ stop(new PublicHelperError("invalid_response", "The helper response is too large."));
49679
+ else chunks.push(chunk);
49680
+ });
49681
+ child2.on("error", (error2) => {
49682
+ settle();
49683
+ reject(
49684
+ failure2 ?? new PublicHelperError("helper_unreachable", `Could not run the helper: ${error2.message}`)
49685
+ );
49686
+ });
49687
+ child2.on("close", (status, exitSignal) => {
49688
+ settle();
49689
+ if (failure2) return reject(failure2);
49690
+ if (status === null && exitSignal)
49691
+ return reject(
49692
+ new PublicHelperError("helper_crashed", `The helper stopped on signal ${exitSignal}.`)
49693
+ );
49694
+ try {
49695
+ resolvePromise(parseHelperOutput(status, Buffer.concat(chunks).toString("utf8")));
49696
+ } catch (error2) {
49697
+ reject(error2);
49698
+ }
49699
+ });
49700
+ child2.stdin?.on("error", () => {
49701
+ });
49702
+ child2.stdin?.end(input);
49703
+ });
49704
+ }
49705
+ function prepareCall(action, fields, deps, options) {
49706
+ if (!PUBLIC_HELPER_ACTIONS.has(action))
49707
+ throw new PublicHelperError(
49708
+ "unknown_action",
49709
+ `"${action}" is not an action the server sends to the public helper.`
49710
+ );
49711
+ let binaryPath = options.binaryPath;
49712
+ if (!binaryPath) {
49713
+ const install = inspectPublicHelper(deps);
49714
+ if (!install.ready)
49715
+ throw new PublicHelperError(install.reason ?? "helper_not_installed", install.detail ?? "");
49716
+ binaryPath = install.binaryPath;
49717
+ }
49718
+ const timeout = options.timeoutMs || Number.parseInt(deps.env[PUBLIC_HELPER_TIMEOUT_ENV] || "", 10) || DEFAULT_TIMEOUT_MS2;
49719
+ const input = JSON.stringify({ protocol: PUBLIC_HELPER_PROTOCOL, action, ...fields });
49720
+ return { binaryPath, timeout, input };
49721
+ }
49722
+ function parseHelperOutput(status, stdout) {
49723
+ let parsed2;
49724
+ try {
49725
+ parsed2 = JSON.parse(stdout.trim());
49726
+ } catch {
49727
+ throw new PublicHelperError(
49728
+ "invalid_response",
49729
+ `The helper exited with status ${status} and no JSON response.`
49730
+ );
49731
+ }
49732
+ if (!parsed2 || typeof parsed2 !== "object" || Array.isArray(parsed2))
49733
+ throw new PublicHelperError("invalid_response", "The helper response is not a JSON object.");
49734
+ const object3 = parsed2;
49735
+ if (status !== 0 || object3.status !== "ok") {
49736
+ const error2 = errorSchema.safeParse(object3);
49737
+ if (!error2.success)
49738
+ throw new PublicHelperError(
49739
+ "invalid_response",
49740
+ `The helper failed with an unrecognized response (exit ${status}).`
49741
+ );
49742
+ throw new PublicHelperError(error2.data.code, error2.data.message);
49743
+ }
49744
+ return object3;
49745
+ }
49746
+ function defaultPublicHelperBuildDeps() {
49747
+ return {
49748
+ ...defaultPublicHelperDeps(),
49749
+ osVersion: () => {
49750
+ const r = spawnSync("/usr/bin/sw_vers", ["-productVersion"], { encoding: "utf8" });
49751
+ return r.status === 0 ? r.stdout.trim() : `Darwin ${release()}`;
49752
+ },
49753
+ now: () => /* @__PURE__ */ new Date()
49754
+ };
49755
+ }
49756
+ function sourceDigestSwift(sourceSha) {
49757
+ return `let helperSourceSHA256 = "${sourceSha}"
49758
+ `;
49759
+ }
49760
+ var PUBLIC_HELPER_BUNDLE_ID = "apple-notes-mcp.public-helper";
49761
+ function publicHelperInfoPlist() {
49762
+ return [
49763
+ '<?xml version="1.0" encoding="UTF-8"?>',
49764
+ '<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">',
49765
+ '<plist version="1.0">',
49766
+ "<dict>",
49767
+ " <key>CFBundleIdentifier</key>",
49768
+ ` <string>${PUBLIC_HELPER_BUNDLE_ID}</string>`,
49769
+ " <key>CFBundleName</key>",
49770
+ " <string>apple-notes-mcp public helper</string>",
49771
+ " <key>CFBundleInfoDictionaryVersion</key>",
49772
+ " <string>6.0</string>",
49773
+ "</dict>",
49774
+ "</plist>",
49775
+ ""
49776
+ ].join("\n");
49777
+ }
49778
+ function publicHelperCompileArguments(sourcePath, digestPath, plistPath, outputPath) {
49779
+ return [
49780
+ "swiftc",
49781
+ "-O",
49782
+ "-parse-as-library",
49783
+ "-framework",
49784
+ "AppKit",
49785
+ "-framework",
49786
+ "PencilKit",
49787
+ "-framework",
49788
+ "AVFoundation",
49789
+ "-framework",
49790
+ "Speech",
49791
+ "-Xlinker",
49792
+ "-sectcreate",
49793
+ "-Xlinker",
49794
+ "__TEXT",
49795
+ "-Xlinker",
49796
+ "__info_plist",
49797
+ "-Xlinker",
49798
+ plistPath,
49799
+ sourcePath,
49800
+ digestPath,
49801
+ "-o",
49802
+ outputPath
49803
+ ];
49804
+ }
49805
+ function buildPublicHelper(checkOnly, deps = defaultPublicHelperBuildDeps()) {
49806
+ const steps = [];
49807
+ const done = (ok2) => ({
49808
+ ok: ok2,
49809
+ checkOnly,
49810
+ steps,
49811
+ installation: inspectPublicHelper(deps)
49812
+ });
49813
+ if (checkOnly) {
49814
+ const installation2 = inspectPublicHelper(deps);
49815
+ steps.push({
49816
+ step: "inspect installed helper",
49817
+ ok: installation2.ready,
49818
+ detail: installation2.ready ? installation2.binaryPath : installation2.detail ?? void 0
49819
+ });
49820
+ return { ok: installation2.ready, checkOnly, steps, installation: installation2 };
49821
+ }
49822
+ if (deps.platform !== "darwin") {
49823
+ steps.push({ step: "platform", ok: false, detail: "macOS only" });
49824
+ return done(false);
49825
+ }
49826
+ if (!deps.exists(deps.sourcePath)) {
49827
+ steps.push({ step: "locate source", ok: false, detail: deps.sourcePath });
49828
+ return done(false);
49829
+ }
49830
+ const sourceSha = sha256Hex(deps.readFile(deps.sourcePath));
49831
+ steps.push({ step: "locate source", ok: true, detail: `sha256 ${sourceSha}` });
49832
+ const version3 = deps.spawn("/usr/bin/xcrun", ["swiftc", "--version"], { encoding: "utf8" });
49833
+ if (version3.status !== 0) {
49834
+ steps.push({
49835
+ step: "find compiler",
49836
+ ok: false,
49837
+ detail: "No Swift compiler found. Install the Command Line Tools with `xcode-select --install`."
49838
+ });
49839
+ return done(false);
49840
+ }
49841
+ const compiler = String(version3.stdout || version3.stderr || "").split("\n").find((line) => line.includes("Swift version"))?.trim() || "swiftc";
49842
+ steps.push({ step: "find compiler", ok: true, detail: compiler });
49843
+ const installDir = publicHelperInstallDir(deps.env);
49844
+ mkdirSync4(installDir, { recursive: true, mode: 448 });
49845
+ const staging = mkdtempSync5(join19(installDir, ".staging-"));
49846
+ try {
49847
+ const stagedBinary = join19(staging, PUBLIC_HELPER_BINARY);
49848
+ const digestPath = join19(staging, "source-digest.swift");
49849
+ const plistPath = join19(staging, "Info.plist");
49850
+ writeFileSync4(digestPath, sourceDigestSwift(sourceSha), { mode: 384 });
49851
+ writeFileSync4(plistPath, publicHelperInfoPlist(), { mode: 384 });
49852
+ const compile = deps.spawn(
49853
+ "/usr/bin/xcrun",
49854
+ publicHelperCompileArguments(deps.sourcePath, digestPath, plistPath, stagedBinary),
49855
+ { encoding: "utf8", timeout: 3e5 }
49856
+ );
49857
+ if (compile.status !== 0) {
49858
+ steps.push({
49859
+ step: "compile",
49860
+ ok: false,
49861
+ detail: String(compile.stderr || compile.error?.message || "swiftc failed").slice(0, 4e3)
49862
+ });
49863
+ return done(false);
49864
+ }
49865
+ steps.push({ step: "compile", ok: true });
49866
+ const sign = deps.spawn(
49867
+ "/usr/bin/codesign",
49868
+ ["--force", "--sign", "-", "--identifier", PUBLIC_HELPER_BUNDLE_ID, stagedBinary],
49869
+ { encoding: "utf8" }
49870
+ );
49871
+ if (sign.status !== 0) {
49872
+ steps.push({
49873
+ step: "ad-hoc sign",
49874
+ ok: false,
49875
+ detail: String(sign.stderr || "codesign failed")
49876
+ });
49877
+ return done(false);
49878
+ }
49879
+ steps.push({ step: "ad-hoc sign", ok: true });
49880
+ let hello;
49881
+ try {
49882
+ hello = publicHelloSchema.parse(
49883
+ callPublicHelper("hello", {}, deps, { binaryPath: stagedBinary })
49884
+ );
49885
+ } catch (error2) {
49886
+ steps.push({
49887
+ step: "handshake",
49888
+ ok: false,
49889
+ detail: error2 instanceof Error ? error2.message : String(error2)
49890
+ });
49891
+ return done(false);
49892
+ }
49893
+ if (hello.protocolVersion !== PUBLIC_HELPER_PROTOCOL || hello.sourceSha256 !== sourceSha) {
49894
+ steps.push({
49895
+ step: "handshake",
49896
+ ok: false,
49897
+ detail: `helper reported protocol ${hello.protocolVersion}, source ${hello.sourceSha256}`
49898
+ });
49899
+ return done(false);
49900
+ }
49901
+ steps.push({ step: "handshake", ok: true, detail: `actions: ${hello.actions.join(", ")}` });
49902
+ const manifest = {
49903
+ schemaVersion: 1,
49904
+ protocolVersion: hello.protocolVersion,
49905
+ sourceSha256: sourceSha,
49906
+ binarySha256: sha256Hex(deps.readFile(stagedBinary)),
49907
+ builtAt: deps.now().toISOString(),
49908
+ osVersion: deps.osVersion(),
49909
+ compiler
49910
+ };
49911
+ chmodSync(stagedBinary, 448);
49912
+ renameSync(stagedBinary, join19(installDir, PUBLIC_HELPER_BINARY));
49913
+ writeFileSync4(
49914
+ join19(installDir, PUBLIC_HELPER_MANIFEST),
49915
+ JSON.stringify(manifest, null, 2) + "\n",
49916
+ { mode: 384 }
49917
+ );
49918
+ steps.push({ step: "install", ok: true, detail: installDir });
49919
+ } finally {
49920
+ rmSync5(staging, { recursive: true, force: true });
49921
+ }
49922
+ const installation = inspectPublicHelper(deps);
49923
+ steps.push({
49924
+ step: "verify installation",
49925
+ ok: installation.ready,
49926
+ detail: installation.ready ? void 0 : installation.detail ?? void 0
49927
+ });
49928
+ return { ok: installation.ready, checkOnly, steps, installation };
49929
+ }
49930
+ function formatPublicHelperBuild(report) {
49931
+ const lines = ["Apple Notes MCP public native helper", ""];
49932
+ for (const step of report.steps)
49933
+ lines.push(`${step.ok ? "\u2713" : "\u2717"} ${step.step}${step.detail ? `: ${step.detail}` : ""}`);
49934
+ lines.push("");
49935
+ if (report.ok) lines.push(`Installed at ${report.installation.binaryPath}.`);
49936
+ else if (report.checkOnly) lines.push(`Run \`${PUBLIC_HELPER_SETUP_COMMAND}\` to build it.`);
49937
+ else lines.push("The helper was not installed. Fix the failed step above and run setup again.");
49938
+ return lines.join("\n");
49939
+ }
49940
+
49941
+ // src/services/publicHelperStatus.ts
49942
+ var speechStatusSchema = external_exports.object({
49943
+ status: external_exports.literal("ok"),
49944
+ speechAuthorization: external_exports.enum(["authorized", "denied", "restricted", "notDetermined"]),
49945
+ requiresGrant: external_exports.boolean()
49946
+ });
49947
+ function unprobedPublicHelperStatus() {
49948
+ return {
49949
+ ready: false,
49950
+ reason: "not_probed",
49951
+ detail: "The public native helper has not been checked.",
49952
+ actions: [],
49953
+ speech: { authorization: null, requiresGrant: null, verified: false, detail: "Not probed." }
49954
+ };
49955
+ }
49956
+ function probePublicHelperStatus(deps = {
49957
+ inspect: inspectPublicHelper,
49958
+ call: (action) => callPublicHelper(action, {}, void 0, { timeoutMs: 3e3 })
49959
+ }) {
49960
+ const result = unprobedPublicHelperStatus();
49961
+ try {
49962
+ const installed = deps.inspect();
49963
+ if (!installed.ready) return { ...result, reason: installed.reason, detail: installed.detail };
49964
+ const hello = publicHelloSchema.safeParse(deps.call("hello"));
49965
+ if (!hello.success)
49966
+ return {
49967
+ ...result,
49968
+ reason: "invalid_response",
49969
+ detail: "The helper returned an invalid handshake."
49970
+ };
49971
+ if (hello.data.protocolVersion !== PUBLIC_HELPER_PROTOCOL || hello.data.sourceSha256 !== installed.manifest?.sourceSha256)
49972
+ return {
49973
+ ...result,
49974
+ reason: "helper_stale",
49975
+ detail: "The helper handshake does not match the installed protocol and source."
49976
+ };
49977
+ result.actions = hello.data.actions;
49978
+ const missing = ["decode_drawing", "transcribe", "speech_status"].filter(
49979
+ (action) => !result.actions.includes(action)
49980
+ );
49981
+ if (missing.length)
49982
+ return {
49983
+ ...result,
49984
+ reason: "helper_action_missing",
49985
+ detail: `The helper does not advertise: ${missing.join(", ")}.`
49986
+ };
49987
+ result.ready = true;
49988
+ result.reason = null;
49989
+ result.detail = "Installed digests, protocol, and required actions verified; no drawing or audio was processed.";
49990
+ } catch (error2) {
49991
+ return {
49992
+ ...result,
49993
+ reason: "helper_unreachable",
49994
+ detail: error2 instanceof Error ? error2.message : String(error2)
49995
+ };
49996
+ }
49997
+ try {
49998
+ const speech = speechStatusSchema.safeParse(deps.call("speech_status"));
49999
+ if (!speech.success) {
50000
+ result.speech.detail = "The helper returned an unknown or invalid Speech Recognition status.";
50001
+ } else {
50002
+ result.speech = {
50003
+ authorization: speech.data.speechAuthorization,
50004
+ requiresGrant: speech.data.requiresGrant,
50005
+ verified: true,
50006
+ detail: "Permission status only; locale support and model availability are checked when transcription is requested."
50007
+ };
50008
+ }
50009
+ } catch (error2) {
50010
+ result.speech.detail = error2 instanceof Error ? error2.message : String(error2);
50011
+ }
50012
+ return result;
50013
+ }
50014
+
50015
+ // src/services/capabilityMatrix.ts
49339
50016
  var MACOS_SHORTCUTS_CLI = "12.0";
49340
50017
  var MACOS_MARKDOWN_IMPORT = "26.0";
49341
50018
  var FEATURES = [
@@ -49412,7 +50089,8 @@ var FEATURES = [
49412
50089
  { kind: "notes_automation" },
49413
50090
  { kind: "full_disk_access" },
49414
50091
  { kind: "shortcuts_cli" },
49415
- { kind: "shortcut", name: backgroundShortcutName }
50092
+ { kind: "shortcut", name: backgroundShortcutName },
50093
+ { kind: "shortcut_consent" }
49416
50094
  ]
49417
50095
  },
49418
50096
  {
@@ -49424,7 +50102,8 @@ var FEATURES = [
49424
50102
  { kind: "notes_automation" },
49425
50103
  { kind: "full_disk_access" },
49426
50104
  { kind: "shortcuts_cli" },
49427
- { kind: "shortcut", name: nativeTagsShortcutName }
50105
+ { kind: "shortcut", name: nativeTagsShortcutName },
50106
+ { kind: "shortcut_consent" }
49428
50107
  ]
49429
50108
  },
49430
50109
  {
@@ -49436,7 +50115,8 @@ var FEATURES = [
49436
50115
  { kind: "notes_automation" },
49437
50116
  { kind: "full_disk_access" },
49438
50117
  { kind: "shortcuts_cli" },
49439
- { kind: "shortcut", name: markdownShortcutName }
50118
+ { kind: "shortcut", name: markdownShortcutName },
50119
+ { kind: "shortcut_consent" }
49440
50120
  ]
49441
50121
  },
49442
50122
  // Placeholders for features that need a native WRITE helper, which this
@@ -49473,12 +50153,31 @@ var FEATURES = [
49473
50153
  requirements: [{ kind: "full_disk_access" }]
49474
50154
  },
49475
50155
  {
49476
- name: "audioTranscription",
49477
- description: "Read the transcripts Notes stored for a note's audio recordings, or transcribe them on this Mac (transcribe-note-audio also needs the public helper built with setup --public-helper)",
49478
- tools: ["get-audio-transcripts", "transcribe-note-audio"],
50156
+ name: "storedAudioTranscripts",
50157
+ description: "Read transcripts Notes already stored for a note's audio recordings; no speech helper is needed",
50158
+ tools: ["get-audio-transcripts"],
49479
50159
  minimumMacOSVersion: null,
49480
50160
  requirements: [{ kind: "full_disk_access" }]
49481
50161
  },
50162
+ {
50163
+ name: "classicDrawingDecode",
50164
+ description: "Decode classic PencilKit drawings with the verified public native helper",
50165
+ tools: ["get-note-drawings"],
50166
+ minimumMacOSVersion: null,
50167
+ requirements: [{ kind: "full_disk_access" }, { kind: "public_native_helper" }]
50168
+ },
50169
+ {
50170
+ name: "audioTranscription",
50171
+ description: "Transcribe audio on this Mac with the verified public helper; locale and speech-model readiness are checked per request",
50172
+ tools: ["transcribe-note-audio"],
50173
+ minimumMacOSVersion: null,
50174
+ requirements: [
50175
+ { kind: "full_disk_access" },
50176
+ { kind: "public_native_helper" },
50177
+ { kind: "speech_recognition" },
50178
+ { kind: "speech_locale_and_assets" }
50179
+ ]
50180
+ },
49482
50181
  {
49483
50182
  name: "markdownTemplateLibrary",
49484
50183
  description: "Validate, save, list, show and delete Markdown export templates (local JSON files; exporting with one still needs Full Disk Access)",
@@ -49519,6 +50218,9 @@ function evaluateFeature(feature, env) {
49519
50218
  case "notes_automation":
49520
50219
  unverified.push(label);
49521
50220
  break;
50221
+ case "shortcut_consent":
50222
+ unverified.push(label);
50223
+ break;
49522
50224
  case "full_disk_access":
49523
50225
  if (!env.fullDiskAccess) {
49524
50226
  missing.push(label);
@@ -49542,6 +50244,29 @@ function evaluateFeature(feature, env) {
49542
50244
  missing.push(label);
49543
50245
  failures.add("not_implemented");
49544
50246
  break;
50247
+ case "public_native_helper":
50248
+ if (!env.publicHelper || env.publicHelper.reason === "not_probed") {
50249
+ unverified.push(label);
50250
+ failures.add("public_helper_unverified");
50251
+ } else if (!env.publicHelper.ready) {
50252
+ missing.push(label);
50253
+ failures.add("public_helper_unavailable");
50254
+ }
50255
+ break;
50256
+ case "speech_recognition": {
50257
+ const speech = env.publicHelper?.speech;
50258
+ if (!speech?.verified || speech.authorization === null || speech.requiresGrant === null) {
50259
+ unverified.push(label);
50260
+ failures.add("speech_status_unverified");
50261
+ } else if (speech.authorization === "denied" || speech.authorization === "restricted" || speech.requiresGrant && speech.authorization !== "authorized") {
50262
+ missing.push(label);
50263
+ failures.add("speech_permission_required");
50264
+ }
50265
+ break;
50266
+ }
50267
+ case "speech_locale_and_assets":
50268
+ unverified.push(label);
50269
+ break;
49545
50270
  }
49546
50271
  }
49547
50272
  let reason = null;
@@ -49552,6 +50277,10 @@ function evaluateFeature(feature, env) {
49552
50277
  else if (failures.has("full_disk_access_missing")) reason = "full_disk_access_missing";
49553
50278
  else if (failures.has("shortcuts_unavailable")) reason = "shortcuts_unavailable";
49554
50279
  else if (failures.has("shortcut_not_installed")) reason = "shortcut_not_installed";
50280
+ else if (failures.has("public_helper_unavailable")) reason = "public_helper_unavailable";
50281
+ else if (failures.has("public_helper_unverified")) reason = "public_helper_unverified";
50282
+ else if (failures.has("speech_permission_required")) reason = "speech_permission_required";
50283
+ else if (failures.has("speech_status_unverified")) reason = "speech_status_unverified";
49555
50284
  return {
49556
50285
  description: feature.description,
49557
50286
  tools: feature.tools,
@@ -49571,7 +50300,8 @@ function evaluateFeatures(env, features = FEATURES) {
49571
50300
  macOSVersion: env.macOSVersion,
49572
50301
  darwinRelease: env.darwinRelease
49573
50302
  },
49574
- features: Object.fromEntries(features.map((f) => [f.name, evaluateFeature(f, env)]))
50303
+ features: Object.fromEntries(features.map((f) => [f.name, evaluateFeature(f, env)])),
50304
+ publicHelper: env.publicHelper ?? unprobedPublicHelperStatus()
49575
50305
  };
49576
50306
  }
49577
50307
  function readMacOSVersion() {
@@ -49601,9 +50331,10 @@ function probeCapabilityEnvironment() {
49601
50331
  return {
49602
50332
  platform,
49603
50333
  macOSVersion: readMacOSVersion(),
49604
- darwinRelease: release(),
50334
+ darwinRelease: release2(),
49605
50335
  fullDiskAccess: isMac && hasFullDiskAccess(),
49606
- shortcutLines
50336
+ shortcutLines,
50337
+ publicHelper: isMac ? probePublicHelperStatus() : unprobedPublicHelperStatus()
49607
50338
  };
49608
50339
  }
49609
50340
  function getCapabilityMatrix(probe = probeCapabilityEnvironment) {
@@ -49616,7 +50347,7 @@ function formatCapabilityMatrix(matrix) {
49616
50347
  ];
49617
50348
  for (const [name, status] of Object.entries(matrix.features)) {
49618
50349
  lines.push(
49619
- status.available ? ` \u2713 ${name}: available${status.unverified.length ? ` (unverified: ${status.unverified.join(", ")})` : ""}` : ` \u2717 ${name}: ${status.reason}${status.missing.length ? ` (missing: ${status.missing.join(", ")})` : ""}`
50350
+ status.available ? ` \u2713 ${name}: available${status.unverified.length ? ` (unverified: ${status.unverified.join(", ")})` : ""}` : ` \u2717 ${name}: ${status.reason}${status.missing.length ? ` (missing: ${status.missing.join(", ")})` : ""}${status.unverified.length ? ` (unverified: ${status.unverified.join(", ")})` : ""}`
49620
50351
  );
49621
50352
  }
49622
50353
  return lines.join("\n");
@@ -49651,7 +50382,7 @@ function runDoctor(manager, capabilityMatrix = getCapabilityMatrix) {
49651
50382
  checks.push({
49652
50383
  name: "Full Disk Access",
49653
50384
  status: fda ? "ok" : "warn",
49654
- detail: fda ? "granted \u2014 the Notes database is readable (checklist state, note metadata, note links, sync detail)" : "not granted \u2014 get-checklist-state, get-note-metadata, and the checklist annotations in get-note-markdown won't work; get-note-link fails on macOS 26+ (macOS 12-15 falls back to AppleScript); get-sync-status still answers but cannot see pending uploads. Everything else is pure AppleScript and is unaffected. " + fdaRemediation()
50385
+ detail: fda ? "granted \u2014 the Notes database is readable (queries, native structure, exports, mutation guards, and sync detail)" : "not granted \u2014 database-backed queries, native structure and checklist state, media and portable exports, and database-backed mutation guards/readback are unavailable. Whole-body updates cannot proceed when their safety metadata is unreadable. Basic AppleScript read/create paths may still work with Automation permission. get-note-link fails on macOS 26+ (macOS 12-15 has an AppleScript fallback); get-sync-status cannot verify pending uploads or active sync. " + fdaRemediation()
49655
50386
  });
49656
50387
  const consentReminder = "After install or upgrade, run each bridge Shortcut once in the foreground in Shortcuts.app and choose Always Allow: a background run cannot display a first-run consent prompt, so an unanswered one stalls that bridge's native writes until they time out while this check stays ok";
49657
50388
  try {
@@ -49680,7 +50411,21 @@ function runDoctor(manager, capabilityMatrix = getCapabilityMatrix) {
49680
50411
  } catch {
49681
50412
  matrix = void 0;
49682
50413
  }
49683
- return matrix ? { healthy, checks, runtimeOS: matrix.runtimeOS, features: matrix.features } : { healthy, checks };
50414
+ const publicHelper = matrix?.publicHelper ?? unprobedPublicHelperStatus();
50415
+ checks.push({
50416
+ name: "Public native helper",
50417
+ status: publicHelper.ready ? "ok" : "warn",
50418
+ detail: publicHelper.ready ? publicHelper.detail ?? "Installed helper handshake verified." : `${publicHelper.reason ?? "unknown"}: ${publicHelper.detail ?? "Could not verify helper readiness."} Classic drawing decode and on-device transcription need a current public helper; run apple-notes-mcp setup --public-helper --check.`
50419
+ });
50420
+ if (publicHelper.ready) {
50421
+ const audio = matrix?.features.audioTranscription;
50422
+ checks.push({
50423
+ name: "On-device transcription",
50424
+ status: audio?.available ? "ok" : "warn",
50425
+ detail: audio ? `${audio.available ? "Prerequisites available" : audio.reason ?? "unverified"}. Unverified: ${audio.unverified.join(", ") || "none"}. ` + (publicHelper.speech.detail ?? "") : "Transcription prerequisites were not verified."
50426
+ });
50427
+ }
50428
+ return matrix ? { healthy, checks, runtimeOS: matrix.runtimeOS, features: matrix.features, publicHelper } : { healthy, checks, publicHelper };
49684
50429
  }
49685
50430
  function markdownBridgeDetail() {
49686
50431
  const purpose = 'needed only for create-note format: "markdown" on macOS 26+';
@@ -49693,7 +50438,7 @@ function markdownBridgeDetail() {
49693
50438
  function checkNodeRuntimeSignature() {
49694
50439
  const name = "Node runtime signature";
49695
50440
  try {
49696
- const r = spawnSync("codesign", ["-dvvv", process.execPath], { encoding: "utf8" });
50441
+ const r = spawnSync2("codesign", ["-dvvv", process.execPath], { encoding: "utf8" });
49697
50442
  const out = `${r.stdout ?? ""}${r.stderr ?? ""}`;
49698
50443
  if (r.error || !out.trim()) {
49699
50444
  return {
@@ -49730,22 +50475,22 @@ function formatDoctorReport(r) {
49730
50475
  }
49731
50476
 
49732
50477
  // src/services/fileConfig.ts
49733
- import { existsSync as existsSync12, readFileSync as readFileSync2 } from "fs";
49734
- import { join as join19 } from "path";
49735
- import { homedir as homedir16 } from "os";
50478
+ import { existsSync as existsSync13, readFileSync as readFileSync3 } from "fs";
50479
+ import { join as join20 } from "path";
50480
+ import { homedir as homedir17 } from "os";
49736
50481
  function fileConfigPath(env = process.env) {
49737
50482
  const override = env.APPLE_NOTES_MCP_CONFIG_FILE;
49738
50483
  if (override && override.trim()) return override.trim();
49739
- return join19(homedir16(), "Library", "Application Support", "apple-notes-mcp", "config.json");
50484
+ return join20(homedir17(), "Library", "Application Support", "apple-notes-mcp", "config.json");
49740
50485
  }
49741
50486
  function loadFileConfig(env = process.env, path10 = fileConfigPath(env)) {
49742
50487
  if (env.APPLE_NOTES_MCP_BROKERED === "1") return [];
49743
50488
  const applied = [];
49744
50489
  try {
49745
- if (!existsSync12(path10)) return applied;
49746
- const parsed = JSON.parse(readFileSync2(path10, "utf8"));
49747
- if (!parsed || typeof parsed !== "object") return applied;
49748
- for (const [k, v] of Object.entries(parsed)) {
50490
+ if (!existsSync13(path10)) return applied;
50491
+ const parsed2 = JSON.parse(readFileSync3(path10, "utf8"));
50492
+ if (!parsed2 || typeof parsed2 !== "object") return applied;
50493
+ for (const [k, v] of Object.entries(parsed2)) {
49749
50494
  if (typeof v !== "string") continue;
49750
50495
  if (env[k] === void 0 || env[k] === "") {
49751
50496
  env[k] = v;
@@ -50271,7 +51016,7 @@ function paragraphLink(note, selector) {
50271
51016
  }
50272
51017
 
50273
51018
  // src/utils/noteStructure.ts
50274
- import { dirname as dirname4 } from "node:path";
51019
+ import { dirname as dirname5 } from "node:path";
50275
51020
 
50276
51021
  // src/utils/noteLinks.ts
50277
51022
  var NOTE_LINK_UTI = "com.apple.notes.inlinetextattachment.link";
@@ -50457,7 +51202,7 @@ function readNoteStructure(id2, { dbPath: dbPath2 = NOTES_DB_PATH8, includeText
50457
51202
  bodyError = error2.code;
50458
51203
  }
50459
51204
  const { rows: attachmentRows, bodyOrder } = readNoteAttachmentRows(id2, dbPath2);
50460
- const assets = assembleAttachmentAssets(attachmentRows, bodyOrder, dirname4(dbPath2));
51205
+ const assets = assembleAttachmentAssets(attachmentRows, bodyOrder, dirname5(dbPath2));
50461
51206
  const roots = /* @__PURE__ */ new Map();
50462
51207
  const attachments = [];
50463
51208
  const pks = /* @__PURE__ */ new Map();
@@ -50599,7 +51344,7 @@ ${cause} ${remedy}`;
50599
51344
  }
50600
51345
 
50601
51346
  // src/utils/noteLinkInventory.ts
50602
- import { dirname as dirname5 } from "node:path";
51347
+ import { dirname as dirname6 } from "node:path";
50603
51348
  var BODY_BATCH = 100;
50604
51349
  function matchFolder(folders, wanted, account) {
50605
51350
  const paths = folderPaths(folders);
@@ -50735,7 +51480,7 @@ function listNoteLinks(options = {}) {
50735
51480
  accountIdentifier: account?.identifier ?? null
50736
51481
  };
50737
51482
  };
50738
- const containerDir = dirname5(dbPath2);
51483
+ const containerDir = dirname6(dbPath2);
50739
51484
  const previewEntries = /* @__PURE__ */ new Map();
50740
51485
  const previewFor = (identifier, account) => {
50741
51486
  const accountDir = identifier ? resolveAccountDir(containerDir, account) : null;
@@ -50929,7 +51674,7 @@ import {
50929
51674
  closeSync as closeSync4,
50930
51675
  constants as constants4,
50931
51676
  fstatSync as fstatSync4,
50932
- mkdirSync as mkdirSync4,
51677
+ mkdirSync as mkdirSync5,
50933
51678
  openSync as openSync4,
50934
51679
  readdirSync as readdirSync3,
50935
51680
  readSync as readSync3,
@@ -50937,9 +51682,9 @@ import {
50937
51682
  statSync as statSync3,
50938
51683
  writeSync as writeSync3
50939
51684
  } from "node:fs";
50940
- import { homedir as homedir17 } from "node:os";
50941
- import { basename as basename3, extname as extname3, join as join20, relative as relative3, resolve as resolve3, sep as sep3 } from "node:path";
50942
- var NOTES_CONTAINER = join20(homedir17(), "Library/Group Containers/group.com.apple.notes");
51685
+ import { homedir as homedir18 } from "node:os";
51686
+ import { basename as basename3, extname as extname3, join as join21, relative as relative3, resolve as resolve4, sep as sep3 } from "node:path";
51687
+ var NOTES_CONTAINER = join21(homedir18(), "Library/Group Containers/group.com.apple.notes");
50943
51688
  var MAX_EMBED_BYTES = 10 * 1024 * 1024;
50944
51689
  var MAX_EMBED_TOTAL_BYTES = 256 * 1024 * 1024;
50945
51690
  var MAX_DIRECTORY_ENTRIES = 2e4;
@@ -50995,11 +51740,11 @@ var AssetLocator = class {
50995
51740
  constructor(container = NOTES_CONTAINER) {
50996
51741
  let accountsRoot = "";
50997
51742
  try {
50998
- accountsRoot = realpathSync3.native(join20(container, "Accounts"));
51743
+ accountsRoot = realpathSync3.native(join21(container, "Accounts"));
50999
51744
  } catch {
51000
51745
  }
51001
51746
  this.accounts = accountsRoot ? listDirectory(accountsRoot, 1e3).flatMap((name) => {
51002
- const dir = safeComponent2(name) && confine(join20(accountsRoot, name), accountsRoot);
51747
+ const dir = safeComponent2(name) && confine(join21(accountsRoot, name), accountsRoot);
51003
51748
  return dir && isDirectory2(dir) ? [dir] : [];
51004
51749
  }) : [];
51005
51750
  }
@@ -51073,8 +51818,8 @@ var AssetLocator = class {
51073
51818
  if (!mediaId || !filename) return void 0;
51074
51819
  const generation = safeComponent2(source.mediaGeneration);
51075
51820
  const candidates = [
51076
- ...generation ? [join20(account, "Media", mediaId, generation, filename)] : [],
51077
- join20(account, "Media", mediaId, filename)
51821
+ ...generation ? [join21(account, "Media", mediaId, generation, filename)] : [],
51822
+ join21(account, "Media", mediaId, filename)
51078
51823
  ];
51079
51824
  for (const candidate of candidates) {
51080
51825
  const path10 = confine(candidate, account);
@@ -51088,7 +51833,7 @@ var AssetLocator = class {
51088
51833
  * somewhere else.
51089
51834
  */
51090
51835
  fallback(account, dir, id2, generation, names) {
51091
- const base = join20(account, dir, id2);
51836
+ const base = join21(account, dir, id2);
51092
51837
  const gen = safeComponent2(generation);
51093
51838
  const generations = [
51094
51839
  ...gen ? [gen] : [],
@@ -51097,7 +51842,7 @@ var AssetLocator = class {
51097
51842
  ];
51098
51843
  for (const g of generations)
51099
51844
  for (const name of names) {
51100
- const path10 = confine(g ? join20(base, g, name) : join20(base, name), account);
51845
+ const path10 = confine(g ? join21(base, g, name) : join21(base, name), account);
51101
51846
  if (path10 && isFile(path10)) return { path: path10, stale: Boolean(gen) && g !== gen };
51102
51847
  }
51103
51848
  return void 0;
@@ -51107,7 +51852,7 @@ var AssetLocator = class {
51107
51852
  let index = this.previewIndex.get(account);
51108
51853
  if (!index) {
51109
51854
  index = /* @__PURE__ */ new Map();
51110
- for (const name of listDirectory(join20(account, "Previews"), MAX_DIRECTORY_ENTRIES)) {
51855
+ for (const name of listDirectory(join21(account, "Previews"), MAX_DIRECTORY_ENTRIES)) {
51111
51856
  const key = name.slice(0, 36).toUpperCase();
51112
51857
  const entries3 = index.get(key) ?? [];
51113
51858
  entries3.push(name);
@@ -51120,7 +51865,7 @@ var AssetLocator = class {
51120
51865
  return !ext || IMAGE_EXTENSIONS.has(ext) || /^\.\d+$/.test(ext);
51121
51866
  }).sort((a, b) => previewArea(b) - previewArea(a) || a.localeCompare(b));
51122
51867
  for (const name of entries2) {
51123
- const entry = confine(join20(account, "Previews", name), account);
51868
+ const entry = confine(join21(account, "Previews", name), account);
51124
51869
  if (!entry) continue;
51125
51870
  const file = isFile(entry) ? entry : this.bundleImage(entry, account);
51126
51871
  if (file) return { path: file, name: "preview", role: "preview" };
@@ -51131,12 +51876,12 @@ var AssetLocator = class {
51131
51876
  bundleImage(bundle, account) {
51132
51877
  const found = [];
51133
51878
  for (const child2 of listDirectory(bundle, MAX_BUNDLE_ENTRIES2)) {
51134
- const path10 = confine(join20(bundle, child2), account);
51879
+ const path10 = confine(join21(bundle, child2), account);
51135
51880
  if (!path10) continue;
51136
51881
  if (isFile(path10)) found.push(path10);
51137
51882
  else
51138
51883
  for (const grandchild of listDirectory(path10, MAX_BUNDLE_ENTRIES2)) {
51139
- const inner = confine(join20(path10, grandchild), account);
51884
+ const inner = confine(join21(path10, grandchild), account);
51140
51885
  if (inner && isFile(inner)) found.push(inner);
51141
51886
  }
51142
51887
  }
@@ -51197,11 +51942,11 @@ function canonicalForm(abs) {
51197
51942
  for (; ; ) {
51198
51943
  try {
51199
51944
  const real = realpathSync3.native(current);
51200
- return rest ? join20(real, rest) : real;
51945
+ return rest ? join21(real, rest) : real;
51201
51946
  } catch {
51202
- const parent = resolve3(current, "..");
51947
+ const parent = resolve4(current, "..");
51203
51948
  if (parent === current) return abs;
51204
- rest = rest ? join20(basename3(current), rest) : basename3(current);
51949
+ rest = rest ? join21(basename3(current), rest) : basename3(current);
51205
51950
  current = parent;
51206
51951
  }
51207
51952
  }
@@ -51209,7 +51954,7 @@ function canonicalForm(abs) {
51209
51954
  function assertExportPath(p, container = NOTES_CONTAINER) {
51210
51955
  const abs = assertSafeSavePath(p);
51211
51956
  const within = (path10, root) => path10 === root || path10.startsWith(root + sep3);
51212
- const roots = [resolve3(container), canonicalForm(resolve3(container))];
51957
+ const roots = [resolve4(container), canonicalForm(resolve4(container))];
51213
51958
  const forms = [abs, canonicalForm(abs)];
51214
51959
  if (forms.some((form) => roots.some((root) => within(form, root))))
51215
51960
  throw new Error("Refusing to write inside the Notes library container.");
@@ -51315,7 +52060,7 @@ var SidecarWriter = class {
51315
52060
  if (!this.created) {
51316
52061
  try {
51317
52062
  assertExportPath(this.dir);
51318
- mkdirSync4(this.dir, { recursive: true });
52063
+ mkdirSync5(this.dir, { recursive: true });
51319
52064
  } catch (error2) {
51320
52065
  this.directoryError = directoryFailure(this.dir, error2);
51321
52066
  return { error: this.directoryError };
@@ -51328,7 +52073,7 @@ var SidecarWriter = class {
51328
52073
  let target;
51329
52074
  let out;
51330
52075
  for (let n = 1; n <= 1e3 && out === void 0; n++) {
51331
- target = join20(this.dir, n === 1 ? safe2 : `${stem}-${n}${ext}`);
52076
+ target = join21(this.dir, n === 1 ? safe2 : `${stem}-${n}${ext}`);
51332
52077
  try {
51333
52078
  out = openSync4(target, CREATE_FLAGS, 420);
51334
52079
  } catch (error2) {
@@ -51987,468 +52732,6 @@ function drawingToSvg(strokes, fallback) {
51987
52732
  return parts.join("\n");
51988
52733
  }
51989
52734
 
51990
- // src/services/publicHelper.ts
51991
- import { spawn, spawnSync as spawnSync2 } from "node:child_process";
51992
- import { createHash as createHash2 } from "node:crypto";
51993
- import {
51994
- chmodSync,
51995
- existsSync as existsSync13,
51996
- mkdirSync as mkdirSync5,
51997
- mkdtempSync as mkdtempSync5,
51998
- readFileSync as readFileSync3,
51999
- renameSync,
52000
- rmSync as rmSync5,
52001
- writeFileSync as writeFileSync4
52002
- } from "node:fs";
52003
- import { homedir as homedir18, release as release2 } from "node:os";
52004
- import { dirname as dirname6, join as join21, resolve as resolve4 } from "node:path";
52005
- import { fileURLToPath } from "node:url";
52006
- var PUBLIC_HELPER_PROTOCOL = 1;
52007
- var PUBLIC_HELPER_DIR_ENV = "APPLE_NOTES_MCP_PUBLIC_HELPER_DIR";
52008
- var PUBLIC_HELPER_TIMEOUT_ENV = "APPLE_NOTES_MCP_PUBLIC_HELPER_TIMEOUT_MS";
52009
- var PUBLIC_HELPER_BINARY = "apple-notes-public-helper";
52010
- var PUBLIC_HELPER_SOURCE = "native/public-helper/apple-notes-public-helper.swift";
52011
- var PUBLIC_HELPER_MANIFEST = "manifest.json";
52012
- var PUBLIC_HELPER_SETUP_COMMAND = "apple-notes-mcp setup --public-helper";
52013
- var PUBLIC_HELPER_ACTIONS = /* @__PURE__ */ new Set([
52014
- "hello",
52015
- "decode_drawing",
52016
- "transcribe",
52017
- "speech_status"
52018
- ]);
52019
- var DEFAULT_TIMEOUT_MS2 = 3e4;
52020
- var MAX_OUTPUT_BYTES2 = 256 * 1024 * 1024;
52021
- var publicManifestSchema = external_exports.object({
52022
- schemaVersion: external_exports.literal(1),
52023
- protocolVersion: external_exports.number().int(),
52024
- sourceSha256: external_exports.string().regex(/^[a-f0-9]{64}$/),
52025
- binarySha256: external_exports.string().regex(/^[a-f0-9]{64}$/),
52026
- builtAt: external_exports.string(),
52027
- osVersion: external_exports.string(),
52028
- compiler: external_exports.string()
52029
- });
52030
- function packageRoot(fromDir = dirname6(fileURLToPath(import.meta.url))) {
52031
- let dir = fromDir;
52032
- for (; ; ) {
52033
- const candidate = join21(dir, "package.json");
52034
- if (existsSync13(candidate)) {
52035
- try {
52036
- if (JSON.parse(readFileSync3(candidate, "utf8")).name === "apple-notes-mcp")
52037
- return dir;
52038
- } catch {
52039
- }
52040
- }
52041
- const parent = dirname6(dir);
52042
- if (parent === dir) return resolve4(fromDir, "..");
52043
- dir = parent;
52044
- }
52045
- }
52046
- function defaultPublicHelperDeps(overrides = {}) {
52047
- return {
52048
- env: process.env,
52049
- platform: process.platform,
52050
- sourcePath: join21(packageRoot(), PUBLIC_HELPER_SOURCE),
52051
- exists: existsSync13,
52052
- readFile: (path10) => readFileSync3(path10),
52053
- spawn: spawnSync2,
52054
- spawnAsync: spawn,
52055
- ...overrides
52056
- };
52057
- }
52058
- function publicHelperInstallDir(env = process.env) {
52059
- const override = env[PUBLIC_HELPER_DIR_ENV]?.trim();
52060
- if (override) return override;
52061
- return join21(homedir18(), "Library", "Application Support", "apple-notes-mcp", "public-helper");
52062
- }
52063
- function sha256Hex(data) {
52064
- return createHash2("sha256").update(data).digest("hex");
52065
- }
52066
- function inspectPublicHelper(deps = defaultPublicHelperDeps()) {
52067
- const installDir = publicHelperInstallDir(deps.env);
52068
- const binaryPath = join21(installDir, PUBLIC_HELPER_BINARY);
52069
- const base = { installDir, binaryPath, sourcePath: deps.sourcePath, manifest: null };
52070
- const fail = (reason, detail) => ({
52071
- ...base,
52072
- ready: false,
52073
- reason,
52074
- detail
52075
- });
52076
- if (deps.platform !== "darwin") return fail("unsupported_platform", "macOS only");
52077
- if (!deps.exists(deps.sourcePath))
52078
- return fail("helper_not_installed", `Packaged helper source is missing: ${deps.sourcePath}`);
52079
- const manifestPath = join21(installDir, PUBLIC_HELPER_MANIFEST);
52080
- if (!deps.exists(binaryPath) || !deps.exists(manifestPath))
52081
- return fail(
52082
- "helper_not_installed",
52083
- `The public native helper is not built. Run \`${PUBLIC_HELPER_SETUP_COMMAND}\`.`
52084
- );
52085
- let manifest;
52086
- try {
52087
- manifest = publicManifestSchema.parse(JSON.parse(deps.readFile(manifestPath).toString("utf8")));
52088
- } catch {
52089
- return fail(
52090
- "helper_manifest_invalid",
52091
- `The helper manifest is unreadable. Run \`${PUBLIC_HELPER_SETUP_COMMAND}\`.`
52092
- );
52093
- }
52094
- if (manifest.sourceSha256 !== sha256Hex(deps.readFile(deps.sourcePath)) || manifest.protocolVersion !== PUBLIC_HELPER_PROTOCOL)
52095
- return {
52096
- ...fail(
52097
- "helper_stale",
52098
- `The installed helper was built from a different source than this apple-notes-mcp version ships. Run \`${PUBLIC_HELPER_SETUP_COMMAND}\` again.`
52099
- ),
52100
- manifest
52101
- };
52102
- if (sha256Hex(deps.readFile(binaryPath)) !== manifest.binarySha256)
52103
- return {
52104
- ...fail(
52105
- "helper_modified",
52106
- `The helper binary no longer matches the checksum recorded when it was built. Run \`${PUBLIC_HELPER_SETUP_COMMAND}\` to rebuild it.`
52107
- ),
52108
- manifest
52109
- };
52110
- return { ...base, manifest, ready: true, reason: null, detail: null };
52111
- }
52112
- var UNAVAILABLE_CODES = /* @__PURE__ */ new Set([
52113
- "unsupported_platform",
52114
- "helper_not_installed",
52115
- "helper_stale",
52116
- "helper_modified",
52117
- "helper_manifest_invalid"
52118
- ]);
52119
- var ENVELOPE_CODES = {
52120
- invalid_request: "validation_error",
52121
- attachment_not_found: "not_found"
52122
- };
52123
- var PublicHelperError = class extends CodedError {
52124
- constructor(code, message) {
52125
- super(message, {
52126
- code: UNAVAILABLE_CODES.has(code) ? "unsupported" : ENVELOPE_CODES[code] ?? "operation_failed",
52127
- helperCode: code
52128
- });
52129
- this.code = code;
52130
- this.name = "PublicHelperError";
52131
- }
52132
- code;
52133
- };
52134
- var errorSchema = external_exports.object({ status: external_exports.literal("error"), code: external_exports.string(), message: external_exports.string() });
52135
- var publicHelloSchema = external_exports.object({
52136
- status: external_exports.literal("ok"),
52137
- protocolVersion: external_exports.number().int(),
52138
- sourceSha256: external_exports.string(),
52139
- actions: external_exports.array(external_exports.string())
52140
- }).passthrough();
52141
- function callPublicHelper(action, fields = {}, deps = defaultPublicHelperDeps(), options = {}) {
52142
- const { binaryPath, timeout, input } = prepareCall(action, fields, deps, options);
52143
- const result = deps.spawn(binaryPath, [], {
52144
- input,
52145
- encoding: "utf8",
52146
- timeout,
52147
- killSignal: "SIGKILL",
52148
- maxBuffer: MAX_OUTPUT_BYTES2
52149
- });
52150
- const errno = result.error?.code;
52151
- if (errno === "ETIMEDOUT" || result.signal && result.status === null)
52152
- throw new PublicHelperError("timeout", `The helper did not answer within ${timeout} ms.`);
52153
- if (result.error)
52154
- throw new PublicHelperError(
52155
- "helper_unreachable",
52156
- `Could not run the helper: ${result.error.message}`
52157
- );
52158
- return parseHelperOutput(result.status, String(result.stdout ?? ""));
52159
- }
52160
- async function callPublicHelperAsync(action, fields = {}, deps = defaultPublicHelperDeps(), options = {}) {
52161
- const { binaryPath, timeout, input } = prepareCall(action, fields, deps, options);
52162
- const { signal } = options;
52163
- const aborted2 = () => new PublicHelperError("aborted", "The request was cancelled; the helper was stopped.");
52164
- if (signal?.aborted) throw aborted2();
52165
- return new Promise((resolvePromise, reject) => {
52166
- const child2 = (deps.spawnAsync ?? spawn)(binaryPath, [], {
52167
- stdio: ["pipe", "pipe", "ignore"]
52168
- });
52169
- const chunks = [];
52170
- let size = 0;
52171
- let failure2 = null;
52172
- const stop = (error2) => {
52173
- failure2 ??= error2;
52174
- child2.kill("SIGKILL");
52175
- };
52176
- const timer = setTimeout(
52177
- () => stop(new PublicHelperError("timeout", `The helper did not answer within ${timeout} ms.`)),
52178
- timeout
52179
- );
52180
- const onAbort = () => stop(aborted2());
52181
- signal?.addEventListener("abort", onAbort, { once: true });
52182
- const settle = () => {
52183
- clearTimeout(timer);
52184
- signal?.removeEventListener("abort", onAbort);
52185
- };
52186
- child2.stdout?.on("data", (chunk) => {
52187
- size += chunk.length;
52188
- if (size > MAX_OUTPUT_BYTES2)
52189
- stop(new PublicHelperError("invalid_response", "The helper response is too large."));
52190
- else chunks.push(chunk);
52191
- });
52192
- child2.on("error", (error2) => {
52193
- settle();
52194
- reject(
52195
- failure2 ?? new PublicHelperError("helper_unreachable", `Could not run the helper: ${error2.message}`)
52196
- );
52197
- });
52198
- child2.on("close", (status, exitSignal) => {
52199
- settle();
52200
- if (failure2) return reject(failure2);
52201
- if (status === null && exitSignal)
52202
- return reject(
52203
- new PublicHelperError("helper_crashed", `The helper stopped on signal ${exitSignal}.`)
52204
- );
52205
- try {
52206
- resolvePromise(parseHelperOutput(status, Buffer.concat(chunks).toString("utf8")));
52207
- } catch (error2) {
52208
- reject(error2);
52209
- }
52210
- });
52211
- child2.stdin?.on("error", () => {
52212
- });
52213
- child2.stdin?.end(input);
52214
- });
52215
- }
52216
- function prepareCall(action, fields, deps, options) {
52217
- if (!PUBLIC_HELPER_ACTIONS.has(action))
52218
- throw new PublicHelperError(
52219
- "unknown_action",
52220
- `"${action}" is not an action the server sends to the public helper.`
52221
- );
52222
- let binaryPath = options.binaryPath;
52223
- if (!binaryPath) {
52224
- const install = inspectPublicHelper(deps);
52225
- if (!install.ready)
52226
- throw new PublicHelperError(install.reason ?? "helper_not_installed", install.detail ?? "");
52227
- binaryPath = install.binaryPath;
52228
- }
52229
- const timeout = options.timeoutMs || Number.parseInt(deps.env[PUBLIC_HELPER_TIMEOUT_ENV] || "", 10) || DEFAULT_TIMEOUT_MS2;
52230
- const input = JSON.stringify({ protocol: PUBLIC_HELPER_PROTOCOL, action, ...fields });
52231
- return { binaryPath, timeout, input };
52232
- }
52233
- function parseHelperOutput(status, stdout) {
52234
- let parsed;
52235
- try {
52236
- parsed = JSON.parse(stdout.trim());
52237
- } catch {
52238
- throw new PublicHelperError(
52239
- "invalid_response",
52240
- `The helper exited with status ${status} and no JSON response.`
52241
- );
52242
- }
52243
- if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
52244
- throw new PublicHelperError("invalid_response", "The helper response is not a JSON object.");
52245
- const object3 = parsed;
52246
- if (status !== 0 || object3.status !== "ok") {
52247
- const error2 = errorSchema.safeParse(object3);
52248
- if (!error2.success)
52249
- throw new PublicHelperError(
52250
- "invalid_response",
52251
- `The helper failed with an unrecognized response (exit ${status}).`
52252
- );
52253
- throw new PublicHelperError(error2.data.code, error2.data.message);
52254
- }
52255
- return object3;
52256
- }
52257
- function defaultPublicHelperBuildDeps() {
52258
- return {
52259
- ...defaultPublicHelperDeps(),
52260
- osVersion: () => {
52261
- const r = spawnSync2("/usr/bin/sw_vers", ["-productVersion"], { encoding: "utf8" });
52262
- return r.status === 0 ? r.stdout.trim() : `Darwin ${release2()}`;
52263
- },
52264
- now: () => /* @__PURE__ */ new Date()
52265
- };
52266
- }
52267
- function sourceDigestSwift(sourceSha) {
52268
- return `let helperSourceSHA256 = "${sourceSha}"
52269
- `;
52270
- }
52271
- var PUBLIC_HELPER_BUNDLE_ID = "apple-notes-mcp.public-helper";
52272
- function publicHelperInfoPlist() {
52273
- return [
52274
- '<?xml version="1.0" encoding="UTF-8"?>',
52275
- '<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">',
52276
- '<plist version="1.0">',
52277
- "<dict>",
52278
- " <key>CFBundleIdentifier</key>",
52279
- ` <string>${PUBLIC_HELPER_BUNDLE_ID}</string>`,
52280
- " <key>CFBundleName</key>",
52281
- " <string>apple-notes-mcp public helper</string>",
52282
- " <key>CFBundleInfoDictionaryVersion</key>",
52283
- " <string>6.0</string>",
52284
- "</dict>",
52285
- "</plist>",
52286
- ""
52287
- ].join("\n");
52288
- }
52289
- function publicHelperCompileArguments(sourcePath, digestPath, plistPath, outputPath) {
52290
- return [
52291
- "swiftc",
52292
- "-O",
52293
- "-parse-as-library",
52294
- "-framework",
52295
- "AppKit",
52296
- "-framework",
52297
- "PencilKit",
52298
- "-framework",
52299
- "AVFoundation",
52300
- "-framework",
52301
- "Speech",
52302
- "-Xlinker",
52303
- "-sectcreate",
52304
- "-Xlinker",
52305
- "__TEXT",
52306
- "-Xlinker",
52307
- "__info_plist",
52308
- "-Xlinker",
52309
- plistPath,
52310
- sourcePath,
52311
- digestPath,
52312
- "-o",
52313
- outputPath
52314
- ];
52315
- }
52316
- function buildPublicHelper(checkOnly, deps = defaultPublicHelperBuildDeps()) {
52317
- const steps = [];
52318
- const done = (ok2) => ({
52319
- ok: ok2,
52320
- checkOnly,
52321
- steps,
52322
- installation: inspectPublicHelper(deps)
52323
- });
52324
- if (checkOnly) {
52325
- const installation2 = inspectPublicHelper(deps);
52326
- steps.push({
52327
- step: "inspect installed helper",
52328
- ok: installation2.ready,
52329
- detail: installation2.ready ? installation2.binaryPath : installation2.detail ?? void 0
52330
- });
52331
- return { ok: installation2.ready, checkOnly, steps, installation: installation2 };
52332
- }
52333
- if (deps.platform !== "darwin") {
52334
- steps.push({ step: "platform", ok: false, detail: "macOS only" });
52335
- return done(false);
52336
- }
52337
- if (!deps.exists(deps.sourcePath)) {
52338
- steps.push({ step: "locate source", ok: false, detail: deps.sourcePath });
52339
- return done(false);
52340
- }
52341
- const sourceSha = sha256Hex(deps.readFile(deps.sourcePath));
52342
- steps.push({ step: "locate source", ok: true, detail: `sha256 ${sourceSha}` });
52343
- const version3 = deps.spawn("/usr/bin/xcrun", ["swiftc", "--version"], { encoding: "utf8" });
52344
- if (version3.status !== 0) {
52345
- steps.push({
52346
- step: "find compiler",
52347
- ok: false,
52348
- detail: "No Swift compiler found. Install the Command Line Tools with `xcode-select --install`."
52349
- });
52350
- return done(false);
52351
- }
52352
- const compiler = String(version3.stdout || version3.stderr || "").split("\n").find((line) => line.includes("Swift version"))?.trim() || "swiftc";
52353
- steps.push({ step: "find compiler", ok: true, detail: compiler });
52354
- const installDir = publicHelperInstallDir(deps.env);
52355
- mkdirSync5(installDir, { recursive: true, mode: 448 });
52356
- const staging = mkdtempSync5(join21(installDir, ".staging-"));
52357
- try {
52358
- const stagedBinary = join21(staging, PUBLIC_HELPER_BINARY);
52359
- const digestPath = join21(staging, "source-digest.swift");
52360
- const plistPath = join21(staging, "Info.plist");
52361
- writeFileSync4(digestPath, sourceDigestSwift(sourceSha), { mode: 384 });
52362
- writeFileSync4(plistPath, publicHelperInfoPlist(), { mode: 384 });
52363
- const compile = deps.spawn(
52364
- "/usr/bin/xcrun",
52365
- publicHelperCompileArguments(deps.sourcePath, digestPath, plistPath, stagedBinary),
52366
- { encoding: "utf8", timeout: 3e5 }
52367
- );
52368
- if (compile.status !== 0) {
52369
- steps.push({
52370
- step: "compile",
52371
- ok: false,
52372
- detail: String(compile.stderr || compile.error?.message || "swiftc failed").slice(0, 4e3)
52373
- });
52374
- return done(false);
52375
- }
52376
- steps.push({ step: "compile", ok: true });
52377
- const sign = deps.spawn(
52378
- "/usr/bin/codesign",
52379
- ["--force", "--sign", "-", "--identifier", PUBLIC_HELPER_BUNDLE_ID, stagedBinary],
52380
- { encoding: "utf8" }
52381
- );
52382
- if (sign.status !== 0) {
52383
- steps.push({
52384
- step: "ad-hoc sign",
52385
- ok: false,
52386
- detail: String(sign.stderr || "codesign failed")
52387
- });
52388
- return done(false);
52389
- }
52390
- steps.push({ step: "ad-hoc sign", ok: true });
52391
- let hello;
52392
- try {
52393
- hello = publicHelloSchema.parse(
52394
- callPublicHelper("hello", {}, deps, { binaryPath: stagedBinary })
52395
- );
52396
- } catch (error2) {
52397
- steps.push({
52398
- step: "handshake",
52399
- ok: false,
52400
- detail: error2 instanceof Error ? error2.message : String(error2)
52401
- });
52402
- return done(false);
52403
- }
52404
- if (hello.protocolVersion !== PUBLIC_HELPER_PROTOCOL || hello.sourceSha256 !== sourceSha) {
52405
- steps.push({
52406
- step: "handshake",
52407
- ok: false,
52408
- detail: `helper reported protocol ${hello.protocolVersion}, source ${hello.sourceSha256}`
52409
- });
52410
- return done(false);
52411
- }
52412
- steps.push({ step: "handshake", ok: true, detail: `actions: ${hello.actions.join(", ")}` });
52413
- const manifest = {
52414
- schemaVersion: 1,
52415
- protocolVersion: hello.protocolVersion,
52416
- sourceSha256: sourceSha,
52417
- binarySha256: sha256Hex(deps.readFile(stagedBinary)),
52418
- builtAt: deps.now().toISOString(),
52419
- osVersion: deps.osVersion(),
52420
- compiler
52421
- };
52422
- chmodSync(stagedBinary, 448);
52423
- renameSync(stagedBinary, join21(installDir, PUBLIC_HELPER_BINARY));
52424
- writeFileSync4(
52425
- join21(installDir, PUBLIC_HELPER_MANIFEST),
52426
- JSON.stringify(manifest, null, 2) + "\n",
52427
- { mode: 384 }
52428
- );
52429
- steps.push({ step: "install", ok: true, detail: installDir });
52430
- } finally {
52431
- rmSync5(staging, { recursive: true, force: true });
52432
- }
52433
- const installation = inspectPublicHelper(deps);
52434
- steps.push({
52435
- step: "verify installation",
52436
- ok: installation.ready,
52437
- detail: installation.ready ? void 0 : installation.detail ?? void 0
52438
- });
52439
- return { ok: installation.ready, checkOnly, steps, installation };
52440
- }
52441
- function formatPublicHelperBuild(report) {
52442
- const lines = ["Apple Notes MCP public native helper", ""];
52443
- for (const step of report.steps)
52444
- lines.push(`${step.ok ? "\u2713" : "\u2717"} ${step.step}${step.detail ? `: ${step.detail}` : ""}`);
52445
- lines.push("");
52446
- if (report.ok) lines.push(`Installed at ${report.installation.binaryPath}.`);
52447
- else if (report.checkOnly) lines.push(`Run \`${PUBLIC_HELPER_SETUP_COMMAND}\` to build it.`);
52448
- else lines.push("The helper was not installed. Fix the failed step above and run setup again.");
52449
- return lines.join("\n");
52450
- }
52451
-
52452
52735
  // src/services/noteDrawings.ts
52453
52736
  var bounds = external_exports.object({ x: external_exports.number(), y: external_exports.number(), width: external_exports.number(), height: external_exports.number() });
52454
52737
  var strokeSchema = external_exports.object({
@@ -52500,10 +52783,10 @@ function decodeRow(row, format, includePoints, deps) {
52500
52783
  { dataBase64: row.data.toString("base64"), includePoints: needPoints },
52501
52784
  deps
52502
52785
  );
52503
- const parsed = decodedDrawingSchema.safeParse(raw);
52504
- if (!parsed.success)
52786
+ const parsed2 = decodedDrawingSchema.safeParse(raw);
52787
+ if (!parsed2.success)
52505
52788
  return { ...base, code: "invalid_response", message: "Unexpected helper response." };
52506
- decoded = parsed.data;
52789
+ decoded = parsed2.data;
52507
52790
  } catch (error2) {
52508
52791
  const code = error2 instanceof PublicHelperError ? error2.code : "internal_error";
52509
52792
  return { ...base, code, message: error2 instanceof Error ? error2.message : String(error2) };
@@ -53026,18 +53309,18 @@ function readExportNote(id2, { dbPath: dbPath2 = NOTES_DB_PATH11 } = {}) {
53026
53309
  `.parameter set @pk ${pk}`,
53027
53310
  attachmentQuery(objectColumns(dbPath2))
53028
53311
  ]);
53029
- let parsed;
53312
+ let parsed2;
53030
53313
  try {
53031
- parsed = JSON.parse(output);
53314
+ parsed2 = JSON.parse(output);
53032
53315
  } catch {
53033
53316
  throw new NoteBlocksError("query-failed", "Unexpected Notes database response");
53034
53317
  }
53035
- const rows = Array.isArray(parsed.attachments) ? parsed.attachments : [];
53318
+ const rows = Array.isArray(parsed2.attachments) ? parsed2.attachments : [];
53036
53319
  const { byId, ordered } = buildAttachments(rows);
53037
53320
  const firstLine = doc.blocks.find((block) => block.text.trim())?.text.trim() ?? "";
53038
53321
  return {
53039
53322
  id: id2,
53040
- title: text(parsed.title) ?? firstLine,
53323
+ title: text(parsed2.title) ?? firstLine,
53041
53324
  doc,
53042
53325
  attachments: byId,
53043
53326
  ordered
@@ -53529,9 +53812,9 @@ function parseTemplate(text2) {
53529
53812
  throw new TemplateValidationError([
53530
53813
  { path: "$", message: `template is ${bytes} bytes; the limit is ${MAX_TEMPLATE_BYTES}` }
53531
53814
  ]);
53532
- let parsed;
53815
+ let parsed2;
53533
53816
  try {
53534
- parsed = JSON.parse(text2);
53817
+ parsed2 = JSON.parse(text2);
53535
53818
  } catch (error2) {
53536
53819
  const at = jsonErrorLocation(text2, error2.message);
53537
53820
  throw new TemplateValidationError([
@@ -53541,7 +53824,7 @@ function parseTemplate(text2) {
53541
53824
  }
53542
53825
  ]);
53543
53826
  }
53544
- return validateTemplate(parsed);
53827
+ return validateTemplate(parsed2);
53545
53828
  }
53546
53829
  function resolveTemplate(template, name) {
53547
53830
  if (template === STANDARD) return merge2(void 0, STANDARD, name);
@@ -53560,15 +53843,15 @@ function merge2(base, template, name) {
53560
53843
  var plainValue = (text2) => ({ md: text2, raw: text2 });
53561
53844
  function fillPlaceholders(text2, values) {
53562
53845
  return text2.replace(TOKEN, (token, body) => {
53563
- const parsed = TOKEN_BODY.exec(body);
53564
- const raw = parsed ? values[parsed[1]] : void 0;
53846
+ const parsed2 = TOKEN_BODY.exec(body);
53847
+ const raw = parsed2 ? values[parsed2[1]] : void 0;
53565
53848
  const value = typeof raw === "string" ? plainValue(raw) : raw;
53566
- if (parsed?.[2] === "yaml") {
53849
+ if (parsed2?.[2] === "yaml") {
53567
53850
  if (!value) return "null";
53568
53851
  return JSON.stringify(value.list ?? value.raw);
53569
53852
  }
53570
53853
  if (!value) return "";
53571
- return parsed?.[2] === "raw" ? value.raw : value.md;
53854
+ return parsed2?.[2] === "raw" ? value.raw : value.md;
53572
53855
  });
53573
53856
  }
53574
53857
  function ruleUses(rule, name) {
@@ -53606,9 +53889,9 @@ var KIND_RULES = {
53606
53889
  var IMAGE_URL_EXTENSIONS = /\.(?:apng|avif|bmp|gif|heic|heif|ico|jfif|jpe?g|jxl|png|svgz?|tiff?|webp)$/i;
53607
53890
  function isImageUrl(url) {
53608
53891
  try {
53609
- const parsed = new URL(url);
53610
- if (parsed.protocol !== "http:" && parsed.protocol !== "https:") return false;
53611
- let path10 = parsed.pathname;
53892
+ const parsed2 = new URL(url);
53893
+ if (parsed2.protocol !== "http:" && parsed2.protocol !== "https:") return false;
53894
+ let path10 = parsed2.pathname;
53612
53895
  try {
53613
53896
  path10 = decodeURIComponent(path10);
53614
53897
  } catch {
@@ -56561,7 +56844,7 @@ function parsePathData(d) {
56561
56844
  let lastCubic = null;
56562
56845
  let lastQuad = null;
56563
56846
  let curved = false;
56564
- let command = "";
56847
+ let command2 = "";
56565
56848
  const result = (error2) => ({ subpaths, error: error2, curved });
56566
56849
  const lineTo = (to) => {
56567
56850
  current.segments.push({ kind: "L", to });
@@ -56569,9 +56852,9 @@ function parsePathData(d) {
56569
56852
  };
56570
56853
  while (!s.done()) {
56571
56854
  const next = s.peek();
56572
- if (/[a-zA-Z]/.test(next)) command = s.take();
56573
- else if (!command || command === "z" || command === "Z") return result(true);
56574
- const rel = command === command.toLowerCase();
56855
+ if (/[a-zA-Z]/.test(next)) command2 = s.take();
56856
+ else if (!command2 || command2 === "z" || command2 === "Z") return result(true);
56857
+ const rel = command2 === command2.toLowerCase();
56575
56858
  const base = rel ? pen : [0, 0];
56576
56859
  const num2 = () => s.number();
56577
56860
  const pt = () => {
@@ -56579,7 +56862,7 @@ function parsePathData(d) {
56579
56862
  const y = x === null ? null : num2();
56580
56863
  return x === null || y === null ? null : [x + base[0], y + base[1]];
56581
56864
  };
56582
- const upper = command.toUpperCase();
56865
+ const upper = command2.toUpperCase();
56583
56866
  if (!current && upper !== "M") return result(true);
56584
56867
  let cubicCtrl = null;
56585
56868
  let quadCtrl = null;
@@ -56591,7 +56874,7 @@ function parsePathData(d) {
56591
56874
  subpaths.push(current);
56592
56875
  pen = p;
56593
56876
  start = p;
56594
- command = rel ? "l" : "L";
56877
+ command2 = rel ? "l" : "L";
56595
56878
  break;
56596
56879
  }
56597
56880
  case "L": {
@@ -57865,22 +58148,22 @@ var Analyzer = class {
57865
58148
  case "path": {
57866
58149
  const d = attr(el, "d");
57867
58150
  if (d === void 0 || !d.trim()) return null;
57868
- const parsed = parsePathData(d);
57869
- const segs = parsed.subpaths.reduce((s, p) => s + p.segments.length, 0);
58151
+ const parsed2 = parsePathData(d);
58152
+ const segs = parsed2.subpaths.reduce((s, p) => s + p.segments.length, 0);
57870
58153
  this.pathSegments += segs;
57871
58154
  if (this.pathSegments > SVG_LIMITS.maxPathSegments)
57872
58155
  throw new SvgError(
57873
58156
  "svg_complexity_limit",
57874
58157
  `More than ${SVG_LIMITS.maxPathSegments} path segments`
57875
58158
  );
57876
- if (parsed.error)
58159
+ if (parsed2.error)
57877
58160
  this.issue(
57878
58161
  "path_data_error",
57879
58162
  "drop-content",
57880
58163
  ctx.location,
57881
58164
  "Path data has an error; the part after it is dropped"
57882
58165
  );
57883
- return { subpaths: parsed.subpaths, fillable: true };
58166
+ return { subpaths: parsed2.subpaths, fillable: true };
57884
58167
  }
57885
58168
  case "rect": {
57886
58169
  const x = len("x", pw) ?? 0;
@@ -59922,9 +60205,9 @@ async function transcribeTake(take, ctx) {
59922
60205
  text: ""
59923
60206
  };
59924
60207
  }
59925
- const parsed = helperTranscriptSchema.safeParse(raw);
59926
- if (!parsed.success) return failed("invalid_response", "Unexpected helper response.");
59927
- const { transcript, complete, stopReason, engine, durationSeconds } = parsed.data;
60208
+ const parsed2 = helperTranscriptSchema.safeParse(raw);
60209
+ if (!parsed2.success) return failed("invalid_response", "Unexpected helper response.");
60210
+ const { transcript, complete, stopReason, engine, durationSeconds } = parsed2.data;
59928
60211
  const text2 = transcript.trim();
59929
60212
  return {
59930
60213
  take: {
@@ -60298,18 +60581,18 @@ function callPrivateHelper(action, fields = {}, deps = defaultDeps2(), options =
60298
60581
  `The helper was terminated by ${result.signal} before it answered.`
60299
60582
  );
60300
60583
  const stdout = String(result.stdout ?? "").trim();
60301
- let parsed;
60584
+ let parsed2;
60302
60585
  try {
60303
- parsed = JSON.parse(stdout);
60586
+ parsed2 = JSON.parse(stdout);
60304
60587
  } catch {
60305
60588
  throw new PrivateHelperError(
60306
60589
  "invalid_response",
60307
60590
  `The helper exited with status ${result.status} and no JSON response.`
60308
60591
  );
60309
60592
  }
60310
- if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
60593
+ if (!parsed2 || typeof parsed2 !== "object" || Array.isArray(parsed2))
60311
60594
  throw new PrivateHelperError("invalid_response", "The helper response is not a JSON object");
60312
- const object3 = parsed;
60595
+ const object3 = parsed2;
60313
60596
  if (result.status !== 0 || object3.status === "error") {
60314
60597
  const error2 = errorSchema2.safeParse(object3);
60315
60598
  if (!error2.success)
@@ -60324,13 +60607,13 @@ function callPrivateHelper(action, fields = {}, deps = defaultDeps2(), options =
60324
60607
  return object3;
60325
60608
  }
60326
60609
  function parseOrThrow(schema, value) {
60327
- const parsed = schema.safeParse(value);
60328
- if (!parsed.success)
60610
+ const parsed2 = schema.safeParse(value);
60611
+ if (!parsed2.success)
60329
60612
  throw new PrivateHelperError(
60330
60613
  "invalid_response",
60331
- `Unexpected helper response: ${parsed.error.issues.map((i) => i.path.join(".") + " " + i.message).join("; ")}`
60614
+ `Unexpected helper response: ${parsed2.error.issues.map((i) => i.path.join(".") + " " + i.message).join("; ")}`
60332
60615
  );
60333
- return parsed.data;
60616
+ return parsed2.data;
60334
60617
  }
60335
60618
  var UUID2 = /^[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}$/i;
60336
60619
  function assertNoteIdentifier(identifier) {
@@ -61196,24 +61479,24 @@ function buildPermissionsWindow(checkOnly, deps = defaultPermissionsWindowDeps()
61196
61479
  timeout: 1e4,
61197
61480
  killSignal: "SIGKILL"
61198
61481
  });
61199
- let parsed = null;
61482
+ let parsed2 = null;
61200
61483
  try {
61201
- parsed = helloSchema2.parse(JSON.parse(String(hello.stdout ?? "").trim()));
61484
+ parsed2 = helloSchema2.parse(JSON.parse(String(hello.stdout ?? "").trim()));
61202
61485
  } catch {
61203
- parsed = null;
61486
+ parsed2 = null;
61204
61487
  }
61205
- if (!parsed || parsed.protocolVersion !== PERMISSIONS_WINDOW_PROTOCOL || parsed.sourceSha256 !== sourceSha) {
61488
+ if (!parsed2 || parsed2.protocolVersion !== PERMISSIONS_WINDOW_PROTOCOL || parsed2.sourceSha256 !== sourceSha) {
61206
61489
  steps.push({
61207
61490
  step: "handshake",
61208
61491
  ok: false,
61209
- detail: parsed ? `window reported protocol ${parsed.protocolVersion}, source ${parsed.sourceSha256}` : `no valid hello (exit ${hello.status})`
61492
+ detail: parsed2 ? `window reported protocol ${parsed2.protocolVersion}, source ${parsed2.sourceSha256}` : `no valid hello (exit ${hello.status})`
61210
61493
  });
61211
61494
  return finish();
61212
61495
  }
61213
61496
  steps.push({ step: "handshake", ok: true });
61214
61497
  const manifest = {
61215
61498
  schemaVersion: 1,
61216
- protocolVersion: parsed.protocolVersion,
61499
+ protocolVersion: parsed2.protocolVersion,
61217
61500
  sourceSha256: sourceSha,
61218
61501
  binarySha256: sha256Hex(deps.readFile(stagedBinary)),
61219
61502
  builtAt: deps.now().toISOString(),
@@ -62084,15 +62367,15 @@ async function readEditorJson(req) {
62084
62367
  throw new EditorHttpError(413, "too-large", "Request body too large.");
62085
62368
  chunks.push(chunk);
62086
62369
  }
62087
- let parsed;
62370
+ let parsed2;
62088
62371
  try {
62089
- parsed = JSON.parse(Buffer.concat(chunks).toString("utf8"));
62372
+ parsed2 = JSON.parse(Buffer.concat(chunks).toString("utf8"));
62090
62373
  } catch {
62091
62374
  throw new EditorHttpError(400, "bad-request", "Request body is not valid JSON.");
62092
62375
  }
62093
- if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
62376
+ if (!parsed2 || typeof parsed2 !== "object" || Array.isArray(parsed2))
62094
62377
  throw new EditorHttpError(400, "bad-request", "Request body must be a JSON object.");
62095
- return parsed;
62378
+ return parsed2;
62096
62379
  }
62097
62380
  var editorStringField = (body, key) => {
62098
62381
  const value = body[key];
@@ -62319,8 +62602,8 @@ Every request needs the per-run token in the printed URL. Press Ctrl-C to stop.
62319
62602
  `;
62320
62603
  function parseTemplatesArgs(argv) {
62321
62604
  if (argv.length === 0 || argv.includes("--help") || argv.includes("-h")) return "help";
62322
- const [command, ...rest] = argv;
62323
- if (command !== "edit") throw new Error(`Unknown templates command "${command}".`);
62605
+ const [command2, ...rest] = argv;
62606
+ if (command2 !== "edit") throw new Error(`Unknown templates command "${command2}".`);
62324
62607
  const args = {
62325
62608
  idleMinutes: DEFAULT_EDITOR_IDLE_MS / 6e4,
62326
62609
  tailnet: false
@@ -62947,17 +63230,17 @@ var AnchorRegistry = class _AnchorRegistry {
62947
63230
  closeSync9(fd);
62948
63231
  }
62949
63232
  if (text2.trim() === "") return [];
62950
- let parsed;
63233
+ let parsed2;
62951
63234
  try {
62952
- parsed = JSON.parse(text2);
63235
+ parsed2 = JSON.parse(text2);
62953
63236
  } catch {
62954
63237
  throw new AnchorRegistryError(
62955
63238
  "corrupt-registry",
62956
63239
  `${this.path} is not valid JSON; it was left unchanged. Move it aside to start a new registry.`
62957
63240
  );
62958
63241
  }
62959
- const anchors = parsed?.anchors;
62960
- if (parsed?.version !== 1 || !Array.isArray(anchors) || !anchors.every(isAnchor))
63242
+ const anchors = parsed2?.anchors;
63243
+ if (parsed2?.version !== 1 || !Array.isArray(anchors) || !anchors.every(isAnchor))
62961
63244
  throw new AnchorRegistryError(
62962
63245
  "corrupt-registry",
62963
63246
  `${this.path} is not a version 1 anchor registry; it was left unchanged.`
@@ -63183,25 +63466,23 @@ function registryLookup(registry2 = new AnchorRegistry(), dbPath2) {
63183
63466
 
63184
63467
  // src/index.ts
63185
63468
  loadFileConfig();
63186
- var require2 = createRequire(import.meta.url);
63187
- var { version: version2 } = require2("../package.json");
63188
- if (process.argv[2] === "setup" && process.argv.slice(3).includes("--public-helper")) {
63189
- const report = buildPublicHelper(process.argv.slice(3).includes("--check"));
63469
+ if (command.kind === "setup" && command.target === "public-helper") {
63470
+ const report = buildPublicHelper(command.checkOnly);
63190
63471
  process.stdout.write(formatPublicHelperBuild(report) + "\n");
63191
63472
  process.exit(report.ok ? 0 : 1);
63192
63473
  }
63193
- if (process.argv[2] === "setup" && process.argv.slice(3).includes("--native-helper")) {
63194
- const report = buildPrivateHelper(process.argv.slice(3).includes("--check"));
63474
+ if (command.kind === "setup" && command.target === "native-helper") {
63475
+ const report = buildPrivateHelper(command.checkOnly);
63195
63476
  process.stdout.write(formatHelperBuild(report) + "\n");
63196
63477
  process.exit(report.ok ? 0 : 1);
63197
63478
  }
63198
- if (process.argv[2] === "setup" && process.argv.slice(3).includes("--permissions-window")) {
63199
- const report = buildPermissionsWindow(process.argv.slice(3).includes("--check"));
63479
+ if (command.kind === "setup" && command.target === "permissions-window") {
63480
+ const report = buildPermissionsWindow(command.checkOnly);
63200
63481
  process.stdout.write(formatPermissionsWindowBuild(report) + "\n");
63201
63482
  process.exit(report.ok ? 0 : 1);
63202
63483
  }
63203
- if (process.argv[2] === "setup" && process.argv.slice(3).includes("--permissions")) {
63204
- const args = process.argv.slice(3);
63484
+ if (command.kind === "setup" && command.target === "permissions") {
63485
+ const args = command.args;
63205
63486
  const options = parsePermissionsArgs(args);
63206
63487
  const cli = defaultPermissionsCliDeps(options);
63207
63488
  let code;
@@ -63221,22 +63502,22 @@ if (process.argv[2] === "setup" && process.argv.slice(3).includes("--permissions
63221
63502
  cli.close();
63222
63503
  process.exit(code);
63223
63504
  }
63224
- if (process.argv[2] === "setup" && process.argv.slice(3).includes("--broker")) {
63225
- const report = await setupBroker(parseBrokerArgs(process.argv.slice(3)));
63505
+ if (command.kind === "setup" && command.target === "broker") {
63506
+ const report = await setupBroker(parseBrokerArgs(command.args));
63226
63507
  process.stdout.write(formatBrokerSetup(report) + "\n");
63227
63508
  process.exit(report.ok ? 0 : 1);
63228
63509
  }
63229
- if (process.argv[2] === "setup") {
63230
- const report = setupShortcuts(process.argv.slice(3).includes("--check"));
63510
+ if (command.kind === "setup") {
63511
+ const report = setupShortcuts(command.checkOnly);
63231
63512
  process.stdout.write(formatShortcutSetup(report) + "\n");
63232
63513
  process.exit(report.ready || !report.checkOnly ? 0 : 1);
63233
63514
  }
63234
- if (process.argv[2] === "templates") {
63235
- process.exit(await runTemplatesCommand(process.argv.slice(3)));
63515
+ if (command.kind === "templates") {
63516
+ process.exit(await runTemplatesCommand(command.args));
63236
63517
  }
63237
- if (process.argv[2] === "anchors") {
63518
+ if (command.kind === "anchors") {
63238
63519
  process.exit(
63239
- await runAnchorsCli(process.argv.slice(3), { resolve: registryLookup(new AnchorRegistry()) })
63520
+ await runAnchorsCli(command.args, { resolve: registryLookup(new AnchorRegistry()) })
63240
63521
  );
63241
63522
  }
63242
63523
  if (await startBrokerProxy()) {
@@ -63245,7 +63526,7 @@ if (await startBrokerProxy()) {
63245
63526
  }
63246
63527
  var server = new McpServer({
63247
63528
  name: "apple-notes",
63248
- version: version2,
63529
+ version,
63249
63530
  description: "MCP server for managing Apple Notes - create, search, update, and organize notes"
63250
63531
  });
63251
63532
  installSdkErrorCodes(server);
@@ -63886,9 +64167,10 @@ registerTool(
63886
64167
  },
63887
64168
  withErrorHandling(({ id: id2, title, account }) => {
63888
64169
  if (id2) {
63889
- const note2 = notesManager.getNoteById(id2);
64170
+ const { note: note2, error: metadataError } = notesManager.readNoteById(id2);
63890
64171
  if (!note2) {
63891
- return notFoundResponse(`Note with ID "${id2}" not found`);
64172
+ const message = `Failed to read metadata of note with ID "${id2}": ${metadataError}`;
64173
+ return metadataError === NOTE_ID_NOT_FOUND_MESSAGE ? notFoundResponse(message) : errorResponse(message);
63892
64174
  }
63893
64175
  if (note2.passwordProtected) {
63894
64176
  return errorResponse(
@@ -65665,6 +65947,7 @@ registerTool(
65665
65947
  checks: external_exports.array(external_exports.object({}).passthrough()).optional(),
65666
65948
  runtimeOS: external_exports.object({}).passthrough().optional(),
65667
65949
  features: external_exports.record(external_exports.string(), external_exports.object({}).passthrough()).optional(),
65950
+ publicHelper: external_exports.object({}).passthrough().optional(),
65668
65951
  broker: external_exports.object({}).passthrough().optional()
65669
65952
  }
65670
65953
  },