@mulmoclaude/core 0.24.0 → 0.25.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.
Files changed (76) hide show
  1. package/assets/helps/google-calendar-collection.md +79 -0
  2. package/assets/helps/index.md +1 -0
  3. package/dist/collection/core/schemaZ.d.ts +29 -0
  4. package/dist/collection/index.cjs +15 -14
  5. package/dist/collection/index.cjs.map +1 -1
  6. package/dist/collection/index.js +2 -1
  7. package/dist/collection/index.js.map +1 -1
  8. package/dist/collection/paths.cjs +5 -55
  9. package/dist/collection/paths.js +1 -51
  10. package/dist/collection/registry/server/index.cjs +20 -19
  11. package/dist/collection/registry/server/index.cjs.map +1 -1
  12. package/dist/collection/registry/server/index.js +3 -2
  13. package/dist/collection/registry/server/index.js.map +1 -1
  14. package/dist/collection/server/index.cjs +41 -40
  15. package/dist/collection/server/index.js +4 -3
  16. package/dist/collection-watchers/index.cjs +12 -11
  17. package/dist/collection-watchers/index.cjs.map +1 -1
  18. package/dist/collection-watchers/index.js +3 -2
  19. package/dist/collection-watchers/index.js.map +1 -1
  20. package/dist/discovery-3K_Wtkvn.js +1636 -0
  21. package/dist/discovery-3K_Wtkvn.js.map +1 -0
  22. package/dist/discovery-BZ2ms1tE.cjs +1865 -0
  23. package/dist/discovery-BZ2ms1tE.cjs.map +1 -0
  24. package/dist/feeds/index.cjs +4 -4
  25. package/dist/feeds/index.js +2 -2
  26. package/dist/feeds/server/index.cjs +16 -15
  27. package/dist/feeds/server/index.cjs.map +1 -1
  28. package/dist/feeds/server/index.js +4 -3
  29. package/dist/feeds/server/index.js.map +1 -1
  30. package/dist/google/apiClient.d.ts +8 -1
  31. package/dist/google/calendar.d.ts +35 -0
  32. package/dist/google/calendarSyncStore.d.ts +7 -0
  33. package/dist/google/collectionSync.d.ts +70 -0
  34. package/dist/google/index.cjs +296 -4
  35. package/dist/google/index.cjs.map +1 -1
  36. package/dist/google/index.d.ts +4 -2
  37. package/dist/google/index.js +281 -5
  38. package/dist/google/index.js.map +1 -1
  39. package/dist/ids-BR4U1dJD.cjs +150 -0
  40. package/dist/ids-BR4U1dJD.cjs.map +1 -0
  41. package/dist/ids-D4e10971.js +85 -0
  42. package/dist/ids-D4e10971.js.map +1 -0
  43. package/dist/{ingestTypes-CFEgTItj.js → ingestTypes-BsGOjR2l.js} +2 -2
  44. package/dist/{ingestTypes-CFEgTItj.js.map → ingestTypes-BsGOjR2l.js.map} +1 -1
  45. package/dist/{ingestTypes-Stc7iQyA.cjs → ingestTypes-CygUXsjf.cjs} +3 -3
  46. package/dist/{ingestTypes-Stc7iQyA.cjs.map → ingestTypes-CygUXsjf.cjs.map} +1 -1
  47. package/dist/{promptSafety-BLUcImzd.js → promptSafety-Boz5qOs-.js} +2 -84
  48. package/dist/promptSafety-Boz5qOs-.js.map +1 -0
  49. package/dist/{promptSafety-DI_1Rvhk.cjs → promptSafety-Co4cYQ_Z.cjs} +1 -149
  50. package/dist/promptSafety-Co4cYQ_Z.cjs.map +1 -0
  51. package/dist/remote-host/server/index.cjs +6 -4
  52. package/dist/remote-host/server/index.cjs.map +1 -1
  53. package/dist/remote-host/server/index.js +6 -4
  54. package/dist/remote-host/server/index.js.map +1 -1
  55. package/dist/scheduler/index.cjs +3 -1
  56. package/dist/scheduler/index.cjs.map +1 -1
  57. package/dist/scheduler/index.js +3 -1
  58. package/dist/scheduler/index.js.map +1 -1
  59. package/dist/{server-CkysfLh4.cjs → server-DLRz-U7F.cjs} +76 -1884
  60. package/dist/server-DLRz-U7F.cjs.map +1 -0
  61. package/dist/{server-BpEo0FOd.js → server-DZH7OjOD.js} +5 -1609
  62. package/dist/server-DZH7OjOD.js.map +1 -0
  63. package/dist/skill-bridge/index.cjs +2 -2
  64. package/dist/skill-bridge/index.cjs.map +1 -1
  65. package/dist/skill-bridge/index.js +1 -1
  66. package/dist/templatePath-27vUZowm.cjs +75 -0
  67. package/dist/templatePath-27vUZowm.cjs.map +1 -0
  68. package/dist/templatePath-k_WNbL_Q.js +52 -0
  69. package/dist/templatePath-k_WNbL_Q.js.map +1 -0
  70. package/package.json +1 -1
  71. package/dist/collection/paths.cjs.map +0 -1
  72. package/dist/collection/paths.js.map +0 -1
  73. package/dist/promptSafety-BLUcImzd.js.map +0 -1
  74. package/dist/promptSafety-DI_1Rvhk.cjs.map +0 -1
  75. package/dist/server-BpEo0FOd.js.map +0 -1
  76. package/dist/server-CkysfLh4.cjs.map +0 -1
@@ -1,11 +1,13 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_rolldown_runtime = require("../rolldown-runtime-D6vf50IK.cjs");
3
+ const require_discovery = require("../discovery-BZ2ms1tE.cjs");
3
4
  let node_path = require("node:path");
4
5
  node_path = require_rolldown_runtime.__toESM(node_path, 1);
5
6
  let node_fs = require("node:fs");
6
7
  let node_fs_promises = require("node:fs/promises");
7
8
  let node_crypto = require("node:crypto");
8
9
  let node_os = require("node:os");
10
+ let _receptron_task_scheduler = require("@receptron/task-scheduler");
9
11
  let node_http = require("node:http");
10
12
  node_http = require_rolldown_runtime.__toESM(node_http, 1);
11
13
  let google_auth_library = require("google-auth-library");
@@ -611,12 +613,21 @@ var ERROR_BODY_MAX_CHARS = 300;
611
613
  var HTTP_FORBIDDEN = 403;
612
614
  var DEFAULT_LIST_MAX_RESULTS = 10;
613
615
  var MAX_LIST_RESULTS = 50;
616
+ /** Carries the HTTP status so callers can branch on it (e.g. an expired
617
+ * calendar syncToken answers 410) without parsing the message. */
618
+ var GoogleApiError = class extends Error {
619
+ status;
620
+ constructor(status, message) {
621
+ super(message);
622
+ this.name = "GoogleApiError";
623
+ this.status = status;
624
+ }
625
+ };
626
+ var isGoogleApiError = (value) => value instanceof GoogleApiError;
614
627
  /** 403 usually means the API is not enabled for the user's Cloud project —
615
628
  * name the API so the agent's recovery guidance can be specific. */
616
629
  var googleApiError = (apiLabel, status, body) => {
617
- const hint = status === HTTP_FORBIDDEN ? ` (is the ${apiLabel} enabled for the Cloud project?)` : "";
618
- const detail = body ? ` — ${truncate(body, ERROR_BODY_MAX_CHARS)}` : "";
619
- return /* @__PURE__ */ new Error(`${apiLabel}: HTTP ${status}${hint}${detail}`);
630
+ return new GoogleApiError(status, `${apiLabel}: HTTP ${status}${status === HTTP_FORBIDDEN ? ` (is the ${apiLabel} enabled for the Cloud project?)` : ""}${body ? ` — ${truncate(body, ERROR_BODY_MAX_CHARS)}` : ""}`);
620
631
  };
