@anuma/sdk 7.3.4 → 7.5.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 +215 -15
- package/dist/expo/index.d.mts +33 -1
- package/dist/expo/index.d.ts +33 -1
- package/dist/expo/index.mjs +215 -15
- package/dist/react/index.cjs +215 -15
- package/dist/react/index.d.mts +33 -1
- package/dist/react/index.d.ts +33 -1
- package/dist/react/index.mjs +215 -15
- package/dist/server/index.cjs +72 -15
- package/dist/server/index.d.mts +33 -1
- package/dist/server/index.d.ts +33 -1
- package/dist/server/index.mjs +72 -15
- package/package.json +1 -1
package/dist/expo/index.mjs
CHANGED
|
@@ -17095,9 +17095,51 @@ function isBorderline(input) {
|
|
|
17095
17095
|
}
|
|
17096
17096
|
return false;
|
|
17097
17097
|
}
|
|
17098
|
+
function vaultDecayBackend(vaultCtx) {
|
|
17099
|
+
return {
|
|
17100
|
+
candidates: () => getDecayCandidatesRawOp(vaultCtx),
|
|
17101
|
+
archive: async (rows, now) => {
|
|
17102
|
+
const archived = /* @__PURE__ */ new Set();
|
|
17103
|
+
for (const c of rows) {
|
|
17104
|
+
const ok = await archiveVaultMemoryOp(vaultCtx, c.uniqueId, {
|
|
17105
|
+
now,
|
|
17106
|
+
expectedUpdatedAt: c.updatedAt,
|
|
17107
|
+
expectedLastObservedAt: c.lastObservedAt ?? null
|
|
17108
|
+
});
|
|
17109
|
+
if (ok) archived.add(c.uniqueId);
|
|
17110
|
+
}
|
|
17111
|
+
return archived;
|
|
17112
|
+
},
|
|
17113
|
+
hardDelete: async (rows, deleteOptions) => {
|
|
17114
|
+
const deleted = /* @__PURE__ */ new Set();
|
|
17115
|
+
for (const c of rows) {
|
|
17116
|
+
if (await hardDeleteDecayedOp(vaultCtx, c.uniqueId, deleteOptions)) deleted.add(c.uniqueId);
|
|
17117
|
+
}
|
|
17118
|
+
return deleted;
|
|
17119
|
+
}
|
|
17120
|
+
};
|
|
17121
|
+
}
|
|
17098
17122
|
function createDecaySweeper(options) {
|
|
17099
|
-
const { vaultCtx,
|
|
17123
|
+
const { vaultCtx, ...sweepOptions } = options;
|
|
17100
17124
|
assertVaultScopeForSweep(vaultCtx);
|
|
17125
|
+
return createDecaySweeperOver(vaultDecayBackend(vaultCtx), sweepOptions);
|
|
17126
|
+
}
|
|
17127
|
+
function ruleBasedDecayOptions(options = {}) {
|
|
17128
|
+
if (options.classifier !== void 0)
|
|
17129
|
+
throw new Error(
|
|
17130
|
+
"MemoryStore.decay sweeps by rule only; a decay classifier needs decrypted content"
|
|
17131
|
+
);
|
|
17132
|
+
const { now, policy, onSwept, onError } = options;
|
|
17133
|
+
return {
|
|
17134
|
+
...now !== void 0 && { now },
|
|
17135
|
+
...policy && { policy },
|
|
17136
|
+
...onSwept && { onSwept },
|
|
17137
|
+
...onError && { onError }
|
|
17138
|
+
};
|
|
17139
|
+
}
|
|
17140
|
+
function createDecaySweeperOver(backend, options) {
|
|
17141
|
+
const { policy, classifier, onSwept, onError } = options;
|
|
17142
|
+
const maxTransitions = options.maxTransitionsPerSweep ?? Number.POSITIVE_INFINITY;
|
|
17101
17143
|
const hardDeleteWindowMs = policy?.hardDeleteWindowMs ?? DEFAULT_DECAY_POLICY.hardDeleteWindowMs;
|
|
17102
17144
|
const maxClassifierCalls = options.maxClassifierCallsPerSweep ?? DEFAULT_MAX_CLASSIFIER_CALLS_PER_SWEEP;
|
|
17103
17145
|
const classifierCache = /* @__PURE__ */ new Map();
|
|
@@ -17139,7 +17181,7 @@ function createDecaySweeper(options) {
|
|
|
17139
17181
|
const now = resolveNow(options.now);
|
|
17140
17182
|
let candidates;
|
|
17141
17183
|
try {
|
|
17142
|
-
candidates = await
|
|
17184
|
+
candidates = await backend.candidates();
|
|
17143
17185
|
} catch (err) {
|
|
17144
17186
|
onError?.(err instanceof Error ? err : new Error(String(err)));
|
|
17145
17187
|
return emptyResult();
|
|
@@ -17162,25 +17204,37 @@ function createDecaySweeper(options) {
|
|
|
17162
17204
|
result.scanned = candidates.length;
|
|
17163
17205
|
result.classifierCalls = sweep.classifierCalls;
|
|
17164
17206
|
result.classifierCapHits = sweep.classifierCapHits;
|
|
17207
|
+
let landed = 0;
|
|
17208
|
+
const apply = async (queue, run, count2) => {
|
|
17209
|
+
let next = 0;
|
|
17210
|
+
while (next < queue.length && landed < maxTransitions) {
|
|
17211
|
+
const batch = queue.slice(next, next + (maxTransitions - landed));
|
|
17212
|
+
next += batch.length;
|
|
17213
|
+
const done = await run(batch.map(({ candidate }) => candidate));
|
|
17214
|
+
for (const { candidate, source } of batch) {
|
|
17215
|
+
if (!done.has(candidate.uniqueId)) continue;
|
|
17216
|
+
landed++;
|
|
17217
|
+
count2(source);
|
|
17218
|
+
}
|
|
17219
|
+
}
|
|
17220
|
+
};
|
|
17165
17221
|
try {
|
|
17166
|
-
|
|
17167
|
-
|
|
17168
|
-
|
|
17169
|
-
|
|
17170
|
-
expectedLastObservedAt: c.lastObservedAt ?? null
|
|
17171
|
-
});
|
|
17172
|
-
if (ok) {
|
|
17222
|
+
await apply(
|
|
17223
|
+
toArchive,
|
|
17224
|
+
(rows) => backend.archive(rows, now),
|
|
17225
|
+
(source) => {
|
|
17173
17226
|
result.archived++;
|
|
17174
17227
|
result[source].archived++;
|
|
17175
17228
|
}
|
|
17176
|
-
|
|
17177
|
-
|
|
17178
|
-
|
|
17179
|
-
|
|
17229
|
+
);
|
|
17230
|
+
await apply(
|
|
17231
|
+
toDelete,
|
|
17232
|
+
(rows) => backend.hardDelete(rows, { hardDeleteWindowMs, now }),
|
|
17233
|
+
(source) => {
|
|
17180
17234
|
result.deleted++;
|
|
17181
17235
|
result[source].deleted++;
|
|
17182
17236
|
}
|
|
17183
|
-
|
|
17237
|
+
);
|
|
17184
17238
|
} catch (err) {
|
|
17185
17239
|
onError?.(err instanceof Error ? err : new Error(String(err)));
|
|
17186
17240
|
}
|
|
@@ -19224,7 +19278,10 @@ function createLocalMemoryStore(options) {
|
|
|
19224
19278
|
return () => subscriptions.forEach((s) => s.unsubscribe());
|
|
19225
19279
|
},
|
|
19226
19280
|
maintenance,
|
|
19227
|
-
topicMaintenance: maintenance
|
|
19281
|
+
topicMaintenance: maintenance,
|
|
19282
|
+
decay: {
|
|
19283
|
+
createDecaySweeper: (sweeperOptions) => createDecaySweeper({ ...ruleBasedDecayOptions(sweeperOptions), vaultCtx })
|
|
19284
|
+
}
|
|
19228
19285
|
};
|
|
19229
19286
|
}
|
|
19230
19287
|
|
|
@@ -20614,6 +20671,9 @@ var MAX_QUERY_TOPICS = 100;
|
|
|
20614
20671
|
var MAX_QUERY_FILTER = 20;
|
|
20615
20672
|
var GRAPH_LANE_ROWS = 256;
|
|
20616
20673
|
var TEMPORAL_LANE_ROWS = 256;
|
|
20674
|
+
var REPAIR_ROWS = 50;
|
|
20675
|
+
var REPAIR_SCAN = 2e3;
|
|
20676
|
+
var DECAY_TRANSITIONS_PER_SWEEP = 200;
|
|
20617
20677
|
var RemoteMemoryPartialCreateError = class extends Error {
|
|
20618
20678
|
constructor(created, cause) {
|
|
20619
20679
|
super(`createMany stored ${created.length} memories before a batch failed`);
|
|
@@ -20622,6 +20682,9 @@ var RemoteMemoryPartialCreateError = class extends Error {
|
|
|
20622
20682
|
this.name = "RemoteMemoryPartialCreateError";
|
|
20623
20683
|
}
|
|
20624
20684
|
};
|
|
20685
|
+
function rejectsInput(error) {
|
|
20686
|
+
return error instanceof EmbeddingHttpError && error.status !== void 0 && error.status >= 400 && error.status < 500 && error.status !== 429 && !isFatalEmbeddingError(error);
|
|
20687
|
+
}
|
|
20625
20688
|
function warnFailed(failed) {
|
|
20626
20689
|
if (failed.length)
|
|
20627
20690
|
getLogger().warn(
|
|
@@ -21127,6 +21190,42 @@ function createRemoteMemoryStore(options) {
|
|
|
21127
21190
|
relinkTopics: () => Promise.resolve([]),
|
|
21128
21191
|
backfillTopics: () => Promise.resolve([])
|
|
21129
21192
|
};
|
|
21193
|
+
const decayRow = (memory) => ({
|
|
21194
|
+
uniqueId: memory.memory_id,
|
|
21195
|
+
factType: memory.fact_type ?? null,
|
|
21196
|
+
eventTimeEnd: memory.event_time_end ?? null,
|
|
21197
|
+
eventTimeKind: memory.event_time_kind ?? null,
|
|
21198
|
+
updatedAt: memory.updated_at,
|
|
21199
|
+
lastObservedAt: memory.last_observed_at ?? null,
|
|
21200
|
+
archivedAt: memory.archived_at ?? null,
|
|
21201
|
+
source: memory.source ?? null,
|
|
21202
|
+
trustTier: memory.trust_tier ?? null
|
|
21203
|
+
});
|
|
21204
|
+
const decayWrite = async (rows, change, edit) => {
|
|
21205
|
+
if (rows.length === 0) return /* @__PURE__ */ new Set();
|
|
21206
|
+
const seen2 = new Map(rows.map((row) => [row.uniqueId, row]));
|
|
21207
|
+
const { saved, failed } = await mutateMany(
|
|
21208
|
+
[...seen2.keys()],
|
|
21209
|
+
() => change,
|
|
21210
|
+
(memory) => edit(memory, seen2.get(memory.memory_id))
|
|
21211
|
+
);
|
|
21212
|
+
if (failed.size)
|
|
21213
|
+
getLogger().warn("[memory/remote-store] Decay skipped memories:", [...failed.values()]);
|
|
21214
|
+
return new Set(saved.keys());
|
|
21215
|
+
};
|
|
21216
|
+
const decayBackend = {
|
|
21217
|
+
candidates: async () => (await pages(metadata2, { include_archived: true, include_quarantined: true })).filter(({ memory }) => memory.kind === void 0 || memory.kind === null).map(({ memory }) => decayRow(memory)),
|
|
21218
|
+
archive: (rows, now) => decayWrite(
|
|
21219
|
+
rows,
|
|
21220
|
+
"edit",
|
|
21221
|
+
(memory, seen2) => (memory.archived_at ?? null) === null && memory.updated_at === seen2.updatedAt && (memory.last_observed_at ?? null) === (seen2.lastObservedAt ?? null) ? { ...memory, archived_at: now } : null
|
|
21222
|
+
),
|
|
21223
|
+
hardDelete: (rows, { hardDeleteWindowMs, now }) => decayWrite(
|
|
21224
|
+
rows,
|
|
21225
|
+
"membership",
|
|
21226
|
+
(memory) => memory.archived_at !== void 0 && memory.archived_at !== null && now - memory.archived_at > hardDeleteWindowMs ? { ...memory, is_deleted: true } : null
|
|
21227
|
+
)
|
|
21228
|
+
};
|
|
21130
21229
|
const everyState = {
|
|
21131
21230
|
include_deleted: true,
|
|
21132
21231
|
include_archived: true,
|
|
@@ -21202,9 +21301,104 @@ function createRemoteMemoryStore(options) {
|
|
|
21202
21301
|
polling = false;
|
|
21203
21302
|
});
|
|
21204
21303
|
};
|
|
21304
|
+
const unrepairable = /* @__PURE__ */ new Set();
|
|
21305
|
+
let repairCursor;
|
|
21306
|
+
const repairEmbeddings = async ({
|
|
21307
|
+
maxRows = REPAIR_ROWS,
|
|
21308
|
+
maxScan = REPAIR_SCAN,
|
|
21309
|
+
cursor: start = repairCursor
|
|
21310
|
+
} = {}) => {
|
|
21311
|
+
const scannedRows = [];
|
|
21312
|
+
let cursor2 = start;
|
|
21313
|
+
do {
|
|
21314
|
+
const page = await metadata2({
|
|
21315
|
+
include_deleted: true,
|
|
21316
|
+
include_archived: true,
|
|
21317
|
+
include_quarantined: true,
|
|
21318
|
+
include_superseded: true,
|
|
21319
|
+
limit: Math.min(200, Math.max(1, maxScan - scannedRows.length)),
|
|
21320
|
+
...cursor2 && { cursor: cursor2 }
|
|
21321
|
+
});
|
|
21322
|
+
scannedRows.push(...page.items);
|
|
21323
|
+
cursor2 = page.next_cursor;
|
|
21324
|
+
} while (cursor2 && scannedRows.length < maxScan);
|
|
21325
|
+
const allStale = scannedRows.filter(
|
|
21326
|
+
({ memory }) => memory.embedding_model !== model && !unrepairable.has(memory.memory_id)
|
|
21327
|
+
);
|
|
21328
|
+
const repaired = /* @__PURE__ */ new Set();
|
|
21329
|
+
const result = {
|
|
21330
|
+
scanned: scannedRows.length,
|
|
21331
|
+
reembedded: 0,
|
|
21332
|
+
failed: 0,
|
|
21333
|
+
skippedConflict: 0
|
|
21334
|
+
};
|
|
21335
|
+
const finish = () => {
|
|
21336
|
+
const settled = allStale.every(
|
|
21337
|
+
({ memory }) => repaired.has(memory.memory_id) || unrepairable.has(memory.memory_id)
|
|
21338
|
+
);
|
|
21339
|
+
repairCursor = settled ? cursor2 : start;
|
|
21340
|
+
return repairCursor ? { ...result, cursor: repairCursor } : result;
|
|
21341
|
+
};
|
|
21342
|
+
const stale = allStale.slice(0, maxRows).map(({ memory }) => memory.memory_id);
|
|
21343
|
+
if (stale.length === 0) return finish();
|
|
21344
|
+
const { records, unreadable } = await readEveryState(stale);
|
|
21345
|
+
result.failed += unreadable.size;
|
|
21346
|
+
for (const id of stale)
|
|
21347
|
+
if (unreadable.has(id) || !records.get(id)?.memory.content.trim()) unrepairable.add(id);
|
|
21348
|
+
const targets = stale.filter((id) => !unrepairable.has(id)).map((id) => records.get(id));
|
|
21349
|
+
if (targets.length === 0) return finish();
|
|
21350
|
+
const vectors = await embedForRepair(targets);
|
|
21351
|
+
if (!vectors) {
|
|
21352
|
+
result.failed += targets.length;
|
|
21353
|
+
return finish();
|
|
21354
|
+
}
|
|
21355
|
+
for (const [i, record2] of targets.entries()) {
|
|
21356
|
+
const vector = vectors[i];
|
|
21357
|
+
if (!vector) {
|
|
21358
|
+
result.failed++;
|
|
21359
|
+
continue;
|
|
21360
|
+
}
|
|
21361
|
+
await serialized(record2.memory.memory_id, async () => {
|
|
21362
|
+
try {
|
|
21363
|
+
const saved = await persistence.put(
|
|
21364
|
+
{ ...record2.memory, embedding: storedVector(vector), embedding_model: model },
|
|
21365
|
+
record2
|
|
21366
|
+
);
|
|
21367
|
+
notify("embedding", [saved]);
|
|
21368
|
+
repaired.add(record2.memory.memory_id);
|
|
21369
|
+
result.reembedded++;
|
|
21370
|
+
} catch (error) {
|
|
21371
|
+
if (error instanceof RemoteMemoryError && error.code === "version_conflict")
|
|
21372
|
+
result.skippedConflict++;
|
|
21373
|
+
else result.failed++;
|
|
21374
|
+
}
|
|
21375
|
+
});
|
|
21376
|
+
}
|
|
21377
|
+
return finish();
|
|
21378
|
+
};
|
|
21379
|
+
const embedForRepair = async (targets) => {
|
|
21380
|
+
const texts = targets.map(({ memory }) => memory.content);
|
|
21381
|
+
try {
|
|
21382
|
+
return await generateEmbeddings(texts, embeddingOptions);
|
|
21383
|
+
} catch (error) {
|
|
21384
|
+
getLogger().warn("[memory/remote-store] Failed to embed memories for repair:", error);
|
|
21385
|
+
if (!rejectsInput(error)) return null;
|
|
21386
|
+
}
|
|
21387
|
+
const vectors = [];
|
|
21388
|
+
for (const [i, text14] of texts.entries()) {
|
|
21389
|
+
try {
|
|
21390
|
+
[vectors[i]] = await generateEmbeddings([text14], embeddingOptions);
|
|
21391
|
+
} catch (error) {
|
|
21392
|
+
if (!rejectsInput(error)) return null;
|
|
21393
|
+
unrepairable.add(targets[i].memory.memory_id);
|
|
21394
|
+
}
|
|
21395
|
+
}
|
|
21396
|
+
return vectors;
|
|
21397
|
+
};
|
|
21205
21398
|
return {
|
|
21206
21399
|
masksEmbeddingInput: embeddingOptions.maskInput !== void 0,
|
|
21207
21400
|
topicMaintenance,
|
|
21401
|
+
repairEmbeddings,
|
|
21208
21402
|
list: async (listOptions = {}) => (await listRows(decrypted, listOptions, listFilters(listOptions), maxOf(listOptions))).map(
|
|
21209
21403
|
(r) => stored(r.memory)
|
|
21210
21404
|
),
|
|
@@ -21404,6 +21598,12 @@ function createRemoteMemoryStore(options) {
|
|
|
21404
21598
|
else if (result.action === "update" || result.action === "merge") notify("edit");
|
|
21405
21599
|
return result;
|
|
21406
21600
|
},
|
|
21601
|
+
decay: {
|
|
21602
|
+
createDecaySweeper: (sweeperOptions) => createDecaySweeperOver(decayBackend, {
|
|
21603
|
+
...ruleBasedDecayOptions(sweeperOptions),
|
|
21604
|
+
maxTransitionsPerSweep: DECAY_TRANSITIONS_PER_SWEEP
|
|
21605
|
+
})
|
|
21606
|
+
},
|
|
21407
21607
|
subscribe: (onChange, subscribeOptions = {}) => {
|
|
21408
21608
|
const subscriber = { onChange, options: subscribeOptions };
|
|
21409
21609
|
subscribers.add(subscriber);
|
package/dist/react/index.cjs
CHANGED
|
@@ -21016,9 +21016,51 @@ function isBorderline(input) {
|
|
|
21016
21016
|
}
|
|
21017
21017
|
return false;
|
|
21018
21018
|
}
|
|
21019
|
+
function vaultDecayBackend(vaultCtx) {
|
|
21020
|
+
return {
|
|
21021
|
+
candidates: () => getDecayCandidatesRawOp(vaultCtx),
|
|
21022
|
+
archive: async (rows, now) => {
|
|
21023
|
+
const archived = /* @__PURE__ */ new Set();
|
|
21024
|
+
for (const c of rows) {
|
|
21025
|
+
const ok = await archiveVaultMemoryOp(vaultCtx, c.uniqueId, {
|
|
21026
|
+
now,
|
|
21027
|
+
expectedUpdatedAt: c.updatedAt,
|
|
21028
|
+
expectedLastObservedAt: c.lastObservedAt ?? null
|
|
21029
|
+
});
|
|
21030
|
+
if (ok) archived.add(c.uniqueId);
|
|
21031
|
+
}
|
|
21032
|
+
return archived;
|
|
21033
|
+
},
|
|
21034
|
+
hardDelete: async (rows, deleteOptions) => {
|
|
21035
|
+
const deleted = /* @__PURE__ */ new Set();
|
|
21036
|
+
for (const c of rows) {
|
|
21037
|
+
if (await hardDeleteDecayedOp(vaultCtx, c.uniqueId, deleteOptions)) deleted.add(c.uniqueId);
|
|
21038
|
+
}
|
|
21039
|
+
return deleted;
|
|
21040
|
+
}
|
|
21041
|
+
};
|
|
21042
|
+
}
|
|
21019
21043
|
function createDecaySweeper(options) {
|
|
21020
|
-
const { vaultCtx,
|
|
21044
|
+
const { vaultCtx, ...sweepOptions } = options;
|
|
21021
21045
|
assertVaultScopeForSweep(vaultCtx);
|
|
21046
|
+
return createDecaySweeperOver(vaultDecayBackend(vaultCtx), sweepOptions);
|
|
21047
|
+
}
|
|
21048
|
+
function ruleBasedDecayOptions(options = {}) {
|
|
21049
|
+
if (options.classifier !== void 0)
|
|
21050
|
+
throw new Error(
|
|
21051
|
+
"MemoryStore.decay sweeps by rule only; a decay classifier needs decrypted content"
|
|
21052
|
+
);
|
|
21053
|
+
const { now, policy, onSwept, onError } = options;
|
|
21054
|
+
return {
|
|
21055
|
+
...now !== void 0 && { now },
|
|
21056
|
+
...policy && { policy },
|
|
21057
|
+
...onSwept && { onSwept },
|
|
21058
|
+
...onError && { onError }
|
|
21059
|
+
};
|
|
21060
|
+
}
|
|
21061
|
+
function createDecaySweeperOver(backend, options) {
|
|
21062
|
+
const { policy, classifier, onSwept, onError } = options;
|
|
21063
|
+
const maxTransitions = options.maxTransitionsPerSweep ?? Number.POSITIVE_INFINITY;
|
|
21022
21064
|
const hardDeleteWindowMs = policy?.hardDeleteWindowMs ?? DEFAULT_DECAY_POLICY.hardDeleteWindowMs;
|
|
21023
21065
|
const maxClassifierCalls = options.maxClassifierCallsPerSweep ?? DEFAULT_MAX_CLASSIFIER_CALLS_PER_SWEEP;
|
|
21024
21066
|
const classifierCache = /* @__PURE__ */ new Map();
|
|
@@ -21060,7 +21102,7 @@ function createDecaySweeper(options) {
|
|
|
21060
21102
|
const now = resolveNow(options.now);
|
|
21061
21103
|
let candidates;
|
|
21062
21104
|
try {
|
|
21063
|
-
candidates = await
|
|
21105
|
+
candidates = await backend.candidates();
|
|
21064
21106
|
} catch (err) {
|
|
21065
21107
|
onError?.(err instanceof Error ? err : new Error(String(err)));
|
|
21066
21108
|
return emptyResult();
|
|
@@ -21083,25 +21125,37 @@ function createDecaySweeper(options) {
|
|
|
21083
21125
|
result.scanned = candidates.length;
|
|
21084
21126
|
result.classifierCalls = sweep.classifierCalls;
|
|
21085
21127
|
result.classifierCapHits = sweep.classifierCapHits;
|
|
21128
|
+
let landed = 0;
|
|
21129
|
+
const apply = async (queue, run, count2) => {
|
|
21130
|
+
let next = 0;
|
|
21131
|
+
while (next < queue.length && landed < maxTransitions) {
|
|
21132
|
+
const batch = queue.slice(next, next + (maxTransitions - landed));
|
|
21133
|
+
next += batch.length;
|
|
21134
|
+
const done = await run(batch.map(({ candidate }) => candidate));
|
|
21135
|
+
for (const { candidate, source } of batch) {
|
|
21136
|
+
if (!done.has(candidate.uniqueId)) continue;
|
|
21137
|
+
landed++;
|
|
21138
|
+
count2(source);
|
|
21139
|
+
}
|
|
21140
|
+
}
|
|
21141
|
+
};
|
|
21086
21142
|
try {
|
|
21087
|
-
|
|
21088
|
-
|
|
21089
|
-
|
|
21090
|
-
|
|
21091
|
-
expectedLastObservedAt: c.lastObservedAt ?? null
|
|
21092
|
-
});
|
|
21093
|
-
if (ok) {
|
|
21143
|
+
await apply(
|
|
21144
|
+
toArchive,
|
|
21145
|
+
(rows) => backend.archive(rows, now),
|
|
21146
|
+
(source) => {
|
|
21094
21147
|
result.archived++;
|
|
21095
21148
|
result[source].archived++;
|
|
21096
21149
|
}
|
|
21097
|
-
|
|
21098
|
-
|
|
21099
|
-
|
|
21100
|
-
|
|
21150
|
+
);
|
|
21151
|
+
await apply(
|
|
21152
|
+
toDelete,
|
|
21153
|
+
(rows) => backend.hardDelete(rows, { hardDeleteWindowMs, now }),
|
|
21154
|
+
(source) => {
|
|
21101
21155
|
result.deleted++;
|
|
21102
21156
|
result[source].deleted++;
|
|
21103
21157
|
}
|
|
21104
|
-
|
|
21158
|
+
);
|
|
21105
21159
|
} catch (err) {
|
|
21106
21160
|
onError?.(err instanceof Error ? err : new Error(String(err)));
|
|
21107
21161
|
}
|
|
@@ -23186,7 +23240,10 @@ function createLocalMemoryStore(options) {
|
|
|
23186
23240
|
return () => subscriptions.forEach((s) => s.unsubscribe());
|
|
23187
23241
|
},
|
|
23188
23242
|
maintenance,
|
|
23189
|
-
topicMaintenance: maintenance
|
|
23243
|
+
topicMaintenance: maintenance,
|
|
23244
|
+
decay: {
|
|
23245
|
+
createDecaySweeper: (sweeperOptions) => createDecaySweeper({ ...ruleBasedDecayOptions(sweeperOptions), vaultCtx })
|
|
23246
|
+
}
|
|
23190
23247
|
};
|
|
23191
23248
|
}
|
|
23192
23249
|
|
|
@@ -24582,6 +24639,9 @@ var MAX_QUERY_TOPICS = 100;
|
|
|
24582
24639
|
var MAX_QUERY_FILTER = 20;
|
|
24583
24640
|
var GRAPH_LANE_ROWS = 256;
|
|
24584
24641
|
var TEMPORAL_LANE_ROWS = 256;
|
|
24642
|
+
var REPAIR_ROWS = 50;
|
|
24643
|
+
var REPAIR_SCAN = 2e3;
|
|
24644
|
+
var DECAY_TRANSITIONS_PER_SWEEP = 200;
|
|
24585
24645
|
var RemoteMemoryPartialCreateError = class extends Error {
|
|
24586
24646
|
constructor(created, cause) {
|
|
24587
24647
|
super(`createMany stored ${created.length} memories before a batch failed`);
|
|
@@ -24590,6 +24650,9 @@ var RemoteMemoryPartialCreateError = class extends Error {
|
|
|
24590
24650
|
this.name = "RemoteMemoryPartialCreateError";
|
|
24591
24651
|
}
|
|
24592
24652
|
};
|
|
24653
|
+
function rejectsInput(error) {
|
|
24654
|
+
return error instanceof EmbeddingHttpError && error.status !== void 0 && error.status >= 400 && error.status < 500 && error.status !== 429 && !isFatalEmbeddingError(error);
|
|
24655
|
+
}
|
|
24593
24656
|
function warnFailed(failed) {
|
|
24594
24657
|
if (failed.length)
|
|
24595
24658
|
getLogger().warn(
|
|
@@ -25095,6 +25158,42 @@ function createRemoteMemoryStore(options) {
|
|
|
25095
25158
|
relinkTopics: () => Promise.resolve([]),
|
|
25096
25159
|
backfillTopics: () => Promise.resolve([])
|
|
25097
25160
|
};
|
|
25161
|
+
const decayRow = (memory) => ({
|
|
25162
|
+
uniqueId: memory.memory_id,
|
|
25163
|
+
factType: memory.fact_type ?? null,
|
|
25164
|
+
eventTimeEnd: memory.event_time_end ?? null,
|
|
25165
|
+
eventTimeKind: memory.event_time_kind ?? null,
|
|
25166
|
+
updatedAt: memory.updated_at,
|
|
25167
|
+
lastObservedAt: memory.last_observed_at ?? null,
|
|
25168
|
+
archivedAt: memory.archived_at ?? null,
|
|
25169
|
+
source: memory.source ?? null,
|
|
25170
|
+
trustTier: memory.trust_tier ?? null
|
|
25171
|
+
});
|
|
25172
|
+
const decayWrite = async (rows, change, edit) => {
|
|
25173
|
+
if (rows.length === 0) return /* @__PURE__ */ new Set();
|
|
25174
|
+
const seen2 = new Map(rows.map((row) => [row.uniqueId, row]));
|
|
25175
|
+
const { saved, failed } = await mutateMany(
|
|
25176
|
+
[...seen2.keys()],
|
|
25177
|
+
() => change,
|
|
25178
|
+
(memory) => edit(memory, seen2.get(memory.memory_id))
|
|
25179
|
+
);
|
|
25180
|
+
if (failed.size)
|
|
25181
|
+
getLogger().warn("[memory/remote-store] Decay skipped memories:", [...failed.values()]);
|
|
25182
|
+
return new Set(saved.keys());
|
|
25183
|
+
};
|
|
25184
|
+
const decayBackend = {
|
|
25185
|
+
candidates: async () => (await pages(metadata2, { include_archived: true, include_quarantined: true })).filter(({ memory }) => memory.kind === void 0 || memory.kind === null).map(({ memory }) => decayRow(memory)),
|
|
25186
|
+
archive: (rows, now) => decayWrite(
|
|
25187
|
+
rows,
|
|
25188
|
+
"edit",
|
|
25189
|
+
(memory, seen2) => (memory.archived_at ?? null) === null && memory.updated_at === seen2.updatedAt && (memory.last_observed_at ?? null) === (seen2.lastObservedAt ?? null) ? { ...memory, archived_at: now } : null
|
|
25190
|
+
),
|
|
25191
|
+
hardDelete: (rows, { hardDeleteWindowMs, now }) => decayWrite(
|
|
25192
|
+
rows,
|
|
25193
|
+
"membership",
|
|
25194
|
+
(memory) => memory.archived_at !== void 0 && memory.archived_at !== null && now - memory.archived_at > hardDeleteWindowMs ? { ...memory, is_deleted: true } : null
|
|
25195
|
+
)
|
|
25196
|
+
};
|
|
25098
25197
|
const everyState = {
|
|
25099
25198
|
include_deleted: true,
|
|
25100
25199
|
include_archived: true,
|
|
@@ -25170,9 +25269,104 @@ function createRemoteMemoryStore(options) {
|
|
|
25170
25269
|
polling = false;
|
|
25171
25270
|
});
|
|
25172
25271
|
};
|
|
25272
|
+
const unrepairable = /* @__PURE__ */ new Set();
|
|
25273
|
+
let repairCursor;
|
|
25274
|
+
const repairEmbeddings = async ({
|
|
25275
|
+
maxRows = REPAIR_ROWS,
|
|
25276
|
+
maxScan = REPAIR_SCAN,
|
|
25277
|
+
cursor: start = repairCursor
|
|
25278
|
+
} = {}) => {
|
|
25279
|
+
const scannedRows = [];
|
|
25280
|
+
let cursor2 = start;
|
|
25281
|
+
do {
|
|
25282
|
+
const page = await metadata2({
|
|
25283
|
+
include_deleted: true,
|
|
25284
|
+
include_archived: true,
|
|
25285
|
+
include_quarantined: true,
|
|
25286
|
+
include_superseded: true,
|
|
25287
|
+
limit: Math.min(200, Math.max(1, maxScan - scannedRows.length)),
|
|
25288
|
+
...cursor2 && { cursor: cursor2 }
|
|
25289
|
+
});
|
|
25290
|
+
scannedRows.push(...page.items);
|
|
25291
|
+
cursor2 = page.next_cursor;
|
|
25292
|
+
} while (cursor2 && scannedRows.length < maxScan);
|
|
25293
|
+
const allStale = scannedRows.filter(
|
|
25294
|
+
({ memory }) => memory.embedding_model !== model && !unrepairable.has(memory.memory_id)
|
|
25295
|
+
);
|
|
25296
|
+
const repaired = /* @__PURE__ */ new Set();
|
|
25297
|
+
const result = {
|
|
25298
|
+
scanned: scannedRows.length,
|
|
25299
|
+
reembedded: 0,
|
|
25300
|
+
failed: 0,
|
|
25301
|
+
skippedConflict: 0
|
|
25302
|
+
};
|
|
25303
|
+
const finish = () => {
|
|
25304
|
+
const settled = allStale.every(
|
|
25305
|
+
({ memory }) => repaired.has(memory.memory_id) || unrepairable.has(memory.memory_id)
|
|
25306
|
+
);
|
|
25307
|
+
repairCursor = settled ? cursor2 : start;
|
|
25308
|
+
return repairCursor ? { ...result, cursor: repairCursor } : result;
|
|
25309
|
+
};
|
|
25310
|
+
const stale = allStale.slice(0, maxRows).map(({ memory }) => memory.memory_id);
|
|
25311
|
+
if (stale.length === 0) return finish();
|
|
25312
|
+
const { records, unreadable } = await readEveryState(stale);
|
|
25313
|
+
result.failed += unreadable.size;
|
|
25314
|
+
for (const id of stale)
|
|
25315
|
+
if (unreadable.has(id) || !records.get(id)?.memory.content.trim()) unrepairable.add(id);
|
|
25316
|
+
const targets = stale.filter((id) => !unrepairable.has(id)).map((id) => records.get(id));
|
|
25317
|
+
if (targets.length === 0) return finish();
|
|
25318
|
+
const vectors = await embedForRepair(targets);
|
|
25319
|
+
if (!vectors) {
|
|
25320
|
+
result.failed += targets.length;
|
|
25321
|
+
return finish();
|
|
25322
|
+
}
|
|
25323
|
+
for (const [i, record2] of targets.entries()) {
|
|
25324
|
+
const vector = vectors[i];
|
|
25325
|
+
if (!vector) {
|
|
25326
|
+
result.failed++;
|
|
25327
|
+
continue;
|
|
25328
|
+
}
|
|
25329
|
+
await serialized(record2.memory.memory_id, async () => {
|
|
25330
|
+
try {
|
|
25331
|
+
const saved = await persistence.put(
|
|
25332
|
+
{ ...record2.memory, embedding: storedVector(vector), embedding_model: model },
|
|
25333
|
+
record2
|
|
25334
|
+
);
|
|
25335
|
+
notify("embedding", [saved]);
|
|
25336
|
+
repaired.add(record2.memory.memory_id);
|
|
25337
|
+
result.reembedded++;
|
|
25338
|
+
} catch (error) {
|
|
25339
|
+
if (error instanceof RemoteMemoryError && error.code === "version_conflict")
|
|
25340
|
+
result.skippedConflict++;
|
|
25341
|
+
else result.failed++;
|
|
25342
|
+
}
|
|
25343
|
+
});
|
|
25344
|
+
}
|
|
25345
|
+
return finish();
|
|
25346
|
+
};
|
|
25347
|
+
const embedForRepair = async (targets) => {
|
|
25348
|
+
const texts = targets.map(({ memory }) => memory.content);
|
|
25349
|
+
try {
|
|
25350
|
+
return await generateEmbeddings(texts, embeddingOptions);
|
|
25351
|
+
} catch (error) {
|
|
25352
|
+
getLogger().warn("[memory/remote-store] Failed to embed memories for repair:", error);
|
|
25353
|
+
if (!rejectsInput(error)) return null;
|
|
25354
|
+
}
|
|
25355
|
+
const vectors = [];
|
|
25356
|
+
for (const [i, text14] of texts.entries()) {
|
|
25357
|
+
try {
|
|
25358
|
+
[vectors[i]] = await generateEmbeddings([text14], embeddingOptions);
|
|
25359
|
+
} catch (error) {
|
|
25360
|
+
if (!rejectsInput(error)) return null;
|
|
25361
|
+
unrepairable.add(targets[i].memory.memory_id);
|
|
25362
|
+
}
|
|
25363
|
+
}
|
|
25364
|
+
return vectors;
|
|
25365
|
+
};
|
|
25173
25366
|
return {
|
|
25174
25367
|
masksEmbeddingInput: embeddingOptions.maskInput !== void 0,
|
|
25175
25368
|
topicMaintenance,
|
|
25369
|
+
repairEmbeddings,
|
|
25176
25370
|
list: async (listOptions = {}) => (await listRows(decrypted, listOptions, listFilters(listOptions), maxOf(listOptions))).map(
|
|
25177
25371
|
(r) => stored(r.memory)
|
|
25178
25372
|
),
|
|
@@ -25372,6 +25566,12 @@ function createRemoteMemoryStore(options) {
|
|
|
25372
25566
|
else if (result.action === "update" || result.action === "merge") notify("edit");
|
|
25373
25567
|
return result;
|
|
25374
25568
|
},
|
|
25569
|
+
decay: {
|
|
25570
|
+
createDecaySweeper: (sweeperOptions) => createDecaySweeperOver(decayBackend, {
|
|
25571
|
+
...ruleBasedDecayOptions(sweeperOptions),
|
|
25572
|
+
maxTransitionsPerSweep: DECAY_TRANSITIONS_PER_SWEEP
|
|
25573
|
+
})
|
|
25574
|
+
},
|
|
25375
25575
|
subscribe: (onChange, subscribeOptions = {}) => {
|
|
25376
25576
|
const subscriber = { onChange, options: subscribeOptions };
|
|
25377
25577
|
subscribers.add(subscriber);
|