@mulmoclaude/core 2.1.0 → 3.0.1

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 (42) hide show
  1. package/dist/collection/registry/server/client.d.ts +4 -4
  2. package/dist/collection/registry/server/collectionFiles.d.ts +3 -2
  3. package/dist/collection/registry/server/importCollection.d.ts +3 -2
  4. package/dist/collection/registry/server/index.cjs +27 -26
  5. package/dist/collection/registry/server/index.cjs.map +1 -1
  6. package/dist/collection/registry/server/index.d.ts +3 -2
  7. package/dist/collection/registry/server/index.js +27 -26
  8. package/dist/collection/registry/server/index.js.map +1 -1
  9. package/dist/collection/registry/server/registriesConfig.d.ts +11 -4
  10. package/dist/collection/server/host.d.ts +42 -5
  11. package/dist/collection/server/index.cjs +5 -3
  12. package/dist/collection/server/index.d.ts +1 -1
  13. package/dist/collection/server/index.js +3 -3
  14. package/dist/collection/server/paths.d.ts +0 -3
  15. package/dist/collection-watchers/index.cjs +79 -12
  16. package/dist/collection-watchers/index.cjs.map +1 -1
  17. package/dist/collection-watchers/index.d.ts +1 -1
  18. package/dist/collection-watchers/index.js +79 -13
  19. package/dist/collection-watchers/index.js.map +1 -1
  20. package/dist/collection-watchers/watcher.d.ts +23 -4
  21. package/dist/{discovery-BvnXyUel.js → discovery-4Z-ZWFam.js} +50 -21
  22. package/dist/discovery-4Z-ZWFam.js.map +1 -0
  23. package/dist/{discovery-B_sHig7n.cjs → discovery-CtiZMlsX.cjs} +67 -26
  24. package/dist/discovery-CtiZMlsX.cjs.map +1 -0
  25. package/dist/feeds/server/index.cjs +2 -2
  26. package/dist/feeds/server/index.js +2 -2
  27. package/dist/google/index.cjs +1 -1
  28. package/dist/google/index.js +1 -1
  29. package/dist/remote-host/server/index.cjs +37 -13
  30. package/dist/remote-host/server/index.cjs.map +1 -1
  31. package/dist/remote-host/server/index.js +37 -13
  32. package/dist/remote-host/server/index.js.map +1 -1
  33. package/dist/remote-host/server/monotonicClock.d.ts +3 -0
  34. package/dist/remote-host/server/presenceBeat.d.ts +3 -2
  35. package/dist/remote-host/server/resilientRunner.d.ts +6 -0
  36. package/dist/{server-DJt6USBQ.js → server-CedIocRS.js} +2 -2
  37. package/dist/{server-DJt6USBQ.js.map → server-CedIocRS.js.map} +1 -1
  38. package/dist/{server-DoyGZMPS.cjs → server-DOZFzx5l.cjs} +2 -2
  39. package/dist/{server-DoyGZMPS.cjs.map → server-DOZFzx5l.cjs.map} +1 -1
  40. package/package.json +1 -1
  41. package/dist/discovery-B_sHig7n.cjs.map +0 -1
  42. package/dist/discovery-BvnXyUel.js.map +0 -1
@@ -3,8 +3,8 @@ const require_rolldown_runtime = require("../../rolldown-runtime-VH7oDXx4.cjs");
3
3
  const require_dist = require("../../dist-CsgSfWwR.cjs");
4
4
  const require_calendarGrid = require("../../calendarGrid-p8K-7cuB.cjs");
5
5
  const require_project = require("../../project-C1ep9pvo.cjs");
6
- const require_discovery = require("../../discovery-B_sHig7n.cjs");
7
- const require_server = require("../../server-DoyGZMPS.cjs");
6
+ const require_discovery = require("../../discovery-CtiZMlsX.cjs");
7
+ const require_server = require("../../server-DOZFzx5l.cjs");
8
8
  const require_feeds_paths = require("../paths.cjs");
9
9
  const require_ingestTypes = require("../../ingestTypes-CPR-h-OZ.cjs");
10
10
  const require_notifier = require("../../notifier-DZJj0sOh.cjs");
@@ -1,8 +1,8 @@
1
1
  import { a as isErrorWithCode, l as isUnknownArray, s as isRecord$1 } from "../../dist-D8zokgGo.js";
2
2
  import { C as FEED_SCHEDULES, w as INGEST_KINDS } from "../../calendarGrid-Csy2rpjp.js";
3
3
  import { t as mergeIntoExisting } from "../../project-B0j_Vf_Q.js";
4
- import { N as listItems, V as resolveDataDir, W as safeSlugName, d as storeFor, et as createForwardingLogger, n as discoverCollections, tt as createHostSlot } from "../../discovery-BvnXyUel.js";
5
- import { A as buildCollectionActionSeedPrompt, P as readSkillTemplate, j as promptPathsFor } from "../../server-DJt6USBQ.js";
4
+ import { B as resolveDataDir, N as listItems, U as safeSlugName, d as storeFor, n as discoverCollections, nt as createForwardingLogger, rt as createHostSlot } from "../../discovery-4Z-ZWFam.js";
5
+ import { A as buildCollectionActionSeedPrompt, P as readSkillTemplate, j as promptPathsFor } from "../../server-CedIocRS.js";
6
6
  import { FEEDS_DIR, feedDir, feedStatePath, feedsRoot, ingestStateDir, ingestStatePath } from "../paths.js";
