@anuma/sdk 6.24.1 → 6.25.1
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-XDBX4FZY.mjs → chunk-EDABJLYN.mjs} +441 -2
- package/dist/{react/consolidate-XKS6IZFC.mjs → expo/consolidate-5WM3CFKK.mjs} +2 -4
- package/dist/expo/index.cjs +16259 -16469
- package/dist/expo/index.d.mts +106 -18
- package/dist/expo/index.d.ts +106 -18
- package/dist/expo/index.mjs +14022 -5927
- package/dist/index.cjs +88 -46
- package/dist/index.mjs +88 -46
- package/dist/memory/context.d.mts +20 -1
- package/dist/memory/context.d.ts +20 -1
- package/dist/{server/chunk-RKQ4MRS2.mjs → react/chunk-BPMINZPO.mjs} +443 -2
- package/dist/{expo/consolidate-XBYKAFKT.mjs → react/consolidate-A2X3M47N.mjs} +2 -4
- package/dist/react/index.cjs +17892 -18131
- package/dist/react/index.d.mts +113 -18
- package/dist/react/index.d.ts +113 -18
- package/dist/react/index.mjs +11492 -3153
- package/dist/{react/chunk-GPLMMMZN.mjs → server/chunk-DWNEDXA5.mjs} +425 -4
- package/dist/server/{consolidate-54P6QZKU.mjs → consolidate-53I4CTD7.mjs} +2 -4
- package/dist/server/index.cjs +11333 -11520
- package/dist/server/index.d.mts +113 -18
- package/dist/server/index.d.ts +113 -18
- package/dist/server/index.mjs +26288 -4192
- package/dist/telemetry/index.d.mts +4 -0
- package/dist/telemetry/index.d.ts +4 -0
- package/dist/tools/index.cjs +112 -2
- package/dist/tools/index.d.mts +106 -1
- package/dist/tools/index.d.ts +106 -1
- package/dist/tools/index.mjs +110 -2
- package/dist/tools/selection/index.cjs +88 -46
- package/dist/tools/selection/index.mjs +88 -46
- package/package.json +1 -1
- package/dist/expo/chunk-5LKHK5LN.mjs +0 -8142
- package/dist/expo/chunk-WUG6GTHO.mjs +0 -445
- package/dist/expo/recall-4FSY2MC4.mjs +0 -8
- package/dist/react/chunk-DOYXFYB3.mjs +0 -8472
- package/dist/react/chunk-MHZB6KIX.mjs +0 -445
- package/dist/react/recall-6FVSDGWU.mjs +0 -8
- package/dist/server/chunk-FEDRFVHD.mjs +0 -22161
- package/dist/server/chunk-YXL5VKCO.mjs +0 -429
- package/dist/server/recall-Z2WJGXOL.mjs +0 -8
package/dist/tools/index.mjs
CHANGED
|
@@ -680,6 +680,76 @@ function createChoiceTool(options) {
|
|
|
680
680
|
});
|
|
681
681
|
}
|
|
682
682
|
|
|
683
|
+
// src/tools/confirm.ts
|
|
684
|
+
function createConfirmTool(options) {
|
|
685
|
+
return createInteractiveTool(options, {
|
|
686
|
+
name: "prompt_user_confirm",
|
|
687
|
+
description: "Ask the user to approve a specific action before it happens. Use before anything that spends money or is hard to undo, such as booking a restaurant table or placing an order. List every parameter of the action, with the exact values you are about to use \u2014 the user approves what this card shows, and nothing else. Returns whether they confirmed. Do not use for ordinary yes/no questions; use prompt_user_choice for those.",
|
|
688
|
+
parameters: {
|
|
689
|
+
type: "object",
|
|
690
|
+
properties: {
|
|
691
|
+
title: {
|
|
692
|
+
type: "string",
|
|
693
|
+
description: "Short heading naming the action, e.g. 'Confirm your reservation'"
|
|
694
|
+
},
|
|
695
|
+
description: {
|
|
696
|
+
type: "string",
|
|
697
|
+
description: "Optional extra context, e.g. the cancellation policy"
|
|
698
|
+
},
|
|
699
|
+
action: {
|
|
700
|
+
type: "string",
|
|
701
|
+
description: "Machine-readable id of the action being confirmed, matching the tool that will carry it out, e.g. 'book_restaurant'"
|
|
702
|
+
},
|
|
703
|
+
parameters: {
|
|
704
|
+
type: "array",
|
|
705
|
+
items: {
|
|
706
|
+
type: "object",
|
|
707
|
+
properties: {
|
|
708
|
+
name: {
|
|
709
|
+
type: "string",
|
|
710
|
+
description: "Argument name of the acting tool, e.g. 'party_size'"
|
|
711
|
+
},
|
|
712
|
+
label: {
|
|
713
|
+
type: "string",
|
|
714
|
+
description: "Display label shown to the user, e.g. 'Party size'"
|
|
715
|
+
},
|
|
716
|
+
value: {
|
|
717
|
+
type: "string",
|
|
718
|
+
description: "The exact value you will use, as a string. Not a paraphrase \u2014 this is what the user is agreeing to."
|
|
719
|
+
}
|
|
720
|
+
},
|
|
721
|
+
required: ["name", "label", "value"]
|
|
722
|
+
},
|
|
723
|
+
description: "Every parameter of the action, with the exact values. The user sees these and nothing else."
|
|
724
|
+
}
|
|
725
|
+
},
|
|
726
|
+
required: ["title", "action", "parameters"]
|
|
727
|
+
},
|
|
728
|
+
interactionType: "confirm",
|
|
729
|
+
validate: (args) => {
|
|
730
|
+
const { title, action, parameters } = args;
|
|
731
|
+
if (typeof title !== "string" || !title) return false;
|
|
732
|
+
if (typeof action !== "string" || !action) return false;
|
|
733
|
+
if (!Array.isArray(parameters) || parameters.length === 0) return false;
|
|
734
|
+
return parameters.every((parameter) => {
|
|
735
|
+
return typeof parameter?.name === "string" && !!parameter.name && typeof parameter.label === "string" && !!parameter.label && typeof parameter.value === "string";
|
|
736
|
+
});
|
|
737
|
+
},
|
|
738
|
+
mapResult: (result, args) => {
|
|
739
|
+
if (typeof result.confirmed !== "boolean") return { cancelled: true };
|
|
740
|
+
return {
|
|
741
|
+
confirmed: result.confirmed,
|
|
742
|
+
// From the arguments rather than from the card's reply. The card was
|
|
743
|
+
// handed these to render, so echoing them back would only create a
|
|
744
|
+
// second copy that could disagree with what was on screen.
|
|
745
|
+
action: args.action,
|
|
746
|
+
parameters: args.parameters,
|
|
747
|
+
answeredAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
748
|
+
};
|
|
749
|
+
}
|
|
750
|
+
});
|
|
751
|
+
}
|
|
752
|
+
|
|
683
753
|
// src/tools/form.ts
|
|
684
754
|
var VALID_FIELD_TYPES = [
|
|
685
755
|
"text",
|
|
@@ -2418,6 +2488,12 @@ var SiwxUnsupportedError = class extends Error {
|
|
|
2418
2488
|
this.name = "SiwxUnsupportedError";
|
|
2419
2489
|
}
|
|
2420
2490
|
};
|
|
2491
|
+
var AgentresPathError = class extends Error {
|
|
2492
|
+
constructor(message) {
|
|
2493
|
+
super(message);
|
|
2494
|
+
this.name = "AgentresPathError";
|
|
2495
|
+
}
|
|
2496
|
+
};
|
|
2421
2497
|
var SiwxChallengeError = class extends Error {
|
|
2422
2498
|
constructor(message, options) {
|
|
2423
2499
|
super(message);
|
|
@@ -2495,6 +2571,7 @@ var PAYMENT_REQUIRED_HEADER = "PAYMENT-REQUIRED";
|
|
|
2495
2571
|
var SIWX_HEADER = "SIGN-IN-WITH-X";
|
|
2496
2572
|
var SIWX_EXTENSION = "sign-in-with-x";
|
|
2497
2573
|
var SOLANA_NAMESPACE = "solana:";
|
|
2574
|
+
var ED25519_SIGNATURE_BYTES = 64;
|
|
2498
2575
|
function parseChallenge(paymentRequiredHeader, expectedOrigin) {
|
|
2499
2576
|
const decoded = decodeHeader(paymentRequiredHeader);
|
|
2500
2577
|
const extensions = asRecord(decoded.extensions);
|
|
@@ -2566,6 +2643,11 @@ Resources:
|
|
|
2566
2643
|
${resources}`;
|
|
2567
2644
|
}
|
|
2568
2645
|
function buildPayload(challenge, address, signature) {
|
|
2646
|
+
if (signature.length !== ED25519_SIGNATURE_BYTES) {
|
|
2647
|
+
throw new SiwxChallengeError(
|
|
2648
|
+
`expected a ${ED25519_SIGNATURE_BYTES}-byte ed25519 signature, got ${signature.length} bytes`
|
|
2649
|
+
);
|
|
2650
|
+
}
|
|
2569
2651
|
const payload = {
|
|
2570
2652
|
domain: challenge.domain,
|
|
2571
2653
|
address,
|
|
@@ -2668,7 +2750,7 @@ function createAgentresClient(options) {
|
|
|
2668
2750
|
const fetchImpl = options.fetch ?? globalThis.fetch.bind(globalThis);
|
|
2669
2751
|
const { address, signMessage } = options;
|
|
2670
2752
|
async function withSiwx(request) {
|
|
2671
|
-
const url =
|
|
2753
|
+
const url = resolveUrl(baseUrl, request.path);
|
|
2672
2754
|
const init = requestInit(request);
|
|
2673
2755
|
const challenged = await fetchImpl(url, init);
|
|
2674
2756
|
if (challenged.status !== 402) {
|
|
@@ -2723,6 +2805,21 @@ function createAgentresClient(options) {
|
|
|
2723
2805
|
}
|
|
2724
2806
|
};
|
|
2725
2807
|
}
|
|
2808
|
+
function resolveUrl(baseUrl, path) {
|
|
2809
|
+
if (!path.startsWith("/") || path.startsWith("//")) {
|
|
2810
|
+
throw new AgentresPathError(
|
|
2811
|
+
`"${path}" is not a path on ${baseUrl} \u2014 it must start with a single "/"`
|
|
2812
|
+
);
|
|
2813
|
+
}
|
|
2814
|
+
const base = new URL(baseUrl);
|
|
2815
|
+
const resolved = new URL(path, base);
|
|
2816
|
+
if (resolved.origin !== base.origin) {
|
|
2817
|
+
throw new AgentresPathError(
|
|
2818
|
+
`"${path}" resolves to ${resolved.origin} but this client talks to ${base.origin} \u2014 refusing to send it`
|
|
2819
|
+
);
|
|
2820
|
+
}
|
|
2821
|
+
return resolved.toString();
|
|
2822
|
+
}
|
|
2726
2823
|
function requestInit(request) {
|
|
2727
2824
|
const headers = { Accept: "application/json" };
|
|
2728
2825
|
if (request.body === void 0) {
|
|
@@ -2736,7 +2833,16 @@ async function readBody(response) {
|
|
|
2736
2833
|
if (!response.ok) {
|
|
2737
2834
|
throw parseAgentresError(response.status, body);
|
|
2738
2835
|
}
|
|
2739
|
-
|
|
2836
|
+
try {
|
|
2837
|
+
return JSON.parse(body);
|
|
2838
|
+
} catch {
|
|
2839
|
+
throw new AgentresError(
|
|
2840
|
+
response.status,
|
|
2841
|
+
"INVALID_JSON",
|
|
2842
|
+
`agentres answered ${response.status} with a body that is not JSON`,
|
|
2843
|
+
response.status >= 500
|
|
2844
|
+
);
|
|
2845
|
+
}
|
|
2740
2846
|
}
|
|
2741
2847
|
|
|
2742
2848
|
// src/lib/connectors/client.ts
|
|
@@ -13865,6 +13971,7 @@ export {
|
|
|
13865
13971
|
APP_PREVIEW_BASELINE_CSS,
|
|
13866
13972
|
AUDIT_DESIGN_SCHEMA,
|
|
13867
13973
|
AgentresError,
|
|
13974
|
+
AgentresPathError,
|
|
13868
13975
|
AnumaJsxError,
|
|
13869
13976
|
CONNECTOR_ERROR_MARKER,
|
|
13870
13977
|
CREATE_DOCUMENT_SCHEMA,
|
|
@@ -13915,6 +14022,7 @@ export {
|
|
|
13915
14022
|
createChartTool,
|
|
13916
14023
|
createChatTools,
|
|
13917
14024
|
createChoiceTool,
|
|
14025
|
+
createConfirmTool,
|
|
13918
14026
|
createConnectorOfferTool,
|
|
13919
14027
|
createConnectorTokenGetter,
|
|
13920
14028
|
createDisplayTool,
|
|
@@ -922,11 +922,54 @@ var DEFAULT_API_EMBEDDING_MODEL = "qwen/qwen3-embedding-8b";
|
|
|
922
922
|
|
|
923
923
|
// src/lib/memoryEngine/generate.ts
|
|
924
924
|
var EMBED_MAX_ATTEMPTS = 4;
|
|
925
|
-
|
|
925
|
+
var DEFAULT_EMBEDDING_REQUEST_TIMEOUT_MS = 15e3;
|
|
926
|
+
var DEFAULT_EMBEDDING_TOKEN_TIMEOUT_MS = 1e4;
|
|
927
|
+
async function withDeadline(run, ms, what, parent) {
|
|
928
|
+
if (!(ms > 0) || !Number.isFinite(ms)) return Promise.resolve().then(() => run(parent));
|
|
929
|
+
const controller = new AbortController();
|
|
930
|
+
const onParentAbort = () => controller.abort(parent?.reason);
|
|
931
|
+
let timer;
|
|
932
|
+
try {
|
|
933
|
+
if (parent?.aborted) onParentAbort();
|
|
934
|
+
else parent?.addEventListener("abort", onParentAbort, { once: true });
|
|
935
|
+
const work = Promise.resolve().then(() => run(controller.signal));
|
|
936
|
+
work.catch(() => {
|
|
937
|
+
});
|
|
938
|
+
const deadline = new Promise((_, reject) => {
|
|
939
|
+
timer = setTimeout(() => {
|
|
940
|
+
const err = new Error(`${what} timed out after ${ms}ms`);
|
|
941
|
+
err.name = "TimeoutError";
|
|
942
|
+
controller.abort(err);
|
|
943
|
+
reject(err);
|
|
944
|
+
}, ms);
|
|
945
|
+
});
|
|
946
|
+
return await Promise.race([work, deadline]);
|
|
947
|
+
} finally {
|
|
948
|
+
clearTimeout(timer);
|
|
949
|
+
parent?.removeEventListener("abort", onParentAbort);
|
|
950
|
+
}
|
|
951
|
+
}
|
|
952
|
+
async function resolveAuthHeaders(options, parent) {
|
|
953
|
+
const { getToken, apiKey } = options;
|
|
954
|
+
if (apiKey) return { "X-API-Key": apiKey };
|
|
955
|
+
if (!getToken) throw new Error("Either apiKey or getToken must be provided");
|
|
956
|
+
const token = await withDeadline(
|
|
957
|
+
() => getToken(),
|
|
958
|
+
options.tokenTimeoutMs ?? DEFAULT_EMBEDDING_TOKEN_TIMEOUT_MS,
|
|
959
|
+
"embedding auth token read",
|
|
960
|
+
parent
|
|
961
|
+
);
|
|
962
|
+
if (!token) {
|
|
963
|
+
throw new Error("No token available for embedding generation");
|
|
964
|
+
}
|
|
965
|
+
return { Authorization: `Bearer ${token}` };
|
|
966
|
+
}
|
|
967
|
+
async function withEmbeddingRetry(call, stop) {
|
|
926
968
|
let last;
|
|
927
969
|
let lastThrown;
|
|
928
970
|
let threw = false;
|
|
929
971
|
for (let attempt = 1; attempt <= EMBED_MAX_ATTEMPTS; attempt++) {
|
|
972
|
+
if (stop?.aborted) throw stop.reason;
|
|
930
973
|
try {
|
|
931
974
|
threw = false;
|
|
932
975
|
last = await call();
|
|
@@ -961,34 +1004,36 @@ function embeddingErrorFrom(response) {
|
|
|
961
1004
|
return new EmbeddingHttpError(message, response.response?.status);
|
|
962
1005
|
}
|
|
963
1006
|
async function generateEmbedding(text, options) {
|
|
964
|
-
const
|
|
1007
|
+
const total = options.totalTimeoutMs;
|
|
1008
|
+
if (total === void 0) return embedOne(text, options, void 0);
|
|
1009
|
+
return withDeadline((signal) => embedOne(text, options, signal), total, "embedding");
|
|
1010
|
+
}
|
|
1011
|
+
async function embedOne(text, options, outer) {
|
|
1012
|
+
const { baseUrl = BASE_URL, model, cache } = options;
|
|
1013
|
+
const timeoutMs = options.timeoutMs ?? DEFAULT_EMBEDDING_REQUEST_TIMEOUT_MS;
|
|
965
1014
|
if (cache) {
|
|
966
1015
|
const cached = cache.get(text);
|
|
967
1016
|
if (cached) return Array.from(cached);
|
|
968
1017
|
}
|
|
969
|
-
|
|
970
|
-
if (apiKey) {
|
|
971
|
-
headers = { "X-API-Key": apiKey };
|
|
972
|
-
} else if (getToken) {
|
|
973
|
-
const token = await getToken();
|
|
974
|
-
if (!token) {
|
|
975
|
-
throw new Error("No token available for embedding generation");
|
|
976
|
-
}
|
|
977
|
-
headers = { Authorization: `Bearer ${token}` };
|
|
978
|
-
} else {
|
|
979
|
-
throw new Error("Either apiKey or getToken must be provided");
|
|
980
|
-
}
|
|
1018
|
+
const headers = await resolveAuthHeaders(options, outer);
|
|
981
1019
|
const response = await withEmbeddingRetry(
|
|
982
|
-
() =>
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
1020
|
+
() => withDeadline(
|
|
1021
|
+
(signal) => postApiV1Embeddings({
|
|
1022
|
+
baseUrl,
|
|
1023
|
+
body: {
|
|
1024
|
+
// Mask PII from the request body only — the cache above still keys on
|
|
1025
|
+
// the original `text`, so callers keep their original values.
|
|
1026
|
+
input: options.maskInput ? options.maskInput(text) : text,
|
|
1027
|
+
model: model ?? DEFAULT_API_EMBEDDING_MODEL
|
|
1028
|
+
},
|
|
1029
|
+
headers,
|
|
1030
|
+
...signal && { signal }
|
|
1031
|
+
}),
|
|
1032
|
+
timeoutMs,
|
|
1033
|
+
"embedding request",
|
|
1034
|
+
outer
|
|
1035
|
+
),
|
|
1036
|
+
outer
|
|
992
1037
|
);
|
|
993
1038
|
if (response.error) {
|
|
994
1039
|
throw embeddingErrorFrom(response);
|
|
@@ -1011,14 +1056,19 @@ async function generateEmbedding(text, options) {
|
|
|
1011
1056
|
}
|
|
1012
1057
|
var DEFAULT_EMBEDDING_BATCH_SIZE = 100;
|
|
1013
1058
|
var DEFAULT_EMBEDDING_BATCH_CONCURRENCY = 3;
|
|
1014
|
-
async function generateEmbeddingsBatch(texts, headers, baseUrl, model, onUsage, maskInput) {
|
|
1059
|
+
async function generateEmbeddingsBatch(texts, headers, baseUrl, model, onUsage, maskInput, timeoutMs) {
|
|
1015
1060
|
const response = await withEmbeddingRetry(
|
|
1016
|
-
() =>
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1061
|
+
() => withDeadline(
|
|
1062
|
+
(signal) => postApiV1Embeddings({
|
|
1063
|
+
baseUrl,
|
|
1064
|
+
// Mask PII from the request body only; cache/order still key on originals.
|
|
1065
|
+
body: { input: maskInput ? texts.map(maskInput) : texts, model },
|
|
1066
|
+
headers,
|
|
1067
|
+
...signal && { signal }
|
|
1068
|
+
}),
|
|
1069
|
+
timeoutMs,
|
|
1070
|
+
"embedding batch request"
|
|
1071
|
+
)
|
|
1022
1072
|
);
|
|
1023
1073
|
if (response.error) {
|
|
1024
1074
|
throw embeddingErrorFrom(response);
|
|
@@ -1036,7 +1086,8 @@ async function generateEmbeddingsBatch(texts, headers, baseUrl, model, onUsage,
|
|
|
1036
1086
|
}
|
|
1037
1087
|
async function generateEmbeddings(texts, options) {
|
|
1038
1088
|
if (texts.length === 0) return [];
|
|
1039
|
-
const { baseUrl = BASE_URL,
|
|
1089
|
+
const { baseUrl = BASE_URL, model, batchSize, cache } = options;
|
|
1090
|
+
const timeoutMs = options.timeoutMs ?? DEFAULT_EMBEDDING_REQUEST_TIMEOUT_MS;
|
|
1040
1091
|
const chunkSize = batchSize ?? DEFAULT_EMBEDDING_BATCH_SIZE;
|
|
1041
1092
|
const results = new Array(texts.length).fill(null);
|
|
1042
1093
|
const uncachedIndices = [];
|
|
@@ -1055,18 +1106,7 @@ async function generateEmbeddings(texts, options) {
|
|
|
1055
1106
|
if (uncachedTexts.length === 0) {
|
|
1056
1107
|
return results;
|
|
1057
1108
|
}
|
|
1058
|
-
|
|
1059
|
-
if (apiKey) {
|
|
1060
|
-
headers = { "X-API-Key": apiKey };
|
|
1061
|
-
} else if (getToken) {
|
|
1062
|
-
const token = await getToken();
|
|
1063
|
-
if (!token) {
|
|
1064
|
-
throw new Error("No token available for embedding generation");
|
|
1065
|
-
}
|
|
1066
|
-
headers = { Authorization: `Bearer ${token}` };
|
|
1067
|
-
} else {
|
|
1068
|
-
throw new Error("Either apiKey or getToken must be provided");
|
|
1069
|
-
}
|
|
1109
|
+
const headers = await resolveAuthHeaders(options);
|
|
1070
1110
|
const embeddingModel = model ?? DEFAULT_API_EMBEDDING_MODEL;
|
|
1071
1111
|
let newEmbeddings;
|
|
1072
1112
|
if (uncachedTexts.length <= chunkSize) {
|
|
@@ -1076,7 +1116,8 @@ async function generateEmbeddings(texts, options) {
|
|
|
1076
1116
|
baseUrl,
|
|
1077
1117
|
embeddingModel,
|
|
1078
1118
|
options.onUsage,
|
|
1079
|
-
options.maskInput
|
|
1119
|
+
options.maskInput,
|
|
1120
|
+
timeoutMs
|
|
1080
1121
|
);
|
|
1081
1122
|
} else {
|
|
1082
1123
|
const chunks = [];
|
|
@@ -1094,7 +1135,8 @@ async function generateEmbeddings(texts, options) {
|
|
|
1094
1135
|
baseUrl,
|
|
1095
1136
|
embeddingModel,
|
|
1096
1137
|
options.onUsage,
|
|
1097
|
-
options.maskInput
|
|
1138
|
+
options.maskInput,
|
|
1139
|
+
timeoutMs
|
|
1098
1140
|
);
|
|
1099
1141
|
}
|
|
1100
1142
|
};
|
|
@@ -801,11 +801,54 @@ var DEFAULT_API_EMBEDDING_MODEL = "qwen/qwen3-embedding-8b";
|
|
|
801
801
|
|
|
802
802
|
// src/lib/memoryEngine/generate.ts
|
|
803
803
|
var EMBED_MAX_ATTEMPTS = 4;
|
|
804
|
-
|
|
804
|
+
var DEFAULT_EMBEDDING_REQUEST_TIMEOUT_MS = 15e3;
|
|
805
|
+
var DEFAULT_EMBEDDING_TOKEN_TIMEOUT_MS = 1e4;
|
|
806
|
+
async function withDeadline(run, ms, what, parent) {
|
|
807
|
+
if (!(ms > 0) || !Number.isFinite(ms)) return Promise.resolve().then(() => run(parent));
|
|
808
|
+
const controller = new AbortController();
|
|
809
|
+
const onParentAbort = () => controller.abort(parent?.reason);
|
|
810
|
+
let timer;
|
|
811
|
+
try {
|
|
812
|
+
if (parent?.aborted) onParentAbort();
|
|
813
|
+
else parent?.addEventListener("abort", onParentAbort, { once: true });
|
|
814
|
+
const work = Promise.resolve().then(() => run(controller.signal));
|
|
815
|
+
work.catch(() => {
|
|
816
|
+
});
|
|
817
|
+
const deadline = new Promise((_, reject) => {
|
|
818
|
+
timer = setTimeout(() => {
|
|
819
|
+
const err = new Error(`${what} timed out after ${ms}ms`);
|
|
820
|
+
err.name = "TimeoutError";
|
|
821
|
+
controller.abort(err);
|
|
822
|
+
reject(err);
|
|
823
|
+
}, ms);
|
|
824
|
+
});
|
|
825
|
+
return await Promise.race([work, deadline]);
|
|
826
|
+
} finally {
|
|
827
|
+
clearTimeout(timer);
|
|
828
|
+
parent?.removeEventListener("abort", onParentAbort);
|
|
829
|
+
}
|
|
830
|
+
}
|
|
831
|
+
async function resolveAuthHeaders(options, parent) {
|
|
832
|
+
const { getToken, apiKey } = options;
|
|
833
|
+
if (apiKey) return { "X-API-Key": apiKey };
|
|
834
|
+
if (!getToken) throw new Error("Either apiKey or getToken must be provided");
|
|
835
|
+
const token = await withDeadline(
|
|
836
|
+
() => getToken(),
|
|
837
|
+
options.tokenTimeoutMs ?? DEFAULT_EMBEDDING_TOKEN_TIMEOUT_MS,
|
|
838
|
+
"embedding auth token read",
|
|
839
|
+
parent
|
|
840
|
+
);
|
|
841
|
+
if (!token) {
|
|
842
|
+
throw new Error("No token available for embedding generation");
|
|
843
|
+
}
|
|
844
|
+
return { Authorization: `Bearer ${token}` };
|
|
845
|
+
}
|
|
846
|
+
async function withEmbeddingRetry(call, stop) {
|
|
805
847
|
let last;
|
|
806
848
|
let lastThrown;
|
|
807
849
|
let threw = false;
|
|
808
850
|
for (let attempt = 1; attempt <= EMBED_MAX_ATTEMPTS; attempt++) {
|
|
851
|
+
if (stop?.aborted) throw stop.reason;
|
|
809
852
|
try {
|
|
810
853
|
threw = false;
|
|
811
854
|
last = await call();
|
|
@@ -840,34 +883,36 @@ function embeddingErrorFrom(response) {
|
|
|
840
883
|
return new EmbeddingHttpError(message, response.response?.status);
|
|
841
884
|
}
|
|
842
885
|
async function generateEmbedding(text, options) {
|
|
843
|
-
const
|
|
886
|
+
const total = options.totalTimeoutMs;
|
|
887
|
+
if (total === void 0) return embedOne(text, options, void 0);
|
|
888
|
+
return withDeadline((signal) => embedOne(text, options, signal), total, "embedding");
|
|
889
|
+
}
|
|
890
|
+
async function embedOne(text, options, outer) {
|
|
891
|
+
const { baseUrl = BASE_URL, model, cache } = options;
|
|
892
|
+
const timeoutMs = options.timeoutMs ?? DEFAULT_EMBEDDING_REQUEST_TIMEOUT_MS;
|
|
844
893
|
if (cache) {
|
|
845
894
|
const cached = cache.get(text);
|
|
846
895
|
if (cached) return Array.from(cached);
|
|
847
896
|
}
|
|
848
|
-
|
|
849
|
-
if (apiKey) {
|
|
850
|
-
headers = { "X-API-Key": apiKey };
|
|
851
|
-
} else if (getToken) {
|
|
852
|
-
const token = await getToken();
|
|
853
|
-
if (!token) {
|
|
854
|
-
throw new Error("No token available for embedding generation");
|
|
855
|
-
}
|
|
856
|
-
headers = { Authorization: `Bearer ${token}` };
|
|
857
|
-
} else {
|
|
858
|
-
throw new Error("Either apiKey or getToken must be provided");
|
|
859
|
-
}
|
|
897
|
+
const headers = await resolveAuthHeaders(options, outer);
|
|
860
898
|
const response = await withEmbeddingRetry(
|
|
861
|
-
() =>
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
899
|
+
() => withDeadline(
|
|
900
|
+
(signal) => postApiV1Embeddings({
|
|
901
|
+
baseUrl,
|
|
902
|
+
body: {
|
|
903
|
+
// Mask PII from the request body only — the cache above still keys on
|
|
904
|
+
// the original `text`, so callers keep their original values.
|
|
905
|
+
input: options.maskInput ? options.maskInput(text) : text,
|
|
906
|
+
model: model ?? DEFAULT_API_EMBEDDING_MODEL
|
|
907
|
+
},
|
|
908
|
+
headers,
|
|
909
|
+
...signal && { signal }
|
|
910
|
+
}),
|
|
911
|
+
timeoutMs,
|
|
912
|
+
"embedding request",
|
|
913
|
+
outer
|
|
914
|
+
),
|
|
915
|
+
outer
|
|
871
916
|
);
|
|
872
917
|
if (response.error) {
|
|
873
918
|
throw embeddingErrorFrom(response);
|
|
@@ -890,14 +935,19 @@ async function generateEmbedding(text, options) {
|
|
|
890
935
|
}
|
|
891
936
|
var DEFAULT_EMBEDDING_BATCH_SIZE = 100;
|
|
892
937
|
var DEFAULT_EMBEDDING_BATCH_CONCURRENCY = 3;
|
|
893
|
-
async function generateEmbeddingsBatch(texts, headers, baseUrl, model, onUsage, maskInput) {
|
|
938
|
+
async function generateEmbeddingsBatch(texts, headers, baseUrl, model, onUsage, maskInput, timeoutMs) {
|
|
894
939
|
const response = await withEmbeddingRetry(
|
|
895
|
-
() =>
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
940
|
+
() => withDeadline(
|
|
941
|
+
(signal) => postApiV1Embeddings({
|
|
942
|
+
baseUrl,
|
|
943
|
+
// Mask PII from the request body only; cache/order still key on originals.
|
|
944
|
+
body: { input: maskInput ? texts.map(maskInput) : texts, model },
|
|
945
|
+
headers,
|
|
946
|
+
...signal && { signal }
|
|
947
|
+
}),
|
|
948
|
+
timeoutMs,
|
|
949
|
+
"embedding batch request"
|
|
950
|
+
)
|
|
901
951
|
);
|
|
902
952
|
if (response.error) {
|
|
903
953
|
throw embeddingErrorFrom(response);
|
|
@@ -915,7 +965,8 @@ async function generateEmbeddingsBatch(texts, headers, baseUrl, model, onUsage,
|
|
|
915
965
|
}
|
|
916
966
|
async function generateEmbeddings(texts, options) {
|
|
917
967
|
if (texts.length === 0) return [];
|
|
918
|
-
const { baseUrl = BASE_URL,
|
|
968
|
+
const { baseUrl = BASE_URL, model, batchSize, cache } = options;
|
|
969
|
+
const timeoutMs = options.timeoutMs ?? DEFAULT_EMBEDDING_REQUEST_TIMEOUT_MS;
|
|
919
970
|
const chunkSize = batchSize ?? DEFAULT_EMBEDDING_BATCH_SIZE;
|
|
920
971
|
const results = new Array(texts.length).fill(null);
|
|
921
972
|
const uncachedIndices = [];
|
|
@@ -934,18 +985,7 @@ async function generateEmbeddings(texts, options) {
|
|
|
934
985
|
if (uncachedTexts.length === 0) {
|
|
935
986
|
return results;
|
|
936
987
|
}
|
|
937
|
-
|
|
938
|
-
if (apiKey) {
|
|
939
|
-
headers = { "X-API-Key": apiKey };
|
|
940
|
-
} else if (getToken) {
|
|
941
|
-
const token = await getToken();
|
|
942
|
-
if (!token) {
|
|
943
|
-
throw new Error("No token available for embedding generation");
|
|
944
|
-
}
|
|
945
|
-
headers = { Authorization: `Bearer ${token}` };
|
|
946
|
-
} else {
|
|
947
|
-
throw new Error("Either apiKey or getToken must be provided");
|
|
948
|
-
}
|
|
988
|
+
const headers = await resolveAuthHeaders(options);
|
|
949
989
|
const embeddingModel = model ?? DEFAULT_API_EMBEDDING_MODEL;
|
|
950
990
|
let newEmbeddings;
|
|
951
991
|
if (uncachedTexts.length <= chunkSize) {
|
|
@@ -955,7 +995,8 @@ async function generateEmbeddings(texts, options) {
|
|
|
955
995
|
baseUrl,
|
|
956
996
|
embeddingModel,
|
|
957
997
|
options.onUsage,
|
|
958
|
-
options.maskInput
|
|
998
|
+
options.maskInput,
|
|
999
|
+
timeoutMs
|
|
959
1000
|
);
|
|
960
1001
|
} else {
|
|
961
1002
|
const chunks = [];
|
|
@@ -973,7 +1014,8 @@ async function generateEmbeddings(texts, options) {
|
|
|
973
1014
|
baseUrl,
|
|
974
1015
|
embeddingModel,
|
|
975
1016
|
options.onUsage,
|
|
976
|
-
options.maskInput
|
|
1017
|
+
options.maskInput,
|
|
1018
|
+
timeoutMs
|
|
977
1019
|
);
|
|
978
1020
|
}
|
|
979
1021
|
};
|