@modelrelay/sdk 0.4.0 → 0.7.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/index.cjs +851 -33
- package/dist/index.d.cts +626 -12
- package/dist/index.d.ts +626 -12
- package/dist/index.js +824 -30
- package/package.json +3 -2
package/dist/index.cjs
CHANGED
|
@@ -34,11 +34,26 @@ __export(index_exports, {
|
|
|
34
34
|
ModelRelayError: () => ModelRelayError,
|
|
35
35
|
Models: () => Models,
|
|
36
36
|
Providers: () => Providers,
|
|
37
|
-
SANDBOX_BASE_URL: () => SANDBOX_BASE_URL,
|
|
38
37
|
SDK_VERSION: () => SDK_VERSION,
|
|
39
|
-
STAGING_BASE_URL: () => STAGING_BASE_URL,
|
|
40
38
|
StopReasons: () => StopReasons,
|
|
39
|
+
TiersClient: () => TiersClient,
|
|
40
|
+
ToolArgsError: () => ToolArgsError,
|
|
41
|
+
ToolCallAccumulator: () => ToolCallAccumulator,
|
|
42
|
+
ToolChoiceTypes: () => ToolChoiceTypes,
|
|
43
|
+
ToolRegistry: () => ToolRegistry,
|
|
44
|
+
ToolTypes: () => ToolTypes,
|
|
41
45
|
TransportError: () => TransportError,
|
|
46
|
+
assistantMessageWithToolCalls: () => assistantMessageWithToolCalls,
|
|
47
|
+
createFunctionTool: () => createFunctionTool,
|
|
48
|
+
createFunctionToolFromSchema: () => createFunctionToolFromSchema,
|
|
49
|
+
createRetryMessages: () => createRetryMessages,
|
|
50
|
+
createWebSearchTool: () => createWebSearchTool,
|
|
51
|
+
executeWithRetry: () => executeWithRetry,
|
|
52
|
+
firstToolCall: () => firstToolCall,
|
|
53
|
+
formatToolErrorForModel: () => formatToolErrorForModel,
|
|
54
|
+
getRetryableErrors: () => getRetryableErrors,
|
|
55
|
+
hasRetryableErrors: () => hasRetryableErrors,
|
|
56
|
+
hasToolCalls: () => hasToolCalls,
|
|
42
57
|
isPublishableKey: () => isPublishableKey,
|
|
43
58
|
mergeMetrics: () => mergeMetrics,
|
|
44
59
|
mergeTrace: () => mergeTrace,
|
|
@@ -47,8 +62,17 @@ __export(index_exports, {
|
|
|
47
62
|
normalizeProvider: () => normalizeProvider,
|
|
48
63
|
normalizeStopReason: () => normalizeStopReason,
|
|
49
64
|
parseErrorResponse: () => parseErrorResponse,
|
|
65
|
+
parseToolArgs: () => parseToolArgs,
|
|
66
|
+
parseToolArgsRaw: () => parseToolArgsRaw,
|
|
50
67
|
providerToString: () => providerToString,
|
|
51
|
-
|
|
68
|
+
respondToToolCall: () => respondToToolCall,
|
|
69
|
+
stopReasonToString: () => stopReasonToString,
|
|
70
|
+
toolChoiceAuto: () => toolChoiceAuto,
|
|
71
|
+
toolChoiceNone: () => toolChoiceNone,
|
|
72
|
+
toolChoiceRequired: () => toolChoiceRequired,
|
|
73
|
+
toolResultMessage: () => toolResultMessage,
|
|
74
|
+
tryParseToolArgs: () => tryParseToolArgs,
|
|
75
|
+
zodToJsonSchema: () => zodToJsonSchema
|
|
52
76
|
});
|
|
53
77
|
module.exports = __toCommonJS(index_exports);
|
|
54
78
|
|
|
@@ -272,7 +296,7 @@ function isTokenReusable(token) {
|
|
|
272
296
|
// package.json
|
|
273
297
|
var package_default = {
|
|
274
298
|
name: "@modelrelay/sdk",
|
|
275
|
-
version: "0.
|
|
299
|
+
version: "0.7.0",
|
|
276
300
|
description: "TypeScript SDK for the ModelRelay API",
|
|
277
301
|
type: "module",
|
|
278
302
|
main: "dist/index.cjs",
|
|
@@ -306,15 +330,14 @@ var package_default = {
|
|
|
306
330
|
devDependencies: {
|
|
307
331
|
tsup: "^8.2.4",
|
|
308
332
|
typescript: "^5.6.3",
|
|
309
|
-
vitest: "^2.1.4"
|
|
333
|
+
vitest: "^2.1.4",
|
|
334
|
+
zod: "^3.23.0"
|
|
310
335
|
}
|
|
311
336
|
};
|
|
312
337
|
|
|
313
338
|
// src/types.ts
|
|
314
339
|
var SDK_VERSION = package_default.version || "0.0.0";
|
|
315
340
|
var DEFAULT_BASE_URL = "https://api.modelrelay.ai/api/v1";
|
|
316
|
-
var STAGING_BASE_URL = "https://api-stg.modelrelay.ai/api/v1";
|
|
317
|
-
var SANDBOX_BASE_URL = "https://api.sandbox.modelrelay.ai/api/v1";
|
|
318
341
|
var DEFAULT_CLIENT_HEADER = `modelrelay-ts/${SDK_VERSION}`;
|
|
319
342
|
var DEFAULT_CONNECT_TIMEOUT_MS = 5e3;
|
|
320
343
|
var DEFAULT_REQUEST_TIMEOUT_MS = 6e4;
|
|
@@ -336,7 +359,6 @@ var Providers = {
|
|
|
336
359
|
OpenAI: "openai",
|
|
337
360
|
Anthropic: "anthropic",
|
|
338
361
|
Grok: "grok",
|
|
339
|
-
OpenRouter: "openrouter",
|
|
340
362
|
Echo: "echo"
|
|
341
363
|
};
|
|
342
364
|
var Models = {
|
|
@@ -346,11 +368,23 @@ var Models = {
|
|
|
346
368
|
AnthropicClaude35HaikuLatest: "anthropic/claude-3-5-haiku-latest",
|
|
347
369
|
AnthropicClaude35SonnetLatest: "anthropic/claude-3-5-sonnet-latest",
|
|
348
370
|
AnthropicClaudeOpus45: "anthropic/claude-opus-4-5-20251101",
|
|
349
|
-
|
|
371
|
+
AnthropicClaude35Haiku: "anthropic/claude-3.5-haiku",
|
|
350
372
|
Grok2: "grok-2",
|
|
351
|
-
|
|
373
|
+
Grok4_1FastNonReasoning: "grok-4-1-fast-non-reasoning",
|
|
374
|
+
Grok4_1FastReasoning: "grok-4-1-fast-reasoning",
|
|
352
375
|
Echo1: "echo-1"
|
|
353
376
|
};
|
|
377
|
+
var ToolTypes = {
|
|
378
|
+
Function: "function",
|
|
379
|
+
WebSearch: "web_search",
|
|
380
|
+
XSearch: "x_search",
|
|
381
|
+
CodeExecution: "code_execution"
|
|
382
|
+
};
|
|
383
|
+
var ToolChoiceTypes = {
|
|
384
|
+
Auto: "auto",
|
|
385
|
+
Required: "required",
|
|
386
|
+
None: "none"
|
|
387
|
+
};
|
|
354
388
|
function mergeMetrics(base, override) {
|
|
355
389
|
if (!base && !override) return void 0;
|
|
356
390
|
return {
|
|
@@ -587,7 +621,7 @@ var ChatCompletionsStream = class {
|
|
|
587
621
|
const context = this.enrichContext(evt);
|
|
588
622
|
this.context = context;
|
|
589
623
|
this.trace?.streamEvent?.({ context, event: evt });
|
|
590
|
-
if (evt.type === "message_start" || evt.type === "message_delta" || evt.type === "message_stop") {
|
|
624
|
+
if (evt.type === "message_start" || evt.type === "message_delta" || evt.type === "message_stop" || evt.type === "tool_use_start" || evt.type === "tool_use_delta" || evt.type === "tool_use_stop") {
|
|
591
625
|
this.recordFirstToken();
|
|
592
626
|
}
|
|
593
627
|
if (evt.type === "message_stop" && evt.usage && this.metrics?.usage) {
|
|
@@ -672,11 +706,15 @@ function mapChatEvent(raw, requestId) {
|
|
|
672
706
|
const model = normalizeModelId(p.model || p?.message?.model);
|
|
673
707
|
const stopReason = normalizeStopReason(p.stop_reason);
|
|
674
708
|
const textDelta = extractTextDelta(p);
|
|
709
|
+
const toolCallDelta = extractToolCallDelta(p, type);
|
|
710
|
+
const toolCalls = extractToolCalls(p, type);
|
|
675
711
|
return {
|
|
676
712
|
type,
|
|
677
713
|
event: raw.event || type,
|
|
678
714
|
data: p,
|
|
679
715
|
textDelta,
|
|
716
|
+
toolCallDelta,
|
|
717
|
+
toolCalls,
|
|
680
718
|
responseId,
|
|
681
719
|
model,
|
|
682
720
|
stopReason,
|
|
@@ -696,6 +734,12 @@ function normalizeEventType(eventName, payload) {
|
|
|
696
734
|
return "message_delta";
|
|
697
735
|
case "message_stop":
|
|
698
736
|
return "message_stop";
|
|
737
|
+
case "tool_use_start":
|
|
738
|
+
return "tool_use_start";
|
|
739
|
+
case "tool_use_delta":
|
|
740
|
+
return "tool_use_delta";
|
|
741
|
+
case "tool_use_stop":
|
|
742
|
+
return "tool_use_stop";
|
|
699
743
|
case "ping":
|
|
700
744
|
return "ping";
|
|
701
745
|
default:
|
|
@@ -706,6 +750,9 @@ function extractTextDelta(payload) {
|
|
|
706
750
|
if (!payload || typeof payload !== "object") {
|
|
707
751
|
return void 0;
|
|
708
752
|
}
|
|
753
|
+
if (typeof payload.text_delta === "string" && payload.text_delta !== "") {
|
|
754
|
+
return payload.text_delta;
|
|
755
|
+
}
|
|
709
756
|
if (typeof payload.delta === "string") {
|
|
710
757
|
return payload.delta;
|
|
711
758
|
}
|
|
@@ -719,9 +766,56 @@ function extractTextDelta(payload) {
|
|
|
719
766
|
}
|
|
720
767
|
return void 0;
|
|
721
768
|
}
|
|
769
|
+
function extractToolCallDelta(payload, type) {
|
|
770
|
+
if (!payload || typeof payload !== "object") {
|
|
771
|
+
return void 0;
|
|
772
|
+
}
|
|
773
|
+
if (type !== "tool_use_start" && type !== "tool_use_delta") {
|
|
774
|
+
return void 0;
|
|
775
|
+
}
|
|
776
|
+
if (payload.tool_call_delta) {
|
|
777
|
+
const d = payload.tool_call_delta;
|
|
778
|
+
return {
|
|
779
|
+
index: d.index ?? 0,
|
|
780
|
+
id: d.id,
|
|
781
|
+
type: d.type,
|
|
782
|
+
function: d.function ? {
|
|
783
|
+
name: d.function.name,
|
|
784
|
+
arguments: d.function.arguments
|
|
785
|
+
} : void 0
|
|
786
|
+
};
|
|
787
|
+
}
|
|
788
|
+
if (typeof payload.index === "number" || payload.id || payload.name) {
|
|
789
|
+
return {
|
|
790
|
+
index: payload.index ?? 0,
|
|
791
|
+
id: payload.id,
|
|
792
|
+
type: payload.tool_type,
|
|
793
|
+
function: payload.name || payload.arguments ? {
|
|
794
|
+
name: payload.name,
|
|
795
|
+
arguments: payload.arguments
|
|
796
|
+
} : void 0
|
|
797
|
+
};
|
|
798
|
+
}
|
|
799
|
+
return void 0;
|
|
800
|
+
}
|
|
801
|
+
function extractToolCalls(payload, type) {
|
|
802
|
+
if (!payload || typeof payload !== "object") {
|
|
803
|
+
return void 0;
|
|
804
|
+
}
|
|
805
|
+
if (type !== "tool_use_stop" && type !== "message_stop") {
|
|
806
|
+
return void 0;
|
|
807
|
+
}
|
|
808
|
+
if (payload.tool_calls?.length) {
|
|
809
|
+
return normalizeToolCalls(payload.tool_calls);
|
|
810
|
+
}
|
|
811
|
+
if (payload.tool_call) {
|
|
812
|
+
return normalizeToolCalls([payload.tool_call]);
|
|
813
|
+
}
|
|
814
|
+
return void 0;
|
|
815
|
+
}
|
|
722
816
|
function normalizeChatResponse(payload, requestId) {
|
|
723
817
|
const p = payload;
|
|
724
|
-
|
|
818
|
+
const response = {
|
|
725
819
|
id: p?.id,
|
|
726
820
|
provider: normalizeProvider(p?.provider),
|
|
727
821
|
content: Array.isArray(p?.content) ? p.content : p?.content ? [String(p.content)] : [],
|
|
@@ -730,6 +824,17 @@ function normalizeChatResponse(payload, requestId) {
|
|
|
730
824
|
usage: normalizeUsage(p?.usage),
|
|
731
825
|
requestId
|
|
732
826
|
};
|
|
827
|
+
if (p?.tool_calls?.length) {
|
|
828
|
+
response.toolCalls = normalizeToolCalls(p.tool_calls);
|
|
829
|
+
}
|
|
830
|
+
return response;
|
|
831
|
+
}
|
|
832
|
+
function normalizeToolCalls(toolCalls) {
|
|
833
|
+
return toolCalls.map((tc) => ({
|
|
834
|
+
id: tc.id,
|
|
835
|
+
type: tc.type || ToolTypes.Function,
|
|
836
|
+
function: tc.function ? { name: tc.function.name, arguments: tc.function.arguments } : void 0
|
|
837
|
+
}));
|
|
733
838
|
}
|
|
734
839
|
function normalizeUsage(payload) {
|
|
735
840
|
if (!payload) {
|
|
@@ -757,13 +862,65 @@ function buildProxyBody(params, metadata) {
|
|
|
757
862
|
if (metadata && Object.keys(metadata).length > 0) body.metadata = metadata;
|
|
758
863
|
if (params.stop?.length) body.stop = params.stop;
|
|
759
864
|
if (params.stopSequences?.length) body.stop_sequences = params.stopSequences;
|
|
865
|
+
if (params.tools?.length) body.tools = normalizeTools(params.tools);
|
|
866
|
+
if (params.toolChoice) body.tool_choice = normalizeToolChoice(params.toolChoice);
|
|
760
867
|
return body;
|
|
761
868
|
}
|
|
762
869
|
function normalizeMessages(messages) {
|
|
763
|
-
return messages.map((msg) =>
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
870
|
+
return messages.map((msg) => {
|
|
871
|
+
const normalized = {
|
|
872
|
+
role: msg.role || "user",
|
|
873
|
+
content: msg.content
|
|
874
|
+
};
|
|
875
|
+
if (msg.toolCalls?.length) {
|
|
876
|
+
normalized.tool_calls = msg.toolCalls.map((tc) => ({
|
|
877
|
+
id: tc.id,
|
|
878
|
+
type: tc.type,
|
|
879
|
+
function: tc.function ? { name: tc.function.name, arguments: tc.function.arguments } : void 0
|
|
880
|
+
}));
|
|
881
|
+
}
|
|
882
|
+
if (msg.toolCallId) {
|
|
883
|
+
normalized.tool_call_id = msg.toolCallId;
|
|
884
|
+
}
|
|
885
|
+
return normalized;
|
|
886
|
+
});
|
|
887
|
+
}
|
|
888
|
+
function normalizeTools(tools) {
|
|
889
|
+
return tools.map((tool) => {
|
|
890
|
+
const normalized = { type: tool.type };
|
|
891
|
+
if (tool.function) {
|
|
892
|
+
normalized.function = {
|
|
893
|
+
name: tool.function.name,
|
|
894
|
+
description: tool.function.description,
|
|
895
|
+
parameters: tool.function.parameters
|
|
896
|
+
};
|
|
897
|
+
}
|
|
898
|
+
if (tool.webSearch) {
|
|
899
|
+
normalized.web_search = {
|
|
900
|
+
allowed_domains: tool.webSearch.allowedDomains,
|
|
901
|
+
excluded_domains: tool.webSearch.excludedDomains,
|
|
902
|
+
max_uses: tool.webSearch.maxUses
|
|
903
|
+
};
|
|
904
|
+
}
|
|
905
|
+
if (tool.xSearch) {
|
|
906
|
+
normalized.x_search = {
|
|
907
|
+
allowed_handles: tool.xSearch.allowedHandles,
|
|
908
|
+
excluded_handles: tool.xSearch.excludedHandles,
|
|
909
|
+
from_date: tool.xSearch.fromDate,
|
|
910
|
+
to_date: tool.xSearch.toDate
|
|
911
|
+
};
|
|
912
|
+
}
|
|
913
|
+
if (tool.codeExecution) {
|
|
914
|
+
normalized.code_execution = {
|
|
915
|
+
language: tool.codeExecution.language,
|
|
916
|
+
timeout_ms: tool.codeExecution.timeoutMs
|
|
917
|
+
};
|
|
918
|
+
}
|
|
919
|
+
return normalized;
|
|
920
|
+
});
|
|
921
|
+
}
|
|
922
|
+
function normalizeToolChoice(tc) {
|
|
923
|
+
return { type: tc.type };
|
|
767
924
|
}
|
|
768
925
|
function requestIdFromHeaders(headers) {
|
|
769
926
|
return headers.get(REQUEST_ID_HEADER) || headers.get("X-Request-Id") || void 0;
|
|
@@ -917,13 +1074,50 @@ var CustomersClient = class {
|
|
|
917
1074
|
}
|
|
918
1075
|
};
|
|
919
1076
|
|
|
1077
|
+
// src/tiers.ts
|
|
1078
|
+
var TiersClient = class {
|
|
1079
|
+
constructor(http, cfg) {
|
|
1080
|
+
this.http = http;
|
|
1081
|
+
this.apiKey = cfg.apiKey;
|
|
1082
|
+
}
|
|
1083
|
+
ensureApiKey() {
|
|
1084
|
+
if (!this.apiKey || !this.apiKey.startsWith("mr_pk_") && !this.apiKey.startsWith("mr_sk_")) {
|
|
1085
|
+
throw new ConfigError(
|
|
1086
|
+
"API key (mr_pk_* or mr_sk_*) required for tier operations"
|
|
1087
|
+
);
|
|
1088
|
+
}
|
|
1089
|
+
}
|
|
1090
|
+
/**
|
|
1091
|
+
* List all tiers in the project.
|
|
1092
|
+
*/
|
|
1093
|
+
async list() {
|
|
1094
|
+
this.ensureApiKey();
|
|
1095
|
+
const response = await this.http.json("/tiers", {
|
|
1096
|
+
method: "GET",
|
|
1097
|
+
apiKey: this.apiKey
|
|
1098
|
+
});
|
|
1099
|
+
return response.tiers;
|
|
1100
|
+
}
|
|
1101
|
+
/**
|
|
1102
|
+
* Get a tier by ID.
|
|
1103
|
+
*/
|
|
1104
|
+
async get(tierId) {
|
|
1105
|
+
this.ensureApiKey();
|
|
1106
|
+
if (!tierId?.trim()) {
|
|
1107
|
+
throw new ConfigError("tierId is required");
|
|
1108
|
+
}
|
|
1109
|
+
const response = await this.http.json(`/tiers/${tierId}`, {
|
|
1110
|
+
method: "GET",
|
|
1111
|
+
apiKey: this.apiKey
|
|
1112
|
+
});
|
|
1113
|
+
return response.tier;
|
|
1114
|
+
}
|
|
1115
|
+
};
|
|
1116
|
+
|
|
920
1117
|
// src/http.ts
|
|
921
1118
|
var HTTPClient = class {
|
|
922
1119
|
constructor(cfg) {
|
|
923
|
-
const
|
|
924
|
-
const resolvedBase = normalizeBaseUrl(
|
|
925
|
-
cfg.baseUrl || baseFromEnv || DEFAULT_BASE_URL
|
|
926
|
-
);
|
|
1120
|
+
const resolvedBase = normalizeBaseUrl(cfg.baseUrl || DEFAULT_BASE_URL);
|
|
927
1121
|
if (!isValidHttpUrl(resolvedBase)) {
|
|
928
1122
|
throw new ConfigError(
|
|
929
1123
|
"baseUrl must start with http:// or https://"
|
|
@@ -1136,12 +1330,6 @@ function normalizeBaseUrl(value) {
|
|
|
1136
1330
|
function isValidHttpUrl(value) {
|
|
1137
1331
|
return /^https?:\/\//i.test(value);
|
|
1138
1332
|
}
|
|
1139
|
-
function baseUrlForEnvironment(env) {
|
|
1140
|
-
if (!env || env === "production") return void 0;
|
|
1141
|
-
if (env === "staging") return STAGING_BASE_URL;
|
|
1142
|
-
if (env === "sandbox") return SANDBOX_BASE_URL;
|
|
1143
|
-
return void 0;
|
|
1144
|
-
}
|
|
1145
1333
|
function normalizeRetryConfig(retry) {
|
|
1146
1334
|
if (retry === false) return void 0;
|
|
1147
1335
|
const cfg = retry || {};
|
|
@@ -1253,6 +1441,610 @@ function withRequestId(context, headers) {
|
|
|
1253
1441
|
return { ...context, requestId };
|
|
1254
1442
|
}
|
|
1255
1443
|
|
|
1444
|
+
// src/tools.ts
|
|
1445
|
+
function zodToJsonSchema(schema, options = {}) {
|
|
1446
|
+
const result = convertZodType(schema);
|
|
1447
|
+
if (options.includeSchema) {
|
|
1448
|
+
const schemaVersion = options.target === "draft-04" ? "http://json-schema.org/draft-04/schema#" : options.target === "draft-2019-09" ? "https://json-schema.org/draft/2019-09/schema" : options.target === "draft-2020-12" ? "https://json-schema.org/draft/2020-12/schema" : "http://json-schema.org/draft-07/schema#";
|
|
1449
|
+
return { $schema: schemaVersion, ...result };
|
|
1450
|
+
}
|
|
1451
|
+
return result;
|
|
1452
|
+
}
|
|
1453
|
+
function convertZodType(schema) {
|
|
1454
|
+
const def = schema._def;
|
|
1455
|
+
const typeName = def.typeName;
|
|
1456
|
+
switch (typeName) {
|
|
1457
|
+
case "ZodString":
|
|
1458
|
+
return convertZodString(def);
|
|
1459
|
+
case "ZodNumber":
|
|
1460
|
+
return convertZodNumber(def);
|
|
1461
|
+
case "ZodBoolean":
|
|
1462
|
+
return { type: "boolean" };
|
|
1463
|
+
case "ZodNull":
|
|
1464
|
+
return { type: "null" };
|
|
1465
|
+
case "ZodArray":
|
|
1466
|
+
return convertZodArray(def);
|
|
1467
|
+
case "ZodObject":
|
|
1468
|
+
return convertZodObject(def);
|
|
1469
|
+
case "ZodEnum":
|
|
1470
|
+
return convertZodEnum(def);
|
|
1471
|
+
case "ZodNativeEnum":
|
|
1472
|
+
return convertZodNativeEnum(def);
|
|
1473
|
+
case "ZodLiteral":
|
|
1474
|
+
return { const: def.value };
|
|
1475
|
+
case "ZodUnion":
|
|
1476
|
+
return convertZodUnion(def);
|
|
1477
|
+
case "ZodOptional": {
|
|
1478
|
+
const inner = convertZodType(def.innerType);
|
|
1479
|
+
if (def.description && !inner.description) {
|
|
1480
|
+
inner.description = def.description;
|
|
1481
|
+
}
|
|
1482
|
+
return inner;
|
|
1483
|
+
}
|
|
1484
|
+
case "ZodNullable":
|
|
1485
|
+
return convertZodNullable(def);
|
|
1486
|
+
case "ZodDefault":
|
|
1487
|
+
return { ...convertZodType(def.innerType), default: def.defaultValue() };
|
|
1488
|
+
case "ZodEffects":
|
|
1489
|
+
return convertZodType(def.schema);
|
|
1490
|
+
case "ZodRecord":
|
|
1491
|
+
return convertZodRecord(def);
|
|
1492
|
+
case "ZodTuple":
|
|
1493
|
+
return convertZodTuple(def);
|
|
1494
|
+
case "ZodAny":
|
|
1495
|
+
case "ZodUnknown":
|
|
1496
|
+
return {};
|
|
1497
|
+
default:
|
|
1498
|
+
return {};
|
|
1499
|
+
}
|
|
1500
|
+
}
|
|
1501
|
+
function convertZodString(def) {
|
|
1502
|
+
const result = { type: "string" };
|
|
1503
|
+
const checks = def.checks;
|
|
1504
|
+
if (checks) {
|
|
1505
|
+
for (const check of checks) {
|
|
1506
|
+
switch (check.kind) {
|
|
1507
|
+
case "min":
|
|
1508
|
+
result.minLength = check.value;
|
|
1509
|
+
break;
|
|
1510
|
+
case "max":
|
|
1511
|
+
result.maxLength = check.value;
|
|
1512
|
+
break;
|
|
1513
|
+
case "length":
|
|
1514
|
+
result.minLength = check.value;
|
|
1515
|
+
result.maxLength = check.value;
|
|
1516
|
+
break;
|
|
1517
|
+
case "email":
|
|
1518
|
+
result.format = "email";
|
|
1519
|
+
break;
|
|
1520
|
+
case "url":
|
|
1521
|
+
result.format = "uri";
|
|
1522
|
+
break;
|
|
1523
|
+
case "uuid":
|
|
1524
|
+
result.format = "uuid";
|
|
1525
|
+
break;
|
|
1526
|
+
case "datetime":
|
|
1527
|
+
result.format = "date-time";
|
|
1528
|
+
break;
|
|
1529
|
+
case "regex":
|
|
1530
|
+
result.pattern = check.value.source;
|
|
1531
|
+
break;
|
|
1532
|
+
}
|
|
1533
|
+
}
|
|
1534
|
+
}
|
|
1535
|
+
if (def.description) {
|
|
1536
|
+
result.description = def.description;
|
|
1537
|
+
}
|
|
1538
|
+
return result;
|
|
1539
|
+
}
|
|
1540
|
+
function convertZodNumber(def) {
|
|
1541
|
+
const result = { type: "number" };
|
|
1542
|
+
const checks = def.checks;
|
|
1543
|
+
if (checks) {
|
|
1544
|
+
for (const check of checks) {
|
|
1545
|
+
switch (check.kind) {
|
|
1546
|
+
case "int":
|
|
1547
|
+
result.type = "integer";
|
|
1548
|
+
break;
|
|
1549
|
+
case "min":
|
|
1550
|
+
if (check.inclusive === false) {
|
|
1551
|
+
result.exclusiveMinimum = check.value;
|
|
1552
|
+
} else {
|
|
1553
|
+
result.minimum = check.value;
|
|
1554
|
+
}
|
|
1555
|
+
break;
|
|
1556
|
+
case "max":
|
|
1557
|
+
if (check.inclusive === false) {
|
|
1558
|
+
result.exclusiveMaximum = check.value;
|
|
1559
|
+
} else {
|
|
1560
|
+
result.maximum = check.value;
|
|
1561
|
+
}
|
|
1562
|
+
break;
|
|
1563
|
+
case "multipleOf":
|
|
1564
|
+
result.multipleOf = check.value;
|
|
1565
|
+
break;
|
|
1566
|
+
}
|
|
1567
|
+
}
|
|
1568
|
+
}
|
|
1569
|
+
if (def.description) {
|
|
1570
|
+
result.description = def.description;
|
|
1571
|
+
}
|
|
1572
|
+
return result;
|
|
1573
|
+
}
|
|
1574
|
+
function convertZodArray(def) {
|
|
1575
|
+
const result = {
|
|
1576
|
+
type: "array",
|
|
1577
|
+
items: convertZodType(def.type)
|
|
1578
|
+
};
|
|
1579
|
+
if (def.minLength !== void 0 && def.minLength !== null) {
|
|
1580
|
+
result.minItems = def.minLength.value;
|
|
1581
|
+
}
|
|
1582
|
+
if (def.maxLength !== void 0 && def.maxLength !== null) {
|
|
1583
|
+
result.maxItems = def.maxLength.value;
|
|
1584
|
+
}
|
|
1585
|
+
if (def.description) {
|
|
1586
|
+
result.description = def.description;
|
|
1587
|
+
}
|
|
1588
|
+
return result;
|
|
1589
|
+
}
|
|
1590
|
+
function convertZodObject(def) {
|
|
1591
|
+
const shape = def.shape;
|
|
1592
|
+
const shapeObj = typeof shape === "function" ? shape() : shape;
|
|
1593
|
+
const properties = {};
|
|
1594
|
+
const required = [];
|
|
1595
|
+
for (const [key, value] of Object.entries(shapeObj)) {
|
|
1596
|
+
properties[key] = convertZodType(value);
|
|
1597
|
+
const valueDef = value._def;
|
|
1598
|
+
const isOptional = valueDef.typeName === "ZodOptional" || valueDef.typeName === "ZodDefault" || valueDef.typeName === "ZodNullable" && valueDef.innerType?._def?.typeName === "ZodDefault";
|
|
1599
|
+
if (!isOptional) {
|
|
1600
|
+
required.push(key);
|
|
1601
|
+
}
|
|
1602
|
+
}
|
|
1603
|
+
const result = {
|
|
1604
|
+
type: "object",
|
|
1605
|
+
properties
|
|
1606
|
+
};
|
|
1607
|
+
if (required.length > 0) {
|
|
1608
|
+
result.required = required;
|
|
1609
|
+
}
|
|
1610
|
+
if (def.description) {
|
|
1611
|
+
result.description = def.description;
|
|
1612
|
+
}
|
|
1613
|
+
const unknownKeys = def.unknownKeys;
|
|
1614
|
+
if (unknownKeys === "strict") {
|
|
1615
|
+
result.additionalProperties = false;
|
|
1616
|
+
}
|
|
1617
|
+
return result;
|
|
1618
|
+
}
|
|
1619
|
+
function convertZodEnum(def) {
|
|
1620
|
+
const result = {
|
|
1621
|
+
type: "string",
|
|
1622
|
+
enum: def.values
|
|
1623
|
+
};
|
|
1624
|
+
if (def.description) {
|
|
1625
|
+
result.description = def.description;
|
|
1626
|
+
}
|
|
1627
|
+
return result;
|
|
1628
|
+
}
|
|
1629
|
+
function convertZodNativeEnum(def) {
|
|
1630
|
+
const enumValues = def.values;
|
|
1631
|
+
const values = Object.values(enumValues).filter(
|
|
1632
|
+
(v) => typeof v === "string" || typeof v === "number"
|
|
1633
|
+
);
|
|
1634
|
+
const result = { enum: values };
|
|
1635
|
+
if (def.description) {
|
|
1636
|
+
result.description = def.description;
|
|
1637
|
+
}
|
|
1638
|
+
return result;
|
|
1639
|
+
}
|
|
1640
|
+
function convertZodUnion(def) {
|
|
1641
|
+
const options = def.options;
|
|
1642
|
+
const result = {
|
|
1643
|
+
anyOf: options.map(convertZodType)
|
|
1644
|
+
};
|
|
1645
|
+
if (def.description) {
|
|
1646
|
+
result.description = def.description;
|
|
1647
|
+
}
|
|
1648
|
+
return result;
|
|
1649
|
+
}
|
|
1650
|
+
function convertZodNullable(def) {
|
|
1651
|
+
const inner = convertZodType(def.innerType);
|
|
1652
|
+
return {
|
|
1653
|
+
anyOf: [inner, { type: "null" }]
|
|
1654
|
+
};
|
|
1655
|
+
}
|
|
1656
|
+
function convertZodRecord(def) {
|
|
1657
|
+
const result = {
|
|
1658
|
+
type: "object",
|
|
1659
|
+
additionalProperties: convertZodType(def.valueType)
|
|
1660
|
+
};
|
|
1661
|
+
if (def.description) {
|
|
1662
|
+
result.description = def.description;
|
|
1663
|
+
}
|
|
1664
|
+
return result;
|
|
1665
|
+
}
|
|
1666
|
+
function convertZodTuple(def) {
|
|
1667
|
+
const items = def.items;
|
|
1668
|
+
const result = {
|
|
1669
|
+
type: "array",
|
|
1670
|
+
items: items.map(convertZodType),
|
|
1671
|
+
minItems: items.length,
|
|
1672
|
+
maxItems: items.length
|
|
1673
|
+
};
|
|
1674
|
+
if (def.description) {
|
|
1675
|
+
result.description = def.description;
|
|
1676
|
+
}
|
|
1677
|
+
return result;
|
|
1678
|
+
}
|
|
1679
|
+
function createFunctionToolFromSchema(name, description, schema, options) {
|
|
1680
|
+
const jsonSchema = zodToJsonSchema(schema, options);
|
|
1681
|
+
return createFunctionTool(name, description, jsonSchema);
|
|
1682
|
+
}
|
|
1683
|
+
function createFunctionTool(name, description, parameters) {
|
|
1684
|
+
const fn = { name, description };
|
|
1685
|
+
if (parameters) {
|
|
1686
|
+
fn.parameters = parameters;
|
|
1687
|
+
}
|
|
1688
|
+
return {
|
|
1689
|
+
type: ToolTypes.Function,
|
|
1690
|
+
function: fn
|
|
1691
|
+
};
|
|
1692
|
+
}
|
|
1693
|
+
function createWebSearchTool(options) {
|
|
1694
|
+
return {
|
|
1695
|
+
type: ToolTypes.WebSearch,
|
|
1696
|
+
webSearch: options ? {
|
|
1697
|
+
allowedDomains: options.allowedDomains,
|
|
1698
|
+
excludedDomains: options.excludedDomains,
|
|
1699
|
+
maxUses: options.maxUses
|
|
1700
|
+
} : void 0
|
|
1701
|
+
};
|
|
1702
|
+
}
|
|
1703
|
+
function toolChoiceAuto() {
|
|
1704
|
+
return { type: ToolChoiceTypes.Auto };
|
|
1705
|
+
}
|
|
1706
|
+
function toolChoiceRequired() {
|
|
1707
|
+
return { type: ToolChoiceTypes.Required };
|
|
1708
|
+
}
|
|
1709
|
+
function toolChoiceNone() {
|
|
1710
|
+
return { type: ToolChoiceTypes.None };
|
|
1711
|
+
}
|
|
1712
|
+
function hasToolCalls(response) {
|
|
1713
|
+
return (response.toolCalls?.length ?? 0) > 0;
|
|
1714
|
+
}
|
|
1715
|
+
function firstToolCall(response) {
|
|
1716
|
+
return response.toolCalls?.[0];
|
|
1717
|
+
}
|
|
1718
|
+
function toolResultMessage(toolCallId, result) {
|
|
1719
|
+
const content = typeof result === "string" ? result : JSON.stringify(result);
|
|
1720
|
+
return {
|
|
1721
|
+
role: "tool",
|
|
1722
|
+
content,
|
|
1723
|
+
toolCallId
|
|
1724
|
+
};
|
|
1725
|
+
}
|
|
1726
|
+
function respondToToolCall(call, result) {
|
|
1727
|
+
return toolResultMessage(call.id, result);
|
|
1728
|
+
}
|
|
1729
|
+
function assistantMessageWithToolCalls(content, toolCalls) {
|
|
1730
|
+
return {
|
|
1731
|
+
role: "assistant",
|
|
1732
|
+
content,
|
|
1733
|
+
toolCalls
|
|
1734
|
+
};
|
|
1735
|
+
}
|
|
1736
|
+
var ToolCallAccumulator = class {
|
|
1737
|
+
constructor() {
|
|
1738
|
+
this.calls = /* @__PURE__ */ new Map();
|
|
1739
|
+
}
|
|
1740
|
+
/**
|
|
1741
|
+
* Processes a streaming tool call delta.
|
|
1742
|
+
* Returns true if this started a new tool call.
|
|
1743
|
+
*/
|
|
1744
|
+
processDelta(delta) {
|
|
1745
|
+
const existing = this.calls.get(delta.index);
|
|
1746
|
+
if (!existing) {
|
|
1747
|
+
this.calls.set(delta.index, {
|
|
1748
|
+
id: delta.id ?? "",
|
|
1749
|
+
type: delta.type ?? ToolTypes.Function,
|
|
1750
|
+
function: {
|
|
1751
|
+
name: delta.function?.name ?? "",
|
|
1752
|
+
arguments: delta.function?.arguments ?? ""
|
|
1753
|
+
}
|
|
1754
|
+
});
|
|
1755
|
+
return true;
|
|
1756
|
+
}
|
|
1757
|
+
if (delta.function) {
|
|
1758
|
+
if (delta.function.name) {
|
|
1759
|
+
existing.function = existing.function ?? { name: "", arguments: "" };
|
|
1760
|
+
existing.function.name = delta.function.name;
|
|
1761
|
+
}
|
|
1762
|
+
if (delta.function.arguments) {
|
|
1763
|
+
existing.function = existing.function ?? { name: "", arguments: "" };
|
|
1764
|
+
existing.function.arguments += delta.function.arguments;
|
|
1765
|
+
}
|
|
1766
|
+
}
|
|
1767
|
+
return false;
|
|
1768
|
+
}
|
|
1769
|
+
/**
|
|
1770
|
+
* Returns all accumulated tool calls in index order.
|
|
1771
|
+
*/
|
|
1772
|
+
getToolCalls() {
|
|
1773
|
+
if (this.calls.size === 0) {
|
|
1774
|
+
return [];
|
|
1775
|
+
}
|
|
1776
|
+
const maxIdx = Math.max(...this.calls.keys());
|
|
1777
|
+
const result = [];
|
|
1778
|
+
for (let i = 0; i <= maxIdx; i++) {
|
|
1779
|
+
const call = this.calls.get(i);
|
|
1780
|
+
if (call) {
|
|
1781
|
+
result.push(call);
|
|
1782
|
+
}
|
|
1783
|
+
}
|
|
1784
|
+
return result;
|
|
1785
|
+
}
|
|
1786
|
+
/**
|
|
1787
|
+
* Returns a specific tool call by index, or undefined if not found.
|
|
1788
|
+
*/
|
|
1789
|
+
getToolCall(index) {
|
|
1790
|
+
return this.calls.get(index);
|
|
1791
|
+
}
|
|
1792
|
+
/**
|
|
1793
|
+
* Clears all accumulated tool calls.
|
|
1794
|
+
*/
|
|
1795
|
+
reset() {
|
|
1796
|
+
this.calls.clear();
|
|
1797
|
+
}
|
|
1798
|
+
};
|
|
1799
|
+
var ToolArgsError = class extends Error {
|
|
1800
|
+
constructor(message, toolCallId, toolName, rawArguments) {
|
|
1801
|
+
super(message);
|
|
1802
|
+
this.name = "ToolArgsError";
|
|
1803
|
+
this.toolCallId = toolCallId;
|
|
1804
|
+
this.toolName = toolName;
|
|
1805
|
+
this.rawArguments = rawArguments;
|
|
1806
|
+
}
|
|
1807
|
+
};
|
|
1808
|
+
function parseToolArgs(call, schema) {
|
|
1809
|
+
const toolName = call.function?.name ?? "unknown";
|
|
1810
|
+
const rawArgs = call.function?.arguments ?? "";
|
|
1811
|
+
let parsed;
|
|
1812
|
+
try {
|
|
1813
|
+
parsed = rawArgs ? JSON.parse(rawArgs) : {};
|
|
1814
|
+
} catch (err) {
|
|
1815
|
+
const message = err instanceof Error ? err.message : "Invalid JSON in arguments";
|
|
1816
|
+
throw new ToolArgsError(
|
|
1817
|
+
`Failed to parse arguments for tool '${toolName}': ${message}`,
|
|
1818
|
+
call.id,
|
|
1819
|
+
toolName,
|
|
1820
|
+
rawArgs
|
|
1821
|
+
);
|
|
1822
|
+
}
|
|
1823
|
+
try {
|
|
1824
|
+
return schema.parse(parsed);
|
|
1825
|
+
} catch (err) {
|
|
1826
|
+
let message;
|
|
1827
|
+
if (err instanceof Error) {
|
|
1828
|
+
const zodErr = err;
|
|
1829
|
+
if (zodErr.errors && Array.isArray(zodErr.errors)) {
|
|
1830
|
+
const issues = zodErr.errors.map((e) => {
|
|
1831
|
+
const path = e.path.length > 0 ? `${e.path.join(".")}: ` : "";
|
|
1832
|
+
return `${path}${e.message}`;
|
|
1833
|
+
}).join("; ");
|
|
1834
|
+
message = issues;
|
|
1835
|
+
} else {
|
|
1836
|
+
message = err.message;
|
|
1837
|
+
}
|
|
1838
|
+
} else {
|
|
1839
|
+
message = String(err);
|
|
1840
|
+
}
|
|
1841
|
+
throw new ToolArgsError(
|
|
1842
|
+
`Invalid arguments for tool '${toolName}': ${message}`,
|
|
1843
|
+
call.id,
|
|
1844
|
+
toolName,
|
|
1845
|
+
rawArgs
|
|
1846
|
+
);
|
|
1847
|
+
}
|
|
1848
|
+
}
|
|
1849
|
+
function tryParseToolArgs(call, schema) {
|
|
1850
|
+
try {
|
|
1851
|
+
const data = parseToolArgs(call, schema);
|
|
1852
|
+
return { success: true, data };
|
|
1853
|
+
} catch (err) {
|
|
1854
|
+
if (err instanceof ToolArgsError) {
|
|
1855
|
+
return { success: false, error: err };
|
|
1856
|
+
}
|
|
1857
|
+
const toolName = call.function?.name ?? "unknown";
|
|
1858
|
+
const rawArgs = call.function?.arguments ?? "";
|
|
1859
|
+
return {
|
|
1860
|
+
success: false,
|
|
1861
|
+
error: new ToolArgsError(
|
|
1862
|
+
err instanceof Error ? err.message : String(err),
|
|
1863
|
+
call.id,
|
|
1864
|
+
toolName,
|
|
1865
|
+
rawArgs
|
|
1866
|
+
)
|
|
1867
|
+
};
|
|
1868
|
+
}
|
|
1869
|
+
}
|
|
1870
|
+
function parseToolArgsRaw(call) {
|
|
1871
|
+
const toolName = call.function?.name ?? "unknown";
|
|
1872
|
+
const rawArgs = call.function?.arguments ?? "";
|
|
1873
|
+
try {
|
|
1874
|
+
return rawArgs ? JSON.parse(rawArgs) : {};
|
|
1875
|
+
} catch (err) {
|
|
1876
|
+
const message = err instanceof Error ? err.message : "Invalid JSON in arguments";
|
|
1877
|
+
throw new ToolArgsError(
|
|
1878
|
+
`Failed to parse arguments for tool '${toolName}': ${message}`,
|
|
1879
|
+
call.id,
|
|
1880
|
+
toolName,
|
|
1881
|
+
rawArgs
|
|
1882
|
+
);
|
|
1883
|
+
}
|
|
1884
|
+
}
|
|
1885
|
+
var ToolRegistry = class {
|
|
1886
|
+
constructor() {
|
|
1887
|
+
this.handlers = /* @__PURE__ */ new Map();
|
|
1888
|
+
}
|
|
1889
|
+
/**
|
|
1890
|
+
* Registers a handler function for a tool name.
|
|
1891
|
+
* @param name - The tool name (must match the function name in the tool definition)
|
|
1892
|
+
* @param handler - Function to execute when this tool is called
|
|
1893
|
+
* @returns this for chaining
|
|
1894
|
+
*/
|
|
1895
|
+
register(name, handler) {
|
|
1896
|
+
this.handlers.set(name, handler);
|
|
1897
|
+
return this;
|
|
1898
|
+
}
|
|
1899
|
+
/**
|
|
1900
|
+
* Unregisters a tool handler.
|
|
1901
|
+
* @param name - The tool name to unregister
|
|
1902
|
+
* @returns true if the handler was removed, false if it didn't exist
|
|
1903
|
+
*/
|
|
1904
|
+
unregister(name) {
|
|
1905
|
+
return this.handlers.delete(name);
|
|
1906
|
+
}
|
|
1907
|
+
/**
|
|
1908
|
+
* Checks if a handler is registered for the given tool name.
|
|
1909
|
+
*/
|
|
1910
|
+
has(name) {
|
|
1911
|
+
return this.handlers.has(name);
|
|
1912
|
+
}
|
|
1913
|
+
/**
|
|
1914
|
+
* Returns the list of registered tool names.
|
|
1915
|
+
*/
|
|
1916
|
+
getRegisteredTools() {
|
|
1917
|
+
return Array.from(this.handlers.keys());
|
|
1918
|
+
}
|
|
1919
|
+
/**
|
|
1920
|
+
* Executes a single tool call.
|
|
1921
|
+
* @param call - The tool call to execute
|
|
1922
|
+
* @returns The execution result
|
|
1923
|
+
*/
|
|
1924
|
+
async execute(call) {
|
|
1925
|
+
const toolName = call.function?.name ?? "";
|
|
1926
|
+
const handler = this.handlers.get(toolName);
|
|
1927
|
+
if (!handler) {
|
|
1928
|
+
return {
|
|
1929
|
+
toolCallId: call.id,
|
|
1930
|
+
toolName,
|
|
1931
|
+
result: null,
|
|
1932
|
+
error: `Unknown tool: '${toolName}'. Available tools: ${this.getRegisteredTools().join(", ") || "none"}`
|
|
1933
|
+
};
|
|
1934
|
+
}
|
|
1935
|
+
let args;
|
|
1936
|
+
try {
|
|
1937
|
+
args = call.function?.arguments ? JSON.parse(call.function.arguments) : {};
|
|
1938
|
+
} catch (err) {
|
|
1939
|
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
1940
|
+
return {
|
|
1941
|
+
toolCallId: call.id,
|
|
1942
|
+
toolName,
|
|
1943
|
+
result: null,
|
|
1944
|
+
error: `Invalid JSON in arguments: ${errorMessage}`,
|
|
1945
|
+
isRetryable: true
|
|
1946
|
+
};
|
|
1947
|
+
}
|
|
1948
|
+
try {
|
|
1949
|
+
const result = await handler(args, call);
|
|
1950
|
+
return {
|
|
1951
|
+
toolCallId: call.id,
|
|
1952
|
+
toolName,
|
|
1953
|
+
result
|
|
1954
|
+
};
|
|
1955
|
+
} catch (err) {
|
|
1956
|
+
const isRetryable = err instanceof ToolArgsError;
|
|
1957
|
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
1958
|
+
return {
|
|
1959
|
+
toolCallId: call.id,
|
|
1960
|
+
toolName,
|
|
1961
|
+
result: null,
|
|
1962
|
+
error: errorMessage,
|
|
1963
|
+
isRetryable
|
|
1964
|
+
};
|
|
1965
|
+
}
|
|
1966
|
+
}
|
|
1967
|
+
/**
|
|
1968
|
+
* Executes multiple tool calls in parallel.
|
|
1969
|
+
* @param calls - Array of tool calls to execute
|
|
1970
|
+
* @returns Array of execution results in the same order as input
|
|
1971
|
+
*/
|
|
1972
|
+
async executeAll(calls) {
|
|
1973
|
+
return Promise.all(calls.map((call) => this.execute(call)));
|
|
1974
|
+
}
|
|
1975
|
+
/**
|
|
1976
|
+
* Converts execution results to tool result messages.
|
|
1977
|
+
* Useful for appending to the conversation history.
|
|
1978
|
+
* @param results - Array of execution results
|
|
1979
|
+
* @returns Array of ChatMessage objects with role "tool"
|
|
1980
|
+
*/
|
|
1981
|
+
resultsToMessages(results) {
|
|
1982
|
+
return results.map((r) => {
|
|
1983
|
+
const content = r.error ? `Error: ${r.error}` : typeof r.result === "string" ? r.result : JSON.stringify(r.result);
|
|
1984
|
+
return toolResultMessage(r.toolCallId, content);
|
|
1985
|
+
});
|
|
1986
|
+
}
|
|
1987
|
+
};
|
|
1988
|
+
function formatToolErrorForModel(result) {
|
|
1989
|
+
const lines = [
|
|
1990
|
+
`Tool call error for '${result.toolName}': ${result.error}`
|
|
1991
|
+
];
|
|
1992
|
+
if (result.isRetryable) {
|
|
1993
|
+
lines.push("");
|
|
1994
|
+
lines.push("Please correct the arguments and try again.");
|
|
1995
|
+
}
|
|
1996
|
+
return lines.join("\n");
|
|
1997
|
+
}
|
|
1998
|
+
function hasRetryableErrors(results) {
|
|
1999
|
+
return results.some((r) => r.error && r.isRetryable);
|
|
2000
|
+
}
|
|
2001
|
+
function getRetryableErrors(results) {
|
|
2002
|
+
return results.filter((r) => r.error && r.isRetryable);
|
|
2003
|
+
}
|
|
2004
|
+
function createRetryMessages(results) {
|
|
2005
|
+
return results.filter((r) => r.error && r.isRetryable).map((r) => toolResultMessage(r.toolCallId, formatToolErrorForModel(r)));
|
|
2006
|
+
}
|
|
2007
|
+
async function executeWithRetry(registry, toolCalls, options = {}) {
|
|
2008
|
+
const maxRetries = options.maxRetries ?? 2;
|
|
2009
|
+
let currentCalls = toolCalls;
|
|
2010
|
+
let attempt = 0;
|
|
2011
|
+
const successfulResults = /* @__PURE__ */ new Map();
|
|
2012
|
+
while (attempt <= maxRetries) {
|
|
2013
|
+
const results = await registry.executeAll(currentCalls);
|
|
2014
|
+
for (const result of results) {
|
|
2015
|
+
if (!result.error || !result.isRetryable) {
|
|
2016
|
+
successfulResults.set(result.toolCallId, result);
|
|
2017
|
+
}
|
|
2018
|
+
}
|
|
2019
|
+
const retryableResults = getRetryableErrors(results);
|
|
2020
|
+
if (retryableResults.length === 0 || !options.onRetry) {
|
|
2021
|
+
for (const result of results) {
|
|
2022
|
+
if (result.error && result.isRetryable) {
|
|
2023
|
+
successfulResults.set(result.toolCallId, result);
|
|
2024
|
+
}
|
|
2025
|
+
}
|
|
2026
|
+
return Array.from(successfulResults.values());
|
|
2027
|
+
}
|
|
2028
|
+
attempt++;
|
|
2029
|
+
if (attempt > maxRetries) {
|
|
2030
|
+
for (const result of retryableResults) {
|
|
2031
|
+
successfulResults.set(result.toolCallId, result);
|
|
2032
|
+
}
|
|
2033
|
+
return Array.from(successfulResults.values());
|
|
2034
|
+
}
|
|
2035
|
+
const errorMessages = createRetryMessages(retryableResults);
|
|
2036
|
+
const newCalls = await options.onRetry(errorMessages, attempt);
|
|
2037
|
+
if (newCalls.length === 0) {
|
|
2038
|
+
for (const result of retryableResults) {
|
|
2039
|
+
successfulResults.set(result.toolCallId, result);
|
|
2040
|
+
}
|
|
2041
|
+
return Array.from(successfulResults.values());
|
|
2042
|
+
}
|
|
2043
|
+
currentCalls = newCalls;
|
|
2044
|
+
}
|
|
2045
|
+
return Array.from(successfulResults.values());
|
|
2046
|
+
}
|
|
2047
|
+
|
|
1256
2048
|
// src/index.ts
|
|
1257
2049
|
var ModelRelay = class {
|
|
1258
2050
|
constructor(options) {
|
|
@@ -1260,7 +2052,7 @@ var ModelRelay = class {
|
|
|
1260
2052
|
if (!cfg.key && !cfg.token) {
|
|
1261
2053
|
throw new ConfigError("Provide an API key or access token");
|
|
1262
2054
|
}
|
|
1263
|
-
this.baseUrl = resolveBaseUrl(cfg.
|
|
2055
|
+
this.baseUrl = resolveBaseUrl(cfg.baseUrl);
|
|
1264
2056
|
const http = new HTTPClient({
|
|
1265
2057
|
baseUrl: this.baseUrl,
|
|
1266
2058
|
apiKey: cfg.key,
|
|
@@ -1271,7 +2063,6 @@ var ModelRelay = class {
|
|
|
1271
2063
|
timeoutMs: cfg.timeoutMs,
|
|
1272
2064
|
retry: cfg.retry,
|
|
1273
2065
|
defaultHeaders: cfg.defaultHeaders,
|
|
1274
|
-
environment: cfg.environment,
|
|
1275
2066
|
metrics: cfg.metrics,
|
|
1276
2067
|
trace: cfg.trace
|
|
1277
2068
|
});
|
|
@@ -1289,10 +2080,13 @@ var ModelRelay = class {
|
|
|
1289
2080
|
this.customers = new CustomersClient(http, {
|
|
1290
2081
|
apiKey: cfg.key
|
|
1291
2082
|
});
|
|
2083
|
+
this.tiers = new TiersClient(http, {
|
|
2084
|
+
apiKey: cfg.key
|
|
2085
|
+
});
|
|
1292
2086
|
}
|
|
1293
2087
|
};
|
|
1294
|
-
function resolveBaseUrl(
|
|
1295
|
-
const base = override ||
|
|
2088
|
+
function resolveBaseUrl(override) {
|
|
2089
|
+
const base = override || DEFAULT_BASE_URL;
|
|
1296
2090
|
return base.replace(/\/+$/, "");
|
|
1297
2091
|
}
|
|
1298
2092
|
// Annotate the CommonJS export names for ESM import in node:
|
|
@@ -1311,11 +2105,26 @@ function resolveBaseUrl(env, override) {
|
|
|
1311
2105
|
ModelRelayError,
|
|
1312
2106
|
Models,
|
|
1313
2107
|
Providers,
|
|
1314
|
-
SANDBOX_BASE_URL,
|
|
1315
2108
|
SDK_VERSION,
|
|
1316
|
-
STAGING_BASE_URL,
|
|
1317
2109
|
StopReasons,
|
|
2110
|
+
TiersClient,
|
|
2111
|
+
ToolArgsError,
|
|
2112
|
+
ToolCallAccumulator,
|
|
2113
|
+
ToolChoiceTypes,
|
|
2114
|
+
ToolRegistry,
|
|
2115
|
+
ToolTypes,
|
|
1318
2116
|
TransportError,
|
|
2117
|
+
assistantMessageWithToolCalls,
|
|
2118
|
+
createFunctionTool,
|
|
2119
|
+
createFunctionToolFromSchema,
|
|
2120
|
+
createRetryMessages,
|
|
2121
|
+
createWebSearchTool,
|
|
2122
|
+
executeWithRetry,
|
|
2123
|
+
firstToolCall,
|
|
2124
|
+
formatToolErrorForModel,
|
|
2125
|
+
getRetryableErrors,
|
|
2126
|
+
hasRetryableErrors,
|
|
2127
|
+
hasToolCalls,
|
|
1319
2128
|
isPublishableKey,
|
|
1320
2129
|
mergeMetrics,
|
|
1321
2130
|
mergeTrace,
|
|
@@ -1324,6 +2133,15 @@ function resolveBaseUrl(env, override) {
|
|
|
1324
2133
|
normalizeProvider,
|
|
1325
2134
|
normalizeStopReason,
|
|
1326
2135
|
parseErrorResponse,
|
|
2136
|
+
parseToolArgs,
|
|
2137
|
+
parseToolArgsRaw,
|
|
1327
2138
|
providerToString,
|
|
1328
|
-
|
|
2139
|
+
respondToToolCall,
|
|
2140
|
+
stopReasonToString,
|
|
2141
|
+
toolChoiceAuto,
|
|
2142
|
+
toolChoiceNone,
|
|
2143
|
+
toolChoiceRequired,
|
|
2144
|
+
toolResultMessage,
|
|
2145
|
+
tryParseToolArgs,
|
|
2146
|
+
zodToJsonSchema
|
|
1329
2147
|
});
|