@modelrelay/sdk 1.29.0 → 1.36.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.js CHANGED
@@ -28,7 +28,6 @@ import {
28
28
  TransportError,
29
29
  WebToolIntents,
30
30
  WorkflowValidationError,
31
- __export,
32
31
  asModelId,
33
32
  asProviderId,
34
33
  asTierCode,
@@ -70,7 +69,10 @@ import {
70
69
  toolResultMessage,
71
70
  tryParseToolArgs,
72
71
  zodToJsonSchema
73
- } from "./chunk-CV3DTA6P.js";
72
+ } from "./chunk-ADQ74R7T.js";
73
+ import {
74
+ __export
75
+ } from "./chunk-MLKGABMK.js";
74
76
 
75
77
  // src/api_keys.ts
76
78
  var PUBLISHABLE_PREFIX = "mr_pk_";
@@ -298,7 +300,7 @@ var AuthClient = class {
298
300
  projectId: apiResp.project_id,
299
301
  customerId: apiResp.customer_id,
300
302
  customerExternalId: apiResp.customer_external_id,
301
- tierCode: apiResp.tier_code
303
+ tierCode: apiResp.tier_code ? asTierCode(apiResp.tier_code) : void 0
302
304
  };
303
305
  }
304
306
  /**
@@ -330,7 +332,7 @@ var AuthClient = class {
330
332
  projectId: apiResp.project_id,
331
333
  customerId: apiResp.customer_id,
332
334
  customerExternalId: apiResp.customer_external_id,
333
- tierCode: apiResp.tier_code
335
+ tierCode: apiResp.tier_code ? asTierCode(apiResp.tier_code) : void 0
334
336
  };
335
337
  }
336
338
  /**
@@ -442,7 +444,7 @@ var AuthClient = class {
442
444
  projectId: apiResp.project_id,
443
445
  customerId: apiResp.customer_id,
444
446
  customerExternalId: apiResp.customer_external_id,
445
- tierCode: apiResp.tier_code
447
+ tierCode: apiResp.tier_code ? asTierCode(apiResp.tier_code) : void 0
446
448
  }
447
449
  };
448
450
  } catch (err) {
@@ -2779,370 +2781,6 @@ var WorkflowsClient = class {
2779
2781
  }
2780
2782
  };
2781
2783
 
2782
- // src/customers.ts
2783
- var EMAIL_REGEX = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
2784
- function isValidEmail(email) {
2785
- return EMAIL_REGEX.test(email);
2786
- }
2787
- var CustomersClient = class {
2788
- constructor(http, cfg) {
2789
- this.http = http;
2790
- this.apiKey = cfg.apiKey ? parseApiKey(cfg.apiKey) : void 0;
2791
- this.hasSecretKey = this.apiKey ? isSecretKey(this.apiKey) : false;
2792
- this.accessToken = cfg.accessToken;
2793
- this.tokenProvider = cfg.tokenProvider;
2794
- }
2795
- ensureSecretKey() {
2796
- if (!this.apiKey || !this.hasSecretKey) {
2797
- throw new ConfigError(
2798
- "Secret key (mr_sk_*) required for customer operations"
2799
- );
2800
- }
2801
- }
2802
- ensureApiKey() {
2803
- if (!this.apiKey) {
2804
- throw new ConfigError(
2805
- "API key (mr_pk_* or mr_sk_*) required for claim operation"
2806
- );
2807
- }
2808
- }
2809
- async customerAccessToken() {
2810
- if (this.accessToken?.trim()) {
2811
- return this.accessToken.trim();
2812
- }
2813
- if (this.tokenProvider) {
2814
- const token = (await this.tokenProvider.getToken())?.trim();
2815
- if (!token) {
2816
- throw new ConfigError("tokenProvider returned an empty token");
2817
- }
2818
- return token;
2819
- }
2820
- throw new ConfigError("Access token or tokenProvider required for customers.me()");
2821
- }
2822
- /**
2823
- * Get the authenticated customer from a customer-scoped bearer token.
2824
- *
2825
- * This endpoint requires a customer bearer token. API keys are not accepted.
2826
- */
2827
- async me() {
2828
- const token = await this.customerAccessToken();
2829
- const response = await this.http.json("/customers/me", {
2830
- method: "GET",
2831
- accessToken: token
2832
- });
2833
- if (!response.customer) {
2834
- throw new ConfigError("missing customer in response");
2835
- }
2836
- return response.customer;
2837
- }
2838
- /**
2839
- * Get the authenticated customer's subscription details.
2840
- *
2841
- * This endpoint requires a customer bearer token. API keys are not accepted.
2842
- */
2843
- async meSubscription() {
2844
- const token = await this.customerAccessToken();
2845
- const response = await this.http.json("/customers/me/subscription", {
2846
- method: "GET",
2847
- accessToken: token
2848
- });
2849
- if (!response.subscription) {
2850
- throw new ConfigError("missing subscription in response");
2851
- }
2852
- return response.subscription;
2853
- }
2854
- /**
2855
- * Get the authenticated customer's usage metrics for the current billing window.
2856
- *
2857
- * This endpoint requires a customer bearer token. API keys are not accepted.
2858
- */
2859
- async meUsage() {
2860
- const token = await this.customerAccessToken();
2861
- const response = await this.http.json("/customers/me/usage", {
2862
- method: "GET",
2863
- accessToken: token
2864
- });
2865
- if (!response.usage) {
2866
- throw new ConfigError("missing usage in response");
2867
- }
2868
- return response.usage;
2869
- }
2870
- /**
2871
- * List all customers in the project.
2872
- */
2873
- async list() {
2874
- this.ensureSecretKey();
2875
- const response = await this.http.json("/customers", {
2876
- method: "GET",
2877
- apiKey: this.apiKey
2878
- });
2879
- return response.customers;
2880
- }
2881
- /**
2882
- * Create a new customer in the project.
2883
- */
2884
- async create(request) {
2885
- this.ensureSecretKey();
2886
- if (!request.external_id?.trim()) {
2887
- throw new ConfigError("external_id is required");
2888
- }
2889
- if (!request.email?.trim()) {
2890
- throw new ConfigError("email is required");
2891
- }
2892
- if (!isValidEmail(request.email)) {
2893
- throw new ConfigError("invalid email format");
2894
- }
2895
- const response = await this.http.json("/customers", {
2896
- method: "POST",
2897
- body: request,
2898
- apiKey: this.apiKey
2899
- });
2900
- return response.customer;
2901
- }
2902
- /**
2903
- * Get a customer by ID.
2904
- */
2905
- async get(customerId) {
2906
- this.ensureSecretKey();
2907
- if (!customerId?.trim()) {
2908
- throw new ConfigError("customerId is required");
2909
- }
2910
- const response = await this.http.json(
2911
- `/customers/${customerId}`,
2912
- {
2913
- method: "GET",
2914
- apiKey: this.apiKey
2915
- }
2916
- );
2917
- return response.customer;
2918
- }
2919
- /**
2920
- * Upsert a customer by external_id.
2921
- * If a customer with the given external_id exists, it is updated.
2922
- * Otherwise, a new customer is created.
2923
- */
2924
- async upsert(request) {
2925
- this.ensureSecretKey();
2926
- if (!request.external_id?.trim()) {
2927
- throw new ConfigError("external_id is required");
2928
- }
2929
- if (!request.email?.trim()) {
2930
- throw new ConfigError("email is required");
2931
- }
2932
- if (!isValidEmail(request.email)) {
2933
- throw new ConfigError("invalid email format");
2934
- }
2935
- const response = await this.http.json("/customers", {
2936
- method: "PUT",
2937
- body: request,
2938
- apiKey: this.apiKey
2939
- });
2940
- return response.customer;
2941
- }
2942
- /**
2943
- * Link a customer identity (provider + subject) to a customer found by email.
2944
- * Used when a customer subscribes via Stripe Checkout (email only) and later authenticates to the app.
2945
- *
2946
- * This is a user self-service operation that works with publishable keys,
2947
- * allowing CLI tools and frontends to link subscriptions to user identities.
2948
- *
2949
- * Works with both publishable keys (mr_pk_*) and secret keys (mr_sk_*).
2950
- *
2951
- * @throws {APIError} with status 404 if customer not found by email
2952
- * @throws {APIError} with status 409 if the identity is already linked to a different customer
2953
- */
2954
- async claim(request) {
2955
- this.ensureApiKey();
2956
- if (!request.email?.trim()) {
2957
- throw new ConfigError("email is required");
2958
- }
2959
- if (!isValidEmail(request.email)) {
2960
- throw new ConfigError("invalid email format");
2961
- }
2962
- if (!request.provider?.trim()) {
2963
- throw new ConfigError("provider is required");
2964
- }
2965
- if (!request.subject?.trim()) {
2966
- throw new ConfigError("subject is required");
2967
- }
2968
- await this.http.request("/customers/claim", {
2969
- method: "POST",
2970
- body: request,
2971
- apiKey: this.apiKey
2972
- });
2973
- }
2974
- /**
2975
- * Delete a customer by ID.
2976
- */
2977
- async delete(customerId) {
2978
- this.ensureSecretKey();
2979
- if (!customerId?.trim()) {
2980
- throw new ConfigError("customerId is required");
2981
- }
2982
- await this.http.request(`/customers/${customerId}`, {
2983
- method: "DELETE",
2984
- apiKey: this.apiKey
2985
- });
2986
- }
2987
- /**
2988
- * Create a Stripe checkout session for a customer subscription.
2989
- */
2990
- async subscribe(customerId, request) {
2991
- this.ensureSecretKey();
2992
- if (!customerId?.trim()) {
2993
- throw new ConfigError("customerId is required");
2994
- }
2995
- if (!request.tier_id?.trim()) {
2996
- throw new ConfigError("tier_id is required");
2997
- }
2998
- if (!request.success_url?.trim() || !request.cancel_url?.trim()) {
2999
- throw new ConfigError("success_url and cancel_url are required");
3000
- }
3001
- return await this.http.json(
3002
- `/customers/${customerId}/subscribe`,
3003
- {
3004
- method: "POST",
3005
- body: request,
3006
- apiKey: this.apiKey
3007
- }
3008
- );
3009
- }
3010
- /**
3011
- * Get the subscription details for a customer.
3012
- */
3013
- async getSubscription(customerId) {
3014
- this.ensureSecretKey();
3015
- if (!customerId?.trim()) {
3016
- throw new ConfigError("customerId is required");
3017
- }
3018
- const response = await this.http.json(
3019
- `/customers/${customerId}/subscription`,
3020
- {
3021
- method: "GET",
3022
- apiKey: this.apiKey
3023
- }
3024
- );
3025
- return response.subscription;
3026
- }
3027
- /**
3028
- * Cancel a customer's subscription at period end.
3029
- */
3030
- async unsubscribe(customerId) {
3031
- this.ensureSecretKey();
3032
- if (!customerId?.trim()) {
3033
- throw new ConfigError("customerId is required");
3034
- }
3035
- await this.http.request(`/customers/${customerId}/subscription`, {
3036
- method: "DELETE",
3037
- apiKey: this.apiKey
3038
- });
3039
- }
3040
- };
3041
-
3042
- // src/tiers.ts
3043
- var TiersClient = class {
3044
- constructor(http, cfg) {
3045
- this.http = http;
3046
- this.apiKey = cfg.apiKey ? parseApiKey(cfg.apiKey) : void 0;
3047
- this.hasSecretKey = this.apiKey ? isSecretKey(this.apiKey) : false;
3048
- }
3049
- ensureApiKey() {
3050
- if (!this.apiKey) {
3051
- throw new ConfigError(
3052
- "API key (mr_pk_* or mr_sk_*) required for tier operations"
3053
- );
3054
- }
3055
- }
3056
- ensureSecretKey() {
3057
- if (!this.apiKey || !this.hasSecretKey) {
3058
- throw new ConfigError(
3059
- "Secret key (mr_sk_*) required for checkout operations"
3060
- );
3061
- }
3062
- }
3063
- /**
3064
- * List all tiers in the project.
3065
- */
3066
- async list() {
3067
- this.ensureApiKey();
3068
- const response = await this.http.json("/tiers", {
3069
- method: "GET",
3070
- apiKey: this.apiKey
3071
- });
3072
- return response.tiers;
3073
- }
3074
- /**
3075
- * Get a tier by ID.
3076
- */
3077
- async get(tierId) {
3078
- this.ensureApiKey();
3079
- if (!tierId?.trim()) {
3080
- throw new ConfigError("tierId is required");
3081
- }
3082
- const response = await this.http.json(`/tiers/${tierId}`, {
3083
- method: "GET",
3084
- apiKey: this.apiKey
3085
- });
3086
- return response.tier;
3087
- }
3088
- /**
3089
- * Create a Stripe checkout session for a tier (Stripe-first flow).
3090
- *
3091
- * This enables users to subscribe before authenticating. Stripe collects
3092
- * the customer's email during checkout. After checkout completes, a
3093
- * customer record is created with the email from Stripe. The customer
3094
- * can later be linked to an identity via POST /customers/claim.
3095
- *
3096
- * Requires a secret key (mr_sk_*).
3097
- *
3098
- * @param tierId - The tier ID to create a checkout session for
3099
- * @param request - Checkout session request with redirect URLs
3100
- * @returns Checkout session with Stripe URL
3101
- */
3102
- async checkout(tierId, request) {
3103
- this.ensureSecretKey();
3104
- if (!tierId?.trim()) {
3105
- throw new ConfigError("tierId is required");
3106
- }
3107
- if (!request.success_url?.trim()) {
3108
- throw new ConfigError("success_url is required");
3109
- }
3110
- if (!request.cancel_url?.trim()) {
3111
- throw new ConfigError("cancel_url is required");
3112
- }
3113
- return await this.http.json(
3114
- `/tiers/${tierId}/checkout`,
3115
- {
3116
- method: "POST",
3117
- apiKey: this.apiKey,
3118
- body: request
3119
- }
3120
- );
3121
- }
3122
- };
3123
-
3124
- // src/models.ts
3125
- var ModelsClient = class {
3126
- constructor(http) {
3127
- this.http = http;
3128
- }
3129
- /**
3130
- * List active models with rich metadata.
3131
- */
3132
- async list(params = {}) {
3133
- const qs = new URLSearchParams();
3134
- if (params.provider?.trim()) {
3135
- qs.set("provider", params.provider.trim());
3136
- }
3137
- if (params.capability) {
3138
- qs.set("capability", params.capability);
3139
- }
3140
- const path = qs.toString() ? `/models?${qs.toString()}` : "/models";
3141
- const resp = await this.http.json(path, { method: "GET" });
3142
- return resp.models;
3143
- }
3144
- };
3145
-
3146
2784
  // src/images.ts
