@anuma/sdk 6.8.2 → 6.9.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-LUGYCFVI.mjs → chunk-4M56MKBV.mjs} +66 -44
- package/dist/expo/index.cjs +71 -45
- package/dist/expo/index.d.mts +24 -0
- package/dist/expo/index.d.ts +24 -0
- package/dist/expo/index.mjs +7 -3
- package/dist/expo/{recall-77QK4RT6.mjs → recall-WIB7RQQZ.mjs} +1 -1
- package/dist/react/{chunk-NPJSO5ES.mjs → chunk-EJ65X4GI.mjs} +74 -46
- package/dist/react/index.cjs +79 -47
- package/dist/react/index.d.mts +24 -0
- package/dist/react/index.d.ts +24 -0
- package/dist/react/index.mjs +7 -3
- package/dist/react/{recall-3I5GDJZE.mjs → recall-FWILZSFH.mjs} +1 -1
- package/dist/server/{chunk-IP6PGI7H.mjs → chunk-I56324FR.mjs} +66 -44
- package/dist/server/index.cjs +71 -45
- package/dist/server/index.d.mts +24 -0
- package/dist/server/index.d.ts +24 -0
- package/dist/server/index.mjs +7 -3
- package/dist/server/{recall-RTW7T7KR.mjs → recall-T7CNXTQ3.mjs} +1 -1
- package/package.json +1 -1
|
@@ -16391,13 +16391,13 @@ async function upsertEntitiesInWrite(ctx, entities) {
|
|
|
16391
16391
|
}
|
|
16392
16392
|
const unique = Array.from(kindByName.keys());
|
|
16393
16393
|
const out = /* @__PURE__ */ new Map();
|
|
16394
|
-
if (unique.length === 0) return { entities: out, operations: [] };
|
|
16394
|
+
if (unique.length === 0) return { entities: out, operations: [], kindBackfills: [] };
|
|
16395
16395
|
const existing = await ctx.entityCollection.query(import_watermelondb2.Q.where("canonical_name", import_watermelondb2.Q.oneOf(unique))).fetch();
|
|
16396
16396
|
const existingNames = new Set(existing.map((e) => e.canonicalName));
|
|
16397
|
-
const
|
|
16397
|
+
const kindBackfills = existing.filter((e) => {
|
|
16398
16398
|
const incoming = kindByName.get(e.canonicalName);
|
|
16399
16399
|
return incoming !== void 0 && (e.kind === null || e.kind === void 0 || e.kind === "");
|
|
16400
|
-
});
|
|
16400
|
+
}).map((record) => ({ record, kind: kindByName.get(record.canonicalName) }));
|
|
16401
16401
|
const missing = unique.filter((n) => !existingNames.has(n));
|
|
16402
16402
|
const created = missing.map(
|
|
16403
16403
|
(name) => ctx.entityCollection.prepareCreate((record) => {
|
|
@@ -16406,14 +16406,19 @@ async function upsertEntitiesInWrite(ctx, entities) {
|
|
|
16406
16406
|
if (kind !== void 0) record._setRaw("kind", kind);
|
|
16407
16407
|
})
|
|
16408
16408
|
);
|
|
16409
|
-
const updated = updates.map(
|
|
16410
|
-
(e) => e.prepareUpdate((record) => {
|
|
16411
|
-
record._setRaw("kind", kindByName.get(e.canonicalName));
|
|
16412
|
-
})
|
|
16413
|
-
);
|
|
16414
16409
|
for (const e of existing) out.set(e.canonicalName, entityToStored(e));
|
|
16415
16410
|
for (const record of created) out.set(record.canonicalName, entityToStored(record));
|
|
16416
|
-
|
|
16411
|
+
for (const { record, kind } of kindBackfills) {
|
|
16412
|
+
out.set(record.canonicalName, { ...entityToStored(record), kind });
|
|
16413
|
+
}
|
|
16414
|
+
return { entities: out, operations: created, kindBackfills };
|
|
16415
|
+
}
|
|
16416
|
+
function prepareKindBackfills(backfills) {
|
|
16417
|
+
return backfills.map(
|
|
16418
|
+
({ record, kind }) => record.prepareUpdate((r) => {
|
|
16419
|
+
r._setRaw("kind", kind);
|
|
16420
|
+
})
|
|
16421
|
+
);
|
|
16417
16422
|
}
|
|
16418
16423
|
async function findVaultRowInWrite(ctx, memoryId) {
|
|
16419
16424
|
try {
|
|
@@ -16463,10 +16468,12 @@ function topicsForEntities(entities, displayNames, source) {
|
|
|
16463
16468
|
function toEntityObjects(entityInputs) {
|
|
16464
16469
|
return entityInputs.map((e) => typeof e === "string" ? { name: e } : e);
|
|
16465
16470
|
}
|
|
16466
|
-
async function
|
|
16471
|
+
async function resolveMemoryTopicsWrite(ctx, memoryId, linked, inputs, source) {
|
|
16467
16472
|
const row = await findVaultRowInWrite(ctx, memoryId);
|
|
16468
|
-
|
|
16469
|
-
|
|
16473
|
+
return resolveTopicsWrite(row, linked, displayNamesOf(toEntityObjects(inputs)), source);
|
|
16474
|
+
}
|
|
16475
|
+
function prepareMemoryTopicsUpdate(write) {
|
|
16476
|
+
return prepareTopicsUpdate(write.row, write.topics, Date.now());
|
|
16470
16477
|
}
|
|
16471
16478
|
async function linkMemoryEntitiesOp(ctx, memoryId, entityInputs, options) {
|
|
16472
16479
|
if (entityInputs.length === 0) return [];
|
|
@@ -16475,15 +16482,16 @@ async function linkMemoryEntitiesOp(ctx, memoryId, entityInputs, options) {
|
|
|
16475
16482
|
let skipped = false;
|
|
16476
16483
|
let entities = [];
|
|
16477
16484
|
await ctx.database.write(async () => {
|
|
16478
|
-
const {
|
|
16479
|
-
|
|
16480
|
-
|
|
16481
|
-
|
|
16485
|
+
const {
|
|
16486
|
+
entities: byName,
|
|
16487
|
+
operations: entityOps,
|
|
16488
|
+
kindBackfills
|
|
16489
|
+
} = await upsertEntitiesInWrite(ctx, normalized);
|
|
16482
16490
|
entities = Array.from(byName.values());
|
|
16483
16491
|
const vaultRow = await findVaultRowInWrite(ctx, memoryId);
|
|
16484
16492
|
if (options?.unlessTopicsUserManaged && autoLinkBlocked(vaultRow)) {
|
|
16485
|
-
if (entityOps.length > 0) {
|
|
16486
|
-
await ctx.database.batch(...entityOps);
|
|
16493
|
+
if (entityOps.length > 0 || kindBackfills.length > 0) {
|
|
16494
|
+
await ctx.database.batch(...entityOps, ...prepareKindBackfills(kindBackfills));
|
|
16487
16495
|
}
|
|
16488
16496
|
skipped = true;
|
|
16489
16497
|
return;
|
|
@@ -16503,7 +16511,9 @@ async function linkMemoryEntitiesOp(ctx, memoryId, entityInputs, options) {
|
|
|
16503
16511
|
displayNamesOf(normalized),
|
|
16504
16512
|
options?.topicsSource ?? "auto"
|
|
16505
16513
|
);
|
|
16506
|
-
if (entityOps.length === 0 && toCreate.length === 0 && topicsWrite === null)
|
|
16514
|
+
if (entityOps.length === 0 && kindBackfills.length === 0 && toCreate.length === 0 && topicsWrite === null) {
|
|
16515
|
+
return;
|
|
16516
|
+
}
|
|
16507
16517
|
const linkOps = toCreate.map(
|
|
16508
16518
|
(e) => ctx.memoryEntityCollection.prepareCreate((record) => {
|
|
16509
16519
|
record._setRaw("memory_id", memoryId);
|
|
@@ -16513,6 +16523,7 @@ async function linkMemoryEntitiesOp(ctx, memoryId, entityInputs, options) {
|
|
|
16513
16523
|
);
|
|
16514
16524
|
await ctx.database.batch(
|
|
16515
16525
|
...entityOps,
|
|
16526
|
+
...prepareKindBackfills(kindBackfills),
|
|
16516
16527
|
...linkOps,
|
|
16517
16528
|
...topicsWrite ? [prepareTopicsUpdate(topicsWrite.row, topicsWrite.topics, Date.now())] : []
|
|
16518
16529
|
);
|
|
@@ -16550,10 +16561,11 @@ async function replaceMemoryEntities(ctx, memoryId, entityInputs, options) {
|
|
|
16550
16561
|
skipped = true;
|
|
16551
16562
|
return;
|
|
16552
16563
|
}
|
|
16553
|
-
const {
|
|
16554
|
-
|
|
16555
|
-
|
|
16556
|
-
|
|
16564
|
+
const {
|
|
16565
|
+
entities: byName,
|
|
16566
|
+
operations: entityOps,
|
|
16567
|
+
kindBackfills
|
|
16568
|
+
} = await upsertEntitiesInWrite(ctx, normalized);
|
|
16557
16569
|
entities = Array.from(byName.values());
|
|
16558
16570
|
const existingLinks = await ctx.memoryEntityCollection.query(import_watermelondb2.Q.where("memory_id", memoryId)).fetch();
|
|
16559
16571
|
const keep = new Set(entities.map((e) => e.uniqueId));
|
|
@@ -16566,12 +16578,13 @@ async function replaceMemoryEntities(ctx, memoryId, entityInputs, options) {
|
|
|
16566
16578
|
displayNamesOf(normalized),
|
|
16567
16579
|
options.topicsSource
|
|
16568
16580
|
);
|
|
16569
|
-
if (entityOps.length === 0 && toCreate.length === 0 && toDestroy.length === 0 && topicsWrite === null) {
|
|
16581
|
+
if (entityOps.length === 0 && kindBackfills.length === 0 && toCreate.length === 0 && toDestroy.length === 0 && topicsWrite === null) {
|
|
16570
16582
|
return;
|
|
16571
16583
|
}
|
|
16572
16584
|
const orphans = await findOrphanedEntities(ctx, memoryId, toDestroy);
|
|
16573
16585
|
await ctx.database.batch(
|
|
16574
16586
|
...entityOps,
|
|
16587
|
+
...prepareKindBackfills(kindBackfills),
|
|
16575
16588
|
...toCreate.map(
|
|
16576
16589
|
(e) => ctx.memoryEntityCollection.prepareCreate((record) => {
|
|
16577
16590
|
record._setRaw("memory_id", memoryId);
|
|
@@ -17622,27 +17635,36 @@ async function backfillMemoryTopicsOp(ctx, memoryIds) {
|
|
|
17622
17635
|
if (!entityCtx) {
|
|
17623
17636
|
throw new Error("backfillMemoryTopicsOp requires ctx.entityCtx");
|
|
17624
17637
|
}
|
|
17638
|
+
const uniqueIds = Array.from(new Set(memoryIds));
|
|
17639
|
+
if (uniqueIds.length === 0) return [];
|
|
17625
17640
|
const filled = [];
|
|
17626
|
-
|
|
17627
|
-
|
|
17628
|
-
|
|
17629
|
-
record = await ctx.vaultMemoryCollection.find(id);
|
|
17630
|
-
} catch {
|
|
17631
|
-
continue;
|
|
17632
|
-
}
|
|
17633
|
-
if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) continue;
|
|
17634
|
-
if (parseTopics(record.topics) !== null) continue;
|
|
17635
|
-
const links = await entityCtx.memoryEntityCollection.query(import_watermelondb3.Q.where("memory_id", id)).unsafeFetchRaw();
|
|
17636
|
-
const entityIds = links.map((l) => String(l.entity_id));
|
|
17637
|
-
if (entityIds.length === 0) continue;
|
|
17638
|
-
const entities = await entityCtx.entityCollection.query(import_watermelondb3.Q.where("id", import_watermelondb3.Q.oneOf(entityIds))).fetch();
|
|
17639
|
-
if (entities.length === 0) continue;
|
|
17640
|
-
const source = record.topicsUserManaged ? "user" : "auto";
|
|
17641
|
+
const CHUNK = 500;
|
|
17642
|
+
for (let i = 0; i < uniqueIds.length; i += CHUNK) {
|
|
17643
|
+
const chunkIds = uniqueIds.slice(i, i + CHUNK);
|
|
17641
17644
|
await ctx.database.write(async () => {
|
|
17642
|
-
const
|
|
17643
|
-
|
|
17644
|
-
|
|
17645
|
-
|
|
17645
|
+
const writes = [];
|
|
17646
|
+
for (const id of chunkIds) {
|
|
17647
|
+
let record;
|
|
17648
|
+
try {
|
|
17649
|
+
record = await ctx.vaultMemoryCollection.find(id);
|
|
17650
|
+
} catch {
|
|
17651
|
+
continue;
|
|
17652
|
+
}
|
|
17653
|
+
if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) continue;
|
|
17654
|
+
if (parseTopics(record.topics) !== null) continue;
|
|
17655
|
+
const links = await entityCtx.memoryEntityCollection.query(import_watermelondb3.Q.where("memory_id", id)).unsafeFetchRaw();
|
|
17656
|
+
const entityIds = links.map((l) => String(l.entity_id));
|
|
17657
|
+
if (entityIds.length === 0) continue;
|
|
17658
|
+
const entities = await entityCtx.entityCollection.query(import_watermelondb3.Q.where("id", import_watermelondb3.Q.oneOf(entityIds))).fetch();
|
|
17659
|
+
if (entities.length === 0) continue;
|
|
17660
|
+
const source = record.topicsUserManaged ? "user" : "auto";
|
|
17661
|
+
const write = await resolveMemoryTopicsWrite(entityCtx, id, entities, [], source);
|
|
17662
|
+
if (write) writes.push(write);
|
|
17663
|
+
}
|
|
17664
|
+
if (writes.length === 0) return;
|
|
17665
|
+
const prepared = writes.map(prepareMemoryTopicsUpdate);
|
|
17666
|
+
await ctx.database.batch(...prepared);
|
|
17667
|
+
for (const write of writes) filled.push(write.row.id);
|
|
17646
17668
|
});
|
|
17647
17669
|
}
|
|
17648
17670
|
return filled;
|
|
@@ -20856,7 +20878,7 @@ function createMemoryVaultSearchTool(vaultCtx, embeddingOptions, cache, searchOp
|
|
|
20856
20878
|
subQueries = decomp.subQueries;
|
|
20857
20879
|
}
|
|
20858
20880
|
}
|
|
20859
|
-
const { recall: recall2 } = await import("./recall-
|
|
20881
|
+
const { recall: recall2 } = await import("./recall-T7CNXTQ3.mjs");
|
|
20860
20882
|
let recallDegraded = [];
|
|
20861
20883
|
const result = await recall2(
|
|
20862
20884
|
query,
|
package/dist/server/index.cjs
CHANGED
|
@@ -17225,13 +17225,13 @@ async function upsertEntitiesInWrite(ctx, entities) {
|
|
|
17225
17225
|
}
|
|
17226
17226
|
const unique = Array.from(kindByName.keys());
|
|
17227
17227
|
const out = /* @__PURE__ */ new Map();
|
|
17228
|
-
if (unique.length === 0) return { entities: out, operations: [] };
|
|
17228
|
+
if (unique.length === 0) return { entities: out, operations: [], kindBackfills: [] };
|
|
17229
17229
|
const existing = await ctx.entityCollection.query(import_watermelondb16.Q.where("canonical_name", import_watermelondb16.Q.oneOf(unique))).fetch();
|
|
17230
17230
|
const existingNames = new Set(existing.map((e) => e.canonicalName));
|
|
17231
|
-
const
|
|
17231
|
+
const kindBackfills = existing.filter((e) => {
|
|
17232
17232
|
const incoming = kindByName.get(e.canonicalName);
|
|
17233
17233
|
return incoming !== void 0 && (e.kind === null || e.kind === void 0 || e.kind === "");
|
|
17234
|
-
});
|
|
17234
|
+
}).map((record) => ({ record, kind: kindByName.get(record.canonicalName) }));
|
|
17235
17235
|
const missing = unique.filter((n) => !existingNames.has(n));
|
|
17236
17236
|
const created = missing.map(
|
|
17237
17237
|
(name) => ctx.entityCollection.prepareCreate((record) => {
|
|
@@ -17240,14 +17240,19 @@ async function upsertEntitiesInWrite(ctx, entities) {
|
|
|
17240
17240
|
if (kind !== void 0) record._setRaw("kind", kind);
|
|
17241
17241
|
})
|
|
17242
17242
|
);
|
|
17243
|
-
const updated = updates.map(
|
|
17244
|
-
(e) => e.prepareUpdate((record) => {
|
|
17245
|
-
record._setRaw("kind", kindByName.get(e.canonicalName));
|
|
17246
|
-
})
|
|
17247
|
-
);
|
|
17248
17243
|
for (const e of existing) out.set(e.canonicalName, entityToStored(e));
|
|
17249
17244
|
for (const record of created) out.set(record.canonicalName, entityToStored(record));
|
|
17250
|
-
|
|
17245
|
+
for (const { record, kind } of kindBackfills) {
|
|
17246
|
+
out.set(record.canonicalName, { ...entityToStored(record), kind });
|
|
17247
|
+
}
|
|
17248
|
+
return { entities: out, operations: created, kindBackfills };
|
|
17249
|
+
}
|
|
17250
|
+
function prepareKindBackfills(backfills) {
|
|
17251
|
+
return backfills.map(
|
|
17252
|
+
({ record, kind }) => record.prepareUpdate((r) => {
|
|
17253
|
+
r._setRaw("kind", kind);
|
|
17254
|
+
})
|
|
17255
|
+
);
|
|
17251
17256
|
}
|
|
17252
17257
|
async function findVaultRowInWrite(ctx, memoryId) {
|
|
17253
17258
|
try {
|
|
@@ -17297,10 +17302,12 @@ function topicsForEntities(entities, displayNames, source) {
|
|
|
17297
17302
|
function toEntityObjects(entityInputs) {
|
|
17298
17303
|
return entityInputs.map((e) => typeof e === "string" ? { name: e } : e);
|
|
17299
17304
|
}
|
|
17300
|
-
async function
|
|
17305
|
+
async function resolveMemoryTopicsWrite(ctx, memoryId, linked, inputs, source) {
|
|
17301
17306
|
const row = await findVaultRowInWrite(ctx, memoryId);
|
|
17302
|
-
|
|
17303
|
-
|
|
17307
|
+
return resolveTopicsWrite(row, linked, displayNamesOf(toEntityObjects(inputs)), source);
|
|
17308
|
+
}
|
|
17309
|
+
function prepareMemoryTopicsUpdate(write) {
|
|
17310
|
+
return prepareTopicsUpdate(write.row, write.topics, Date.now());
|
|
17304
17311
|
}
|
|
17305
17312
|
async function linkMemoryEntitiesOp(ctx, memoryId, entityInputs, options) {
|
|
17306
17313
|
if (entityInputs.length === 0) return [];
|
|
@@ -17309,15 +17316,16 @@ async function linkMemoryEntitiesOp(ctx, memoryId, entityInputs, options) {
|
|
|
17309
17316
|
let skipped = false;
|
|
17310
17317
|
let entities = [];
|
|
17311
17318
|
await ctx.database.write(async () => {
|
|
17312
|
-
const {
|
|
17313
|
-
|
|
17314
|
-
|
|
17315
|
-
|
|
17319
|
+
const {
|
|
17320
|
+
entities: byName,
|
|
17321
|
+
operations: entityOps,
|
|
17322
|
+
kindBackfills
|
|
17323
|
+
} = await upsertEntitiesInWrite(ctx, normalized);
|
|
17316
17324
|
entities = Array.from(byName.values());
|
|
17317
17325
|
const vaultRow = await findVaultRowInWrite(ctx, memoryId);
|
|
17318
17326
|
if (options?.unlessTopicsUserManaged && autoLinkBlocked(vaultRow)) {
|
|
17319
|
-
if (entityOps.length > 0) {
|
|
17320
|
-
await ctx.database.batch(...entityOps);
|
|
17327
|
+
if (entityOps.length > 0 || kindBackfills.length > 0) {
|
|
17328
|
+
await ctx.database.batch(...entityOps, ...prepareKindBackfills(kindBackfills));
|
|
17321
17329
|
}
|
|
17322
17330
|
skipped = true;
|
|
17323
17331
|
return;
|
|
@@ -17337,7 +17345,9 @@ async function linkMemoryEntitiesOp(ctx, memoryId, entityInputs, options) {
|
|
|
17337
17345
|
displayNamesOf(normalized),
|
|
17338
17346
|
options?.topicsSource ?? "auto"
|
|
17339
17347
|
);
|
|
17340
|
-
if (entityOps.length === 0 && toCreate.length === 0 && topicsWrite === null)
|
|
17348
|
+
if (entityOps.length === 0 && kindBackfills.length === 0 && toCreate.length === 0 && topicsWrite === null) {
|
|
17349
|
+
return;
|
|
17350
|
+
}
|
|
17341
17351
|
const linkOps = toCreate.map(
|
|
17342
17352
|
(e) => ctx.memoryEntityCollection.prepareCreate((record) => {
|
|
17343
17353
|
record._setRaw("memory_id", memoryId);
|
|
@@ -17347,6 +17357,7 @@ async function linkMemoryEntitiesOp(ctx, memoryId, entityInputs, options) {
|
|
|
17347
17357
|
);
|
|
17348
17358
|
await ctx.database.batch(
|
|
17349
17359
|
...entityOps,
|
|
17360
|
+
...prepareKindBackfills(kindBackfills),
|
|
17350
17361
|
...linkOps,
|
|
17351
17362
|
...topicsWrite ? [prepareTopicsUpdate(topicsWrite.row, topicsWrite.topics, Date.now())] : []
|
|
17352
17363
|
);
|
|
@@ -17384,10 +17395,11 @@ async function replaceMemoryEntities(ctx, memoryId, entityInputs, options) {
|
|
|
17384
17395
|
skipped = true;
|
|
17385
17396
|
return;
|
|
17386
17397
|
}
|
|
17387
|
-
const {
|
|
17388
|
-
|
|
17389
|
-
|
|
17390
|
-
|
|
17398
|
+
const {
|
|
17399
|
+
entities: byName,
|
|
17400
|
+
operations: entityOps,
|
|
17401
|
+
kindBackfills
|
|
17402
|
+
} = await upsertEntitiesInWrite(ctx, normalized);
|
|
17391
17403
|
entities = Array.from(byName.values());
|
|
17392
17404
|
const existingLinks = await ctx.memoryEntityCollection.query(import_watermelondb16.Q.where("memory_id", memoryId)).fetch();
|
|
17393
17405
|
const keep = new Set(entities.map((e) => e.uniqueId));
|
|
@@ -17400,12 +17412,13 @@ async function replaceMemoryEntities(ctx, memoryId, entityInputs, options) {
|
|
|
17400
17412
|
displayNamesOf(normalized),
|
|
17401
17413
|
options.topicsSource
|
|
17402
17414
|
);
|
|
17403
|
-
if (entityOps.length === 0 && toCreate.length === 0 && toDestroy.length === 0 && topicsWrite === null) {
|
|
17415
|
+
if (entityOps.length === 0 && kindBackfills.length === 0 && toCreate.length === 0 && toDestroy.length === 0 && topicsWrite === null) {
|
|
17404
17416
|
return;
|
|
17405
17417
|
}
|
|
17406
17418
|
const orphans = await findOrphanedEntities(ctx, memoryId, toDestroy);
|
|
17407
17419
|
await ctx.database.batch(
|
|
17408
17420
|
...entityOps,
|
|
17421
|
+
...prepareKindBackfills(kindBackfills),
|
|
17409
17422
|
...toCreate.map(
|
|
17410
17423
|
(e) => ctx.memoryEntityCollection.prepareCreate((record) => {
|
|
17411
17424
|
record._setRaw("memory_id", memoryId);
|
|
@@ -18471,27 +18484,36 @@ async function backfillMemoryTopicsOp(ctx, memoryIds) {
|
|
|
18471
18484
|
if (!entityCtx) {
|
|
18472
18485
|
throw new Error("backfillMemoryTopicsOp requires ctx.entityCtx");
|
|
18473
18486
|
}
|
|
18487
|
+
const uniqueIds = Array.from(new Set(memoryIds));
|
|
18488
|
+
if (uniqueIds.length === 0) return [];
|
|
18474
18489
|
const filled = [];
|
|
18475
|
-
|
|
18476
|
-
|
|
18477
|
-
|
|
18478
|
-
record = await ctx.vaultMemoryCollection.find(id);
|
|
18479
|
-
} catch {
|
|
18480
|
-
continue;
|
|
18481
|
-
}
|
|
18482
|
-
if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) continue;
|
|
18483
|
-
if (parseTopics(record.topics) !== null) continue;
|
|
18484
|
-
const links = await entityCtx.memoryEntityCollection.query(import_watermelondb17.Q.where("memory_id", id)).unsafeFetchRaw();
|
|
18485
|
-
const entityIds = links.map((l) => String(l.entity_id));
|
|
18486
|
-
if (entityIds.length === 0) continue;
|
|
18487
|
-
const entities = await entityCtx.entityCollection.query(import_watermelondb17.Q.where("id", import_watermelondb17.Q.oneOf(entityIds))).fetch();
|
|
18488
|
-
if (entities.length === 0) continue;
|
|
18489
|
-
const source = record.topicsUserManaged ? "user" : "auto";
|
|
18490
|
+
const CHUNK = 500;
|
|
18491
|
+
for (let i = 0; i < uniqueIds.length; i += CHUNK) {
|
|
18492
|
+
const chunkIds = uniqueIds.slice(i, i + CHUNK);
|
|
18490
18493
|
await ctx.database.write(async () => {
|
|
18491
|
-
const
|
|
18492
|
-
|
|
18493
|
-
|
|
18494
|
-
|
|
18494
|
+
const writes = [];
|
|
18495
|
+
for (const id of chunkIds) {
|
|
18496
|
+
let record;
|
|
18497
|
+
try {
|
|
18498
|
+
record = await ctx.vaultMemoryCollection.find(id);
|
|
18499
|
+
} catch {
|
|
18500
|
+
continue;
|
|
18501
|
+
}
|
|
18502
|
+
if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) continue;
|
|
18503
|
+
if (parseTopics(record.topics) !== null) continue;
|
|
18504
|
+
const links = await entityCtx.memoryEntityCollection.query(import_watermelondb17.Q.where("memory_id", id)).unsafeFetchRaw();
|
|
18505
|
+
const entityIds = links.map((l) => String(l.entity_id));
|
|
18506
|
+
if (entityIds.length === 0) continue;
|
|
18507
|
+
const entities = await entityCtx.entityCollection.query(import_watermelondb17.Q.where("id", import_watermelondb17.Q.oneOf(entityIds))).fetch();
|
|
18508
|
+
if (entities.length === 0) continue;
|
|
18509
|
+
const source = record.topicsUserManaged ? "user" : "auto";
|
|
18510
|
+
const write = await resolveMemoryTopicsWrite(entityCtx, id, entities, [], source);
|
|
18511
|
+
if (write) writes.push(write);
|
|
18512
|
+
}
|
|
18513
|
+
if (writes.length === 0) return;
|
|
18514
|
+
const prepared = writes.map(prepareMemoryTopicsUpdate);
|
|
18515
|
+
await ctx.database.batch(...prepared);
|
|
18516
|
+
for (const write of writes) filled.push(write.row.id);
|
|
18495
18517
|
});
|
|
18496
18518
|
}
|
|
18497
18519
|
return filled;
|
|
@@ -30011,7 +30033,7 @@ function createAutoExtractor(options) {
|
|
|
30011
30033
|
const t0 = Date.now();
|
|
30012
30034
|
void (async () => {
|
|
30013
30035
|
try {
|
|
30014
|
-
const { candidates, results, failedCount, outcome } = await extractAndRetain(
|
|
30036
|
+
const { candidates, results, failedCount, outcome, failure } = await extractAndRetain(
|
|
30015
30037
|
window2,
|
|
30016
30038
|
retainCtx,
|
|
30017
30039
|
{
|
|
@@ -30051,7 +30073,11 @@ function createAutoExtractor(options) {
|
|
|
30051
30073
|
failedCount,
|
|
30052
30074
|
durationMs: Date.now() - t0,
|
|
30053
30075
|
conversationId,
|
|
30054
|
-
outcome
|
|
30076
|
+
outcome,
|
|
30077
|
+
// Only set alongside `outcome: "empty-after-retry"`. Spread so the key
|
|
30078
|
+
// is absent rather than explicitly undefined on a healthy turn —
|
|
30079
|
+
// analytics backends store an explicit undefined as a real value.
|
|
30080
|
+
...failure !== void 0 && { failure }
|
|
30055
30081
|
});
|
|
30056
30082
|
} catch (err) {
|
|
30057
30083
|
options.onError?.(err instanceof Error ? err : new Error(String(err)), conversationId);
|
package/dist/server/index.d.mts
CHANGED
|
@@ -6615,6 +6615,14 @@ declare function relinkMemoryTopicsOp(ctx: VaultMemoryOperationsContext, memoryI
|
|
|
6615
6615
|
* row has: a curated memory's topics are recorded as `user`, everything else as
|
|
6616
6616
|
* `auto`. Skips deleted, foreign-user, unlinked rows, and rows that already have
|
|
6617
6617
|
* a record. Returns the ids filled.
|
|
6618
|
+
*
|
|
6619
|
+
* Runs as ONE writer over the whole (caller-bounded) list, in two phases:
|
|
6620
|
+
* resolve every row's write — all the awaits — and only then prepare and batch,
|
|
6621
|
+
* synchronously. Resolving and preparing per row inside its own writer is what
|
|
6622
|
+
* fired WatermelonDB's "wasn't sent to batch() synchronously" diagnostic once
|
|
6623
|
+
* per memory (~107 on a single dev launch, sdk#891); it also cost N writes.
|
|
6624
|
+
* Same treatment as {@link stampTopicsExtractedAtOp}, including its
|
|
6625
|
+
* transpilation hazard — the prepare pass MUST stay a `.map()`.
|
|
6618
6626
|
*/
|
|
6619
6627
|
declare function backfillMemoryTopicsOp(ctx: VaultMemoryOperationsContext, memoryIds: readonly string[]): Promise<string[]>;
|
|
6620
6628
|
declare function deleteAllVaultMemoriesForUserOp(ctx: VaultMemoryOperationsContext, userId: string): Promise<number>;
|
|
@@ -7807,6 +7815,22 @@ interface TurnCompleteEvent {
|
|
|
7807
7815
|
* previously indistinguishable (both surfaced as zero candidates).
|
|
7808
7816
|
*/
|
|
7809
7817
|
outcome: ExtractOutcome;
|
|
7818
|
+
/**
|
|
7819
|
+
* Present only alongside `outcome: "empty-after-retry"` — WHICH failure ended
|
|
7820
|
+
* the turn (#888).
|
|
7821
|
+
*
|
|
7822
|
+
* `outcome` says extraction gave up; this says why, from a stable enum. The
|
|
7823
|
+
* distinction is the whole point: a 2026-08-11 audit measured ~63% of
|
|
7824
|
+
* production extraction turns ending in `empty-after-retry` and could not tell
|
|
7825
|
+
* from telemetry whether the cause was the freeloader 403 everyone assumed or
|
|
7826
|
+
* something else. It took a Prometheus cross-check to find the real one — the
|
|
7827
|
+
* portal returning HTTP 200 with an empty body, which it counts as a success.
|
|
7828
|
+
*
|
|
7829
|
+
* Forward `failure.reason` into your extraction analytics event; all three
|
|
7830
|
+
* fields are bounded (an enum, an HTTP status, a small attempt count) and none
|
|
7831
|
+
* carries content.
|
|
7832
|
+
*/
|
|
7833
|
+
failure?: PortalLlmFailure;
|
|
7810
7834
|
}
|
|
7811
7835
|
/** @public */
|
|
7812
7836
|
/**
|
package/dist/server/index.d.ts
CHANGED
|
@@ -6615,6 +6615,14 @@ declare function relinkMemoryTopicsOp(ctx: VaultMemoryOperationsContext, memoryI
|
|
|
6615
6615
|
* row has: a curated memory's topics are recorded as `user`, everything else as
|
|
6616
6616
|
* `auto`. Skips deleted, foreign-user, unlinked rows, and rows that already have
|
|
6617
6617
|
* a record. Returns the ids filled.
|
|
6618
|
+
*
|
|
6619
|
+
* Runs as ONE writer over the whole (caller-bounded) list, in two phases:
|
|
6620
|
+
* resolve every row's write — all the awaits — and only then prepare and batch,
|
|
6621
|
+
* synchronously. Resolving and preparing per row inside its own writer is what
|
|
6622
|
+
* fired WatermelonDB's "wasn't sent to batch() synchronously" diagnostic once
|
|
6623
|
+
* per memory (~107 on a single dev launch, sdk#891); it also cost N writes.
|
|
6624
|
+
* Same treatment as {@link stampTopicsExtractedAtOp}, including its
|
|
6625
|
+
* transpilation hazard — the prepare pass MUST stay a `.map()`.
|
|
6618
6626
|
*/
|
|
6619
6627
|
declare function backfillMemoryTopicsOp(ctx: VaultMemoryOperationsContext, memoryIds: readonly string[]): Promise<string[]>;
|
|
6620
6628
|
declare function deleteAllVaultMemoriesForUserOp(ctx: VaultMemoryOperationsContext, userId: string): Promise<number>;
|
|
@@ -7807,6 +7815,22 @@ interface TurnCompleteEvent {
|
|
|
7807
7815
|
* previously indistinguishable (both surfaced as zero candidates).
|
|
7808
7816
|
*/
|
|
7809
7817
|
outcome: ExtractOutcome;
|
|
7818
|
+
/**
|
|
7819
|
+
* Present only alongside `outcome: "empty-after-retry"` — WHICH failure ended
|
|
7820
|
+
* the turn (#888).
|
|
7821
|
+
*
|
|
7822
|
+
* `outcome` says extraction gave up; this says why, from a stable enum. The
|
|
7823
|
+
* distinction is the whole point: a 2026-08-11 audit measured ~63% of
|
|
7824
|
+
* production extraction turns ending in `empty-after-retry` and could not tell
|
|
7825
|
+
* from telemetry whether the cause was the freeloader 403 everyone assumed or
|
|
7826
|
+
* something else. It took a Prometheus cross-check to find the real one — the
|
|
7827
|
+
* portal returning HTTP 200 with an empty body, which it counts as a success.
|
|
7828
|
+
*
|
|
7829
|
+
* Forward `failure.reason` into your extraction analytics event; all three
|
|
7830
|
+
* fields are bounded (an enum, an HTTP status, a small attempt count) and none
|
|
7831
|
+
* carries content.
|
|
7832
|
+
*/
|
|
7833
|
+
failure?: PortalLlmFailure;
|
|
7810
7834
|
}
|
|
7811
7835
|
/** @public */
|
|
7812
7836
|
/**
|
package/dist/server/index.mjs
CHANGED
|
@@ -141,7 +141,7 @@ import {
|
|
|
141
141
|
updateVaultMemoryOp,
|
|
142
142
|
upsertMessageOp,
|
|
143
143
|
vaultMemoryToStored
|
|
144
|
-
} from "./chunk-
|
|
144
|
+
} from "./chunk-I56324FR.mjs";
|
|
145
145
|
import {
|
|
146
146
|
createStreamingDeAnonymizer,
|
|
147
147
|
notifyConsolidationFallback,
|
|
@@ -6371,7 +6371,7 @@ function createAutoExtractor(options) {
|
|
|
6371
6371
|
const t0 = Date.now();
|
|
6372
6372
|
void (async () => {
|
|
6373
6373
|
try {
|
|
6374
|
-
const { candidates, results, failedCount, outcome } = await extractAndRetain(
|
|
6374
|
+
const { candidates, results, failedCount, outcome, failure } = await extractAndRetain(
|
|
6375
6375
|
window2,
|
|
6376
6376
|
retainCtx,
|
|
6377
6377
|
{
|
|
@@ -6411,7 +6411,11 @@ function createAutoExtractor(options) {
|
|
|
6411
6411
|
failedCount,
|
|
6412
6412
|
durationMs: Date.now() - t0,
|
|
6413
6413
|
conversationId,
|
|
6414
|
-
outcome
|
|
6414
|
+
outcome,
|
|
6415
|
+
// Only set alongside `outcome: "empty-after-retry"`. Spread so the key
|
|
6416
|
+
// is absent rather than explicitly undefined on a healthy turn —
|
|
6417
|
+
// analytics backends store an explicit undefined as a real value.
|
|
6418
|
+
...failure !== void 0 && { failure }
|
|
6415
6419
|
});
|
|
6416
6420
|
} catch (err) {
|
|
6417
6421
|
options.onError?.(err instanceof Error ? err : new Error(String(err)), conversationId);
|