7
7
  import { n as DEFAULT_FEED_MAX_ITEMS, r as isFeedSchedule, t as AGENT_INGEST_KIND } from "../../ingestTypes-F2IJhOLJ.js";
8
8
  import { d as publish, n as clear } from "../../notifier-DhnwR82U.js";
@@ -6,7 +6,7 @@ const require_atomic = require("../atomic-DhUk8uiM.cjs");
6
6
  const require_utils_fetch = require("../utils/fetch.cjs");
7
7
  const require_calendarGrid = require("../calendarGrid-p8K-7cuB.cjs");
8
8
  const require_project = require("../project-C1ep9pvo.cjs");
9
- const require_discovery = require("../discovery-B_sHig7n.cjs");
9
+ const require_discovery = require("../discovery-CtiZMlsX.cjs");
10
10
  const require_paths = require("../paths-ClV946_f.cjs");
11
11
  let node_fs = require("node:fs");
12
12
  let node_path = require("node:path");
@@ -4,7 +4,7 @@ import { t as writeFileAtomic } from "../atomic-DPpdrJzO.js";
4
4
  import { fetchWithTimeout } from "../utils/fetch.js";
5
5
  import { l as parseIsoDate, u as parseIsoDateTime } from "../calendarGrid-Csy2rpjp.js";
6
6
  import { t as mergeIntoExisting } from "../project-B0j_Vf_Q.js";
7
- import { J as getWorkspaceRoot, d as storeFor, et as createForwardingLogger, n as discoverCollections, tt as createHostSlot } from "../discovery-BvnXyUel.js";
7
+ import { Y as getWorkspaceRoot, d as storeFor, n as discoverCollections, nt as createForwardingLogger, rt as createHostSlot } from "../discovery-4Z-ZWFam.js";
8
8
  import { t as mulmoConfigDir } from "../paths-CkJxNZ7T.js";
9
9
  import { promises } from "node:fs";
10
10
  import path, { join } from "node:path";
@@ -2,6 +2,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_dist = require("../../dist-CsgSfWwR.cjs");
3
3
  const require_remote_host = require("../../remote-host-CtQjagPt.cjs");
4
4
  let firebase_firestore = require("firebase/firestore");
5
+ let node_perf_hooks = require("node:perf_hooks");
5
6
  let firebase_auth = require("firebase/auth");
6
7
  let firebase_app = require("firebase/app");
7
8
  let firebase_storage = require("firebase/storage");
@@ -61,6 +62,11 @@ var matchesPathPattern = (path, pattern) => {
61
62
  */
62
63
  var unexpectedPaths = (paths, expected = []) => paths.filter((path) => !expected.some((pattern) => matchesPathPattern(path, pattern)));
63
64
  //#endregion
65
+ //#region src/remote-host/server/monotonicClock.ts
66
+ /** Milliseconds from an arbitrary origin, never moving backwards. Only differences
67
+ * between two readings mean anything — never compare one to a wall-clock time. */
68
+ var monotonicNowMs = () => node_perf_hooks.performance.now();
69
+ //#endregion
64
70
  //#region src/remote-host/server/presenceBeat.ts
65
71
  var PRESENCE_STALE_BEATS = 3;
66
72
  var errorText$1 = (error) => error instanceof Error ? error.message : String(error);
@@ -72,21 +78,25 @@ var notify = (report, onThrow) => {
72
78
  }
73
79
  };
74
80
  var createPresenceBeat = (deps) => {
75
- const now = deps.now ?? Date.now;
76
- const state = { lastAckMs: now() };
81
+ const now = deps.now ?? monotonicNowMs;
82
+ const state = {
83
+ lastAckMs: now(),
84
+ beatsSinceAck: 0
85
+ };
77
86
  const announce = (online) => {
78
87
  const fail = (error) => notify(() => deps.onError(errorText$1(error)));
79
88
  const ack = () => notify(() => {
80
89
  state.lastAckMs = now();
90
+ state.beatsSinceAck = 0;
81
91
  });
82
92
  notify(() => {
83
93
  deps.write(online).then(ack, fail);
84
94
  }, fail);
85
95
  };
86
96
  const beat = () => {
87
- const silentMs = now() - state.lastAckMs;
88
- if (silentMs >= deps.staleAfterMs) {
89
- notify(() => deps.onStale(silentMs));
97
+ state.beatsSinceAck += 1;
98
+ if (state.beatsSinceAck >= deps.staleAfterBeats) {
99
+ notify(() => deps.onStale(now() - state.lastAckMs));
90
100
  return;
91
101
  }
92
102
  announce(true);
@@ -241,7 +251,7 @@ function handleListenError(run, error) {
241
251
  message: error.message
242
252
  });
243
253
  if (run.stopped) return;
244
- const now = Date.now();
254
+ const now = monotonicNowMs();
245
255
  run.downSinceMs ??= now;
246
256
  if (classifyListenerError(error) === "fatal" || shouldGiveUpListening(run.downSinceMs, now)) {
247
257
  run.goOffline();
@@ -292,10 +302,10 @@ var buildPresenceBeat = (firestore, channel, handlers, options, onStale) => {
292
302
  }),
293
303
  onError: (message) => report(`presence write failed: ${message}`),
294
304
  onStale: (silentMs) => {
295
- report(`no presence write acknowledged for ${Math.round(silentMs / 1e3)}s — the remote cannot see this host`);
305
+ report(`no presence write acknowledged across 3 beats (${Math.round(silentMs / 1e3)}s) — the remote cannot see this host`);
296
306
  onStale();
297
307
  },
298
- staleAfterMs: presenceStaleAfterMs(options)
308
+ staleAfterBeats: 3
299
309
  });
