prompt-api-polyfill 1.3.1 → 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 +1 -1
- package/dist/prompt-api-polyfill.js +51 -51
- package/dot_env.json +11 -1
- package/package.json +4 -2
package/README.md
CHANGED
|
@@ -180,7 +180,7 @@ including:
|
|
|
180
180
|
- `prompt()` and `promptStreaming()`
|
|
181
181
|
- Multimodal inputs (text, image, audio)
|
|
182
182
|
- `append()` and `measureContextUsage()`
|
|
183
|
-
- Quota handling via `
|
|
183
|
+
- Quota handling via `oncontextoverflow`
|
|
184
184
|
- `clone()` and `destroy()`
|
|
185
185
|
|
|
186
186
|
A simplified version of how it is wired up:
|
|
@@ -283,7 +283,7 @@ async function C(s, t = globalThis) {
|
|
|
283
283
|
}
|
|
284
284
|
return e;
|
|
285
285
|
}
|
|
286
|
-
class
|
|
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
|
|
305
|
+
get oncontextoverflow() {
|
|
306
306
|
return this.#c;
|
|
307
307
|
}
|
|
308
|
-
set
|
|
308
|
+
set oncontextoverflow(t) {
|
|
309
309
|
this.#c && this.removeEventListener(
|
|
310
|
-
"
|
|
310
|
+
"contextoverflow",
|
|
311
311
|
this.#c
|
|
312
|
-
), this.#c = t, typeof t == "function" && this.addEventListener("
|
|
312
|
+
), this.#c = t, typeof t == "function" && this.addEventListener("contextoverflow", t);
|
|
313
313
|
}
|
|
314
|
-
static #
|
|
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
|
|
329
|
+
d.#h(this.#t);
|
|
330
330
|
}
|
|
331
331
|
static async availability(t = {}) {
|
|
332
332
|
const e = this.__window || globalThis;
|
|
333
|
-
h
|
|
333
|
+
d.#h(e);
|
|
334
334
|
try {
|
|
335
|
-
await
|
|
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
|
|
351
|
+
return (await d.#p(e)).availability(t);
|
|
352
352
|
}
|
|
353
353
|
static #x = A;
|
|
354
|
-
static #
|
|
355
|
-
for (const r of
|
|
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 =
|
|
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 =
|
|
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 &&
|
|
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 &&
|
|
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
|
|
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 =
|
|
459
|
-
|
|
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((
|
|
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
|
|
480
|
+
const h = d.#E([
|
|
481
481
|
{ text: f.content }
|
|
482
482
|
]);
|
|
483
|
-
if (
|
|
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 =
|
|
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 (
|
|
522
|
-
console.error("Error dispatching downloadprogress events:",
|
|
521
|
+
} catch (h) {
|
|
522
|
+
console.error("Error dispatching downloadprogress events:", h);
|
|
523
523
|
}
|
|
524
|
-
return await new Promise((
|
|
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
|
|
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
|
-
|
|
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,
|
|
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(
|
|
659
|
+
Object.defineProperty(h, "code", { value: 22, configurable: !0 });
|
|
660
660
|
const E = 1e7;
|
|
661
|
-
throw
|
|
662
|
-
} else if (a === "
|
|
663
|
-
return this.dispatchEvent(new Event("
|
|
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,
|
|
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(
|
|
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("
|
|
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
|
-
|
|
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 === "
|
|
771
|
-
r.dispatchEvent(new Event("
|
|
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("
|
|
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 = "",
|
|
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 && !
|
|
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),
|
|
811
|
+
g = E.slice(O[0].length), h = !0, E = "";
|
|
812
812
|
else if (E.length > 50)
|
|
813
|
-
g = 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("
|
|
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 === "
|
|
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
|
|
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 ? "
|
|
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
|
|
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 =
|
|
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
|
-
|
|
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
|
+
"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",
|