@anuma/sdk 9.1.3 → 9.1.5
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 +221 -121
- package/dist/expo/index.d.mts +13 -0
- package/dist/expo/index.d.ts +13 -0
- package/dist/expo/index.mjs +221 -121
- package/dist/memory/context.d.mts +123 -0
- package/dist/memory/context.d.ts +123 -0
- package/dist/react/index.cjs +221 -121
- package/dist/react/index.d.mts +13 -0
- package/dist/react/index.d.ts +13 -0
- package/dist/react/index.mjs +221 -121
- package/dist/server/index.cjs +132 -39
- package/dist/server/index.d.mts +9 -0
- package/dist/server/index.d.ts +9 -0
- package/dist/server/index.mjs +132 -39
- package/package.json +1 -1
package/dist/react/index.d.mts
CHANGED
|
@@ -4402,6 +4402,13 @@ interface RecencyOptions {
|
|
|
4402
4402
|
noDateMultiplier?: number;
|
|
4403
4403
|
}
|
|
4404
4404
|
|
|
4405
|
+
type VaultCorpusCache = WeakMap<VaultMemoryOperationsContext, Map<string, Promise<StoredVaultMemory[]>>>;
|
|
4406
|
+
type RowRequests = Map<EmbeddingOptions["maskInput"], Map<string, Promise<number[]>>>;
|
|
4407
|
+
interface VaultPreparation {
|
|
4408
|
+
corpora: VaultCorpusCache;
|
|
4409
|
+
rows: WeakMap<VaultMemoryOperationsContext, RowRequests>;
|
|
4410
|
+
}
|
|
4411
|
+
|
|
4405
4412
|
declare const DEFAULT_VAULT_CACHE_SIZE = 5000;
|
|
4406
4413
|
/**
|
|
4407
4414
|
* Create a VaultEmbeddingCache backed by an LRU with a default cap of
|
|
@@ -4419,6 +4426,7 @@ type VaultEmbeddingCache = Map<string, Float32Array>;
|
|
|
4419
4426
|
* Options for the vault search tool.
|
|
4420
4427
|
*/
|
|
4421
4428
|
interface MemoryVaultSearchOptions {
|
|
4429
|
+
/** @internal */ vaultPreparation?: VaultPreparation;
|
|
4422
4430
|
onCandidateCount?: (count: number) => void;
|
|
4423
4431
|
/** Maximum number of results to return (default: 5) */
|
|
4424
4432
|
limit?: number;
|
|
@@ -4957,6 +4965,7 @@ interface RankedMemory {
|
|
|
4957
4965
|
updatedAt: Date;
|
|
4958
4966
|
}
|
|
4959
4967
|
interface RecallOptions {
|
|
4968
|
+
/** @internal */ vaultPreparation?: VaultPreparation;
|
|
4960
4969
|
/** Embedding cache shared with the rest of the turn, so the query is embedded once across lanes and the send. */
|
|
4961
4970
|
embeddingCache?: Map<string, Float32Array>;
|
|
4962
4971
|
/** Which kinds to search. Default: ['fact']. */
|
|
@@ -11665,6 +11674,10 @@ interface MemoryMigrationOptions extends Pick<RemoteMemoryPersistenceOptions, "b
|
|
|
11665
11674
|
name: string;
|
|
11666
11675
|
kind?: string;
|
|
11667
11676
|
}[];
|
|
11677
|
+
/** Drain all local memory writes, block new writes until the task returns, and retain the block if the remote handoff fails. */
|
|
11678
|
+
withWriteBarrier: (task: () => Promise<MemoryMigrationResult>) => Promise<MemoryMigrationResult>;
|
|
11679
|
+
/** Route all subsequent memory writes to the remote store before this callback returns. */
|
|
11680
|
+
onActivated: () => void | Promise<void>;
|
|
11668
11681
|
signal?: AbortSignal;
|
|
11669
11682
|
onProgress?: (progress: MemoryMigrationProgress) => void;
|
|
11670
11683
|
}
|
package/dist/react/index.d.ts
CHANGED
|
@@ -4402,6 +4402,13 @@ interface RecencyOptions {
|
|
|
4402
4402
|
noDateMultiplier?: number;
|
|
4403
4403
|
}
|
|
4404
4404
|
|
|
4405
|
+
type VaultCorpusCache = WeakMap<VaultMemoryOperationsContext, Map<string, Promise<StoredVaultMemory[]>>>;
|
|
4406
|
+
type RowRequests = Map<EmbeddingOptions["maskInput"], Map<string, Promise<number[]>>>;
|
|
4407
|
+
interface VaultPreparation {
|
|
4408
|
+
corpora: VaultCorpusCache;
|
|
4409
|
+
rows: WeakMap<VaultMemoryOperationsContext, RowRequests>;
|
|
4410
|
+
}
|
|
4411
|
+
|
|
4405
4412
|
declare const DEFAULT_VAULT_CACHE_SIZE = 5000;
|
|
4406
4413
|
/**
|
|
4407
4414
|
* Create a VaultEmbeddingCache backed by an LRU with a default cap of
|
|
@@ -4419,6 +4426,7 @@ type VaultEmbeddingCache = Map<string, Float32Array>;
|
|
|
4419
4426
|
* Options for the vault search tool.
|
|
4420
4427
|
*/
|
|
4421
4428
|
interface MemoryVaultSearchOptions {
|
|
4429
|
+
/** @internal */ vaultPreparation?: VaultPreparation;
|
|
4422
4430
|
onCandidateCount?: (count: number) => void;
|
|
4423
4431
|
/** Maximum number of results to return (default: 5) */
|
|
4424
4432
|
limit?: number;
|
|
@@ -4957,6 +4965,7 @@ interface RankedMemory {
|
|
|
4957
4965
|
updatedAt: Date;
|
|
4958
4966
|
}
|
|
4959
4967
|
interface RecallOptions {
|
|
4968
|
+
/** @internal */ vaultPreparation?: VaultPreparation;
|
|
4960
4969
|
/** Embedding cache shared with the rest of the turn, so the query is embedded once across lanes and the send. */
|
|
4961
4970
|
embeddingCache?: Map<string, Float32Array>;
|
|
4962
4971
|
/** Which kinds to search. Default: ['fact']. */
|
|
@@ -11665,6 +11674,10 @@ interface MemoryMigrationOptions extends Pick<RemoteMemoryPersistenceOptions, "b
|
|
|
11665
11674
|
name: string;
|
|
11666
11675
|
kind?: string;
|
|
11667
11676
|
}[];
|
|
11677
|
+
/** Drain all local memory writes, block new writes until the task returns, and retain the block if the remote handoff fails. */
|
|
11678
|
+
withWriteBarrier: (task: () => Promise<MemoryMigrationResult>) => Promise<MemoryMigrationResult>;
|
|
11679
|
+
/** Route all subsequent memory writes to the remote store before this callback returns. */
|
|
11680
|
+
onActivated: () => void | Promise<void>;
|
|
11668
11681
|
signal?: AbortSignal;
|
|
11669
11682
|
onProgress?: (progress: MemoryMigrationProgress) => void;
|
|
11670
11683
|
}
|
package/dist/react/index.mjs
CHANGED
|
@@ -540,15 +540,16 @@ async function refreshEncryptionKeyIfMatches(walletAddress, probeCiphertext, sig
|
|
|
540
540
|
if (!parsed) {
|
|
541
541
|
return false;
|
|
542
542
|
}
|
|
543
|
+
const startEpoch = sessionEpoch;
|
|
543
544
|
const cached = refreshCandidatesByAddress.get(walletAddress);
|
|
544
545
|
if (cached) {
|
|
545
|
-
return tryCommitCandidatesIfProbeMatches(walletAddress, parsed, cached);
|
|
546
|
+
return tryCommitCandidatesIfProbeMatches(walletAddress, parsed, cached, startEpoch);
|
|
546
547
|
}
|
|
547
548
|
let derivePromise = pendingCandidateDerives.get(walletAddress);
|
|
548
549
|
if (!derivePromise) {
|
|
549
550
|
derivePromise = (async () => {
|
|
550
551
|
const candidates2 = await deriveRefreshCandidates(signMessage, embeddedWalletSigner);
|
|
551
|
-
if (candidates2) {
|
|
552
|
+
if (candidates2 && sessionEpoch === startEpoch) {
|
|
552
553
|
refreshCandidatesByAddress.set(walletAddress, candidates2);
|
|
553
554
|
}
|
|
554
555
|
return candidates2;
|
|
@@ -560,10 +561,10 @@ async function refreshEncryptionKeyIfMatches(walletAddress, probeCiphertext, sig
|
|
|
560
561
|
pendingCandidateDerives.set(walletAddress, derivePromise);
|
|
561
562
|
}
|
|
562
563
|
const candidates = await derivePromise;
|
|
563
|
-
if (!candidates) {
|
|
564
|
+
if (!candidates || sessionEpoch !== startEpoch) {
|
|
564
565
|
return false;
|
|
565
566
|
}
|
|
566
|
-
return tryCommitCandidatesIfProbeMatches(walletAddress, parsed, candidates);
|
|
567
|
+
return tryCommitCandidatesIfProbeMatches(walletAddress, parsed, candidates, startEpoch);
|
|
567
568
|
}
|
|
568
569
|
function parsePrefixedCiphertext(probeCiphertext) {
|
|
569
570
|
const version = probeCiphertext.startsWith("enc:v3:") ? "v3" : probeCiphertext.startsWith("enc:v2:") ? "v2" : null;
|
|
@@ -606,7 +607,7 @@ async function deriveRefreshCandidates(signMessage, embeddedWalletSigner) {
|
|
|
606
607
|
}
|
|
607
608
|
return { legacy: legacyKey, current: currentKey };
|
|
608
609
|
}
|
|
609
|
-
async function tryCommitCandidatesIfProbeMatches(walletAddress, parsed, candidates) {
|
|
610
|
+
async function tryCommitCandidatesIfProbeMatches(walletAddress, parsed, candidates, startEpoch) {
|
|
610
611
|
const candidateHex = parsed.version === "v2" ? candidates.legacy : candidates.current;
|
|
611
612
|
const keyBytes = hexToBytes(candidateHex);
|
|
612
613
|
const candidateCryptoKey = await crypto.subtle.importKey(
|
|
@@ -624,6 +625,9 @@ async function tryCommitCandidatesIfProbeMatches(walletAddress, parsed, candidat
|
|
|
624
625
|
);
|
|
625
626
|
return false;
|
|
626
627
|
}
|
|
628
|
+
if (sessionEpoch !== startEpoch) {
|
|
629
|
+
return false;
|
|
630
|
+
}
|
|
627
631
|
setStoredKey(walletAddress, { legacy: candidates.legacy, current: candidates.current });
|
|
628
632
|
cryptoKeyCache.delete(`${walletAddress}:v2`);
|
|
629
633
|
cryptoKeyCache.delete(`${walletAddress}:v3`);
|
|
@@ -17714,6 +17718,104 @@ function validate(parsed, originalQuery) {
|
|
|
17714
17718
|
return { mode, subQueries };
|
|
17715
17719
|
}
|
|
17716
17720
|
|
|
17721
|
+
// src/lib/memoryVault/vaultPreparation.ts
|
|
17722
|
+
function createVaultPreparation() {
|
|
17723
|
+
return { corpora: /* @__PURE__ */ new WeakMap(), rows: /* @__PURE__ */ new WeakMap() };
|
|
17724
|
+
}
|
|
17725
|
+
var pendingRows = /* @__PURE__ */ new WeakMap();
|
|
17726
|
+
function loadVaultCorpus(ctx, options, preparation) {
|
|
17727
|
+
if (!preparation) return getAllVaultMemoriesOp(ctx, options);
|
|
17728
|
+
const corpusCache = preparation.corpora;
|
|
17729
|
+
let pending = corpusCache.get(ctx);
|
|
17730
|
+
if (!pending) {
|
|
17731
|
+
pending = /* @__PURE__ */ new Map();
|
|
17732
|
+
corpusCache.set(ctx, pending);
|
|
17733
|
+
}
|
|
17734
|
+
const key = JSON.stringify(options ?? {});
|
|
17735
|
+
let request = pending.get(key);
|
|
17736
|
+
if (!request) {
|
|
17737
|
+
const entries = pending;
|
|
17738
|
+
request = getAllVaultMemoriesOp(ctx, options).catch((error) => {
|
|
17739
|
+
entries.delete(key);
|
|
17740
|
+
throw error;
|
|
17741
|
+
});
|
|
17742
|
+
pending.set(key, request);
|
|
17743
|
+
}
|
|
17744
|
+
return request;
|
|
17745
|
+
}
|
|
17746
|
+
function rowRequestsFor(registry2, ctx, maskInput) {
|
|
17747
|
+
let byMask = registry2.get(ctx);
|
|
17748
|
+
if (!byMask) {
|
|
17749
|
+
byMask = /* @__PURE__ */ new Map();
|
|
17750
|
+
registry2.set(ctx, byMask);
|
|
17751
|
+
}
|
|
17752
|
+
let requests = byMask.get(maskInput);
|
|
17753
|
+
if (!requests) {
|
|
17754
|
+
requests = /* @__PURE__ */ new Map();
|
|
17755
|
+
byMask.set(maskInput, requests);
|
|
17756
|
+
}
|
|
17757
|
+
return requests;
|
|
17758
|
+
}
|
|
17759
|
+
function embedVaultRows(ctx, options, rows, preparation) {
|
|
17760
|
+
const pending = rowRequestsFor(pendingRows, ctx, options.maskInput);
|
|
17761
|
+
const prepared = preparation && rowRequestsFor(preparation.rows, ctx, options.maskInput);
|
|
17762
|
+
const model = options.model ?? DEFAULT_API_EMBEDDING_MODEL;
|
|
17763
|
+
const keys = rows.map(
|
|
17764
|
+
(row) => JSON.stringify([
|
|
17765
|
+
row.uniqueId,
|
|
17766
|
+
row.updatedAt?.getTime(),
|
|
17767
|
+
row.content,
|
|
17768
|
+
model,
|
|
17769
|
+
options.baseUrl,
|
|
17770
|
+
options.timeoutMs,
|
|
17771
|
+
options.tokenTimeoutMs,
|
|
17772
|
+
options.totalTimeoutMs
|
|
17773
|
+
])
|
|
17774
|
+
);
|
|
17775
|
+
const missing = /* @__PURE__ */ new Map();
|
|
17776
|
+
rows.forEach((row, index) => {
|
|
17777
|
+
if (!pending.has(keys[index]) && !prepared?.has(keys[index])) missing.set(keys[index], row);
|
|
17778
|
+
});
|
|
17779
|
+
if (missing.size > 0) {
|
|
17780
|
+
const entries = pending;
|
|
17781
|
+
const batch = Promise.resolve().then(
|
|
17782
|
+
() => generateEmbeddings(
|
|
17783
|
+
[...missing.values()].map((row) => row.content),
|
|
17784
|
+
options
|
|
17785
|
+
)
|
|
17786
|
+
);
|
|
17787
|
+
[...missing].forEach(([key, row], index) => {
|
|
17788
|
+
const request = batch.then((vectors) => {
|
|
17789
|
+
const vector = vectors[index];
|
|
17790
|
+
updateVaultMemoryEmbeddingOp(ctx, row.uniqueId, JSON.stringify(vector), model, {
|
|
17791
|
+
content: row.content,
|
|
17792
|
+
updatedAt: row.updatedAt?.getTime()
|
|
17793
|
+
}).catch(() => {
|
|
17794
|
+
});
|
|
17795
|
+
return vector;
|
|
17796
|
+
}).finally(() => {
|
|
17797
|
+
entries.delete(key);
|
|
17798
|
+
if (entries.size === 0) pendingRows.get(ctx)?.delete(options.maskInput);
|
|
17799
|
+
});
|
|
17800
|
+
pending.set(key, request);
|
|
17801
|
+
});
|
|
17802
|
+
}
|
|
17803
|
+
return Promise.all(
|
|
17804
|
+
keys.map((key) => {
|
|
17805
|
+
const cached = prepared?.get(key);
|
|
17806
|
+
if (cached) return cached;
|
|
17807
|
+
const request = pending.get(key);
|
|
17808
|
+
if (!prepared) return request;
|
|
17809
|
+
const retained = request.catch((error) => {
|
|
17810
|
+
prepared.delete(key);
|
|
17811
|
+
throw error;
|
|
17812
|
+
});
|
|
17813
|
+
prepared.set(key, retained);
|
|
17814
|
+
return retained;
|
|
17815
|
+
})
|
|
17816
|
+
);
|
|
17817
|
+
}
|
|
17818
|
+
|
|
17717
17819
|
// src/lib/memoryVault/vectorVersion.ts
|
|
17718
17820
|
var vectorRowVersion = /* @__PURE__ */ new WeakMap();
|
|
17719
17821
|
function contentFingerprint(content) {
|
|
@@ -18276,11 +18378,11 @@ async function rankComposite(originalQuery, originalQueryEmbedding, subQueries,
|
|
|
18276
18378
|
return combined.slice(0, limit);
|
|
18277
18379
|
}
|
|
18278
18380
|
async function preEmbedVaultMemories(vaultCtx, embeddingOptions, cache, options) {
|
|
18279
|
-
const memories = await
|
|
18381
|
+
const memories = await loadVaultCorpus(vaultCtx, options);
|
|
18280
18382
|
const currentModel = embeddingOptions.model ?? DEFAULT_API_EMBEDDING_MODEL;
|
|
18281
18383
|
const uncachedTexts = [];
|
|
18282
18384
|
const uncachedKeys = [];
|
|
18283
|
-
const
|
|
18385
|
+
const uncachedRows = [];
|
|
18284
18386
|
const uncachedVersions = [];
|
|
18285
18387
|
for (const m of memories) {
|
|
18286
18388
|
const content = m.content;
|
|
@@ -18299,12 +18401,12 @@ async function preEmbedVaultMemories(vaultCtx, embeddingOptions, cache, options)
|
|
|
18299
18401
|
}
|
|
18300
18402
|
uncachedTexts.push(m.content);
|
|
18301
18403
|
uncachedKeys.push(m.uniqueId);
|
|
18302
|
-
|
|
18404
|
+
uncachedRows.push(m);
|
|
18303
18405
|
uncachedVersions.push(m.updatedAt);
|
|
18304
18406
|
}
|
|
18305
18407
|
}
|
|
18306
18408
|
if (uncachedTexts.length > 0) {
|
|
18307
|
-
const embeddings = await
|
|
18409
|
+
const embeddings = await embedVaultRows(vaultCtx, embeddingOptions, uncachedRows);
|
|
18308
18410
|
for (let i = 0; i < uncachedKeys.length; i++) {
|
|
18309
18411
|
cacheRowVector(
|
|
18310
18412
|
cache,
|
|
@@ -18313,13 +18415,6 @@ async function preEmbedVaultMemories(vaultCtx, embeddingOptions, cache, options)
|
|
|
18313
18415
|
uncachedVersions[i],
|
|
18314
18416
|
uncachedTexts[i]
|
|
18315
18417
|
);
|
|
18316
|
-
updateVaultMemoryEmbeddingOp(
|
|
18317
|
-
vaultCtx,
|
|
18318
|
-
uncachedIds[i],
|
|
18319
|
-
JSON.stringify(embeddings[i]),
|
|
18320
|
-
currentModel
|
|
18321
|
-
).catch(() => {
|
|
18322
|
-
});
|
|
18323
18418
|
}
|
|
18324
18419
|
}
|
|
18325
18420
|
}
|
|
@@ -18461,10 +18556,7 @@ async function buildProjectedCorpus(query, vaultCtx, embeddingOptions, cache, qu
|
|
|
18461
18556
|
let laneVecs;
|
|
18462
18557
|
if (opts.embedStats) opts.embedStats.rowsEmbedded += laneRows.length;
|
|
18463
18558
|
try {
|
|
18464
|
-
laneVecs = await
|
|
18465
|
-
laneRows.map((m) => m.content),
|
|
18466
|
-
embeddingOptions
|
|
18467
|
-
);
|
|
18559
|
+
laneVecs = await embedVaultRows(vaultCtx, embeddingOptions, laneRows);
|
|
18468
18560
|
} catch (err) {
|
|
18469
18561
|
laneEmbedFailed = true;
|
|
18470
18562
|
getLogger().warn(
|
|
@@ -18478,13 +18570,6 @@ async function buildProjectedCorpus(query, vaultCtx, embeddingOptions, cache, qu
|
|
|
18478
18570
|
cacheRowVector(cache, m.uniqueId, vec, m.updatedAt, m.content);
|
|
18479
18571
|
resolvedThisCall.add(m.uniqueId);
|
|
18480
18572
|
vectored.push({ uniqueId: m.uniqueId, embedding: vec, updatedAt: m.updatedAt });
|
|
18481
|
-
updateVaultMemoryEmbeddingOp(
|
|
18482
|
-
vaultCtx,
|
|
18483
|
-
m.uniqueId,
|
|
18484
|
-
JSON.stringify(vecs[i]),
|
|
18485
|
-
currentModel
|
|
18486
|
-
).catch(() => {
|
|
18487
|
-
});
|
|
18488
18573
|
});
|
|
18489
18574
|
}
|
|
18490
18575
|
}
|
|
@@ -18676,9 +18761,10 @@ async function prepareVaultCandidates(query, vaultCtx, embeddingOptions, cache,
|
|
|
18676
18761
|
};
|
|
18677
18762
|
}
|
|
18678
18763
|
} else {
|
|
18679
|
-
const loaded = await
|
|
18764
|
+
const loaded = await loadVaultCorpus(
|
|
18680
18765
|
vaultCtx,
|
|
18681
|
-
Object.keys(queryOpts).length > 0 ? queryOpts : void 0
|
|
18766
|
+
Object.keys(queryOpts).length > 0 ? queryOpts : void 0,
|
|
18767
|
+
searchOptions?.vaultPreparation
|
|
18682
18768
|
);
|
|
18683
18769
|
vaultSize = loaded.length;
|
|
18684
18770
|
rowsDecrypted = loaded.length;
|
|
@@ -18751,7 +18837,12 @@ async function prepareVaultCandidates(query, vaultCtx, embeddingOptions, cache,
|
|
|
18751
18837
|
let newEmbeddings;
|
|
18752
18838
|
embedStats.rowsEmbedded += uncachedTexts.length;
|
|
18753
18839
|
try {
|
|
18754
|
-
newEmbeddings = await
|
|
18840
|
+
newEmbeddings = await embedVaultRows(
|
|
18841
|
+
vaultCtx,
|
|
18842
|
+
embeddingOptions,
|
|
18843
|
+
uncachedIndices.map((index) => memories[index]),
|
|
18844
|
+
searchOptions?.vaultPreparation
|
|
18845
|
+
);
|
|
18755
18846
|
} catch (err) {
|
|
18756
18847
|
embeddingFailure = true;
|
|
18757
18848
|
getLogger().warn(
|
|
@@ -18767,13 +18858,6 @@ async function prepareVaultCandidates(query, vaultCtx, embeddingOptions, cache,
|
|
|
18767
18858
|
memories[uncachedIndices[j]].updatedAt,
|
|
18768
18859
|
memories[uncachedIndices[j]].content
|
|
18769
18860
|
);
|
|
18770
|
-
updateVaultMemoryEmbeddingOp(
|
|
18771
|
-
vaultCtx,
|
|
18772
|
-
memories[uncachedIndices[j]].uniqueId,
|
|
18773
|
-
JSON.stringify(newEmbeddings[j]),
|
|
18774
|
-
currentModel
|
|
18775
|
-
).catch(() => {
|
|
18776
|
-
});
|
|
18777
18861
|
}
|
|
18778
18862
|
}
|
|
18779
18863
|
}
|
|
@@ -21340,6 +21424,7 @@ async function recall(query, ctx, options = {}) {
|
|
|
21340
21424
|
},
|
|
21341
21425
|
...options.rrfK !== void 0 && { rrfK: options.rrfK },
|
|
21342
21426
|
...options.decryptLast !== void 0 && { decryptLast: options.decryptLast },
|
|
21427
|
+
...options.vaultPreparation && { vaultPreparation: options.vaultPreparation },
|
|
21343
21428
|
...subQueries && { subQueries },
|
|
21344
21429
|
...options.scopes && { scopes: options.scopes },
|
|
21345
21430
|
...options.folderId !== void 0 && { folderId: options.folderId },
|
|
@@ -23357,6 +23442,8 @@ async function backfillTopics(ctx) {
|
|
|
23357
23442
|
if (topicless.length > 0) await backfillMemoryTopicsOp(ctx, topicless);
|
|
23358
23443
|
}
|
|
23359
23444
|
async function migrateMemoriesToRemote(options) {
|
|
23445
|
+
if (typeof options.withWriteBarrier !== "function" || typeof options.onActivated !== "function")
|
|
23446
|
+
throw new Error("A write barrier and a remote store handoff are required");
|
|
23360
23447
|
const { canonical, signal } = options;
|
|
23361
23448
|
const rings = [canonical, ...options.fallbacks ?? []];
|
|
23362
23449
|
const model = options.embeddingOptions?.model ?? DEFAULT_API_EMBEDDING_MODEL;
|
|
@@ -23384,93 +23471,98 @@ async function migrateMemoriesToRemote(options) {
|
|
|
23384
23471
|
const placeholders = /* @__PURE__ */ new Set();
|
|
23385
23472
|
const truncated = /* @__PURE__ */ new Set();
|
|
23386
23473
|
let imported = 0;
|
|
23387
|
-
|
|
23388
|
-
|
|
23389
|
-
|
|
23390
|
-
|
|
23391
|
-
|
|
23392
|
-
|
|
23393
|
-
|
|
23394
|
-
|
|
23395
|
-
|
|
23396
|
-
|
|
23397
|
-
|
|
23398
|
-
|
|
23399
|
-
|
|
23400
|
-
);
|
|
23401
|
-
const needsVector = (raw, server) => !!options.embeddingOptions && !embedding(raw, model) && server.embedding_model !== model;
|
|
23402
|
-
for (const raw of candidates) {
|
|
23403
|
-
const server = remote.get(raw.id);
|
|
23404
|
-
if (server && server.updated_at === raw.updated_at && (!sameMetadata2(raw, server, model) || needsVector(raw, server)))
|
|
23405
|
-
pending.set(raw.id, raw.updated_at + 1);
|
|
23406
|
-
}
|
|
23407
|
-
}
|
|
23408
|
-
if (pending.size === 0) {
|
|
23409
|
-
const result = (state) => ({
|
|
23410
|
-
state,
|
|
23411
|
-
total: rows.length,
|
|
23412
|
-
imported,
|
|
23413
|
-
skipped: [...skipped].map(([memoryId, reason]) => ({ memoryId, reason })),
|
|
23414
|
-
reembedded: reembedded.size,
|
|
23415
|
-
unembedded: unembedded.size,
|
|
23416
|
-
placeholderTombstones: placeholders.size,
|
|
23417
|
-
truncatedSourceChunkIds: truncated.size
|
|
23418
|
-
});
|
|
23419
|
-
if (skipped.size > 0 && !options.allowSkipped) return result("migrating");
|
|
23420
|
-
if (!claimed) await importBatch(request, canonical.keyId, [], signal);
|
|
23421
|
-
if (!active)
|
|
23422
|
-
await request(
|
|
23423
|
-
"/account",
|
|
23424
|
-
{ method: "PUT", body: JSON.stringify({ state: "active" }) },
|
|
23474
|
+
const uploadPasses = async (finalizing = false) => {
|
|
23475
|
+
for (let pass = 0; ; pass++) {
|
|
23476
|
+
const rows = await getAllVaultMemoryRowsOp(options.vaultCtx);
|
|
23477
|
+
for (const raw of rows) if (invalid2(raw)) skipped.set(String(raw.id), "invalid");
|
|
23478
|
+
const candidates = rows.filter((raw) => !skipped.has(String(raw.id)));
|
|
23479
|
+
const missing = await missingIds(request, candidates.map(revision), signal);
|
|
23480
|
+
const pending = /* @__PURE__ */ new Map();
|
|
23481
|
+
for (const raw of candidates)
|
|
23482
|
+
if (missing.has(raw.id)) pending.set(raw.id, raw.updated_at);
|
|
23483
|
+
if (pending.size === 0 && !active) {
|
|
23484
|
+
const remote = await remoteMetadata(
|
|
23485
|
+
request,
|
|
23486
|
+
candidates.map((raw) => raw.id),
|
|
23425
23487
|
signal
|
|
23426
23488
|
);
|
|
23427
|
-
|
|
23428
|
-
|
|
23429
|
-
|
|
23430
|
-
|
|
23431
|
-
|
|
23432
|
-
|
|
23433
|
-
|
|
23434
|
-
)
|
|
23435
|
-
|
|
23436
|
-
|
|
23437
|
-
|
|
23438
|
-
|
|
23439
|
-
|
|
23440
|
-
|
|
23441
|
-
|
|
23442
|
-
|
|
23443
|
-
|
|
23444
|
-
|
|
23445
|
-
|
|
23446
|
-
|
|
23447
|
-
|
|
23448
|
-
|
|
23449
|
-
|
|
23450
|
-
|
|
23451
|
-
|
|
23452
|
-
|
|
23453
|
-
|
|
23454
|
-
|
|
23455
|
-
|
|
23489
|
+
const needsVector = (raw, server) => !!options.embeddingOptions && !embedding(raw, model) && server.embedding_model !== model;
|
|
23490
|
+
for (const raw of candidates) {
|
|
23491
|
+
const server = remote.get(raw.id);
|
|
23492
|
+
if (server && server.updated_at === raw.updated_at && (!sameMetadata2(raw, server, model) || needsVector(raw, server)))
|
|
23493
|
+
pending.set(raw.id, raw.updated_at + 1);
|
|
23494
|
+
}
|
|
23495
|
+
}
|
|
23496
|
+
if (pending.size === 0) {
|
|
23497
|
+
const result = (state) => ({
|
|
23498
|
+
state,
|
|
23499
|
+
total: rows.length,
|
|
23500
|
+
imported,
|
|
23501
|
+
skipped: [...skipped].map(([memoryId, reason]) => ({ memoryId, reason })),
|
|
23502
|
+
reembedded: reembedded.size,
|
|
23503
|
+
unembedded: unembedded.size,
|
|
23504
|
+
placeholderTombstones: placeholders.size,
|
|
23505
|
+
truncatedSourceChunkIds: truncated.size
|
|
23506
|
+
});
|
|
23507
|
+
if (skipped.size > 0 && !options.allowSkipped) return result("migrating");
|
|
23508
|
+
if (!finalizing) return options.withWriteBarrier(() => uploadPasses(true));
|
|
23509
|
+
if (!claimed) await importBatch(request, canonical.keyId, [], signal);
|
|
23510
|
+
if (!active)
|
|
23511
|
+
await request(
|
|
23512
|
+
"/account",
|
|
23513
|
+
{ method: "PUT", body: JSON.stringify({ state: "active" }) },
|
|
23514
|
+
signal
|
|
23515
|
+
);
|
|
23516
|
+
await options.onActivated();
|
|
23517
|
+
return result("active");
|
|
23518
|
+
}
|
|
23519
|
+
if (pass >= MAX_UPLOAD_PASSES)
|
|
23520
|
+
throw new RemoteMemoryError(
|
|
23521
|
+
"Nearby still reports memories missing after importing them",
|
|
23522
|
+
409,
|
|
23523
|
+
"migration_incomplete"
|
|
23524
|
+
);
|
|
23525
|
+
const prepared = [];
|
|
23526
|
+
for (const raw of candidates) {
|
|
23527
|
+
const updatedAt = pending.get(raw.id);
|
|
23528
|
+
if (updatedAt === void 0) continue;
|
|
23529
|
+
try {
|
|
23530
|
+
prepared.push(await prepareRow(raw, canonical, rings, model, updatedAt));
|
|
23531
|
+
} catch (error) {
|
|
23532
|
+
if (!(error instanceof MemoryKeyError)) throw error;
|
|
23533
|
+
skipped.set(raw.id, "unreadable");
|
|
23534
|
+
}
|
|
23535
|
+
}
|
|
23536
|
+
const usable = new Set(prepared.filter((p) => p.row.embedding).map((p) => p.row.memory_id));
|
|
23537
|
+
if (options.embeddingOptions)
|
|
23538
|
+
await embedMissing(prepared, options.embeddingOptions, model, signal);
|
|
23539
|
+
const local = new Map(candidates.map((raw) => [raw.id, raw]));
|
|
23540
|
+
const upload = [];
|
|
23541
|
+
for (const { row, plaintext } of prepared) {
|
|
23542
|
+
const id2 = row.memory_id;
|
|
23543
|
+
if (!fitsNearby(row)) {
|
|
23544
|
+
skipped.set(id2, "invalid");
|
|
23545
|
+
continue;
|
|
23546
|
+
}
|
|
23547
|
+
upload.push(row);
|
|
23548
|
+
const track = (set, on) => on ? set.add(id2) : set.delete(id2);
|
|
23549
|
+
track(reembedded, !!row.embedding && !usable.has(id2));
|
|
23550
|
+
track(unembedded, !row.embedding);
|
|
23551
|
+
track(placeholders, plaintext === void 0);
|
|
23552
|
+
track(truncated, row.source_chunk_ids !== text13(local.get(id2).source_chunk_ids));
|
|
23456
23553
|
}
|
|
23457
|
-
|
|
23458
|
-
const track = (set, on) => on ? set.add(id2) : set.delete(id2);
|
|
23459
|
-
track(reembedded, !!row.embedding && !usable.has(id2));
|
|
23460
|
-
track(unembedded, !row.embedding);
|
|
23461
|
-
track(placeholders, plaintext === void 0);
|
|
23462
|
-
track(truncated, row.source_chunk_ids !== text13(local.get(id2).source_chunk_ids));
|
|
23463
|
-
}
|
|
23464
|
-
let sent = 0;
|
|
23465
|
-
options.onProgress?.({ imported: sent, toImport: upload.length });
|
|
23466
|
-
for (const batch of chunks(upload, IMPORT_BATCH)) {
|
|
23467
|
-
await importBatch(request, canonical.keyId, batch, signal);
|
|
23468
|
-
claimed = true;
|
|
23469
|
-
sent += batch.length;
|
|
23554
|
+
let sent = 0;
|
|
23470
23555
|
options.onProgress?.({ imported: sent, toImport: upload.length });
|
|
23556
|
+
for (const batch of chunks(upload, IMPORT_BATCH)) {
|
|
23557
|
+
await importBatch(request, canonical.keyId, batch, signal);
|
|
23558
|
+
claimed = true;
|
|
23559
|
+
sent += batch.length;
|
|
23560
|
+
options.onProgress?.({ imported: sent, toImport: upload.length });
|
|
23561
|
+
}
|
|
23562
|
+
imported += sent;
|
|
23471
23563
|
}
|
|
23472
|
-
|
|
23473
|
-
|
|
23564
|
+
};
|
|
23565
|
+
return uploadPasses();
|
|
23474
23566
|
}
|
|
23475
23567
|
|
|
23476
23568
|
// src/lib/memory/store/remoteStore.ts
|
|
@@ -24923,13 +25015,20 @@ async function synthesizeProfile(ctx, options = {}) {
|
|
|
24923
25015
|
}
|
|
24924
25016
|
}
|
|
24925
25017
|
}
|
|
25018
|
+
const vaultPreparation = createVaultPreparation();
|
|
24926
25019
|
const settled = await Promise.allSettled(
|
|
24927
25020
|
facets.map(async (facet) => {
|
|
24928
25021
|
const prior = previous?.sections.find((s) => s.key === facet.key);
|
|
24929
25022
|
if (prior && !staleKeys.has(facet.key)) {
|
|
24930
25023
|
return prior;
|
|
24931
25024
|
}
|
|
24932
|
-
return synthesizeFacet(
|
|
25025
|
+
return synthesizeFacet(
|
|
25026
|
+
facet,
|
|
25027
|
+
recallCtx,
|
|
25028
|
+
options,
|
|
25029
|
+
fallbackPriors.get(facet.key),
|
|
25030
|
+
vaultPreparation
|
|
25031
|
+
);
|
|
24933
25032
|
})
|
|
24934
25033
|
);
|
|
24935
25034
|
const sections = settled.map((r, i) => {
|
|
@@ -25083,7 +25182,7 @@ async function attributeFacts(ctx, candidates, facets) {
|
|
|
25083
25182
|
}
|
|
25084
25183
|
return keys;
|
|
25085
25184
|
}
|
|
25086
|
-
async function synthesizeFacet(facet, ctx, options, prior) {
|
|
25185
|
+
async function synthesizeFacet(facet, ctx, options, prior, vaultPreparation) {
|
|
25087
25186
|
const scopes = options.scopes ?? DEFAULT_SCOPES;
|
|
25088
25187
|
const limit = options.limit ?? DEFAULT_FACET_RECALL_LIMIT;
|
|
25089
25188
|
const factTypeWeights = { ...DEFAULT_PROFILE_FACT_TYPE_WEIGHTS, ...options.factTypeWeights };
|
|
@@ -25100,6 +25199,7 @@ async function synthesizeFacet(facet, ctx, options, prior) {
|
|
|
25100
25199
|
};
|
|
25101
25200
|
}
|
|
25102
25201
|
const recalled = await recall(facet.query, ctx, {
|
|
25202
|
+
vaultPreparation,
|
|
25103
25203
|
scopes,
|
|
25104
25204
|
limit: hasReviewGate ? RECALL_MAX_LIMIT : limit,
|
|
25105
25205
|
types: ["fact"],
|