@jambonz/schema 0.1.1
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 +974 -0
- package/callbacks/amd.schema.json +50 -0
- package/callbacks/base.schema.json +29 -0
- package/callbacks/call-status.schema.json +22 -0
- package/callbacks/conference-status.schema.json +24 -0
- package/callbacks/conference-wait.schema.json +11 -0
- package/callbacks/conference.schema.json +11 -0
- package/callbacks/dequeue.schema.json +19 -0
- package/callbacks/dial-dtmf.schema.json +18 -0
- package/callbacks/dial-hold.schema.json +22 -0
- package/callbacks/dial-refer.schema.json +28 -0
- package/callbacks/dial.schema.json +31 -0
- package/callbacks/enqueue-wait.schema.json +17 -0
- package/callbacks/enqueue.schema.json +27 -0
- package/callbacks/gather-partial.schema.json +54 -0
- package/callbacks/gather.schema.json +60 -0
- package/callbacks/listen.schema.json +21 -0
- package/callbacks/llm.schema.json +30 -0
- package/callbacks/message.schema.json +35 -0
- package/callbacks/pipeline-turn.schema.json +109 -0
- package/callbacks/play.schema.json +36 -0
- package/callbacks/session-new.schema.json +143 -0
- package/callbacks/session-reconnect.schema.json +9 -0
- package/callbacks/session-redirect.schema.json +38 -0
- package/callbacks/sip-refer-event.schema.json +20 -0
- package/callbacks/sip-refer.schema.json +22 -0
- package/callbacks/sip-request.schema.json +27 -0
- package/callbacks/transcribe-translation.schema.json +24 -0
- package/callbacks/transcribe.schema.json +46 -0
- package/callbacks/tts-streaming-event.schema.json +77 -0
- package/callbacks/verb-status.schema.json +57 -0
- package/components/actionHook.schema.json +36 -0
- package/components/actionHookDelayAction.schema.json +37 -0
- package/components/amd.schema.json +68 -0
- package/components/auth.schema.json +18 -0
- package/components/bidirectionalAudio.schema.json +22 -0
- package/components/fillerNoise.schema.json +25 -0
- package/components/llm-base.schema.json +94 -0
- package/components/recognizer-assemblyAiOptions.schema.json +66 -0
- package/components/recognizer-awsOptions.schema.json +52 -0
- package/components/recognizer-azureOptions.schema.json +32 -0
- package/components/recognizer-cobaltOptions.schema.json +34 -0
- package/components/recognizer-customOptions.schema.json +27 -0
- package/components/recognizer-deepgramOptions.schema.json +147 -0
- package/components/recognizer-elevenlabsOptions.schema.json +39 -0
- package/components/recognizer-gladiaOptions.schema.json +8 -0
- package/components/recognizer-googleOptions.schema.json +35 -0
- package/components/recognizer-houndifyOptions.schema.json +53 -0
- package/components/recognizer-ibmOptions.schema.json +54 -0
- package/components/recognizer-nuanceOptions.schema.json +150 -0
- package/components/recognizer-nvidiaOptions.schema.json +39 -0
- package/components/recognizer-openaiOptions.schema.json +59 -0
- package/components/recognizer-sonioxOptions.schema.json +46 -0
- package/components/recognizer-speechmaticsOptions.schema.json +100 -0
- package/components/recognizer-verbioOptions.schema.json +46 -0
- package/components/recognizer.schema.json +216 -0
- package/components/synthesizer.schema.json +82 -0
- package/components/target.schema.json +105 -0
- package/components/vad.schema.json +48 -0
- package/docs/components/recognizer.md +78 -0
- package/docs/components/synthesizer.md +27 -0
- package/docs/guides/session-commands.md +417 -0
- package/docs/verbs/conference.md +51 -0
- package/docs/verbs/deepgram_s2s.md +108 -0
- package/docs/verbs/dial.md +8 -0
- package/docs/verbs/listen.md +71 -0
- package/docs/verbs/pipeline.md +475 -0
- package/docs/verbs/stream.md +5 -0
- package/index.js +9 -0
- package/jambonz-app.schema.json +112 -0
- package/lib/normalize.js +72 -0
- package/lib/validator.js +137 -0
- package/package.json +39 -0
- package/verbs/alert.schema.json +34 -0
- package/verbs/answer.schema.json +22 -0
- package/verbs/conference.schema.json +107 -0
- package/verbs/config.schema.json +218 -0
- package/verbs/deepgram_s2s.schema.json +81 -0
- package/verbs/dequeue.schema.json +51 -0
- package/verbs/dial.schema.json +187 -0
- package/verbs/dialogflow.schema.json +148 -0
- package/verbs/dtmf.schema.json +49 -0
- package/verbs/dub.schema.json +103 -0
- package/verbs/elevenlabs_s2s.schema.json +81 -0
- package/verbs/enqueue.schema.json +53 -0
- package/verbs/gather.schema.json +188 -0
- package/verbs/google_s2s.schema.json +42 -0
- package/verbs/hangup.schema.json +36 -0
- package/verbs/leave.schema.json +22 -0
- package/verbs/listen.schema.json +127 -0
- package/verbs/llm.schema.json +44 -0
- package/verbs/message.schema.json +82 -0
- package/verbs/openai_s2s.schema.json +42 -0
- package/verbs/pause.schema.json +36 -0
- package/verbs/pipeline.schema.json +240 -0
- package/verbs/play.schema.json +96 -0
- package/verbs/redirect.schema.json +34 -0
- package/verbs/s2s.schema.json +39 -0
- package/verbs/say.schema.json +107 -0
- package/verbs/sip-decline.schema.json +58 -0
- package/verbs/sip-refer.schema.json +58 -0
- package/verbs/sip-request.schema.json +54 -0
- package/verbs/stream.schema.json +103 -0
- package/verbs/tag.schema.json +41 -0
- package/verbs/transcribe.schema.json +57 -0
- package/verbs/ultravox_s2s.schema.json +41 -0
package/lib/validator.js
ADDED
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
const Ajv = require('ajv');
|
|
2
|
+
const {readFileSync} = require('fs');
|
|
3
|
+
const {resolve, join} = require('path');
|
|
4
|
+
const debug = require('debug')('jambonz:schema:validator');
|
|
5
|
+
const {normalizeJambones} = require('./normalize');
|
|
6
|
+
|
|
7
|
+
const schemaDir = resolve(__dirname, '..');
|
|
8
|
+
|
|
9
|
+
function loadSchema(relativePath) {
|
|
10
|
+
const fullPath = join(schemaDir, relativePath);
|
|
11
|
+
return JSON.parse(readFileSync(fullPath, 'utf-8'));
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function discoverSchemas(subdir) {
|
|
15
|
+
const {readdirSync} = require('fs');
|
|
16
|
+
const dir = join(schemaDir, subdir);
|
|
17
|
+
try {
|
|
18
|
+
return readdirSync(dir)
|
|
19
|
+
.filter((f) => f.endsWith('.schema.json'))
|
|
20
|
+
.map((f) => f.replace('.schema.json', ''));
|
|
21
|
+
} catch {
|
|
22
|
+
return [];
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
let _ajv = null;
|
|
27
|
+
let _validateApp = null;
|
|
28
|
+
|
|
29
|
+
function getAjv() {
|
|
30
|
+
if (_ajv) return _ajv;
|
|
31
|
+
|
|
32
|
+
_ajv = new Ajv({
|
|
33
|
+
allErrors: false,
|
|
34
|
+
strict: false,
|
|
35
|
+
validateSchema: false,
|
|
36
|
+
logger: false,
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
/* register component schemas first (referenced by verb schemas) */
|
|
40
|
+
for (const name of discoverSchemas('components')) {
|
|
41
|
+
const schema = loadSchema(`components/${name}.schema.json`);
|
|
42
|
+
_ajv.addSchema(schema);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/* register callback schemas */
|
|
46
|
+
for (const name of discoverSchemas('callbacks')) {
|
|
47
|
+
const schema = loadSchema(`callbacks/${name}.schema.json`);
|
|
48
|
+
_ajv.addSchema(schema);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/* register verb schemas */
|
|
52
|
+
for (const name of discoverSchemas('verbs')) {
|
|
53
|
+
const schema = loadSchema(`verbs/${name}.schema.json`);
|
|
54
|
+
_ajv.addSchema(schema);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/* compile the root app schema */
|
|
58
|
+
const appSchema = loadSchema('jambonz-app.schema.json');
|
|
59
|
+
_validateApp = _ajv.compile(appSchema);
|
|
60
|
+
|
|
61
|
+
debug('schemas compiled successfully');
|
|
62
|
+
return _ajv;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Validate a single verb against its JSON Schema.
|
|
67
|
+
*
|
|
68
|
+
* API-compatible with @jambonz/verb-specifications validateVerb.
|
|
69
|
+
*
|
|
70
|
+
* @param {string} name - Verb name (e.g. 'say', 'gather', 'llm')
|
|
71
|
+
* @param {object} data - Verb data (without the 'verb' property)
|
|
72
|
+
* @param {object} logger - Logger instance
|
|
73
|
+
* @throws {Error} If the verb is unknown or validation fails
|
|
74
|
+
*/
|
|
75
|
+
function validateVerb(name, data, logger) {
|
|
76
|
+
const ajv = getAjv();
|
|
77
|
+
|
|
78
|
+
/* look up the verb schema by $id */
|
|
79
|
+
const schemaId = `https://jambonz.org/schema/verbs/${name}`;
|
|
80
|
+
const validate = ajv.getSchema(schemaId);
|
|
81
|
+
if (!validate) {
|
|
82
|
+
throw new Error(`invalid instruction: ${name}`);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/* the JSON Schema expects the full verb object including {verb: 'name'} */
|
|
86
|
+
const verbObj = {verb: name, ...data};
|
|
87
|
+
const valid = validate(verbObj);
|
|
88
|
+
if (!valid) {
|
|
89
|
+
const errors = validate.errors || [];
|
|
90
|
+
const messages = errors.map((e) => `${e.instancePath || '/'}: ${e.message}`).join('; ');
|
|
91
|
+
debug(`validation failed for ${name}: ${messages}`);
|
|
92
|
+
throw new Error(`${name}: ${messages}`);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Validate a complete jambonz application (array of verbs).
|
|
98
|
+
*
|
|
99
|
+
* API-compatible with @jambonz/verb-specifications validate.
|
|
100
|
+
*
|
|
101
|
+
* @param {object} logger - Logger instance
|
|
102
|
+
* @param {Array} obj - Array of verb objects
|
|
103
|
+
* @throws {Error} If the payload is malformed or any verb is invalid
|
|
104
|
+
*/
|
|
105
|
+
function validate(logger, obj) {
|
|
106
|
+
/* normalize first (handles both verb formats + transforms) */
|
|
107
|
+
const normalized = normalizeJambones(logger, obj);
|
|
108
|
+
|
|
109
|
+
/* validate each verb individually for better error messages */
|
|
110
|
+
for (const tdata of normalized) {
|
|
111
|
+
const keys = Object.keys(tdata);
|
|
112
|
+
const name = keys[0];
|
|
113
|
+
const data = tdata[name];
|
|
114
|
+
validateVerb(name, data, logger);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Validate a verb array using the root app schema (validates the full array at once).
|
|
120
|
+
*
|
|
121
|
+
* @param {Array} app - Array of verb objects in {verb: 'name', ...} format
|
|
122
|
+
* @returns {{valid: boolean, errors: Array}} Validation result
|
|
123
|
+
*/
|
|
124
|
+
function validateApp(app) {
|
|
125
|
+
getAjv();
|
|
126
|
+
const valid = _validateApp(app);
|
|
127
|
+
if (valid) return {valid: true, errors: []};
|
|
128
|
+
return {
|
|
129
|
+
valid: false,
|
|
130
|
+
errors: (_validateApp.errors || []).map((e) => ({
|
|
131
|
+
path: e.instancePath || '/',
|
|
132
|
+
message: e.message || 'Unknown validation error',
|
|
133
|
+
})),
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
module.exports = {validate, validateVerb, validateApp};
|
package/package.json
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@jambonz/schema",
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "JSON Schema definitions and validation for jambonz verb applications",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"test": "node test/",
|
|
8
|
+
"lint": "eslint lib/ index.js"
|
|
9
|
+
},
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "git+https://github.com/jambonz/schema.git"
|
|
13
|
+
},
|
|
14
|
+
"author": "Dave Horton",
|
|
15
|
+
"license": "MIT",
|
|
16
|
+
"bugs": {
|
|
17
|
+
"url": "https://github.com/jambonz/schema/issues"
|
|
18
|
+
},
|
|
19
|
+
"homepage": "https://github.com/jambonz/schema#readme",
|
|
20
|
+
"dependencies": {
|
|
21
|
+
"ajv": "^8.17.1",
|
|
22
|
+
"debug": "^4.3.4"
|
|
23
|
+
},
|
|
24
|
+
"devDependencies": {
|
|
25
|
+
"eslint": "^9.3.0",
|
|
26
|
+
"eslint-plugin-promise": "^6.2.0",
|
|
27
|
+
"globals": "^15.3.0"
|
|
28
|
+
},
|
|
29
|
+
"files": [
|
|
30
|
+
"index.js",
|
|
31
|
+
"lib/",
|
|
32
|
+
"verbs/",
|
|
33
|
+
"components/",
|
|
34
|
+
"callbacks/",
|
|
35
|
+
"docs/",
|
|
36
|
+
"jambonz-app.schema.json",
|
|
37
|
+
"AGENTS.md"
|
|
38
|
+
]
|
|
39
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://jambonz.org/schema/verbs/alert",
|
|
4
|
+
"minVersion": "0.9.6",
|
|
5
|
+
"title": "Alert",
|
|
6
|
+
"description": "Sends a 180 Ringing provisional response with an Alert-Info header. Used to trigger a specific ring tone or alert behavior on the caller's device before the call is answered.",
|
|
7
|
+
"type": "object",
|
|
8
|
+
"properties": {
|
|
9
|
+
"verb": {
|
|
10
|
+
"const": "alert"
|
|
11
|
+
},
|
|
12
|
+
"id": {
|
|
13
|
+
"type": "string",
|
|
14
|
+
"description": "An optional unique identifier for this verb instance."
|
|
15
|
+
},
|
|
16
|
+
"message": {
|
|
17
|
+
"type": "string",
|
|
18
|
+
"description": "The value to include in the Alert-Info header.",
|
|
19
|
+
"examples": [
|
|
20
|
+
"info=alert-internal",
|
|
21
|
+
"http://example.com/ringtone.wav"
|
|
22
|
+
]
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"required": [
|
|
26
|
+
"message"
|
|
27
|
+
],
|
|
28
|
+
"examples": [
|
|
29
|
+
{
|
|
30
|
+
"verb": "alert",
|
|
31
|
+
"message": "info=alert-internal"
|
|
32
|
+
}
|
|
33
|
+
]
|
|
34
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://jambonz.org/schema/verbs/answer",
|
|
4
|
+
"minVersion": "0.9.6",
|
|
5
|
+
"title": "Answer",
|
|
6
|
+
"description": "Answers an incoming call (sends a 200 OK to the SIP INVITE). Most verbs implicitly answer the call, so this verb is only needed when you want to explicitly control when the call is answered — for example, to play early media before answering.",
|
|
7
|
+
"type": "object",
|
|
8
|
+
"properties": {
|
|
9
|
+
"verb": {
|
|
10
|
+
"const": "answer"
|
|
11
|
+
},
|
|
12
|
+
"id": {
|
|
13
|
+
"type": "string",
|
|
14
|
+
"description": "An optional unique identifier for this verb instance."
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"examples": [
|
|
18
|
+
{
|
|
19
|
+
"verb": "answer"
|
|
20
|
+
}
|
|
21
|
+
]
|
|
22
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://jambonz.org/schema/verbs/conference",
|
|
4
|
+
"minVersion": "0.9.6",
|
|
5
|
+
"title": "Conference",
|
|
6
|
+
"description": "Places the caller into a multi-party conference room. Multiple callers in the same named conference can speak to each other. Supports features like muting, recording, waiting rooms, and participant limits.",
|
|
7
|
+
"type": "object",
|
|
8
|
+
"properties": {
|
|
9
|
+
"verb": {
|
|
10
|
+
"const": "conference"
|
|
11
|
+
},
|
|
12
|
+
"id": {
|
|
13
|
+
"type": "string",
|
|
14
|
+
"description": "An optional unique identifier for this verb instance."
|
|
15
|
+
},
|
|
16
|
+
"name": {
|
|
17
|
+
"type": "string",
|
|
18
|
+
"description": "The name of the conference room. All callers joining the same named conference are connected together.",
|
|
19
|
+
"examples": [
|
|
20
|
+
"team-standup",
|
|
21
|
+
"customer-call-12345"
|
|
22
|
+
]
|
|
23
|
+
},
|
|
24
|
+
"beep": {
|
|
25
|
+
"type": "boolean",
|
|
26
|
+
"description": "If true, play a beep when participants join or leave."
|
|
27
|
+
},
|
|
28
|
+
"memberTag": {
|
|
29
|
+
"type": "string",
|
|
30
|
+
"description": "A tag to identify this participant. Can be used to target specific members for actions like muting or whispering."
|
|
31
|
+
},
|
|
32
|
+
"speakOnlyTo": {
|
|
33
|
+
"type": "string",
|
|
34
|
+
"description": "If set, this participant's audio is only heard by the member with the specified memberTag. Creates a private whisper channel."
|
|
35
|
+
},
|
|
36
|
+
"startConferenceOnEnter": {
|
|
37
|
+
"type": "boolean",
|
|
38
|
+
"description": "If true (default), the conference starts when this participant joins. If false, this participant waits silently until a participant with startConferenceOnEnter=true joins."
|
|
39
|
+
},
|
|
40
|
+
"endConferenceOnExit": {
|
|
41
|
+
"type": "boolean",
|
|
42
|
+
"description": "If true, the conference ends for all participants when this participant leaves."
|
|
43
|
+
},
|
|
44
|
+
"endConferenceDuration": {
|
|
45
|
+
"type": "number",
|
|
46
|
+
"description": "Maximum duration of the conference in seconds."
|
|
47
|
+
},
|
|
48
|
+
"maxParticipants": {
|
|
49
|
+
"type": "number",
|
|
50
|
+
"description": "Maximum number of participants allowed in the conference."
|
|
51
|
+
},
|
|
52
|
+
"joinMuted": {
|
|
53
|
+
"type": "boolean",
|
|
54
|
+
"description": "If true, this participant joins the conference muted."
|
|
55
|
+
},
|
|
56
|
+
"actionHook": {
|
|
57
|
+
"$ref": "../components/actionHook",
|
|
58
|
+
"description": "A webhook invoked when this participant leaves the conference."
|
|
59
|
+
},
|
|
60
|
+
"waitHook": {
|
|
61
|
+
"$ref": "../components/actionHook",
|
|
62
|
+
"description": "A webhook invoked while this participant is waiting for the conference to start. Should return verbs to play (e.g. hold music)."
|
|
63
|
+
},
|
|
64
|
+
"statusEvents": {
|
|
65
|
+
"type": "array",
|
|
66
|
+
"items": {
|
|
67
|
+
"type": "string"
|
|
68
|
+
},
|
|
69
|
+
"description": "List of conference events to receive via the statusHook."
|
|
70
|
+
},
|
|
71
|
+
"statusHook": {
|
|
72
|
+
"$ref": "../components/actionHook",
|
|
73
|
+
"description": "A webhook to receive conference status events (joins, leaves, etc.)."
|
|
74
|
+
},
|
|
75
|
+
"enterHook": {
|
|
76
|
+
"$ref": "../components/actionHook",
|
|
77
|
+
"description": "A webhook invoked when this participant first enters the conference."
|
|
78
|
+
},
|
|
79
|
+
"record": {
|
|
80
|
+
"type": "object",
|
|
81
|
+
"description": "Recording configuration for the conference.",
|
|
82
|
+
"additionalProperties": true
|
|
83
|
+
},
|
|
84
|
+
"listen": {
|
|
85
|
+
"type": "object",
|
|
86
|
+
"description": "Audio streaming configuration for the conference.",
|
|
87
|
+
"additionalProperties": true
|
|
88
|
+
},
|
|
89
|
+
"distributeDtmf": {
|
|
90
|
+
"type": "boolean",
|
|
91
|
+
"description": "If true, DTMF events from this participant are distributed to all other participants."
|
|
92
|
+
}
|
|
93
|
+
},
|
|
94
|
+
"required": [
|
|
95
|
+
"name"
|
|
96
|
+
],
|
|
97
|
+
"examples": [
|
|
98
|
+
{
|
|
99
|
+
"verb": "conference",
|
|
100
|
+
"name": "team-standup",
|
|
101
|
+
"beep": true,
|
|
102
|
+
"startConferenceOnEnter": true,
|
|
103
|
+
"endConferenceOnExit": false,
|
|
104
|
+
"statusHook": "/conference-events"
|
|
105
|
+
}
|
|
106
|
+
]
|
|
107
|
+
}
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://jambonz.org/schema/verbs/config",
|
|
4
|
+
"minVersion": "0.9.6",
|
|
5
|
+
"title": "Config",
|
|
6
|
+
"description": "Sets session-level defaults for the call. Configures default TTS, STT, VAD, recording, streaming, and other session-wide settings. These defaults apply to all subsequent verbs unless overridden at the verb level. Typically the first verb in an application. Can be used multiple times during a call to change settings.",
|
|
7
|
+
"type": "object",
|
|
8
|
+
"properties": {
|
|
9
|
+
"verb": {
|
|
10
|
+
"const": "config",
|
|
11
|
+
"description": "The verb name."
|
|
12
|
+
},
|
|
13
|
+
"id": {
|
|
14
|
+
"type": "string",
|
|
15
|
+
"description": "An optional unique identifier for this verb instance."
|
|
16
|
+
},
|
|
17
|
+
"synthesizer": {
|
|
18
|
+
"$ref": "../components/synthesizer",
|
|
19
|
+
"description": "Default TTS configuration for the session."
|
|
20
|
+
},
|
|
21
|
+
"recognizer": {
|
|
22
|
+
"$ref": "../components/recognizer",
|
|
23
|
+
"description": "Default STT configuration for the session."
|
|
24
|
+
},
|
|
25
|
+
"bargeIn": {
|
|
26
|
+
"type": "object",
|
|
27
|
+
"description": "Default barge-in configuration. When enabled, callers can interrupt playing prompts with speech or DTMF.",
|
|
28
|
+
"properties": {
|
|
29
|
+
"enable": {
|
|
30
|
+
"type": "boolean"
|
|
31
|
+
},
|
|
32
|
+
"sticky": {
|
|
33
|
+
"type": "boolean",
|
|
34
|
+
"description": "If true, barge-in settings persist across verbs rather than resetting after each verb."
|
|
35
|
+
},
|
|
36
|
+
"actionHook": {
|
|
37
|
+
"$ref": "../components/actionHook"
|
|
38
|
+
},
|
|
39
|
+
"input": {
|
|
40
|
+
"type": "array",
|
|
41
|
+
"items": {
|
|
42
|
+
"type": "string",
|
|
43
|
+
"enum": [
|
|
44
|
+
"speech",
|
|
45
|
+
"digits"
|
|
46
|
+
]
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
"minBargeinWordCount": {
|
|
50
|
+
"type": "number"
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
"ttsStream": {
|
|
55
|
+
"type": "object",
|
|
56
|
+
"description": "Default TTS streaming configuration for the session.",
|
|
57
|
+
"properties": {
|
|
58
|
+
"enable": {
|
|
59
|
+
"type": "boolean"
|
|
60
|
+
},
|
|
61
|
+
"synthesizer": {
|
|
62
|
+
"$ref": "../components/synthesizer"
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
"record": {
|
|
67
|
+
"type": "object",
|
|
68
|
+
"description": "Session-level call recording configuration.",
|
|
69
|
+
"additionalProperties": true
|
|
70
|
+
},
|
|
71
|
+
"listen": {
|
|
72
|
+
"$ref": "listen",
|
|
73
|
+
"description": "Nested listen verb — session-level audio streaming configuration."
|
|
74
|
+
},
|
|
75
|
+
"stream": {
|
|
76
|
+
"$ref": "stream",
|
|
77
|
+
"description": "Nested stream verb — session-level audio streaming configuration. Alias for 'listen'."
|
|
78
|
+
},
|
|
79
|
+
"transcribe": {
|
|
80
|
+
"$ref": "transcribe",
|
|
81
|
+
"description": "Nested transcribe verb — session-level real-time transcription configuration."
|
|
82
|
+
},
|
|
83
|
+
"amd": {
|
|
84
|
+
"$ref": "../components/amd",
|
|
85
|
+
"description": "Session-level answering machine detection configuration."
|
|
86
|
+
},
|
|
87
|
+
"fillerNoise": {
|
|
88
|
+
"$ref": "../components/fillerNoise",
|
|
89
|
+
"description": "Default filler noise configuration for the session."
|
|
90
|
+
},
|
|
91
|
+
"vad": {
|
|
92
|
+
"$ref": "../components/vad",
|
|
93
|
+
"description": "Default voice activity detection configuration for the session."
|
|
94
|
+
},
|
|
95
|
+
"notifyEvents": {
|
|
96
|
+
"type": "boolean",
|
|
97
|
+
"description": "If true, send call events (e.g. DTMF, call status changes) to the application via the status webhook."
|
|
98
|
+
},
|
|
99
|
+
"notifySttLatency": {
|
|
100
|
+
"type": "boolean",
|
|
101
|
+
"description": "If true, include STT latency measurements in webhook payloads."
|
|
102
|
+
},
|
|
103
|
+
"reset": {
|
|
104
|
+
"oneOf": [
|
|
105
|
+
{
|
|
106
|
+
"type": "string"
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
"type": "array",
|
|
110
|
+
"items": {
|
|
111
|
+
"type": "string"
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
],
|
|
115
|
+
"description": "Reset specific session-level settings to their defaults. Pass a setting name or array of setting names to reset."
|
|
116
|
+
},
|
|
117
|
+
"onHoldMusic": {
|
|
118
|
+
"type": "string",
|
|
119
|
+
"format": "uri",
|
|
120
|
+
"description": "URL of an audio file to play when the call is placed on hold."
|
|
121
|
+
},
|
|
122
|
+
"actionHookDelayAction": {
|
|
123
|
+
"$ref": "../components/actionHookDelayAction",
|
|
124
|
+
"description": "Default configuration for handling slow webhook responses."
|
|
125
|
+
},
|
|
126
|
+
"sipRequestWithinDialogHook": {
|
|
127
|
+
"$ref": "../components/actionHook",
|
|
128
|
+
"description": "A webhook to invoke when a SIP request (e.g. INFO, NOTIFY) is received within the dialog."
|
|
129
|
+
},
|
|
130
|
+
"boostAudioSignal": {
|
|
131
|
+
"oneOf": [
|
|
132
|
+
{
|
|
133
|
+
"type": "number"
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
"type": "string"
|
|
137
|
+
}
|
|
138
|
+
],
|
|
139
|
+
"description": "Boost (or attenuate) the audio signal in dB for the session."
|
|
140
|
+
},
|
|
141
|
+
"referHook": {
|
|
142
|
+
"$ref": "../components/actionHook",
|
|
143
|
+
"description": "A webhook to invoke when a SIP REFER request is received."
|
|
144
|
+
},
|
|
145
|
+
"earlyMedia": {
|
|
146
|
+
"type": "boolean",
|
|
147
|
+
"description": "If true, allow early media (audio before call answer) for the session."
|
|
148
|
+
},
|
|
149
|
+
"autoStreamTts": {
|
|
150
|
+
"type": "boolean",
|
|
151
|
+
"description": "If true, automatically use streaming TTS for all 'say' verbs in the session."
|
|
152
|
+
},
|
|
153
|
+
"disableTtsCache": {
|
|
154
|
+
"type": "boolean",
|
|
155
|
+
"description": "If true, disable TTS caching for the session."
|
|
156
|
+
},
|
|
157
|
+
"trackTtsPlayout": {
|
|
158
|
+
"type": "boolean",
|
|
159
|
+
"description": "If true, report the actual text spoken via TTS. Requires a TTS vendor that supports alignment data (e.g. ElevenLabs). On each utterance completion or interruption, a tts_spoken event is sent to the '/streaming-event' endpoint with fields: 'text' (string — the text actually spoken) and 'bargein' (boolean — true if the user interrupted before TTS finished). See the tts-streaming-event callback schema for full details."
|
|
160
|
+
},
|
|
161
|
+
"noiseIsolation": {
|
|
162
|
+
"type": "object",
|
|
163
|
+
"description": "Noise isolation configuration to reduce background noise on call audio. Defaults to filtering inbound (caller) audio; can also filter outbound audio via the direction option.",
|
|
164
|
+
"properties": {
|
|
165
|
+
"enable": {
|
|
166
|
+
"type": "boolean"
|
|
167
|
+
},
|
|
168
|
+
"vendor": {
|
|
169
|
+
"type": "string"
|
|
170
|
+
},
|
|
171
|
+
"level": {
|
|
172
|
+
"type": "number"
|
|
173
|
+
},
|
|
174
|
+
"model": {
|
|
175
|
+
"type": "string"
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
},
|
|
179
|
+
"turnTaking": {
|
|
180
|
+
"type": "object",
|
|
181
|
+
"description": "Turn-taking detection configuration for conversational AI applications.",
|
|
182
|
+
"properties": {
|
|
183
|
+
"enable": {
|
|
184
|
+
"type": "boolean"
|
|
185
|
+
},
|
|
186
|
+
"vendor": {
|
|
187
|
+
"type": "string"
|
|
188
|
+
},
|
|
189
|
+
"threshold": {
|
|
190
|
+
"type": "number"
|
|
191
|
+
},
|
|
192
|
+
"model": {
|
|
193
|
+
"type": "string"
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
},
|
|
198
|
+
"required": [],
|
|
199
|
+
"examples": [
|
|
200
|
+
{
|
|
201
|
+
"verb": "config",
|
|
202
|
+
"synthesizer": {
|
|
203
|
+
"vendor": "elevenlabs",
|
|
204
|
+
"voice": "Rachel",
|
|
205
|
+
"language": "en-US"
|
|
206
|
+
},
|
|
207
|
+
"recognizer": {
|
|
208
|
+
"vendor": "deepgram",
|
|
209
|
+
"language": "en-US"
|
|
210
|
+
},
|
|
211
|
+
"fillerNoise": {
|
|
212
|
+
"enable": true,
|
|
213
|
+
"url": "https://example.com/sounds/typing.wav",
|
|
214
|
+
"startDelaySecs": 2
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
]
|
|
218
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://jambonz.org/schema/verbs/deepgram_s2s",
|
|
4
|
+
"minVersion": "10.1.0",
|
|
5
|
+
"title": "Deepgram S2S",
|
|
6
|
+
"description": "Shortcut for 'llm' with vendor automatically set to 'deepgram'. Connects the caller to a Deepgram model for real-time speech-to-speech voice conversation.",
|
|
7
|
+
"type": "object",
|
|
8
|
+
"allOf": [
|
|
9
|
+
{
|
|
10
|
+
"$ref": "../components/llm-base"
|
|
11
|
+
}
|
|
12
|
+
],
|
|
13
|
+
"properties": {
|
|
14
|
+
"verb": {
|
|
15
|
+
"const": "deepgram_s2s",
|
|
16
|
+
"description": "The verb name."
|
|
17
|
+
},
|
|
18
|
+
"vendor": {
|
|
19
|
+
"type": "string",
|
|
20
|
+
"const": "deepgram",
|
|
21
|
+
"description": "The LLM vendor (always 'deepgram' for this shortcut)."
|
|
22
|
+
},
|
|
23
|
+
"llmOptions": {
|
|
24
|
+
"type": "object",
|
|
25
|
+
"description": "IMPORTANT: Deepgram does NOT use a 'messages' array. The llmOptions must contain a 'Settings' object with 'agent.think' (LLM provider, model, and prompt) and 'agent.speak' (TTS provider and voice model). The system prompt goes in Settings.agent.think.prompt, NOT in messages.",
|
|
26
|
+
"additionalProperties": true,
|
|
27
|
+
"examples": [
|
|
28
|
+
{
|
|
29
|
+
"Settings": {
|
|
30
|
+
"agent": {
|
|
31
|
+
"think": {
|
|
32
|
+
"provider": {
|
|
33
|
+
"type": "open_ai",
|
|
34
|
+
"model": "gpt-4o"
|
|
35
|
+
},
|
|
36
|
+
"prompt": "You are a helpful voice assistant."
|
|
37
|
+
},
|
|
38
|
+
"speak": {
|
|
39
|
+
"provider": {
|
|
40
|
+
"type": "deepgram",
|
|
41
|
+
"model": "aura-2-thalia-en"
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
]
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
"required": [
|
|
51
|
+
"llmOptions"
|
|
52
|
+
],
|
|
53
|
+
"examples": [
|
|
54
|
+
{
|
|
55
|
+
"verb": "deepgram_s2s",
|
|
56
|
+
"auth": {
|
|
57
|
+
"apiKey": "your-deepgram-api-key"
|
|
58
|
+
},
|
|
59
|
+
"llmOptions": {
|
|
60
|
+
"Settings": {
|
|
61
|
+
"agent": {
|
|
62
|
+
"think": {
|
|
63
|
+
"provider": {
|
|
64
|
+
"type": "open_ai",
|
|
65
|
+
"model": "gpt-4o"
|
|
66
|
+
},
|
|
67
|
+
"prompt": "You are a helpful voice assistant."
|
|
68
|
+
},
|
|
69
|
+
"speak": {
|
|
70
|
+
"provider": {
|
|
71
|
+
"type": "deepgram",
|
|
72
|
+
"model": "aura-2-thalia-en"
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
"actionHook": "/s2s-complete"
|
|
79
|
+
}
|
|
80
|
+
]
|
|
81
|
+
}
|