iobroker.assistant 0.1.6 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +61 -4
- package/admin/custom/.vite/manifest.json +122 -77
- package/admin/custom/assets/Components-7BDDNrGP.js +1 -0
- package/admin/custom/assets/_virtual_mf-localSharedImportMap___mfe_internal__ConfigCustomAssistant__mf_owner__1-DcAGnE2z.js +1 -0
- package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomAssistant__mf_owner__198531368674860__loadShare___mf_0_emotion_mf_1_react__loadShare__.js-CzBMxGFr.js +1 -0
- package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomAssistant__mf_owner__198531368674860__loadShare___mf_0_emotion_mf_1_styled__loadShare__.js-1XsLCK2M.js +1 -0
- package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomAssistant__mf_owner__198531368674860__loadShare___mf_0_iobroker_mf_1_gui_mf_2_components__loadShare__.js-CMv8bcyA.js +1217 -0
- package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomAssistant__mf_owner__198531368674860__loadShare__shared-3mzaJWDF.js +2 -0
- package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomAssistant__mf_owner__198531368674860__prebuild___mf_0_iobroker_mf_1_json_mf_2_config__prebuild__-DS8oaQQt.js +122 -0
- package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomAssistant__mf_owner__198531368674860__prebuild__react_mf_1_jsx_mf_2_runtime__prebuild__-B_v57Qfr.js +1 -0
- package/admin/custom/assets/dist-DiU1y0R9.js +1 -0
- package/admin/custom/assets/helpers-Dot7vgQQ.js +1 -0
- package/admin/custom/assets/hostInit-MshDicd1.js +1 -0
- package/admin/custom/assets/iconLibraryData-B5fiyl1C.js +1 -0
- package/admin/custom/assets/index-P2Xu9kJm.js +1 -0
- package/admin/custom/assets/lib-DjwHKtRi.js +3 -0
- package/admin/custom/assets/{mf-entry-bootstrap-0-87f15505.js → mf-entry-bootstrap-0-7c1ddf47.js} +14 -2
- package/admin/custom/assets/pendingShares-CaJDCKLB.js +2 -0
- package/admin/custom/assets/rolldown-runtime-Dd_uD5pT.js +1 -0
- package/admin/custom/assets/utils-towTPKqG.js +4 -0
- package/admin/custom/assets/vite-preload-helper-BbbETgeG.js +1 -0
- package/admin/custom/customComponents.js +2 -2
- package/admin/custom/i18n/de.json +64 -57
- package/admin/custom/i18n/en.json +8 -1
- package/admin/custom/i18n/es.json +64 -57
- package/admin/custom/i18n/fr.json +64 -57
- package/admin/custom/i18n/it.json +64 -57
- package/admin/custom/i18n/nl.json +64 -57
- package/admin/custom/i18n/pl.json +64 -57
- package/admin/custom/i18n/pt.json +64 -57
- package/admin/custom/i18n/ru.json +64 -57
- package/admin/custom/i18n/uk.json +64 -57
- package/admin/custom/i18n/zh-cn.json +64 -57
- package/admin/custom/index.html +2 -2
- package/admin/custom/mf-manifest.json +1 -1
- package/admin/custom/mf-stats.json +1 -1
- package/admin/i18n/de.json +59 -3
- package/admin/i18n/en.json +59 -3
- package/admin/i18n/es.json +59 -3
- package/admin/i18n/fr.json +59 -3
- package/admin/i18n/it.json +59 -3
- package/admin/i18n/nl.json +59 -3
- package/admin/i18n/pl.json +59 -3
- package/admin/i18n/pt.json +59 -3
- package/admin/i18n/ru.json +59 -3
- package/admin/i18n/uk.json +59 -3
- package/admin/i18n/zh-cn.json +59 -3
- package/admin/jsonConfig.json +589 -75
- package/build/lib/ask.js +130 -0
- package/build/lib/ask.js.map +1 -0
- package/build/lib/llm.js +135 -13
- package/build/lib/llm.js.map +1 -1
- package/build/lib/nlu.js +74 -1
- package/build/lib/nlu.js.map +1 -1
- package/build/lib/notifications.js +112 -0
- package/build/lib/notifications.js.map +1 -0
- package/build/lib/presence.js +188 -0
- package/build/lib/presence.js.map +1 -0
- package/build/lib/routines.js +115 -0
- package/build/lib/routines.js.map +1 -0
- package/build/lib/targets.js +96 -0
- package/build/lib/targets.js.map +1 -0
- package/build/lib/triggers.js +632 -0
- package/build/lib/triggers.js.map +1 -0
- package/build/lib/voice/aws.js +9 -1
- package/build/lib/voice/aws.js.map +1 -1
- package/build/lib/voice/azure.js +9 -2
- package/build/lib/voice/azure.js.map +1 -1
- package/build/lib/voice/engines.js +82 -0
- package/build/lib/voice/engines.js.map +1 -1
- package/build/lib/voice/esphome.js +732 -0
- package/build/lib/voice/esphome.js.map +1 -0
- package/build/lib/voice/esphomeEntities.js +303 -0
- package/build/lib/voice/esphomeEntities.js.map +1 -0
- package/build/lib/voice/esphomeProto.js +181 -0
- package/build/lib/voice/esphomeProto.js.map +1 -0
- package/build/lib/voice/fallback.js +85 -0
- package/build/lib/voice/fallback.js.map +1 -0
- package/build/lib/voice/mediaServer.js +151 -0
- package/build/lib/voice/mediaServer.js.map +1 -0
- package/build/lib/voice/protocol.js.map +1 -1
- package/build/lib/voice/tone.js +32 -0
- package/build/lib/voice/tone.js.map +1 -0
- package/build/lib/voice/tts.js.map +1 -1
- package/build/lib/voice/ttsCache.js +274 -0
- package/build/lib/voice/ttsCache.js.map +1 -0
- package/build/lib/voice/vad.js +173 -0
- package/build/lib/voice/vad.js.map +1 -0
- package/build/lib/voice/voiceServer.js +13 -0
- package/build/lib/voice/voiceServer.js.map +1 -1
- package/build/main.js +1721 -67
- package/build/main.js.map +1 -1
- package/io-package.json +241 -3
- package/package.json +13 -12
- package/admin/custom/assets/Components-xWdtqvTH.js +0 -1
- package/admin/custom/assets/_virtual_mf-localSharedImportMap___mfe_internal__ConfigCustomAssistant__mf_owner__1-dybYZgsu.js +0 -1
- package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomAssistant__mf_owner__1__loadShare___mf_0_emotion_mf_1_react__loadShare__.js-BnSUsPHa.js +0 -1
- package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomAssistant__mf_owner__1__loadShare___mf_0_emotion_mf_1_styled__loadShare__.js-DlSVT49A.js +0 -1
- package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomAssistant__mf_owner__1__loadShare___mf_0_iobroker_mf_1_gui_mf_2_components__loadShare__.js-Cfsgderv.js +0 -1243
- package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomAssistant__mf_owner__1__loadShare___mf_0_iobroker_mf_1_json_mf_2_config__loadShare__.js-ByJf4zv_.js +0 -1494
- package/admin/custom/assets/hostInit-CZawMH9B.js +0 -1
- package/admin/custom/assets/index-JB7g1jgx.js +0 -1
- package/admin/custom/assets/lib-bB-LHRhZ.js +0 -3
- package/admin/custom/assets/rolldown-runtime-C0FnF6B9.js +0 -1
- package/admin/custom/assets/virtualExposes-brKKZvi0.js +0 -1
- package/admin/custom/assets/virtual_mf-REMOTE_ENTRY_ID___mfe_internal__ConfigCustomAssistant__customComponents_js-CRhwj12f.js +0 -1
- package/admin/custom/assets/virtual_mf-exposes___mfe_internal__ConfigCustomAssistant__customComponents_js-C5XHUc1J.js +0 -2
- package/admin/custom/assets/vite-preload-helper-B7qeedMF.js +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"triggers.js","sourceRoot":"","sources":["../../src/lib/triggers.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Proactive triggers — the assistant speaking first instead of answering.\n *\n * A trigger watches ioBroker states and/or the clock and, when its condition holds, says something, writes\n * a state, or **asks a question and acts on the answer** (\"The fryer has been on for 5 hours. Shall I\n * switch it off?\" → `askUser` → classify the reply → switch it off). The question is what sets this apart\n * from a script or a scene: those can switch, but they cannot have a conversation about it.\n *\n * Semantics are ported from the Python original (`C:\\iot\\Hannah`, `core/hannah/trigger_engine.py`), whose\n * corner cases were earned the hard way and are kept deliberately:\n * - a state trigger fires on the **transition into** the condition, never on a repeated identical value;\n * - `also` with an unknown state blocks (we cannot confirm it), `unless` with an unknown state does not\n * (we cannot confirm the block either, and a lock that fires by accident is worse than one that waits);\n * - the cooldown is consumed when the trigger *starts*, so a delayed trigger cannot re-arm while waiting.\n *\n * Unlike the original there is **no poll loop**: like {@link AlarmManager}, every time trigger fires from\n * its own `setTimeout` at an absolute timestamp, so an idle system does no work at all. Execution itself is\n * the host's job ({@link TriggerEngineOptions.execute}) — this module owns only *whether* and *when*.\n */\nimport { computeNextFire } from './alarms';\n\n/** Values a condition can compare against — what an ioBroker state can hold. */\nexport type TriggerValue = string | number | boolean | null;\n\n/** Explicitly combined group of conditions (a plain list is AND). */\nexport interface TriggerConditionGroup {\n op: 'and' | 'or';\n conditions: TriggerCondition[];\n}\n\n/**\n * One condition. Either state-based (`state` plus an optional `value`/`above`/`below` filter — without a\n * filter any change matches) or time-based (`time` plus optional `days`).\n */\nexport interface TriggerCondition {\n /** State id to watch (state condition). */\n state?: string;\n /** Exact value to match. */\n value?: TriggerValue;\n /** Numeric threshold: value must be greater. */\n above?: number;\n /** Numeric threshold: value must be smaller. */\n below?: number;\n /** Wall-clock time `HH:MM` (time condition). */\n time?: string;\n /** Weekdays the time condition fires on (0 = Sunday … 6 = Saturday). Empty = every day. */\n days?: number[];\n /** Must hold as well. A list is AND; `{op:'or'}` makes it OR. Unknown state → does not hold. */\n also?: TriggerCondition | TriggerCondition[] | TriggerConditionGroup;\n /** Must NOT hold (a lock). A list is AND. Unknown state → does not block. */\n unless?: TriggerCondition | TriggerCondition[];\n}\n\n/** What a trigger does when it fires. */\nexport interface TriggerAction {\n /** Announcement text. */\n say?: string;\n /** Where to say it: a satellite state id / room, empty = all satellites. */\n room?: string;\n /** State to write. */\n setState?: { id: string; value: TriggerValue };\n}\n\n/** One rule for the answer to a trigger's question; the first matching rule wins. */\nexport interface TriggerResponseRule {\n /** Category the answer must express (\"agreement\", \"Zustimmung\", …). Empty = fallback rule. */\n match?: string;\n say?: string;\n setState?: { id: string; value: TriggerValue };\n}\n\n/** A trigger definition — plain data, so it round-trips through the config and JSON states. */\nexport interface TriggerDef {\n /** Unique id; also the `triggers.items.<id>` state-object segment. */\n id: string;\n /** Optional human name for logs and the states. */\n name?: string;\n /** Default enabled flag (the live one can be overridden through the state). */\n enabled?: boolean;\n /** Condition, or a list of alternatives (OR — any one is enough). */\n when: TriggerCondition | TriggerCondition[];\n /** Wait this long after the condition held before acting (\"5h\", \"30m\", \"90s\", or seconds). */\n delay?: string | number;\n /** Abort the pending delay when this holds. */\n cancelWhen?: TriggerCondition | TriggerCondition[];\n /** Minimum gap between two firings in seconds (default 3600; 0 = no cooldown). */\n cooldownSec?: number;\n /** Shorthand for a single `say` action. */\n say?: string;\n /** Target room/satellite for `say` and for the question. */\n room?: string;\n /** Ask this instead of announcing, and evaluate the answer against {@link onResponse}. */\n ask?: string;\n /** Rules for the answer to `ask`. */\n onResponse?: TriggerResponseRule[];\n /** Actions to run; replaces `say` when non-empty. */\n actions?: TriggerAction[];\n /** Have the LLM reword the text before it is spoken, so it doesn't sound canned. */\n rephrase?: boolean;\n}\n\n/** Live status of one trigger, mirrored into the states. */\nexport interface TriggerStatus {\n id: string;\n name: string;\n enabled: boolean;\n /** Epoch ms of the last firing (0 = never since start). */\n lastFired: number;\n /** Epoch ms of the next scheduled firing (time triggers only, 0 otherwise). */\n nextFireAt: number;\n /** Epoch ms at which a pending delay will run (0 = nothing pending). */\n pendingUntil: number;\n}\n\nexport interface TriggerEngineOptions {\n /** Read a state the conditions reference. `undefined`/`null` = unknown (see the `also`/`unless` rules). */\n getState: (id: string) => Promise<TriggerValue | undefined>;\n /** Run a trigger: announce, write states, or ask and evaluate the answer. */\n execute: (trigger: TriggerDef) => void | Promise<void>;\n /** Called whenever the live status changes, for the state mirror. */\n onChange?: (status: TriggerStatus[]) => void;\n log?: Pick<ioBroker.Log, 'debug' | 'info' | 'warn' | 'error'>;\n /** Injectable clock (tests). Defaults to `Date.now`. */\n now?: () => number;\n /** Don't arm real timers — the caller drives {@link TriggerEngine.tick} (tests). */\n manualTick?: boolean;\n}\n\n/** Default minimum gap between two firings of the same trigger. */\nexport const DEFAULT_COOLDOWN_SEC = 3600;\n\n/** Largest delay `setTimeout` accepts (~24.8 days); a longer wait is re-armed in chunks. */\nconst MAX_TIMEOUT = 2 ** 31 - 1;\n\n/** Normalise a condition field that may hold one condition or several. */\nfunction asList(c: TriggerCondition | TriggerCondition[] | undefined): TriggerCondition[] {\n if (!c) {\n return [];\n }\n return Array.isArray(c) ? c.filter(Boolean) : [c];\n}\n\n/** True when the value is a condition group (`{op, conditions}`) rather than a plain condition. */\nfunction isGroup(c: TriggerCondition | TriggerConditionGroup): c is TriggerConditionGroup {\n return Array.isArray((c as TriggerConditionGroup).conditions);\n}\n\n/**\n * Parse a delay: `\"5h\"`, `\"30m\"`, `\"90s\"`, `\"2d\"`, or a plain number of seconds. Returns 0 when there is\n * nothing to wait for and -1 when the text makes no sense (so the caller can complain instead of firing).\n */\nexport function parseDelay(delay: string | number | undefined): number {\n if (delay === undefined || delay === null || delay === '') {\n return 0;\n }\n if (typeof delay === 'number') {\n return Number.isFinite(delay) && delay > 0 ? Math.round(delay) : 0;\n }\n const m = /^\\s*(\\d+(?:[.,]\\d+)?)\\s*([smhd]?)\\s*$/i.exec(delay);\n if (!m) {\n return -1;\n }\n const n = parseFloat(m[1].replace(',', '.'));\n const unit = (m[2] || 's').toLowerCase();\n const factor = unit === 'd' ? 86400 : unit === 'h' ? 3600 : unit === 'm' ? 60 : 1;\n return Math.round(n * factor);\n}\n\n/** `HH:MM` → `{hour, minute}`, or null if it isn't a time. */\nexport function parseTimeOfDay(time: string | undefined): { hour: number; minute: number } | null {\n const m = /^\\s*(\\d{1,2}):(\\d{2})\\s*$/.exec(time || '');\n if (!m) {\n return null;\n }\n const hour = Number(m[1]);\n const minute = Number(m[2]);\n return hour <= 23 && minute <= 59 ? { hour, minute } : null;\n}\n\n/** The actions a trigger runs: its own list, or the `say`/`room` shorthand folded into one. */\nexport function effectiveActions(def: TriggerDef): TriggerAction[] {\n const list = (def.actions || []).filter(a => a && (a.say || a.setState));\n if (list.length) {\n return list.map(a => ({ ...a, room: a.room ?? def.room }));\n }\n return def.say ? [{ say: def.say, room: def.room }] : [];\n}\n\n/** Every state id a trigger references, across `when`, `also`, `unless` and `cancelWhen`. */\nexport function referencedStates(def: TriggerDef): string[] {\n const ids = new Set<string>();\n const walk = (c: TriggerCondition | TriggerConditionGroup | TriggerCondition[] | undefined): void => {\n if (!c) {\n return;\n }\n if (Array.isArray(c)) {\n c.forEach(walk);\n return;\n }\n if (isGroup(c)) {\n c.conditions?.forEach(walk);\n return;\n }\n if (c.state) {\n ids.add(c.state);\n }\n walk(c.also);\n walk(c.unless);\n };\n walk(asList(def.when));\n walk(asList(def.cancelWhen));\n return [...ids];\n}\n\n/**\n * Does `value` satisfy the condition's value filter? `value` wins over `above`/`below`; without any filter\n * every value matches (the caller has already established that it *changed*).\n */\nexport function valueMatches(cond: TriggerCondition, value: TriggerValue | undefined): boolean {\n if (value === undefined) {\n return false;\n }\n if (cond.value !== undefined) {\n // Compare loosely on purpose: a state can hold 'true'/1 where the config says true.\n return normalize(value) === normalize(cond.value);\n }\n if (cond.above !== undefined) {\n const n = Number(value);\n return Number.isFinite(n) && n > Number(cond.above);\n }\n if (cond.below !== undefined) {\n const n = Number(value);\n return Number.isFinite(n) && n < Number(cond.below);\n }\n return true;\n}\n\n/** Fold a value to a comparable primitive: booleans and numeric strings compare across types. */\nfunction normalize(v: TriggerValue): string | number | boolean | null {\n if (typeof v === 'string') {\n const s = v.trim();\n if (/^(true|false)$/i.test(s)) {\n return s.toLowerCase() === 'true';\n }\n if (s !== '' && Number.isFinite(Number(s))) {\n return Number(s);\n }\n return s;\n }\n return v;\n}\n\ninterface RuntimeTrigger {\n def: TriggerDef;\n enabled: boolean;\n lastFired: number;\n nextFireAt: number;\n /** The time condition `nextFireAt` came from, so its `also`/`unless` can be checked when it fires. */\n nextCond: TriggerCondition | null;\n}\n\n/** Trigger scheduler/evaluator. Owns *whether* and *when*; the host owns *what happens*. */\nexport class TriggerEngine {\n private readonly triggers = new Map<string, RuntimeTrigger>();\n /** Last seen value per state, for transition detection. */\n private readonly prev = new Map<string, TriggerValue>();\n private readonly timeHandles = new Map<string, ReturnType<typeof setTimeout>>();\n private readonly delays = new Map<string, { handle: ReturnType<typeof setTimeout> | null; until: number }>();\n private readonly now: () => number;\n\n constructor(private readonly opts: TriggerEngineOptions) {\n this.now = opts.now || Date.now;\n }\n\n /**\n * Replace the trigger set (on start and whenever the configuration changes). Runtime state of a\n * trigger that is still there survives — its cooldown and its live enabled flag — because a config\n * reload must not turn into a free pass to fire again immediately.\n */\n load(defs: TriggerDef[]): void {\n const keep = new Map(this.triggers);\n for (const id of this.triggers.keys()) {\n this.clearTime(id);\n }\n this.triggers.clear();\n for (const def of defs || []) {\n const problem = validate(def);\n if (problem) {\n this.opts.log?.warn(`trigger ${def?.id ? `'${def.id}'` : '(no id)'} ignored: ${problem}`);\n continue;\n }\n if (this.triggers.has(def.id)) {\n this.opts.log?.warn(`trigger '${def.id}' ignored: duplicate id`);\n continue;\n }\n const before = keep.get(def.id);\n this.triggers.set(def.id, {\n def,\n enabled: before ? before.enabled : def.enabled !== false,\n lastFired: before?.lastFired || 0,\n nextFireAt: 0,\n nextCond: null,\n });\n }\n // Drop pending delays of triggers that no longer exist.\n for (const id of [...this.delays.keys()]) {\n if (!this.triggers.has(id)) {\n this.clearDelay(id);\n }\n }\n for (const t of this.triggers.values()) {\n this.armTime(t);\n }\n this.opts.log?.debug(`triggers loaded: ${this.triggers.size}`);\n this.emitChange();\n }\n\n /** Restore live enabled flags (and last-fired times) persisted across a restart. */\n restore(status: Pick<TriggerStatus, 'id' | 'enabled' | 'lastFired'>[]): void {\n for (const s of status || []) {\n const t = this.triggers.get(s?.id);\n if (!t) {\n continue;\n }\n t.lastFired = Number(s.lastFired) || 0;\n if (s.enabled === false) {\n t.enabled = false;\n this.clearTime(s.id);\n t.nextFireAt = 0;\n t.nextCond = null;\n }\n }\n this.emitChange();\n }\n\n /**\n * Read every watched state once and remember its value, so the **first** report after a restart is not\n * mistaken for a transition. Without this, a device that re-sends its unchanged value periodically\n * would fire its trigger shortly after every adapter start. A state that cannot be read stays unknown,\n * so its first real value still counts.\n */\n async prime(): Promise<void> {\n for (const id of this.stateIds()) {\n await this.read(id);\n }\n }\n\n /** All state ids the current triggers reference — exactly what the host has to subscribe to. */\n stateIds(): string[] {\n const ids = new Set<string>();\n for (const t of this.triggers.values()) {\n referencedStates(t.def).forEach(id => ids.add(id));\n }\n return [...ids];\n }\n\n list(): TriggerStatus[] {\n return [...this.triggers.values()]\n .map(t => ({\n id: t.def.id,\n name: t.def.name || '',\n enabled: t.enabled,\n lastFired: t.lastFired,\n nextFireAt: t.nextFireAt,\n pendingUntil: this.delays.get(t.def.id)?.until || 0,\n }))\n .sort((a, b) => a.id.localeCompare(b.id));\n }\n\n get(id: string): TriggerDef | undefined {\n return this.triggers.get(id)?.def;\n }\n\n /** Enable/disable a trigger at runtime (keeps it loaded). Returns true if it existed. */\n setEnabled(id: string, enabled: boolean): boolean {\n const t = this.triggers.get(id);\n if (!t) {\n return false;\n }\n t.enabled = enabled;\n if (enabled) {\n this.armTime(t);\n } else {\n this.clearTime(id);\n this.clearDelay(id);\n t.nextFireAt = 0;\n t.nextCond = null;\n }\n this.emitChange();\n return true;\n }\n\n /**\n * Feed a state change in. Checks `cancelWhen` first (a pending delay may have to be aborted) and then\n * every `when` alternative that watches this state. Values identical to the last one are ignored — a\n * trigger reacts to a transition, not to a device repeating itself.\n */\n async onStateChange(id: string, value: TriggerValue): Promise<void> {\n const prev = this.prev.get(id);\n const known = this.prev.has(id);\n this.prev.set(id, value);\n if (known && normalize(prev as TriggerValue) === normalize(value)) {\n return;\n }\n for (const t of [...this.triggers.values()]) {\n if (!t.enabled) {\n continue;\n }\n for (const cond of asList(t.def.cancelWhen)) {\n if (cond.state === id && valueMatches(cond, value) && this.clearDelay(t.def.id)) {\n this.opts.log?.info(`trigger '${t.def.id}': pending delay cancelled (cancelWhen matched)`);\n this.emitChange();\n }\n }\n for (const cond of asList(t.def.when)) {\n if (cond.state !== id || !valueMatches(cond, value)) {\n continue;\n }\n if (!(await this.extraConditionsHold(cond, t.def.id))) {\n break;\n }\n await this.start(t, 'state');\n break;\n }\n }\n }\n\n /**\n * Fire a trigger by hand (the `fire` button / sendTo). Skips the cooldown and the delay: someone asked\n * for it to happen now. Returns false if the id is unknown.\n */\n async fireNow(id: string): Promise<boolean> {\n const t = this.triggers.get(id);\n if (!t) {\n return false;\n }\n t.lastFired = this.now();\n this.emitChange();\n await this.run(t, 'manual');\n return true;\n }\n\n /**\n * Fire every time trigger that is due — public so tests can drive it with a mocked clock; in\n * production each trigger fires from its own `setTimeout`, so this does nothing there.\n */\n async tick(): Promise<void> {\n const now = this.now();\n for (const t of [...this.triggers.values()]) {\n if (t.enabled && t.nextFireAt && t.nextFireAt <= now) {\n await this.fireTime(t);\n }\n }\n for (const [id, delay] of [...this.delays.entries()]) {\n if (delay.until && delay.until <= now) {\n const t = this.triggers.get(id);\n this.clearDelay(id);\n if (t) {\n await this.run(t, 'delay');\n }\n }\n }\n }\n\n /** Clear all timers and drop everything (no callbacks). Call on unload. */\n dispose(): void {\n for (const id of [...this.triggers.keys()]) {\n this.clearTime(id);\n }\n for (const id of [...this.delays.keys()]) {\n this.clearDelay(id);\n }\n this.triggers.clear();\n this.prev.clear();\n }\n\n /** `also` holds and `unless` does not — the half of a condition that needs other states. */\n private async extraConditionsHold(cond: TriggerCondition, id: string): Promise<boolean> {\n if (!(await this.alsoHolds(cond.also))) {\n this.opts.log?.debug(`trigger '${id}': 'also' condition not met`);\n return false;\n }\n if (await this.unlessBlocks(cond.unless)) {\n this.opts.log?.debug(`trigger '${id}': blocked by 'unless'`);\n return false;\n }\n return true;\n }\n\n private async alsoHolds(also: TriggerCondition['also']): Promise<boolean> {\n if (!also) {\n return true;\n }\n if (Array.isArray(also)) {\n for (const c of also) {\n if (!(await this.alsoHolds(c))) {\n return false;\n }\n }\n return true;\n }\n if (isGroup(also)) {\n const list = also.conditions || [];\n if (also.op === 'or') {\n for (const c of list) {\n if (await this.alsoHolds(c)) {\n return true;\n }\n }\n return false;\n }\n for (const c of list) {\n if (!(await this.alsoHolds(c))) {\n return false;\n }\n }\n return true;\n }\n if (!also.state) {\n return true;\n }\n // Unknown state blocks: we must not claim a condition holds when we cannot read it.\n return valueMatches(also, await this.read(also.state));\n }\n\n private async unlessBlocks(unless: TriggerCondition['unless']): Promise<boolean> {\n for (const c of asList(unless)) {\n if (!c.state) {\n continue;\n }\n const value = await this.read(c.state);\n // Unknown state does NOT block — see the module header.\n if (value !== undefined && valueMatches(c, value)) {\n return true;\n }\n }\n return false;\n }\n\n private async read(id: string): Promise<TriggerValue | undefined> {\n try {\n const value = await this.opts.getState(id);\n if (value !== undefined && value !== null) {\n this.prev.set(id, value);\n }\n return value === null ? undefined : value;\n } catch (e) {\n this.opts.log?.debug(`trigger: cannot read '${id}': ${(e as Error).message}`);\n return undefined;\n }\n }\n\n /**\n * A condition held: take the cooldown, then either run now or start the delay. The cooldown is taken\n * here rather than at execution time so a condition flapping during a long delay cannot queue up.\n */\n private async start(t: RuntimeTrigger, origin: string): Promise<void> {\n const now = this.now();\n const cooldown = (t.def.cooldownSec ?? DEFAULT_COOLDOWN_SEC) * 1000;\n if (cooldown > 0 && t.lastFired && now - t.lastFired < cooldown) {\n const left = Math.round((cooldown - (now - t.lastFired)) / 1000);\n this.opts.log?.debug(`trigger '${t.def.id}' in cooldown (${left}s left) — skipped`);\n return;\n }\n t.lastFired = now;\n const delaySec = parseDelay(t.def.delay);\n if (delaySec < 0) {\n this.opts.log?.warn(`trigger '${t.def.id}': invalid delay '${String(t.def.delay)}' — firing now`);\n }\n if (delaySec > 0) {\n if (this.delays.has(t.def.id)) {\n this.opts.log?.debug(`trigger '${t.def.id}': delay already running — skipped`);\n return;\n }\n const until = now + delaySec * 1000;\n this.opts.log?.info(`trigger '${t.def.id}' armed by ${origin}: waiting ${delaySec}s`);\n const handle = this.opts.manualTick\n ? null\n : setTimeout(\n () => {\n this.clearDelay(t.def.id);\n void this.run(t, 'delay');\n },\n Math.min(delaySec * 1000, MAX_TIMEOUT),\n );\n (handle as { unref?: () => void } | null)?.unref?.();\n this.delays.set(t.def.id, { handle, until });\n this.emitChange();\n return;\n }\n this.emitChange();\n await this.run(t, origin);\n }\n\n /** Hand a trigger to the host and keep going if it throws — one bad trigger must not stop the rest. */\n private async run(t: RuntimeTrigger, origin: string): Promise<void> {\n this.opts.log?.info(`trigger '${t.def.id}' fired (${origin})`);\n try {\n await this.opts.execute(t.def);\n } catch (e) {\n this.opts.log?.error(`trigger '${t.def.id}' failed: ${(e as Error).message}`);\n }\n this.emitChange();\n }\n\n /** A time trigger came due: re-check its extra conditions, fire, and schedule the next occurrence. */\n private async fireTime(t: RuntimeTrigger): Promise<void> {\n const cond = t.nextCond;\n this.clearTime(t.def.id);\n t.nextFireAt = 0;\n t.nextCond = null;\n const allowed = !cond || (await this.extraConditionsHold(cond, t.def.id));\n this.armTime(t); // re-arm first: an execution error must not stop tomorrow's run\n if (allowed) {\n await this.start(t, 'time');\n }\n }\n\n /** Schedule the earliest upcoming time condition of a trigger (no-op if it has none). */\n private armTime(t: RuntimeTrigger): void {\n this.clearTime(t.def.id);\n t.nextFireAt = 0;\n t.nextCond = null;\n if (!t.enabled) {\n return;\n }\n const now = this.now();\n for (const cond of asList(t.def.when)) {\n const clock = parseTimeOfDay(cond.time);\n if (!clock) {\n continue;\n }\n const days = (cond.days || []).filter(d => d >= 0 && d <= 6);\n const at = computeNextFire(clock.hour, clock.minute, days, now);\n if (at && (!t.nextFireAt || at < t.nextFireAt)) {\n t.nextFireAt = at;\n t.nextCond = cond;\n }\n }\n if (!t.nextFireAt || this.opts.manualTick) {\n return;\n }\n const handle = setTimeout(\n () => {\n const current = this.triggers.get(t.def.id);\n if (!current) {\n return;\n }\n if (current.nextFireAt - this.now() > 0) {\n this.armTime(current); // was only a chunk of a long wait\n } else {\n void this.fireTime(current);\n }\n },\n Math.min(Math.max(0, t.nextFireAt - now), MAX_TIMEOUT),\n );\n (handle as { unref?: () => void }).unref?.();\n this.timeHandles.set(t.def.id, handle);\n }\n\n private clearTime(id: string): void {\n const h = this.timeHandles.get(id);\n if (h) {\n clearTimeout(h);\n this.timeHandles.delete(id);\n }\n }\n\n private clearDelay(id: string): boolean {\n const d = this.delays.get(id);\n if (!d) {\n return false;\n }\n if (d.handle) {\n clearTimeout(d.handle);\n }\n this.delays.delete(id);\n return true;\n }\n\n private emitChange(): void {\n try {\n this.opts.onChange?.(this.list());\n } catch (e) {\n this.opts.log?.warn(`trigger onChange failed: ${(e as Error).message}`);\n }\n }\n}\n\n/** One row of the settings table: the structured fields may arrive as JSON text. */\nexport type TriggerRow = Omit<TriggerDef, 'when' | 'onResponse' | 'actions'> & {\n when?: TriggerDef['when'] | string;\n onResponse?: TriggerDef['onResponse'] | string;\n actions?: TriggerDef['actions'] | string;\n};\n\n/**\n * Turn settings-table rows into definitions: the JSON-typed columns are parsed here so a typo surfaces as\n * one clear warning per field instead of breaking the trigger later, and empty cells fall back to the\n * defaults rather than to zero. A row written by a script may pass the structured form straight through.\n */\nexport function parseTriggerRows(\n rows: TriggerRow[] | undefined,\n opts: { rephraseDefault?: boolean; warn?: (message: string) => void } = {},\n): TriggerDef[] {\n const out: TriggerDef[] = [];\n for (const row of rows || []) {\n const id = String(row?.id ?? '').trim();\n if (!id) {\n continue; // an empty row in the table is not an error, it is just empty\n }\n const parse = (field: string, raw: unknown): unknown => {\n if (raw === undefined || raw === null || raw === '') {\n return undefined;\n }\n if (typeof raw !== 'string') {\n return raw;\n }\n try {\n return JSON.parse(raw);\n } catch (e) {\n opts.warn?.(`trigger '${id}': ${field} is not valid JSON (${(e as Error).message}) — ignored`);\n return undefined;\n }\n };\n const cooldown = Number(row.cooldownSec);\n out.push({\n id,\n name: String(row.name ?? '').trim(),\n enabled: row.enabled,\n when: parse('when', row.when) as TriggerDef['when'],\n room: String(row.room ?? '').trim(),\n say: String(row.say ?? '').trim(),\n ask: String(row.ask ?? '').trim(),\n onResponse: parse('onResponse', row.onResponse) as TriggerDef['onResponse'],\n actions: parse('actions', row.actions) as TriggerDef['actions'],\n delay: row.delay,\n cooldownSec:\n row.cooldownSec === undefined ||\n row.cooldownSec === null ||\n (row.cooldownSec as unknown) === '' ||\n !Number.isFinite(cooldown)\n ? undefined\n : cooldown,\n rephrase: row.rephrase ?? opts.rephraseDefault === true,\n });\n }\n return out;\n}\n\n/** Why a definition cannot be used, or '' when it is fine. */\nexport function validate(def: TriggerDef | undefined): string {\n if (!def || typeof def !== 'object') {\n return 'not an object';\n }\n if (!def.id || typeof def.id !== 'string') {\n return 'missing id';\n }\n const when = asList(def.when);\n if (!when.length) {\n return 'missing \"when\" condition';\n }\n for (const cond of when) {\n if (cond.time !== undefined && !parseTimeOfDay(cond.time)) {\n return `invalid time '${String(cond.time)}' (expected HH:MM)`;\n }\n if (!cond.state && cond.time === undefined) {\n return 'a \"when\" condition needs either a state or a time';\n }\n }\n if (parseDelay(def.delay) < 0) {\n return `invalid delay '${String(def.delay)}' (expected 90s, 30m, 5h, 2d or seconds)`;\n }\n if (!def.ask && !effectiveActions(def).length) {\n return 'nothing to do (no say, actions or ask)';\n }\n if (def.ask && !(def.onResponse || []).length) {\n return 'an \"ask\" trigger needs onResponse rules';\n }\n return '';\n}\n"]}
|
package/build/lib/voice/aws.js
CHANGED
|
@@ -82,11 +82,19 @@ class AwsTts {
|
|
|
82
82
|
credentials: { accessKeyId: creds.accessKeyId, secretAccessKey: creds.secretAccessKey },
|
|
83
83
|
});
|
|
84
84
|
}
|
|
85
|
-
|
|
85
|
+
synthesize(text, lang) {
|
|
86
|
+
return this.speak(text, lang, 'text');
|
|
87
|
+
}
|
|
88
|
+
/** Polly speaks SSML natively (`TextType: 'ssml'`), so pauses and emphasis survive. */
|
|
89
|
+
synthesizeSsml(ssml, lang) {
|
|
90
|
+
return this.speak(ssml, lang, 'ssml');
|
|
91
|
+
}
|
|
92
|
+
async speak(text, lang, textType) {
|
|
86
93
|
const iso = (lang || 'en').split('-')[0].toLowerCase();
|
|
87
94
|
const voice = this.voice || DEFAULT_POLLY_VOICE[iso] || 'Joanna';
|
|
88
95
|
const resp = await this.client.send(new client_polly_1.SynthesizeSpeechCommand({
|
|
89
96
|
Text: text,
|
|
97
|
+
TextType: textType,
|
|
90
98
|
OutputFormat: 'pcm', // 16-bit signed 1-channel little-endian
|
|
91
99
|
SampleRate: '16000',
|
|
92
100
|
VoiceId: voice,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"aws.js","sourceRoot":"","sources":["../../../src/lib/voice/aws.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"aws.js","sourceRoot":"","sources":["../../../src/lib/voice/aws.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * AWS speech engines: STT via Amazon Transcribe (streaming) and TTS via Amazon Polly.\n * Credentials: accessKeyId + secretAccessKey + region.\n */\nimport {\n PollyClient,\n SynthesizeSpeechCommand,\n DescribeVoicesCommand,\n type VoiceId,\n type LanguageCode as PollyLanguageCode,\n} from '@aws-sdk/client-polly';\nimport {\n TranscribeStreamingClient,\n StartStreamTranscriptionCommand,\n type AudioStream,\n type LanguageCode,\n} from '@aws-sdk/client-transcribe-streaming';\nimport { isoToLocale } from './lang';\nimport type { SttEngine } from './stt';\nimport type { TtsEngine, TtsResult } from './tts';\n\nexport interface AwsCreds {\n accessKeyId: string;\n secretAccessKey: string;\n region: string;\n}\n\n/** Reasonable default Polly voice per language when none is configured. */\nconst DEFAULT_POLLY_VOICE: Record<string, string> = {\n de: 'Vicki',\n en: 'Joanna',\n ru: 'Tatyana',\n fr: 'Lea',\n it: 'Bianca',\n es: 'Lucia',\n nl: 'Laura',\n pl: 'Ewa',\n pt: 'Ines',\n};\n\n/** ~100 ms of 16 kHz mono 16-bit PCM per Transcribe audio chunk. */\nconst STT_CHUNK_BYTES = 3200;\n\n/** List available Polly voice ids, optionally filtered by language (locale, e.g. 'de-DE'). */\nexport async function listPollyVoices(creds: AwsCreds, languageCode: string): Promise<string[]> {\n const client = new PollyClient({\n region: creds.region,\n credentials: { accessKeyId: creds.accessKeyId, secretAccessKey: creds.secretAccessKey },\n });\n const res = await client.send(\n new DescribeVoicesCommand(languageCode ? { LanguageCode: languageCode as PollyLanguageCode } : {}),\n );\n return (res.Voices || []).map(v => v.Id).filter((id): id is VoiceId => !!id);\n}\n\nexport class AwsStt implements SttEngine {\n private readonly client: TranscribeStreamingClient;\n\n constructor(creds: AwsCreds) {\n this.client = new TranscribeStreamingClient({\n region: creds.region,\n credentials: { accessKeyId: creds.accessKeyId, secretAccessKey: creds.secretAccessKey },\n });\n }\n\n // Note: the SttEngine `hints` vocabulary is intentionally not applied here. Amazon Transcribe biases\n // only via a *custom vocabulary* that must be created/registered ahead of time (CreateVocabulary) and\n // referenced by name — there is no inline per-request word list for streaming. So we skip biasing for AWS.\n async transcribe(pcm: Buffer, sampleRate: number, lang: string): Promise<string> {\n // Must be an async generator: Transcribe's AudioStream is an AsyncIterable.\n // eslint-disable-next-line @typescript-eslint/require-await\n async function* audio(): AsyncGenerator<AudioStream> {\n for (let off = 0; off < pcm.length; off += STT_CHUNK_BYTES) {\n yield { AudioEvent: { AudioChunk: pcm.subarray(off, off + STT_CHUNK_BYTES) } };\n }\n }\n\n const resp = await this.client.send(\n new StartStreamTranscriptionCommand({\n LanguageCode: isoToLocale(lang) as LanguageCode,\n MediaSampleRateHertz: sampleRate,\n MediaEncoding: 'pcm',\n AudioStream: audio(),\n }),\n );\n\n let text = '';\n for await (const event of resp.TranscriptResultStream || []) {\n for (const result of event.TranscriptEvent?.Transcript?.Results || []) {\n const transcript = result.Alternatives?.[0]?.Transcript;\n if (!result.IsPartial && transcript) {\n text += (text ? ' ' : '') + transcript;\n }\n }\n }\n return text.trim();\n }\n}\n\nexport class AwsTts implements TtsEngine {\n private readonly client: PollyClient;\n\n constructor(\n creds: AwsCreds,\n /** Polly VoiceId (e.g. 'Vicki', 'Tatyana'); empty → default per language. */\n private readonly voice: string,\n ) {\n this.client = new PollyClient({\n region: creds.region,\n credentials: { accessKeyId: creds.accessKeyId, secretAccessKey: creds.secretAccessKey },\n });\n }\n\n synthesize(text: string, lang: string): Promise<TtsResult> {\n return this.speak(text, lang, 'text');\n }\n\n /** Polly speaks SSML natively (`TextType: 'ssml'`), so pauses and emphasis survive. */\n synthesizeSsml(ssml: string, lang: string): Promise<TtsResult> {\n return this.speak(ssml, lang, 'ssml');\n }\n\n private async speak(text: string, lang: string, textType: 'text' | 'ssml'): Promise<TtsResult> {\n const iso = (lang || 'en').split('-')[0].toLowerCase();\n const voice = this.voice || DEFAULT_POLLY_VOICE[iso] || 'Joanna';\n const resp = await this.client.send(\n new SynthesizeSpeechCommand({\n Text: text,\n TextType: textType,\n OutputFormat: 'pcm', // 16-bit signed 1-channel little-endian\n SampleRate: '16000',\n VoiceId: voice as VoiceId,\n }),\n );\n if (!resp.AudioStream) {\n throw new Error('Polly returned no audio stream');\n }\n const bytes = await resp.AudioStream.transformToByteArray();\n return { pcm: Buffer.from(bytes), sampleRate: 16000 };\n }\n}\n"]}
|
package/build/lib/voice/azure.js
CHANGED
|
@@ -115,7 +115,14 @@ class AzureTts {
|
|
|
115
115
|
this.region = region;
|
|
116
116
|
this.voice = voice;
|
|
117
117
|
}
|
|
118
|
-
|
|
118
|
+
synthesize(text, lang) {
|
|
119
|
+
return this.speak(lang, (synth, resolve, reject) => synth.speakTextAsync(text, resolve, reject));
|
|
120
|
+
}
|
|
121
|
+
/** Azure speaks SSML natively, so pauses and emphasis survive. */
|
|
122
|
+
synthesizeSsml(ssml, lang) {
|
|
123
|
+
return this.speak(lang, (synth, resolve, reject) => synth.speakSsmlAsync(ssml, resolve, reject));
|
|
124
|
+
}
|
|
125
|
+
async speak(lang, run) {
|
|
119
126
|
const speechConfig = sdk.SpeechConfig.fromSubscription(this.key, this.region);
|
|
120
127
|
speechConfig.speechSynthesisOutputFormat = sdk.SpeechSynthesisOutputFormat.Raw24Khz16BitMonoPcm;
|
|
121
128
|
if (this.voice) {
|
|
@@ -128,7 +135,7 @@ class AzureTts {
|
|
|
128
135
|
const synth = new sdk.SpeechSynthesizer(speechConfig, null);
|
|
129
136
|
try {
|
|
130
137
|
const result = await new Promise((resolve, reject) => {
|
|
131
|
-
synth
|
|
138
|
+
run(synth, resolve, reject);
|
|
132
139
|
});
|
|
133
140
|
if (result.reason === sdk.ResultReason.SynthesizingAudioCompleted) {
|
|
134
141
|
return { pcm: Buffer.from(result.audioData), sampleRate: 24000 };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"azure.js","sourceRoot":"","sources":["../../../src/lib/voice/azure.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"azure.js","sourceRoot":"","sources":["../../../src/lib/voice/azure.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAUA,0CAYC;AAtBD;;;GAGG;AACH,4EAA8D;AAC9D,iCAAqC;AAIrC,yGAAyG;AAClG,KAAK,UAAU,eAAe,CAAC,GAAW,EAAE,MAAc,EAAE,MAAc;IAC7E,MAAM,YAAY,GAAG,GAAG,CAAC,YAAY,CAAC,gBAAgB,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IACpE,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,iBAAiB,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;IAC5D,IAAI,CAAC;QACD,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,cAAc,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC;QACrD,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,CAAC,YAAY,CAAC,mBAAmB,EAAE,CAAC;YACtD,OAAO,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;QAC5C,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,GAAG,CAAC,YAAY,IAAI,yBAAyB,CAAC,CAAC;IACnE,CAAC;YAAS,CAAC;QACP,KAAK,CAAC,KAAK,EAAE,CAAC;IAClB,CAAC;AACL,CAAC;AAED,2FAA2F;AAC3F,MAAa,QAAQ;IAEI;IACA;IAFrB,YACqB,GAAW,EACX,MAAc;QADd,QAAG,GAAH,GAAG,CAAQ;QACX,WAAM,GAAN,MAAM,CAAQ;IAChC,CAAC;IAEJ,KAAK,CAAC,UAAU,CAAC,GAAW,EAAE,UAAkB,EAAE,IAAY,EAAE,KAAgB;QAC5E,MAAM,YAAY,GAAG,GAAG,CAAC,YAAY,CAAC,gBAAgB,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;QAC9E,YAAY,CAAC,yBAAyB,GAAG,IAAA,kBAAW,EAAC,IAAI,CAAC,CAAC;QAE3D,MAAM,MAAM,GAAG,GAAG,CAAC,iBAAiB,CAAC,gBAAgB,CAAC,UAAU,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;QACzE,MAAM,UAAU,GAAG,GAAG,CAAC,gBAAgB,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC;QACjE,oFAAoF;QACpF,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,EAAE,GAAG,CAAC,UAAU,GAAG,GAAG,CAAC,UAAU,CAAgB,CAAC,CAAC;QACnG,UAAU,CAAC,KAAK,EAAE,CAAC;QAEnB,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,gBAAgB,CAAC,YAAY,EAAE,GAAG,CAAC,WAAW,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC,CAAC;QACvG,qGAAqG;QACrG,kDAAkD;QAClD,IAAI,KAAK,EAAE,MAAM,EAAE,CAAC;YAChB,MAAM,UAAU,GAAG,GAAG,CAAC,iBAAiB,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC;YACpE,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;gBACpB,MAAM,IAAI,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;gBAC9B,IAAI,IAAI,EAAE,CAAC;oBACP,UAAU,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;gBAC/B,CAAC;YACL,CAAC;QACL,CAAC;QACD,IAAI,CAAC;YACD,MAAM,MAAM,GAAG,MAAM,IAAI,OAAO,CAA8B,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;gBAC9E,UAAU,CAAC,kBAAkB,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;YACnD,CAAC,CAAC,CAAC;YACH,IAAI,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,YAAY,CAAC,gBAAgB,EAAE,CAAC;gBACtD,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;YAC9B,CAAC;YACD,IAAI,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,YAAY,CAAC,QAAQ,EAAE,CAAC;gBAC9C,MAAM,OAAO,GAAG,GAAG,CAAC,mBAAmB,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;gBAC3D,MAAM,IAAI,KAAK,CAAC,uBAAuB,OAAO,CAAC,YAAY,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;YACrF,CAAC;YACD,OAAO,EAAE,CAAC;QACd,CAAC;gBAAS,CAAC;YACP,UAAU,CAAC,KAAK,EAAE,CAAC;QACvB,CAAC;IACL,CAAC;CACJ;AA5CD,4BA4CC;AAED,yEAAyE;AACzE,MAAa,QAAQ;IAEI;IACA;IAEA;IAJrB,YACqB,GAAW,EACX,MAAc;IAC/B,kFAAkF;IACjE,KAAa;QAHb,QAAG,GAAH,GAAG,CAAQ;QACX,WAAM,GAAN,MAAM,CAAQ;QAEd,UAAK,GAAL,KAAK,CAAQ;IAC/B,CAAC;IAEJ,UAAU,CAAC,IAAY,EAAE,IAAY;QACjC,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,CAAC,KAAK,CAAC,cAAc,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;IACrG,CAAC;IAED,kEAAkE;IAClE,cAAc,CAAC,IAAY,EAAE,IAAY;QACrC,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,CAAC,KAAK,CAAC,cAAc,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;IACrG,CAAC;IAEO,KAAK,CAAC,KAAK,CACf,IAAY,EACZ,GAIS;QAET,MAAM,YAAY,GAAG,GAAG,CAAC,YAAY,CAAC,gBAAgB,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;QAC9E,YAAY,CAAC,2BAA2B,GAAG,GAAG,CAAC,2BAA2B,CAAC,oBAAoB,CAAC;QAChG,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACb,YAAY,CAAC,wBAAwB,GAAG,IAAI,CAAC,KAAK,CAAC;QACvD,CAAC;aAAM,CAAC;YACJ,YAAY,CAAC,uBAAuB,GAAG,IAAA,kBAAW,EAAC,IAAI,CAAC,CAAC;QAC7D,CAAC;QAED,2EAA2E;QAC3E,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,iBAAiB,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;QAC5D,IAAI,CAAC;YACD,MAAM,MAAM,GAAG,MAAM,IAAI,OAAO,CAA4B,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;gBAC5E,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;YAChC,CAAC,CAAC,CAAC;YACH,IAAI,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,YAAY,CAAC,0BAA0B,EAAE,CAAC;gBAChE,OAAO,EAAE,GAAG,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC;YACrE,CAAC;YACD,MAAM,IAAI,KAAK,CAAC,qBAAqB,MAAM,CAAC,YAAY,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;QACjF,CAAC;gBAAS,CAAC;YACP,KAAK,CAAC,KAAK,EAAE,CAAC;QAClB,CAAC;IACL,CAAC;CACJ;AA/CD,4BA+CC","sourcesContent":["/**\n * Azure Cognitive Services Speech engines (STT + TTS).\n * Credentials: a subscription key + region (e.g. 'westeurope').\n */\nimport * as sdk from 'microsoft-cognitiveservices-speech-sdk';\nimport { isoToLocale } from './lang';\nimport type { SttEngine } from './stt';\nimport type { TtsEngine, TtsResult } from './tts';\n\n/** List available Azure voices (short names like 'de-DE-KatjaNeural'), optionally filtered by locale. */\nexport async function listAzureVoices(key: string, region: string, locale: string): Promise<string[]> {\n const speechConfig = sdk.SpeechConfig.fromSubscription(key, region);\n const synth = new sdk.SpeechSynthesizer(speechConfig, null);\n try {\n const res = await synth.getVoicesAsync(locale || '');\n if (res.reason === sdk.ResultReason.VoicesListRetrieved) {\n return res.voices.map(v => v.shortName);\n }\n throw new Error(res.errorDetails || 'Azure voice list failed');\n } finally {\n synth.close();\n }\n}\n\n/** Azure STT via `recognizeOnceAsync` fed from a PCM push stream (one short utterance). */\nexport class AzureStt implements SttEngine {\n constructor(\n private readonly key: string,\n private readonly region: string,\n ) {}\n\n async transcribe(pcm: Buffer, sampleRate: number, lang: string, hints?: string[]): Promise<string> {\n const speechConfig = sdk.SpeechConfig.fromSubscription(this.key, this.region);\n speechConfig.speechRecognitionLanguage = isoToLocale(lang);\n\n const format = sdk.AudioStreamFormat.getWaveFormatPCM(sampleRate, 16, 1);\n const pushStream = sdk.AudioInputStream.createPushStream(format);\n // The push stream needs a standalone ArrayBuffer (not the pooled Node Buffer view).\n pushStream.write(pcm.buffer.slice(pcm.byteOffset, pcm.byteOffset + pcm.byteLength) as ArrayBuffer);\n pushStream.close();\n\n const recognizer = new sdk.SpeechRecognizer(speechConfig, sdk.AudioConfig.fromStreamInput(pushStream));\n // A phrase list softly boosts recognition of the given domain vocabulary (device/room names) without\n // restricting the recognizer to only those words.\n if (hints?.length) {\n const phraseList = sdk.PhraseListGrammar.fromRecognizer(recognizer);\n for (const h of hints) {\n const term = (h || '').trim();\n if (term) {\n phraseList.addPhrase(term);\n }\n }\n }\n try {\n const result = await new Promise<sdk.SpeechRecognitionResult>((resolve, reject) => {\n recognizer.recognizeOnceAsync(resolve, reject);\n });\n if (result.reason === sdk.ResultReason.RecognizedSpeech) {\n return result.text.trim();\n }\n if (result.reason === sdk.ResultReason.Canceled) {\n const details = sdk.CancellationDetails.fromResult(result);\n throw new Error(`Azure STT canceled: ${details.errorDetails || details.reason}`);\n }\n return '';\n } finally {\n recognizer.close();\n }\n }\n}\n\n/** Azure TTS to raw 24 kHz mono 16-bit PCM (no server-side playback). */\nexport class AzureTts implements TtsEngine {\n constructor(\n private readonly key: string,\n private readonly region: string,\n /** Full Azure voice name (e.g. 'de-DE-KatjaNeural'); empty → pick by language. */\n private readonly voice: string,\n ) {}\n\n synthesize(text: string, lang: string): Promise<TtsResult> {\n return this.speak(lang, (synth, resolve, reject) => synth.speakTextAsync(text, resolve, reject));\n }\n\n /** Azure speaks SSML natively, so pauses and emphasis survive. */\n synthesizeSsml(ssml: string, lang: string): Promise<TtsResult> {\n return this.speak(lang, (synth, resolve, reject) => synth.speakSsmlAsync(ssml, resolve, reject));\n }\n\n private async speak(\n lang: string,\n run: (\n synth: sdk.SpeechSynthesizer,\n resolve: (r: sdk.SpeechSynthesisResult) => void,\n reject: (e: unknown) => void,\n ) => void,\n ): Promise<TtsResult> {\n const speechConfig = sdk.SpeechConfig.fromSubscription(this.key, this.region);\n speechConfig.speechSynthesisOutputFormat = sdk.SpeechSynthesisOutputFormat.Raw24Khz16BitMonoPcm;\n if (this.voice) {\n speechConfig.speechSynthesisVoiceName = this.voice;\n } else {\n speechConfig.speechSynthesisLanguage = isoToLocale(lang);\n }\n\n // audioConfig=null → synthesise to memory only, no default-speaker output.\n const synth = new sdk.SpeechSynthesizer(speechConfig, null);\n try {\n const result = await new Promise<sdk.SpeechSynthesisResult>((resolve, reject) => {\n run(synth, resolve, reject);\n });\n if (result.reason === sdk.ResultReason.SynthesizingAudioCompleted) {\n return { pcm: Buffer.from(result.audioData), sampleRate: 24000 };\n }\n throw new Error(`Azure TTS failed: ${result.errorDetails || result.reason}`);\n } finally {\n synth.close();\n }\n }\n}\n"]}
|
|
@@ -1,4 +1,37 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
2
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
36
|
exports.createSttEngine = createSttEngine;
|
|
4
37
|
exports.createTtsEngine = createTtsEngine;
|
|
@@ -15,6 +48,9 @@ const azure_1 = require("./azure");
|
|
|
15
48
|
const aws_1 = require("./aws");
|
|
16
49
|
const vosk_1 = require("./vosk");
|
|
17
50
|
const piper_1 = require("./piper");
|
|
51
|
+
const path = __importStar(require("node:path"));
|
|
52
|
+
const ttsCache_1 = require("./ttsCache");
|
|
53
|
+
const fallback_1 = require("./fallback");
|
|
18
54
|
const lang_1 = require("./lang");
|
|
19
55
|
function requireAzure(creds) {
|
|
20
56
|
if (!creds.azureKey || !creds.azureRegion) {
|
|
@@ -32,6 +68,20 @@ function requireOpenAi(creds) {
|
|
|
32
68
|
}
|
|
33
69
|
}
|
|
34
70
|
function createSttEngine(provider, ctx) {
|
|
71
|
+
const primary = { name: provider, engine: buildSttEngine(provider, ctx) };
|
|
72
|
+
const fallback = ctx.sttFallback && ctx.sttFallback !== provider ? ctx.sttFallback : '';
|
|
73
|
+
if (!fallback) {
|
|
74
|
+
return primary.engine;
|
|
75
|
+
}
|
|
76
|
+
try {
|
|
77
|
+
return new fallback_1.FallbackStt([primary, { name: fallback, engine: buildSttEngine(fallback, ctx) }], ctx.log);
|
|
78
|
+
}
|
|
79
|
+
catch (e) {
|
|
80
|
+
ctx.log.warn(`Speech-to-text fallback '${fallback}' unavailable: ${e.message}`);
|
|
81
|
+
return primary.engine;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
function buildSttEngine(provider, ctx) {
|
|
35
85
|
switch (provider) {
|
|
36
86
|
case 'azure':
|
|
37
87
|
requireAzure(ctx.creds);
|
|
@@ -49,6 +99,38 @@ function createSttEngine(provider, ctx) {
|
|
|
49
99
|
}
|
|
50
100
|
}
|
|
51
101
|
function createTtsEngine(provider, ctx) {
|
|
102
|
+
// Each engine gets the shared behaviour (disk cache, length limit, SSML) and its own cache directory,
|
|
103
|
+
// so a fallback engine's voice can never be served later while the primary one is healthy again.
|
|
104
|
+
const primary = { name: provider, engine: cachedTts(provider, ctx) };
|
|
105
|
+
const fallback = ctx.ttsFallback && ctx.ttsFallback !== provider ? ctx.ttsFallback : '';
|
|
106
|
+
if (!fallback) {
|
|
107
|
+
return primary.engine;
|
|
108
|
+
}
|
|
109
|
+
try {
|
|
110
|
+
return new fallback_1.FallbackTts([primary, { name: fallback, engine: cachedTts(fallback, ctx) }], ctx.log);
|
|
111
|
+
}
|
|
112
|
+
catch (e) {
|
|
113
|
+
// A fallback that cannot even be built (missing key, wrong provider) must not take the main one down.
|
|
114
|
+
ctx.log.warn(`Text-to-speech fallback '${fallback}' unavailable: ${e.message}`);
|
|
115
|
+
return primary.engine;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* One provider binding plus the shared cache/length/SSML layer. One cache directory per provider+voice —
|
|
120
|
+
* a voice change must not serve audio in the old voice.
|
|
121
|
+
*/
|
|
122
|
+
function cachedTts(provider, ctx) {
|
|
123
|
+
const voice = provider === 'azure'
|
|
124
|
+
? ctx.voices.azure
|
|
125
|
+
: provider === 'aws'
|
|
126
|
+
? ctx.voices.aws
|
|
127
|
+
: provider === 'piper'
|
|
128
|
+
? ctx.voices.piper
|
|
129
|
+
: ctx.voices.openai;
|
|
130
|
+
const dir = path.join(ctx.dataDir, 'ttscache', `${provider}-${(voice || 'default').replace(/[^\w.-]/g, '_')}`);
|
|
131
|
+
return new ttsCache_1.CachedTts(buildTtsEngine(provider, ctx), { dir, log: ctx.log });
|
|
132
|
+
}
|
|
133
|
+
function buildTtsEngine(provider, ctx) {
|
|
52
134
|
switch (provider) {
|
|
53
135
|
case 'azure':
|
|
54
136
|
requireAzure(ctx.creds);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"engines.js","sourceRoot":"","sources":["../../../src/lib/voice/engines.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Factory that builds the configured STT/TTS engine. Cloud engines (OpenAI/Azure/AWS) use resolved\n * credentials; local engines (Vosk/Piper) download their models on demand into the data dir.\n * Adding a provider = one new engine class + one `case` here.\n */\nimport { OpenAiStt, type SttEngine } from './stt';\nimport { OpenAiTts, type OpenAiVoice, type TtsEngine } from './tts';\nimport { AzureStt, AzureTts, listAzureVoices } from './azure';\nimport { AwsStt, AwsTts, listPollyVoices, type AwsCreds } from './aws';\nimport { VoskStt, listVoskModels } from './vosk';\nimport { PiperTts, listPiperVoices } from './piper';\nimport { isoToLocale } from './lang';\nimport type { VoiceLogger } from './download';\n\nexport type SpeechProvider = 'openai' | 'azure' | 'aws' | 'vosk' | 'piper';\n\n/** All speech credentials, resolved from config (or the central credential store). */\nexport interface VoiceCredentials {\n openaiKey: string;\n azureKey: string;\n azureRegion: string;\n aws: AwsCreds;\n}\n\n/** Provider-specific voice ids (each provider names voices differently). */\nexport interface VoiceNames {\n openai: string; // alloy/echo/…\n azure: string; // e.g. de-DE-KatjaNeural\n aws: string; // e.g. Vicki\n piper: string; // e.g. de_DE-thorsten-medium\n}\n\n/** Everything the factory needs to build any engine. */\nexport interface EngineContext {\n creds: VoiceCredentials;\n voices: VoiceNames;\n /** Writable instance data dir (for the local engines' downloads). */\n dataDir: string;\n log: VoiceLogger;\n /** Local model overrides ('' → default per language). */\n voskModel: string;\n /** OpenAI STT model ('' → 'whisper-1'; e.g. 'gpt-4o-transcribe'). */\n sttModel: string;\n /** OpenAI TTS model ('' → 'tts-1'; e.g. 'gpt-4o-mini-tts'). */\n ttsModel: string;\n}\n\nfunction requireAzure(creds: VoiceCredentials): void {\n if (!creds.azureKey || !creds.azureRegion) {\n throw new Error('Azure speech needs a subscription key and region');\n }\n}\n\nfunction requireAws(creds: VoiceCredentials): void {\n if (!creds.aws.accessKeyId || !creds.aws.secretAccessKey || !creds.aws.region) {\n throw new Error('AWS speech needs an access key id, secret access key and region');\n }\n}\n\nfunction requireOpenAi(creds: VoiceCredentials): void {\n if (!creds.openaiKey) {\n throw new Error('OpenAI speech needs an API key');\n }\n}\n\nexport function createSttEngine(provider: SpeechProvider, ctx: EngineContext): SttEngine {\n switch (provider) {\n case 'azure':\n requireAzure(ctx.creds);\n return new AzureStt(ctx.creds.azureKey, ctx.creds.azureRegion);\n case 'aws':\n requireAws(ctx.creds);\n return new AwsStt(ctx.creds.aws);\n case 'vosk':\n return new VoskStt(ctx.dataDir, ctx.voskModel, ctx.log);\n case 'piper':\n throw new Error('Piper is a text-to-speech engine, not speech-to-text');\n default:\n requireOpenAi(ctx.creds);\n return new OpenAiStt(ctx.creds.openaiKey, ctx.sttModel || undefined);\n }\n}\n\nexport function createTtsEngine(provider: SpeechProvider, ctx: EngineContext): TtsEngine {\n switch (provider) {\n case 'azure':\n requireAzure(ctx.creds);\n return new AzureTts(ctx.creds.azureKey, ctx.creds.azureRegion, ctx.voices.azure);\n case 'aws':\n requireAws(ctx.creds);\n return new AwsTts(ctx.creds.aws, ctx.voices.aws);\n case 'piper':\n return new PiperTts(ctx.dataDir, ctx.voices.piper, ctx.log);\n case 'vosk':\n throw new Error('Vosk is a speech-to-text engine, not text-to-speech');\n default:\n requireOpenAi(ctx.creds);\n return new OpenAiTts(\n ctx.creds.openaiKey,\n (ctx.voices.openai || 'alloy') as OpenAiVoice,\n ctx.ttsModel || undefined,\n );\n }\n}\n\n/** OpenAI TTS voices are a fixed set (no list API). */\nconst OPENAI_VOICES = ['alloy', 'echo', 'fable', 'onyx', 'nova', 'shimmer'];\n\n/** List the available TTS voices for a provider (for the settings voice dropdown). */\nexport async function listVoices(provider: SpeechProvider, ctx: EngineContext, language: string): Promise<string[]> {\n switch (provider) {\n case 'azure':\n requireAzure(ctx.creds);\n return listAzureVoices(ctx.creds.azureKey, ctx.creds.azureRegion, isoToLocale(language));\n case 'aws':\n requireAws(ctx.creds);\n return listPollyVoices(ctx.creds.aws, isoToLocale(language));\n case 'piper':\n return listPiperVoices();\n default:\n return OPENAI_VOICES;\n }\n}\n\n/** Suggested STT model names for the settings dropdown. Only Vosk has a local model catalogue. */\nexport function listSttModels(provider: SpeechProvider, language: string): string[] {\n return provider === 'vosk' ? listVoskModels(language) : [];\n}\n"]}
|
|
1
|
+
{"version":3,"file":"engines.js","sourceRoot":"","sources":["../../../src/lib/voice/engines.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Factory that builds the configured STT/TTS engine. Cloud engines (OpenAI/Azure/AWS) use resolved\n * credentials; local engines (Vosk/Piper) download their models on demand into the data dir.\n * Adding a provider = one new engine class + one `case` here.\n */\nimport { OpenAiStt, type SttEngine } from './stt';\nimport { OpenAiTts, type OpenAiVoice, type TtsEngine } from './tts';\nimport { AzureStt, AzureTts, listAzureVoices } from './azure';\nimport { AwsStt, AwsTts, listPollyVoices, type AwsCreds } from './aws';\nimport { VoskStt, listVoskModels } from './vosk';\nimport { PiperTts, listPiperVoices } from './piper';\nimport * as path from 'node:path';\n\nimport { CachedTts } from './ttsCache';\nimport { FallbackStt, FallbackTts, type NamedEngine } from './fallback';\nimport { isoToLocale } from './lang';\nimport type { VoiceLogger } from './download';\n\nexport type SpeechProvider = 'openai' | 'azure' | 'aws' | 'vosk' | 'piper';\n\n/** All speech credentials, resolved from config (or the central credential store). */\nexport interface VoiceCredentials {\n openaiKey: string;\n azureKey: string;\n azureRegion: string;\n aws: AwsCreds;\n}\n\n/** Provider-specific voice ids (each provider names voices differently). */\nexport interface VoiceNames {\n openai: string; // alloy/echo/…\n azure: string; // e.g. de-DE-KatjaNeural\n aws: string; // e.g. Vicki\n piper: string; // e.g. de_DE-thorsten-medium\n}\n\n/** Everything the factory needs to build any engine. */\nexport interface EngineContext {\n creds: VoiceCredentials;\n voices: VoiceNames;\n /** Optional second engine, used when the primary one fails ('' = none). */\n sttFallback?: SpeechProvider | '';\n ttsFallback?: SpeechProvider | '';\n /** Writable instance data dir (for the local engines' downloads). */\n dataDir: string;\n log: VoiceLogger;\n /** Local model overrides ('' → default per language). */\n voskModel: string;\n /** OpenAI STT model ('' → 'whisper-1'; e.g. 'gpt-4o-transcribe'). */\n sttModel: string;\n /** OpenAI TTS model ('' → 'tts-1'; e.g. 'gpt-4o-mini-tts'). */\n ttsModel: string;\n}\n\nfunction requireAzure(creds: VoiceCredentials): void {\n if (!creds.azureKey || !creds.azureRegion) {\n throw new Error('Azure speech needs a subscription key and region');\n }\n}\n\nfunction requireAws(creds: VoiceCredentials): void {\n if (!creds.aws.accessKeyId || !creds.aws.secretAccessKey || !creds.aws.region) {\n throw new Error('AWS speech needs an access key id, secret access key and region');\n }\n}\n\nfunction requireOpenAi(creds: VoiceCredentials): void {\n if (!creds.openaiKey) {\n throw new Error('OpenAI speech needs an API key');\n }\n}\n\nexport function createSttEngine(provider: SpeechProvider, ctx: EngineContext): SttEngine {\n const primary: NamedEngine<SttEngine> = { name: provider, engine: buildSttEngine(provider, ctx) };\n const fallback = ctx.sttFallback && ctx.sttFallback !== provider ? ctx.sttFallback : '';\n if (!fallback) {\n return primary.engine;\n }\n try {\n return new FallbackStt([primary, { name: fallback, engine: buildSttEngine(fallback, ctx) }], ctx.log);\n } catch (e) {\n ctx.log.warn(`Speech-to-text fallback '${fallback}' unavailable: ${(e as Error).message}`);\n return primary.engine;\n }\n}\n\nfunction buildSttEngine(provider: SpeechProvider, ctx: EngineContext): SttEngine {\n switch (provider) {\n case 'azure':\n requireAzure(ctx.creds);\n return new AzureStt(ctx.creds.azureKey, ctx.creds.azureRegion);\n case 'aws':\n requireAws(ctx.creds);\n return new AwsStt(ctx.creds.aws);\n case 'vosk':\n return new VoskStt(ctx.dataDir, ctx.voskModel, ctx.log);\n case 'piper':\n throw new Error('Piper is a text-to-speech engine, not speech-to-text');\n default:\n requireOpenAi(ctx.creds);\n return new OpenAiStt(ctx.creds.openaiKey, ctx.sttModel || undefined);\n }\n}\n\nexport function createTtsEngine(provider: SpeechProvider, ctx: EngineContext): TtsEngine {\n // Each engine gets the shared behaviour (disk cache, length limit, SSML) and its own cache directory,\n // so a fallback engine's voice can never be served later while the primary one is healthy again.\n const primary: NamedEngine<TtsEngine> = { name: provider, engine: cachedTts(provider, ctx) };\n const fallback = ctx.ttsFallback && ctx.ttsFallback !== provider ? ctx.ttsFallback : '';\n if (!fallback) {\n return primary.engine;\n }\n try {\n return new FallbackTts([primary, { name: fallback, engine: cachedTts(fallback, ctx) }], ctx.log);\n } catch (e) {\n // A fallback that cannot even be built (missing key, wrong provider) must not take the main one down.\n ctx.log.warn(`Text-to-speech fallback '${fallback}' unavailable: ${(e as Error).message}`);\n return primary.engine;\n }\n}\n\n/**\n * One provider binding plus the shared cache/length/SSML layer. One cache directory per provider+voice —\n * a voice change must not serve audio in the old voice.\n */\nfunction cachedTts(provider: SpeechProvider, ctx: EngineContext): TtsEngine {\n const voice =\n provider === 'azure'\n ? ctx.voices.azure\n : provider === 'aws'\n ? ctx.voices.aws\n : provider === 'piper'\n ? ctx.voices.piper\n : ctx.voices.openai;\n const dir = path.join(ctx.dataDir, 'ttscache', `${provider}-${(voice || 'default').replace(/[^\\w.-]/g, '_')}`);\n return new CachedTts(buildTtsEngine(provider, ctx), { dir, log: ctx.log });\n}\n\nfunction buildTtsEngine(provider: SpeechProvider, ctx: EngineContext): TtsEngine {\n switch (provider) {\n case 'azure':\n requireAzure(ctx.creds);\n return new AzureTts(ctx.creds.azureKey, ctx.creds.azureRegion, ctx.voices.azure);\n case 'aws':\n requireAws(ctx.creds);\n return new AwsTts(ctx.creds.aws, ctx.voices.aws);\n case 'piper':\n return new PiperTts(ctx.dataDir, ctx.voices.piper, ctx.log);\n case 'vosk':\n throw new Error('Vosk is a speech-to-text engine, not text-to-speech');\n default:\n requireOpenAi(ctx.creds);\n return new OpenAiTts(\n ctx.creds.openaiKey,\n (ctx.voices.openai || 'alloy') as OpenAiVoice,\n ctx.ttsModel || undefined,\n );\n }\n}\n\n/** OpenAI TTS voices are a fixed set (no list API). */\nconst OPENAI_VOICES = ['alloy', 'echo', 'fable', 'onyx', 'nova', 'shimmer'];\n\n/** List the available TTS voices for a provider (for the settings voice dropdown). */\nexport async function listVoices(provider: SpeechProvider, ctx: EngineContext, language: string): Promise<string[]> {\n switch (provider) {\n case 'azure':\n requireAzure(ctx.creds);\n return listAzureVoices(ctx.creds.azureKey, ctx.creds.azureRegion, isoToLocale(language));\n case 'aws':\n requireAws(ctx.creds);\n return listPollyVoices(ctx.creds.aws, isoToLocale(language));\n case 'piper':\n return listPiperVoices();\n default:\n return OPENAI_VOICES;\n }\n}\n\n/** Suggested STT model names for the settings dropdown. Only Vosk has a local model catalogue. */\nexport function listSttModels(provider: SpeechProvider, language: string): string[] {\n return provider === 'vosk' ? listVoskModels(language) : [];\n}\n"]}
|