prompt-api-polyfill 1.3.0 → 1.4.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/README.md CHANGED
@@ -140,6 +140,17 @@ npm install prompt-api-polyfill
140
140
  apiKey: 'dummy', // Required for now by the loader
141
141
  device: 'webgpu', // 'webgpu' or 'cpu'
142
142
  dtype: 'q4f16', // Quantization level
143
+ env: {
144
+ // Optional: Pass low-level Transformers.js environment overrides
145
+ allowRemoteModels: true,
146
+ backends: {
147
+ onnx: {
148
+ wasm: {
149
+ wasmPaths: 'https://cdn.example.com/wasm-assets/',
150
+ },
151
+ },
152
+ },
153
+ },
143
154
  };
144
155
 
145
156
  if (!('LanguageModel' in window)) {
@@ -169,7 +180,7 @@ including:
169
180
  - `prompt()` and `promptStreaming()`
170
181
  - Multimodal inputs (text, image, audio)
171
182
  - `append()` and `measureContextUsage()`
172
- - Quota handling via `oncontextwindowoverflow`
183
+ - Quota handling via `oncontextoverflow`
173
184
  - `clone()` and `destroy()`
174
185
 
175
186
  A simplified version of how it is wired up:
@@ -225,6 +236,17 @@ This repo ships with a template file:
225
236
  // For Transformers.js:
226
237
  "device": "webgpu",
227
238
  "dtype": "q4f16",
239
+ // Optional library-level overrides:
240
+ "env": {
241
+ "allowRemoteModels": true,
242
+ "backends": {
243
+ "onnx": {
244
+ "wasm": {
245
+ "wasmPaths": "https://cdn.example.com/wasm-assets/",
246
+ },
247
+ },
248
+ },
249
+ },
228
250
  }
229
251
  ```
230
252
 
@@ -281,7 +303,17 @@ Then open `.env.json` and fill in the values.
281
303
  "apiKey": "dummy",
282
304
  "modelName": "onnx-community/gemma-3-1b-it-ONNX-GQA",
283
305
  "device": "webgpu",
284
- "dtype": "q4f16"
306
+ "dtype": "q4f16",
307
+ "env": {
308
+ "allowRemoteModels": false,
309
+ "backends": {
310
+ "onnx": {
311
+ "wasm": {
312
+ "wasmPaths": "https://cdn.example.com/wasm-assets/"
313
+ }
314
+ }
315
+ }
316
+ }
285
317
  }
286
318
  ```
287
319
 
@@ -304,6 +336,9 @@ Then open `.env.json` and fill in the values.
304
336
 
305
337
  - `device`: **Transformers.js only**. Either `"webgpu"` or `"cpu"`.
306
338
  - `dtype`: **Transformers.js only**. Quantization level (e.g., `"q4f16"`).
