chrome-web-ai-types 0.1.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Kevin Uehara
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,234 @@
1
+ # chrome-web-ai-types
2
+
3
+ TypeScript definitions for **Chrome’s built-in AI APIs** (Summarizer, Writer, Rewriter, Proofreader, Translator, Language Detector, and Prompt API). Works with TypeScript, React, Angular, Vue, and any project using TypeScript.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install chrome-web-ai-types
9
+ # or
10
+ yarn add chrome-web-ai-types
11
+ # or
12
+ pnpm add chrome-web-ai-types
13
+ ```
14
+
15
+ ## Requirements
16
+
17
+ - **TypeScript** 4.5+ (5.x recommended)
18
+ - **Chrome** 138+ (APIs are evolving; see [Chrome docs](https://developer.chrome.com/docs/ai))
19
+ - Some APIs may require an [origin trial](https://developer.chrome.com/docs/origintrials/) or Chrome flags
20
+
21
+ ## APIs covered
22
+
23
+ | API | Description |
24
+ |-----|-------------|
25
+ | **Summarizer** | Summarize text (key-points, tldr, teaser, headline) |
26
+ | **Writer** | Generate text (tone, format, length) |
27
+ | **Rewriter** | Rewrite text (tone, format, length) |
28
+ | **Proofreader** | Grammar and spelling review |
29
+ | **Translator** | Translate between languages |
30
+ | **LanguageDetector** | Detect text language |
31
+ | **LanguageModel** (Prompt API) | Prompts and sessions with Gemini Nano |
32
+ | **window.ai** | `createLanguageModel()` (legacy) |
33
+
34
+ All expose `availability()`, `create(options?)`, streaming where applicable, and language options when documented.
35
+
36
+ ---
37
+
38
+ ## Usage by project type
39
+
40
+ ### TypeScript (Node / generic bundler)
41
+
42
+ The declarations are **global**. After installing the package, types are picked up automatically.
43
+
44
+ ```ts
45
+ // No import needed
46
+ async function main() {
47
+ if (typeof Summarizer === "undefined") {
48
+ console.log("Summarizer not available in this environment.");
49
+ return;
50
+ }
51
+
52
+ const availability = await Summarizer.availability();
53
+ if (availability === "unavailable") return;
54
+
55
+ const summarizer = await Summarizer.create({
56
+ type: "key-points",
57
+ format: "markdown",
58
+ length: "short",
59
+ });
60
+
61
+ const summary = await summarizer.summarize("Your long text here...");
62
+ console.log(summary);
63
+ }
64
+ ```
65
+
66
+ Ensure your `tsconfig.json` includes the right lib (usually automatic after install):
67
+
68
+ ```json
69
+ {
70
+ "compilerOptions": {
71
+ "lib": ["ES2020", "DOM"]
72
+ }
73
+ }
74
+ ```
75
+
76
+ ---
77
+
78
+ ### React (TypeScript)
79
+
80
+ Install the package and use the APIs in components or hooks. Global types are available without imports.
81
+
82
+ ```tsx
83
+ // src/hooks/useSummarizer.ts
84
+ import { useState, useCallback } from "react";
85
+
86
+ export function useSummarizer() {
87
+ const [summary, setSummary] = useState<string>("");
88
+ const [loading, setLoading] = useState(false);
89
+
90
+ const summarize = useCallback(async (text: string) => {
91
+ if (typeof Summarizer === "undefined") {
92
+ throw new Error("Summarizer API not available.");
93
+ }
94
+ setLoading(true);
95
+ try {
96
+ const availability = await Summarizer.availability();
97
+ if (availability === "unavailable") {
98
+ throw new Error("Model unavailable.");
99
+ }
100
+ const summarizer = await Summarizer.create({ type: "key-points" });
101
+ const result = await summarizer.summarize(text);
102
+ setSummary(result);
103
+ return result;
104
+ } finally {
105
+ setLoading(false);
106
+ }
107
+ }, []);
108
+
109
+ return { summary, loading, summarize };
110
+ }
111
+ ```
112
+
113
+ ```tsx
114
+ // src/components/SummarizerDemo.tsx
115
+ import { useSummarizer } from "../hooks/useSummarizer";
116
+
117
+ export function SummarizerDemo() {
118
+ const { summary, loading, summarize } = useSummarizer();
119
+
120
+ return (
121
+ <div>
122
+ <button
123
+ disabled={loading}
124
+ onClick={() => summarize("Long text to summarize...")}
125
+ >
126
+ {loading ? "Summarizing..." : "Summarize"}
127
+ </button>
128
+ {summary && <p>{summary}</p>}
129
+ </div>
130
+ );
131
+ }
132
+ ```
133
+
134
+ In React + Vite or Create React App, a `tsconfig` with `"lib": ["ES2020", "DOM"]` is enough.
135
+
136
+ --
137
+
138
+ Install and use in `<script setup lang="ts">` or composables; global types are recognized.
139
+
140
+ ```vue
141
+ <!-- src/components/LanguageDetector.vue -->
142
+ <script setup lang="ts">
143
+ import { ref } from "vue";
144
+
145
+ const text = ref("");
146
+ const detectedLanguage = ref<string | null>(null);
147
+ const loading = ref(false);
148
+
149
+ async function detect() {
150
+ if (typeof LanguageDetector === "undefined") return;
151
+ loading.value = true;
152
+ try {
153
+ const detector = await LanguageDetector.create();
154
+ const results = await detector.detect(text.value);
155
+ detectedLanguage.value = results[0]?.detectedLanguage ?? null;
156
+ } finally {
157
+ loading.value = false;
158
+ }
159
+ }
160
+ </script>
161
+
162
+ <template>
163
+ <div>
164
+ <textarea v-model="text" placeholder="Enter some text" />
165
+ <button :disabled="loading" @click="detect">Detect language</button>
166
+ <p v-if="detectedLanguage">Language: {{ detectedLanguage }}</p>
167
+ </div>
168
+ </template>
169
+ ```
170
+
171
+ ---
172
+
173
+ ### Checking availability
174
+
175
+ APIs may be missing (older browser) or not ready (model not downloaded). Always check at runtime:
176
+
177
+ ```ts
178
+ if (typeof Summarizer === "undefined") {
179
+ // API does not exist in this environment
180
+ return;
181
+ }
182
+
183
+ const availability = await Summarizer.availability();
184
+ // "available" | "unavailable" | "downloadable"
185
+
186
+ if (availability === "unavailable") {
187
+ // Cannot use
188
+ return;
189
+ }
190
+
191
+ if (availability === "downloadable") {
192
+ // Can call create(); model will download (may take a while)
193
+ const summarizer = await Summarizer.create({
194
+ monitor(m) {
195
+ m.addEventListener("downloadprogress", (e) => {
196
+ console.log(`Download: ${e.loaded * 100}%`);
197
+ });
198
+ },
199
+ });
200
+ // ...
201
+ }
202
+ ```
203
+
204
+ ---
205
+
206
+ ## Type tests (this repo)
207
+
208
+ ```bash
209
+ npm install
210
+ npm run typecheck
211
+ # or
212
+ npm test
213
+ ```
214
+
215
+ Files under `tests/` assert that the definitions accept valid usage and reject invalid usage.
216
+
217
+ ---
218
+
219
+ ## Official documentation
220
+
221
+ - [Chrome AI APIs overview](https://developer.chrome.com/docs/ai)
222
+ - [Summarizer](https://developer.chrome.com/docs/ai/summarizer-api)
223
+ - [Writer](https://developer.chrome.com/docs/ai/writer-api)
224
+ - [Rewriter](https://developer.chrome.com/docs/ai/rewriter-api)
225
+ - [Proofreader](https://developer.chrome.com/docs/ai/proofreader-api)
226
+ - [Translator](https://developer.chrome.com/docs/ai/translator-api)
227
+ - [Language Detector](https://developer.chrome.com/docs/ai/language-detection)
228
+ - [Prompt API](https://developer.chrome.com/docs/ai/prompt-api)
229
+
230
+ ---
231
+
232
+ ## License
233
+
234
+ MIT
package/index.d.ts ADDED
@@ -0,0 +1,432 @@
1
+ /// <reference lib="es2018.asynciterable" />
2
+ export {};
3
+
4
+ declare global {
5
+ /* ---------------------------
6
+ SUMMARIZER
7
+ https://developer.chrome.com/docs/ai/summarizer-api
8
+ --------------------------- */
9
+
10
+ type SummarizerType = "key-points" | "tldr" | "teaser" | "headline";
11
+ type SummarizerFormat = "markdown" | "plain-text";
12
+ type SummarizerLength = "short" | "medium" | "long";
13
+ type SummarizerPreference = "auto" | "speed" | "capability";
14
+ type SummarizerAvailability = "available" | "unavailable" | "downloadable";
15
+
16
+ interface SummarizerDownloadProgressEvent {
17
+ readonly loaded: number;
18
+ }
19
+
20
+ interface SummarizerMonitor {
21
+ addEventListener(
22
+ type: "downloadprogress",
23
+ listener: (e: SummarizerDownloadProgressEvent) => void,
24
+ ): void;
25
+ }
26
+
27
+ interface SummarizerOptions {
28
+ sharedContext?: string;
29
+ type?: SummarizerType;
30
+ format?: SummarizerFormat;
31
+ length?: SummarizerLength;
32
+ preference?: SummarizerPreference;
33
+ expectedInputLanguages?: string[];
34
+ outputLanguage?: string;
35
+ expectedContextLanguages?: string[];
36
+ monitor?(m: SummarizerMonitor): void;
37
+ }
38
+
39
+ interface SummarizerSummarizeOptions {
40
+ /** Optional context to improve the summary for this call. */
41
+ context?: string;
42
+ }
43
+
44
+ interface Summarizer {
45
+ /** Batch summarization: process full input and return the summary. */
46
+ summarize(
47
+ text: string,
48
+ options?: SummarizerSummarizeOptions,
49
+ ): Promise<string>;
50
+ /** Streaming summarization: yields chunks as the summary is generated. */
51
+ summarizeStreaming(
52
+ text: string,
53
+ options?: SummarizerSummarizeOptions,
54
+ ): AsyncGenerator<string, void, undefined>;
55
+ }
56
+
57
+ interface SummarizerConstructor {
58
+ create(options?: SummarizerOptions): Promise<Summarizer>;
59
+ availability(): Promise<SummarizerAvailability>;
60
+ }
61
+
62
+ var Summarizer: SummarizerConstructor;
63
+
64
+ /* ---------------------------
65
+ WRITER
66
+ https://developer.chrome.com/docs/ai/writer-api
67
+ --------------------------- */
68
+
69
+ type WriterTone = "formal" | "neutral" | "casual";
70
+ type WriterFormat = "markdown" | "plain-text";
71
+ type WriterLength = "short" | "medium" | "long";
72
+ type WriterAvailability = "available" | "unavailable" | "downloadable";
73
+
74
+ interface WriterDownloadProgressEvent {
75
+ readonly loaded: number;
76
+ }
77
+
78
+ interface WriterMonitor {
79
+ addEventListener(
80
+ type: "downloadprogress",
81
+ listener: (e: WriterDownloadProgressEvent) => void,
82
+ ): void;
83
+ }
84
+
85
+ interface WriterOptions {
86
+ tone?: WriterTone;
87
+ format?: WriterFormat;
88
+ length?: WriterLength;
89
+ sharedContext?: string;
90
+ expectedInputLanguages?: string[];
91
+ expectedContextLanguages?: string[];
92
+ outputLanguage?: string;
93
+ monitor?(m: WriterMonitor): void;
94
+ signal?: AbortSignal;
95
+ }
96
+
97
+ interface WriterWriteOptions {
98
+ context?: string;
99
+ signal?: AbortSignal;
100
+ }
101
+
102
+ interface Writer {
103
+ write(prompt: string, options?: WriterWriteOptions): Promise<string>;
104
+ writeStreaming(
105
+ prompt: string,
106
+ options?: WriterWriteOptions,
107
+ ): AsyncGenerator<string, void, undefined>;
108
+ destroy(): void;
109
+ }
110
+
111
+ interface WriterConstructor {
112
+ create(options?: WriterOptions): Promise<Writer>;
113
+ availability(): Promise<WriterAvailability>;
114
+ }
115
+
116
+ var Writer: WriterConstructor;
117
+
118
+ /* ---------------------------
119
+ REWRITER
120
+ https://developer.chrome.com/docs/ai/rewriter-api
121
+ --------------------------- */
122
+
123
+ type RewriterTone = "more-formal" | "as-is" | "more-casual";
124
+ type RewriterFormat = "as-is" | "markdown" | "plain-text";
125
+ type RewriterLength = "shorter" | "as-is" | "longer";
126
+ type RewriterAvailability = "available" | "unavailable" | "downloadable";
127
+
128
+ interface RewriterDownloadProgressEvent {
129
+ readonly loaded: number;
130
+ }
131
+
132
+ interface RewriterMonitor {
133
+ addEventListener(
134
+ type: "downloadprogress",
135
+ listener: (e: RewriterDownloadProgressEvent) => void,
136
+ ): void;
137
+ }
138
+
139
+ interface RewriterOptions {
140
+ tone?: RewriterTone;
141
+ format?: RewriterFormat;
142
+ length?: RewriterLength;
143
+ sharedContext?: string;
144
+ expectedInputLanguages?: string[];
145
+ expectedContextLanguages?: string[];
146
+ outputLanguage?: string;
147
+ monitor?(m: RewriterMonitor): void;
148
+ signal?: AbortSignal;
149
+ }
150
+
151
+ interface RewriterRewriteOptions {
152
+ context?: string;
153
+ tone?: RewriterTone;
154
+ signal?: AbortSignal;
155
+ }
156
+
157
+ interface Rewriter {
158
+ rewrite(text: string, options?: RewriterRewriteOptions): Promise<string>;
159
+ rewriteStreaming(
160
+ text: string,
161
+ options?: RewriterRewriteOptions,
162
+ ): AsyncGenerator<string, void, undefined>;
163
+ destroy(): void;
164
+ }
165
+
166
+ interface RewriterConstructor {
167
+ create(options?: RewriterOptions): Promise<Rewriter>;
168
+ availability(): Promise<RewriterAvailability>;
169
+ }
170
+
171
+ var Rewriter: RewriterConstructor;
172
+
173
+ /* ---------------------------
174
+ PROOFREADER
175
+ https://developer.chrome.com/docs/ai/proofreader-api
176
+ --------------------------- */
177
+
178
+ type ProofreaderAvailability = "available" | "unavailable" | "downloadable";
179
+
180
+ interface ProofreaderDownloadProgressEvent {
181
+ readonly loaded: number;
182
+ }
183
+
184
+ interface ProofreaderMonitor {
185
+ addEventListener(
186
+ type: "downloadprogress",
187
+ listener: (e: ProofreaderDownloadProgressEvent) => void,
188
+ ): void;
189
+ }
190
+
191
+ interface ProofreaderOptions {
192
+ expectedInputLanguages?: string[];
193
+ monitor?(m: ProofreaderMonitor): void;
194
+ }
195
+
196
+ interface ProofreaderCorrection {
197
+ startIndex: number;
198
+ endIndex: number;
199
+ replacement?: string;
200
+ }
201
+
202
+ interface ProofreadResult {
203
+ correctedInput: string;
204
+ corrections: ProofreaderCorrection[];
205
+ }
206
+
207
+ interface Proofreader {
208
+ proofread(text: string): Promise<ProofreadResult>;
209
+ }
210
+
211
+ interface ProofreaderConstructor {
212
+ create(options?: ProofreaderOptions): Promise<Proofreader>;
213
+ availability(): Promise<ProofreaderAvailability>;
214
+ }
215
+
216
+ var Proofreader: ProofreaderConstructor;
217
+
218
+ /* ---------------------------
219
+ TRANSLATOR
220
+ https://developer.chrome.com/docs/ai/translator-api
221
+ --------------------------- */
222
+
223
+ type TranslatorAvailability = "available" | "unavailable" | "downloadable";
224
+
225
+ interface TranslatorDownloadProgressEvent {
226
+ readonly loaded: number;
227
+ }
228
+
229
+ interface TranslatorMonitor {
230
+ addEventListener(
231
+ type: "downloadprogress",
232
+ listener: (e: TranslatorDownloadProgressEvent) => void,
233
+ ): void;
234
+ }
235
+
236
+ interface TranslatorOptions {
237
+ sourceLanguage: string;
238
+ targetLanguage: string;
239
+ monitor?(m: TranslatorMonitor): void;
240
+ }
241
+
242
+ interface TranslatorAvailabilityOptions {
243
+ sourceLanguage: string;
244
+ targetLanguage: string;
245
+ }
246
+
247
+ interface Translator {
248
+ translate(text: string): Promise<string>;
249
+ translateStreaming(text: string): AsyncGenerator<string, void, undefined>;
250
+ }
251
+
252
+ interface TranslatorConstructor {
253
+ create(options: TranslatorOptions): Promise<Translator>;
254
+ availability(
255
+ options?: TranslatorAvailabilityOptions,
256
+ ): Promise<TranslatorAvailability>;
257
+ }
258
+
259
+ var Translator: TranslatorConstructor;
260
+
261
+ /* ---------------------------
262
+ LANGUAGE DETECTOR
263
+ https://developer.chrome.com/docs/ai/language-detection
264
+ --------------------------- */
265
+
266
+ type LanguageDetectorAvailability =
267
+ | "available"
268
+ | "unavailable"
269
+ | "downloadable";
270
+
271
+ interface LanguageDetectorDownloadProgressEvent {
272
+ readonly loaded: number;
273
+ }
274
+
275
+ interface LanguageDetectorMonitor {
276
+ addEventListener(
277
+ type: "downloadprogress",
278
+ listener: (e: LanguageDetectorDownloadProgressEvent) => void,
279
+ ): void;
280
+ }
281
+
282
+ interface LanguageDetectionResult {
283
+ detectedLanguage: string;
284
+ confidence: number;
285
+ }
286
+
287
+ interface LanguageDetectorOptions {
288
+ monitor?(m: LanguageDetectorMonitor): void;
289
+ }
290
+
291
+ interface LanguageDetector {
292
+ detect(text: string): Promise<LanguageDetectionResult[]>;
293
+ }
294
+
295
+ interface LanguageDetectorConstructor {
296
+ create(options?: LanguageDetectorOptions): Promise<LanguageDetector>;
297
+ availability(): Promise<LanguageDetectorAvailability>;
298
+ }
299
+
300
+ var LanguageDetector: LanguageDetectorConstructor;
301
+
302
+ /* ---------------------------
303
+ PROMPT API (Language Model)
304
+ https://developer.chrome.com/docs/ai/prompt-api
305
+ --------------------------- */
306
+
307
+ type LanguageModelAvailability = "available" | "unavailable" | "downloading";
308
+
309
+ interface LanguageModelDownloadProgressEvent {
310
+ readonly loaded: number;
311
+ }
312
+
313
+ interface LanguageModelMonitor {
314
+ addEventListener(
315
+ type: "downloadprogress",
316
+ listener: (e: LanguageModelDownloadProgressEvent) => void,
317
+ ): void;
318
+ }
319
+
320
+ interface LanguageModelExpectedInput {
321
+ type: "text" | "image" | "audio";
322
+ languages?: string[];
323
+ }
324
+
325
+ /** Expected output: text only, with optional languages. */
326
+ interface LanguageModelExpectedOutput {
327
+ type: "text";
328
+ languages?: string[];
329
+ }
330
+
331
+ interface TextContentPart {
332
+ type: "text";
333
+ value: string;
334
+ }
335
+
336
+ interface ImageContentPart {
337
+ type: "image";
338
+ value:
339
+ | HTMLImageElement
340
+ | SVGImageElement
341
+ | HTMLVideoElement
342
+ | HTMLCanvasElement
343
+ | ImageBitmap
344
+ | OffscreenCanvas
345
+ | VideoFrame
346
+ | Blob
347
+ | ImageData;
348
+ }
349
+
350
+ interface AudioContentPart {
351
+ type: "audio";
352
+ value: AudioBuffer | ArrayBufferView | ArrayBuffer | Blob;
353
+ }
354
+
355
+ type LanguageModelContentPart =
356
+ | TextContentPart
357
+ | ImageContentPart
358
+ | AudioContentPart;
359
+
360
+ interface LanguageModelPromptMessage {
361
+ role: "system" | "user" | "assistant";
362
+ content: string | LanguageModelContentPart[];
363
+ prefix?: boolean;
364
+ }
365
+
366
+ interface LanguageModelParams {
367
+ defaultTopK: number;
368
+ maxTopK: number;
369
+ defaultTemperature: number;
370
+ maxTemperature: number;
371
+ }
372
+
373
+ interface LanguageModelCreateOptions {
374
+ monitor?(m: LanguageModelMonitor): void;
375
+ signal?: AbortSignal;
376
+ initialPrompts?: LanguageModelPromptMessage[];
377
+ expectedInputs?: LanguageModelExpectedInput[];
378
+ expectedOutputs?: LanguageModelExpectedOutput[];
379
+ temperature?: number;
380
+ topK?: number;
381
+ }
382
+
383
+ interface LanguageModelAvailabilityOptions {
384
+ expectedInputs?: LanguageModelExpectedInput[];
385
+ expectedOutputs?: LanguageModelExpectedOutput[];
386
+ }
387
+
388
+ interface LanguageModelPromptOptions {
389
+ responseConstraint?: object;
390
+ omitResponseConstraintInput?: boolean;
391
+ signal?: AbortSignal;
392
+ }
393
+
394
+ interface LanguageModelSession {
395
+ prompt(
396
+ prompt: string | LanguageModelPromptMessage[],
397
+ options?: LanguageModelPromptOptions,
398
+ ): Promise<string>;
399
+ promptStreaming(
400
+ prompt: string | LanguageModelPromptMessage[],
401
+ options?: LanguageModelPromptOptions,
402
+ ): AsyncGenerator<string, void, undefined>;
403
+ append(messages: LanguageModelPromptMessage[]): Promise<void>;
404
+ clone(options?: { signal?: AbortSignal }): Promise<LanguageModelSession>;
405
+ destroy(): void;
406
+ readonly contextUsage: number;
407
+ readonly contextWindow: number;
408
+ measureContextUsage?(
409
+ prompt?: string | LanguageModelPromptMessage[],
410
+ options?: Pick<LanguageModelPromptOptions, "responseConstraint">,
411
+ ): Promise<{ used: number; total: number }>;
412
+ }
413
+
414
+ interface LanguageModelConstructor {
415
+ availability(
416
+ options?: LanguageModelAvailabilityOptions,
417
+ ): Promise<LanguageModelAvailability>;
418
+ create(options?: LanguageModelCreateOptions): Promise<LanguageModelSession>;
419
+ params?(): Promise<LanguageModelParams>;
420
+ }
421
+
422
+ var LanguageModel: LanguageModelConstructor;
423
+
424
+ /** @deprecated Prefer global LanguageModel. createLanguageModel() may be removed in the future. */
425
+ interface AI {
426
+ createLanguageModel(): Promise<LanguageModelSession>;
427
+ }
428
+
429
+ interface Window {
430
+ ai: AI;
431
+ }
432
+ }
package/package.json ADDED
@@ -0,0 +1,22 @@
1
+ {
2
+ "name": "chrome-web-ai-types",
3
+ "version": "0.1.0",
4
+ "description": "TypeScript definitions for Chrome Web AI APIs",
5
+ "types": "index.d.ts",
6
+ "keywords": [
7
+ "typescript",
8
+ "types",
9
+ "web-ai",
10
+ "chrome-ai",
11
+ "built-in-ai"
12
+ ],
13
+ "author": "Kevin Uehara",
14
+ "license": "MIT",
15
+ "scripts": {
16
+ "typecheck": "tsc --noEmit -p tsconfig.test.json",
17
+ "test": "npm run typecheck"
18
+ },
19
+ "devDependencies": {
20
+ "typescript": "^5.0.0"
21
+ }
22
+ }
@@ -0,0 +1,37 @@
1
+ /// <reference path="../index.d.ts" />
2
+ /**
3
+ * Type tests: these lines must FAIL type-checking.
4
+ * Each block uses @ts-expect-error to assert that the wrong usage is rejected.
5
+ * Run: npm run typecheck — this file should still compile because errors are expected.
6
+ */
7
+
8
+ async function invalidSummarizer() {
9
+ if (typeof Summarizer === "undefined") return;
10
+ // @ts-expect-error - create() expects options object or undefined, not string
11
+ await Summarizer.create("invalid");
12
+ const s = await Summarizer.create();
13
+ // @ts-expect-error - summarize() first arg must be string
14
+ await s.summarize(123);
15
+ }
16
+
17
+ async function invalidTranslator() {
18
+ if (typeof Translator === "undefined") return;
19
+ // @ts-expect-error - create() requires sourceLanguage and targetLanguage
20
+ await Translator.create({});
21
+ // @ts-expect-error - sourceLanguage is required
22
+ await Translator.create({ targetLanguage: "en" });
23
+ }
24
+
25
+ async function invalidProofreader() {
26
+ if (typeof Proofreader === "undefined") return;
27
+ const p = await Proofreader.create();
28
+ // @ts-expect-error - proofread() returns Promise<ProofreadResult>, not string
29
+ const x: string = await p.proofread("text");
30
+ }
31
+
32
+ async function invalidLanguageDetector() {
33
+ if (typeof LanguageDetector === "undefined") return;
34
+ const d = await LanguageDetector.create();
35
+ // @ts-expect-error - detect() returns Promise<LanguageDetectionResult[]>, not string
36
+ const r: string = await d.detect("hi");
37
+ }
@@ -0,0 +1,125 @@
1
+ /// <reference path="../index.d.ts" />
2
+ /**
3
+ * Type tests: valid usage of Chrome Web AI APIs.
4
+ * Run: npm run typecheck
5
+ * If this file compiles, the type definitions are working.
6
+ */
7
+
8
+ async function testSummarizer() {
9
+ if (typeof Summarizer === "undefined") return;
10
+ const availability: SummarizerAvailability = await Summarizer.availability();
11
+ if (availability === "unavailable") return;
12
+ const summarizer = await Summarizer.create({
13
+ type: "key-points",
14
+ format: "markdown",
15
+ length: "short",
16
+ });
17
+ const summary: string = await summarizer.summarize("Some long text.");
18
+ const stream = summarizer.summarizeStreaming("More text.", { context: "Article" });
19
+ for await (const chunk of stream) {
20
+ const _: string = chunk;
21
+ }
22
+ }
23
+
24
+ async function testWriter() {
25
+ if (typeof Writer === "undefined") return;
26
+ const writer = await Writer.create({ tone: "formal", format: "plain-text" });
27
+ const result: string = await writer.write("Write an email.", { context: "Work" });
28
+ const stream = writer.writeStreaming("Another prompt.");
29
+ for await (const chunk of stream) {
30
+ const _: string = chunk;
31
+ }
32
+ writer.destroy();
33
+ }
34
+
35
+ async function testRewriter() {
36
+ if (typeof Rewriter === "undefined") return;
37
+ const rewriter = await Rewriter.create({
38
+ tone: "more-formal",
39
+ length: "as-is",
40
+ });
41
+ const result: string = await rewriter.rewrite("fix this text", {
42
+ context: "Email",
43
+ tone: "more-casual",
44
+ });
45
+ const stream = rewriter.rewriteStreaming("text", { context: "Review" });
46
+ for await (const chunk of stream) {
47
+ const _: string = chunk;
48
+ }
49
+ rewriter.destroy();
50
+ }
51
+
52
+ async function testProofreader() {
53
+ if (typeof Proofreader === "undefined") return;
54
+ const proofreader = await Proofreader.create({
55
+ expectedInputLanguages: ["en"],
56
+ });
57
+ const result: ProofreadResult = await proofreader.proofread(
58
+ "I seen him yesterday."
59
+ );
60
+ const _corrected: string = result.correctedInput;
61
+ const _corrections: ProofreaderCorrection[] = result.corrections;
62
+ result.corrections.forEach((c) => {
63
+ const _s: number = c.startIndex;
64
+ const _e: number = c.endIndex;
65
+ });
66
+ }
67
+
68
+ async function testTranslator() {
69
+ if (typeof Translator === "undefined") return;
70
+ const availability = await Translator.availability({
71
+ sourceLanguage: "en",
72
+ targetLanguage: "es",
73
+ });
74
+ const translator = await Translator.create({
75
+ sourceLanguage: "en",
76
+ targetLanguage: "es",
77
+ });
78
+ const translated: string = await translator.translate("Hello world");
79
+ const stream = translator.translateStreaming("Long text...");
80
+ for await (const chunk of stream) {
81
+ const _: string = chunk;
82
+ }
83
+ }
84
+
85
+ async function testLanguageDetector() {
86
+ if (typeof LanguageDetector === "undefined") return;
87
+ const detector = await LanguageDetector.create();
88
+ const results: LanguageDetectionResult[] = await detector.detect("Hallo Welt");
89
+ results.forEach((r) => {
90
+ const _lang: string = r.detectedLanguage;
91
+ const _conf: number = r.confidence;
92
+ });
93
+ }
94
+
95
+ async function testLanguageModel() {
96
+ if (typeof LanguageModel === "undefined") return;
97
+ const availability = await LanguageModel.availability({
98
+ expectedInputs: [{ type: "text", languages: ["en"] }],
99
+ expectedOutputs: [{ type: "text", languages: ["en"] }],
100
+ });
101
+ if (availability === "unavailable") return;
102
+ const session = await LanguageModel.create({
103
+ expectedInputs: [{ type: "text", languages: ["en"] }],
104
+ expectedOutputs: [{ type: "text", languages: ["en"] }],
105
+ });
106
+ const response: string = await session.prompt("Say hello");
107
+ const stream = session.promptStreaming("Write a poem");
108
+ for await (const chunk of stream) {
109
+ const _: string = chunk;
110
+ }
111
+ await session.append([
112
+ { role: "user", content: "Follow-up" },
113
+ ]);
114
+ const cloned = await session.clone();
115
+ const _usage: number = session.contextUsage;
116
+ const _window: number = session.contextWindow;
117
+ session.destroy();
118
+ }
119
+
120
+ async function testWindowAi() {
121
+ if (typeof window === "undefined" || !window.ai) return;
122
+ const session = await window.ai.createLanguageModel();
123
+ const _: string = await session.prompt("Hi");
124
+ session.destroy();
125
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,9 @@
1
+ {
2
+ "compilerOptions": {
3
+ "declaration": true,
4
+ "emitDeclarationOnly": true,
5
+ "strict": true,
6
+ "lib": ["ES2020", "DOM"]
7
+ },
8
+ "include": ["index.d.ts"]
9
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "extends": "./tsconfig.json",
3
+ "compilerOptions": {
4
+ "noEmit": true
5
+ },
6
+ "include": ["index.d.ts", "tests/**/*.ts"]
7
+ }