外观
callflow-server
callflow-server 是 apps/callflow-webpage 的后端 API,负责:
- 持久化
tts/recording运行时配置,并代理触发callflow-esl热重载。 - 提供 FreeSWITCH PostgreSQL 表的只读分页查询与汇总视图。
- 管理
callflow.call_businesses、callflow.call_business_number_mappings,并代理外呼、TTS / ASR 测试请求。
运行
bash
bun install
bun run start
bun run dev
bun run typecheck
bun run auth:generate默认监听 0.0.0.0:9913。
配置文件
本服务主要读取外置 config.json,仅少量部署相关字段支持环境变量覆盖,不直接读取 apps/callflow-esl/config.json。 凡是需要默认运行信息的接口,都会按需请求 callflow-esl GET /runtime-configs;若该接口不可用或响应不合法,请求直接失败,不再本地兜底。
bun run dev/bun run start:读取当前工作目录下的config.json- 独立可执行文件:优先读取可执行文件同目录下的
config.json - 如果独立可执行文件目录下没有
config.json,则回退读取启动工作目录下的config.json
部署前请确保启动目录或可执行文件目录下存在合法的 config.json。
开发默认样例见 config.json。
配置字段
json
{
"server": {
"host": "0.0.0.0",
"port": 9913
},
"logging": {
"dir": "logs",
"level": "info",
"maxSize": "20m",
"maxFiles": "14d"
},
"databases": {
"freeswitch": {
"url": "postgres://postgres:postgres@192.168.2.246:5432/freeswitch",
"configDir": "/etc/freeswitch"
},
"callflow": {
"url": "postgres://postgres:postgres@localhost:5432/freeswitch?options=-c search_path=callflow"
}
},
"callflowEsl": {
"baseUrl": "http://127.0.0.1:9912",
"token": "esl-0x21"
},
"auth": {
"enabled": true,
"username": "admin",
"passwordHash": "scrypt$CjCVHad_PLuE2lPnHJNvaQ$2AM7XWfy4p2ejRzFu7Qf7XkRpdIizXIefKECSnnbEU_cgfgV_PiZalpUm8-in7OzaElTpLyGlq3lyKLIrO4JIA",
"tokenSecret": "N_jOol1eGo2zohOrPg4L7BwFZXYaTfmZ8BnxZUpW2Zo",
"tokenTtlDays": 30
},
"turn": {
"enabled": false,
"host": "123.57.205.60",
"port": 3478,
"realm": "softphone.ai-voice-platform",
"sharedSecret": "",
"credentialTtlSeconds": 3600
}
}字段说明:
server.host/server.port:HTTP 监听地址。databases.freeswitch.url:FreeSWITCH 核心数据库连接串,只读查询使用。databases.freeswitch.configDir:FreeSWITCH 配置文件目录路径(包含freeswitch.xml、autoload_configs/、dialplan/、directory/、sip_profiles/等)。databases.callflow.url:callflowschema 连接串,运行时配置和业务 CRUD 使用。callflowEsl.baseUrl:callflow-eslHTTP 基址,用于/outbound-calls、/freeswitch/runtime-status、/runtime-configs和/runtime-configs/reload代理。callflowEsl.token:代理到callflow-esl时附带的token请求头;未启用鉴权时可留空串。auth.enabled:是否启用管理台登录鉴权。auth.username:单管理员用户名。auth.passwordHash:管理员密码哈希。支持scrypt$<salt-base64url>$<hash-base64url>,也兼容Bun.password可校验的哈希格式。auth.tokenSecret:Bearer token HMAC 签名密钥;生产环境必须替换。auth.tokenTtlDays:Bearer token 有效期,单位天。
FreeSWITCH 动态配置预处理与拓扑寻址
服务内置了专用的 FreeSWITCH XML 预处理器解析引擎(fs-preprocessor-resolver 与 fs-config-tree):
- 动态入口寻址:服务优先读取
configDir/freeswitch.xml主入口,解析<X-PRE-PROCESS cmd="include" data="..."/>语法与<configuration name="...">拓扑。 - 高效文件扫描:基于 Bun 原生 SIMD 加速的
Bun.Glob与Bun.file异步 I/O,支持通配符 include(如autoload_configs/*.xml、dialplan/*.xml)。 - 循环引用守卫:解析器记录访问栈,防止 XML include 循环递归。
- 平滑兜底:当
freeswitch.xml不存在或部分路径无法解析时,自动平滑降级为目录扫描,确保高可用。
HTTP API
| 方法 | 路径 | 用途 |
|---|---|---|
GET | /api/health | 管理台主用健康检查;返回服务状态与两个数据库的连通性 |
GET | /health | 与 /api/health 完全一致的兼容 / 运维别名 |
POST | /api/auth/login | 管理员登录并返回 Bearer token |
GET | /api/auth/me | 返回当前登录状态与是否启用鉴权;带 token 时校验其有效性 |
POST | /api/auth/logout | 幂等成功;前端自行删除本地 token |
GET | /api/freeswitch/overview | 通话 / 注册数量,以及近期 channels / registrations |
GET | /api/freeswitch/runtime-status | 代理 callflow-esl FreeSWITCH 运行时状态 |
GET | /api/freeswitch/tables | 列出可浏览的 FreeSWITCH 表(元数据) |
GET | /api/freeswitch/tables/{name} | 分页、可搜索地读取 FreeSWITCH 表数据 |
GET | /api/freeswitch/basic-calls | tables/basic_calls 的快捷入口 |
GET | /api/freeswitch/detailed-calls | tables/detailed_calls 的快捷入口 |
GET | /api/freeswitch/vars | 获取 FreeSWITCH 全局变量 (vars.xml) 解析列表与 raw XML |
PUT | /api/freeswitch/vars | 更新 FreeSWITCH 全局变量 (支持全量与增量保存并生成备份) |
GET | /api/freeswitch/autoload-configs | 列出所有动态解析的自动加载配置文件 (autoload_configs) |
GET | /api/freeswitch/autoload-configs/{file} | 获取指定模块配置文件的结构化参数与原始 XML |
PUT | /api/freeswitch/autoload-configs/{file} | 保存指定模块配置文件 |
GET | /api/freeswitch/sip-profiles | 获取 SIP Profile (internal/external) 列表及网关 (Gateways) 列表 |
PUT | /api/freeswitch/sip-profiles/{profile} | 保存 SIP Profile 与 Gateway 配置 |
GET | /api/freeswitch/dialplans | 获取 Dialplan Context 与规则列表 |
PUT | /api/freeswitch/dialplans/{context} | 保存 Dialplan Context 规则 |
GET | /api/freeswitch/directory | 获取 Directory 用户、域与分组列表 |
POST | /api/freeswitch/reloadxml | 触发 FreeSWITCH ESL 执行 reloadxml 指令 |
GET | /api/callflow/businesses | 分页读取 callflow 业务 |
PUT | /api/callflow/businesses/{id} | 更新业务级 JSON 配置,固定请求体 { "businessConfig": { ... } } |
DELETE | /api/callflow/businesses/{id} | 软删除业务 |
GET | /api/callflow/number-mappings | 分页读取号码 → 业务映射 |
POST | /api/callflow/number-mappings | 创建号码映射 |
PUT | /api/callflow/number-mappings/{id} | 更新号码映射 |
DELETE | /api/callflow/number-mappings/{id} | 软删除号码映射 |
POST | /api/callflow/outbound-calls | 附加配置的 ESL token,代理调用 callflow-esl POST /outbound-calls |
GET | /api/callflow/runtime-configs | 当前 tts + recording 运行时配置 |
PUT | /api/callflow/runtime-configs/tts | 更新 tts 运行时配置 |
PUT | /api/callflow/runtime-configs/recording | 更新 recording 运行时配置 |
POST | /api/callflow/runtime-configs/reload | 转发重载请求到 {callflowEsl.baseUrl}/runtime-configs/reload |
POST | /api/tts/audition | 通过 sherpa-tts-server 或兼容 TTS 网关合成试听音频 |
POST | /api/tts/health | 探测 sherpa-tts-server 或兼容 TTS 网关 /health |
POST | /api/asr/health | 探测 sherpa-asr-online-server 或兼容 ASR 网关 /health |
POST | /api/asr/recognize | 接收 16kHz mono PCM16 WAV,转发到 ASR WebSocket 并返回 partial / final 结果 |
所有普通 JSON 响应都使用 { code, data, msg } 结构,三个字段始终存在。成功码固定为 字符串 "0000";失败码使用与错误语义对应的字符串,并保留 HTTP status。SSE、下载、 音频流与 OPTIONS 预检不套用该信封。
外呼管理接口接收与 callflow-esl POST /outbound-calls 相同的字段: destinationNumber、businessCode、variables、callerIdNumber、 callerIdName、dialStringTemplate。当上游 HTTP 请求成功且响应符合 { ok: boolean } 协议时,管理接口会解析上游结果并重新封装。上游 ok=true 时结果位于 data(其中业务字段 data.ok 保留);上游 ok=false 时管理接口返回失败码与 msg, 不会把旧信封直接透传。调用链为:
text
callflow-webpage -> callflow-server -> callflow-esl -> FreeSWITCH inbound ESL页面与调用方不能覆盖 callflowEsl.baseUrl 或 token;这两项始终取自服务端配置。
数据来源
callflow数据库:call_businesses、call_business_number_mappings、callflow_runtime_configs- FreeSWITCH 数据库:
channels、calls、registrations、sip_registrations、sip_dialogs、basic_calls、detailed_calls等 - sherpa-tts-server / 兼容 TTS 网关:TTS 试听与健康检查
- sherpa-asr-online-server / 兼容 ASR 网关:ASR 健康检查与识别测试
callflow-esl:外呼 originate、运行时配置默认值读取、运行时配置重载与 FreeSWITCH 运行时状态代理
call_businesses.businessConfig 与号码映射的 mappingConfig 都是直接的业务配置 JSON 对象;保存 {} 表示清空该层覆盖。callflow-esl 对新通话按“配置文件 < 业务配置 < 号码映射配置”深合并。显式 business_code 路由只使用前两层,不读取号码映射。 数据库升级时须先增加字段,再启动新服务:
sql
ALTER TABLE callflow.call_businesses
ADD COLUMN IF NOT EXISTS "businessConfig" jsonb NOT NULL DEFAULT '{}'::jsonb;日志
服务同时输出彩色控制台日志和每日滚动文件 logs/application-YYYY-MM-DD.log。config.json 的 logging.dir、level、maxSize、maxFiles 分别控制目录、最低级别、单文件大小和保留周期, 默认值为 logs、info、20m、14d。可用 CALLFLOW_SERVER_LOG_DIR、 CALLFLOW_SERVER_LOG_LEVEL、CALLFLOW_SERVER_LOG_MAX_SIZE、CALLFLOW_SERVER_LOG_MAX_FILES 覆盖。HTTP 日志跳过健康检查,只记录 method、path、status、durationMs 等摘要,不记录密码、 Bearer token、数据库连接串或请求体。