Add isolated SIP call tool, optional debug capture and split interface schemas

This commit is contained in:
2026-10-08 12:44:45 +08:00
parent 98b3fd469d
commit 385bda0822
49 changed files with 3688 additions and 28 deletions
+71
View File
@@ -0,0 +1,71 @@
# 按接口拆分的 JSON Schema
此目录提供五类 HTTP 响应和六类 MQ 消息的独立校验入口,使用 JSON Schema Draft 2020-12。重复且约束相同的结构通过相对 `$ref` 引用 `common.schema.json`,仅单个入口使用的结构保留在该入口的 `$defs` 中。
本次仅新增文件,不替换或删除 `contracts/local/` 的原文件,不修改现有程序的校验入口、嵌入资源或来源清单。程序仍使用原有 Schema;此目录尚未接入运行或发布流程,不构成外部 SaaS 签收。
## HTTP 响应
下列入口校验响应 JSON 正文,不校验请求路径、查询参数或 HTTP 状态码。每个入口仅接受自己的成功响应或公共错误响应。
| 接口 | Schema | 现有示例(相对本目录) |
| --- | --- | --- |
| `GET /internal/v1/dispatcher/sip` | [`http-sip.schema.json`](http-sip.schema.json) | [`config-read-sip.json`](../local/examples/config-read-sip.json)、[`config-read-sip-no-revision.json`](../local/examples/config-read-sip-no-revision.json) |
| `GET /internal/v1/dispatcher/task/:task_id` | [`http-task-detail.schema.json`](http-task-detail.schema.json) | [`config-read-task-full.json`](../local/examples/config-read-task-full.json)、[`config-read-task-asr.json`](../local/examples/config-read-task-asr.json) |
| `GET /internal/v1/dispatcher/tasks` | [`http-task-list.schema.json`](http-task-list.schema.json) | [`task-discovery-page.json`](../local/examples/task-discovery-page.json)、[`task-discovery-end.json`](../local/examples/task-discovery-end.json) |
| `GET /internal/v1/dispatcher/tenant/:tenant_id/quota` | [`http-tenant-quota.schema.json`](http-tenant-quota.schema.json) | [`config-read-quota.json`](../local/examples/config-read-quota.json) |
| `GET /internal/v1/dispatcher/ai-providers` | [`http-ai-providers.schema.json`](http-ai-providers.schema.json) | [`config-read-providers.json`](../local/examples/config-read-providers.json)、[`config-read-bailian-providers.json`](../local/examples/config-read-bailian-providers.json) |
公共错误响应示例:[`config-read-error.json`](../local/examples/config-read-error.json)。
## MQ 消息
按消息类型和方向选择入口。`task.control` 的请求和回执共用事件名称,`call.execute` 的请求和派发回执也共用事件名称,不能仅依据 `event_type` 选择 Schema。
| 消息 | 方向 | Schema | 现有示例(相对本目录) |
| --- | --- | --- | --- |
| `sip.config` | SaaS → Dispatcher | [`mq-sip-config.schema.json`](mq-sip-config.schema.json) | [`mq-sip-change.json`](../local/examples/mq-sip-change.json) |
| `task.control` 请求 | SaaS → Dispatcher | [`mq-task-control-request.schema.json`](mq-task-control-request.schema.json) | [`mq-control.json`](../local/examples/mq-control.json)、[`mq-control-start.json`](../local/examples/mq-control-start.json)、[`mq-control-edit.json`](../local/examples/mq-control-edit.json) |
| `task.control` 回执 | Dispatcher → SaaS | [`mq-task-control-receipt.schema.json`](mq-task-control-receipt.schema.json) | [`mq-control-ack.json`](../local/examples/mq-control-ack.json) |
| `call.execute` 请求 | SaaS → Dispatcher | [`mq-call-execute-request.schema.json`](mq-call-execute-request.schema.json) | [`mq-execute.json`](../local/examples/mq-execute.json) |
| `call.execute` 派发/拒绝回执 | Dispatcher → SaaS | [`mq-call-execute-receipt.schema.json`](mq-call-execute-receipt.schema.json) | [`mq-execute-ack.json`](../local/examples/mq-execute-ack.json)、[`mq-execute-rejected.json`](../local/examples/mq-execute-rejected.json) |
| `call.execute.result` 最终结果 | Dispatcher → SaaS | [`mq-call-execute-result.schema.json`](mq-call-execute-result.schema.json) | [`mq-result-uploaded.json`](../local/examples/mq-result-uploaded.json)、[`mq-result-no-recording.json`](../local/examples/mq-result-no-recording.json) |
## 公共定义与引用
[`common.schema.json`](common.schema.json) 仅包含 `$defs`,不是独立消息的校验入口:
- `dispatcher_id`、`tenant_id`、`task_id`:公共身份字段约束。
- `event_id`、`issued_at`:MQ 事件身份和时间约束。
- `task_status`:任务详情与任务列表共用的任务状态。
- `error`:公共 HTTP 错误响应。
- `weekly_windows`、`windows`:任务和线路共用的每周时段。
引用示例:
```json
{
"dispatcher_id": {
"$ref": "./common.schema.json#/$defs/dispatcher_id"
}
}
```
任务时段和线路时段仍分别定义:任务保留有效起止时间和排除日期,线路不包含排除日期。任务详情内的 AI、SIP 线路和最终结果中的录音结构不增加跨入口抽象。
## 使用方式
1. 根据上表选择一个入口文件,而不是把所有入口合并为一个 `oneOf`。
2. 向校验器注册所用入口及其公共依赖。各文件的 `$id` 是稳定的资源标识,不是要求联网访问的下载地址;注册时使用文件内的 `$id`;若按本地文件 URI 加载,须将这些 `$id` 映射到对应的本地资源。
3. 离线解析 `./common.schema.json`。不得静默忽略缺失引用或改为联网下载;缺少依赖必须报错。移动或分发文件时保留相对目录关系。
4. 开启 `format` 校验,使 `uuid`、`date-time`、`date` 的检查与现有 Go 校验入口一致。现有 `github.com/santhosh-tekuri/jsonschema/v6` 支持 `AddResource`、`Compile` 和 `AssertFormat`,无需新增依赖。
5. 对响应或消息的 JSON 正文执行校验。资源归属、任务授权、时段关系、线路可用性等业务检查仍由程序执行,Schema 通过不代表业务获准。
## 来源及维护边界
- 五个配置响应(含公共错误、身份和时段定义)的来源:[`../local/config-read.schema.json`](../local/config-read.schema.json);任务列表来源:[`../local/task-discovery.schema.json`](../local/task-discovery.schema.json)。
- 六个 MQ 入口的来源:[`../local/mq.schema.json`](../local/mq.schema.json)。
- 拆分仅改变定义位置和引用方式,不增加、删除或放宽原有字段约束。任务列表对 `schema_version`、`control_seq` 的现有忽略规则也保持不变。
- HTTP 入口保留原有公共错误分支;MQ 入口严格区分原有消息分支。MQ 回执字段按原 Schema 保留,不自行补充字段。
- 此目录不引用旧目录中的 Schema;旧目录只作为拆分来源和现有示例位置。独立分发时仅需所用入口及 `common.schema.json`。
- 原文件、程序和清单仍保持原样。未来如需接入此目录或改变字段,必须另行确认范围,并同步核验新旧定义,不能假定本次已完成切换。
+122
View File
@@ -0,0 +1,122 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://go-sip.local/contracts/schema/common.schema.json",
"title": "Shared HTTP and MQ definitions; not a standalone message schema",
"$defs": {
"dispatcher_id": {
"type": "string",
"format": "uuid"
},
"tenant_id": {
"type": "integer",
"minimum": 1
},
"task_id": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{1,128}$"
},
"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
}
}
}
}
},
"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)$"
}
}
}
},
"event_id": {
"type": "string",
"minLength": 1
},
"issued_at": {
"type": "string",
"format": "date-time"
},
"task_status": {
"enum": [
"running",
"paused",
"stopped"
]
}
}
}
@@ -0,0 +1,93 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://go-sip.local/contracts/schema/http-ai-providers.schema.json",
"title": "GET /internal/v1/dispatcher/ai-providers response; external SaaS compatibility unverified",
"oneOf": [
{
"type": "object",
"additionalProperties": false,
"required": [
"resource",
"dispatcher_id",
"providers"
],
"properties": {
"resource": {
"const": "ai_providers"
},
"dispatcher_id": {
"$ref": "./common.schema.json#/$defs/dispatcher_id"
},
"providers": {
"type": "array",
"items": {
"$ref": "#/$defs/provider"
}
}
}
},
{
"$ref": "./common.schema.json#/$defs/error"
}
],
"$defs": {
"provider": {
"type": "object",
"additionalProperties": false,
"required": [
"provider_id",
"provider_code",
"api_key"
],
"properties": {
"provider_id": {
"type": "string",
"minLength": 1
},
"provider_code": {
"type": "string",
"minLength": 1
},
"name": {
"type": "string"
},
"api_endpoint": {
"type": "string"
},
"ws_endpoint": {
"type": "string"
},
"api_key": {
"type": "string",
"minLength": 1,
"$comment": "Connection credential; never log its content."
},
"extra_config": {
"type": "object"
}
},
"anyOf": [
{
"required": [
"api_endpoint"
],
"properties": {
"api_endpoint": {
"minLength": 1
}
}
},
{
"required": [
"ws_endpoint"
],
"properties": {
"ws_endpoint": {
"minLength": 1
}
}
}
]
}
}
}
+136
View File
@@ -0,0 +1,136 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://go-sip.local/contracts/schema/http-sip.schema.json",
"title": "GET /internal/v1/dispatcher/sip response; external SaaS compatibility unverified",
"oneOf": [
{
"type": "object",
"additionalProperties": false,
"required": [
"resource",
"dispatcher_id",
"trunks"
],
"properties": {
"resource": {
"const": "sip_config"
},
"dispatcher_id": {
"$ref": "./common.schema.json#/$defs/dispatcher_id"
},
"revision": {
"type": "integer",
"minimum": 1
},
"trunks": {
"type": "array",
"items": {
"$ref": "#/$defs/trunk"
}
}
}
},
{
"$ref": "./common.schema.json#/$defs/error"
}
],
"$defs": {
"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_id",
"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": {
"type": [
"string",
"null"
],
"pattern": "^(?:[uU][dD][pP]|[tT][cC][pP]|[tT][lL][sS])$"
},
"auth_mode": {
"type": [
"string",
"null"
],
"pattern": "^(?:[iI][pP]|[dD][iI][gG][eE][sS][tT]|[nN][oO][nN][eE])$"
},
"registration_required": {
"type": [
"boolean",
"null"
]
},
"max_concurrent_calls": {
"type": [
"integer",
"null"
],
"minimum": 1
},
"caller_id": {
"type": "string",
"pattern": "^[A-Za-z0-9][A-Za-z0-9._+-]{0,63}$"
},
"schedule": {
"$ref": "#/$defs/weekly_schedule"
}
}
},
"weekly_schedule": {
"type": "object",
"additionalProperties": false,
"required": [
"time_zone",
"weekly_windows"
],
"properties": {
"time_zone": {
"const": "Asia/Shanghai"
},
"weekly_windows": {
"$ref": "./common.schema.json#/$defs/weekly_windows"
}
}
}
}
}
@@ -0,0 +1,457 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://go-sip.local/contracts/schema/http-task-detail.schema.json",
"title": "GET /internal/v1/dispatcher/task/:task_id response; external SaaS compatibility unverified",
"oneOf": [
{
"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",
"allowed_trunk_ids",
"schedule",
"agent"
],
"properties": {
"resource": {
"const": "task_config"
},
"dispatcher_id": {
"$ref": "./common.schema.json#/$defs/dispatcher_id"
},
"tenant_id": {
"$ref": "./common.schema.json#/$defs/tenant_id"
},
"task_id": {
"$ref": "./common.schema.json#/$defs/task_id"
},
"task_revision": {
"type": "integer",
"minimum": 1
},
"status": {
"$ref": "./common.schema.json#/$defs/task_status"
},
"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
},
"allowed_trunk_ids": {
"type": "array",
"minItems": 1,
"uniqueItems": true,
"items": {
"type": "string",
"minLength": 1
}
},
"schedule": {
"$ref": "#/$defs/task_schedule"
},
"agent": {
"$ref": "#/$defs/agent"
}
}
},
{
"$ref": "./common.schema.json#/$defs/error"
}
],
"$defs": {
"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": "./common.schema.json#/$defs/weekly_windows"
},
"excluded_dates": {
"type": "array",
"uniqueItems": true,
"items": {
"type": "string",
"format": "date"
}
}
}
},
"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_id",
"language",
"input"
],
"properties": {
"provider_id": {
"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_id",
"model"
],
"properties": {
"provider_id": {
"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_id",
"model",
"voice",
"language_type",
"format"
],
"properties": {
"provider_id": {
"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
}
}
},
"hangup_keyword": {
"type": "object",
"additionalProperties": false,
"required": [
"name",
"triggers",
"closingRemark"
],
"properties": {
"name": {
"type": "string",
"minLength": 1,
"pattern": "\\S"
},
"triggers": {
"type": "array",
"minItems": 1,
"items": {
"type": "string",
"minLength": 1,
"pattern": "\\S"
}
},
"closingRemark": {
"type": "string",
"minLength": 1,
"pattern": "\\S"
}
}
},
"conversation": {
"type": "object",
"additionalProperties": false,
"properties": {
"opening": {
"type": "string"
},
"hangup_keywords": {
"type": "array",
"items": {
"$ref": "#/$defs/hangup_keyword"
}
},
"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
}
}
}
}
}
@@ -0,0 +1,66 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://go-sip.local/contracts/schema/http-task-list.schema.json",
"title": "GET /internal/v1/dispatcher/tasks response; external SaaS compatibility unverified",
"oneOf": [
{
"type": "object",
"additionalProperties": false,
"required": [
"dispatcher_id",
"cursor",
"tasks"
],
"properties": {
"schema_version": {},
"control_seq": {},
"dispatcher_id": {
"$ref": "./common.schema.json#/$defs/dispatcher_id"
},
"cursor": {
"type": "string",
"minLength": 1
},
"tasks": {
"type": "array",
"items": {
"$ref": "#/$defs/task"
}
}
},
"$comment": "A page containing zero tasks and a cursor ends enumeration. Non-empty short pages never end enumeration. Persist non-empty pages before using their returned cursor."
},
{
"$ref": "./common.schema.json#/$defs/error"
}
],
"$defs": {
"task": {
"type": "object",
"additionalProperties": false,
"required": [
"task_id",
"tenant_id",
"status",
"task_revision"
],
"properties": {
"schema_version": {},
"control_seq": {},
"task_id": {
"$ref": "./common.schema.json#/$defs/task_id"
},
"tenant_id": {
"$ref": "./common.schema.json#/$defs/tenant_id"
},
"status": {
"$ref": "./common.schema.json#/$defs/task_status"
},
"task_revision": {
"type": "integer",
"minimum": 1
}
}
}
}
}
@@ -0,0 +1,40 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://go-sip.local/contracts/schema/http-tenant-quota.schema.json",
"title": "GET /internal/v1/dispatcher/tenant/:tenant_id/quota response; external SaaS compatibility unverified",
"oneOf": [
{
"type": "object",
"additionalProperties": false,
"required": [
"resource",
"dispatcher_id",
"tenant_id",
"quota_revision",
"max_concurrent_calls"
],
"properties": {
"resource": {
"const": "tenant_quota"
},
"dispatcher_id": {
"$ref": "./common.schema.json#/$defs/dispatcher_id"
},
"tenant_id": {
"$ref": "./common.schema.json#/$defs/tenant_id"
},
"quota_revision": {
"type": "integer",
"minimum": 1
},
"max_concurrent_calls": {
"type": "integer",
"minimum": 0
}
}
},
{
"$ref": "./common.schema.json#/$defs/error"
}
]
}
@@ -0,0 +1,69 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://go-sip.local/contracts/schema/mq-call-execute-receipt.schema.json",
"title": "Dispatcher to SaaS: call.execute dispatch/rejection receipt; external SaaS compatibility unverified",
"type": "object",
"additionalProperties": false,
"required": [
"event_id",
"event_type",
"dispatcher_id",
"tenant_id",
"issued_at",
"payload"
],
"properties": {
"event_id": {
"$ref": "./common.schema.json#/$defs/event_id"
},
"event_type": {
"const": "call.execute"
},
"dispatcher_id": {
"$ref": "./common.schema.json#/$defs/dispatcher_id"
},
"tenant_id": {
"$ref": "./common.schema.json#/$defs/tenant_id"
},
"issued_at": {
"$ref": "./common.schema.json#/$defs/issued_at"
},
"payload": {
"oneOf": [
{
"type": "object",
"additionalProperties": false,
"required": [
"status"
],
"properties": {
"status": {
"const": "dispatched"
}
}
},
{
"type": "object",
"additionalProperties": false,
"required": [
"status",
"reason_code",
"reason_message"
],
"properties": {
"status": {
"const": "rejected"
},
"reason_code": {
"type": "null"
},
"reason_message": {
"type": "string",
"minLength": 1
}
}
}
]
}
}
}
@@ -0,0 +1,50 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://go-sip.local/contracts/schema/mq-call-execute-request.schema.json",
"title": "SaaS to Dispatcher: call.execute request; external SaaS compatibility unverified",
"type": "object",
"additionalProperties": false,
"required": [
"event_id",
"event_type",
"dispatcher_id",
"tenant_id",
"issued_at",
"payload"
],
"properties": {
"event_id": {
"$ref": "./common.schema.json#/$defs/event_id"
},
"event_type": {
"const": "call.execute"
},
"dispatcher_id": {
"$ref": "./common.schema.json#/$defs/dispatcher_id"
},
"tenant_id": {
"$ref": "./common.schema.json#/$defs/tenant_id"
},
"issued_at": {
"$ref": "./common.schema.json#/$defs/issued_at"
},
"payload": {
"type": "object",
"additionalProperties": false,
"required": [
"task_id",
"callee"
],
"properties": {
"task_id": {
"$ref": "./common.schema.json#/$defs/task_id"
},
"callee": {
"type": "string",
"minLength": 1,
"description": "SaaS event original callee; Dispatcher rejects non-ASCII digits or more than 32 digits with an application receipt after persisting the event"
}
}
}
}
}
@@ -0,0 +1,248 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://go-sip.local/contracts/schema/mq-call-execute-result.schema.json",
"title": "Dispatcher to SaaS: call.execute.result final result; external SaaS compatibility unverified",
"type": "object",
"additionalProperties": false,
"required": [
"event_id",
"event_type",
"dispatcher_id",
"tenant_id",
"issued_at",
"payload"
],
"properties": {
"event_id": {
"$ref": "./common.schema.json#/$defs/event_id"
},
"event_type": {
"const": "call.execute.result"
},
"dispatcher_id": {
"$ref": "./common.schema.json#/$defs/dispatcher_id"
},
"tenant_id": {
"$ref": "./common.schema.json#/$defs/tenant_id"
},
"issued_at": {
"$ref": "./common.schema.json#/$defs/issued_at"
},
"payload": {
"type": "object",
"additionalProperties": false,
"required": [
"task_id",
"callee",
"trunk_id",
"started_at",
"ended_at",
"duration_ms",
"outcome",
"reason_code",
"status_line",
"raw",
"sip_capture_error",
"transcript",
"opt_out",
"recording"
],
"properties": {
"task_id": {
"$ref": "./common.schema.json#/$defs/task_id"
},
"callee": {
"type": "string",
"minLength": 1
},
"trunk_id": {
"type": "string",
"minLength": 1
},
"started_at": {
"$ref": "./common.schema.json#/$defs/issued_at"
},
"ended_at": {
"$ref": "./common.schema.json#/$defs/issued_at"
},
"duration_ms": {
"type": "integer",
"minimum": 0
},
"outcome": {
"enum": [
"answered",
"no_answer",
"failed"
]
},
"reason_code": {
"type": [
"integer",
"null"
],
"minimum": 100,
"maximum": 699
},
"reason_message": {
"type": "string",
"minLength": 1
},
"status_line": {
"type": [
"string",
"null"
],
"pattern": "^SIP/2\\.0 [1-6][0-9]{2} .+",
"maxLength": 256
},
"raw": {
"type": [
"string",
"null"
],
"minLength": 12,
"maxLength": 65535
},
"sip_capture_error": {
"type": [
"string",
"null"
],
"minLength": 1,
"maxLength": 256
},
"transcript": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": false,
"required": [
"turn_id",
"segment_id",
"role",
"text",
"start_ms",
"end_ms"
],
"properties": {
"turn_id": {
"type": "string",
"minLength": 1
},
"segment_id": {
"type": "string",
"minLength": 1
},
"role": {
"enum": [
"user",
"assistant"
]
},
"text": {
"type": "string"
},
"start_ms": {
"type": "integer",
"minimum": 0
},
"end_ms": {
"type": "integer",
"minimum": 0
}
}
}
},
"opt_out": {
"type": "boolean"
},
"recording": {
"oneOf": [
{
"type": "object",
"additionalProperties": false,
"maxProperties": 0
},
{
"$ref": "#/$defs/recording_uploaded"
}
]
}
},
"allOf": [
{
"if": {
"properties": {
"reason_code": {
"type": "null"
}
},
"required": [
"reason_code"
]
},
"then": {
"required": [
"reason_message"
]
}
}
]
}
},
"$defs": {
"recording_uploaded": {
"type": "object",
"additionalProperties": false,
"required": [
"status",
"bucket",
"object_key",
"format",
"channels",
"sample_rate_hz",
"duration_ms",
"size_bytes",
"checksum_sha256"
],
"properties": {
"status": {
"const": "uploaded"
},
"bucket": {
"type": "string",
"minLength": 1
},
"object_key": {
"type": "string",
"minLength": 1
},
"format": {
"type": "string",
"minLength": 1
},
"channels": {
"type": "integer",
"minimum": 1
},
"sample_rate_hz": {
"type": "integer",
"minimum": 1
},
"duration_ms": {
"type": "integer",
"minimum": 0
},
"size_bytes": {
"type": "integer",
"minimum": 0
},
"checksum_sha256": {
"type": "string",
"pattern": "^[0-9a-f]{64}$"
}
}
}
}
}
@@ -0,0 +1,51 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://go-sip.local/contracts/schema/mq-sip-config.schema.json",
"title": "SaaS to Dispatcher: sip.config notification; external SaaS compatibility unverified",
"type": "object",
"additionalProperties": false,
"required": [
"event_id",
"event_type",
"dispatcher_id",
"payload"
],
"properties": {
"event_id": {
"$ref": "./common.schema.json#/$defs/event_id"
},
"event_type": {
"const": "sip.config"
},
"dispatcher_id": {
"$ref": "./common.schema.json#/$defs/dispatcher_id"
},
"payload": {
"type": "object",
"additionalProperties": false,
"required": [
"trunk_id",
"change_type",
"revision"
],
"properties": {
"trunk_id": {
"type": "string",
"minLength": 1
},
"change_type": {
"enum": [
"enabled",
"disabled",
"removed",
"created"
]
},
"revision": {
"type": "integer",
"minimum": 1
}
}
}
}
}
@@ -0,0 +1,41 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://go-sip.local/contracts/schema/mq-task-control-receipt.schema.json",
"title": "Dispatcher to SaaS: task.control receipt; external SaaS compatibility unverified",
"type": "object",
"additionalProperties": false,
"required": [
"event_id",
"event_type",
"dispatcher_id",
"tenant_id",
"payload"
],
"properties": {
"event_id": {
"$ref": "./common.schema.json#/$defs/event_id"
},
"event_type": {
"const": "task.control"
},
"dispatcher_id": {
"$ref": "./common.schema.json#/$defs/dispatcher_id"
},
"tenant_id": {
"$ref": "./common.schema.json#/$defs/tenant_id"
},
"payload": {
"type": "object",
"additionalProperties": false,
"required": [
"status"
],
"properties": {
"status": {
"type": "string",
"minLength": 1
}
}
}
}
}
@@ -0,0 +1,89 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://go-sip.local/contracts/schema/mq-task-control-request.schema.json",
"title": "SaaS to Dispatcher: task.control request; external SaaS compatibility unverified",
"type": "object",
"additionalProperties": false,
"required": [
"event_id",
"event_type",
"dispatcher_id",
"tenant_id",
"issued_at",
"payload"
],
"properties": {
"event_id": {
"$ref": "./common.schema.json#/$defs/event_id"
},
"event_type": {
"const": "task.control"
},
"dispatcher_id": {
"$ref": "./common.schema.json#/$defs/dispatcher_id"
},
"tenant_id": {
"$ref": "./common.schema.json#/$defs/tenant_id"
},
"issued_at": {
"$ref": "./common.schema.json#/$defs/issued_at"
},
"payload": {
"type": "object",
"additionalProperties": false,
"required": [
"task_id",
"action",
"reason"
],
"properties": {
"task_id": {
"$ref": "./common.schema.json#/$defs/task_id"
},
"action": {
"enum": [
"start",
"pause",
"resume",
"stop",
"edit"
]
},
"reason": {
"type": "string",
"minLength": 1
},
"options": {
"type": "object",
"additionalProperties": false,
"properties": {
"active_call_policy": {
"enum": [
"drain",
"hangup"
]
}
}
}
},
"allOf": [
{
"if": {
"properties": {
"action": {
"const": "edit"
}
}
},
"then": {
"not": {
"required": [
"options"
]
}
}
}
]
}
}
}