prompt-api-polyfill 1.2.2 → 1.3.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.
- package/README.md +26 -23
- package/dist/prompt-api-polyfill.js +232 -227
- package/dot_env.json +1 -11
- package/package.json +4 -3
package/README.md
CHANGED
|
@@ -179,8 +179,8 @@ including:
|
|
|
179
179
|
- `LanguageModel.create()` with options
|
|
180
180
|
- `prompt()` and `promptStreaming()`
|
|
181
181
|
- Multimodal inputs (text, image, audio)
|
|
182
|
-
- `append()` and `
|
|
183
|
-
- Quota handling via `
|
|
182
|
+
- `append()` and `measureContextUsage()`
|
|
183
|
+
- Quota handling via `oncontextwindowoverflow`
|
|
184
184
|
- `clone()` and `destroy()`
|
|
185
185
|
|
|
186
186
|
A simplified version of how it is wired up:
|
|
@@ -236,18 +236,17 @@ This repo ships with a template file:
|
|
|
236
236
|
// For Transformers.js:
|
|
237
237
|
"device": "webgpu",
|
|
238
238
|
"dtype": "q4f16",
|
|
239
|
-
|
|
240
239
|
// Optional library-level overrides:
|
|
241
240
|
"env": {
|
|
242
241
|
"allowRemoteModels": true,
|
|
243
242
|
"backends": {
|
|
244
243
|
"onnx": {
|
|
245
244
|
"wasm": {
|
|
246
|
-
"wasmPaths": "https://cdn.example.com/wasm-assets/"
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
}
|
|
245
|
+
"wasmPaths": "https://cdn.example.com/wasm-assets/",
|
|
246
|
+
},
|
|
247
|
+
},
|
|
248
|
+
},
|
|
249
|
+
},
|
|
251
250
|
}
|
|
252
251
|
```
|
|
253
252
|
|
|
@@ -460,21 +459,17 @@ export default class CustomBackend extends PolyfillBackend {
|
|
|
460
459
|
|
|
461
460
|
### Register your backend
|
|
462
461
|
|
|
463
|
-
The polyfill uses
|
|
464
|
-
|
|
465
|
-
file by adding it to the static `#backends` array:
|
|
462
|
+
The polyfill uses an automated registration strategy. To register your new
|
|
463
|
+
backend, simply run the registration script:
|
|
466
464
|
|
|
467
|
-
```
|
|
468
|
-
|
|
469
|
-
static #backends = [
|
|
470
|
-
// ... existing backends
|
|
471
|
-
{
|
|
472
|
-
config: 'CUSTOM_CONFIG', // The global object to look for on `window`
|
|
473
|
-
path: './backends/custom.js',
|
|
474
|
-
},
|
|
475
|
-
];
|
|
465
|
+
```bash
|
|
466
|
+
npm run generate:registry
|
|
476
467
|
```
|
|
477
468
|
|
|
469
|
+
This updates the `backends-registry.js` file, which the polyfill imports. The
|
|
470
|
+
registry contains the configuration mapping and a dynamic loader that ensures
|
|
471
|
+
compatibility with bundlers and CDNs.
|
|
472
|
+
|
|
478
473
|
### Set a default model
|
|
479
474
|
|
|
480
475
|
Define the fallback model identity in `backends/defaults.js`. This is used when
|
|
@@ -490,9 +485,11 @@ export const DEFAULT_MODELS = {
|
|
|
490
485
|
|
|
491
486
|
### Enable local development and testing
|
|
492
487
|
|
|
493
|
-
The project uses a discovery script (`scripts/
|
|
494
|
-
test matrices
|
|
495
|
-
`.env-[name].json`
|
|
488
|
+
The project uses a discovery script (`scripts/backend-discovery.js`) to generate
|
|
489
|
+
test matrices and list active backends based on the presence of
|
|
490
|
+
`.env-[name].json` files. To include your new backend in the test runner, create
|
|
491
|
+
a `.env-[name].json` file (for example, `.env-custom.json`) in the root
|
|
492
|
+
directory:
|
|
496
493
|
|
|
497
494
|
```json
|
|
498
495
|
{
|
|
@@ -501,6 +498,12 @@ test matrices. To include your new backend in the test runner, create a
|
|
|
501
498
|
}
|
|
502
499
|
```
|
|
503
500
|
|
|
501
|
+
Then run the WPT generation script:
|
|
502
|
+
|
|
503
|
+
```bash
|
|
504
|
+
npm run generate:wpt
|
|
505
|
+
```
|
|
506
|
+
|
|
504
507
|
### Verify via Web Platform Tests (WPT)
|
|
505
508
|
|
|
506
509
|
The final step is ensuring compliance. Because the polyfill is spec-driven, any
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import { Schema as T } from "firebase/ai";
|
|
2
2
|
ReadableStream.prototype[Symbol.asyncIterator] || (ReadableStream.prototype[Symbol.asyncIterator] = async function* () {
|
|
3
|
-
const
|
|
3
|
+
const s = this.getReader();
|
|
4
4
|
try {
|
|
5
5
|
for (; ; ) {
|
|
6
|
-
const { done: t, value: e } = await
|
|
6
|
+
const { done: t, value: e } = await s.read();
|
|
7
7
|
if (t)
|
|
8
8
|
return;
|
|
9
9
|
yield e;
|
|
10
10
|
}
|
|
11
11
|
} finally {
|
|
12
|
-
|
|
12
|
+
s.releaseLock();
|
|
13
13
|
}
|
|
14
14
|
});
|
|
15
15
|
class M {
|
|
@@ -110,21 +110,21 @@ class M {
|
|
|
110
110
|
static async canvasSourceToInlineData(t) {
|
|
111
111
|
typeof HTMLImageElement < "u" && t instanceof HTMLImageElement && !t.complete && await t.decode().catch(() => {
|
|
112
112
|
});
|
|
113
|
-
const e = (
|
|
114
|
-
const
|
|
115
|
-
return typeof
|
|
113
|
+
const e = (a) => {
|
|
114
|
+
const l = t[a];
|
|
115
|
+
return typeof l == "object" && l !== null && "baseVal" in l ? l.baseVal.value : typeof l == "number" ? l : 0;
|
|
116
116
|
};
|
|
117
117
|
let r = t.displayWidth || t.naturalWidth || t.videoWidth || e("width"), o = t.displayHeight || t.naturalHeight || t.videoHeight || e("height");
|
|
118
118
|
if ((!r || !o) && typeof t.getBBox == "function")
|
|
119
119
|
try {
|
|
120
|
-
const
|
|
121
|
-
r = r ||
|
|
120
|
+
const a = t.getBBox();
|
|
121
|
+
r = r || a.width, o = o || a.height;
|
|
122
122
|
} catch {
|
|
123
123
|
}
|
|
124
124
|
if ((!r || !o) && typeof t.getBoundingClientRect == "function")
|
|
125
125
|
try {
|
|
126
|
-
const
|
|
127
|
-
r = r ||
|
|
126
|
+
const a = t.getBoundingClientRect();
|
|
127
|
+
r = r || a.width, o = o || a.height;
|
|
128
128
|
} catch {
|
|
129
129
|
}
|
|
130
130
|
if (!r || !o)
|
|
@@ -163,8 +163,8 @@ class M {
|
|
|
163
163
|
return o;
|
|
164
164
|
}
|
|
165
165
|
static encodeWAV(t, e, r, o, n) {
|
|
166
|
-
const i = n / 8,
|
|
167
|
-
return this.writeString(
|
|
166
|
+
const i = n / 8, c = o * i, a = new ArrayBuffer(44 + t.length * i), l = new DataView(a);
|
|
167
|
+
return this.writeString(l, 0, "RIFF"), l.setUint32(4, 36 + t.length * i, !0), this.writeString(l, 8, "WAVE"), this.writeString(l, 12, "fmt "), l.setUint32(16, 16, !0), l.setUint16(20, e, !0), l.setUint16(22, o, !0), l.setUint32(24, r, !0), l.setUint32(28, r * c, !0), l.setUint16(32, c, !0), l.setUint16(34, n, !0), this.writeString(l, 36, "data"), l.setUint32(40, t.length * i, !0), this.floatTo16BitPCM(l, 44, t), a;
|
|
168
168
|
}
|
|
169
169
|
static floatTo16BitPCM(t, e, r) {
|
|
170
170
|
for (let o = 0; o < r.length; o++, e += 2) {
|
|
@@ -177,19 +177,19 @@ class M {
|
|
|
177
177
|
t.setUint8(e + o, r.charCodeAt(o));
|
|
178
178
|
}
|
|
179
179
|
}
|
|
180
|
-
function v(
|
|
181
|
-
if (!
|
|
180
|
+
function v(s) {
|
|
181
|
+
if (!s)
|
|
182
182
|
return;
|
|
183
183
|
const t = {
|
|
184
|
-
description:
|
|
185
|
-
nullable:
|
|
186
|
-
format:
|
|
184
|
+
description: s.description,
|
|
185
|
+
nullable: s.nullable || !1,
|
|
186
|
+
format: s.format
|
|
187
187
|
};
|
|
188
|
-
switch (Array.isArray(
|
|
188
|
+
switch (Array.isArray(s.type) && s.type.includes("null") && (t.nullable = !0, s.type = s.type.find((e) => e !== "null")), s.type) {
|
|
189
189
|
case "string":
|
|
190
|
-
return
|
|
190
|
+
return s.enum && Array.isArray(s.enum) ? T.enumString({
|
|
191
191
|
...t,
|
|
192
|
-
enum:
|
|
192
|
+
enum: s.enum
|
|
193
193
|
}) : T.string(t);
|
|
194
194
|
case "number":
|
|
195
195
|
return T.number(t);
|
|
@@ -201,16 +201,16 @@ function v(l) {
|
|
|
201
201
|
return T.array({
|
|
202
202
|
...t,
|
|
203
203
|
// Recursively convert the 'items' schema
|
|
204
|
-
items: v(
|
|
204
|
+
items: v(s.items)
|
|
205
205
|
});
|
|
206
206
|
case "object":
|
|
207
|
-
const e = {}, r =
|
|
207
|
+
const e = {}, r = s.properties ? Object.keys(s.properties) : [];
|
|
208
208
|
r.forEach((i) => {
|
|
209
209
|
e[i] = v(
|
|
210
|
-
|
|
210
|
+
s.properties[i]
|
|
211
211
|
);
|
|
212
212
|
});
|
|
213
|
-
const o =
|
|
213
|
+
const o = s.required || [], n = r.filter(
|
|
214
214
|
(i) => !o.includes(i)
|
|
215
215
|
);
|
|
216
216
|
return T.object({
|
|
@@ -220,33 +220,62 @@ function v(l) {
|
|
|
220
220
|
});
|
|
221
221
|
default:
|
|
222
222
|
return console.warn(
|
|
223
|
-
`Unsupported type: ${
|
|
223
|
+
`Unsupported type: ${s.type}, defaulting to string.`
|
|
224
224
|
), T.string(t);
|
|
225
225
|
}
|
|
226
226
|
}
|
|
227
|
-
|
|
227
|
+
const A = [
|
|
228
|
+
{
|
|
229
|
+
config: "FIREBASE_CONFIG",
|
|
230
|
+
path: "./backends/firebase.js"
|
|
231
|
+
},
|
|
232
|
+
{
|
|
233
|
+
config: "GEMINI_CONFIG",
|
|
234
|
+
path: "./backends/gemini.js"
|
|
235
|
+
},
|
|
236
|
+
{
|
|
237
|
+
config: "OPENAI_CONFIG",
|
|
238
|
+
path: "./backends/openai.js"
|
|
239
|
+
},
|
|
240
|
+
{
|
|
241
|
+
config: "TRANSFORMERS_CONFIG",
|
|
242
|
+
path: "./backends/transformers.js"
|
|
243
|
+
}
|
|
244
|
+
];
|
|
245
|
+
async function I(s) {
|
|
246
|
+
if (s === "./backends/firebase.js")
|
|
247
|
+
return (await import("./backends/firebase.js")).default;
|
|
248
|
+
if (s === "./backends/gemini.js")
|
|
249
|
+
return (await import("./backends/gemini.js")).default;
|
|
250
|
+
if (s === "./backends/openai.js")
|
|
251
|
+
return (await import("./backends/openai.js")).default;
|
|
252
|
+
if (s === "./backends/transformers.js")
|
|
253
|
+
return (await import("./backends/transformers.js")).default;
|
|
254
|
+
throw new Error(`Unknown backend path "${s}"`);
|
|
255
|
+
}
|
|
256
|
+
async function C(s, t = globalThis) {
|
|
228
257
|
const e = [];
|
|
229
|
-
for (const r of
|
|
258
|
+
for (const r of s) {
|
|
230
259
|
const o = r.role === "assistant" ? "model" : "user", n = o === "model";
|
|
231
260
|
let i = [];
|
|
232
261
|
if (Array.isArray(r.content))
|
|
233
|
-
for (const
|
|
234
|
-
if (
|
|
235
|
-
const
|
|
236
|
-
if (typeof
|
|
262
|
+
for (const c of r.content)
|
|
263
|
+
if (c.type === "text") {
|
|
264
|
+
const a = c.value || c.text || "";
|
|
265
|
+
if (typeof a != "string")
|
|
237
266
|
throw new (t.DOMException || globalThis.DOMException)(
|
|
238
267
|
'The content type "text" must have a string value.',
|
|
239
268
|
"SyntaxError"
|
|
240
269
|
);
|
|
241
|
-
i.push({ text:
|
|
270
|
+
i.push({ text: a });
|
|
242
271
|
} else {
|
|
243
272
|
if (n)
|
|
244
273
|
throw new (t.DOMException || globalThis.DOMException)(
|
|
245
274
|
"Assistant messages only support text content.",
|
|
246
275
|
"NotSupportedError"
|
|
247
276
|
);
|
|
248
|
-
const
|
|
249
|
-
i.push(
|
|
277
|
+
const a = await M.convert(c.type, c.value);
|
|
278
|
+
i.push(a);
|
|
250
279
|
}
|
|
251
280
|
else
|
|
252
281
|
i.push({ text: r.content });
|
|
@@ -254,7 +283,7 @@ async function I(l, t = globalThis) {
|
|
|
254
283
|
}
|
|
255
284
|
return e;
|
|
256
285
|
}
|
|
257
|
-
class
|
|
286
|
+
class h extends EventTarget {
|
|
258
287
|
#o;
|
|
259
288
|
#f;
|
|
260
289
|
#r;
|
|
@@ -262,24 +291,27 @@ class d extends EventTarget {
|
|
|
262
291
|
#e;
|
|
263
292
|
#n;
|
|
264
293
|
#i;
|
|
265
|
-
#
|
|
294
|
+
#c;
|
|
266
295
|
#t;
|
|
267
|
-
constructor(t, e, r, o = {}, n, i = 0,
|
|
268
|
-
super(), this.#o = t, this.#f = e, this.#r = r || [], this.#s = o, this.#e = n, this.#n = !1, this.#i = i, this.#
|
|
296
|
+
constructor(t, e, r, o = {}, n, i = 0, c = globalThis) {
|
|
297
|
+
super(), this.#o = t, this.#f = e, this.#r = r || [], this.#s = o, this.#e = n, this.#n = !1, this.#i = i, this.#c = {}, this.#t = c;
|
|
269
298
|
}
|
|
270
|
-
get
|
|
299
|
+
get contextUsage() {
|
|
271
300
|
return this.#i;
|
|
272
301
|
}
|
|
273
|
-
get
|
|
302
|
+
get contextWindow() {
|
|
274
303
|
return 1e6;
|
|
275
304
|
}
|
|
276
|
-
get
|
|
277
|
-
return this.#
|
|
305
|
+
get oncontextwindowoverflow() {
|
|
306
|
+
return this.#c;
|
|
278
307
|
}
|
|
279
|
-
set
|
|
280
|
-
this.#
|
|
308
|
+
set oncontextwindowoverflow(t) {
|
|
309
|
+
this.#c && this.removeEventListener(
|
|
310
|
+
"contextwindowoverflow",
|
|
311
|
+
this.#c
|
|
312
|
+
), this.#c = t, typeof t == "function" && this.addEventListener("contextwindowoverflow", t);
|
|
281
313
|
}
|
|
282
|
-
static #
|
|
314
|
+
static #d(t) {
|
|
283
315
|
try {
|
|
284
316
|
if (!t || !t.document || t.document.defaultView !== t)
|
|
285
317
|
throw new Error();
|
|
@@ -294,13 +326,13 @@ class d extends EventTarget {
|
|
|
294
326
|
}
|
|
295
327
|
}
|
|
296
328
|
#a() {
|
|
297
|
-
d
|
|
329
|
+
h.#d(this.#t);
|
|
298
330
|
}
|
|
299
331
|
static async availability(t = {}) {
|
|
300
332
|
const e = this.__window || globalThis;
|
|
301
|
-
d
|
|
333
|
+
h.#d(e);
|
|
302
334
|
try {
|
|
303
|
-
await
|
|
335
|
+
await h.#w(t, e);
|
|
304
336
|
} catch (o) {
|
|
305
337
|
if (o instanceof RangeError) {
|
|
306
338
|
if (o.message.includes("language tag"))
|
|
@@ -316,64 +348,37 @@ class d extends EventTarget {
|
|
|
316
348
|
}
|
|
317
349
|
return "unavailable";
|
|
318
350
|
}
|
|
319
|
-
return (await
|
|
351
|
+
return (await h.#p(e)).availability(t);
|
|
320
352
|
}
|
|
321
|
-
static #
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
config: "GEMINI_CONFIG",
|
|
328
|
-
path: "./backends/gemini.js"
|
|
329
|
-
},
|
|
330
|
-
{
|
|
331
|
-
config: "OPENAI_CONFIG",
|
|
332
|
-
path: "./backends/openai.js"
|
|
333
|
-
},
|
|
334
|
-
{
|
|
335
|
-
config: "TRANSFORMERS_CONFIG",
|
|
336
|
-
path: "./backends/transformers.js"
|
|
337
|
-
}
|
|
338
|
-
];
|
|
339
|
-
static #d(t = globalThis) {
|
|
340
|
-
for (const e of d.#m) {
|
|
341
|
-
const r = t[e.config] || globalThis[e.config];
|
|
342
|
-
if (r && r.apiKey)
|
|
343
|
-
return { ...e, configValue: r };
|
|
353
|
+
static #x = A;
|
|
354
|
+
static #h(t = globalThis) {
|
|
355
|
+
for (const r of h.#x) {
|
|
356
|
+
const o = t[r.config] || globalThis[r.config];
|
|
357
|
+
if (o && o.apiKey)
|
|
358
|
+
return { ...r, configValue: o };
|
|
344
359
|
}
|
|
360
|
+
const e = h.#x.map((r) => `window.${r.config}`).join(", ");
|
|
345
361
|
throw new (t.DOMException || globalThis.DOMException)(
|
|
346
|
-
|
|
362
|
+
`Prompt API Polyfill: No backend configuration found. Please set one of: ${e}.`,
|
|
347
363
|
"NotSupportedError"
|
|
348
364
|
);
|
|
349
365
|
}
|
|
350
366
|
static async #p(t = globalThis) {
|
|
351
|
-
const e =
|
|
352
|
-
|
|
353
|
-
return (await import("./backends/firebase.js")).default;
|
|
354
|
-
if (e.path === "./backends/gemini.js")
|
|
355
|
-
return (await import("./backends/gemini.js")).default;
|
|
356
|
-
if (e.path === "./backends/openai.js")
|
|
357
|
-
return (await import("./backends/openai.js")).default;
|
|
358
|
-
if (e.path === "./backends/transformers.js")
|
|
359
|
-
return (await import("./backends/transformers.js")).default;
|
|
360
|
-
throw new (t.DOMException || globalThis.DOMException)(
|
|
361
|
-
`Prompt API Polyfill: Unknown backend path "${e.path}".`,
|
|
362
|
-
"NotSupportedError"
|
|
363
|
-
);
|
|
367
|
+
const e = h.#h(t);
|
|
368
|
+
return I(e.path);
|
|
364
369
|
}
|
|
365
|
-
static async #
|
|
370
|
+
static async #w(t = {}, e = globalThis) {
|
|
366
371
|
if (t.expectedInputs)
|
|
367
372
|
for (const o of t.expectedInputs) {
|
|
368
373
|
if (o.type !== "text" && o.type !== "image" && o.type !== "audio")
|
|
369
374
|
throw new TypeError(`Invalid input type: ${o.type}`);
|
|
370
|
-
o.languages &&
|
|
375
|
+
o.languages && h.#y(o.languages);
|
|
371
376
|
}
|
|
372
377
|
if (t.expectedOutputs)
|
|
373
378
|
for (const o of t.expectedOutputs) {
|
|
374
379
|
if (o.type !== "text")
|
|
375
380
|
throw new RangeError(`Unsupported output type: ${o.type}`);
|
|
376
|
-
o.languages &&
|
|
381
|
+
o.languages && h.#y(o.languages);
|
|
377
382
|
}
|
|
378
383
|
const r = t.expectedInputs ? ["text", ...t.expectedInputs.map((o) => o.type)] : ["text"];
|
|
379
384
|
if (t.initialPrompts && Array.isArray(t.initialPrompts)) {
|
|
@@ -392,11 +397,11 @@ class d extends EventTarget {
|
|
|
392
397
|
o = !0;
|
|
393
398
|
}
|
|
394
399
|
if (Array.isArray(i.content))
|
|
395
|
-
for (const
|
|
396
|
-
const
|
|
397
|
-
if (!r.includes(
|
|
400
|
+
for (const c of i.content) {
|
|
401
|
+
const a = c.type || "text";
|
|
402
|
+
if (!r.includes(a))
|
|
398
403
|
throw new (e.DOMException || globalThis.DOMException)(
|
|
399
|
-
`The content type "${
|
|
404
|
+
`The content type "${a}" is not in the expectedInputs.`,
|
|
400
405
|
"NotSupportedError"
|
|
401
406
|
);
|
|
402
407
|
}
|
|
@@ -408,7 +413,7 @@ class d extends EventTarget {
|
|
|
408
413
|
}
|
|
409
414
|
}
|
|
410
415
|
}
|
|
411
|
-
static #
|
|
416
|
+
static #y(t) {
|
|
412
417
|
if (!Array.isArray(t))
|
|
413
418
|
throw new RangeError("The `languages` option must be an array.");
|
|
414
419
|
for (const e of t) {
|
|
@@ -429,7 +434,7 @@ class d extends EventTarget {
|
|
|
429
434
|
}
|
|
430
435
|
static async create(t = {}) {
|
|
431
436
|
const e = this.__window || globalThis;
|
|
432
|
-
if (d
|
|
437
|
+
if (h.#d(e), await h.#w(t, e), t.signal?.aborted)
|
|
433
438
|
throw t.signal.reason || new (e.DOMException || globalThis.DOMException)(
|
|
434
439
|
"Aborted",
|
|
435
440
|
"AbortError"
|
|
@@ -450,33 +455,33 @@ class d extends EventTarget {
|
|
|
450
455
|
"Aborted",
|
|
451
456
|
"AbortError"
|
|
452
457
|
);
|
|
453
|
-
const o =
|
|
454
|
-
|
|
455
|
-
|
|
458
|
+
const o = h.#h(e), n = await h.#p(e), i = new n(o.configValue), c = { ...t };
|
|
459
|
+
h.#g(
|
|
460
|
+
c.responseConstraint,
|
|
456
461
|
e
|
|
457
462
|
);
|
|
458
|
-
const
|
|
463
|
+
const a = {
|
|
459
464
|
model: i.modelName,
|
|
460
465
|
generationConfig: {}
|
|
461
466
|
};
|
|
462
|
-
let
|
|
463
|
-
if (
|
|
464
|
-
const
|
|
467
|
+
let l = [], y = 0;
|
|
468
|
+
if (c.initialPrompts && Array.isArray(c.initialPrompts)) {
|
|
469
|
+
const w = c.initialPrompts.filter(
|
|
465
470
|
(f) => f.role === "system"
|
|
466
|
-
), p =
|
|
471
|
+
), p = c.initialPrompts.filter(
|
|
467
472
|
(f) => f.role !== "system"
|
|
468
473
|
);
|
|
469
|
-
|
|
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(`
|
|
470
475
|
`) : "").join(`
|
|
471
|
-
`)),
|
|
472
|
-
for (const f of
|
|
476
|
+
`)), l = await C(p, e);
|
|
477
|
+
for (const f of c.initialPrompts) {
|
|
473
478
|
if (typeof f.content != "string")
|
|
474
479
|
continue;
|
|
475
|
-
const
|
|
480
|
+
const d = h.#E([
|
|
476
481
|
{ text: f.content }
|
|
477
482
|
]);
|
|
478
|
-
if (
|
|
479
|
-
const
|
|
483
|
+
if (d === "QuotaExceededError" || d === "contextwindowoverflow") {
|
|
484
|
+
const E = e.QuotaExceededError || e.DOMException || globalThis.QuotaExceededError || globalThis.DOMException, u = new E(
|
|
480
485
|
"The initial prompts are too large, they exceed the quota.",
|
|
481
486
|
"QuotaExceededError"
|
|
482
487
|
);
|
|
@@ -484,25 +489,25 @@ class d extends EventTarget {
|
|
|
484
489
|
value: 22,
|
|
485
490
|
configurable: !0
|
|
486
491
|
});
|
|
487
|
-
const g =
|
|
492
|
+
const g = d === "QuotaExceededError" ? 1e7 : 5e5;
|
|
488
493
|
throw u.requested = g, u.quota = 1e6, u;
|
|
489
494
|
}
|
|
490
495
|
}
|
|
491
496
|
}
|
|
492
497
|
let x = null;
|
|
493
|
-
if (typeof
|
|
498
|
+
if (typeof c.monitor == "function") {
|
|
494
499
|
x = new EventTarget();
|
|
495
500
|
try {
|
|
496
|
-
|
|
497
|
-
} catch (
|
|
498
|
-
throw
|
|
501
|
+
c.monitor(x);
|
|
502
|
+
} catch (w) {
|
|
503
|
+
throw w;
|
|
499
504
|
}
|
|
500
505
|
}
|
|
501
506
|
x && (x.__lastProgressLoaded = -1);
|
|
502
|
-
const b = async (
|
|
507
|
+
const b = async (w) => {
|
|
503
508
|
if (!x || t.signal?.aborted)
|
|
504
509
|
return !t.signal?.aborted;
|
|
505
|
-
const p = 1 / 65536, f = Math.floor(
|
|
510
|
+
const p = 1 / 65536, f = Math.floor(w / p) * p;
|
|
506
511
|
if (f <= x.__lastProgressLoaded)
|
|
507
512
|
return !0;
|
|
508
513
|
try {
|
|
@@ -513,10 +518,10 @@ class d extends EventTarget {
|
|
|
513
518
|
lengthComputable: !0
|
|
514
519
|
})
|
|
515
520
|
), x.__lastProgressLoaded = f;
|
|
516
|
-
} catch (
|
|
517
|
-
console.error("Error dispatching downloadprogress events:",
|
|
521
|
+
} catch (d) {
|
|
522
|
+
console.error("Error dispatching downloadprogress events:", d);
|
|
518
523
|
}
|
|
519
|
-
return await new Promise((
|
|
524
|
+
return await new Promise((d) => setTimeout(d, 0)), !t.signal?.aborted;
|
|
520
525
|
};
|
|
521
526
|
if (!await b(0))
|
|
522
527
|
throw t.signal.reason || new (e.DOMException || globalThis.DOMException)(
|
|
@@ -524,8 +529,8 @@ class d extends EventTarget {
|
|
|
524
529
|
"AbortError"
|
|
525
530
|
);
|
|
526
531
|
const m = await i.createSession(
|
|
532
|
+
c,
|
|
527
533
|
a,
|
|
528
|
-
s,
|
|
529
534
|
x
|
|
530
535
|
);
|
|
531
536
|
if (!await b(1))
|
|
@@ -533,26 +538,26 @@ class d extends EventTarget {
|
|
|
533
538
|
"Aborted",
|
|
534
539
|
"AbortError"
|
|
535
540
|
);
|
|
536
|
-
if (
|
|
537
|
-
const
|
|
538
|
-
if (
|
|
541
|
+
if (c.initialPrompts?.length > 0) {
|
|
542
|
+
const w = [...l];
|
|
543
|
+
if (a.systemInstruction && w.unshift({
|
|
539
544
|
role: "system",
|
|
540
|
-
parts: [{ text:
|
|
541
|
-
}),
|
|
545
|
+
parts: [{ text: a.systemInstruction }]
|
|
546
|
+
}), y = await i.countTokens(w) || 0, y > 1e6) {
|
|
542
547
|
const p = e.QuotaExceededError || e.DOMException || globalThis.QuotaExceededError || globalThis.DOMException, f = new p(
|
|
543
548
|
"The initial prompts are too large, they exceed the quota.",
|
|
544
549
|
"QuotaExceededError"
|
|
545
550
|
);
|
|
546
|
-
throw Object.defineProperty(f, "code", { value: 22, configurable: !0 }), f.requested =
|
|
551
|
+
throw Object.defineProperty(f, "code", { value: 22, configurable: !0 }), f.requested = y, f.quota = 1e6, f;
|
|
547
552
|
}
|
|
548
553
|
}
|
|
549
554
|
return new this(
|
|
550
555
|
i,
|
|
551
556
|
m,
|
|
557
|
+
l,
|
|
552
558
|
c,
|
|
553
559
|
a,
|
|
554
|
-
|
|
555
|
-
w,
|
|
560
|
+
y,
|
|
556
561
|
e
|
|
557
562
|
);
|
|
558
563
|
}
|
|
@@ -568,7 +573,7 @@ class d extends EventTarget {
|
|
|
568
573
|
"Aborted",
|
|
569
574
|
"AbortError"
|
|
570
575
|
);
|
|
571
|
-
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 h.#p(this.#t), n = h.#h(this.#t), i = new o(n.configValue), c = await i.createSession(
|
|
572
577
|
r,
|
|
573
578
|
this.#e
|
|
574
579
|
);
|
|
@@ -579,7 +584,7 @@ class d extends EventTarget {
|
|
|
579
584
|
);
|
|
580
585
|
return new this.constructor(
|
|
581
586
|
i,
|
|
582
|
-
|
|
587
|
+
c,
|
|
583
588
|
e,
|
|
584
589
|
r,
|
|
585
590
|
this.#e,
|
|
@@ -604,27 +609,27 @@ class d extends EventTarget {
|
|
|
604
609
|
if (typeof t == "object" && t !== null && !Array.isArray(t) && Object.keys(t).length === 0)
|
|
605
610
|
return "[object Object]";
|
|
606
611
|
if (e.responseConstraint) {
|
|
607
|
-
|
|
612
|
+
h.#g(
|
|
608
613
|
e.responseConstraint,
|
|
609
614
|
this.#t
|
|
610
615
|
);
|
|
611
|
-
const
|
|
616
|
+
const a = v(
|
|
612
617
|
e.responseConstraint
|
|
613
618
|
);
|
|
614
|
-
this.#e.generationConfig.responseMimeType = "application/json", this.#e.generationConfig.responseSchema =
|
|
619
|
+
this.#e.generationConfig.responseMimeType = "application/json", this.#e.generationConfig.responseSchema = a, this.#f = this.#o.createSession(
|
|
615
620
|
this.#s,
|
|
616
621
|
this.#e
|
|
617
622
|
);
|
|
618
623
|
}
|
|
619
|
-
const r = this.#
|
|
624
|
+
const r = this.#b(t), o = await this.#l(t);
|
|
620
625
|
if (this.#n)
|
|
621
626
|
throw new (this.#t.DOMException || globalThis.DOMException)(
|
|
622
627
|
"Session is destroyed",
|
|
623
628
|
"InvalidStateError"
|
|
624
629
|
);
|
|
625
|
-
const n = { role: "user", parts: o }, i = new Promise((
|
|
630
|
+
const n = { role: "user", parts: o }, i = new Promise((a, l) => {
|
|
626
631
|
if (e.signal?.aborted) {
|
|
627
|
-
|
|
632
|
+
l(
|
|
628
633
|
e.signal.reason || new (this.#t.DOMException || globalThis.DOMException)(
|
|
629
634
|
"Aborted",
|
|
630
635
|
"AbortError"
|
|
@@ -635,7 +640,7 @@ class d extends EventTarget {
|
|
|
635
640
|
e.signal?.addEventListener(
|
|
636
641
|
"abort",
|
|
637
642
|
() => {
|
|
638
|
-
|
|
643
|
+
l(
|
|
639
644
|
e.signal.reason || new (this.#t.DOMException || globalThis.DOMException)(
|
|
640
645
|
"Aborted",
|
|
641
646
|
"AbortError"
|
|
@@ -644,53 +649,53 @@ class d extends EventTarget {
|
|
|
644
649
|
},
|
|
645
650
|
{ once: !0 }
|
|
646
651
|
);
|
|
647
|
-
}),
|
|
648
|
-
const
|
|
649
|
-
if (
|
|
650
|
-
const f = this.#t && this.#t.QuotaExceededError || this.#t && this.#t.DOMException || globalThis.QuotaExceededError || globalThis.DOMException,
|
|
652
|
+
}), c = (async () => {
|
|
653
|
+
const a = this.#u(o);
|
|
654
|
+
if (a === "QuotaExceededError") {
|
|
655
|
+
const f = this.#t && this.#t.QuotaExceededError || this.#t && this.#t.DOMException || globalThis.QuotaExceededError || globalThis.DOMException, d = new f(
|
|
651
656
|
"The prompt is too large, it exceeds the quota.",
|
|
652
657
|
"QuotaExceededError"
|
|
653
658
|
);
|
|
654
|
-
Object.defineProperty(
|
|
655
|
-
const
|
|
656
|
-
throw
|
|
657
|
-
} else if (
|
|
658
|
-
return this.dispatchEvent(new Event("
|
|
659
|
-
const
|
|
660
|
-
this.#e.systemInstruction &&
|
|
659
|
+
Object.defineProperty(d, "code", { value: 22, configurable: !0 });
|
|
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.";
|
|
664
|
+
const l = [...this.#r, n];
|
|
665
|
+
this.#e.systemInstruction && l.unshift({
|
|
661
666
|
role: "system",
|
|
662
667
|
parts: [{ text: this.#e.systemInstruction }]
|
|
663
668
|
});
|
|
664
|
-
const
|
|
665
|
-
|
|
669
|
+
const y = await this.#o.countTokens(
|
|
670
|
+
l
|
|
666
671
|
);
|
|
667
|
-
if (
|
|
668
|
-
const f = this.#t && this.#t.QuotaExceededError || this.#t && this.#t.DOMException || globalThis.QuotaExceededError || globalThis.DOMException,
|
|
669
|
-
`The prompt is too large (${
|
|
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(
|
|
674
|
+
`The prompt is too large (${y} tokens), it exceeds the quota of ${this.contextWindow} tokens.`,
|
|
670
675
|
"QuotaExceededError"
|
|
671
676
|
);
|
|
672
|
-
throw Object.defineProperty(
|
|
677
|
+
throw Object.defineProperty(d, "code", { value: 22, configurable: !0 }), d.requested = y, d.quota = this.contextWindow, d;
|
|
673
678
|
}
|
|
674
|
-
|
|
679
|
+
y > this.contextWindow && this.dispatchEvent(new Event("contextwindowoverflow"));
|
|
675
680
|
const x = [...this.#r, n];
|
|
676
681
|
let b;
|
|
677
682
|
try {
|
|
678
683
|
b = await this.#o.generateContent(x);
|
|
679
684
|
} catch (f) {
|
|
680
|
-
throw this.#
|
|
685
|
+
throw this.#m(f, o), f;
|
|
681
686
|
}
|
|
682
|
-
const { text: m, usage:
|
|
687
|
+
const { text: m, usage: w } = b;
|
|
683
688
|
let p = m;
|
|
684
689
|
if (r) {
|
|
685
690
|
const f = p.match(/^\s*{\s*"Rating"\s*:\s*/);
|
|
686
691
|
f && (p = p.slice(f[0].length));
|
|
687
692
|
}
|
|
688
|
-
return
|
|
693
|
+
return w && (this.#i = w), this.#r.push(n), this.#r.push({ role: "model", parts: [{ text: p }] }), p;
|
|
689
694
|
})();
|
|
690
695
|
try {
|
|
691
|
-
return await Promise.race([
|
|
692
|
-
} catch (
|
|
693
|
-
throw
|
|
696
|
+
return await Promise.race([c, i]);
|
|
697
|
+
} catch (a) {
|
|
698
|
+
throw a.name === "AbortError" || console.error("Prompt API Polyfill Error:", a), a;
|
|
694
699
|
}
|
|
695
700
|
}
|
|
696
701
|
promptStreaming(t, e = {}) {
|
|
@@ -714,25 +719,25 @@ class d extends EventTarget {
|
|
|
714
719
|
return new ReadableStream({
|
|
715
720
|
async start(n) {
|
|
716
721
|
let i = !1;
|
|
717
|
-
const
|
|
722
|
+
const c = () => {
|
|
718
723
|
i = !0;
|
|
719
724
|
try {
|
|
720
|
-
const
|
|
725
|
+
const a = o?.reason || new (r.#t.DOMException || globalThis.DOMException)(
|
|
721
726
|
"Aborted",
|
|
722
727
|
"AbortError"
|
|
723
728
|
);
|
|
724
|
-
n.error(
|
|
729
|
+
n.error(a);
|
|
725
730
|
} catch {
|
|
726
731
|
}
|
|
727
732
|
};
|
|
728
733
|
if (o?.aborted) {
|
|
729
|
-
|
|
734
|
+
c();
|
|
730
735
|
return;
|
|
731
736
|
}
|
|
732
|
-
o && o.addEventListener("abort",
|
|
737
|
+
o && o.addEventListener("abort", c);
|
|
733
738
|
try {
|
|
734
739
|
if (e.responseConstraint) {
|
|
735
|
-
|
|
740
|
+
h.#g(
|
|
736
741
|
e.responseConstraint,
|
|
737
742
|
r.#t
|
|
738
743
|
);
|
|
@@ -744,13 +749,13 @@ class d extends EventTarget {
|
|
|
744
749
|
r.#e
|
|
745
750
|
);
|
|
746
751
|
}
|
|
747
|
-
const
|
|
752
|
+
const a = r.#b(t), l = await r.#l(t);
|
|
748
753
|
if (r.#n)
|
|
749
754
|
throw new (r.#t.DOMException || globalThis.DOMException)(
|
|
750
755
|
"Session is destroyed",
|
|
751
756
|
"InvalidStateError"
|
|
752
757
|
);
|
|
753
|
-
const
|
|
758
|
+
const y = { role: "user", parts: l }, x = r.#u(l);
|
|
754
759
|
if (x === "QuotaExceededError") {
|
|
755
760
|
const u = r.#t && r.#t.QuotaExceededError || r.#t && r.#t.DOMException || globalThis.QuotaExceededError || globalThis.DOMException, g = new u(
|
|
756
761
|
"The prompt is too large, it exceeds the quota.",
|
|
@@ -761,12 +766,12 @@ class d extends EventTarget {
|
|
|
761
766
|
configurable: !0
|
|
762
767
|
});
|
|
763
768
|
const O = 1e7;
|
|
764
|
-
throw g.requested = O, g.quota = r.
|
|
765
|
-
} else if (x === "
|
|
766
|
-
r.dispatchEvent(new Event("
|
|
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();
|
|
767
772
|
return;
|
|
768
773
|
}
|
|
769
|
-
const b = [...r.#r,
|
|
774
|
+
const b = [...r.#r, y];
|
|
770
775
|
r.#e.systemInstruction && b.unshift({
|
|
771
776
|
role: "system",
|
|
772
777
|
parts: [{ text: r.#e.systemInstruction }]
|
|
@@ -774,51 +779,51 @@ class d extends EventTarget {
|
|
|
774
779
|
const m = await r.#o.countTokens(
|
|
775
780
|
b
|
|
776
781
|
);
|
|
777
|
-
if (m > r.
|
|
782
|
+
if (m > r.contextWindow) {
|
|
778
783
|
const u = r.#t && r.#t.QuotaExceededError || r.#t && r.#t.DOMException || globalThis.QuotaExceededError || globalThis.DOMException, g = new u(
|
|
779
|
-
`The prompt is too large (${m} tokens), it exceeds the quota of ${r.
|
|
784
|
+
`The prompt is too large (${m} tokens), it exceeds the quota of ${r.contextWindow} tokens.`,
|
|
780
785
|
"QuotaExceededError"
|
|
781
786
|
);
|
|
782
787
|
throw Object.defineProperty(g, "code", {
|
|
783
788
|
value: 22,
|
|
784
789
|
configurable: !0
|
|
785
|
-
}), g.requested = m, g.quota = r.
|
|
790
|
+
}), g.requested = m, g.quota = r.contextWindow, g;
|
|
786
791
|
}
|
|
787
|
-
m > r.
|
|
788
|
-
const
|
|
792
|
+
m > r.contextWindow && r.dispatchEvent(new Event("contextwindowoverflow"));
|
|
793
|
+
const w = [...r.#r, y];
|
|
789
794
|
let p;
|
|
790
795
|
try {
|
|
791
|
-
p = await r.#o.generateContentStream(
|
|
796
|
+
p = await r.#o.generateContentStream(w);
|
|
792
797
|
} catch (u) {
|
|
793
|
-
throw r.#
|
|
798
|
+
throw r.#m(u, l), u;
|
|
794
799
|
}
|
|
795
|
-
let f = "",
|
|
800
|
+
let f = "", d = !1, E = "";
|
|
796
801
|
for await (const u of p) {
|
|
797
802
|
if (i) {
|
|
798
803
|
typeof p.return == "function" && await p.return();
|
|
799
804
|
return;
|
|
800
805
|
}
|
|
801
806
|
let g = u.text();
|
|
802
|
-
if (
|
|
803
|
-
|
|
804
|
-
const O =
|
|
807
|
+
if (a && !d) {
|
|
808
|
+
E += g;
|
|
809
|
+
const O = E.match(/^\s*{\s*"Rating"\s*:\s*/);
|
|
805
810
|
if (O)
|
|
806
|
-
g =
|
|
807
|
-
else if (
|
|
808
|
-
g =
|
|
811
|
+
g = E.slice(O[0].length), d = !0, E = "";
|
|
812
|
+
else if (E.length > 50)
|
|
813
|
+
g = E, d = !0, E = "";
|
|
809
814
|
else
|
|
810
815
|
continue;
|
|
811
816
|
}
|
|
812
817
|
f += g, u.usageMetadata?.totalTokenCount && (r.#i = u.usageMetadata.totalTokenCount), n.enqueue(g);
|
|
813
818
|
}
|
|
814
|
-
i || (r.#r.push(
|
|
819
|
+
i || (r.#r.push(y), r.#r.push({
|
|
815
820
|
role: "model",
|
|
816
821
|
parts: [{ text: f }]
|
|
817
822
|
}), n.close());
|
|
818
|
-
} catch (
|
|
819
|
-
i || n.error(
|
|
823
|
+
} catch (a) {
|
|
824
|
+
i || n.error(a);
|
|
820
825
|
} finally {
|
|
821
|
-
o && o.removeEventListener("abort",
|
|
826
|
+
o && o.removeEventListener("abort", c);
|
|
822
827
|
}
|
|
823
828
|
}
|
|
824
829
|
});
|
|
@@ -834,7 +839,7 @@ class d extends EventTarget {
|
|
|
834
839
|
"Aborted",
|
|
835
840
|
"AbortError"
|
|
836
841
|
);
|
|
837
|
-
const r = await this.#
|
|
842
|
+
const r = await this.#l(t);
|
|
838
843
|
if (this.#n)
|
|
839
844
|
throw new (this.#t.DOMException || globalThis.DOMException)(
|
|
840
845
|
"Session is destroyed",
|
|
@@ -852,23 +857,23 @@ class d extends EventTarget {
|
|
|
852
857
|
this.#i = i || 0;
|
|
853
858
|
} catch {
|
|
854
859
|
}
|
|
855
|
-
this.#i > this.
|
|
860
|
+
this.#i > this.contextWindow && this.dispatchEvent(new Event("contextwindowoverflow"));
|
|
856
861
|
}
|
|
857
|
-
async
|
|
862
|
+
async measureContextUsage(t) {
|
|
858
863
|
if (this.#a(), this.#n)
|
|
859
864
|
throw new (this.#t.DOMException || globalThis.DOMException)(
|
|
860
865
|
"Session is destroyed",
|
|
861
866
|
"InvalidStateError"
|
|
862
867
|
);
|
|
863
868
|
try {
|
|
864
|
-
const e = await this.#
|
|
869
|
+
const e = await this.#l(t);
|
|
865
870
|
if (this.#n)
|
|
866
871
|
throw new (this.#t.DOMException || globalThis.DOMException)(
|
|
867
872
|
"Session is destroyed",
|
|
868
873
|
"InvalidStateError"
|
|
869
874
|
);
|
|
870
875
|
const r = this.#u(e);
|
|
871
|
-
return r === "QuotaExceededError" ? 1e7 : r === "
|
|
876
|
+
return r === "QuotaExceededError" ? 1e7 : r === "contextwindowoverflow" ? 5e5 : await this.#o.countTokens([
|
|
872
877
|
{ role: "user", parts: e }
|
|
873
878
|
]) || 0;
|
|
874
879
|
} catch {
|
|
@@ -879,13 +884,13 @@ class d extends EventTarget {
|
|
|
879
884
|
}
|
|
880
885
|
// Volkswagen mode detection to avoid cloud costs for WPT tests.
|
|
881
886
|
#u(t) {
|
|
882
|
-
return
|
|
887
|
+
return h.#E(t);
|
|
883
888
|
}
|
|
884
|
-
static #
|
|
889
|
+
static #E(t) {
|
|
885
890
|
if (t.length !== 1 || !t[0].text)
|
|
886
891
|
return null;
|
|
887
892
|
const e = t[0].text;
|
|
888
|
-
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 ? "contextwindowoverflow" : null;
|
|
889
894
|
}
|
|
890
895
|
static #g(t, e) {
|
|
891
896
|
if (t)
|
|
@@ -898,7 +903,7 @@ class d extends EventTarget {
|
|
|
898
903
|
);
|
|
899
904
|
}
|
|
900
905
|
}
|
|
901
|
-
#
|
|
906
|
+
#b(t) {
|
|
902
907
|
if (Array.isArray(t)) {
|
|
903
908
|
for (const e of t)
|
|
904
909
|
if (e.prefix && (e.role === "assistant" || e.role === "model") && typeof e.content == "string" && e.content.includes('"Rating":'))
|
|
@@ -907,7 +912,7 @@ class d extends EventTarget {
|
|
|
907
912
|
return null;
|
|
908
913
|
}
|
|
909
914
|
// Private Helper to process diverse input types
|
|
910
|
-
async #
|
|
915
|
+
async #l(t) {
|
|
911
916
|
const e = this.#s.expectedInputs ? ["text", ...this.#s.expectedInputs.map((o) => o.type)] : ["text"];
|
|
912
917
|
if (typeof t == "string") {
|
|
913
918
|
if (!e.includes("text"))
|
|
@@ -934,28 +939,28 @@ class d extends EventTarget {
|
|
|
934
939
|
"The `prefix` flag isn't supported and was ignored."
|
|
935
940
|
);
|
|
936
941
|
} else if (Array.isArray(n.content))
|
|
937
|
-
for (const
|
|
938
|
-
const
|
|
939
|
-
if (!e.includes(
|
|
942
|
+
for (const c of n.content) {
|
|
943
|
+
const a = c.type || "text";
|
|
944
|
+
if (!e.includes(a))
|
|
940
945
|
throw new (this.#t.DOMException || globalThis.DOMException)(
|
|
941
|
-
`The content type "${
|
|
946
|
+
`The content type "${a}" is not in the expectedInputs.`,
|
|
942
947
|
"NotSupportedError"
|
|
943
948
|
);
|
|
944
|
-
if (
|
|
945
|
-
if (typeof
|
|
949
|
+
if (a === "text") {
|
|
950
|
+
if (typeof c.value != "string")
|
|
946
951
|
throw new (this.#t.DOMException || globalThis.DOMException)(
|
|
947
952
|
'The content type "text" must have a string value.',
|
|
948
953
|
"SyntaxError"
|
|
949
954
|
);
|
|
950
|
-
o.push({ text:
|
|
955
|
+
o.push({ text: c.value });
|
|
951
956
|
} else {
|
|
952
957
|
if (i)
|
|
953
958
|
throw new (this.#t.DOMException || globalThis.DOMException)(
|
|
954
959
|
"Assistant messages only support text content.",
|
|
955
960
|
"NotSupportedError"
|
|
956
961
|
);
|
|
957
|
-
const
|
|
958
|
-
o.push(
|
|
962
|
+
const l = await M.convert(c.type, c.value);
|
|
963
|
+
o.push(l);
|
|
959
964
|
}
|
|
960
965
|
}
|
|
961
966
|
}
|
|
@@ -978,13 +983,13 @@ class d extends EventTarget {
|
|
|
978
983
|
return [{ text: JSON.stringify(t) }];
|
|
979
984
|
}
|
|
980
985
|
// Map backend errors to WPT expectations
|
|
981
|
-
#
|
|
986
|
+
#m(t, e) {
|
|
982
987
|
const r = String(t.message || t);
|
|
983
988
|
if (r.includes("400") || r.toLowerCase().includes("unable to process") || r.toLowerCase().includes("invalid")) {
|
|
984
989
|
const o = e.some(
|
|
985
|
-
(
|
|
990
|
+
(c) => c.inlineData?.mimeType.startsWith("audio/")
|
|
986
991
|
), n = e.some(
|
|
987
|
-
(
|
|
992
|
+
(c) => c.inlineData?.mimeType.startsWith("image/")
|
|
988
993
|
), i = this.#t.DOMException || globalThis.DOMException;
|
|
989
994
|
if (o)
|
|
990
995
|
throw new i("Invalid audio data", "DataError");
|
|
@@ -994,47 +999,47 @@ class d extends EventTarget {
|
|
|
994
999
|
}
|
|
995
1000
|
}
|
|
996
1001
|
globalThis.DOMException && (globalThis.QuotaExceededError = globalThis.DOMException);
|
|
997
|
-
const D = (
|
|
1002
|
+
const D = (s) => {
|
|
998
1003
|
try {
|
|
999
|
-
if (!
|
|
1004
|
+
if (!s || s.LanguageModel?.__isPolyfill)
|
|
1000
1005
|
return;
|
|
1001
|
-
const t = class extends
|
|
1006
|
+
const t = class extends h {
|
|
1002
1007
|
};
|
|
1003
|
-
t.__window =
|
|
1008
|
+
t.__window = s, t.__isPolyfill = !0, s.LanguageModel = t, s.DOMException && (s.QuotaExceededError = s.DOMException);
|
|
1004
1009
|
} catch {
|
|
1005
1010
|
}
|
|
1006
1011
|
};
|
|
1007
1012
|
if (typeof HTMLIFrameElement < "u")
|
|
1008
1013
|
try {
|
|
1009
|
-
const
|
|
1014
|
+
const s = Object.getOwnPropertyDescriptor(
|
|
1010
1015
|
HTMLIFrameElement.prototype,
|
|
1011
1016
|
"contentWindow"
|
|
1012
1017
|
);
|
|
1013
|
-
|
|
1018
|
+
s && s.get && Object.defineProperty(HTMLIFrameElement.prototype, "contentWindow", {
|
|
1014
1019
|
get() {
|
|
1015
|
-
const t =
|
|
1020
|
+
const t = s.get.call(this);
|
|
1016
1021
|
return t && D(t), t;
|
|
1017
1022
|
},
|
|
1018
1023
|
configurable: !0
|
|
1019
1024
|
});
|
|
1020
1025
|
} catch {
|
|
1021
1026
|
}
|
|
1022
|
-
const
|
|
1023
|
-
for (const t of
|
|
1027
|
+
const P = new MutationObserver((s) => {
|
|
1028
|
+
for (const t of s)
|
|
1024
1029
|
for (const e of t.addedNodes)
|
|
1025
1030
|
e.tagName === "IFRAME" && (D(e.contentWindow), e.addEventListener("load", () => D(e.contentWindow), {
|
|
1026
1031
|
once: !1
|
|
1027
1032
|
}));
|
|
1028
1033
|
});
|
|
1029
|
-
globalThis.document?.documentElement && (
|
|
1034
|
+
globalThis.document?.documentElement && (P.observe(globalThis.document.documentElement, {
|
|
1030
1035
|
childList: !0,
|
|
1031
1036
|
subtree: !0
|
|
1032
|
-
}), globalThis.document.querySelectorAll("iframe").forEach((
|
|
1033
|
-
D(
|
|
1037
|
+
}), globalThis.document.querySelectorAll("iframe").forEach((s) => {
|
|
1038
|
+
D(s.contentWindow);
|
|
1034
1039
|
}));
|
|
1035
|
-
(!("LanguageModel" in globalThis) || globalThis.__FORCE_PROMPT_API_POLYFILL__) && (globalThis.LanguageModel =
|
|
1040
|
+
(!("LanguageModel" in globalThis) || globalThis.__FORCE_PROMPT_API_POLYFILL__) && (globalThis.LanguageModel = h, h.__isPolyfill = !0, console.log(
|
|
1036
1041
|
"Polyfill: window.LanguageModel is now backed by the Prompt API polyfill."
|
|
1037
1042
|
));
|
|
1038
1043
|
export {
|
|
1039
|
-
|
|
1044
|
+
h as LanguageModel
|
|
1040
1045
|
};
|
package/dot_env.json
CHANGED
|
@@ -7,15 +7,5 @@
|
|
|
7
7
|
"reCaptchaSiteKey": "",
|
|
8
8
|
"useLimitedUseAppCheckTokens": true,
|
|
9
9
|
"device": "webgpu",
|
|
10
|
-
"dtype": "q4f16"
|
|
11
|
-
"env": {
|
|
12
|
-
"allowRemoteModels": true,
|
|
13
|
-
"backends": {
|
|
14
|
-
"onnx": {
|
|
15
|
-
"wasm": {
|
|
16
|
-
"wasmPaths": ""
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
}
|
|
10
|
+
"dtype": "q4f16"
|
|
21
11
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "prompt-api-polyfill",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.1",
|
|
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",
|
|
@@ -38,9 +38,10 @@
|
|
|
38
38
|
"start": "vite",
|
|
39
39
|
"build": "vite build",
|
|
40
40
|
"prepublishOnly": "npm run build",
|
|
41
|
+
"generate:registry": "node scripts/generate-registry.js",
|
|
41
42
|
"sync:wpt": "node scripts/sync-wpt.js",
|
|
42
|
-
"generate:wpt": "node scripts/
|
|
43
|
-
"test:wpt": "npm run sync:wpt && npm run generate:wpt && npx vite --open /tests/wpt/index.html",
|
|
43
|
+
"generate:wpt": "npm run generate:registry && node scripts/backend-discovery.js && node scripts/generate-wpt-wrappers.js",
|
|
44
|
+
"test:wpt": "npm run generate:registry && npm run sync:wpt && npm run generate:wpt && npx vite --open /tests/wpt/index.html",
|
|
44
45
|
"fix": "npx prettier --write ."
|
|
45
46
|
},
|
|
46
47
|
"devDependencies": {
|