@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.cjs
CHANGED
|
@@ -12118,11 +12118,12 @@ function isRemoteWorkLeaseExpired(error) {
|
|
|
12118
12118
|
|
|
12119
12119
|
// src/lib/memory/store/remotePersistence.ts
|
|
12120
12120
|
var RemoteMemoryError = class extends Error {
|
|
12121
|
-
constructor(message, status, code, retryAfterMs) {
|
|
12121
|
+
constructor(message, status, code, retryAfterMs, rateLimitBucket) {
|
|
12122
12122
|
super(message);
|
|
12123
12123
|
this.status = status;
|
|
12124
12124
|
this.code = code;
|
|
12125
12125
|
this.retryAfterMs = retryAfterMs;
|
|
12126
|
+
this.rateLimitBucket = rateLimitBucket;
|
|
12126
12127
|
this.name = "RemoteMemoryError";
|
|
12127
12128
|
}
|
|
12128
12129
|
};
|
|
@@ -12217,6 +12218,14 @@ function createNearbyRequest(options, apiPath = "/api/private-memories") {
|
|
|
12217
12218
|
throw new Error("timeoutMs must be a positive number");
|
|
12218
12219
|
const root = base.href.replace(/\/$/, "") + apiPath;
|
|
12219
12220
|
const fetcher = options.fetch ?? globalThis.fetch;
|
|
12221
|
+
const cooldowns = /* @__PURE__ */ new Map();
|
|
12222
|
+
const memoryBudget = (path, method) => {
|
|
12223
|
+
if (method === "PUT")
|
|
12224
|
+
return path === "/topics" ? "private-memory-import" : "private-memory-write";
|
|
12225
|
+
if (method === "POST" && ["/import", "/memories/batch", "/topics/import"].includes(path))
|
|
12226
|
+
return "private-memory-import";
|
|
12227
|
+
return "private-memory-read";
|
|
12228
|
+
};
|
|
12220
12229
|
const request = async (path, init = {}, signal) => {
|
|
12221
12230
|
const controller = new AbortController();
|
|
12222
12231
|
let timedOut = false;
|
|
@@ -12240,6 +12249,25 @@ function createNearbyRequest(options, apiPath = "/api/private-memories") {
|
|
|
12240
12249
|
const token = await Promise.race([options.getToken(), aborted2]);
|
|
12241
12250
|
if (controller.signal.aborted) await aborted2;
|
|
12242
12251
|
if (!token) throw new RemoteMemoryError("Authentication required", 401);
|
|
12252
|
+
const pathname = path.split("?")[0];
|
|
12253
|
+
const route = `${init.method ?? "GET"} ${pathname}`;
|
|
12254
|
+
const budgets = ["*", route];
|
|
12255
|
+
if (apiPath === "/api/private-memories")
|
|
12256
|
+
budgets.push("private-memory-ip", memoryBudget(pathname, init.method ?? "GET"));
|
|
12257
|
+
for (const bucket of budgets) {
|
|
12258
|
+
const cooldown = cooldowns.get(bucket);
|
|
12259
|
+
if (!cooldown) continue;
|
|
12260
|
+
const remaining = cooldown.until - Date.now();
|
|
12261
|
+
if (remaining > 0)
|
|
12262
|
+
throw new RemoteMemoryError(
|
|
12263
|
+
cooldown.error.message,
|
|
12264
|
+
429,
|
|
12265
|
+
cooldown.error.code,
|
|
12266
|
+
remaining,
|
|
12267
|
+
cooldown.error.rateLimitBucket
|
|
12268
|
+
);
|
|
12269
|
+
cooldowns.delete(bucket);
|
|
12270
|
+
}
|
|
12243
12271
|
const response = await fetcher(root + path, {
|
|
12244
12272
|
...init,
|
|
12245
12273
|
headers: {
|
|
@@ -12252,12 +12280,18 @@ function createNearbyRequest(options, apiPath = "/api/private-memories") {
|
|
|
12252
12280
|
if (!response.ok) {
|
|
12253
12281
|
const body = await response.json().catch(() => null);
|
|
12254
12282
|
const retryAfter = parseRetryAfterMs(response.headers.get("Retry-After"));
|
|
12255
|
-
|
|
12283
|
+
const error = new RemoteMemoryError(
|
|
12256
12284
|
record(body) && typeof body.detail === "string" ? body.detail : `Nearby request failed (${response.status})`,
|
|
12257
12285
|
response.status,
|
|
12258
12286
|
record(body) && typeof body.code === "string" ? body.code : void 0,
|
|
12259
|
-
retryAfter ?? void 0
|
|
12287
|
+
retryAfter ?? void 0,
|
|
12288
|
+
record(body) && typeof body.rate_limit_bucket === "string" ? body.rate_limit_bucket : void 0
|
|
12260
12289
|
);
|
|
12290
|
+
if (response.status === 429 && retryAfter !== null && retryAfter > 0 && (!error.code || error.code === "rate_limited")) {
|
|
12291
|
+
const bucket = error.rateLimitBucket && budgets.includes(error.rateLimitBucket) ? error.rateLimitBucket : record(body) && (body.limit_scope === "account" || body.limit_scope === "ip") && !error.rateLimitBucket ? "*" : route;
|
|
12292
|
+
cooldowns.set(bucket, { until: Date.now() + retryAfter, error });
|
|
12293
|
+
}
|
|
12294
|
+
throw error;
|
|
12261
12295
|
}
|
|
12262
12296
|
return await response.json();
|
|
12263
12297
|
} catch (error) {
|
|
@@ -12497,6 +12531,7 @@ async function createRemoteMemoryPersistence(options) {
|
|
|
12497
12531
|
return {
|
|
12498
12532
|
...createRemoteTopicPersistence(request),
|
|
12499
12533
|
...createRemoteWorkPersistence(request),
|
|
12534
|
+
supportsRealtimeChanges: account.realtime_changes === true,
|
|
12500
12535
|
counts: async () => {
|
|
12501
12536
|
const result = await request("/counts", {});
|
|
12502
12537
|
if (!record(result) || ["live", "archived", "quarantined"].some(
|
|
@@ -16599,9 +16634,10 @@ async function getVaultRankingProjectionsOp(ctx, options) {
|
|
|
16599
16634
|
}
|
|
16600
16635
|
function baseVaultSql(ctx, options) {
|
|
16601
16636
|
const clauses = [
|
|
16637
|
+
`"_status" is not 'deleted'`,
|
|
16602
16638
|
'"is_deleted" = 0',
|
|
16603
16639
|
...options?.includeArchived ? [] : ['"archived_at" is null'],
|
|
16604
|
-
`"trust_tier" is not 'quarantined'
|
|
16640
|
+
...options?.includeQuarantined ? [] : [`"trust_tier" is not 'quarantined'`],
|
|
16605
16641
|
'"superseded_by" is null'
|
|
16606
16642
|
];
|
|
16607
16643
|
const args = [];
|
|
@@ -17087,8 +17123,17 @@ async function getMemoriesNeedingTopicExtractionOp(ctx, options) {
|
|
|
17087
17123
|
if (!entityCtx) {
|
|
17088
17124
|
throw new Error("getMemoriesNeedingTopicExtractionOp requires ctx.entityCtx");
|
|
17089
17125
|
}
|
|
17090
|
-
|
|
17091
|
-
|
|
17126
|
+
let rows;
|
|
17127
|
+
try {
|
|
17128
|
+
const base = baseVaultSql(ctx);
|
|
17129
|
+
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`;
|
|
17130
|
+
rows = await ctx.vaultMemoryCollection.query(import_watermelondb24.Q.unsafeSqlQuery(sql, base.args)).unsafeFetchRaw();
|
|
17131
|
+
} catch (err) {
|
|
17132
|
+
getLogger().debug(
|
|
17133
|
+
"memoryVault: topic sweep SQL unavailable; use the adapter query: " + (err instanceof Error ? err.message : String(err))
|
|
17134
|
+
);
|
|
17135
|
+
rows = await ctx.vaultMemoryCollection.query(...baseVaultConditions(ctx), import_watermelondb24.Q.sortBy("created_at", import_watermelondb24.Q.desc)).unsafeFetchRaw();
|
|
17136
|
+
}
|
|
17092
17137
|
const linkedNames = await linkedEntityNamesByMemory(
|
|
17093
17138
|
entityCtx,
|
|
17094
17139
|
rows.map((r) => r.id)
|
|
@@ -17147,10 +17192,19 @@ async function getMemoriesNeedingTopicExtractionOp(ctx, options) {
|
|
|
17147
17192
|
}
|
|
17148
17193
|
const orderedPendingRaw = [...stampedPendingRaw, ...pendingRaw];
|
|
17149
17194
|
const limitedPendingRaw = cap !== void 0 ? orderedPendingRaw.slice(0, cap) : orderedPendingRaw;
|
|
17150
|
-
const pending =
|
|
17151
|
-
|
|
17152
|
-
|
|
17153
|
-
|
|
17195
|
+
const pending = [];
|
|
17196
|
+
for (let i = 0; i < limitedPendingRaw.length; i += 500) {
|
|
17197
|
+
const chunk = limitedPendingRaw.slice(i, i + 500);
|
|
17198
|
+
const memories = await getVaultMemoriesByIdsOp(
|
|
17199
|
+
ctx,
|
|
17200
|
+
chunk.map((raw) => raw.id)
|
|
17201
|
+
);
|
|
17202
|
+
const byId = new Map(memories.map((memory) => [memory.uniqueId, memory]));
|
|
17203
|
+
for (const raw of chunk) {
|
|
17204
|
+
const memory = byId.get(raw.id);
|
|
17205
|
+
if (memory) pending.push(memory);
|
|
17206
|
+
}
|
|
17207
|
+
}
|
|
17154
17208
|
const applyCap = (ids) => cap !== void 0 ? ids.slice(0, cap) : ids;
|
|
17155
17209
|
return {
|
|
17156
17210
|
pending,
|
|
@@ -17297,10 +17351,20 @@ function assertVaultScopeForSweep(ctx) {
|
|
|
17297
17351
|
}
|
|
17298
17352
|
async function getDecayCandidatesRawOp(ctx) {
|
|
17299
17353
|
assertVaultScopeForSweep(ctx);
|
|
17300
|
-
|
|
17301
|
-
|
|
17302
|
-
|
|
17303
|
-
|
|
17354
|
+
let results;
|
|
17355
|
+
try {
|
|
17356
|
+
const base = baseVaultSql(ctx, { includeArchived: true, includeQuarantined: true });
|
|
17357
|
+
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`;
|
|
17358
|
+
results = await ctx.vaultMemoryCollection.query(import_watermelondb24.Q.unsafeSqlQuery(sql, base.args)).unsafeFetchRaw();
|
|
17359
|
+
} catch (err) {
|
|
17360
|
+
getLogger().debug(
|
|
17361
|
+
"memoryVault: decay sweep SQL unavailable; use the adapter query: " + (err instanceof Error ? err.message : String(err))
|
|
17362
|
+
);
|
|
17363
|
+
results = await ctx.vaultMemoryCollection.query(
|
|
17364
|
+
...baseVaultConditions(ctx, { includeArchived: true, includeQuarantined: true }),
|
|
17365
|
+
import_watermelondb24.Q.where("kind", null)
|
|
17366
|
+
).unsafeFetchRaw();
|
|
17367
|
+
}
|
|
17304
17368
|
return results.map((raw) => ({
|
|
17305
17369
|
uniqueId: raw.id,
|
|
17306
17370
|
factType: raw.fact_type ?? null,
|
|
@@ -25334,6 +25398,9 @@ var RemoteMemoryPartialCreateError = class extends Error {
|
|
|
25334
25398
|
function rejectsInput(error) {
|
|
25335
25399
|
return error instanceof EmbeddingHttpError && error.status !== void 0 && error.status >= 400 && error.status < 500 && error.status !== 429 && !isFatalEmbeddingError(error);
|
|
25336
25400
|
}
|
|
25401
|
+
function rejectsMemoryWrite(error) {
|
|
25402
|
+
return error instanceof RemoteMemoryError && (error.status === 400 || error.status === 422) && (error.code === void 0 || error.code === "unknown_field");
|
|
25403
|
+
}
|
|
25337
25404
|
function warnFailed(failed) {
|
|
25338
25405
|
if (failed.length)
|
|
25339
25406
|
getLogger().warn(
|
|
@@ -25421,16 +25488,47 @@ function createRemoteMemoryStore(options) {
|
|
|
25421
25488
|
const { persistence, embeddingOptions } = options;
|
|
25422
25489
|
const model = embeddingOptions.model ?? DEFAULT_API_EMBEDDING_MODEL;
|
|
25423
25490
|
const pollIntervalMs = options.pollIntervalMs ?? 6e4;
|
|
25491
|
+
const activity = options.activity ?? {
|
|
25492
|
+
isActive: () => (typeof document === "undefined" || document.visibilityState !== "hidden") && (typeof navigator === "undefined" || navigator.onLine !== false),
|
|
25493
|
+
subscribe: (onChange) => {
|
|
25494
|
+
if (typeof window === "undefined" || typeof document === "undefined") return () => {
|
|
25495
|
+
};
|
|
25496
|
+
document.addEventListener("visibilitychange", onChange);
|
|
25497
|
+
window.addEventListener("online", onChange);
|
|
25498
|
+
window.addEventListener("offline", onChange);
|
|
25499
|
+
return () => {
|
|
25500
|
+
document.removeEventListener("visibilitychange", onChange);
|
|
25501
|
+
window.removeEventListener("online", onChange);
|
|
25502
|
+
window.removeEventListener("offline", onChange);
|
|
25503
|
+
};
|
|
25504
|
+
}
|
|
25505
|
+
};
|
|
25424
25506
|
const pipeline = createRemoteMemoryPipeline({
|
|
25425
25507
|
...options,
|
|
25426
25508
|
graphRanking: options.graphRanking ?? ((query, _traverse, recallOptions) => topicGraphRanking(query, recallOptions)),
|
|
25427
25509
|
temporalRanking: options.temporalRanking ?? ((query, now) => eventTimeRanking(query, now))
|
|
25428
25510
|
});
|
|
25429
25511
|
const subscribers = /* @__PURE__ */ new Set();
|
|
25512
|
+
const retainTopics = () => pollIntervalMs > 0 && [...subscribers].some((subscriber) => subscriber.options.topics);
|
|
25430
25513
|
const seen = /* @__PURE__ */ new Map();
|
|
25514
|
+
const reads = /* @__PURE__ */ new Map();
|
|
25515
|
+
const metadataReads = /* @__PURE__ */ new Map();
|
|
25516
|
+
let topicSnapshot;
|
|
25517
|
+
let topicCatalog;
|
|
25518
|
+
const invalidateReads = () => {
|
|
25519
|
+
reads.clear();
|
|
25520
|
+
metadataReads.clear();
|
|
25521
|
+
topicSnapshot = void 0;
|
|
25522
|
+
topicCatalog = void 0;
|
|
25523
|
+
};
|
|
25431
25524
|
let timer;
|
|
25525
|
+
let scheduledAt;
|
|
25526
|
+
let stopActivity;
|
|
25527
|
+
let stopChanges;
|
|
25528
|
+
let changesConnected = false;
|
|
25432
25529
|
const notify = (change, records = []) => {
|
|
25433
|
-
|
|
25530
|
+
invalidateReads();
|
|
25531
|
+
if (subscribers.size)
|
|
25434
25532
|
for (const record2 of records) {
|
|
25435
25533
|
const previous = seen.get(record2.memory.memory_id);
|
|
25436
25534
|
if ((previous?.version ?? 0) + 1 === record2.version)
|
|
@@ -25454,8 +25552,37 @@ function createRemoteMemoryStore(options) {
|
|
|
25454
25552
|
} while (cursor2 && records.length < max);
|
|
25455
25553
|
return records.slice(0, max);
|
|
25456
25554
|
};
|
|
25457
|
-
const
|
|
25458
|
-
|
|
25555
|
+
const shareRead = (inflight, options2, read) => {
|
|
25556
|
+
if (options2.signal) return read();
|
|
25557
|
+
const key = JSON.stringify(Object.entries(options2).sort(([a], [b]) => a.localeCompare(b)));
|
|
25558
|
+
const active = inflight.get(key);
|
|
25559
|
+
if (active) return active;
|
|
25560
|
+
const pending2 = read();
|
|
25561
|
+
inflight.set(key, pending2);
|
|
25562
|
+
const clear = () => {
|
|
25563
|
+
if (inflight.get(key) === pending2) inflight.delete(key);
|
|
25564
|
+
};
|
|
25565
|
+
void pending2.then(clear, clear);
|
|
25566
|
+
return pending2;
|
|
25567
|
+
};
|
|
25568
|
+
const decrypted = (options2) => shareRead(reads, options2, () => persistence.query(options2));
|
|
25569
|
+
const metadata3 = (options2) => shareRead(
|
|
25570
|
+
metadataReads,
|
|
25571
|
+
options2,
|
|
25572
|
+
() => persistence.queryMetadata(options2)
|
|
25573
|
+
);
|
|
25574
|
+
const readTopics = () => {
|
|
25575
|
+
if (topicCatalog) return topicCatalog;
|
|
25576
|
+
const pending2 = persistence.topics();
|
|
25577
|
+
topicCatalog = pending2;
|
|
25578
|
+
const clear = () => {
|
|
25579
|
+
if (topicCatalog === pending2) topicCatalog = void 0;
|
|
25580
|
+
};
|
|
25581
|
+
void pending2.then(() => {
|
|
25582
|
+
if (!retainTopics()) clear();
|
|
25583
|
+
}, clear);
|
|
25584
|
+
return pending2;
|
|
25585
|
+
};
|
|
25459
25586
|
const enumerate = (filters, max = Infinity) => pages(decrypted, filters, max);
|
|
25460
25587
|
const memoriesByTopics = async (names) => {
|
|
25461
25588
|
const wanted = new Set(names.map(normalizeEntityName).filter(Boolean));
|
|
@@ -25909,11 +26036,11 @@ function createRemoteMemoryStore(options) {
|
|
|
25909
26036
|
};
|
|
25910
26037
|
const changesSince = async (cursor2, pending2) => {
|
|
25911
26038
|
const records = [];
|
|
25912
|
-
const failed = /* @__PURE__ */ new
|
|
26039
|
+
const failed = /* @__PURE__ */ new Map();
|
|
25913
26040
|
const collect = (page) => {
|
|
25914
26041
|
warnFailed(page.failed);
|
|
25915
26042
|
records.push(...page.items);
|
|
25916
|
-
for (const failure of page.failed) failed.
|
|
26043
|
+
for (const failure of page.failed) failed.set(failure.memory_id, failure.version);
|
|
25917
26044
|
};
|
|
25918
26045
|
let resume = cursor2;
|
|
25919
26046
|
let next;
|
|
@@ -25947,25 +26074,72 @@ function createRemoteMemoryStore(options) {
|
|
|
25947
26074
|
let ready = false;
|
|
25948
26075
|
let cursor;
|
|
25949
26076
|
let pending = /* @__PURE__ */ new Set();
|
|
26077
|
+
let failedVersions = /* @__PURE__ */ new Map();
|
|
25950
26078
|
let topicFingerprint;
|
|
25951
26079
|
let polling = false;
|
|
26080
|
+
let pollRequested = false;
|
|
26081
|
+
let failures = 0;
|
|
26082
|
+
let retryAt = 0;
|
|
26083
|
+
const backoff = (error) => {
|
|
26084
|
+
failures++;
|
|
26085
|
+
retryAt = Date.now() + Math.max(
|
|
26086
|
+
error instanceof RemoteMemoryError ? error.retryAfterMs ?? 0 : 0,
|
|
26087
|
+
Math.min(pollIntervalMs * 2 ** Math.min(failures - 1, 10), 15 * 6e4)
|
|
26088
|
+
);
|
|
26089
|
+
};
|
|
26090
|
+
const schedulePoll = (delay, keepEarlier = false) => {
|
|
26091
|
+
const at = Math.max(Date.now() + delay, retryAt);
|
|
26092
|
+
if (keepEarlier && timer && scheduledAt !== void 0 && scheduledAt <= at) return;
|
|
26093
|
+
if (timer) clearTimeout(timer);
|
|
26094
|
+
timer = void 0;
|
|
26095
|
+
scheduledAt = void 0;
|
|
26096
|
+
if (!subscribers.size || pollIntervalMs <= 0 || !activity.isActive()) return;
|
|
26097
|
+
scheduledAt = at;
|
|
26098
|
+
timer = setTimeout(poll, Math.max(0, at - Date.now()));
|
|
26099
|
+
};
|
|
25952
26100
|
const poll = () => {
|
|
25953
|
-
if (
|
|
26101
|
+
if (timer) clearTimeout(timer);
|
|
26102
|
+
timer = void 0;
|
|
26103
|
+
scheduledAt = void 0;
|
|
26104
|
+
if (!subscribers.size || pollIntervalMs <= 0 || !activity.isActive()) return;
|
|
26105
|
+
if (Date.now() < retryAt) {
|
|
26106
|
+
schedulePoll(0);
|
|
26107
|
+
return;
|
|
26108
|
+
}
|
|
26109
|
+
if (polling) {
|
|
26110
|
+
pollRequested = true;
|
|
26111
|
+
return;
|
|
26112
|
+
}
|
|
25954
26113
|
polling = true;
|
|
26114
|
+
pollRequested = false;
|
|
25955
26115
|
const current = generation;
|
|
25956
26116
|
changesSince(cursor, pending).then(async ({ records, resume, failed }) => {
|
|
25957
26117
|
let topicState;
|
|
26118
|
+
let topicFailed = false;
|
|
25958
26119
|
if ([...subscribers].some((s) => s.options.topics))
|
|
25959
26120
|
try {
|
|
25960
|
-
|
|
25961
|
-
|
|
25962
|
-
);
|
|
26121
|
+
topicCatalog = void 0;
|
|
26122
|
+
topicState = JSON.stringify((await readTopics()).map((t) => [t.name, t.version]));
|
|
25963
26123
|
} catch (error) {
|
|
26124
|
+
topicFailed = true;
|
|
26125
|
+
if (current === generation) backoff(error);
|
|
25964
26126
|
getLogger().warn("[memory/remote-store] Topic subscription poll failed:", error);
|
|
25965
26127
|
}
|
|
25966
26128
|
if (current !== generation) return;
|
|
26129
|
+
if (!topicFailed) {
|
|
26130
|
+
failures = 0;
|
|
26131
|
+
retryAt = 0;
|
|
26132
|
+
}
|
|
26133
|
+
const failedChanged = [...failed].some(
|
|
26134
|
+
([id2, version]) => failedVersions.get(id2) !== version
|
|
26135
|
+
);
|
|
26136
|
+
if (records.length || failedChanged || topicState !== void 0 && topicState !== topicFingerprint) {
|
|
26137
|
+
reads.clear();
|
|
26138
|
+
metadataReads.clear();
|
|
26139
|
+
topicSnapshot = void 0;
|
|
26140
|
+
}
|
|
25967
26141
|
const changed = /* @__PURE__ */ new Set();
|
|
25968
|
-
if (topicState !== void 0 && topicFingerprint !== void 0 && topicState !== topicFingerprint) {
|
|
26142
|
+
if (ready && failedChanged || topicState !== void 0 && topicFingerprint !== void 0 && topicState !== topicFingerprint) {
|
|
25969
26143
|
for (const subscriber of subscribers)
|
|
25970
26144
|
if (subscriber.options.topics) changed.add(subscriber);
|
|
25971
26145
|
}
|
|
@@ -25982,15 +26156,40 @@ function createRemoteMemoryStore(options) {
|
|
|
25982
26156
|
}
|
|
25983
26157
|
ready = true;
|
|
25984
26158
|
cursor = resume;
|
|
25985
|
-
pending = failed;
|
|
26159
|
+
pending = new Set(failed.keys());
|
|
26160
|
+
failedVersions = failed;
|
|
25986
26161
|
for (const subscriber of changed)
|
|
25987
26162
|
if (subscribers.has(subscriber)) safely(subscriber.onChange);
|
|
25988
26163
|
}).catch((error) => {
|
|
26164
|
+
if (current === generation) backoff(error);
|
|
25989
26165
|
getLogger().warn("[memory/remote-store] Subscription poll failed:", error);
|
|
25990
26166
|
}).finally(() => {
|
|
25991
26167
|
polling = false;
|
|
26168
|
+
schedulePoll(
|
|
26169
|
+
current !== generation ? 0 : pollRequested ? 200 : changesConnected ? Math.max(pollIntervalMs, 5 * 6e4) : pollIntervalMs
|
|
26170
|
+
);
|
|
25992
26171
|
});
|
|
25993
26172
|
};
|
|
26173
|
+
const refreshActivity = () => {
|
|
26174
|
+
if (timer) clearTimeout(timer);
|
|
26175
|
+
timer = void 0;
|
|
26176
|
+
if (!activity.isActive()) {
|
|
26177
|
+
stopChanges?.();
|
|
26178
|
+
stopChanges = void 0;
|
|
26179
|
+
changesConnected = false;
|
|
26180
|
+
return;
|
|
26181
|
+
}
|
|
26182
|
+
if (!stopChanges && persistence.supportsRealtimeChanges && options.subscribeChanges)
|
|
26183
|
+
stopChanges = options.subscribeChanges((connected) => {
|
|
26184
|
+
changesConnected = connected;
|
|
26185
|
+
if (polling) {
|
|
26186
|
+
pollRequested = true;
|
|
26187
|
+
return;
|
|
26188
|
+
}
|
|
26189
|
+
schedulePoll(connected ? 200 : 0, true);
|
|
26190
|
+
});
|
|
26191
|
+
poll();
|
|
26192
|
+
};
|
|
25994
26193
|
const unrepairable = /* @__PURE__ */ new Set();
|
|
25995
26194
|
let repairCursor;
|
|
25996
26195
|
const repairEmbeddingsUnlocked = async ({
|
|
@@ -26046,40 +26245,78 @@ function createRemoteMemoryStore(options) {
|
|
|
26046
26245
|
result.failed += targets.length;
|
|
26047
26246
|
return finish();
|
|
26048
26247
|
}
|
|
26049
|
-
|
|
26248
|
+
const writes = targets.flatMap((record2, i) => {
|
|
26050
26249
|
const vector = vectors[i];
|
|
26051
26250
|
if (!vector) {
|
|
26052
26251
|
result.failed++;
|
|
26053
|
-
|
|
26252
|
+
return [];
|
|
26054
26253
|
}
|
|
26055
|
-
|
|
26056
|
-
|
|
26057
|
-
|
|
26058
|
-
|
|
26059
|
-
|
|
26060
|
-
|
|
26061
|
-
|
|
26062
|
-
|
|
26063
|
-
|
|
26064
|
-
|
|
26065
|
-
|
|
26066
|
-
|
|
26067
|
-
|
|
26068
|
-
|
|
26069
|
-
|
|
26070
|
-
|
|
26071
|
-
|
|
26072
|
-
|
|
26073
|
-
|
|
26074
|
-
|
|
26075
|
-
} catch (error) {
|
|
26254
|
+
try {
|
|
26255
|
+
return [
|
|
26256
|
+
{
|
|
26257
|
+
memory: {
|
|
26258
|
+
...record2.memory,
|
|
26259
|
+
embedding: storedVector(vector),
|
|
26260
|
+
embedding_model: model
|
|
26261
|
+
},
|
|
26262
|
+
expectedVersion: record2
|
|
26263
|
+
}
|
|
26264
|
+
];
|
|
26265
|
+
} catch {
|
|
26266
|
+
result.failed++;
|
|
26267
|
+
return [];
|
|
26268
|
+
}
|
|
26269
|
+
});
|
|
26270
|
+
for (const batch of chunks2(writes, MAX_BATCH)) {
|
|
26271
|
+
const continueRepair = await serializedAll(
|
|
26272
|
+
batch.map(({ memory }) => memory.memory_id),
|
|
26273
|
+
async () => {
|
|
26076
26274
|
signal?.throwIfAborted();
|
|
26077
|
-
|
|
26078
|
-
|
|
26079
|
-
|
|
26080
|
-
|
|
26275
|
+
const commit = async (slice) => {
|
|
26276
|
+
const saved = await persistence.putMany(slice, signal, leaseToken);
|
|
26277
|
+
for (const record2 of saved) repaired.add(record2.memory.memory_id);
|
|
26278
|
+
result.reembedded += saved.length;
|
|
26279
|
+
notify("embedding", saved);
|
|
26280
|
+
};
|
|
26281
|
+
try {
|
|
26282
|
+
await commit(batch);
|
|
26283
|
+
} catch (error) {
|
|
26284
|
+
signal?.throwIfAborted();
|
|
26285
|
+
if (isRemoteWorkLeaseExpired(error)) throw error;
|
|
26286
|
+
if (!(error instanceof RemoteMemoryError && error.code === "version_conflict") && !rejectsMemoryWrite(error)) {
|
|
26287
|
+
result.failed += batch.length;
|
|
26288
|
+
return false;
|
|
26289
|
+
}
|
|
26290
|
+
if (batch.length === 1) {
|
|
26291
|
+
if (rejectsMemoryWrite(error)) {
|
|
26292
|
+
unrepairable.add(batch[0].memory.memory_id);
|
|
26293
|
+
result.failed++;
|
|
26294
|
+
} else result.skippedConflict++;
|
|
26295
|
+
return true;
|
|
26296
|
+
}
|
|
26297
|
+
for (const [index, write] of batch.entries()) {
|
|
26298
|
+
signal?.throwIfAborted();
|
|
26299
|
+
try {
|
|
26300
|
+
await commit([write]);
|
|
26301
|
+
} catch (error2) {
|
|
26302
|
+
signal?.throwIfAborted();
|
|
26303
|
+
if (isRemoteWorkLeaseExpired(error2)) throw error2;
|
|
26304
|
+
if (error2 instanceof RemoteMemoryError && error2.code === "version_conflict")
|
|
26305
|
+
result.skippedConflict++;
|
|
26306
|
+
else if (rejectsMemoryWrite(error2)) {
|
|
26307
|
+
unrepairable.add(write.memory.memory_id);
|
|
26308
|
+
result.failed++;
|
|
26309
|
+
} else {
|
|
26310
|
+
result.failed += batch.length - index;
|
|
26311
|
+
return false;
|
|
26312
|
+
}
|
|
26313
|
+
}
|
|
26314
|
+
}
|
|
26315
|
+
}
|
|
26316
|
+
return true;
|
|
26081
26317
|
}
|
|
26082
|
-
|
|
26318
|
+
);
|
|
26319
|
+
if (!continueRepair) break;
|
|
26083
26320
|
}
|
|
26084
26321
|
return finish();
|
|
26085
26322
|
};
|
|
@@ -26119,7 +26356,7 @@ function createRemoteMemoryStore(options) {
|
|
|
26119
26356
|
},
|
|
26120
26357
|
importTopics: async (topics) => {
|
|
26121
26358
|
if (!topics.length) return;
|
|
26122
|
-
const existing = new Set((await
|
|
26359
|
+
const existing = new Set((await readTopics()).map((topic2) => topic2.name));
|
|
26123
26360
|
const missing = topics.flatMap((topic2) => {
|
|
26124
26361
|
const name = normalizeEntityName(topic2.name);
|
|
26125
26362
|
if (existing.has(name)) return [];
|
|
@@ -26128,6 +26365,7 @@ function createRemoteMemoryStore(options) {
|
|
|
26128
26365
|
});
|
|
26129
26366
|
if (!missing.length) return;
|
|
26130
26367
|
await persistence.importTopics(missing);
|
|
26368
|
+
invalidateReads();
|
|
26131
26369
|
for (const subscriber of [...subscribers])
|
|
26132
26370
|
if (subscriber.options.topics) safely(subscriber.onChange);
|
|
26133
26371
|
},
|
|
@@ -26141,40 +26379,51 @@ function createRemoteMemoryStore(options) {
|
|
|
26141
26379
|
listProjections: async (listOptions = {}) => (await listRows(metadata3, listOptions, listFilters(listOptions), maxOf(listOptions))).map(
|
|
26142
26380
|
projection
|
|
26143
26381
|
),
|
|
26144
|
-
listTopics:
|
|
26145
|
-
|
|
26146
|
-
|
|
26147
|
-
|
|
26148
|
-
|
|
26149
|
-
|
|
26150
|
-
|
|
26151
|
-
|
|
26152
|
-
|
|
26153
|
-
|
|
26154
|
-
|
|
26155
|
-
name
|
|
26156
|
-
|
|
26157
|
-
|
|
26158
|
-
|
|
26159
|
-
|
|
26160
|
-
|
|
26161
|
-
|
|
26162
|
-
|
|
26163
|
-
|
|
26164
|
-
|
|
26165
|
-
|
|
26166
|
-
|
|
26167
|
-
const
|
|
26168
|
-
|
|
26169
|
-
|
|
26170
|
-
|
|
26171
|
-
|
|
26172
|
-
|
|
26173
|
-
|
|
26174
|
-
|
|
26175
|
-
|
|
26176
|
-
|
|
26177
|
-
|
|
26382
|
+
listTopics: () => {
|
|
26383
|
+
if (topicSnapshot) return topicSnapshot.then((topics) => structuredClone(topics));
|
|
26384
|
+
const snapshot = (async () => {
|
|
26385
|
+
const topics = /* @__PURE__ */ new Map();
|
|
26386
|
+
for (const { memory } of await pages(metadata3, {
|
|
26387
|
+
include_archived: true,
|
|
26388
|
+
include_quarantined: true,
|
|
26389
|
+
include_superseded: true
|
|
26390
|
+
})) {
|
|
26391
|
+
for (const topic2 of parseTopics(memory.topics) ?? []) {
|
|
26392
|
+
const name = normalizeEntityName(topic2.name);
|
|
26393
|
+
if (!name) continue;
|
|
26394
|
+
const entry = topics.get(name) ?? {
|
|
26395
|
+
name,
|
|
26396
|
+
kind: null,
|
|
26397
|
+
memoryCount: 0,
|
|
26398
|
+
members: /* @__PURE__ */ new Set()
|
|
26399
|
+
};
|
|
26400
|
+
entry.kind ?? (entry.kind = topic2.kind ?? null);
|
|
26401
|
+
entry.members.add(memory.memory_id);
|
|
26402
|
+
topics.set(name, entry);
|
|
26403
|
+
}
|
|
26404
|
+
}
|
|
26405
|
+
for (const topic2 of await readTopics()) {
|
|
26406
|
+
if (topic2.is_deleted) continue;
|
|
26407
|
+
const current = topics.get(topic2.name);
|
|
26408
|
+
if (current) current.kind ?? (current.kind = topic2.kind ?? null);
|
|
26409
|
+
else
|
|
26410
|
+
topics.set(topic2.name, {
|
|
26411
|
+
name: topic2.name,
|
|
26412
|
+
kind: topic2.kind ?? null,
|
|
26413
|
+
memoryCount: 0,
|
|
26414
|
+
members: /* @__PURE__ */ new Set()
|
|
26415
|
+
});
|
|
26416
|
+
}
|
|
26417
|
+
return [...topics.values()].map(({ members, ...topic2 }) => ({ ...topic2, memoryCount: members.size })).sort((a, b) => a.name.localeCompare(b.name));
|
|
26418
|
+
})();
|
|
26419
|
+
topicSnapshot = snapshot;
|
|
26420
|
+
const clear = () => {
|
|
26421
|
+
if (topicSnapshot === snapshot) topicSnapshot = void 0;
|
|
26422
|
+
};
|
|
26423
|
+
void snapshot.then(() => {
|
|
26424
|
+
if (!retainTopics()) clear();
|
|
26425
|
+
}, clear);
|
|
26426
|
+
return snapshot.then((topics) => structuredClone(topics));
|
|
26178
26427
|
},
|
|
26179
26428
|
get: async (id2) => asStored(await live(id2)),
|
|
26180
26429
|
listArchived: async () => (await enumerate({ archived_only: true, order: "archived", include_embeddings: true })).map(
|
|
@@ -26355,20 +26604,23 @@ function createRemoteMemoryStore(options) {
|
|
|
26355
26604
|
subscribe: (onChange, subscribeOptions = {}) => {
|
|
26356
26605
|
const subscriber = { onChange, options: subscribeOptions };
|
|
26357
26606
|
subscribers.add(subscriber);
|
|
26358
|
-
if (pollIntervalMs > 0 &&
|
|
26359
|
-
|
|
26360
|
-
|
|
26607
|
+
if (pollIntervalMs > 0 && subscribers.size === 1) {
|
|
26608
|
+
stopActivity = activity.subscribe(refreshActivity);
|
|
26609
|
+
refreshActivity();
|
|
26361
26610
|
}
|
|
26362
26611
|
return () => {
|
|
26363
26612
|
subscribers.delete(subscriber);
|
|
26364
|
-
if (
|
|
26365
|
-
|
|
26613
|
+
if (!retainTopics()) invalidateReads();
|
|
26614
|
+
if (subscribers.size) return;
|
|
26615
|
+
if (timer) clearTimeout(timer);
|
|
26366
26616
|
timer = void 0;
|
|
26617
|
+
stopActivity?.();
|
|
26618
|
+
stopActivity = void 0;
|
|
26619
|
+
stopChanges?.();
|
|
26620
|
+
stopChanges = void 0;
|
|
26621
|
+
changesConnected = false;
|
|
26367
26622
|
generation++;
|
|
26368
|
-
|
|
26369
|
-
ready = false;
|
|
26370
|
-
cursor = void 0;
|
|
26371
|
-
pending = /* @__PURE__ */ new Set();
|
|
26623
|
+
invalidateReads();
|
|
26372
26624
|
};
|
|
26373
26625
|
}
|
|
26374
26626
|
};
|