{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://go-sip.local/contracts/current/config-read.schema.json", "title": "Project-local read-only Dispatcher configuration; external SaaS compatibility unverified", "oneOf": [ {"$ref": "#/$defs/sip"}, {"$ref": "#/$defs/providers"}, {"$ref": "#/$defs/task"}, {"$ref": "#/$defs/quota"}, {"$ref": "#/$defs/error"} ], "$defs": { "dispatcher_id": {"type": "string", "format": "uuid"}, "tenant_id": {"type": "integer", "minimum": 1}, "task_id": {"type": "string", "pattern": "^[A-Za-z0-9_-]{1,128}$"}, "sip": { "type": "object", "additionalProperties": false, "required": ["resource", "dispatcher_id", "revision", "trunks"], "properties": { "resource": {"const": "sip_config"}, "dispatcher_id": {"$ref": "#/$defs/dispatcher_id"}, "revision": {"type": "integer", "minimum": 1}, "trunks": {"type": "array", "items": {"$ref": "#/$defs/trunk"}} } }, "trunk": { "type": "object", "additionalProperties": false, "required": ["trunk_id", "provider_id", "codec", "dial_prefix", "enabled", "server_host", "server_port", "transport", "auth_mode", "registration_required", "max_concurrent_calls", "caller_profiles", "schedule"], "properties": { "trunk_id": {"type": "string", "minLength": 1}, "provider_id": {"type": "string", "minLength": 1}, "codec": {"const": "PCMA"}, "dial_prefix": {"type": "string"}, "enabled": {"type": "boolean"}, "server_host": {"type": "string", "minLength": 1}, "server_port": {"type": "integer", "minimum": 1, "maximum": 65535}, "transport": {"enum": ["udp", "tcp", "tls", null]}, "auth_mode": {"enum": ["ip", "digest", "none", null]}, "registration_required": {"type": ["boolean", "null"]}, "max_concurrent_calls": {"type": ["integer", "null"], "minimum": 1}, "caller_profiles": {"type": "array", "items": {"type": "object", "additionalProperties": false, "required": ["caller_profile_id", "caller_id"], "properties": {"caller_profile_id": {"type": "string", "minLength": 1}, "caller_id": {"type": "string", "minLength": 1}}}}, "schedule": {"$ref": "#/$defs/weekly_schedule"} } }, "providers": { "type": "object", "additionalProperties": false, "required": ["resource", "dispatcher_id", "providers"], "properties": { "resource": {"const": "ai_providers"}, "dispatcher_id": {"$ref": "#/$defs/dispatcher_id"}, "providers": {"type": "array", "items": {"$ref": "#/$defs/provider"}} } }, "provider": { "type": "object", "additionalProperties": false, "required": ["provider_ref", "role", "enabled", "adapter", "endpoint", "credential"], "properties": { "provider_ref": {"type": "string", "minLength": 1}, "role": {"enum": ["asr", "llm", "tts"]}, "enabled": {"type": "boolean"}, "adapter": {"type": "string", "minLength": 1}, "endpoint": {"type": "string", "minLength": 1}, "credential": {"type": "string", "minLength": 1, "$comment": "Value is supplied verbatim to the provider SDK. Never log its content."} } }, "task": { "type": "object", "additionalProperties": false, "required": ["resource", "dispatcher_id", "tenant_id", "task_id", "task_revision", "status", "max_concurrent_calls", "ring_timeout_ms", "max_call_duration_ms", "route_policy_id", "caller_profile_id", "allowed_trunk_ids", "schedule", "agent"], "properties": { "resource": {"const": "task_config"}, "dispatcher_id": {"$ref": "#/$defs/dispatcher_id"}, "tenant_id": {"$ref": "#/$defs/tenant_id"}, "task_id": {"$ref": "#/$defs/task_id"}, "task_revision": {"type": "integer", "minimum": 1}, "status": {"enum": ["running", "paused", "stopped"]}, "name": {"type": "string", "minLength": 1}, "max_concurrent_calls": {"type": "integer", "minimum": 1}, "ring_timeout_ms": {"type": "integer", "minimum": 1}, "max_call_duration_ms": {"type": "integer", "minimum": 1}, "route_policy_id": {"type": "string", "minLength": 1}, "caller_profile_id": {"type": "string", "minLength": 1}, "allowed_trunk_ids": {"type": "array", "minItems": 1, "uniqueItems": true, "items": {"type": "string", "minLength": 1}}, "schedule": {"$ref": "#/$defs/task_schedule"}, "agent": {"$ref": "#/$defs/agent"} } }, "quota": { "type": "object", "additionalProperties": false, "required": ["resource", "dispatcher_id", "tenant_id", "quota_revision", "max_concurrent_calls"], "properties": { "resource": {"const": "tenant_quota"}, "dispatcher_id": {"$ref": "#/$defs/dispatcher_id"}, "tenant_id": {"$ref": "#/$defs/tenant_id"}, "quota_revision": {"type": "integer", "minimum": 1}, "max_concurrent_calls": {"type": "integer", "minimum": 0} } }, "error": { "type": "object", "additionalProperties": false, "required": ["resource", "error"], "properties": { "resource": {"const": "error"}, "error": {"type": "object", "additionalProperties": false, "required": ["code", "message"], "properties": {"code": {"type": "string", "minLength": 1}, "message": {"type": "string", "minLength": 1}}} } }, "task_schedule": { "type": "object", "additionalProperties": false, "required": ["time_zone", "starts_at", "ends_at", "weekly_windows", "excluded_dates"], "properties": { "time_zone": {"const": "Asia/Shanghai"}, "starts_at": {"type": ["string", "null"], "format": "date-time"}, "ends_at": {"type": ["string", "null"], "format": "date-time"}, "weekly_windows": {"$ref": "#/$defs/weekly_windows"}, "excluded_dates": {"type": "array", "uniqueItems": true, "items": {"type": "string", "format": "date"}} } }, "weekly_schedule": { "type": "object", "additionalProperties": false, "required": ["time_zone", "weekly_windows"], "properties": {"time_zone": {"const": "Asia/Shanghai"}, "weekly_windows": {"$ref": "#/$defs/weekly_windows"}} }, "weekly_windows": { "type": "object", "additionalProperties": false, "required": ["monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday"], "properties": { "monday": {"$ref": "#/$defs/windows"}, "tuesday": {"$ref": "#/$defs/windows"}, "wednesday": {"$ref": "#/$defs/windows"}, "thursday": {"$ref": "#/$defs/windows"}, "friday": {"$ref": "#/$defs/windows"}, "saturday": {"$ref": "#/$defs/windows"}, "sunday": {"$ref": "#/$defs/windows"} } }, "windows": {"type": "array", "items": {"type": "object", "additionalProperties": false, "required": ["start", "end"], "properties": {"start": {"type": "string", "pattern": "^(?:[01][0-9]|2[0-3]):[0-5][0-9]$"}, "end": {"type": "string", "pattern": "^(?:(?:[01][0-9]|2[0-3]):[0-5][0-9]|24:00)$"}}}}, "agent": { "type": "object", "additionalProperties": false, "required": ["immutable", "mode", "asr"], "properties": { "immutable": {"const": true}, "mode": {"enum": ["asr_only", "full_ai"]}, "asr": {"$ref": "#/$defs/asr"}, "llm": {"$ref": "#/$defs/llm"}, "tts": {"$ref": "#/$defs/tts"}, "prompt": {"$ref": "#/$defs/prompt"}, "conversation": {"$ref": "#/$defs/conversation"} }, "allOf": [ {"if": {"properties": {"mode": {"const": "full_ai"}}}, "then": {"required": ["llm", "tts", "prompt", "conversation"]}}, {"if": {"properties": {"mode": {"const": "asr_only"}}}, "then": {"not": {"anyOf": [{"required": ["llm"]}, {"required": ["tts"]}, {"required": ["prompt"]}]}}} ] }, "asr": { "type": "object", "additionalProperties": false, "required": ["provider_ref", "language", "input"], "properties": { "provider_ref": {"type": "string", "minLength": 1}, "model": {"type": "string", "minLength": 1}, "language": {"type": "string", "minLength": 1}, "interim": {"type": "boolean"}, "timeout_ms": {"type": "integer", "minimum": 1}, "input": {"$ref": "#/$defs/audio_input"} } }, "audio_input": { "type": "object", "additionalProperties": false, "required": ["encoding", "sample_rate_hz", "channels", "sample_width_bytes"], "properties": { "encoding": {"const": "pcm_s16le"}, "sample_rate_hz": {"type": "integer", "minimum": 8000}, "channels": {"const": 1}, "sample_width_bytes": {"const": 2} } }, "llm": { "type": "object", "additionalProperties": false, "required": ["provider_ref", "model"], "properties": { "provider_ref": {"type": "string", "minLength": 1}, "model": {"type": "string", "minLength": 1}, "temperature": {"type": "number", "minimum": 0, "maximum": 2}, "max_tokens": {"type": "integer", "minimum": 1}, "timeout_ms": {"type": "integer", "minimum": 1} } }, "tts": { "type": "object", "additionalProperties": false, "required": ["provider_ref", "model", "voice", "language_type", "format"], "properties": { "provider_ref": {"type": "string", "minLength": 1}, "model": {"type": "string", "minLength": 1}, "voice": {"type": "string", "minLength": 1}, "language_type": {"type": "string", "minLength": 1}, "speed": {"type": "number", "minimum": 0.25, "maximum": 3}, "timeout_ms": {"type": "integer", "minimum": 1}, "format": {"type": "object", "additionalProperties": false, "required": ["encoding", "sample_rate_hz", "channels"], "properties": {"encoding": {"enum": ["pcm_s16le", "pcma"]}, "sample_rate_hz": {"type": "integer", "minimum": 8000}, "channels": {"const": 1}}} } }, "prompt": { "type": "object", "additionalProperties": false, "required": ["text", "allowed_variables"], "properties": {"text": {"type": "string", "minLength": 1}, "allowed_variables": {"type": "array", "uniqueItems": true, "items": {"type": "string", "minLength": 1}}, "max_bytes": {"type": "integer", "minimum": 1}} }, "conversation": { "type": "object", "additionalProperties": false, "properties": {"opening": {"type": "string"}, "hangup_keywords": {"type": "array", "items": {"type": "string", "minLength": 1}}, "allow_interrupt": {"type": "boolean"}, "silence_timeout_ms": {"type": "integer", "minimum": 1}, "max_duration_ms": {"type": "integer", "minimum": 1}, "max_turns": {"type": "integer", "minimum": 1}, "sentence_max_chars": {"type": "integer", "minimum": 1}, "max_pending_audio_chunks": {"type": "integer", "minimum": 1}} } } }