@modelrelay/sdk 0.5.0 → 0.14.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/index.cjs CHANGED
@@ -30,16 +30,39 @@ __export(index_exports, {
30
30
  DEFAULT_CLIENT_HEADER: () => DEFAULT_CLIENT_HEADER,
31
31
  DEFAULT_CONNECT_TIMEOUT_MS: () => DEFAULT_CONNECT_TIMEOUT_MS,
32
32
  DEFAULT_REQUEST_TIMEOUT_MS: () => DEFAULT_REQUEST_TIMEOUT_MS,
33
+ ErrorCodes: () => ErrorCodes,
33
34
  ModelRelay: () => ModelRelay,
34
35
  ModelRelayError: () => ModelRelayError,
35
36
  Models: () => Models,
36
37
  Providers: () => Providers,
37
- SANDBOX_BASE_URL: () => SANDBOX_BASE_URL,
38
38
  SDK_VERSION: () => SDK_VERSION,
39
- STAGING_BASE_URL: () => STAGING_BASE_URL,
40
39
  StopReasons: () => StopReasons,
41
40
  TiersClient: () => TiersClient,
41
+ ToolArgsError: () => ToolArgsError,
42
+ ToolCallAccumulator: () => ToolCallAccumulator,
43
+ ToolChoiceTypes: () => ToolChoiceTypes,
44
+ ToolRegistry: () => ToolRegistry,
45
+ ToolTypes: () => ToolTypes,
42
46
  TransportError: () => TransportError,
47
+ assistantMessageWithToolCalls: () => assistantMessageWithToolCalls,
48
+ createAccessTokenAuth: () => createAccessTokenAuth,
49
+ createApiKeyAuth: () => createApiKeyAuth,
50
+ createAssistantMessage: () => createAssistantMessage,
51
+ createFunctionCall: () => createFunctionCall,
52
+ createFunctionTool: () => createFunctionTool,
53
+ createFunctionToolFromSchema: () => createFunctionToolFromSchema,
54
+ createRetryMessages: () => createRetryMessages,
55
+ createSystemMessage: () => createSystemMessage,
56
+ createToolCall: () => createToolCall,
57
+ createUsage: () => createUsage,
58
+ createUserMessage: () => createUserMessage,
59
+ createWebTool: () => createWebTool,
60
+ executeWithRetry: () => executeWithRetry,
61
+ firstToolCall: () => firstToolCall,
62
+ formatToolErrorForModel: () => formatToolErrorForModel,
63
+ getRetryableErrors: () => getRetryableErrors,
64
+ hasRetryableErrors: () => hasRetryableErrors,
65
+ hasToolCalls: () => hasToolCalls,
43
66
  isPublishableKey: () => isPublishableKey,
44
67
  mergeMetrics: () => mergeMetrics,
45
68
  mergeTrace: () => mergeTrace,
@@ -48,12 +71,34 @@ __export(index_exports, {
48
71
  normalizeProvider: () => normalizeProvider,
49
72
  normalizeStopReason: () => normalizeStopReason,
50
73
  parseErrorResponse: () => parseErrorResponse,
74
+ parseToolArgs: () => parseToolArgs,
75
+ parseToolArgsRaw: () => parseToolArgsRaw,
51
76
  providerToString: () => providerToString,
52
- stopReasonToString: () => stopReasonToString
77
+ respondToToolCall: () => respondToToolCall,
78
+ stopReasonToString: () => stopReasonToString,
79
+ toolChoiceAuto: () => toolChoiceAuto,
80
+ toolChoiceNone: () => toolChoiceNone,
81
+ toolChoiceRequired: () => toolChoiceRequired,
82
+ toolResultMessage: () => toolResultMessage,
83
+ tryParseToolArgs: () => tryParseToolArgs,
84
+ zodToJsonSchema: () => zodToJsonSchema
53
85
  });
54
86
  module.exports = __toCommonJS(index_exports);
55
87
 
56
88
  // src/errors.ts
89
+ var ErrorCodes = {
90
+ NOT_FOUND: "NOT_FOUND",
91
+ VALIDATION_ERROR: "VALIDATION_ERROR",
92
+ RATE_LIMIT: "RATE_LIMIT",
93
+ UNAUTHORIZED: "UNAUTHORIZED",
94
+ FORBIDDEN: "FORBIDDEN",
95
+ CONFLICT: "CONFLICT",
96
+ INTERNAL_ERROR: "INTERNAL_ERROR",
97
+ SERVICE_UNAVAILABLE: "SERVICE_UNAVAILABLE",
98
+ INVALID_INPUT: "INVALID_INPUT",
99
+ PAYMENT_REQUIRED: "PAYMENT_REQUIRED",
100
+ METHOD_NOT_ALLOWED: "METHOD_NOT_ALLOWED"
101
+ };
57
102
  var ModelRelayError = class extends Error {
58
103
  constructor(message, opts) {
59
104
  super(message);
@@ -97,6 +142,30 @@ var APIError = class extends ModelRelayError {
97
142
  retries: opts.retries
98
143
  });
99
144
  }
145
+ /** Returns true if the error is a not found error. */
146
+ isNotFound() {
147
+ return this.code === ErrorCodes.NOT_FOUND;
148
+ }
149
+ /** Returns true if the error is a validation error. */
150
+ isValidation() {
151
+ return this.code === ErrorCodes.VALIDATION_ERROR || this.code === ErrorCodes.INVALID_INPUT;
152
+ }
153
+ /** Returns true if the error is a rate limit error. */
154
+ isRateLimit() {
155
+ return this.code === ErrorCodes.RATE_LIMIT;
156
+ }
157
+ /** Returns true if the error is an unauthorized error. */
158
+ isUnauthorized() {
159
+ return this.code === ErrorCodes.UNAUTHORIZED;
160
+ }
161
+ /** Returns true if the error is a forbidden error. */
162
+ isForbidden() {
163
+ return this.code === ErrorCodes.FORBIDDEN;
164
+ }
165
+ /** Returns true if the error is a service unavailable error. */
166
+ isUnavailable() {
167
+ return this.code === ErrorCodes.SERVICE_UNAVAILABLE;
168
+ }
100
169
  };
101
170
  async function parseErrorResponse(response, retries) {
102
171
  const requestId = response.headers.get("X-ModelRelay-Chat-Request-Id") || response.headers.get("X-Request-Id") || void 0;
@@ -151,6 +220,12 @@ async function parseErrorResponse(response, retries) {
151
220
  }
152
221
 
153
222
  // src/auth.ts
223
+ function createApiKeyAuth(apiKey) {
224
+ return { apiKey };
225
+ }
226
+ function createAccessTokenAuth(accessToken) {
227
+ return { accessToken };
228
+ }
154
229
  var AuthClient = class {
155
230
  constructor(http, cfg) {
156
231
  this.cachedFrontend = /* @__PURE__ */ new Map();
@@ -210,7 +285,7 @@ var AuthClient = class {
210
285
  */
211
286
  async authForChat(customerId, overrides) {
212
287
  if (this.accessToken) {
213
- return { accessToken: this.accessToken };
288
+ return createAccessTokenAuth(this.accessToken);
214
289
  }
215
290
  if (!this.apiKey) {
216
291
  throw new ConfigError("API key or token is required");
@@ -221,21 +296,21 @@ var AuthClient = class {
221
296
  deviceId: overrides?.deviceId,
222
297
  ttlSeconds: overrides?.ttlSeconds
223
298
  });
224
- return { accessToken: token.token };
299
+ return createAccessTokenAuth(token.token);
225
300
  }
226
- return { apiKey: this.apiKey };
301
+ return createApiKeyAuth(this.apiKey);
227
302
  }
228
303
  /**
229
304
  * Billing calls accept either bearer tokens or API keys (including publishable keys).
230
305
  */
231
306
  authForBilling() {
232
307
  if (this.accessToken) {
233
- return { accessToken: this.accessToken };
308
+ return createAccessTokenAuth(this.accessToken);
234
309
  }
235
310
  if (!this.apiKey) {
236
311
  throw new ConfigError("API key or token is required");
237
312
  }
238
- return { apiKey: this.apiKey };
313
+ return createApiKeyAuth(this.apiKey);
239
314
  }
240
315
  };
241
316
  function isPublishableKey(value) {
@@ -273,7 +348,7 @@ function isTokenReusable(token) {
273
348
  // package.json
274
349
  var package_default = {
275
350
  name: "@modelrelay/sdk",
276
- version: "0.5.0",
351
+ version: "0.14.1",
277
352
  description: "TypeScript SDK for the ModelRelay API",
278
353
  type: "module",
279
354
  main: "dist/index.cjs",
@@ -307,15 +382,14 @@ var package_default = {
307
382
  devDependencies: {
308
383
  tsup: "^8.2.4",
309
384
  typescript: "^5.6.3",
310
- vitest: "^2.1.4"
385
+ vitest: "^2.1.4",
386
+ zod: "^3.23.0"
311
387
  }
312
388
  };
313
389
 
314
390
  // src/types.ts
315
391
  var SDK_VERSION = package_default.version || "0.0.0";
316
392
  var DEFAULT_BASE_URL = "https://api.modelrelay.ai/api/v1";
317
- var STAGING_BASE_URL = "https://api-stg.modelrelay.ai/api/v1";
318
- var SANDBOX_BASE_URL = "https://api.sandbox.modelrelay.ai/api/v1";
319
393
  var DEFAULT_CLIENT_HEADER = `modelrelay-ts/${SDK_VERSION}`;
320
394
  var DEFAULT_CONNECT_TIMEOUT_MS = 5e3;
321
395
  var DEFAULT_REQUEST_TIMEOUT_MS = 6e4;
@@ -336,22 +410,45 @@ var StopReasons = {
336
410
  var Providers = {
337
411
  OpenAI: "openai",
338
412
  Anthropic: "anthropic",
339
- Grok: "grok",
340
- OpenRouter: "openrouter",
413
+ XAI: "xai",
414
+ GoogleAIStudio: "google-ai-studio",
341
415
  Echo: "echo"
342
416
  };
343
417
  var Models = {
344
- OpenAIGpt4o: "openai/gpt-4o",
345
- OpenAIGpt4oMini: "openai/gpt-4o-mini",
346
- OpenAIGpt51: "openai/gpt-5.1",
347
- AnthropicClaude35HaikuLatest: "anthropic/claude-3-5-haiku-latest",
348
- AnthropicClaude35SonnetLatest: "anthropic/claude-3-5-sonnet-latest",
349
- AnthropicClaudeOpus45: "anthropic/claude-opus-4-5-20251101",
350
- OpenRouterClaude35Haiku: "anthropic/claude-3.5-haiku",
418
+ // OpenAI models (provider-agnostic identifiers)
419
+ Gpt4o: "gpt-4o",
420
+ Gpt4oMini: "gpt-4o-mini",
421
+ Gpt51: "gpt-5.1",
422
+ // Anthropic models (provider-agnostic identifiers)
423
+ Claude35HaikuLatest: "claude-3-5-haiku-latest",
424
+ Claude35SonnetLatest: "claude-3-5-sonnet-latest",
425
+ ClaudeOpus45: "claude-opus-4-5",
426
+ Claude35Haiku: "claude-3.5-haiku",
427
+ // xAI / Grok models
351
428
  Grok2: "grok-2",
352
- Grok4Fast: "grok-4-fast",
429
+ Grok4_1FastNonReasoning: "grok-4-1-fast-non-reasoning",
430
+ Grok4_1FastReasoning: "grok-4-1-fast-reasoning",
431
+ // Internal echo model for testing.
353
432
  Echo1: "echo-1"
354
433
  };
434
+ function createUsage(inputTokens, outputTokens, totalTokens) {
435
+ return {
436
+ inputTokens,
437
+ outputTokens,
438
+ totalTokens: totalTokens ?? inputTokens + outputTokens
439
+ };
440
+ }
441
+ var ToolTypes = {
442
+ Function: "function",
443
+ Web: "web",
444
+ XSearch: "x_search",
445
+ CodeExecution: "code_execution"
446
+ };
447
+ var ToolChoiceTypes = {
448
+ Auto: "auto",
449
+ Required: "required",
450
+ None: "none"
451
+ };
355
452
  function mergeMetrics(base, override) {
356
453
  if (!base && !override) return void 0;
357
454
  return {
@@ -415,6 +512,630 @@ function modelToString(value) {
415
512
  return value.other?.trim() || "";
416
513
  }
417
514
 
515
+ // src/tools.ts
516
+ function createUserMessage(content) {
517
+ return { role: "user", content };
518
+ }
519
+ function createAssistantMessage(content) {
520
+ return { role: "assistant", content };
521
+ }
522
+ function createSystemMessage(content) {
523
+ return { role: "system", content };
524
+ }
525
+ function createToolCall(id, name, args, type = ToolTypes.Function) {
526
+ return {
527
+ id,
528
+ type,
529
+ function: createFunctionCall(name, args)
530
+ };
531
+ }
532
+ function createFunctionCall(name, args) {
533
+ return { name, arguments: args };
534
+ }
535
+ function zodToJsonSchema(schema, options = {}) {
536
+ const result = convertZodType(schema);
537
+ if (options.includeSchema) {
538
+ 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#";
539
+ return { $schema: schemaVersion, ...result };
540
+ }
541
+ return result;
542
+ }
543
+ function convertZodType(schema) {
544
+ const def = schema._def;
545
+ const typeName = def.typeName;
546
+ switch (typeName) {
547
+ case "ZodString":
548
+ return convertZodString(def);
549
+ case "ZodNumber":
550
+ return convertZodNumber(def);
551
+ case "ZodBoolean":
552
+ return { type: "boolean" };
553
+ case "ZodNull":
554
+ return { type: "null" };
555
+ case "ZodArray":
556
+ return convertZodArray(def);
557
+ case "ZodObject":
558
+ return convertZodObject(def);
559
+ case "ZodEnum":
560
+ return convertZodEnum(def);
561
+ case "ZodNativeEnum":
562
+ return convertZodNativeEnum(def);
563
+ case "ZodLiteral":
564
+ return { const: def.value };
565
+ case "ZodUnion":
566
+ return convertZodUnion(def);
567
+ case "ZodOptional": {
568
+ const inner = convertZodType(def.innerType);
569
+ if (def.description && !inner.description) {
570
+ inner.description = def.description;
571
+ }
572
+ return inner;
573
+ }
574
+ case "ZodNullable":
575
+ return convertZodNullable(def);
576
+ case "ZodDefault":
577
+ return { ...convertZodType(def.innerType), default: def.defaultValue() };
578
+ case "ZodEffects":
579
+ return convertZodType(def.schema);
580
+ case "ZodRecord":
581
+ return convertZodRecord(def);
582
+ case "ZodTuple":
583
+ return convertZodTuple(def);
584
+ case "ZodAny":
585
+ case "ZodUnknown":
586
+ return {};
587
+ default:
588
+ return {};
589
+ }
590
+ }
591
+ function convertZodString(def) {
592
+ const result = { type: "string" };
593
+ const checks = def.checks;
594
+ if (checks) {
595
+ for (const check of checks) {
596
+ switch (check.kind) {
597
+ case "min":
598
+ result.minLength = check.value;
599
+ break;
600
+ case "max":
601
+ result.maxLength = check.value;
602
+ break;
603
+ case "length":
604
+ result.minLength = check.value;
605
+ result.maxLength = check.value;
606
+ break;
607
+ case "email":
608
+ result.format = "email";
609
+ break;
610
+ case "url":
611
+ result.format = "uri";
612
+ break;
613
+ case "uuid":
614
+ result.format = "uuid";
615
+ break;
616
+ case "datetime":
617
+ result.format = "date-time";
618
+ break;
619
+ case "regex":
620
+ result.pattern = check.value.source;
621
+ break;
622
+ }
623
+ }
624
+ }
625
+ if (def.description) {
626
+ result.description = def.description;
627
+ }
628
+ return result;
629
+ }
630
+ function convertZodNumber(def) {
631
+ const result = { type: "number" };
632
+ const checks = def.checks;
633
+ if (checks) {
634
+ for (const check of checks) {
635
+ switch (check.kind) {
636
+ case "int":
637
+ result.type = "integer";
638
+ break;
639
+ case "min":
640
+ if (check.inclusive === false) {
641
+ result.exclusiveMinimum = check.value;
642
+ } else {
643
+ result.minimum = check.value;
644
+ }
645
+ break;
646
+ case "max":
647
+ if (check.inclusive === false) {
648
+ result.exclusiveMaximum = check.value;
649
+ } else {
650
+ result.maximum = check.value;
651
+ }
652
+ break;
653
+ case "multipleOf":
654
+ result.multipleOf = check.value;
655
+ break;
656
+ }
657
+ }
658
+ }
659
+ if (def.description) {
660
+ result.description = def.description;
661
+ }
662
+ return result;
663
+ }
664
+ function convertZodArray(def) {
665
+ const result = {
666
+ type: "array",
667
+ items: convertZodType(def.type)
668
+ };
669
+ if (def.minLength !== void 0 && def.minLength !== null) {
670
+ result.minItems = def.minLength.value;
671
+ }
672
+ if (def.maxLength !== void 0 && def.maxLength !== null) {
673
+ result.maxItems = def.maxLength.value;
674
+ }
675
+ if (def.description) {
676
+ result.description = def.description;
677
+ }
678
+ return result;
679
+ }
680
+ function convertZodObject(def) {
681
+ const shape = def.shape;
682
+ const shapeObj = typeof shape === "function" ? shape() : shape;
683
+ const properties = {};
684
+ const required = [];
685
+ for (const [key, value] of Object.entries(shapeObj)) {
686
+ properties[key] = convertZodType(value);
687
+ const valueDef = value._def;
688
+ const isOptional = valueDef.typeName === "ZodOptional" || valueDef.typeName === "ZodDefault" || valueDef.typeName === "ZodNullable" && valueDef.innerType?._def?.typeName === "ZodDefault";
689
+ if (!isOptional) {
690
+ required.push(key);
691
+ }
692
+ }
693
+ const result = {
694
+ type: "object",
695
+ properties
696
+ };
697
+ if (required.length > 0) {
698
+ result.required = required;
699
+ }
700
+ if (def.description) {
701
+ result.description = def.description;
702
+ }
703
+ const unknownKeys = def.unknownKeys;
704
+ if (unknownKeys === "strict") {
705
+ result.additionalProperties = false;
706
+ }
707
+ return result;
708
+ }
709
+ function convertZodEnum(def) {
710
+ const result = {
711
+ type: "string",
712
+ enum: def.values
713
+ };
714
+ if (def.description) {
715
+ result.description = def.description;
716
+ }
717
+ return result;
718
+ }
719
+ function convertZodNativeEnum(def) {
720
+ const enumValues = def.values;
721
+ const values = Object.values(enumValues).filter(
722
+ (v) => typeof v === "string" || typeof v === "number"
723
+ );
724
+ const result = { enum: values };
725
+ if (def.description) {
726
+ result.description = def.description;
727
+ }
728
+ return result;
729
+ }
730
+ function convertZodUnion(def) {
731
+ const options = def.options;
732
+ const result = {
733
+ anyOf: options.map(convertZodType)
734
+ };
735
+ if (def.description) {
736
+ result.description = def.description;
737
+ }
738
+ return result;
739
+ }
740
+ function convertZodNullable(def) {
741
+ const inner = convertZodType(def.innerType);
742
+ return {
743
+ anyOf: [inner, { type: "null" }]
744
+ };
745
+ }
746
+ function convertZodRecord(def) {
747
+ const result = {
748
+ type: "object",
749
+ additionalProperties: convertZodType(def.valueType)
750
+ };
751
+ if (def.description) {
752
+ result.description = def.description;
753
+ }
754
+ return result;
755
+ }
756
+ function convertZodTuple(def) {
757
+ const items = def.items;
758
+ const result = {
759
+ type: "array",
760
+ items: items.map(convertZodType),
761
+ minItems: items.length,
762
+ maxItems: items.length
763
+ };
764
+ if (def.description) {
765
+ result.description = def.description;
766
+ }
767
+ return result;
768
+ }
769
+ function createFunctionToolFromSchema(name, description, schema, options) {
770
+ const jsonSchema = zodToJsonSchema(schema, options);
771
+ return createFunctionTool(name, description, jsonSchema);
772
+ }
773
+ function createFunctionTool(name, description, parameters) {
774
+ const fn = { name, description };
775
+ if (parameters) {
776
+ fn.parameters = parameters;
777
+ }
778
+ return {
779
+ type: ToolTypes.Function,
780
+ function: fn
781
+ };
782
+ }
783
+ function createWebTool(options) {
784
+ return {
785
+ type: ToolTypes.Web,
786
+ web: options ? {
787
+ mode: options.mode,
788
+ allowedDomains: options.allowedDomains,
789
+ excludedDomains: options.excludedDomains,
790
+ maxUses: options.maxUses
791
+ } : void 0
792
+ };
793
+ }
794
+ function toolChoiceAuto() {
795
+ return { type: ToolChoiceTypes.Auto };
796
+ }
797
+ function toolChoiceRequired() {
798
+ return { type: ToolChoiceTypes.Required };
799
+ }
800
+ function toolChoiceNone() {
801
+ return { type: ToolChoiceTypes.None };
802
+ }
803
+ function hasToolCalls(response) {
804
+ return (response.toolCalls?.length ?? 0) > 0;
805
+ }
806
+ function firstToolCall(response) {
807
+ return response.toolCalls?.[0];
808
+ }
809
+ function toolResultMessage(toolCallId, result) {
810
+ const content = typeof result === "string" ? result : JSON.stringify(result);
811
+ return {
812
+ role: "tool",
813
+ content,
814
+ toolCallId
815
+ };
816
+ }
817
+ function respondToToolCall(call, result) {
818
+ return toolResultMessage(call.id, result);
819
+ }
820
+ function assistantMessageWithToolCalls(content, toolCalls) {
821
+ return {
822
+ role: "assistant",
823
+ content,
824
+ toolCalls
825
+ };
826
+ }
827
+ var ToolCallAccumulator = class {
828
+ constructor() {
829
+ this.calls = /* @__PURE__ */ new Map();
830
+ }
831
+ /**
832
+ * Processes a streaming tool call delta.
833
+ * Returns true if this started a new tool call.
834
+ */
835
+ processDelta(delta) {
836
+ const existing = this.calls.get(delta.index);
837
+ if (!existing) {
838
+ this.calls.set(delta.index, {
839
+ id: delta.id ?? "",
840
+ type: delta.type ?? ToolTypes.Function,
841
+ function: {
842
+ name: delta.function?.name ?? "",
843
+ arguments: delta.function?.arguments ?? ""
844
+ }
845
+ });
846
+ return true;
847
+ }
848
+ if (delta.function) {
849
+ if (delta.function.name) {
850
+ existing.function = existing.function ?? { name: "", arguments: "" };
851
+ existing.function.name = delta.function.name;
852
+ }
853
+ if (delta.function.arguments) {
854
+ existing.function = existing.function ?? { name: "", arguments: "" };
855
+ existing.function.arguments += delta.function.arguments;
856
+ }
857
+ }
858
+ return false;
859
+ }
860
+ /**
861
+ * Returns all accumulated tool calls in index order.
862
+ */
863
+ getToolCalls() {
864
+ if (this.calls.size === 0) {
865
+ return [];
866
+ }
867
+ const maxIdx = Math.max(...this.calls.keys());
868
+ const result = [];
869
+ for (let i = 0; i <= maxIdx; i++) {
870
+ const call = this.calls.get(i);
871
+ if (call) {
872
+ result.push(call);
873
+ }
874
+ }
875
+ return result;
876
+ }
877
+ /**
878
+ * Returns a specific tool call by index, or undefined if not found.
879
+ */
880
+ getToolCall(index) {
881
+ return this.calls.get(index);
882
+ }
883
+ /**
884
+ * Clears all accumulated tool calls.
885
+ */
886
+ reset() {
887
+ this.calls.clear();
888
+ }
889
+ };
890
+ var ToolArgsError = class extends Error {
891
+ constructor(message, toolCallId, toolName, rawArguments) {
892
+ super(message);
893
+ this.name = "ToolArgsError";
894
+ this.toolCallId = toolCallId;
895
+ this.toolName = toolName;
896
+ this.rawArguments = rawArguments;
897
+ }
898
+ };
899
+ function parseToolArgs(call, schema) {
900
+ const toolName = call.function?.name ?? "unknown";
901
+ const rawArgs = call.function?.arguments ?? "";
902
+ let parsed;
903
+ try {
904
+ parsed = rawArgs ? JSON.parse(rawArgs) : {};
905
+ } catch (err) {
906
+ const message = err instanceof Error ? err.message : "Invalid JSON in arguments";
907
+ throw new ToolArgsError(
908
+ `Failed to parse arguments for tool '${toolName}': ${message}`,
909
+ call.id,
910
+ toolName,
911
+ rawArgs
912
+ );
913
+ }
914
+ try {
915
+ return schema.parse(parsed);
916
+ } catch (err) {
917
+ let message;
918
+ if (err instanceof Error) {
919
+ const zodErr = err;
920
+ if (zodErr.errors && Array.isArray(zodErr.errors)) {
921
+ const issues = zodErr.errors.map((e) => {
922
+ const path = e.path.length > 0 ? `${e.path.join(".")}: ` : "";
923
+ return `${path}${e.message}`;
924
+ }).join("; ");
925
+ message = issues;
926
+ } else {
927
+ message = err.message;
928
+ }
929
+ } else {
930
+ message = String(err);
931
+ }
932
+ throw new ToolArgsError(
933
+ `Invalid arguments for tool '${toolName}': ${message}`,
934
+ call.id,
935
+ toolName,
936
+ rawArgs
937
+ );
938
+ }
939
+ }
940
+ function tryParseToolArgs(call, schema) {
941
+ try {
942
+ const data = parseToolArgs(call, schema);
943
+ return { success: true, data };
944
+ } catch (err) {
945
+ if (err instanceof ToolArgsError) {
946
+ return { success: false, error: err };
947
+ }
948
+ const toolName = call.function?.name ?? "unknown";
949
+ const rawArgs = call.function?.arguments ?? "";
950
+ return {
951
+ success: false,
952
+ error: new ToolArgsError(
953
+ err instanceof Error ? err.message : String(err),
954
+ call.id,
955
+ toolName,
956
+ rawArgs
957
+ )
958
+ };
959
+ }
960
+ }
961
+ function parseToolArgsRaw(call) {
962
+ const toolName = call.function?.name ?? "unknown";
963
+ const rawArgs = call.function?.arguments ?? "";
964
+ try {
965
+ return rawArgs ? JSON.parse(rawArgs) : {};
966
+ } catch (err) {
967
+ const message = err instanceof Error ? err.message : "Invalid JSON in arguments";
968
+ throw new ToolArgsError(
969
+ `Failed to parse arguments for tool '${toolName}': ${message}`,
970
+ call.id,
971
+ toolName,
972
+ rawArgs
973
+ );
974
+ }
975
+ }
976
+ var ToolRegistry = class {
977
+ constructor() {
978
+ this.handlers = /* @__PURE__ */ new Map();
979
+ }
980
+ /**
981
+ * Registers a handler function for a tool name.
982
+ * @param name - The tool name (must match the function name in the tool definition)
983
+ * @param handler - Function to execute when this tool is called
984
+ * @returns this for chaining
985
+ */
986
+ register(name, handler) {
987
+ this.handlers.set(name, handler);
988
+ return this;
989
+ }
990
+ /**
991
+ * Unregisters a tool handler.
992
+ * @param name - The tool name to unregister
993
+ * @returns true if the handler was removed, false if it didn't exist
994
+ */
995
+ unregister(name) {
996
+ return this.handlers.delete(name);
997
+ }
998
+ /**
999
+ * Checks if a handler is registered for the given tool name.
1000
+ */
1001
+ has(name) {
1002
+ return this.handlers.has(name);
1003
+ }
1004
+ /**
1005
+ * Returns the list of registered tool names.
1006
+ */
1007
+ getRegisteredTools() {
1008
+ return Array.from(this.handlers.keys());
1009
+ }
1010
+ /**
1011
+ * Executes a single tool call.
1012
+ * @param call - The tool call to execute
1013
+ * @returns The execution result
1014
+ */
1015
+ async execute(call) {
1016
+ const toolName = call.function?.name ?? "";
1017
+ const handler = this.handlers.get(toolName);
1018
+ if (!handler) {
1019
+ return {
1020
+ toolCallId: call.id,
1021
+ toolName,
1022
+ result: null,
1023
+ error: `Unknown tool: '${toolName}'. Available tools: ${this.getRegisteredTools().join(", ") || "none"}`
1024
+ };
1025
+ }
1026
+ let args;
1027
+ try {
1028
+ args = call.function?.arguments ? JSON.parse(call.function.arguments) : {};
1029
+ } catch (err) {
1030
+ const errorMessage = err instanceof Error ? err.message : String(err);
1031
+ return {
1032
+ toolCallId: call.id,
1033
+ toolName,
1034
+ result: null,
1035
+ error: `Invalid JSON in arguments: ${errorMessage}`,
1036
+ isRetryable: true
1037
+ };
1038
+ }
1039
+ try {
1040
+ const result = await handler(args, call);
1041
+ return {
1042
+ toolCallId: call.id,
1043
+ toolName,
1044
+ result
1045
+ };
1046
+ } catch (err) {
1047
+ const isRetryable = err instanceof ToolArgsError;
1048
+ const errorMessage = err instanceof Error ? err.message : String(err);
1049
+ return {
1050
+ toolCallId: call.id,
1051
+ toolName,
1052
+ result: null,
1053
+ error: errorMessage,
1054
+ isRetryable
1055
+ };
1056
+ }
1057
+ }
1058
+ /**
1059
+ * Executes multiple tool calls in parallel.
1060
+ * @param calls - Array of tool calls to execute
1061
+ * @returns Array of execution results in the same order as input
1062
+ */
1063
+ async executeAll(calls) {
1064
+ return Promise.all(calls.map((call) => this.execute(call)));
1065
+ }
1066
+ /**
1067
+ * Converts execution results to tool result messages.
1068
+ * Useful for appending to the conversation history.
1069
+ * @param results - Array of execution results
1070
+ * @returns Array of ChatMessage objects with role "tool"
1071
+ */
1072
+ resultsToMessages(results) {
1073
+ return results.map((r) => {
1074
+ const content = r.error ? `Error: ${r.error}` : typeof r.result === "string" ? r.result : JSON.stringify(r.result);
1075
+ return toolResultMessage(r.toolCallId, content);
1076
+ });
1077
+ }
1078
+ };
1079
+ function formatToolErrorForModel(result) {
1080
+ const lines = [
1081
+ `Tool call error for '${result.toolName}': ${result.error}`
1082
+ ];
1083
+ if (result.isRetryable) {
1084
+ lines.push("");
1085
+ lines.push("Please correct the arguments and try again.");
1086
+ }
1087
+ return lines.join("\n");
1088
+ }
1089
+ function hasRetryableErrors(results) {
1090
+ return results.some((r) => r.error && r.isRetryable);
1091
+ }
1092
+ function getRetryableErrors(results) {
1093
+ return results.filter((r) => r.error && r.isRetryable);
1094
+ }
1095
+ function createRetryMessages(results) {
1096
+ return results.filter((r) => r.error && r.isRetryable).map((r) => toolResultMessage(r.toolCallId, formatToolErrorForModel(r)));
1097
+ }
1098
+ async function executeWithRetry(registry, toolCalls, options = {}) {
1099
+ const maxRetries = options.maxRetries ?? 2;
1100
+ let currentCalls = toolCalls;
1101
+ let attempt = 0;
1102
+ const successfulResults = /* @__PURE__ */ new Map();
1103
+ while (attempt <= maxRetries) {
1104
+ const results = await registry.executeAll(currentCalls);
1105
+ for (const result of results) {
1106
+ if (!result.error || !result.isRetryable) {
1107
+ successfulResults.set(result.toolCallId, result);
1108
+ }
1109
+ }
1110
+ const retryableResults = getRetryableErrors(results);
1111
+ if (retryableResults.length === 0 || !options.onRetry) {
1112
+ for (const result of results) {
1113
+ if (result.error && result.isRetryable) {
1114
+ successfulResults.set(result.toolCallId, result);
1115
+ }
1116
+ }
1117
+ return Array.from(successfulResults.values());
1118
+ }
1119
+ attempt++;
1120
+ if (attempt > maxRetries) {
1121
+ for (const result of retryableResults) {
1122
+ successfulResults.set(result.toolCallId, result);
1123
+ }
1124
+ return Array.from(successfulResults.values());
1125
+ }
1126
+ const errorMessages = createRetryMessages(retryableResults);
1127
+ const newCalls = await options.onRetry(errorMessages, attempt);
1128
+ if (newCalls.length === 0) {
1129
+ for (const result of retryableResults) {
1130
+ successfulResults.set(result.toolCallId, result);
1131
+ }
1132
+ return Array.from(successfulResults.values());
1133
+ }
1134
+ currentCalls = newCalls;
1135
+ }
1136
+ return Array.from(successfulResults.values());
1137
+ }
1138
+
418
1139
  // src/chat.ts
419
1140
  var REQUEST_ID_HEADER = "X-ModelRelay-Chat-Request-Id";
420
1141
  var ChatClient = class {
@@ -440,16 +1161,13 @@ var ChatCompletionsClient = class {
440
1161
  const stream = options.stream ?? params.stream ?? true;
441
1162
  const metrics = mergeMetrics(this.metrics, options.metrics);
442
1163
  const trace = mergeTrace(this.trace, options.trace);
443
- const modelValue = modelToString(params.model).trim();
444
- if (!modelValue) {
445
- throw new ConfigError("model is required");
446
- }
447
1164
  if (!params?.messages?.length) {
448
1165
  throw new ConfigError("at least one message is required");
449
1166
  }
450
1167
  if (!hasUserMessage(params.messages)) {
451
1168
  throw new ConfigError("at least one user message is required");
452
1169
  }
1170
+ validateRequestModel(params.model);
453
1171
  const authHeaders = await this.auth.authForChat(params.customerId);
454
1172
  const body = buildProxyBody(
455
1173
  params,
@@ -588,7 +1306,7 @@ var ChatCompletionsStream = class {
588
1306
  const context = this.enrichContext(evt);
589
1307
  this.context = context;
590
1308
  this.trace?.streamEvent?.({ context, event: evt });
591
- if (evt.type === "message_start" || evt.type === "message_delta" || evt.type === "message_stop") {
1309
+ 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") {
592
1310
  this.recordFirstToken();
593
1311
  }
594
1312
  if (evt.type === "message_stop" && evt.usage && this.metrics?.usage) {
@@ -673,11 +1391,15 @@ function mapChatEvent(raw, requestId) {
673
1391
  const model = normalizeModelId(p.model || p?.message?.model);
674
1392
  const stopReason = normalizeStopReason(p.stop_reason);
675
1393
  const textDelta = extractTextDelta(p);
1394
+ const toolCallDelta = extractToolCallDelta(p, type);
1395
+ const toolCalls = extractToolCalls(p, type);
676
1396
  return {
677
1397
  type,
678
1398
  event: raw.event || type,
679
1399
  data: p,
680
1400
  textDelta,
1401
+ toolCallDelta,
1402
+ toolCalls,
681
1403
  responseId,
682
1404
  model,
683
1405
  stopReason,
@@ -697,6 +1419,12 @@ function normalizeEventType(eventName, payload) {
697
1419
  return "message_delta";
698
1420
  case "message_stop":
699
1421
  return "message_stop";
1422
+ case "tool_use_start":
1423
+ return "tool_use_start";
1424
+ case "tool_use_delta":
1425
+ return "tool_use_delta";
1426
+ case "tool_use_stop":
1427
+ return "tool_use_stop";
700
1428
  case "ping":
701
1429
  return "ping";
702
1430
  default:
@@ -707,6 +1435,9 @@ function extractTextDelta(payload) {
707
1435
  if (!payload || typeof payload !== "object") {
708
1436
  return void 0;
709
1437
  }
1438
+ if (typeof payload.text_delta === "string" && payload.text_delta !== "") {
1439
+ return payload.text_delta;
1440
+ }
710
1441
  if (typeof payload.delta === "string") {
711
1442
  return payload.delta;
712
1443
  }
@@ -720,9 +1451,56 @@ function extractTextDelta(payload) {
720
1451
  }
721
1452
  return void 0;
722
1453
  }
1454
+ function extractToolCallDelta(payload, type) {
1455
+ if (!payload || typeof payload !== "object") {
1456
+ return void 0;
1457
+ }
1458
+ if (type !== "tool_use_start" && type !== "tool_use_delta") {
1459
+ return void 0;
1460
+ }
1461
+ if (payload.tool_call_delta) {
1462
+ const d = payload.tool_call_delta;
1463
+ return {
1464
+ index: d.index ?? 0,
1465
+ id: d.id,
1466
+ type: d.type,
1467
+ function: d.function ? {
1468
+ name: d.function.name,
1469
+ arguments: d.function.arguments
1470
+ } : void 0
1471
+ };
1472
+ }
1473
+ if (typeof payload.index === "number" || payload.id || payload.name) {
1474
+ return {
1475
+ index: payload.index ?? 0,
1476
+ id: payload.id,
1477
+ type: payload.tool_type,
1478
+ function: payload.name || payload.arguments ? {
1479
+ name: payload.name,
1480
+ arguments: payload.arguments
1481
+ } : void 0
1482
+ };
1483
+ }
1484
+ return void 0;
1485
+ }
1486
+ function extractToolCalls(payload, type) {
1487
+ if (!payload || typeof payload !== "object") {
1488
+ return void 0;
1489
+ }
1490
+ if (type !== "tool_use_stop" && type !== "message_stop") {
1491
+ return void 0;
1492
+ }
1493
+ if (payload.tool_calls?.length) {
1494
+ return normalizeToolCalls(payload.tool_calls);
1495
+ }
1496
+ if (payload.tool_call) {
1497
+ return normalizeToolCalls([payload.tool_call]);
1498
+ }
1499
+ return void 0;
1500
+ }
723
1501
  function normalizeChatResponse(payload, requestId) {
724
1502
  const p = payload;
725
- return {
1503
+ const response = {
726
1504
  id: p?.id,
727
1505
  provider: normalizeProvider(p?.provider),
728
1506
  content: Array.isArray(p?.content) ? p.content : p?.content ? [String(p.content)] : [],
@@ -731,26 +1509,51 @@ function normalizeChatResponse(payload, requestId) {
731
1509
  usage: normalizeUsage(p?.usage),
732
1510
  requestId
733
1511
  };
1512
+ if (p?.tool_calls?.length) {
1513
+ response.toolCalls = normalizeToolCalls(p.tool_calls);
1514
+ }
1515
+ return response;
1516
+ }
1517
+ function normalizeToolCalls(toolCalls) {
1518
+ return toolCalls.map(
1519
+ (tc) => createToolCall(
1520
+ tc.id,
1521
+ tc.function?.name ?? "",
1522
+ tc.function?.arguments ?? "",
1523
+ tc.type || ToolTypes.Function
1524
+ )
1525
+ );
734
1526
  }
735
1527
  function normalizeUsage(payload) {
736
1528
  if (!payload) {
737
- return { inputTokens: 0, outputTokens: 0, totalTokens: 0 };
1529
+ return createUsage(0, 0, 0);
738
1530
  }
739
- const usage = {
740
- inputTokens: Number(payload.input_tokens ?? 0),
741
- outputTokens: Number(payload.output_tokens ?? 0),
742
- totalTokens: Number(payload.total_tokens ?? 0)
743
- };
744
- if (!usage.totalTokens) {
745
- usage.totalTokens = usage.inputTokens + usage.outputTokens;
1531
+ const inputTokens = Number(payload.input_tokens ?? 0);
1532
+ const outputTokens = Number(payload.output_tokens ?? 0);
1533
+ const totalTokens = Number(payload.total_tokens ?? 0);
1534
+ return createUsage(inputTokens, outputTokens, totalTokens || void 0);
1535
+ }
1536
+ function validateRequestModel(model) {
1537
+ if (model === void 0 || model === null) return;
1538
+ const value = modelToString(model).trim();
1539
+ if (!value) {
1540
+ throw new ConfigError("model id must be a non-empty string when provided");
1541
+ }
1542
+ const knownModels = Object.values(Models);
1543
+ if (!knownModels.includes(value)) {
1544
+ throw new ConfigError(
1545
+ `unsupported model id "${value}". Use one of the SDK Models.* constants or omit model to use the tier's default model.`
1546
+ );
746
1547
  }
747
- return usage;
748
1548
  }
749
1549
  function buildProxyBody(params, metadata) {
1550
+ const modelValue = params.model ? modelToString(params.model).trim() : "";
750
1551
  const body = {
751
- model: modelToString(params.model),
752
1552
  messages: normalizeMessages(params.messages)
753
1553
  };
1554
+ if (modelValue) {
1555
+ body.model = modelValue;
1556
+ }
754
1557
  if (typeof params.maxTokens === "number") body.max_tokens = params.maxTokens;
755
1558
  if (params.provider) body.provider = providerToString(params.provider);
756
1559
  if (typeof params.temperature === "number")
@@ -758,13 +1561,69 @@ function buildProxyBody(params, metadata) {
758
1561
  if (metadata && Object.keys(metadata).length > 0) body.metadata = metadata;
759
1562
  if (params.stop?.length) body.stop = params.stop;
760
1563
  if (params.stopSequences?.length) body.stop_sequences = params.stopSequences;
1564
+ if (params.tools?.length) body.tools = normalizeTools(params.tools);
1565
+ if (params.toolChoice) body.tool_choice = normalizeToolChoice(params.toolChoice);
761
1566
  return body;
762
1567
  }
763
1568
  function normalizeMessages(messages) {
764
- return messages.map((msg) => ({
765
- role: msg.role || "user",
766
- content: msg.content
767
- }));
1569
+ return messages.map((msg) => {
1570
+ const normalized = {
1571
+ role: msg.role || "user",
1572
+ content: msg.content
1573
+ };
1574
+ if (msg.toolCalls?.length) {
1575
+ normalized.tool_calls = msg.toolCalls.map((tc) => ({
1576
+ id: tc.id,
1577
+ type: tc.type,
1578
+ function: tc.function ? createFunctionCall(tc.function.name, tc.function.arguments) : void 0
1579
+ }));
1580
+ }
1581
+ if (msg.toolCallId) {
1582
+ normalized.tool_call_id = msg.toolCallId;
1583
+ }
1584
+ return normalized;
1585
+ });
1586
+ }
1587
+ function normalizeTools(tools) {
1588
+ return tools.map((tool) => {
1589
+ const normalized = { type: tool.type };
1590
+ if (tool.function) {
1591
+ normalized.function = {
1592
+ name: tool.function.name,
1593
+ description: tool.function.description,
1594
+ parameters: tool.function.parameters
1595
+ };
1596
+ }
1597
+ if (tool.web) {
1598
+ const web = {
1599
+ allowed_domains: tool.web.allowedDomains,
1600
+ excluded_domains: tool.web.excludedDomains,
1601
+ max_uses: tool.web.maxUses
1602
+ };
1603
+ if (tool.web.mode) {
1604
+ web.mode = tool.web.mode;
1605
+ }
1606
+ normalized.web = web;
1607
+ }
1608
+ if (tool.xSearch) {
1609
+ normalized.x_search = {
1610
+ allowed_handles: tool.xSearch.allowedHandles,
1611
+ excluded_handles: tool.xSearch.excludedHandles,
1612
+ from_date: tool.xSearch.fromDate,
1613
+ to_date: tool.xSearch.toDate
1614
+ };
1615
+ }
1616
+ if (tool.codeExecution) {
1617
+ normalized.code_execution = {
1618
+ language: tool.codeExecution.language,
1619
+ timeout_ms: tool.codeExecution.timeoutMs
1620
+ };
1621
+ }
1622
+ return normalized;
1623
+ });
1624
+ }
1625
+ function normalizeToolChoice(tc) {
1626
+ return { type: tc.type };
768
1627
  }
769
1628
  function requestIdFromHeaders(headers) {
770
1629
  return headers.get(REQUEST_ID_HEADER) || headers.get("X-Request-Id") || void 0;
@@ -789,6 +1648,10 @@ function hasUserMessage(messages) {
789
1648
  }
790
1649
 
791
1650
  // src/customers.ts
1651
+ var EMAIL_REGEX = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
1652
+ function isValidEmail(email) {
1653
+ return EMAIL_REGEX.test(email);
1654
+ }
792
1655
  var CustomersClient = class {
793
1656
  constructor(http, cfg) {
794
1657
  this.http = http;
@@ -823,6 +1686,12 @@ var CustomersClient = class {
823
1686
  if (!request.external_id?.trim()) {
824
1687
  throw new ConfigError("external_id is required");
825
1688
  }
1689
+ if (!request.email?.trim()) {
1690
+ throw new ConfigError("email is required");
1691
+ }
1692
+ if (!isValidEmail(request.email)) {
1693
+ throw new ConfigError("invalid email format");
1694
+ }
826
1695
  const response = await this.http.json("/customers", {
827
1696
  method: "POST",
828
1697
  body: request,
@@ -860,6 +1729,12 @@ var CustomersClient = class {
860
1729
  if (!request.external_id?.trim()) {
861
1730
  throw new ConfigError("external_id is required");
862
1731
  }
1732
+ if (!request.email?.trim()) {
1733
+ throw new ConfigError("email is required");
1734
+ }
1735
+ if (!isValidEmail(request.email)) {
1736
+ throw new ConfigError("invalid email format");
1737
+ }
863
1738
  const response = await this.http.json("/customers", {
864
1739
  method: "PUT",
865
1740
  body: request,
@@ -961,10 +1836,7 @@ var TiersClient = class {
961
1836
  // src/http.ts
962
1837
  var HTTPClient = class {
963
1838
  constructor(cfg) {
964
- const baseFromEnv = baseUrlForEnvironment(cfg.environment);
965
- const resolvedBase = normalizeBaseUrl(
966
- cfg.baseUrl || baseFromEnv || DEFAULT_BASE_URL
967
- );
1839
+ const resolvedBase = normalizeBaseUrl(cfg.baseUrl || DEFAULT_BASE_URL);
968
1840
  if (!isValidHttpUrl(resolvedBase)) {
969
1841
  throw new ConfigError(
970
1842
  "baseUrl must start with http:// or https://"
@@ -1177,12 +2049,6 @@ function normalizeBaseUrl(value) {
1177
2049
  function isValidHttpUrl(value) {
1178
2050
  return /^https?:\/\//i.test(value);
1179
2051
  }
1180
- function baseUrlForEnvironment(env) {
1181
- if (!env || env === "production") return void 0;
1182
- if (env === "staging") return STAGING_BASE_URL;
1183
- if (env === "sandbox") return SANDBOX_BASE_URL;
1184
- return void 0;
1185
- }
1186
2052
  function normalizeRetryConfig(retry) {
1187
2053
  if (retry === false) return void 0;
1188
2054
  const cfg = retry || {};
@@ -1301,7 +2167,7 @@ var ModelRelay = class {
1301
2167
  if (!cfg.key && !cfg.token) {
1302
2168
  throw new ConfigError("Provide an API key or access token");
1303
2169
  }
1304
- this.baseUrl = resolveBaseUrl(cfg.environment, cfg.baseUrl);
2170
+ this.baseUrl = resolveBaseUrl(cfg.baseUrl);
1305
2171
  const http = new HTTPClient({
1306
2172
  baseUrl: this.baseUrl,
1307
2173
  apiKey: cfg.key,
@@ -1312,7 +2178,6 @@ var ModelRelay = class {
1312
2178
  timeoutMs: cfg.timeoutMs,
1313
2179
  retry: cfg.retry,
1314
2180
  defaultHeaders: cfg.defaultHeaders,
1315
- environment: cfg.environment,
1316
2181
  metrics: cfg.metrics,
1317
2182
  trace: cfg.trace
1318
2183
  });
@@ -1335,8 +2200,8 @@ var ModelRelay = class {
1335
2200
  });
1336
2201
  }
1337
2202
  };
1338
- function resolveBaseUrl(env, override) {
1339
- const base = override || (env === "staging" ? STAGING_BASE_URL : env === "sandbox" ? SANDBOX_BASE_URL : DEFAULT_BASE_URL);
2203
+ function resolveBaseUrl(override) {
2204
+ const base = override || DEFAULT_BASE_URL;
1340
2205
  return base.replace(/\/+$/, "");
1341
2206
  }
1342
2207
  // Annotate the CommonJS export names for ESM import in node:
@@ -1351,16 +2216,39 @@ function resolveBaseUrl(env, override) {
1351
2216
  DEFAULT_CLIENT_HEADER,
1352
2217
  DEFAULT_CONNECT_TIMEOUT_MS,
1353
2218
  DEFAULT_REQUEST_TIMEOUT_MS,
2219
+ ErrorCodes,
1354
2220
  ModelRelay,
1355
2221
  ModelRelayError,
1356
2222
  Models,
1357
2223
  Providers,
1358
- SANDBOX_BASE_URL,
1359
2224
  SDK_VERSION,
1360
- STAGING_BASE_URL,
1361
2225
  StopReasons,
1362
2226
  TiersClient,
2227
+ ToolArgsError,
2228
+ ToolCallAccumulator,
2229
+ ToolChoiceTypes,
2230
+ ToolRegistry,
2231
+ ToolTypes,
1363
2232
  TransportError,
2233
+ assistantMessageWithToolCalls,
2234
+ createAccessTokenAuth,
2235
+ createApiKeyAuth,
2236
+ createAssistantMessage,
2237
+ createFunctionCall,
2238
+ createFunctionTool,
2239
+ createFunctionToolFromSchema,
2240
+ createRetryMessages,
2241
+ createSystemMessage,
2242
+ createToolCall,
2243
+ createUsage,
2244
+ createUserMessage,
2245
+ createWebTool,
2246
+ executeWithRetry,
2247
+ firstToolCall,
2248
+ formatToolErrorForModel,
2249
+ getRetryableErrors,
2250
+ hasRetryableErrors,
2251
+ hasToolCalls,
1364
2252
  isPublishableKey,
1365
2253
  mergeMetrics,
1366
2254
  mergeTrace,
@@ -1369,6 +2257,15 @@ function resolveBaseUrl(env, override) {
1369
2257
  normalizeProvider,
1370
2258
  normalizeStopReason,
1371
2259
  parseErrorResponse,
2260
+ parseToolArgs,
2261
+ parseToolArgsRaw,
1372
2262
  providerToString,
1373
- stopReasonToString
2263
+ respondToToolCall,
2264
+ stopReasonToString,
2265
+ toolChoiceAuto,
2266
+ toolChoiceNone,
2267
+ toolChoiceRequired,
2268
+ toolResultMessage,
2269
+ tryParseToolArgs,
2270
+ zodToJsonSchema
1374
2271
  });