@adhdev/mesh-shared 1.0.60-rc.69 → 1.0.60-rc.70
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/index.d.ts +2 -0
- package/dist/index.js +405 -3
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +398 -3
- package/dist/index.mjs.map +1 -1
- package/dist/keyed-doc-delta.d.ts +83 -0
- package/dist/keyed-status-delta.d.ts +76 -0
- package/dist/protocol/daemon-server.d.ts +3 -10
- package/dist/protocol/dashboard-daemon-p2p.d.ts +14 -10
- package/package.json +1 -1
- package/src/index.ts +2 -0
- package/src/keyed-doc-delta.ts +348 -0
- package/src/keyed-status-delta.ts +239 -0
- package/src/protocol/daemon-server.ts +3 -10
- package/src/protocol/dashboard-daemon-p2p.ts +15 -7
package/dist/index.mjs
CHANGED
|
@@ -1228,7 +1228,6 @@ var DAEMON_TO_DASHBOARD_P2P_TYPES = [
|
|
|
1228
1228
|
"ping",
|
|
1229
1229
|
"pong",
|
|
1230
1230
|
"p2p_evicted",
|
|
1231
|
-
"status_report",
|
|
1232
1231
|
"status_event",
|
|
1233
1232
|
"topic_update",
|
|
1234
1233
|
"topic_update_chunk",
|
|
@@ -1237,7 +1236,8 @@ var DAEMON_TO_DASHBOARD_P2P_TYPES = [
|
|
|
1237
1236
|
"session_io_error",
|
|
1238
1237
|
"command_result",
|
|
1239
1238
|
"command_result_chunk",
|
|
1240
|
-
"response"
|
|
1239
|
+
"response",
|
|
1240
|
+
"transcript_topics_available"
|
|
1241
1241
|
];
|
|
1242
1242
|
var isDaemonToDashboardP2PType = makeTypeGuard(DAEMON_TO_DASHBOARD_P2P_TYPES);
|
|
1243
1243
|
function decodeDaemonToDashboardP2P(raw) {
|
|
@@ -1251,7 +1251,6 @@ function decodeDaemonToDashboardP2P(raw) {
|
|
|
1251
1251
|
case "pong":
|
|
1252
1252
|
case "p2p_evicted":
|
|
1253
1253
|
return raw;
|
|
1254
|
-
case "status_report":
|
|
1255
1254
|
case "status_event":
|
|
1256
1255
|
return isRecord(raw.payload) ? raw : null;
|
|
1257
1256
|
case "topic_update":
|
|
@@ -1273,6 +1272,8 @@ function decodeDaemonToDashboardP2P(raw) {
|
|
|
1273
1272
|
case "command_result":
|
|
1274
1273
|
case "response":
|
|
1275
1274
|
return isNonEmptyString(raw.id) ? raw : null;
|
|
1275
|
+
case "transcript_topics_available":
|
|
1276
|
+
return Array.isArray(raw.topics) && raw.topics.every((topic) => typeof topic === "string") ? { type: raw.type, topics: raw.topics } : null;
|
|
1276
1277
|
}
|
|
1277
1278
|
}
|
|
1278
1279
|
var DASHBOARD_P2P_MESSAGE_KINDS = [
|
|
@@ -3167,6 +3168,393 @@ function touchedFilesOutsideOwnership(touched, owned) {
|
|
|
3167
3168
|
const unusedDeclarations = owned.paths.map((p) => p.path).filter((p) => !usedDeclarations.has(p));
|
|
3168
3169
|
return { undeclaredTouched, unusedDeclarations };
|
|
3169
3170
|
}
|
|
3171
|
+
|
|
3172
|
+
// src/keyed-status-delta.ts
|
|
3173
|
+
function sig(value) {
|
|
3174
|
+
if (value === void 0) return void 0;
|
|
3175
|
+
try {
|
|
3176
|
+
return JSON.stringify(value);
|
|
3177
|
+
} catch {
|
|
3178
|
+
return void 0;
|
|
3179
|
+
}
|
|
3180
|
+
}
|
|
3181
|
+
function digestFields(source, ignore) {
|
|
3182
|
+
const sigs = /* @__PURE__ */ new Map();
|
|
3183
|
+
const values = {};
|
|
3184
|
+
for (const [key, value] of Object.entries(source)) {
|
|
3185
|
+
if (ignore.has(key)) continue;
|
|
3186
|
+
const s = sig(value);
|
|
3187
|
+
if (s === void 0) continue;
|
|
3188
|
+
sigs.set(key, s);
|
|
3189
|
+
values[key] = value;
|
|
3190
|
+
}
|
|
3191
|
+
return { sigs, values };
|
|
3192
|
+
}
|
|
3193
|
+
function sessionSignature(session, volatile) {
|
|
3194
|
+
if (volatile.size === 0) return sig(session) ?? "";
|
|
3195
|
+
const stable = {};
|
|
3196
|
+
for (const [key, value] of Object.entries(session)) {
|
|
3197
|
+
if (!volatile.has(key)) stable[key] = value;
|
|
3198
|
+
}
|
|
3199
|
+
return sig(stable) ?? "";
|
|
3200
|
+
}
|
|
3201
|
+
function fieldSigsOf(digest) {
|
|
3202
|
+
if (!digest.fieldSigs) {
|
|
3203
|
+
const sigs = /* @__PURE__ */ new Map();
|
|
3204
|
+
for (const [key, value] of Object.entries(digest.value)) {
|
|
3205
|
+
const s = sig(value);
|
|
3206
|
+
if (s !== void 0) sigs.set(key, s);
|
|
3207
|
+
}
|
|
3208
|
+
digest.fieldSigs = sigs;
|
|
3209
|
+
}
|
|
3210
|
+
return digest.fieldSigs;
|
|
3211
|
+
}
|
|
3212
|
+
function digestKeyedStatus(body, options = {}) {
|
|
3213
|
+
const volatile = new Set(options.volatileSessionFields ?? []);
|
|
3214
|
+
const top = digestFields(body, /* @__PURE__ */ new Set(["status", ...options.ignoreTopLevel ?? []]));
|
|
3215
|
+
const status = digestFields(body.status, /* @__PURE__ */ new Set(["sessions", ...options.ignoreStatus ?? []]));
|
|
3216
|
+
const sessions = /* @__PURE__ */ new Map();
|
|
3217
|
+
const order = [];
|
|
3218
|
+
for (const session of Array.isArray(body.status?.sessions) ? body.status.sessions : []) {
|
|
3219
|
+
if (!session || typeof session.id !== "string" || !session.id) continue;
|
|
3220
|
+
if (sessions.has(session.id)) continue;
|
|
3221
|
+
sessions.set(session.id, { value: session, sig: sessionSignature(session, volatile) });
|
|
3222
|
+
order.push(session.id);
|
|
3223
|
+
}
|
|
3224
|
+
return { top: top.sigs, topValues: top.values, status: status.sigs, statusValues: status.values, sessions, order, volatile };
|
|
3225
|
+
}
|
|
3226
|
+
function diffFieldMaps(prev, next, nextValues) {
|
|
3227
|
+
let set;
|
|
3228
|
+
let unset;
|
|
3229
|
+
for (const [key, s] of next) {
|
|
3230
|
+
if (prev.get(key) === s) continue;
|
|
3231
|
+
(set ??= {})[key] = nextValues[key];
|
|
3232
|
+
}
|
|
3233
|
+
for (const key of prev.keys()) {
|
|
3234
|
+
if (!next.has(key)) (unset ??= []).push(key);
|
|
3235
|
+
}
|
|
3236
|
+
return { ...set ? { set } : {}, ...unset ? { unset } : {} };
|
|
3237
|
+
}
|
|
3238
|
+
function sameOrder(a, b) {
|
|
3239
|
+
if (a.length !== b.length) return false;
|
|
3240
|
+
for (let i = 0; i < a.length; i += 1) if (a[i] !== b[i]) return false;
|
|
3241
|
+
return true;
|
|
3242
|
+
}
|
|
3243
|
+
function diffKeyedStatus(prev, next) {
|
|
3244
|
+
const delta = {};
|
|
3245
|
+
const top = diffFieldMaps(prev.top, next.top, next.topValues);
|
|
3246
|
+
if (top.set) delta.set = top.set;
|
|
3247
|
+
if (top.unset) delta.unset = top.unset;
|
|
3248
|
+
const status = diffFieldMaps(prev.status, next.status, next.statusValues);
|
|
3249
|
+
if (status.set) delta.statusSet = status.set;
|
|
3250
|
+
if (status.unset) delta.statusUnset = status.unset;
|
|
3251
|
+
for (const [id2, nextSession] of next.sessions) {
|
|
3252
|
+
const prevSession = prev.sessions.get(id2);
|
|
3253
|
+
if (!prevSession) {
|
|
3254
|
+
;
|
|
3255
|
+
(delta.sessions ??= []).push(nextSession.value);
|
|
3256
|
+
continue;
|
|
3257
|
+
}
|
|
3258
|
+
if (prevSession.sig === nextSession.sig) continue;
|
|
3259
|
+
const prevSigs = fieldSigsOf(prevSession);
|
|
3260
|
+
const nextSigs = fieldSigsOf(nextSession);
|
|
3261
|
+
const change = { id: id2 };
|
|
3262
|
+
let changed = false;
|
|
3263
|
+
for (const [key, s] of nextSigs) {
|
|
3264
|
+
if (key === "id" || prevSigs.get(key) === s) continue;
|
|
3265
|
+
change[key] = nextSession.value[key];
|
|
3266
|
+
changed = true;
|
|
3267
|
+
}
|
|
3268
|
+
const gone = [];
|
|
3269
|
+
for (const key of prevSigs.keys()) {
|
|
3270
|
+
if (!nextSigs.has(key)) gone.push(key);
|
|
3271
|
+
}
|
|
3272
|
+
if (changed) (delta.sessions ??= []).push(change);
|
|
3273
|
+
if (gone.length > 0) (delta.sessionUnset ??= {})[id2] = gone;
|
|
3274
|
+
}
|
|
3275
|
+
for (const id2 of prev.sessions.keys()) {
|
|
3276
|
+
if (!next.sessions.has(id2)) (delta.removedSessionIds ??= []).push(id2);
|
|
3277
|
+
}
|
|
3278
|
+
if (!sameOrder(prev.order, next.order)) delta.sessionOrder = [...next.order];
|
|
3279
|
+
return Object.keys(delta).length > 0 ? delta : null;
|
|
3280
|
+
}
|
|
3281
|
+
function foldKeyedStatus(held, delta) {
|
|
3282
|
+
const next = { ...held };
|
|
3283
|
+
for (const key of delta.unset ?? []) delete next[key];
|
|
3284
|
+
Object.assign(next, delta.set ?? {});
|
|
3285
|
+
const status = { ...held.status };
|
|
3286
|
+
for (const key of delta.statusUnset ?? []) delete status[key];
|
|
3287
|
+
Object.assign(status, delta.statusSet ?? {});
|
|
3288
|
+
const byId = /* @__PURE__ */ new Map();
|
|
3289
|
+
for (const session of held.status.sessions ?? []) byId.set(session.id, session);
|
|
3290
|
+
for (const id2 of delta.removedSessionIds ?? []) byId.delete(id2);
|
|
3291
|
+
for (const change of delta.sessions ?? []) {
|
|
3292
|
+
const base = byId.get(change.id);
|
|
3293
|
+
byId.set(change.id, base ? { ...base, ...change } : { ...change });
|
|
3294
|
+
}
|
|
3295
|
+
for (const [id2, keys] of Object.entries(delta.sessionUnset ?? {})) {
|
|
3296
|
+
const base = byId.get(id2);
|
|
3297
|
+
if (!base) continue;
|
|
3298
|
+
const trimmed = { ...base };
|
|
3299
|
+
for (const key of keys) delete trimmed[key];
|
|
3300
|
+
byId.set(id2, trimmed);
|
|
3301
|
+
}
|
|
3302
|
+
const order = delta.sessionOrder ?? (held.status.sessions ?? []).map((session) => session.id);
|
|
3303
|
+
const sessions = [];
|
|
3304
|
+
const placed = /* @__PURE__ */ new Set();
|
|
3305
|
+
for (const id2 of order) {
|
|
3306
|
+
const session = byId.get(id2);
|
|
3307
|
+
if (!session || placed.has(id2)) continue;
|
|
3308
|
+
sessions.push(session);
|
|
3309
|
+
placed.add(id2);
|
|
3310
|
+
}
|
|
3311
|
+
for (const [id2, session] of byId) {
|
|
3312
|
+
if (!placed.has(id2)) sessions.push(session);
|
|
3313
|
+
}
|
|
3314
|
+
status.sessions = sessions;
|
|
3315
|
+
next.status = status;
|
|
3316
|
+
return next;
|
|
3317
|
+
}
|
|
3318
|
+
|
|
3319
|
+
// src/keyed-doc-delta.ts
|
|
3320
|
+
function sig2(value) {
|
|
3321
|
+
if (value === void 0) return void 0;
|
|
3322
|
+
try {
|
|
3323
|
+
return JSON.stringify(value);
|
|
3324
|
+
} catch {
|
|
3325
|
+
return void 0;
|
|
3326
|
+
}
|
|
3327
|
+
}
|
|
3328
|
+
function isRecord3(value) {
|
|
3329
|
+
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
3330
|
+
}
|
|
3331
|
+
function readPath(doc, path) {
|
|
3332
|
+
const [head, tail] = splitPath(path);
|
|
3333
|
+
if (!tail) return doc[head];
|
|
3334
|
+
const parent = doc[head];
|
|
3335
|
+
return isRecord3(parent) ? parent[tail] : void 0;
|
|
3336
|
+
}
|
|
3337
|
+
function splitPath(path) {
|
|
3338
|
+
const dot = path.indexOf(".");
|
|
3339
|
+
return dot < 0 ? [path, void 0] : [path.slice(0, dot), path.slice(dot + 1)];
|
|
3340
|
+
}
|
|
3341
|
+
function stripCollections(doc, spec) {
|
|
3342
|
+
const out = { ...doc };
|
|
3343
|
+
for (const path of Object.keys(spec.collections)) {
|
|
3344
|
+
const [head, tail] = splitPath(path);
|
|
3345
|
+
if (!tail) {
|
|
3346
|
+
delete out[head];
|
|
3347
|
+
continue;
|
|
3348
|
+
}
|
|
3349
|
+
const parent = out[head];
|
|
3350
|
+
if (!isRecord3(parent) || !(tail in parent)) continue;
|
|
3351
|
+
const copy = { ...parent };
|
|
3352
|
+
delete copy[tail];
|
|
3353
|
+
out[head] = copy;
|
|
3354
|
+
}
|
|
3355
|
+
return out;
|
|
3356
|
+
}
|
|
3357
|
+
function fieldSigsOf2(digest) {
|
|
3358
|
+
if (!digest.fieldSigs) {
|
|
3359
|
+
const sigs = /* @__PURE__ */ new Map();
|
|
3360
|
+
for (const [key, value] of Object.entries(digest.stable)) {
|
|
3361
|
+
const s = sig2(value);
|
|
3362
|
+
if (s !== void 0) sigs.set(key, s);
|
|
3363
|
+
}
|
|
3364
|
+
digest.fieldSigs = sigs;
|
|
3365
|
+
}
|
|
3366
|
+
return digest.fieldSigs;
|
|
3367
|
+
}
|
|
3368
|
+
function digestKeyedDoc(doc, spec) {
|
|
3369
|
+
const top = /* @__PURE__ */ new Map();
|
|
3370
|
+
const topValues = {};
|
|
3371
|
+
for (const [key, value] of Object.entries(stripCollections(doc, spec))) {
|
|
3372
|
+
const s = sig2(value);
|
|
3373
|
+
if (s === void 0) continue;
|
|
3374
|
+
top.set(key, s);
|
|
3375
|
+
topValues[key] = value;
|
|
3376
|
+
}
|
|
3377
|
+
const collections = /* @__PURE__ */ new Map();
|
|
3378
|
+
for (const [path, idField] of Object.entries(spec.collections)) {
|
|
3379
|
+
const list = readPath(doc, path);
|
|
3380
|
+
if (!Array.isArray(list)) continue;
|
|
3381
|
+
const rows = /* @__PURE__ */ new Map();
|
|
3382
|
+
const order = [];
|
|
3383
|
+
for (const row of list) {
|
|
3384
|
+
if (!isRecord3(row)) continue;
|
|
3385
|
+
const id2 = row[idField];
|
|
3386
|
+
if (typeof id2 !== "string" || !id2 || rows.has(id2)) continue;
|
|
3387
|
+
const stable = spec.stableRow ? spec.stableRow(path, row) : row;
|
|
3388
|
+
rows.set(id2, { value: row, stable, sig: sig2(stable) ?? "" });
|
|
3389
|
+
order.push(id2);
|
|
3390
|
+
}
|
|
3391
|
+
collections.set(path, { rows, order });
|
|
3392
|
+
}
|
|
3393
|
+
return { top, topValues, collections, volatile: new Set(spec.volatileTopLevel ?? []) };
|
|
3394
|
+
}
|
|
3395
|
+
function sameOrder2(a, b) {
|
|
3396
|
+
if (a.length !== b.length) return false;
|
|
3397
|
+
for (let i = 0; i < a.length; i += 1) if (a[i] !== b[i]) return false;
|
|
3398
|
+
return true;
|
|
3399
|
+
}
|
|
3400
|
+
function diffCollection(prev, next, idField) {
|
|
3401
|
+
if (!next) return prev ? { absent: true } : null;
|
|
3402
|
+
const delta = {};
|
|
3403
|
+
const prevRows = prev?.rows ?? /* @__PURE__ */ new Map();
|
|
3404
|
+
const nextRows = next?.rows ?? /* @__PURE__ */ new Map();
|
|
3405
|
+
for (const [id2, nextRow] of nextRows) {
|
|
3406
|
+
const prevRow = prevRows.get(id2);
|
|
3407
|
+
if (!prevRow) {
|
|
3408
|
+
;
|
|
3409
|
+
(delta.upsert ??= []).push(nextRow.value);
|
|
3410
|
+
continue;
|
|
3411
|
+
}
|
|
3412
|
+
if (prevRow.sig === nextRow.sig) continue;
|
|
3413
|
+
const prevSigs = fieldSigsOf2(prevRow);
|
|
3414
|
+
const nextSigs = fieldSigsOf2(nextRow);
|
|
3415
|
+
const change = { [idField]: id2 };
|
|
3416
|
+
let changed = false;
|
|
3417
|
+
for (const [key, s] of nextSigs) {
|
|
3418
|
+
if (key === idField || prevSigs.get(key) === s) continue;
|
|
3419
|
+
change[key] = nextRow.value[key];
|
|
3420
|
+
changed = true;
|
|
3421
|
+
}
|
|
3422
|
+
const gone = [];
|
|
3423
|
+
for (const key of prevSigs.keys()) if (!nextSigs.has(key) && !(key in nextRow.value)) gone.push(key);
|
|
3424
|
+
if (changed) (delta.upsert ??= []).push(change);
|
|
3425
|
+
if (gone.length > 0) (delta.unsetFields ??= {})[id2] = gone;
|
|
3426
|
+
}
|
|
3427
|
+
for (const id2 of prevRows.keys()) {
|
|
3428
|
+
if (!nextRows.has(id2)) (delta.removed ??= []).push(id2);
|
|
3429
|
+
}
|
|
3430
|
+
if (!sameOrder2(prev?.order ?? [], next?.order ?? [])) delta.order = [...next?.order ?? []];
|
|
3431
|
+
return Object.keys(delta).length > 0 ? delta : null;
|
|
3432
|
+
}
|
|
3433
|
+
function diffKeyedDoc(prev, next, spec) {
|
|
3434
|
+
const delta = {};
|
|
3435
|
+
let meaningful = false;
|
|
3436
|
+
let set;
|
|
3437
|
+
let unset;
|
|
3438
|
+
for (const [key, s] of next.top) {
|
|
3439
|
+
if (prev.top.get(key) === s) continue;
|
|
3440
|
+
(set ??= {})[key] = next.topValues[key];
|
|
3441
|
+
if (!next.volatile.has(key)) meaningful = true;
|
|
3442
|
+
}
|
|
3443
|
+
for (const key of prev.top.keys()) {
|
|
3444
|
+
if (next.top.has(key)) continue;
|
|
3445
|
+
(unset ??= []).push(key);
|
|
3446
|
+
if (!next.volatile.has(key)) meaningful = true;
|
|
3447
|
+
}
|
|
3448
|
+
for (const [path, idField] of Object.entries(spec.collections)) {
|
|
3449
|
+
const change = diffCollection(prev.collections.get(path), next.collections.get(path), idField);
|
|
3450
|
+
if (!change) continue;
|
|
3451
|
+
(delta.collections ??= {})[path] = change;
|
|
3452
|
+
meaningful = true;
|
|
3453
|
+
}
|
|
3454
|
+
if (!meaningful) return null;
|
|
3455
|
+
if (set) delta.set = set;
|
|
3456
|
+
if (unset) delta.unset = unset;
|
|
3457
|
+
return delta;
|
|
3458
|
+
}
|
|
3459
|
+
function foldCollection(held, change, idField) {
|
|
3460
|
+
const byId = /* @__PURE__ */ new Map();
|
|
3461
|
+
const heldOrder = [];
|
|
3462
|
+
for (const row of Array.isArray(held) ? held : []) {
|
|
3463
|
+
if (!isRecord3(row) || typeof row[idField] !== "string") continue;
|
|
3464
|
+
byId.set(row[idField], row);
|
|
3465
|
+
heldOrder.push(row[idField]);
|
|
3466
|
+
}
|
|
3467
|
+
for (const id2 of change.removed ?? []) byId.delete(id2);
|
|
3468
|
+
for (const row of change.upsert ?? []) {
|
|
3469
|
+
const id2 = row[idField];
|
|
3470
|
+
if (typeof id2 !== "string") continue;
|
|
3471
|
+
const base = byId.get(id2);
|
|
3472
|
+
byId.set(id2, base ? { ...base, ...row } : { ...row });
|
|
3473
|
+
}
|
|
3474
|
+
for (const [id2, keys] of Object.entries(change.unsetFields ?? {})) {
|
|
3475
|
+
const base = byId.get(id2);
|
|
3476
|
+
if (!base) continue;
|
|
3477
|
+
const trimmed = { ...base };
|
|
3478
|
+
for (const key of keys) delete trimmed[key];
|
|
3479
|
+
byId.set(id2, trimmed);
|
|
3480
|
+
}
|
|
3481
|
+
const order = change.order ?? heldOrder;
|
|
3482
|
+
const out = [];
|
|
3483
|
+
const placed = /* @__PURE__ */ new Set();
|
|
3484
|
+
for (const id2 of order) {
|
|
3485
|
+
const row = byId.get(id2);
|
|
3486
|
+
if (!row || placed.has(id2)) continue;
|
|
3487
|
+
out.push(row);
|
|
3488
|
+
placed.add(id2);
|
|
3489
|
+
}
|
|
3490
|
+
for (const [id2, row] of byId) if (!placed.has(id2)) out.push(row);
|
|
3491
|
+
return out;
|
|
3492
|
+
}
|
|
3493
|
+
function foldKeyedDoc(held, delta, spec) {
|
|
3494
|
+
const heldCollections = /* @__PURE__ */ new Map();
|
|
3495
|
+
for (const path of Object.keys(spec.collections)) heldCollections.set(path, readPath(held, path));
|
|
3496
|
+
const next = stripCollections(held, spec);
|
|
3497
|
+
for (const key of delta.unset ?? []) delete next[key];
|
|
3498
|
+
Object.assign(next, delta.set ?? {});
|
|
3499
|
+
for (const [path, idField] of Object.entries(spec.collections)) {
|
|
3500
|
+
const change = delta.collections?.[path];
|
|
3501
|
+
const heldList = heldCollections.get(path);
|
|
3502
|
+
if (change?.absent) {
|
|
3503
|
+
const [head2, tail2] = splitPath(path);
|
|
3504
|
+
if (!tail2) delete next[head2];
|
|
3505
|
+
continue;
|
|
3506
|
+
}
|
|
3507
|
+
if (!change && heldList === void 0) continue;
|
|
3508
|
+
const list = change ? foldCollection(heldList, change, idField) : heldList;
|
|
3509
|
+
const [head, tail] = splitPath(path);
|
|
3510
|
+
if (!tail) {
|
|
3511
|
+
next[head] = list;
|
|
3512
|
+
continue;
|
|
3513
|
+
}
|
|
3514
|
+
const parent = isRecord3(next[head]) ? { ...next[head] } : {};
|
|
3515
|
+
parent[tail] = list;
|
|
3516
|
+
next[head] = parent;
|
|
3517
|
+
}
|
|
3518
|
+
return next;
|
|
3519
|
+
}
|
|
3520
|
+
var MESH_STATUS_DOC_SPEC = {
|
|
3521
|
+
collections: { nodes: "nodeId", "queue.tasks": "id", missions: "id" },
|
|
3522
|
+
volatileTopLevel: [
|
|
3523
|
+
"refreshedAt",
|
|
3524
|
+
"sourceOfTruth",
|
|
3525
|
+
"turnPresentationCounters",
|
|
3526
|
+
"meshProtocolV2Counters",
|
|
3527
|
+
"pendingRetentionCounters",
|
|
3528
|
+
"meshProtocolMetrics"
|
|
3529
|
+
],
|
|
3530
|
+
stableRow: (collection, row) => collection === "nodes" ? stableMeshNodeRow(row) : row
|
|
3531
|
+
};
|
|
3532
|
+
function without(value, keys) {
|
|
3533
|
+
if (!isRecord3(value)) return value;
|
|
3534
|
+
const out = { ...value };
|
|
3535
|
+
for (const key of keys) delete out[key];
|
|
3536
|
+
return out;
|
|
3537
|
+
}
|
|
3538
|
+
function stableMeshNodeRow(row) {
|
|
3539
|
+
const out = { ...row };
|
|
3540
|
+
delete out.lastSeenAt;
|
|
3541
|
+
delete out.updatedAt;
|
|
3542
|
+
delete out.last_seen_at;
|
|
3543
|
+
delete out.updated_at;
|
|
3544
|
+
if ("dataFreshness" in out) out.dataFreshness = without(out.dataFreshness, ["ageMs", "lastProbeAt", "staleness"]);
|
|
3545
|
+
if ("connection" in out) out.connection = without(out.connection, ["lastStateChangeAt"]);
|
|
3546
|
+
if ("git" in out) {
|
|
3547
|
+
const git = without(out.git, ["lastCheckedAt"]);
|
|
3548
|
+
if (isRecord3(git) && Array.isArray(git.submodules) && git.submodules.length === 0) delete git.submodules;
|
|
3549
|
+
out.git = git;
|
|
3550
|
+
}
|
|
3551
|
+
if ("nodeFacts" in out) out.nodeFacts = without(out.nodeFacts, ["reportedAt"]);
|
|
3552
|
+
const observation = out.gitObservation;
|
|
3553
|
+
if (isRecord3(observation) && (observation.source === "self" || observation.source === "local")) {
|
|
3554
|
+
out.gitObservation = without(observation, ["observedAt"]);
|
|
3555
|
+
}
|
|
3556
|
+
return out;
|
|
3557
|
+
}
|
|
3170
3558
|
export {
|
|
3171
3559
|
CANCEL_REASONS,
|
|
3172
3560
|
CANONICAL_MESH_TOOL_COUNT,
|
|
@@ -3212,6 +3600,7 @@ export {
|
|
|
3212
3600
|
MESH_P2P_SIGNAL_TYPES,
|
|
3213
3601
|
MESH_RECORD_PAYLOAD_KEYS,
|
|
3214
3602
|
MESH_SESSION_CLEANUP_MODES,
|
|
3603
|
+
MESH_STATUS_DOC_SPEC,
|
|
3215
3604
|
MESH_TASK_DIFFICULTIES,
|
|
3216
3605
|
MESH_TASK_MODES,
|
|
3217
3606
|
MESH_TASK_PRIORITIES,
|
|
@@ -3362,10 +3751,16 @@ export {
|
|
|
3362
3751
|
deriveProviderPriorityFromSlots,
|
|
3363
3752
|
deriveSlotsFromLegacy,
|
|
3364
3753
|
describeModelSelection,
|
|
3754
|
+
diffKeyedDoc,
|
|
3755
|
+
diffKeyedStatus,
|
|
3756
|
+
digestKeyedDoc,
|
|
3757
|
+
digestKeyedStatus,
|
|
3365
3758
|
effectiveModelSelectionValue,
|
|
3366
3759
|
enumOf,
|
|
3367
3760
|
expandDaemonIdForms,
|
|
3368
3761
|
findOwnershipConflicts,
|
|
3762
|
+
foldKeyedDoc,
|
|
3763
|
+
foldKeyedStatus,
|
|
3369
3764
|
formatQuotaAccount,
|
|
3370
3765
|
hasGitStatusEvidence,
|
|
3371
3766
|
hasWorkerProtocolFooter,
|