3147
2785
  var IMAGES_PATH = "/images/generate";
3148
2786
  var ImagesClient = class {
@@ -3439,8 +3077,8 @@ function getModelContextCacheEntry(client) {
3439
3077
  async function populateModelContextCache(client, entry) {
3440
3078
  if (!entry.listPromise) {
3441
3079
  entry.listPromise = (async () => {
3442
- const models = await client.models.list();
3443
- for (const model of models) {
3080
+ const response = await client.http.json("/models");
3081
+ for (const model of response.models) {
3444
3082
  entry.byId.set(String(model.model_id), {
3445
3083
  contextWindow: model.context_window,
3446
3084
  maxOutputTokens: model.max_output_tokens
@@ -8159,9 +7797,6 @@ var ModelRelay = class _ModelRelay {
8159
7797
  trace: cfg.trace
8160
7798
  });
8161
7799
  this.images = new ImagesClient(this.http, auth);
8162
- this.customers = new CustomersClient(this.http, { apiKey, accessToken, tokenProvider });
8163
- this.tiers = new TiersClient(this.http, { apiKey });
8164
- this.models = new ModelsClient(this.http);
8165
7800
  this.sessions = new SessionsClient(this, this.http, auth);
8166
7801
  }
8167
7802
  forCustomer(customerId) {
@@ -8184,7 +7819,6 @@ export {
8184
7819
  CustomerResponsesClient,
8185
7820
  CustomerScopedModelRelay,
8186
7821
  CustomerTokenProvider,
8187
- CustomersClient,
8188
7822
  DEFAULT_BASE_URL,
8189
7823
  DEFAULT_CLIENT_HEADER,
8190
7824
  DEFAULT_CONNECT_TIMEOUT_MS,
@@ -8220,7 +7854,6 @@ export {
8220
7854
  MessageRoles,
8221
7855
  ModelRelay,
8222
7856
  ModelRelayError,
8223
- ModelsClient,
8224
7857
  OIDCExchangeTokenProvider,
8225
7858
  OutputFormatTypes,
8226
7859
  OutputItemTypes,
@@ -8240,7 +7873,6 @@ export {
8240
7873
  StructuredExhaustedError,
8241
7874
  StructuredJSONStream,
8242
7875
  SubscriptionStatuses,
8243
- TiersClient,
8244
7876
  ToolArgsError,
8245
7877
  ToolArgumentError,
8246
7878
  ToolCallAccumulator,
package/dist/node.cjs CHANGED
@@ -52,7 +52,7 @@ var import_child_process = require("child_process");
52
52
  // package.json
53
53
  var package_default = {
54
54
  name: "@modelrelay/sdk",
55
- version: "1.29.0",
55
+ version: "1.36.0",
56
56
  description: "TypeScript SDK for the ModelRelay API",
57
57
  type: "module",
58
58
  main: "dist/index.cjs",
@@ -64,6 +64,11 @@ var package_default = {
64
64
  import: "./dist/index.js",
65
65
  require: "./dist/index.cjs"
66
66
  },
67
+ "./billing": {
68
+ types: "./dist/billing/index.d.ts",
69
+ import: "./dist/billing/index.js",
70
+ require: "./dist/billing/index.cjs"
71
+ },
67
72
  "./node": {
68
73
  types: "./dist/node.d.ts",
69
74
  import: "./dist/node.js",
@@ -77,8 +82,8 @@ var package_default = {
77
82
  "dist"
78
83
  ],
79
84
  scripts: {
80
- build: "tsup src/index.ts src/node.ts --format esm,cjs --dts --external playwright",
81
- dev: "tsup src/index.ts src/node.ts --format esm,cjs --dts --watch",
85
+ build: "tsup src/index.ts src/node.ts src/billing/index.ts --format esm,cjs --dts --external playwright",
86
+ dev: "tsup src/index.ts src/node.ts src/billing/index.ts --format esm,cjs --dts --watch",
82
87
  lint: "tsc --noEmit --project tsconfig.lint.json",
83
88
  test: "vitest run",
84
89
  "generate:types": "openapi-typescript ../../api/openapi/api.json -o src/generated/api.ts"
@@ -93,7 +98,7 @@ var package_default = {
93
98
  license: "Apache-2.0",
94
99
  dependencies: {
95
100
  "fast-json-patch": "^3.1.1",
96
- zod: "^3.23.0"
101
+ zod: "^3.25.76"
97
102
  },
98
103
  peerDependencies: {
99
104
  playwright: ">=1.40.0"
@@ -105,11 +110,11 @@ var package_default = {
105
110
  },
106
111
  devDependencies: {
107
112
  "@types/node": "^25.0.3",
108
- "openapi-typescript": "^7.4.4",
109
- playwright: "^1.49.0",
110
- tsup: "^8.2.4",
111
- typescript: "^5.6.3",
112
- vitest: "^2.1.4"
113
+ "openapi-typescript": "^7.10.1",
114
+ playwright: "^1.57.0",
115
+ tsup: "^8.5.1",
116
+ typescript: "^5.9.3",
117
+ vitest: "^2.1.9"
113
118
  }
114
119
  };
115
120
 
package/dist/node.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { k as Tool, u as ToolRegistry } from './tools-Db-F5rIL.cjs';
1
+ import { k as Tool, r as ToolRegistry } from './tools-Cnl2MgVa.cjs';
2
2
 
3
3
  /**
4
4
  * Local filesystem tool pack for client-side tool execution.
package/dist/node.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { k as Tool, u as ToolRegistry } from './tools-Db-F5rIL.js';
1
+ import { k as Tool, r as ToolRegistry } from './tools-Cnl2MgVa.js';
2
2
 
3
3
  /**
4
4
  * Local filesystem tool pack for client-side tool execution.
package/dist/node.js CHANGED
@@ -3,7 +3,8 @@ import {
3
3
  ToolArgumentError,
4
4
  ToolRegistry,
5
5
  ToolTypes
6
- } from "./chunk-CV3DTA6P.js";
6
+ } from "./chunk-ADQ74R7T.js";
7
+ import "./chunk-MLKGABMK.js";
7
8
 
8
9
  // src/tools_local_fs.ts
9
10
  import { promises as fs } from "fs";