@mgcrea/mcp-apple-calendar 1.16.0 → 1.18.0
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/dist/cli.js +1 -1
- package/dist/index.d.ts +11 -18
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/{server-BgyYeCba.js → server-CLAGQcwG.js} +49 -163
- package/dist/server-CLAGQcwG.js.map +1 -0
- package/package.json +2 -2
- package/dist/server-BgyYeCba.js.map +0 -1
package/dist/cli.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { A as BUILD_INFO, C as CALENDAR_SURFACE, a as loadConfig, r as createServer } from "./server-
|
|
2
|
+
import { A as BUILD_INFO, C as CALENDAR_SURFACE, a as loadConfig, r as createServer } from "./server-CLAGQcwG.js";
|
|
3
3
|
import { runStdioServer } from "@mgcrea/mcp-apple-core";
|
|
4
4
|
//#region src/cli.ts
|
|
5
5
|
const LOG_PREFIX = "apple-calendar-mcp";
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AppBusyError as CalendarBusyError, AppNotRunningError as CalendarNotRunningError, AppleAutomationError, AppleAutomationError as AppleCalendarError, BuildInfo, Logger, OsascriptRunner, ReadOnlyMode, StoreFacts, SurfaceContext } from "@mgcrea/mcp-apple-core";
|
|
1
|
+
import { AppBusyError as CalendarBusyError, AppNotRunningError as CalendarNotRunningError, AppleAutomationError, AppleAutomationError as AppleCalendarError, BuildInfo, InvalidDateError, Logger, OsascriptRunner, ReadOnlyMode, StoreFacts, SurfaceContext } from "@mgcrea/mcp-apple-core";
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
4
4
|
import { DatabaseSync } from "node:sqlite";
|
|
@@ -221,13 +221,6 @@ declare const WEEKDAY_KEYS: readonly ["sun", "mon", "tue", "wed", "thu", "fri",
|
|
|
221
221
|
type WeekdayKey = (typeof WEEKDAY_KEYS)[number];
|
|
222
222
|
//#endregion
|
|
223
223
|
//#region src/client/dates.d.ts
|
|
224
|
-
/**
|
|
225
|
-
* What a tool reports for an event's start or end.
|
|
226
|
-
*
|
|
227
|
-
* A union rather than one struct with an `allDay` flag: an all-day event names
|
|
228
|
-
* a DAY and has no instant, and giving it an `iso` field would invite callers to
|
|
229
|
-
* read one. The type makes that impossible instead of merely discouraged.
|
|
230
|
-
*/
|
|
231
224
|
type EventInstant = {
|
|
232
225
|
allDay: true;
|
|
233
226
|
day: string;
|
|
@@ -362,6 +355,16 @@ type EventDetail = EventSummary & {
|
|
|
362
355
|
};
|
|
363
356
|
type EventPage = {
|
|
364
357
|
events: EventSummary[];
|
|
358
|
+
/**
|
|
359
|
+
* More events matched the window than fit under `limit`.
|
|
360
|
+
*
|
|
361
|
+
* Distinct from `truncated`, which is about the store's expansion COVERAGE
|
|
362
|
+
* running out. Both mean "this is not the whole picture" and they mean it for
|
|
363
|
+
* different reasons, so collapsing them would leave a caller unable to tell a
|
|
364
|
+
* dense day from an unexpanded one — and a short list of events is
|
|
365
|
+
* indistinguishable from a free afternoon.
|
|
366
|
+
*/
|
|
367
|
+
hasMore: boolean;
|
|
365
368
|
expansion: ExpansionState;
|
|
366
369
|
expansionReason?: string;
|
|
367
370
|
/** The window actually queried, echoed so a clamp is visible. */
|
|
@@ -617,16 +620,6 @@ declare class AppleCalendarClient {
|
|
|
617
620
|
declare const CALENDAR_SURFACE: SurfaceContext;
|
|
618
621
|
/** Calendar's Apple Events target. Not `com.apple.Calendar`, which does not exist. */
|
|
619
622
|
declare const CALENDAR_BUNDLE_ID = "com.apple.iCal";
|
|
620
|
-
/**
|
|
621
|
-
* A date argument could not be understood.
|
|
622
|
-
*
|
|
623
|
-
* Carries the accepted grammar rather than just rejecting, because the caller is
|
|
624
|
-
* usually a model that will retry once and needs to know what shape to retry in.
|
|
625
|
-
*/
|
|
626
|
-
declare class InvalidDateError extends AppleAutomationError {
|
|
627
|
-
readonly name = "InvalidDateError";
|
|
628
|
-
constructor(field: string, raw: string, reason: string);
|
|
629
|
-
}
|
|
630
623
|
/** A CalendarRef no longer resolves — deleted, or moved to another calendar. */
|
|
631
624
|
declare class EventNotFoundError extends AppleAutomationError {
|
|
632
625
|
readonly name = "EventNotFoundError";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/build-info.ts","../src/client/store.ts","../src/config.ts","../src/client/availability.ts","../src/client/dates.ts","../src/client/locate.ts","../src/client/recurrence.ts","../src/client/calendar.ts","../src/client/errors.ts","../src/client/ref.ts","../src/server.ts","../src/tools/index.ts"],"mappings":";;;;;cAkBa,YAAY;;;KCiDb;EACV;;EAEA,aAAa;EACb,iBAAiB;EACjB,mBAAmB;EACnB,mBAAmB;EACnB,cAAc;;;;;;;;;EASd;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;KAIU;EACV;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;EAEA;EACA;;EAEA;;KAGU;;EAEV;;EAEA;;EAEA;EACA;;KAGU,cAAc;EACxB;EACA;;;KAIU;EAAa;EAAmB;EAAiB;;KAEjD;EACV;EACA;EACA;EACA;EACA;EACA;EACA;;;;;;;;;;;EAWA;EACA;;KAGU;EAAiB;EAAqB;EAAqB;;cAM1D;;WACF,IAAI;WACJ;WACA,MAAM;EAEf,YAAY,IAAI,cAAc,cAAc,MAAM;;;;;;;;;;;;EAyHlD,WAAW,GAAG,aAAa;;;;;;;;;EAuC3B,iBAAiB,GAAG,aAAa;;;;;;;;;EAgCjC,YAAY,GAAG,cAAc;;EAgC7B,OAAO,eAAe;;;;;;;;;EAuBtB,YAAY;EAgBZ,aAAa;EAgCb,YAAY;EAkBZ;;cASW,aAAU,IAAQ,iBAAe;cAuCjC,YAAS,qBACD,MACb,cAAY,SACT,WACR;;;;;;;;;;;;;;;;cCtfG,cAAY,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiEP,EAAA,KAAA;KAEC,SAAS,EAAE,aAAa;;;;;cAMvB,aAAU,MAAS,OAAO,eAA2B;;;cCvErD;KACD,qBAAqB
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/build-info.ts","../src/client/store.ts","../src/config.ts","../src/client/availability.ts","../src/client/dates.ts","../src/client/locate.ts","../src/client/recurrence.ts","../src/client/calendar.ts","../src/client/errors.ts","../src/client/ref.ts","../src/server.ts","../src/tools/index.ts"],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { A as BUILD_INFO, C as CALENDAR_SURFACE, D as CalendarNotWritableError, E as CalendarNotRunningError, O as EventNotFoundError, S as CALENDAR_BUNDLE_ID, T as CalendarNotFoundError, _ as STORE_FILENAME, a as loadConfig, b as locateStore, c as introspect, d as decodeRef, f as encodeRef, g as GROUP_CONTAINER, h as EXTRAS_FILENAME, i as registerTools, k as InvalidDateError, l as openStore, m as uuidOf, n as SERVER_VERSION, o as AppleCalendarClient, p as seriesRefOf, r as createServer, s as CalendarStore, t as SERVER_NAME, u as REF_VERSION, v as defaultContainerPath, w as CalendarBusyError, x as AppleCalendarError, y as defaultStorePath } from "./server-
|
|
1
|
+
import { A as BUILD_INFO, C as CALENDAR_SURFACE, D as CalendarNotWritableError, E as CalendarNotRunningError, O as EventNotFoundError, S as CALENDAR_BUNDLE_ID, T as CalendarNotFoundError, _ as STORE_FILENAME, a as loadConfig, b as locateStore, c as introspect, d as decodeRef, f as encodeRef, g as GROUP_CONTAINER, h as EXTRAS_FILENAME, i as registerTools, k as InvalidDateError, l as openStore, m as uuidOf, n as SERVER_VERSION, o as AppleCalendarClient, p as seriesRefOf, r as createServer, s as CalendarStore, t as SERVER_NAME, u as REF_VERSION, v as defaultContainerPath, w as CalendarBusyError, x as AppleCalendarError, y as defaultStorePath } from "./server-CLAGQcwG.js";
|
|
2
2
|
export { AppleCalendarClient, AppleCalendarError, BUILD_INFO, CALENDAR_BUNDLE_ID, CALENDAR_SURFACE, CalendarBusyError, CalendarNotFoundError, CalendarNotRunningError, CalendarNotWritableError, CalendarStore, EXTRAS_FILENAME, EventNotFoundError, GROUP_CONTAINER, InvalidDateError, REF_VERSION, SERVER_NAME, SERVER_VERSION, STORE_FILENAME, createServer, decodeRef, defaultContainerPath, defaultStorePath, encodeRef, introspect, loadConfig, locateStore, openStore, registerTools, seriesRefOf, uuidOf };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AppBusyError as CalendarBusyError, AppNotRunningError as CalendarNotRunningError, AppleAutomationError, AppleAutomationError as AppleCalendarError, BaseConfigSchema, CORE_DATA_EPOCH_OFFSET, IndexUnavailableError, PreconditionError, SchemaDriftError, columnsOf, confirmArg, createOsascriptRunner, describeStore, escapeLike, fingerprintSchema, limitArg, ok, openReadOnly, parseBool, parseConfig, parseIntOpt, parseList, promptArg, readPackageIdentity, registerSurfaceResources, registerWorkflowPrompt, requiredPromptArg, resolveLimit, trimmed, withBusyRetry, withLazyTools, wrap } from "@mgcrea/mcp-apple-core";
|
|
1
|
+
import { AppBusyError as CalendarBusyError, AppNotRunningError as CalendarNotRunningError, AppleAutomationError, AppleAutomationError as AppleCalendarError, BaseConfigSchema, CORE_DATA_EPOCH_OFFSET, IndexUnavailableError, InvalidDateError, PreconditionError, SchemaDriftError, addLocalDays, columnsOf, confirmArg, createOsascriptRunner, describeStore, escapeLike, fingerprintSchema, limitArg, ok, openReadOnly, parseBool, parseBound, parseBound as parseBound$1, parseConfig, parseDate, parseIntOpt, parseList, promptArg, readPackageIdentity, registerSurfaceResources, registerWorkflowPrompt, requiredPromptArg, resolveLimit, startOfLocalDay, toLocalIso, toLocalIso as toLocalIso$1, trimmed, withBusyRetry, withLazyTools, wrap } from "@mgcrea/mcp-apple-core";
|
|
2
2
|
import { readdirSync } from "node:fs";
|
|
3
3
|
import { homedir } from "node:os";
|
|
4
4
|
import { join } from "node:path";
|
|
@@ -12,8 +12,8 @@ const pkg = readPackageIdentity(new URL("../package.json", import.meta.url), {
|
|
|
12
12
|
const BUILD_INFO = {
|
|
13
13
|
name: pkg.name,
|
|
14
14
|
version: pkg.version,
|
|
15
|
-
gitCommit: "
|
|
16
|
-
gitCommitDate: "2026-09-
|
|
15
|
+
gitCommit: "657cbf0",
|
|
16
|
+
gitCommitDate: "2026-09-07T21:40:45+02:00"
|
|
17
17
|
};
|
|
18
18
|
//#endregion
|
|
19
19
|
//#region src/client/errors.ts
|
|
@@ -35,21 +35,6 @@ const CALENDAR_SURFACE = {
|
|
|
35
35
|
};
|
|
36
36
|
/** Calendar's Apple Events target. Not `com.apple.Calendar`, which does not exist. */
|
|
37
37
|
const CALENDAR_BUNDLE_ID = "com.apple.iCal";
|
|
38
|
-
/**
|
|
39
|
-
* A date argument could not be understood.
|
|
40
|
-
*
|
|
41
|
-
* Carries the accepted grammar rather than just rejecting, because the caller is
|
|
42
|
-
* usually a model that will retry once and needs to know what shape to retry in.
|
|
43
|
-
*/
|
|
44
|
-
var InvalidDateError = class extends AppleAutomationError {
|
|
45
|
-
name = "InvalidDateError";
|
|
46
|
-
constructor(field, raw, reason) {
|
|
47
|
-
super(`Could not read ${field} from ${JSON.stringify(raw)}: ${reason}. Accepted: an ISO-8601 date "2026-08-20" (a whole day) or date-time "2026-08-20T09:00" (an instant), or a relative offset like "+2d", "+3h", "+45m", "+1w", "today", "tomorrow", "tomorrow 09:00", or "next monday".`, {
|
|
48
|
-
field,
|
|
49
|
-
raw
|
|
50
|
-
});
|
|
51
|
-
}
|
|
52
|
-
};
|
|
53
38
|
/** A CalendarRef no longer resolves — deleted, or moved to another calendar. */
|
|
54
39
|
var EventNotFoundError = class extends AppleAutomationError {
|
|
55
40
|
name = "EventNotFoundError";
|
|
@@ -143,9 +128,9 @@ const parseClock = (field, raw) => {
|
|
|
143
128
|
};
|
|
144
129
|
};
|
|
145
130
|
const weekdaySet = (keys) => new Set(keys.map((k) => WEEKDAY_KEYS.indexOf(k)).filter((i) => i !== -1));
|
|
146
|
-
const startOfLocalDay = (d) => new Date(d.getFullYear(), d.getMonth(), d.getDate(), 0, 0, 0, 0);
|
|
131
|
+
const startOfLocalDay$2 = (d) => new Date(d.getFullYear(), d.getMonth(), d.getDate(), 0, 0, 0, 0);
|
|
147
132
|
/** Same wall-clock time, n days later. Calendar arithmetic, so DST-safe. */
|
|
148
|
-
const addDays
|
|
133
|
+
const addDays = (d, n) => {
|
|
149
134
|
const out = new Date(d.getTime());
|
|
150
135
|
out.setDate(out.getDate() + n);
|
|
151
136
|
return out;
|
|
@@ -221,7 +206,7 @@ const subtractBusy = (window, busy) => {
|
|
|
221
206
|
const dayWindows = (opts) => {
|
|
222
207
|
const out = [];
|
|
223
208
|
const last = opts.to.getTime();
|
|
224
|
-
for (let day = startOfLocalDay(opts.from); day.getTime() <= last; day = addDays
|
|
209
|
+
for (let day = startOfLocalDay$2(opts.from); day.getTime() <= last; day = addDays(day, 1)) {
|
|
225
210
|
if (!opts.weekdays.has(day.getDay())) continue;
|
|
226
211
|
const open = atClock(day, opts.dayStart);
|
|
227
212
|
const close = atClock(day, opts.dayEnd);
|
|
@@ -251,9 +236,9 @@ const alignUp = (ms, granularityMinutes) => {
|
|
|
251
236
|
return topOfHour + Math.ceil(past / step) * step;
|
|
252
237
|
};
|
|
253
238
|
/** Local midnight at the start of the day an instant falls on. */
|
|
254
|
-
const startOfLocalDayMs = (ms) => startOfLocalDay(new Date(ms)).getTime();
|
|
239
|
+
const startOfLocalDayMs = (ms) => startOfLocalDay$2(new Date(ms)).getTime();
|
|
255
240
|
/** The following local midnight. Calendar arithmetic, so a DST day is 23h or 25h. */
|
|
256
|
-
const nextLocalDayMs = (ms) => addDays
|
|
241
|
+
const nextLocalDayMs = (ms) => addDays(startOfLocalDay$2(new Date(ms)), 1).getTime();
|
|
257
242
|
/** `2026-08-24`, in local components — the day a slot falls on. */
|
|
258
243
|
const localDay = (ms) => {
|
|
259
244
|
const d = new Date(ms);
|
|
@@ -291,124 +276,11 @@ const localDay = (ms) => {
|
|
|
291
276
|
* classified apart here. Anything matching `GMT±HHMM` is honoured as an offset;
|
|
292
277
|
* only what is left over floats.
|
|
293
278
|
*/
|
|
294
|
-
|
|
295
|
-
"sunday",
|
|
296
|
-
"monday",
|
|
297
|
-
"tuesday",
|
|
298
|
-
"wednesday",
|
|
299
|
-
"thursday",
|
|
300
|
-
"friday",
|
|
301
|
-
"saturday"
|
|
302
|
-
];
|
|
303
|
-
const ISO_DATE = /^(\d{4})-(\d{2})-(\d{2})$/;
|
|
304
|
-
const ISO_DATETIME = /^(\d{4})-(\d{2})-(\d{2})[T ](\d{2}):(\d{2})(?::(\d{2}))?(?:\.\d+)?(Z|[+-]\d{2}:?\d{2})?$/;
|
|
305
|
-
const OFFSET = /^\+(\d+)\s*(m|min|mins|minute|minutes|h|hr|hrs|hour|hours|d|day|days|w|week|weeks)$/;
|
|
306
|
-
const DAY_WORD = /^(today|tomorrow)(?:\s+(\d{1,2}):(\d{2}))?$/;
|
|
307
|
-
const NEXT_DAY = /^next\s+([a-z]+)(?:\s+(\d{1,2}):(\d{2}))?$/;
|
|
279
|
+
/** `90`, `"90"`, `"90m"`, `"2h"` — the duration half, which core has no view on. */
|
|
308
280
|
const DURATION = /^(\d+)\s*(m|min|mins|minute|minutes|h|hr|hrs|hour|hours)?$/;
|
|
309
|
-
/** `GMT+
|
|
281
|
+
/** `GMT+02:00` and friends, which Calendar stores alongside real IANA names. */
|
|
310
282
|
const FIXED_OFFSET = /^(?:GMT|UTC)([+-])(\d{2}):?(\d{2})$/i;
|
|
311
283
|
const pad$1 = (n, w = 2) => String(n).padStart(w, "0");
|
|
312
|
-
/** `+02:00` / `-05:00` / `Z` for a given instant, in the system zone. */
|
|
313
|
-
const offsetOf = (d) => {
|
|
314
|
-
const mins = -d.getTimezoneOffset();
|
|
315
|
-
if (mins === 0) return "Z";
|
|
316
|
-
const sign = mins < 0 ? "-" : "+";
|
|
317
|
-
const abs = Math.abs(mins);
|
|
318
|
-
return `${sign}${pad$1(Math.floor(abs / 60))}:${pad$1(abs % 60)}`;
|
|
319
|
-
};
|
|
320
|
-
/**
|
|
321
|
-
* Local wall-clock time rendered with its offset.
|
|
322
|
-
*
|
|
323
|
-
* Deliberately not `toISOString()`, which converts to UTC and would report a
|
|
324
|
-
* 09:00 meeting as `07:00Z` — correct as an instant, unreadable in a result
|
|
325
|
-
* whose purpose is confirming what the caller asked for.
|
|
326
|
-
*/
|
|
327
|
-
const toLocalIso = (d) => `${d.getFullYear()}-${pad$1(d.getMonth() + 1)}-${pad$1(d.getDate())}T${pad$1(d.getHours())}:${pad$1(d.getMinutes())}:${pad$1(d.getSeconds())}${offsetOf(d)}`;
|
|
328
|
-
const startOfDay = (d) => new Date(d.getFullYear(), d.getMonth(), d.getDate(), 0, 0, 0, 0);
|
|
329
|
-
const endOfDay = (d) => new Date(d.getFullYear(), d.getMonth(), d.getDate(), 23, 59, 59, 999);
|
|
330
|
-
/** Calendar-aware day arithmetic: same wall-clock time, n days later. */
|
|
331
|
-
const addDays = (d, n) => {
|
|
332
|
-
const out = new Date(d.getTime());
|
|
333
|
-
out.setDate(out.getDate() + n);
|
|
334
|
-
return out;
|
|
335
|
-
};
|
|
336
|
-
const at = (day, hours, minutes) => new Date(day.getFullYear(), day.getMonth(), day.getDate(), hours, minutes, 0, 0);
|
|
337
|
-
const result = (kind, when, raw) => ({
|
|
338
|
-
kind,
|
|
339
|
-
at: when,
|
|
340
|
-
iso: toLocalIso(when),
|
|
341
|
-
raw
|
|
342
|
-
});
|
|
343
|
-
/**
|
|
344
|
-
* Parse one date argument.
|
|
345
|
-
*
|
|
346
|
-
* @param field Named in the error, so a failure says WHICH argument was bad.
|
|
347
|
-
* @param raw The caller's string.
|
|
348
|
-
* @param now Injected for hermetic tests.
|
|
349
|
-
*/
|
|
350
|
-
const parseDate = (field, raw, now = /* @__PURE__ */ new Date()) => {
|
|
351
|
-
const text = String(raw ?? "").trim();
|
|
352
|
-
if (!text) throw new InvalidDateError(field, String(raw), "it is empty");
|
|
353
|
-
const lower = text.toLowerCase();
|
|
354
|
-
const dt = ISO_DATETIME.exec(text);
|
|
355
|
-
if (dt) {
|
|
356
|
-
const [, y, mo, d, hh, mm, ss, zone] = dt;
|
|
357
|
-
const when = zone ? new Date(text.replace(" ", "T")) : new Date(Number(y), Number(mo) - 1, Number(d), Number(hh), Number(mm), Number(ss ?? "0"), 0);
|
|
358
|
-
if (Number.isNaN(when.getTime())) throw new InvalidDateError(field, text, "it is not a real date");
|
|
359
|
-
return result("timed", when, text);
|
|
360
|
-
}
|
|
361
|
-
const only = ISO_DATE.exec(text);
|
|
362
|
-
if (only) {
|
|
363
|
-
const [, y, mo, d] = only;
|
|
364
|
-
const when = new Date(Number(y), Number(mo) - 1, Number(d), 0, 0, 0, 0);
|
|
365
|
-
if (Number.isNaN(when.getTime())) throw new InvalidDateError(field, text, "it is not a real date");
|
|
366
|
-
if (when.getMonth() !== Number(mo) - 1 || when.getDate() !== Number(d)) throw new InvalidDateError(field, text, `there is no day ${d} in month ${mo}`);
|
|
367
|
-
return result("allDay", when, text);
|
|
368
|
-
}
|
|
369
|
-
const off = OFFSET.exec(lower);
|
|
370
|
-
if (off) {
|
|
371
|
-
const n = Number(off[1]);
|
|
372
|
-
const unit = String(off[2]);
|
|
373
|
-
if (!Number.isFinite(n)) throw new InvalidDateError(field, text, "the amount is not a number");
|
|
374
|
-
if (unit.startsWith("d")) return result("timed", addDays(now, n), text);
|
|
375
|
-
if (unit.startsWith("w")) return result("timed", addDays(now, n * 7), text);
|
|
376
|
-
const ms = unit.startsWith("h") ? n * 36e5 : n * 6e4;
|
|
377
|
-
return result("timed", new Date(now.getTime() + ms), text);
|
|
378
|
-
}
|
|
379
|
-
const word = DAY_WORD.exec(lower);
|
|
380
|
-
if (word) {
|
|
381
|
-
const day = word[1] === "tomorrow" ? addDays(now, 1) : now;
|
|
382
|
-
if (word[2] === void 0) return result("allDay", startOfDay(day), text);
|
|
383
|
-
const [hh, mm] = [Number(word[2]), Number(word[3])];
|
|
384
|
-
if (hh > 23 || mm > 59) throw new InvalidDateError(field, text, `${hh}:${word[3]} is not a time`);
|
|
385
|
-
return result("timed", at(day, hh, mm), text);
|
|
386
|
-
}
|
|
387
|
-
const next = NEXT_DAY.exec(lower);
|
|
388
|
-
if (next) {
|
|
389
|
-
const idx = DAY_NAMES.findIndex((n) => n === next[1] || n.slice(0, 3) === next[1]);
|
|
390
|
-
if (idx === -1) throw new InvalidDateError(field, text, `"${next[1]}" is not a day of the week`);
|
|
391
|
-
const ahead = (idx - now.getDay() + 7) % 7 || 7;
|
|
392
|
-
const day = addDays(now, ahead);
|
|
393
|
-
if (next[2] === void 0) return result("allDay", startOfDay(day), text);
|
|
394
|
-
const [hh, mm] = [Number(next[2]), Number(next[3])];
|
|
395
|
-
if (hh > 23 || mm > 59) throw new InvalidDateError(field, text, `${hh}:${next[3]} is not a time`);
|
|
396
|
-
return result("timed", at(day, hh, mm), text);
|
|
397
|
-
}
|
|
398
|
-
throw new InvalidDateError(field, text, "it matches none of the accepted forms");
|
|
399
|
-
};
|
|
400
|
-
/**
|
|
401
|
-
* Parse a bound for a range filter.
|
|
402
|
-
*
|
|
403
|
-
* A bare day means the WHOLE day, so which edge it resolves to depends on which
|
|
404
|
-
* side of the range it is. Resolving both to midnight would make an end bound
|
|
405
|
-
* quietly exclude the day the caller named.
|
|
406
|
-
*/
|
|
407
|
-
const parseBound = (field, raw, edge, now = /* @__PURE__ */ new Date()) => {
|
|
408
|
-
const parsed = parseDate(field, raw, now);
|
|
409
|
-
if (parsed.kind !== "allDay") return parsed.at;
|
|
410
|
-
return edge === "end" ? endOfDay(parsed.at) : startOfDay(parsed.at);
|
|
411
|
-
};
|
|
412
284
|
/**
|
|
413
285
|
* Resolve a query window.
|
|
414
286
|
*
|
|
@@ -418,8 +290,8 @@ const parseBound = (field, raw, edge, now = /* @__PURE__ */ new Date()) => {
|
|
|
418
290
|
* next Tuesday, and every window is bounded on both ends.
|
|
419
291
|
*/
|
|
420
292
|
const parseRange = (opts, now = /* @__PURE__ */ new Date()) => {
|
|
421
|
-
const from = opts.from ? parseBound("from", opts.from, "start", now) :
|
|
422
|
-
const to = opts.to ? parseBound("to", opts.to, "end", now) :
|
|
293
|
+
const from = opts.from ? parseBound("from", opts.from, "start", now) : startOfLocalDay(now);
|
|
294
|
+
const to = opts.to ? parseBound("to", opts.to, "end", now) : startOfLocalDay(addLocalDays(from, opts.defaultRangeDays));
|
|
423
295
|
if (to.getTime() < from.getTime()) throw new InvalidDateError("to", String(opts.to ?? ""), `it resolves to ${toLocalIso(to)}, which is before from (${toLocalIso(from)})`);
|
|
424
296
|
const maxMs = opts.maxRangeDays * 864e5;
|
|
425
297
|
if (to.getTime() - from.getTime() > maxMs) return {
|
|
@@ -1836,11 +1708,13 @@ var AppleCalendarClient = class {
|
|
|
1836
1708
|
});
|
|
1837
1709
|
const declined = filters.includeDeclined ?? this.config.includeDeclined;
|
|
1838
1710
|
const cancelled = filters.includeCancelled ?? this.config.includeCancelled;
|
|
1711
|
+
const visible = merged.rows.filter((r) => this.#visible(r, {
|
|
1712
|
+
declined,
|
|
1713
|
+
cancelled
|
|
1714
|
+
}));
|
|
1839
1715
|
return {
|
|
1840
|
-
events:
|
|
1841
|
-
|
|
1842
|
-
cancelled
|
|
1843
|
-
})).slice(0, filters.limit).map((r) => this.#summarise(r, store)),
|
|
1716
|
+
events: visible.slice(0, filters.limit).map((r) => this.#summarise(r, store)),
|
|
1717
|
+
hasMore: visible.length > filters.limit,
|
|
1844
1718
|
expansion: merged.expansion,
|
|
1845
1719
|
...merged.expansionReason ? { expansionReason: merged.expansionReason } : {},
|
|
1846
1720
|
window: {
|
|
@@ -1895,11 +1769,13 @@ var AppleCalendarClient = class {
|
|
|
1895
1769
|
});
|
|
1896
1770
|
const declined = args.includeDeclined ?? this.config.includeDeclined;
|
|
1897
1771
|
const cancelled = args.includeCancelled ?? this.config.includeCancelled;
|
|
1772
|
+
const visible = rows.filter((r) => this.#visible(r, {
|
|
1773
|
+
declined,
|
|
1774
|
+
cancelled
|
|
1775
|
+
}));
|
|
1898
1776
|
return {
|
|
1899
|
-
events:
|
|
1900
|
-
|
|
1901
|
-
cancelled
|
|
1902
|
-
})).slice(0, args.limit).map((r) => this.#summarise(r, store)),
|
|
1777
|
+
events: visible.slice(0, args.limit).map((r) => this.#summarise(r, store)),
|
|
1778
|
+
hasMore: visible.length > args.limit,
|
|
1903
1779
|
expansion: "unavailable",
|
|
1904
1780
|
expansionReason: "search matches each event once, at its series start; use apple_calendar_list_events with a date range to see individual occurrences",
|
|
1905
1781
|
window: {
|
|
@@ -1992,14 +1868,14 @@ var AppleCalendarClient = class {
|
|
|
1992
1868
|
if (windowTo.getTime() > covTo.getTime()) {
|
|
1993
1869
|
truncated = {
|
|
1994
1870
|
reason,
|
|
1995
|
-
requestedTo: toLocalIso(range.to)
|
|
1871
|
+
requestedTo: toLocalIso$1(/* @__PURE__ */ new Date(range.to.getTime() - 1))
|
|
1996
1872
|
};
|
|
1997
1873
|
windowTo = covTo;
|
|
1998
1874
|
}
|
|
1999
1875
|
if (windowFrom.getTime() < covFrom.getTime()) {
|
|
2000
1876
|
truncated = {
|
|
2001
1877
|
...truncated ?? { reason },
|
|
2002
|
-
requestedFrom: toLocalIso(range.from)
|
|
1878
|
+
requestedFrom: toLocalIso$1(range.from)
|
|
2003
1879
|
};
|
|
2004
1880
|
windowFrom = covFrom;
|
|
2005
1881
|
}
|
|
@@ -2007,7 +1883,7 @@ var AppleCalendarClient = class {
|
|
|
2007
1883
|
degraded: true,
|
|
2008
1884
|
capability: "occurrence-coverage",
|
|
2009
1885
|
reason: "The whole requested window lies outside the range this store has expanded, so every gap in it would be invented rather than found.",
|
|
2010
|
-
hint: `The expansion reaches ${toLocalIso(covFrom)} to ${toLocalIso(covTo)}. Ask inside that, or use apple_calendar_list_events, which reports single events correctly at any distance.`
|
|
1886
|
+
hint: `The expansion reaches ${toLocalIso$1(covFrom)} to ${toLocalIso$1(covTo)}. Ask inside that, or use apple_calendar_list_events, which reports single events correctly at any distance.`
|
|
2011
1887
|
};
|
|
2012
1888
|
}
|
|
2013
1889
|
const startedAtNow = windowFrom.getTime() < now.getTime();
|
|
@@ -2015,8 +1891,8 @@ var AppleCalendarClient = class {
|
|
|
2015
1891
|
const shell = {
|
|
2016
1892
|
durationMinutes: args.durationMinutes,
|
|
2017
1893
|
window: {
|
|
2018
|
-
from: toLocalIso(windowFrom),
|
|
2019
|
-
to: toLocalIso(windowTo),
|
|
1894
|
+
from: toLocalIso$1(windowFrom),
|
|
1895
|
+
to: toLocalIso$1(windowTo),
|
|
2020
1896
|
clamped: range.clamped,
|
|
2021
1897
|
startedAtNow
|
|
2022
1898
|
},
|
|
@@ -2099,8 +1975,8 @@ var AppleCalendarClient = class {
|
|
|
2099
1975
|
const start = alignUp(gap.from, args.granularityMinutes);
|
|
2100
1976
|
if (gap.to - start < needMs) continue;
|
|
2101
1977
|
slots.push({
|
|
2102
|
-
start: toLocalIso(new Date(start)),
|
|
2103
|
-
end: toLocalIso(new Date(gap.to)),
|
|
1978
|
+
start: toLocalIso$1(new Date(start)),
|
|
1979
|
+
end: toLocalIso$1(new Date(gap.to)),
|
|
2104
1980
|
day: localDay(start),
|
|
2105
1981
|
minutes: Math.round((gap.to - start) / 6e4)
|
|
2106
1982
|
});
|
|
@@ -2262,11 +2138,11 @@ var AppleCalendarClient = class {
|
|
|
2262
2138
|
* word: `{start: "2026-09-21", end: "2026-09-21"}`, the natural way to say
|
|
2263
2139
|
* "a one-day event", was refused as ending before it began.
|
|
2264
2140
|
*/
|
|
2265
|
-
const to = parseBound("end", end, "end", now);
|
|
2266
|
-
if (to.getTime() <= from.at.getTime()) throw new PreconditionError(`end (${toLocalIso(to)}) is not after start (${from.iso}). An event cannot finish before it begins.`);
|
|
2141
|
+
const to = parseBound$1("end", end, "end", now);
|
|
2142
|
+
if (to.getTime() <= from.at.getTime()) throw new PreconditionError(`end (${toLocalIso$1(to)}) is not after start (${from.iso}). An event cannot finish before it begins.`);
|
|
2267
2143
|
return {
|
|
2268
2144
|
startIso: from.iso,
|
|
2269
|
-
endIso: toLocalIso(to),
|
|
2145
|
+
endIso: toLocalIso$1(to),
|
|
2270
2146
|
allDayHint: from.kind === "allDay"
|
|
2271
2147
|
};
|
|
2272
2148
|
}
|
|
@@ -2274,7 +2150,7 @@ var AppleCalendarClient = class {
|
|
|
2274
2150
|
const to = new Date(from.at.getTime() + minutes * 6e4);
|
|
2275
2151
|
return {
|
|
2276
2152
|
startIso: from.iso,
|
|
2277
|
-
endIso: toLocalIso(to),
|
|
2153
|
+
endIso: toLocalIso$1(to),
|
|
2278
2154
|
allDayHint: from.kind === "allDay"
|
|
2279
2155
|
};
|
|
2280
2156
|
}
|
|
@@ -2311,12 +2187,22 @@ var AppleCalendarClient = class {
|
|
|
2311
2187
|
ref: fields.ref,
|
|
2312
2188
|
seriesRef: seriesRefOf(ref)
|
|
2313
2189
|
});
|
|
2314
|
-
|
|
2190
|
+
let window = null;
|
|
2191
|
+
let endOnly = false;
|
|
2192
|
+
if (fields.start !== void 0) window = this.#resolveWindow(fields.start, fields.end, fields.durationMinutes);
|
|
2193
|
+
else if (fields.end !== void 0 || fields.durationMinutes !== void 0) {
|
|
2194
|
+
const store = this.#require();
|
|
2195
|
+
const row = store.byUuid(ref.eventUid);
|
|
2196
|
+
if (!row || row.startApple === null) throw new PreconditionError("Give start as well. Moving only the end needs the event's current start, and this store does not have one for that ref.", { ref: fields.ref });
|
|
2197
|
+
const startIso = toLocalIso$1(/* @__PURE__ */ new Date((row.startApple + store.caps.epochOffset) * 1e3));
|
|
2198
|
+
window = this.#resolveWindow(startIso, fields.end, fields.durationMinutes);
|
|
2199
|
+
endOnly = true;
|
|
2200
|
+
}
|
|
2315
2201
|
const data = await this.#run(UPDATE_EVENT, {
|
|
2316
2202
|
calendar: this.#nameForRefCalendar(ref.calendarUid) ?? null,
|
|
2317
2203
|
uid: ref.eventUid,
|
|
2318
2204
|
...fields.summary !== void 0 ? { summary: fields.summary } : {},
|
|
2319
|
-
...window ? {
|
|
2205
|
+
...window ? endOnly ? { endDate: window.endIso } : {
|
|
2320
2206
|
startDate: window.startIso,
|
|
2321
2207
|
endDate: window.endIso
|
|
2322
2208
|
} : {},
|
|
@@ -2857,7 +2743,7 @@ const filterSchema = {
|
|
|
2857
2743
|
};
|
|
2858
2744
|
const registerEventTools = (server, client) => {
|
|
2859
2745
|
server.registerTool("apple_calendar_list_events", {
|
|
2860
|
-
description: "List events in a date range, earliest first. Occurrences of repeating events are expanded, so a weekly standup appears once per week rather than once. The result carries a `coverage` block naming the window the expansion is known to cover; if your range runs past it, `truncated` is set and says what is missing rather than returning a short list silently. Returns a `ref` per event for get_event.",
|
|
2746
|
+
description: "List events in a date range, earliest first. Occurrences of repeating events are expanded, so a weekly standup appears once per week rather than once. The result carries a `coverage` block naming the window the expansion is known to cover; if your range runs past it, `truncated` is set and says what is missing rather than returning a short list silently. `hasMore` is the other reason a list can be partial: more events matched than `limit` allowed. Returns a `ref` per event for get_event.",
|
|
2861
2747
|
inputSchema: {
|
|
2862
2748
|
from: fromArg,
|
|
2863
2749
|
to: toArg,
|
|
@@ -2964,4 +2850,4 @@ const createServer = (opts) => {
|
|
|
2964
2850
|
//#endregion
|
|
2965
2851
|
export { BUILD_INFO as A, CALENDAR_SURFACE as C, CalendarNotWritableError as D, CalendarNotRunningError as E, EventNotFoundError as O, CALENDAR_BUNDLE_ID as S, CalendarNotFoundError as T, STORE_FILENAME as _, loadConfig as a, locateStore as b, introspect as c, decodeRef as d, encodeRef as f, GROUP_CONTAINER as g, EXTRAS_FILENAME as h, registerTools as i, InvalidDateError as k, openStore as l, uuidOf as m, SERVER_VERSION as n, AppleCalendarClient as o, seriesRefOf as p, createServer as r, CalendarStore as s, SERVER_NAME as t, REF_VERSION as u, defaultContainerPath as v, CalendarBusyError as w, AppleCalendarError as x, defaultStorePath as y };
|
|
2966
2852
|
|
|
2967
|
-
//# sourceMappingURL=server-
|
|
2853
|
+
//# sourceMappingURL=server-CLAGQcwG.js.map
|