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/README.md +256 -253
- package/build/index.js +983 -700
- package/docs/FULL-DISK-ACCESS.md +95 -117
- package/package.json +1 -1
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(
|
|
4014
|
-
if (matches[2] !== void 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
|
|
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(
|
|
4041
|
-
if (!options.unicodeSupport && (!schemeHandler || !schemeHandler.unicodeSupport) &&
|
|
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
|
-
|
|
4043
|
+
parsed2.host = new URL("http://" + parsed2.host).hostname;
|
|
4044
4044
|
} catch (e) {
|
|
4045
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
4098
|
-
|
|
4099
|
-
|
|
4100
|
-
|
|
4101
|
-
|
|
4102
|
-
|
|
4103
|
-
|
|
4104
|
-
if (
|
|
4105
|
-
const decodedScheme = unescape(
|
|
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
|
-
|
|
4107
|
+
parsed2.scheme = decodedScheme.toLowerCase();
|
|
4108
4108
|
} else {
|
|
4109
|
-
|
|
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
|
-
|
|
4115
|
+
parsed2.error = parsed2.error || "URI contains malformed percent-encoding.";
|
|
4116
4116
|
}
|
|
4117
|
-
if (isNaN(
|
|
4118
|
-
|
|
4117
|
+
if (isNaN(parsed2.port)) {
|
|
4118
|
+
parsed2.port = matches[5];
|
|
4119
4119
|
}
|
|
4120
|
-
const parseError = getParseError(
|
|
4120
|
+
const parseError = getParseError(parsed2, matches);
|
|
4121
4121
|
if (parseError !== void 0) {
|
|
4122
|
-
|
|
4122
|
+
parsed2.error = parsed2.error || parseError;
|
|
4123
4123
|
malformedAuthorityOrPort = true;
|
|
4124
4124
|
}
|
|
4125
|
-
if (
|
|
4126
|
-
const ipv4result = isIPv4(
|
|
4125
|
+
if (parsed2.host) {
|
|
4126
|
+
const ipv4result = isIPv4(parsed2.host);
|
|
4127
4127
|
if (ipv4result === false) {
|
|
4128
|
-
const bracketedIPLiteral = isIPLiteral(
|
|
4129
|
-
const hasIPLiteralBracket =
|
|
4130
|
-
const ipv6result = normalizeIPv6(
|
|
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
|
-
|
|
4133
|
+
parsed2.host = isIP ? ipv6result.host : ipv6result.host.toLowerCase();
|
|
4134
4134
|
if (malformedIPLiteral) {
|
|
4135
|
-
|
|
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 (
|
|
4143
|
-
|
|
4144
|
-
} else if (
|
|
4145
|
-
|
|
4146
|
-
} else if (
|
|
4147
|
-
|
|
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
|
-
|
|
4149
|
+
parsed2.reference = "uri";
|
|
4150
4150
|
}
|
|
4151
|
-
if (options.reference && options.reference !== "suffix" && options.reference !==
|
|
4152
|
-
|
|
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 ||
|
|
4154
|
+
const schemeHandler = getSchemeHandler(options.scheme || parsed2.scheme);
|
|
4155
4155
|
if (!malformedIPLiteral) {
|
|
4156
|
-
malformedHost = canonicalizeHost(
|
|
4156
|
+
malformedHost = canonicalizeHost(parsed2, options, schemeHandler, isIP);
|
|
4157
4157
|
}
|
|
4158
|
-
if (uri.indexOf("%") !== -1 &&
|
|
4159
|
-
let host = isIP ?
|
|
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
|
-
|
|
4163
|
+
parsed2.host = reescapeHostDelimiters(host, isIP);
|
|
4164
4164
|
}
|
|
4165
4165
|
if (!schemeHandler || schemeHandler && !schemeHandler.skipNormalize) {
|
|
4166
|
-
if (
|
|
4167
|
-
|
|
4166
|
+
if (parsed2.path) {
|
|
4167
|
+
parsed2.path = normalizePathEncoding(parsed2.path);
|
|
4168
4168
|
}
|
|
4169
|
-
if (
|
|
4170
|
-
|
|
4169
|
+
if (parsed2.query) {
|
|
4170
|
+
parsed2.query = normalizeQueryFragmentEncoding(parsed2.query);
|
|
4171
4171
|
}
|
|
4172
|
-
if (
|
|
4173
|
-
|
|
4172
|
+
if (parsed2.fragment) {
|
|
4173
|
+
parsed2.fragment = normalizeQueryFragmentEncoding(parsed2.fragment);
|
|
4174
4174
|
}
|
|
4175
4175
|
}
|
|
4176
4176
|
if (schemeHandler && schemeHandler.parse) {
|
|
4177
|
-
schemeHandler.parse(
|
|
4178
|
-
if (schemeHandler === SCHEMES.urn &&
|
|
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
|
-
|
|
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(
|
|
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/
|
|
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
|
|
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 =
|
|
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
|
|
36877
|
-
return Promise.resolve(handler(
|
|
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
|
|
36903
|
-
return Promise.resolve(handler(
|
|
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:
|
|
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
|
|
39731
|
-
const rows = typeof
|
|
39732
|
-
return { store:
|
|
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
|
|
41558
|
+
let parsed2;
|
|
41436
41559
|
try {
|
|
41437
|
-
|
|
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(
|
|
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,
|
|
41447
|
-
query:
|
|
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
|
|
43091
|
-
return isNaN(
|
|
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,
|
|
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
|
-
${
|
|
43410
|
+
${command2}
|
|
43288
43411
|
end tell
|
|
43289
43412
|
end tell
|
|
43290
43413
|
`;
|
|
43291
43414
|
}
|
|
43292
|
-
function buildAppLevelScript(
|
|
43415
|
+
function buildAppLevelScript(command2) {
|
|
43293
43416
|
return `
|
|
43294
43417
|
tell application "Notes"
|
|
43295
|
-
${
|
|
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
|
|
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
|
|
43942
|
+
return {
|
|
43943
|
+
note: null,
|
|
43944
|
+
error: result.error?.trim() ? result.error : "AppleScript note metadata read failed"
|
|
43945
|
+
};
|
|
43809
43946
|
}
|
|
43810
|
-
const
|
|
43811
|
-
if (!
|
|
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
|
-
|
|
43816
|
-
|
|
43817
|
-
|
|
43818
|
-
|
|
43819
|
-
|
|
43820
|
-
|
|
43821
|
-
|
|
43822
|
-
|
|
43823
|
-
|
|
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
|
|
43870
|
-
if (!
|
|
44008
|
+
const parsed2 = parseNotePropertiesOutput(result.output);
|
|
44009
|
+
if (!parsed2) {
|
|
43871
44010
|
return null;
|
|
43872
44011
|
}
|
|
43873
44012
|
return {
|
|
43874
|
-
id:
|
|
43875
|
-
title:
|
|
44013
|
+
id: parsed2.id,
|
|
44014
|
+
title: parsed2.title,
|
|
43876
44015
|
content: "",
|
|
43877
44016
|
// Not fetched
|
|
43878
44017
|
tags: [],
|
|
43879
|
-
created:
|
|
43880
|
-
modified:
|
|
43881
|
-
shared:
|
|
43882
|
-
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
|
|
44431
|
+
const parsed2 = this.parseBulkListRecords(records2, safeLimit, {
|
|
44293
44432
|
ids: trashIds2,
|
|
44294
44433
|
include: includeRecentlyDeleted
|
|
44295
44434
|
});
|
|
44296
|
-
if (!Number.isNaN(totalCount) && (
|
|
44297
|
-
return
|
|
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
|
|
44502
|
-
if (!Number.isInteger(
|
|
44503
|
-
return
|
|
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
|
|
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(
|
|
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
|
|
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(
|
|
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: "
|
|
49477
|
-
description: "Read
|
|
49478
|
-
tools: ["get-audio-transcripts"
|
|
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:
|
|
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 (
|
|
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
|
-
|
|
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 =
|
|
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
|
|
49734
|
-
import { join as
|
|
49735
|
-
import { homedir as
|
|
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
|
|
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 (!
|
|
49746
|
-
const
|
|
49747
|
-
if (!
|
|
49748
|
-
for (const [k, v] of Object.entries(
|
|
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
|
|
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,
|
|
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
|
|
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 =
|
|
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
|
|
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
|
|
50941
|
-
import { basename as basename3, extname as extname3, join as
|
|
50942
|
-
var NOTES_CONTAINER =
|
|
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(
|
|
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(
|
|
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 ? [
|
|
51077
|
-
|
|
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 =
|
|
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 ?
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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 ?
|
|
51945
|
+
return rest ? join21(real, rest) : real;
|
|
51201
51946
|
} catch {
|
|
51202
|
-
const parent =
|
|
51947
|
+
const parent = resolve4(current, "..");
|
|
51203
51948
|
if (parent === current) return abs;
|
|
51204
|
-
rest = rest ?
|
|
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 = [
|
|
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
|
-
|
|
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 =
|
|
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
|
|
52504
|
-
if (!
|
|
52786
|
+
const parsed2 = decodedDrawingSchema.safeParse(raw);
|
|
52787
|
+
if (!parsed2.success)
|
|
52505
52788
|
return { ...base, code: "invalid_response", message: "Unexpected helper response." };
|
|
52506
|
-
decoded =
|
|
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
|
|
53312
|
+
let parsed2;
|
|
53030
53313
|
try {
|
|
53031
|
-
|
|
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(
|
|
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(
|
|
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
|
|
53815
|
+
let parsed2;
|
|
53533
53816
|
try {
|
|
53534
|
-
|
|
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(
|
|
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
|
|
53564
|
-
const raw =
|
|
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 (
|
|
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
|
|
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
|
|
53610
|
-
if (
|
|
53611
|
-
let path10 =
|
|
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
|
|
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))
|
|
56573
|
-
else if (!
|
|
56574
|
-
const rel =
|
|
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 =
|
|
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
|
-
|
|
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
|
|
57869
|
-
const segs =
|
|
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 (
|
|
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:
|
|
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
|
|
59926
|
-
if (!
|
|
59927
|
-
const { transcript, complete, stopReason, engine, durationSeconds } =
|
|
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
|
|
60584
|
+
let parsed2;
|
|
60302
60585
|
try {
|
|
60303
|
-
|
|
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 (!
|
|
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 =
|
|
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
|
|
60328
|
-
if (!
|
|
60610
|
+
const parsed2 = schema.safeParse(value);
|
|
60611
|
+
if (!parsed2.success)
|
|
60329
60612
|
throw new PrivateHelperError(
|
|
60330
60613
|
"invalid_response",
|
|
60331
|
-
`Unexpected helper response: ${
|
|
60614
|
+
`Unexpected helper response: ${parsed2.error.issues.map((i) => i.path.join(".") + " " + i.message).join("; ")}`
|
|
60332
60615
|
);
|
|
60333
|
-
return
|
|
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
|
|
61482
|
+
let parsed2 = null;
|
|
61200
61483
|
try {
|
|
61201
|
-
|
|
61484
|
+
parsed2 = helloSchema2.parse(JSON.parse(String(hello.stdout ?? "").trim()));
|
|
61202
61485
|
} catch {
|
|
61203
|
-
|
|
61486
|
+
parsed2 = null;
|
|
61204
61487
|
}
|
|
61205
|
-
if (!
|
|
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:
|
|
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:
|
|
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
|
|
62370
|
+
let parsed2;
|
|
62088
62371
|
try {
|
|
62089
|
-
|
|
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 (!
|
|
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
|
|
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 [
|
|
62323
|
-
if (
|
|
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
|
|
63233
|
+
let parsed2;
|
|
62951
63234
|
try {
|
|
62952
|
-
|
|
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 =
|
|
62960
|
-
if (
|
|
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
|
-
|
|
63187
|
-
|
|
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 (
|
|
63194
|
-
const report = buildPrivateHelper(
|
|
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 (
|
|
63199
|
-
const report = buildPermissionsWindow(
|
|
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 (
|
|
63204
|
-
const args =
|
|
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 (
|
|
63225
|
-
const report = await setupBroker(parseBrokerArgs(
|
|
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 (
|
|
63230
|
-
const report = setupShortcuts(
|
|
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 (
|
|
63235
|
-
process.exit(await runTemplatesCommand(
|
|
63515
|
+
if (command.kind === "templates") {
|
|
63516
|
+
process.exit(await runTemplatesCommand(command.args));
|
|
63236
63517
|
}
|
|
63237
|
-
if (
|
|
63518
|
+
if (command.kind === "anchors") {
|
|
63238
63519
|
process.exit(
|
|
63239
|
-
await runAnchorsCli(
|
|
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
|
|
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.
|
|
64170
|
+
const { note: note2, error: metadataError } = notesManager.readNoteById(id2);
|
|
63890
64171
|
if (!note2) {
|
|
63891
|
-
|
|
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
|
},
|