@voicethere/agent 0.9.1 → 0.9.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/dist/templates/language-switch/agent.js +20 -3
- package/dist/templates/registry.d.ts.map +1 -1
- package/dist/templates/registry.js +5 -2
- package/dist/templates/registry.js.map +1 -1
- package/package.json +1 -1
- package/templates/README.md +1 -1
- package/templates/language-switch/README.md +2 -2
- package/templates/language-switch/agent.ts +34 -6
|
@@ -941,6 +941,17 @@ function parseChatText(message) {
|
|
|
941
941
|
// templates/language-switch/agent.ts
|
|
942
942
|
var ECHO_PREFIX = "you said:";
|
|
943
943
|
var ECHO_WAIT_MS = 4e3;
|
|
944
|
+
var ECHO_PREFIXES = {
|
|
945
|
+
en: "you said:",
|
|
946
|
+
de: "Du hast gesagt:",
|
|
947
|
+
es: "Dijiste:",
|
|
948
|
+
fr: "Tu as dit :",
|
|
949
|
+
it: "Hai detto:",
|
|
950
|
+
pt: "Voc\xEA disse:",
|
|
951
|
+
nl: "Je zei:",
|
|
952
|
+
pl: "Powiedzia\u0142e\u015B:",
|
|
953
|
+
ru: "\u0412\u044B \u0441\u043A\u0430\u0437\u0430\u043B\u0438:"
|
|
954
|
+
};
|
|
944
955
|
var REPLIES = {
|
|
945
956
|
de: "Guten Tag. Ich antworte jetzt auf Deutsch.",
|
|
946
957
|
es: "Hola. Ahora respondo en espa\xF1ol.",
|
|
@@ -967,6 +978,9 @@ function stateFor(sessionId, env) {
|
|
|
967
978
|
function replyFor(language) {
|
|
968
979
|
return REPLIES[language] ?? `Continuing in ${language}.`;
|
|
969
980
|
}
|
|
981
|
+
function echoPrefixFor(language) {
|
|
982
|
+
return ECHO_PREFIXES[language] ?? ECHO_PREFIXES.en;
|
|
983
|
+
}
|
|
970
984
|
function logSwitch(sessionId, side, result) {
|
|
971
985
|
if (!result.ok) {
|
|
972
986
|
agentLog(
|
|
@@ -1008,16 +1022,15 @@ defineAgent({
|
|
|
1008
1022
|
async onUserLanguage({ sessionId, language }) {
|
|
1009
1023
|
const state = stateFor(sessionId);
|
|
1010
1024
|
if (!language || language === state.language) return;
|
|
1011
|
-
prepareLanguageTransition(state);
|
|
1012
1025
|
if (state.runnerAutoSwitch) {
|
|
1013
1026
|
agentLog(
|
|
1014
1027
|
"info",
|
|
1015
|
-
`LID detected ${language}; runner auto-switch applies STT/TTS \u2014 agent
|
|
1028
|
+
`LID detected ${language}; runner auto-switch applies STT/TTS \u2014 agent only remembers the language`
|
|
1016
1029
|
);
|
|
1017
1030
|
state.language = language;
|
|
1018
|
-
speak(sessionId, replyFor(language));
|
|
1019
1031
|
return;
|
|
1020
1032
|
}
|
|
1033
|
+
prepareLanguageTransition(state);
|
|
1021
1034
|
const tts = await setVoiceLanguage(sessionId, {
|
|
1022
1035
|
scope: "tts",
|
|
1023
1036
|
language,
|
|
@@ -1094,6 +1107,10 @@ defineAgent({
|
|
|
1094
1107
|
},
|
|
1095
1108
|
onUserSpeechFinal({ sessionId, text }) {
|
|
1096
1109
|
const state = stateFor(sessionId);
|
|
1110
|
+
if (state.runnerAutoSwitch) {
|
|
1111
|
+
speak(sessionId, `${echoPrefixFor(state.language)} ${text}`.trim());
|
|
1112
|
+
return;
|
|
1113
|
+
}
|
|
1097
1114
|
if (state.suppressNextFinal) {
|
|
1098
1115
|
state.suppressNextFinal = false;
|
|
1099
1116
|
return;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/templates/registry.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,KAAK,CAAC;AAE7C,MAAM,WAAW,uBAAuB;IACtC,EAAE,EAAE,MAAM,CAAC;IACX,mFAAmF;IACnF,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,YAAY,CAAC;IACnB,mFAAmF;IACnF,YAAY,EAAE,OAAO,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,yEAAyE;IACzE,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,oFAAoF;IACpF,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC1C;AAED,eAAO,MAAM,eAAe,EAAE,SAAS,uBAAuB,
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/templates/registry.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,KAAK,CAAC;AAE7C,MAAM,WAAW,uBAAuB;IACtC,EAAE,EAAE,MAAM,CAAC;IACX,mFAAmF;IACnF,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,YAAY,CAAC;IACnB,mFAAmF;IACnF,YAAY,EAAE,OAAO,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,yEAAyE;IACzE,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,oFAAoF;IACpF,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC1C;AAED,eAAO,MAAM,eAAe,EAAE,SAAS,uBAAuB,EAiMpD,CAAC;AAEX,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC;AAMrE,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,MAAM,GAAG,EAAE,IAAI,eAAe,CAEnE;AAED,wBAAgB,eAAe,CAAC,EAAE,EAAE,MAAM,GAAG,uBAAuB,CAMnE;AAED,wBAAgB,yBAAyB,IAAI,uBAAuB,EAAE,CAErE"}
|
|
@@ -20,7 +20,7 @@ export const AGENT_TEMPLATES = [
|
|
|
20
20
|
entry: "language-switch/agent.ts",
|
|
21
21
|
kind: "product",
|
|
22
22
|
seedOnCreate: true,
|
|
23
|
-
description: "Switches STT and TTS independently from onUserLanguage, and can change one vendor mid-conversation.
|
|
23
|
+
description: "Switches STT and TTS independently from onUserLanguage, and can change one vendor mid-conversation. With project auto-switch on, the runner switches and replays the utterance, and the agent answers the recognized text in the new language. With auto-switch off, detection does not change either side until this agent calls setVoiceLanguage.",
|
|
24
24
|
sourceFiles: ["language-switch/agent.ts"],
|
|
25
25
|
},
|
|
26
26
|
{
|
|
@@ -45,7 +45,10 @@ export const AGENT_TEMPLATES = [
|
|
|
45
45
|
kind: "product",
|
|
46
46
|
seedOnCreate: true,
|
|
47
47
|
description: "Single-agent binary world sync — onDataChannelBinary + sendBinaryToClient ArrayBuffer poses, no Redis.",
|
|
48
|
-
sourceFiles: [
|
|
48
|
+
sourceFiles: [
|
|
49
|
+
"world-sync-binary/agent.ts",
|
|
50
|
+
"world-sync-binary/protocol.ts",
|
|
51
|
+
],
|
|
49
52
|
},
|
|
50
53
|
{
|
|
51
54
|
id: "game-sync",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/templates/registry.ts"],"names":[],"mappings":"AAgBA,MAAM,CAAC,MAAM,eAAe,GAAuC;IACjE;QACE,EAAE,EAAE,MAAM;QACV,KAAK,EAAE,eAAe;QACtB,IAAI,EAAE,SAAS;QACf,YAAY,EAAE,IAAI;QAClB,WAAW,EACT,8EAA8E;QAChF,WAAW,EAAE,CAAC,eAAe,CAAC;KAC/B;IACD;QACE,EAAE,EAAE,SAAS;QACb,KAAK,EAAE,kBAAkB;QACzB,IAAI,EAAE,SAAS;QACf,YAAY,EAAE,IAAI;QAClB,WAAW,EACT,qEAAqE;QACvE,WAAW,EAAE,CAAC,kBAAkB,CAAC;KAClC;IACD;QACE,EAAE,EAAE,iBAAiB;QACrB,KAAK,EAAE,0BAA0B;QACjC,IAAI,EAAE,SAAS;QACf,YAAY,EAAE,IAAI;QAClB,WAAW,EACT,
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/templates/registry.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/templates/README.md
CHANGED
|
@@ -64,7 +64,7 @@ Each folder has its own README. Summary:
|
|
|
64
64
|
| `echo` | `echo/` | Voice + chat echo |
|
|
65
65
|
| `echo-dc` | `echo-dc/` | Data-channel echo, no TTS |
|
|
66
66
|
| `voice-starter` | `voice-starter/` | Every speech event |
|
|
67
|
-
| `language-switch` | `language-switch/` | Manual `setVoiceLanguage
|
|
67
|
+
| `language-switch` | `language-switch/` | Manual `setVoiceLanguage`, or runner auto-switch with a localized echo of the recognized text |
|
|
68
68
|
| `world-sync` | `world-sync/` | JSON pose broadcast |
|
|
69
69
|
| `world-sync-binary` | `world-sync-binary/` | Binary pose `ArrayBuffer` |
|
|
70
70
|
| `game-sync` | `game-sync/` | Authoritative sim, Redis + binary snapshots |
|
|
@@ -13,7 +13,7 @@ A Sherpa language with no STT id (`it`, `pt`, `nl`, `pl`, `hi`) fails the STT ca
|
|
|
13
13
|
|
|
14
14
|
## Mode B — Runner auto-switch
|
|
15
15
|
|
|
16
|
-
Enable auto-switch in the project voice settings (runner applies STT/TTS when LID detects a new language). When `session_start.env` includes a truthy `SHERPA_LID_AUTO_SWITCH`, this template **does not** call `setVoiceLanguage
|
|
16
|
+
Enable auto-switch in the project voice settings (runner applies STT/TTS when LID detects a new language). When `session_start.env` includes a truthy `SHERPA_LID_AUTO_SWITCH`, this template **does not** call `setVoiceLanguage`. The runner replays the utterance into the new language's STT, so the next final is the recognized text in the new language. The agent remembers the language from `onUserLanguage` / `onVoiceLanguageChanged` and answers each final right away with a short localized prefix, for example `you said: …` in English and `Du hast gesagt: …` in German. Use `onVoiceLanguageChanged` when you need the committed language after the runner applies the change.
|
|
17
17
|
|
|
18
18
|
Detection and chat commands are unchanged: `/tts` and `/stt` still call `setVoiceLanguage` for one vendor at a time.
|
|
19
19
|
|
|
@@ -24,7 +24,7 @@ Chat commands change one vendor while the session stays connected. API keys are
|
|
|
24
24
|
- `/tts elevenlabs` — ElevenLabs TTS, current STT stays
|
|
25
25
|
- `/stt deepgram de` — Deepgram STT, current voice stays
|
|
26
26
|
|
|
27
|
-
English finals are echoed as `you said: …` after a short wait, so a language event for the same utterance can cancel the echo. The revealing utterance is not spoken back as an English transcript.
|
|
27
|
+
In manual mode, English finals are echoed as `you said: …` after a short wait, so a language event for the same utterance can cancel the echo. The revealing utterance is not spoken back as an English transcript.
|
|
28
28
|
|
|
29
29
|
`voice` and `stt` are Sherpa catalog ids (`de`, `en-lessac`, `en-small`), listed in the spoken-language docs. Vendor ids are `local-sherpa`, `openai`, `deepgram`, `assemblyai`, `google`, `elevenlabs`, and `cartesia`.
|
|
30
30
|
|
|
@@ -5,8 +5,11 @@
|
|
|
5
5
|
*
|
|
6
6
|
* (A) Project auto-switch off — this agent calls `setVoiceLanguage` from
|
|
7
7
|
* `onUserLanguage` when LID detects a new language.
|
|
8
|
-
* (B) Project enables runner auto-switch — STT/TTS are runner-owned
|
|
9
|
-
*
|
|
8
|
+
* (B) Project enables runner auto-switch — STT/TTS are runner-owned. The
|
|
9
|
+
* runner replays the utterance into the new language's STT, so the next
|
|
10
|
+
* final is the correctly recognized text. The agent never calls
|
|
11
|
+
* `setVoiceLanguage`; it remembers the language and answers each final
|
|
12
|
+
* right away with a short localized prefix ("Du hast gesagt: …").
|
|
10
13
|
*
|
|
11
14
|
* Chat commands change a single vendor mid-conversation:
|
|
12
15
|
*
|
|
@@ -31,6 +34,19 @@ import {
|
|
|
31
34
|
const ECHO_PREFIX = "you said:";
|
|
32
35
|
const ECHO_WAIT_MS = 4000;
|
|
33
36
|
|
|
37
|
+
/** Echo prefix per language for runner auto-switch mode. */
|
|
38
|
+
const ECHO_PREFIXES: Record<string, string> = {
|
|
39
|
+
en: "you said:",
|
|
40
|
+
de: "Du hast gesagt:",
|
|
41
|
+
es: "Dijiste:",
|
|
42
|
+
fr: "Tu as dit :",
|
|
43
|
+
it: "Hai detto:",
|
|
44
|
+
pt: "Você disse:",
|
|
45
|
+
nl: "Je zei:",
|
|
46
|
+
pl: "Powiedziałeś:",
|
|
47
|
+
ru: "Вы сказали:",
|
|
48
|
+
};
|
|
49
|
+
|
|
34
50
|
const REPLIES: Record<string, string> = {
|
|
35
51
|
de: "Guten Tag. Ich antworte jetzt auf Deutsch.",
|
|
36
52
|
es: "Hola. Ahora respondo en español.",
|
|
@@ -71,6 +87,10 @@ function replyFor(language: string): string {
|
|
|
71
87
|
return REPLIES[language] ?? `Continuing in ${language}.`;
|
|
72
88
|
}
|
|
73
89
|
|
|
90
|
+
function echoPrefixFor(language: string): string {
|
|
91
|
+
return ECHO_PREFIXES[language] ?? ECHO_PREFIXES.en!;
|
|
92
|
+
}
|
|
93
|
+
|
|
74
94
|
function logSwitch(
|
|
75
95
|
sessionId: string,
|
|
76
96
|
side: string,
|
|
@@ -120,18 +140,20 @@ defineAgent({
|
|
|
120
140
|
const state = stateFor(sessionId);
|
|
121
141
|
if (!language || language === state.language) return;
|
|
122
142
|
|
|
123
|
-
prepareLanguageTransition(state);
|
|
124
|
-
|
|
125
143
|
if (state.runnerAutoSwitch) {
|
|
144
|
+
// The runner switches STT/TTS and replays the utterance into the new
|
|
145
|
+
// STT; the next final is the real utterance, so nothing is suppressed
|
|
146
|
+
// and no fixed sentence is spoken.
|
|
126
147
|
agentLog(
|
|
127
148
|
"info",
|
|
128
|
-
`LID detected ${language}; runner auto-switch applies STT/TTS — agent
|
|
149
|
+
`LID detected ${language}; runner auto-switch applies STT/TTS — agent only remembers the language`,
|
|
129
150
|
);
|
|
130
151
|
state.language = language;
|
|
131
|
-
speak(sessionId, replyFor(language));
|
|
132
152
|
return;
|
|
133
153
|
}
|
|
134
154
|
|
|
155
|
+
prepareLanguageTransition(state);
|
|
156
|
+
|
|
135
157
|
const tts = await setVoiceLanguage(sessionId, {
|
|
136
158
|
scope: "tts",
|
|
137
159
|
language,
|
|
@@ -214,6 +236,12 @@ defineAgent({
|
|
|
214
236
|
|
|
215
237
|
onUserSpeechFinal({ sessionId, text }) {
|
|
216
238
|
const state = stateFor(sessionId);
|
|
239
|
+
if (state.runnerAutoSwitch) {
|
|
240
|
+
// Reply immediately: the runner already holds the final until LID has
|
|
241
|
+
// decided, so no extra wait is needed to avoid a wrong-language echo.
|
|
242
|
+
speak(sessionId, `${echoPrefixFor(state.language)} ${text}`.trim());
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
217
245
|
if (state.suppressNextFinal) {
|
|
218
246
|
state.suppressNextFinal = false;
|
|
219
247
|
return;
|