@anuma/sdk 6.30.1 → 6.30.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/{chunk-N5CKISI3.mjs → chunk-VD5M6QAI.mjs} +31 -4
- package/dist/expo/{consolidate-N56RXPCW.mjs → consolidate-6J5HHAJY.mjs} +1 -1
- package/dist/expo/index.cjs +115 -39
- package/dist/expo/index.d.mts +12 -3
- package/dist/expo/index.d.ts +12 -3
- package/dist/expo/index.mjs +86 -37
- package/dist/react/{chunk-LBIKGBXE.mjs → chunk-NLTO6Q36.mjs} +31 -4
- package/dist/react/{consolidate-2NLZAEWR.mjs → consolidate-MYS55OAB.mjs} +1 -1
- package/dist/react/index.cjs +115 -39
- package/dist/react/index.d.mts +12 -3
- package/dist/react/index.d.ts +12 -3
- package/dist/react/index.mjs +86 -37
- package/dist/server/{chunk-Z2QBL4HB.mjs → chunk-7GHESNOH.mjs} +31 -4
- package/dist/server/{consolidate-QWVI25WQ.mjs → consolidate-3RNRDM75.mjs} +1 -1
- package/dist/server/index.cjs +106 -30
- package/dist/server/index.d.mts +12 -3
- package/dist/server/index.d.ts +12 -3
- package/dist/server/index.mjs +77 -28
- package/package.json +1 -1
|
@@ -726,13 +726,21 @@ function responsesExtra(extra) {
|
|
|
726
726
|
}
|
|
727
727
|
return out;
|
|
728
728
|
}
|
|
729
|
+
function splitEndpoint(endpoint) {
|
|
730
|
+
const cut = endpoint.search(/[?#]/);
|
|
731
|
+
const rawPath = cut === -1 ? endpoint : endpoint.slice(0, cut);
|
|
732
|
+
return {
|
|
733
|
+
path: rawPath.replace(/\/+$/, ""),
|
|
734
|
+
rest: cut === -1 ? "" : endpoint.slice(cut)
|
|
735
|
+
};
|
|
736
|
+
}
|
|
729
737
|
var FOREIGN_ENDPOINT_SUFFIX = {
|
|
730
738
|
chat: "/responses",
|
|
731
739
|
responses: "/chat/completions"
|
|
732
740
|
};
|
|
733
741
|
function assertTransportMatchesEndpoint(transport, endpoint) {
|
|
734
742
|
const foreign = FOREIGN_ENDPOINT_SUFFIX[transport];
|
|
735
|
-
if (!endpoint.endsWith(foreign)) return;
|
|
743
|
+
if (!splitEndpoint(endpoint).path.endsWith(foreign)) return;
|
|
736
744
|
throw new Error(
|
|
737
745
|
`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
746
|
);
|
|
@@ -778,14 +786,20 @@ async function resolvePortalAuthHeaders(auth, tag) {
|
|
|
778
786
|
}
|
|
779
787
|
async function callPortalJsonCompletion(req) {
|
|
780
788
|
const log = getLogger();
|
|
781
|
-
|
|
789
|
+
const transport = req.transport ?? (requiresResponsesTransport(req.model) ? "responses" : "chat");
|
|
790
|
+
const autoUpgraded = req.transport === void 0 && transport === "responses";
|
|
791
|
+
let endpoint = transport === "responses" ? "/api/v1/responses" : "/api/v1/chat/completions";
|
|
782
792
|
if (req.endpointOverride !== void 0) {
|
|
783
793
|
const overrideValidation = validateEndpointOverride(req.endpointOverride);
|
|
784
794
|
if (!overrideValidation.valid) {
|
|
785
795
|
throw new Error(overrideValidation.message);
|
|
786
796
|
}
|
|
787
797
|
endpoint = overrideValidation.endpoint;
|
|
788
|
-
|
|
798
|
+
const { path, rest } = splitEndpoint(endpoint);
|
|
799
|
+
if (autoUpgraded && path.endsWith("/chat/completions")) {
|
|
800
|
+
endpoint = `${path.slice(0, -"/chat/completions".length)}/responses${rest}`;
|
|
801
|
+
}
|
|
802
|
+
assertTransportMatchesEndpoint(transport, endpoint);
|
|
789
803
|
}
|
|
790
804
|
const maxAttempts = Math.max(1, req.maxAttempts ?? 3);
|
|
791
805
|
const startedAt = Date.now();
|
|
@@ -810,7 +824,10 @@ async function callPortalJsonCompletion(req) {
|
|
|
810
824
|
),
|
|
811
825
|
...reinforce && { reinforceJsonContract: true }
|
|
812
826
|
} : reinforce ? { ...req, reinforceJsonContract: true } : req;
|
|
813
|
-
const outcome = await attemptPortalJson(
|
|
827
|
+
const outcome = await attemptPortalJson(
|
|
828
|
+
{ ...attemptReq, transport },
|
|
829
|
+
endpoint
|
|
830
|
+
);
|
|
814
831
|
if (outcome.kind === "ok") {
|
|
815
832
|
req.onAttempt?.({ attempt, ok: true });
|
|
816
833
|
return outcome.value;
|
|
@@ -962,6 +979,13 @@ async function attemptPortalJson(req, endpoint) {
|
|
|
962
979
|
}
|
|
963
980
|
clearTimeout(timer);
|
|
964
981
|
logPortalUsage(body, req.tag);
|
|
982
|
+
if (isModerationResponse(body)) {
|
|
983
|
+
return {
|
|
984
|
+
kind: "terminal",
|
|
985
|
+
code: "content-flagged",
|
|
986
|
+
reason: "portal moderation refused the request"
|
|
987
|
+
};
|
|
988
|
+
}
|
|
965
989
|
const rawContent = extractCompletionContent(body);
|
|
966
990
|
if (!rawContent) {
|
|
967
991
|
return {
|
|
@@ -1047,6 +1071,9 @@ function logPortalUsage(body, tag) {
|
|
|
1047
1071
|
} catch {
|
|
1048
1072
|
}
|
|
1049
1073
|
}
|
|
1074
|
+
function isModerationResponse(body) {
|
|
1075
|
+
return typeof body === "object" && body !== null && body.id === "moderation";
|
|
1076
|
+
}
|
|
1050
1077
|
function extractCompletionContent(body) {
|
|
1051
1078
|
if (typeof body !== "object" || body === null) return null;
|
|
1052
1079
|
const responsesText = extractResponsesContent(body);
|
package/dist/react/index.cjs
CHANGED
|
@@ -828,9 +828,17 @@ function responsesExtra(extra) {
|
|
|
828
828
|
}
|
|
829
829
|
return out;
|
|
830
830
|
}
|
|
831
|
+
function splitEndpoint(endpoint) {
|
|
832
|
+
const cut = endpoint.search(/[?#]/);
|
|
833
|
+
const rawPath = cut === -1 ? endpoint : endpoint.slice(0, cut);
|
|
834
|
+
return {
|
|
835
|
+
path: rawPath.replace(/\/+$/, ""),
|
|
836
|
+
rest: cut === -1 ? "" : endpoint.slice(cut)
|
|
837
|
+
};
|
|
838
|
+
}
|
|
831
839
|
function assertTransportMatchesEndpoint(transport, endpoint) {
|
|
832
840
|
const foreign = FOREIGN_ENDPOINT_SUFFIX[transport];
|
|
833
|
-
if (!endpoint.endsWith(foreign)) return;
|
|
841
|
+
if (!splitEndpoint(endpoint).path.endsWith(foreign)) return;
|
|
834
842
|
throw new Error(
|
|
835
843
|
`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
844
|
);
|
|
@@ -875,14 +883,20 @@ async function resolvePortalAuthHeaders(auth, tag) {
|
|
|
875
883
|
}
|
|
876
884
|
async function callPortalJsonCompletion(req) {
|
|
877
885
|
const log = getLogger();
|
|
878
|
-
|
|
886
|
+
const transport = req.transport ?? (requiresResponsesTransport(req.model) ? "responses" : "chat");
|
|
887
|
+
const autoUpgraded = req.transport === void 0 && transport === "responses";
|
|
888
|
+
let endpoint = transport === "responses" ? "/api/v1/responses" : "/api/v1/chat/completions";
|
|
879
889
|
if (req.endpointOverride !== void 0) {
|
|
880
890
|
const overrideValidation = validateEndpointOverride(req.endpointOverride);
|
|
881
891
|
if (!overrideValidation.valid) {
|
|
882
892
|
throw new Error(overrideValidation.message);
|
|
883
893
|
}
|
|
884
894
|
endpoint = overrideValidation.endpoint;
|
|
885
|
-
|
|
895
|
+
const { path, rest } = splitEndpoint(endpoint);
|
|
896
|
+
if (autoUpgraded && path.endsWith("/chat/completions")) {
|
|
897
|
+
endpoint = `${path.slice(0, -"/chat/completions".length)}/responses${rest}`;
|
|
898
|
+
}
|
|
899
|
+
assertTransportMatchesEndpoint(transport, endpoint);
|
|
886
900
|
}
|
|
887
901
|
const maxAttempts = Math.max(1, req.maxAttempts ?? 3);
|
|
888
902
|
const startedAt = Date.now();
|
|
@@ -907,7 +921,10 @@ async function callPortalJsonCompletion(req) {
|
|
|
907
921
|
),
|
|
908
922
|
...reinforce && { reinforceJsonContract: true }
|
|
909
923
|
} : reinforce ? { ...req, reinforceJsonContract: true } : req;
|
|
910
|
-
const outcome = await attemptPortalJson(
|
|
924
|
+
const outcome = await attemptPortalJson(
|
|
925
|
+
{ ...attemptReq, transport },
|
|
926
|
+
endpoint
|
|
927
|
+
);
|
|
911
928
|
if (outcome.kind === "ok") {
|
|
912
929
|
req.onAttempt?.({ attempt, ok: true });
|
|
913
930
|
return outcome.value;
|
|
@@ -1059,6 +1076,13 @@ async function attemptPortalJson(req, endpoint) {
|
|
|
1059
1076
|
}
|
|
1060
1077
|
clearTimeout(timer);
|
|
1061
1078
|
logPortalUsage(body, req.tag);
|
|
1079
|
+
if (isModerationResponse(body)) {
|
|
1080
|
+
return {
|
|
1081
|
+
kind: "terminal",
|
|
1082
|
+
code: "content-flagged",
|
|
1083
|
+
reason: "portal moderation refused the request"
|
|
1084
|
+
};
|
|
1085
|
+
}
|
|
1062
1086
|
const rawContent = extractCompletionContent(body);
|
|
1063
1087
|
if (!rawContent) {
|
|
1064
1088
|
return {
|
|
@@ -1144,6 +1168,9 @@ function logPortalUsage(body, tag) {
|
|
|
1144
1168
|
} catch {
|
|
1145
1169
|
}
|
|
1146
1170
|
}
|
|
1171
|
+
function isModerationResponse(body) {
|
|
1172
|
+
return typeof body === "object" && body !== null && body.id === "moderation";
|
|
1173
|
+
}
|
|
1147
1174
|
function extractCompletionContent(body) {
|
|
1148
1175
|
if (typeof body !== "object" || body === null) return null;
|
|
1149
1176
|
const responsesText = extractResponsesContent(body);
|
|
@@ -21616,6 +21643,28 @@ var BatchFailureError = class extends Error {
|
|
|
21616
21643
|
this.terminal = terminal;
|
|
21617
21644
|
}
|
|
21618
21645
|
};
|
|
21646
|
+
var FlaggedBatchError = class extends Error {
|
|
21647
|
+
};
|
|
21648
|
+
function extracted(result) {
|
|
21649
|
+
return result.failedCount === 0 && result.outcome !== "empty-after-retry";
|
|
21650
|
+
}
|
|
21651
|
+
function batchError(result) {
|
|
21652
|
+
const failure = result.failure;
|
|
21653
|
+
if (failure?.reason === "http-terminal") {
|
|
21654
|
+
const status = failure.httpStatus;
|
|
21655
|
+
if (status !== void 0 && REQUEST_REJECTED_STATUSES.has(status))
|
|
21656
|
+
return new BatchFailureError(
|
|
21657
|
+
`Extraction rejected the batch (HTTP ${status}); not retried this session`,
|
|
21658
|
+
true
|
|
21659
|
+
);
|
|
21660
|
+
return new AccountFailureError(
|
|
21661
|
+
`Extraction refused for the account (HTTP ${status ?? "unknown"}); retried next session`
|
|
21662
|
+
);
|
|
21663
|
+
}
|
|
21664
|
+
if (result.failedCount > 0 || failure !== void 0 && CONTENT_FAILURE_REASONS.has(failure.reason))
|
|
21665
|
+
return new BatchFailureError("Extraction batch incomplete; retained for retry", false);
|
|
21666
|
+
return new Error("Extraction batch incomplete; retained for retry");
|
|
21667
|
+
}
|
|
21619
21668
|
var AccountFailureError = class extends Error {
|
|
21620
21669
|
};
|
|
21621
21670
|
var LockedSourcesError = class extends Error {
|
|
@@ -21624,6 +21673,16 @@ var LockedSourcesError = class extends Error {
|
|
|
21624
21673
|
this.persistentIds = persistentIds;
|
|
21625
21674
|
}
|
|
21626
21675
|
};
|
|
21676
|
+
function splitTurns(messages) {
|
|
21677
|
+
const turns = [];
|
|
21678
|
+
for (const message of messages) {
|
|
21679
|
+
const last = turns[turns.length - 1];
|
|
21680
|
+
if (!last || message.role === "user" && last.some((m) => m.role === "user"))
|
|
21681
|
+
turns.push([message]);
|
|
21682
|
+
else last.push(message);
|
|
21683
|
+
}
|
|
21684
|
+
return turns;
|
|
21685
|
+
}
|
|
21627
21686
|
function idsOf(job) {
|
|
21628
21687
|
return JSON.parse(String(job._getRaw("message_ids")));
|
|
21629
21688
|
}
|
|
@@ -21774,6 +21833,10 @@ function createDurableAutoExtractor(options) {
|
|
|
21774
21833
|
skippedThisSession.add(job.id);
|
|
21775
21834
|
return false;
|
|
21776
21835
|
}
|
|
21836
|
+
if (error instanceof FlaggedBatchError) {
|
|
21837
|
+
await acknowledge(job, ids, loaded, true);
|
|
21838
|
+
return true;
|
|
21839
|
+
}
|
|
21777
21840
|
const counted = error instanceof BatchFailureError || error instanceof LockedSourcesError && error.persistentIds.length > 0;
|
|
21778
21841
|
if (!counted) return false;
|
|
21779
21842
|
const prior = sessionFailures.get(job.id);
|
|
@@ -21900,37 +21963,50 @@ function createDurableAutoExtractor(options) {
|
|
|
21900
21963
|
const messages = loaded.flatMap(
|
|
21901
21964
|
(m) => m && m.conversationId === conversationId && (m.role === "user" || m.role === "assistant") ? [{ id: m.uniqueId, role: m.role, content: m.content }] : []
|
|
21902
21965
|
);
|
|
21903
|
-
|
|
21904
|
-
|
|
21905
|
-
|
|
21906
|
-
result = await extractBatch(
|
|
21907
|
-
|
|
21966
|
+
const jobScope = currentScope() === "private" ? "private" : String(job._getRaw("scope"));
|
|
21967
|
+
const jobFolderId = job._getRaw("folder_id") ?? null;
|
|
21968
|
+
const runExtraction = async (batch, batchIds) => {
|
|
21969
|
+
const result = await extractBatch(
|
|
21970
|
+
batch,
|
|
21908
21971
|
conversationId,
|
|
21909
|
-
|
|
21910
|
-
|
|
21911
|
-
|
|
21972
|
+
batchIds,
|
|
21973
|
+
jobScope,
|
|
21974
|
+
jobFolderId
|
|
21912
21975
|
);
|
|
21913
|
-
success = result.failedCount === 0 && result.outcome !== "empty-after-retry";
|
|
21914
21976
|
options.onTurnComplete?.(result);
|
|
21915
|
-
|
|
21916
|
-
|
|
21917
|
-
|
|
21918
|
-
|
|
21919
|
-
|
|
21920
|
-
|
|
21921
|
-
|
|
21922
|
-
|
|
21923
|
-
|
|
21977
|
+
return result;
|
|
21978
|
+
};
|
|
21979
|
+
const flaggedIds = /* @__PURE__ */ new Set();
|
|
21980
|
+
if (messages.length) {
|
|
21981
|
+
const result = await runExtraction(messages, ids);
|
|
21982
|
+
if (result.failure?.reason === "content-flagged") {
|
|
21983
|
+
const turns = splitTurns(messages);
|
|
21984
|
+
if (turns.length < 2)
|
|
21985
|
+
throw new FlaggedBatchError("Extraction batch refused by moderation; abandoned");
|
|
21986
|
+
for (const turn of turns) {
|
|
21987
|
+
const turnResult = await runExtraction(
|
|
21988
|
+
turn,
|
|
21989
|
+
turn.map((m) => m.id)
|
|
21924
21990
|
);
|
|
21925
|
-
|
|
21926
|
-
|
|
21927
|
-
|
|
21928
|
-
|
|
21929
|
-
|
|
21930
|
-
|
|
21931
|
-
|
|
21991
|
+
if (turnResult.failure?.reason === "content-flagged")
|
|
21992
|
+
for (const m of turn) flaggedIds.add(m.id);
|
|
21993
|
+
else if (!extracted(turnResult)) throw batchError(turnResult);
|
|
21994
|
+
}
|
|
21995
|
+
if (flaggedIds.size)
|
|
21996
|
+
reportError(
|
|
21997
|
+
new Error(
|
|
21998
|
+
`Dropped ${flaggedIds.size} source id(s) of an extraction batch refused by moderation`
|
|
21999
|
+
),
|
|
22000
|
+
conversationId
|
|
22001
|
+
);
|
|
22002
|
+
} else if (!extracted(result)) throw batchError(result);
|
|
21932
22003
|
}
|
|
21933
|
-
await acknowledge(
|
|
22004
|
+
await acknowledge(
|
|
22005
|
+
job,
|
|
22006
|
+
ids,
|
|
22007
|
+
loaded,
|
|
22008
|
+
ids.slice(-2).some((id) => flaggedIds.has(id))
|
|
22009
|
+
);
|
|
21934
22010
|
scheduleAfterSuccess = true;
|
|
21935
22011
|
} catch (error) {
|
|
21936
22012
|
attempts.set(job.id, attempted + 1);
|
|
@@ -25171,10 +25247,10 @@ function useChatStorage(options) {
|
|
|
25171
25247
|
let skipStorageEmbeddings = null;
|
|
25172
25248
|
let skipStorageEmbeddingsFailed = false;
|
|
25173
25249
|
if (needsEmbeddings2 && getToken) {
|
|
25174
|
-
const
|
|
25250
|
+
const extracted3 = extractUserMessageFromMessages(messages);
|
|
25175
25251
|
const messageContent = resolveStoredUserContent(
|
|
25176
25252
|
storedUserContent,
|
|
25177
|
-
|
|
25253
|
+
extracted3?.content ?? ""
|
|
25178
25254
|
);
|
|
25179
25255
|
if (messageContent.length >= MIN_CONTENT_LENGTH_FOR_TOOLS) {
|
|
25180
25256
|
const embeddingOptions = {
|
|
@@ -25331,15 +25407,15 @@ function useChatStorage(options) {
|
|
|
25331
25407
|
skipped: true
|
|
25332
25408
|
};
|
|
25333
25409
|
}
|
|
25334
|
-
const
|
|
25335
|
-
if (!
|
|
25410
|
+
const extracted2 = extractUserMessageFromMessages(messages);
|
|
25411
|
+
if (!extracted2 || !extracted2.content && !extracted2.files?.length) {
|
|
25336
25412
|
return {
|
|
25337
25413
|
data: null,
|
|
25338
25414
|
error: "No user message found in messages array"
|
|
25339
25415
|
};
|
|
25340
25416
|
}
|
|
25341
|
-
const contentForStorage = resolveStoredUserContent(storedUserContent,
|
|
25342
|
-
const filesForStorage = files ??
|
|
25417
|
+
const contentForStorage = resolveStoredUserContent(storedUserContent, extracted2.content);
|
|
25418
|
+
const filesForStorage = files ?? extracted2.files;
|
|
25343
25419
|
let fileContextForRequest;
|
|
25344
25420
|
let fileContextIsCurrentTurn = false;
|
|
25345
25421
|
let preprocessedFileIds = [];
|
|
@@ -25798,9 +25874,9 @@ function useChatStorage(options) {
|
|
|
25798
25874
|
if (result.error || !result.data) {
|
|
25799
25875
|
const abortedResult = result;
|
|
25800
25876
|
if (abortedResult.error === "Request aborted") {
|
|
25801
|
-
const
|
|
25802
|
-
const assistantContent2 =
|
|
25803
|
-
const abortedThinkingContent =
|
|
25877
|
+
const extracted3 = abortedResult.data ? extractAssistantText(abortedResult.data) : { content: "", thinking: void 0 };
|
|
25878
|
+
const assistantContent2 = extracted3.content;
|
|
25879
|
+
const abortedThinkingContent = extracted3.thinking;
|
|
25804
25880
|
const responseModel = abortedResult.data?.model || model || "";
|
|
25805
25881
|
let storedAssistantMessage2;
|
|
25806
25882
|
try {
|
package/dist/react/index.d.mts
CHANGED
|
@@ -6529,7 +6529,12 @@ type PortalLlmFailureReason =
|
|
|
6529
6529
|
/** Content parsed to a literal `null`, which is never a valid response. */
|
|
6530
6530
|
| "null-completion"
|
|
6531
6531
|
/** `totalTimeoutMs` was spent before the next attempt could run. */
|
|
6532
|
-
| "time-budget-exhausted"
|
|
6532
|
+
| "time-budget-exhausted"
|
|
6533
|
+
/**
|
|
6534
|
+
* The portal's moderation gate refused the request. Terminal: the same input
|
|
6535
|
+
* is flagged again on every retry. See {@link isModerationResponse}.
|
|
6536
|
+
*/
|
|
6537
|
+
| "content-flagged";
|
|
6533
6538
|
/**
|
|
6534
6539
|
* One attempt of a {@link callPortalJsonCompletion} call, reported to
|
|
6535
6540
|
* `onAttempt` as it settles — success included. The wire-level diagnostic the
|
|
@@ -7766,7 +7771,9 @@ interface ExtractFactsOptions extends PortalLlmAuth {
|
|
|
7766
7771
|
* Optional per-call request path override, forwarded to
|
|
7767
7772
|
* {@link callPortalJsonCompletion}. When set, the extraction call POSTs to
|
|
7768
7773
|
* `baseUrl + endpointOverride` instead of the default
|
|
7769
|
-
* `/api/v1/chat/completions
|
|
7774
|
+
* `/api/v1/chat/completions`. The body follows the transport, not the path: a
|
|
7775
|
+
* model that needs the Responses API is moved from a `.../chat/completions`
|
|
7776
|
+
* override to its sibling `.../responses` with a Responses-shaped body. Lets callers route
|
|
7770
7777
|
* this internal-utility pass to a dedicated endpoint. Invalid values throw at
|
|
7771
7778
|
* call time (see {@link validateEndpointOverride}).
|
|
7772
7779
|
*
|
|
@@ -10414,7 +10421,9 @@ interface TopicExtractOptions extends PortalLlmAuth {
|
|
|
10414
10421
|
* Optional per-call request path override, forwarded to
|
|
10415
10422
|
* {@link callPortalJsonCompletion}. When set, topic extraction POSTs to
|
|
10416
10423
|
* `baseUrl + endpointOverride` instead of the default
|
|
10417
|
-
* `/api/v1/chat/completions
|
|
10424
|
+
* `/api/v1/chat/completions`. The body follows the transport, not the path: a
|
|
10425
|
+
* model that needs the Responses API is moved from a `.../chat/completions`
|
|
10426
|
+
* override to its sibling `.../responses` with a Responses-shaped body. Lets callers route
|
|
10418
10427
|
* this internal-utility pass to a dedicated endpoint. Invalid values throw at
|
|
10419
10428
|
* call time (see {@link validateEndpointOverride}).
|
|
10420
10429
|
*/
|
package/dist/react/index.d.ts
CHANGED
|
@@ -6529,7 +6529,12 @@ type PortalLlmFailureReason =
|
|
|
6529
6529
|
/** Content parsed to a literal `null`, which is never a valid response. */
|
|
6530
6530
|
| "null-completion"
|
|
6531
6531
|
/** `totalTimeoutMs` was spent before the next attempt could run. */
|
|
6532
|
-
| "time-budget-exhausted"
|
|
6532
|
+
| "time-budget-exhausted"
|
|
6533
|
+
/**
|
|
6534
|
+
* The portal's moderation gate refused the request. Terminal: the same input
|
|
6535
|
+
* is flagged again on every retry. See {@link isModerationResponse}.
|
|
6536
|
+
*/
|
|
6537
|
+
| "content-flagged";
|
|
6533
6538
|
/**
|
|
6534
6539
|
* One attempt of a {@link callPortalJsonCompletion} call, reported to
|
|
6535
6540
|
* `onAttempt` as it settles — success included. The wire-level diagnostic the
|
|
@@ -7766,7 +7771,9 @@ interface ExtractFactsOptions extends PortalLlmAuth {
|
|
|
7766
7771
|
* Optional per-call request path override, forwarded to
|
|
7767
7772
|
* {@link callPortalJsonCompletion}. When set, the extraction call POSTs to
|
|
7768
7773
|
* `baseUrl + endpointOverride` instead of the default
|
|
7769
|
-
* `/api/v1/chat/completions
|
|
7774
|
+
* `/api/v1/chat/completions`. The body follows the transport, not the path: a
|
|
7775
|
+
* model that needs the Responses API is moved from a `.../chat/completions`
|
|
7776
|
+
* override to its sibling `.../responses` with a Responses-shaped body. Lets callers route
|
|
7770
7777
|
* this internal-utility pass to a dedicated endpoint. Invalid values throw at
|
|
7771
7778
|
* call time (see {@link validateEndpointOverride}).
|
|
7772
7779
|
*
|
|
@@ -10414,7 +10421,9 @@ interface TopicExtractOptions extends PortalLlmAuth {
|
|
|
10414
10421
|
* Optional per-call request path override, forwarded to
|
|
10415
10422
|
* {@link callPortalJsonCompletion}. When set, topic extraction POSTs to
|
|
10416
10423
|
* `baseUrl + endpointOverride` instead of the default
|
|
10417
|
-
* `/api/v1/chat/completions
|
|
10424
|
+
* `/api/v1/chat/completions`. The body follows the transport, not the path: a
|
|
10425
|
+
* model that needs the Responses API is moved from a `.../chat/completions`
|
|
10426
|
+
* override to its sibling `.../responses` with a Responses-shaped body. Lets callers route
|
|
10418
10427
|
* this internal-utility pass to a dedicated endpoint. Invalid values throw at
|
|
10419
10428
|
* call time (see {@link validateEndpointOverride}).
|
|
10420
10429
|
*/
|
package/dist/react/index.mjs
CHANGED
|
@@ -18,7 +18,7 @@ import {
|
|
|
18
18
|
taskTypeHeader,
|
|
19
19
|
validateEndpointOverride,
|
|
20
20
|
withInternalFlowMarker
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-NLTO6Q36.mjs";
|
|
22
22
|
import {
|
|
23
23
|
BASE_URL,
|
|
24
24
|
MCP_R2_DOMAIN,
|
|
@@ -16054,7 +16054,7 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
|
|
|
16054
16054
|
content: m.content,
|
|
16055
16055
|
similarity: m.similarity
|
|
16056
16056
|
}));
|
|
16057
|
-
const { consolidateMemory: doConsolidate } = await import("./consolidate-
|
|
16057
|
+
const { consolidateMemory: doConsolidate } = await import("./consolidate-MYS55OAB.mjs");
|
|
16058
16058
|
const decision = await doConsolidate(trimmed, candidates, consolidateOptions);
|
|
16059
16059
|
if (decision.action === "create") return decision.fallbackReason ? null : { create: true };
|
|
16060
16060
|
if (decision.action === "supersede" && decision.content) {
|
|
@@ -19701,6 +19701,28 @@ var BatchFailureError = class extends Error {
|
|
|
19701
19701
|
this.terminal = terminal;
|
|
19702
19702
|
}
|
|
19703
19703
|
};
|
|
19704
|
+
var FlaggedBatchError = class extends Error {
|
|
19705
|
+
};
|
|
19706
|
+
function extracted(result) {
|
|
19707
|
+
return result.failedCount === 0 && result.outcome !== "empty-after-retry";
|
|
19708
|
+
}
|
|
19709
|
+
function batchError(result) {
|
|
19710
|
+
const failure = result.failure;
|
|
19711
|
+
if (failure?.reason === "http-terminal") {
|
|
19712
|
+
const status = failure.httpStatus;
|
|
19713
|
+
if (status !== void 0 && REQUEST_REJECTED_STATUSES.has(status))
|
|
19714
|
+
return new BatchFailureError(
|
|
19715
|
+
`Extraction rejected the batch (HTTP ${status}); not retried this session`,
|
|
19716
|
+
true
|
|
19717
|
+
);
|
|
19718
|
+
return new AccountFailureError(
|
|
19719
|
+
`Extraction refused for the account (HTTP ${status ?? "unknown"}); retried next session`
|
|
19720
|
+
);
|
|
19721
|
+
}
|
|
19722
|
+
if (result.failedCount > 0 || failure !== void 0 && CONTENT_FAILURE_REASONS.has(failure.reason))
|
|
19723
|
+
return new BatchFailureError("Extraction batch incomplete; retained for retry", false);
|
|
19724
|
+
return new Error("Extraction batch incomplete; retained for retry");
|
|
19725
|
+
}
|
|
19704
19726
|
var AccountFailureError = class extends Error {
|
|
19705
19727
|
};
|
|
19706
19728
|
var LockedSourcesError = class extends Error {
|
|
@@ -19709,6 +19731,16 @@ var LockedSourcesError = class extends Error {
|
|
|
19709
19731
|
this.persistentIds = persistentIds;
|
|
19710
19732
|
}
|
|
19711
19733
|
};
|
|
19734
|
+
function splitTurns(messages) {
|
|
19735
|
+
const turns = [];
|
|
19736
|
+
for (const message of messages) {
|
|
19737
|
+
const last = turns[turns.length - 1];
|
|
19738
|
+
if (!last || message.role === "user" && last.some((m) => m.role === "user"))
|
|
19739
|
+
turns.push([message]);
|
|
19740
|
+
else last.push(message);
|
|
19741
|
+
}
|
|
19742
|
+
return turns;
|
|
19743
|
+
}
|
|
19712
19744
|
function idsOf(job) {
|
|
19713
19745
|
return JSON.parse(String(job._getRaw("message_ids")));
|
|
19714
19746
|
}
|
|
@@ -19859,6 +19891,10 @@ function createDurableAutoExtractor(options) {
|
|
|
19859
19891
|
skippedThisSession.add(job.id);
|
|
19860
19892
|
return false;
|
|
19861
19893
|
}
|
|
19894
|
+
if (error instanceof FlaggedBatchError) {
|
|
19895
|
+
await acknowledge(job, ids, loaded, true);
|
|
19896
|
+
return true;
|
|
19897
|
+
}
|
|
19862
19898
|
const counted = error instanceof BatchFailureError || error instanceof LockedSourcesError && error.persistentIds.length > 0;
|
|
19863
19899
|
if (!counted) return false;
|
|
19864
19900
|
const prior = sessionFailures.get(job.id);
|
|
@@ -19985,37 +20021,50 @@ function createDurableAutoExtractor(options) {
|
|
|
19985
20021
|
const messages = loaded.flatMap(
|
|
19986
20022
|
(m) => m && m.conversationId === conversationId && (m.role === "user" || m.role === "assistant") ? [{ id: m.uniqueId, role: m.role, content: m.content }] : []
|
|
19987
20023
|
);
|
|
19988
|
-
|
|
19989
|
-
|
|
19990
|
-
|
|
19991
|
-
result = await extractBatch(
|
|
19992
|
-
|
|
20024
|
+
const jobScope = currentScope() === "private" ? "private" : String(job._getRaw("scope"));
|
|
20025
|
+
const jobFolderId = job._getRaw("folder_id") ?? null;
|
|
20026
|
+
const runExtraction = async (batch, batchIds) => {
|
|
20027
|
+
const result = await extractBatch(
|
|
20028
|
+
batch,
|
|
19993
20029
|
conversationId,
|
|
19994
|
-
|
|
19995
|
-
|
|
19996
|
-
|
|
20030
|
+
batchIds,
|
|
20031
|
+
jobScope,
|
|
20032
|
+
jobFolderId
|
|
19997
20033
|
);
|
|
19998
|
-
success = result.failedCount === 0 && result.outcome !== "empty-after-retry";
|
|
19999
20034
|
options.onTurnComplete?.(result);
|
|
20000
|
-
|
|
20001
|
-
|
|
20002
|
-
|
|
20003
|
-
|
|
20004
|
-
|
|
20005
|
-
|
|
20006
|
-
|
|
20007
|
-
|
|
20008
|
-
|
|
20035
|
+
return result;
|
|
20036
|
+
};
|
|
20037
|
+
const flaggedIds = /* @__PURE__ */ new Set();
|
|
20038
|
+
if (messages.length) {
|
|
20039
|
+
const result = await runExtraction(messages, ids);
|
|
20040
|
+
if (result.failure?.reason === "content-flagged") {
|
|
20041
|
+
const turns = splitTurns(messages);
|
|
20042
|
+
if (turns.length < 2)
|
|
20043
|
+
throw new FlaggedBatchError("Extraction batch refused by moderation; abandoned");
|
|
20044
|
+
for (const turn of turns) {
|
|
20045
|
+
const turnResult = await runExtraction(
|
|
20046
|
+
turn,
|
|
20047
|
+
turn.map((m) => m.id)
|
|
20009
20048
|
);
|
|
20010
|
-
|
|
20011
|
-
|
|
20012
|
-
|
|
20013
|
-
|
|
20014
|
-
|
|
20015
|
-
|
|
20016
|
-
|
|
20049
|
+
if (turnResult.failure?.reason === "content-flagged")
|
|
20050
|
+
for (const m of turn) flaggedIds.add(m.id);
|
|
20051
|
+
else if (!extracted(turnResult)) throw batchError(turnResult);
|
|
20052
|
+
}
|
|
20053
|
+
if (flaggedIds.size)
|
|
20054
|
+
reportError(
|
|
20055
|
+
new Error(
|
|
20056
|
+
`Dropped ${flaggedIds.size} source id(s) of an extraction batch refused by moderation`
|
|
20057
|
+
),
|
|
20058
|
+
conversationId
|
|
20059
|
+
);
|
|
20060
|
+
} else if (!extracted(result)) throw batchError(result);
|
|
20017
20061
|
}
|
|
20018
|
-
await acknowledge(
|
|
20062
|
+
await acknowledge(
|
|
20063
|
+
job,
|
|
20064
|
+
ids,
|
|
20065
|
+
loaded,
|
|
20066
|
+
ids.slice(-2).some((id) => flaggedIds.has(id))
|
|
20067
|
+
);
|
|
20019
20068
|
scheduleAfterSuccess = true;
|
|
20020
20069
|
} catch (error) {
|
|
20021
20070
|
attempts.set(job.id, attempted + 1);
|
|
@@ -23244,10 +23293,10 @@ function useChatStorage(options) {
|
|
|
23244
23293
|
let skipStorageEmbeddings = null;
|
|
23245
23294
|
let skipStorageEmbeddingsFailed = false;
|
|
23246
23295
|
if (needsEmbeddings2 && getToken) {
|
|
23247
|
-
const
|
|
23296
|
+
const extracted3 = extractUserMessageFromMessages(messages);
|
|
23248
23297
|
const messageContent = resolveStoredUserContent(
|
|
23249
23298
|
storedUserContent,
|
|
23250
|
-
|
|
23299
|
+
extracted3?.content ?? ""
|
|
23251
23300
|
);
|
|
23252
23301
|
if (messageContent.length >= MIN_CONTENT_LENGTH_FOR_TOOLS) {
|
|
23253
23302
|
const embeddingOptions = {
|
|
@@ -23404,15 +23453,15 @@ function useChatStorage(options) {
|
|
|
23404
23453
|
skipped: true
|
|
23405
23454
|
};
|
|
23406
23455
|
}
|
|
23407
|
-
const
|
|
23408
|
-
if (!
|
|
23456
|
+
const extracted2 = extractUserMessageFromMessages(messages);
|
|
23457
|
+
if (!extracted2 || !extracted2.content && !extracted2.files?.length) {
|
|
23409
23458
|
return {
|
|
23410
23459
|
data: null,
|
|
23411
23460
|
error: "No user message found in messages array"
|
|
23412
23461
|
};
|
|
23413
23462
|
}
|
|
23414
|
-
const contentForStorage = resolveStoredUserContent(storedUserContent,
|
|
23415
|
-
const filesForStorage = files ??
|
|
23463
|
+
const contentForStorage = resolveStoredUserContent(storedUserContent, extracted2.content);
|
|
23464
|
+
const filesForStorage = files ?? extracted2.files;
|
|
23416
23465
|
let fileContextForRequest;
|
|
23417
23466
|
let fileContextIsCurrentTurn = false;
|
|
23418
23467
|
let preprocessedFileIds = [];
|
|
@@ -23871,9 +23920,9 @@ function useChatStorage(options) {
|
|
|
23871
23920
|
if (result.error || !result.data) {
|
|
23872
23921
|
const abortedResult = result;
|
|
23873
23922
|
if (abortedResult.error === "Request aborted") {
|
|
23874
|
-
const
|
|
23875
|
-
const assistantContent2 =
|
|
23876
|
-
const abortedThinkingContent =
|
|
23923
|
+
const extracted3 = abortedResult.data ? extractAssistantText(abortedResult.data) : { content: "", thinking: void 0 };
|
|
23924
|
+
const assistantContent2 = extracted3.content;
|
|
23925
|
+
const abortedThinkingContent = extracted3.thinking;
|
|
23877
23926
|
const responseModel = abortedResult.data?.model || model || "";
|
|
23878
23927
|
let storedAssistantMessage2;
|
|
23879
23928
|
try {
|