@jambonz/schema 0.4.23 → 0.4.25

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/AGENTS.md CHANGED
@@ -35,7 +35,7 @@ The verb schemas and JSON structure are identical in both modes. The difference
35
35
  - **Webhook**: Simple IVR, call routing, voicemail, basic gather-and-respond patterns.
36
36
  - **WebSocket**: LLM-powered voice agents, real-time audio streaming, complex conversational flows, anything requiring bidirectional communication, or asynchronous logic, or streaming tts.
37
37
 
38
- **IMPORTANT**: Any application that uses a speech-to-speech verb (`openai_s2s`, `gptlive_s2s`, `voicelive_s2s`, `google_s2s`, `deepgram_s2s`, `ultravox_s2s`, `qwen_s2s`, `elevenlabs_s2s`, `s2s`, or `agent`) MUST use WebSocket transport, not webhooks. These verbs require persistent bidirectional communication for real-time audio and events.
38
+ **IMPORTANT**: Any application that uses a speech-to-speech verb (`openai_s2s`, `gptlive_s2s`, `voicelive_s2s`, `nova_s2s`, `google_s2s`, `deepgram_s2s`, `ultravox_s2s`, `qwen_s2s`, `elevenlabs_s2s`, `s2s`, or `agent`) MUST use WebSocket transport, not webhooks. These verbs require persistent bidirectional communication for real-time audio and events.
39
39
 
40
40
  ## Schema
41
41
 
@@ -65,6 +65,7 @@ Two tools are available:
65
65
  - **openai_s2s** / **google_s2s** / **deepgram_s2s** / **ultravox_s2s** / **qwen_s2s** — Connect the caller to a vendor-specific LLM for real-time voice conversation. These are the **preferred** verbs when the vendor is known. Each handles the full STT→LLM→TTS flow with the vendor pre-set.
66
66
  - **gptlive_s2s** — Connect the caller to OpenAI's GPT Live API (limited-access alpha). A different wire protocol from `openai_s2s` (Realtime): `llmOptions` carries only a `session_update`, there is no `response_create`, and tool calls arrive via a Responses-targeted *delegation*. See [GPT Live S2S specifics](#gpt-live-s2s-specifics) below.
67
67
  - **voicelive_s2s** — Connect the caller to the Azure Voice Live API. Requires `connectOptions.host` (your Foundry/Speech resource). Unlike `openai_s2s`, the `session_update` uses Voice Live's flat shape and is sent verbatim, so Azure-only settings (`azure_semantic_vad`, `azure_deep_noise_suppression`, Azure TTS voices) work.
