@mulmoclaude/core 3.0.0 → 3.1.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/assets/helps/collection-skills.md +72 -8
- package/assets/helps/custom-view.md +9 -1
- package/assets/helps/error-recovery.md +36 -0
- package/assets/helps/feeds.md +6 -4
- package/dist/calendarGrid-Csy2rpjp.js.map +1 -1
- package/dist/calendarGrid-p8K-7cuB.cjs.map +1 -1
- package/dist/collection/core/presentCollection.d.ts +49 -0
- package/dist/collection/core/schema.d.ts +16 -1
- package/dist/collection/index.cjs +56 -7
- package/dist/collection/index.cjs.map +1 -1
- package/dist/collection/index.js +53 -8
- package/dist/collection/index.js.map +1 -1
- package/dist/collection/registry/server/importWriter.d.ts +2 -1
- package/dist/collection/registry/server/index.cjs +31 -10
- package/dist/collection/registry/server/index.cjs.map +1 -1
- package/dist/collection/registry/server/index.js +30 -9
- package/dist/collection/registry/server/index.js.map +1 -1
- package/dist/collection/server/host.d.ts +34 -4
- package/dist/collection/server/index.cjs +4 -2
- package/dist/collection/server/index.d.ts +1 -1
- package/dist/collection/server/index.js +4 -3
- package/dist/collection/server/manageTool.d.ts +19 -0
- package/dist/collection/server/schemaDocs.d.ts +5 -1
- package/dist/collection-watchers/config.d.ts +15 -2
- package/dist/collection-watchers/index.cjs +310 -198
- package/dist/collection-watchers/index.cjs.map +1 -1
- package/dist/collection-watchers/index.js +310 -198
- package/dist/collection-watchers/index.js.map +1 -1
- package/dist/collection-watchers/reconciler.d.ts +1 -5
- package/dist/collection-watchers/watcher.d.ts +31 -26
- package/dist/{discovery-4Z-ZWFam.js → discovery-CC7kuwHf.js} +21 -7
- package/dist/discovery-CC7kuwHf.js.map +1 -0
- package/dist/{discovery-CtiZMlsX.cjs → discovery-CDOjfctD.cjs} +33 -7
- package/dist/discovery-CDOjfctD.cjs.map +1 -0
- package/dist/feeds/server/index.cjs +26 -6
- package/dist/feeds/server/index.cjs.map +1 -1
- package/dist/feeds/server/index.d.ts +1 -1
- package/dist/feeds/server/index.js +26 -7
- package/dist/feeds/server/index.js.map +1 -1
- package/dist/feeds/server/scheduledRefresh.d.ts +16 -1
- package/dist/files/index.cjs +6 -5
- package/dist/files/index.cjs.map +1 -1
- package/dist/files/index.d.ts +1 -0
- package/dist/files/index.js +2 -2
- package/dist/files/root.d.ts +15 -0
- package/dist/google/index.cjs +3 -3
- package/dist/google/index.cjs.map +1 -1
- package/dist/google/index.js +2 -2
- package/dist/remote-host/index.cjs +3 -1
- package/dist/remote-host/index.d.ts +30 -0
- package/dist/remote-host/index.js +2 -2
- package/dist/remote-host/server/index.cjs +38 -14
- package/dist/remote-host/server/index.cjs.map +1 -1
- package/dist/remote-host/server/index.js +38 -14
- package/dist/remote-host/server/index.js.map +1 -1
- package/dist/remote-host/server/monotonicClock.d.ts +3 -0
- package/dist/remote-host/server/presenceBeat.d.ts +3 -2
- package/dist/remote-host/server/resilientRunner.d.ts +6 -0
- package/dist/{remote-host-Dba4lF3Z.js → remote-host-CFnl1I-L.js} +35 -2
- package/dist/{remote-host-Dba4lF3Z.js.map → remote-host-CFnl1I-L.js.map} +1 -1
- package/dist/{remote-host-CtQjagPt.cjs → remote-host-EQPlccB9.cjs} +46 -1
- package/dist/{remote-host-CtQjagPt.cjs.map → remote-host-EQPlccB9.cjs.map} +1 -1
- package/dist/{atomic-DPpdrJzO.js → root-BMroU_mB.js} +21 -2
- package/dist/root-BMroU_mB.js.map +1 -0
- package/dist/{atomic-DhUk8uiM.cjs → root-rPH6FGDT.cjs} +26 -1
- package/dist/root-rPH6FGDT.cjs.map +1 -0
- package/dist/{server-CedIocRS.js → server-AA2kfDfk.js} +137 -42
- package/dist/server-AA2kfDfk.js.map +1 -0
- package/dist/{server-DOZFzx5l.cjs → server-WU35UYlF.cjs} +138 -43
- package/dist/server-WU35UYlF.cjs.map +1 -0
- package/package.json +1 -1
- package/dist/atomic-DPpdrJzO.js.map +0 -1
- package/dist/atomic-DhUk8uiM.cjs.map +0 -1
- package/dist/discovery-4Z-ZWFam.js.map +0 -1
- package/dist/discovery-CtiZMlsX.cjs.map +0 -1
- package/dist/server-CedIocRS.js.map +0 -1
- package/dist/server-DOZFzx5l.cjs.map +0 -1
package/dist/google/index.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { i as hasStringProp, t as errorMessage } from "../dist-D8zokgGo.js";
|
|
2
2
|
import { t as truncate } from "../text-CjDbP2O1.js";
|
|
3
|
-
import {
|
|
3
|
+
import { n as writeFileAtomic } from "../root-BMroU_mB.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 { Y as getWorkspaceRoot,
|
|
7
|
+
import { Y as getWorkspaceRoot, at as createHostSlot, d as storeFor, it as createForwardingLogger, n as discoverCollections } from "../discovery-CC7kuwHf.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";
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_remote_host = require("../remote-host-
|
|
2
|
+
const require_remote_host = require("../remote-host-EQPlccB9.cjs");
|
|
3
|
+
exports.COMMAND_SCOPE_PARAM = require_remote_host.COMMAND_SCOPE_PARAM;
|
|
3
4
|
exports.REMOTE_HOST_PROTOCOL_VERSION = require_remote_host.REMOTE_HOST_PROTOCOL_VERSION;
|
|
4
5
|
exports.RUNNER_HEALTH_STATES = require_remote_host.RUNNER_HEALTH_STATES;
|
|
5
6
|
exports.buildHostPresence = require_remote_host.buildHostPresence;
|
|
@@ -10,4 +11,5 @@ exports.hostDoc = require_remote_host.hostDoc;
|
|
|
10
11
|
exports.isExpired = require_remote_host.isExpired;
|
|
11
12
|
exports.isRunnerHealth = require_remote_host.isRunnerHealth;
|
|
12
13
|
exports.isRunnerHealthState = require_remote_host.isRunnerHealthState;
|
|
14
|
+
exports.readCommandScope = require_remote_host.readCommandScope;
|
|
13
15
|
exports.toJsonObject = require_remote_host.toJsonObject;
|
|
@@ -58,6 +58,36 @@ export declare const isExpired: (command: Pick<Command, "expiresAt">, now: numbe
|
|
|
58
58
|
export declare const byCreatedAt: (left: Pick<Command, "createdAt">, right: Pick<Command, "createdAt">) => number;
|
|
59
59
|
export type CommandHandler = (params: JsonObject) => JsonValue | Promise<JsonValue>;
|
|
60
60
|
export type CommandHandlers = Record<string, CommandHandler>;
|
|
61
|
+
/** The param name a collection-serving command uses to say WHICH project's
|
|
62
|
+
* collections it means. Reserved and documented now, before a phone client
|
|
63
|
+
* ships, because the parts that are hard to change later are the ones being
|
|
64
|
+
* written today. Four rules go with it:
|
|
65
|
+
*
|
|
66
|
+
* 1. **It is an OPAQUE scope, never a path.** The phone is a genuinely remote
|
|
67
|
+
* client; an absolute root in a command, an artifact or a token publishes
|
|
68
|
+
* the user's home directory over the wire. Mint a project id host-side and
|
|
69
|
+
* resolve it host-side.
|
|
70
|
+
* 2. **The phone must be able to LEARN the list.** A picker needs
|
|
71
|
+
* `{ id, label }` pairs from the host — a command of its own, or a field on
|
|
72
|
+
* an existing listing. Designing the scope value now is what keeps that the
|
|
73
|
+
* ONLY new thing when the feature lands.
|
|
74
|
+
* 3. **Handlers RESOLVE a scope; they do not hard-code one.** Write each
|
|
75
|
+
* collection handler as "read the scope from params, defaulting to the
|
|
76
|
+
* host's root" rather than calling the workspace accessor inline. Today
|
|
77
|
+
* every call resolves the default and behaves exactly as it does now; the
|
|
78
|
+
* day the param arrives, no handler changes.
|
|
79
|
+
* 4. **The artifact stays host-built.** A remote view's srcdoc, its inlined
|
|
80
|
+
* image thumbnails and its token are assembled on the host, so the phone
|
|
81
|
+
* never resolves a path itself. That is what makes (1) hold without
|
|
82
|
+
* trusting the client. */
|
|
83
|
+
export declare const COMMAND_SCOPE_PARAM = "project";
|
|
84
|
+
/** Read the opaque project scope off a command's params, or `undefined` for
|
|
85
|
+
* "the host's own root" — which is what every command means today. A
|
|
86
|
+
* non-string (or empty) value is treated as absent rather than as an error: a
|
|
87
|
+
* scope the host cannot resolve must fall back to the default, never to a
|
|
88
|
+
* guess. Hosts pass the result to their own id → root resolver; this module
|
|
89
|
+
* deliberately never sees a path. */
|
|
90
|
+
export declare const readCommandScope: (params: JsonObject) => string | undefined;
|
|
61
91
|
export declare const REMOTE_HOST_PROTOCOL_VERSION = 2;
|
|
62
92
|
export interface HostPresence {
|
|
63
93
|
online: boolean;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as
|
|
2
|
-
export { REMOTE_HOST_PROTOCOL_VERSION, RUNNER_HEALTH_STATES, buildHostPresence, byCreatedAt, coerceJsonObject, commandsCollection, hostDoc, isExpired, isRunnerHealth, isRunnerHealthState, toJsonObject };
|
|
1
|
+
import { a as coerceJsonObject, c as isExpired, d as RUNNER_HEALTH_STATES, f as isRunnerHealth, i as byCreatedAt, l as readCommandScope, n as REMOTE_HOST_PROTOCOL_VERSION, o as commandsCollection, p as isRunnerHealthState, r as buildHostPresence, s as hostDoc, t as COMMAND_SCOPE_PARAM, u as toJsonObject } from "../remote-host-CFnl1I-L.js";
|
|
2
|
+
export { COMMAND_SCOPE_PARAM, REMOTE_HOST_PROTOCOL_VERSION, RUNNER_HEALTH_STATES, buildHostPresence, byCreatedAt, coerceJsonObject, commandsCollection, hostDoc, isExpired, isRunnerHealth, isRunnerHealthState, readCommandScope, toJsonObject };
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
const require_dist = require("../../dist-CsgSfWwR.cjs");
|
|
3
|
-
const require_remote_host = require("../../remote-host-
|
|
3
|
+
const require_remote_host = require("../../remote-host-EQPlccB9.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 ??
|
|
76
|
-
const state = {
|
|
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
|
-
|
|
88
|
-
if (
|
|
89
|
-
notify(() => deps.onStale(
|
|
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 =
|
|
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
|
|
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
|
-
|
|
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.
|
|
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
|
|
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
|
|
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
|
|
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 ??
|
|
504
|
+
now: deps.now ?? monotonicNowMs,
|
|
505
|
+
wallNow: deps.wallNow ?? Date.now,
|
|
482
506
|
stopUnderlying: null,
|
|
483
507
|
cancelTimer: null,
|
|
484
508
|
attempt: 0,
|