@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/expo/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);
|
|
@@ -20269,6 +20296,28 @@ var BatchFailureError = class extends Error {
|
|
|
20269
20296
|
this.terminal = terminal;
|
|
20270
20297
|
}
|
|
20271
20298
|
};
|
|
20299
|
+
var FlaggedBatchError = class extends Error {
|
|
20300
|
+
};
|
|
20301
|
+
function extracted(result) {
|
|
20302
|
+
return result.failedCount === 0 && result.outcome !== "empty-after-retry";
|
|
20303
|
+
}
|
|
20304
|
+
function batchError(result) {
|
|
20305
|
+
const failure = result.failure;
|
|
20306
|
+
if (failure?.reason === "http-terminal") {
|
|
20307
|
+
const status = failure.httpStatus;
|
|
20308
|
+
if (status !== void 0 && REQUEST_REJECTED_STATUSES.has(status))
|
|
20309
|
+
return new BatchFailureError(
|
|
20310
|
+
`Extraction rejected the batch (HTTP ${status}); not retried this session`,
|
|
20311
|
+
true
|
|
20312
|
+
);
|
|
20313
|
+
return new AccountFailureError(
|
|
20314
|
+
`Extraction refused for the account (HTTP ${status ?? "unknown"}); retried next session`
|
|
20315
|
+
);
|
|
20316
|
+
}
|
|
20317
|
+
if (result.failedCount > 0 || failure !== void 0 && CONTENT_FAILURE_REASONS.has(failure.reason))
|
|
20318
|
+
return new BatchFailureError("Extraction batch incomplete; retained for retry", false);
|
|
20319
|
+
return new Error("Extraction batch incomplete; retained for retry");
|
|
20320
|
+
}
|
|
20272
20321
|
var AccountFailureError = class extends Error {
|
|
20273
20322
|
};
|
|
20274
20323
|
var LockedSourcesError = class extends Error {
|
|
@@ -20277,6 +20326,16 @@ var LockedSourcesError = class extends Error {
|
|
|
20277
20326
|
this.persistentIds = persistentIds;
|
|
20278
20327
|
}
|
|
20279
20328
|
};
|
|
20329
|
+
function splitTurns(messages) {
|
|
20330
|
+
const turns = [];
|
|
20331
|
+
for (const message of messages) {
|
|
20332
|
+
const last = turns[turns.length - 1];
|
|
20333
|
+
if (!last || message.role === "user" && last.some((m) => m.role === "user"))
|
|
20334
|
+
turns.push([message]);
|
|
20335
|
+
else last.push(message);
|
|
20336
|
+
}
|
|
20337
|
+
return turns;
|
|
20338
|
+
}
|
|
20280
20339
|
function idsOf(job) {
|
|
20281
20340
|
return JSON.parse(String(job._getRaw("message_ids")));
|
|
20282
20341
|
}
|
|
@@ -20427,6 +20486,10 @@ function createDurableAutoExtractor(options) {
|
|
|
20427
20486
|
skippedThisSession.add(job.id);
|
|
20428
20487
|
return false;
|
|
20429
20488
|
}
|
|
20489
|
+
if (error instanceof FlaggedBatchError) {
|
|
20490
|
+
await acknowledge(job, ids, loaded, true);
|
|
20491
|
+
return true;
|
|
20492
|
+
}
|
|
20430
20493
|
const counted = error instanceof BatchFailureError || error instanceof LockedSourcesError && error.persistentIds.length > 0;
|
|
20431
20494
|
if (!counted) return false;
|
|
20432
20495
|
const prior = sessionFailures.get(job.id);
|
|
@@ -20553,37 +20616,50 @@ function createDurableAutoExtractor(options) {
|
|
|
20553
20616
|
const messages = loaded.flatMap(
|
|
20554
20617
|
(m) => m && m.conversationId === conversationId && (m.role === "user" || m.role === "assistant") ? [{ id: m.uniqueId, role: m.role, content: m.content }] : []
|
|
20555
20618
|
);
|
|
20556
|
-
|
|
20557
|
-
|
|
20558
|
-
|
|
20559
|
-
result = await extractBatch(
|
|
20560
|
-
|
|
20619
|
+
const jobScope = currentScope() === "private" ? "private" : String(job._getRaw("scope"));
|
|
20620
|
+
const jobFolderId = job._getRaw("folder_id") ?? null;
|
|
20621
|
+
const runExtraction = async (batch, batchIds) => {
|
|
20622
|
+
const result = await extractBatch(
|
|
20623
|
+
batch,
|
|
20561
20624
|
conversationId,
|
|
20562
|
-
|
|
20563
|
-
|
|
20564
|
-
|
|
20625
|
+
batchIds,
|
|
20626
|
+
jobScope,
|
|
20627
|
+
jobFolderId
|
|
20565
20628
|
);
|
|
20566
|
-
success = result.failedCount === 0 && result.outcome !== "empty-after-retry";
|
|
20567
20629
|
options.onTurnComplete?.(result);
|
|
20568
|
-
|
|
20569
|
-
|
|
20570
|
-
|
|
20571
|
-
|
|
20572
|
-
|
|
20573
|
-
|
|
20574
|
-
|
|
20575
|
-
|
|
20576
|
-
|
|
20630
|
+
return result;
|
|
20631
|
+
};
|
|
20632
|
+
const flaggedIds = /* @__PURE__ */ new Set();
|
|
20633
|
+
if (messages.length) {
|
|
20634
|
+
const result = await runExtraction(messages, ids);
|
|
20635
|
+
if (result.failure?.reason === "content-flagged") {
|
|
20636
|
+
const turns = splitTurns(messages);
|
|
20637
|
+
if (turns.length < 2)
|
|
20638
|
+
throw new FlaggedBatchError("Extraction batch refused by moderation; abandoned");
|
|
20639
|
+
for (const turn of turns) {
|
|
20640
|
+
const turnResult = await runExtraction(
|
|
20641
|
+
turn,
|
|
20642
|
+
turn.map((m) => m.id)
|
|
20577
20643
|
);
|
|
20578
|
-
|
|
20579
|
-
|
|
20580
|
-
|
|
20581
|
-
|
|
20582
|
-
|
|
20583
|
-
|
|
20584
|
-
|
|
20644
|
+
if (turnResult.failure?.reason === "content-flagged")
|
|
20645
|
+
for (const m of turn) flaggedIds.add(m.id);
|
|
20646
|
+
else if (!extracted(turnResult)) throw batchError(turnResult);
|
|
20647
|
+
}
|
|
20648
|
+
if (flaggedIds.size)
|
|
20649
|
+
reportError(
|
|
20650
|
+
new Error(
|
|
20651
|
+
`Dropped ${flaggedIds.size} source id(s) of an extraction batch refused by moderation`
|
|
20652
|
+
),
|
|
20653
|
+
conversationId
|
|
20654
|
+
);
|
|
20655
|
+
} else if (!extracted(result)) throw batchError(result);
|
|
20585
20656
|
}
|
|
20586
|
-
await acknowledge(
|
|
20657
|
+
await acknowledge(
|
|
20658
|
+
job,
|
|
20659
|
+
ids,
|
|
20660
|
+
loaded,
|
|
20661
|
+
ids.slice(-2).some((id) => flaggedIds.has(id))
|
|
20662
|
+
);
|
|
20587
20663
|
scheduleAfterSuccess = true;
|
|
20588
20664
|
} catch (error) {
|
|
20589
20665
|
attempts.set(job.id, attempted + 1);
|
|
@@ -22241,10 +22317,10 @@ function useChatStorage(options) {
|
|
|
22241
22317
|
let mergedTools2 = void 0;
|
|
22242
22318
|
let filteredServerTools2 = [];
|
|
22243
22319
|
const isServerToolsFunction2 = typeof serverToolsFilter === "function";
|
|
22244
|
-
const
|
|
22320
|
+
const extracted3 = extractUserMessageFromMessages(messages);
|
|
22245
22321
|
const messageContent = resolveStoredUserContent(
|
|
22246
22322
|
storedUserContent,
|
|
22247
|
-
|
|
22323
|
+
extracted3?.content ?? ""
|
|
22248
22324
|
);
|
|
22249
22325
|
let skipUserEmbedding;
|
|
22250
22326
|
let skipEmbeddingFailed = false;
|
|
@@ -22410,15 +22486,15 @@ function useChatStorage(options) {
|
|
|
22410
22486
|
skipped: true
|
|
22411
22487
|
};
|
|
22412
22488
|
}
|
|
22413
|
-
const
|
|
22414
|
-
if (!
|
|
22489
|
+
const extracted2 = extractUserMessageFromMessages(messages);
|
|
22490
|
+
if (!extracted2 || !extracted2.content && !extracted2.files?.length) {
|
|
22415
22491
|
return {
|
|
22416
22492
|
data: null,
|
|
22417
22493
|
error: "No user message found in messages array"
|
|
22418
22494
|
};
|
|
22419
22495
|
}
|
|
22420
|
-
const contentForStorage = resolveStoredUserContent(storedUserContent,
|
|
22421
|
-
const filesForStorage = files ??
|
|
22496
|
+
const contentForStorage = resolveStoredUserContent(storedUserContent, extracted2.content);
|
|
22497
|
+
const filesForStorage = files ?? extracted2.files;
|
|
22422
22498
|
let convId;
|
|
22423
22499
|
try {
|
|
22424
22500
|
convId = await ensureConversation();
|
|
@@ -22746,9 +22822,9 @@ function useChatStorage(options) {
|
|
|
22746
22822
|
if (result.error || !result.data) {
|
|
22747
22823
|
const abortedResult = result;
|
|
22748
22824
|
if (abortedResult.error === "Request aborted") {
|
|
22749
|
-
const
|
|
22750
|
-
const assistantContent2 =
|
|
22751
|
-
const abortedThinkingContent =
|
|
22825
|
+
const extracted3 = abortedResult.data ? extractAssistantText(abortedResult.data) : { content: "", thinking: void 0 };
|
|
22826
|
+
const assistantContent2 = extracted3.content;
|
|
22827
|
+
const abortedThinkingContent = extracted3.thinking;
|
|
22752
22828
|
const responseModel = abortedResult.data?.model || model || "";
|
|
22753
22829
|
let storedAssistantMessage2;
|
|
22754
22830
|
try {
|
package/dist/expo/index.d.mts
CHANGED
|
@@ -5202,7 +5202,12 @@ type PortalLlmFailureReason =
|
|
|
5202
5202
|
/** Content parsed to a literal `null`, which is never a valid response. */
|
|
5203
5203
|
| "null-completion"
|
|
5204
5204
|
/** `totalTimeoutMs` was spent before the next attempt could run. */
|
|
5205
|
-
| "time-budget-exhausted"
|
|
5205
|
+
| "time-budget-exhausted"
|
|
5206
|
+
/**
|
|
5207
|
+
* The portal's moderation gate refused the request. Terminal: the same input
|
|
5208
|
+
* is flagged again on every retry. See {@link isModerationResponse}.
|
|
5209
|
+
*/
|
|
5210
|
+
| "content-flagged";
|
|
5206
5211
|
/**
|
|
5207
5212
|
* One attempt of a {@link callPortalJsonCompletion} call, reported to
|
|
5208
5213
|
* `onAttempt` as it settles — success included. The wire-level diagnostic the
|
|
@@ -6439,7 +6444,9 @@ interface ExtractFactsOptions extends PortalLlmAuth {
|
|
|
6439
6444
|
* Optional per-call request path override, forwarded to
|
|
6440
6445
|
* {@link callPortalJsonCompletion}. When set, the extraction call POSTs to
|
|
6441
6446
|
* `baseUrl + endpointOverride` instead of the default
|
|
6442
|
-
* `/api/v1/chat/completions
|
|
6447
|
+
* `/api/v1/chat/completions`. The body follows the transport, not the path: a
|
|
6448
|
+
* model that needs the Responses API is moved from a `.../chat/completions`
|
|
6449
|
+
* override to its sibling `.../responses` with a Responses-shaped body. Lets callers route
|
|
6443
6450
|
* this internal-utility pass to a dedicated endpoint. Invalid values throw at
|
|
6444
6451
|
* call time (see {@link validateEndpointOverride}).
|
|
6445
6452
|
*
|
|
@@ -9121,7 +9128,9 @@ interface TopicExtractOptions extends PortalLlmAuth {
|
|
|
9121
9128
|
* Optional per-call request path override, forwarded to
|
|
9122
9129
|
* {@link callPortalJsonCompletion}. When set, topic extraction POSTs to
|
|
9123
9130
|
* `baseUrl + endpointOverride` instead of the default
|
|
9124
|
-
* `/api/v1/chat/completions
|
|
9131
|
+
* `/api/v1/chat/completions`. The body follows the transport, not the path: a
|
|
9132
|
+
* model that needs the Responses API is moved from a `.../chat/completions`
|
|
9133
|
+
* override to its sibling `.../responses` with a Responses-shaped body. Lets callers route
|
|
9125
9134
|
* this internal-utility pass to a dedicated endpoint. Invalid values throw at
|
|
9126
9135
|
* call time (see {@link validateEndpointOverride}).
|
|
9127
9136
|
*/
|
package/dist/expo/index.d.ts
CHANGED
|
@@ -5202,7 +5202,12 @@ type PortalLlmFailureReason =
|
|
|
5202
5202
|
/** Content parsed to a literal `null`, which is never a valid response. */
|
|
5203
5203
|
| "null-completion"
|
|
5204
5204
|
/** `totalTimeoutMs` was spent before the next attempt could run. */
|
|
5205
|
-
| "time-budget-exhausted"
|
|
5205
|
+
| "time-budget-exhausted"
|
|
5206
|
+
/**
|
|
5207
|
+
* The portal's moderation gate refused the request. Terminal: the same input
|
|
5208
|
+
* is flagged again on every retry. See {@link isModerationResponse}.
|
|
5209
|
+
*/
|
|
5210
|
+
| "content-flagged";
|
|
5206
5211
|
/**
|
|
5207
5212
|
* One attempt of a {@link callPortalJsonCompletion} call, reported to
|
|
5208
5213
|
* `onAttempt` as it settles — success included. The wire-level diagnostic the
|
|
@@ -6439,7 +6444,9 @@ interface ExtractFactsOptions extends PortalLlmAuth {
|
|
|
6439
6444
|
* Optional per-call request path override, forwarded to
|
|
6440
6445
|
* {@link callPortalJsonCompletion}. When set, the extraction call POSTs to
|
|
6441
6446
|
* `baseUrl + endpointOverride` instead of the default
|
|
6442
|
-
* `/api/v1/chat/completions
|
|
6447
|
+
* `/api/v1/chat/completions`. The body follows the transport, not the path: a
|
|
6448
|
+
* model that needs the Responses API is moved from a `.../chat/completions`
|
|
6449
|
+
* override to its sibling `.../responses` with a Responses-shaped body. Lets callers route
|
|
6443
6450
|
* this internal-utility pass to a dedicated endpoint. Invalid values throw at
|
|
6444
6451
|
* call time (see {@link validateEndpointOverride}).
|
|
6445
6452
|
*
|
|
@@ -9121,7 +9128,9 @@ interface TopicExtractOptions extends PortalLlmAuth {
|
|
|
9121
9128
|
* Optional per-call request path override, forwarded to
|
|
9122
9129
|
* {@link callPortalJsonCompletion}. When set, topic extraction POSTs to
|
|
9123
9130
|
* `baseUrl + endpointOverride` instead of the default
|
|
9124
|
-
* `/api/v1/chat/completions
|
|
9131
|
+
* `/api/v1/chat/completions`. The body follows the transport, not the path: a
|
|
9132
|
+
* model that needs the Responses API is moved from a `.../chat/completions`
|
|
9133
|
+
* override to its sibling `.../responses` with a Responses-shaped body. Lets callers route
|
|
9125
9134
|
* this internal-utility pass to a dedicated endpoint. Invalid values throw at
|
|
9126
9135
|
* call time (see {@link validateEndpointOverride}).
|
|
9127
9136
|
*/
|
package/dist/expo/index.mjs
CHANGED
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
taskTypeHeader,
|
|
20
20
|
validateEndpointOverride,
|
|
21
21
|
withInternalFlowMarker
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-VD5M6QAI.mjs";
|
|
23
23
|
import {
|
|
24
24
|
BASE_URL,
|
|
25
25
|
MCP_R2_DOMAIN,
|
|
@@ -14952,7 +14952,7 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
|
|
|
14952
14952
|
content: m.content,
|
|
14953
14953
|
similarity: m.similarity
|
|
14954
14954
|
}));
|
|
14955
|
-
const { consolidateMemory: doConsolidate } = await import("./consolidate-
|
|
14955
|
+
const { consolidateMemory: doConsolidate } = await import("./consolidate-6J5HHAJY.mjs");
|
|
14956
14956
|
const decision = await doConsolidate(trimmed, candidates, consolidateOptions);
|
|
14957
14957
|
if (decision.action === "create") return decision.fallbackReason ? null : { create: true };
|
|
14958
14958
|
if (decision.action === "supersede" && decision.content) {
|
|
@@ -18599,6 +18599,28 @@ var BatchFailureError = class extends Error {
|
|
|
18599
18599
|
this.terminal = terminal;
|
|
18600
18600
|
}
|
|
18601
18601
|
};
|
|
18602
|
+
var FlaggedBatchError = class extends Error {
|
|
18603
|
+
};
|
|
18604
|
+
function extracted(result) {
|
|
18605
|
+
return result.failedCount === 0 && result.outcome !== "empty-after-retry";
|
|
18606
|
+
}
|
|
18607
|
+
function batchError(result) {
|
|
18608
|
+
const failure = result.failure;
|
|
18609
|
+
if (failure?.reason === "http-terminal") {
|
|
18610
|
+
const status = failure.httpStatus;
|
|
18611
|
+
if (status !== void 0 && REQUEST_REJECTED_STATUSES.has(status))
|
|
18612
|
+
return new BatchFailureError(
|
|
18613
|
+
`Extraction rejected the batch (HTTP ${status}); not retried this session`,
|
|
18614
|
+
true
|
|
18615
|
+
);
|
|
18616
|
+
return new AccountFailureError(
|
|
18617
|
+
`Extraction refused for the account (HTTP ${status ?? "unknown"}); retried next session`
|
|
18618
|
+
);
|
|
18619
|
+
}
|
|
18620
|
+
if (result.failedCount > 0 || failure !== void 0 && CONTENT_FAILURE_REASONS.has(failure.reason))
|
|
18621
|
+
return new BatchFailureError("Extraction batch incomplete; retained for retry", false);
|
|
18622
|
+
return new Error("Extraction batch incomplete; retained for retry");
|
|
18623
|
+
}
|
|
18602
18624
|
var AccountFailureError = class extends Error {
|
|
18603
18625
|
};
|
|
18604
18626
|
var LockedSourcesError = class extends Error {
|
|
@@ -18607,6 +18629,16 @@ var LockedSourcesError = class extends Error {
|
|
|
18607
18629
|
this.persistentIds = persistentIds;
|
|
18608
18630
|
}
|
|
18609
18631
|
};
|
|
18632
|
+
function splitTurns(messages) {
|
|
18633
|
+
const turns = [];
|
|
18634
|
+
for (const message of messages) {
|
|
18635
|
+
const last = turns[turns.length - 1];
|
|
18636
|
+
if (!last || message.role === "user" && last.some((m) => m.role === "user"))
|
|
18637
|
+
turns.push([message]);
|
|
18638
|
+
else last.push(message);
|
|
18639
|
+
}
|
|
18640
|
+
return turns;
|
|
18641
|
+
}
|
|
18610
18642
|
function idsOf(job) {
|
|
18611
18643
|
return JSON.parse(String(job._getRaw("message_ids")));
|
|
18612
18644
|
}
|
|
@@ -18757,6 +18789,10 @@ function createDurableAutoExtractor(options) {
|
|
|
18757
18789
|
skippedThisSession.add(job.id);
|
|
18758
18790
|
return false;
|
|
18759
18791
|
}
|
|
18792
|
+
if (error instanceof FlaggedBatchError) {
|
|
18793
|
+
await acknowledge(job, ids, loaded, true);
|
|
18794
|
+
return true;
|
|
18795
|
+
}
|
|
18760
18796
|
const counted = error instanceof BatchFailureError || error instanceof LockedSourcesError && error.persistentIds.length > 0;
|
|
18761
18797
|
if (!counted) return false;
|
|
18762
18798
|
const prior = sessionFailures.get(job.id);
|
|
@@ -18883,37 +18919,50 @@ function createDurableAutoExtractor(options) {
|
|
|
18883
18919
|
const messages = loaded.flatMap(
|
|
18884
18920
|
(m) => m && m.conversationId === conversationId && (m.role === "user" || m.role === "assistant") ? [{ id: m.uniqueId, role: m.role, content: m.content }] : []
|
|
18885
18921
|
);
|
|
18886
|
-
|
|
18887
|
-
|
|
18888
|
-
|
|
18889
|
-
result = await extractBatch(
|
|
18890
|
-
|
|
18922
|
+
const jobScope = currentScope() === "private" ? "private" : String(job._getRaw("scope"));
|
|
18923
|
+
const jobFolderId = job._getRaw("folder_id") ?? null;
|
|
18924
|
+
const runExtraction = async (batch, batchIds) => {
|
|
18925
|
+
const result = await extractBatch(
|
|
18926
|
+
batch,
|
|
18891
18927
|
conversationId,
|
|
18892
|
-
|
|
18893
|
-
|
|
18894
|
-
|
|
18928
|
+
batchIds,
|
|
18929
|
+
jobScope,
|
|
18930
|
+
jobFolderId
|
|
18895
18931
|
);
|
|
18896
|
-
success = result.failedCount === 0 && result.outcome !== "empty-after-retry";
|
|
18897
18932
|
options.onTurnComplete?.(result);
|
|
18898
|
-
|
|
18899
|
-
|
|
18900
|
-
|
|
18901
|
-
|
|
18902
|
-
|
|
18903
|
-
|
|
18904
|
-
|
|
18905
|
-
|
|
18906
|
-
|
|
18933
|
+
return result;
|
|
18934
|
+
};
|
|
18935
|
+
const flaggedIds = /* @__PURE__ */ new Set();
|
|
18936
|
+
if (messages.length) {
|
|
18937
|
+
const result = await runExtraction(messages, ids);
|
|
18938
|
+
if (result.failure?.reason === "content-flagged") {
|
|
18939
|
+
const turns = splitTurns(messages);
|
|
18940
|
+
if (turns.length < 2)
|
|
18941
|
+
throw new FlaggedBatchError("Extraction batch refused by moderation; abandoned");
|
|
18942
|
+
for (const turn of turns) {
|
|
18943
|
+
const turnResult = await runExtraction(
|
|
18944
|
+
turn,
|
|
18945
|
+
turn.map((m) => m.id)
|
|
18907
18946
|
);
|
|
18908
|
-
|
|
18909
|
-
|
|
18910
|
-
|
|
18911
|
-
|
|
18912
|
-
|
|
18913
|
-
|
|
18914
|
-
|
|
18947
|
+
if (turnResult.failure?.reason === "content-flagged")
|
|
18948
|
+
for (const m of turn) flaggedIds.add(m.id);
|
|
18949
|
+
else if (!extracted(turnResult)) throw batchError(turnResult);
|
|
18950
|
+
}
|
|
18951
|
+
if (flaggedIds.size)
|
|
18952
|
+
reportError(
|
|
18953
|
+
new Error(
|
|
18954
|
+
`Dropped ${flaggedIds.size} source id(s) of an extraction batch refused by moderation`
|
|
18955
|
+
),
|
|
18956
|
+
conversationId
|
|
18957
|
+
);
|
|
18958
|
+
} else if (!extracted(result)) throw batchError(result);
|
|
18915
18959
|
}
|
|
18916
|
-
await acknowledge(
|
|
18960
|
+
await acknowledge(
|
|
18961
|
+
job,
|
|
18962
|
+
ids,
|
|
18963
|
+
loaded,
|
|
18964
|
+
ids.slice(-2).some((id) => flaggedIds.has(id))
|
|
18965
|
+
);
|
|
18917
18966
|
scheduleAfterSuccess = true;
|
|
18918
18967
|
} catch (error) {
|
|
18919
18968
|
attempts.set(job.id, attempted + 1);
|
|
@@ -20568,10 +20617,10 @@ function useChatStorage(options) {
|
|
|
20568
20617
|
let mergedTools2 = void 0;
|
|
20569
20618
|
let filteredServerTools2 = [];
|
|
20570
20619
|
const isServerToolsFunction2 = typeof serverToolsFilter === "function";
|
|
20571
|
-
const
|
|
20620
|
+
const extracted3 = extractUserMessageFromMessages(messages);
|
|
20572
20621
|
const messageContent = resolveStoredUserContent(
|
|
20573
20622
|
storedUserContent,
|
|
20574
|
-
|
|
20623
|
+
extracted3?.content ?? ""
|
|
20575
20624
|
);
|
|
20576
20625
|
let skipUserEmbedding;
|
|
20577
20626
|
let skipEmbeddingFailed = false;
|
|
@@ -20737,15 +20786,15 @@ function useChatStorage(options) {
|
|
|
20737
20786
|
skipped: true
|
|
20738
20787
|
};
|
|
20739
20788
|
}
|
|
20740
|
-
const
|
|
20741
|
-
if (!
|
|
20789
|
+
const extracted2 = extractUserMessageFromMessages(messages);
|
|
20790
|
+
if (!extracted2 || !extracted2.content && !extracted2.files?.length) {
|
|
20742
20791
|
return {
|
|
20743
20792
|
data: null,
|
|
20744
20793
|
error: "No user message found in messages array"
|
|
20745
20794
|
};
|
|
20746
20795
|
}
|
|
20747
|
-
const contentForStorage = resolveStoredUserContent(storedUserContent,
|
|
20748
|
-
const filesForStorage = files ??
|
|
20796
|
+
const contentForStorage = resolveStoredUserContent(storedUserContent, extracted2.content);
|
|
20797
|
+
const filesForStorage = files ?? extracted2.files;
|
|
20749
20798
|
let convId;
|
|
20750
20799
|
try {
|
|
20751
20800
|
convId = await ensureConversation();
|
|
@@ -21073,9 +21122,9 @@ function useChatStorage(options) {
|
|
|
21073
21122
|
if (result.error || !result.data) {
|
|
21074
21123
|
const abortedResult = result;
|
|
21075
21124
|
if (abortedResult.error === "Request aborted") {
|
|
21076
|
-
const
|
|
21077
|
-
const assistantContent2 =
|
|
21078
|
-
const abortedThinkingContent =
|
|
21125
|
+
const extracted3 = abortedResult.data ? extractAssistantText(abortedResult.data) : { content: "", thinking: void 0 };
|
|
21126
|
+
const assistantContent2 = extracted3.content;
|
|
21127
|
+
const abortedThinkingContent = extracted3.thinking;
|
|
21079
21128
|
const responseModel = abortedResult.data?.model || model || "";
|
|
21080
21129
|
let storedAssistantMessage2;
|
|
21081
21130
|
try {
|