68
+ - **nova_s2s** — Connect the caller to Amazon Nova Sonic on Amazon Bedrock. `auth` takes AWS IAM credentials (`accessKeyId`, `secretAccessKey`, optional `sessionToken`) plus `region`; `model` defaults to `amazon.nova-2-5-sonic`. `llmOptions` (`systemPrompt`, `history`, `greeting`, `sessionStart`, `promptStart`) is optional. Nova waits for the caller unless a `greeting` is set. Requires the mediajam media server.
68
69
  - **elevenlabs_s2s** — Connect the caller to an ElevenLabs Conversational AI agent. **Unlike other s2s vendors**, ElevenLabs requires a pre-configured `agent_id` (created in the ElevenLabs dashboard) rather than a model and messages. See [ElevenLabs S2S specifics](#elevenlabs-s2s-specifics) below.
69
70
  - **s2s** — Generic LLM voice conversation verb. Use only when the vendor is determined at runtime (e.g. from an env var). Requires `vendor` to be specified.
70
71
  - **agent** — Higher-level voice AI agent with integrated turn detection. Mix-and-match STT, LLM, and TTS vendors.
@@ -100,7 +101,7 @@ Two tools are available:
100
101
  **IMPORTANT — Code generation rules:**
101
102
 
102
103
  1. **Always use `stream`, never `listen`** — they are synonyms; `stream` is the preferred name.
103
- 2. **Always use the vendor-specific shortcut when the LLM vendor is known** — use `openai_s2s`, `gptlive_s2s`, `voicelive_s2s`, `google_s2s`, `elevenlabs_s2s`, `deepgram_s2s`, `qwen_s2s`, or `ultravox_s2s`. Do NOT use `llm` or `s2s` with a `vendor` property when a shortcut exists.
104
+ 2. **Always use the vendor-specific shortcut when the LLM vendor is known** — use `openai_s2s`, `gptlive_s2s`, `voicelive_s2s`, `nova_s2s`, `google_s2s`, `elevenlabs_s2s`, `deepgram_s2s`, `qwen_s2s`, or `ultravox_s2s`. Do NOT use `llm` or `s2s` with a `vendor` property when a shortcut exists.
104
105
  3. **Use `s2s` (not `llm`) when the vendor is dynamic** — e.g. the vendor comes from an env var or runtime config. Both `s2s` and `llm` are synonyms, but prefer `s2s`.
105
106
  4. **Never use `llm` in generated code** — it is a legacy name. Use either a vendor shortcut or `s2s`.
106
107
 
@@ -0,0 +1,86 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://jambonz.org/schema/components/recognizer-mistralOptions",
4
+ "title": "Mistral Recognizer Options",
5
+ "description": "Mistral Voxtral realtime STT options. Only applies when recognizer vendor is 'mistral'. Voxtral streams text as it is recognized (sent as interim results when interim is enabled); with turn detection on (the default) a final transcript is produced when Voxtral detects the end of the speaker's turn, and in the agent verb each final ends the user's turn. Transcripts are reported with confidence 1.0. The language is sent as a two-letter code (en-US becomes en); leave it unset or 'any' for automatic detection.",
6
+ "type": "object",
7
+ "properties": {
8
+ "apiKey": {
9
+ "type": "string",
10
+ "description": "Mistral API key. Overrides the key configured in jambonz."
11
+ },
12
+ "model": {
13
+ "type": "string",
14
+ "description": "Realtime transcription model. Defaults to voxtral-mini-transcribe-realtime-3.",
15
+ "examples": ["voxtral-mini-transcribe-realtime-3"]
16
+ },
17
+ "streamingDelayMs": {
18
+ "type": "integer",
19
+ "description": "Target streaming delay in ms: how far the model looks ahead before emitting text. Lower is faster, higher is more accurate. Any value from 80 to 1200, or 2400. Voxtral's default is 480.",
20
+ "anyOf": [
21
+ { "minimum": 80, "maximum": 1200 },
22
+ { "const": 2400 }
23
+ ]
24
+ },
25
+ "verbatim": {
26
+ "type": "boolean",
27
+ "description": "Ask Voxtral for a verbatim transcript (sent as verbatim). Not in Mistral's docs yet; the realtime API accepts it."
28
+ },
29
+ "contextBias": {
30
+ "type": "array",
31
+ "items": { "type": "string" },
32
+ "maxItems": 100,
33
+ "description": "Words or phrases to favor (names, brands, jargon). When omitted, recognizer.hints are used."
34
+ },
35
+ "diarize": {
36
+ "type": "boolean",
37
+ "description": "Label each transcript with a speaker. Voxtral cannot diarize and detect turns at once, so this turns off turn detection: a final transcript closes at each sentence end or change of speaker. recognizer.diarization has the same effect. Ignored in the agent verb, which needs turn detection."
38
+ },
39
+ "speakerReferences": {
40
+ "type": "array",
41
+ "maxItems": 8,
42
+ "description": "Reference clips (3 to 15 seconds each) that let diarization name known speakers. Passed to Mistral as speaker_references. Requires diarize.",
43
+ "items": { "type": "object" }
44
+ },
45
+ "turnDetection": {
46
+ "type": "object",
47
+ "description": "Tunes when Voxtral ends a turn. Ignored when diarize is on. Thresholds must satisfy startThreshold >= eagerEndThreshold > endThreshold.",
48
+ "properties": {
49
+ "startThreshold": {
50
+ "type": "number",
51
+ "minimum": 0,
52
+ "maximum": 1,
53
+ "description": "Speech probability that starts a turn. Default 0.5."
54
+ },
55
+ "eagerEndThreshold": {
56
+ "type": "number",
57
+ "minimum": 0,
58
+ "maximum": 1,
59
+ "description": "Probability at which Voxtral signals a likely end of turn early; the agent verb uses it for early generation. Default 0.5."
60
+ },
61
+ "endThreshold": {
62
+ "type": "number",
63
+ "minimum": 0,
64
+ "maximum": 1,
65
+ "description": "Probability below which silence counts toward ending the turn. Default 0.33."
66
+ },
67
+ "minSilenceMs": {
68
+ "type": "integer",
69
+ "minimum": 0,
70
+ "description": "Silence in ms before a turn can end. Default 500; raised to streamingDelayMs when that is longer, since Voxtral's text lags the audio by about that much."
71
+ },
72
+ "endTimeoutMs": {
73
+ "type": "integer",
74
+ "minimum": 0,
75
+ "description": "Silence in ms after which the turn ends regardless of the model. Default 3000; must be at least minSilenceMs."
76
+ }
77
+ },
78
+ "additionalProperties": false
79
+ },
80
+ "mistralSttUri": {
81
+ "type": "string",
82
+ "description": "Custom host to connect to instead of api.mistral.ai, e.g. a proxy. A ws:// or http:// prefix disables TLS."
83
+ }
84
+ },
85
+ "additionalProperties": false
86
+ }
@@ -8,7 +8,7 @@
8
8
  "vendor": {
9
9
  "type": "string",
10
10
  "description": "The STT vendor to use. Must match a vendor configured in the jambonz platform.",
11
- "examples": ["google", "aws", "microsoft", "deepgram", "ibm", "nvidia", "soniox", "xai", "modulate", "zoom", "gradium", "assemblyai", "speechmatics", "openai", "houndify", "gladia", "elevenlabs", "custom"]
11
+ "examples": ["google", "aws", "microsoft", "deepgram", "ibm", "nvidia", "soniox", "xai", "modulate", "zoom", "gradium", "mistral", "assemblyai", "speechmatics", "openai", "houndify", "gladia", "elevenlabs", "custom"]
12
12
  },
