@huggingface/inference 4.0.0 → 4.0.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.
@@ -1,3 +1,3 @@
1
- export declare const PACKAGE_VERSION = "4.0.0";
1
+ export declare const PACKAGE_VERSION = "4.0.1";
2
2
  export declare const PACKAGE_NAME = "@huggingface/inference";
3
3
  //# sourceMappingURL=package.d.ts.map
@@ -2,5 +2,5 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.PACKAGE_NAME = exports.PACKAGE_VERSION = void 0;
4
4
  // Generated file from package.json. Issues importing JSON directly when publishing on commonjs/ESM - see https://github.com/microsoft/TypeScript/issues/51783
5
- exports.PACKAGE_VERSION = "4.0.0";
5
+ exports.PACKAGE_VERSION = "4.0.1";
6
6
  exports.PACKAGE_NAME = "@huggingface/inference";
@@ -4,6 +4,7 @@ import type { InferenceProviderOrPolicy } from "../types.js";
4
4
  export type InferenceSnippetOptions = {
5
5
  streaming?: boolean;
6
6
  billTo?: string;
7
+ accessToken?: string;
7
8
  } & Record<string, unknown>;
8
- export declare function getInferenceSnippets(model: ModelDataMinimal, accessToken: string, provider: InferenceProviderOrPolicy, inferenceProviderMapping?: InferenceProviderModelMapping, opts?: Record<string, unknown>): InferenceSnippet[];
9
+ export declare function getInferenceSnippets(model: ModelDataMinimal, provider: InferenceProviderOrPolicy, inferenceProviderMapping?: InferenceProviderModelMapping, opts?: Record<string, unknown>): InferenceSnippet[];
9
10
  //# sourceMappingURL=getInferenceSnippets.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"getInferenceSnippets.d.ts","sourceRoot":"","sources":["../../../src/snippets/getInferenceSnippets.ts"],"names":[],"mappings":"AACA,OAAO,EACN,KAAK,gBAAgB,EAErB,KAAK,gBAAgB,EAGrB,MAAM,oBAAoB,CAAC;AAG5B,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,uCAAuC,CAAC;AAG3F,OAAO,KAAK,EAAE,yBAAyB,EAA8B,MAAM,aAAa,CAAC;AAGzF,MAAM,MAAM,uBAAuB,GAAG;IAAE,SAAS,CAAC,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAmUzG,wBAAgB,oBAAoB,CACnC,KAAK,EAAE,gBAAgB,EACvB,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,yBAAyB,EACnC,wBAAwB,CAAC,EAAE,6BAA6B,EACxD,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,gBAAgB,EAAE,CAIpB"}
1
+ {"version":3,"file":"getInferenceSnippets.d.ts","sourceRoot":"","sources":["../../../src/snippets/getInferenceSnippets.ts"],"names":[],"mappings":"AACA,OAAO,EACN,KAAK,gBAAgB,EAErB,KAAK,gBAAgB,EAGrB,MAAM,oBAAoB,CAAC;AAG5B,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,uCAAuC,CAAC;AAG3F,OAAO,KAAK,EAAE,yBAAyB,EAA8B,MAAM,aAAa,CAAC;AAGzF,MAAM,MAAM,uBAAuB,GAAG;IAAE,SAAS,CAAC,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAC5G,MAAM,EACN,OAAO,CACP,CAAC;AA0UF,wBAAgB,oBAAoB,CACnC,KAAK,EAAE,gBAAgB,EACvB,QAAQ,EAAE,yBAAyB,EACnC,wBAAwB,CAAC,EAAE,6BAA6B,EACxD,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,gBAAgB,EAAE,CAIpB"}
@@ -76,9 +76,10 @@ const HF_JS_METHODS = {
76
76
  "text-to-speech": "textToSpeech",
77
77
  translation: "translation",
78
78
  };
79
+ const ACCESS_TOKEN_PLACEHOLDER = "<ACCESS_TOKEN>"; // Placeholder to replace with env variable in snippets
79
80
  // Snippet generators
