@modelrelay/sdk 1.29.0 → 1.37.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 CHANGED
@@ -41,7 +41,6 @@ __export(index_exports, {
41
41
  CustomerResponsesClient: () => CustomerResponsesClient,
42
42
  CustomerScopedModelRelay: () => CustomerScopedModelRelay,
43
43
  CustomerTokenProvider: () => CustomerTokenProvider,
44
- CustomersClient: () => CustomersClient,
45
44
  DEFAULT_BASE_URL: () => DEFAULT_BASE_URL,
46
45
  DEFAULT_CLIENT_HEADER: () => DEFAULT_CLIENT_HEADER,
47
46
  DEFAULT_CONNECT_TIMEOUT_MS: () => DEFAULT_CONNECT_TIMEOUT_MS,
@@ -77,7 +76,6 @@ __export(index_exports, {
77
76
  MessageRoles: () => MessageRoles,
78
77
  ModelRelay: () => ModelRelay,
79
78
  ModelRelayError: () => ModelRelayError,
80
- ModelsClient: () => ModelsClient,
81
79
  OIDCExchangeTokenProvider: () => OIDCExchangeTokenProvider,
82
80
  OutputFormatTypes: () => OutputFormatTypes,
83
81
  OutputItemTypes: () => OutputItemTypes,
@@ -140,6 +138,7 @@ __export(index_exports, {
140
138
  createUserMessage: () => createUserMessage,
141
139
  createWebTool: () => createWebTool,
142
140
  defaultRetryHandler: () => defaultRetryHandler,
141
+ defaultTierModelId: () => defaultTierModelId,
143
142
  executeWithRetry: () => executeWithRetry,
144
143
  firstToolCall: () => firstToolCall,
145
144
  formatToolErrorForModel: () => formatToolErrorForModel,
@@ -516,6 +515,205 @@ function isSecretKey(key) {
516
515
  return key.startsWith(SECRET_PREFIX);
517
516
  }
518
517
 
518
+ // package.json
519
+ var package_default = {
520
+ name: "@modelrelay/sdk",
521
+ version: "1.37.0",
522
+ description: "TypeScript SDK for the ModelRelay API",
523
+ type: "module",
524
+ main: "dist/index.cjs",
525
+ module: "dist/index.js",
526
+ types: "dist/index.d.ts",
527
+ exports: {
528
+ ".": {
529
+ types: "./dist/index.d.ts",
530
+ import: "./dist/index.js",
531
+ require: "./dist/index.cjs"
532
+ },
533
+ "./billing": {
534
+ types: "./dist/billing/index.d.ts",
535
+ import: "./dist/billing/index.js",
536
+ require: "./dist/billing/index.cjs"
537
+ },
538
+ "./node": {
539
+ types: "./dist/node.d.ts",
540
+ import: "./dist/node.js",
541
+ require: "./dist/node.cjs"
542
+ }
543
+ },
544
+ publishConfig: {
545
+ access: "public"
546
+ },
547
+ files: [
548
+ "dist"
549
+ ],
550
+ scripts: {
551
+ build: "tsup src/index.ts src/node.ts src/billing/index.ts --format esm,cjs --dts --external playwright",
552
+ dev: "tsup src/index.ts src/node.ts src/billing/index.ts --format esm,cjs --dts --watch",
553
+ lint: "tsc --noEmit --project tsconfig.lint.json",
554
+ test: "vitest run",
555
+ "generate:types": "openapi-typescript ../../api/openapi/api.json -o src/generated/api.ts"
556
+ },
557
+ keywords: [
558
+ "modelrelay",
559
+ "llm",
560
+ "sdk",
561
+ "typescript"
562
+ ],
563
+ author: "Shane Vitarana",
564
+ license: "Apache-2.0",
565
+ dependencies: {
566
+ "fast-json-patch": "^3.1.1",
567
+ zod: "^3.25.76"
568
+ },
569
+ peerDependencies: {
570
+ playwright: ">=1.40.0"
571
+ },
572
+ peerDependenciesMeta: {
573
+ playwright: {
574
+ optional: true
575
+ }
576
+ },
577
+ devDependencies: {
578
+ "@types/node": "^25.0.3",
579
+ "openapi-typescript": "^7.10.1",
580
+ playwright: "^1.57.0",
581
+ tsup: "^8.5.1",
582
+ typescript: "^5.9.3",
583
+ vitest: "^2.1.9"
584
+ }
585
+ };
586
+
587
+ // src/types.ts
588
+ var SDK_VERSION = package_default.version || "0.0.0";
589
+ var DEFAULT_BASE_URL = "https://api.modelrelay.ai/api/v1";
590
+ var DEFAULT_CLIENT_HEADER = `modelrelay-ts/${SDK_VERSION}`;
591
+ var DEFAULT_CONNECT_TIMEOUT_MS = 5e3;
592
+ var DEFAULT_REQUEST_TIMEOUT_MS = 6e4;
593
+ var StopReasons = {
594
+ Completed: "completed",
595
+ Stop: "stop",
596
+ StopSequence: "stop_sequence",
597
+ EndTurn: "end_turn",
598
+ MaxTokens: "max_tokens",
599
+ MaxLength: "max_len",
600
+ MaxContext: "max_context",
601
+ ToolCalls: "tool_calls",
602
+ TimeLimit: "time_limit",
603
+ ContentFilter: "content_filter",
604
+ Incomplete: "incomplete",
605
+ Unknown: "unknown"
606
+ };
607
+ function asProviderId(value) {
608
+ return value;
609
+ }
610
+ function asModelId(value) {
611
+ return value;
612
+ }
613
+ function asTierCode(value) {
614
+ return value;
615
+ }
616
+ var SubscriptionStatuses = {
617
+ Active: "active",
618
+ Trialing: "trialing",
619
+ PastDue: "past_due",
620
+ Canceled: "canceled",
621
+ Unpaid: "unpaid",
622
+ Incomplete: "incomplete",
623
+ IncompleteExpired: "incomplete_expired",
624
+ Paused: "paused"
625
+ };
626
+ var BillingProviders = {
627
+ Stripe: "stripe",
628
+ Crypto: "crypto",
629
+ AppStore: "app_store",
630
+ External: "external"
631
+ };
632
+ function createUsage(inputTokens, outputTokens, totalTokens) {
633
+ return {
634
+ inputTokens,
635
+ outputTokens,
636
+ totalTokens: totalTokens ?? inputTokens + outputTokens
637
+ };
638
+ }
639
+ var MessageRoles = {
640
+ User: "user",
641
+ Assistant: "assistant",
642
+ System: "system",
643
+ Tool: "tool"
644
+ };
645
+ var ContentPartTypes = {
646
+ Text: "text"
647
+ };
648
+ var InputItemTypes = {
649
+ Message: "message"
650
+ };
651
+ var OutputItemTypes = {
652
+ Message: "message"
653
+ };
654
+ var ToolTypes = {
655
+ Function: "function",
656
+ Web: "web",
657
+ XSearch: "x_search",
658
+ CodeExecution: "code_execution"
659
+ };
660
+ var WebToolIntents = {
661
+ Auto: "auto",
662
+ SearchWeb: "search_web",
663
+ FetchURL: "fetch_url"
664
+ };
665
+ var ToolChoiceTypes = {
666
+ Auto: "auto",
667
+ Required: "required",
668
+ None: "none"
669
+ };
670
+ var OutputFormatTypes = {
671
+ Text: "text",
672
+ JsonSchema: "json_schema"
673
+ };
674
+ function mergeMetrics(base, override) {
675
+ if (!base && !override) return void 0;
676
+ return {
677
+ ...base || {},
678
+ ...override || {}
679
+ };
680
+ }
681
+ function mergeTrace(base, override) {
682
+ if (!base && !override) return void 0;
683
+ return {
684
+ ...base || {},
685
+ ...override || {}
686
+ };
687
+ }
688
+ function normalizeStopReason(value) {
689
+ if (value === void 0 || value === null) return void 0;
690
+ const str = String(value).trim();
691
+ const lower = str.toLowerCase();
692
+ for (const reason of Object.values(StopReasons)) {
693
+ if (lower === reason) return reason;
694
+ }
695
+ switch (lower) {
696
+ case "length":
697
+ return StopReasons.MaxLength;
698
+ default:
699
+ return { other: str };
700
+ }
701
+ }
702
+ function stopReasonToString(value) {
703
+ if (!value) return void 0;
704
+ if (typeof value === "string") return value;
705
+ return value.other?.trim() || void 0;
706
+ }
707
+ function normalizeModelId(value) {
708
+ if (value === void 0 || value === null) return void 0;
709
+ const str = String(value).trim();
710
+ if (!str) return void 0;
711
+ return str;
712
+ }
713
+ function modelToString(value) {
714
+ return String(value).trim();
715
+ }
716
+
519
717
  // src/auth.ts
520
718
  function createApiKeyAuth(apiKey) {
521
719
  return { apiKey };
@@ -700,7 +898,7 @@ var AuthClient = class {
700
898
  projectId: apiResp.project_id,
701
899
  customerId: apiResp.customer_id,
702
900
  customerExternalId: apiResp.customer_external_id,
703
- tierCode: apiResp.tier_code
901
+ tierCode: apiResp.tier_code ? asTierCode(apiResp.tier_code) : void 0
704
902
  };
705
903
  }
706
904
  /**
@@ -732,7 +930,7 @@ var AuthClient = class {
732
930
  projectId: apiResp.project_id,
733
931
  customerId: apiResp.customer_id,
734
932
  customerExternalId: apiResp.customer_external_id,
735
- tierCode: apiResp.tier_code
933
+ tierCode: apiResp.tier_code ? asTierCode(apiResp.tier_code) : void 0
736
934
  };
737
935
  }
738
936
  /**
@@ -844,7 +1042,7 @@ var AuthClient = class {
844
1042
  projectId: apiResp.project_id,
845
1043
  customerId: apiResp.customer_id,
846
1044
  customerExternalId: apiResp.customer_external_id,
847
- tierCode: apiResp.tier_code
1045
+ tierCode: apiResp.tier_code ? asTierCode(apiResp.tier_code) : void 0
848
1046
  }
849
1047
  };
850
1048
  } catch (err) {
@@ -896,200 +1094,6 @@ function isTokenReusable(token) {
896
1094
  return token.expiresAt.getTime() - Date.now() > 6e4;
897
1095
  }
898
1096
 
899
- // package.json
900
- var package_default = {
901
- name: "@modelrelay/sdk",
902
- version: "1.29.0",
903
- description: "TypeScript SDK for the ModelRelay API",
904
- type: "module",
905
- main: "dist/index.cjs",
906
- module: "dist/index.js",
907
- types: "dist/index.d.ts",
908
- exports: {
909
- ".": {
910
- types: "./dist/index.d.ts",
911
- import: "./dist/index.js",
912
- require: "./dist/index.cjs"
913
- },
914
- "./node": {
915
- types: "./dist/node.d.ts",
916
- import: "./dist/node.js",
917
- require: "./dist/node.cjs"
918
- }
919
- },
920
- publishConfig: {
921
- access: "public"
922
- },
923
- files: [
924
- "dist"
925
- ],
926
- scripts: {
927
- build: "tsup src/index.ts src/node.ts --format esm,cjs --dts --external playwright",
928
- dev: "tsup src/index.ts src/node.ts --format esm,cjs --dts --watch",
929
- lint: "tsc --noEmit --project tsconfig.lint.json",
930
- test: "vitest run",
931
- "generate:types": "openapi-typescript ../../api/openapi/api.json -o src/generated/api.ts"
932
- },
933
- keywords: [
934
- "modelrelay",
935
- "llm",
936
- "sdk",
937
- "typescript"
938
- ],
939
- author: "Shane Vitarana",
940
- license: "Apache-2.0",
941
- dependencies: {
942
- "fast-json-patch": "^3.1.1",
943
- zod: "^3.23.0"
944
- },
945
- peerDependencies: {
946
- playwright: ">=1.40.0"
947
- },
948
- peerDependenciesMeta: {
949
- playwright: {
950
- optional: true
951
- }
952
- },
953
- devDependencies: {
954
- "@types/node": "^25.0.3",
955
- "openapi-typescript": "^7.4.4",
956
- playwright: "^1.49.0",
957
- tsup: "^8.2.4",
958
- typescript: "^5.6.3",
959
- vitest: "^2.1.4"
960
- }
961
- };
962
-
963
- // src/types.ts
964
- var SDK_VERSION = package_default.version || "0.0.0";
965
- var DEFAULT_BASE_URL = "https://api.modelrelay.ai/api/v1";
966
- var DEFAULT_CLIENT_HEADER = `modelrelay-ts/${SDK_VERSION}`;
967
- var DEFAULT_CONNECT_TIMEOUT_MS = 5e3;
968
- var DEFAULT_REQUEST_TIMEOUT_MS = 6e4;
969
- var StopReasons = {
970
- Completed: "completed",
971
- Stop: "stop",
972
- StopSequence: "stop_sequence",
973
- EndTurn: "end_turn",
974
- MaxTokens: "max_tokens",
975
- MaxLength: "max_len",
976
- MaxContext: "max_context",
977
- ToolCalls: "tool_calls",
978
- TimeLimit: "time_limit",
979
- ContentFilter: "content_filter",
980
- Incomplete: "incomplete",
981
- Unknown: "unknown"
982
- };
983
- function asProviderId(value) {
984
- return value;
985
- }
986
- function asModelId(value) {
987
- return value;
988
- }
989
- function asTierCode(value) {
990
- return value;
991
- }
992
- var SubscriptionStatuses = {
993
- Active: "active",
994
- Trialing: "trialing",
995
- PastDue: "past_due",
996
- Canceled: "canceled",
997
- Unpaid: "unpaid",
998
- Incomplete: "incomplete",
999
- IncompleteExpired: "incomplete_expired",
1000
- Paused: "paused"
1001
- };
1002
- var BillingProviders = {
1003
- Stripe: "stripe",
1004
- Crypto: "crypto",
1005
- AppStore: "app_store",
1006
- External: "external"
1007
- };
1008
- function createUsage(inputTokens, outputTokens, totalTokens) {
1009
- return {
1010
- inputTokens,
1011
- outputTokens,
1012
- totalTokens: totalTokens ?? inputTokens + outputTokens
1013
- };
1014
- }
1015
- var MessageRoles = {
1016
- User: "user",
1017
- Assistant: "assistant",
1018
- System: "system",
1019
- Tool: "tool"
1020
- };
1021
- var ContentPartTypes = {
1022
- Text: "text"
1023
- };
1024
- var InputItemTypes = {
1025
- Message: "message"
1026
- };
1027
- var OutputItemTypes = {
1028
- Message: "message"
1029
- };
1030
- var ToolTypes = {
1031
- Function: "function",
1032
- Web: "web",
1033
- XSearch: "x_search",
1034
- CodeExecution: "code_execution"
1035
- };
1036
- var WebToolIntents = {
1037
- Auto: "auto",
1038
- SearchWeb: "search_web",
1039
- FetchURL: "fetch_url"
1040
- };
1041
- var ToolChoiceTypes = {
1042
- Auto: "auto",
1043
- Required: "required",
1044
- None: "none"
1045
- };
1046
- var OutputFormatTypes = {
1047
- Text: "text",
1048
- JsonSchema: "json_schema"
1049
- };
1050
- function mergeMetrics(base, override) {
1051
- if (!base && !override) return void 0;
1052
- return {
1053
- ...base || {},
1054
- ...override || {}
1055
- };
1056
- }
1057
- function mergeTrace(base, override) {
1058
- if (!base && !override) return void 0;
1059
- return {
1060
- ...base || {},
1061
- ...override || {}
1062
- };
1063
- }
1064
- function normalizeStopReason(value) {
1065
- if (value === void 0 || value === null) return void 0;
1066
- const str = String(value).trim();
1067
- const lower = str.toLowerCase();
1068
- for (const reason of Object.values(StopReasons)) {
1069
- if (lower === reason) return reason;
1070
- }
1071
- switch (lower) {
1072
- case "length":
1073
- return StopReasons.MaxLength;
1074
- default:
1075
- return { other: str };
1076
- }
1077
- }
1078
- function stopReasonToString(value) {
1079
- if (!value) return void 0;
1080
- if (typeof value === "string") return value;
1081
- return value.other?.trim() || void 0;
1082
- }
1083
- function normalizeModelId(value) {
1084
- if (value === void 0 || value === null) return void 0;
1085
- const str = String(value).trim();
1086
- if (!str) return void 0;
1087
- return str;
1088
- }
1089
- function modelToString(value) {
1090
- return String(value).trim();
1091
- }
1092
-
1093
1097
  // src/tools.ts
1094
1098
  function createUserMessage(content) {
1095
1099
  return {
@@ -3880,510 +3884,146 @@ var RunsClient = class {
3880
3884
  trace,
3881
3885
  context: { method: "GET", path }
3882
3886
  });
3883
- return {
3884
- ...out,
3885
- run_id: parseRunId(out.run_id),
3886
- pending: out.pending.map((p) => ({
3887
- ...p,
3888
- node_id: parseNodeId(p.node_id),
3889
- tool_calls: p.tool_calls
3890
- }))
3891
- };
3892
- }
3893
- };
3894
-
3895
- // src/workflows_request.ts
3896
- var WORKFLOWS_COMPILE_PATH = "/workflows/compile";
3897
-
3898
- // src/workflows_client.ts
3899
- var WorkflowsClient = class {
3900
- constructor(http, auth, cfg = {}) {
3901
- this.http = http;
3902
- this.auth = auth;
3903
- this.metrics = cfg.metrics;
3904
- this.trace = cfg.trace;
3905
- }
3906
- async compileV0(spec, options = {}) {
3907
- const metrics = mergeMetrics(this.metrics, options.metrics);
3908
- const trace = mergeTrace(this.trace, options.trace);
3909
- const authHeaders = await this.auth.authForResponses();
3910
- const headers = { ...options.headers || {} };
3911
- const customerId = options.customerId?.trim();
3912
- if (customerId) {
3913
- headers[CUSTOMER_ID_HEADER] = customerId;
3914
- }
3915
- try {
3916
- const out = await this.http.json(
3917
- WORKFLOWS_COMPILE_PATH,
3918
- {
3919
- method: "POST",
3920
- headers,
3921
- body: spec,
3922
- signal: options.signal,
3923
- apiKey: authHeaders.apiKey,
3924
- accessToken: authHeaders.accessToken,
3925
- timeoutMs: options.timeoutMs,
3926
- connectTimeoutMs: options.connectTimeoutMs,
3927
- retry: options.retry,
3928
- metrics,
3929
- trace,
3930
- context: { method: "POST", path: WORKFLOWS_COMPILE_PATH }
3931
- }
3932
- );
3933
- return {
3934
- ok: true,
3935
- plan_json: out.plan_json,
3936
- plan_hash: parsePlanHash(out.plan_hash)
3937
- };
3938
- } catch (err) {
3939
- if (err instanceof WorkflowValidationError) {
3940
- return { ok: false, error_type: "validation_error", issues: err.issues };
3941
- }
3942
- if (err instanceof APIError) {
3943
- return {
3944
- ok: false,
3945
- error_type: "internal_error",
3946
- status: err.status ?? 0,
3947
- message: err.message,
3948
- code: err.code,
3949
- requestId: err.requestId
3950
- };
3951
- }
3952
- if (err instanceof ModelRelayError && err.category === "api") {
3953
- return {
3954
- ok: false,
3955
- error_type: "internal_error",
3956
- status: err.status ?? 0,
3957
- message: err.message,
3958
- code: err.code,
3959
- requestId: err.requestId
3960
- };
3961
- }
3962
- throw err;
3963
- }
3964
- }
3965
- async compileV1(spec, options = {}) {
3966
- const metrics = mergeMetrics(this.metrics, options.metrics);
3967
- const trace = mergeTrace(this.trace, options.trace);
3968
- const authHeaders = await this.auth.authForResponses();
3969
- const headers = { ...options.headers || {} };
3970
- const customerId = options.customerId?.trim();
3971
- if (customerId) {
3972
- headers[CUSTOMER_ID_HEADER] = customerId;
3973
- }
3974
- try {
3975
- const out = await this.http.json(
3976
- WORKFLOWS_COMPILE_PATH,
3977
- {
3978
- method: "POST",
3979
- headers,
3980
- body: spec,
3981
- signal: options.signal,
3982
- apiKey: authHeaders.apiKey,
3983
- accessToken: authHeaders.accessToken,
3984
- timeoutMs: options.timeoutMs,
3985
- connectTimeoutMs: options.connectTimeoutMs,
3986
- retry: options.retry,
3987
- metrics,
3988
- trace,
3989
- context: { method: "POST", path: WORKFLOWS_COMPILE_PATH }
3990
- }
3991
- );
3992
- return {
3993
- ok: true,
3994
- plan_json: out.plan_json,
3995
- plan_hash: parsePlanHash(out.plan_hash)
3996
- };
3997
- } catch (err) {
3998
- if (err instanceof WorkflowValidationError) {
3999
- return { ok: false, error_type: "validation_error", issues: err.issues };
4000
- }
4001
- if (err instanceof APIError) {
4002
- return {
4003
- ok: false,
4004
- error_type: "internal_error",
4005
- status: err.status ?? 0,
4006
- message: err.message,
4007
- code: err.code,
4008
- requestId: err.requestId
4009
- };
4010
- }
4011
- if (err instanceof ModelRelayError && err.category === "api") {
4012
- return {
4013
- ok: false,
4014
- error_type: "internal_error",
4015
- status: err.status ?? 0,
4016
- message: err.message,
4017
- code: err.code,
4018
- requestId: err.requestId
4019
- };
4020
- }
4021
- throw err;
4022
- }
4023
- }
4024
- };
4025
-
4026
- // src/customers.ts
4027
- var EMAIL_REGEX = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
4028
- function isValidEmail(email) {
4029
- return EMAIL_REGEX.test(email);
4030
- }
4031
- var CustomersClient = class {
4032
- constructor(http, cfg) {
4033
- this.http = http;
4034
- this.apiKey = cfg.apiKey ? parseApiKey(cfg.apiKey) : void 0;
4035
- this.hasSecretKey = this.apiKey ? isSecretKey(this.apiKey) : false;
4036
- this.accessToken = cfg.accessToken;
4037
- this.tokenProvider = cfg.tokenProvider;
4038
- }
4039
- ensureSecretKey() {
4040
- if (!this.apiKey || !this.hasSecretKey) {
4041
- throw new ConfigError(
4042
- "Secret key (mr_sk_*) required for customer operations"
4043
- );
4044
- }
4045
- }
4046
- ensureApiKey() {
4047
- if (!this.apiKey) {
4048
- throw new ConfigError(
4049
- "API key (mr_pk_* or mr_sk_*) required for claim operation"
4050
- );
4051
- }
4052
- }
4053
- async customerAccessToken() {
4054
- if (this.accessToken?.trim()) {
4055
- return this.accessToken.trim();
4056
- }
4057
- if (this.tokenProvider) {
4058
- const token = (await this.tokenProvider.getToken())?.trim();
4059
- if (!token) {
4060
- throw new ConfigError("tokenProvider returned an empty token");
4061
- }
4062
- return token;
4063
- }
4064
- throw new ConfigError("Access token or tokenProvider required for customers.me()");
4065
- }
4066
- /**
4067
- * Get the authenticated customer from a customer-scoped bearer token.
4068
- *
4069
- * This endpoint requires a customer bearer token. API keys are not accepted.
4070
- */
4071
- async me() {
4072
- const token = await this.customerAccessToken();
4073
- const response = await this.http.json("/customers/me", {
4074
- method: "GET",
4075
- accessToken: token
4076
- });
4077
- if (!response.customer) {
4078
- throw new ConfigError("missing customer in response");
4079
- }
4080
- return response.customer;
4081
- }
4082
- /**
4083
- * Get the authenticated customer's subscription details.
4084
- *
4085
- * This endpoint requires a customer bearer token. API keys are not accepted.
4086
- */
4087
- async meSubscription() {
4088
- const token = await this.customerAccessToken();
4089
- const response = await this.http.json("/customers/me/subscription", {
4090
- method: "GET",
4091
- accessToken: token
4092
- });
4093
- if (!response.subscription) {
4094
- throw new ConfigError("missing subscription in response");
4095
- }
4096
- return response.subscription;
4097
- }
4098
- /**
4099
- * Get the authenticated customer's usage metrics for the current billing window.
4100
- *
4101
- * This endpoint requires a customer bearer token. API keys are not accepted.
4102
- */
4103
- async meUsage() {
4104
- const token = await this.customerAccessToken();
4105
- const response = await this.http.json("/customers/me/usage", {
4106
- method: "GET",
4107
- accessToken: token
4108
- });
4109
- if (!response.usage) {
4110
- throw new ConfigError("missing usage in response");
4111
- }
4112
- return response.usage;
4113
- }
4114
- /**
4115
- * List all customers in the project.
4116
- */
4117
- async list() {
4118
- this.ensureSecretKey();
4119
- const response = await this.http.json("/customers", {
4120
- method: "GET",
4121
- apiKey: this.apiKey
4122
- });
4123
- return response.customers;
4124
- }
4125
- /**
4126
- * Create a new customer in the project.
4127
- */
4128
- async create(request) {
4129
- this.ensureSecretKey();
4130
- if (!request.external_id?.trim()) {
4131
- throw new ConfigError("external_id is required");
4132
- }
4133
- if (!request.email?.trim()) {
4134
- throw new ConfigError("email is required");
4135
- }
4136
- if (!isValidEmail(request.email)) {
4137
- throw new ConfigError("invalid email format");
4138
- }
4139
- const response = await this.http.json("/customers", {
4140
- method: "POST",
4141
- body: request,
4142
- apiKey: this.apiKey
4143
- });
4144
- return response.customer;
4145
- }
4146
- /**
4147
- * Get a customer by ID.
4148
- */
4149
- async get(customerId) {
4150
- this.ensureSecretKey();
4151
- if (!customerId?.trim()) {
4152
- throw new ConfigError("customerId is required");
4153
- }
4154
- const response = await this.http.json(
4155
- `/customers/${customerId}`,
4156
- {
4157
- method: "GET",
4158
- apiKey: this.apiKey
4159
- }
4160
- );
4161
- return response.customer;
4162
- }
4163
- /**
4164
- * Upsert a customer by external_id.
4165
- * If a customer with the given external_id exists, it is updated.
4166
- * Otherwise, a new customer is created.
4167
- */
4168
- async upsert(request) {
4169
- this.ensureSecretKey();
4170
- if (!request.external_id?.trim()) {
4171
- throw new ConfigError("external_id is required");
4172
- }
4173
- if (!request.email?.trim()) {
4174
- throw new ConfigError("email is required");
4175
- }
4176
- if (!isValidEmail(request.email)) {
4177
- throw new ConfigError("invalid email format");
4178
- }
4179
- const response = await this.http.json("/customers", {
4180
- method: "PUT",
4181
- body: request,
4182
- apiKey: this.apiKey
4183
- });
4184
- return response.customer;
4185
- }
4186
- /**
4187
- * Link a customer identity (provider + subject) to a customer found by email.
4188
- * Used when a customer subscribes via Stripe Checkout (email only) and later authenticates to the app.
4189
- *
4190
- * This is a user self-service operation that works with publishable keys,
4191
- * allowing CLI tools and frontends to link subscriptions to user identities.
4192
- *
4193
- * Works with both publishable keys (mr_pk_*) and secret keys (mr_sk_*).
4194
- *
4195
- * @throws {APIError} with status 404 if customer not found by email
4196
- * @throws {APIError} with status 409 if the identity is already linked to a different customer
4197
- */
4198
- async claim(request) {
4199
- this.ensureApiKey();
4200
- if (!request.email?.trim()) {
4201
- throw new ConfigError("email is required");
4202
- }
4203
- if (!isValidEmail(request.email)) {
4204
- throw new ConfigError("invalid email format");
4205
- }
4206
- if (!request.provider?.trim()) {
4207
- throw new ConfigError("provider is required");
4208
- }
4209
- if (!request.subject?.trim()) {
4210
- throw new ConfigError("subject is required");
4211
- }
4212
- await this.http.request("/customers/claim", {
4213
- method: "POST",
4214
- body: request,
4215
- apiKey: this.apiKey
4216
- });
4217
- }
4218
- /**
4219
- * Delete a customer by ID.
4220
- */
4221
- async delete(customerId) {
4222
- this.ensureSecretKey();
4223
- if (!customerId?.trim()) {
4224
- throw new ConfigError("customerId is required");
4225
- }
4226
- await this.http.request(`/customers/${customerId}`, {
4227
- method: "DELETE",
4228
- apiKey: this.apiKey
4229
- });
4230
- }
4231
- /**
4232
- * Create a Stripe checkout session for a customer subscription.
4233
- */
4234
- async subscribe(customerId, request) {
4235
- this.ensureSecretKey();
4236
- if (!customerId?.trim()) {
4237
- throw new ConfigError("customerId is required");
4238
- }
4239
- if (!request.tier_id?.trim()) {
4240
- throw new ConfigError("tier_id is required");
4241
- }
4242
- if (!request.success_url?.trim() || !request.cancel_url?.trim()) {
4243
- throw new ConfigError("success_url and cancel_url are required");
4244
- }
4245
- return await this.http.json(
4246
- `/customers/${customerId}/subscribe`,
4247
- {
4248
- method: "POST",
4249
- body: request,
4250
- apiKey: this.apiKey
4251
- }
4252
- );
4253
- }
4254
- /**
4255
- * Get the subscription details for a customer.
4256
- */
4257
- async getSubscription(customerId) {
4258
- this.ensureSecretKey();
4259
- if (!customerId?.trim()) {
4260
- throw new ConfigError("customerId is required");
4261
- }
4262
- const response = await this.http.json(
4263
- `/customers/${customerId}/subscription`,
4264
- {
4265
- method: "GET",
4266
- apiKey: this.apiKey
4267
- }
4268
- );
4269
- return response.subscription;
4270
- }
4271
- /**
4272
- * Cancel a customer's subscription at period end.
4273
- */
4274
- async unsubscribe(customerId) {
4275
- this.ensureSecretKey();
4276
- if (!customerId?.trim()) {
4277
- throw new ConfigError("customerId is required");
4278
- }
4279
- await this.http.request(`/customers/${customerId}/subscription`, {
4280
- method: "DELETE",
4281
- apiKey: this.apiKey
4282
- });
4283
- }
4284
- };
4285
-
4286
- // src/tiers.ts
4287
- var TiersClient = class {
4288
- constructor(http, cfg) {
4289
- this.http = http;
4290
- this.apiKey = cfg.apiKey ? parseApiKey(cfg.apiKey) : void 0;
4291
- this.hasSecretKey = this.apiKey ? isSecretKey(this.apiKey) : false;
4292
- }
4293
- ensureApiKey() {
4294
- if (!this.apiKey) {
4295
- throw new ConfigError(
4296
- "API key (mr_pk_* or mr_sk_*) required for tier operations"
4297
- );
4298
- }
4299
- }
4300
- ensureSecretKey() {
4301
- if (!this.apiKey || !this.hasSecretKey) {
4302
- throw new ConfigError(
4303
- "Secret key (mr_sk_*) required for checkout operations"
4304
- );
4305
- }
4306
- }
4307
- /**
4308
- * List all tiers in the project.
4309
- */
4310
- async list() {
4311
- this.ensureApiKey();
4312
- const response = await this.http.json("/tiers", {
4313
- method: "GET",
4314
- apiKey: this.apiKey
4315
- });
4316
- return response.tiers;
4317
- }
4318
- /**
4319
- * Get a tier by ID.
4320
- */
4321
- async get(tierId) {
4322
- this.ensureApiKey();
4323
- if (!tierId?.trim()) {
4324
- throw new ConfigError("tierId is required");
4325
- }
4326
- const response = await this.http.json(`/tiers/${tierId}`, {
4327
- method: "GET",
4328
- apiKey: this.apiKey
4329
- });
4330
- return response.tier;
4331
- }
4332
- /**
4333
- * Create a Stripe checkout session for a tier (Stripe-first flow).
4334
- *
4335
- * This enables users to subscribe before authenticating. Stripe collects
4336
- * the customer's email during checkout. After checkout completes, a
4337
- * customer record is created with the email from Stripe. The customer
4338
- * can later be linked to an identity via POST /customers/claim.
4339
- *
4340
- * Requires a secret key (mr_sk_*).
4341
- *
4342
- * @param tierId - The tier ID to create a checkout session for
4343
- * @param request - Checkout session request with redirect URLs
4344
- * @returns Checkout session with Stripe URL
4345
- */
4346
- async checkout(tierId, request) {
4347
- this.ensureSecretKey();
4348
- if (!tierId?.trim()) {
4349
- throw new ConfigError("tierId is required");
4350
- }
4351
- if (!request.success_url?.trim()) {
4352
- throw new ConfigError("success_url is required");
4353
- }
4354
- if (!request.cancel_url?.trim()) {
4355
- throw new ConfigError("cancel_url is required");
4356
- }
4357
- return await this.http.json(
4358
- `/tiers/${tierId}/checkout`,
4359
- {
4360
- method: "POST",
4361
- apiKey: this.apiKey,
4362
- body: request
4363
- }
4364
- );
3887
+ return {
3888
+ ...out,
3889
+ run_id: parseRunId(out.run_id),
3890
+ pending: out.pending.map((p) => ({
3891
+ ...p,
3892
+ node_id: parseNodeId(p.node_id),
3893
+ tool_calls: p.tool_calls
3894
+ }))
3895
+ };
4365
3896
  }
4366
3897
  };
4367
3898
 
4368
- // src/models.ts
4369
- var ModelsClient = class {
4370
- constructor(http) {
3899
+ // src/workflows_request.ts
3900
+ var WORKFLOWS_COMPILE_PATH = "/workflows/compile";
3901
+
3902
+ // src/workflows_client.ts
3903
+ var WorkflowsClient = class {
3904
+ constructor(http, auth, cfg = {}) {
4371
3905
  this.http = http;
3906
+ this.auth = auth;
3907
+ this.metrics = cfg.metrics;
3908
+ this.trace = cfg.trace;
4372
3909
  }
4373
- /**
4374
- * List active models with rich metadata.
4375
- */
4376
- async list(params = {}) {
4377
- const qs = new URLSearchParams();
4378
- if (params.provider?.trim()) {
4379
- qs.set("provider", params.provider.trim());
3910
+ async compileV0(spec, options = {}) {
3911
+ const metrics = mergeMetrics(this.metrics, options.metrics);
3912
+ const trace = mergeTrace(this.trace, options.trace);
3913
+ const authHeaders = await this.auth.authForResponses();
3914
+ const headers = { ...options.headers || {} };
3915
+ const customerId = options.customerId?.trim();
3916
+ if (customerId) {
3917
+ headers[CUSTOMER_ID_HEADER] = customerId;
3918
+ }
3919
+ try {
3920
+ const out = await this.http.json(
3921
+ WORKFLOWS_COMPILE_PATH,
3922
+ {
3923
+ method: "POST",
3924
+ headers,
3925
+ body: spec,
3926
+ signal: options.signal,
3927
+ apiKey: authHeaders.apiKey,
3928
+ accessToken: authHeaders.accessToken,
3929
+ timeoutMs: options.timeoutMs,
3930
+ connectTimeoutMs: options.connectTimeoutMs,
3931
+ retry: options.retry,
3932
+ metrics,
3933
+ trace,
3934
+ context: { method: "POST", path: WORKFLOWS_COMPILE_PATH }
3935
+ }
3936
+ );
3937
+ return {
3938
+ ok: true,
3939
+ plan_json: out.plan_json,
3940
+ plan_hash: parsePlanHash(out.plan_hash)
3941
+ };
3942
+ } catch (err) {
3943
+ if (err instanceof WorkflowValidationError) {
3944
+ return { ok: false, error_type: "validation_error", issues: err.issues };
3945
+ }
3946
+ if (err instanceof APIError) {
3947
+ return {
3948
+ ok: false,
3949
+ error_type: "internal_error",
3950
+ status: err.status ?? 0,
3951
+ message: err.message,
3952
+ code: err.code,
3953
+ requestId: err.requestId
3954
+ };
3955
+ }
3956
+ if (err instanceof ModelRelayError && err.category === "api") {
3957
+ return {
3958
+ ok: false,
3959
+ error_type: "internal_error",
3960
+ status: err.status ?? 0,
3961
+ message: err.message,
3962
+ code: err.code,
3963
+ requestId: err.requestId
3964
+ };
3965
+ }
3966
+ throw err;
4380
3967
  }
4381
- if (params.capability) {
4382
- qs.set("capability", params.capability);
3968
+ }
3969
+ async compileV1(spec, options = {}) {
3970
+ const metrics = mergeMetrics(this.metrics, options.metrics);
3971
+ const trace = mergeTrace(this.trace, options.trace);
3972
+ const authHeaders = await this.auth.authForResponses();
3973
+ const headers = { ...options.headers || {} };
3974
+ const customerId = options.customerId?.trim();
3975
+ if (customerId) {
3976
+ headers[CUSTOMER_ID_HEADER] = customerId;
3977
+ }
3978
+ try {
3979
+ const out = await this.http.json(
3980
+ WORKFLOWS_COMPILE_PATH,
3981
+ {
3982
+ method: "POST",
3983
+ headers,
3984
+ body: spec,
3985
+ signal: options.signal,
3986
+ apiKey: authHeaders.apiKey,
3987
+ accessToken: authHeaders.accessToken,
3988
+ timeoutMs: options.timeoutMs,
3989
+ connectTimeoutMs: options.connectTimeoutMs,
3990
+ retry: options.retry,
3991
+ metrics,
3992
+ trace,
3993
+ context: { method: "POST", path: WORKFLOWS_COMPILE_PATH }
3994
+ }
3995
+ );
3996
+ return {
3997
+ ok: true,
3998
+ plan_json: out.plan_json,
3999
+ plan_hash: parsePlanHash(out.plan_hash)
4000
+ };
4001
+ } catch (err) {
4002
+ if (err instanceof WorkflowValidationError) {
4003
+ return { ok: false, error_type: "validation_error", issues: err.issues };
4004
+ }
4005
+ if (err instanceof APIError) {
4006
+ return {
4007
+ ok: false,
4008
+ error_type: "internal_error",
4009
+ status: err.status ?? 0,
4010
+ message: err.message,
4011
+ code: err.code,
4012
+ requestId: err.requestId
4013
+ };
4014
+ }
4015
+ if (err instanceof ModelRelayError && err.category === "api") {
4016
+ return {
4017
+ ok: false,
4018
+ error_type: "internal_error",
4019
+ status: err.status ?? 0,
4020
+ message: err.message,
4021
+ code: err.code,
4022
+ requestId: err.requestId
4023
+ };
4024
+ }
4025
+ throw err;
4383
4026
  }
4384
- const path = qs.toString() ? `/models?${qs.toString()}` : "/models";
4385
- const resp = await this.http.json(path, { method: "GET" });
4386
- return resp.models;
4387
4027
  }
4388
4028
  };
4389
4029
 
@@ -4683,8 +4323,8 @@ function getModelContextCacheEntry(client) {
4683
4323
  async function populateModelContextCache(client, entry) {
4684
4324
  if (!entry.listPromise) {
4685
4325
  entry.listPromise = (async () => {
4686
- const models = await client.models.list();
4687
- for (const model of models) {
4326
+ const response = await client.http.json("/models");
4327
+ for (const model of response.models) {
4688
4328
  entry.byId.set(String(model.model_id), {
4689
4329
  contextWindow: model.context_window,
4690
4330
  maxOutputTokens: model.max_output_tokens
@@ -5828,6 +5468,94 @@ var SessionsClient = class {
5828
5468
  }
5829
5469
  };
5830
5470
 
5471
+ // src/tiers.ts
5472
+ function defaultTierModelId(tier) {
5473
+ const def = tier.models.find((m) => m.is_default);
5474
+ if (def) return def.model_id;
5475
+ if (tier.models.length === 1) return tier.models[0].model_id;
5476
+ return void 0;
5477
+ }
5478
+ var TiersClient = class {
5479
+ constructor(http, cfg) {
5480
+ this.http = http;
5481
+ this.apiKey = cfg.apiKey ? parseApiKey(cfg.apiKey) : void 0;
5482
+ this.hasSecretKey = this.apiKey ? isSecretKey(this.apiKey) : false;
5483
+ }
5484
+ ensureApiKey() {
5485
+ if (!this.apiKey) {
5486
+ throw new ConfigError(
5487
+ "API key (mr_pk_* or mr_sk_*) required for tier operations"
5488
+ );
5489
+ }
5490
+ }
5491
+ ensureSecretKey() {
5492
+ if (!this.apiKey || !this.hasSecretKey) {
5493
+ throw new ConfigError(
5494
+ "Secret key (mr_sk_*) required for checkout operations"
5495
+ );
5496
+ }
5497
+ }
5498
+ /**
5499
+ * List all tiers in the project.
5500
+ */
5501
+ async list() {
5502
+ this.ensureApiKey();
5503
+ const response = await this.http.json("/tiers", {
5504
+ method: "GET",
5505
+ apiKey: this.apiKey
5506
+ });
5507
+ return response.tiers;
5508
+ }
5509
+ /**
5510
+ * Get a tier by ID.
5511
+ */
5512
+ async get(tierId) {
5513
+ this.ensureApiKey();
5514
+ if (!tierId?.trim()) {
5515
+ throw new ConfigError("tierId is required");
5516
+ }
5517
+ const response = await this.http.json(`/tiers/${tierId}`, {
5518
+ method: "GET",
5519
+ apiKey: this.apiKey
5520
+ });
5521
+ return response.tier;
5522
+ }
5523
+ /**
5524
+ * Create a Stripe checkout session for a tier (Stripe-first flow).
5525
+ *
5526
+ * This enables users to subscribe before authenticating. Stripe collects
5527
+ * the customer's email during checkout. After checkout completes, a
5528
+ * customer record is created with the email from Stripe. The customer
5529
+ * can later be linked to an identity via POST /customers/claim.
5530
+ *
5531
+ * Requires a secret key (mr_sk_*).
5532
+ *
5533
+ * @param tierId - The tier ID to create a checkout session for
5534
+ * @param request - Checkout session request with redirect URLs
5535
+ * @returns Checkout session with Stripe URL
5536
+ */
5537
+ async checkout(tierId, request) {
5538
+ this.ensureSecretKey();
5539
+ if (!tierId?.trim()) {
5540
+ throw new ConfigError("tierId is required");
5541
+ }
5542
+ if (!request.success_url?.trim()) {
5543
+ throw new ConfigError("success_url is required");
5544
+ }
5545
+ if (!request.cancel_url?.trim()) {
5546
+ throw new ConfigError("cancel_url is required");
5547
+ }
5548
+ return await this.http.json(
5549
+ `/tiers/${tierId}/checkout`,
5550
+ {
5551
+ method: "POST",
5552
+ apiKey: this.apiKey,
5553
+ body: request
5554
+ }
5555
+ );
5556
+ }
5557
+ };
5558
+
5831
5559
  // src/http.ts
5832
5560
  var HTTPClient = class {
5833
5561
  constructor(cfg) {
@@ -9403,10 +9131,8 @@ var ModelRelay = class _ModelRelay {
9403
9131
  trace: cfg.trace
9404
9132
  });
9405
9133
  this.images = new ImagesClient(this.http, auth);
9406
- this.customers = new CustomersClient(this.http, { apiKey, accessToken, tokenProvider });
9407
- this.tiers = new TiersClient(this.http, { apiKey });
9408
- this.models = new ModelsClient(this.http);
9409
9134
  this.sessions = new SessionsClient(this, this.http, auth);
9135
+ this.tiers = new TiersClient(this.http, { apiKey });
9410
9136
  }
9411
9137
  forCustomer(customerId) {
9412
9138
  return new CustomerScopedModelRelay(this.responses, customerId, this.baseUrl);
@@ -9429,7 +9155,6 @@ function resolveBaseUrl(override) {
9429
9155
  CustomerResponsesClient,
9430
9156
  CustomerScopedModelRelay,
9431
9157
  CustomerTokenProvider,
9432
- CustomersClient,
9433
9158
  DEFAULT_BASE_URL,
9434
9159
  DEFAULT_CLIENT_HEADER,
9435
9160
  DEFAULT_CONNECT_TIMEOUT_MS,
@@ -9465,7 +9190,6 @@ function resolveBaseUrl(override) {
9465
9190
  MessageRoles,
9466
9191
  ModelRelay,
9467
9192
  ModelRelayError,
9468
- ModelsClient,
9469
9193
  OIDCExchangeTokenProvider,
9470
9194
  OutputFormatTypes,
9471
9195
  OutputItemTypes,
@@ -9528,6 +9252,7 @@ function resolveBaseUrl(override) {
9528
9252
  createUserMessage,
9529
9253
  createWebTool,
9530
9254
  defaultRetryHandler,
9255
+ defaultTierModelId,
9531
9256
  executeWithRetry,
9532
9257
  firstToolCall,
9533
9258
  formatToolErrorForModel,