@anuma/sdk 6.30.1 → 6.31.0
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/{chunk-N5CKISI3.mjs → chunk-XD6WOQ5I.mjs} +50 -7
- package/dist/expo/{consolidate-N56RXPCW.mjs → consolidate-7DBUHQRK.mjs} +1 -1
- package/dist/expo/index.cjs +173 -56
- package/dist/expo/index.d.mts +39 -19
- package/dist/expo/index.d.ts +39 -19
- package/dist/expo/index.mjs +124 -50
- package/dist/index.cjs +19 -3
- package/dist/index.d.mts +19 -8
- package/dist/index.d.ts +19 -8
- package/dist/index.mjs +19 -3
- package/dist/react/{chunk-LBIKGBXE.mjs → chunk-XNQRJBIH.mjs} +50 -7
- package/dist/react/{consolidate-2NLZAEWR.mjs → consolidate-5DVINCUE.mjs} +1 -1
- package/dist/react/index.cjs +173 -56
- package/dist/react/index.d.mts +39 -19
- package/dist/react/index.d.ts +39 -19
- package/dist/react/index.mjs +124 -50
- package/dist/server/{chunk-Z2QBL4HB.mjs → chunk-KSYV7UO2.mjs} +49 -6
- package/dist/server/{consolidate-QWVI25WQ.mjs → consolidate-MCNBSUXD.mjs} +1 -1
- package/dist/server/index.cjs +157 -46
- package/dist/server/index.d.mts +35 -11
- package/dist/server/index.d.ts +35 -11
- package/dist/server/index.mjs +109 -41
- package/dist/tools/index.cjs +18 -2
- package/dist/tools/index.d.mts +15 -0
- package/dist/tools/index.d.ts +15 -0
- package/dist/tools/index.mjs +18 -2
- package/dist/tools/selection/index.cjs +24 -2
- package/dist/tools/selection/index.d.mts +15 -0
- package/dist/tools/selection/index.d.ts +15 -0
- package/dist/tools/selection/index.mjs +24 -2
- package/package.json +2 -2
|
@@ -19,12 +19,28 @@ var noopLogger = {
|
|
|
19
19
|
error: () => {
|
|
20
20
|
}
|
|
21
21
|
};
|
|
22
|
-
var
|
|
22
|
+
var LOGGER_STATE_KEY = /* @__PURE__ */ Symbol.for("@anuma/sdk/logger/v1");
|
|
23
|
+
var loggerGlobal = globalThis;
|
|
24
|
+
var fallbackLoggerState = { logger: consoleLogger };
|
|
25
|
+
var fallbackWarned = false;
|
|
26
|
+
function getLoggerState() {
|
|
27
|
+
try {
|
|
28
|
+
return loggerGlobal[LOGGER_STATE_KEY] ?? (loggerGlobal[LOGGER_STATE_KEY] = fallbackLoggerState);
|
|
29
|
+
} catch {
|
|
30
|
+
if (!fallbackWarned) {
|
|
31
|
+
fallbackWarned = true;
|
|
32
|
+
fallbackLoggerState.logger.warn(
|
|
33
|
+
"@anuma/sdk: the global object rejects new properties. This entrypoint keeps its own logger, so setLogger does not reach other entrypoints."
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
return fallbackLoggerState;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
23
39
|
function setLogger(logger) {
|
|
24
|
-
|
|
40
|
+
getLoggerState().logger = logger;
|
|
25
41
|
}
|
|
26
42
|
function getLogger() {
|
|
27
|
-
return
|
|
43
|
+
return getLoggerState().logger;
|
|
28
44
|
}
|
|
29
45
|
|
|
30
46
|
// src/lib/pii/patterns.ts
|
|
@@ -726,13 +742,21 @@ function responsesExtra(extra) {
|
|
|
726
742
|
}
|
|
727
743
|
return out;
|
|
728
744
|
}
|
|
745
|
+
function splitEndpoint(endpoint) {
|
|
746
|
+
const cut = endpoint.search(/[?#]/);
|
|
747
|
+
const rawPath = cut === -1 ? endpoint : endpoint.slice(0, cut);
|
|
748
|
+
return {
|
|
749
|
+
path: rawPath.replace(/\/+$/, ""),
|
|
750
|
+
rest: cut === -1 ? "" : endpoint.slice(cut)
|
|
751
|
+
};
|
|
752
|
+
}
|
|
729
753
|
var FOREIGN_ENDPOINT_SUFFIX = {
|
|
730
754
|
chat: "/responses",
|
|
731
755
|
responses: "/chat/completions"
|
|
732
756
|
};
|
|
733
757
|
function assertTransportMatchesEndpoint(transport, endpoint) {
|
|
734
758
|
const foreign = FOREIGN_ENDPOINT_SUFFIX[transport];
|
|
735
|
-
if (!endpoint.endsWith(foreign)) return;
|
|
759
|
+
if (!splitEndpoint(endpoint).path.endsWith(foreign)) return;
|
|
736
760
|
throw new Error(
|
|
737
761
|
`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.`
|
|
738
762
|
);
|
|
@@ -778,14 +802,20 @@ async function resolvePortalAuthHeaders(auth, tag) {
|
|
|
778
802
|
}
|
|
779
803
|
async function callPortalJsonCompletion(req) {
|
|
780
804
|
const log = getLogger();
|
|
781
|
-
|
|
805
|
+
const transport = req.transport ?? (requiresResponsesTransport(req.model) ? "responses" : "chat");
|
|
806
|
+
const autoUpgraded = req.transport === void 0 && transport === "responses";
|
|
807
|
+
let endpoint = transport === "responses" ? "/api/v1/responses" : "/api/v1/chat/completions";
|
|
782
808
|
if (req.endpointOverride !== void 0) {
|
|
783
809
|
const overrideValidation = validateEndpointOverride(req.endpointOverride);
|
|
784
810
|
if (!overrideValidation.valid) {
|
|
785
811
|
throw new Error(overrideValidation.message);
|
|
786
812
|
}
|
|
787
813
|
endpoint = overrideValidation.endpoint;
|
|
788
|
-
|
|
814
|
+
const { path, rest } = splitEndpoint(endpoint);
|
|
815
|
+
if (autoUpgraded && path.endsWith("/chat/completions")) {
|
|
816
|
+
endpoint = `${path.slice(0, -"/chat/completions".length)}/responses${rest}`;
|
|
817
|
+
}
|
|
818
|
+
assertTransportMatchesEndpoint(transport, endpoint);
|
|
789
819
|
}
|
|
790
820
|
const maxAttempts = Math.max(1, req.maxAttempts ?? 3);
|
|
791
821
|
const startedAt = Date.now();
|
|
@@ -810,7 +840,10 @@ async function callPortalJsonCompletion(req) {
|
|
|
810
840
|
),
|
|
811
841
|
...reinforce && { reinforceJsonContract: true }
|
|
812
842
|
} : reinforce ? { ...req, reinforceJsonContract: true } : req;
|
|
813
|
-
const outcome = await attemptPortalJson(
|
|
843
|
+
const outcome = await attemptPortalJson(
|
|
844
|
+
{ ...attemptReq, transport },
|
|
845
|
+
endpoint
|
|
846
|
+
);
|
|
814
847
|
if (outcome.kind === "ok") {
|
|
815
848
|
req.onAttempt?.({ attempt, ok: true });
|
|
816
849
|
return outcome.value;
|
|
@@ -962,6 +995,13 @@ async function attemptPortalJson(req, endpoint) {
|
|
|
962
995
|
}
|
|
963
996
|
clearTimeout(timer);
|
|
964
997
|
logPortalUsage(body, req.tag);
|
|
998
|
+
if (isModerationResponse(body)) {
|
|
999
|
+
return {
|
|
1000
|
+
kind: "terminal",
|
|
1001
|
+
code: "content-flagged",
|
|
1002
|
+
reason: "portal moderation refused the request"
|
|
1003
|
+
};
|
|
1004
|
+
}
|
|
965
1005
|
const rawContent = extractCompletionContent(body);
|
|
966
1006
|
if (!rawContent) {
|
|
967
1007
|
return {
|
|
@@ -1047,6 +1087,9 @@ function logPortalUsage(body, tag) {
|
|
|
1047
1087
|
} catch {
|
|
1048
1088
|
}
|
|
1049
1089
|
}
|
|
1090
|
+
function isModerationResponse(body) {
|
|
1091
|
+
return typeof body === "object" && body !== null && body.id === "moderation";
|
|
1092
|
+
}
|
|
1050
1093
|
function extractCompletionContent(body) {
|
|
1051
1094
|
if (typeof body !== "object" || body === null) return null;
|
|
1052
1095
|
const responsesText = extractResponsesContent(body);
|
package/dist/react/index.cjs
CHANGED
|
@@ -76,13 +76,26 @@ var init_clientConfig = __esm({
|
|
|
76
76
|
});
|
|
77
77
|
|
|
78
78
|
// src/lib/logger.ts
|
|
79
|
+
function getLoggerState() {
|
|
80
|
+
try {
|
|
81
|
+
return loggerGlobal[LOGGER_STATE_KEY] ?? (loggerGlobal[LOGGER_STATE_KEY] = fallbackLoggerState);
|
|
82
|
+
} catch {
|
|
83
|
+
if (!fallbackWarned) {
|
|
84
|
+
fallbackWarned = true;
|
|
85
|
+
fallbackLoggerState.logger.warn(
|
|
86
|
+
"@anuma/sdk: the global object rejects new properties. This entrypoint keeps its own logger, so setLogger does not reach other entrypoints."
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
return fallbackLoggerState;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
79
92
|
function setLogger(logger) {
|
|
80
|
-
|
|
93
|
+
getLoggerState().logger = logger;
|
|
81
94
|
}
|
|
82
95
|
function getLogger() {
|
|
83
|
-
return
|
|
96
|
+
return getLoggerState().logger;
|
|
84
97
|
}
|
|
85
|
-
var consoleLogger, noopLogger,
|
|
98
|
+
var consoleLogger, noopLogger, LOGGER_STATE_KEY, loggerGlobal, fallbackLoggerState, fallbackWarned;
|
|
86
99
|
var init_logger = __esm({
|
|
87
100
|
"src/lib/logger.ts"() {
|
|
88
101
|
"use strict";
|
|
@@ -102,7 +115,10 @@ var init_logger = __esm({
|
|
|
102
115
|
error: () => {
|
|
103
116
|
}
|
|
104
117
|
};
|
|
105
|
-
|
|
118
|
+
LOGGER_STATE_KEY = /* @__PURE__ */ Symbol.for("@anuma/sdk/logger/v1");
|
|
119
|
+
loggerGlobal = globalThis;
|
|
120
|
+
fallbackLoggerState = { logger: consoleLogger };
|
|
121
|
+
fallbackWarned = false;
|
|
106
122
|
}
|
|
107
123
|
});
|
|
108
124
|
|
|
@@ -828,9 +844,17 @@ function responsesExtra(extra) {
|
|
|
828
844
|
}
|
|
829
845
|
return out;
|
|
830
846
|
}
|
|
847
|
+
function splitEndpoint(endpoint) {
|
|
848
|
+
const cut = endpoint.search(/[?#]/);
|
|
849
|
+
const rawPath = cut === -1 ? endpoint : endpoint.slice(0, cut);
|
|
850
|
+
return {
|
|
851
|
+
path: rawPath.replace(/\/+$/, ""),
|
|
852
|
+
rest: cut === -1 ? "" : endpoint.slice(cut)
|
|
853
|
+
};
|
|
854
|
+
}
|
|
831
855
|
function assertTransportMatchesEndpoint(transport, endpoint) {
|
|
832
856
|
const foreign = FOREIGN_ENDPOINT_SUFFIX[transport];
|
|
833
|
-
if (!endpoint.endsWith(foreign)) return;
|
|
857
|
+
if (!splitEndpoint(endpoint).path.endsWith(foreign)) return;
|
|
834
858
|
throw new Error(
|
|
835
859
|
`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.`
|
|
836
860
|
);
|
|
@@ -875,14 +899,20 @@ async function resolvePortalAuthHeaders(auth, tag) {
|
|
|
875
899
|
}
|
|
876
900
|
async function callPortalJsonCompletion(req) {
|
|
877
901
|
const log = getLogger();
|
|
878
|
-
|
|
902
|
+
const transport = req.transport ?? (requiresResponsesTransport(req.model) ? "responses" : "chat");
|
|
903
|
+
const autoUpgraded = req.transport === void 0 && transport === "responses";
|
|
904
|
+
let endpoint = transport === "responses" ? "/api/v1/responses" : "/api/v1/chat/completions";
|
|
879
905
|
if (req.endpointOverride !== void 0) {
|
|
880
906
|
const overrideValidation = validateEndpointOverride(req.endpointOverride);
|
|
881
907
|
if (!overrideValidation.valid) {
|
|
882
908
|
throw new Error(overrideValidation.message);
|
|
883
909
|
}
|
|
884
910
|
endpoint = overrideValidation.endpoint;
|
|
885
|
-
|
|
911
|
+
const { path, rest } = splitEndpoint(endpoint);
|
|
912
|
+
if (autoUpgraded && path.endsWith("/chat/completions")) {
|
|
913
|
+
endpoint = `${path.slice(0, -"/chat/completions".length)}/responses${rest}`;
|
|
914
|
+
}
|
|
915
|
+
assertTransportMatchesEndpoint(transport, endpoint);
|
|
886
916
|
}
|
|
887
917
|
const maxAttempts = Math.max(1, req.maxAttempts ?? 3);
|
|
888
918
|
const startedAt = Date.now();
|
|
@@ -907,7 +937,10 @@ async function callPortalJsonCompletion(req) {
|
|
|
907
937
|
),
|
|
908
938
|
...reinforce && { reinforceJsonContract: true }
|
|
909
939
|
} : reinforce ? { ...req, reinforceJsonContract: true } : req;
|
|
910
|
-
const outcome = await attemptPortalJson(
|
|
940
|
+
const outcome = await attemptPortalJson(
|
|
941
|
+
{ ...attemptReq, transport },
|
|
942
|
+
endpoint
|
|
943
|
+
);
|
|
911
944
|
if (outcome.kind === "ok") {
|
|
912
945
|
req.onAttempt?.({ attempt, ok: true });
|
|
913
946
|
return outcome.value;
|
|
@@ -1059,6 +1092,13 @@ async function attemptPortalJson(req, endpoint) {
|
|
|
1059
1092
|
}
|
|
1060
1093
|
clearTimeout(timer);
|
|
1061
1094
|
logPortalUsage(body, req.tag);
|
|
1095
|
+
if (isModerationResponse(body)) {
|
|
1096
|
+
return {
|
|
1097
|
+
kind: "terminal",
|
|
1098
|
+
code: "content-flagged",
|
|
1099
|
+
reason: "portal moderation refused the request"
|
|
1100
|
+
};
|
|
1101
|
+
}
|
|
1062
1102
|
const rawContent = extractCompletionContent(body);
|
|
1063
1103
|
if (!rawContent) {
|
|
1064
1104
|
return {
|
|
@@ -1144,6 +1184,9 @@ function logPortalUsage(body, tag) {
|
|
|
1144
1184
|
} catch {
|
|
1145
1185
|
}
|
|
1146
1186
|
}
|
|
1187
|
+
function isModerationResponse(body) {
|
|
1188
|
+
return typeof body === "object" && body !== null && body.id === "moderation";
|
|
1189
|
+
}
|
|
1147
1190
|
function extractCompletionContent(body) {
|
|
1148
1191
|
if (typeof body !== "object" || body === null) return null;
|
|
1149
1192
|
const responsesText = extractResponsesContent(body);
|
|
@@ -4169,6 +4212,9 @@ async function updateMessageEmbeddingOp(ctx, uniqueId, vector, embeddingModel) {
|
|
|
4169
4212
|
await ctx.database.write(async () => {
|
|
4170
4213
|
await message.update((msg) => {
|
|
4171
4214
|
msg._setRaw("vector", JSON.stringify(vector));
|
|
4215
|
+
if (msg.origin === "chunks_discarded" && vector.length > 0) {
|
|
4216
|
+
msg._setRaw("origin", "message");
|
|
4217
|
+
}
|
|
4172
4218
|
msg._setRaw("embedding_model", embeddingModel);
|
|
4173
4219
|
});
|
|
4174
4220
|
});
|
|
@@ -4185,6 +4231,9 @@ async function updateMessageChunksOp(ctx, uniqueId, chunks, embeddingModel) {
|
|
|
4185
4231
|
await ctx.database.write(async () => {
|
|
4186
4232
|
await message.update((msg) => {
|
|
4187
4233
|
msg._setRaw("chunks", JSON.stringify(storedChunks));
|
|
4234
|
+
if (msg.origin === "chunks_discarded" && storedChunks.length > 0 && storedChunks.every((chunk) => chunk.vector.length > 0)) {
|
|
4235
|
+
msg._setRaw("origin", "message");
|
|
4236
|
+
}
|
|
4188
4237
|
msg._setRaw("embedding_model", embeddingModel);
|
|
4189
4238
|
});
|
|
4190
4239
|
});
|
|
@@ -6336,6 +6385,9 @@ function clientToolToResponsesFormat(tool) {
|
|
|
6336
6385
|
...toolConfig.removeAfterExecution !== void 0 && {
|
|
6337
6386
|
removeAfterExecution: toolConfig.removeAfterExecution
|
|
6338
6387
|
},
|
|
6388
|
+
...toolConfig.removeAfterResult !== void 0 && {
|
|
6389
|
+
removeAfterResult: toolConfig.removeAfterResult
|
|
6390
|
+
},
|
|
6339
6391
|
...toolConfig.executorTimeout !== void 0 && {
|
|
6340
6392
|
executorTimeout: toolConfig.executorTimeout
|
|
6341
6393
|
},
|
|
@@ -6369,6 +6421,9 @@ function clientToolToCompletionsFormat(tool) {
|
|
|
6369
6421
|
...toolConfig.removeAfterExecution !== void 0 && {
|
|
6370
6422
|
removeAfterExecution: toolConfig.removeAfterExecution
|
|
6371
6423
|
},
|
|
6424
|
+
...toolConfig.removeAfterResult !== void 0 && {
|
|
6425
|
+
removeAfterResult: toolConfig.removeAfterResult
|
|
6426
|
+
},
|
|
6372
6427
|
...toolConfig.executorTimeout !== void 0 && {
|
|
6373
6428
|
executorTimeout: toolConfig.executorTimeout
|
|
6374
6429
|
},
|
|
@@ -7351,6 +7406,7 @@ function toolsToApiFormat(tools, apiType) {
|
|
|
7351
7406
|
executor: _executor,
|
|
7352
7407
|
skipContinuation: _skipContinuation,
|
|
7353
7408
|
removeAfterExecution: _removeAfterExecution,
|
|
7409
|
+
removeAfterResult: _removeAfterResult,
|
|
7354
7410
|
executorTimeout: _executorTimeout,
|
|
7355
7411
|
dependsOn: _dependsOn,
|
|
7356
7412
|
deAnonymizeArgs: _deAnonymizeArgs,
|
|
@@ -9795,9 +9851,11 @@ Executing tool: ${toolInfo}
|
|
|
9795
9851
|
}
|
|
9796
9852
|
if (tools && apiTools) {
|
|
9797
9853
|
const successfullyExecutedNames = /* @__PURE__ */ new Set();
|
|
9854
|
+
const successfulResults = [];
|
|
9798
9855
|
for (const r of executionResults) {
|
|
9799
9856
|
if (!r.error && !isToolErrorResult(r.result) && "name" in r && r.name) {
|
|
9800
9857
|
successfullyExecutedNames.add(r.name);
|
|
9858
|
+
successfulResults.push(r.result);
|
|
9801
9859
|
}
|
|
9802
9860
|
}
|
|
9803
9861
|
if (successfullyExecutedNames.size > 0) {
|
|
@@ -9806,7 +9864,15 @@ Executing tool: ${toolInfo}
|
|
|
9806
9864
|
const tc = t;
|
|
9807
9865
|
const func = tc.function;
|
|
9808
9866
|
const toolName = typeof func?.name === "string" ? func.name : typeof tc.name === "string" ? tc.name : void 0;
|
|
9809
|
-
if (
|
|
9867
|
+
if (!toolName) continue;
|
|
9868
|
+
const removeAfterResult = tc.removeAfterResult;
|
|
9869
|
+
if (tc.removeAfterExecution === true && successfullyExecutedNames.has(toolName) || typeof removeAfterResult === "function" && successfulResults.some((result) => {
|
|
9870
|
+
try {
|
|
9871
|
+
return removeAfterResult(result);
|
|
9872
|
+
} catch {
|
|
9873
|
+
return false;
|
|
9874
|
+
}
|
|
9875
|
+
})) {
|
|
9810
9876
|
toolsToRemove.add(toolName);
|
|
9811
9877
|
}
|
|
9812
9878
|
}
|
|
@@ -14894,7 +14960,7 @@ async function getMemoriesNeedingTopicExtractionOp(ctx, options) {
|
|
|
14894
14960
|
const id = raw.id;
|
|
14895
14961
|
const topics = parseTopics(raw.topics);
|
|
14896
14962
|
const linked = linkedNames.get(id);
|
|
14897
|
-
if (topics !== null &&
|
|
14963
|
+
if (topics !== null && linksDivergeFromTopics(topics, linked ?? /* @__PURE__ */ new Set())) {
|
|
14898
14964
|
topicsToRelinkAll.push(id);
|
|
14899
14965
|
continue;
|
|
14900
14966
|
}
|
|
@@ -14988,18 +15054,20 @@ async function relinkMemoryTopicsOp(ctx, memoryIds) {
|
|
|
14988
15054
|
}
|
|
14989
15055
|
const relinked = [];
|
|
14990
15056
|
for (const id of Array.from(new Set(memoryIds))) {
|
|
14991
|
-
let record;
|
|
14992
15057
|
try {
|
|
14993
|
-
|
|
14994
|
-
|
|
14995
|
-
|
|
14996
|
-
|
|
14997
|
-
|
|
14998
|
-
|
|
14999
|
-
|
|
15000
|
-
|
|
15001
|
-
|
|
15002
|
-
|
|
15058
|
+
await ctx.database.write(async (writer) => {
|
|
15059
|
+
let record;
|
|
15060
|
+
try {
|
|
15061
|
+
record = await ctx.vaultMemoryCollection.find(id);
|
|
15062
|
+
} catch {
|
|
15063
|
+
return;
|
|
15064
|
+
}
|
|
15065
|
+
if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) return;
|
|
15066
|
+
const topics = parseTopics(record.topics);
|
|
15067
|
+
if (topics === null) return;
|
|
15068
|
+
await writer.callWriter(() => relinkMemoryEntitiesFromTopicsOp(entityCtx, id, topics));
|
|
15069
|
+
relinked.push(id);
|
|
15070
|
+
});
|
|
15003
15071
|
} catch (err) {
|
|
15004
15072
|
getLogger().warn("[memory/topics] relink failed", err);
|
|
15005
15073
|
}
|
|
@@ -21616,6 +21684,28 @@ var BatchFailureError = class extends Error {
|
|
|
21616
21684
|
this.terminal = terminal;
|
|
21617
21685
|
}
|
|
21618
21686
|
};
|
|
21687
|
+
var FlaggedBatchError = class extends Error {
|
|
21688
|
+
};
|
|
21689
|
+
function extracted(result) {
|
|
21690
|
+
return result.failedCount === 0 && result.outcome !== "empty-after-retry";
|
|
21691
|
+
}
|
|
21692
|
+
function batchError(result) {
|
|
21693
|
+
const failure = result.failure;
|
|
21694
|
+
if (failure?.reason === "http-terminal") {
|
|
21695
|
+
const status = failure.httpStatus;
|
|
21696
|
+
if (status !== void 0 && REQUEST_REJECTED_STATUSES.has(status))
|
|
21697
|
+
return new BatchFailureError(
|
|
21698
|
+
`Extraction rejected the batch (HTTP ${status}); not retried this session`,
|
|
21699
|
+
true
|
|
21700
|
+
);
|
|
21701
|
+
return new AccountFailureError(
|
|
21702
|
+
`Extraction refused for the account (HTTP ${status ?? "unknown"}); retried next session`
|
|
21703
|
+
);
|
|
21704
|
+
}
|
|
21705
|
+
if (result.failedCount > 0 || failure !== void 0 && CONTENT_FAILURE_REASONS.has(failure.reason))
|
|
21706
|
+
return new BatchFailureError("Extraction batch incomplete; retained for retry", false);
|
|
21707
|
+
return new Error("Extraction batch incomplete; retained for retry");
|
|
21708
|
+
}
|
|
21619
21709
|
var AccountFailureError = class extends Error {
|
|
21620
21710
|
};
|
|
21621
21711
|
var LockedSourcesError = class extends Error {
|
|
@@ -21624,6 +21714,16 @@ var LockedSourcesError = class extends Error {
|
|
|
21624
21714
|
this.persistentIds = persistentIds;
|
|
21625
21715
|
}
|
|
21626
21716
|
};
|
|
21717
|
+
function splitTurns(messages) {
|
|
21718
|
+
const turns = [];
|
|
21719
|
+
for (const message of messages) {
|
|
21720
|
+
const last = turns[turns.length - 1];
|
|
21721
|
+
if (!last || message.role === "user" && last.some((m) => m.role === "user"))
|
|
21722
|
+
turns.push([message]);
|
|
21723
|
+
else last.push(message);
|
|
21724
|
+
}
|
|
21725
|
+
return turns;
|
|
21726
|
+
}
|
|
21627
21727
|
function idsOf(job) {
|
|
21628
21728
|
return JSON.parse(String(job._getRaw("message_ids")));
|
|
21629
21729
|
}
|
|
@@ -21774,6 +21874,10 @@ function createDurableAutoExtractor(options) {
|
|
|
21774
21874
|
skippedThisSession.add(job.id);
|
|
21775
21875
|
return false;
|
|
21776
21876
|
}
|
|
21877
|
+
if (error instanceof FlaggedBatchError) {
|
|
21878
|
+
await acknowledge(job, ids, loaded, true);
|
|
21879
|
+
return true;
|
|
21880
|
+
}
|
|
21777
21881
|
const counted = error instanceof BatchFailureError || error instanceof LockedSourcesError && error.persistentIds.length > 0;
|
|
21778
21882
|
if (!counted) return false;
|
|
21779
21883
|
const prior = sessionFailures.get(job.id);
|
|
@@ -21900,37 +22004,50 @@ function createDurableAutoExtractor(options) {
|
|
|
21900
22004
|
const messages = loaded.flatMap(
|
|
21901
22005
|
(m) => m && m.conversationId === conversationId && (m.role === "user" || m.role === "assistant") ? [{ id: m.uniqueId, role: m.role, content: m.content }] : []
|
|
21902
22006
|
);
|
|
21903
|
-
|
|
21904
|
-
|
|
21905
|
-
|
|
21906
|
-
result = await extractBatch(
|
|
21907
|
-
|
|
22007
|
+
const jobScope = currentScope() === "private" ? "private" : String(job._getRaw("scope"));
|
|
22008
|
+
const jobFolderId = job._getRaw("folder_id") ?? null;
|
|
22009
|
+
const runExtraction = async (batch, batchIds) => {
|
|
22010
|
+
const result = await extractBatch(
|
|
22011
|
+
batch,
|
|
21908
22012
|
conversationId,
|
|
21909
|
-
|
|
21910
|
-
|
|
21911
|
-
|
|
22013
|
+
batchIds,
|
|
22014
|
+
jobScope,
|
|
22015
|
+
jobFolderId
|
|
21912
22016
|
);
|
|
21913
|
-
success = result.failedCount === 0 && result.outcome !== "empty-after-retry";
|
|
21914
22017
|
options.onTurnComplete?.(result);
|
|
21915
|
-
|
|
21916
|
-
|
|
21917
|
-
|
|
21918
|
-
|
|
21919
|
-
|
|
21920
|
-
|
|
21921
|
-
|
|
21922
|
-
|
|
21923
|
-
|
|
22018
|
+
return result;
|
|
22019
|
+
};
|
|
22020
|
+
const flaggedIds = /* @__PURE__ */ new Set();
|
|
22021
|
+
if (messages.length) {
|
|
22022
|
+
const result = await runExtraction(messages, ids);
|
|
22023
|
+
if (result.failure?.reason === "content-flagged") {
|
|
22024
|
+
const turns = splitTurns(messages);
|
|
22025
|
+
if (turns.length < 2)
|
|
22026
|
+
throw new FlaggedBatchError("Extraction batch refused by moderation; abandoned");
|
|
22027
|
+
for (const turn of turns) {
|
|
22028
|
+
const turnResult = await runExtraction(
|
|
22029
|
+
turn,
|
|
22030
|
+
turn.map((m) => m.id)
|
|
21924
22031
|
);
|
|
21925
|
-
|
|
21926
|
-
|
|
21927
|
-
|
|
21928
|
-
|
|
21929
|
-
|
|
21930
|
-
|
|
21931
|
-
|
|
22032
|
+
if (turnResult.failure?.reason === "content-flagged")
|
|
22033
|
+
for (const m of turn) flaggedIds.add(m.id);
|
|
22034
|
+
else if (!extracted(turnResult)) throw batchError(turnResult);
|
|
22035
|
+
}
|
|
22036
|
+
if (flaggedIds.size)
|
|
22037
|
+
reportError(
|
|
22038
|
+
new Error(
|
|
22039
|
+
`Dropped ${flaggedIds.size} source id(s) of an extraction batch refused by moderation`
|
|
22040
|
+
),
|
|
22041
|
+
conversationId
|
|
22042
|
+
);
|
|
22043
|
+
} else if (!extracted(result)) throw batchError(result);
|
|
21932
22044
|
}
|
|
21933
|
-
await acknowledge(
|
|
22045
|
+
await acknowledge(
|
|
22046
|
+
job,
|
|
22047
|
+
ids,
|
|
22048
|
+
loaded,
|
|
22049
|
+
ids.slice(-2).some((id) => flaggedIds.has(id))
|
|
22050
|
+
);
|
|
21934
22051
|
scheduleAfterSuccess = true;
|
|
21935
22052
|
} catch (error) {
|
|
21936
22053
|
attempts.set(job.id, attempted + 1);
|
|
@@ -25171,10 +25288,10 @@ function useChatStorage(options) {
|
|
|
25171
25288
|
let skipStorageEmbeddings = null;
|
|
25172
25289
|
let skipStorageEmbeddingsFailed = false;
|
|
25173
25290
|
if (needsEmbeddings2 && getToken) {
|
|
25174
|
-
const
|
|
25291
|
+
const extracted3 = extractUserMessageFromMessages(messages);
|
|
25175
25292
|
const messageContent = resolveStoredUserContent(
|
|
25176
25293
|
storedUserContent,
|
|
25177
|
-
|
|
25294
|
+
extracted3?.content ?? ""
|
|
25178
25295
|
);
|
|
25179
25296
|
if (messageContent.length >= MIN_CONTENT_LENGTH_FOR_TOOLS) {
|
|
25180
25297
|
const embeddingOptions = {
|
|
@@ -25331,15 +25448,15 @@ function useChatStorage(options) {
|
|
|
25331
25448
|
skipped: true
|
|
25332
25449
|
};
|
|
25333
25450
|
}
|
|
25334
|
-
const
|
|
25335
|
-
if (!
|
|
25451
|
+
const extracted2 = extractUserMessageFromMessages(messages);
|
|
25452
|
+
if (!extracted2 || !extracted2.content && !extracted2.files?.length) {
|
|
25336
25453
|
return {
|
|
25337
25454
|
data: null,
|
|
25338
25455
|
error: "No user message found in messages array"
|
|
25339
25456
|
};
|
|
25340
25457
|
}
|
|
25341
|
-
const contentForStorage = resolveStoredUserContent(storedUserContent,
|
|
25342
|
-
const filesForStorage = files ??
|
|
25458
|
+
const contentForStorage = resolveStoredUserContent(storedUserContent, extracted2.content);
|
|
25459
|
+
const filesForStorage = files ?? extracted2.files;
|
|
25343
25460
|
let fileContextForRequest;
|
|
25344
25461
|
let fileContextIsCurrentTurn = false;
|
|
25345
25462
|
let preprocessedFileIds = [];
|
|
@@ -25798,9 +25915,9 @@ function useChatStorage(options) {
|
|
|
25798
25915
|
if (result.error || !result.data) {
|
|
25799
25916
|
const abortedResult = result;
|
|
25800
25917
|
if (abortedResult.error === "Request aborted") {
|
|
25801
|
-
const
|
|
25802
|
-
const assistantContent2 =
|
|
25803
|
-
const abortedThinkingContent =
|
|
25918
|
+
const extracted3 = abortedResult.data ? extractAssistantText(abortedResult.data) : { content: "", thinking: void 0 };
|
|
25919
|
+
const assistantContent2 = extracted3.content;
|
|
25920
|
+
const abortedThinkingContent = extracted3.thinking;
|
|
25804
25921
|
const responseModel = abortedResult.data?.model || model || "";
|
|
25805
25922
|
let storedAssistantMessage2;
|
|
25806
25923
|
try {
|
package/dist/react/index.d.mts
CHANGED
|
@@ -2138,6 +2138,21 @@ type ToolConfig = LlmapiChatCompletionTool & {
|
|
|
2138
2138
|
* execution fails, allowing the model to retry.
|
|
2139
2139
|
*/
|
|
2140
2140
|
removeAfterExecution?: boolean;
|
|
2141
|
+
/**
|
|
2142
|
+
* Remove this tool for the rest of the turn once ANY tool returns a
|
|
2143
|
+
* successful result this predicate accepts — its own or another's. Errors
|
|
2144
|
+
* never count, as for `removeAfterExecution`.
|
|
2145
|
+
*
|
|
2146
|
+
* Only results of tools executed on this client are offered; tools the
|
|
2147
|
+
* portal runs server-side never reach the predicate. A predicate that throws
|
|
2148
|
+
* is treated as not matching.
|
|
2149
|
+
*
|
|
2150
|
+
* For a family of tools that has to leave together: when one of them
|
|
2151
|
+
* declines an out-of-scope request, the model otherwise works through its
|
|
2152
|
+
* siblings round after round until the round cap. Give every member the same
|
|
2153
|
+
* predicate and the first refusal removes the whole family.
|
|
2154
|
+
*/
|
|
2155
|
+
removeAfterResult?: (result: unknown) => boolean;
|
|
2141
2156
|
/**
|
|
2142
2157
|
* Timeout in milliseconds for this tool's executor.
|
|
2143
2158
|
* Overrides the default 30-second timeout.
|
|
@@ -4995,6 +5010,7 @@ type MessageFeedback = "like" | "dislike" | null;
|
|
|
4995
5010
|
* - `tool_result`: the hidden `[Tool Execution Results]` row built from a
|
|
4996
5011
|
* turn's auto-executed tool results. Skipped by the embedding sweep (see
|
|
4997
5012
|
* `memoryEngine/embeddings`) AND hidden from the transcript.
|
|
5013
|
+
* - `message`: an ordinary message with an index after explicit repair.
|
|
4998
5014
|
* - `chunks_discarded`: an ordinary, still-rendered message whose chunk vectors
|
|
4999
5015
|
* were built over `enc:v3:` ciphertext (sdk#864) and have been discarded
|
|
5000
5016
|
* rather than re-embedded at the user's own expense (client#5618). Skipped by
|
|
@@ -5007,7 +5023,7 @@ type MessageFeedback = "like" | "dislike" | null;
|
|
|
5007
5023
|
* encrypted flag would be unreadable exactly where it matters and the skip
|
|
5008
5024
|
* would fail open.
|
|
5009
5025
|
*/
|
|
5010
|
-
type MessageOrigin = "tool_result" | "chunks_discarded";
|
|
5026
|
+
type MessageOrigin = "tool_result" | "chunks_discarded" | "message";
|
|
5011
5027
|
/**
|
|
5012
5028
|
* Metadata for files attached to messages.
|
|
5013
5029
|
*
|
|
@@ -6529,7 +6545,12 @@ type PortalLlmFailureReason =
|
|
|
6529
6545
|
/** Content parsed to a literal `null`, which is never a valid response. */
|
|
6530
6546
|
| "null-completion"
|
|
6531
6547
|
/** `totalTimeoutMs` was spent before the next attempt could run. */
|
|
6532
|
-
| "time-budget-exhausted"
|
|
6548
|
+
| "time-budget-exhausted"
|
|
6549
|
+
/**
|
|
6550
|
+
* The portal's moderation gate refused the request. Terminal: the same input
|
|
6551
|
+
* is flagged again on every retry. See {@link isModerationResponse}.
|
|
6552
|
+
*/
|
|
6553
|
+
| "content-flagged";
|
|
6533
6554
|
/**
|
|
6534
6555
|
* One attempt of a {@link callPortalJsonCompletion} call, reported to
|
|
6535
6556
|
* `onAttempt` as it settles — success included. The wire-level diagnostic the
|
|
@@ -7766,7 +7787,9 @@ interface ExtractFactsOptions extends PortalLlmAuth {
|
|
|
7766
7787
|
* Optional per-call request path override, forwarded to
|
|
7767
7788
|
* {@link callPortalJsonCompletion}. When set, the extraction call POSTs to
|
|
7768
7789
|
* `baseUrl + endpointOverride` instead of the default
|
|
7769
|
-
* `/api/v1/chat/completions
|
|
7790
|
+
* `/api/v1/chat/completions`. The body follows the transport, not the path: a
|
|
7791
|
+
* model that needs the Responses API is moved from a `.../chat/completions`
|
|
7792
|
+
* override to its sibling `.../responses` with a Responses-shaped body. Lets callers route
|
|
7770
7793
|
* this internal-utility pass to a dedicated endpoint. Invalid values throw at
|
|
7771
7794
|
* call time (see {@link validateEndpointOverride}).
|
|
7772
7795
|
*
|
|
@@ -8706,7 +8729,8 @@ declare function stampTopicsExtractedAtOp(ctx: VaultMemoryOperationsContext, mem
|
|
|
8706
8729
|
* `topics_user_managed` in particular is left exactly as it arrived, so the
|
|
8707
8730
|
* autotagger stays off a curated memory whose links this just restored.
|
|
8708
8731
|
*
|
|
8709
|
-
* Skips deleted, foreign-user, and
|
|
8732
|
+
* Skips deleted rows, foreign-user rows, and rows with null topics.
|
|
8733
|
+
* Empty topics remove stale links. Returns the relinked IDs.
|
|
8710
8734
|
*/
|
|
8711
8735
|
declare function relinkMemoryTopicsOp(ctx: VaultMemoryOperationsContext, memoryIds: readonly string[]): Promise<string[]>;
|
|
8712
8736
|
/**
|
|
@@ -10414,7 +10438,9 @@ interface TopicExtractOptions extends PortalLlmAuth {
|
|
|
10414
10438
|
* Optional per-call request path override, forwarded to
|
|
10415
10439
|
* {@link callPortalJsonCompletion}. When set, topic extraction POSTs to
|
|
10416
10440
|
* `baseUrl + endpointOverride` instead of the default
|
|
10417
|
-
* `/api/v1/chat/completions
|
|
10441
|
+
* `/api/v1/chat/completions`. The body follows the transport, not the path: a
|
|
10442
|
+
* model that needs the Responses API is moved from a `.../chat/completions`
|
|
10443
|
+
* override to its sibling `.../responses` with a Responses-shaped body. Lets callers route
|
|
10418
10444
|
* this internal-utility pass to a dedicated endpoint. Invalid values throw at
|
|
10419
10445
|
* call time (see {@link validateEndpointOverride}).
|
|
10420
10446
|
*/
|
|
@@ -11040,14 +11066,10 @@ declare function generateEmbeddings(texts: string[], options: EmbeddingOptions):
|
|
|
11040
11066
|
* re-index. Off by default, so no background pass can spend a user's credits
|
|
11041
11067
|
* without being asked to.
|
|
11042
11068
|
*
|
|
11043
|
-
*
|
|
11044
|
-
*
|
|
11045
|
-
*
|
|
11046
|
-
*
|
|
11047
|
-
* before it can do anything, so the repaired rows stay on the old model, and
|
|
11048
|
-
* `searchChunksOp` already drops stale-model vectors — they go quiet with
|
|
11049
|
-
* nothing telling them apart from rows that were never repaired. Clearing the
|
|
11050
|
-
* marker on a successful re-index is the real fix, tracked in #879.
|
|
11069
|
+
* A successful repair replaces the marker with `message` in the index write.
|
|
11070
|
+
* The new marker preserves ordinary message provenance during chat replay.
|
|
11071
|
+
* Later model migrations can then include the repaired row without this flag.
|
|
11072
|
+
* Failed embedding requests and empty index data do not clear the marker.
|
|
11051
11073
|
*
|
|
11052
11074
|
* `satisfies MessageOrigin` so the constant and the union cannot drift apart
|
|
11053
11075
|
* silently — the column's type is the union, and a typo here would otherwise
|
|
@@ -11084,9 +11106,8 @@ declare function embedAllMessages(ctx: StorageOperationsContext, options: Embedd
|
|
|
11084
11106
|
* to an explicit user action, never to a background pass. Opens that marker
|
|
11085
11107
|
* only — `tool_result` rows stay excluded.
|
|
11086
11108
|
*
|
|
11087
|
-
*
|
|
11088
|
-
*
|
|
11089
|
-
* {@link CHUNKS_DISCARDED_ORIGIN}.
|
|
11109
|
+
* A successful repair clears the marker. Later model migrations include
|
|
11110
|
+
* the repaired row without this flag. See {@link CHUNKS_DISCARDED_ORIGIN}.
|
|
11090
11111
|
*/
|
|
11091
11112
|
reembedDiscarded?: boolean;
|
|
11092
11113
|
}): Promise<number>;
|
|
@@ -11144,9 +11165,8 @@ declare function chunkAndEmbedAllMessages(ctx: StorageOperationsContext, options
|
|
|
11144
11165
|
* chunks nor vector, so it never reaches that check and falls straight to the
|
|
11145
11166
|
* origin gate.
|
|
11146
11167
|
*
|
|
11147
|
-
*
|
|
11148
|
-
*
|
|
11149
|
-
* {@link CHUNKS_DISCARDED_ORIGIN}.
|
|
11168
|
+
* A successful repair clears the marker. Later model migrations include
|
|
11169
|
+
* the repaired row without this flag. See {@link CHUNKS_DISCARDED_ORIGIN}.
|
|
11150
11170
|
*/
|
|
11151
11171
|
reembedDiscarded?: boolean;
|
|
11152
11172
|
}): Promise<number>;
|