@anuma/sdk 3.8.3 → 3.8.4
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-IFZZQPRO.mjs → chunk-42Y42CAZ.mjs} +60 -40
- package/dist/expo/index.cjs +223 -43
- package/dist/expo/index.d.mts +1 -1
- package/dist/expo/index.d.ts +1 -1
- package/dist/expo/index.mjs +165 -5
- package/dist/expo/{recall-MUFOZB6P.mjs → recall-JFZ3Z6EX.mjs} +1 -1
- package/dist/react/{chunk-35BHTCK4.mjs → chunk-NLVSQAYH.mjs} +60 -40
- package/dist/react/index.cjs +223 -43
- package/dist/react/index.d.mts +9 -4
- package/dist/react/index.d.ts +9 -4
- package/dist/react/index.mjs +165 -5
- package/dist/react/{recall-JUERXQA7.mjs → recall-BCEH7U2Z.mjs} +1 -1
- package/dist/server/{chunk-GKN5NJKZ.mjs → chunk-FS56IDOW.mjs} +60 -40
- package/dist/server/index.cjs +223 -43
- package/dist/server/index.d.mts +1 -1
- package/dist/server/index.d.ts +1 -1
- package/dist/server/index.mjs +165 -5
- package/dist/server/{recall-XZ6WLFPJ.mjs → recall-VDMDNQNB.mjs} +1 -1
- package/package.json +1 -1
|
@@ -16003,7 +16003,7 @@ function entityToStored(e) {
|
|
|
16003
16003
|
updatedAt: e.updatedAt
|
|
16004
16004
|
};
|
|
16005
16005
|
}
|
|
16006
|
-
async function
|
|
16006
|
+
async function upsertEntitiesInWrite(ctx, entities) {
|
|
16007
16007
|
const kindByName = /* @__PURE__ */ new Map();
|
|
16008
16008
|
for (const e of entities) {
|
|
16009
16009
|
const name = normalizeEntityName(e.name);
|
|
@@ -16017,60 +16017,62 @@ async function upsertEntitiesOp(ctx, entities) {
|
|
|
16017
16017
|
}
|
|
16018
16018
|
const unique = Array.from(kindByName.keys());
|
|
16019
16019
|
const out = /* @__PURE__ */ new Map();
|
|
16020
|
-
if (unique.length === 0) return out;
|
|
16021
|
-
|
|
16022
|
-
|
|
16023
|
-
|
|
16024
|
-
const
|
|
16025
|
-
|
|
16026
|
-
return incoming !== void 0 && (e.kind === null || e.kind === void 0 || e.kind === "");
|
|
16027
|
-
});
|
|
16028
|
-
const missing = unique.filter((n) => !existingNames.has(n));
|
|
16029
|
-
const created = missing.map(
|
|
16030
|
-
(name) => ctx.entityCollection.prepareCreate((record) => {
|
|
16031
|
-
record._setRaw("canonical_name", name);
|
|
16032
|
-
const kind = kindByName.get(name);
|
|
16033
|
-
if (kind !== void 0) record._setRaw("kind", kind);
|
|
16034
|
-
})
|
|
16035
|
-
);
|
|
16036
|
-
const updated = updates.map(
|
|
16037
|
-
(e) => e.prepareUpdate((record) => {
|
|
16038
|
-
record._setRaw("kind", kindByName.get(e.canonicalName));
|
|
16039
|
-
})
|
|
16040
|
-
);
|
|
16041
|
-
if (created.length > 0 || updated.length > 0) {
|
|
16042
|
-
await ctx.database.batch(...created, ...updated);
|
|
16043
|
-
}
|
|
16044
|
-
for (const e of existing) out.set(e.canonicalName, entityToStored(e));
|
|
16045
|
-
for (const record of created) out.set(record.canonicalName, entityToStored(record));
|
|
16046
|
-
return out;
|
|
16020
|
+
if (unique.length === 0) return { entities: out, operations: [] };
|
|
16021
|
+
const existing = await ctx.entityCollection.query(import_watermelondb2.Q.where("canonical_name", import_watermelondb2.Q.oneOf(unique))).fetch();
|
|
16022
|
+
const existingNames = new Set(existing.map((e) => e.canonicalName));
|
|
16023
|
+
const updates = existing.filter((e) => {
|
|
16024
|
+
const incoming = kindByName.get(e.canonicalName);
|
|
16025
|
+
return incoming !== void 0 && (e.kind === null || e.kind === void 0 || e.kind === "");
|
|
16047
16026
|
});
|
|
16027
|
+
const missing = unique.filter((n) => !existingNames.has(n));
|
|
16028
|
+
const created = missing.map(
|
|
16029
|
+
(name) => ctx.entityCollection.prepareCreate((record) => {
|
|
16030
|
+
record._setRaw("canonical_name", name);
|
|
16031
|
+
const kind = kindByName.get(name);
|
|
16032
|
+
if (kind !== void 0) record._setRaw("kind", kind);
|
|
16033
|
+
})
|
|
16034
|
+
);
|
|
16035
|
+
const updated = updates.map(
|
|
16036
|
+
(e) => e.prepareUpdate((record) => {
|
|
16037
|
+
record._setRaw("kind", kindByName.get(e.canonicalName));
|
|
16038
|
+
})
|
|
16039
|
+
);
|
|
16040
|
+
for (const e of existing) out.set(e.canonicalName, entityToStored(e));
|
|
16041
|
+
for (const record of created) out.set(record.canonicalName, entityToStored(record));
|
|
16042
|
+
return { entities: out, operations: [...created, ...updated] };
|
|
16048
16043
|
}
|
|
16049
16044
|
async function linkMemoryEntitiesOp(ctx, memoryId, entityInputs, options) {
|
|
16050
16045
|
if (entityInputs.length === 0) return [];
|
|
16051
16046
|
const normalized = entityInputs.map((e) => typeof e === "string" ? { name: e } : e);
|
|
16052
|
-
const byName = await upsertEntitiesOp(ctx, normalized);
|
|
16053
|
-
const entities = Array.from(byName.values());
|
|
16054
|
-
if (entities.length === 0) return [];
|
|
16055
16047
|
const userId = ctx.userId;
|
|
16056
16048
|
let skipped = false;
|
|
16049
|
+
let entities = [];
|
|
16057
16050
|
await ctx.database.write(async () => {
|
|
16051
|
+
const { entities: byName, operations: entityOps } = await upsertEntitiesInWrite(
|
|
16052
|
+
ctx,
|
|
16053
|
+
normalized
|
|
16054
|
+
);
|
|
16055
|
+
entities = Array.from(byName.values());
|
|
16058
16056
|
if (options?.unlessTopicsUserManaged && await autoLinkBlocked(ctx, memoryId)) {
|
|
16057
|
+
if (entityOps.length > 0) {
|
|
16058
|
+
await ctx.database.batch(...entityOps);
|
|
16059
|
+
}
|
|
16059
16060
|
skipped = true;
|
|
16060
16061
|
return;
|
|
16061
16062
|
}
|
|
16063
|
+
if (entities.length === 0) return;
|
|
16062
16064
|
const existingLinks = await ctx.memoryEntityCollection.query(import_watermelondb2.Q.where("memory_id", memoryId)).fetch();
|
|
16063
16065
|
const existingEntityIds = new Set(existingLinks.map((l) => String(l.entityId)));
|
|
16064
16066
|
const toCreate = entities.filter((e) => !existingEntityIds.has(e.uniqueId));
|
|
16065
|
-
if (toCreate.length === 0) return;
|
|
16066
|
-
const
|
|
16067
|
+
if (entityOps.length === 0 && toCreate.length === 0) return;
|
|
16068
|
+
const linkOps = toCreate.map(
|
|
16067
16069
|
(e) => ctx.memoryEntityCollection.prepareCreate((record) => {
|
|
16068
16070
|
record._setRaw("memory_id", memoryId);
|
|
16069
16071
|
record._setRaw("entity_id", e.uniqueId);
|
|
16070
16072
|
if (userId !== void 0) record._setRaw("user_id", userId);
|
|
16071
16073
|
})
|
|
16072
16074
|
);
|
|
16073
|
-
await ctx.database.batch(...
|
|
16075
|
+
await ctx.database.batch(...entityOps, ...linkOps);
|
|
16074
16076
|
});
|
|
16075
16077
|
return skipped ? [] : entities;
|
|
16076
16078
|
}
|
|
@@ -16085,22 +16087,28 @@ async function autoLinkBlocked(ctx, memoryId) {
|
|
|
16085
16087
|
}
|
|
16086
16088
|
async function replaceMemoryEntitiesGuardedOp(ctx, memoryId, entityInputs) {
|
|
16087
16089
|
const normalized = entityInputs.map((e) => typeof e === "string" ? { name: e } : e);
|
|
16088
|
-
const byName = await upsertEntitiesOp(ctx, normalized);
|
|
16089
|
-
const entities = Array.from(byName.values());
|
|
16090
16090
|
const userId = ctx.userId;
|
|
16091
16091
|
let skipped = false;
|
|
16092
|
+
let entities = [];
|
|
16092
16093
|
await ctx.database.write(async () => {
|
|
16093
16094
|
if (await autoLinkBlocked(ctx, memoryId)) {
|
|
16094
16095
|
skipped = true;
|
|
16095
16096
|
return;
|
|
16096
16097
|
}
|
|
16098
|
+
const { entities: byName, operations: entityOps } = await upsertEntitiesInWrite(
|
|
16099
|
+
ctx,
|
|
16100
|
+
normalized
|
|
16101
|
+
);
|
|
16102
|
+
entities = Array.from(byName.values());
|
|
16097
16103
|
const existingLinks = await ctx.memoryEntityCollection.query(import_watermelondb2.Q.where("memory_id", memoryId)).fetch();
|
|
16098
16104
|
const keep = new Set(entities.map((e) => e.uniqueId));
|
|
16099
16105
|
const existingEntityIds = new Set(existingLinks.map((l) => String(l.entityId)));
|
|
16100
16106
|
const toCreate = entities.filter((e) => !existingEntityIds.has(e.uniqueId));
|
|
16101
16107
|
const toDestroy = existingLinks.filter((l) => !keep.has(String(l.entityId)));
|
|
16102
|
-
if (toCreate.length === 0 && toDestroy.length === 0) return;
|
|
16108
|
+
if (entityOps.length === 0 && toCreate.length === 0 && toDestroy.length === 0) return;
|
|
16109
|
+
const orphans = await findOrphanedEntities(ctx, memoryId, toDestroy);
|
|
16103
16110
|
await ctx.database.batch(
|
|
16111
|
+
...entityOps,
|
|
16104
16112
|
...toCreate.map(
|
|
16105
16113
|
(e) => ctx.memoryEntityCollection.prepareCreate((record) => {
|
|
16106
16114
|
record._setRaw("memory_id", memoryId);
|
|
@@ -16108,11 +16116,23 @@ async function replaceMemoryEntitiesGuardedOp(ctx, memoryId, entityInputs) {
|
|
|
16108
16116
|
if (userId !== void 0) record._setRaw("user_id", userId);
|
|
16109
16117
|
})
|
|
16110
16118
|
),
|
|
16111
|
-
...toDestroy.map((l) => l.prepareDestroyPermanently())
|
|
16119
|
+
...toDestroy.map((l) => l.prepareDestroyPermanently()),
|
|
16120
|
+
...orphans.map((e) => e.prepareDestroyPermanently())
|
|
16112
16121
|
);
|
|
16113
16122
|
});
|
|
16114
16123
|
return skipped ? null : entities;
|
|
16115
16124
|
}
|
|
16125
|
+
async function findOrphanedEntities(ctx, memoryId, toDestroy) {
|
|
16126
|
+
const candidateIds = [...new Set(toDestroy.map((l) => String(l.entityId)))];
|
|
16127
|
+
if (candidateIds.length === 0) return [];
|
|
16128
|
+
const links = await ctx.memoryEntityCollection.query(import_watermelondb2.Q.where("entity_id", import_watermelondb2.Q.oneOf(candidateIds))).fetch();
|
|
16129
|
+
const stillLinked = new Set(
|
|
16130
|
+
links.filter((l) => String(l.memoryId) !== memoryId).map((l) => String(l.entityId))
|
|
16131
|
+
);
|
|
16132
|
+
const orphanIds = candidateIds.filter((id) => !stillLinked.has(id));
|
|
16133
|
+
if (orphanIds.length === 0) return [];
|
|
16134
|
+
return await ctx.entityCollection.query(import_watermelondb2.Q.where("id", import_watermelondb2.Q.oneOf(orphanIds))).fetch();
|
|
16135
|
+
}
|
|
16116
16136
|
async function unlinkMemoryEntitiesOp(ctx, memoryIds) {
|
|
16117
16137
|
if (memoryIds.length === 0) return;
|
|
16118
16138
|
const links = await ctx.memoryEntityCollection.query(import_watermelondb2.Q.where("memory_id", import_watermelondb2.Q.oneOf(Array.from(memoryIds)))).fetch();
|
|
@@ -16733,7 +16753,7 @@ async function getUnfiledVaultMemoriesOp(ctx) {
|
|
|
16733
16753
|
(record) => vaultMemoryToStored(record, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner)
|
|
16734
16754
|
);
|
|
16735
16755
|
}
|
|
16736
|
-
var TOPICS_EXTRACTION_VERSION =
|
|
16756
|
+
var TOPICS_EXTRACTION_VERSION = 3;
|
|
16737
16757
|
async function getMemoriesNeedingTopicExtractionOp(ctx, options) {
|
|
16738
16758
|
const entityCtx = ctx.entityCtx;
|
|
16739
16759
|
if (!entityCtx) {
|
|
@@ -19554,7 +19574,7 @@ function createMemoryVaultSearchTool(vaultCtx, embeddingOptions, cache, searchOp
|
|
|
19554
19574
|
legacy.map((r) => ({ id: r.uniqueId, content: r.content, score: r.similarity }))
|
|
19555
19575
|
);
|
|
19556
19576
|
}
|
|
19557
|
-
const { recall: recall2 } = await import("./recall-
|
|
19577
|
+
const { recall: recall2 } = await import("./recall-VDMDNQNB.mjs");
|
|
19558
19578
|
const result = await recall2(
|
|
19559
19579
|
query,
|
|
19560
19580
|
{ vaultCtx, embeddingOptions, vaultCache: cache },
|
package/dist/server/index.cjs
CHANGED
|
@@ -16797,7 +16797,7 @@ function entityToStored(e) {
|
|
|
16797
16797
|
updatedAt: e.updatedAt
|
|
16798
16798
|
};
|
|
16799
16799
|
}
|
|
16800
|
-
async function
|
|
16800
|
+
async function upsertEntitiesInWrite(ctx, entities) {
|
|
16801
16801
|
const kindByName = /* @__PURE__ */ new Map();
|
|
16802
16802
|
for (const e of entities) {
|
|
16803
16803
|
const name = normalizeEntityName(e.name);
|
|
@@ -16811,60 +16811,62 @@ async function upsertEntitiesOp(ctx, entities) {
|
|
|
16811
16811
|
}
|
|
16812
16812
|
const unique = Array.from(kindByName.keys());
|
|
16813
16813
|
const out = /* @__PURE__ */ new Map();
|
|
16814
|
-
if (unique.length === 0) return out;
|
|
16815
|
-
|
|
16816
|
-
|
|
16817
|
-
|
|
16818
|
-
const
|
|
16819
|
-
|
|
16820
|
-
return incoming !== void 0 && (e.kind === null || e.kind === void 0 || e.kind === "");
|
|
16821
|
-
});
|
|
16822
|
-
const missing = unique.filter((n) => !existingNames.has(n));
|
|
16823
|
-
const created = missing.map(
|
|
16824
|
-
(name) => ctx.entityCollection.prepareCreate((record) => {
|
|
16825
|
-
record._setRaw("canonical_name", name);
|
|
16826
|
-
const kind = kindByName.get(name);
|
|
16827
|
-
if (kind !== void 0) record._setRaw("kind", kind);
|
|
16828
|
-
})
|
|
16829
|
-
);
|
|
16830
|
-
const updated = updates.map(
|
|
16831
|
-
(e) => e.prepareUpdate((record) => {
|
|
16832
|
-
record._setRaw("kind", kindByName.get(e.canonicalName));
|
|
16833
|
-
})
|
|
16834
|
-
);
|
|
16835
|
-
if (created.length > 0 || updated.length > 0) {
|
|
16836
|
-
await ctx.database.batch(...created, ...updated);
|
|
16837
|
-
}
|
|
16838
|
-
for (const e of existing) out.set(e.canonicalName, entityToStored(e));
|
|
16839
|
-
for (const record of created) out.set(record.canonicalName, entityToStored(record));
|
|
16840
|
-
return out;
|
|
16814
|
+
if (unique.length === 0) return { entities: out, operations: [] };
|
|
16815
|
+
const existing = await ctx.entityCollection.query(import_watermelondb16.Q.where("canonical_name", import_watermelondb16.Q.oneOf(unique))).fetch();
|
|
16816
|
+
const existingNames = new Set(existing.map((e) => e.canonicalName));
|
|
16817
|
+
const updates = existing.filter((e) => {
|
|
16818
|
+
const incoming = kindByName.get(e.canonicalName);
|
|
16819
|
+
return incoming !== void 0 && (e.kind === null || e.kind === void 0 || e.kind === "");
|
|
16841
16820
|
});
|
|
16821
|
+
const missing = unique.filter((n) => !existingNames.has(n));
|
|
16822
|
+
const created = missing.map(
|
|
16823
|
+
(name) => ctx.entityCollection.prepareCreate((record) => {
|
|
16824
|
+
record._setRaw("canonical_name", name);
|
|
16825
|
+
const kind = kindByName.get(name);
|
|
16826
|
+
if (kind !== void 0) record._setRaw("kind", kind);
|
|
16827
|
+
})
|
|
16828
|
+
);
|
|
16829
|
+
const updated = updates.map(
|
|
16830
|
+
(e) => e.prepareUpdate((record) => {
|
|
16831
|
+
record._setRaw("kind", kindByName.get(e.canonicalName));
|
|
16832
|
+
})
|
|
16833
|
+
);
|
|
16834
|
+
for (const e of existing) out.set(e.canonicalName, entityToStored(e));
|
|
16835
|
+
for (const record of created) out.set(record.canonicalName, entityToStored(record));
|
|
16836
|
+
return { entities: out, operations: [...created, ...updated] };
|
|
16842
16837
|
}
|
|
16843
16838
|
async function linkMemoryEntitiesOp(ctx, memoryId, entityInputs, options) {
|
|
16844
16839
|
if (entityInputs.length === 0) return [];
|
|
16845
16840
|
const normalized = entityInputs.map((e) => typeof e === "string" ? { name: e } : e);
|
|
16846
|
-
const byName = await upsertEntitiesOp(ctx, normalized);
|
|
16847
|
-
const entities = Array.from(byName.values());
|
|
16848
|
-
if (entities.length === 0) return [];
|
|
16849
16841
|
const userId = ctx.userId;
|
|
16850
16842
|
let skipped = false;
|
|
16843
|
+
let entities = [];
|
|
16851
16844
|
await ctx.database.write(async () => {
|
|
16845
|
+
const { entities: byName, operations: entityOps } = await upsertEntitiesInWrite(
|
|
16846
|
+
ctx,
|
|
16847
|
+
normalized
|
|
16848
|
+
);
|
|
16849
|
+
entities = Array.from(byName.values());
|
|
16852
16850
|
if (options?.unlessTopicsUserManaged && await autoLinkBlocked(ctx, memoryId)) {
|
|
16851
|
+
if (entityOps.length > 0) {
|
|
16852
|
+
await ctx.database.batch(...entityOps);
|
|
16853
|
+
}
|
|
16853
16854
|
skipped = true;
|
|
16854
16855
|
return;
|
|
16855
16856
|
}
|
|
16857
|
+
if (entities.length === 0) return;
|
|
16856
16858
|
const existingLinks = await ctx.memoryEntityCollection.query(import_watermelondb16.Q.where("memory_id", memoryId)).fetch();
|
|
16857
16859
|
const existingEntityIds = new Set(existingLinks.map((l) => String(l.entityId)));
|
|
16858
16860
|
const toCreate = entities.filter((e) => !existingEntityIds.has(e.uniqueId));
|
|
16859
|
-
if (toCreate.length === 0) return;
|
|
16860
|
-
const
|
|
16861
|
+
if (entityOps.length === 0 && toCreate.length === 0) return;
|
|
16862
|
+
const linkOps = toCreate.map(
|
|
16861
16863
|
(e) => ctx.memoryEntityCollection.prepareCreate((record) => {
|
|
16862
16864
|
record._setRaw("memory_id", memoryId);
|
|
16863
16865
|
record._setRaw("entity_id", e.uniqueId);
|
|
16864
16866
|
if (userId !== void 0) record._setRaw("user_id", userId);
|
|
16865
16867
|
})
|
|
16866
16868
|
);
|
|
16867
|
-
await ctx.database.batch(...
|
|
16869
|
+
await ctx.database.batch(...entityOps, ...linkOps);
|
|
16868
16870
|
});
|
|
16869
16871
|
return skipped ? [] : entities;
|
|
16870
16872
|
}
|
|
@@ -16879,22 +16881,28 @@ async function autoLinkBlocked(ctx, memoryId) {
|
|
|
16879
16881
|
}
|
|
16880
16882
|
async function replaceMemoryEntitiesGuardedOp(ctx, memoryId, entityInputs) {
|
|
16881
16883
|
const normalized = entityInputs.map((e) => typeof e === "string" ? { name: e } : e);
|
|
16882
|
-
const byName = await upsertEntitiesOp(ctx, normalized);
|
|
16883
|
-
const entities = Array.from(byName.values());
|
|
16884
16884
|
const userId = ctx.userId;
|
|
16885
16885
|
let skipped = false;
|
|
16886
|
+
let entities = [];
|
|
16886
16887
|
await ctx.database.write(async () => {
|
|
16887
16888
|
if (await autoLinkBlocked(ctx, memoryId)) {
|
|
16888
16889
|
skipped = true;
|
|
16889
16890
|
return;
|
|
16890
16891
|
}
|
|
16892
|
+
const { entities: byName, operations: entityOps } = await upsertEntitiesInWrite(
|
|
16893
|
+
ctx,
|
|
16894
|
+
normalized
|
|
16895
|
+
);
|
|
16896
|
+
entities = Array.from(byName.values());
|
|
16891
16897
|
const existingLinks = await ctx.memoryEntityCollection.query(import_watermelondb16.Q.where("memory_id", memoryId)).fetch();
|
|
16892
16898
|
const keep = new Set(entities.map((e) => e.uniqueId));
|
|
16893
16899
|
const existingEntityIds = new Set(existingLinks.map((l) => String(l.entityId)));
|
|
16894
16900
|
const toCreate = entities.filter((e) => !existingEntityIds.has(e.uniqueId));
|
|
16895
16901
|
const toDestroy = existingLinks.filter((l) => !keep.has(String(l.entityId)));
|
|
16896
|
-
if (toCreate.length === 0 && toDestroy.length === 0) return;
|
|
16902
|
+
if (entityOps.length === 0 && toCreate.length === 0 && toDestroy.length === 0) return;
|
|
16903
|
+
const orphans = await findOrphanedEntities(ctx, memoryId, toDestroy);
|
|
16897
16904
|
await ctx.database.batch(
|
|
16905
|
+
...entityOps,
|
|
16898
16906
|
...toCreate.map(
|
|
16899
16907
|
(e) => ctx.memoryEntityCollection.prepareCreate((record) => {
|
|
16900
16908
|
record._setRaw("memory_id", memoryId);
|
|
@@ -16902,11 +16910,23 @@ async function replaceMemoryEntitiesGuardedOp(ctx, memoryId, entityInputs) {
|
|
|
16902
16910
|
if (userId !== void 0) record._setRaw("user_id", userId);
|
|
16903
16911
|
})
|
|
16904
16912
|
),
|
|
16905
|
-
...toDestroy.map((l) => l.prepareDestroyPermanently())
|
|
16913
|
+
...toDestroy.map((l) => l.prepareDestroyPermanently()),
|
|
16914
|
+
...orphans.map((e) => e.prepareDestroyPermanently())
|
|
16906
16915
|
);
|
|
16907
16916
|
});
|
|
16908
16917
|
return skipped ? null : entities;
|
|
16909
16918
|
}
|
|
16919
|
+
async function findOrphanedEntities(ctx, memoryId, toDestroy) {
|
|
16920
|
+
const candidateIds = [...new Set(toDestroy.map((l) => String(l.entityId)))];
|
|
16921
|
+
if (candidateIds.length === 0) return [];
|
|
16922
|
+
const links = await ctx.memoryEntityCollection.query(import_watermelondb16.Q.where("entity_id", import_watermelondb16.Q.oneOf(candidateIds))).fetch();
|
|
16923
|
+
const stillLinked = new Set(
|
|
16924
|
+
links.filter((l) => String(l.memoryId) !== memoryId).map((l) => String(l.entityId))
|
|
16925
|
+
);
|
|
16926
|
+
const orphanIds = candidateIds.filter((id) => !stillLinked.has(id));
|
|
16927
|
+
if (orphanIds.length === 0) return [];
|
|
16928
|
+
return await ctx.entityCollection.query(import_watermelondb16.Q.where("id", import_watermelondb16.Q.oneOf(orphanIds))).fetch();
|
|
16929
|
+
}
|
|
16910
16930
|
async function unlinkMemoryEntitiesOp(ctx, memoryIds) {
|
|
16911
16931
|
if (memoryIds.length === 0) return;
|
|
16912
16932
|
const links = await ctx.memoryEntityCollection.query(import_watermelondb16.Q.where("memory_id", import_watermelondb16.Q.oneOf(Array.from(memoryIds)))).fetch();
|
|
@@ -17764,7 +17784,7 @@ var init_operations3 = __esm({
|
|
|
17764
17784
|
init_operations2();
|
|
17765
17785
|
init_encryption2();
|
|
17766
17786
|
KNOWN_TRUST_TIERS = /* @__PURE__ */ new Set(["quarantined", "trusted"]);
|
|
17767
|
-
TOPICS_EXTRACTION_VERSION =
|
|
17787
|
+
TOPICS_EXTRACTION_VERSION = 3;
|
|
17768
17788
|
}
|
|
17769
17789
|
});
|
|
17770
17790
|
|
|
@@ -26900,6 +26920,162 @@ init_types3();
|
|
|
26900
26920
|
init_logger();
|
|
26901
26921
|
init_redactor();
|
|
26902
26922
|
|
|
26923
|
+
// src/lib/memory/entitySalience.ts
|
|
26924
|
+
var GENERIC_ENTITY_NAMES = /* @__PURE__ */ new Set([
|
|
26925
|
+
// Relative and absolute time
|
|
26926
|
+
"today",
|
|
26927
|
+
"tomorrow",
|
|
26928
|
+
"yesterday",
|
|
26929
|
+
"tonight",
|
|
26930
|
+
"morning",
|
|
26931
|
+
"afternoon",
|
|
26932
|
+
"evening",
|
|
26933
|
+
"night",
|
|
26934
|
+
"day",
|
|
26935
|
+
"date",
|
|
26936
|
+
"time",
|
|
26937
|
+
"week",
|
|
26938
|
+
"weekend",
|
|
26939
|
+
"weekday",
|
|
26940
|
+
"month",
|
|
26941
|
+
"year",
|
|
26942
|
+
"monday",
|
|
26943
|
+
"tuesday",
|
|
26944
|
+
"wednesday",
|
|
26945
|
+
"thursday",
|
|
26946
|
+
"friday",
|
|
26947
|
+
"saturday",
|
|
26948
|
+
"sunday",
|
|
26949
|
+
"january",
|
|
26950
|
+
"february",
|
|
26951
|
+
"march",
|
|
26952
|
+
"april",
|
|
26953
|
+
"may",
|
|
26954
|
+
"june",
|
|
26955
|
+
"july",
|
|
26956
|
+
"august",
|
|
26957
|
+
"september",
|
|
26958
|
+
"october",
|
|
26959
|
+
"november",
|
|
26960
|
+
"december",
|
|
26961
|
+
// Generic containers and venues — the named ones ("Blue Bottle on Valencia",
|
|
26962
|
+
// "Stanford") are unaffected because they are not bare tokens.
|
|
26963
|
+
"home",
|
|
26964
|
+
"house",
|
|
26965
|
+
"apartment",
|
|
26966
|
+
"room",
|
|
26967
|
+
"office",
|
|
26968
|
+
"work",
|
|
26969
|
+
"workplace",
|
|
26970
|
+
"school",
|
|
26971
|
+
"gym",
|
|
26972
|
+
"store",
|
|
26973
|
+
"shop",
|
|
26974
|
+
"hospital",
|
|
26975
|
+
"airport",
|
|
26976
|
+
"hotel",
|
|
26977
|
+
"city",
|
|
26978
|
+
"town",
|
|
26979
|
+
"country",
|
|
26980
|
+
"place",
|
|
26981
|
+
// Generic calendar entries — "Chicago Marathon" survives, "meeting" doesn't.
|
|
26982
|
+
"meeting",
|
|
26983
|
+
"call",
|
|
26984
|
+
"appointment",
|
|
26985
|
+
"reminder",
|
|
26986
|
+
"event",
|
|
26987
|
+
"birthday",
|
|
26988
|
+
"breakfast",
|
|
26989
|
+
"lunch",
|
|
26990
|
+
"dinner",
|
|
26991
|
+
"brunch",
|
|
26992
|
+
"vacation",
|
|
26993
|
+
"holiday",
|
|
26994
|
+
"trip",
|
|
26995
|
+
// Plurals are listed explicitly rather than stemmed: naive `s`-stripping
|
|
26996
|
+
// would fold real titles into generics ("The Times" → "time"). Only plurals
|
|
26997
|
+
// that are junk as topics in their own right belong here — note the absence
|
|
26998
|
+
// of "times", "places", and anything else that reads as a name.
|
|
26999
|
+
"days",
|
|
27000
|
+
"weeks",
|
|
27001
|
+
"weekends",
|
|
27002
|
+
"months",
|
|
27003
|
+
"years",
|
|
27004
|
+
"rooms",
|
|
27005
|
+
"offices",
|
|
27006
|
+
"houses",
|
|
27007
|
+
"apartments",
|
|
27008
|
+
"stores",
|
|
27009
|
+
"shops",
|
|
27010
|
+
"hotels",
|
|
27011
|
+
"meetings",
|
|
27012
|
+
"calls",
|
|
27013
|
+
"appointments",
|
|
27014
|
+
"reminders",
|
|
27015
|
+
"events",
|
|
27016
|
+
"birthdays",
|
|
27017
|
+
"trips",
|
|
27018
|
+
"vacations",
|
|
27019
|
+
"holidays",
|
|
27020
|
+
// Meta / filler the models occasionally echo back as an entity
|
|
27021
|
+
"user",
|
|
27022
|
+
"assistant",
|
|
27023
|
+
"memory",
|
|
27024
|
+
"memories",
|
|
27025
|
+
"note",
|
|
27026
|
+
"notes",
|
|
27027
|
+
"thing",
|
|
27028
|
+
"things",
|
|
27029
|
+
"stuff",
|
|
27030
|
+
"something",
|
|
27031
|
+
"someone",
|
|
27032
|
+
"anything",
|
|
27033
|
+
"everything",
|
|
27034
|
+
"none",
|
|
27035
|
+
"other",
|
|
27036
|
+
"misc",
|
|
27037
|
+
"general",
|
|
27038
|
+
"unknown"
|
|
27039
|
+
]);
|
|
27040
|
+
function isGenericEntityName(name) {
|
|
27041
|
+
const tokens = name.toLowerCase().split(/[^\p{L}\p{N}]+/u).filter((token) => token.length > 0);
|
|
27042
|
+
if (tokens.length === 0) return true;
|
|
27043
|
+
const distinctive = tokens.filter(
|
|
27044
|
+
(token) => !GENERIC_ENTITY_NAMES.has(token) && !ARTICLES.has(token) && !WEAK_MODIFIERS.has(token)
|
|
27045
|
+
);
|
|
27046
|
+
if (distinctive.length > 0) return false;
|
|
27047
|
+
const generic = tokens.filter((token) => GENERIC_ENTITY_NAMES.has(token));
|
|
27048
|
+
if (generic.length === 0) return true;
|
|
27049
|
+
const titleShaped = generic.length === 1 && tokens.some((token) => ARTICLES.has(token)) && !tokens.some((token) => WEAK_MODIFIERS.has(token));
|
|
27050
|
+
return !titleShaped;
|
|
27051
|
+
}
|
|
27052
|
+
var ARTICLES = /* @__PURE__ */ new Set(["the", "a", "an"]);
|
|
27053
|
+
var WEAK_MODIFIERS = /* @__PURE__ */ new Set([
|
|
27054
|
+
"my",
|
|
27055
|
+
"our",
|
|
27056
|
+
"their",
|
|
27057
|
+
"his",
|
|
27058
|
+
"her",
|
|
27059
|
+
"its",
|
|
27060
|
+
"this",
|
|
27061
|
+
"that",
|
|
27062
|
+
"next",
|
|
27063
|
+
"last",
|
|
27064
|
+
"upcoming",
|
|
27065
|
+
"every",
|
|
27066
|
+
"at",
|
|
27067
|
+
"in",
|
|
27068
|
+
"on",
|
|
27069
|
+
"of",
|
|
27070
|
+
"for",
|
|
27071
|
+
"with",
|
|
27072
|
+
"from",
|
|
27073
|
+
"to",
|
|
27074
|
+
"by",
|
|
27075
|
+
"and",
|
|
27076
|
+
"or"
|
|
27077
|
+
]);
|
|
27078
|
+
|
|
26903
27079
|
// src/lib/memory/injectionClassifier.ts
|
|
26904
27080
|
init_logger();
|
|
26905
27081
|
init_redactor();
|
|
@@ -27840,13 +28016,13 @@ function parseEntities(raw) {
|
|
|
27840
28016
|
for (const e of raw) {
|
|
27841
28017
|
if (typeof e === "string") {
|
|
27842
28018
|
const name2 = e.trim();
|
|
27843
|
-
if (name2.length > 0) out.push({ name: name2 });
|
|
28019
|
+
if (name2.length > 0 && !isGenericEntityName(name2)) out.push({ name: name2 });
|
|
27844
28020
|
continue;
|
|
27845
28021
|
}
|
|
27846
28022
|
if (typeof e !== "object" || e === null) continue;
|
|
27847
28023
|
const obj = e;
|
|
27848
28024
|
const name = typeof obj.name === "string" ? obj.name.trim() : "";
|
|
27849
|
-
if (name.length === 0) continue;
|
|
28025
|
+
if (name.length === 0 || isGenericEntityName(name)) continue;
|
|
27850
28026
|
const kind = typeof obj.kind === "string" && ENTITY_KINDS.includes(obj.kind) ? obj.kind : void 0;
|
|
27851
28027
|
out.push(kind !== void 0 ? { name, kind } : { name });
|
|
27852
28028
|
}
|
|
@@ -29188,7 +29364,11 @@ var SYSTEM_PROMPT6 = `You assign topics to saved memories for a personal memory
|
|
|
29188
29364
|
|
|
29189
29365
|
Each memory is a short statement about the user. For each memory, list the NAMED entities it mentions \u2014 these become the memory's topics, used to connect related memories in a knowledge graph.
|
|
29190
29366
|
|
|
29191
|
-
Include only NAMED entities, skip generic/common nouns.
|
|
29367
|
+
Include only NAMED entities, skip generic/common nouns. A topic must identify a specific thing the user could recognize by name; if it would be equally true of thousands of unrelated memories, leave it out:
|
|
29368
|
+
- SKIP bare generic nouns even when the memory capitalizes them or a calendar entry is titled that way \u2014 "Home", "Work", "Meeting", "Lunch", "Birthday", "Appointment", "Trip", "Today", "Friday", "March" are NOT topics.
|
|
29369
|
+
- KEEP the specific thing instead, when the memory names one: "Blue Bottle on Valencia" over "cafe", "Chicago Marathon" over "event", "Hollowpoint Labs" over "work".
|
|
29370
|
+
- Prefer 0 entities over a weak one. A memory whose only candidate is a generic noun has NO entities.
|
|
29371
|
+
${ENTITY_KIND_GUIDELINES}
|
|
29192
29372
|
|
|
29193
29373
|
Each memory below is written as "<id>: <text>". Output strict JSON: {"memories": [{"id": string, "entities": [{"name": string, "kind": string}]}]}
|
|
29194
29374
|
- exactly one element per input memory; copy its id EXACTLY as written (the token before the first ": "), with no brackets, quotes, or extra characters
|
|
@@ -29200,7 +29380,7 @@ async function extractEntitiesForMemories(memories, options) {
|
|
|
29200
29380
|
const redactor = resolvePiiRedactor(options.piiRedaction);
|
|
29201
29381
|
const vocabulary = (options.existingEntityNames ?? []).filter((n) => n.trim().length > 0).slice(0, MAX_VOCABULARY_NAMES).map((n) => redactor ? redactor.redactText(n).text : n);
|
|
29202
29382
|
const vocabularyNote = vocabulary.length > 0 ? `The user's existing topics: ${vocabulary.join(", ")}.
|
|
29203
|
-
When a memory refers to one of these, reuse the EXACT existing name (same spelling and
|
|
29383
|
+
When a memory refers to one of these, reuse the EXACT existing name (same spelling, casing, spacing and punctuation) instead of a variant \u2014 if "Foo.ai" is listed, never emit "Foo ai" or "Foo AI", and if "Jane Roe" is listed, emit that rather than a bare "Jane".
|
|
29204
29384
|
|
|
29205
29385
|
` : "";
|
|
29206
29386
|
for (let i = 0; i < memories.length; i += TOPIC_EXTRACTION_BATCH_SIZE) {
|
package/dist/server/index.d.mts
CHANGED
|
@@ -5805,7 +5805,7 @@ declare function getUnfiledVaultMemoriesOp(ctx: VaultMemoryOperationsContext): P
|
|
|
5805
5805
|
* by the next sweep, so topic-quality improvements propagate across the existing
|
|
5806
5806
|
* vault. The worker's `limit` drains that re-extraction across sweeps.
|
|
5807
5807
|
*/
|
|
5808
|
-
declare const TOPICS_EXTRACTION_VERSION =
|
|
5808
|
+
declare const TOPICS_EXTRACTION_VERSION = 3;
|
|
5809
5809
|
/**
|
|
5810
5810
|
* Result of {@link getMemoriesNeedingTopicExtractionOp}: which memories the
|
|
5811
5811
|
* background topic worker should run LLM entity extraction on, and which it
|
package/dist/server/index.d.ts
CHANGED
|
@@ -5805,7 +5805,7 @@ declare function getUnfiledVaultMemoriesOp(ctx: VaultMemoryOperationsContext): P
|
|
|
5805
5805
|
* by the next sweep, so topic-quality improvements propagate across the existing
|
|
5806
5806
|
* vault. The worker's `limit` drains that re-extraction across sweeps.
|
|
5807
5807
|
*/
|
|
5808
|
-
declare const TOPICS_EXTRACTION_VERSION =
|
|
5808
|
+
declare const TOPICS_EXTRACTION_VERSION = 3;
|
|
5809
5809
|
/**
|
|
5810
5810
|
* Result of {@link getMemoriesNeedingTopicExtractionOp}: which memories the
|
|
5811
5811
|
* background topic worker should run LLM entity extraction on, and which it
|