@hyperdrive.bot/paseo-protocol 0.3.45 → 0.3.47
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/agent-filter.d.ts +248 -0
- package/dist/agent-filter.js +340 -0
- package/dist/agent-types.d.ts +17 -0
- package/dist/language.d.ts +82 -0
- package/dist/language.js +148 -0
- package/dist/messages.d.ts +127 -117
- package/dist/messages.js +24 -1
- package/dist/validation/ws-outbound-schema-metadata.d.ts +24 -24
- package/package.json +1 -1
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/** BCP-47 tag used when nothing else is known. */
|
|
2
|
+
export declare const DEFAULT_LANGUAGE_TAG = "en-US";
|
|
3
|
+
/**
|
|
4
|
+
* Curated language list offered in the audio-mode pickers.
|
|
5
|
+
*
|
|
6
|
+
* Covers the app's own eight shipped UI locales plus the widely-requested
|
|
7
|
+
* European speech languages. It is intentionally a curated list rather than
|
|
8
|
+
* "everything a provider supports": STT coverage is provider-dependent (the
|
|
9
|
+
* default local Parakeet v2 model is English-only; OpenAI Whisper is not), so a
|
|
10
|
+
* longer list would promise accuracy paseo cannot deliver on the default stack.
|
|
11
|
+
*/
|
|
12
|
+
export declare const AUDIO_LANGUAGES: readonly [{
|
|
13
|
+
readonly tag: "en-US";
|
|
14
|
+
readonly label: "English";
|
|
15
|
+
readonly nativeLabel: "English";
|
|
16
|
+
}, {
|
|
17
|
+
readonly tag: "pt-BR";
|
|
18
|
+
readonly label: "Portuguese (Brazil)";
|
|
19
|
+
readonly nativeLabel: "Português (Brasil)";
|
|
20
|
+
}, {
|
|
21
|
+
readonly tag: "es-ES";
|
|
22
|
+
readonly label: "Spanish";
|
|
23
|
+
readonly nativeLabel: "Español";
|
|
24
|
+
}, {
|
|
25
|
+
readonly tag: "fr-FR";
|
|
26
|
+
readonly label: "French";
|
|
27
|
+
readonly nativeLabel: "Français";
|
|
28
|
+
}, {
|
|
29
|
+
readonly tag: "de-DE";
|
|
30
|
+
readonly label: "German";
|
|
31
|
+
readonly nativeLabel: "Deutsch";
|
|
32
|
+
}, {
|
|
33
|
+
readonly tag: "it-IT";
|
|
34
|
+
readonly label: "Italian";
|
|
35
|
+
readonly nativeLabel: "Italiano";
|
|
36
|
+
}, {
|
|
37
|
+
readonly tag: "ja-JP";
|
|
38
|
+
readonly label: "Japanese";
|
|
39
|
+
readonly nativeLabel: "日本語";
|
|
40
|
+
}, {
|
|
41
|
+
readonly tag: "zh-CN";
|
|
42
|
+
readonly label: "Chinese (Simplified)";
|
|
43
|
+
readonly nativeLabel: "简体中文";
|
|
44
|
+
}, {
|
|
45
|
+
readonly tag: "ru-RU";
|
|
46
|
+
readonly label: "Russian";
|
|
47
|
+
readonly nativeLabel: "Русский";
|
|
48
|
+
}, {
|
|
49
|
+
readonly tag: "ar-SA";
|
|
50
|
+
readonly label: "Arabic";
|
|
51
|
+
readonly nativeLabel: "العربية";
|
|
52
|
+
}];
|
|
53
|
+
export type AudioLanguageTag = (typeof AUDIO_LANGUAGES)[number]["tag"];
|
|
54
|
+
/**
|
|
55
|
+
* Normalize any user- or config-supplied tag to canonical BCP-47 casing
|
|
56
|
+
* ("PT-br" -> "pt-BR"). Returns undefined for empty/unusable input rather than
|
|
57
|
+
* inventing a default, so callers decide their own fallback.
|
|
58
|
+
*/
|
|
59
|
+
export declare function normalizeLanguageTag(value: string | null | undefined): string | undefined;
|
|
60
|
+
/**
|
|
61
|
+
* BCP-47 -> ISO-639-1, the form the speech daemon and OpenAI Whisper expect
|
|
62
|
+
* ("pt-BR" -> "pt"). This is the ONLY place the conversion happens.
|
|
63
|
+
*/
|
|
64
|
+
export declare function toIso639(value: string | null | undefined): string | undefined;
|
|
65
|
+
/**
|
|
66
|
+
* True when the tag resolves to a language paseo can NAME in English.
|
|
67
|
+
*
|
|
68
|
+
* `normalizeLanguageTag` only checks shape, and a 2-3 letter shape is cheap to
|
|
69
|
+
* hit by accident: "not-a-language" normalizes to the syntactically valid
|
|
70
|
+
* subtag "not". Callers that put the name into a prompt must gate on this, so
|
|
71
|
+
* a typo produces NO instruction rather than a confident instruction to write
|
|
72
|
+
* everything in "not".
|
|
73
|
+
*/
|
|
74
|
+
export declare function isKnownLanguage(value: string | null | undefined): boolean;
|
|
75
|
+
/**
|
|
76
|
+
* Human-readable English name for a language tag, for embedding in prompts and
|
|
77
|
+
* logs. Falls back to the normalized tag itself so an unlisted-but-valid
|
|
78
|
+
* language still renders as something in a UI or a log line. Prompt builders
|
|
79
|
+
* must gate on {@link isKnownLanguage} first.
|
|
80
|
+
*/
|
|
81
|
+
export declare function languageLabel(value: string | null | undefined): string | undefined;
|
|
82
|
+
//# sourceMappingURL=language.d.ts.map
|
package/dist/language.js
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
// Shared language vocabulary for paseo's two audio modes (dictation + voice mode)
|
|
2
|
+
// and for the agent's output language.
|
|
3
|
+
//
|
|
4
|
+
// Two DIFFERENT parameters live here, and conflating them is the bug this module
|
|
5
|
+
// exists to prevent:
|
|
6
|
+
//
|
|
7
|
+
// - **input language** = the language the human SPEAKS into the microphone.
|
|
8
|
+
// Per device, never per session: the same agent can be open on a phone, a
|
|
9
|
+
// desktop and a watch, each with a different microphone in front of a
|
|
10
|
+
// different mouth. It drives STT only.
|
|
11
|
+
// - **output language** = the language the agent WRITES and SPEAKS back in.
|
|
12
|
+
// Per session, replicated with the agent record, because it is a property of
|
|
13
|
+
// the work ("this agent works in English"), not of any one microphone.
|
|
14
|
+
//
|
|
15
|
+
// The two are deliberately decoupled: speaking Portuguese while the repo, the
|
|
16
|
+
// commits and the docs stay English is a first-class combination, not an edge
|
|
17
|
+
// case.
|
|
18
|
+
//
|
|
19
|
+
// Tag formats: the app edge speaks BCP-47 ("pt-BR"), the speech daemon speaks
|
|
20
|
+
// ISO-639-1 ("pt"). `toIso639` is the single conversion point; do the
|
|
21
|
+
// conversion at the boundary and nowhere else.
|
|
22
|
+
/** BCP-47 tag used when nothing else is known. */
|
|
23
|
+
export const DEFAULT_LANGUAGE_TAG = "en-US";
|
|
24
|
+
/**
|
|
25
|
+
* Curated language list offered in the audio-mode pickers.
|
|
26
|
+
*
|
|
27
|
+
* Covers the app's own eight shipped UI locales plus the widely-requested
|
|
28
|
+
* European speech languages. It is intentionally a curated list rather than
|
|
29
|
+
* "everything a provider supports": STT coverage is provider-dependent (the
|
|
30
|
+
* default local Parakeet v2 model is English-only; OpenAI Whisper is not), so a
|
|
31
|
+
* longer list would promise accuracy paseo cannot deliver on the default stack.
|
|
32
|
+
*/
|
|
33
|
+
export const AUDIO_LANGUAGES = [
|
|
34
|
+
{ tag: "en-US", label: "English", nativeLabel: "English" },
|
|
35
|
+
{ tag: "pt-BR", label: "Portuguese (Brazil)", nativeLabel: "Português (Brasil)" },
|
|
36
|
+
{ tag: "es-ES", label: "Spanish", nativeLabel: "Español" },
|
|
37
|
+
{ tag: "fr-FR", label: "French", nativeLabel: "Français" },
|
|
38
|
+
{ tag: "de-DE", label: "German", nativeLabel: "Deutsch" },
|
|
39
|
+
{ tag: "it-IT", label: "Italian", nativeLabel: "Italiano" },
|
|
40
|
+
{ tag: "ja-JP", label: "Japanese", nativeLabel: "日本語" },
|
|
41
|
+
{ tag: "zh-CN", label: "Chinese (Simplified)", nativeLabel: "简体中文" },
|
|
42
|
+
{ tag: "ru-RU", label: "Russian", nativeLabel: "Русский" },
|
|
43
|
+
{ tag: "ar-SA", label: "Arabic", nativeLabel: "العربية" },
|
|
44
|
+
];
|
|
45
|
+
/**
|
|
46
|
+
* English display names keyed by ISO-639-1, used to render a language name
|
|
47
|
+
* inside a system prompt.
|
|
48
|
+
*
|
|
49
|
+
* Deliberately a static map rather than `Intl.DisplayNames`: the value is
|
|
50
|
+
* embedded in a prompt and must be byte-identical across the daemon, the tests
|
|
51
|
+
* and every Node/Hermes runtime paseo runs on. `Intl` availability and output
|
|
52
|
+
* both vary by runtime.
|
|
53
|
+
*/
|
|
54
|
+
const LANGUAGE_LABELS_BY_ISO639 = {
|
|
55
|
+
ar: "Arabic",
|
|
56
|
+
de: "German",
|
|
57
|
+
en: "English",
|
|
58
|
+
es: "Spanish",
|
|
59
|
+
fr: "French",
|
|
60
|
+
hi: "Hindi",
|
|
61
|
+
it: "Italian",
|
|
62
|
+
ja: "Japanese",
|
|
63
|
+
ko: "Korean",
|
|
64
|
+
nl: "Dutch",
|
|
65
|
+
pl: "Polish",
|
|
66
|
+
pt: "Portuguese",
|
|
67
|
+
ru: "Russian",
|
|
68
|
+
sv: "Swedish",
|
|
69
|
+
tr: "Turkish",
|
|
70
|
+
zh: "Chinese",
|
|
71
|
+
};
|
|
72
|
+
/** Region subtags worth naming explicitly, because the variants differ in use. */
|
|
73
|
+
const REGION_LABELS = {
|
|
74
|
+
"pt-BR": "Portuguese (Brazil)",
|
|
75
|
+
"pt-PT": "Portuguese (Portugal)",
|
|
76
|
+
"en-US": "English (US)",
|
|
77
|
+
"en-GB": "English (UK)",
|
|
78
|
+
"zh-CN": "Chinese (Simplified)",
|
|
79
|
+
"zh-TW": "Chinese (Traditional)",
|
|
80
|
+
};
|
|
81
|
+
/**
|
|
82
|
+
* Normalize any user- or config-supplied tag to canonical BCP-47 casing
|
|
83
|
+
* ("PT-br" -> "pt-BR"). Returns undefined for empty/unusable input rather than
|
|
84
|
+
* inventing a default, so callers decide their own fallback.
|
|
85
|
+
*/
|
|
86
|
+
export function normalizeLanguageTag(value) {
|
|
87
|
+
const trimmed = value?.trim();
|
|
88
|
+
if (!trimmed) {
|
|
89
|
+
return undefined;
|
|
90
|
+
}
|
|
91
|
+
const [primary, ...rest] = trimmed.replace(/_/g, "-").split("-");
|
|
92
|
+
if (!primary) {
|
|
93
|
+
return undefined;
|
|
94
|
+
}
|
|
95
|
+
const language = primary.toLowerCase();
|
|
96
|
+
if (!/^[a-z]{2,3}$/.test(language)) {
|
|
97
|
+
return undefined;
|
|
98
|
+
}
|
|
99
|
+
const region = rest.find((part) => /^[A-Za-z]{2}$/.test(part) || /^[0-9]{3}$/.test(part));
|
|
100
|
+
return region ? `${language}-${region.toUpperCase()}` : language;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* BCP-47 -> ISO-639-1, the form the speech daemon and OpenAI Whisper expect
|
|
104
|
+
* ("pt-BR" -> "pt"). This is the ONLY place the conversion happens.
|
|
105
|
+
*/
|
|
106
|
+
export function toIso639(value) {
|
|
107
|
+
const normalized = normalizeLanguageTag(value);
|
|
108
|
+
return normalized?.split("-")[0];
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* True when the tag resolves to a language paseo can NAME in English.
|
|
112
|
+
*
|
|
113
|
+
* `normalizeLanguageTag` only checks shape, and a 2-3 letter shape is cheap to
|
|
114
|
+
* hit by accident: "not-a-language" normalizes to the syntactically valid
|
|
115
|
+
* subtag "not". Callers that put the name into a prompt must gate on this, so
|
|
116
|
+
* a typo produces NO instruction rather than a confident instruction to write
|
|
117
|
+
* everything in "not".
|
|
118
|
+
*/
|
|
119
|
+
export function isKnownLanguage(value) {
|
|
120
|
+
const normalized = normalizeLanguageTag(value);
|
|
121
|
+
if (!normalized) {
|
|
122
|
+
return false;
|
|
123
|
+
}
|
|
124
|
+
if (REGION_LABELS[normalized]) {
|
|
125
|
+
return true;
|
|
126
|
+
}
|
|
127
|
+
const iso = normalized.split("-")[0] ?? normalized;
|
|
128
|
+
return Boolean(LANGUAGE_LABELS_BY_ISO639[iso]);
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Human-readable English name for a language tag, for embedding in prompts and
|
|
132
|
+
* logs. Falls back to the normalized tag itself so an unlisted-but-valid
|
|
133
|
+
* language still renders as something in a UI or a log line. Prompt builders
|
|
134
|
+
* must gate on {@link isKnownLanguage} first.
|
|
135
|
+
*/
|
|
136
|
+
export function languageLabel(value) {
|
|
137
|
+
const normalized = normalizeLanguageTag(value);
|
|
138
|
+
if (!normalized) {
|
|
139
|
+
return undefined;
|
|
140
|
+
}
|
|
141
|
+
const regionLabel = REGION_LABELS[normalized];
|
|
142
|
+
if (regionLabel) {
|
|
143
|
+
return regionLabel;
|
|
144
|
+
}
|
|
145
|
+
const iso = normalized.split("-")[0] ?? normalized;
|
|
146
|
+
return LANGUAGE_LABELS_BY_ISO639[iso] ?? normalized;
|
|
147
|
+
}
|
|
148
|
+
//# sourceMappingURL=language.js.map
|