621
632
  async function googleRequest(apiLabel, accessToken, url, init = {}) {
622
633
  const { contentType = "application/json", expectText = false, ...rest } = init;
@@ -649,7 +660,16 @@ var CALENDAR_API_LABEL = "Google Calendar API";
649
660
  var DEFAULT_CALENDAR_ID = "primary";
650
661
  var CALENDAR_LIST_PAGE_SIZE = 250;
651
662
  var MAX_CALENDAR_LIST_PAGES = 40;
652
- var eventsUrl = (calendarId) => `${CALENDAR_BASE_URL}/calendars/${encodeURIComponent(calendarId || DEFAULT_CALENDAR_ID)}/events`;
663
+ var EVENT_SYNC_PAGE_SIZE = 2500;
664
+ var MAX_EVENT_SYNC_PAGES = 200;
665
+ var HTTP_GONE = 410;
666
+ /** Resolve a declared calendarId to the one the API and the sync-token store
667
+ * both address. `||` (not `??`) so an empty string also falls back instead of
668
+ * building a malformed `/calendars//events` URL. Single-sourced because an
669
+ * omitted id and an explicit "primary" MUST agree everywhere — grouping them
670
+ * apart while they share a sync token silently loses events (#2184). */
671
+ var canonicalCalendarId = (calendarId) => calendarId || DEFAULT_CALENDAR_ID;
672
+ var eventsUrl = (calendarId) => `${CALENDAR_BASE_URL}/calendars/${encodeURIComponent(canonicalCalendarId(calendarId))}/events`;
653
673
  var eventTime = (value) => {
654
674
  if (!isRecord(value)) return "";
655
675
  if (typeof value.dateTime === "string") return value.dateTime;
@@ -716,6 +736,54 @@ async function listCalendarEvents(accessToken, input = {}) {
716
736
  });
717
737
  return itemsOf(await googleRequest(CALENDAR_API_LABEL, accessToken, `${eventsUrl(input.calendarId)}?${params.toString()}`)).map(toEventSummary);
718
738
  }
739
+ var GONE = Symbol("calendar-sync-gone");
740
+ async function fetchSyncPage(accessToken, calendarId, params) {
741
+ try {
742
+ return await googleRequest(CALENDAR_API_LABEL, accessToken, `${eventsUrl(calendarId)}?${params.toString()}`);
743
+ } catch (err) {
744
+ if (isGoogleApiError(err) && err.status === HTTP_GONE) return GONE;
745
+ throw err;
746
+ }
747
+ }
748
+ /** Incremental sync over the events of one calendar (#2095).
749
+ *
750
+ * Deliberately separate from `listCalendarEvents`: Google forbids combining
751
+ * `syncToken` with `timeMin` / `timeMax` / `updatedMin` / `orderBy` / `q`,
752
+ * and that function always sends `timeMin` + `orderBy`. So this one sends
753
+ * neither — a sync covers the WHOLE calendar and the caller sorts / windows
754
+ * client-side. `showDeleted` must stay true or deletions would be invisible.
755
+ *
756
+ * `nextSyncToken` is only present on the LAST page, so every page must be
757
+ * walked before the token is worth storing. */
758
+ async function syncCalendarEvents(accessToken, input = {}) {
759
+ const events = [];
760
+ let pageToken;
761
+ let nextSyncToken;
762
+ for (let page = 0; page < MAX_EVENT_SYNC_PAGES; page += 1) {
763
+ const params = new URLSearchParams({
764
+ singleEvents: "true",
765
+ showDeleted: "true",
766
+ maxResults: String(input.maxResults ?? EVENT_SYNC_PAGE_SIZE)
767
+ });
768
+ if (input.syncToken) params.set("syncToken", input.syncToken);
769
+ if (pageToken) params.set("pageToken", pageToken);
770
+ const payload = await fetchSyncPage(accessToken, input.calendarId, params);
771
+ if (payload === GONE) return {
772
+ events: [],
773
+ fullResyncRequired: true
774
+ };
775
+ const record = asRecord(payload);
776
+ events.push(...itemsOf(payload).map(toEventSummary));
777
+ nextSyncToken = stringField(record, "nextSyncToken") || void 0;
778
+ pageToken = stringField(record, "nextPageToken") || void 0;
779
+ if (!pageToken) break;
780
+ }
781
+ return {
782
+ events,
783
+ nextSyncToken,
784
+ fullResyncRequired: false
785
+ };
786
+ }
719
787
  /** Pagination loop for CalendarList.list, extracted so it can be tested without
720
788
  * network. Stops at the last page (no token) or the runaway page cap. */
