16 KiB
16 KiB
APP 对接外部服务 API 接口测试详细清单
Last Updated: 2026-04-22
本文记录 xworkmate-app 当前对外部服务的 APP 侧接口对接清单,重点覆盖:
- 账户服务
accounts.svc.plus - 桥接服务
xworkmate-bridge.svc.plus - 桥接侧 JSON-RPC 会话接口
session.start/session.message/session.cancel/session.close
本文目标不是抽象协议说明,而是把 APP 真实会调用的接口、请求体、返回体、鉴权方式、已验证结果和当前风险点整理成可执行测试清单。
1. 范围与用途
1.1 涵盖范围
- 账户登录与会话查询
- 账户同步返回的 bridge 元数据
- bridge 主入口
/acp/rpc acp.capabilitiesxworkmate.routing.resolve- 会话生命周期接口:
session.startsession.messagesession.cancelsession.close
1.2 不涵盖范围
- UI 视觉样式
- 纯本地文件系统工具
- 账户注册、找回密码、管理后台页面
- bridge 后端内部
/acp-server/*//gateway/*私有映射细节
1.3 适用场景
- Apple 审核只读账号连通性确认
- APP 上线前外部依赖冒烟
- bridge 协议改动后的回归核验
- 安全边界确认:
BRIDGE_AUTH_TOKEN是否只作为 Bearer token 使用BRIDGE_SERVER_URL是否仅作为元数据- 会话接口是否仍通过统一
/acp/rpc入口
2. 统一测试前提
2.1 环境变量 / 外部参数
BRIDGE_SERVER_URL=https://xworkmate-bridge.svc.plusBRIDGE_AUTH_TOKEN=<managed bridge token>
2.2 账户信息
url:https://accounts.svc.pluslogin_name:review@svc.pluslogin_password:***REMOVED-CREDENTIAL***
2.3 鉴权规则
- 账户接口使用账户登录返回的 session token
- bridge 接口使用
Authorization: Bearer <BRIDGE_AUTH_TOKEN> - 不允许用 gateway profile token 代替 bridge token
- 不允许把
BRIDGE_SERVER_URL当作 runtime 入口真源
2.4 当前代码侧入口
lib/runtime/account_runtime_client.dartlib/runtime/gateway_acp_client.dartlib/runtime/go_task_service_client.dartlib/runtime/external_code_agent_acp_desktop_transport.dart
3. 接口总览
| 服务 | 方法 / 路径 | HTTP 方法 | 鉴权 | 当前用途 | 备注 |
|---|---|---|---|---|---|
| accounts | /api/auth/login |
POST |
无 | 登录并拿 session token | Apple 审核只读账号使用 |
| accounts | /api/auth/session |
GET |
Authorization: Bearer <session token> |
获取当前会话和用户信息 | APP 端登录态校验 |
| accounts | /api/auth/xworkmate/profile/sync |
GET |
Authorization: Bearer <session token> |
拉取 bridge 同步元数据 | 返回 BRIDGE_SERVER_URL / BRIDGE_AUTH_TOKEN |
| bridge | /acp/rpc |
POST |
Authorization: Bearer <BRIDGE_AUTH_TOKEN> |
bridge JSON-RPC 主入口 | 所有运行时任务统一走这里 |
| bridge | acp.capabilities |
JSON-RPC method | 同上 | 拉取 provider catalog / target catalog | capability 只读快照 |
| bridge | xworkmate.routing.resolve |
JSON-RPC method | 同上 | 解析 provider / gateway / skills 路由 | 返回 resolved / unavailable 信息 |
| bridge | session.start |
JSON-RPC method | 同上 | 开启新会话 | session 生命周期起点 |
| bridge | session.message |
JSON-RPC method | 同上 | 继续现有会话 | 续写 / follow-up |
| bridge | session.cancel |
JSON-RPC method | 同上 | 取消正在进行的会话 | 终止流式任务 |
| bridge | session.close |
JSON-RPC method | 同上 | 关闭会话 | 释放会话资源 |
4. 账户服务测试清单
4.1 POST /api/auth/login
目标
- 验证只读审核账号可以正常登录
- 验证账户服务返回 session token
请求
{
"identifier": "review@svc.plus",
"password": "***REMOVED-CREDENTIAL***"
}
期望返回
- HTTP
200 - 响应体包含:
access_tokentokenexpiresAtusermfaRequired/mfa_required
当前实测结果
- 已通过
- 返回
200 - 返回体包含用户
readonly角色与会话 token
关键断言
- 不应返回 MFA 挑战
- 不应要求额外二次登录
- token 不应写入普通 settings
4.2 GET /api/auth/session
目标
- 校验登录 token 是否可用于读取当前会话
- 校验用户信息、角色、权限是否可见
请求
- Header:
Authorization: Bearer <session token>
期望返回
- HTTP
200 user.emailuser.usernameuser.roleuser.permissionsuser.tenants或等价租户信息
当前实测结果
- 已通过
- 返回
200 - 能读取会话和权限
关键断言
- 不能依赖 bridge token
- 不能读取旧的 managed secret 代替 session token
4.3 GET /api/auth/xworkmate/profile/sync
目标
- 读取 bridge 同步元数据
- 确认 APP 只把
BRIDGE_SERVER_URL作为 metadata - 确认
BRIDGE_AUTH_TOKEN能被同步回 APP 侧 secure storage
请求
- Header:
Authorization: Bearer <session token>
期望返回
- HTTP
200 - 响应体包含:
BRIDGE_SERVER_URLBRIDGE_AUTH_TOKEN
当前实测结果
- 已通过
- 返回:
BRIDGE_SERVER_URL=https://xworkmate-bridge.svc.plusBRIDGE_AUTH_TOKEN=<managed bridge token>
关键断言
BRIDGE_SERVER_URL只作为同步元数据,不参与 runtime endpoint 选择BRIDGE_AUTH_TOKEN只进入 secure storage / managed secret
5. 桥接主入口测试清单
5.1 POST /acp/rpc
目标
- 验证 bridge 主入口可连通
- 验证鉴权头正确
- 验证 JSON-RPC 协议错误返回格式
请求
- Header:
Authorization: Bearer <BRIDGE_AUTH_TOKEN> - Header:
Content-Type: application/json - Body: JSON-RPC payload
期望返回
- HTTP
200或 JSON-RPC 协议级错误 - 响应体为 JSON-RPC 风格:
jsonrpcidokresulterror
当前实测结果
- 发送空对象会返回协议错误:
missing method
- 说明服务在线,入口正确
关键断言
- 不应走
/acp-server/* - 不应走
/gateway/* - 不应回退到本地 loopback 作为 runtime 主入口
5.2 acp.capabilities
请求体
{
"jsonrpc": "2.0",
"id": "1",
"method": "acp.capabilities",
"params": {}
}
返回体重点
availableExecutionTargetsproviderCataloggatewayProviderssingleAgentmultiAgentcapabilities
当前实测结果
availableExecutionTargets:agent,gatewayproviderCatalog:codexopencodegeminihermes
gatewayProviders:openclaw
关键断言
providerCatalog只作为 agent 目标 cataloggatewayProviders只作为 gateway 目标 catalog- APP 侧 provider 菜单必须来自这里,不可静态硬编码
5.3 xworkmate.routing.resolve
请求体
{
"jsonrpc": "2.0",
"id": "1",
"method": "xworkmate.routing.resolve",
"params": {
"taskPrompt": "check api",
"workingDirectory": "/tmp",
"routing": {
"routingMode": "auto",
"preferredGatewayTarget": "codex",
"explicitExecutionTarget": "agent",
"explicitProviderId": "codex",
"explicitModel": "",
"explicitSkills": [],
"allowSkillInstall": false,
"availableSkills": []
}
}
}
返回体重点
resolvedExecutionTargetresolvedProviderIdresolvedGatewayProviderIdresolvedModelresolvedSkillsunavailableunavailableCodeunavailableMessage
当前实测结果
resolvedExecutionTarget:single-agentresolvedProviderId:codexunavailable:false
关键断言
- 路由解析结果必须和 UI / controller 的执行目标一致
unavailable为真时必须能带出原因字段
6. 会话接口测试清单
6.1 通用请求模型
桥接侧会话接口都使用 JSON-RPC,且共享同一套会话标识:
sessionIdthreadId- 任务类请求还会带:
modetaskPromptworkingDirectoryselectedSkillsattachmentsproviderroutingrequestedExecutionTargetexecutionTarget
这些字段由 GoTaskServiceRequest.toExternalAcpParams() 生成。
6.2 session.start
目标
- 开启新任务会话
- 验证桥接会话起点是否正确走向下游执行面
最小请求体
{
"jsonrpc": "2.0",
"id": "1",
"method": "session.start",
"params": {
"sessionId": "test-session-001",
"threadId": "test-session-001",
"mode": "gateway-chat",
"taskPrompt": "Say hello in one short sentence.",
"workingDirectory": "/tmp",
"selectedSkills": [],
"attachments": [],
"provider": "codex",
"routing": {
"routingMode": "auto",
"preferredGatewayTarget": "codex",
"explicitExecutionTarget": "agent",
"explicitProviderId": "codex",
"explicitModel": "",
"explicitSkills": [],
"allowSkillInstall": false,
"availableSkills": []
},
"requestedExecutionTarget": "agent",
"executionTarget": "agent"
}
}
返回体重点
oksuccesserrormodeproviderresolvedExecutionTargetresolvedProviderIdresolvedGatewayProviderIdresolvedModelresolvedSkillsskillResolutionSourceneedsSkillInstallturnIdunavailable
当前实测结果
- HTTP
200 - 返回
success: false - 返回错误:
dial tcp 127.0.0.1:9001: connect: connection refused
- 返回
resolvedExecutionTarget: single-agent - 返回
resolvedProviderId: codex - 返回
turnId
结论
- 协议入口正常
- 会话方法可用
- 当前失败点在桥接后端继续转发到本地
127.0.0.1:9001
关键断言
- 不能回退到本地 hardcoded endpoint 作为 APP runtime 真源
- 不能把 provider 路由走成
/acp-server/*直连
6.3 session.message
目标
- 继续已有会话
- 校验 follow-up 是否沿用同一
sessionId/threadId
最小请求体
{
"jsonrpc": "2.0",
"id": "2",
"method": "session.message",
"params": {
"sessionId": "test-session-001",
"threadId": "test-session-001",
"mode": "gateway-chat",
"taskPrompt": "Continue with a very short acknowledgement.",
"workingDirectory": "/tmp",
"selectedSkills": [],
"attachments": [],
"provider": "codex",
"routing": {
"routingMode": "auto",
"preferredGatewayTarget": "codex",
"explicitExecutionTarget": "agent",
"explicitProviderId": "codex",
"explicitModel": "",
"explicitSkills": [],
"allowSkillInstall": false,
"availableSkills": []
},
"requestedExecutionTarget": "agent",
"executionTarget": "agent"
}
}
返回体重点
- 与
session.start相同的会话结果字段
当前实测结果
- HTTP
200 - 返回
success: false - 返回错误:
dial tcp 127.0.0.1:9001: connect: connection refused
- 返回
turnId
关键断言
- 续写请求不能改写线程归属
- 续写请求不能偷偷切换到另一个 provider
6.4 session.cancel
目标
- 取消进行中的会话
- 校验取消接口是否幂等可用
最小请求体
{
"jsonrpc": "2.0",
"id": "3",
"method": "session.cancel",
"params": {
"sessionId": "test-session-001",
"threadId": "test-session-001"
}
}
返回体重点
acceptedcancelled
当前实测结果
- HTTP
200 - 返回:
accepted: truecancelled: false
关键断言
- 取消接口应可在会话失败后调用
- 不应因会话已失败而返回协议错误
6.5 session.close
目标
- 关闭会话
- 回收会话资源
最小请求体
{
"jsonrpc": "2.0",
"id": "4",
"method": "session.close",
"params": {
"sessionId": "test-session-001",
"threadId": "test-session-001"
}
}
返回体重点
acceptedclosed
当前实测结果
- HTTP
200 - 返回:
accepted: trueclosed: true
关键断言
- 会话关闭应始终可调用
- 关闭接口不能依赖会话先成功完成
7. 代码到接口的映射
| 代码位置 | 说明 |
|---|---|
lib/runtime/account_runtime_client.dart |
账户登录、会话、同步接口封装 |
lib/runtime/gateway_acp_client.dart |
bridge JSON-RPC 请求、capabilities、routing、session 生命周期 |
lib/runtime/go_task_service_client.dart |
会话请求参数组装 |
lib/runtime/external_code_agent_acp_desktop_transport.dart |
session.start / session.message 触发路径 |
8. 自动化测试建议
8.1 现有自动化基础
test/runtime/gateway_acp_client_auth_test.darttest/runtime/runtime_controllers_settings_account_test.dart
8.2 推荐新增测试
桥接协议层
test/runtime/gateway_acp_client_session_test.dart- 覆盖
session.start - 覆盖
session.message - 覆盖
session.cancel - 覆盖
session.close - 断言 Bearer 头、JSON-RPC method、params 结构
- 覆盖
失败分支
session.start下游连接失败时,返回值中应保留:success: falseerrorturnIdresolvedProviderId
session.messagefollow-up 失败时,不应破坏会话标识
8.3 建议断言
Authorization必须是Bearer <token>- 请求路径必须是
/acp/rpc - 不允许出现
/acp-server/或/gateway/直连请求 session.cancel/session.close必须接受sessionId+threadIdBRIDGE_SERVER_URL不可参与运行时路径拼接
9. 当前已知风险
session.start/session.message当前环境下下游连接到127.0.0.1:9001失败- 这说明 bridge 主入口可用,但后端 provider 适配层在当前运行环境里未就绪
- 这是 bridge 后端运行态问题,不是 APP 侧 JSON-RPC 协议错误
10. 执行顺序建议
POST /api/auth/loginGET /api/auth/sessionGET /api/auth/xworkmate/profile/syncacp.capabilitiesxworkmate.routing.resolvesession.startsession.messagesession.cancelsession.close
11. 结论
当前 APP 对接外部服务的主链路已经明确:
- 账户侧负责登录与同步元数据
- bridge 侧负责 capability、路由解析和会话生命周期
- 任务执行必须统一经过
/acp/rpc session.start/session.message的协议入口已验证通畅session.cancel/session.close的协议入口已验证可用- 当前剩余风险集中在桥接后端下游 provider 连接,而不是 APP 侧接口拼接