@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/expo/index.mjs
CHANGED
|
@@ -9683,11 +9683,12 @@ function isRemoteWorkLeaseExpired(error) {
|
|
|
9683
9683
|
|
|
9684
9684
|
// src/lib/memory/store/remotePersistence.ts
|
|
9685
9685
|
var RemoteMemoryError = class extends Error {
|
|
9686
|
-
constructor(message, status, code, retryAfterMs) {
|
|
9686
|
+
constructor(message, status, code, retryAfterMs, rateLimitBucket) {
|
|
9687
9687
|
super(message);
|
|
9688
9688
|
this.status = status;
|
|
9689
9689
|
this.code = code;
|
|
9690
9690
|
this.retryAfterMs = retryAfterMs;
|
|
9691
|
+
this.rateLimitBucket = rateLimitBucket;
|
|
9691
9692
|
this.name = "RemoteMemoryError";
|
|
9692
9693
|
}
|
|
9693
9694
|
};
|
|
@@ -9782,6 +9783,14 @@ function createNearbyRequest(options, apiPath = "/api/private-memories") {
|
|
|
9782
9783
|
throw new Error("timeoutMs must be a positive number");
|
|
9783
9784
|
const root = base.href.replace(/\/$/, "") + apiPath;
|
|
9784
9785
|
const fetcher = options.fetch ?? globalThis.fetch;
|
|
9786
|
+
const cooldowns = /* @__PURE__ */ new Map();
|
|
9787
|
+
const memoryBudget = (path, method) => {
|
|
9788
|
+
if (method === "PUT")
|
|
9789
|
+
return path === "/topics" ? "private-memory-import" : "private-memory-write";
|
|
9790
|
+
if (method === "POST" && ["/import", "/memories/batch", "/topics/import"].includes(path))
|
|
9791
|
+
return "private-memory-import";
|
|
9792
|
+
return "private-memory-read";
|
|
9793
|
+
};
|
|
9785
9794
|
const request = async (path, init = {}, signal) => {
|
|
9786
9795
|
const controller = new AbortController();
|
|
9787
9796
|
let timedOut = false;
|
|
@@ -9805,6 +9814,25 @@ function createNearbyRequest(options, apiPath = "/api/private-memories") {
|
|
|
9805
9814
|
const token = await Promise.race([options.getToken(), aborted2]);
|
|
9806
9815
|
if (controller.signal.aborted) await aborted2;
|
|
9807
9816
|
if (!token) throw new RemoteMemoryError("Authentication required", 401);
|
|
9817
|
+
const pathname = path.split("?")[0];
|
|
9818
|
+
const route = `${init.method ?? "GET"} ${pathname}`;
|
|
9819
|
+
const budgets = ["*", route];
|
|
9820
|
+
if (apiPath === "/api/private-memories")
|
|
9821
|
+
budgets.push("private-memory-ip", memoryBudget(pathname, init.method ?? "GET"));
|
|
9822
|
+
for (const bucket of budgets) {
|
|
9823
|
+
const cooldown = cooldowns.get(bucket);
|
|
9824
|
+
if (!cooldown) continue;
|
|
9825
|
+
const remaining = cooldown.until - Date.now();
|
|
9826
|
+
if (remaining > 0)
|
|
9827
|
+
throw new RemoteMemoryError(
|
|
9828
|
+
cooldown.error.message,
|
|
9829
|
+
429,
|
|
9830
|
+
cooldown.error.code,
|
|
9831
|
+
remaining,
|
|
9832
|
+
cooldown.error.rateLimitBucket
|
|
9833
|
+
);
|
|
9834
|
+
cooldowns.delete(bucket);
|
|
9835
|
+
}
|
|
9808
9836
|
const response = await fetcher(root + path, {
|
|
9809
9837
|
...init,
|
|
9810
9838
|
headers: {
|
|
@@ -9817,12 +9845,18 @@ function createNearbyRequest(options, apiPath = "/api/private-memories") {
|
|
|
9817
9845
|
if (!response.ok) {
|
|
9818
9846
|
const body = await response.json().catch(() => null);
|
|
9819
9847
|
const retryAfter = parseRetryAfterMs(response.headers.get("Retry-After"));
|
|
9820
|
-
|
|
9848
|
+
const error = new RemoteMemoryError(
|
|
9821
9849
|
record(body) && typeof body.detail === "string" ? body.detail : `Nearby request failed (${response.status})`,
|
|
9822
9850
|
response.status,
|
|
9823
9851
|
record(body) && typeof body.code === "string" ? body.code : void 0,
|
|
9824
|
-
retryAfter ?? void 0
|
|
9852
|
+
retryAfter ?? void 0,
|
|
9853
|
+
record(body) && typeof body.rate_limit_bucket === "string" ? body.rate_limit_bucket : void 0
|
|
9825
9854
|
);
|
|
9855
|
+
if (response.status === 429 && retryAfter !== null && retryAfter > 0 && (!error.code || error.code === "rate_limited")) {
|
|
9856
|
+
const bucket = error.rateLimitBucket && budgets.includes(error.rateLimitBucket) ? error.rateLimitBucket : record(body) && (body.limit_scope === "account" || body.limit_scope === "ip") && !error.rateLimitBucket ? "*" : route;
|
|
9857
|
+
cooldowns.set(bucket, { until: Date.now() + retryAfter, error });
|
|
9858
|
+
}
|
|
9859
|
+
throw error;
|
|
9826
9860
|
}
|
|
9827
9861
|
return await response.json();
|
|
9828
9862
|
} catch (error) {
|
|
@@ -10062,6 +10096,7 @@ async function createRemoteMemoryPersistence(options) {
|
|
|
10062
10096
|
return {
|
|
10063
10097
|
...createRemoteTopicPersistence(request),
|
|
10064
10098
|
...createRemoteWorkPersistence(request),
|
|
10099
|
+
supportsRealtimeChanges: account.realtime_changes === true,
|
|
10065
10100
|
counts: async () => {
|
|
10066
10101
|
const result = await request("/counts", {});
|
|
10067
10102
|
if (!record(result) || ["live", "archived", "quarantined"].some(
|
|
@@ -13156,9 +13191,10 @@ async function getVaultRankingProjectionsOp(ctx, options) {
|
|
|
13156
13191
|
}
|
|
13157
13192
|
function baseVaultSql(ctx, options) {
|
|
13158
13193
|
const clauses = [
|
|
13194
|
+
`"_status" is not 'deleted'`,
|
|
13159
13195
|
'"is_deleted" = 0',
|
|
13160
13196
|
...options?.includeArchived ? [] : ['"archived_at" is null'],
|
|
13161
|
-
`"trust_tier" is not 'quarantined'
|
|
13197
|
+
...options?.includeQuarantined ? [] : [`"trust_tier" is not 'quarantined'`],
|
|
13162
13198
|
'"superseded_by" is null'
|
|
13163
13199
|
];
|
|
13164
13200
|
const args = [];
|
|
@@ -13644,8 +13680,17 @@ async function getMemoriesNeedingTopicExtractionOp(ctx, options) {
|
|
|
13644
13680
|
if (!entityCtx) {
|
|
13645
13681
|
throw new Error("getMemoriesNeedingTopicExtractionOp requires ctx.entityCtx");
|
|
13646
13682
|
}
|
|
13647
|
-
|
|
13648
|
-
|
|
13683
|
+
let rows;
|
|
13684
|
+
try {
|
|
13685
|
+
const base = baseVaultSql(ctx);
|
|
13686
|
+
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`;
|
|
13687
|
+
rows = await ctx.vaultMemoryCollection.query(Q6.unsafeSqlQuery(sql, base.args)).unsafeFetchRaw();
|
|
13688
|
+
} catch (err) {
|
|
13689
|
+
getLogger().debug(
|
|
13690
|
+
"memoryVault: topic sweep SQL unavailable; use the adapter query: " + (err instanceof Error ? err.message : String(err))
|
|
13691
|
+
);
|
|
13692
|
+
rows = await ctx.vaultMemoryCollection.query(...baseVaultConditions(ctx), Q6.sortBy("created_at", Q6.desc)).unsafeFetchRaw();
|
|
13693
|
+
}
|
|
13649
13694
|
const linkedNames = await linkedEntityNamesByMemory(
|
|
13650
13695
|
entityCtx,
|
|
13651
13696
|
rows.map((r) => r.id)
|
|
@@ -13704,10 +13749,19 @@ async function getMemoriesNeedingTopicExtractionOp(ctx, options) {
|
|
|
13704
13749
|
}
|
|
13705
13750
|
const orderedPendingRaw = [...stampedPendingRaw, ...pendingRaw];
|
|
13706
13751
|
const limitedPendingRaw = cap !== void 0 ? orderedPendingRaw.slice(0, cap) : orderedPendingRaw;
|
|
13707
|
-
const pending =
|
|
13708
|
-
|
|
13709
|
-
|
|
13710
|
-
|
|
13752
|
+
const pending = [];
|
|
13753
|
+
for (let i = 0; i < limitedPendingRaw.length; i += 500) {
|
|
13754
|
+
const chunk = limitedPendingRaw.slice(i, i + 500);
|
|
13755
|
+
const memories = await getVaultMemoriesByIdsOp(
|
|
13756
|
+
ctx,
|
|
13757
|
+
chunk.map((raw) => raw.id)
|
|
13758
|
+
);
|
|
13759
|
+
const byId = new Map(memories.map((memory) => [memory.uniqueId, memory]));
|
|
13760
|
+
for (const raw of chunk) {
|
|
13761
|
+
const memory = byId.get(raw.id);
|
|
13762
|
+
if (memory) pending.push(memory);
|
|
13763
|
+
}
|
|
13764
|
+
}
|
|
13711
13765
|
const applyCap = (ids) => cap !== void 0 ? ids.slice(0, cap) : ids;
|
|
13712
13766
|
return {
|
|
13713
13767
|
pending,
|
|
@@ -13854,10 +13908,20 @@ function assertVaultScopeForSweep(ctx) {
|
|
|
13854
13908
|
}
|
|
13855
13909
|
async function getDecayCandidatesRawOp(ctx) {
|
|
13856
13910
|
assertVaultScopeForSweep(ctx);
|
|
13857
|
-
|
|
13858
|
-
|
|
13859
|
-
|
|
13860
|
-
|
|
13911
|
+
let results;
|
|
13912
|
+
try {
|
|
13913
|
+
const base = baseVaultSql(ctx, { includeArchived: true, includeQuarantined: true });
|
|
13914
|
+
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`;
|
|
13915
|
+
results = await ctx.vaultMemoryCollection.query(Q6.unsafeSqlQuery(sql, base.args)).unsafeFetchRaw();
|
|
13916
|
+
} catch (err) {
|
|
13917
|
+
getLogger().debug(
|
|
13918
|
+
"memoryVault: decay sweep SQL unavailable; use the adapter query: " + (err instanceof Error ? err.message : String(err))
|
|
13919
|
+
);
|
|
13920
|
+
results = await ctx.vaultMemoryCollection.query(
|
|
13921
|
+
...baseVaultConditions(ctx, { includeArchived: true, includeQuarantined: true }),
|
|
13922
|
+
Q6.where("kind", null)
|
|
13923
|
+
).unsafeFetchRaw();
|
|
13924
|
+
}
|
|
13861
13925
|
return results.map((raw) => ({
|
|
13862
13926
|
uniqueId: raw.id,
|
|
13863
13927
|
factType: raw.fact_type ?? null,
|
|
@@ -21345,6 +21409,9 @@ var RemoteMemoryPartialCreateError = class extends Error {
|
|
|
21345
21409
|
function rejectsInput(error) {
|
|
21346
21410
|
return error instanceof EmbeddingHttpError && error.status !== void 0 && error.status >= 400 && error.status < 500 && error.status !== 429 && !isFatalEmbeddingError(error);
|
|
21347
21411
|
}
|
|
21412
|
+
function rejectsMemoryWrite(error) {
|
|
21413
|
+
return error instanceof RemoteMemoryError && (error.status === 400 || error.status === 422) && (error.code === void 0 || error.code === "unknown_field");
|
|
21414
|
+
}
|
|
21348
21415
|
function warnFailed(failed) {
|
|
21349
21416
|
if (failed.length)
|
|
21350
21417
|
getLogger().warn(
|
|
@@ -21432,16 +21499,47 @@ function createRemoteMemoryStore(options) {
|
|
|
21432
21499
|
const { persistence, embeddingOptions } = options;
|
|
21433
21500
|
const model = embeddingOptions.model ?? DEFAULT_API_EMBEDDING_MODEL;
|
|
21434
21501
|
const pollIntervalMs = options.pollIntervalMs ?? 6e4;
|
|
21502
|
+
const activity = options.activity ?? {
|
|
21503
|
+
isActive: () => (typeof document === "undefined" || document.visibilityState !== "hidden") && (typeof navigator === "undefined" || navigator.onLine !== false),
|
|
21504
|
+
subscribe: (onChange) => {
|
|
21505
|
+
if (typeof window === "undefined" || typeof document === "undefined") return () => {
|
|
21506
|
+
};
|
|
21507
|
+
document.addEventListener("visibilitychange", onChange);
|
|
21508
|
+
window.addEventListener("online", onChange);
|
|
21509
|
+
window.addEventListener("offline", onChange);
|
|
21510
|
+
return () => {
|
|
21511
|
+
document.removeEventListener("visibilitychange", onChange);
|
|
21512
|
+
window.removeEventListener("online", onChange);
|
|
21513
|
+
window.removeEventListener("offline", onChange);
|
|
21514
|
+
};
|
|
21515
|
+
}
|
|
21516
|
+
};
|
|
21435
21517
|
const pipeline = createRemoteMemoryPipeline({
|
|
21436
21518
|
...options,
|
|
21437
21519
|
graphRanking: options.graphRanking ?? ((query, _traverse, recallOptions) => topicGraphRanking(query, recallOptions)),
|
|
21438
21520
|
temporalRanking: options.temporalRanking ?? ((query, now) => eventTimeRanking(query, now))
|
|
21439
21521
|
});
|
|
21440
21522
|
const subscribers = /* @__PURE__ */ new Set();
|
|
21523
|
+
const retainTopics = () => pollIntervalMs > 0 && [...subscribers].some((subscriber) => subscriber.options.topics);
|
|
21441
21524
|
const seen = /* @__PURE__ */ new Map();
|
|
21525
|
+
const reads = /* @__PURE__ */ new Map();
|
|
21526
|
+
const metadataReads = /* @__PURE__ */ new Map();
|
|
21527
|
+
let topicSnapshot;
|
|
21528
|
+
let topicCatalog;
|
|
21529
|
+
const invalidateReads = () => {
|
|
21530
|
+
reads.clear();
|
|
21531
|
+
metadataReads.clear();
|
|
21532
|
+
topicSnapshot = void 0;
|
|
21533
|
+
topicCatalog = void 0;
|
|
21534
|
+
};
|
|
21442
21535
|
let timer;
|
|
21536
|
+
let scheduledAt;
|
|
21537
|
+
let stopActivity;
|
|
21538
|
+
let stopChanges;
|
|
21539
|
+
let changesConnected = false;
|
|
21443
21540
|
const notify = (change, records = []) => {
|
|
21444
|
-
|
|
21541
|
+
invalidateReads();
|
|
21542
|
+
if (subscribers.size)
|
|
21445
21543
|
for (const record2 of records) {
|
|
21446
21544
|
const previous = seen.get(record2.memory.memory_id);
|
|
21447
21545
|
if ((previous?.version ?? 0) + 1 === record2.version)
|
|
@@ -21465,8 +21563,37 @@ function createRemoteMemoryStore(options) {
|
|
|
21465
21563
|
} while (cursor2 && records.length < max);
|
|
21466
21564
|
return records.slice(0, max);
|
|
21467
21565
|
};
|
|
21468
|
-
const
|
|
21469
|
-
|
|
21566
|
+
const shareRead = (inflight, options2, read) => {
|
|
21567
|
+
if (options2.signal) return read();
|
|
21568
|
+
const key = JSON.stringify(Object.entries(options2).sort(([a], [b]) => a.localeCompare(b)));
|
|
21569
|
+
const active = inflight.get(key);
|
|
21570
|
+
if (active) return active;
|
|
21571
|
+
const pending2 = read();
|
|
21572
|
+
inflight.set(key, pending2);
|
|
21573
|
+
const clear = () => {
|
|
21574
|
+
if (inflight.get(key) === pending2) inflight.delete(key);
|
|
21575
|
+
};
|
|
21576
|
+
void pending2.then(clear, clear);
|
|
21577
|
+
return pending2;
|
|
21578
|
+
};
|
|
21579
|
+
const decrypted = (options2) => shareRead(reads, options2, () => persistence.query(options2));
|
|
21580
|
+
const metadata3 = (options2) => shareRead(
|
|
21581
|
+
metadataReads,
|
|
21582
|
+
options2,
|
|
21583
|
+
() => persistence.queryMetadata(options2)
|
|
21584
|
+
);
|
|
21585
|
+
const readTopics = () => {
|
|
21586
|
+
if (topicCatalog) return topicCatalog;
|
|
21587
|
+
const pending2 = persistence.topics();
|
|
21588
|
+
topicCatalog = pending2;
|
|
21589
|
+
const clear = () => {
|
|
21590
|
+
if (topicCatalog === pending2) topicCatalog = void 0;
|
|
21591
|
+
};
|
|
21592
|
+
void pending2.then(() => {
|
|
21593
|
+
if (!retainTopics()) clear();
|
|
21594
|
+
}, clear);
|
|
21595
|
+
return pending2;
|
|
21596
|
+
};
|
|
21470
21597
|
const enumerate = (filters, max = Infinity) => pages(decrypted, filters, max);
|
|
21471
21598
|
const memoriesByTopics = async (names) => {
|
|
21472
21599
|
const wanted = new Set(names.map(normalizeEntityName).filter(Boolean));
|
|
@@ -21920,11 +22047,11 @@ function createRemoteMemoryStore(options) {
|
|
|
21920
22047
|
};
|
|
21921
22048
|
const changesSince = async (cursor2, pending2) => {
|
|
21922
22049
|
const records = [];
|
|
21923
|
-
const failed = /* @__PURE__ */ new
|
|
22050
|
+
const failed = /* @__PURE__ */ new Map();
|
|
21924
22051
|
const collect = (page) => {
|
|
21925
22052
|
warnFailed(page.failed);
|
|
21926
22053
|
records.push(...page.items);
|
|
21927
|
-
for (const failure of page.failed) failed.
|
|
22054
|
+
for (const failure of page.failed) failed.set(failure.memory_id, failure.version);
|
|
21928
22055
|
};
|
|
21929
22056
|
let resume = cursor2;
|
|
21930
22057
|
let next;
|
|
@@ -21958,25 +22085,72 @@ function createRemoteMemoryStore(options) {
|
|
|
21958
22085
|
let ready = false;
|
|
21959
22086
|
let cursor;
|
|
21960
22087
|
let pending = /* @__PURE__ */ new Set();
|
|
22088
|
+
let failedVersions = /* @__PURE__ */ new Map();
|
|
21961
22089
|
let topicFingerprint;
|
|
21962
22090
|
let polling = false;
|
|
22091
|
+
let pollRequested = false;
|
|
22092
|
+
let failures = 0;
|
|
22093
|
+
let retryAt = 0;
|
|
22094
|
+
const backoff = (error) => {
|
|
22095
|
+
failures++;
|
|
22096
|
+
retryAt = Date.now() + Math.max(
|
|
22097
|
+
error instanceof RemoteMemoryError ? error.retryAfterMs ?? 0 : 0,
|
|
22098
|
+
Math.min(pollIntervalMs * 2 ** Math.min(failures - 1, 10), 15 * 6e4)
|
|
22099
|
+
);
|
|
22100
|
+
};
|
|
22101
|
+
const schedulePoll = (delay, keepEarlier = false) => {
|
|
22102
|
+
const at = Math.max(Date.now() + delay, retryAt);
|
|
22103
|
+
if (keepEarlier && timer && scheduledAt !== void 0 && scheduledAt <= at) return;
|
|
22104
|
+
if (timer) clearTimeout(timer);
|
|
22105
|
+
timer = void 0;
|
|
22106
|
+
scheduledAt = void 0;
|
|
22107
|
+
if (!subscribers.size || pollIntervalMs <= 0 || !activity.isActive()) return;
|
|
22108
|
+
scheduledAt = at;
|
|
22109
|
+
timer = setTimeout(poll, Math.max(0, at - Date.now()));
|
|
22110
|
+
};
|
|
21963
22111
|
const poll = () => {
|
|
21964
|
-
if (
|
|
22112
|
+
if (timer) clearTimeout(timer);
|
|
22113
|
+
timer = void 0;
|
|
22114
|
+
scheduledAt = void 0;
|
|
22115
|
+
if (!subscribers.size || pollIntervalMs <= 0 || !activity.isActive()) return;
|
|
22116
|
+
if (Date.now() < retryAt) {
|
|
22117
|
+
schedulePoll(0);
|
|
22118
|
+
return;
|
|
22119
|
+
}
|
|
22120
|
+
if (polling) {
|
|
22121
|
+
pollRequested = true;
|
|
22122
|
+
return;
|
|
22123
|
+
}
|
|
21965
22124
|
polling = true;
|
|
22125
|
+
pollRequested = false;
|
|
21966
22126
|
const current = generation;
|
|
21967
22127
|
changesSince(cursor, pending).then(async ({ records, resume, failed }) => {
|
|
21968
22128
|
let topicState;
|
|
22129
|
+
let topicFailed = false;
|
|
21969
22130
|
if ([...subscribers].some((s) => s.options.topics))
|
|
21970
22131
|
try {
|
|
21971
|
-
|
|
21972
|
-
|
|
21973
|
-
);
|
|
22132
|
+
topicCatalog = void 0;
|
|
22133
|
+
topicState = JSON.stringify((await readTopics()).map((t) => [t.name, t.version]));
|
|
21974
22134
|
} catch (error) {
|
|
22135
|
+
topicFailed = true;
|
|
22136
|
+
if (current === generation) backoff(error);
|
|
21975
22137
|
getLogger().warn("[memory/remote-store] Topic subscription poll failed:", error);
|
|
21976
22138
|
}
|
|
21977
22139
|
if (current !== generation) return;
|
|
22140
|
+
if (!topicFailed) {
|
|
22141
|
+
failures = 0;
|
|
22142
|
+
retryAt = 0;
|
|
22143
|
+
}
|
|
22144
|
+
const failedChanged = [...failed].some(
|
|
22145
|
+
([id2, version]) => failedVersions.get(id2) !== version
|
|
22146
|
+
);
|
|
22147
|
+
if (records.length || failedChanged || topicState !== void 0 && topicState !== topicFingerprint) {
|
|
22148
|
+
reads.clear();
|
|
22149
|
+
metadataReads.clear();
|
|
22150
|
+
topicSnapshot = void 0;
|
|
22151
|
+
}
|
|
21978
22152
|
const changed = /* @__PURE__ */ new Set();
|
|
21979
|
-
if (topicState !== void 0 && topicFingerprint !== void 0 && topicState !== topicFingerprint) {
|
|
22153
|
+
if (ready && failedChanged || topicState !== void 0 && topicFingerprint !== void 0 && topicState !== topicFingerprint) {
|
|
21980
22154
|
for (const subscriber of subscribers)
|
|
21981
22155
|
if (subscriber.options.topics) changed.add(subscriber);
|
|
21982
22156
|
}
|
|
@@ -21993,15 +22167,40 @@ function createRemoteMemoryStore(options) {
|
|
|
21993
22167
|
}
|
|
21994
22168
|
ready = true;
|
|
21995
22169
|
cursor = resume;
|
|
21996
|
-
pending = failed;
|
|
22170
|
+
pending = new Set(failed.keys());
|
|
22171
|
+
failedVersions = failed;
|
|
21997
22172
|
for (const subscriber of changed)
|
|
21998
22173
|
if (subscribers.has(subscriber)) safely(subscriber.onChange);
|
|
21999
22174
|
}).catch((error) => {
|
|
22175
|
+
if (current === generation) backoff(error);
|
|
22000
22176
|
getLogger().warn("[memory/remote-store] Subscription poll failed:", error);
|
|
22001
22177
|
}).finally(() => {
|
|
22002
22178
|
polling = false;
|
|
22179
|
+
schedulePoll(
|
|
22180
|
+
current !== generation ? 0 : pollRequested ? 200 : changesConnected ? Math.max(pollIntervalMs, 5 * 6e4) : pollIntervalMs
|
|
22181
|
+
);
|
|
22003
22182
|
});
|
|
22004
22183
|
};
|
|
22184
|
+
const refreshActivity = () => {
|
|
22185
|
+
if (timer) clearTimeout(timer);
|
|
22186
|
+
timer = void 0;
|
|
22187
|
+
if (!activity.isActive()) {
|
|
22188
|
+
stopChanges?.();
|
|
22189
|
+
stopChanges = void 0;
|
|
22190
|
+
changesConnected = false;
|
|
22191
|
+
return;
|
|
22192
|
+
}
|
|
22193
|
+
if (!stopChanges && persistence.supportsRealtimeChanges && options.subscribeChanges)
|
|
22194
|
+
stopChanges = options.subscribeChanges((connected) => {
|
|
22195
|
+
changesConnected = connected;
|
|
22196
|
+
if (polling) {
|
|
22197
|
+
pollRequested = true;
|
|
22198
|
+
return;
|
|
22199
|
+
}
|
|
22200
|
+
schedulePoll(connected ? 200 : 0, true);
|
|
22201
|
+
});
|
|
22202
|
+
poll();
|
|
22203
|
+
};
|
|
22005
22204
|
const unrepairable = /* @__PURE__ */ new Set();
|
|
22006
22205
|
let repairCursor;
|
|
22007
22206
|
const repairEmbeddingsUnlocked = async ({
|
|
@@ -22057,40 +22256,78 @@ function createRemoteMemoryStore(options) {
|
|
|
22057
22256
|
result.failed += targets.length;
|
|
22058
22257
|
return finish();
|
|
22059
22258
|
}
|
|
22060
|
-
|
|
22259
|
+
const writes = targets.flatMap((record2, i) => {
|
|
22061
22260
|
const vector = vectors[i];
|
|
22062
22261
|
if (!vector) {
|
|
22063
22262
|
result.failed++;
|
|
22064
|
-
|
|
22263
|
+
return [];
|
|
22065
22264
|
}
|
|
22066
|
-
|
|
22067
|
-
|
|
22068
|
-
|
|
22069
|
-
|
|
22070
|
-
|
|
22071
|
-
|
|
22072
|
-
|
|
22073
|
-
|
|
22074
|
-
|
|
22075
|
-
|
|
22076
|
-
|
|
22077
|
-
|
|
22078
|
-
|
|
22079
|
-
|
|
22080
|
-
|
|
22081
|
-
|
|
22082
|
-
|
|
22083
|
-
|
|
22084
|
-
|
|
22085
|
-
|
|
22086
|
-
} catch (error) {
|
|
22265
|
+
try {
|
|
22266
|
+
return [
|
|
22267
|
+
{
|
|
22268
|
+
memory: {
|
|
22269
|
+
...record2.memory,
|
|
22270
|
+
embedding: storedVector(vector),
|
|
22271
|
+
embedding_model: model
|
|
22272
|
+
},
|
|
22273
|
+
expectedVersion: record2
|
|
22274
|
+
}
|
|
22275
|
+
];
|
|
22276
|
+
} catch {
|
|
22277
|
+
result.failed++;
|
|
22278
|
+
return [];
|
|
22279
|
+
}
|
|
22280
|
+
});
|
|
22281
|
+
for (const batch of chunks2(writes, MAX_BATCH)) {
|
|
22282
|
+
const continueRepair = await serializedAll(
|
|
22283
|
+
batch.map(({ memory }) => memory.memory_id),
|
|
22284
|
+
async () => {
|
|
22087
22285
|
signal?.throwIfAborted();
|
|
22088
|
-
|
|
22089
|
-
|
|
22090
|
-
|
|
22091
|
-
|
|
22286
|
+
const commit = async (slice) => {
|
|
22287
|
+
const saved = await persistence.putMany(slice, signal, leaseToken);
|
|
22288
|
+
for (const record2 of saved) repaired.add(record2.memory.memory_id);
|
|
22289
|
+
result.reembedded += saved.length;
|
|
22290
|
+
notify("embedding", saved);
|
|
22291
|
+
};
|
|
22292
|
+
try {
|
|
22293
|
+
await commit(batch);
|
|
22294
|
+
} catch (error) {
|
|
22295
|
+
signal?.throwIfAborted();
|
|
22296
|
+
if (isRemoteWorkLeaseExpired(error)) throw error;
|
|
22297
|
+
if (!(error instanceof RemoteMemoryError && error.code === "version_conflict") && !rejectsMemoryWrite(error)) {
|
|
22298
|
+
result.failed += batch.length;
|
|
22299
|
+
return false;
|
|
22300
|
+
}
|
|
22301
|
+
if (batch.length === 1) {
|
|
22302
|
+
if (rejectsMemoryWrite(error)) {
|
|
22303
|
+
unrepairable.add(batch[0].memory.memory_id);
|
|
22304
|
+
result.failed++;
|
|
22305
|
+
} else result.skippedConflict++;
|
|
22306
|
+
return true;
|
|
22307
|
+
}
|
|
22308
|
+
for (const [index, write] of batch.entries()) {
|
|
22309
|
+
signal?.throwIfAborted();
|
|
22310
|
+
try {
|
|
22311
|
+
await commit([write]);
|
|
22312
|
+
} catch (error2) {
|
|
22313
|
+
signal?.throwIfAborted();
|
|
22314
|
+
if (isRemoteWorkLeaseExpired(error2)) throw error2;
|
|
22315
|
+
if (error2 instanceof RemoteMemoryError && error2.code === "version_conflict")
|
|
22316
|
+
result.skippedConflict++;
|
|
22317
|
+
else if (rejectsMemoryWrite(error2)) {
|
|
22318
|
+
unrepairable.add(write.memory.memory_id);
|
|
22319
|
+
result.failed++;
|
|
22320
|
+
} else {
|
|
22321
|
+
result.failed += batch.length - index;
|
|
22322
|
+
return false;
|
|
22323
|
+
}
|
|
22324
|
+
}
|
|
22325
|
+
}
|
|
22326
|
+
}
|
|
22327
|
+
return true;
|
|
22092
22328
|
}
|
|
22093
|
-
|
|
22329
|
+
);
|
|
22330
|
+
if (!continueRepair) break;
|
|
22094
22331
|
}
|
|
22095
22332
|
return finish();
|
|
22096
22333
|
};
|
|
@@ -22130,7 +22367,7 @@ function createRemoteMemoryStore(options) {
|
|
|
22130
22367
|
},
|
|
22131
22368
|
importTopics: async (topics) => {
|
|
22132
22369
|
if (!topics.length) return;
|
|
22133
|
-
const existing = new Set((await
|
|
22370
|
+
const existing = new Set((await readTopics()).map((topic2) => topic2.name));
|
|
22134
22371
|
const missing = topics.flatMap((topic2) => {
|
|
22135
22372
|
const name = normalizeEntityName(topic2.name);
|
|
22136
22373
|
if (existing.has(name)) return [];
|
|
@@ -22139,6 +22376,7 @@ function createRemoteMemoryStore(options) {
|
|
|
22139
22376
|
});
|
|
22140
22377
|
if (!missing.length) return;
|
|
22141
22378
|
await persistence.importTopics(missing);
|
|
22379
|
+
invalidateReads();
|
|
22142
22380
|
for (const subscriber of [...subscribers])
|
|
22143
22381
|
if (subscriber.options.topics) safely(subscriber.onChange);
|
|
22144
22382
|
},
|
|
@@ -22152,40 +22390,51 @@ function createRemoteMemoryStore(options) {
|
|
|
22152
22390
|
listProjections: async (listOptions = {}) => (await listRows(metadata3, listOptions, listFilters(listOptions), maxOf(listOptions))).map(
|
|
22153
22391
|
projection
|
|
22154
22392
|
),
|
|
22155
|
-
listTopics:
|
|
22156
|
-
|
|
22157
|
-
|
|
22158
|
-
|
|
22159
|
-
|
|
22160
|
-
|
|
22161
|
-
|
|
22162
|
-
|
|
22163
|
-
|
|
22164
|
-
|
|
22165
|
-
|
|
22166
|
-
name
|
|
22167
|
-
|
|
22168
|
-
|
|
22169
|
-
|
|
22170
|
-
|
|
22171
|
-
|
|
22172
|
-
|
|
22173
|
-
|
|
22393
|
+
listTopics: () => {
|
|
22394
|
+
if (topicSnapshot) return topicSnapshot.then((topics) => structuredClone(topics));
|
|
22395
|
+
const snapshot = (async () => {
|
|
22396
|
+
const topics = /* @__PURE__ */ new Map();
|
|
22397
|
+
for (const { memory } of await pages(metadata3, {
|
|
22398
|
+
include_archived: true,
|
|
22399
|
+
include_quarantined: true,
|
|
22400
|
+
include_superseded: true
|
|
22401
|
+
})) {
|
|
22402
|
+
for (const topic2 of parseTopics(memory.topics) ?? []) {
|
|
22403
|
+
const name = normalizeEntityName(topic2.name);
|
|
22404
|
+
if (!name) continue;
|
|
22405
|
+
const entry = topics.get(name) ?? {
|
|
22406
|
+
name,
|
|
22407
|
+
kind: null,
|
|
22408
|
+
memoryCount: 0,
|
|
22409
|
+
members: /* @__PURE__ */ new Set()
|
|
22410
|
+
};
|
|
22411
|
+
entry.kind ?? (entry.kind = topic2.kind ?? null);
|
|
22412
|
+
entry.members.add(memory.memory_id);
|
|
22413
|
+
topics.set(name, entry);
|
|
22414
|
+
}
|
|
22174
22415
|
}
|
|
22175
|
-
|
|
22176
|
-
|
|
22177
|
-
|
|
22178
|
-
|
|
22179
|
-
|
|
22180
|
-
|
|
22181
|
-
|
|
22182
|
-
|
|
22183
|
-
|
|
22184
|
-
|
|
22185
|
-
|
|
22186
|
-
|
|
22187
|
-
|
|
22188
|
-
|
|
22416
|
+
for (const topic2 of await readTopics()) {
|
|
22417
|
+
if (topic2.is_deleted) continue;
|
|
22418
|
+
const current = topics.get(topic2.name);
|
|
22419
|
+
if (current) current.kind ?? (current.kind = topic2.kind ?? null);
|
|
22420
|
+
else
|
|
22421
|
+
topics.set(topic2.name, {
|
|
22422
|
+
name: topic2.name,
|
|
22423
|
+
kind: topic2.kind ?? null,
|
|
22424
|
+
memoryCount: 0,
|
|
22425
|
+
members: /* @__PURE__ */ new Set()
|
|
22426
|
+
});
|
|
22427
|
+
}
|
|
22428
|
+
return [...topics.values()].map(({ members, ...topic2 }) => ({ ...topic2, memoryCount: members.size })).sort((a, b) => a.name.localeCompare(b.name));
|
|
22429
|
+
})();
|
|
22430
|
+
topicSnapshot = snapshot;
|
|
22431
|
+
const clear = () => {
|
|
22432
|
+
if (topicSnapshot === snapshot) topicSnapshot = void 0;
|
|
22433
|
+
};
|
|
22434
|
+
void snapshot.then(() => {
|
|
22435
|
+
if (!retainTopics()) clear();
|
|
22436
|
+
}, clear);
|
|
22437
|
+
return snapshot.then((topics) => structuredClone(topics));
|
|
22189
22438
|
},
|
|
22190
22439
|
get: async (id2) => asStored(await live(id2)),
|
|
22191
22440
|
listArchived: async () => (await enumerate({ archived_only: true, order: "archived", include_embeddings: true })).map(
|
|
@@ -22366,20 +22615,23 @@ function createRemoteMemoryStore(options) {
|
|
|
22366
22615
|
subscribe: (onChange, subscribeOptions = {}) => {
|
|
22367
22616
|
const subscriber = { onChange, options: subscribeOptions };
|
|
22368
22617
|
subscribers.add(subscriber);
|
|
22369
|
-
if (pollIntervalMs > 0 &&
|
|
22370
|
-
|
|
22371
|
-
|
|
22618
|
+
if (pollIntervalMs > 0 && subscribers.size === 1) {
|
|
22619
|
+
stopActivity = activity.subscribe(refreshActivity);
|
|
22620
|
+
refreshActivity();
|
|
22372
22621
|
}
|
|
22373
22622
|
return () => {
|
|
22374
22623
|
subscribers.delete(subscriber);
|
|
22375
|
-
if (
|
|
22376
|
-
|
|
22624
|
+
if (!retainTopics()) invalidateReads();
|
|
22625
|
+
if (subscribers.size) return;
|
|
22626
|
+
if (timer) clearTimeout(timer);
|
|
22377
22627
|
timer = void 0;
|
|
22628
|
+
stopActivity?.();
|
|
22629
|
+
stopActivity = void 0;
|
|
22630
|
+
stopChanges?.();
|
|
22631
|
+
stopChanges = void 0;
|
|
22632
|
+
changesConnected = false;
|
|
22378
22633
|
generation++;
|
|
22379
|
-
|
|
22380
|
-
ready = false;
|
|
22381
|
-
cursor = void 0;
|
|
22382
|
-
pending = /* @__PURE__ */ new Set();
|
|
22634
|
+
invalidateReads();
|
|
22383
22635
|
};
|
|
22384
22636
|
}
|
|
22385
22637
|
};
|