721
789
  async function collectCalendarPages(fetchPage, maxPages = MAX_CALENDAR_LIST_PAGES) {
@@ -753,6 +821,214 @@ async function getCalendarColors(accessToken) {
753
821
  };
754
822
  }
755
823
  //#endregion
824
+ //#region src/google/calendarSyncStore.ts
825
+ var SYNC_STATE_MODE = 384;
826
+ /** `<workspace>/data/calendar/.sync-state.json` */
827
+ function calendarSyncStatePath(workspaceRoot) {
828
+ return node_path.default.join(workspaceRoot ?? require_discovery.getWorkspaceRoot(), "data", "calendar", ".sync-state.json");
829
+ }
830
+ var calendarKey = canonicalCalendarId;
831
+ async function readState(workspaceRoot) {
832
+ const stored = await readJsonOrNull(calendarSyncStatePath(workspaceRoot));
833
+ return stored?.tokens ? stored : { tokens: {} };
834
+ }
835
+ var writeQueue = { tail: Promise.resolve() };
836
+ async function updateState(mutate, workspaceRoot) {
837
+ const run = writeQueue.tail.then(async () => {
838
+ const state = await readState(workspaceRoot);
839
+ await writeJsonAtomicWithMode(calendarSyncStatePath(workspaceRoot), { tokens: mutate(state.tokens) }, SYNC_STATE_MODE);
840
+ });
841
+ writeQueue.tail = run.catch(() => void 0);
842
+ return await run;
843
+ }
844
+ async function loadCalendarSyncToken(calendarId, workspaceRoot) {
845
+ return (await readState(workspaceRoot)).tokens[calendarKey(calendarId)] ?? null;
846
+ }
847
+ async function saveCalendarSyncToken(calendarId, syncToken, workspaceRoot) {
848
+ const stored = calendarKey(calendarId);
849
+ await updateState((tokens) => ({
850
+ ...tokens,
851
+ [stored]: syncToken
852
+ }), workspaceRoot);
853
+ }
854
+ /** Drop one calendar's token — used when Google answers 410, so the next run
855
+ * starts a clean full sync. */
856
+ async function clearCalendarSyncToken(calendarId, workspaceRoot) {
857
+ const dropped = calendarKey(calendarId);
858
+ await updateState((tokens) => Object.fromEntries(Object.entries(tokens).filter(([key]) => key !== dropped)), workspaceRoot);
859
+ }
860
+ //#endregion
861
+ //#region src/google/collectionSync.ts
862
+ var GOOGLE_CALENDAR_SYNC_TASK_ID = "system:google-calendar-sync";
863
+ var DEFAULT_SYNC_INTERVAL_MS = 3600 * 1e3;
864
+ var CANCELLED_STATUS = "cancelled";
865
+ /** Project one Google event onto the collection's own field names. The
866
+ * primary field always takes the event id — upsert-by-id is what keeps the
867
+ * sync idempotent, so it is deliberately not remappable. */
868
+ function toCollectionRecord(event, map, primaryKey) {
869
+ const mapped = Object.entries(map).map(([field, source]) => [field, event[source]]);
870
+ return {
871
+ ...Object.fromEntries(mapped),
872
+ [primaryKey]: event.id
873
+ };
874
+ }
875
+ function classifyWrite(eventId, kind) {
876
+ if (kind === "ok") return { kind: "written" };
877
+ if (kind === "invalid-id") return {
878
+ kind: "unwritable",
879
+ message: `write ${eventId}: invalid-id`
880
+ };
881
+ return {
882
+ kind: "error",
883
+ message: `write ${eventId}: ${kind}`
884
+ };
885
+ }
886
+ function classifyDelete(eventId, kind) {
887
+ if (kind === "ok") return { kind: "removed" };
888
+ if (kind === "not-found") return { kind: "skipped" };
889
+ if (kind === "invalid-id") return {
890
+ kind: "unwritable",
891
+ message: `delete ${eventId}: invalid-id`
892
+ };
893
+ return {
894
+ kind: "error",
895
+ message: `delete ${eventId}: ${kind}`
896
+ };
897
+ }
898
+ async function applyEvent(collection, event, workspaceRoot) {
899
+ const { slug, dataDir, schema } = collection;
900
+ try {
901
+ if (event.status === CANCELLED_STATUS) {
902
+ const deleted = await require_discovery.deleteItem(dataDir, event.id, {
903
+ workspaceRoot,
904
+ slug
905
+ });
906
+ return classifyDelete(event.id, deleted.kind);
907
+ }
908
+ const record = toCollectionRecord(event, schema.googleCalendar?.map ?? {}, schema.primaryKey);
909
+ const written = await require_discovery.writeItem(dataDir, event.id, record, {
910
+ refuseOverwrite: false,
911
+ workspaceRoot,
912
+ slug
913
+ });
914
+ return classifyWrite(event.id, written.kind);
915
+ } catch (error) {
916
+ return {
917
+ kind: "error",
918
+ message: `apply ${event.id}: ${String(error)}`
919
+ };
920
+ }
921
+ }
922
+ async function restartFullSync(accessToken, calendarId, workspaceRoot) {
923
+ await clearCalendarSyncToken(calendarId, workspaceRoot);
924
+ return await syncCalendarEvents(accessToken, { calendarId });
925
+ }
926
+ /** Sync ONE calendar and fan its events out to every collection bound to it.
927
+ *
928
+ * The fan-out is not an optimisation, it is correctness: the sync token is
929
+ * keyed by `calendarId`, so syncing collection-by-collection would let the
930
+ * first collection advance the shared token and leave every later collection
931
+ * on the same calendar reading an already-consumed window — silently missing
932
+ * those events forever. Fetch once, apply to all, then advance the token.
933
+ * (Codex + CodeRabbit review on #2184.) */
934
+ async function syncCalendarGroup(calendarId, collections, workspaceRoot) {
935
+ const accessToken = await getGoogleAccessToken();
936
+ const first = await syncCalendarEvents(accessToken, {
937
+ calendarId,
938
+ syncToken: await loadCalendarSyncToken(calendarId, workspaceRoot) ?? void 0
939
+ });
940
+ const result = first.fullResyncRequired ? await restartFullSync(accessToken, calendarId, workspaceRoot) : first;
941
+ const results = [];
942
+ for (const collection of collections) results.push(await applyEventsToCollection(collection, result.events, workspaceRoot));
943
+ const unwritable = results.flatMap((entry) => entry.unwritable);
944
+ if (unwritable.length > 0) log.warn("google", "skipping calendar events that can never be stored", {
945
+ calendarId,
946
+ unwritable
947
+ });
948
+ const failed = results.flatMap((entry) => entry.errors);
949
+ if (result.nextSyncToken && failed.length === 0) await saveCalendarSyncToken(calendarId, result.nextSyncToken, workspaceRoot);
950
+ else if (failed.length > 0) log.warn("google", "holding back calendar sync token after failed writes", {
951
+ calendarId,
952
+ failed: failed.length
953
+ });
954
+ return results;
955
+ }
956
+ async function applyEventsToCollection(collection, events, workspaceRoot) {
957
+ const outcomes = [];
958
+ for (const event of events) outcomes.push(await applyEvent(collection, event, workspaceRoot));
959
+ return {
960
+ slug: collection.slug,
961
+ written: outcomes.filter((outcome) => outcome.kind === "written").length,
962
+ removed: outcomes.filter((outcome) => outcome.kind === "removed").length,
963
+ unwritable: outcomes.flatMap((outcome) => outcome.kind === "unwritable" ? [outcome.message] : []),
964
+ errors: outcomes.flatMap((outcome) => outcome.kind === "error" ? [outcome.message] : [])
965
+ };
966
+ }
967
+ /** A refresh token is what lets the scheduler run unattended; without one
968
+ * there is nothing to sync with. */
969
+ async function isGoogleLinked() {
970
+ return Boolean((await loadGoogleTokens())?.refresh_token);
971
+ }
972
+ /** Group the declaring collections by the calendar they read, so each calendar
973
+ * is fetched exactly once.
974
+ *
975
+ * Keyed by the CANONICAL id, not the declared one: an omitted `calendarId` and
976
+ * an explicit `"primary"` address the same calendar and therefore share one
977
+ * sync token, so grouping them apart would let one group advance the token out
978
+ * from under the other — the very loss this grouping exists to prevent
979
+ * (Codex review #2184). */
980
+ function groupByCalendar(collections) {
981
+ const groups = /* @__PURE__ */ new Map();
982
+ for (const collection of collections) {
983
+ const key = canonicalCalendarId(collection.schema.googleCalendar?.calendarId);
984
+ groups.set(key, [...groups.get(key) ?? [], collection]);
985
+ }
986
+ return groups;
987
+ }
988
+ /** Sync every collection that declares `googleCalendar`. Failures are isolated
989
+ * per calendar — one unreachable calendar (or a revoked grant) must not stop
990
+ * the others. */
991
+ async function syncDueCalendarCollections(workspaceRoot) {
992
+ const declaring = (await require_discovery.discoverCollections({ workspaceRoot })).filter((collection) => collection.schema.googleCalendar);
993
+ if (declaring.length === 0) return [];
994
+ if (!await isGoogleLinked()) {
995
+ log.info("google", "skipping calendar sync — no Google account linked on this host", { collections: declaring.length });
996
+ return [];
997
+ }
998
+ const results = [];
999
+ for (const [calendarId, collections] of groupByCalendar(declaring)) try {
1000
+ results.push(...await syncCalendarGroup(calendarId, collections, workspaceRoot));
1001
+ } catch (error) {
1002
+ log.warn("google", "calendar sync failed", {
1003
+ calendarId,
1004
+ error: String(error)
1005
+ });
1006
+ results.push(...collections.map((collection) => ({
1007
+ slug: collection.slug,
1008
+ written: 0,
1009
+ removed: 0,
1010
+ unwritable: [],
1011
+ errors: [String(error)]
1012
+ })));
1013
+ }
1014
+ return results;
1015
+ }
1016
+ /** Scheduler registration, shaped like `feedRefreshTaskDef` so hosts wire it
1017
+ * with a single line. */
1018
+ function googleCalendarSyncTaskDef(opts) {
1019
+ return {
1020
+ id: GOOGLE_CALENDAR_SYNC_TASK_ID,
1021
+ name: "Google Calendar sync",
1022
+ description: "Pulls changed Google Calendar events into any collection declaring `googleCalendar`, without invoking the LLM.",
1023
+ schedule: {
1024
+ type: _receptron_task_scheduler.SCHEDULE_TYPES.interval,
1025
+ intervalMs: opts?.intervalMs ?? DEFAULT_SYNC_INTERVAL_MS
1026
+ },
1027
+ missedRunPolicy: _receptron_task_scheduler.MISSED_RUN_POLICIES.runOnce,
1028
+ run: () => syncDueCalendarCollections(opts?.workspaceRoot ?? require_discovery.getWorkspaceRoot()).then(() => {})
1029
+ };
1030
+ }
1031
+ //#endregion
756
1032
  //#region src/google/tasks.ts
