@mieweb/ui 0.11.0-dev.1 → 0.11.0-dev.10
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/dist/ag-grid.cjs +11 -2
- package/dist/ag-grid.cjs.map +1 -1
- package/dist/ag-grid.d.cts +8 -0
- package/dist/ag-grid.d.ts +8 -0
- package/dist/ag-grid.js +11 -2
- package/dist/ag-grid.js.map +1 -1
- package/dist/brands/index.cjs +12 -12
- package/dist/brands/index.js +3 -3
- package/dist/{chunk-U2RS574O.cjs → chunk-2GBVJHWN.cjs} +120 -63
- package/dist/chunk-2GBVJHWN.cjs.map +1 -0
- package/dist/{chunk-7UTBDFFL.cjs → chunk-2S76TRBJ.cjs} +4 -4
- package/dist/{chunk-7UTBDFFL.cjs.map → chunk-2S76TRBJ.cjs.map} +1 -1
- package/dist/{chunk-IJYTASQQ.cjs → chunk-3AD4HFYI.cjs} +15 -7
- package/dist/chunk-3AD4HFYI.cjs.map +1 -0
- package/dist/{chunk-CFI3TQMA.cjs → chunk-56C7K4MV.cjs} +9 -4
- package/dist/chunk-56C7K4MV.cjs.map +1 -0
- package/dist/{chunk-TNUL4LGG.js → chunk-5ILCNY74.js} +15 -7
- package/dist/chunk-5ILCNY74.js.map +1 -0
- package/dist/{chunk-AFDW64EF.cjs → chunk-5K7PRPSV.cjs} +30 -2
- package/dist/chunk-5K7PRPSV.cjs.map +1 -0
- package/dist/{chunk-QQCHM7BZ.cjs → chunk-5VA2HJ5B.cjs} +6 -6
- package/dist/{chunk-QQCHM7BZ.cjs.map → chunk-5VA2HJ5B.cjs.map} +1 -1
- package/dist/{chunk-PJ6CC53R.cjs → chunk-AKMTPCLC.cjs} +13 -8
- package/dist/chunk-AKMTPCLC.cjs.map +1 -0
- package/dist/{chunk-OODVC2UD.cjs → chunk-AWSSWNJY.cjs} +2 -2
- package/dist/{chunk-OODVC2UD.cjs.map → chunk-AWSSWNJY.cjs.map} +1 -1
- package/dist/chunk-BFVYM6IT.cjs +345 -0
- package/dist/chunk-BFVYM6IT.cjs.map +1 -0
- package/dist/{chunk-VVDE4CHU.js → chunk-C4GEPUE7.js} +13 -8
- package/dist/chunk-C4GEPUE7.js.map +1 -0
- package/dist/{chunk-TJ4GWQPM.js → chunk-DAAJ3B2T.js} +121 -65
- package/dist/chunk-DAAJ3B2T.js.map +1 -0
- package/dist/{chunk-QJ2L5RU6.js → chunk-DSQCYX7L.js} +2 -2
- package/dist/{chunk-QJ2L5RU6.js.map → chunk-DSQCYX7L.js.map} +1 -1
- package/dist/{chunk-NUB5HRKS.js → chunk-DT3X3RBM.js} +3 -3
- package/dist/{chunk-NUB5HRKS.js.map → chunk-DT3X3RBM.js.map} +1 -1
- package/dist/{chunk-AG5EKCE4.js → chunk-EBQG3NGT.js} +30 -2
- package/dist/chunk-EBQG3NGT.js.map +1 -0
- package/dist/{chunk-MYAU2ZUC.cjs → chunk-GDKOYVX3.cjs} +14 -10
- package/dist/chunk-GDKOYVX3.cjs.map +1 -0
- package/dist/{chunk-JTSKPDPH.cjs → chunk-HIYQ3M5V.cjs} +4 -3
- package/dist/chunk-HIYQ3M5V.cjs.map +1 -0
- package/dist/{chunk-7IBZA7G6.js → chunk-I6Y2KLTZ.js} +5 -2
- package/dist/chunk-I6Y2KLTZ.js.map +1 -0
- package/dist/chunk-IZY4CMOO.js +715 -0
- package/dist/chunk-IZY4CMOO.js.map +1 -0
- package/dist/{chunk-753ENNB6.js → chunk-J3QEMZCH.js} +2 -2
- package/dist/{chunk-753ENNB6.js.map → chunk-J3QEMZCH.js.map} +1 -1
- package/dist/{chunk-S2JZL4JC.js → chunk-JM4YFLO4.js} +22 -15
- package/dist/chunk-JM4YFLO4.js.map +1 -0
- package/dist/{chunk-QX6AAVDE.cjs → chunk-L4APW65W.cjs} +15 -6
- package/dist/chunk-L4APW65W.cjs.map +1 -0
- package/dist/{chunk-OHKO5THF.cjs → chunk-MGFRGPWI.cjs} +3 -2
- package/dist/chunk-MGFRGPWI.cjs.map +1 -0
- package/dist/{chunk-RM2HPQIC.js → chunk-MQ5WJ3NO.js} +4 -4
- package/dist/chunk-MQ5WJ3NO.js.map +1 -0
- package/dist/{chunk-VNWJTCBQ.js → chunk-MQOYDQTF.js} +4 -3
- package/dist/chunk-MQOYDQTF.js.map +1 -0
- package/dist/chunk-MZA2LDS4.js +321 -0
- package/dist/chunk-MZA2LDS4.js.map +1 -0
- package/dist/{chunk-VYNFJVRZ.js → chunk-N6XBE47W.js} +3 -3
- package/dist/{chunk-VYNFJVRZ.js.map → chunk-N6XBE47W.js.map} +1 -1
- package/dist/{chunk-T5BBZQ66.js → chunk-OTIKWEFZ.js} +9 -4
- package/dist/chunk-OTIKWEFZ.js.map +1 -0
- package/dist/{chunk-YZCM7CXK.js → chunk-OZKJYLN6.js} +3 -3
- package/dist/{chunk-YZCM7CXK.js.map → chunk-OZKJYLN6.js.map} +1 -1
- package/dist/{chunk-ZSGEGISB.cjs → chunk-PHUTJKHL.cjs} +5 -2
- package/dist/chunk-PHUTJKHL.cjs.map +1 -0
- package/dist/{chunk-FMEA6WAY.cjs → chunk-Q6QLGCL7.cjs} +9 -9
- package/dist/{chunk-FMEA6WAY.cjs.map → chunk-Q6QLGCL7.cjs.map} +1 -1
- package/dist/{chunk-XOIIUO6O.js → chunk-QDNHN7R2.js} +3 -2
- package/dist/chunk-QDNHN7R2.js.map +1 -0
- package/dist/{chunk-XRVMYT5G.cjs → chunk-QKW2QCGI.cjs} +5 -5
- package/dist/chunk-QKW2QCGI.cjs.map +1 -0
- package/dist/{chunk-NAH65KPK.cjs → chunk-TOJ56HKQ.cjs} +2 -2
- package/dist/{chunk-NAH65KPK.cjs.map → chunk-TOJ56HKQ.cjs.map} +1 -1
- package/dist/chunk-TRZLN32I.cjs +740 -0
- package/dist/chunk-TRZLN32I.cjs.map +1 -0
- package/dist/{chunk-O6XDA3SI.js → chunk-UY2EZYIC.js} +15 -6
- package/dist/chunk-UY2EZYIC.js.map +1 -0
- package/dist/{chunk-2BPIVWAK.js → chunk-V5VPECJI.js} +14 -10
- package/dist/chunk-V5VPECJI.js.map +1 -0
- package/dist/{chunk-O6BJMVGT.cjs → chunk-XZNHS7YQ.cjs} +24 -17
- package/dist/chunk-XZNHS7YQ.cjs.map +1 -0
- package/dist/components/AudioPlayer/index.cjs +7 -6
- package/dist/components/AudioPlayer/index.js +2 -1
- package/dist/components/CollabStatus/index.cjs +5 -4
- package/dist/components/CollabStatus/index.js +2 -1
- package/dist/components/CountryCodeDropdown/index.cjs +4 -4
- package/dist/components/CountryCodeDropdown/index.js +1 -1
- package/dist/components/DateInput/index.cjs +2 -2
- package/dist/components/DateInput/index.js +1 -1
- package/dist/components/DictationButton/index.cjs +23 -0
- package/dist/components/DictationButton/index.cjs.map +1 -0
- package/dist/components/DictationButton/index.d.cts +78 -0
- package/dist/components/DictationButton/index.d.ts +78 -0
- package/dist/components/DictationButton/index.js +6 -0
- package/dist/components/DictationButton/index.js.map +1 -0
- package/dist/components/Markdown/index.cjs +10 -10
- package/dist/components/Markdown/index.js +2 -2
- package/dist/components/MediaEditor/index.cjs +8 -7
- package/dist/components/MediaEditor/index.js +3 -2
- package/dist/components/PhoneInput/index.cjs +3 -3
- package/dist/components/PhoneInput/index.js +1 -1
- package/dist/components/RecordButton/index.cjs +4 -4
- package/dist/components/RecordButton/index.js +1 -1
- package/dist/components/Slider/index.cjs +6 -5
- package/dist/components/Slider/index.js +2 -1
- package/dist/components/SliderCalculator/index.cjs +5 -4
- package/dist/components/SliderCalculator/index.js +3 -2
- package/dist/components/SuperChat/index.cjs +14 -14
- package/dist/components/SuperChat/index.cjs.map +1 -1
- package/dist/components/SuperChat/index.d.cts +10 -6
- package/dist/components/SuperChat/index.d.ts +10 -6
- package/dist/components/SuperChat/index.js +4 -4
- package/dist/components/SuperChat/index.js.map +1 -1
- package/dist/components/SuperChat/plugins/index.cjs +3 -3
- package/dist/components/SuperChat/plugins/index.d.cts +2 -2
- package/dist/components/SuperChat/plugins/index.d.ts +2 -2
- package/dist/components/SuperChat/plugins/index.js +2 -2
- package/dist/components/Table/index.cjs +9 -9
- package/dist/components/Table/index.d.cts +17 -1
- package/dist/components/Table/index.d.ts +17 -1
- package/dist/components/Table/index.js +1 -1
- package/dist/deck.cjs +1 -1
- package/dist/deck.cjs.map +1 -1
- package/dist/deck.js +1 -1
- package/dist/deck.js.map +1 -1
- package/dist/esheet.cjs +5 -5
- package/dist/esheet.js +2 -2
- package/dist/index.cjs +600 -1134
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +154 -14
- package/dist/index.d.ts +154 -14
- package/dist/index.js +230 -834
- package/dist/index.js.map +1 -1
- package/dist/styles/init.css +39 -0
- package/dist/styles.css +1 -1
- package/dist/tailwind-preset.cjs +4 -4
- package/dist/tailwind-preset.js +1 -1
- package/dist/{types-Cx1FHLq2.d.ts → types-DSWbrVkM.d.cts} +1 -1
- package/dist/{types-Cx1FHLq2.d.cts → types-DSWbrVkM.d.ts} +1 -1
- package/dist/whisperTranscribe-AV752TZI.cjs +81 -0
- package/dist/whisperTranscribe-AV752TZI.cjs.map +1 -0
- package/dist/whisperTranscribe-UBNUWXUQ.js +4 -0
- package/dist/whisperTranscribe-UBNUWXUQ.js.map +1 -0
- package/package.json +1 -1
- package/dist/chunk-2BPIVWAK.js.map +0 -1
- package/dist/chunk-7IBZA7G6.js.map +0 -1
- package/dist/chunk-AFDW64EF.cjs.map +0 -1
- package/dist/chunk-AG5EKCE4.js.map +0 -1
- package/dist/chunk-CFI3TQMA.cjs.map +0 -1
- package/dist/chunk-IJYTASQQ.cjs.map +0 -1
- package/dist/chunk-JTSKPDPH.cjs.map +0 -1
- package/dist/chunk-MYAU2ZUC.cjs.map +0 -1
- package/dist/chunk-O6BJMVGT.cjs.map +0 -1
- package/dist/chunk-O6XDA3SI.js.map +0 -1
- package/dist/chunk-OHKO5THF.cjs.map +0 -1
- package/dist/chunk-PJ6CC53R.cjs.map +0 -1
- package/dist/chunk-QX6AAVDE.cjs.map +0 -1
- package/dist/chunk-RM2HPQIC.js.map +0 -1
- package/dist/chunk-S2JZL4JC.js.map +0 -1
- package/dist/chunk-T5BBZQ66.js.map +0 -1
- package/dist/chunk-TJ4GWQPM.js.map +0 -1
- package/dist/chunk-TNUL4LGG.js.map +0 -1
- package/dist/chunk-U2RS574O.cjs.map +0 -1
- package/dist/chunk-VNWJTCBQ.js.map +0 -1
- package/dist/chunk-VVDE4CHU.js.map +0 -1
- package/dist/chunk-XOIIUO6O.js.map +0 -1
- package/dist/chunk-XRVMYT5G.cjs.map +0 -1
- package/dist/chunk-ZSGEGISB.cjs.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/AI/modelCache.ts","../src/components/AI/ozwellChat.ts","../src/components/AI/whisperTranscribe.ts"],"names":["o"],"mappings":"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","file":"chunk-IZY4CMOO.js","sourcesContent":["/**\n * Registers the model-cache service worker. In this repo the SW file lives at\n * `.storybook/public/ozwell-model-sw.js` and is served at `/ozwell-model-sw.js` by Storybook only — a\n * consumer that wants caching outside Storybook must serve/copy the SW at the `swUrl` path passed below.\n *\n * Why: cache the wake-word + speaker-verification model assets across app opens so a returning user\n * loads them from disk instead of re-downloading. The service worker fetches the full file itself and\n * serves a complete copy on later opens.\n * NOTE: Whisper turbo caching is handled SEPARATELY by transformers.js (it streams the model into the\n * Cache API, and the model is hosted on Cloudflare R2 which sends Content-Length) — the SW intentionally\n * does NOT intercept the Whisper weight files. See ozwell-model-sw.js / AI/MODEL-HOSTING.md.\n *\n * Idempotent and best-effort: safe to call from multiple mount points; no-ops without SW support.\n * The SW intercepts on the NEXT load (it activates + claims after first registration), so the very\n * first visit still downloads normally; subsequent opens are cache hits.\n */\nconst registered = new Set<string>();\n\nexport function registerModelServiceWorker(\n swUrl = '/ozwell-model-sw.js'\n): void {\n // Bail BEFORE memoizing if SW is unavailable (SSR / unsupported), so we don't mark the URL \"registered\"\n // and then skip the real registration once running in a proper browser.\n if (typeof navigator === 'undefined' || !('serviceWorker' in navigator))\n return;\n if (registered.has(swUrl)) return; // memoize per-URL, so a different swUrl isn't silently ignored\n registered.add(swUrl);\n navigator.serviceWorker.register(swUrl).then(\n () => console.log('[modelCache] model service worker registered'),\n (e) => {\n // Un-memoize on failure (404 in local dev, transient offline/CSP) so a later call can retry this\n // session instead of caching staying disabled until a full reload.\n registered.delete(swUrl);\n console.warn(\n '[modelCache] SW registration failed (models will still load, just not cached):',\n e\n );\n }\n );\n}\n","/**\n * Ozwell chat backend — the real call that replaces the demo stub.\n *\n * Mirrors the ozwellai-api TypeScript SDK (clients/typescript/src/index.ts) with plain `fetch`,\n * so there's no SDK dependency to install: OpenAI-compatible POST /v1/chat/completions, Bearer auth,\n * `messages` array in / `choices[0].message.content` (or streamed `delta.content`) out.\n *\n * KEY HANDLING (deliberate): the API key is NEVER hardcoded or committed. It's read at runtime from\n * - `window.__ozwell` (e.g. `window.__ozwell = { apiKey: 'sk-...' }` in the console), or\n * - `localStorage['ozwellConfig']` (JSON, survives reloads).\n * If no key is configured, `isOzwellConfigured()` is false and the chat falls back to its canned reply —\n * so this file is always safe to push and the demo still works keyless. For a PUBLIC deploy the key\n * should live server-side behind a proxy (a browser-direct Bearer key is visible to anyone with the page);\n * point `baseURL` at that proxy then. See AI/MODEL-HOSTING.md / the hosted-demo plan.\n */\n\nexport interface OzwellMessage {\n role: 'system' | 'user' | 'assistant';\n content: string;\n}\n\nexport interface OzwellConfig {\n /** API base. Defaults to https://api.ozwell.ai (or http://localhost:11434 when apiKey === 'ollama'). */\n baseURL: string;\n /** Bearer key. Empty = not configured → callers fall back to the stub. */\n apiKey: string;\n /** Model id. */\n model: string;\n /** System prompt prepended to the conversation (omit by setting to ''). */\n system: string;\n /** Sampling temperature. */\n temperature: number;\n}\n\nconst DEFAULT_BASE = 'https://api.ozwell.ai';\nconst OLLAMA_BASE = 'http://localhost:11434';\nconst DEFAULTS = {\n model: 'gpt-4o-mini',\n system:\n 'You are Ozwell, a concise and helpful clinical assistant. Answer briefly and clearly.',\n temperature: 0.7,\n};\n\n// Storybook renders each story in an IFRAME, so a console-set `window.__ozwell` usually lands on the\n// parent frame, not the story's. Check current → parent → top (all same-origin, so safe). localStorage\n// is shared across same-origin frames, so the localStorage form always works regardless of frame.\nfunction readWindowGlobal(): Partial<OzwellConfig> {\n if (typeof window === 'undefined') return {}; // SSR / Node — no window\n const get = (w?: Window | null): Partial<OzwellConfig> | undefined => {\n try {\n return (w as unknown as { __ozwell?: Partial<OzwellConfig> })?.__ozwell;\n } catch {\n return undefined;\n }\n };\n return get(window) || get(window.parent) || get(window.top) || {};\n}\n// Copy only safe, own keys from parsed/external config (drop __proto__/constructor/prototype). Object\n// spread alone can't pollute Object.prototype (CreateDataProperty semantics), but the rest of this PR's\n// config parsers (voiceprintStore, diarize) filter dangerous keys — keep this one consistent.\nfunction sanitizeConfig(o: unknown): Partial<OzwellConfig> {\n if (!o || typeof o !== 'object') return {};\n const out: Record<string, unknown> = {};\n for (const k of Object.keys(o)) {\n if (k === '__proto__' || k === 'constructor' || k === 'prototype') continue;\n out[k] = (o as Record<string, unknown>)[k];\n }\n return out as Partial<OzwellConfig>;\n}\nfunction readRaw(): Partial<OzwellConfig> {\n let stored: Partial<OzwellConfig> = {};\n try {\n stored = sanitizeConfig(\n JSON.parse(localStorage.getItem('ozwellConfig') || '{}')\n );\n } catch {\n /* ignore bad JSON */\n }\n return { ...stored, ...sanitizeConfig(readWindowGlobal()) }; // window override wins over localStorage\n}\n\n/** Resolve the effective config from runtime sources + defaults. */\nexport function getOzwellConfig(): OzwellConfig {\n const c = readRaw();\n const apiKey = c.apiKey || '';\n const baseURL =\n c.baseURL || (apiKey === 'ollama' ? OLLAMA_BASE : DEFAULT_BASE);\n return {\n baseURL,\n apiKey,\n model: c.model || DEFAULTS.model,\n system: c.system ?? DEFAULTS.system,\n // Coerce: temperature set via console/localStorage often arrives as a string; a string in the request\n // body can be rejected by OpenAI-compatible servers. Fall back to the default if it's not a real number —\n // and guard the empty/whitespace string explicitly, since Number('') is 0 (a valid-looking temperature)\n // and would silently pin sampling to 0 instead of using the default.\n temperature:\n c.temperature != null &&\n String(c.temperature).trim() !== '' &&\n Number.isFinite(Number(c.temperature))\n ? Number(c.temperature)\n : DEFAULTS.temperature,\n };\n}\n\n/** True once a key is configured — gate the real call on this; otherwise keep the stub reply. */\nexport function isOzwellConfigured(): boolean {\n return !!getOzwellConfig().apiKey;\n}\n\n/** Map AIChat's message blocks to the API's role/content shape (user+assistant text only) for multi-turn. */\nexport function toOzwellMessages(\n msgs: { role: string; content: { type?: string; text?: string }[] }[]\n): OzwellMessage[] {\n const out: OzwellMessage[] = [];\n for (const m of msgs) {\n if (m.role !== 'user' && m.role !== 'assistant') continue;\n const text = (m.content || [])\n .map((c) => c.text || '')\n .join(' ')\n .trim();\n if (text) out.push({ role: m.role, content: text });\n }\n return out;\n}\n\nfunction withSystem(\n messages: OzwellMessage[],\n system: string\n): OzwellMessage[] {\n if (!system || messages.some((m) => m.role === 'system')) return messages;\n return [{ role: 'system', content: system }, ...messages];\n}\n\nfunction buildRequest(\n messages: OzwellMessage[] | string,\n cfg: OzwellConfig,\n stream: boolean\n) {\n const msgs =\n typeof messages === 'string'\n ? [{ role: 'user' as const, content: messages }]\n : messages;\n return {\n url: `${cfg.baseURL.replace(/\\/$/, '')}/v1/chat/completions`,\n headers: {\n 'Content-Type': 'application/json',\n // 'ollama' is a sentinel that points baseURL at the local Ollama server, not a real credential —\n // don't send it as a Bearer token (some local OpenAI-compatible servers reject unexpected auth).\n ...(cfg.apiKey && cfg.apiKey !== 'ollama'\n ? { Authorization: `Bearer ${cfg.apiKey}` }\n : {}),\n } as Record<string, string>,\n body: JSON.stringify({\n model: cfg.model,\n messages: withSystem(msgs, cfg.system),\n temperature: cfg.temperature,\n stream,\n }),\n };\n}\n\nexport interface AskOpts extends Partial<OzwellConfig> {\n signal?: AbortSignal;\n}\n\n/**\n * Merge call-time opts over the runtime config. The `apiKey: 'ollama'` sentinel switches baseURL to the\n * local Ollama server inside getOzwellConfig(); honor it when the caller passes it via opts too (without\n * also passing a baseURL), so the request doesn't target the non-Ollama default.\n */\nfunction resolveConfig(opts: AskOpts): OzwellConfig {\n const cfg = { ...getOzwellConfig(), ...opts };\n // When the caller overrides the apiKey but not the baseURL (and there's no explicit baseURL in the\n // runtime config either), re-derive the baseURL from the EFFECTIVE apiKey. Otherwise a runtime config\n // using the 'ollama' sentinel would keep a real key pointed at the Ollama server (and vice-versa). An\n // explicit baseURL — from opts or the runtime config — is always respected.\n if (opts.apiKey && !opts.baseURL && !readRaw().baseURL) {\n cfg.baseURL = cfg.apiKey === 'ollama' ? OLLAMA_BASE : DEFAULT_BASE;\n }\n return cfg;\n}\n\n/** One-shot (non-streaming) completion → the answer text. Throws on HTTP error. */\nexport async function askOzwell(\n messages: OzwellMessage[] | string,\n opts: AskOpts = {}\n): Promise<string> {\n const cfg = resolveConfig(opts);\n const req = buildRequest(messages, cfg, false);\n const res = await fetch(req.url, {\n method: 'POST',\n headers: req.headers,\n body: req.body,\n signal: opts.signal,\n });\n if (!res.ok) throw new Error(`Ozwell API ${res.status}: ${res.statusText}`);\n const data = await res.json();\n return (data?.choices?.[0]?.message?.content ?? '').trim();\n}\n\n/**\n * Streaming completion (SSE). Calls `onToken(delta, full)` as text arrives and resolves with the full text.\n * Token-by-token is the natural fit for a spoken/hands-free reply. Throws on HTTP error.\n */\nexport async function askOzwellStream(\n messages: OzwellMessage[] | string,\n onToken: (delta: string, full: string) => void,\n opts: AskOpts = {}\n): Promise<string> {\n const cfg = resolveConfig(opts);\n const req = buildRequest(messages, cfg, true);\n const res = await fetch(req.url, {\n method: 'POST',\n headers: req.headers,\n body: req.body,\n signal: opts.signal,\n });\n if (!res.ok || !res.body)\n throw new Error(`Ozwell API ${res.status}: ${res.statusText}`);\n\n const reader = res.body.getReader();\n const decoder = new TextDecoder();\n let buf = '';\n let full = '';\n // Process one SSE event's `data:` lines; returns true once the terminal [DONE] frame is seen.\n const processEvent = (ev: string): boolean => {\n for (const line of ev.split(/\\r?\\n/)) {\n if (!line.startsWith('data:')) continue;\n const payload = line.slice(5).trim();\n if (payload === '[DONE]') return true;\n try {\n const json = JSON.parse(payload);\n const delta: string = json?.choices?.[0]?.delta?.content || '';\n if (delta) {\n full += delta;\n onToken(delta, full);\n }\n } catch {\n /* keep-alive / partial line — ignore */\n }\n }\n return false;\n };\n try {\n for (;;) {\n const { done, value } = await reader.read();\n if (done) break;\n buf += decoder.decode(value, { stream: true });\n const events = buf.split(/\\r?\\n\\r?\\n/); // SSE events are separated by a blank line (handle CRLF too)\n buf = events.pop() || ''; // keep the trailing partial event for the next chunk\n for (const ev of events) if (processEvent(ev)) return full;\n }\n // Stream ended: flush the decoder (a final multi-byte UTF-8 char can be split across chunks) and\n // process any trailing event that arrived WITHOUT a blank line, so the last token(s) aren't dropped.\n buf += decoder.decode();\n if (buf.trim()) processEvent(buf);\n } finally {\n // Release the connection promptly on BOTH normal completion and the early `[DONE]` return, so we\n // don't hold the socket open or fight a caller's AbortController. cancel() also releases the lock.\n try {\n await reader.cancel();\n } catch {\n /* stream already closed/errored — nothing to release */\n }\n }\n return full;\n}\n","/**\n * On-device Whisper transcription (Transformers.js from CDN, no install).\n * Shared by the AIChat voice story and the hands-free composition.\n *\n * Whisper runs in a dedicated Web Worker (see WORKER_SRC below) so its heavy download + model\n * instantiation + inference never runs on the main thread. That matters because the on-device WAKE\n * detector runs its ONNX inference on the main thread (single-threaded WASM); before this, loading the\n * ~1.3 GB turbo model starved the wake loop and \"hey ozwell\" wasn't detected until Whisper had loaded.\n * The worker relocates the compute only — same models, same output, same PHI-safe on-device path (audio\n * never leaves the page). The public API here is unchanged; callers don't know a worker exists.\n *\n * transcribeBlob(blob) — decode a recorded blob → 16 kHz mono → transcribe in the worker → text.\n * transcribeGate(samples) — a SECOND, fast (base.en) model used only for the hands-free \"stop-confirm\"\n * check. Independent of the dictation model so the heavy turbo stays the final-transcription path.\n */\nimport { registerModelServiceWorker } from './modelCache';\nimport { getOzwellConfig } from './ozwellChat';\nimport type { TranscriptSegment } from './diarize';\n\nconst HF_HOST = 'https://huggingface.co';\nconst HF_PATH = '{model}/resolve/{revision}/';\n// turbo's weights are served from our Cloudflare R2 bucket, which sends a Content-Length header so\n// transformers.js can stream it into the Cache API (HuggingFace Xet doesn't → re-downloads ~1.3GB each\n// open). This is the DEFAULT; it's runtime-overridable (see whisperHost) so the hosting cutover is a\n// pure-config swap, consistent with the wake/speaker assets and the transformers CDN. See MODEL-HOSTING.md.\nconst R2_HOST = 'https://pub-64db68afc2cb4e108ff06e7e583f09d1.r2.dev';\n\n// Where the turbo Whisper weights load from. Defaults to R2_HOST, overridable at runtime so a consumer can\n// repoint EVERY model to a mieweb-owned host with zero source edits — mirrors `window.__ozwellAssets`\n// (wake/speaker) and `window.__ozwellTransformersUrl` (the ESM). Checks current → parent → top frame\n// (Storybook iframe) → localStorage `ozwellConfig.whisperHost`. Trailing slash trimmed (the worker adds it).\nfunction whisperHost(): string {\n if (typeof window === 'undefined') return R2_HOST;\n const fromWin = (w?: Window | null): string | undefined => {\n try {\n return (w as unknown as { __ozwellWhisperHost?: string })\n ?.__ozwellWhisperHost;\n } catch {\n return undefined;\n }\n };\n const win = fromWin(window) || fromWin(window.parent) || fromWin(window.top);\n if (win) return win.replace(/\\/$/, '');\n try {\n const h = JSON.parse(\n localStorage.getItem('ozwellConfig') || '{}'\n ).whisperHost;\n if (h) return String(h).replace(/\\/$/, '');\n } catch {\n /* ignore */\n }\n return R2_HOST;\n}\n\nconst SMALL_MODELS: Record<string, string> = {\n tiny: 'Xenova/whisper-tiny.en',\n 'tiny.en': 'Xenova/whisper-tiny.en',\n base: 'Xenova/whisper-base.en',\n 'base.en': 'Xenova/whisper-base.en',\n small: 'Xenova/whisper-small.en',\n 'small.en': 'Xenova/whisper-small.en',\n};\nconst GATE_MODEL = 'Xenova/whisper-base.en'; // stop-confirm: fast + reliable on the single word \"done\"\n\n// Optional model override, read from the same ozwellConfig used by the chat. Set\n// `{ ..., whisper: 'base.en' }` to force the small (~75 MB) English model instead of the heavy turbo\n// one — much faster to download and runs even when browser storage is tight/over-quota. Checks current →\n// parent → top frame (Storybook iframe) and localStorage. Resolved HERE (main thread) and passed into the\n// worker, which can't read window/localStorage.\nfunction whisperPref(): string | null {\n if (typeof window === 'undefined') return null; // SSR / Node — no window/localStorage\n const fromWin = (w?: Window | null): string | undefined => {\n try {\n return (w as unknown as { __ozwell?: { whisper?: string } })?.__ozwell\n ?.whisper;\n } catch {\n return undefined;\n }\n };\n const win = fromWin(window) || fromWin(window.parent) || fromWin(window.top);\n if (win) return win;\n try {\n return (\n JSON.parse(localStorage.getItem('ozwellConfig') || '{}').whisper || null\n );\n } catch {\n return null;\n }\n}\n\n// Optional inference-device override for the small English models: set\n// `window.__ozwell.whisperDevice = 'wasm'` (or `ozwellConfig.whisperDevice` in localStorage) to skip the\n// WebGPU attempt. WebGPU on software/broken adapters (headless & automation browsers, some VMs) can\n// \"succeed\" while computing garbage tokens — wasm is slower but always correct. Same window→parent→top→\n// localStorage resolution as the model pref.\nfunction whisperDevice(): string | null {\n if (typeof window === 'undefined') return null;\n const fromWin = (w?: Window | null): string | undefined => {\n try {\n return (w as unknown as { __ozwell?: { whisperDevice?: string } })\n ?.__ozwell?.whisperDevice;\n } catch {\n return undefined;\n }\n };\n const win = fromWin(window) || fromWin(window.parent) || fromWin(window.top);\n if (win) return win;\n try {\n return (\n JSON.parse(localStorage.getItem('ozwellConfig') || '{}').whisperDevice ||\n null\n );\n } catch {\n return null;\n }\n}\n\n// Optional dtype override for the small English models' WebGPU attempt (default 'q8'). The q8 WebGPU\n// kernels miscompute on some Chrome/driver combos while fp16/fp32 work (turbo's fp16/q4 path is fine on\n// the same machines) — set `window.__ozwell.whisperDtype = 'fp16'` to trade a larger download for\n// correct GPU inference. The wasm fallback always uses q8 (CPU arithmetic is deterministic).\nfunction whisperDtype(): string | null {\n if (typeof window === 'undefined') return null;\n const fromWin = (w?: Window | null): string | undefined => {\n try {\n return (w as unknown as { __ozwell?: { whisperDtype?: string } })\n ?.__ozwell?.whisperDtype;\n } catch {\n return undefined;\n }\n };\n const win = fromWin(window) || fromWin(window.parent) || fromWin(window.top);\n if (win) return win;\n try {\n return (\n JSON.parse(localStorage.getItem('ozwellConfig') || '{}').whisperDtype ||\n null\n );\n } catch {\n return null;\n }\n}\n\n// Pinned to an EXACT validated version (a floating `@3` lets jsDelivr serve newer 3.x that can break at\n// runtime). Override the ESM URL for strict-CSP / offline / self-hosted setups via\n// `window.__ozwellTransformersUrl` or `localStorage['ozwellTransformersUrl']`.\nconst DEFAULT_TRANSFORMERS_URL =\n 'https://cdn.jsdelivr.net/npm/@huggingface/transformers@3.8.1';\nfunction transformersUrl(): string {\n try {\n const w = (window as unknown as { __ozwellTransformersUrl?: string })\n .__ozwellTransformersUrl;\n if (w) return w;\n const ls = localStorage.getItem('ozwellTransformersUrl');\n if (ls) return ls;\n } catch {\n /* ignore */\n }\n return DEFAULT_TRANSFORMERS_URL;\n}\n\n// --- dictation-model load progress, surfaced to the UI (the ~1.3GB turbo download is the slow one) ---\nexport interface WhisperLoadState {\n /** A load is in flight. */ active: boolean;\n /** Overall fraction 0..1 (averaged over the model's files). */ progress: number;\n /** The model is loaded. */ done: boolean;\n}\nlet dictationLoad: WhisperLoadState = {\n active: false,\n progress: 0,\n done: false,\n};\nconst loadListeners = new Set<() => void>();\nfunction setDictationLoad(patch: Partial<WhisperLoadState>): void {\n dictationLoad = { ...dictationLoad, ...patch };\n loadListeners.forEach((l) => l());\n}\n/** Current dictation-model load state (for a progress indicator). */\nexport function getDictationLoad(): WhisperLoadState {\n return dictationLoad;\n}\n/** Subscribe to dictation-model load changes; returns an unsubscribe. Pair with getDictationLoad in\n * React.useSyncExternalStore. */\nexport function subscribeDictationLoad(cb: () => void): () => void {\n loadListeners.add(cb);\n return () => {\n loadListeners.delete(cb);\n };\n}\n\n// ---------------------------------------------------------------------------------------------------------\n// The Whisper worker. Inlined as a string + spawned from a Blob URL so it bundles cleanly in the tsup-built\n// library (no reliance on the consumer's bundler handling worker URLs). It's a MODULE worker so it can\n// `import()` transformers.js from the CDN. Config (URLs, model prefs) is passed in via the 'init' message\n// because a worker can't read window/localStorage. Message protocol:\n// main→worker: {type:'init', cfg} · {type:'warm'} · {type:'warmGate'} · {type:'transcribe', id, want, samples}\n// worker→main: {type:'loadState', patch} · {type:'progress', frac} · {type:'result', id, text, chunks} · {type:'error', id, message}\n// A model load mutates the SHARED env.remoteHost (turbo→whisperHost, english→HF), read per-file as\n// transformers.js fetches — so every load is serialized through one chain to avoid mid-download clobber.\nconst WORKER_SRC = `\nlet cfg = null, modP = null, pipeP = null, gateP = null, isMulti = false;\nlet chain = Promise.resolve();\nconst serialize = (fn) => { const r = chain.then(fn, fn); chain = r.then(() => {}, () => {}); return r; };\n\nfunction getMod() {\n if (modP) return modP;\n modP = (async () => {\n const mod = await import(cfg.transformersUrl);\n mod.env.allowLocalModels = false;\n // transformers.js's OWN cache STREAMS the model straight to the Cache API (how whisper-web caches this\n // 1.2GB turbo model). A hand-rolled SW that buffers the whole file chokes (QuotaExceeded).\n mod.env.useBrowserCache = true;\n mod.env.backends.onnx.wasm.numThreads = 1;\n try { if (navigator.storage && navigator.storage.persist) await navigator.storage.persist(); } catch (e) {}\n return mod;\n })();\n return modP;\n}\n\nfunction progressCb() {\n const frac = {};\n const report = () => {\n const v = Object.values(frac);\n self.postMessage({ type: 'progress', frac: v.length ? v.reduce((a, b) => a + b, 0) / v.length : 0 });\n };\n return (p) => {\n if (!p || !p.file) return;\n if (p.status === 'initiate') { frac[p.file] = frac[p.file] || 0; report(); }\n else if (p.status === 'done') { frac[p.file] = 1; report(); }\n else if (p.status === 'progress' && typeof p.progress === 'number') { frac[p.file] = p.progress / 100; report(); }\n };\n}\n\nasync function buildEnglish(modelId) {\n const mod = await getMod();\n mod.env.remoteHost = cfg.hfHost;\n mod.env.remotePathTemplate = cfg.hfPath;\n if ((cfg.whisperDevice || '').toLowerCase() !== 'wasm') {\n try {\n const gpuDtype = cfg.whisperDtype || 'q8';\n const pipe = await mod.pipeline('automatic-speech-recognition', modelId, { device: 'webgpu', dtype: gpuDtype, progress_callback: progressCb() });\n console.log('[whisper] ready (' + modelId + ' / WebGPU ' + gpuDtype + ', worker)');\n return pipe;\n } catch (e) { /* fall through to wasm */ }\n }\n const pipe = await mod.pipeline('automatic-speech-recognition', modelId, { dtype: 'q8', progress_callback: progressCb() });\n console.log('[whisper] ready (' + modelId + ' / wasm, worker)');\n return pipe;\n}\n\nasync function buildTurbo() {\n const mod = await getMod();\n mod.env.remoteHost = cfg.whisperHost;\n mod.env.remotePathTemplate = '{model}/';\n const pipe = await mod.pipeline('automatic-speech-recognition', 'whisper-turbo', {\n device: 'webgpu',\n dtype: { encoder_model: 'fp16', decoder_model_merged: 'q4' },\n progress_callback: progressCb(),\n });\n isMulti = true;\n console.log('[whisper] ready (turbo / worker)');\n return pipe;\n}\n\nfunction loadWhisper() {\n if (pipeP) return pipeP;\n self.postMessage({ type: 'loadState', patch: { active: true, progress: 0, done: false } });\n pipeP = (async () => {\n const pref = (cfg.whisperPref || '').toLowerCase();\n if (pref && pref !== 'turbo' && cfg.smallModels[pref]) {\n console.log('[whisper] loading ' + pref + ' (forced via ozwellConfig.whisper)…');\n return serialize(() => buildEnglish(cfg.smallModels[pref]));\n }\n console.log('[whisper] loading turbo…');\n try { return await serialize(() => buildTurbo()); }\n catch (e) {\n console.log('[whisper] turbo unavailable (' + (e && e.message ? e.message : e) + ') → base.en fallback');\n return serialize(() => buildEnglish(cfg.gateModel));\n }\n })();\n pipeP.then(\n () => self.postMessage({ type: 'loadState', patch: { active: false, progress: 1, done: true } }),\n () => { pipeP = null; self.postMessage({ type: 'loadState', patch: { active: false } }); }\n );\n return pipeP;\n}\n\nfunction loadGate() {\n if (gateP) return gateP;\n console.log('[whisper] loading stop-confirm gate (base.en)…');\n gateP = serialize(() => buildEnglish(cfg.gateModel));\n gateP.catch(() => { gateP = null; });\n return gateP;\n}\n\nself.onmessage = async (e) => {\n const m = e.data;\n if (!m) return;\n if (m.type === 'init') { cfg = m.cfg; return; }\n if (m.type === 'warm') { loadWhisper().catch(() => {}); return; }\n if (m.type === 'warmGate') { loadGate().catch(() => {}); return; }\n if (m.type === 'transcribe') {\n try {\n let pipe, opts;\n if (m.want === 'gate') { pipe = await loadGate(); opts = { chunk_length_s: 30 }; }\n else {\n pipe = await loadWhisper();\n if (m.want === 'segments' || m.want === 'words') opts = Object.assign({ chunk_length_s: 30, return_timestamps: m.want === 'words' ? 'word' : true }, isMulti ? { language: 'english', task: 'transcribe' } : {});\n else opts = isMulti ? { chunk_length_s: 30, language: 'english', task: 'transcribe' } : { chunk_length_s: 30 };\n }\n const out = await pipe(m.samples, opts);\n self.postMessage({ type: 'result', id: m.id, text: (out && out.text ? out.text : '').trim(), chunks: (out && out.chunks) || null });\n } catch (err) {\n self.postMessage({ type: 'error', id: m.id, message: err && err.message ? err.message : String(err) });\n }\n }\n};\n`;\n\ntype WorkerResult = {\n text: string;\n chunks: { timestamp: [number, number | null]; text?: string }[] | null;\n};\nlet worker: Worker | null = null;\nlet reqId = 0;\nconst pending = new Map<\n number,\n { resolve: (r: WorkerResult) => void; reject: (e: Error) => void }\n>();\n\nfunction buildWorkerCfg() {\n return {\n transformersUrl: transformersUrl(),\n whisperHost: whisperHost(),\n whisperPref: whisperPref(),\n whisperDevice: whisperDevice(),\n whisperDtype: whisperDtype(),\n hfHost: HF_HOST,\n hfPath: HF_PATH,\n smallModels: SMALL_MODELS,\n gateModel: GATE_MODEL,\n };\n}\n\nfunction getWorker(): Worker {\n if (worker) return worker;\n registerModelServiceWorker(); // main-thread SW registration (caches the wake/sherpa models)\n const url = URL.createObjectURL(\n new Blob([WORKER_SRC], { type: 'application/javascript' })\n );\n const w = new Worker(url, { type: 'module' });\n w.onmessage = (e: MessageEvent) => {\n const m = e.data;\n if (!m) return;\n if (m.type === 'loadState') {\n setDictationLoad(m.patch);\n return;\n }\n if (m.type === 'progress') {\n setDictationLoad({ progress: m.frac });\n return;\n }\n if (m.type === 'result') {\n const p = pending.get(m.id);\n if (p) {\n pending.delete(m.id);\n p.resolve({ text: m.text, chunks: m.chunks });\n }\n return;\n }\n if (m.type === 'error') {\n const p = pending.get(m.id);\n if (p) {\n pending.delete(m.id);\n p.reject(new Error(m.message));\n }\n return;\n }\n };\n w.onerror = (e) => {\n // A worker-level failure (e.g. the transformers.js import blocked by CSP) — fail any in-flight calls so\n // callers fall back instead of hanging, and reset the load indicator.\n const err = new Error(\n `whisper worker error: ${e.message || 'failed to load'}`\n );\n pending.forEach((p) => p.reject(err));\n pending.clear();\n setDictationLoad({ active: false });\n };\n w.postMessage({ type: 'init', cfg: buildWorkerCfg() });\n worker = w;\n return worker;\n}\n\n// Post a transcribe request to the worker; the 16 kHz mono samples are TRANSFERRED (zero-copy). Resolves\n// with the worker's { text, chunks }.\nfunction callWorker(\n want: 'text' | 'segments' | 'words' | 'gate',\n samples: Float32Array\n): Promise<WorkerResult> {\n const w = getWorker();\n const id = ++reqId;\n return new Promise<WorkerResult>((resolve, reject) => {\n pending.set(id, { resolve, reject });\n w.postMessage({ type: 'transcribe', id, want, samples }, [samples.buffer]);\n });\n}\n\n/** True only once the dictation model has actually finished loading (not merely started, not rejected). */\nexport function isWhisperLoaded(): boolean {\n return getDictationLoad().done;\n}\n\n/** Terminate the whisper worker so the next call spawns a fresh one with current config\n * (model pref / device / hosts re-read from window+localStorage). Model weights stay in the\n * browser Cache API, so a respawn re-instantiates in seconds rather than re-downloading.\n * Lets callers switch models/devices at runtime or recover from a bad pipeline (e.g. WebGPU\n * computing garbage on a broken adapter). In-flight requests are rejected. */\nexport function resetWhisperWorker(): void {\n if (!worker) return;\n const err = new Error('whisper worker reset');\n pending.forEach((p) => p.reject(err));\n pending.clear();\n worker.terminate();\n worker = null;\n setDictationLoad({ active: false, progress: 0, done: false });\n}\n\n/** Start loading the dictation model NOW (in the worker) so the first dictation doesn't pay the load. */\nexport function warmWhisper(): void {\n getWorker().postMessage({ type: 'warm' });\n}\n\n/** Start loading the stop-confirm gate model (base.en) in the worker. Warm this BEFORE warmWhisper so the\n * fast model isn't queued behind slow turbo. */\nexport function warmStopGate(): void {\n getWorker().postMessage({ type: 'warmGate' });\n}\n\n// Downmix all channels of a decoded buffer to mono (average), so stereo recordings don't lose half the\n// signal. Single-channel buffers pass through.\nfunction downmixToMono(audio: AudioBuffer): Float32Array {\n if (audio.numberOfChannels <= 1) return audio.getChannelData(0);\n const n = audio.length;\n const out = new Float32Array(n);\n for (let ch = 0; ch < audio.numberOfChannels; ch++) {\n const data = audio.getChannelData(ch);\n for (let i = 0; i < n; i++) out[i] += data[i];\n }\n for (let i = 0; i < n; i++) out[i] /= audio.numberOfChannels;\n return out;\n}\n\n// Linear-resample mono audio to 16 kHz (what Whisper wants). Shared by the blob + raw-samples paths. Always\n// returns a fresh, standalone Float32Array (safe to transfer to the worker).\nfunction resampleTo16kMono(\n src: Float32Array,\n sampleRate: number\n): Float32Array {\n const ratio = 16000 / sampleRate;\n const n = Math.round(src.length * ratio);\n const out = new Float32Array(n);\n for (let i = 0; i < n; i++) {\n const t = i / ratio;\n const i0 = Math.floor(t);\n const i1 = Math.min(i0 + 1, src.length - 1);\n out[i] = src[i0] + (src[i1] - src[i0]) * (t - i0);\n }\n return out;\n}\n\n// Decode a recorded Blob → 16 kHz mono Float32 (what Whisper + TitaNet want). decodeAudioData needs the\n// main thread (no AudioContext in workers), but it's cheap; the heavy inference is what moved off-thread.\n// try/finally so a failed decode still closes the AudioContext (they'd otherwise leak across retries).\nexport async function decodeTo16kMono(blob: Blob): Promise<Float32Array> {\n const Ctx =\n window.AudioContext ||\n (window as unknown as { webkitAudioContext: typeof AudioContext })\n .webkitAudioContext;\n const ctx = new Ctx();\n try {\n const audio = await ctx.decodeAudioData(await blob.arrayBuffer());\n return resampleTo16kMono(downmixToMono(audio), audio.sampleRate);\n } finally {\n void ctx.close();\n }\n}\n\n/** Encode 16 kHz mono Float32 samples as a 16-bit PCM WAV blob, so a trimmed clip can flow back through the\n * existing blob-based transcribe/diarize/server paths (which decode it). */\nfunction encodeWav16kMono(samples: Float32Array): Blob {\n const sr = 16000;\n const buf = new ArrayBuffer(44 + samples.length * 2);\n const view = new DataView(buf);\n const str = (o: number, s: string) => {\n for (let i = 0; i < s.length; i++) view.setUint8(o + i, s.charCodeAt(i));\n };\n str(0, 'RIFF');\n view.setUint32(4, 36 + samples.length * 2, true);\n str(8, 'WAVE');\n str(12, 'fmt ');\n view.setUint32(16, 16, true);\n view.setUint16(20, 1, true);\n view.setUint16(22, 1, true);\n view.setUint32(24, sr, true);\n view.setUint32(28, sr * 2, true);\n view.setUint16(32, 2, true);\n view.setUint16(34, 16, true);\n str(36, 'data');\n view.setUint32(40, samples.length * 2, true);\n let o = 44;\n for (let i = 0; i < samples.length; i++) {\n const s = Math.max(-1, Math.min(1, samples[i]));\n view.setInt16(o, s < 0 ? s * 0x8000 : s * 0x7fff, true);\n o += 2;\n }\n return new Blob([buf], { type: 'audio/wav' });\n}\n\n/**\n * Trim the spoken \"ozwell i'm done\" off the END of a clip BEFORE it reaches ASR. Whisper mishears the phrase\n * differently every time (\"all was well\" / \"I was long done\" / …), so stripping the transcript text can\n * never catch them all — the reliable fix is to cut the audio so the phrase is never transcribed.\n *\n * `phraseHintSec` (from the wake detector's detection run) is an estimate of the phrase's length. When\n * given, the cut is anchored at `end - phraseHintSec` and snapped to the nearest pause within ~0.35 s — so\n * it works whether or not the speaker paused (the pause-independent case that pure energy can't handle).\n * Without a hint, it walks back from the end to the last natural pause (energy only). Capped so it never\n * removes too much. Returns a trimmed WAV blob (or the original on failure / nothing sensible to cut). Only\n * call on a PHRASE-triggered stop — not a manual button stop, where there's no phrase to remove.\n */\nexport async function trimTrailingStopPhrase(\n blob: Blob,\n phraseHintSec = 0\n): Promise<Blob> {\n let samples: Float32Array;\n try {\n samples = await decodeTo16kMono(blob);\n } catch {\n return blob;\n }\n const SR = 16000;\n const n = samples.length;\n if (n < SR * 0.8) return blob; // too short to safely trim\n\n // Short-time energy (RMS) per 30 ms frame.\n const fr = Math.round(SR * 0.03);\n const nf = Math.ceil(n / fr);\n const e = new Float32Array(nf);\n let peak = 0;\n for (let f = 0; f < nf; f++) {\n const a = f * fr,\n b = Math.min(n, a + fr);\n let s = 0;\n for (let i = a; i < b; i++) s += samples[i] * samples[i];\n e[f] = Math.sqrt(s / (b - a));\n if (e[f] > peak) peak = e[f];\n }\n const sil = Math.max(0.008, peak * 0.15); // \"silence\" threshold, adaptive to the clip's level\n const minGap = Math.max(1, Math.round((0.15 * SR) / fr)); // a real pause = >= ~150 ms of silence\n const maxTrimFrames = Math.round((2.2 * SR) / fr); // never cut more than ~2.2 s\n const floor = Math.max(0, nf - maxTrimFrames);\n\n let cutFrame: number;\n if (phraseHintSec > 0.2) {\n // Detector-anchored: the phrase is the last ~phraseHintSec. Snap to the nearest quiet frame within a\n // window of that anchor (catches the pause/word-boundary before the phrase even when it's very brief);\n // if none is near, cut at the anchor itself. Pause-independent.\n const anchor = Math.max(0, nf - Math.round((phraseHintSec * SR) / fr));\n const win = Math.round((0.35 * SR) / fr);\n let best = -1,\n bestDist = Infinity;\n for (\n let f = Math.max(0, anchor - win);\n f <= Math.min(nf - 1, anchor + win);\n f++\n ) {\n if (e[f] < sil) {\n const dist = Math.abs(f - anchor);\n if (dist < bestDist) {\n bestDist = dist;\n best = f;\n }\n }\n }\n cutFrame = best >= 0 ? best : anchor;\n } else {\n // Energy-only fallback: walk back from the end to the last sustained pause.\n let k = nf - 1;\n while (k >= floor && e[k] < sil) k--; // skip any trailing quiet after \"done\"\n cutFrame = -1;\n while (k >= floor) {\n if (e[k] < sil) {\n let m = k;\n while (m >= floor && e[m] < sil) m--; // measure this silence run\n if (k - m >= minGap) {\n cutFrame = k + 1;\n break;\n } // sustained pause → the phrase starts after it\n k = m; // micro-pause inside the phrase → keep going back\n } else k--;\n }\n if (cutFrame < 0) cutFrame = Math.max(0, nf - Math.round((1.1 * SR) / fr)); // no pause → conservative fixed trim\n }\n cutFrame = Math.max(cutFrame, floor); // enforce the max-trim cap\n const cutSample = Math.min(n, cutFrame * fr);\n if (cutSample < SR * 0.2) return blob; // would leave almost nothing — bail (text-strip covers it)\n return encodeWav16kMono(samples.subarray(0, cutSample));\n}\n\nexport async function transcribeBlob(\n blob: Blob,\n trimEndSeconds = 0\n): Promise<string> {\n let samples = await decodeTo16kMono(blob);\n if (trimEndSeconds > 0) {\n const cut = Math.round(trimEndSeconds * 16000);\n if (samples.length > cut + 16000)\n samples = samples.slice(0, samples.length - cut); // keep >=1s (slice = standalone buffer)\n }\n const out = await callWorker('text', samples);\n return (out.text ?? '').trim();\n}\n\n/** Transcribe raw mono samples (any sample rate) → text. For the live dictation caption, where we re-run\n * the growing utterance every couple seconds; the FINAL send still uses transcribeBlob. */\nexport async function transcribeSamples(\n samples: Float32Array,\n sampleRate: number\n): Promise<string> {\n const out = await callWorker('text', resampleTo16kMono(samples, sampleRate));\n return (out.text ?? '').trim();\n}\n\n/** Map raw worker chunks (`{ timestamp: [s, e], text }`) to TranscriptSegments in seconds. */\nfunction chunksToSegments(chunks: WorkerResult['chunks']): TranscriptSegment[] {\n return (chunks ?? [])\n .map((c) => ({\n start: c.timestamp?.[0] ?? 0,\n end: c.timestamp?.[1] ?? c.timestamp?.[0] ?? 0,\n text: (c.text ?? '').trim(),\n }))\n .filter((s) => s.text);\n}\n\n/** Transcribe with timestamps → segments `[{ start, end, text }]`, for diarization (align speaker turns to\n * text). Returns 16 kHz-relative seconds. See `useDiarization`. */\nexport async function transcribeSegments(\n blob: Blob\n): Promise<TranscriptSegment[]> {\n const samples = await decodeTo16kMono(blob);\n const out = await callWorker('segments', samples);\n return chunksToSegments(out.chunks);\n}\n\n/** Transcribe with WORD-level timestamps → `[{ start, end, text }]` (seconds), one entry per word — the\n * shape word-level editors (MediaEditor) need. Uses transformers.js `return_timestamps: 'word'`\n * (cross-attention alignment). Some models/runtimes reject word-level alignment — callers should catch\n * and fall back to `transcribeSegments`. */\nexport async function transcribeWords(\n blob: Blob\n): Promise<TranscriptSegment[]> {\n return transcribeWordsFromSamples(await decodeTo16kMono(blob));\n}\n\n/** Word-level transcription from already-decoded 16 kHz mono samples. Lets callers decode once (with\n * their own status/timeout handling) and retry/fall back without re-decoding. NOTE: samples are\n * transferred to the worker — pass a copy (`samples.slice()`) if you need them again. */\nexport async function transcribeWordsFromSamples(\n samples: Float32Array\n): Promise<TranscriptSegment[]> {\n const out = await callWorker('words', samples);\n return chunksToSegments(out.chunks);\n}\n\n/** Segment-level transcription from already-decoded 16 kHz mono samples (see transcribeWordsFromSamples). */\nexport async function transcribeSegmentsFromSamples(\n samples: Float32Array\n): Promise<TranscriptSegment[]> {\n const out = await callWorker('segments', samples);\n return chunksToSegments(out.chunks);\n}\n\n// Server-ASR model id (override via localStorage ozwellConfig.serverWhisper); defaults to the\n// OpenAI-compatible 'whisper-1'.\nfunction serverAsrModel(): string {\n try {\n return (\n JSON.parse(localStorage.getItem('ozwellConfig') || '{}').serverWhisper ||\n 'whisper-1'\n );\n } catch {\n return 'whisper-1';\n }\n}\n\n/** Server-side transcription: POST the recorded audio to the OpenAI-compatible /v1/audio/transcriptions\n * endpoint (same baseURL/apiKey as the chat). NOTE: audio LEAVES the browser — the on-device path\n * (transcribeBlob) is the PHI-safe default; this is the experiment alternative. Throws on HTTP error so\n * the caller can fall back to on-device. */\nexport async function transcribeServer(blob: Blob): Promise<string> {\n const cfg = getOzwellConfig();\n const form = new FormData();\n form.append('file', blob, 'audio.webm');\n form.append('model', serverAsrModel());\n const url = `${cfg.baseURL.replace(/\\/$/, '')}/v1/audio/transcriptions`;\n const headers: Record<string, string> = {};\n if (cfg.apiKey && cfg.apiKey !== 'ollama')\n headers.Authorization = `Bearer ${cfg.apiKey}`;\n const res = await fetch(url, { method: 'POST', headers, body: form });\n if (!res.ok) {\n // statusText is often empty — include a short body snippet so the failure is actionable (the caller\n // still catches this and falls back to on-device transcription).\n const body = await res.text().catch(() => '');\n throw new Error(\n `Server ASR ${res.status}: ${res.statusText || body.slice(0, 200) || 'request failed'}`\n );\n }\n const data = await res.json();\n return (typeof data?.text === 'string' ? data.text : '').trim();\n}\n\n/** Stop-confirm gate: transcribe a short raw-sample window (e.g. the rolling recorder's last ~2s) with the\n * FAST model and return the text. Used to verify a \"ozwell i'm done\" wake actually ended with \"done\"\n * before committing the stop. Cheap — accuracy on the lone word \"done\" is all it needs. */\nexport async function transcribeGate(\n samples: Float32Array,\n sampleRate: number\n): Promise<string> {\n const out = await callWorker('gate', resampleTo16kMono(samples, sampleRate));\n return (out.text ?? '').trim();\n}\n\n/** Peel a trailing \"ozwell i'm done\"-style stop phrase off the end of a transcript. Mirrors the\n * standalone demo: handles Whisper's mishearings (Ozwell / As well / All('s/was) well / Also / Oswald /\n * \"I am done\") including the bare word alone. Bare \"as well\" is NOT stripped (too common) unless joined\n * to \"i'm done\". */\nexport function stripStopPhrase(text: string): string {\n // All whitespace quantifiers are BOUNDED ({0,4}/{1,4}) so backtracking through the optional groups\n // stays constant — ReDoS hardening (transcript words are never separated by more than a couple of\n // spaces, so behavior is unchanged). The trailing-junk trim below uses a linear char walk for the\n // same reason (see trimTrailingPunct — the actual CodeQL js/polynomial-redos finding).\n const tail =\n /(?:\\b(?:oz\\s{0,4}well|all(?:['’]?s|\\s{1,4}was)?\\s{0,4}well|as\\s{0,4}well|also|oswald)\\b[\\s,]{0,6}i(?:['’]?m|\\s{1,4}am)\\s{1,4}done\\b|\\b(?:oz\\s{0,4}well|all(?:['’]?s|\\s{1,4}was)?\\s{0,4}well|oswald)\\b|\\bi(?:['’]?m|\\s{1,4}am)\\s{1,4}done\\b|\\b(?:that\\s{1,4}was\\s{1,4}|was\\s{1,4})?well\\s{1,4}done\\b|\\bthat['’]?s?\\s{1,4}(?:was\\s{1,4})?all\\b|\\bthank(?:s|\\s{1,4}you)(?:\\s{1,4}for\\s{1,4}watching)?\\b|\\bbye\\b)[\\s.,!?-]{0,24}$/i;\n let prev: string | null = null;\n let t = text;\n while (t !== prev && t) {\n prev = t;\n t = trimTrailingPunct(t.replace(tail, ''));\n }\n return t.trim();\n}\n\n/** Strip trailing whitespace/punctuation with a linear char walk. The regex form `/[\\s.,!?-]+$/` restarts\n * its scan at every position of a long trailing run (quadratic on adversarial input — the CodeQL\n * js/polynomial-redos finding on stripStopPhrase). Testing one char at a time can't backtrack. */\nfunction trimTrailingPunct(s: string): string {\n let end = s.length;\n while (end > 0 && /[\\s.,!?-]/.test(s[end - 1])) end--;\n return end === s.length ? s : s.slice(0, end);\n}\n\n/** True if a transcript ENDS with a clear \"done\" stop (\"…done\" / \"…I'm done\" / \"…all done\" / \"…well done\"),\n * tolerating trailing punctuation. Deliberately STRICTER than stripStopPhrase: the stop-confirm gate must\n * NOT fire on a bare \"ozwell\" or a mid-sentence \"done\" — \"we're almost done here\" ends on \"here\", so no\n * match. Favors precision: a missed real stop just means \"say it again\"; a false stop loses dictation. */\nexport function endsWithDone(text: string): boolean {\n // Whitespace bounded for the same polynomial-backtracking reason as stripStopPhrase's tail regex.\n return /\\b(?:i(?:['’]?m|\\s{1,4}am)\\s{1,4}|all\\s{1,4}|well\\s{1,4})?done\\b[\\s.,!?-]{0,24}$/i.test(\n text\n );\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/brands/index.ts"],"names":[],"mappings":";AAkCO,IAAM,MAAA,GAAS;AAAA,EACpB,QAAA,EAAU,MAAM,OAAO,sBAAY,EAAE,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,aAAa,CAAA;AAAA,EAChE,IAAA,EAAM,MAAM,OAAO,kBAAQ,EAAE,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,SAAS,CAAA;AAAA,EACpD,OAAA,EAAS,MAAM,OAAO,uBAAW,EAAE,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,YAAY,CAAA;AAAA,EAC7D,mBAAA,EAAqB,MACnB,OAAO,iCAAqB,EAAE,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,qBAAqB,CAAA;AAAA,EACnE,MAAA,EAAQ,MAAM,OAAO,sBAAU,EAAE,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,WAAW,CAAA;AAAA,EAC1D,MAAA,EAAQ,MAAM,OAAO,oBAAU,EAAE,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,WAAW,CAAA;AAAA,EAC1D,UAAA,EAAY,MAAM,OAAO,0BAAc,EAAE,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,eAAe,CAAA;AAAA,EACtE,QAAA,EAAU,MAAM,OAAO,wBAAY,EAAE,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,aAAa;AAClE","file":"chunk-
|
|
1
|
+
{"version":3,"sources":["../src/brands/index.ts"],"names":[],"mappings":";AAkCO,IAAM,MAAA,GAAS;AAAA,EACpB,QAAA,EAAU,MAAM,OAAO,sBAAY,EAAE,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,aAAa,CAAA;AAAA,EAChE,IAAA,EAAM,MAAM,OAAO,kBAAQ,EAAE,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,SAAS,CAAA;AAAA,EACpD,OAAA,EAAS,MAAM,OAAO,uBAAW,EAAE,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,YAAY,CAAA;AAAA,EAC7D,mBAAA,EAAqB,MACnB,OAAO,iCAAqB,EAAE,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,qBAAqB,CAAA;AAAA,EACnE,MAAA,EAAQ,MAAM,OAAO,sBAAU,EAAE,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,WAAW,CAAA;AAAA,EAC1D,MAAA,EAAQ,MAAM,OAAO,oBAAU,EAAE,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,WAAW,CAAA;AAAA,EAC1D,UAAA,EAAY,MAAM,OAAO,0BAAc,EAAE,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,eAAe,CAAA;AAAA,EACtE,QAAA,EAAU,MAAM,OAAO,wBAAY,EAAE,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,aAAa;AAClE","file":"chunk-J3QEMZCH.js","sourcesContent":["/**\n * @mieweb/ui Brand System\n *\n * Export all brand-related types, utilities, and configurations.\n */\n\n// Types and utilities\nexport type {\n BrandConfig,\n BrandColors,\n BrandTypography,\n BrandBorderRadius,\n BrandBoxShadow,\n ColorScale,\n SemanticColors,\n} from './types';\n\nexport {\n generateBrandCSS,\n generateTailwindTheme,\n createBrandPreset,\n} from './types';\n\n// Brand configurations\nexport { bluehiveBrand } from './bluehive';\nexport { ccmeBrand } from './ccme';\nexport { defaultBrand } from './default';\nexport { enterpriseHealthBrand } from './enterprise-health';\nexport { miewebBrand } from './mieweb';\nexport { ozwellBrand } from './ozwell';\nexport { wagglelineBrand } from './waggleline';\nexport { webchartBrand } from './webchart';\n\n// All brands for iteration\nexport const brands = {\n bluehive: () => import('./bluehive').then((m) => m.bluehiveBrand),\n ccme: () => import('./ccme').then((m) => m.ccmeBrand),\n default: () => import('./default').then((m) => m.defaultBrand),\n 'enterprise-health': () =>\n import('./enterprise-health').then((m) => m.enterpriseHealthBrand),\n mieweb: () => import('./mieweb').then((m) => m.miewebBrand),\n ozwell: () => import('./ozwell').then((m) => m.ozwellBrand),\n waggleline: () => import('./waggleline').then((m) => m.wagglelineBrand),\n webchart: () => import('./webchart').then((m) => m.webchartBrand),\n} as const;\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Slider } from './chunk-
|
|
1
|
+
import { Slider } from './chunk-V5VPECJI.js';
|
|
2
2
|
import { MediaPlayer } from './chunk-N54FYWG6.js';
|
|
3
3
|
import { Checkbox } from './chunk-753Z3NXL.js';
|
|
4
4
|
import { useTranscriptEdits, DEFAULT_FILLER_WORDS } from './chunk-UUI7WXI5.js';
|
|
@@ -6,6 +6,7 @@ import { isSilenceType, PLAYBACK_SPEEDS } from './chunk-6CGM5H4J.js';
|
|
|
6
6
|
import { Select } from './chunk-VCI2Y7ST.js';
|
|
7
7
|
import { Modal, ModalHeader, ModalTitle, ModalClose, ModalBody, ModalFooter } from './chunk-TWQSMUE6.js';
|
|
8
8
|
import { Input } from './chunk-3IMM2PM4.js';
|
|
9
|
+
import { isRtl } from './chunk-YVKBXNPK.js';
|
|
9
10
|
import { Button } from './chunk-WFBUBT54.js';
|
|
10
11
|
import * as React6 from 'react';
|
|
11
12
|
import { cva } from 'class-variance-authority';
|
|
@@ -556,7 +557,11 @@ var SpeedMarkerMenu = ({
|
|
|
556
557
|
{
|
|
557
558
|
ref: menuRef,
|
|
558
559
|
className: "border-border bg-card text-card-foreground fixed z-50 min-w-36 overflow-hidden rounded-lg border shadow-lg",
|
|
559
|
-
style: {
|
|
560
|
+
style: {
|
|
561
|
+
// rtl-ignore -- fixed viewport coordinate from the pointer event
|
|
562
|
+
left: position.x,
|
|
563
|
+
top: position.y
|
|
564
|
+
},
|
|
560
565
|
role: "menu",
|
|
561
566
|
"aria-label": "Set speed marker",
|
|
562
567
|
children: [
|
|
@@ -1475,18 +1480,20 @@ var MediaEditor = React6.forwardRef(
|
|
|
1475
1480
|
if (canRedoWords) redo();
|
|
1476
1481
|
else if (canRedo && onRedo) onRedo();
|
|
1477
1482
|
handled = true;
|
|
1478
|
-
} else if (e.key === "ArrowLeft") {
|
|
1479
|
-
|
|
1480
|
-
|
|
1483
|
+
} else if (e.key === "ArrowLeft" || e.key === "ArrowRight") {
|
|
1484
|
+
const forward = e.key === "ArrowRight" !== isRtl(e.currentTarget);
|
|
1485
|
+
if (forward) {
|
|
1486
|
+
if (cursorIndex === wordCount - 1 && cursorPosition === "before") {
|
|
1487
|
+
setCursorPosition("after");
|
|
1488
|
+
} else if (cursorPosition !== "after") {
|
|
1489
|
+
newIndex = Math.min(wordCount - 1, cursorIndex + 1);
|
|
1490
|
+
}
|
|
1481
1491
|
} else {
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
setCursorPosition("after");
|
|
1488
|
-
} else if (cursorPosition !== "after") {
|
|
1489
|
-
newIndex = Math.min(wordCount - 1, cursorIndex + 1);
|
|
1492
|
+
if (cursorPosition === "after") {
|
|
1493
|
+
setCursorPosition("before");
|
|
1494
|
+
} else {
|
|
1495
|
+
newIndex = Math.max(0, cursorIndex - 1);
|
|
1496
|
+
}
|
|
1490
1497
|
}
|
|
1491
1498
|
handled = true;
|
|
1492
1499
|
} else if (e.key === "ArrowUp" || e.key === "ArrowDown") {
|
|
@@ -1999,5 +2006,5 @@ var MediaEditor = React6.forwardRef(
|
|
|
1999
2006
|
MediaEditor.displayName = "MediaEditor";
|
|
2000
2007
|
|
|
2001
2008
|
export { FillerWordsModal, MediaEditor, SilenceSettingsModal, SpeedMarkerMenu, WordEditorModal };
|
|
2002
|
-
//# sourceMappingURL=chunk-
|
|
2003
|
-
//# sourceMappingURL=chunk-
|
|
2009
|
+
//# sourceMappingURL=chunk-JM4YFLO4.js.map
|
|
2010
|
+
//# sourceMappingURL=chunk-JM4YFLO4.js.map
|