Skip to content

Commit 7418080

Browse files
committed
language fix
1 parent 068ae5a commit 7418080

File tree

2 files changed

+116
-30
lines changed

2 files changed

+116
-30
lines changed

agents/src/voice/transcription/transforms.test.ts

Lines changed: 45 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { describe, expect, it } from 'vitest';
66
import {
77
DEFAULT_TTS_TEXT_TRANSFORMS,
88
applyTextTransforms,
9+
getAllAvailableTransforms,
910
getAvailableTransforms,
1011
} from './transforms.js';
1112

@@ -57,11 +58,24 @@ describe('Text Transforms Core', () => {
5758
expect(transforms.has('format_euro_amounts')).toBe(true);
5859
});
5960

61+
it('should list all available transforms across all languages', () => {
62+
const transforms = getAllAvailableTransforms();
63+
// Language-agnostic transforms
64+
expect(transforms.has('filter_markdown')).toBe(true);
65+
expect(transforms.has('filter_emoji')).toBe(true);
66+
// English transforms
67+
expect(transforms.has('format_numbers')).toBe(true);
68+
expect(transforms.has('format_dollar_amounts')).toBe(true);
69+
// German transforms
70+
expect(transforms.has('format_numbers_de')).toBe(true);
71+
expect(transforms.has('format_euro_amounts')).toBe(true);
72+
});
73+
6074
it('should throw error for invalid transform name', async () => {
6175
const stream = stringToStream('test');
62-
await expect(
63-
applyTextTransforms(stream, ['invalid_transform' as any], { language: 'en' }),
64-
).rejects.toThrow('Invalid transform');
76+
await expect(applyTextTransforms(stream, ['invalid_transform' as any])).rejects.toThrow(
77+
'Invalid transform',
78+
);
6579
});
6680