13
13
  "label": {
14
14
  "type": "string",
@@ -202,6 +202,7 @@
202
202
  "modulateOptions": { "$ref": "recognizer-modulateOptions" },
203
203
  "zoomOptions": { "$ref": "recognizer-zoomOptions" },
204
204
  "gradiumOptions": { "$ref": "recognizer-gradiumOptions" },
205
+ "mistralOptions": { "$ref": "recognizer-mistralOptions" },
205
206
  "assemblyAiOptions": { "$ref": "recognizer-assemblyAiOptions" },
206
207
  "speechmaticsOptions": { "$ref": "recognizer-speechmaticsOptions" },
207
208
  "openaiOptions": { "$ref": "recognizer-openaiOptions" },
@@ -8,7 +8,7 @@
8
8
  "vendor": {
9
9
  "type": "string",
10
10
  "description": "The TTS vendor to use. Must match a vendor configured in the jambonz platform.",
11
- "examples": ["google", "aws", "microsoft", "elevenlabs", "cartesia", "fishaudio", "gradium", "kugelaudio", "nineninesix", "speechify", "deepgram", "deepgramflux", "ibm", "nvidia", "wellsaid", "whisper", "custom"]
11
+ "examples": ["google", "aws", "microsoft", "elevenlabs", "cartesia", "fishaudio", "gradium", "kugelaudio", "mistral", "nineninesix", "speechify", "deepgram", "deepgramflux", "ibm", "nvidia", "wellsaid", "whisper", "custom"]
12
12
  },
13
13
  "label": {
14
14
  "type": "string",
@@ -49,10 +49,11 @@ For other STT vendors with native turn-taking (assemblyai, speechmatics), early
49
49
 
50
50
  ## Noise isolation
51
51
 
52
- The `noiseIsolation` property enables server-side noise cancellation on the call audio. By default it filters the inbound (caller) audio, improving STT accuracy in noisy environments. It can also be configured to filter outbound audio via the `direction` option. Two vendors are available:
52
+ The `noiseIsolation` property enables server-side noise cancellation on the call audio. By default it filters the inbound (caller) audio, improving STT accuracy in noisy environments. It can also be configured to filter outbound audio via the `direction` option. Three vendors are available:
53
53
 
54
54
  - **`"krisp"`** — Krisp's proprietary noise cancellation. Requires a Krisp API key on self-hosted systems.
55
55
  - **`"rnnoise"`** — Open-source RNNoise-based noise cancellation. No API key required.
56
+ - **`"kugelaudio"`** — KugelAudio Clarity (`clarity-1`) cloud speech enhancement. Uses a KugelAudio speech credential with "use for noise isolation" enabled (pick one with `label` in the object form, or pass `auth: {apiKey, apiUri}` inline); adds a short delay (the round trip to KugelAudio) to the filtered audio. `level` is ignored.
56
57
 
57
58
  Shorthand (default settings):
58
59
 
@@ -30,6 +30,7 @@
30
30
  { "$ref": "verbs/qwen_s2s" },
31
31
  { "$ref": "verbs/gptlive_s2s" },
32
32
  { "$ref": "verbs/voicelive_s2s" },
33
+ { "$ref": "verbs/nova_s2s" },
33
34
  { "$ref": "verbs/dialogflow" },
34
35
  { "$ref": "verbs/agent" },
35
36
  { "$ref": "verbs/transfer" },
package/lib/normalize.js CHANGED
@@ -17,6 +17,7 @@ const verbTransforms = new Map([
17
17
  ['qwen_s2s', {verb: 'llm', properties: {vendor: 'qwen'}}],
18
18
  ['gptlive_s2s', {verb: 'llm', properties: {vendor: 'gptlive'}}],
19
19
  ['voicelive_s2s', {verb: 'llm', properties: {vendor: 'voicelive'}}],
20
+ ['nova_s2s', {verb: 'llm', properties: {vendor: 'nova'}}],
20
21
  ]);
21
22
 
22
23
  function applyVerbTransform(name, data) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jambonz/schema",
3
- "version": "0.4.23",
3
+ "version": "0.4.25",
4
4
  "description": "JSON Schema definitions and validation for jambonz verb applications",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -119,7 +119,13 @@
119
119
  "noResponseTimeout": {
120
120
  "type": "number",
121
121
  "minimum": 0,
122
- "description": "Seconds to wait after the assistant finishes speaking before prompting the user to respond. 0 disables. Default: 0.",
122
+ "description": "Seconds to wait after the assistant finishes speaking before prompting the user to respond. 0 disables. Default: 12.",
123
+ "default": 12
124
+ },
125
+ "noResponseMaxPrompts": {
126
+ "type": "integer",
127
+ "minimum": 0,
128
+ "description": "End the agent after this many no-response prompts in a row get no reply. The actionHook then fires with completionReason 'no_response', so the application decides what happens next. The count resets whenever the user speaks. 0 or unset: no limit (the agent keeps prompting). Requires feature-server with jambonz/feature-server#259.",
123
129
  "default": 0
124
130
  },
125
131
  "llm": {
@@ -229,7 +235,7 @@
229
235
  "oneOf": [
230
236
  {
231
237
  "type": "string",
232
- "enum": ["krisp", "rnnoise"],
238
+ "enum": ["krisp", "rnnoise", "kugelaudio"],
233
239
  "description": "Shorthand — enable noise isolation with the specified vendor using default settings."
234
240
  },
235
241
  {
@@ -240,6 +246,24 @@
240
246
  "type": "string",
241
247
  "description": "Noise isolation vendor/mode (e.g. 'krisp')."
242
248
  },
249
+ "label": {
250
+ "type": "string",
251
+ "description": "Label of the speech credential to use, for vendors that need one (kugelaudio)."
252
+ },
253
+ "auth": {
254
+ "type": "object",
255
+ "description": "Optional inline credentials for vendors that need them (kugelaudio). When omitted, feature-server looks up the speech credential by (vendor, label).",
256
+ "properties": {
257
+ "apiKey": {
258
+ "type": "string"
259
+ },
260
+ "apiUri": {
261
+ "type": "string",
262
+ "description": "Vendor API host, e.g. api.eu.kugelaudio.com."
263
+ }
264
+ },
265
+ "additionalProperties": true
266
+ },
243
267
  "level": {
244
268
  "type": "number",
245
269
  "minimum": 0,
@@ -176,6 +176,24 @@
176
176
  },
177
177
  "model": {
178
178
  "type": "string"
179
+ },
180
+ "label": {
181
+ "type": "string",
182
+ "description": "Label of the speech credential to use, for vendors that need one (kugelaudio)."
183
+ },
184
+ "auth": {
185
+ "type": "object",
186
+ "description": "Optional inline credentials for vendors that need them (kugelaudio). When omitted, feature-server looks up the speech credential by (vendor, label).",
187
+ "properties": {
188
+ "apiKey": {
189
+ "type": "string"
190
+ },
191
+ "apiUri": {
192
+ "type": "string",
193
+ "description": "Vendor API host, e.g. api.eu.kugelaudio.com."
194
+ }
195
+ },
196
+ "additionalProperties": true
179
197
  }
180
198
  }
181
199
  },
@@ -0,0 +1,179 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://jambonz.org/schema/verbs/nova_s2s",
4
+ "minVersion": "11.1.7",
5
+ "title": "Amazon Nova Sonic S2S",
6
+ "description": "Shortcut for 'llm' with vendor automatically set to 'nova'. Connects the caller to Amazon Nova Sonic (Nova 2 / Nova 2.5 Sonic) on Amazon Bedrock for real-time speech-to-speech conversation. auth takes AWS IAM credentials (accessKeyId, secretAccessKey, optional sessionToken) and the Bedrock region; the credentials need bedrock:InvokeModelWithBidirectionalStream on the model. llmOptions is optional: systemPrompt, history, greeting, and sessionStart / promptStart bodies merged into Nova's own events (the audio formats are fixed by jambonz). Requires the mediajam media server.",
7
+ "type": "object",
8
+ "allOf": [
9
+ {
10
+ "$ref": "../components/llm-base"
11
+ }
12
+ ],
13
+ "properties": {
14
+ "verb": {
15
+ "const": "nova_s2s",
16
+ "description": "The verb name."
17
+ },
18
+ "vendor": {
19
+ "type": "string",
20
+ "const": "nova",
21
+ "description": "The LLM vendor (always 'nova' for this shortcut)."
22
+ },
23
+ "model": {
24
+ "type": "string",
25
+ "description": "The Bedrock model id. Defaults to amazon.nova-2-5-sonic.",
26
+ "examples": [
27
+ "amazon.nova-2-5-sonic",
28
+ "amazon.nova-2-sonic-v1:0"
29
+ ]
30
+ },
31
+ "auth": {
32
+ "type": "object",
33
+ "description": "AWS IAM credentials and the Bedrock region.",
34
+ "properties": {
35
+ "accessKeyId": {
36
+ "type": "string",
37
+ "minLength": 1,
38
+ "description": "AWS access key id."
39
+ },
40
+ "secretAccessKey": {
41
+ "type": "string",
42
+ "minLength": 1,
43
+ "description": "AWS secret access key."
44
+ },
45
+ "sessionToken": {
46
+ "type": "string",
47
+ "description": "Session token, for temporary (STS) credentials."
48
+ },
49
+ "region": {
50
+ "type": "string",
51
+ "description": "Bedrock region serving Nova Sonic. Defaults to us-east-1.",
52
+ "examples": [
53
+ "us-east-1",
54
+ "us-west-2",
55
+ "eu-north-1",
56
+ "ap-northeast-1"
57
+ ]
58
+ }
59
+ },
60
+ "required": [
61
+ "accessKeyId",
62
+ "secretAccessKey"
63
+ ],
64
+ "additionalProperties": true
65
+ },
66
+ "llmOptions": {
67
+ "type": "object",
68
+ "description": "Nova session options. A systemPrompt or other text above 50KB is split across several textInput events.",
69
+ "properties": {
70
+ "systemPrompt": {
71
+ "type": "string",
72
+ "description": "System instructions, sent as the SYSTEM text content."
73
+ },
74
+ "speechPrompt": {
75
+ "type": "string",
76
+ "description": "Sent after the system prompt with role SYSTEM_SPEECH. Nova accepts one of three fixed sentences that choose Latin, Devanagari or mixed script for Hindi transcription and responses."
77
+ },
78
+ "history": {
79
+ "type": "array",
80
+ "description": "Prior turns sent before the audio starts. Following Nova's rules, consecutive turns with the same role are merged, leading assistant turns are dropped, and the total is capped at 200KB.",
81
+ "items": {
82
+ "type": "object",
83
+ "properties": {
84
+ "role": {
85
+ "type": "string",
86
+ "enum": [
87
+ "user",
88
+ "assistant",
89
+ "USER",
90
+ "ASSISTANT"
91
+ ]
92
+ },
93
+ "content": {
94
+ "type": "string"
95
+ }
96
+ },
97
+ "required": [
98
+ "role",
99
+ "content"
100
+ ]
101
+ }
102
+ },
103
+ "greeting": {
104
+ "type": "string",
105
+ "description": "Sent as a user text turn once the audio starts, so Nova speaks first (Nova otherwise waits for the caller)."
106
+ },
107
+ "sessionStart": {
108
+ "type": "object",
109
+ "description": "Merged into Nova's sessionStart event: inferenceConfiguration, turnDetectionConfiguration.endpointingSensitivity (HIGH, MEDIUM, LOW)."
110
+ },
111
+ "promptStart": {
112
+ "type": "object",
113
+ "description": "Merged into Nova's promptStart event: audioOutputConfiguration.voiceId (default matthew), toolConfiguration.tools in Nova's toolSpec shape and toolConfiguration.toolChoice ({auto:{}}, {any:{}} or {tool:{name}}). The audio format fields are set by jambonz."
114
+ },
115
+ "dtmf": {
116
+ "type": "object",
117
+ "description": "Caller keypad input. Nova has no DTMF support, so each completed entry is sent as a user text turn. Takes the gather verb's digit options.",
118
+ "properties": {
119
+ "enable": {
120
+ "type": "boolean"
121
+ },
122
+ "finishOnKey": {
123
+ "type": "string"
124
+ },
125
+ "numDigits": {
126
+ "type": "number"
127
+ },
128
+ "minDigits": {
129
+ "type": "number"
130
+ },
131
+ "maxDigits": {
132
+ "type": "number"
133
+ },
134
+ "interDigitTimeout": {
135
+ "type": "number"
136
+ },
137
+ "timeout": {
138
+ "type": "number"
139
+ }
140
+ },
141
+ "required": [
142
+ "enable"
143
+ ]
144
+ }
145
+ },
146
+ "additionalProperties": true
147
+ }
148
+ },
149
+ "required": [
150
+ "auth"
151
+ ],
152
+ "examples": [
153
+ {
154
+ "verb": "nova_s2s",
155
+ "model": "amazon.nova-2-5-sonic",
156
+ "auth": {
157
+ "accessKeyId": "AKIA...",
158
+ "secretAccessKey": "...",
159
+ "region": "us-east-1"
160
+ },
161
+ "llmOptions": {
162
+ "systemPrompt": "You are a helpful voice assistant. Keep answers short.",
163
+ "greeting": "Greet the caller and ask how you can help.",
164
+ "sessionStart": {
165
+ "turnDetectionConfiguration": {
166
+ "endpointingSensitivity": "MEDIUM"
167
+ }
168
+ },
169
+ "promptStart": {
170
+ "audioOutputConfiguration": {
171
+ "voiceId": "tiffany"
172
+ }
173
+ }
174
+ },
175
+ "toolHook": "/tool-call",
176
+ "actionHook": "/s2s-complete"
177
+ }
178
+ ]
179
+ }