300
310
  };
301
311
  var shutDown = (run, presence) => {
@@ -337,6 +347,7 @@ var RECONNECT_MAX_MS = ONE_MINUTE_MS;
337
347
  var SETTLE_MS = ONE_MINUTE_MS;
338
348
  var GIVE_UP_MS = 5 * ONE_MINUTE_MS;
339
349
  var PROBE_INTERVAL_MS = 90 * ONE_SECOND_MS$1;
350
+ var RESUME_GAP_MS = ONE_MINUTE_MS;
340
351
  var reconnectDelayMs = (attempt) => Math.min(RECONNECT_MAX_MS, RECONNECT_BASE_MS * 2 ** attempt);
341
352
  var errorText = (error) => error instanceof Error ? error.message : String(error);
342
353
  var scheduleWithTimeout = (task, delayMs) => {
@@ -349,7 +360,7 @@ var setState = (ctx, next) => {
349
360
  ctx.deps.onHealth?.({
350
361
  state: next,
351
362
  lastError: ctx.lastError,
352
- changedAt: ctx.now()
363
+ changedAt: ctx.wallNow()
353
364
  });
354
365
  } catch (error) {
355
366
  ctx.deps.log.warn(`host runner health observer threw: ${errorText(error)}`);
@@ -363,10 +374,22 @@ var clearProbe = (ctx) => {
363
374
  ctx.cancelProbe?.();
364
375
  ctx.cancelProbe = null;
365
376
  };
377
+ var after = (ctx, delayMs, task) => {
378
+ const dueMs = ctx.now() + delayMs;
379
+ return ctx.schedule(() => {
380
+ const overshootMs = ctx.now() - dueMs;
381
+ if (overshootMs > RESUME_GAP_MS) {
382
+ ctx.deps.log.warn(`host runner resumed after a ${Math.round(overshootMs / ONE_SECOND_MS$1)}s gap; that time does not count as outage`);
383
+ ctx.downSinceMs = null;
384
+ ctx.attempt = 0;
385
+ }
386
+ task();
387
+ }, delayMs);
388
+ };
366
389
  function scheduleProbe(ctx) {
367
390
  if (ctx.stopped || !ctx.deps.checkAlive) return;
368
391
  clearProbe(ctx);
369
- ctx.cancelProbe = ctx.schedule(() => void runProbe(ctx), PROBE_INTERVAL_MS);
392
+ ctx.cancelProbe = after(ctx, PROBE_INTERVAL_MS, () => void runProbe(ctx));
370
393
  }
371
394
  var STALE_REASON = "presence went stale — the phone can no longer see this host";
372
395
  async function askAlive(ctx) {
@@ -438,7 +461,7 @@ function scheduleRelaunch(ctx) {
438
461
  ctx.attempt += 1;
439
462
  ctx.deps.log.warn(`host runner closed (${ctx.lastError ?? "no error reported"}); re-subscribing in ${Math.round(delayMs / ONE_SECOND_MS$1)}s`);
440
463
  if (ctx.state !== "reconnecting") setState(ctx, "reconnecting");
441
- ctx.cancelTimer = ctx.schedule(() => launch(ctx), delayMs);
464
+ ctx.cancelTimer = after(ctx, delayMs, () => launch(ctx));
442
465
  }
443
466
  function onUnderlyingClosed(ctx) {
444
467
  if (ctx.stopped) return;
@@ -472,13 +495,14 @@ function launch(ctx) {
472
495
  onUnderlyingClosed(ctx);
473
496
  return;
474
497
  }
475
- ctx.cancelTimer = ctx.schedule(() => void settle(ctx), SETTLE_MS);
498
+ ctx.cancelTimer = after(ctx, SETTLE_MS, () => void settle(ctx));
476
499
  }
477
500
  function startResilientHostRunner(deps) {
478
501
  const ctx = {
479
502
  deps,
480
503
  schedule: deps.schedule ?? scheduleWithTimeout,
481
- now: deps.now ?? Date.now,
504
+ now: deps.now ?? monotonicNowMs,
505
+ wallNow: deps.wallNow ?? Date.now,
482
506
  stopUnderlying: null,
483
507
  cancelTimer: null,
484
508
  attempt: 0,