757
1033
  var TASKS_BASE_URL = "https://tasks.googleapis.com/tasks/v1";
758
1034
  var TASKS_API_LABEL = "Google Tasks API";
@@ -905,9 +1181,11 @@ exports.DEFAULT_LIST_MAX_RESULTS = DEFAULT_LIST_MAX_RESULTS;
905
1181
  exports.GOOGLE_AUTH_CANCELLED = GOOGLE_AUTH_CANCELLED;
906
1182
  exports.GOOGLE_CALENDARLIST_SCOPE = GOOGLE_CALENDARLIST_SCOPE;
907
1183
  exports.GOOGLE_CALENDAR_SCOPE = GOOGLE_CALENDAR_SCOPE;
1184
+ exports.GOOGLE_CALENDAR_SYNC_TASK_ID = GOOGLE_CALENDAR_SYNC_TASK_ID;
908
1185
  exports.GOOGLE_DRIVE_FILE_SCOPE = GOOGLE_DRIVE_FILE_SCOPE;
909
1186
  exports.GOOGLE_SCOPES = GOOGLE_SCOPES;
910
1187
  exports.GOOGLE_TASKS_SCOPE = GOOGLE_TASKS_SCOPE;
1188
+ exports.GoogleApiError = GoogleApiError;
911
1189
  exports.MAX_LIST_RESULTS = MAX_LIST_RESULTS;
