@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.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,