Files

90 lines
14 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# go-sip
面向生产的Go SIP调度与执行项目:同一module/二进制通过Cobra提供 `dispatcher``agent` 两个业务子命令,分阶段替换Python,保留既有业务语义,SaaS交互统一为MQ-only。
> **当前状态:本轮单节点/单Dispatcher/单Agent/单Cell/单租户的 MQ-only 本地范围已完成。** 控制、AI配置/授权、查询/补传、上传通知及恢复均有 loopback RabbitMQ 证据;业务源码覆盖率为65.8%。真实SaaS/MQ、供应商/ECS、生产切换及第二Cell/第二租户仍属第二阶段;当前开发主机缺少 Asterisk/tcpdump,部署 preflight 已按要求 fail-closed,未冒充 mixed/real 通过。
> 本项目已独立拆仓运营;源码、配置、依赖、迁移、测试、部署和文档均在此目录内维护。远程仓库为 `git.ipao.vip/rogee/go-sip`,本地 Git 默认分支为 `main`;真实外呼仍受逐次授权、capture-first、白名单和时间门禁约束。
## 已确认的范围
- 使用 **Go 1.27.1**、Cobra单项目双命令和同一发布制品;角色分进程、权限/目录分离。
- 不接PGDispatcher独立SQLite统一任务/配额/outboxAgent无业务数据库,文本/录音/必要恢复信息落文件。
- 内部 **Unary gRPC**Dispatcher配置Agent Endpoint列表,Agent业务启动只需Dispatcher Endpoint,证书/监听/本地资源通过部署提供。
- 所有Agent共用mTLS证书、Dispatcher身份独立;需Endpoint主动激活/受限节点会话,不能把群组证书当单节点身份。
- 本次以稳定、快速单节点上线为目标:**1 个 Agent、1 套 Asterisk、1 个单活 Dispatcher、单 Cell、至少 3 家独立 SIP trunk 的契约/协议 fixture、1 个内测商务租户**;双节点、第二 Cell、双租户延期第二阶段。
- SIP 使用管理平台批准的不可变静态快照;维护窗口发布、排空和实际加载确认保留,在线动态发布/回滚编排暂缓。外呼仅允许 Asia/Shanghai 每日 `09:00`(含)至 `20:00`(不含),窗口外 Dispatcher/Agent fail-closed;按供应商授权登记单 Cell/出口 fixture。
- 有适用开源库/官方 SDK 时强制复用,不从零手写 SIP/ARI、RTP、MQ、数据库、OSS 或 AI 协议客户端;选库失败先报告阻塞,不静默转自研。
- 重写完整 Agent:调度控制面、Cell 外呼执行、ARI/RTP/录音、AI 流式适配、Cell 配置接收。
- 分阶段迁移,最终构建、测试和运行不依赖 Python、父仓库目录或其它业务项目内部代码。
- Asterisk 继续负责 SIP;独立 SIP 管理平台继续拥有配置管理权,均不纳入重写。
- **SaaS↔Dispatcher全部请求、响应和事件只走RabbitMQ,双方禁止任何HTTP。每个D都有全局唯一ID及独立接收Topic/队列,不能共享队列抢收或广播后过滤。** 执行/控制/查询/补传、AI配置/授权及 `recording.uploaded` 均在内;本地契约已冻结,P1不扩为多D协调/HA。
- **OSS配置存于Dispatcher配置文件,Agent向Dispatcher领取临时上传TOKEN后直传OSS,不保存长期凭据。** SaaS不下发OSS配置/TOKEN;D保留SDK签发能力,不转发文件。上传不申请SaaS会话、不等待verified/OSS ID或业务处理回复;D仅在原上传事实可靠进入指定持久MQ队列后记录交付完成。实时文字仍为 `transcript.updated`,归档不能替代实时事件。
- 本次必须支持 **ASR-only****ASR + LLM + TTS** 两种模式;本阶段已完成本地/协议隔离双模式验收。百炼/火山ASR、OpenAI兼容LLM、火山TTS的真实供应商能力和生产参数联调仍标第二阶段/未启用,不能将 Mock 写成真实供应商通过;禁止复用旧LLM/TTS。
- **AI业务配置/授权由D按任务agent_version_id经MQ向SaaS取得,经本D专用Topic收响应、校验并持久绑定后交付Agent;旧AI GET已废弃。** 模型、提示词、音色/语速、识别、超时/打断等参数不写死;新版本用于新任务,无需重启,在途通话固定快照。静态SIP发布不代表AI配置静态硬编码。
- 本轮验收范围收敛为单节点、单 Agent、单 Cell、单租户;保留 tenant_key 原值、独立队列、复合幂等和有界窗口。双节点、第二 Cell、双租户公平/背压/恢复不在本轮开发或验收范围,作为后续阶段。
- 上传链路仅包含R12临时授权、Agent直传、R13报告及 `recording.uploaded` 可靠入队;SaaS后续资产处理不属于本项目。真实SaaS/MQ联调仍第二阶段,不新增生产授权。
## 当前本地实现
MQ身份隔离、严格配置文件、执行接收/回执、查询/补传、任务控制、AI配置/授权及上传通知已有 loopback RabbitMQ 本地往返;旧HTTP业务入口已删除。最终质量检查通过,部署 preflight 在缺失 Asterisk/tcpdump 时明确失败并保留日志;这不等同真实SaaS、供应商或生产验收。阶段证据见 `docs/evidence/20260922-mq-only-local-final.md`
- `contracts/upstream/` 嵌入项目内自包含 W01 基线,记录父源 commit、dirty 继承和 SHA-256;运行时代码读取该包,不读取父目录。
- `internal/store/` 提供 SQLite inbox、任务、租户/跨 Cell 配额、控制 CAS、replay 和 outbox 事务。
- `internal/agent/` 只使用文件保存执行状态、transcript、录音/资产和崩溃恢复信息;boot 不释放未知占用;录音通过 Dispatcher 授权的短期 Alibaba OSS presigned PUT 直传,上传尝试和通知恢复分别持久记录,失败/过期保留源文件,不自动续期或重新PUT。
- `internal/ai/` 对固定 AI Schema 做不可变快照校验,支持项目内显式 `full_ai`/`asr_only` 分支;`mock_pipeline` 只用于隔离协议/取消/参数测试,不宣称真实供应商已启用。
-`internal/control/` HTTP业务实现、启动入口、CLI参数及环境配置已删除,不保留兼容通道。
- `internal/rpc/` 提供 `agent.v1` Unary handlers、mTLS TLS1.3 配置、会话世代/fencing、CAS、permit/fact/upload metadata 边界;Agent CLI 可选启动受证书保护的 gRPC listener,并校验静态 Cell 制品与 AI 授权边界。`internal/calllog/` 提供按手机号 HMAC 关联、掩码和 allow-list JSONL 外呼业务日志,不写原始号码、凭据、音频、转写或 prompt。
- `internal/health/` 使用 gopsutil 采样主机/进程资源;媒体端口和 AI 配额未接入时明确报告 unknown。`internal/mq/` 默认 bounded prefetch=1、per-tenant DLQ 和 publisher confirm`make mq-integration-local` 只启动 disposable RabbitMQ。
- `make acceptance-local` 会校验固定契约、跑 race/vet/build、执行 mock Agent/Dispatcher smoke,并确认 real mode 无凭据时拒绝;Alibaba OSS 实际授权测试由 `AGENT_CALL_OSS_INTEGRATION=1` 门控,使用受控环境变量,不把凭据写入仓库;`make release` 生成带 dirty-source/哈希的 local-development manifest;证据见 [`docs/evidence/20260918-local-development.json`](docs/evidence/20260918-local-development.json)。
- 直接依赖版本/本地许可证清单见 [`docs/evidence/20260918-dependencies.md`](docs/evidence/20260918-dependencies.md);门禁结论见 [`docs/evidence/20260918-acceptance-matrix.md`](docs/evidence/20260918-acceptance-matrix.md)SIP 注册/认证/From/PAI/前缀/选路对比见 [`docs/evidence/20260919-sip-routing-implementation-comparison.md`](docs/evidence/20260919-sip-routing-implementation-comparison.md),手机号业务日志边界见 [`docs/evidence/20260919-phone-call-business-log.md`](docs/evidence/20260919-phone-call-business-log.md)。
这些证据只签收旧基线的单节点/单Cell/单租户P1适用范围,不覆盖本次MQ-only修订,也不等于真实供应商、生产SaaS/MQ receipt、生产切换或第二阶段拓扑通过。范围和延期项见 [`docs/evidence/20260920-scope-amendment.md`](docs/evidence/20260920-scope-amendment.md)。
## 显式重新申请上传授权
仅对已有失败或结果未知的上传使用:
```sh
sip-go-agent agent upload-retry --spool /path/to/agent-spool \
--upload-id '<原上传ID>' --request-id '<新的小写UUID v4>' \
--file '/path/to/retained-recording.wav'
```
该命令使用既有Dispatcher端点/mTLS部署配置,不发起呼叫。请求ID必须由调用方显式提供;每个ID最多一次PUT,已成功上传的文件只恢复通知,不能再次PUT。重复旧请求不会获得续期TOKEN。`completed` 只表示指定持久MQ队列已接收原通知,不表示SaaS已处理。使用前仍需满足对应环境的统一部署与诊断要求。
## 文档
文档目录总览见 [`docs/README.md`](docs/README.md)。后续Agent先读 [项目开发计划与需求阅读索引](docs/plan-0918.md),按W/子任务确认I/M/G前置并阅读详细设计/权威契约。并行开发按§9登记单写范围、隔离工作区/测试资源和合并回归,由集成负责人统一维护总台账;开发子Agent固定使用 **gpt-5.6-lunamaxfast**,不可用时报告阻塞,不静默降级。本轮未启动开发子Agent。
| 文档 | 内容 |
| --- | --- |
| [plan-0918:开发计划与需求阅读索引](docs/plan-0918.md) | 首读入口:W00–W16及并行子任务、I/M/G关口、R0–R10索引、认领/单写/隔离/合并规则;部署候选前置到W13-a |
| [Go重写方案 v0.3](docs/Go重写方案_v0.3.md) | 本次单节点/单 Cell/单租户目标、至少3 SIP fixture、双AI模式、P0/P1/第二阶段分期 |
| [通信与事件数据交互 v0.1](docs/通信与事件数据交互_v0.1.md) | 首发Unary、静态SIP与双模式、§6.16.3 SaaS配置来源/参数矩阵/安全边界 |
| [SaaS↔Dispatcher契约](docs/contracts/saas-dispatcher.md) | MQ-only目标、D唯一身份/独立Topic、待冻结消息及旧实现差异 |
| [Dispatcher↔Agent契约](docs/contracts/dispatcher-agent.md) | 当前Unary/Proto事实及MQ上传结果的衔接待办 |
| [SaaS/MQ/D/A/OSS泳道图](docs/contracts/saas-rabbitmq-oss-dispatcher-agent-timeline.md) | 全MQ目标时序,Agent直传OSS,无SaaS↔D HTTP |
| [OpenAPI与MQ字段索引 v0.1](docs/OpenAPI与MQ字段索引_v0.1.md) | 旧源只读提取42个HTTP操作/115个组件及哈希;不代表新MQ-only入口,不手改生成物 |
| [deploys:物理机 systemd 发布包](deploys/README.md) | 锁定 Debian 13/Go 1.27.1/发布版本,构建并上传不依赖 Docker 的 Agent/Dispatcher 安装包 |
| [验证与切换验收 v0.3](docs/验证与切换验收_v0.3.md) | 10个首发汇总门禁、88项基线按阶段适用、P2公平性及独立容量验收 |
| [开源组件选型与复用清单 v0.2](docs/开源组件选型与复用清单_v0.2.md) | §1.3首发基础库/AI SDK选择,§4.3参数能力及锁版/许可/PoC门禁 |
| [G0开发准备与契约冻结方案 v0.1](docs/G0开发准备与契约冻结提案_v0.1.md) | 原D01D10方向已确认;MQ-only新增GAP-10及受影响G0须重新验证,真实外部发布/生产联调另行安排 |
| [AGENTS.md](AGENTS.md) | 本独立子项目的开发与安全约束 |
## 独立项目原则
- 当前设计文档以本目录 `docs/` 为唯一维护位置,不再向父项目另存一份。
- 对接协议的现有权威来源仍属于上游;后续在本项目导入带来源、版本和 SHA-256 的不可变契约发布包,不能另写一套同名 Schema。
- 后续发行包、CI、数据库和运行配置独立。不能靠 `../agent_call``../management``../sip_mock_server` 或父项目环境文件运行。
- 业务代码范围仅包括 SIP Agent/Dispatcher 与 AsteriskRabbitMQ、OSS、AI 供应商及 SaaS API 是 SaaS 提供的基础设施,不在本项目生产包中部署。独立集成测试使用自有隔离数据库、RabbitMQ 和契约 fixtureOSS数据面复用官方SDK/标准HTTP,D按自身配置文件提供临时TOKEN,A直传且不持有长期AK/SK;不申请SaaS上传会话,不等待SaaS校验或业务处理;外部 SIP Mock 只能以固定镜像及版本化协议接入,不导入其源码。
- 真实外呼、云创建、供应商调用和消费授权均是独立门禁,不能由测试成功或本文档自动授权。
## 阶段与下一步
1. **P0:先完成MQ-only新合同(GAP-10)。** 冻结D唯一ID/生命周期、独立Topic/队列/绑定、全部请求响应/关联/错误/期限及Unary异步衔接;旧包原样保留。其余已有基线按受影响范围重新验证,包括8种事件payload、双AI模式(GAP-08)、SaaS任务AI配置读取/调参(GAP-09)、首发Unary职责、单 Cell 静态快照来源/加载回执、D配置文件/临时上传TOKEN及上传通知可靠入队和至少3家SIP trunk的配置/协议 fixture。只核验实际采用的SDK;火山TTS参数覆盖、精确版本/许可证未核验前不宣布锁库,不等待未来动态发布/文本OSS归档合同。
2. **P1:本次单节点内测上线。** 完成单 Cell、单租户、双模式、幂等/控制/配额/恢复/录音安全的本地/隔离闭环;真实 ECS、真实外呼、生产 SaaS/MQ 联调不作为本阶段前置。
3. **第二阶段:** 真实 SaaS/MQ 对接、RabbitMQ ACL/TLS及适用的业务回执、真实供应商/ECS 联调,以及双节点、第二 Cell、第二租户公平调度。
4. **后续另立项:** 在线动态发布、自动跨供应商FALLBACK、多Dispatcher HA/分布式配额、权重借用、文本OSS归档、1000路完整AI/N+1。既有call/command整体补传不是通用回放平台,当前单节点首发仍保留。
阶段目标详见主方案§1/§10,首发验收见验收方案§1.1–§1.2;文件名保持不变。本次MQ-only本地门禁以计划§8.2和`docs/evidence/20260922-mq-only-local-final.md`为准;真实依赖、供应商、云/拨号、生产receipt、容量和切换仍属第二阶段,归档旧证据见 `docs/archive/evidence/20260920-local-p1-acceptance.md`