@missionsquad/browserai 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 +15 -0
- package/README.md +229 -0
- package/dist/audio/clip.d.ts +51 -0
- package/dist/audio/clip.d.ts.map +1 -0
- package/dist/audio/clip.js +71 -0
- package/dist/audio/clip.js.map +1 -0
- package/dist/audio/decode.d.ts +7 -0
- package/dist/audio/decode.d.ts.map +1 -0
- package/dist/audio/decode.js +19 -0
- package/dist/audio/decode.js.map +1 -0
- package/dist/audio/pcm.d.ts +13 -0
- package/dist/audio/pcm.d.ts.map +1 -0
- package/dist/audio/pcm.js +66 -0
- package/dist/audio/pcm.js.map +1 -0
- package/dist/audio/recorder.d.ts +40 -0
- package/dist/audio/recorder.d.ts.map +1 -0
- package/dist/audio/recorder.js +127 -0
- package/dist/audio/recorder.js.map +1 -0
- package/dist/audio/streaming-player.d.ts +29 -0
- package/dist/audio/streaming-player.d.ts.map +1 -0
- package/dist/audio/streaming-player.js +82 -0
- package/dist/audio/streaming-player.js.map +1 -0
- package/dist/client.d.ts +195 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +638 -0
- package/dist/client.js.map +1 -0
- package/dist/config.d.ts +81 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +19 -0
- package/dist/config.js.map +1 -0
- package/dist/errors.d.ts +52 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +74 -0
- package/dist/errors.js.map +1 -0
- package/dist/events.d.ts +18 -0
- package/dist/events.d.ts.map +1 -0
- package/dist/events.js +43 -0
- package/dist/events.js.map +1 -0
- package/dist/generation.d.ts +12 -0
- package/dist/generation.d.ts.map +1 -0
- package/dist/generation.js +30 -0
- package/dist/generation.js.map +1 -0
- package/dist/hardware.d.ts +23 -0
- package/dist/hardware.d.ts.map +1 -0
- package/dist/hardware.js +150 -0
- package/dist/hardware.js.map +1 -0
- package/dist/history.d.ts +81 -0
- package/dist/history.d.ts.map +1 -0
- package/dist/history.js +193 -0
- package/dist/history.js.map +1 -0
- package/dist/index.d.ts +51 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +50 -0
- package/dist/index.js.map +1 -0
- package/dist/inference.d.ts +89 -0
- package/dist/inference.d.ts.map +1 -0
- package/dist/inference.js +411 -0
- package/dist/inference.js.map +1 -0
- package/dist/json.d.ts +22 -0
- package/dist/json.d.ts.map +1 -0
- package/dist/json.js +145 -0
- package/dist/json.js.map +1 -0
- package/dist/metrics.d.ts +18 -0
- package/dist/metrics.d.ts.map +1 -0
- package/dist/metrics.js +59 -0
- package/dist/metrics.js.map +1 -0
- package/dist/model-cache.d.ts +49 -0
- package/dist/model-cache.d.ts.map +1 -0
- package/dist/model-cache.js +511 -0
- package/dist/model-cache.js.map +1 -0
- package/dist/model-source.d.ts +27 -0
- package/dist/model-source.d.ts.map +1 -0
- package/dist/model-source.js +110 -0
- package/dist/model-source.js.map +1 -0
- package/dist/models.d.ts +103 -0
- package/dist/models.d.ts.map +1 -0
- package/dist/models.js +1052 -0
- package/dist/models.js.map +1 -0
- package/dist/multimodal.d.ts +261 -0
- package/dist/multimodal.d.ts.map +1 -0
- package/dist/multimodal.js +506 -0
- package/dist/multimodal.js.map +1 -0
- package/dist/prompt.d.ts +13 -0
- package/dist/prompt.d.ts.map +1 -0
- package/dist/prompt.js +32 -0
- package/dist/prompt.js.map +1 -0
- package/dist/proxy-verify.d.ts +10 -0
- package/dist/proxy-verify.d.ts.map +1 -0
- package/dist/proxy-verify.js +98 -0
- package/dist/proxy-verify.js.map +1 -0
- package/dist/schema-validator.d.ts +6 -0
- package/dist/schema-validator.d.ts.map +1 -0
- package/dist/schema-validator.js +104 -0
- package/dist/schema-validator.js.map +1 -0
- package/dist/schema.d.ts +98 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +115 -0
- package/dist/schema.js.map +1 -0
- package/dist/text-utils.d.ts +8 -0
- package/dist/text-utils.d.ts.map +1 -0
- package/dist/text-utils.js +14 -0
- package/dist/text-utils.js.map +1 -0
- package/dist/voice/helpers.d.ts +35 -0
- package/dist/voice/helpers.d.ts.map +1 -0
- package/dist/voice/helpers.js +49 -0
- package/dist/voice/helpers.js.map +1 -0
- package/dist/voice/voice-pipeline.d.ts +155 -0
- package/dist/voice/voice-pipeline.d.ts.map +1 -0
- package/dist/voice/voice-pipeline.js +407 -0
- package/dist/voice/voice-pipeline.js.map +1 -0
- package/dist/webllm.worker.d.ts +2 -0
- package/dist/webllm.worker.d.ts.map +1 -0
- package/dist/webllm.worker.js +8 -0
- package/dist/webllm.worker.js.map +1 -0
- package/package.json +62 -0
- package/src/audio/clip.ts +94 -0
- package/src/audio/decode.ts +19 -0
- package/src/audio/pcm.ts +62 -0
- package/src/audio/recorder.ts +146 -0
- package/src/audio/streaming-player.ts +99 -0
- package/src/client.ts +784 -0
- package/src/config.ts +104 -0
- package/src/errors.ts +81 -0
- package/src/events.ts +53 -0
- package/src/generation.ts +39 -0
- package/src/hardware.ts +193 -0
- package/src/history.ts +257 -0
- package/src/index.ts +203 -0
- package/src/inference.ts +579 -0
- package/src/json.ts +169 -0
- package/src/metrics.ts +63 -0
- package/src/model-cache.ts +637 -0
- package/src/model-source.ts +142 -0
- package/src/models.ts +1171 -0
- package/src/multimodal.ts +697 -0
- package/src/prompt.ts +33 -0
- package/src/proxy-verify.ts +113 -0
- package/src/schema-validator.ts +117 -0
- package/src/schema.ts +118 -0
- package/src/text-utils.ts +12 -0
- package/src/voice/helpers.ts +59 -0
- package/src/voice/voice-pipeline.ts +513 -0
- package/src/webllm.worker.ts +9 -0
- package/worker-template/README.md +39 -0
- package/worker-template/cloudflare-worker.ts +389 -0
- package/worker-template/wrangler.jsonc +19 -0
package/src/history.ts
ADDED
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
import type { ModelPreset } from "./models.js";
|
|
2
|
+
import type { StorageLike } from "./config.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Run-history persistence + aggregation. Ported from small-ai with the storage injected: pass any
|
|
6
|
+
* `StorageLike` (or `null` for in-memory only); the default is `globalThis.localStorage` when present.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/** Suggested task keys for logged runs (hosts may use their own strings). */
|
|
10
|
+
export type RunCaseKey = "json" | "chat" | "summarize" | "classify" | "qa" | "voice" | "vision";
|
|
11
|
+
|
|
12
|
+
export type ModelVendor =
|
|
13
|
+
| "qwen"
|
|
14
|
+
| "google"
|
|
15
|
+
| "meta"
|
|
16
|
+
| "openai"
|
|
17
|
+
| "ibm"
|
|
18
|
+
| "microsoft"
|
|
19
|
+
| "nvidia"
|
|
20
|
+
| "liquid"
|
|
21
|
+
| "huggingface"
|
|
22
|
+
| "mistral"
|
|
23
|
+
| "other";
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* One logged generation. This is the persisted shape, so every field is a primitive and the
|
|
27
|
+
* set is intentionally minimal: exactly what comparison views need to rebuild their aggregates
|
|
28
|
+
* (decode/ttft by model, run log) without storing full prompts/outputs. Storing raw text or
|
|
29
|
+
* per-token arrays would blow up the storage footprint, so those are excluded.
|
|
30
|
+
*/
|
|
31
|
+
export type RunRecord = {
|
|
32
|
+
/** Epoch milliseconds. */
|
|
33
|
+
ts: number;
|
|
34
|
+
/** Model short name, e.g. "Qwen3.5 0.8B". */
|
|
35
|
+
model: string;
|
|
36
|
+
/** Derived vendor bucket for filtering/labels. */
|
|
37
|
+
vendor: ModelVendor;
|
|
38
|
+
/** Backend used for the run. */
|
|
39
|
+
backend: "webllm" | "transformers-js";
|
|
40
|
+
/** Task key ({@link RunCaseKey} suggested; any non-empty string accepted). */
|
|
41
|
+
case: string;
|
|
42
|
+
promptTokens: number;
|
|
43
|
+
completionTokens: number;
|
|
44
|
+
/** Decode speed in tokens/sec. */
|
|
45
|
+
decode: number;
|
|
46
|
+
/** Time to first token in seconds. */
|
|
47
|
+
ttft: number;
|
|
48
|
+
/** Measured wall-clock time in milliseconds. */
|
|
49
|
+
totalMs: number;
|
|
50
|
+
/** Measured completion tokens/sec over wall-clock time. */
|
|
51
|
+
measured: number;
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
export type ModelAggregate = {
|
|
55
|
+
model: string;
|
|
56
|
+
vendor: ModelVendor;
|
|
57
|
+
runs: number;
|
|
58
|
+
decode: number;
|
|
59
|
+
ttft: number;
|
|
60
|
+
totalMs: number;
|
|
61
|
+
measured: number;
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
export const DEFAULT_HISTORY_KEY = "browserai:v1:history";
|
|
65
|
+
export const DEFAULT_HISTORY_MAX_RECORDS = 200;
|
|
66
|
+
|
|
67
|
+
const VALID_VENDORS = new Set<ModelVendor>([
|
|
68
|
+
"qwen",
|
|
69
|
+
"google",
|
|
70
|
+
"meta",
|
|
71
|
+
"openai",
|
|
72
|
+
"ibm",
|
|
73
|
+
"microsoft",
|
|
74
|
+
"nvidia",
|
|
75
|
+
"liquid",
|
|
76
|
+
"huggingface",
|
|
77
|
+
"mistral",
|
|
78
|
+
"other",
|
|
79
|
+
]);
|
|
80
|
+
|
|
81
|
+
export type RunHistoryOptions = {
|
|
82
|
+
/** Persistence. Defaults to `globalThis.localStorage` when available; `null` = in-memory only. */
|
|
83
|
+
storage?: StorageLike | null;
|
|
84
|
+
key?: string;
|
|
85
|
+
maxRecords?: number;
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
function defaultStorage(): StorageLike | null {
|
|
89
|
+
try {
|
|
90
|
+
// `localStorage` can throw in private-mode / sandboxed contexts; history becomes ephemeral.
|
|
91
|
+
return (globalThis as { localStorage?: StorageLike }).localStorage ?? null;
|
|
92
|
+
} catch {
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function isFiniteNumber(value: unknown): value is number {
|
|
98
|
+
return typeof value === "number" && Number.isFinite(value);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function coerceRecord(value: unknown): RunRecord | null {
|
|
102
|
+
if (!value || typeof value !== "object") return null;
|
|
103
|
+
const record = value as Record<string, unknown>;
|
|
104
|
+
const numericKeys = ["ts", "promptTokens", "completionTokens", "decode", "ttft", "totalMs", "measured"] as const;
|
|
105
|
+
for (const key of numericKeys) {
|
|
106
|
+
if (!isFiniteNumber(record[key])) return null;
|
|
107
|
+
}
|
|
108
|
+
if (typeof record.model !== "string" || typeof record.case !== "string" || record.case.length === 0) return null;
|
|
109
|
+
|
|
110
|
+
return {
|
|
111
|
+
ts: record.ts as number,
|
|
112
|
+
model: record.model,
|
|
113
|
+
vendor: VALID_VENDORS.has(record.vendor as ModelVendor) ? (record.vendor as ModelVendor) : "other",
|
|
114
|
+
backend: record.backend === "transformers-js" ? "transformers-js" : "webllm",
|
|
115
|
+
case: record.case,
|
|
116
|
+
promptTokens: record.promptTokens as number,
|
|
117
|
+
completionTokens: record.completionTokens as number,
|
|
118
|
+
decode: record.decode as number,
|
|
119
|
+
ttft: record.ttft as number,
|
|
120
|
+
totalMs: record.totalMs as number,
|
|
121
|
+
measured: record.measured as number,
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* A persisted, capped run log (newest first). All storage errors are swallowed: quota failures and
|
|
127
|
+
* unavailable storage degrade to in-memory history rather than breaking generation flows.
|
|
128
|
+
*/
|
|
129
|
+
export class RunHistoryStore {
|
|
130
|
+
readonly #storage: StorageLike | null;
|
|
131
|
+
readonly #key: string;
|
|
132
|
+
readonly #maxRecords: number;
|
|
133
|
+
#records: RunRecord[];
|
|
134
|
+
|
|
135
|
+
constructor(options: RunHistoryOptions = {}) {
|
|
136
|
+
this.#storage = options.storage === undefined ? defaultStorage() : options.storage;
|
|
137
|
+
this.#key = options.key ?? DEFAULT_HISTORY_KEY;
|
|
138
|
+
this.#maxRecords = options.maxRecords ?? DEFAULT_HISTORY_MAX_RECORDS;
|
|
139
|
+
this.#records = this.#load();
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/** The in-memory records, newest first. */
|
|
143
|
+
get records(): readonly RunRecord[] {
|
|
144
|
+
return this.#records;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/** Prepend a record and persist. Returns the updated list. */
|
|
148
|
+
append(record: RunRecord): readonly RunRecord[] {
|
|
149
|
+
this.#records = [record, ...this.#records].slice(0, this.#maxRecords);
|
|
150
|
+
this.#persist(this.#records);
|
|
151
|
+
return this.#records;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/** Overwrite the history (e.g. after deleting selected rows). */
|
|
155
|
+
replace(records: RunRecord[]): void {
|
|
156
|
+
this.#records = records.slice(0, this.#maxRecords);
|
|
157
|
+
this.#persist(this.#records);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
clear(): void {
|
|
161
|
+
this.#records = [];
|
|
162
|
+
try {
|
|
163
|
+
this.#storage?.removeItem(this.#key);
|
|
164
|
+
} catch {
|
|
165
|
+
// Clearing is best-effort.
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
aggregateByModel(caseFilter: string | "all" = "all"): ModelAggregate[] {
|
|
170
|
+
return aggregateByModel(this.#records, caseFilter);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
#load(): RunRecord[] {
|
|
174
|
+
if (!this.#storage) return [];
|
|
175
|
+
try {
|
|
176
|
+
const raw = this.#storage.getItem(this.#key);
|
|
177
|
+
if (!raw) return [];
|
|
178
|
+
const parsed = JSON.parse(raw);
|
|
179
|
+
if (!Array.isArray(parsed)) return [];
|
|
180
|
+
return parsed.map(coerceRecord).filter((record): record is RunRecord => record !== null);
|
|
181
|
+
} catch {
|
|
182
|
+
return [];
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
#persist(records: RunRecord[]): void {
|
|
187
|
+
if (!this.#storage) return;
|
|
188
|
+
try {
|
|
189
|
+
this.#storage.setItem(this.#key, JSON.stringify(records));
|
|
190
|
+
} catch {
|
|
191
|
+
// Quota errors are non-fatal; the list still lives in memory for this session.
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Derive a vendor bucket from a preset. Uses explicit id/name matching rather than the repo owner
|
|
198
|
+
* so re-hosted artifacts (e.g. onnx-community mirrors) still map to the true model vendor.
|
|
199
|
+
*/
|
|
200
|
+
export function vendorForModel(preset: ModelPreset): ModelVendor {
|
|
201
|
+
const haystack = `${preset.id} ${preset.shortName}`.toLowerCase();
|
|
202
|
+
if (haystack.includes("qwen")) return "qwen";
|
|
203
|
+
if (haystack.includes("gemma")) return "google";
|
|
204
|
+
if (haystack.includes("llama") || haystack.includes("hermes")) return "meta";
|
|
205
|
+
if (haystack.includes("whisper")) return "openai";
|
|
206
|
+
if (haystack.includes("granite")) return "ibm";
|
|
207
|
+
if (haystack.includes("phi")) return "microsoft";
|
|
208
|
+
if (haystack.includes("nemotron") || haystack.includes("parakeet")) return "nvidia";
|
|
209
|
+
if (haystack.includes("lfm") || haystack.includes("liquid")) return "liquid";
|
|
210
|
+
if (haystack.includes("smollm") || haystack.includes("smolvlm")) return "huggingface";
|
|
211
|
+
if (haystack.includes("mistral") || haystack.includes("ministral") || haystack.includes("voxtral")) return "mistral";
|
|
212
|
+
if (haystack.includes("olmo")) return "other";
|
|
213
|
+
if (haystack.includes("minicpm")) return "other";
|
|
214
|
+
return "other";
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
export const VENDOR_LABELS: Record<ModelVendor, string> = {
|
|
218
|
+
qwen: "Qwen",
|
|
219
|
+
google: "Google",
|
|
220
|
+
meta: "Meta",
|
|
221
|
+
openai: "OpenAI",
|
|
222
|
+
ibm: "IBM",
|
|
223
|
+
microsoft: "Microsoft",
|
|
224
|
+
nvidia: "NVIDIA",
|
|
225
|
+
liquid: "Liquid",
|
|
226
|
+
huggingface: "HuggingFace",
|
|
227
|
+
mistral: "Mistral",
|
|
228
|
+
other: "Other",
|
|
229
|
+
};
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Group runs by model (optionally filtered by case) and average the per-run metrics.
|
|
233
|
+
*/
|
|
234
|
+
export function aggregateByModel(history: readonly RunRecord[], caseFilter: string | "all"): ModelAggregate[] {
|
|
235
|
+
const buckets = new Map<string, { vendor: ModelVendor; runs: number; decode: number; ttft: number; totalMs: number; measured: number }>();
|
|
236
|
+
|
|
237
|
+
for (const record of history) {
|
|
238
|
+
if (caseFilter !== "all" && record.case !== caseFilter) continue;
|
|
239
|
+
const bucket = buckets.get(record.model) ?? { vendor: record.vendor, runs: 0, decode: 0, ttft: 0, totalMs: 0, measured: 0 };
|
|
240
|
+
bucket.runs += 1;
|
|
241
|
+
bucket.decode += record.decode;
|
|
242
|
+
bucket.ttft += record.ttft;
|
|
243
|
+
bucket.totalMs += record.totalMs;
|
|
244
|
+
bucket.measured += record.measured;
|
|
245
|
+
buckets.set(record.model, bucket);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
return Array.from(buckets.entries()).map(([model, bucket]) => ({
|
|
249
|
+
model,
|
|
250
|
+
vendor: bucket.vendor,
|
|
251
|
+
runs: bucket.runs,
|
|
252
|
+
decode: bucket.decode / bucket.runs,
|
|
253
|
+
ttft: bucket.ttft / bucket.runs,
|
|
254
|
+
totalMs: bucket.totalMs / bucket.runs,
|
|
255
|
+
measured: bucket.measured / bucket.runs,
|
|
256
|
+
}));
|
|
257
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @missionsquad/browserai — run small open AI models entirely in the browser with WebGPU.
|
|
3
|
+
*
|
|
4
|
+
* Core entry points:
|
|
5
|
+
* - {@link BrowserAI} — model catalog + capability-slot manager + inference façade.
|
|
6
|
+
* - {@link VoicePipeline} — headless press-to-talk voice assistant (mic → STT → LLM → TTS).
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
// Client
|
|
10
|
+
export { BrowserAI, buildModelCacheTarget, normalizeContextLength } from "./client.js";
|
|
11
|
+
export type { BrowserAIEvents, GenerateTextOptions, LoadOptions, LoadProgress, LoadedModel, StreamingTtsSession, TtsOverrides } from "./client.js";
|
|
12
|
+
|
|
13
|
+
// Configuration
|
|
14
|
+
export { DEFAULT_CONTEXT_LENGTH, resolveConfig } from "./config.js";
|
|
15
|
+
export type { BrowserAIConfig, HistoryOptions, KokoroOptions, ResolvedConfig, StorageLike, TtsDefaults, WebLLMOptions } from "./config.js";
|
|
16
|
+
|
|
17
|
+
// Errors
|
|
18
|
+
export {
|
|
19
|
+
BrowserAIError,
|
|
20
|
+
formatError,
|
|
21
|
+
MicrophoneError,
|
|
22
|
+
MissingModelError,
|
|
23
|
+
ModelLoadError,
|
|
24
|
+
ProxyVerificationError,
|
|
25
|
+
UnknownModelError,
|
|
26
|
+
VoiceTurnError,
|
|
27
|
+
WebGPUUnavailableError,
|
|
28
|
+
} from "./errors.js";
|
|
29
|
+
|
|
30
|
+
// Events
|
|
31
|
+
export { TypedEmitter } from "./events.js";
|
|
32
|
+
export type { EventMap, Listener } from "./events.js";
|
|
33
|
+
|
|
34
|
+
// Model catalog
|
|
35
|
+
export {
|
|
36
|
+
applyCuratedModelRecordOverrides,
|
|
37
|
+
CUSTOM_MODEL_RECORD_IDS,
|
|
38
|
+
CUSTOM_MODEL_RECORDS,
|
|
39
|
+
formatMB,
|
|
40
|
+
getModelPreset,
|
|
41
|
+
KOKORO_MODEL_ID,
|
|
42
|
+
KOKORO_VOICES,
|
|
43
|
+
MODALITY_ICONS,
|
|
44
|
+
MODALITY_LABELS,
|
|
45
|
+
MODEL_PRESETS,
|
|
46
|
+
MODEL_RECORD_OVERRIDES,
|
|
47
|
+
modelRepoLabel,
|
|
48
|
+
modelSlots,
|
|
49
|
+
presetModalityIn,
|
|
50
|
+
presetModalityOut,
|
|
51
|
+
presetTasks,
|
|
52
|
+
SLOT_ORDER,
|
|
53
|
+
SUPERTONIC_2_MODEL_ID,
|
|
54
|
+
SUPERTONIC_MODEL_ID,
|
|
55
|
+
SUPERTONIC_VOICES,
|
|
56
|
+
TASK_ICONS,
|
|
57
|
+
TASK_LABELS,
|
|
58
|
+
ttsVoicesForModel,
|
|
59
|
+
} from "./models.js";
|
|
60
|
+
export type { Modality, ModelBackend, ModelPreset, ModelTask, MultimodalRuntime, RuntimePreset, TtsVoice } from "./models.js";
|
|
61
|
+
|
|
62
|
+
// Generation parameters + JSON mode
|
|
63
|
+
export { buildResponseFormat, clampNumber, parseOptionalInteger, runtimeParamsFromPreset } from "./generation.js";
|
|
64
|
+
export type { JsonMode, RuntimeParameters } from "./generation.js";
|
|
65
|
+
|
|
66
|
+
// Text inference
|
|
67
|
+
export { buildRuntimeStatsText, collectGenericStats, EMPTY_RESPONSE, generate, normalizeLatencyBreakdown } from "./inference.js";
|
|
68
|
+
export type {
|
|
69
|
+
ChatMessage,
|
|
70
|
+
EngineHandles,
|
|
71
|
+
GenerateOptions,
|
|
72
|
+
GenerationResult,
|
|
73
|
+
LatencyBreakdown,
|
|
74
|
+
RuntimeStats,
|
|
75
|
+
TransformersModule,
|
|
76
|
+
TransformersTextGenerationPipeline,
|
|
77
|
+
TransformersTokenizer,
|
|
78
|
+
WebLLMUsageExtra,
|
|
79
|
+
} from "./inference.js";
|
|
80
|
+
|
|
81
|
+
// Multimodal runtimes (STT / TTS / VLM / Gemma)
|
|
82
|
+
export {
|
|
83
|
+
capSrc,
|
|
84
|
+
DEFAULT_KOKORO_CDN,
|
|
85
|
+
describeImage,
|
|
86
|
+
disposeMultimodal,
|
|
87
|
+
generateGemmaText,
|
|
88
|
+
loadMultimodal,
|
|
89
|
+
planGemmaAudioWindows,
|
|
90
|
+
runAudioLm,
|
|
91
|
+
runGemma,
|
|
92
|
+
runVoxtralRealtime,
|
|
93
|
+
supertonicVoiceUrl,
|
|
94
|
+
supportsStreamingTts,
|
|
95
|
+
synthesize,
|
|
96
|
+
synthesizeStream,
|
|
97
|
+
transcribe,
|
|
98
|
+
} from "./multimodal.js";
|
|
99
|
+
export type {
|
|
100
|
+
AudioWindow,
|
|
101
|
+
GenStats,
|
|
102
|
+
KokoroModule,
|
|
103
|
+
LoadMultimodalOptions,
|
|
104
|
+
MultimodalDevice,
|
|
105
|
+
MultimodalHandle,
|
|
106
|
+
MultimodalTransformers,
|
|
107
|
+
ProgressCallback,
|
|
108
|
+
RawAudio,
|
|
109
|
+
SttResult,
|
|
110
|
+
TextTurn,
|
|
111
|
+
TtsTextSplitter,
|
|
112
|
+
VlmResult,
|
|
113
|
+
} from "./multimodal.js";
|
|
114
|
+
|
|
115
|
+
// JSON helpers + schema validation
|
|
116
|
+
export { detectLikelyRepetition, extractJsonCandidate, normalizeModelText, parseJsonFromModel, prettyJson } from "./json.js";
|
|
117
|
+
export type { JsonParseResult } from "./json.js";
|
|
118
|
+
export { validateAgainstJsonSchema } from "./schema-validator.js";
|
|
119
|
+
export { DEFAULT_EXTRACTION_SCHEMA, stringifySchema, stripSchemaMetadata } from "./schema.js";
|
|
120
|
+
export { buildExtractionMessages, DEFAULT_EXTRACTION_INSTRUCTIONS } from "./prompt.js";
|
|
121
|
+
|
|
122
|
+
// Model source (direct vs proxy) + proxy verification
|
|
123
|
+
export {
|
|
124
|
+
applyContextOverride,
|
|
125
|
+
buildProxiedAppConfig,
|
|
126
|
+
buildWebLLMAppConfig,
|
|
127
|
+
modelSourceDescription,
|
|
128
|
+
proxyHuggingFaceUrl,
|
|
129
|
+
proxyModelLibraryUrl,
|
|
130
|
+
proxyModelRecord,
|
|
131
|
+
proxyRawGithubUrl,
|
|
132
|
+
TRANSFORMERS_CACHE_KEY,
|
|
133
|
+
withCustomModelRecords,
|
|
134
|
+
} from "./model-source.js";
|
|
135
|
+
export type { BrowserCacheBackend, ModelSourceMode } from "./model-source.js";
|
|
136
|
+
export { splitHuggingFaceRepoId, verifyTransformersProxy, verifyWebLLMProxy } from "./proxy-verify.js";
|
|
137
|
+
|
|
138
|
+
// Hardware probing
|
|
139
|
+
export { collectHardwareSnapshot, formatBytes, formatHardwareSnapshot, modelSafetyHint } from "./hardware.js";
|
|
140
|
+
export type { HardwareSnapshot } from "./hardware.js";
|
|
141
|
+
|
|
142
|
+
// Model artifact cache management
|
|
143
|
+
export {
|
|
144
|
+
deleteOneModelArtifactsFromBrowserStorage,
|
|
145
|
+
deleteTransformersModelArtifactsFromBrowserStorage,
|
|
146
|
+
deleteTransformersModelFromBrowserCache,
|
|
147
|
+
deleteWebLLMModelArtifactsFromBrowserStorage,
|
|
148
|
+
estimateOriginStorage,
|
|
149
|
+
getCachedModelStatus,
|
|
150
|
+
hasTransformersModelInBrowserCache,
|
|
151
|
+
matchesModelCacheTarget,
|
|
152
|
+
TRANSFORMERS_CACHE_SCOPE,
|
|
153
|
+
WEBLLM_CACHE_SCOPES,
|
|
154
|
+
} from "./model-cache.js";
|
|
155
|
+
export type {
|
|
156
|
+
CacheCleanupResult,
|
|
157
|
+
CacheCleanupScopeResult,
|
|
158
|
+
CachedModelStatus,
|
|
159
|
+
IndividualModelCacheStatus,
|
|
160
|
+
IndividualModelCleanupResult,
|
|
161
|
+
ModelCacheTarget,
|
|
162
|
+
StorageEstimateSnapshot,
|
|
163
|
+
} from "./model-cache.js";
|
|
164
|
+
|
|
165
|
+
// Metrics + run history
|
|
166
|
+
export { buildMultimodalStats, runRecordFromStats, wordCountGenStats } from "./metrics.js";
|
|
167
|
+
export {
|
|
168
|
+
aggregateByModel,
|
|
169
|
+
DEFAULT_HISTORY_KEY,
|
|
170
|
+
DEFAULT_HISTORY_MAX_RECORDS,
|
|
171
|
+
RunHistoryStore,
|
|
172
|
+
VENDOR_LABELS,
|
|
173
|
+
vendorForModel,
|
|
174
|
+
} from "./history.js";
|
|
175
|
+
export type { ModelAggregate, ModelVendor, RunCaseKey, RunHistoryOptions, RunRecord } from "./history.js";
|
|
176
|
+
|
|
177
|
+
// Audio utilities
|
|
178
|
+
export { AUDIO_SR, encodeWavBlob, pitchShiftBuffer } from "./audio/pcm.js";
|
|
179
|
+
export { decodeAudioTo16kMono } from "./audio/decode.js";
|
|
180
|
+
export { MicRecorder } from "./audio/recorder.js";
|
|
181
|
+
export type { MicRecorderOptions } from "./audio/recorder.js";
|
|
182
|
+
export { createStreamingAudioPlayer } from "./audio/streaming-player.js";
|
|
183
|
+
export type { StreamingAudioPlayer, StreamingAudioPlayerOptions } from "./audio/streaming-player.js";
|
|
184
|
+
export { clipFromRawAudio, clipPlaybackRate, playClipThroughElement, releaseClip, repitchClip, synthesizeClip } from "./audio/clip.js";
|
|
185
|
+
export type { SynthClip, SynthesizeClipOptions } from "./audio/clip.js";
|
|
186
|
+
|
|
187
|
+
// Text utilities
|
|
188
|
+
export { stripThinkTags } from "./text-utils.js";
|
|
189
|
+
|
|
190
|
+
// Voice pipeline
|
|
191
|
+
export {
|
|
192
|
+
capPipelineHistory,
|
|
193
|
+
missingPipelineModels,
|
|
194
|
+
PIPELINE_HISTORY_MAX_TURNS,
|
|
195
|
+
PIPELINE_RECOMMENDED,
|
|
196
|
+
PIPELINE_SYSTEM_PROMPT,
|
|
197
|
+
PIPELINE_TASKS,
|
|
198
|
+
shouldSpeakReply,
|
|
199
|
+
streamedDelta,
|
|
200
|
+
} from "./voice/helpers.js";
|
|
201
|
+
export type { PipelineTask } from "./voice/helpers.js";
|
|
202
|
+
export { VoicePipeline } from "./voice/voice-pipeline.js";
|
|
203
|
+
export type { TurnDiscardReason, VoicePipelineEvents, VoicePipelineOptions, VoicePipelineStage } from "./voice/voice-pipeline.js";
|