@anuma/sdk 3.12.2 → 3.13.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/{chunk-ORVYPS3R.mjs → chunk-BOAKGY4R.mjs} +277 -46
- package/dist/expo/index.cjs +330 -46
- package/dist/expo/index.d.mts +133 -13
- package/dist/expo/index.d.ts +133 -13
- package/dist/expo/index.mjs +56 -2
- package/dist/expo/{recall-A4WZELH5.mjs → recall-O65PGPIQ.mjs} +1 -1
- package/dist/react/{chunk-QURYPMCE.mjs → chunk-XXCZVG4Z.mjs} +290 -49
- package/dist/react/index.cjs +343 -49
- package/dist/react/index.d.mts +146 -14
- package/dist/react/index.d.ts +146 -14
- package/dist/react/index.mjs +56 -2
- package/dist/react/{recall-NQNZDPNU.mjs → recall-KTJCUAXN.mjs} +1 -1
- package/dist/server/{chunk-FXGG7JA5.mjs → chunk-ME6ZQN52.mjs} +277 -46
- package/dist/server/index.cjs +330 -46
- package/dist/server/index.d.mts +133 -13
- package/dist/server/index.d.ts +133 -13
- package/dist/server/index.mjs +56 -2
- package/dist/server/{recall-SLMMIFHM.mjs → recall-RMCSM6L6.mjs} +1 -1
- package/package.json +1 -1
|
@@ -15992,6 +15992,31 @@ var ENTITY_KINDS = [
|
|
|
15992
15992
|
function normalizeEntityName(name) {
|
|
15993
15993
|
return name.trim().toLowerCase();
|
|
15994
15994
|
}
|
|
15995
|
+
function serializeTopics(topics) {
|
|
15996
|
+
return JSON.stringify(topics);
|
|
15997
|
+
}
|
|
15998
|
+
function parseTopics(value) {
|
|
15999
|
+
if (typeof value !== "string" || value.length === 0) return null;
|
|
16000
|
+
let parsed;
|
|
16001
|
+
try {
|
|
16002
|
+
parsed = JSON.parse(value);
|
|
16003
|
+
} catch {
|
|
16004
|
+
return null;
|
|
16005
|
+
}
|
|
16006
|
+
if (!Array.isArray(parsed)) return null;
|
|
16007
|
+
const out = [];
|
|
16008
|
+
for (const raw of parsed) {
|
|
16009
|
+
if (typeof raw !== "object" || raw === null) continue;
|
|
16010
|
+
const { name, kind, source } = raw;
|
|
16011
|
+
if (typeof name !== "string" || name.trim().length === 0) continue;
|
|
16012
|
+
out.push({
|
|
16013
|
+
name,
|
|
16014
|
+
...typeof kind === "string" && kind.length > 0 ? { kind } : {},
|
|
16015
|
+
source: source === "user" ? "user" : "auto"
|
|
16016
|
+
});
|
|
16017
|
+
}
|
|
16018
|
+
return out;
|
|
16019
|
+
}
|
|
15995
16020
|
|
|
15996
16021
|
// src/lib/db/entities/operations.ts
|
|
15997
16022
|
function entityToStored(e) {
|
|
@@ -16041,9 +16066,62 @@ async function upsertEntitiesInWrite(ctx, entities) {
|
|
|
16041
16066
|
for (const record of created) out.set(record.canonicalName, entityToStored(record));
|
|
16042
16067
|
return { entities: out, operations: [...created, ...updated] };
|
|
16043
16068
|
}
|
|
16069
|
+
async function findVaultRowInWrite(ctx, memoryId) {
|
|
16070
|
+
try {
|
|
16071
|
+
const rows = await ctx.database.get("memory_vault").query(import_watermelondb2.Q.where("id", memoryId)).fetch();
|
|
16072
|
+
return rows[0] ?? null;
|
|
16073
|
+
} catch {
|
|
16074
|
+
return null;
|
|
16075
|
+
}
|
|
16076
|
+
}
|
|
16077
|
+
function prepareTopicsUpdate(row, topics, now) {
|
|
16078
|
+
const originalUpdatedAt = row.updatedAt.getTime();
|
|
16079
|
+
return row.prepareUpdate((r) => {
|
|
16080
|
+
r._setRaw("topics", serializeTopics(topics));
|
|
16081
|
+
r._setRaw("topics_updated_at", now);
|
|
16082
|
+
r._setRaw("updated_at", originalUpdatedAt);
|
|
16083
|
+
});
|
|
16084
|
+
}
|
|
16085
|
+
function displayNamesOf(entities) {
|
|
16086
|
+
const out = /* @__PURE__ */ new Map();
|
|
16087
|
+
for (const e of entities) {
|
|
16088
|
+
const name = e.name.trim();
|
|
16089
|
+
const normalized = normalizeEntityName(name);
|
|
16090
|
+
if (normalized.length === 0 || out.has(normalized)) continue;
|
|
16091
|
+
out.set(normalized, name);
|
|
16092
|
+
}
|
|
16093
|
+
return out;
|
|
16094
|
+
}
|
|
16095
|
+
function topicsEqual(stored, computed) {
|
|
16096
|
+
if (stored === null || stored.length !== computed.length) return false;
|
|
16097
|
+
const key = (t) => JSON.stringify([t.name, t.kind ?? null, t.source]);
|
|
16098
|
+
const storedKeys = stored.map(key).sort();
|
|
16099
|
+
const computedKeys = computed.map(key).sort();
|
|
16100
|
+
return storedKeys.every((k, i) => k === computedKeys[i]);
|
|
16101
|
+
}
|
|
16102
|
+
function resolveTopicsWrite(row, linked, displayNames, source) {
|
|
16103
|
+
if (row === null || source === null) return null;
|
|
16104
|
+
const topics = topicsForEntities(linked, displayNames, source);
|
|
16105
|
+
if (topicsEqual(parseTopics(row.topics), topics)) return null;
|
|
16106
|
+
return { row, topics };
|
|
16107
|
+
}
|
|
16108
|
+
function topicsForEntities(entities, displayNames, source) {
|
|
16109
|
+
return entities.map((e) => {
|
|
16110
|
+
const name = displayNames.get(e.canonicalName) ?? e.canonicalName;
|
|
16111
|
+
return { name, ...e.kind ? { kind: e.kind } : {}, source };
|
|
16112
|
+
});
|
|
16113
|
+
}
|
|
16114
|
+
function toEntityObjects(entityInputs) {
|
|
16115
|
+
return entityInputs.map((e) => typeof e === "string" ? { name: e } : e);
|
|
16116
|
+
}
|
|
16117
|
+
async function prepareMemoryTopicsUpdate(ctx, memoryId, linked, inputs, source) {
|
|
16118
|
+
const row = await findVaultRowInWrite(ctx, memoryId);
|
|
16119
|
+
const write = resolveTopicsWrite(row, linked, displayNamesOf(toEntityObjects(inputs)), source);
|
|
16120
|
+
return write === null ? null : prepareTopicsUpdate(write.row, write.topics, Date.now());
|
|
16121
|
+
}
|
|
16044
16122
|
async function linkMemoryEntitiesOp(ctx, memoryId, entityInputs, options) {
|
|
16045
16123
|
if (entityInputs.length === 0) return [];
|
|
16046
|
-
const normalized = entityInputs
|
|
16124
|
+
const normalized = toEntityObjects(entityInputs);
|
|
16047
16125
|
const userId = ctx.userId;
|
|
16048
16126
|
let skipped = false;
|
|
16049
16127
|
let entities = [];
|
|
@@ -16053,7 +16131,8 @@ async function linkMemoryEntitiesOp(ctx, memoryId, entityInputs, options) {
|
|
|
16053
16131
|
normalized
|
|
16054
16132
|
);
|
|
16055
16133
|
entities = Array.from(byName.values());
|
|
16056
|
-
|
|
16134
|
+
const vaultRow = await findVaultRowInWrite(ctx, memoryId);
|
|
16135
|
+
if (options?.unlessTopicsUserManaged && autoLinkBlocked(vaultRow)) {
|
|
16057
16136
|
if (entityOps.length > 0) {
|
|
16058
16137
|
await ctx.database.batch(...entityOps);
|
|
16059
16138
|
}
|
|
@@ -16064,7 +16143,18 @@ async function linkMemoryEntitiesOp(ctx, memoryId, entityInputs, options) {
|
|
|
16064
16143
|
const existingLinks = await ctx.memoryEntityCollection.query(import_watermelondb2.Q.where("memory_id", memoryId)).fetch();
|
|
16065
16144
|
const existingEntityIds = new Set(existingLinks.map((l) => String(l.entityId)));
|
|
16066
16145
|
const toCreate = entities.filter((e) => !existingEntityIds.has(e.uniqueId));
|
|
16067
|
-
|
|
16146
|
+
const keptIds = entities.map((e) => e.uniqueId);
|
|
16147
|
+
const carriedOver = await resolveEntitiesByIds(
|
|
16148
|
+
ctx,
|
|
16149
|
+
[...existingEntityIds].filter((id) => !keptIds.includes(id))
|
|
16150
|
+
);
|
|
16151
|
+
const topicsWrite = resolveTopicsWrite(
|
|
16152
|
+
vaultRow,
|
|
16153
|
+
[...carriedOver, ...entities],
|
|
16154
|
+
displayNamesOf(normalized),
|
|
16155
|
+
options?.topicsSource ?? "auto"
|
|
16156
|
+
);
|
|
16157
|
+
if (entityOps.length === 0 && toCreate.length === 0 && topicsWrite === null) return;
|
|
16068
16158
|
const linkOps = toCreate.map(
|
|
16069
16159
|
(e) => ctx.memoryEntityCollection.prepareCreate((record) => {
|
|
16070
16160
|
record._setRaw("memory_id", memoryId);
|
|
@@ -16072,26 +16162,42 @@ async function linkMemoryEntitiesOp(ctx, memoryId, entityInputs, options) {
|
|
|
16072
16162
|
if (userId !== void 0) record._setRaw("user_id", userId);
|
|
16073
16163
|
})
|
|
16074
16164
|
);
|
|
16075
|
-
await ctx.database.batch(
|
|
16165
|
+
await ctx.database.batch(
|
|
16166
|
+
...entityOps,
|
|
16167
|
+
...linkOps,
|
|
16168
|
+
...topicsWrite ? [prepareTopicsUpdate(topicsWrite.row, topicsWrite.topics, Date.now())] : []
|
|
16169
|
+
);
|
|
16076
16170
|
});
|
|
16077
16171
|
return skipped ? [] : entities;
|
|
16078
16172
|
}
|
|
16079
|
-
async function
|
|
16080
|
-
|
|
16081
|
-
|
|
16082
|
-
|
|
16083
|
-
|
|
16084
|
-
|
|
16085
|
-
|
|
16086
|
-
}
|
|
16173
|
+
async function resolveEntitiesByIds(ctx, entityIds) {
|
|
16174
|
+
if (entityIds.length === 0) return [];
|
|
16175
|
+
const rows = await ctx.entityCollection.query(import_watermelondb2.Q.where("id", import_watermelondb2.Q.oneOf(Array.from(entityIds)))).fetch();
|
|
16176
|
+
return rows.map(entityToStored);
|
|
16177
|
+
}
|
|
16178
|
+
function autoLinkBlocked(row) {
|
|
16179
|
+
return !row || !!row.isDeleted || !!row.topicsUserManaged;
|
|
16087
16180
|
}
|
|
16088
16181
|
async function replaceMemoryEntitiesGuardedOp(ctx, memoryId, entityInputs) {
|
|
16089
|
-
|
|
16182
|
+
return replaceMemoryEntities(ctx, memoryId, entityInputs, {
|
|
16183
|
+
guarded: true,
|
|
16184
|
+
topicsSource: "auto"
|
|
16185
|
+
});
|
|
16186
|
+
}
|
|
16187
|
+
async function relinkMemoryEntitiesFromTopicsOp(ctx, memoryId, topics) {
|
|
16188
|
+
return replaceMemoryEntities(ctx, memoryId, topics, {
|
|
16189
|
+
guarded: false,
|
|
16190
|
+
topicsSource: null
|
|
16191
|
+
});
|
|
16192
|
+
}
|
|
16193
|
+
async function replaceMemoryEntities(ctx, memoryId, entityInputs, options) {
|
|
16194
|
+
const normalized = toEntityObjects(entityInputs);
|
|
16090
16195
|
const userId = ctx.userId;
|
|
16091
16196
|
let skipped = false;
|
|
16092
16197
|
let entities = [];
|
|
16093
16198
|
await ctx.database.write(async () => {
|
|
16094
|
-
|
|
16199
|
+
const vaultRow = await findVaultRowInWrite(ctx, memoryId);
|
|
16200
|
+
if (options.guarded && autoLinkBlocked(vaultRow)) {
|
|
16095
16201
|
skipped = true;
|
|
16096
16202
|
return;
|
|
16097
16203
|
}
|
|
@@ -16105,7 +16211,15 @@ async function replaceMemoryEntitiesGuardedOp(ctx, memoryId, entityInputs) {
|
|
|
16105
16211
|
const existingEntityIds = new Set(existingLinks.map((l) => String(l.entityId)));
|
|
16106
16212
|
const toCreate = entities.filter((e) => !existingEntityIds.has(e.uniqueId));
|
|
16107
16213
|
const toDestroy = existingLinks.filter((l) => !keep.has(String(l.entityId)));
|
|
16108
|
-
|
|
16214
|
+
const topicsWrite = resolveTopicsWrite(
|
|
16215
|
+
vaultRow,
|
|
16216
|
+
entities,
|
|
16217
|
+
displayNamesOf(normalized),
|
|
16218
|
+
options.topicsSource
|
|
16219
|
+
);
|
|
16220
|
+
if (entityOps.length === 0 && toCreate.length === 0 && toDestroy.length === 0 && topicsWrite === null) {
|
|
16221
|
+
return;
|
|
16222
|
+
}
|
|
16109
16223
|
const orphans = await findOrphanedEntities(ctx, memoryId, toDestroy);
|
|
16110
16224
|
await ctx.database.batch(
|
|
16111
16225
|
...entityOps,
|
|
@@ -16117,7 +16231,8 @@ async function replaceMemoryEntitiesGuardedOp(ctx, memoryId, entityInputs) {
|
|
|
16117
16231
|
})
|
|
16118
16232
|
),
|
|
16119
16233
|
...toDestroy.map((l) => l.prepareDestroyPermanently()),
|
|
16120
|
-
...orphans.map((e) => e.prepareDestroyPermanently())
|
|
16234
|
+
...orphans.map((e) => e.prepareDestroyPermanently()),
|
|
16235
|
+
...topicsWrite ? [prepareTopicsUpdate(topicsWrite.row, topicsWrite.topics, Date.now())] : []
|
|
16121
16236
|
);
|
|
16122
16237
|
});
|
|
16123
16238
|
return skipped ? null : entities;
|
|
@@ -16305,6 +16420,8 @@ function vaultMemoryToStoredRaw(memory) {
|
|
|
16305
16420
|
eventTimeEnd: memory.eventTimeEnd ?? null,
|
|
16306
16421
|
eventTimeKind: memory.eventTimeKind ?? null,
|
|
16307
16422
|
topicsUserManaged: memory.topicsUserManaged ?? false,
|
|
16423
|
+
topics: parseTopics(memory.topics),
|
|
16424
|
+
topicsUpdatedAt: memory.topicsUpdatedAt ?? null,
|
|
16308
16425
|
topicsExtractedAt: memory.topicsExtractedAt ?? null,
|
|
16309
16426
|
topicsExtractedVersion: memory.topicsExtractedVersion ?? null,
|
|
16310
16427
|
supersededBy: memory.supersededBy ?? null,
|
|
@@ -16581,6 +16698,8 @@ function vaultMemoryRawToStoredRaw(raw) {
|
|
|
16581
16698
|
eventTimeKind: raw.event_time_kind ?? null,
|
|
16582
16699
|
// SQLite stores booleans as 0/1, LokiJS as true/false — coerce both.
|
|
16583
16700
|
topicsUserManaged: raw.topics_user_managed === true || raw.topics_user_managed === 1,
|
|
16701
|
+
topics: parseTopics(raw.topics),
|
|
16702
|
+
topicsUpdatedAt: raw.topics_updated_at ?? null,
|
|
16584
16703
|
topicsExtractedAt: raw.topics_extracted_at ?? null,
|
|
16585
16704
|
topicsExtractedVersion: raw.topics_extracted_version ?? null,
|
|
16586
16705
|
supersededBy: raw.superseded_by ?? null,
|
|
@@ -16928,56 +17047,111 @@ async function getUnfiledVaultMemoriesOp(ctx) {
|
|
|
16928
17047
|
);
|
|
16929
17048
|
}
|
|
16930
17049
|
var TOPICS_EXTRACTION_VERSION = 3;
|
|
17050
|
+
async function linkedEntityNamesByMemory(entityCtx, memoryIds) {
|
|
17051
|
+
const CHUNK = 500;
|
|
17052
|
+
const entityIdByMemory = /* @__PURE__ */ new Map();
|
|
17053
|
+
const allEntityIds = /* @__PURE__ */ new Set();
|
|
17054
|
+
for (let i = 0; i < memoryIds.length; i += CHUNK) {
|
|
17055
|
+
const links = await entityCtx.memoryEntityCollection.query(import_watermelondb3.Q.where("memory_id", import_watermelondb3.Q.oneOf(memoryIds.slice(i, i + CHUNK)))).unsafeFetchRaw();
|
|
17056
|
+
for (const link of links) {
|
|
17057
|
+
const memoryId = String(link.memory_id);
|
|
17058
|
+
const entityId = String(link.entity_id);
|
|
17059
|
+
allEntityIds.add(entityId);
|
|
17060
|
+
let bucket = entityIdByMemory.get(memoryId);
|
|
17061
|
+
if (!bucket) {
|
|
17062
|
+
bucket = /* @__PURE__ */ new Set();
|
|
17063
|
+
entityIdByMemory.set(memoryId, bucket);
|
|
17064
|
+
}
|
|
17065
|
+
bucket.add(entityId);
|
|
17066
|
+
}
|
|
17067
|
+
}
|
|
17068
|
+
const entityIds = Array.from(allEntityIds);
|
|
17069
|
+
const nameById = /* @__PURE__ */ new Map();
|
|
17070
|
+
for (let i = 0; i < entityIds.length; i += CHUNK) {
|
|
17071
|
+
const entities = await entityCtx.entityCollection.query(import_watermelondb3.Q.where("id", import_watermelondb3.Q.oneOf(entityIds.slice(i, i + CHUNK)))).unsafeFetchRaw();
|
|
17072
|
+
for (const e of entities) {
|
|
17073
|
+
if (typeof e.canonical_name === "string") nameById.set(String(e.id), e.canonical_name);
|
|
17074
|
+
}
|
|
17075
|
+
}
|
|
17076
|
+
const out = /* @__PURE__ */ new Map();
|
|
17077
|
+
for (const [memoryId, ids] of entityIdByMemory) {
|
|
17078
|
+
const names = /* @__PURE__ */ new Set();
|
|
17079
|
+
for (const id of ids) {
|
|
17080
|
+
const name = nameById.get(id);
|
|
17081
|
+
if (name !== void 0) names.add(name);
|
|
17082
|
+
}
|
|
17083
|
+
if (names.size > 0) out.set(memoryId, names);
|
|
17084
|
+
}
|
|
17085
|
+
return out;
|
|
17086
|
+
}
|
|
17087
|
+
function linksDivergeFromTopics(topics, linked) {
|
|
17088
|
+
const wanted = new Set(
|
|
17089
|
+
topics.map((t) => normalizeEntityName(t.name)).filter((n) => n.length > 0)
|
|
17090
|
+
);
|
|
17091
|
+
if (wanted.size !== linked.size) return true;
|
|
17092
|
+
for (const name of wanted) if (!linked.has(name)) return true;
|
|
17093
|
+
return false;
|
|
17094
|
+
}
|
|
16931
17095
|
async function getMemoriesNeedingTopicExtractionOp(ctx, options) {
|
|
16932
17096
|
const entityCtx = ctx.entityCtx;
|
|
16933
17097
|
if (!entityCtx) {
|
|
16934
17098
|
throw new Error("getMemoriesNeedingTopicExtractionOp requires ctx.entityCtx");
|
|
16935
17099
|
}
|
|
16936
|
-
const conditions = [
|
|
16937
|
-
// Boolean optional column: null (legacy) and false both mean auto-managed.
|
|
16938
|
-
// Q.notEq(true) is a NULL trap on SQLite (NULL <> TRUE is NULL) — enumerate.
|
|
16939
|
-
import_watermelondb3.Q.or(import_watermelondb3.Q.where("topics_user_managed", null), import_watermelondb3.Q.where("topics_user_managed", false)),
|
|
16940
|
-
...baseVaultConditions(ctx),
|
|
16941
|
-
import_watermelondb3.Q.sortBy("created_at", import_watermelondb3.Q.desc)
|
|
16942
|
-
];
|
|
17100
|
+
const conditions = [...baseVaultConditions(ctx), import_watermelondb3.Q.sortBy("created_at", import_watermelondb3.Q.desc)];
|
|
16943
17101
|
const rows = await ctx.vaultMemoryCollection.query(...conditions).unsafeFetchRaw();
|
|
16944
|
-
const
|
|
16945
|
-
|
|
17102
|
+
const linkedNames = await linkedEntityNamesByMemory(
|
|
17103
|
+
entityCtx,
|
|
17104
|
+
rows.map((r) => r.id)
|
|
17105
|
+
);
|
|
17106
|
+
const pendingRaw = [];
|
|
17107
|
+
const stampedPendingRaw = [];
|
|
17108
|
+
const linkedUnstampedAll = [];
|
|
17109
|
+
const topicsToRelinkAll = [];
|
|
17110
|
+
const topicsBackfillAll = [];
|
|
16946
17111
|
for (const raw of rows) {
|
|
17112
|
+
const id = raw.id;
|
|
17113
|
+
const topics = parseTopics(raw.topics);
|
|
17114
|
+
const linked = linkedNames.get(id);
|
|
17115
|
+
if (topics !== null && topics.length > 0 && linksDivergeFromTopics(topics, linked ?? /* @__PURE__ */ new Set())) {
|
|
17116
|
+
topicsToRelinkAll.push(id);
|
|
17117
|
+
continue;
|
|
17118
|
+
}
|
|
17119
|
+
if (raw.topics_user_managed) {
|
|
17120
|
+
if (topics === null && linked !== void 0) topicsBackfillAll.push(id);
|
|
17121
|
+
continue;
|
|
17122
|
+
}
|
|
16947
17123
|
const stamp = raw.topics_extracted_at ?? null;
|
|
17124
|
+
let isPending = false;
|
|
16948
17125
|
if (stamp !== null) {
|
|
16949
17126
|
const version = raw.topics_extracted_version ?? 0;
|
|
16950
17127
|
if (raw.updated_at > stamp || version < TOPICS_EXTRACTION_VERSION) {
|
|
16951
|
-
|
|
17128
|
+
stampedPendingRaw.push(raw);
|
|
17129
|
+
isPending = true;
|
|
16952
17130
|
}
|
|
16953
|
-
} else {
|
|
16954
|
-
|
|
16955
|
-
}
|
|
16956
|
-
}
|
|
16957
|
-
const linkedIds = /* @__PURE__ */ new Set();
|
|
16958
|
-
const CHUNK = 500;
|
|
16959
|
-
for (let i = 0; i < unstamped.length; i += CHUNK) {
|
|
16960
|
-
const ids = unstamped.slice(i, i + CHUNK).map((r) => r.id);
|
|
16961
|
-
const links = await entityCtx.memoryEntityCollection.query(import_watermelondb3.Q.where("memory_id", import_watermelondb3.Q.oneOf(ids))).unsafeFetchRaw();
|
|
16962
|
-
for (const link of links) linkedIds.add(String(link.memory_id));
|
|
16963
|
-
}
|
|
16964
|
-
const linkedUnstampedAll = [];
|
|
16965
|
-
const pendingRaw = [...stampedPending];
|
|
16966
|
-
for (const raw of unstamped) {
|
|
16967
|
-
if (linkedIds.has(raw.id)) {
|
|
16968
|
-
linkedUnstampedAll.push(raw.id);
|
|
17131
|
+
} else if (linked !== void 0) {
|
|
17132
|
+
linkedUnstampedAll.push(id);
|
|
16969
17133
|
} else {
|
|
16970
17134
|
pendingRaw.push(raw);
|
|
17135
|
+
isPending = true;
|
|
17136
|
+
}
|
|
17137
|
+
if (!isPending && topics === null && linked !== void 0) {
|
|
17138
|
+
topicsBackfillAll.push(id);
|
|
16971
17139
|
}
|
|
16972
17140
|
}
|
|
16973
17141
|
const cap = options?.limit !== void 0 && options.limit > 0 ? options.limit : void 0;
|
|
16974
|
-
const
|
|
16975
|
-
const
|
|
17142
|
+
const orderedPendingRaw = [...stampedPendingRaw, ...pendingRaw];
|
|
17143
|
+
const limitedPendingRaw = cap !== void 0 ? orderedPendingRaw.slice(0, cap) : orderedPendingRaw;
|
|
16976
17144
|
const pending = await mapInBatches(
|
|
16977
17145
|
limitedPendingRaw,
|
|
16978
17146
|
(raw) => vaultMemoryRawToStored(raw, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner)
|
|
16979
17147
|
);
|
|
16980
|
-
|
|
17148
|
+
const applyCap = (ids) => cap !== void 0 ? ids.slice(0, cap) : ids;
|
|
17149
|
+
return {
|
|
17150
|
+
pending,
|
|
17151
|
+
linkedUnstamped: applyCap(linkedUnstampedAll),
|
|
17152
|
+
topicsToRelink: applyCap(topicsToRelinkAll),
|
|
17153
|
+
topicsBackfill: applyCap(topicsBackfillAll)
|
|
17154
|
+
};
|
|
16981
17155
|
}
|
|
16982
17156
|
async function stampTopicsExtractedAtOp(ctx, memoryIds, extractedAt, version = TOPICS_EXTRACTION_VERSION) {
|
|
16983
17157
|
if (memoryIds.length === 0) return [];
|
|
@@ -17011,6 +17185,61 @@ async function stampTopicsExtractedAtOp(ctx, memoryIds, extractedAt, version = T
|
|
|
17011
17185
|
}
|
|
17012
17186
|
return stamped;
|
|
17013
17187
|
}
|
|
17188
|
+
async function relinkMemoryTopicsOp(ctx, memoryIds) {
|
|
17189
|
+
const entityCtx = ctx.entityCtx;
|
|
17190
|
+
if (!entityCtx) {
|
|
17191
|
+
throw new Error("relinkMemoryTopicsOp requires ctx.entityCtx");
|
|
17192
|
+
}
|
|
17193
|
+
const relinked = [];
|
|
17194
|
+
for (const id of Array.from(new Set(memoryIds))) {
|
|
17195
|
+
let record;
|
|
17196
|
+
try {
|
|
17197
|
+
record = await ctx.vaultMemoryCollection.find(id);
|
|
17198
|
+
} catch {
|
|
17199
|
+
continue;
|
|
17200
|
+
}
|
|
17201
|
+
if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) continue;
|
|
17202
|
+
const topics = parseTopics(record.topics);
|
|
17203
|
+
if (topics === null || topics.length === 0) continue;
|
|
17204
|
+
try {
|
|
17205
|
+
await relinkMemoryEntitiesFromTopicsOp(entityCtx, id, topics);
|
|
17206
|
+
relinked.push(id);
|
|
17207
|
+
} catch (err) {
|
|
17208
|
+
getLogger().warn("[memory/topics] relink failed", err);
|
|
17209
|
+
}
|
|
17210
|
+
}
|
|
17211
|
+
return relinked;
|
|
17212
|
+
}
|
|
17213
|
+
async function backfillMemoryTopicsOp(ctx, memoryIds) {
|
|
17214
|
+
const entityCtx = ctx.entityCtx;
|
|
17215
|
+
if (!entityCtx) {
|
|
17216
|
+
throw new Error("backfillMemoryTopicsOp requires ctx.entityCtx");
|
|
17217
|
+
}
|
|
17218
|
+
const filled = [];
|
|
17219
|
+
for (const id of Array.from(new Set(memoryIds))) {
|
|
17220
|
+
let record;
|
|
17221
|
+
try {
|
|
17222
|
+
record = await ctx.vaultMemoryCollection.find(id);
|
|
17223
|
+
} catch {
|
|
17224
|
+
continue;
|
|
17225
|
+
}
|
|
17226
|
+
if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) continue;
|
|
17227
|
+
if (parseTopics(record.topics) !== null) continue;
|
|
17228
|
+
const links = await entityCtx.memoryEntityCollection.query(import_watermelondb3.Q.where("memory_id", id)).unsafeFetchRaw();
|
|
17229
|
+
const entityIds = links.map((l) => String(l.entity_id));
|
|
17230
|
+
if (entityIds.length === 0) continue;
|
|
17231
|
+
const entities = await entityCtx.entityCollection.query(import_watermelondb3.Q.where("id", import_watermelondb3.Q.oneOf(entityIds))).fetch();
|
|
17232
|
+
if (entities.length === 0) continue;
|
|
17233
|
+
const source = record.topicsUserManaged ? "user" : "auto";
|
|
17234
|
+
await ctx.database.write(async () => {
|
|
17235
|
+
const topicsOp = await prepareMemoryTopicsUpdate(entityCtx, id, entities, [], source);
|
|
17236
|
+
if (!topicsOp) return;
|
|
17237
|
+
await ctx.database.batch(topicsOp);
|
|
17238
|
+
filled.push(id);
|
|
17239
|
+
});
|
|
17240
|
+
}
|
|
17241
|
+
return filled;
|
|
17242
|
+
}
|
|
17014
17243
|
async function deleteAllVaultMemoriesForUserOp(ctx, userId) {
|
|
17015
17244
|
if (ctx.userId !== void 0 && ctx.userId !== userId) return 0;
|
|
17016
17245
|
const records = await ctx.vaultMemoryCollection.query(import_watermelondb3.Q.where("user_id", userId), import_watermelondb3.Q.where("is_deleted", false)).fetch();
|
|
@@ -20081,7 +20310,7 @@ function createMemoryVaultSearchTool(vaultCtx, embeddingOptions, cache, searchOp
|
|
|
20081
20310
|
legacy.map((r) => ({ id: r.uniqueId, content: r.content, score: r.similarity }))
|
|
20082
20311
|
);
|
|
20083
20312
|
}
|
|
20084
|
-
const { recall: recall2 } = await import("./recall-
|
|
20313
|
+
const { recall: recall2 } = await import("./recall-RMCSM6L6.mjs");
|
|
20085
20314
|
let recallDegraded = [];
|
|
20086
20315
|
const result = await recall2(
|
|
20087
20316
|
query,
|
|
@@ -21106,6 +21335,8 @@ export {
|
|
|
21106
21335
|
TOPICS_EXTRACTION_VERSION,
|
|
21107
21336
|
getMemoriesNeedingTopicExtractionOp,
|
|
21108
21337
|
stampTopicsExtractedAtOp,
|
|
21338
|
+
relinkMemoryTopicsOp,
|
|
21339
|
+
backfillMemoryTopicsOp,
|
|
21109
21340
|
deleteAllVaultMemoriesForUserOp,
|
|
21110
21341
|
assertVaultScopeForSweep,
|
|
21111
21342
|
getDecayCandidatesRawOp,
|