mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-07-31 19:16:29 +00:00
feat(voice): route wake phrases to their profile — "hey <profile>" wakes that profile
One sherpa listener now enrolls every wake-enabled profile's phrase (defaulting to "hey <profile name>") and reports WHICH phrase fired. wake.detected gains a profile field; the desktop live-switches to the matching profile (same path as the profile rail), opens a fresh session there, and starts hands-free voice. The single-profile CLI/TUI print the hermes -p switch command for foreign-profile phrases instead of answering as the wrong profile. Opt out per listener with wake_word.profile_routing: false.
This commit is contained in:
parent
567f47f01f
commit
2a35c8f0b8
10 changed files with 274 additions and 16 deletions
|
|
@ -34,7 +34,7 @@ import { requestVoiceConversationStart } from '@/store/composer'
|
|||
import { setCronFocusJobId } from '@/store/cron'
|
||||
import { $pinnedSessionIds, pinSession, restoreWorktree, unpinSession } from '@/store/layout'
|
||||
import { $previewTarget } from '@/store/preview'
|
||||
import { $activeGatewayProfile, $freshSessionRequest, $profileScope, refreshActiveProfile } from '@/store/profile'
|
||||
import { $activeGatewayProfile, $freshSessionRequest, $profileScope, ensureGatewayProfile, newSessionInProfile, normalizeProfileKey, refreshActiveProfile } from '@/store/profile'
|
||||
import { $startWorkSessionRequest, followActiveSessionCwd } from '@/store/projects'
|
||||
import {
|
||||
$activeSessionId,
|
||||
|
|
@ -666,9 +666,24 @@ export function ContribWiring({ children }: { children: ReactNode }) {
|
|||
emitGatewayEvent(event)
|
||||
|
||||
if (event.type === 'wake.detected') {
|
||||
const payload = event.payload as { start_new_session?: boolean } | undefined
|
||||
const payload = event.payload as
|
||||
| { profile?: null | string; start_new_session?: boolean }
|
||||
| undefined
|
||||
|
||||
if (payload?.start_new_session !== false) {
|
||||
// Multi-profile routing: a wake phrase enrolled by another profile
|
||||
// re-homes the gateway to that profile first (live swap — same path
|
||||
// as clicking it in the profile rail), then opens the fresh session
|
||||
// and starts voice there.
|
||||
const targetProfile = payload?.profile?.trim()
|
||||
const activeProfile = normalizeProfileKey($activeGatewayProfile.get())
|
||||
|
||||
if (targetProfile && normalizeProfileKey(targetProfile) !== activeProfile) {
|
||||
if (payload?.start_new_session !== false) {
|
||||
newSessionInProfile(targetProfile)
|
||||
} else {
|
||||
void ensureGatewayProfile(normalizeProfileKey(targetProfile))
|
||||
}
|
||||
} else if (payload?.start_new_session !== false) {
|
||||
startFreshSessionDraft()
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue