@anuma/sdk 6.39.3 → 6.40.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/dist/expo/index.cjs +229 -26
- package/dist/expo/index.d.mts +24 -2
- package/dist/expo/index.d.ts +24 -2
- package/dist/expo/index.mjs +229 -26
- package/dist/react/index.cjs +229 -26
- package/dist/react/index.d.mts +24 -2
- package/dist/react/index.d.ts +24 -2
- package/dist/react/index.mjs +229 -26
- package/dist/server/index.cjs +19 -16
- package/dist/server/index.d.mts +24 -2
- package/dist/server/index.d.ts +24 -2
- package/dist/server/index.mjs +19 -16
- package/package.json +1 -1
package/dist/expo/index.mjs
CHANGED
|
@@ -18246,6 +18246,14 @@ function createLocalMemoryStore(options) {
|
|
|
18246
18246
|
getLogger().warn("[memory/store] Failed to embed memory:", err);
|
|
18247
18247
|
});
|
|
18248
18248
|
};
|
|
18249
|
+
const maintenance = {
|
|
18250
|
+
createDecaySweeper: (sweeperOptions) => createDecaySweeper({ ...sweeperOptions, vaultCtx }),
|
|
18251
|
+
getTopicBacklog: (backlogOptions) => getMemoriesNeedingTopicExtractionOp(vaultCtx, backlogOptions),
|
|
18252
|
+
extractTopics: (memoryIds, extractOptions) => extractAndLinkEntitiesForMemoriesOp(vaultCtx, memoryIds, extractOptions),
|
|
18253
|
+
stampTopicsExtracted: (memoryIds, extractedAt, version) => stampTopicsExtractedAtOp(vaultCtx, memoryIds, extractedAt, version),
|
|
18254
|
+
relinkTopics: (memoryIds) => relinkMemoryTopicsOp(vaultCtx, memoryIds),
|
|
18255
|
+
backfillTopics: (memoryIds) => backfillMemoryTopicsOp(vaultCtx, memoryIds)
|
|
18256
|
+
};
|
|
18249
18257
|
return {
|
|
18250
18258
|
masksEmbeddingInput: options.embeddingOptions.maskInput !== void 0,
|
|
18251
18259
|
list: (listOptions) => getAllVaultMemoriesOp(vaultCtx, listOptions),
|
|
@@ -18259,21 +18267,22 @@ function createLocalMemoryStore(options) {
|
|
|
18259
18267
|
memoriesByTopics: (names) => getMemoriesByEntityNamesOp(entityCtx, names),
|
|
18260
18268
|
topicsByMemories: (memoryIds) => getEntitiesByMemoryIdsOp(entityCtx, memoryIds),
|
|
18261
18269
|
listTopics: async () => {
|
|
18262
|
-
const links = await entityCtx.memoryEntityCollection.query(...linksOwnedBy).
|
|
18270
|
+
const links = await entityCtx.memoryEntityCollection.query(...linksOwnedBy).unsafeFetchRaw();
|
|
18263
18271
|
const members = /* @__PURE__ */ new Map();
|
|
18264
18272
|
for (const link of links) {
|
|
18265
|
-
const entityId = String(link.
|
|
18273
|
+
const entityId = String(link.entity_id);
|
|
18266
18274
|
const set = members.get(entityId) ?? /* @__PURE__ */ new Set();
|
|
18267
|
-
set.add(String(link.
|
|
18275
|
+
set.add(String(link.memory_id));
|
|
18268
18276
|
members.set(entityId, set);
|
|
18269
18277
|
}
|
|
18270
|
-
const entities = userId === void 0 ? await entityCtx.entityCollection.query().
|
|
18278
|
+
const entities = userId === void 0 ? await entityCtx.entityCollection.query().unsafeFetchRaw() : members.size ? await entityCtx.entityCollection.query(Q8.where("id", Q8.oneOf([...members.keys()]))).unsafeFetchRaw() : [];
|
|
18271
18279
|
const byName = /* @__PURE__ */ new Map();
|
|
18272
18280
|
for (const entity of entities) {
|
|
18273
|
-
const
|
|
18274
|
-
const
|
|
18275
|
-
byName.
|
|
18276
|
-
|
|
18281
|
+
const name = String(entity.canonical_name);
|
|
18282
|
+
const count2 = members.get(String(entity.id))?.size ?? 0;
|
|
18283
|
+
const existing = byName.get(name);
|
|
18284
|
+
byName.set(name, {
|
|
18285
|
+
name,
|
|
18277
18286
|
kind: existing?.kind ?? entity.kind ?? null,
|
|
18278
18287
|
memoryCount: (existing?.memoryCount ?? 0) + count2
|
|
18279
18288
|
});
|
|
@@ -18364,14 +18373,8 @@ function createLocalMemoryStore(options) {
|
|
|
18364
18373
|
}
|
|
18365
18374
|
return () => subscriptions.forEach((s) => s.unsubscribe());
|
|
18366
18375
|
},
|
|
18367
|
-
maintenance
|
|
18368
|
-
|
|
18369
|
-
getTopicBacklog: (backlogOptions) => getMemoriesNeedingTopicExtractionOp(vaultCtx, backlogOptions),
|
|
18370
|
-
extractTopics: (memoryIds, extractOptions) => extractAndLinkEntitiesForMemoriesOp(vaultCtx, memoryIds, extractOptions),
|
|
18371
|
-
stampTopicsExtracted: (memoryIds, extractedAt, version) => stampTopicsExtractedAtOp(vaultCtx, memoryIds, extractedAt, version),
|
|
18372
|
-
relinkTopics: (memoryIds) => relinkMemoryTopicsOp(vaultCtx, memoryIds),
|
|
18373
|
-
backfillTopics: (memoryIds) => backfillMemoryTopicsOp(vaultCtx, memoryIds)
|
|
18374
|
-
}
|
|
18376
|
+
maintenance,
|
|
18377
|
+
topicMaintenance: maintenance
|
|
18375
18378
|
};
|
|
18376
18379
|
}
|
|
18377
18380
|
|
|
@@ -19155,7 +19158,7 @@ function createRemoteMemoryPipeline(options) {
|
|
|
19155
19158
|
const memory = {
|
|
19156
19159
|
...snapshot.memory,
|
|
19157
19160
|
content: patch.content,
|
|
19158
|
-
updated_at: patch.preserveUpdatedAt ? snapshot.memory.updated_at : Date.now()
|
|
19161
|
+
updated_at: patch.preserveUpdatedAt ? snapshot.memory.updated_at : Math.max(Date.now(), (snapshot.memory.topics_extracted_at ?? 0) + 1)
|
|
19159
19162
|
};
|
|
19160
19163
|
if (patch.scope !== void 0) memory.scope = patch.scope;
|
|
19161
19164
|
if (patch.embedding === void 0 && patch.content !== snapshot.memory.content) {
|
|
@@ -19288,6 +19291,7 @@ function projection({ memory }) {
|
|
|
19288
19291
|
};
|
|
19289
19292
|
}
|
|
19290
19293
|
function relevant(change, options) {
|
|
19294
|
+
if (change === "metadata") return false;
|
|
19291
19295
|
return options.includeDeleted ? change === "membership" : change !== "embedding" || !!options.embeddings;
|
|
19292
19296
|
}
|
|
19293
19297
|
function safely(onChange) {
|
|
@@ -19379,6 +19383,17 @@ function mergeTopics(existing, added) {
|
|
|
19379
19383
|
}
|
|
19380
19384
|
return [...byName.values()];
|
|
19381
19385
|
}
|
|
19386
|
+
function sameTopics(stored2, next) {
|
|
19387
|
+
const key = (t) => JSON.stringify([t.name, t.kind ?? null, t.source]);
|
|
19388
|
+
if (stored2 === null || stored2.length !== next.length) return false;
|
|
19389
|
+
const keys = new Set(stored2.map(key));
|
|
19390
|
+
return next.every((t) => keys.has(key(t)));
|
|
19391
|
+
}
|
|
19392
|
+
function extractionDue(memory) {
|
|
19393
|
+
const stamp = memory.topics_extracted_at;
|
|
19394
|
+
if (stamp === void 0 || stamp === null) return "fresh";
|
|
19395
|
+
return memory.updated_at > stamp || (memory.topics_extracted_version ?? 0) < TOPICS_EXTRACTION_VERSION ? "stale" : null;
|
|
19396
|
+
}
|
|
19382
19397
|
function canonicalTopics(row) {
|
|
19383
19398
|
return new Set((parseTopics(row.topics) ?? []).map((topic) => normalizeEntityName(topic.name)));
|
|
19384
19399
|
}
|
|
@@ -19391,7 +19406,12 @@ function createRemoteMemoryStore(options) {
|
|
|
19391
19406
|
const seen = /* @__PURE__ */ new Map();
|
|
19392
19407
|
let timer;
|
|
19393
19408
|
const notify = (change, records = []) => {
|
|
19394
|
-
if (timer)
|
|
19409
|
+
if (timer)
|
|
19410
|
+
for (const record2 of records) {
|
|
19411
|
+
const previous = seen.get(record2.memory.memory_id);
|
|
19412
|
+
if ((previous?.version ?? 0) + 1 === record2.version)
|
|
19413
|
+
seen.set(record2.memory.memory_id, record2);
|
|
19414
|
+
}
|
|
19395
19415
|
for (const subscriber of [...subscribers])
|
|
19396
19416
|
if (relevant(change, subscriber.options)) safely(subscriber.onChange);
|
|
19397
19417
|
};
|
|
@@ -19452,15 +19472,72 @@ function createRemoteMemoryStore(options) {
|
|
|
19452
19472
|
const record2 = await persistence.get(id);
|
|
19453
19473
|
return record2 && !record2.memory.is_deleted ? record2 : null;
|
|
19454
19474
|
};
|
|
19455
|
-
const
|
|
19475
|
+
const mutateLocked = async (id, change, edit) => {
|
|
19456
19476
|
const record2 = await live(id);
|
|
19457
19477
|
if (!record2) return null;
|
|
19458
19478
|
const next = edit(structuredClone(record2.memory));
|
|
19459
19479
|
if (!next) return null;
|
|
19460
19480
|
const saved = await persistence.put(next, record2);
|
|
19461
|
-
notify(change, [saved]);
|
|
19481
|
+
notify(typeof change === "function" ? change(record2.memory) : change, [saved]);
|
|
19462
19482
|
return saved;
|
|
19463
|
-
}
|
|
19483
|
+
};
|
|
19484
|
+
const mutate = (id, change, edit) => serialized(id, () => mutateLocked(id, change, edit));
|
|
19485
|
+
const serializedAll = (ids, task) => [...new Set(ids)].sort().reduceRight((inner, id) => () => serialized(id, inner), task)();
|
|
19486
|
+
const mutateMany = async (ids, change, edit) => {
|
|
19487
|
+
const saved = /* @__PURE__ */ new Map();
|
|
19488
|
+
const failed = /* @__PURE__ */ new Map();
|
|
19489
|
+
for (const slice of chunks([...new Set(ids)], MAX_BATCH)) {
|
|
19490
|
+
await serializedAll(slice, async () => {
|
|
19491
|
+
const writes = [];
|
|
19492
|
+
let read;
|
|
19493
|
+
try {
|
|
19494
|
+
read = await readEveryState(slice);
|
|
19495
|
+
} catch (error) {
|
|
19496
|
+
for (const id of slice) failed.set(id, error);
|
|
19497
|
+
return;
|
|
19498
|
+
}
|
|
19499
|
+
const { records, unreadable } = read;
|
|
19500
|
+
for (const id of slice) {
|
|
19501
|
+
const record2 = records.get(id);
|
|
19502
|
+
if (unreadable.has(id)) failed.set(id, new Error(`Memory ${id} could not be decrypted`));
|
|
19503
|
+
else if (!record2) failed.set(id, new Error(`Memory ${id} was not found`));
|
|
19504
|
+
else if (!record2.memory.is_deleted) {
|
|
19505
|
+
const memory = edit(structuredClone(record2.memory));
|
|
19506
|
+
if (memory) writes.push({ before: record2, memory });
|
|
19507
|
+
}
|
|
19508
|
+
}
|
|
19509
|
+
if (writes.length === 0) return;
|
|
19510
|
+
try {
|
|
19511
|
+
const written = await persistence.putMany(
|
|
19512
|
+
writes.map(({ before, memory }) => ({ memory, expectedVersion: before }))
|
|
19513
|
+
);
|
|
19514
|
+
const byChange = /* @__PURE__ */ new Map();
|
|
19515
|
+
written.forEach((record2, i) => {
|
|
19516
|
+
saved.set(record2.memory.memory_id, record2);
|
|
19517
|
+
const kind = change(writes[i].before.memory);
|
|
19518
|
+
byChange.set(kind, [...byChange.get(kind) ?? [], record2]);
|
|
19519
|
+
});
|
|
19520
|
+
for (const [kind, changed] of byChange) notify(kind, changed);
|
|
19521
|
+
} catch (error) {
|
|
19522
|
+
const perRow = error instanceof RemoteMemoryError && (error.code === "version_conflict" || error.status === 429);
|
|
19523
|
+
for (const { before } of writes) {
|
|
19524
|
+
const id = before.memory.memory_id;
|
|
19525
|
+
if (!perRow) {
|
|
19526
|
+
failed.set(id, error);
|
|
19527
|
+
continue;
|
|
19528
|
+
}
|
|
19529
|
+
try {
|
|
19530
|
+
const record2 = await mutateLocked(id, change, edit);
|
|
19531
|
+
if (record2) saved.set(id, record2);
|
|
19532
|
+
} catch (rowError) {
|
|
19533
|
+
failed.set(id, rowError);
|
|
19534
|
+
}
|
|
19535
|
+
}
|
|
19536
|
+
}
|
|
19537
|
+
});
|
|
19538
|
+
}
|
|
19539
|
+
return { saved, failed };
|
|
19540
|
+
};
|
|
19464
19541
|
const embedInBackground = ({ memory: { memory_id: id, content } }) => {
|
|
19465
19542
|
generateEmbedding(content, embeddingOptions).then(
|
|
19466
19543
|
(vector) => serialized(id, async () => {
|
|
@@ -19516,11 +19593,10 @@ function createRemoteMemoryStore(options) {
|
|
|
19516
19593
|
return records.map((record2) => stored(record2.memory));
|
|
19517
19594
|
};
|
|
19518
19595
|
const asStored = (record2) => record2 ? stored(record2.memory) : null;
|
|
19519
|
-
const
|
|
19596
|
+
const knownKinds = async (topics) => {
|
|
19520
19597
|
const unkinded = [
|
|
19521
19598
|
...new Set(topics.filter((t) => !t.kind).map((t) => normalizeEntityName(t.name)))
|
|
19522
19599
|
];
|
|
19523
|
-
if (unkinded.length === 0) return topics;
|
|
19524
19600
|
const kinds = /* @__PURE__ */ new Map();
|
|
19525
19601
|
for (const names of chunks(unkinded, MAX_QUERY_TOPICS)) {
|
|
19526
19602
|
for (const { memory } of await pages(metadata, {
|
|
@@ -19535,10 +19611,136 @@ function createRemoteMemoryStore(options) {
|
|
|
19535
19611
|
}
|
|
19536
19612
|
}
|
|
19537
19613
|
}
|
|
19538
|
-
return
|
|
19614
|
+
return (topic) => {
|
|
19539
19615
|
const kind = topic.kind ?? kinds.get(normalizeEntityName(topic.name));
|
|
19540
19616
|
return kind ? { ...topic, kind } : topic;
|
|
19541
|
-
}
|
|
19617
|
+
};
|
|
19618
|
+
};
|
|
19619
|
+
const withKnownKinds = async (topics) => topics.map(await knownKinds(topics));
|
|
19620
|
+
const readEveryState = async (ids) => {
|
|
19621
|
+
const records = /* @__PURE__ */ new Map();
|
|
19622
|
+
const unreadable = /* @__PURE__ */ new Set();
|
|
19623
|
+
for (const memory_ids of chunks(ids, MAX_QUERY_IDS)) {
|
|
19624
|
+
let cursor2;
|
|
19625
|
+
do {
|
|
19626
|
+
const page = await persistence.query({
|
|
19627
|
+
memory_ids,
|
|
19628
|
+
include_deleted: true,
|
|
19629
|
+
include_archived: true,
|
|
19630
|
+
include_quarantined: true,
|
|
19631
|
+
include_superseded: true,
|
|
19632
|
+
limit: 200,
|
|
19633
|
+
...cursor2 && { cursor: cursor2 }
|
|
19634
|
+
});
|
|
19635
|
+
warnFailed(page.failed);
|
|
19636
|
+
for (const record2 of page.items) records.set(record2.memory.memory_id, record2);
|
|
19637
|
+
for (const failure of page.failed) unreadable.add(failure.memory_id);
|
|
19638
|
+
cursor2 = page.next_cursor;
|
|
19639
|
+
} while (cursor2);
|
|
19640
|
+
}
|
|
19641
|
+
return { records, unreadable };
|
|
19642
|
+
};
|
|
19643
|
+
const topicMaintenance = {
|
|
19644
|
+
getTopicBacklog: async (backlogOptions = {}) => {
|
|
19645
|
+
const stale = [];
|
|
19646
|
+
const fresh = [];
|
|
19647
|
+
for (const { memory } of await pages(metadata, { order: "created" })) {
|
|
19648
|
+
if (memory.topics_user_managed) continue;
|
|
19649
|
+
const due = extractionDue(memory);
|
|
19650
|
+
if (due === "stale") stale.push(memory.memory_id);
|
|
19651
|
+
else if (due === "fresh") fresh.push(memory.memory_id);
|
|
19652
|
+
}
|
|
19653
|
+
const limit = backlogOptions.limit !== void 0 && backlogOptions.limit > 0 ? backlogOptions.limit : Infinity;
|
|
19654
|
+
return {
|
|
19655
|
+
pending: [...stale, ...fresh].slice(0, limit).map((uniqueId) => ({ uniqueId })),
|
|
19656
|
+
linkedUnstamped: [],
|
|
19657
|
+
topicsToRelink: [],
|
|
19658
|
+
topicsBackfill: []
|
|
19659
|
+
};
|
|
19660
|
+
},
|
|
19661
|
+
extractTopics: async (memoryIds, extractOptions) => {
|
|
19662
|
+
const extractedAt = extractOptions.now ?? Date.now();
|
|
19663
|
+
const skippedIds = [];
|
|
19664
|
+
const skippedReasons = /* @__PURE__ */ new Map();
|
|
19665
|
+
const skip = (id, reason) => {
|
|
19666
|
+
if (skippedReasons.has(id)) return;
|
|
19667
|
+
skippedIds.push(id);
|
|
19668
|
+
skippedReasons.set(id, reason);
|
|
19669
|
+
};
|
|
19670
|
+
const ids = [...new Set(memoryIds)];
|
|
19671
|
+
const { records, unreadable } = await readEveryState(ids);
|
|
19672
|
+
const inputs = [];
|
|
19673
|
+
for (const id of ids) {
|
|
19674
|
+
const memory = records.get(id)?.memory;
|
|
19675
|
+
if (unreadable.has(id)) skip(id, "unreadable");
|
|
19676
|
+
else if (!memory) skip(id, "not-found");
|
|
19677
|
+
else if (memory.is_deleted || memory.topics_user_managed) skip(id, "excluded");
|
|
19678
|
+
else inputs.push({ id, content: memory.content });
|
|
19679
|
+
}
|
|
19680
|
+
const entitiesByMemory = await extractEntitiesForMemories(inputs, extractOptions);
|
|
19681
|
+
const answered = /* @__PURE__ */ new Map();
|
|
19682
|
+
for (const input of inputs) {
|
|
19683
|
+
const entities = entitiesByMemory.get(input.id);
|
|
19684
|
+
if (entities === void 0) skip(input.id, "llm-unanswered");
|
|
19685
|
+
else
|
|
19686
|
+
answered.set(input.id, { content: input.content, topics: topicInputs(entities, "auto") });
|
|
19687
|
+
}
|
|
19688
|
+
const stampedIds = [];
|
|
19689
|
+
const fail = (id, reason) => {
|
|
19690
|
+
skip(id, reason);
|
|
19691
|
+
entitiesByMemory.delete(id);
|
|
19692
|
+
};
|
|
19693
|
+
try {
|
|
19694
|
+
const kinded = await knownKinds([...answered.values()].flatMap((a) => a.topics));
|
|
19695
|
+
const topics = new Map(
|
|
19696
|
+
[...answered].map(([id, a]) => [id, mergeTopics([], a.topics.map(kinded))])
|
|
19697
|
+
);
|
|
19698
|
+
const unchanged = (memory) => sameTopics(parseTopics(memory.topics), topics.get(memory.memory_id));
|
|
19699
|
+
const { saved, failed } = await mutateMany(
|
|
19700
|
+
[...answered.keys()],
|
|
19701
|
+
(before) => sameTopics(parseTopics(before.topics) ?? [], topics.get(before.memory_id)) ? "metadata" : "edit",
|
|
19702
|
+
(memory) => {
|
|
19703
|
+
if (memory.topics_user_managed || memory.content !== answered.get(memory.memory_id).content)
|
|
19704
|
+
return null;
|
|
19705
|
+
return {
|
|
19706
|
+
...memory,
|
|
19707
|
+
...!unchanged(memory) && {
|
|
19708
|
+
topics: serializeTopics(topics.get(memory.memory_id)),
|
|
19709
|
+
topics_updated_at: Date.now()
|
|
19710
|
+
},
|
|
19711
|
+
topics_extracted_at: Math.max(extractedAt, memory.updated_at),
|
|
19712
|
+
topics_extracted_version: TOPICS_EXTRACTION_VERSION
|
|
19713
|
+
};
|
|
19714
|
+
}
|
|
19715
|
+
);
|
|
19716
|
+
for (const id of answered.keys()) {
|
|
19717
|
+
if (saved.has(id)) stampedIds.push(id);
|
|
19718
|
+
else fail(id, failed.has(id) ? "link-failed" : "link-declined");
|
|
19719
|
+
}
|
|
19720
|
+
if (failed.size)
|
|
19721
|
+
getLogger().warn(
|
|
19722
|
+
"[memory/remote-store] Failed to write extracted topics:",
|
|
19723
|
+
failed.values().next().value
|
|
19724
|
+
);
|
|
19725
|
+
} catch (error) {
|
|
19726
|
+
getLogger().warn("[memory/remote-store] Failed to write extracted topics:", error);
|
|
19727
|
+
for (const id of answered.keys()) fail(id, "link-failed");
|
|
19728
|
+
}
|
|
19729
|
+
return { entitiesByMemory, stampedIds, skippedIds, skippedReasons };
|
|
19730
|
+
},
|
|
19731
|
+
stampTopicsExtracted: async (memoryIds, extractedAt, version = TOPICS_EXTRACTION_VERSION) => {
|
|
19732
|
+
const ids = [...new Set(memoryIds)];
|
|
19733
|
+
const { saved, failed } = await mutateMany(
|
|
19734
|
+
ids,
|
|
19735
|
+
() => "metadata",
|
|
19736
|
+
(memory) => memory.topics_user_managed ? null : { ...memory, topics_extracted_at: extractedAt, topics_extracted_version: version }
|
|
19737
|
+
);
|
|
19738
|
+
if (failed.size)
|
|
19739
|
+
getLogger().warn("[memory/remote-store] Failed to stamp topics:", [...failed.values()]);
|
|
19740
|
+
return ids.filter((id) => saved.has(id));
|
|
19741
|
+
},
|
|
19742
|
+
relinkTopics: () => Promise.resolve([]),
|
|
19743
|
+
backfillTopics: () => Promise.resolve([])
|
|
19542
19744
|
};
|
|
19543
19745
|
const everyState = {
|
|
19544
19746
|
include_deleted: true,
|
|
@@ -19617,6 +19819,7 @@ function createRemoteMemoryStore(options) {
|
|
|
19617
19819
|
};
|
|
19618
19820
|
return {
|
|
19619
19821
|
masksEmbeddingInput: embeddingOptions.maskInput !== void 0,
|
|
19822
|
+
topicMaintenance,
|
|
19620
19823
|
list: async (listOptions = {}) => (await listRows(decrypted, listOptions, listFilters(listOptions), maxOf(listOptions))).map(
|
|
19621
19824
|
(r) => stored(r.memory)
|
|
19622
19825
|
),
|
|
@@ -19701,7 +19904,7 @@ function createRemoteMemoryStore(options) {
|
|
|
19701
19904
|
const kind = patch.kind !== void 0 ? patch.kind : memory.kind;
|
|
19702
19905
|
assertValidKindLevel(kind, level);
|
|
19703
19906
|
memory.content = patch.content;
|
|
19704
|
-
memory.updated_at = Date.now();
|
|
19907
|
+
memory.updated_at = Math.max(Date.now(), (memory.topics_extracted_at ?? 0) + 1);
|
|
19705
19908
|
if (patch.level !== void 0) {
|
|
19706
19909
|
memory.level = level;
|
|
19707
19910
|
memory.scope = scopeForLevel(level);
|