80
81
  const snippetGenerator = (templateName, inputPreparationFn) => {
81
- return (model, accessToken, provider, inferenceProviderMapping, opts) => {
82
+ return (model, provider, inferenceProviderMapping, opts) => {
82
83
  const providerModelId = inferenceProviderMapping?.providerId ?? model.id;
83
84
  /// Hacky: hard-code conversational templates here
84
85
  let task = model.pipeline_tag;
@@ -97,10 +98,11 @@ const snippetGenerator = (templateName, inputPreparationFn) => {
97
98
  console.error(`Failed to get provider helper for ${provider} (${task})`, e);
98
99
  return [];
99
100
  }
101
+ const accessTokenOrPlaceholder = opts?.accessToken ?? ACCESS_TOKEN_PLACEHOLDER;
100
102
  /// Prepare inputs + make request
101
103
  const inputs = inputPreparationFn ? inputPreparationFn(model, opts) : { inputs: (0, tasks_1.getModelInputSnippet)(model) };
102
104
  const request = (0, makeRequestOptions_js_1.makeRequestOptionsFromResolvedModel)(providerModelId, providerHelper, {
103
- accessToken,
105
+ accessToken: accessTokenOrPlaceholder,
104
106
  provider,
105
107
  ...inputs,
106
108
  }, inferenceProviderMapping, {
@@ -121,7 +123,7 @@ const snippetGenerator = (templateName, inputPreparationFn) => {
121
123
  }
122
124
  /// Prepare template injection data
123
125
  const params = {
124
- accessToken,
126
+ accessToken: accessTokenOrPlaceholder,
125
127
  authorizationHeader: request.info.headers?.Authorization,
126
128
  baseUrl: removeSuffix(request.url, "/chat/completions"),
127
129
  fullUrl: request.url,
@@ -185,6 +187,10 @@ const snippetGenerator = (templateName, inputPreparationFn) => {
185
187
  });
186
188
  snippet = `${importSection}\n\n${snippet}`;
187
189
  }
190
+ /// Replace access token placeholder
191
+ if (snippet.includes(ACCESS_TOKEN_PLACEHOLDER)) {
192
+ snippet = replaceAccessTokenPlaceholder(snippet, language, provider);
193
+ }
188
194
  /// Snippet is ready!
189
195
  return { language, client: client, content: snippet };
190
196
  })
@@ -247,9 +253,9 @@ const snippets = {
247
253
  "zero-shot-classification": snippetGenerator("zeroShotClassification"),
248
254
  "zero-shot-image-classification": snippetGenerator("zeroShotImageClassification"),
249
255
  };
250
- function getInferenceSnippets(model, accessToken, provider, inferenceProviderMapping, opts) {
256
+ function getInferenceSnippets(model, provider, inferenceProviderMapping, opts) {
251
257
  return model.pipeline_tag && model.pipeline_tag in snippets
252
- ? snippets[model.pipeline_tag]?.(model, accessToken, provider, inferenceProviderMapping, opts) ?? []
258
+ ? snippets[model.pipeline_tag]?.(model, provider, inferenceProviderMapping, opts) ?? []
253
259
  : [];
254
260
  }
255
261
  // String manipulation helpers
@@ -310,3 +316,36 @@ function indentString(str) {
310
316
  function removeSuffix(str, suffix) {
311
317
  return str.endsWith(suffix) ? str.slice(0, -suffix.length) : str;
312
318
  }
319
+ function replaceAccessTokenPlaceholder(snippet, language, provider) {
320
+ // If "opts.accessToken" is not set, the snippets are generated with a placeholder.
321
+ // Once snippets are rendered, we replace the placeholder with code to fetch the access token from an environment variable.
322
+ // Determine if HF_TOKEN or specific provider token should be used
323
+ const accessTokenEnvVar = !snippet.includes("https://") || // no URL provided => using a client => use $HF_TOKEN
324
+ snippet.includes("https://router.huggingface.co") || // explicit routed request => use $HF_TOKEN
325
+ provider == "hf-inference" // hf-inference provider => use $HF_TOKEN
326
+ ? "HF_TOKEN"
327
+ : provider.toUpperCase().replace("-", "_") + "_API_KEY"; // e.g. "REPLICATE_API_KEY"
328
+ // Replace the placeholder with the env variable
329
+ if (language === "sh") {
330
+ snippet = snippet.replace(`'Authorization: Bearer ${ACCESS_TOKEN_PLACEHOLDER}'`, `"Authorization: Bearer $${accessTokenEnvVar}"` // e.g. "Authorization: Bearer $HF_TOKEN"
331
+ );
332
+ }
333
+ else if (language === "python") {
334
+ snippet = "import os\n" + snippet;
335
+ snippet = snippet.replace(`"${ACCESS_TOKEN_PLACEHOLDER}"`, `os.environ["${accessTokenEnvVar}"]` // e.g. os.environ["HF_TOKEN")
336
+ );
337
+ snippet = snippet.replace(`"Bearer ${ACCESS_TOKEN_PLACEHOLDER}"`, `f"Bearer {os.environ['${accessTokenEnvVar}']}"` // e.g. f"Bearer {os.environ['HF_TOKEN']}"
338
+ );
339
+ snippet = snippet.replace(`"Key ${ACCESS_TOKEN_PLACEHOLDER}"`, `f"Key {os.environ['${accessTokenEnvVar}']}"` // e.g. f"Key {os.environ['FAL_AI_API_KEY']}"
340
+ );
341
+ }
342
+ else if (language === "js") {
343
+ snippet = snippet.replace(`"${ACCESS_TOKEN_PLACEHOLDER}"`, `process.env.${accessTokenEnvVar}` // e.g. process.env.HF_TOKEN
344
+ );
345
+ snippet = snippet.replace(`Authorization: "Bearer ${ACCESS_TOKEN_PLACEHOLDER}",`, `Authorization: \`Bearer $\{process.env.${accessTokenEnvVar}}\`,` // e.g. Authorization: `Bearer ${process.env.HF_TOKEN}`,
346
+ );
347
+ snippet = snippet.replace(`Authorization: "Key ${ACCESS_TOKEN_PLACEHOLDER}",`, `Authorization: \`Key $\{process.env.${accessTokenEnvVar}}\`,` // e.g. Authorization: `Key ${process.env.FAL_AI_API_KEY}`,
348
+ );
349
+ }
350
+ return snippet;
351
+ }
@@ -35,8 +35,8 @@ async function innerRequest(args, providerHelper, options) {
35
35
  body: requestArgsToJson(args),
36
36
  }, { requestId: response.headers.get("x-request-id") ?? "", status: response.status, body: output });
37
37
  }
38
- if (typeof output.error === "string" || typeof output.detail === "string") {
39
- throw new errors_js_1.InferenceClientProviderApiError(`Failed to perform inference: ${output.error ?? output.detail}`, {
38
+ if (typeof output.error === "string" || typeof output.detail === "string" || typeof output.message === "string") {
39
+ throw new errors_js_1.InferenceClientProviderApiError(`Failed to perform inference: ${output.error ?? output.detail ?? output.message}`, {
40
40
  url,
41
41
  method: info.method ?? "GET",
42
42
  headers: info.headers,
@@ -1,3 +1,3 @@
1
- export declare const PACKAGE_VERSION = "4.0.0";
1
+ export declare const PACKAGE_VERSION = "4.0.1";
2
2
  export declare const PACKAGE_NAME = "@huggingface/inference";
3
3
  //# sourceMappingURL=package.d.ts.map
@@ -1,3 +1,3 @@
1
1
  // Generated file from package.json. Issues importing JSON directly when publishing on commonjs/ESM - see https://github.com/microsoft/TypeScript/issues/51783
2
- export const PACKAGE_VERSION = "4.0.0";
2
+ export const PACKAGE_VERSION = "4.0.1";
3
3
  export const PACKAGE_NAME = "@huggingface/inference";
@@ -4,6 +4,7 @@ import type { InferenceProviderOrPolicy } from "../types.js";
4
4
  export type InferenceSnippetOptions = {
5
5
  streaming?: boolean;
6
6
  billTo?: string;
7
+ accessToken?: string;
7
8
  } & Record<string, unknown>;
8
- export declare function getInferenceSnippets(model: ModelDataMinimal, accessToken: string, provider: InferenceProviderOrPolicy, inferenceProviderMapping?: InferenceProviderModelMapping, opts?: Record<string, unknown>): InferenceSnippet[];
9
+ export declare function getInferenceSnippets(model: ModelDataMinimal, provider: InferenceProviderOrPolicy, inferenceProviderMapping?: InferenceProviderModelMapping, opts?: Record<string, unknown>): InferenceSnippet[];
9
10
  //# sourceMappingURL=getInferenceSnippets.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"getInferenceSnippets.d.ts","sourceRoot":"","sources":["../../../src/snippets/getInferenceSnippets.ts"],"names":[],"mappings":"AACA,OAAO,EACN,KAAK,gBAAgB,EAErB,KAAK,gBAAgB,EAGrB,MAAM,oBAAoB,CAAC;AAG5B,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,uCAAuC,CAAC;AAG3F,OAAO,KAAK,EAAE,yBAAyB,EAA8B,MAAM,aAAa,CAAC;AAGzF,MAAM,MAAM,uBAAuB,GAAG;IAAE,SAAS,CAAC,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAmUzG,wBAAgB,oBAAoB,CACnC,KAAK,EAAE,gBAAgB,EACvB,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,yBAAyB,EACnC,wBAAwB,CAAC,EAAE,6BAA6B,EACxD,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,gBAAgB,EAAE,CAIpB"}
1
+ {"version":3,"file":"getInferenceSnippets.d.ts","sourceRoot":"","sources":["../../../src/snippets/getInferenceSnippets.ts"],"names":[],"mappings":"AACA,OAAO,EACN,KAAK,gBAAgB,EAErB,KAAK,gBAAgB,EAGrB,MAAM,oBAAoB,CAAC;AAG5B,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,uCAAuC,CAAC;AAG3F,OAAO,KAAK,EAAE,yBAAyB,EAA8B,MAAM,aAAa,CAAC;AAGzF,MAAM,MAAM,uBAAuB,GAAG;IAAE,SAAS,CAAC,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAC5G,MAAM,EACN,OAAO,CACP,CAAC;AA0UF,wBAAgB,oBAAoB,CACnC,KAAK,EAAE,gBAAgB,EACvB,QAAQ,EAAE,yBAAyB,EACnC,wBAAwB,CAAC,EAAE,6BAA6B,EACxD,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,gBAAgB,EAAE,CAIpB"}
@@ -73,9 +73,10 @@ const HF_JS_METHODS = {
73
73
  "text-to-speech": "textToSpeech",
74
74
  translation: "translation",
75
75
  };
76
+ const ACCESS_TOKEN_PLACEHOLDER = "<ACCESS_TOKEN>"; // Placeholder to replace with env variable in snippets
76
77
  // Snippet generators
77
78
  const snippetGenerator = (templateName, inputPreparationFn) => {
78
- return (model, accessToken, provider, inferenceProviderMapping, opts) => {
79
+ return (model, provider, inferenceProviderMapping, opts) => {
79
80
  const providerModelId = inferenceProviderMapping?.providerId ?? model.id;
80
81
  /// Hacky: hard-code conversational templates here
81
82
  let task = model.pipeline_tag;
@@ -94,10 +95,11 @@ const snippetGenerator = (templateName, inputPreparationFn) => {
94
95
  console.error(`Failed to get provider helper for ${provider} (${task})`, e);
95
96
  return [];
96
97
  }
98
+ const accessTokenOrPlaceholder = opts?.accessToken ?? ACCESS_TOKEN_PLACEHOLDER;
97
99
  /// Prepare inputs + make request
98
100
  const inputs = inputPreparationFn ? inputPreparationFn(model, opts) : { inputs: getModelInputSnippet(model) };
99
101
  const request = makeRequestOptionsFromResolvedModel(providerModelId, providerHelper, {
100
- accessToken,
102
+ accessToken: accessTokenOrPlaceholder,
101
103
  provider,
102
104
  ...inputs,
103
105
  }, inferenceProviderMapping, {
@@ -118,7 +120,7 @@ const snippetGenerator = (templateName, inputPreparationFn) => {
118
120
  }
119
121
  /// Prepare template injection data
120
122
  const params = {
121
- accessToken,
123
+ accessToken: accessTokenOrPlaceholder,
122
124
  authorizationHeader: request.info.headers?.Authorization,
123
125
  baseUrl: removeSuffix(request.url, "/chat/completions"),
124
126
  fullUrl: request.url,
@@ -182,6 +184,10 @@ const snippetGenerator = (templateName, inputPreparationFn) => {
182
184
  });
183
185
  snippet = `${importSection}\n\n${snippet}`;
184
186
  }
187
+ /// Replace access token placeholder
188
+ if (snippet.includes(ACCESS_TOKEN_PLACEHOLDER)) {
189
+ snippet = replaceAccessTokenPlaceholder(snippet, language, provider);
190
+ }
185
191
  /// Snippet is ready!
186
192
  return { language, client: client, content: snippet };
187
193
  })
@@ -244,9 +250,9 @@ const snippets = {
244
250
  "zero-shot-classification": snippetGenerator("zeroShotClassification"),
245
251
  "zero-shot-image-classification": snippetGenerator("zeroShotImageClassification"),
246
252
  };
247
- export function getInferenceSnippets(model, accessToken, provider, inferenceProviderMapping, opts) {
253
+ export function getInferenceSnippets(model, provider, inferenceProviderMapping, opts) {
248
254
  return model.pipeline_tag && model.pipeline_tag in snippets
249
- ? snippets[model.pipeline_tag]?.(model, accessToken, provider, inferenceProviderMapping, opts) ?? []
255
+ ? snippets[model.pipeline_tag]?.(model, provider, inferenceProviderMapping, opts) ?? []
250
256
  : [];
251
257
  }
252
258
  // String manipulation helpers
@@ -307,3 +313,36 @@ function indentString(str) {
307
313
  function removeSuffix(str, suffix) {
308
314
  return str.endsWith(suffix) ? str.slice(0, -suffix.length) : str;
309
315
  }
316
+ function replaceAccessTokenPlaceholder(snippet, language, provider) {
317
+ // If "opts.accessToken" is not set, the snippets are generated with a placeholder.
318
+ // Once snippets are rendered, we replace the placeholder with code to fetch the access token from an environment variable.
319
+ // Determine if HF_TOKEN or specific provider token should be used
320
+ const accessTokenEnvVar = !snippet.includes("https://") || // no URL provided => using a client => use $HF_TOKEN
321
+ snippet.includes("https://router.huggingface.co") || // explicit routed request => use $HF_TOKEN
322
+ provider == "hf-inference" // hf-inference provider => use $HF_TOKEN
323
+ ? "HF_TOKEN"
324
+ : provider.toUpperCase().replace("-", "_") + "_API_KEY"; // e.g. "REPLICATE_API_KEY"
325
+ // Replace the placeholder with the env variable
326
+ if (language === "sh") {
327
+ snippet = snippet.replace(`'Authorization: Bearer ${ACCESS_TOKEN_PLACEHOLDER}'`, `"Authorization: Bearer $${accessTokenEnvVar}"` // e.g. "Authorization: Bearer $HF_TOKEN"
328
+ );
329
+ }
330
+ else if (language === "python") {
331
+ snippet = "import os\n" + snippet;
332
+ snippet = snippet.replace(`"${ACCESS_TOKEN_PLACEHOLDER}"`, `os.environ["${accessTokenEnvVar}"]` // e.g. os.environ["HF_TOKEN")
333
+ );
334
+ snippet = snippet.replace(`"Bearer ${ACCESS_TOKEN_PLACEHOLDER}"`, `f"Bearer {os.environ['${accessTokenEnvVar}']}"` // e.g. f"Bearer {os.environ['HF_TOKEN']}"
335
+ );
336
+ snippet = snippet.replace(`"Key ${ACCESS_TOKEN_PLACEHOLDER}"`, `f"Key {os.environ['${accessTokenEnvVar}']}"` // e.g. f"Key {os.environ['FAL_AI_API_KEY']}"
337
+ );
338
+ }
339
+ else if (language === "js") {
340
+ snippet = snippet.replace(`"${ACCESS_TOKEN_PLACEHOLDER}"`, `process.env.${accessTokenEnvVar}` // e.g. process.env.HF_TOKEN
341
+ );
342
+ snippet = snippet.replace(`Authorization: "Bearer ${ACCESS_TOKEN_PLACEHOLDER}",`, `Authorization: \`Bearer $\{process.env.${accessTokenEnvVar}}\`,` // e.g. Authorization: `Bearer ${process.env.HF_TOKEN}`,
343
+ );
344
+ snippet = snippet.replace(`Authorization: "Key ${ACCESS_TOKEN_PLACEHOLDER}",`, `Authorization: \`Key $\{process.env.${accessTokenEnvVar}}\`,` // e.g. Authorization: `Key ${process.env.FAL_AI_API_KEY}`,
345
+ );
346
+ }
347
+ return snippet;
348
+ }
@@ -31,8 +31,8 @@ export async function innerRequest(args, providerHelper, options) {
31
31
  body: requestArgsToJson(args),
32
32
  }, { requestId: response.headers.get("x-request-id") ?? "", status: response.status, body: output });
33
33
  }
34
- if (typeof output.error === "string" || typeof output.detail === "string") {
35
- throw new InferenceClientProviderApiError(`Failed to perform inference: ${output.error ?? output.detail}`, {
34
+ if (typeof output.error === "string" || typeof output.detail === "string" || typeof output.message === "string") {
35
+ throw new InferenceClientProviderApiError(`Failed to perform inference: ${output.error ?? output.detail ?? output.message}`, {
36
36
  url,
37
37
  method: info.method ?? "GET",
38
38
  headers: info.headers,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@huggingface/inference",
3
- "version": "4.0.0",
3
+ "version": "4.0.1",
4
4
  "license": "MIT",
5
5
  "author": "Hugging Face and Tim Mikeladze <tim.mikeladze@gmail.com>",
6
6
  "description": "Typescript client for the Hugging Face Inference Providers and Inference Endpoints",
package/src/package.ts CHANGED
@@ -1,3 +1,3 @@
1
1
  // Generated file from package.json. Issues importing JSON directly when publishing on commonjs/ESM - see https://github.com/microsoft/TypeScript/issues/51783
2
- export const PACKAGE_VERSION = "4.0.0";
2
+ export const PACKAGE_VERSION = "4.0.1";
3
3
  export const PACKAGE_NAME = "@huggingface/inference";
@@ -14,7 +14,10 @@ import { makeRequestOptionsFromResolvedModel } from "../lib/makeRequestOptions.j
14
14
  import type { InferenceProviderOrPolicy, InferenceTask, RequestArgs } from "../types.js";
15
15
  import { templates } from "./templates.exported.js";
16
16
 
17
- export type InferenceSnippetOptions = { streaming?: boolean; billTo?: string } & Record<string, unknown>;
17
+ export type InferenceSnippetOptions = { streaming?: boolean; billTo?: string; accessToken?: string } & Record<
18
+ string,
19
+ unknown
20
+ >;
18
21
 
19
22
  const PYTHON_CLIENTS = ["huggingface_hub", "fal_client", "requests", "openai"] as const;
20
23
  const JS_CLIENTS = ["fetch", "huggingface.js", "openai"] as const;
@@ -121,11 +124,12 @@ const HF_JS_METHODS: Partial<Record<WidgetType, string>> = {
121
124
  translation: "translation",
122
125
  };
123
126
 
127
+ const ACCESS_TOKEN_PLACEHOLDER = "<ACCESS_TOKEN>"; // Placeholder to replace with env variable in snippets
128
+
124
129
  // Snippet generators
125
130
  const snippetGenerator = (templateName: string, inputPreparationFn?: InputPreparationFn) => {
126
131
  return (
127
132
  model: ModelDataMinimal,
128
- accessToken: string,
129
133
  provider: InferenceProviderOrPolicy,
130
134
  inferenceProviderMapping?: InferenceProviderModelMapping,
131
135
  opts?: InferenceSnippetOptions
@@ -149,13 +153,15 @@ const snippetGenerator = (templateName: string, inputPreparationFn?: InputPrepar
149
153
  console.error(`Failed to get provider helper for ${provider} (${task})`, e);
150
154
  return [];
151
155
  }
156
+ const accessTokenOrPlaceholder = opts?.accessToken ?? ACCESS_TOKEN_PLACEHOLDER;
157
+
152
158
  /// Prepare inputs + make request
153
159
  const inputs = inputPreparationFn ? inputPreparationFn(model, opts) : { inputs: getModelInputSnippet(model) };
154
160
  const request = makeRequestOptionsFromResolvedModel(
155
161
  providerModelId,
156
162
  providerHelper,
157
163
  {
158
- accessToken,
164
+ accessToken: accessTokenOrPlaceholder,
159
165
  provider,
160
166
  ...inputs,
161
167
  } as RequestArgs,
@@ -180,7 +186,7 @@ const snippetGenerator = (templateName: string, inputPreparationFn?: InputPrepar
180
186
 
181
187
  /// Prepare template injection data
182
188
  const params: TemplateParams = {
183
- accessToken,
189
+ accessToken: accessTokenOrPlaceholder,
184
190
  authorizationHeader: (request.info.headers as Record<string, string>)?.Authorization,
185
191
  baseUrl: removeSuffix(request.url, "/chat/completions"),
186
192
  fullUrl: request.url,
@@ -248,6 +254,11 @@ const snippetGenerator = (templateName: string, inputPreparationFn?: InputPrepar
248
254
  snippet = `${importSection}\n\n${snippet}`;
249
255
  }
250
256
 
257
+ /// Replace access token placeholder
258
+ if (snippet.includes(ACCESS_TOKEN_PLACEHOLDER)) {
259
+ snippet = replaceAccessTokenPlaceholder(snippet, language, provider);
260
+ }
261
+
251
262
  /// Snippet is ready!
252
263
  return { language, client: client as string, content: snippet };
253
264
  })
@@ -299,7 +310,6 @@ const snippets: Partial<
299
310
  PipelineType,
300
311
  (
301
312
  model: ModelDataMinimal,
302
- accessToken: string,
303
313
  provider: InferenceProviderOrPolicy,
304
314
  inferenceProviderMapping?: InferenceProviderModelMapping,
305
315
  opts?: InferenceSnippetOptions
@@ -339,13 +349,12 @@ const snippets: Partial<
339
349
 
340
350
  export function getInferenceSnippets(
341
351
  model: ModelDataMinimal,
342
- accessToken: string,
343
352
  provider: InferenceProviderOrPolicy,
344
353
  inferenceProviderMapping?: InferenceProviderModelMapping,
345
354
  opts?: Record<string, unknown>
346
355
  ): InferenceSnippet[] {
347
356
  return model.pipeline_tag && model.pipeline_tag in snippets
348
- ? snippets[model.pipeline_tag]?.(model, accessToken, provider, inferenceProviderMapping, opts) ?? []
357
+ ? snippets[model.pipeline_tag]?.(model, provider, inferenceProviderMapping, opts) ?? []
349
358
  : [];
350
359
  }
351
360
 
@@ -420,3 +429,56 @@ function indentString(str: string): string {
420
429
  function removeSuffix(str: string, suffix: string) {
421
430
  return str.endsWith(suffix) ? str.slice(0, -suffix.length) : str;
422
431
  }
432
+
433
+ function replaceAccessTokenPlaceholder(
434
+ snippet: string,
435
+ language: InferenceSnippetLanguage,
436
+ provider: InferenceProviderOrPolicy
437
+ ): string {
438
+ // If "opts.accessToken" is not set, the snippets are generated with a placeholder.
439
+ // Once snippets are rendered, we replace the placeholder with code to fetch the access token from an environment variable.
440
+
441
+ // Determine if HF_TOKEN or specific provider token should be used
442
+ const accessTokenEnvVar =
443
+ !snippet.includes("https://") || // no URL provided => using a client => use $HF_TOKEN
444
+ snippet.includes("https://router.huggingface.co") || // explicit routed request => use $HF_TOKEN
445
+ provider == "hf-inference" // hf-inference provider => use $HF_TOKEN
446
+ ? "HF_TOKEN"
447
+ : provider.toUpperCase().replace("-", "_") + "_API_KEY"; // e.g. "REPLICATE_API_KEY"
448
+
449
+ // Replace the placeholder with the env variable
450
+ if (language === "sh") {
451
+ snippet = snippet.replace(
452
+ `'Authorization: Bearer ${ACCESS_TOKEN_PLACEHOLDER}'`,
453
+ `"Authorization: Bearer $${accessTokenEnvVar}"` // e.g. "Authorization: Bearer $HF_TOKEN"
454
+ );
455
+ } else if (language === "python") {
456
+ snippet = "import os\n" + snippet;
457
+ snippet = snippet.replace(
458
+ `"${ACCESS_TOKEN_PLACEHOLDER}"`,
459
+ `os.environ["${accessTokenEnvVar}"]` // e.g. os.environ["HF_TOKEN")
460
+ );
461
+ snippet = snippet.replace(
462
+ `"Bearer ${ACCESS_TOKEN_PLACEHOLDER}"`,
463
+ `f"Bearer {os.environ['${accessTokenEnvVar}']}"` // e.g. f"Bearer {os.environ['HF_TOKEN']}"
464
+ );
465
+ snippet = snippet.replace(
466
+ `"Key ${ACCESS_TOKEN_PLACEHOLDER}"`,
467
+ `f"Key {os.environ['${accessTokenEnvVar}']}"` // e.g. f"Key {os.environ['FAL_AI_API_KEY']}"
468
+ );
469
+ } else if (language === "js") {
470
+ snippet = snippet.replace(
471
+ `"${ACCESS_TOKEN_PLACEHOLDER}"`,
472
+ `process.env.${accessTokenEnvVar}` // e.g. process.env.HF_TOKEN
473
+ );
474
+ snippet = snippet.replace(
475
+ `Authorization: "Bearer ${ACCESS_TOKEN_PLACEHOLDER}",`,
476
+ `Authorization: \`Bearer $\{process.env.${accessTokenEnvVar}}\`,` // e.g. Authorization: `Bearer ${process.env.HF_TOKEN}`,
477
+ );
478
+ snippet = snippet.replace(
479
+ `Authorization: "Key ${ACCESS_TOKEN_PLACEHOLDER}",`,
480
+ `Authorization: \`Key $\{process.env.${accessTokenEnvVar}}\`,` // e.g. Authorization: `Key ${process.env.FAL_AI_API_KEY}`,
481
+ );
482
+ }
483
+ return snippet;
484
+ }
@@ -65,9 +65,9 @@ export async function innerRequest<T>(
65
65
  { requestId: response.headers.get("x-request-id") ?? "", status: response.status, body: output }
66
66
  );
67
67
  }
68
- if (typeof output.error === "string" || typeof output.detail === "string") {
68
+ if (typeof output.error === "string" || typeof output.detail === "string" || typeof output.message === "string") {
69
69
  throw new InferenceClientProviderApiError(
70
- `Failed to perform inference: ${output.error ?? output.detail}`,
70
+ `Failed to perform inference: ${output.error ?? output.detail ?? output.message}`,
71
71
  {
72
72
  url,
73
73
  method: info.method ?? "GET",