6781
it('should apply custom transform function', async () => {
@@ -89,15 +103,38 @@ describe('Text Transforms Core', () => {
89103

90104
it('should apply multiple transforms in sequence', async () => {
91105
const stream = stringToStream('**Price: $5** 🎉');
92-
const result = await applyTextTransforms(
93-
stream,
94-
['filter_markdown', 'filter_emoji', 'format_dollar_amounts'],
95-
{ language: 'en' },
96-
);
106+
const result = await applyTextTransforms(stream, [
107+
'filter_markdown',
108+
'filter_emoji',
109+
'format_dollar_amounts',
110+
]);
97111
const output = await streamToString(result);
98112
expect(output).toContain('Price:');
99113
expect(output).toContain('five dollars');
100114
expect(output).not.toContain('**');
101115
expect(output).not.toContain('🎉');
102116
});
117+
118+
it('should find transforms across all languages without specifying language', async () => {
119+
// Test that English transform can be found without language config
120+
const stream1 = stringToStream('$5');
121+
const result1 = await applyTextTransforms(stream1, ['format_dollar_amounts']);
122+
const output1 = await streamToString(result1);
123+
expect(output1).toBe('five dollars');
124+
125+
// Test that German transform can be found without language config
126+
const stream2 = stringToStream('5€');
127+
const result2 = await applyTextTransforms(stream2, ['format_euro_amounts']);
128+
const output2 = await streamToString(result2);
129+
expect(output2).toBe('fünf Euro');
130+
131+
// Test that mixed language transforms can be used together
132+
const stream3 = stringToStream('$5 and 5€');
133+
const result3 = await applyTextTransforms(stream3, [
134+
'format_dollar_amounts',
135+
'format_euro_amounts',
136+
]);
137+
const output3 = await streamToString(result3);
138+
expect(output3).toBe('five dollars and fünf Euro');
139+
});
103140
});

agents/src/voice/transcription/transforms.ts

Lines changed: 71 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,6 @@ export type Language = 'en' | 'de' | string;
1717
*/
1818
export type TextTransform = (text: ReadableStream<string>) => ReadableStream<string>;
1919

20-
/**
21-
* Configuration for language-specific transforms
22-
*/
23-
export interface LanguageTransformConfig {
24-
/**
25-
* The language code for language-specific transforms
26-
* Defaults to 'en' (English)
27-
*/
28-
language?: Language;
29-
}
30-
3120
/**
3221
* Built-in language-agnostic transform names
3322
*/
@@ -135,30 +124,49 @@ export function getRecommendedTTSTransforms(language: Language = 'en'): BuiltInT
135124
/**
136125
* Apply a sequence of text transforms to a text stream
137126
*
127+
* Transforms can be specified either as built-in transform names (strings)
128+
* or as custom transform functions. Built-in transforms are looked up across
129+
* all registered transforms (language-agnostic and all language-specific).
130+
*
138131
* @param text - Input text stream
139132
* @param transforms - Array of transform names or custom transform functions
140-
* @param config - Configuration for language-specific transforms
141133
* @returns Transformed text stream
134+
*
135+
* @example
136+
* ```typescript
137+
* // Use built-in transforms (names)
138+
* const text = new ReadableStream(...);
139+
* const transformed = await applyTextTransforms(text, [
140+
* 'filter_markdown',
141+
* 'format_numbers', // English
142+
* 'format_euro_amounts', // German
143+
* ]);
144+
*
145+
* // Mix built-in and custom transforms
146+
* const customTransform: TextTransform = (stream) => ...;
147+
* const transformed = await applyTextTransforms(text, [
148+
* 'filter_markdown',
149+
* customTransform,
150+
* ]);
151+
* ```
142152
*/
143153
export async function applyTextTransforms(
144154
text: ReadableStream<string>,
145155
transforms: readonly TextTransformSpec[],
146-
config: LanguageTransformConfig = {},
147156
): Promise<ReadableStream<string>> {
148-
const { language = 'en' } = config;
149157
let result = text;
150158

151159
for (const transform of transforms) {
152160
if (typeof transform === 'function') {
153161
// Custom transform function
154162
result = transform(result);
155163
} else {
156-
// Built-in transform name
157-
const transformFn = getBuiltInTransform(transform, language);
164+
// Built-in transform name - search across all registries
165+
const transformFn = getBuiltInTransform(transform);
158166
if (!transformFn) {
159167
throw new Error(
160168
`Invalid transform: ${transform}. ` +
161-
`Available transforms: ${Array.from(getAvailableTransforms(language)).join(', ')}`,
169+
`Available transforms: ${Array.from(getAllAvailableTransforms()).join(', ')}`,
162170
);
163171
}
164172
result = transformFn(result);
@@ -170,25 +178,66 @@ export async function applyTextTransforms(
170178

171179
/**
172180
* Get a built-in transform function by name
181+
*
182+
* Searches across all registered transforms:
183+
* 1. First checks language-agnostic transforms
184+
* 2. Then searches through all language-specific transform registries
185+
*
186+
* @param name - The built-in transform name
187+
* @returns The transform function, or null if not found
173188
*/
174-
function getBuiltInTransform(name: BuiltInTransformName, language: Language): TextTransform | null {
189+
function getBuiltInTransform(name: BuiltInTransformName): TextTransform | null {
175190
// Check language-agnostic transforms first
176191
const agnostic = languageAgnosticTransforms.get(name as LanguageAgnosticTransformName);
177192
if (agnostic) {
178193
return agnostic;
179194
}
180195

181-
// Check language-specific transforms
182-
const langTransforms = languageSpecificTransforms.get(language);
183-
if (langTransforms) {
184-
return langTransforms.get(name) || null;
196+
// Check all language-specific transform registries
197+
for (const langTransforms of languageSpecificTransforms.values()) {
198+
const transform = langTransforms.get(name);
199+
if (transform) {
200+
return transform;
201+
}
185202
}
186203

187204
return null;
188205
}
189206

207+
/**
208+
* Get all available transform names across all languages
209+
*
210+
* Returns a set containing all registered transform names, including
211+
* language-agnostic and all language-specific transforms.
212+
*
213+
* @returns Set of all available transform names
214+
*/
215+
export function getAllAvailableTransforms(): Set<string> {
216+
const available = new Set<string>();
217+
218+
// Add language-agnostic transforms
219+
for (const name of languageAgnosticTransforms.keys()) {
220+
available.add(name);
221+
}
222+
223+
// Add all language-specific transforms
224+
for (const langTransforms of languageSpecificTransforms.values()) {
225+
for (const name of langTransforms.keys()) {
226+
available.add(name);
227+
}
228+
}
229+
230+
return available;
231+
}
232+
190233
/**
191234
* Get all available transform names for a given language
235+
*
236+
* Returns a set containing language-agnostic transforms plus transforms
237+
* specific to the requested language.
238+
*
239+
* @param language - The language code (e.g., 'en', 'de')
240+
* @returns Set of available transform names for the language
192241
*/
193242
export function getAvailableTransforms(language: Language = 'en'): Set<string> {
194243
const available = new Set<string>();

0 commit comments

Comments
 (0)