@modelrelay/sdk 0.20.0 → 0.21.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
@@ -100,7 +100,9 @@ var ErrorCodes = {
100
100
  /** No tiers configured for the project - create a tier first. */
101
101
  NO_TIERS: "NO_TIERS",
102
102
  /** No free tier available for auto-provisioning - create a free tier or use checkout flow. */
103
- NO_FREE_TIER: "NO_FREE_TIER"
103
+ NO_FREE_TIER: "NO_FREE_TIER",
104
+ /** Email required for auto-provisioning a new customer. */
105
+ EMAIL_REQUIRED: "EMAIL_REQUIRED"
104
106
  };
105
107
  var ModelRelayError = class extends Error {
106
108
  constructor(message, opts) {
@@ -185,12 +187,19 @@ var APIError = class extends ModelRelayError {
185
187
  return this.code === ErrorCodes.NO_FREE_TIER;
186
188
  }
187
189
  /**
188
- * Returns true if this is a customer provisioning error (NO_TIERS or NO_FREE_TIER).
190
+ * Returns true if email is required for auto-provisioning a new customer.
191
+ * To resolve: provide the 'email' field in FrontendTokenRequest.
192
+ */
193
+ isEmailRequired() {
194
+ return this.code === ErrorCodes.EMAIL_REQUIRED;
195
+ }
196
+ /**
197
+ * Returns true if this is a customer provisioning error (NO_TIERS, NO_FREE_TIER, or EMAIL_REQUIRED).
189
198
  * These errors occur when calling frontendToken() with a customer that doesn't exist
190
199
  * and automatic provisioning cannot complete.
191
200
  */
192
201
  isProvisioningError() {
193
- return this.isNoTiers() || this.isNoFreeTier();
202
+ return this.isNoTiers() || this.isNoFreeTier() || this.isEmailRequired();
194
203
  }
195
204
  };
196
205
  async function parseErrorResponse(response, retries) {
@@ -261,20 +270,47 @@ var AuthClient = class {
261
270
  this.customer = cfg.customer;
262
271
  }
263
272
  /**
264
- * Exchange a publishable key for a short-lived frontend token.
273
+ * Exchange a publishable key for a short-lived frontend token for an existing customer.
265
274
  * Tokens are cached until they are close to expiry.
275
+ *
276
+ * Use this method when the customer already exists in the system.
277
+ * For auto-provisioning new customers, use frontendTokenAutoProvision instead.
266
278
  */
267
279
  async frontendToken(request) {
268
- const publishableKey = request?.publishableKey || (isPublishableKey(this.apiKey) ? this.apiKey : void 0);
269
- if (!publishableKey) {
270
- throw new ConfigError("publishable key required to issue frontend tokens");
280
+ if (!request.publishableKey?.trim()) {
281
+ throw new ConfigError("publishableKey is required");
282
+ }
283
+ if (!request.customerId?.trim()) {
284
+ throw new ConfigError("customerId is required");
285
+ }
286
+ return this.sendFrontendTokenRequest(request);
287
+ }
288
+ /**
289
+ * Exchange a publishable key for a frontend token, creating the customer if needed.
290
+ * The customer will be auto-provisioned on the project's free tier.
291
+ * Tokens are cached until they are close to expiry.
292
+ *
293
+ * Use this method when the customer may not exist and should be created automatically.
294
+ * The email is required for auto-provisioning.
295
+ */
296
+ async frontendTokenAutoProvision(request) {
297
+ if (!request.publishableKey?.trim()) {
298
+ throw new ConfigError("publishableKey is required");
271
299
  }
272
- const customerId = request?.customerId || this.customer?.id;
273
- if (!customerId) {
274
- throw new ConfigError("customerId is required to mint a frontend token");
300
+ if (!request.customerId?.trim()) {
301
+ throw new ConfigError("customerId is required");
302
+ }
303
+ if (!request.email?.trim()) {
304
+ throw new ConfigError("email is required for auto-provisioning");
275
305
  }
276
- const deviceId = request?.deviceId || this.customer?.deviceId;
277
- const ttlSeconds = request?.ttlSeconds ?? this.customer?.ttlSeconds;
306
+ return this.sendFrontendTokenRequest(request);
307
+ }
308
+ /**
309
+ * Internal method to send frontend token requests.
310
+ */
311
+ async sendFrontendTokenRequest(request) {
312
+ const { publishableKey, customerId, deviceId, ttlSeconds } = request;
313
+ const email = "email" in request ? request.email : void 0;
278
314
  const cacheKey = `${publishableKey}:${customerId}:${deviceId || ""}`;
279
315
  const cached = this.cachedFrontend.get(cacheKey);
280
316
  if (cached && isTokenReusable(cached)) {
@@ -290,6 +326,9 @@ var AuthClient = class {
290
326
  if (typeof ttlSeconds === "number" && ttlSeconds > 0) {
291
327
  payload.ttl_seconds = ttlSeconds;
292
328
  }
329
+ if (email) {
330
+ payload.email = email;
331
+ }
293
332
  const response = await this.http.json(
294
333
  "/auth/frontend-token",
295
334
  {
@@ -317,10 +356,15 @@ var AuthClient = class {
317
356
  throw new ConfigError("API key or token is required");
318
357
  }
319
358
  if (isPublishableKey(this.apiKey)) {
359
+ const resolvedCustomerId = customerId || overrides?.id || this.customer?.id;
360
+ if (!resolvedCustomerId) {
361
+ throw new ConfigError("customerId is required to mint a frontend token");
362
+ }
320
363
  const token = await this.frontendToken({
321
- customerId: customerId || overrides?.id,
322
- deviceId: overrides?.deviceId,
323
- ttlSeconds: overrides?.ttlSeconds
364
+ publishableKey: this.apiKey,
365
+ customerId: resolvedCustomerId,
366
+ deviceId: overrides?.deviceId || this.customer?.deviceId,
367
+ ttlSeconds: overrides?.ttlSeconds ?? this.customer?.ttlSeconds
324
368
  });
325
369
  return createAccessTokenAuth(token.token);
326
370
  }
@@ -374,7 +418,7 @@ function isTokenReusable(token) {
374
418
  // package.json
375
419
  var package_default = {
376
420
  name: "@modelrelay/sdk",
377
- version: "0.20.0",
421
+ version: "0.21.0",
378
422
  description: "TypeScript SDK for the ModelRelay API",
379
423
  type: "module",
380
424
  main: "dist/index.cjs",
package/dist/index.d.cts CHANGED
@@ -180,10 +180,35 @@ interface FrontendCustomer {
180
180
  deviceId?: string;
181
181
  ttlSeconds?: number;
182
182
  }
183
+ /**
184
+ * Request for fetching a frontend token for an existing customer.
185
+ * Use this when the customer already exists in the system.
186
+ */
183
187
  interface FrontendTokenRequest {
184
- publishableKey?: string;
188
+ /** Publishable key (mr_pk_*) - required for authentication. */
189
+ publishableKey: string;
190
+ /** Customer identifier - required to issue a token for this customer. */
191
+ customerId: string;
192
+ /** Optional device identifier for tracking/rate limiting. */
193
+ deviceId?: string;
194
+ /** Optional TTL in seconds for the issued token. */
195
+ ttlSeconds?: number;
196
+ }
197
+ /**
198
+ * Request for fetching a frontend token with auto-provisioning.
199
+ * Use this when the customer may not exist and should be created on the free tier.
200
+ * The email is required for auto-provisioning.
201
+ */
202
+ interface FrontendTokenAutoProvisionRequest {
203
+ /** Publishable key (mr_pk_*) - required for authentication. */
204
+ publishableKey: string;
205
+ /** Customer identifier - required to issue a token for this customer. */
185
206
  customerId: string;
207
+ /** Email address - required for auto-provisioning a new customer. */
208
+ email: string;
209
+ /** Optional device identifier for tracking/rate limiting. */
186
210
  deviceId?: string;
211
+ /** Optional TTL in seconds for the issued token. */
187
212
  ttlSeconds?: number;
188
213
  }
189
214
  interface FrontendToken {
@@ -640,10 +665,26 @@ declare class AuthClient {
640
665
  private cachedFrontend;
641
666
  constructor(http: HTTPClient, cfg: AuthConfig);
642
667
  /**
643
- * Exchange a publishable key for a short-lived frontend token.
668
+ * Exchange a publishable key for a short-lived frontend token for an existing customer.
644
669
  * Tokens are cached until they are close to expiry.
670
+ *
671
+ * Use this method when the customer already exists in the system.
672
+ * For auto-provisioning new customers, use frontendTokenAutoProvision instead.
673
+ */
674
+ frontendToken(request: FrontendTokenRequest): Promise<FrontendToken>;
675
+ /**
676
+ * Exchange a publishable key for a frontend token, creating the customer if needed.
677
+ * The customer will be auto-provisioned on the project's free tier.
678
+ * Tokens are cached until they are close to expiry.
679
+ *
680
+ * Use this method when the customer may not exist and should be created automatically.
681
+ * The email is required for auto-provisioning.
645
682
  */
646
- frontendToken(request?: Partial<FrontendTokenRequest>): Promise<FrontendToken>;
683
+ frontendTokenAutoProvision(request: FrontendTokenAutoProvisionRequest): Promise<FrontendToken>;
684
+ /**
685
+ * Internal method to send frontend token requests.
686
+ */
687
+ private sendFrontendTokenRequest;
647
688
  /**
648
689
  * Determine the correct auth headers for chat completions.
649
690
  * Publishable keys are automatically exchanged for frontend tokens.
@@ -981,6 +1022,8 @@ declare const ErrorCodes: {
981
1022
  readonly NO_TIERS: "NO_TIERS";
982
1023
  /** No free tier available for auto-provisioning - create a free tier or use checkout flow. */
983
1024
  readonly NO_FREE_TIER: "NO_FREE_TIER";
1025
+ /** Email required for auto-provisioning a new customer. */
1026
+ readonly EMAIL_REQUIRED: "EMAIL_REQUIRED";
984
1027
  };
985
1028
  type ErrorCode = (typeof ErrorCodes)[keyof typeof ErrorCodes];
986
1029
  type ErrorCategory = "config" | "transport" | "api";
@@ -1048,7 +1091,12 @@ declare class APIError extends ModelRelayError {
1048
1091
  */
1049
1092
  isNoFreeTier(): boolean;
1050
1093
  /**
1051
- * Returns true if this is a customer provisioning error (NO_TIERS or NO_FREE_TIER).
1094
+ * Returns true if email is required for auto-provisioning a new customer.
1095
+ * To resolve: provide the 'email' field in FrontendTokenRequest.
1096
+ */
1097
+ isEmailRequired(): boolean;
1098
+ /**
1099
+ * Returns true if this is a customer provisioning error (NO_TIERS, NO_FREE_TIER, or EMAIL_REQUIRED).
1052
1100
  * These errors occur when calling frontendToken() with a customer that doesn't exist
1053
1101
  * and automatic provisioning cannot complete.
1054
1102
  */
@@ -1482,4 +1530,4 @@ declare class ModelRelay {
1482
1530
  constructor(options: ModelRelayOptions);
1483
1531
  }
1484
1532
 
1485
- export { type APIChatResponse, type APIChatUsage, type APICheckoutSession, type APICustomerRef, APIError, type APIFrontendToken, type APIKey, AuthClient, type AuthHeaders, ChatClient, type ChatCompletionCreateParams, type ChatCompletionEvent, type ChatCompletionResponse, ChatCompletionsStream, type ChatEventType, type ChatMessage, type CheckoutSession, type CheckoutSessionRequest, type CodeExecConfig, ConfigError, type Customer, type CustomerClaimRequest, type CustomerCreateRequest, type CustomerMetadata, type CustomerUpsertRequest, CustomersClient, DEFAULT_BASE_URL, DEFAULT_CLIENT_HEADER, DEFAULT_CONNECT_TIMEOUT_MS, DEFAULT_REQUEST_TIMEOUT_MS, type ErrorCategory, type ErrorCode, ErrorCodes, type FieldError, type FrontendCustomer, type FrontendToken, type FrontendTokenRequest, type FunctionCall, type FunctionCallDelta, type FunctionTool, type HttpRequestMetrics, type JsonSchemaOptions, type KnownStopReason, type MessageDeltaData, type MessageStartData, type MessageStopData, type MetricsCallbacks, type ModelId, ModelRelay, type ModelRelayBaseOptions, ModelRelayError, type ModelRelayKeyOptions, type ModelRelayOptions, type ModelRelayOptionsLegacy, type ModelRelayTokenOptions, type NonEmptyArray, type PriceInterval, type Project, type ProviderId, type RequestContext, type ResponseFormat, type ResponseFormatType, ResponseFormatTypes, type ResponseJSONSchemaFormat, type RetryConfig, type RetryMetadata, type RetryOptions, SDK_VERSION, type Schema, type StopReason, StopReasons, type StreamFirstTokenMetrics, type StructuredJSONEvent, type StructuredJSONRecordType, StructuredJSONStream, type SubscriptionStatus, type Tier, type TierCheckoutRequest, type TierCheckoutSession, TiersClient, type TokenUsageMetrics, type Tool, ToolArgsError, type ToolCall, ToolCallAccumulator, type ToolCallDelta, type ToolChoice, type ToolChoiceType, ToolChoiceTypes, type ToolExecutionResult, type ToolHandler, ToolRegistry, type ToolType, ToolTypes, type TraceCallbacks, TransportError, type TransportErrorKind, type Usage, type UsageSummary, type WebSearchConfig, type WebToolMode, WebToolModes, type XSearchConfig, type ZodLikeSchema, assistantMessageWithToolCalls, createAccessTokenAuth, createApiKeyAuth, createAssistantMessage, createFunctionCall, createFunctionTool, createFunctionToolFromSchema, createRetryMessages, createSystemMessage, createToolCall, createUsage, createUserMessage, createWebTool, executeWithRetry, firstToolCall, formatToolErrorForModel, getRetryableErrors, hasRetryableErrors, hasToolCalls, isPublishableKey, mergeMetrics, mergeTrace, modelToString, normalizeModelId, normalizeStopReason, parseErrorResponse, parseToolArgs, parseToolArgsRaw, respondToToolCall, stopReasonToString, toolChoiceAuto, toolChoiceNone, toolChoiceRequired, toolResultMessage, tryParseToolArgs, zodToJsonSchema };
1533
+ export { type APIChatResponse, type APIChatUsage, type APICheckoutSession, type APICustomerRef, APIError, type APIFrontendToken, type APIKey, AuthClient, type AuthHeaders, ChatClient, type ChatCompletionCreateParams, type ChatCompletionEvent, type ChatCompletionResponse, ChatCompletionsStream, type ChatEventType, type ChatMessage, type CheckoutSession, type CheckoutSessionRequest, type CodeExecConfig, ConfigError, type Customer, type CustomerClaimRequest, type CustomerCreateRequest, type CustomerMetadata, type CustomerUpsertRequest, CustomersClient, DEFAULT_BASE_URL, DEFAULT_CLIENT_HEADER, DEFAULT_CONNECT_TIMEOUT_MS, DEFAULT_REQUEST_TIMEOUT_MS, type ErrorCategory, type ErrorCode, ErrorCodes, type FieldError, type FrontendCustomer, type FrontendToken, type FrontendTokenAutoProvisionRequest, type FrontendTokenRequest, type FunctionCall, type FunctionCallDelta, type FunctionTool, type HttpRequestMetrics, type JsonSchemaOptions, type KnownStopReason, type MessageDeltaData, type MessageStartData, type MessageStopData, type MetricsCallbacks, type ModelId, ModelRelay, type ModelRelayBaseOptions, ModelRelayError, type ModelRelayKeyOptions, type ModelRelayOptions, type ModelRelayOptionsLegacy, type ModelRelayTokenOptions, type NonEmptyArray, type PriceInterval, type Project, type ProviderId, type RequestContext, type ResponseFormat, type ResponseFormatType, ResponseFormatTypes, type ResponseJSONSchemaFormat, type RetryConfig, type RetryMetadata, type RetryOptions, SDK_VERSION, type Schema, type StopReason, StopReasons, type StreamFirstTokenMetrics, type StructuredJSONEvent, type StructuredJSONRecordType, StructuredJSONStream, type SubscriptionStatus, type Tier, type TierCheckoutRequest, type TierCheckoutSession, TiersClient, type TokenUsageMetrics, type Tool, ToolArgsError, type ToolCall, ToolCallAccumulator, type ToolCallDelta, type ToolChoice, type ToolChoiceType, ToolChoiceTypes, type ToolExecutionResult, type ToolHandler, ToolRegistry, type ToolType, ToolTypes, type TraceCallbacks, TransportError, type TransportErrorKind, type Usage, type UsageSummary, type WebSearchConfig, type WebToolMode, WebToolModes, type XSearchConfig, type ZodLikeSchema, assistantMessageWithToolCalls, createAccessTokenAuth, createApiKeyAuth, createAssistantMessage, createFunctionCall, createFunctionTool, createFunctionToolFromSchema, createRetryMessages, createSystemMessage, createToolCall, createUsage, createUserMessage, createWebTool, executeWithRetry, firstToolCall, formatToolErrorForModel, getRetryableErrors, hasRetryableErrors, hasToolCalls, isPublishableKey, mergeMetrics, mergeTrace, modelToString, normalizeModelId, normalizeStopReason, parseErrorResponse, parseToolArgs, parseToolArgsRaw, respondToToolCall, stopReasonToString, toolChoiceAuto, toolChoiceNone, toolChoiceRequired, toolResultMessage, tryParseToolArgs, zodToJsonSchema };
package/dist/index.d.ts CHANGED
@@ -180,10 +180,35 @@ interface FrontendCustomer {
180
180
  deviceId?: string;
181
181
  ttlSeconds?: number;
182
182
  }
183
+ /**
184
+ * Request for fetching a frontend token for an existing customer.
185
+ * Use this when the customer already exists in the system.
186
+ */
183
187
  interface FrontendTokenRequest {
184
- publishableKey?: string;
188
+ /** Publishable key (mr_pk_*) - required for authentication. */
189
+ publishableKey: string;
190
+ /** Customer identifier - required to issue a token for this customer. */
191
+ customerId: string;
192
+ /** Optional device identifier for tracking/rate limiting. */
193
+ deviceId?: string;
194
+ /** Optional TTL in seconds for the issued token. */
195
+ ttlSeconds?: number;
196
+ }
197
+ /**
198
+ * Request for fetching a frontend token with auto-provisioning.
199
+ * Use this when the customer may not exist and should be created on the free tier.
200
+ * The email is required for auto-provisioning.
201
+ */
202
+ interface FrontendTokenAutoProvisionRequest {
203
+ /** Publishable key (mr_pk_*) - required for authentication. */
204
+ publishableKey: string;
205
+ /** Customer identifier - required to issue a token for this customer. */
185
206
  customerId: string;
207
+ /** Email address - required for auto-provisioning a new customer. */
208
+ email: string;
209
+ /** Optional device identifier for tracking/rate limiting. */
186
210
  deviceId?: string;
211
+ /** Optional TTL in seconds for the issued token. */
187
212
  ttlSeconds?: number;
188
213
  }
189
214
  interface FrontendToken {
@@ -640,10 +665,26 @@ declare class AuthClient {
640
665
  private cachedFrontend;
641
666
  constructor(http: HTTPClient, cfg: AuthConfig);
642
667
  /**
643
- * Exchange a publishable key for a short-lived frontend token.
668
+ * Exchange a publishable key for a short-lived frontend token for an existing customer.
644
669
  * Tokens are cached until they are close to expiry.
670
+ *
671
+ * Use this method when the customer already exists in the system.
672
+ * For auto-provisioning new customers, use frontendTokenAutoProvision instead.
673
+ */
674
+ frontendToken(request: FrontendTokenRequest): Promise<FrontendToken>;
675
+ /**
676
+ * Exchange a publishable key for a frontend token, creating the customer if needed.
677
+ * The customer will be auto-provisioned on the project's free tier.
678
+ * Tokens are cached until they are close to expiry.
679
+ *
680
+ * Use this method when the customer may not exist and should be created automatically.
681
+ * The email is required for auto-provisioning.
645
682
  */
646
- frontendToken(request?: Partial<FrontendTokenRequest>): Promise<FrontendToken>;
683
+ frontendTokenAutoProvision(request: FrontendTokenAutoProvisionRequest): Promise<FrontendToken>;
684
+ /**
685
+ * Internal method to send frontend token requests.
686
+ */
687
+ private sendFrontendTokenRequest;
647
688
  /**
648
689
  * Determine the correct auth headers for chat completions.
649
690
  * Publishable keys are automatically exchanged for frontend tokens.
@@ -981,6 +1022,8 @@ declare const ErrorCodes: {
981
1022
  readonly NO_TIERS: "NO_TIERS";
982
1023
  /** No free tier available for auto-provisioning - create a free tier or use checkout flow. */
983
1024
  readonly NO_FREE_TIER: "NO_FREE_TIER";
1025
+ /** Email required for auto-provisioning a new customer. */
1026
+ readonly EMAIL_REQUIRED: "EMAIL_REQUIRED";
984
1027
  };
985
1028
  type ErrorCode = (typeof ErrorCodes)[keyof typeof ErrorCodes];
986
1029
  type ErrorCategory = "config" | "transport" | "api";
@@ -1048,7 +1091,12 @@ declare class APIError extends ModelRelayError {
1048
1091
  */
1049
1092
  isNoFreeTier(): boolean;
1050
1093
  /**
1051
- * Returns true if this is a customer provisioning error (NO_TIERS or NO_FREE_TIER).
1094
+ * Returns true if email is required for auto-provisioning a new customer.
1095
+ * To resolve: provide the 'email' field in FrontendTokenRequest.
1096
+ */
1097
+ isEmailRequired(): boolean;
1098
+ /**
1099
+ * Returns true if this is a customer provisioning error (NO_TIERS, NO_FREE_TIER, or EMAIL_REQUIRED).
1052
1100
  * These errors occur when calling frontendToken() with a customer that doesn't exist
1053
1101
  * and automatic provisioning cannot complete.
1054
1102
  */
@@ -1482,4 +1530,4 @@ declare class ModelRelay {
1482
1530
  constructor(options: ModelRelayOptions);
1483
1531
  }
1484
1532
 
1485
- export { type APIChatResponse, type APIChatUsage, type APICheckoutSession, type APICustomerRef, APIError, type APIFrontendToken, type APIKey, AuthClient, type AuthHeaders, ChatClient, type ChatCompletionCreateParams, type ChatCompletionEvent, type ChatCompletionResponse, ChatCompletionsStream, type ChatEventType, type ChatMessage, type CheckoutSession, type CheckoutSessionRequest, type CodeExecConfig, ConfigError, type Customer, type CustomerClaimRequest, type CustomerCreateRequest, type CustomerMetadata, type CustomerUpsertRequest, CustomersClient, DEFAULT_BASE_URL, DEFAULT_CLIENT_HEADER, DEFAULT_CONNECT_TIMEOUT_MS, DEFAULT_REQUEST_TIMEOUT_MS, type ErrorCategory, type ErrorCode, ErrorCodes, type FieldError, type FrontendCustomer, type FrontendToken, type FrontendTokenRequest, type FunctionCall, type FunctionCallDelta, type FunctionTool, type HttpRequestMetrics, type JsonSchemaOptions, type KnownStopReason, type MessageDeltaData, type MessageStartData, type MessageStopData, type MetricsCallbacks, type ModelId, ModelRelay, type ModelRelayBaseOptions, ModelRelayError, type ModelRelayKeyOptions, type ModelRelayOptions, type ModelRelayOptionsLegacy, type ModelRelayTokenOptions, type NonEmptyArray, type PriceInterval, type Project, type ProviderId, type RequestContext, type ResponseFormat, type ResponseFormatType, ResponseFormatTypes, type ResponseJSONSchemaFormat, type RetryConfig, type RetryMetadata, type RetryOptions, SDK_VERSION, type Schema, type StopReason, StopReasons, type StreamFirstTokenMetrics, type StructuredJSONEvent, type StructuredJSONRecordType, StructuredJSONStream, type SubscriptionStatus, type Tier, type TierCheckoutRequest, type TierCheckoutSession, TiersClient, type TokenUsageMetrics, type Tool, ToolArgsError, type ToolCall, ToolCallAccumulator, type ToolCallDelta, type ToolChoice, type ToolChoiceType, ToolChoiceTypes, type ToolExecutionResult, type ToolHandler, ToolRegistry, type ToolType, ToolTypes, type TraceCallbacks, TransportError, type TransportErrorKind, type Usage, type UsageSummary, type WebSearchConfig, type WebToolMode, WebToolModes, type XSearchConfig, type ZodLikeSchema, assistantMessageWithToolCalls, createAccessTokenAuth, createApiKeyAuth, createAssistantMessage, createFunctionCall, createFunctionTool, createFunctionToolFromSchema, createRetryMessages, createSystemMessage, createToolCall, createUsage, createUserMessage, createWebTool, executeWithRetry, firstToolCall, formatToolErrorForModel, getRetryableErrors, hasRetryableErrors, hasToolCalls, isPublishableKey, mergeMetrics, mergeTrace, modelToString, normalizeModelId, normalizeStopReason, parseErrorResponse, parseToolArgs, parseToolArgsRaw, respondToToolCall, stopReasonToString, toolChoiceAuto, toolChoiceNone, toolChoiceRequired, toolResultMessage, tryParseToolArgs, zodToJsonSchema };
1533
+ export { type APIChatResponse, type APIChatUsage, type APICheckoutSession, type APICustomerRef, APIError, type APIFrontendToken, type APIKey, AuthClient, type AuthHeaders, ChatClient, type ChatCompletionCreateParams, type ChatCompletionEvent, type ChatCompletionResponse, ChatCompletionsStream, type ChatEventType, type ChatMessage, type CheckoutSession, type CheckoutSessionRequest, type CodeExecConfig, ConfigError, type Customer, type CustomerClaimRequest, type CustomerCreateRequest, type CustomerMetadata, type CustomerUpsertRequest, CustomersClient, DEFAULT_BASE_URL, DEFAULT_CLIENT_HEADER, DEFAULT_CONNECT_TIMEOUT_MS, DEFAULT_REQUEST_TIMEOUT_MS, type ErrorCategory, type ErrorCode, ErrorCodes, type FieldError, type FrontendCustomer, type FrontendToken, type FrontendTokenAutoProvisionRequest, type FrontendTokenRequest, type FunctionCall, type FunctionCallDelta, type FunctionTool, type HttpRequestMetrics, type JsonSchemaOptions, type KnownStopReason, type MessageDeltaData, type MessageStartData, type MessageStopData, type MetricsCallbacks, type ModelId, ModelRelay, type ModelRelayBaseOptions, ModelRelayError, type ModelRelayKeyOptions, type ModelRelayOptions, type ModelRelayOptionsLegacy, type ModelRelayTokenOptions, type NonEmptyArray, type PriceInterval, type Project, type ProviderId, type RequestContext, type ResponseFormat, type ResponseFormatType, ResponseFormatTypes, type ResponseJSONSchemaFormat, type RetryConfig, type RetryMetadata, type RetryOptions, SDK_VERSION, type Schema, type StopReason, StopReasons, type StreamFirstTokenMetrics, type StructuredJSONEvent, type StructuredJSONRecordType, StructuredJSONStream, type SubscriptionStatus, type Tier, type TierCheckoutRequest, type TierCheckoutSession, TiersClient, type TokenUsageMetrics, type Tool, ToolArgsError, type ToolCall, ToolCallAccumulator, type ToolCallDelta, type ToolChoice, type ToolChoiceType, ToolChoiceTypes, type ToolExecutionResult, type ToolHandler, ToolRegistry, type ToolType, ToolTypes, type TraceCallbacks, TransportError, type TransportErrorKind, type Usage, type UsageSummary, type WebSearchConfig, type WebToolMode, WebToolModes, type XSearchConfig, type ZodLikeSchema, assistantMessageWithToolCalls, createAccessTokenAuth, createApiKeyAuth, createAssistantMessage, createFunctionCall, createFunctionTool, createFunctionToolFromSchema, createRetryMessages, createSystemMessage, createToolCall, createUsage, createUserMessage, createWebTool, executeWithRetry, firstToolCall, formatToolErrorForModel, getRetryableErrors, hasRetryableErrors, hasToolCalls, isPublishableKey, mergeMetrics, mergeTrace, modelToString, normalizeModelId, normalizeStopReason, parseErrorResponse, parseToolArgs, parseToolArgsRaw, respondToToolCall, stopReasonToString, toolChoiceAuto, toolChoiceNone, toolChoiceRequired, toolResultMessage, tryParseToolArgs, zodToJsonSchema };
package/dist/index.js CHANGED
@@ -14,7 +14,9 @@ var ErrorCodes = {
14
14
  /** No tiers configured for the project - create a tier first. */
15
15
  NO_TIERS: "NO_TIERS",
16
16
  /** No free tier available for auto-provisioning - create a free tier or use checkout flow. */
17
- NO_FREE_TIER: "NO_FREE_TIER"
17
+ NO_FREE_TIER: "NO_FREE_TIER",
18
+ /** Email required for auto-provisioning a new customer. */
19
+ EMAIL_REQUIRED: "EMAIL_REQUIRED"
18
20
  };
19
21
  var ModelRelayError = class extends Error {
20
22
  constructor(message, opts) {
@@ -99,12 +101,19 @@ var APIError = class extends ModelRelayError {
99
101
  return this.code === ErrorCodes.NO_FREE_TIER;
100
102
  }
101
103
  /**
102
- * Returns true if this is a customer provisioning error (NO_TIERS or NO_FREE_TIER).
104
+ * Returns true if email is required for auto-provisioning a new customer.
105
+ * To resolve: provide the 'email' field in FrontendTokenRequest.
106
+ */
107
+ isEmailRequired() {
108
+ return this.code === ErrorCodes.EMAIL_REQUIRED;
109
+ }
110
+ /**
111
+ * Returns true if this is a customer provisioning error (NO_TIERS, NO_FREE_TIER, or EMAIL_REQUIRED).
103
112
  * These errors occur when calling frontendToken() with a customer that doesn't exist
104
113
  * and automatic provisioning cannot complete.
105
114
  */
106
115
  isProvisioningError() {
107
- return this.isNoTiers() || this.isNoFreeTier();
116
+ return this.isNoTiers() || this.isNoFreeTier() || this.isEmailRequired();
108
117
  }
109
118
  };
110
119
  async function parseErrorResponse(response, retries) {
@@ -175,20 +184,47 @@ var AuthClient = class {
175
184
  this.customer = cfg.customer;
176
185
  }
177
186
  /**
178
- * Exchange a publishable key for a short-lived frontend token.
187
+ * Exchange a publishable key for a short-lived frontend token for an existing customer.
179
188
  * Tokens are cached until they are close to expiry.
189
+ *
190
+ * Use this method when the customer already exists in the system.
191
+ * For auto-provisioning new customers, use frontendTokenAutoProvision instead.
180
192
  */
181
193
  async frontendToken(request) {
182
- const publishableKey = request?.publishableKey || (isPublishableKey(this.apiKey) ? this.apiKey : void 0);
183
- if (!publishableKey) {
184
- throw new ConfigError("publishable key required to issue frontend tokens");
194
+ if (!request.publishableKey?.trim()) {
195
+ throw new ConfigError("publishableKey is required");
196
+ }
197
+ if (!request.customerId?.trim()) {
198
+ throw new ConfigError("customerId is required");
199
+ }
200
+ return this.sendFrontendTokenRequest(request);
201
+ }
202
+ /**
203
+ * Exchange a publishable key for a frontend token, creating the customer if needed.
204
+ * The customer will be auto-provisioned on the project's free tier.
205
+ * Tokens are cached until they are close to expiry.
206
+ *
207
+ * Use this method when the customer may not exist and should be created automatically.
208
+ * The email is required for auto-provisioning.
209
+ */
210
+ async frontendTokenAutoProvision(request) {
211
+ if (!request.publishableKey?.trim()) {
212
+ throw new ConfigError("publishableKey is required");
185
213
  }
186
- const customerId = request?.customerId || this.customer?.id;
187
- if (!customerId) {
188
- throw new ConfigError("customerId is required to mint a frontend token");
214
+ if (!request.customerId?.trim()) {
215
+ throw new ConfigError("customerId is required");
216
+ }
217
+ if (!request.email?.trim()) {
218
+ throw new ConfigError("email is required for auto-provisioning");
189
219
  }
190
- const deviceId = request?.deviceId || this.customer?.deviceId;
191
- const ttlSeconds = request?.ttlSeconds ?? this.customer?.ttlSeconds;
220
+ return this.sendFrontendTokenRequest(request);
221
+ }
222
+ /**
223
+ * Internal method to send frontend token requests.
224
+ */
225
+ async sendFrontendTokenRequest(request) {
226
+ const { publishableKey, customerId, deviceId, ttlSeconds } = request;
227
+ const email = "email" in request ? request.email : void 0;
192
228
  const cacheKey = `${publishableKey}:${customerId}:${deviceId || ""}`;
193
229
  const cached = this.cachedFrontend.get(cacheKey);
194
230
  if (cached && isTokenReusable(cached)) {
@@ -204,6 +240,9 @@ var AuthClient = class {
204
240
  if (typeof ttlSeconds === "number" && ttlSeconds > 0) {
205
241
  payload.ttl_seconds = ttlSeconds;
206
242
  }
243
+ if (email) {
244
+ payload.email = email;
245
+ }
207
246
  const response = await this.http.json(
208
247
  "/auth/frontend-token",
209
248
  {
@@ -231,10 +270,15 @@ var AuthClient = class {
231
270
  throw new ConfigError("API key or token is required");
232
271
  }
233
272
  if (isPublishableKey(this.apiKey)) {
273
+ const resolvedCustomerId = customerId || overrides?.id || this.customer?.id;
274
+ if (!resolvedCustomerId) {
275
+ throw new ConfigError("customerId is required to mint a frontend token");
276
+ }
234
277
  const token = await this.frontendToken({
235
- customerId: customerId || overrides?.id,
236
- deviceId: overrides?.deviceId,
237
- ttlSeconds: overrides?.ttlSeconds
278
+ publishableKey: this.apiKey,
279
+ customerId: resolvedCustomerId,
280
+ deviceId: overrides?.deviceId || this.customer?.deviceId,
281
+ ttlSeconds: overrides?.ttlSeconds ?? this.customer?.ttlSeconds
238
282
  });
239
283
  return createAccessTokenAuth(token.token);
240
284
  }
@@ -288,7 +332,7 @@ function isTokenReusable(token) {
288
332
  // package.json
289
333
  var package_default = {
290
334
  name: "@modelrelay/sdk",
291
- version: "0.20.0",
335
+ version: "0.21.0",
292
336
  description: "TypeScript SDK for the ModelRelay API",
293
337
  type: "module",
294
338
  main: "dist/index.cjs",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@modelrelay/sdk",
3
- "version": "0.20.0",
3
+ "version": "0.21.0",
4
4
  "description": "TypeScript SDK for the ModelRelay API",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",