339
+ - `env` (optional): **Transformers.js only**. A flexible object to override
340
+ [Transformers.js environment variables](https://huggingface.co/docs/transformers.js/api/env).
341
+ This is useful for specifying local `wasmPaths` or proxy settings.
307
342
 
308
343
  - `modelName` (optional): The model ID to use. If not provided, the polyfill
309
344
  uses the defaults defined in [`backends/defaults.js`](backends/defaults.js).
@@ -1,6 +1,6 @@
1
1
  import { initializeApp as Fe } from "firebase/app";
2
2
  import { VertexAIBackend as ze, GoogleAIBackend as Ue, getAI as je, getGenerativeModel as Ve, InferenceMode as We } from "firebase/ai";
3
- import { P as Ke, D as Ge } from "../chunks/defaults-CNQngzSd.js";
3
+ import { P as Ke, D as Ge } from "../chunks/defaults-_qJIFiOb.js";
4
4
  const qe = () => {
5
5
  };
6
6
  const be = function(t) {
@@ -1,5 +1,5 @@
1
1
  import { GoogleGenAI as s } from "@google/genai";
2
- import { P as a, D as i } from "../chunks/defaults-CNQngzSd.js";
2
+ import { P as a, D as i } from "../chunks/defaults-_qJIFiOb.js";
3
3
  class u extends a {
4
4
  #n;
5
5
  #e;
@@ -1,5 +1,5 @@
1
1
  import u from "openai";
2
- import { P as m, D as l } from "../chunks/defaults-CNQngzSd.js";
2
+ import { P as m, D as l } from "../chunks/defaults-_qJIFiOb.js";
3
3
  class y extends m {
4
4
  #e;
5
5
  constructor(t) {
@@ -1,68 +1,74 @@
1
- import { pipeline as z, TextStreamer as C } from "@huggingface/transformers";
2
- import { P as j, D as y } from "../chunks/defaults-CNQngzSd.js";
3
- class D extends j {
1
+ import { env as j, pipeline as z, TextStreamer as C } from "@huggingface/transformers";
2
+ import { P as $, D as y } from "../chunks/defaults-_qJIFiOb.js";
3
+ class I extends $ {
4
4
  #e;
5
5
  #t;
6
- #a;
7
- #n;
6
+ #i;
8
7
  #o;
9
- constructor(n = {}) {
10
- super(n.modelName || y.transformers.modelName), this.#a = n.device || y.transformers.device, this.#n = n.dtype || y.transformers.dtype;
8
+ #n;
9
+ constructor(o = {}) {
10
+ if (super(o.modelName || y.transformers.modelName), this.#i = o.device || y.transformers.device, this.#o = o.dtype || y.transformers.dtype, o.env) {
11
+ const t = (n, a) => {
12
+ for (const [l, e] of Object.entries(a))
13
+ e && typeof e == "object" && !Array.isArray(e) && n[l] && typeof n[l] == "object" ? t(n[l], e) : n[l] = e;
14
+ };
15
+ t(j, o.env);
16
+ }
11
17
  }
12
18
  /**
13
19
  * Loaded models can be large, so we initialize them lazily.
14
20
  * @param {EventTarget} [monitorTarget] - The event target to dispatch download progress events to.
15
21
  * @returns {Promise<Object>} The generator.
16
22
  */
17
- async #s(n) {
23
+ async #s(o) {
18
24
  if (!this.#e) {
19
- const t = /* @__PURE__ */ new Map(), a = await $(this.modelName, {
20
- dtype: this.#n
25
+ const t = /* @__PURE__ */ new Map(), n = await M(this.modelName, {
26
+ dtype: this.#o
21
27
  });
22
- for (const { path: e, size: o } of a)
23
- t.set(e, { loaded: 0, total: o });
24
- const i = (e) => {
25
- if (!n)
28
+ for (const { path: e, size: r } of n)
29
+ t.set(e, { loaded: 0, total: r });
30
+ const a = (e) => {
31
+ if (!o)
26
32
  return;
27
- const o = 1 / 65536, c = Math.floor(e / o) * o;
28
- c <= n.__lastProgressLoaded || (n.dispatchEvent(
33
+ const r = 1 / 65536, c = Math.floor(e / r) * r;
34
+ c <= o.__lastProgressLoaded || (o.dispatchEvent(
29
35
  new ProgressEvent("downloadprogress", {
30
36
  loaded: c,
31
37
  total: 1,
32
38
  lengthComputable: !0
33
39
  })
34
- ), n.__lastProgressLoaded = c);
40
+ ), o.__lastProgressLoaded = c);
35
41
  }, l = (e) => {
36
42
  if (e.status === "initiate")
37
43
  if (t.has(e.file)) {
38
- const o = t.get(e.file);
39
- e.total && (o.total = e.total);
44
+ const r = t.get(e.file);
45
+ e.total && (r.total = e.total);
40
46
  } else
41
47
  t.set(e.file, { loaded: 0, total: e.total || 0 });
42
48
  else if (e.status === "progress")
43
49
  t.has(e.file) && (t.get(e.file).loaded = e.loaded);
44
50
  else if (e.status === "done") {
45
51
  if (t.has(e.file)) {
46
- const o = t.get(e.file);
47
- o.loaded = o.total;
52
+ const r = t.get(e.file);
53
+ r.loaded = r.total;
48
54
  }
49
55
  } else if (e.status === "ready") {
50
- i(1);
56
+ a(1);
51
57
  return;
52
58
  }
53
59
  if (e.status === "progress" || e.status === "done") {
54
- let o = 0, c = 0;
60
+ let r = 0, c = 0;
55
61
  for (const { loaded: f, total: d } of t.values())
56
- o += f, c += d;
62
+ r += f, c += d;
57
63
  if (c > 0) {
58
- const f = o / c;
59
- i(Math.min(f, 0.9999));
64
+ const f = r / c;
65
+ a(Math.min(f, 0.9999));
60
66
  }
61
67
  }
62
68
  };
63
- i(0), this.#e = await z("text-generation", this.modelName, {
64
- device: this.#a,
65
- dtype: this.#n,
69
+ a(0), this.#e = await z("text-generation", this.modelName, {
70
+ device: this.#i,
71
+ dtype: this.#o,
66
72
  progress_callback: l
67
73
  }), this.#t = this.#e.tokenizer;
68
74
  }
@@ -73,9 +79,9 @@ class D extends j {
73
79
  * @param {Object} options - LanguageModel options.
74
80
  * @returns {string} 'available' or 'unavailable'.
75
81
  */
76
- static availability(n) {
77
- if (n?.expectedInputs && Array.isArray(n.expectedInputs)) {
78
- for (const t of n.expectedInputs)
82
+ static availability(o) {
83
+ if (o?.expectedInputs && Array.isArray(o.expectedInputs)) {
84
+ for (const t of o.expectedInputs)
79
85
  if (t.type === "audio" || t.type === "image")
80
86
  return "unavailable";
81
87
  }
@@ -88,55 +94,55 @@ class D extends j {
88
94
  * @param {EventTarget} [monitorTarget] - The event target to dispatch download progress events to.
89
95
  * @returns {Promise<Object>} The generator.
90
96
  */
91
- async createSession(n, t, a) {
92
- return n.responseConstraint && console.warn(
97
+ async createSession(o, t, n) {
98
+ return o.responseConstraint && console.warn(
93
99
  "The `responseConstraint` flag isn't supported by the Transformers.js backend and was ignored."
94
- ), await this.#s(a), this.generationConfig = {
100
+ ), await this.#s(n), this.generationConfig = {
95
101
  max_new_tokens: 512,
96
102
  // Default limit
97
103
  temperature: t.generationConfig?.temperature ?? 1,
98
104
  top_p: 1,
99
105
  do_sample: t.generationConfig?.temperature !== 0,
100
106
  return_full_text: !1
101
- }, this.#o = t.systemInstruction, this.#e;
107
+ }, this.#n = t.systemInstruction, this.#e;
102
108
  }
103
- async generateContent(n) {
104
- const t = await this.#s(), a = this.#r(n), i = this.#t.apply_chat_template(a, {
109
+ async generateContent(o) {
110
+ const t = await this.#s(), n = this.#r(o), a = this.#t.apply_chat_template(n, {
105
111
  tokenize: !1,
106
112
  add_generation_prompt: !0
107
- }), e = (await t(i, {
113
+ }), e = (await t(a, {
108
114
  ...this.generationConfig,
109
115
  add_special_tokens: !1
110
- }))[0].generated_text, o = await this.countTokens(n);
111
- return { text: e, usage: o };
116
+ }))[0].generated_text, r = await this.countTokens(o);
117
+ return { text: e, usage: r };
112
118
  }
113
- async generateContentStream(n) {
114
- const t = await this.#s(), a = this.#r(n), i = this.#t.apply_chat_template(a, {
119
+ async generateContentStream(o) {
120
+ const t = await this.#s(), n = this.#r(o), a = this.#t.apply_chat_template(n, {
115
121
  tokenize: !1,
116
122
  add_generation_prompt: !0
117
123
  }), l = [];
118
- let e, o = new Promise((r) => e = r), c = !1;
119
- const f = (r) => {
120
- l.push(r), e && (e(), e = null);
124
+ let e, r = new Promise((i) => e = i), c = !1;
125
+ const f = (i) => {
126
+ l.push(i), e && (e(), e = null);
121
127
  }, d = new C(this.#t, {
122
128
  skip_prompt: !0,
123
129
  skip_special_tokens: !0,
124
130
  callback_function: f
125
131
  });
126
- return t(i, {
132
+ return t(a, {
127
133
  ...this.generationConfig,
128
134
  add_special_tokens: !1,
129
135
  streamer: d
130
136
  }).then(() => {
131
137
  c = !0, e && (e(), e = null);
132
- }).catch((r) => {
133
- console.error("[Transformers.js] Generation error:", r), c = !0, e && (e(), e = null);
138
+ }).catch((i) => {
139
+ console.error("[Transformers.js] Generation error:", i), c = !0, e && (e(), e = null);
134
140
  }), (async function* () {
135
141
  for (; ; ) {
136
- for (l.length === 0 && !c && (e || (o = new Promise((r) => e = r)), await o); l.length > 0; ) {
137
- const r = l.shift();
142
+ for (l.length === 0 && !c && (e || (r = new Promise((i) => e = i)), await r); l.length > 0; ) {
143
+ const i = l.shift();
138
144
  yield {
139
- text: () => r,
145
+ text: () => i,
140
146
  usageMetadata: { totalTokenCount: 0 }
141
147
  };
142
148
  }
@@ -145,67 +151,67 @@ class D extends j {
145
151
  }
146
152
  })();
147
153
  }
148
- async countTokens(n) {
154
+ async countTokens(o) {
149
155
  await this.#s();
150
- const t = this.#r(n);
156
+ const t = this.#r(o);
151
157
  return this.#t.apply_chat_template(t, {
152
158
  tokenize: !0,
153
159
  add_generation_prompt: !1,
154
160
  return_tensor: !1
155
161
  }).length;
156
162
  }
157
- #r(n) {
158
- const t = n.map((a) => {
159
- let i = a.role === "model" ? "assistant" : a.role === "system" ? "system" : "user";
160
- const l = a.parts.map((e) => e.text).join("");
161
- return { role: i, content: l };
163
+ #r(o) {
164
+ const t = o.map((n) => {
165
+ let a = n.role === "model" ? "assistant" : n.role === "system" ? "system" : "user";
166
+ const l = n.parts.map((e) => e.text).join("");
167
+ return { role: a, content: l };
162
168
  });
163
- if (this.#o && !t.some((a) => a.role === "system") && t.unshift({ role: "system", content: this.#o }), this.modelName.toLowerCase().includes("gemma")) {
164
- const a = t.findIndex((i) => i.role === "system");
165
- if (a !== -1) {
166
- const i = t[a], l = t.findIndex(
167
- (e, o) => e.role === "user" && o > a
169
+ if (this.#n && !t.some((n) => n.role === "system") && t.unshift({ role: "system", content: this.#n }), this.modelName.toLowerCase().includes("gemma")) {
170
+ const n = t.findIndex((a) => a.role === "system");
171
+ if (n !== -1) {
172
+ const a = t[n], l = t.findIndex(
173
+ (e, r) => e.role === "user" && r > n
168
174
  );
169
- l !== -1 ? (t[l].content = i.content + `
175
+ l !== -1 ? (t[l].content = a.content + `
170
176
 
171
- ` + t[l].content, t.splice(a, 1)) : (i.content += `
177
+ ` + t[l].content, t.splice(n, 1)) : (a.content += `
172
178
 
173
- `, i.role = "user");
179
+ `, a.role = "user");
174
180
  }
175
181
  }
176
182
  return t;
177
183
  }
178
184
  }
179
- async function $(g, n = {}) {
180
- const { dtype: t = "q8", branch: a = "main" } = n;
181
- let i = null;
182
- const l = `transformers_model_files_${g}_${t}_${a}`;
185
+ async function M(g, o = {}) {
186
+ const { dtype: t = "q8", branch: n = "main" } = o;
187
+ let a = null;
188
+ const l = `transformers_model_files_${g}_${t}_${n}`;
183
189
  try {
184
190
  const s = localStorage.getItem(l);
185
191
  if (s) {
186
- i = JSON.parse(s);
187
- const { timestamp: p, files: u } = i, v = 1440 * 60 * 1e3;
192
+ a = JSON.parse(s);
193
+ const { timestamp: p, files: u } = a, v = 1440 * 60 * 1e3;
188
194
  if (Date.now() - p < v)
189
195
  return u;
190
196
  }
191
197
  } catch (s) {
192
198
  console.warn("Failed to read from localStorage cache:", s);
193
199
  }
194
- const e = `https://huggingface.co/api/models/${g}/tree/${a}?recursive=true`;
195
- let o;
200
+ const e = `https://huggingface.co/api/models/${g}/tree/${n}?recursive=true`;
201
+ let r;
196
202
  try {
197
- if (o = await fetch(e), !o.ok)
198
- throw new Error(`Manifest fetch failed: ${o.status}`);
203
+ if (r = await fetch(e), !r.ok)
204
+ throw new Error(`Manifest fetch failed: ${r.status}`);
199
205
  } catch (s) {
200
- if (i)
206
+ if (a)
201
207
  return console.warn(
202
208
  "Failed to fetch manifest from network, falling back to cached data (expired):",
203
209
  s
204
- ), i.files;
210
+ ), a.files;
205
211
  throw s;
206
212
  }
207
- const c = await o.json(), f = new Map(c.map((s) => [s.path, s.size])), d = [], h = (s) => f.has(s), r = (s) => h(s) ? (d.push({ path: s, size: f.get(s) }), !0) : !1;
208
- r("config.json"), r("generation_config.json"), r("preprocessor_config.json"), h("tokenizer.json") ? (r("tokenizer.json"), r("tokenizer_config.json")) : (r("tokenizer_config.json"), r("special_tokens_map.json"), r("vocab.json"), r("merges.txt"), r("vocab.txt"));
213
+ const c = await r.json(), f = new Map(c.map((s) => [s.path, s.size])), d = [], h = (s) => f.has(s), i = (s) => h(s) ? (d.push({ path: s, size: f.get(s) }), !0) : !1;
214
+ i("config.json"), i("generation_config.json"), i("preprocessor_config.json"), h("tokenizer.json") ? (i("tokenizer.json"), i("tokenizer_config.json")) : (i("tokenizer_config.json"), i("special_tokens_map.json"), i("vocab.json"), i("merges.txt"), i("vocab.txt"));
209
215
  const w = "onnx";
210
216
  let m = [];
211
217
  t === "fp32" ? m = [""] : t === "quantized" ? m = ["_quantized"] : (m = [`_${t}`], t === "q8" && m.push(""));
@@ -228,11 +234,11 @@ async function $(g, n = {}) {
228
234
  (s) => s.includes("decoder_model_merged")
229
235
  ), b = _.filter((s) => !(x && s.includes("decoder_model") && !s.includes("merged")));
230
236
  for (const s of b) {
231
- r(s);
237
+ i(s);
232
238
  const p = `${s}_data`;
233
- if (r(p)) {
239
+ if (i(p)) {
234
240
  let u = 1;
235
- for (; r(`${p}_${u}`); )
241
+ for (; i(`${p}_${u}`); )
236
242
  u++;
237
243
  }
238
244
  }
@@ -250,5 +256,5 @@ async function $(g, n = {}) {
250
256
  return d;
251
257
  }
252
258
  export {
253
- D as default
259
+ I as default
254
260
  };
@@ -1,4 +1,4 @@
1
- class r {
1
+ class a {
2
2
  #e;
3
3
  /**
4
4
  * @param {string} modelName - The name of the model.
@@ -49,9 +49,9 @@ class r {
49
49
  throw new Error("Not implemented");
50
50
  }
51
51
  }
52
- const a = {
52
+ const r = {
53
53
  firebase: { modelName: "gemini-2.5-flash-lite" },
54
- gemini: { modelName: "gemini-2.0-flash-lite-preview-02-05" },
54
+ gemini: { modelName: "gemini-2.5-flash-lite" },
55
55
  openai: { modelName: "gpt-4o" },
56
56
  transformers: {
57
57
  modelName: "onnx-community/gemma-3-1b-it-ONNX-GQA",
@@ -60,6 +60,6 @@ const a = {
60
60
  }
61
61
  };
62
62
  export {
63
- a as D,
64
- r as P
63
+ r as D,
64
+ a as P
65
65
  };
@@ -283,7 +283,7 @@ async function C(s, t = globalThis) {
283
283
  }
284
284
  return e;
285
285
  }
286
- class h extends EventTarget {
286
+ class d extends EventTarget {
287
287
  #o;
288
288
  #f;
289
289
  #r;
@@ -302,16 +302,16 @@ class h extends EventTarget {
302
302
  get contextWindow() {
303
303
  return 1e6;
304
304
  }
305
- get oncontextwindowoverflow() {
305
+ get oncontextoverflow() {
306
306
  return this.#c;
307
307
  }
308
- set oncontextwindowoverflow(t) {
308
+ set oncontextoverflow(t) {
309
309
  this.#c && this.removeEventListener(
310
- "contextwindowoverflow",
310
+ "contextoverflow",
311
311
  this.#c
312
- ), this.#c = t, typeof t == "function" && this.addEventListener("contextwindowoverflow", t);
312
+ ), this.#c = t, typeof t == "function" && this.addEventListener("contextoverflow", t);
313
313
  }
314
- static #d(t) {
314
+ static #h(t) {
315
315
  try {
316
316
  if (!t || !t.document || t.document.defaultView !== t)
317
317
  throw new Error();
@@ -326,13 +326,13 @@ class h extends EventTarget {
326
326
  }
327
327
  }
328
328
  #a() {
329
- h.#d(this.#t);
329
+ d.#h(this.#t);
330
330
  }
331
331
  static async availability(t = {}) {
332
332
  const e = this.__window || globalThis;
333
- h.#d(e);
333
+ d.#h(e);
334
334
  try {
335
- await h.#w(t, e);
335
+ await d.#w(t, e);
336
336
  } catch (o) {
337
337
  if (o instanceof RangeError) {
338
338
  if (o.message.includes("language tag"))
@@ -348,23 +348,23 @@ class h extends EventTarget {
348
348
  }
349
349
  return "unavailable";
350
350
  }
351
- return (await h.#p(e)).availability(t);
351
+ return (await d.#p(e)).availability(t);
352
352
  }
353
353
  static #x = A;
354
- static #h(t = globalThis) {
355
- for (const r of h.#x) {
354
+ static #d(t = globalThis) {
355
+ for (const r of d.#x) {
356
356
  const o = t[r.config] || globalThis[r.config];
357
357
  if (o && o.apiKey)
358
358
  return { ...r, configValue: o };
359
359
  }
360
- const e = h.#x.map((r) => `window.${r.config}`).join(", ");
360
+ const e = d.#x.map((r) => `window.${r.config}`).join(", ");
361
361
  throw new (t.DOMException || globalThis.DOMException)(
362
362
  `Prompt API Polyfill: No backend configuration found. Please set one of: ${e}.`,
363
363
  "NotSupportedError"
364
364
  );
365
365
  }
366
366
  static async #p(t = globalThis) {
367
- const e = h.#h(t);
367
+ const e = d.#d(t);
368
368
  return I(e.path);
369
369
  }
370
370
  static async #w(t = {}, e = globalThis) {
@@ -372,13 +372,13 @@ class h extends EventTarget {
372
372
  for (const o of t.expectedInputs) {
373
373
  if (o.type !== "text" && o.type !== "image" && o.type !== "audio")
374
374
  throw new TypeError(`Invalid input type: ${o.type}`);
375
- o.languages && h.#y(o.languages);
375
+ o.languages && d.#y(o.languages);
376
376
  }
377
377
  if (t.expectedOutputs)
378
378
  for (const o of t.expectedOutputs) {
379
379
  if (o.type !== "text")
380
380
  throw new RangeError(`Unsupported output type: ${o.type}`);
381
- o.languages && h.#y(o.languages);
381
+ o.languages && d.#y(o.languages);
382
382
  }
383
383
  const r = t.expectedInputs ? ["text", ...t.expectedInputs.map((o) => o.type)] : ["text"];
384
384
  if (t.initialPrompts && Array.isArray(t.initialPrompts)) {
@@ -434,7 +434,7 @@ class h extends EventTarget {
434
434
  }
435
435
  static async create(t = {}) {
436
436
  const e = this.__window || globalThis;
437
- if (h.#d(e), await h.#w(t, e), t.signal?.aborted)
437
+ if (d.#h(e), await d.#w(t, e), t.signal?.aborted)
438
438
  throw t.signal.reason || new (e.DOMException || globalThis.DOMException)(
439
439
  "Aborted",
440
440
  "AbortError"
@@ -455,8 +455,8 @@ class h extends EventTarget {
455
455
  "Aborted",
456
456
  "AbortError"
457
457
  );
458
- const o = h.#h(e), n = await h.#p(e), i = new n(o.configValue), c = { ...t };
459
- h.#g(
458
+ const o = d.#d(e), n = await d.#p(e), i = new n(o.configValue), c = { ...t };
459
+ d.#g(
460
460
  c.responseConstraint,
461
461
  e
462
462
  );
@@ -471,16 +471,16 @@ class h extends EventTarget {
471
471
  ), p = c.initialPrompts.filter(
472
472
  (f) => f.role !== "system"
473
473
  );
474
- w.length > 0 && (a.systemInstruction = w.map((f) => typeof f.content == "string" ? f.content : Array.isArray(f.content) ? f.content.filter((d) => d.type === "text").map((d) => d.value || d.text || "").join(`
474
+ w.length > 0 && (a.systemInstruction = w.map((f) => typeof f.content == "string" ? f.content : Array.isArray(f.content) ? f.content.filter((h) => h.type === "text").map((h) => h.value || h.text || "").join(`
475
475
  `) : "").join(`
476
476
  `)), l = await C(p, e);
477
477
  for (const f of c.initialPrompts) {
478
478
  if (typeof f.content != "string")
479
479
  continue;
480
- const d = h.#E([
480
+ const h = d.#E([
481
481
  { text: f.content }
482
482
  ]);
483
- if (d === "QuotaExceededError" || d === "contextwindowoverflow") {
483
+ if (h === "QuotaExceededError" || h === "contextoverflow") {
484
484
  const E = e.QuotaExceededError || e.DOMException || globalThis.QuotaExceededError || globalThis.DOMException, u = new E(
485
485
  "The initial prompts are too large, they exceed the quota.",
486
486
  "QuotaExceededError"
@@ -489,7 +489,7 @@ class h extends EventTarget {
489
489
  value: 22,
490
490
  configurable: !0
491
491
  });
492
- const g = d === "QuotaExceededError" ? 1e7 : 5e5;
492
+ const g = h === "QuotaExceededError" ? 1e7 : 5e5;
493
493
  throw u.requested = g, u.quota = 1e6, u;
494
494
  }
495
495
  }
@@ -518,10 +518,10 @@ class h extends EventTarget {
518
518
  lengthComputable: !0
519
519
  })
520
520
  ), x.__lastProgressLoaded = f;
521
- } catch (d) {
522
- console.error("Error dispatching downloadprogress events:", d);
521
+ } catch (h) {
522
+ console.error("Error dispatching downloadprogress events:", h);
523
523
  }
524
- return await new Promise((d) => setTimeout(d, 0)), !t.signal?.aborted;
524
+ return await new Promise((h) => setTimeout(h, 0)), !t.signal?.aborted;
525
525
  };
526
526
  if (!await b(0))
527
527
  throw t.signal.reason || new (e.DOMException || globalThis.DOMException)(
@@ -573,7 +573,7 @@ class h extends EventTarget {
573
573
  "Aborted",
574
574
  "AbortError"
575
575
  );
576
- const e = JSON.parse(JSON.stringify(this.#r)), r = { ...this.#s, ...t }, o = await h.#p(this.#t), n = h.#h(this.#t), i = new o(n.configValue), c = await i.createSession(
576
+ const e = JSON.parse(JSON.stringify(this.#r)), r = { ...this.#s, ...t }, o = await d.#p(this.#t), n = d.#d(this.#t), i = new o(n.configValue), c = await i.createSession(
577
577
  r,
578
578
  this.#e
579
579
  );
@@ -609,7 +609,7 @@ class h extends EventTarget {
609
609
  if (typeof t == "object" && t !== null && !Array.isArray(t) && Object.keys(t).length === 0)
610
610
  return "[object Object]";
611
611
  if (e.responseConstraint) {
612
- h.#g(
612
+ d.#g(
613
613
  e.responseConstraint,
614
614
  this.#t
615
615
  );
@@ -652,15 +652,15 @@ class h extends EventTarget {
652
652
  }), c = (async () => {
653
653
  const a = this.#u(o);
654
654
  if (a === "QuotaExceededError") {
655
- const f = this.#t && this.#t.QuotaExceededError || this.#t && this.#t.DOMException || globalThis.QuotaExceededError || globalThis.DOMException, d = new f(
655
+ const f = this.#t && this.#t.QuotaExceededError || this.#t && this.#t.DOMException || globalThis.QuotaExceededError || globalThis.DOMException, h = new f(
656
656
  "The prompt is too large, it exceeds the quota.",
657
657
  "QuotaExceededError"
658
658
  );
659
- Object.defineProperty(d, "code", { value: 22, configurable: !0 });
659
+ Object.defineProperty(h, "code", { value: 22, configurable: !0 });
660
660
  const E = 1e7;
661
- throw d.requested = E, d.quota = this.contextWindow, d;
662
- } else if (a === "contextwindowoverflow")
663
- return this.dispatchEvent(new Event("contextwindowoverflow")), "Mock response for quota overflow test.";
661
+ throw h.requested = E, h.quota = this.contextWindow, h;
662
+ } else if (a === "contextoverflow")
663
+ return this.dispatchEvent(new Event("contextoverflow")), "Mock response for quota overflow test.";
664
664
  const l = [...this.#r, n];
665
665
  this.#e.systemInstruction && l.unshift({
666
666
  role: "system",
@@ -670,13 +670,13 @@ class h extends EventTarget {
670
670
  l
671
671
  );
672
672
  if (y > this.contextWindow) {
673
- const f = this.#t && this.#t.QuotaExceededError || this.#t && this.#t.DOMException || globalThis.QuotaExceededError || globalThis.DOMException, d = new f(
673
+ const f = this.#t && this.#t.QuotaExceededError || this.#t && this.#t.DOMException || globalThis.QuotaExceededError || globalThis.DOMException, h = new f(
674
674
  `The prompt is too large (${y} tokens), it exceeds the quota of ${this.contextWindow} tokens.`,
675
675
  "QuotaExceededError"
676
676
  );
677
- throw Object.defineProperty(d, "code", { value: 22, configurable: !0 }), d.requested = y, d.quota = this.contextWindow, d;
677
+ throw Object.defineProperty(h, "code", { value: 22, configurable: !0 }), h.requested = y, h.quota = this.contextWindow, h;
678
678
  }
679
- y > this.contextWindow && this.dispatchEvent(new Event("contextwindowoverflow"));
679
+ y > this.contextWindow && this.dispatchEvent(new Event("contextoverflow"));
680
680
  const x = [...this.#r, n];
681
681
  let b;
682
682
  try {
@@ -737,7 +737,7 @@ class h extends EventTarget {
737
737
  o && o.addEventListener("abort", c);
738
738
  try {
739
739
  if (e.responseConstraint) {
740
- h.#g(
740
+ d.#g(
741
741
  e.responseConstraint,
742
742
  r.#t
743
743
  );
@@ -767,8 +767,8 @@ class h extends EventTarget {
767
767
  });
768
768
  const O = 1e7;
769
769
  throw g.requested = O, g.quota = r.contextWindow, g;
770
- } else if (x === "contextwindowoverflow") {
771
- r.dispatchEvent(new Event("contextwindowoverflow")), n.enqueue("Mock response for quota overflow test."), n.close();
770
+ } else if (x === "contextoverflow") {
771
+ r.dispatchEvent(new Event("contextoverflow")), n.enqueue("Mock response for quota overflow test."), n.close();
772
772
  return;
773
773
  }
774
774
  const b = [...r.#r, y];
@@ -789,7 +789,7 @@ class h extends EventTarget {
789
789
  configurable: !0
790
790
  }), g.requested = m, g.quota = r.contextWindow, g;
791
791
  }
792
- m > r.contextWindow && r.dispatchEvent(new Event("contextwindowoverflow"));
792
+ m > r.contextWindow && r.dispatchEvent(new Event("contextoverflow"));
793
793
  const w = [...r.#r, y];
794
794
  let p;
795
795
  try {
@@ -797,20 +797,20 @@ class h extends EventTarget {
797
797
  } catch (u) {
798
798
  throw r.#m(u, l), u;
799
799
  }
800
- let f = "", d = !1, E = "";
800
+ let f = "", h = !1, E = "";
801
801
  for await (const u of p) {
802
802
  if (i) {
803
803
  typeof p.return == "function" && await p.return();
804
804
  return;
805
805
  }
806
806
  let g = u.text();
807
- if (a && !d) {
807
+ if (a && !h) {
808
808
  E += g;
809
809
  const O = E.match(/^\s*{\s*"Rating"\s*:\s*/);
810
810
  if (O)
811
- g = E.slice(O[0].length), d = !0, E = "";
811
+ g = E.slice(O[0].length), h = !0, E = "";
812
812
  else if (E.length > 50)
813
- g = E, d = !0, E = "";
813
+ g = E, h = !0, E = "";
814
814
  else
815
815
  continue;
816
816
  }
@@ -857,7 +857,7 @@ class h extends EventTarget {
857
857
  this.#i = i || 0;
858
858
  } catch {
859
859
  }
860
- this.#i > this.contextWindow && this.dispatchEvent(new Event("contextwindowoverflow"));
860
+ this.#i > this.contextWindow && this.dispatchEvent(new Event("contextoverflow"));
861
861
  }
862
862
  async measureContextUsage(t) {
863
863
  if (this.#a(), this.#n)
@@ -873,7 +873,7 @@ class h extends EventTarget {
873
873
  "InvalidStateError"
874
874
  );
875
875
  const r = this.#u(e);
876
- return r === "QuotaExceededError" ? 1e7 : r === "contextwindowoverflow" ? 5e5 : await this.#o.countTokens([
876
+ return r === "QuotaExceededError" ? 1e7 : r === "contextoverflow" ? 5e5 : await this.#o.countTokens([
877
877
  { role: "user", parts: e }
878
878
  ]) || 0;
879
879
  } catch {
@@ -884,13 +884,13 @@ class h extends EventTarget {
884
884
  }
885
885
  // Volkswagen mode detection to avoid cloud costs for WPT tests.
886
886
  #u(t) {
887
- return h.#E(t);
887
+ return d.#E(t);
888
888
  }
889
889
  static #E(t) {
890
890
  if (t.length !== 1 || !t[0].text)
891
891
  return null;
892
892
  const e = t[0].text;
893
- return typeof e != "string" || !e.startsWith("Please write a sentence in English.") ? null : e.length > 1e7 ? "QuotaExceededError" : e.length > 5e4 ? "contextwindowoverflow" : null;
893
+ return typeof e != "string" || !e.startsWith("Please write a sentence in English.") ? null : e.length > 1e7 ? "QuotaExceededError" : e.length > 5e4 ? "contextoverflow" : null;
894
894
  }
895
895
  static #g(t, e) {
896
896
  if (t)
@@ -1003,7 +1003,7 @@ const D = (s) => {
1003
1003
  try {
1004
1004
  if (!s || s.LanguageModel?.__isPolyfill)
1005
1005
  return;
1006
- const t = class extends h {
1006
+ const t = class extends d {
1007
1007
  };
1008
1008
  t.__window = s, t.__isPolyfill = !0, s.LanguageModel = t, s.DOMException && (s.QuotaExceededError = s.DOMException);
1009
1009
  } catch {
@@ -1037,9 +1037,9 @@ globalThis.document?.documentElement && (P.observe(globalThis.document.documentE
1037
1037
  }), globalThis.document.querySelectorAll("iframe").forEach((s) => {
1038
1038
  D(s.contentWindow);
1039
1039
  }));
1040
- (!("LanguageModel" in globalThis) || globalThis.__FORCE_PROMPT_API_POLYFILL__) && (globalThis.LanguageModel = h, h.__isPolyfill = !0, console.log(
1040
+ (!("LanguageModel" in globalThis) || globalThis.__FORCE_PROMPT_API_POLYFILL__) && (globalThis.LanguageModel = d, d.__isPolyfill = !0, console.log(
1041
1041
  "Polyfill: window.LanguageModel is now backed by the Prompt API polyfill."
1042
1042
  ));
1043
1043
  export {
1044
- h as LanguageModel
1044
+ d as LanguageModel
1045
1045
  };
package/dot_env.json CHANGED
@@ -7,5 +7,15 @@
7
7
  "reCaptchaSiteKey": "",
8
8
  "useLimitedUseAppCheckTokens": true,
9
9
  "device": "webgpu",
10
- "dtype": "q4f16"
10
+ "dtype": "q4f16",
11
+ "env": {
12
+ "allowRemoteModels": true,
13
+ "backends": {
14
+ "onnx": {
15
+ "wasm": {
16
+ "wasmPaths": ""
17
+ }
18
+ }
19
+ }
20
+ }
11
21
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prompt-api-polyfill",
3
- "version": "1.3.0",
3
+ "version": "1.4.0",
4
4
  "description": "Polyfill for the Prompt API (`LanguageModel`) backed by Firebase AI Logic, Gemini API, OpenAI API, or Transformers.js.",
5
5
  "type": "module",
6
6
  "main": "./dist/prompt-api-polyfill.js",
@@ -47,7 +47,9 @@
47
47
  "devDependencies": {
48
48
  "prettier": "^3.8.1",
49
49
  "prettier-plugin-curly": "^0.4.1",
50
- "vite": "^7.3.1"
50
+ "vite": "^7.3.1",
51
+ "node-gyp": "^12.2.0",
52
+ "node-addon-api": "^8.5.0"
51
53
  },
52
54
  "dependencies": {
53
55
  "@google/genai": "^1.42.0",