@anuma/sdk 9.1.0 → 9.1.2
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 +349 -97
- package/dist/expo/index.d.mts +10 -15
- package/dist/expo/index.d.ts +10 -15
- package/dist/expo/index.mjs +348 -96
- package/dist/index.cjs +37 -3
- package/dist/index.mjs +37 -3
- package/dist/react/index.cjs +349 -97
- package/dist/react/index.d.mts +10 -15
- package/dist/react/index.d.ts +10 -15
- package/dist/react/index.mjs +349 -97
- package/dist/server/index.cjs +40 -11
- package/dist/server/index.d.mts +1 -14
- package/dist/server/index.d.ts +1 -14
- package/dist/server/index.mjs +40 -11
- package/package.json +1 -1
package/dist/react/index.mjs
CHANGED
|
@@ -10287,11 +10287,12 @@ function isRemoteWorkLeaseExpired(error) {
|
|
|
10287
10287
|
|
|
10288
10288
|
// src/lib/memory/store/remotePersistence.ts
|
|
10289
10289
|
var RemoteMemoryError = class extends Error {
|
|
10290
|
-
constructor(message, status, code, retryAfterMs) {
|
|
10290
|
+
constructor(message, status, code, retryAfterMs, rateLimitBucket) {
|
|
10291
10291
|
super(message);
|
|
10292
10292
|
this.status = status;
|
|
10293
10293
|
this.code = code;
|
|
10294
10294
|
this.retryAfterMs = retryAfterMs;
|
|
10295
|
+
this.rateLimitBucket = rateLimitBucket;
|
|
10295
10296
|
this.name = "RemoteMemoryError";
|
|
10296
10297
|
}
|
|
10297
10298
|
};
|
|
@@ -10386,6 +10387,14 @@ function createNearbyRequest(options, apiPath = "/api/private-memories") {
|
|
|
10386
10387
|
throw new Error("timeoutMs must be a positive number");
|
|
10387
10388
|
const root = base.href.replace(/\/$/, "") + apiPath;
|
|
10388
10389
|
const fetcher = options.fetch ?? globalThis.fetch;
|
|
10390
|
+
const cooldowns = /* @__PURE__ */ new Map();
|
|
10391
|
+
const memoryBudget = (path, method) => {
|
|
10392
|
+
if (method === "PUT")
|
|
10393
|
+
return path === "/topics" ? "private-memory-import" : "private-memory-write";
|
|
10394
|
+
if (method === "POST" && ["/import", "/memories/batch", "/topics/import"].includes(path))
|
|
10395
|
+
return "private-memory-import";
|
|
10396
|
+
return "private-memory-read";
|
|
10397
|
+
};
|
|
10389
10398
|
const request = async (path, init = {}, signal) => {
|
|
10390
10399
|
const controller = new AbortController();
|
|
10391
10400
|
let timedOut = false;
|
|
@@ -10409,6 +10418,25 @@ function createNearbyRequest(options, apiPath = "/api/private-memories") {
|
|
|
10409
10418
|
const token = await Promise.race([options.getToken(), aborted2]);
|
|
10410
10419
|
if (controller.signal.aborted) await aborted2;
|
|
10411
10420
|
if (!token) throw new RemoteMemoryError("Authentication required", 401);
|
|
10421
|
+
const pathname = path.split("?")[0];
|
|
10422
|
+
const route = `${init.method ?? "GET"} ${pathname}`;
|
|
10423
|
+
const budgets = ["*", route];
|
|
10424
|
+
if (apiPath === "/api/private-memories")
|
|
10425
|
+
budgets.push("private-memory-ip", memoryBudget(pathname, init.method ?? "GET"));
|
|
10426
|
+
for (const bucket of budgets) {
|
|
10427
|
+
const cooldown = cooldowns.get(bucket);
|
|
10428
|
+
if (!cooldown) continue;
|
|
10429
|
+
const remaining = cooldown.until - Date.now();
|
|
10430
|
+
if (remaining > 0)
|
|
10431
|
+
throw new RemoteMemoryError(
|
|
10432
|
+
cooldown.error.message,
|
|
10433
|
+
429,
|
|
10434
|
+
cooldown.error.code,
|
|
10435
|
+
remaining,
|
|
10436
|
+
cooldown.error.rateLimitBucket
|
|
10437
|
+
);
|
|
10438
|
+
cooldowns.delete(bucket);
|
|
10439
|
+
}
|
|
10412
10440
|
const response = await fetcher(root + path, {
|
|
10413
10441
|
...init,
|
|
10414
10442
|
headers: {
|
|
@@ -10421,12 +10449,18 @@ function createNearbyRequest(options, apiPath = "/api/private-memories") {
|
|
|
10421
10449
|
if (!response.ok) {
|
|
10422
10450
|
const body = await response.json().catch(() => null);
|
|
10423
10451
|
const retryAfter = parseRetryAfterMs(response.headers.get("Retry-After"));
|
|
10424
|
-
|
|
10452
|
+
const error = new RemoteMemoryError(
|
|
10425
10453
|
record(body) && typeof body.detail === "string" ? body.detail : `Nearby request failed (${response.status})`,
|
|
10426
10454
|
response.status,
|
|
10427
10455
|
record(body) && typeof body.code === "string" ? body.code : void 0,
|
|
10428
|
-
retryAfter ?? void 0
|
|
10456
|
+
retryAfter ?? void 0,
|
|
10457
|
+
record(body) && typeof body.rate_limit_bucket === "string" ? body.rate_limit_bucket : void 0
|
|
10429
10458
|
);
|
|
10459
|
+
if (response.status === 429 && retryAfter !== null && retryAfter > 0 && (!error.code || error.code === "rate_limited")) {
|
|
10460
|
+
const bucket = error.rateLimitBucket && budgets.includes(error.rateLimitBucket) ? error.rateLimitBucket : record(body) && (body.limit_scope === "account" || body.limit_scope === "ip") && !error.rateLimitBucket ? "*" : route;
|
|
10461
|
+
cooldowns.set(bucket, { until: Date.now() + retryAfter, error });
|
|
10462
|
+
}
|
|
10463
|
+
throw error;
|
|
10430
10464
|
}
|
|
10431
10465
|
return await response.json();
|
|
10432
10466
|
} catch (error) {
|
|
@@ -10666,6 +10700,7 @@ async function createRemoteMemoryPersistence(options) {
|
|
|
10666
10700
|
return {
|
|
10667
10701
|
...createRemoteTopicPersistence(request),
|
|
10668
10702
|
...createRemoteWorkPersistence(request),
|
|
10703
|
+
supportsRealtimeChanges: account.realtime_changes === true,
|
|
10669
10704
|
counts: async () => {
|
|
10670
10705
|
const result = await request("/counts", {});
|
|
10671
10706
|
if (!record(result) || ["live", "archived", "quarantined"].some(
|
|
@@ -14768,9 +14803,10 @@ async function getVaultRankingProjectionsOp(ctx, options) {
|
|
|
14768
14803
|
}
|
|
14769
14804
|
function baseVaultSql(ctx, options) {
|
|
14770
14805
|
const clauses = [
|
|
14806
|
+
`"_status" is not 'deleted'`,
|
|
14771
14807
|
'"is_deleted" = 0',
|
|
14772
14808
|
...options?.includeArchived ? [] : ['"archived_at" is null'],
|
|
14773
|
-
`"trust_tier" is not 'quarantined'
|
|
14809
|
+
...options?.includeQuarantined ? [] : [`"trust_tier" is not 'quarantined'`],
|
|
14774
14810
|
'"superseded_by" is null'
|
|
14775
14811
|
];
|
|
14776
14812
|
const args = [];
|
|
@@ -15256,8 +15292,17 @@ async function getMemoriesNeedingTopicExtractionOp(ctx, options) {
|
|
|
15256
15292
|
if (!entityCtx) {
|
|
15257
15293
|
throw new Error("getMemoriesNeedingTopicExtractionOp requires ctx.entityCtx");
|
|
15258
15294
|
}
|
|
15259
|
-
|
|
15260
|
-
|
|
15295
|
+
let rows;
|
|
15296
|
+
try {
|
|
15297
|
+
const base = baseVaultSql(ctx);
|
|
15298
|
+
const sql = `select "id", "topics", "topics_user_managed", "topics_extracted_at", "topics_extracted_version", "updated_at" from "memory_vault" where ${base.sql} order by "created_at" desc`;
|
|
15299
|
+
rows = await ctx.vaultMemoryCollection.query(Q9.unsafeSqlQuery(sql, base.args)).unsafeFetchRaw();
|
|
15300
|
+
} catch (err) {
|
|
15301
|
+
getLogger().debug(
|
|
15302
|
+
"memoryVault: topic sweep SQL unavailable; use the adapter query: " + (err instanceof Error ? err.message : String(err))
|
|
15303
|
+
);
|
|
15304
|
+
rows = await ctx.vaultMemoryCollection.query(...baseVaultConditions(ctx), Q9.sortBy("created_at", Q9.desc)).unsafeFetchRaw();
|
|
15305
|
+
}
|
|
15261
15306
|
const linkedNames = await linkedEntityNamesByMemory(
|
|
15262
15307
|
entityCtx,
|
|
15263
15308
|
rows.map((r) => r.id)
|
|
@@ -15316,10 +15361,19 @@ async function getMemoriesNeedingTopicExtractionOp(ctx, options) {
|
|
|
15316
15361
|
}
|
|
15317
15362
|
const orderedPendingRaw = [...stampedPendingRaw, ...pendingRaw];
|
|
15318
15363
|
const limitedPendingRaw = cap !== void 0 ? orderedPendingRaw.slice(0, cap) : orderedPendingRaw;
|
|
15319
|
-
const pending =
|
|
15320
|
-
|
|
15321
|
-
|
|
15322
|
-
|
|
15364
|
+
const pending = [];
|
|
15365
|
+
for (let i = 0; i < limitedPendingRaw.length; i += 500) {
|
|
15366
|
+
const chunk = limitedPendingRaw.slice(i, i + 500);
|
|
15367
|
+
const memories = await getVaultMemoriesByIdsOp(
|
|
15368
|
+
ctx,
|
|
15369
|
+
chunk.map((raw) => raw.id)
|
|
15370
|
+
);
|
|
15371
|
+
const byId = new Map(memories.map((memory) => [memory.uniqueId, memory]));
|
|
15372
|
+
for (const raw of chunk) {
|
|
15373
|
+
const memory = byId.get(raw.id);
|
|
15374
|
+
if (memory) pending.push(memory);
|
|
15375
|
+
}
|
|
15376
|
+
}
|
|
15323
15377
|
const applyCap = (ids) => cap !== void 0 ? ids.slice(0, cap) : ids;
|
|
15324
15378
|
return {
|
|
15325
15379
|
pending,
|
|
@@ -15466,10 +15520,20 @@ function assertVaultScopeForSweep(ctx) {
|
|
|
15466
15520
|
}
|
|
15467
15521
|
async function getDecayCandidatesRawOp(ctx) {
|
|
15468
15522
|
assertVaultScopeForSweep(ctx);
|
|
15469
|
-
|
|
15470
|
-
|
|
15471
|
-
|
|
15472
|
-
|
|
15523
|
+
let results;
|
|
15524
|
+
try {
|
|
15525
|
+
const base = baseVaultSql(ctx, { includeArchived: true, includeQuarantined: true });
|
|
15526
|
+
const sql = `select "id", "fact_type", "event_time_end", "event_time_kind", "updated_at", "last_observed_at", "archived_at", "source", "trust_tier" from "memory_vault" where ${base.sql} and "kind" is null`;
|
|
15527
|
+
results = await ctx.vaultMemoryCollection.query(Q9.unsafeSqlQuery(sql, base.args)).unsafeFetchRaw();
|
|
15528
|
+
} catch (err) {
|
|
15529
|
+
getLogger().debug(
|
|
15530
|
+
"memoryVault: decay sweep SQL unavailable; use the adapter query: " + (err instanceof Error ? err.message : String(err))
|
|
15531
|
+
);
|
|
15532
|
+
results = await ctx.vaultMemoryCollection.query(
|
|
15533
|
+
...baseVaultConditions(ctx, { includeArchived: true, includeQuarantined: true }),
|
|
15534
|
+
Q9.where("kind", null)
|
|
15535
|
+
).unsafeFetchRaw();
|
|
15536
|
+
}
|
|
15473
15537
|
return results.map((raw) => ({
|
|
15474
15538
|
uniqueId: raw.id,
|
|
15475
15539
|
factType: raw.fact_type ?? null,
|
|
@@ -23450,6 +23514,9 @@ var RemoteMemoryPartialCreateError = class extends Error {
|
|
|
23450
23514
|
function rejectsInput(error) {
|
|
23451
23515
|
return error instanceof EmbeddingHttpError && error.status !== void 0 && error.status >= 400 && error.status < 500 && error.status !== 429 && !isFatalEmbeddingError(error);
|
|
23452
23516
|
}
|
|
23517
|
+
function rejectsMemoryWrite(error) {
|
|
23518
|
+
return error instanceof RemoteMemoryError && (error.status === 400 || error.status === 422) && (error.code === void 0 || error.code === "unknown_field");
|
|
23519
|
+
}
|
|
23453
23520
|
function warnFailed(failed) {
|
|
23454
23521
|
if (failed.length)
|
|
23455
23522
|
getLogger().warn(
|
|
@@ -23537,16 +23604,47 @@ function createRemoteMemoryStore(options) {
|
|
|
23537
23604
|
const { persistence, embeddingOptions } = options;
|
|
23538
23605
|
const model = embeddingOptions.model ?? DEFAULT_API_EMBEDDING_MODEL;
|
|
23539
23606
|
const pollIntervalMs = options.pollIntervalMs ?? 6e4;
|
|
23607
|
+
const activity = options.activity ?? {
|
|
23608
|
+
isActive: () => (typeof document === "undefined" || document.visibilityState !== "hidden") && (typeof navigator === "undefined" || navigator.onLine !== false),
|
|
23609
|
+
subscribe: (onChange) => {
|
|
23610
|
+
if (typeof window === "undefined" || typeof document === "undefined") return () => {
|
|
23611
|
+
};
|
|
23612
|
+
document.addEventListener("visibilitychange", onChange);
|
|
23613
|
+
window.addEventListener("online", onChange);
|
|
23614
|
+
window.addEventListener("offline", onChange);
|
|
23615
|
+
return () => {
|
|
23616
|
+
document.removeEventListener("visibilitychange", onChange);
|
|
23617
|
+
window.removeEventListener("online", onChange);
|
|
23618
|
+
window.removeEventListener("offline", onChange);
|
|
23619
|
+
};
|
|
23620
|
+
}
|
|
23621
|
+
};
|
|
23540
23622
|
const pipeline = createRemoteMemoryPipeline({
|
|
23541
23623
|
...options,
|
|
23542
23624
|
graphRanking: options.graphRanking ?? ((query, _traverse, recallOptions) => topicGraphRanking(query, recallOptions)),
|
|
23543
23625
|
temporalRanking: options.temporalRanking ?? ((query, now) => eventTimeRanking(query, now))
|
|
23544
23626
|
});
|
|
23545
23627
|
const subscribers = /* @__PURE__ */ new Set();
|
|
23628
|
+
const retainTopics = () => pollIntervalMs > 0 && [...subscribers].some((subscriber) => subscriber.options.topics);
|
|
23546
23629
|
const seen = /* @__PURE__ */ new Map();
|
|
23630
|
+
const reads = /* @__PURE__ */ new Map();
|
|
23631
|
+
const metadataReads = /* @__PURE__ */ new Map();
|
|
23632
|
+
let topicSnapshot;
|
|
23633
|
+
let topicCatalog;
|
|
23634
|
+
const invalidateReads = () => {
|
|
23635
|
+
reads.clear();
|
|
23636
|
+
metadataReads.clear();
|
|
23637
|
+
topicSnapshot = void 0;
|
|
23638
|
+
topicCatalog = void 0;
|
|
23639
|
+
};
|
|
23547
23640
|
let timer;
|
|
23641
|
+
let scheduledAt;
|
|
23642
|
+
let stopActivity;
|
|
23643
|
+
let stopChanges;
|
|
23644
|
+
let changesConnected = false;
|
|
23548
23645
|
const notify = (change, records = []) => {
|
|
23549
|
-
|
|
23646
|
+
invalidateReads();
|
|
23647
|
+
if (subscribers.size)
|
|
23550
23648
|
for (const record2 of records) {
|
|
23551
23649
|
const previous = seen.get(record2.memory.memory_id);
|
|
23552
23650
|
if ((previous?.version ?? 0) + 1 === record2.version)
|
|
@@ -23570,8 +23668,37 @@ function createRemoteMemoryStore(options) {
|
|
|
23570
23668
|
} while (cursor2 && records.length < max);
|
|
23571
23669
|
return records.slice(0, max);
|
|
23572
23670
|
};
|
|
23573
|
-
const
|
|
23574
|
-
|
|
23671
|
+
const shareRead = (inflight, options2, read) => {
|
|
23672
|
+
if (options2.signal) return read();
|
|
23673
|
+
const key = JSON.stringify(Object.entries(options2).sort(([a], [b]) => a.localeCompare(b)));
|
|
23674
|
+
const active = inflight.get(key);
|
|
23675
|
+
if (active) return active;
|
|
23676
|
+
const pending2 = read();
|
|
23677
|
+
inflight.set(key, pending2);
|
|
23678
|
+
const clear = () => {
|
|
23679
|
+
if (inflight.get(key) === pending2) inflight.delete(key);
|
|
23680
|
+
};
|
|
23681
|
+
void pending2.then(clear, clear);
|
|
23682
|
+
return pending2;
|
|
23683
|
+
};
|
|
23684
|
+
const decrypted = (options2) => shareRead(reads, options2, () => persistence.query(options2));
|
|
23685
|
+
const metadata3 = (options2) => shareRead(
|
|
23686
|
+
metadataReads,
|
|
23687
|
+
options2,
|
|
23688
|
+
() => persistence.queryMetadata(options2)
|
|
23689
|
+
);
|
|
23690
|
+
const readTopics = () => {
|
|
23691
|
+
if (topicCatalog) return topicCatalog;
|
|
23692
|
+
const pending2 = persistence.topics();
|
|
23693
|
+
topicCatalog = pending2;
|
|
23694
|
+
const clear = () => {
|
|
23695
|
+
if (topicCatalog === pending2) topicCatalog = void 0;
|
|
23696
|
+
};
|
|
23697
|
+
void pending2.then(() => {
|
|
23698
|
+
if (!retainTopics()) clear();
|
|
23699
|
+
}, clear);
|
|
23700
|
+
return pending2;
|
|
23701
|
+
};
|
|
23575
23702
|
const enumerate = (filters, max = Infinity) => pages(decrypted, filters, max);
|
|
23576
23703
|
const memoriesByTopics = async (names) => {
|
|
23577
23704
|
const wanted = new Set(names.map(normalizeEntityName).filter(Boolean));
|
|
@@ -24025,11 +24152,11 @@ function createRemoteMemoryStore(options) {
|
|
|
24025
24152
|
};
|
|
24026
24153
|
const changesSince = async (cursor2, pending2) => {
|
|
24027
24154
|
const records = [];
|
|
24028
|
-
const failed = /* @__PURE__ */ new
|
|
24155
|
+
const failed = /* @__PURE__ */ new Map();
|
|
24029
24156
|
const collect = (page) => {
|
|
24030
24157
|
warnFailed(page.failed);
|
|
24031
24158
|
records.push(...page.items);
|
|
24032
|
-
for (const failure of page.failed) failed.
|
|
24159
|
+
for (const failure of page.failed) failed.set(failure.memory_id, failure.version);
|
|
24033
24160
|
};
|
|
24034
24161
|
let resume = cursor2;
|
|
24035
24162
|
let next;
|
|
@@ -24063,25 +24190,72 @@ function createRemoteMemoryStore(options) {
|
|
|
24063
24190
|
let ready = false;
|
|
24064
24191
|
let cursor;
|
|
24065
24192
|
let pending = /* @__PURE__ */ new Set();
|
|
24193
|
+
let failedVersions = /* @__PURE__ */ new Map();
|
|
24066
24194
|
let topicFingerprint;
|
|
24067
24195
|
let polling = false;
|
|
24196
|
+
let pollRequested = false;
|
|
24197
|
+
let failures = 0;
|
|
24198
|
+
let retryAt = 0;
|
|
24199
|
+
const backoff = (error) => {
|
|
24200
|
+
failures++;
|
|
24201
|
+
retryAt = Date.now() + Math.max(
|
|
24202
|
+
error instanceof RemoteMemoryError ? error.retryAfterMs ?? 0 : 0,
|
|
24203
|
+
Math.min(pollIntervalMs * 2 ** Math.min(failures - 1, 10), 15 * 6e4)
|
|
24204
|
+
);
|
|
24205
|
+
};
|
|
24206
|
+
const schedulePoll = (delay, keepEarlier = false) => {
|
|
24207
|
+
const at = Math.max(Date.now() + delay, retryAt);
|
|
24208
|
+
if (keepEarlier && timer && scheduledAt !== void 0 && scheduledAt <= at) return;
|
|
24209
|
+
if (timer) clearTimeout(timer);
|
|
24210
|
+
timer = void 0;
|
|
24211
|
+
scheduledAt = void 0;
|
|
24212
|
+
if (!subscribers.size || pollIntervalMs <= 0 || !activity.isActive()) return;
|
|
24213
|
+
scheduledAt = at;
|
|
24214
|
+
timer = setTimeout(poll, Math.max(0, at - Date.now()));
|
|
24215
|
+
};
|
|
24068
24216
|
const poll = () => {
|
|
24069
|
-
if (
|
|
24217
|
+
if (timer) clearTimeout(timer);
|
|
24218
|
+
timer = void 0;
|
|
24219
|
+
scheduledAt = void 0;
|
|
24220
|
+
if (!subscribers.size || pollIntervalMs <= 0 || !activity.isActive()) return;
|
|
24221
|
+
if (Date.now() < retryAt) {
|
|
24222
|
+
schedulePoll(0);
|
|
24223
|
+
return;
|
|
24224
|
+
}
|
|
24225
|
+
if (polling) {
|
|
24226
|
+
pollRequested = true;
|
|
24227
|
+
return;
|
|
24228
|
+
}
|
|
24070
24229
|
polling = true;
|
|
24230
|
+
pollRequested = false;
|
|
24071
24231
|
const current = generation;
|
|
24072
24232
|
changesSince(cursor, pending).then(async ({ records, resume, failed }) => {
|
|
24073
24233
|
let topicState;
|
|
24234
|
+
let topicFailed = false;
|
|
24074
24235
|
if ([...subscribers].some((s) => s.options.topics))
|
|
24075
24236
|
try {
|
|
24076
|
-
|
|
24077
|
-
|
|
24078
|
-
);
|
|
24237
|
+
topicCatalog = void 0;
|
|
24238
|
+
topicState = JSON.stringify((await readTopics()).map((t) => [t.name, t.version]));
|
|
24079
24239
|
} catch (error) {
|
|
24240
|
+
topicFailed = true;
|
|
24241
|
+
if (current === generation) backoff(error);
|
|
24080
24242
|
getLogger().warn("[memory/remote-store] Topic subscription poll failed:", error);
|
|
24081
24243
|
}
|
|
24082
24244
|
if (current !== generation) return;
|
|
24245
|
+
if (!topicFailed) {
|
|
24246
|
+
failures = 0;
|
|
24247
|
+
retryAt = 0;
|
|
24248
|
+
}
|
|
24249
|
+
const failedChanged = [...failed].some(
|
|
24250
|
+
([id2, version]) => failedVersions.get(id2) !== version
|
|
24251
|
+
);
|
|
24252
|
+
if (records.length || failedChanged || topicState !== void 0 && topicState !== topicFingerprint) {
|
|
24253
|
+
reads.clear();
|
|
24254
|
+
metadataReads.clear();
|
|
24255
|
+
topicSnapshot = void 0;
|
|
24256
|
+
}
|
|
24083
24257
|
const changed = /* @__PURE__ */ new Set();
|
|
24084
|
-
if (topicState !== void 0 && topicFingerprint !== void 0 && topicState !== topicFingerprint) {
|
|
24258
|
+
if (ready && failedChanged || topicState !== void 0 && topicFingerprint !== void 0 && topicState !== topicFingerprint) {
|
|
24085
24259
|
for (const subscriber of subscribers)
|
|
24086
24260
|
if (subscriber.options.topics) changed.add(subscriber);
|
|
24087
24261
|
}
|
|
@@ -24098,15 +24272,40 @@ function createRemoteMemoryStore(options) {
|
|
|
24098
24272
|
}
|
|
24099
24273
|
ready = true;
|
|
24100
24274
|
cursor = resume;
|
|
24101
|
-
pending = failed;
|
|
24275
|
+
pending = new Set(failed.keys());
|
|
24276
|
+
failedVersions = failed;
|
|
24102
24277
|
for (const subscriber of changed)
|
|
24103
24278
|
if (subscribers.has(subscriber)) safely(subscriber.onChange);
|
|
24104
24279
|
}).catch((error) => {
|
|
24280
|
+
if (current === generation) backoff(error);
|
|
24105
24281
|
getLogger().warn("[memory/remote-store] Subscription poll failed:", error);
|
|
24106
24282
|
}).finally(() => {
|
|
24107
24283
|
polling = false;
|
|
24284
|
+
schedulePoll(
|
|
24285
|
+
current !== generation ? 0 : pollRequested ? 200 : changesConnected ? Math.max(pollIntervalMs, 5 * 6e4) : pollIntervalMs
|
|
24286
|
+
);
|
|
24108
24287
|
});
|
|
24109
24288
|
};
|
|
24289
|
+
const refreshActivity = () => {
|
|
24290
|
+
if (timer) clearTimeout(timer);
|
|
24291
|
+
timer = void 0;
|
|
24292
|
+
if (!activity.isActive()) {
|
|
24293
|
+
stopChanges?.();
|
|
24294
|
+
stopChanges = void 0;
|
|
24295
|
+
changesConnected = false;
|
|
24296
|
+
return;
|
|
24297
|
+
}
|
|
24298
|
+
if (!stopChanges && persistence.supportsRealtimeChanges && options.subscribeChanges)
|
|
24299
|
+
stopChanges = options.subscribeChanges((connected) => {
|
|
24300
|
+
changesConnected = connected;
|
|
24301
|
+
if (polling) {
|
|
24302
|
+
pollRequested = true;
|
|
24303
|
+
return;
|
|
24304
|
+
}
|
|
24305
|
+
schedulePoll(connected ? 200 : 0, true);
|
|
24306
|
+
});
|
|
24307
|
+
poll();
|
|
24308
|
+
};
|
|
24110
24309
|
const unrepairable = /* @__PURE__ */ new Set();
|
|
24111
24310
|
let repairCursor;
|
|
24112
24311
|
const repairEmbeddingsUnlocked = async ({
|
|
@@ -24162,40 +24361,78 @@ function createRemoteMemoryStore(options) {
|
|
|
24162
24361
|
result.failed += targets.length;
|
|
24163
24362
|
return finish();
|
|
24164
24363
|
}
|
|
24165
|
-
|
|
24364
|
+
const writes = targets.flatMap((record2, i) => {
|
|
24166
24365
|
const vector = vectors[i];
|
|
24167
24366
|
if (!vector) {
|
|
24168
24367
|
result.failed++;
|
|
24169
|
-
|
|
24368
|
+
return [];
|
|
24170
24369
|
}
|
|
24171
|
-
|
|
24172
|
-
|
|
24173
|
-
|
|
24174
|
-
|
|
24175
|
-
|
|
24176
|
-
|
|
24177
|
-
|
|
24178
|
-
|
|
24179
|
-
|
|
24180
|
-
|
|
24181
|
-
|
|
24182
|
-
|
|
24183
|
-
|
|
24184
|
-
|
|
24185
|
-
|
|
24186
|
-
|
|
24187
|
-
|
|
24188
|
-
|
|
24189
|
-
|
|
24190
|
-
|
|
24191
|
-
} catch (error) {
|
|
24370
|
+
try {
|
|
24371
|
+
return [
|
|
24372
|
+
{
|
|
24373
|
+
memory: {
|
|
24374
|
+
...record2.memory,
|
|
24375
|
+
embedding: storedVector(vector),
|
|
24376
|
+
embedding_model: model
|
|
24377
|
+
},
|
|
24378
|
+
expectedVersion: record2
|
|
24379
|
+
}
|
|
24380
|
+
];
|
|
24381
|
+
} catch {
|
|
24382
|
+
result.failed++;
|
|
24383
|
+
return [];
|
|
24384
|
+
}
|
|
24385
|
+
});
|
|
24386
|
+
for (const batch of chunks2(writes, MAX_BATCH)) {
|
|
24387
|
+
const continueRepair = await serializedAll(
|
|
24388
|
+
batch.map(({ memory }) => memory.memory_id),
|
|
24389
|
+
async () => {
|
|
24192
24390
|
signal?.throwIfAborted();
|
|
24193
|
-
|
|
24194
|
-
|
|
24195
|
-
|
|
24196
|
-
|
|
24391
|
+
const commit = async (slice) => {
|
|
24392
|
+
const saved = await persistence.putMany(slice, signal, leaseToken);
|
|
24393
|
+
for (const record2 of saved) repaired.add(record2.memory.memory_id);
|
|
24394
|
+
result.reembedded += saved.length;
|
|
24395
|
+
notify("embedding", saved);
|
|
24396
|
+
};
|
|
24397
|
+
try {
|
|
24398
|
+
await commit(batch);
|
|
24399
|
+
} catch (error) {
|
|
24400
|
+
signal?.throwIfAborted();
|
|
24401
|
+
if (isRemoteWorkLeaseExpired(error)) throw error;
|
|
24402
|
+
if (!(error instanceof RemoteMemoryError && error.code === "version_conflict") && !rejectsMemoryWrite(error)) {
|
|
24403
|
+
result.failed += batch.length;
|
|
24404
|
+
return false;
|
|
24405
|
+
}
|
|
24406
|
+
if (batch.length === 1) {
|
|
24407
|
+
if (rejectsMemoryWrite(error)) {
|
|
24408
|
+
unrepairable.add(batch[0].memory.memory_id);
|
|
24409
|
+
result.failed++;
|
|
24410
|
+
} else result.skippedConflict++;
|
|
24411
|
+
return true;
|
|
24412
|
+
}
|
|
24413
|
+
for (const [index, write] of batch.entries()) {
|
|
24414
|
+
signal?.throwIfAborted();
|
|
24415
|
+
try {
|
|
24416
|
+
await commit([write]);
|
|
24417
|
+
} catch (error2) {
|
|
24418
|
+
signal?.throwIfAborted();
|
|
24419
|
+
if (isRemoteWorkLeaseExpired(error2)) throw error2;
|
|
24420
|
+
if (error2 instanceof RemoteMemoryError && error2.code === "version_conflict")
|
|
24421
|
+
result.skippedConflict++;
|
|
24422
|
+
else if (rejectsMemoryWrite(error2)) {
|
|
24423
|
+
unrepairable.add(write.memory.memory_id);
|
|
24424
|
+
result.failed++;
|
|
24425
|
+
} else {
|
|
24426
|
+
result.failed += batch.length - index;
|
|
24427
|
+
return false;
|
|
24428
|
+
}
|
|
24429
|
+
}
|
|
24430
|
+
}
|
|
24431
|
+
}
|
|
24432
|
+
return true;
|
|
24197
24433
|
}
|
|
24198
|
-
|
|
24434
|
+
);
|
|
24435
|
+
if (!continueRepair) break;
|
|
24199
24436
|
}
|
|
24200
24437
|
return finish();
|
|
24201
24438
|
};
|
|
@@ -24235,7 +24472,7 @@ function createRemoteMemoryStore(options) {
|
|
|
24235
24472
|
},
|
|
24236
24473
|
importTopics: async (topics) => {
|
|
24237
24474
|
if (!topics.length) return;
|
|
24238
|
-
const existing = new Set((await
|
|
24475
|
+
const existing = new Set((await readTopics()).map((topic2) => topic2.name));
|
|
24239
24476
|
const missing = topics.flatMap((topic2) => {
|
|
24240
24477
|
const name = normalizeEntityName(topic2.name);
|
|
24241
24478
|
if (existing.has(name)) return [];
|
|
@@ -24244,6 +24481,7 @@ function createRemoteMemoryStore(options) {
|
|
|
24244
24481
|
});
|
|
24245
24482
|
if (!missing.length) return;
|
|
24246
24483
|
await persistence.importTopics(missing);
|
|
24484
|
+
invalidateReads();
|
|
24247
24485
|
for (const subscriber of [...subscribers])
|
|
24248
24486
|
if (subscriber.options.topics) safely(subscriber.onChange);
|
|
24249
24487
|
},
|
|
@@ -24257,40 +24495,51 @@ function createRemoteMemoryStore(options) {
|
|
|
24257
24495
|
listProjections: async (listOptions = {}) => (await listRows(metadata3, listOptions, listFilters(listOptions), maxOf(listOptions))).map(
|
|
24258
24496
|
projection
|
|
24259
24497
|
),
|
|
24260
|
-
listTopics:
|
|
24261
|
-
|
|
24262
|
-
|
|
24263
|
-
|
|
24264
|
-
|
|
24265
|
-
|
|
24266
|
-
|
|
24267
|
-
|
|
24268
|
-
|
|
24269
|
-
|
|
24270
|
-
|
|
24271
|
-
name
|
|
24272
|
-
|
|
24273
|
-
|
|
24274
|
-
|
|
24275
|
-
|
|
24276
|
-
|
|
24277
|
-
|
|
24278
|
-
|
|
24279
|
-
|
|
24280
|
-
|
|
24281
|
-
|
|
24282
|
-
|
|
24283
|
-
const
|
|
24284
|
-
|
|
24285
|
-
|
|
24286
|
-
|
|
24287
|
-
|
|
24288
|
-
|
|
24289
|
-
|
|
24290
|
-
|
|
24291
|
-
|
|
24292
|
-
|
|
24293
|
-
|
|
24498
|
+
listTopics: () => {
|
|
24499
|
+
if (topicSnapshot) return topicSnapshot.then((topics) => structuredClone(topics));
|
|
24500
|
+
const snapshot = (async () => {
|
|
24501
|
+
const topics = /* @__PURE__ */ new Map();
|
|
24502
|
+
for (const { memory } of await pages(metadata3, {
|
|
24503
|
+
include_archived: true,
|
|
24504
|
+
include_quarantined: true,
|
|
24505
|
+
include_superseded: true
|
|
24506
|
+
})) {
|
|
24507
|
+
for (const topic2 of parseTopics(memory.topics) ?? []) {
|
|
24508
|
+
const name = normalizeEntityName(topic2.name);
|
|
24509
|
+
if (!name) continue;
|
|
24510
|
+
const entry = topics.get(name) ?? {
|
|
24511
|
+
name,
|
|
24512
|
+
kind: null,
|
|
24513
|
+
memoryCount: 0,
|
|
24514
|
+
members: /* @__PURE__ */ new Set()
|
|
24515
|
+
};
|
|
24516
|
+
entry.kind ?? (entry.kind = topic2.kind ?? null);
|
|
24517
|
+
entry.members.add(memory.memory_id);
|
|
24518
|
+
topics.set(name, entry);
|
|
24519
|
+
}
|
|
24520
|
+
}
|
|
24521
|
+
for (const topic2 of await readTopics()) {
|
|
24522
|
+
if (topic2.is_deleted) continue;
|
|
24523
|
+
const current = topics.get(topic2.name);
|
|
24524
|
+
if (current) current.kind ?? (current.kind = topic2.kind ?? null);
|
|
24525
|
+
else
|
|
24526
|
+
topics.set(topic2.name, {
|
|
24527
|
+
name: topic2.name,
|
|
24528
|
+
kind: topic2.kind ?? null,
|
|
24529
|
+
memoryCount: 0,
|
|
24530
|
+
members: /* @__PURE__ */ new Set()
|
|
24531
|
+
});
|
|
24532
|
+
}
|
|
24533
|
+
return [...topics.values()].map(({ members, ...topic2 }) => ({ ...topic2, memoryCount: members.size })).sort((a, b) => a.name.localeCompare(b.name));
|
|
24534
|
+
})();
|
|
24535
|
+
topicSnapshot = snapshot;
|
|
24536
|
+
const clear = () => {
|
|
24537
|
+
if (topicSnapshot === snapshot) topicSnapshot = void 0;
|
|
24538
|
+
};
|
|
24539
|
+
void snapshot.then(() => {
|
|
24540
|
+
if (!retainTopics()) clear();
|
|
24541
|
+
}, clear);
|
|
24542
|
+
return snapshot.then((topics) => structuredClone(topics));
|
|
24294
24543
|
},
|
|
24295
24544
|
get: async (id2) => asStored(await live(id2)),
|
|
24296
24545
|
listArchived: async () => (await enumerate({ archived_only: true, order: "archived", include_embeddings: true })).map(
|
|
@@ -24471,20 +24720,23 @@ function createRemoteMemoryStore(options) {
|
|
|
24471
24720
|
subscribe: (onChange, subscribeOptions = {}) => {
|
|
24472
24721
|
const subscriber = { onChange, options: subscribeOptions };
|
|
24473
24722
|
subscribers.add(subscriber);
|
|
24474
|
-
if (pollIntervalMs > 0 &&
|
|
24475
|
-
|
|
24476
|
-
|
|
24723
|
+
if (pollIntervalMs > 0 && subscribers.size === 1) {
|
|
24724
|
+
stopActivity = activity.subscribe(refreshActivity);
|
|
24725
|
+
refreshActivity();
|
|
24477
24726
|
}
|
|
24478
24727
|
return () => {
|
|
24479
24728
|
subscribers.delete(subscriber);
|
|
24480
|
-
if (
|
|
24481
|
-
|
|
24729
|
+
if (!retainTopics()) invalidateReads();
|
|
24730
|
+
if (subscribers.size) return;
|
|
24731
|
+
if (timer) clearTimeout(timer);
|
|
24482
24732
|
timer = void 0;
|
|
24733
|
+
stopActivity?.();
|
|
24734
|
+
stopActivity = void 0;
|
|
24735
|
+
stopChanges?.();
|
|
24736
|
+
stopChanges = void 0;
|
|
24737
|
+
changesConnected = false;
|
|
24483
24738
|
generation++;
|
|
24484
|
-
|
|
24485
|
-
ready = false;
|
|
24486
|
-
cursor = void 0;
|
|
24487
|
-
pending = /* @__PURE__ */ new Set();
|
|
24739
|
+
invalidateReads();
|
|
24488
24740
|
};
|
|
24489
24741
|
}
|
|
24490
24742
|
};
|