912
1190
  exports.assertSafeMimeType = assertSafeMimeType;
913
1191
  exports.authorizeGoogle = authorizeGoogle;
@@ -917,6 +1195,11 @@ exports.brokerRefresh = brokerRefresh;
917
1195
  exports.brokerStart = brokerStart;
918
1196
  exports.buildMultipartBody = buildMultipartBody;
919
1197
  exports.calendarApiError = calendarApiError;
1198
+ exports.calendarSyncStatePath = calendarSyncStatePath;
1199
+ exports.canonicalCalendarId = canonicalCalendarId;
1200
+ exports.classifyDelete = classifyDelete;
1201
+ exports.classifyWrite = classifyWrite;
1202
+ exports.clearCalendarSyncToken = clearCalendarSyncToken;
920
1203
  exports.clientSecretPresence = clientSecretPresence;
921
1204
  exports.collectCalendarPages = collectCalendarPages;
922
1205
  exports.commitLinkedTokens = commitLinkedTokens;
@@ -934,9 +1217,12 @@ exports.getCalendarColors = getCalendarColors;
934
1217
  exports.getGoogleAccessToken = getGoogleAccessToken;
935
1218
  exports.googleApiError = googleApiError;
936
1219
  exports.googleAuthFlow = googleAuthFlow;
