@anuma/sdk 9.1.5 → 9.1.7
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/client/index.cjs +106 -94
- package/dist/client/index.mjs +106 -94
- package/dist/expo/{chunk-XW3LYSDA.mjs → chunk-WRZTH4OS.mjs} +38 -13
- package/dist/expo/{consolidate-4CQJYKRK.mjs → consolidate-HKL5EGZT.mjs} +1 -1
- package/dist/expo/index.cjs +84 -31
- package/dist/expo/index.d.mts +9 -5
- package/dist/expo/index.d.ts +9 -5
- package/dist/expo/index.mjs +47 -19
- package/dist/index.cjs +47 -35
- package/dist/index.mjs +47 -35
- package/dist/react/{chunk-7QX4J7KV.mjs → chunk-RSA3S6OA.mjs} +38 -13
- package/dist/react/{consolidate-WLDYJF6J.mjs → consolidate-WFTPBHDV.mjs} +1 -1
- package/dist/react/index.cjs +109 -46
- package/dist/react/index.d.mts +9 -5
- package/dist/react/index.d.ts +9 -5
- package/dist/react/index.mjs +77 -39
- package/dist/server/{chunk-AU3Z7NBC.mjs → chunk-QEROZ4VH.mjs} +38 -13
- package/dist/server/{consolidate-B6OSCZU4.mjs → consolidate-PYED62LW.mjs} +1 -1
- package/dist/server/index.cjs +89 -27
- package/dist/server/index.d.mts +9 -5
- package/dist/server/index.d.ts +9 -5
- package/dist/server/index.mjs +52 -15
- package/dist/tools/selection/index.cjs +14 -2
- package/dist/tools/selection/index.mjs +14 -2
- package/package.json +1 -1
|
@@ -723,6 +723,12 @@ function assertTransportMatchesEndpoint(transport, endpoint) {
|
|
|
723
723
|
`endpointOverride "${endpoint}" is the other transport's endpoint, but transport is "${transport}". The request body is built for the transport, so this sends the wrong shape and 400s without retry.`
|
|
724
724
|
);
|
|
725
725
|
}
|
|
726
|
+
var TIME_BUDGET_EXHAUSTED = {
|
|
727
|
+
kind: "terminal",
|
|
728
|
+
code: "time-budget-exhausted",
|
|
729
|
+
reason: "time budget exhausted"
|
|
730
|
+
};
|
|
731
|
+
var MAX_TIMER_DELAY_MS = 2147483647;
|
|
726
732
|
var RETRYABLE_HTTP = /* @__PURE__ */ new Set([408, 409, 425, 429]);
|
|
727
733
|
function isRetryableStatus(status) {
|
|
728
734
|
return status >= 500 || RETRYABLE_HTTP.has(status);
|
|
@@ -778,7 +784,8 @@ async function callPortalJsonCompletion(req) {
|
|
|
778
784
|
}
|
|
779
785
|
const maxAttempts = Math.max(1, req.maxAttempts ?? 3);
|
|
780
786
|
const startedAt = Date.now();
|
|
781
|
-
const
|
|
787
|
+
const deadlineAt = req.totalTimeoutMs === void 0 ? void 0 : startedAt + req.totalTimeoutMs;
|
|
788
|
+
const overBudget = () => deadlineAt !== void 0 && Date.now() >= deadlineAt;
|
|
782
789
|
let lastFailure;
|
|
783
790
|
let reinforce = false;
|
|
784
791
|
const giveUp = () => {
|
|
@@ -791,17 +798,11 @@ async function callPortalJsonCompletion(req) {
|
|
|
791
798
|
lastFailure = { reason: "time-budget-exhausted", attempts: attempt - 1 };
|
|
792
799
|
break;
|
|
793
800
|
}
|
|
794
|
-
const attemptReq = req
|
|
795
|
-
...req,
|
|
796
|
-
timeoutMs: Math.max(
|
|
797
|
-
1,
|
|
798
|
-
Math.min(req.timeoutMs ?? 6e4, req.totalTimeoutMs - (Date.now() - startedAt))
|
|
799
|
-
),
|
|
800
|
-
...reinforce && { reinforceJsonContract: true }
|
|
801
|
-
} : reinforce ? { ...req, reinforceJsonContract: true } : req;
|
|
801
|
+
const attemptReq = reinforce ? { ...req, reinforceJsonContract: true } : req;
|
|
802
802
|
const outcome = await attemptPortalJson(
|
|
803
803
|
{ ...attemptReq, transport },
|
|
804
|
-
endpoint
|
|
804
|
+
endpoint,
|
|
805
|
+
deadlineAt
|
|
805
806
|
);
|
|
806
807
|
if (outcome.kind === "ok") {
|
|
807
808
|
req.onAttempt?.({ attempt, ok: true });
|
|
@@ -841,13 +842,38 @@ async function callPortalJsonCompletion(req) {
|
|
|
841
842
|
}
|
|
842
843
|
return giveUp();
|
|
843
844
|
}
|
|
844
|
-
async function attemptPortalJson(req, endpoint) {
|
|
845
|
+
async function attemptPortalJson(req, endpoint, deadlineAt) {
|
|
846
|
+
const controller = new AbortController();
|
|
847
|
+
if (deadlineAt === void 0 || deadlineAt - Date.now() > MAX_TIMER_DELAY_MS) {
|
|
848
|
+
return requestPortalJson(req, endpoint, controller);
|
|
849
|
+
}
|
|
850
|
+
const remainingMs = deadlineAt - Date.now();
|
|
851
|
+
if (remainingMs <= 0) return TIME_BUDGET_EXHAUSTED;
|
|
852
|
+
let timer;
|
|
853
|
+
try {
|
|
854
|
+
const outcome = await Promise.race([
|
|
855
|
+
new Promise((resolve) => {
|
|
856
|
+
timer = setTimeout(() => {
|
|
857
|
+
resolve(TIME_BUDGET_EXHAUSTED);
|
|
858
|
+
controller.abort();
|
|
859
|
+
}, remainingMs);
|
|
860
|
+
}),
|
|
861
|
+
requestPortalJson(req, endpoint, controller, deadlineAt)
|
|
862
|
+
]);
|
|
863
|
+
return Date.now() >= deadlineAt ? TIME_BUDGET_EXHAUSTED : outcome;
|
|
864
|
+
} finally {
|
|
865
|
+
clearTimeout(timer);
|
|
866
|
+
}
|
|
867
|
+
}
|
|
868
|
+
async function requestPortalJson(req, endpoint, controller, deadlineAt) {
|
|
845
869
|
const baseUrl = req.baseUrl ?? defaultBaseUrl();
|
|
846
870
|
const fetchImpl = req.fetchFn ?? fetch;
|
|
847
|
-
const timeoutMs = req.timeoutMs ?? 6e4;
|
|
848
871
|
const authHeaders = await resolvePortalAuthHeaders(req, req.tag);
|
|
872
|
+
const remainingMs = deadlineAt === void 0 ? Infinity : deadlineAt - Date.now();
|
|
873
|
+
if (controller.signal.aborted || remainingMs <= 0) return TIME_BUDGET_EXHAUSTED;
|
|
849
874
|
if (authHeaders === null)
|
|
850
875
|
return { kind: "terminal", code: "auth-unavailable", reason: "auth unavailable (no token)" };
|
|
876
|
+
const timeoutMs = Math.min(req.timeoutMs ?? 6e4, remainingMs);
|
|
851
877
|
const usesPrefill = req.transport !== "responses" && req.model.startsWith("anthropic/");
|
|
852
878
|
const prefill = usesPrefill ? "{" : "";
|
|
853
879
|
const messages = [
|
|
@@ -857,7 +883,6 @@ async function attemptPortalJson(req, endpoint) {
|
|
|
857
883
|
];
|
|
858
884
|
if (prefill) messages.push({ role: "assistant", content: prefill });
|
|
859
885
|
const supportsJsonObjectFormat = supportsResponseFormat(req.model);
|
|
860
|
-
const controller = new AbortController();
|
|
861
886
|
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
862
887
|
const requestBody = req.transport === "responses" ? {
|
|
863
888
|
model: req.model,
|
package/dist/expo/index.cjs
CHANGED
|
@@ -875,7 +875,8 @@ async function callPortalJsonCompletion(req) {
|
|
|
875
875
|
}
|
|
876
876
|
const maxAttempts = Math.max(1, req.maxAttempts ?? 3);
|
|
877
877
|
const startedAt = Date.now();
|
|
878
|
-
const
|
|
878
|
+
const deadlineAt = req.totalTimeoutMs === void 0 ? void 0 : startedAt + req.totalTimeoutMs;
|
|
879
|
+
const overBudget = () => deadlineAt !== void 0 && Date.now() >= deadlineAt;
|
|
879
880
|
let lastFailure;
|
|
880
881
|
let reinforce = false;
|
|
881
882
|
const giveUp = () => {
|
|
@@ -888,17 +889,11 @@ async function callPortalJsonCompletion(req) {
|
|
|
888
889
|
lastFailure = { reason: "time-budget-exhausted", attempts: attempt - 1 };
|
|
889
890
|
break;
|
|
890
891
|
}
|
|
891
|
-
const attemptReq = req
|
|
892
|
-
...req,
|
|
893
|
-
timeoutMs: Math.max(
|
|
894
|
-
1,
|
|
895
|
-
Math.min(req.timeoutMs ?? 6e4, req.totalTimeoutMs - (Date.now() - startedAt))
|
|
896
|
-
),
|
|
897
|
-
...reinforce && { reinforceJsonContract: true }
|
|
898
|
-
} : reinforce ? { ...req, reinforceJsonContract: true } : req;
|
|
892
|
+
const attemptReq = reinforce ? { ...req, reinforceJsonContract: true } : req;
|
|
899
893
|
const outcome2 = await attemptPortalJson(
|
|
900
894
|
{ ...attemptReq, transport },
|
|
901
|
-
endpoint
|
|
895
|
+
endpoint,
|
|
896
|
+
deadlineAt
|
|
902
897
|
);
|
|
903
898
|
if (outcome2.kind === "ok") {
|
|
904
899
|
req.onAttempt?.({ attempt, ok: true });
|
|
@@ -938,13 +933,38 @@ async function callPortalJsonCompletion(req) {
|
|
|
938
933
|
}
|
|
939
934
|
return giveUp();
|
|
940
935
|
}
|
|
941
|
-
async function attemptPortalJson(req, endpoint) {
|
|
936
|
+
async function attemptPortalJson(req, endpoint, deadlineAt) {
|
|
937
|
+
const controller = new AbortController();
|
|
938
|
+
if (deadlineAt === void 0 || deadlineAt - Date.now() > MAX_TIMER_DELAY_MS) {
|
|
939
|
+
return requestPortalJson(req, endpoint, controller);
|
|
940
|
+
}
|
|
941
|
+
const remainingMs = deadlineAt - Date.now();
|
|
942
|
+
if (remainingMs <= 0) return TIME_BUDGET_EXHAUSTED;
|
|
943
|
+
let timer;
|
|
944
|
+
try {
|
|
945
|
+
const outcome2 = await Promise.race([
|
|
946
|
+
new Promise((resolve) => {
|
|
947
|
+
timer = setTimeout(() => {
|
|
948
|
+
resolve(TIME_BUDGET_EXHAUSTED);
|
|
949
|
+
controller.abort();
|
|
950
|
+
}, remainingMs);
|
|
951
|
+
}),
|
|
952
|
+
requestPortalJson(req, endpoint, controller, deadlineAt)
|
|
953
|
+
]);
|
|
954
|
+
return Date.now() >= deadlineAt ? TIME_BUDGET_EXHAUSTED : outcome2;
|
|
955
|
+
} finally {
|
|
956
|
+
clearTimeout(timer);
|
|
957
|
+
}
|
|
958
|
+
}
|
|
959
|
+
async function requestPortalJson(req, endpoint, controller, deadlineAt) {
|
|
942
960
|
const baseUrl = req.baseUrl ?? defaultBaseUrl();
|
|
943
961
|
const fetchImpl = req.fetchFn ?? fetch;
|
|
944
|
-
const timeoutMs = req.timeoutMs ?? 6e4;
|
|
945
962
|
const authHeaders = await resolvePortalAuthHeaders(req, req.tag);
|
|
963
|
+
const remainingMs = deadlineAt === void 0 ? Infinity : deadlineAt - Date.now();
|
|
964
|
+
if (controller.signal.aborted || remainingMs <= 0) return TIME_BUDGET_EXHAUSTED;
|
|
946
965
|
if (authHeaders === null)
|
|
947
966
|
return { kind: "terminal", code: "auth-unavailable", reason: "auth unavailable (no token)" };
|
|
967
|
+
const timeoutMs = Math.min(req.timeoutMs ?? 6e4, remainingMs);
|
|
948
968
|
const usesPrefill = req.transport !== "responses" && req.model.startsWith("anthropic/");
|
|
949
969
|
const prefill = usesPrefill ? "{" : "";
|
|
950
970
|
const messages = [
|
|
@@ -954,7 +974,6 @@ async function attemptPortalJson(req, endpoint) {
|
|
|
954
974
|
];
|
|
955
975
|
if (prefill) messages.push({ role: "assistant", content: prefill });
|
|
956
976
|
const supportsJsonObjectFormat = supportsResponseFormat(req.model);
|
|
957
|
-
const controller = new AbortController();
|
|
958
977
|
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
959
978
|
const requestBody = req.transport === "responses" ? {
|
|
960
979
|
model: req.model,
|
|
@@ -1139,7 +1158,7 @@ function extractResponsesContent(body) {
|
|
|
1139
1158
|
const text14 = root.output.filter((item) => asRecord(item)?.type === "message").flatMap((item) => Array.isArray(item.content) ? item.content : []).map((part) => asRecord(part)?.text).filter((t) => typeof t === "string").join("");
|
|
1140
1159
|
return text14;
|
|
1141
1160
|
}
|
|
1142
|
-
var RESPONSE_FORMAT_OK, RESPONSE_SCHEMA_OK, JSON_CONTRACT_REMINDER, RESPONSES_ONLY_MODEL_PREFIXES, CHAT_TO_RESPONSES_FIELDS, FOREIGN_ENDPOINT_SUFFIX, RETRYABLE_HTTP;
|
|
1161
|
+
var RESPONSE_FORMAT_OK, RESPONSE_SCHEMA_OK, JSON_CONTRACT_REMINDER, RESPONSES_ONLY_MODEL_PREFIXES, CHAT_TO_RESPONSES_FIELDS, FOREIGN_ENDPOINT_SUFFIX, TIME_BUDGET_EXHAUSTED, MAX_TIMER_DELAY_MS, RETRYABLE_HTTP;
|
|
1143
1162
|
var init_portalLlm = __esm({
|
|
1144
1163
|
"src/lib/memory/portalLlm.ts"() {
|
|
1145
1164
|
"use strict";
|
|
@@ -1159,6 +1178,12 @@ var init_portalLlm = __esm({
|
|
|
1159
1178
|
chat: "/responses",
|
|
1160
1179
|
responses: "/chat/completions"
|
|
1161
1180
|
};
|
|
1181
|
+
TIME_BUDGET_EXHAUSTED = {
|
|
1182
|
+
kind: "terminal",
|
|
1183
|
+
code: "time-budget-exhausted",
|
|
1184
|
+
reason: "time budget exhausted"
|
|
1185
|
+
};
|
|
1186
|
+
MAX_TIMER_DELAY_MS = 2147483647;
|
|
1162
1187
|
RETRYABLE_HTTP = /* @__PURE__ */ new Set([408, 409, 425, 429]);
|
|
1163
1188
|
}
|
|
1164
1189
|
});
|
|
@@ -5436,7 +5461,7 @@ var mergeHeaders = (...headers) => {
|
|
|
5436
5461
|
if (!header || typeof header !== "object") {
|
|
5437
5462
|
continue;
|
|
5438
5463
|
}
|
|
5439
|
-
const iterator = header instanceof Headers ? headersEntries(header) : Object.entries(header);
|
|
5464
|
+
const iterator = Array.isArray(header) || header instanceof Headers ? headersEntries(new Headers(header)) : Object.entries(header);
|
|
5440
5465
|
for (const [key, value] of iterator) {
|
|
5441
5466
|
if (value === null) {
|
|
5442
5467
|
mergedHeaders.delete(key);
|
|
@@ -5712,6 +5737,18 @@ var createClient = (config = {}) => {
|
|
|
5712
5737
|
init_clientConfig();
|
|
5713
5738
|
var client = createClient(createClientConfig(createConfig()));
|
|
5714
5739
|
|
|
5740
|
+
// src/clientHeaders.ts
|
|
5741
|
+
function normalizeHeaders(headers) {
|
|
5742
|
+
if (headers instanceof Headers || Array.isArray(headers)) {
|
|
5743
|
+
const normalized = /* @__PURE__ */ Object.create(null);
|
|
5744
|
+
new Headers(headers).forEach((value, name) => {
|
|
5745
|
+
normalized[name] = value;
|
|
5746
|
+
});
|
|
5747
|
+
return normalized;
|
|
5748
|
+
}
|
|
5749
|
+
return headers;
|
|
5750
|
+
}
|
|
5751
|
+
|
|
5715
5752
|
// src/client/sdk.gen.ts
|
|
5716
5753
|
var getApiV1CreditsBalance = (options) => (options?.client ?? client).get({ url: "/api/v1/credits/balance", ...options });
|
|
5717
5754
|
var getApiV1CreditsPacks = (options) => (options?.client ?? client).get({ url: "/api/v1/credits/packs", ...options });
|
|
@@ -5720,7 +5757,7 @@ var postApiV1CreditsPurchase = (options) => (options.client ?? client).post({
|
|
|
5720
5757
|
...options,
|
|
5721
5758
|
headers: {
|
|
5722
5759
|
"Content-Type": "application/json",
|
|
5723
|
-
...options.headers
|
|
5760
|
+
...normalizeHeaders(options.headers)
|
|
5724
5761
|
}
|
|
5725
5762
|
});
|
|
5726
5763
|
var postApiV1Embeddings = (options) => (options.client ?? client).post({
|
|
@@ -5728,7 +5765,7 @@ var postApiV1Embeddings = (options) => (options.client ?? client).post({
|
|
|
5728
5765
|
...options,
|
|
5729
5766
|
headers: {
|
|
5730
5767
|
"Content-Type": "application/json",
|
|
5731
|
-
...options.headers
|
|
5768
|
+
...normalizeHeaders(options.headers)
|
|
5732
5769
|
}
|
|
5733
5770
|
});
|
|
5734
5771
|
var getApiV1Models = (options) => (options?.client ?? client).get({ url: "/api/v1/models", ...options });
|
|
@@ -14971,6 +15008,16 @@ async function updateVaultMemoryOp(ctx, id2, opts) {
|
|
|
14971
15008
|
const probe = await ctx.vaultMemoryCollection.find(id2);
|
|
14972
15009
|
if (probe.isDeleted || probe.supersededBy || !isOwnedByCtxUser(ctx, probe)) return null;
|
|
14973
15010
|
if (opts.freeFormOnly && isKinded(probe)) return null;
|
|
15011
|
+
const readStoredContent = probe._getRaw("content");
|
|
15012
|
+
if (opts.expectedContent !== void 0) {
|
|
15013
|
+
const current = await vaultMemoryToStored(
|
|
15014
|
+
probe,
|
|
15015
|
+
ctx.walletAddress,
|
|
15016
|
+
ctx.signMessage,
|
|
15017
|
+
ctx.embeddedWalletSigner
|
|
15018
|
+
);
|
|
15019
|
+
if (current.content !== opts.expectedContent) return null;
|
|
15020
|
+
}
|
|
14974
15021
|
const levelAfter = (current) => {
|
|
14975
15022
|
if (opts.level !== void 0) return opts.level;
|
|
14976
15023
|
if (opts.scope === void 0) return resolveMemoryLevel(current.level, current.scope);
|
|
@@ -14978,7 +15025,7 @@ async function updateVaultMemoryOp(ctx, id2, opts) {
|
|
|
14978
15025
|
};
|
|
14979
15026
|
assertValidKindLevel(opts.kind !== void 0 ? opts.kind : probe.kind, levelAfter(probe));
|
|
14980
15027
|
const encryptedKindValue = await encryptKindValue(ctx, opts.kindValue);
|
|
14981
|
-
const encryptedContent = ctx.walletAddress && ctx.signMessage ? await encryptVaultMemoryContent(
|
|
15028
|
+
const encryptedContent = opts.content !== void 0 && ctx.walletAddress && ctx.signMessage ? await encryptVaultMemoryContent(
|
|
14982
15029
|
opts.content,
|
|
14983
15030
|
ctx.walletAddress,
|
|
14984
15031
|
ctx.signMessage,
|
|
@@ -14986,13 +15033,13 @@ async function updateVaultMemoryOp(ctx, id2, opts) {
|
|
|
14986
15033
|
) : opts.content;
|
|
14987
15034
|
let stale = false;
|
|
14988
15035
|
const record2 = probe;
|
|
14989
|
-
const originalUpdatedAt = record2.updatedAt.getTime();
|
|
14990
15036
|
await ctx.database.write(async () => {
|
|
14991
15037
|
await assertCanWrite2(ctx);
|
|
14992
|
-
if (record2.isDeleted || record2.supersededBy || !isOwnedByCtxUser(ctx, record2) || opts.freeFormOnly && isKinded(record2)) {
|
|
15038
|
+
if (record2.isDeleted || record2.supersededBy || !isOwnedByCtxUser(ctx, record2) || opts.freeFormOnly && isKinded(record2) || opts.expectedContent !== void 0 && record2._getRaw("content") !== readStoredContent) {
|
|
14993
15039
|
stale = true;
|
|
14994
15040
|
return;
|
|
14995
15041
|
}
|
|
15042
|
+
const originalUpdatedAt = record2.updatedAt.getTime();
|
|
14996
15043
|
const nextKind = opts.kind !== void 0 ? opts.kind : record2.kind;
|
|
14997
15044
|
const nextLevel = levelAfter(record2);
|
|
14998
15045
|
assertValidKindLevel(nextKind, nextLevel);
|
|
@@ -15008,7 +15055,7 @@ async function updateVaultMemoryOp(ctx, id2, opts) {
|
|
|
15008
15055
|
replayedObservation = opts.observationSourceIds.every((id3) => observedSources.includes(id3));
|
|
15009
15056
|
}
|
|
15010
15057
|
await record2.update((r) => {
|
|
15011
|
-
r._setRaw("content", encryptedContent);
|
|
15058
|
+
if (encryptedContent !== void 0) r._setRaw("content", encryptedContent);
|
|
15012
15059
|
if (opts.level !== void 0) {
|
|
15013
15060
|
r._setRaw("level", nextLevel);
|
|
15014
15061
|
r._setRaw("scope", scopeForLevel(nextLevel));
|
|
@@ -15776,7 +15823,7 @@ function classifyDecay(m, now, policy) {
|
|
|
15776
15823
|
if (m.source === "manual" || m.source === SOURCE_PHOTO) return "keep";
|
|
15777
15824
|
if (isTimeSensitiveType(m.factType) && m.eventTimeEnd !== null) {
|
|
15778
15825
|
if (m.eventTimeEnd < now - resolved.pastEventGraceMs) return "archive";
|
|
15779
|
-
|
|
15826
|
+
return "keep";
|
|
15780
15827
|
}
|
|
15781
15828
|
if (now - lastActivityAt(m) > ttlForType(m.factType, resolved)) return "archive";
|
|
15782
15829
|
return "keep";
|
|
@@ -18832,7 +18879,6 @@ async function retainWithPersistence(content, ctx, options = {}) {
|
|
|
18832
18879
|
const factTypeUpdate = pickFactTypeUpdate(existing, options.factType);
|
|
18833
18880
|
const resurrect = resurrectFields(existing);
|
|
18834
18881
|
const updated = await ctx.persistence.update(targetId, {
|
|
18835
|
-
content: existing.content,
|
|
18836
18882
|
freeFormOnly: true,
|
|
18837
18883
|
proofCountIncrement: 1,
|
|
18838
18884
|
observationSourceIds: options.sourceChunkIds,
|
|
@@ -19071,7 +19117,6 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
|
|
|
19071
19117
|
const factTypeUpdate = pickFactTypeUpdate(existing, options.factType);
|
|
19072
19118
|
const resurrect = resurrectFields(existing);
|
|
19073
19119
|
const updated = await ctx.persistence.update(decision.targetId, {
|
|
19074
|
-
content: existing.content,
|
|
19075
19120
|
freeFormOnly: true,
|
|
19076
19121
|
proofCountIncrement: 1,
|
|
19077
19122
|
observationSourceIds: options.sourceChunkIds,
|
|
@@ -19099,6 +19144,10 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
|
|
|
19099
19144
|
};
|
|
19100
19145
|
}
|
|
19101
19146
|
if (decision.action === "update" && decision.targetId && decision.content) {
|
|
19147
|
+
const expectedContent = candidates.find(
|
|
19148
|
+
(candidate) => candidate.id === decision.targetId
|
|
19149
|
+
)?.content;
|
|
19150
|
+
if (expectedContent === void 0) return null;
|
|
19102
19151
|
const existing = await ctx.persistence.get(decision.targetId);
|
|
19103
19152
|
if (!existing || existing.supersededBy) {
|
|
19104
19153
|
return abandonToRace(
|
|
@@ -19106,6 +19155,9 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
|
|
|
19106
19155
|
`update: target ${decision.targetId} ${existing ? "superseded" : "deleted"} before the write`
|
|
19107
19156
|
);
|
|
19108
19157
|
}
|
|
19158
|
+
if (existing.content !== expectedContent) {
|
|
19159
|
+
return abandonToRace(options, `update: target ${decision.targetId} edited before the write`);
|
|
19160
|
+
}
|
|
19109
19161
|
const mergedSourceIds = unionStrings(
|
|
19110
19162
|
existing.sourceChunkIds ?? [],
|
|
19111
19163
|
options.sourceChunkIds ?? []
|
|
@@ -19118,6 +19170,7 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
|
|
|
19118
19170
|
const resurrect = resurrectFields(existing);
|
|
19119
19171
|
const updated = await ctx.persistence.update(decision.targetId, {
|
|
19120
19172
|
content: decision.content,
|
|
19173
|
+
expectedContent,
|
|
19121
19174
|
freeFormOnly: true,
|
|
19122
19175
|
proofCountIncrement: 1,
|
|
19123
19176
|
observationSourceIds: options.sourceChunkIds,
|
|
@@ -19130,10 +19183,10 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
|
|
|
19130
19183
|
...factTypeUpdate !== void 0 && { factType: factTypeUpdate }
|
|
19131
19184
|
});
|
|
19132
19185
|
if (!updated) {
|
|
19133
|
-
await assertMergeTargetGoneOrThrow(ctx, decision.targetId);
|
|
19186
|
+
await assertMergeTargetGoneOrThrow(ctx, decision.targetId, expectedContent);
|
|
19134
19187
|
return abandonToRace(
|
|
19135
19188
|
options,
|
|
19136
|
-
`update: target ${decision.targetId}
|
|
19189
|
+
`update: target ${decision.targetId} changed mid-write (consolidated rewrite lost)`
|
|
19137
19190
|
);
|
|
19138
19191
|
}
|
|
19139
19192
|
cacheRowVector(
|
|
@@ -19160,9 +19213,9 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
|
|
|
19160
19213
|
);
|
|
19161
19214
|
return null;
|
|
19162
19215
|
}
|
|
19163
|
-
async function assertMergeTargetGoneOrThrow(ctx, targetId) {
|
|
19216
|
+
async function assertMergeTargetGoneOrThrow(ctx, targetId, expectedContent) {
|
|
19164
19217
|
const stillExists = await (ctx.persistence.getFresh ? ctx.persistence.getFresh(targetId) : ctx.persistence.get(targetId));
|
|
19165
|
-
if (stillExists && (stillExists.kind === null || stillExists.kind === void 0)) {
|
|
19218
|
+
if (stillExists && (stillExists.kind === null || stillExists.kind === void 0) && (expectedContent === void 0 || stillExists.content === expectedContent)) {
|
|
19166
19219
|
throw new RetainError(
|
|
19167
19220
|
"merge-not-persisted",
|
|
19168
19221
|
`retain: merge into memory ${targetId} failed to persist`
|
|
@@ -22574,16 +22627,16 @@ function createRemoteMemoryPipeline(options) {
|
|
|
22574
22627
|
create: (input) => write(createRow(input), 0),
|
|
22575
22628
|
update: async (id2, patch) => {
|
|
22576
22629
|
const existing = await get(id2);
|
|
22577
|
-
if (!existing || patch.freeFormOnly && existing.kind !== null && existing.kind !== void 0)
|
|
22630
|
+
if (!existing || patch.expectedContent !== void 0 && existing.content !== patch.expectedContent || patch.freeFormOnly && existing.kind !== null && existing.kind !== void 0)
|
|
22578
22631
|
return null;
|
|
22579
22632
|
const snapshot = snapshots.get(id2);
|
|
22580
22633
|
const memory = {
|
|
22581
22634
|
...snapshot.memory,
|
|
22582
|
-
content: patch.content,
|
|
22635
|
+
content: patch.content ?? snapshot.memory.content,
|
|
22583
22636
|
updated_at: patch.preserveUpdatedAt ? snapshot.memory.updated_at : Math.max(Date.now(), (snapshot.memory.topics_extracted_at ?? 0) + 1)
|
|
22584
22637
|
};
|
|
22585
22638
|
if (patch.scope !== void 0) memory.scope = patch.scope;
|
|
22586
|
-
if (patch.embedding === void 0 && patch.content !== snapshot.memory.content) {
|
|
22639
|
+
if (patch.embedding === void 0 && patch.content !== void 0 && patch.content !== snapshot.memory.content) {
|
|
22587
22640
|
delete memory.embedding;
|
|
22588
22641
|
delete memory.embedding_model;
|
|
22589
22642
|
}
|
package/dist/expo/index.d.mts
CHANGED
|
@@ -5669,7 +5669,8 @@ interface CreateVaultMemoryOptions {
|
|
|
5669
5669
|
geohash?: string;
|
|
5670
5670
|
}
|
|
5671
5671
|
interface UpdateVaultMemoryOptions {
|
|
5672
|
-
content
|
|
5672
|
+
content?: string;
|
|
5673
|
+
expectedContent?: string;
|
|
5673
5674
|
/** When true, the write is skipped (returns null) if the row carries a profile kind. */
|
|
5674
5675
|
freeFormOnly?: boolean;
|
|
5675
5676
|
/**
|
|
@@ -6273,9 +6274,10 @@ declare function ttlForType(factType: string | null, policy?: Partial<DecayPolic
|
|
|
6273
6274
|
* null `eventTimeEnd` is still ongoing, so this rule does not fire for it.
|
|
6274
6275
|
* 4. Age fallback — `now - updatedAt > TTL(factType)` → archive. Durable types
|
|
6275
6276
|
* have Infinity TTL, so this never fires for them; null/unknown use medium.
|
|
6276
|
-
* EXCEPTION: a `plan
|
|
6277
|
-
* (`eventTimeEnd >= now
|
|
6278
|
-
*
|
|
6277
|
+
* EXCEPTION: a `plan` / `ongoing_context` with an upcoming event or an event
|
|
6278
|
+
* within the grace period (`eventTimeEnd >= now - pastEventGraceMs`) stays
|
|
6279
|
+
* active, even after its activity TTL expires. Rule 3 archives it after the
|
|
6280
|
+
* grace period ends.
|
|
6279
6281
|
* 5. Otherwise → keep.
|
|
6280
6282
|
*
|
|
6281
6283
|
* @param m Plaintext decay inputs for one row.
|
|
@@ -6606,7 +6608,9 @@ type MemoryCreate = Pick<CreateVaultMemoryOptions, "content" | "scope" | "factTy
|
|
|
6606
6608
|
* `embedding` (with `embeddingModel`) only when you already have the new one.
|
|
6607
6609
|
* @public
|
|
6608
6610
|
*/
|
|
6609
|
-
type MemoryUpdate = Pick<UpdateVaultMemoryOptions, "
|
|
6611
|
+
type MemoryUpdate = Pick<UpdateVaultMemoryOptions, "scope" | "factType" | "eventTime" | "embedding" | "embeddingModel" | "kind" | "kindValue" | "level"> & {
|
|
6612
|
+
content: string;
|
|
6613
|
+
};
|
|
6610
6614
|
/**
|
|
6611
6615
|
* Fact-only recall. Conversation chunks are message storage, not memory, so
|
|
6612
6616
|
* the chunk-lane knobs are not part of this surface; nor is `folderId` (see
|
package/dist/expo/index.d.ts
CHANGED
|
@@ -5669,7 +5669,8 @@ interface CreateVaultMemoryOptions {
|
|
|
5669
5669
|
geohash?: string;
|
|
5670
5670
|
}
|
|
5671
5671
|
interface UpdateVaultMemoryOptions {
|
|
5672
|
-
content
|
|
5672
|
+
content?: string;
|
|
5673
|
+
expectedContent?: string;
|
|
5673
5674
|
/** When true, the write is skipped (returns null) if the row carries a profile kind. */
|
|
5674
5675
|
freeFormOnly?: boolean;
|
|
5675
5676
|
/**
|
|
@@ -6273,9 +6274,10 @@ declare function ttlForType(factType: string | null, policy?: Partial<DecayPolic
|
|
|
6273
6274
|
* null `eventTimeEnd` is still ongoing, so this rule does not fire for it.
|
|
6274
6275
|
* 4. Age fallback — `now - updatedAt > TTL(factType)` → archive. Durable types
|
|
6275
6276
|
* have Infinity TTL, so this never fires for them; null/unknown use medium.
|
|
6276
|
-
* EXCEPTION: a `plan
|
|
6277
|
-
* (`eventTimeEnd >= now
|
|
6278
|
-
*
|
|
6277
|
+
* EXCEPTION: a `plan` / `ongoing_context` with an upcoming event or an event
|
|
6278
|
+
* within the grace period (`eventTimeEnd >= now - pastEventGraceMs`) stays
|
|
6279
|
+
* active, even after its activity TTL expires. Rule 3 archives it after the
|
|
6280
|
+
* grace period ends.
|
|
6279
6281
|
* 5. Otherwise → keep.
|
|
6280
6282
|
*
|
|
6281
6283
|
* @param m Plaintext decay inputs for one row.
|
|
@@ -6606,7 +6608,9 @@ type MemoryCreate = Pick<CreateVaultMemoryOptions, "content" | "scope" | "factTy
|
|
|
6606
6608
|
* `embedding` (with `embeddingModel`) only when you already have the new one.
|
|
6607
6609
|
* @public
|
|
6608
6610
|
*/
|
|
6609
|
-
type MemoryUpdate = Pick<UpdateVaultMemoryOptions, "
|
|
6611
|
+
type MemoryUpdate = Pick<UpdateVaultMemoryOptions, "scope" | "factType" | "eventTime" | "embedding" | "embeddingModel" | "kind" | "kindValue" | "level"> & {
|
|
6612
|
+
content: string;
|
|
6613
|
+
};
|
|
6610
6614
|
/**
|
|
6611
6615
|
* Fact-only recall. Conversation chunks are message storage, not memory, so
|
|
6612
6616
|
* the chunk-lane knobs are not part of this surface; nor is `folderId` (see
|