1220
+ exports.googleCalendarSyncTaskDef = googleCalendarSyncTaskDef;
937
1221
  exports.googleConfigDir = googleConfigDir;
938
1222
  exports.googleSecretsDir = googleSecretsDir;
939
1223
  exports.googleTokenPath = googleTokenPath;
1224
+ exports.groupByCalendar = groupByCalendar;
1225
+ exports.isGoogleApiError = isGoogleApiError;
940
1226
  exports.isIsoDateTimeWithOffset = isIsoDateTimeWithOffset;
941
1227
  exports.isTextMimeType = isTextMimeType;
942
1228
  exports.legacyGoogleTokenPath = legacyGoogleTokenPath;
@@ -945,13 +1231,19 @@ exports.listCalendars = listCalendars;
945
1231
  exports.listDriveFiles = listDriveFiles;
946
1232
  exports.listTaskLists = listTaskLists;
947
1233
  exports.listTasks = listTasks;
1234
+ exports.loadCalendarSyncToken = loadCalendarSyncToken;
948
1235
  exports.loadClientSecret = loadClientSecret;
949
1236
  exports.loadGoogleTokens = loadGoogleTokens;
950
1237
  exports.mergeGoogleTokens = mergeGoogleTokens;
951
1238
  exports.pickBoundary = pickBoundary;
952
1239
  exports.readDriveFile = readDriveFile;
1240
+ exports.saveCalendarSyncToken = saveCalendarSyncToken;
953
1241
  exports.saveGoogleTokens = saveGoogleTokens;
1242
+ exports.syncCalendarEvents = syncCalendarEvents;
1243
+ exports.syncCalendarGroup = syncCalendarGroup;
1244
+ exports.syncDueCalendarCollections = syncDueCalendarCollections;
954
1245
  exports.toCalendarSummary = toCalendarSummary;
1246
+ exports.toCollectionRecord = toCollectionRecord;
955
1247
  exports.toDriveFileSummary = toDriveFileSummary;
956
1248
  exports.toEventSummary = toEventSummary;
957
1249
  exports.toTaskListSummary = toTaskListSummary;